messageList: Use GObject properties for Message

This will allow us to use property bindings.

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/3173>
This commit is contained in:
Julian Sparber 2024-02-14 12:10:29 +01:00 committed by Florian Müllner
parent ffaec5615a
commit f0e863f529
3 changed files with 76 additions and 31 deletions

View File

@ -767,14 +767,10 @@ export const Calendar = GObject.registerClass({
export const NotificationMessage = GObject.registerClass( export const NotificationMessage = GObject.registerClass(
class NotificationMessage extends MessageList.Message { class NotificationMessage extends MessageList.Message {
_init(notification) { constructor(notification) {
super._init(notification.source, notification.title, notification.body); super(notification.source);
this.setUseBodyMarkup(notification.useBodyMarkup);
this.notification = notification; this.notification = notification;
this.datetime = notification.datetime;
this.setIcon(notification.gicon);
this.connect('close', () => { this.connect('close', () => {
this._closed = true; this._closed = true;
@ -792,6 +788,8 @@ class NotificationMessage extends MessageList.Message {
this.close(); this.close();
}, this); }, this);
this._onUpdated(notification);
this._actions = new Map(); this._actions = new Map();
this.notification.actions.forEach(action => { this.notification.actions.forEach(action => {
this._addAction(action); this._addAction(action);
@ -800,10 +798,10 @@ class NotificationMessage extends MessageList.Message {
_onUpdated(n, _clear) { _onUpdated(n, _clear) {
this.datetime = n.datetime; this.datetime = n.datetime;
this.setIcon(n.gicon); this.icon = n.gicon;
this.setTitle(n.title); this.title = n.title;
this.setBody(n.body); this.body = n.body;
this.setUseBodyMarkup(n.useBodyMarkup); this.useBodyMarkup = n.useBodyMarkup;
} }
vfunc_clicked() { vfunc_clicked() {

View File

@ -437,14 +437,36 @@ class MessageHeader extends St.BoxLayout {
}); });
export const Message = GObject.registerClass({ export const Message = GObject.registerClass({
Properties: {
'title': GObject.ParamSpec.string(
'title', 'title', 'title',
GObject.ParamFlags.READWRITE,
null),
'body': GObject.ParamSpec.string(
'body', 'body', 'body',
GObject.ParamFlags.READWRITE,
null),
'use-body-markup': GObject.ParamSpec.boolean(
'use-body-markup', 'use-body-markup', 'use-body-markup',
GObject.ParamFlags.READWRITE,
false),
'icon': GObject.ParamSpec.object(
'icon', 'icon', 'icon',
GObject.ParamFlags.READWRITE,
Gio.Icon),
'datetime': GObject.ParamSpec.boxed(
'datetime', 'datetime', 'datetime',
GObject.ParamFlags.READWRITE,
GLib.DateTime),
},
Signals: { Signals: {
'close': {}, 'close': {},
'expanded': {}, 'expanded': {},
'unexpanded': {}, 'unexpanded': {},
}, },
}, class Message extends St.Button { }, class Message extends St.Button {
_init(source, title, body) { constructor(source) {
super._init({ super({
style_class: 'message', style_class: 'message',
accessible_role: Atk.Role.NOTIFICATION, accessible_role: Atk.Role.NOTIFICATION,
can_focus: true, can_focus: true,
@ -497,7 +519,6 @@ export const Message = GObject.registerClass({
style_class: 'message-title', style_class: 'message-title',
y_align: Clutter.ActorAlign.END, y_align: Clutter.ActorAlign.END,
}); });
this.setTitle(title);
contentBox.add_child(this.titleLabel); contentBox.add_child(this.titleLabel);
this._bodyStack = new St.Widget({x_expand: true}); this._bodyStack = new St.Widget({x_expand: true});
@ -509,7 +530,6 @@ export const Message = GObject.registerClass({
this._bodyStack.add_child(this.bodyLabel); this._bodyStack.add_child(this.bodyLabel);
this._expandedLabel = new URLHighlighter('', true, this._useBodyMarkup); this._expandedLabel = new URLHighlighter('', true, this._useBodyMarkup);
this._bodyStack.add_child(this._expandedLabel); this._bodyStack.add_child(this._expandedLabel);
this.setBody(body);
this.connect('destroy', this._onDestroy.bind(this)); this.connect('destroy', this._onDestroy.bind(this));
@ -523,7 +543,7 @@ export const Message = GObject.registerClass({
this.emit('close'); this.emit('close');
} }
setIcon(icon) { set icon(icon) {
this._icon.gicon = icon; this._icon.gicon = icon;
if (icon instanceof Gio.ThemedIcon) if (icon instanceof Gio.ThemedIcon)
@ -532,34 +552,57 @@ export const Message = GObject.registerClass({
this._icon.remove_style_class_name('message-themed-icon'); this._icon.remove_style_class_name('message-themed-icon');
this._icon.visible = !!icon; this._icon.visible = !!icon;
this.notify('icon');
}
get icon() {
return this._icon.gicon;
}
set datetime(datetime) {
this._header.timeLabel.datetime = datetime;
this.notify('datetime');
} }
get datetime() { get datetime() {
return this._header.timeLabel.datetime; return this._header.timeLabel.datetime;
} }
set datetime(datetime) { set title(text) {
this._header.timeLabel.datetime = datetime; this._titleText = text;
} const title = text ? _fixMarkup(text.replace(/\n/g, ' '), false) : '';
setTitle(text) {
let title = text ? _fixMarkup(text.replace(/\n/g, ' '), false) : '';
this.titleLabel.clutter_text.set_markup(title); this.titleLabel.clutter_text.set_markup(title);
this.notify('title');
} }
setBody(text) { get title() {
return this._titleText;
}
set body(text) {
this._bodyText = text; this._bodyText = text;
this.bodyLabel.setMarkup(text ? text.replace(/\n/g, ' ') : '', this.bodyLabel.setMarkup(text ? text.replace(/\n/g, ' ') : '',
this._useBodyMarkup); this._useBodyMarkup);
this._expandedLabel.setMarkup(text, this._useBodyMarkup); this._expandedLabel.setMarkup(text, this._useBodyMarkup);
this.notify('body');
} }
setUseBodyMarkup(enable) { get body() {
return this._bodyText;
}
set useBodyMarkup(enable) {
if (this._useBodyMarkup === enable) if (this._useBodyMarkup === enable)
return; return;
this._useBodyMarkup = enable; this._useBodyMarkup = enable;
if (this.bodyLabel) if (this.bodyLabel)
this.setBody(this._bodyText); this.setBody(this._bodyText);
this.notify('use-body-markup');
}
get useBodyMarkup() {
return this._useBodyMarkup;
} }
setActionArea(actor) { setActionArea(actor) {

View File

@ -21,11 +21,11 @@ const MPRIS_PLAYER_PREFIX = 'org.mpris.MediaPlayer2.';
export const MediaMessage = GObject.registerClass( export const MediaMessage = GObject.registerClass(
class MediaMessage extends MessageList.Message { class MediaMessage extends MessageList.Message {
_init(player) { constructor(player) {
super._init(player.source, '', ''); super(player.source);
this.add_style_class_name('media-message');
this._player = player; this._player = player;
this.add_style_class_name('media-message');
this._prevButton = this.addMediaControl('media-skip-backward-symbolic', this._prevButton = this.addMediaControl('media-skip-backward-symbolic',
() => { () => {
@ -58,16 +58,20 @@ class MediaMessage extends MessageList.Message {
} }
_update() { _update() {
this.setTitle(this._player.trackTitle); let icon;
this.setBody(this._player.trackArtists.join(', '));
if (this._player.trackCoverUrl) { if (this._player.trackCoverUrl) {
const file = Gio.File.new_for_uri(this._player.trackCoverUrl); const file = Gio.File.new_for_uri(this._player.trackCoverUrl);
this.setIcon(new Gio.FileIcon({file})); icon = new Gio.FileIcon({file});
} else { } else {
this.setIcon(new Gio.ThemedIcon({name: 'audio-x-generic-symbolic'})); icon = new Gio.ThemedIcon({name: 'audio-x-generic-symbolic'});
} }
this.set({
title: this._player.trackTitle,
body: this._player.trackArtists.join(', '),
icon,
});
let isPlaying = this._player.status === 'Playing'; let isPlaying = this._player.status === 'Playing';
let iconName = isPlaying let iconName = isPlaying
? 'media-playback-pause-symbolic' ? 'media-playback-pause-symbolic'