notifications: Add buttons to Calendar.NotificationMessage via actions
Since we also want to show the buttons in the calendar move the code to add buttons/actions from `MessageTray.NotificationBanner` to `Calendar.NotificationMessage`. As nothing uses custom buttons that aren't backed by actions anymore, remove that bit of the public API. Closes: https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/7099 Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/3173>
This commit is contained in:
parent
7ff5f4ea51
commit
d44adf3b78
@ -14,12 +14,12 @@ $notification_banner_width: 34em;
|
||||
@if $contrast == 'high' {
|
||||
@include draw_hc_inset();
|
||||
}
|
||||
|
||||
.notification-actions {
|
||||
spacing: 0;
|
||||
}
|
||||
|
||||
.notification-button {
|
||||
@extend %bubble_button;
|
||||
}
|
||||
}
|
||||
|
||||
.notification-buttons-bin {
|
||||
spacing: 0;
|
||||
}
|
||||
|
||||
.notification-button {
|
||||
@extend %bubble_button;
|
||||
}
|
||||
|
@ -18,6 +18,7 @@ import {formatDateWithCFormatString} from '../misc/dateUtils.js';
|
||||
import {loadInterfaceXML} from '../misc/fileUtils.js';
|
||||
|
||||
const SHOW_WEEKDATE_KEY = 'show-weekdate';
|
||||
const MAX_NOTIFICATION_BUTTONS = 3;
|
||||
|
||||
const NC_ = (context, str) => `${context}\u0004${str}`;
|
||||
|
||||
@ -782,11 +783,19 @@ class NotificationMessage extends MessageList.Message {
|
||||
});
|
||||
notification.connectObject(
|
||||
'updated', this._onUpdated.bind(this),
|
||||
'action-added', (_, action) => this._addAction(action),
|
||||
'action-removed', (_, action) => this._removeAction(action),
|
||||
|
||||
'destroy', () => {
|
||||
this.notification = null;
|
||||
if (!this._closed)
|
||||
this.close();
|
||||
}, this);
|
||||
|
||||
this._actions = new Map();
|
||||
this.notification.actions.forEach(action => {
|
||||
this._addAction(action);
|
||||
});
|
||||
}
|
||||
|
||||
_getIcon() {
|
||||
@ -815,6 +824,36 @@ class NotificationMessage extends MessageList.Message {
|
||||
canClose() {
|
||||
return true;
|
||||
}
|
||||
|
||||
_addAction(action) {
|
||||
if (!this._buttonBox) {
|
||||
this._buttonBox = new St.BoxLayout({
|
||||
x_expand: true,
|
||||
style_class: 'notification-buttons-bin',
|
||||
});
|
||||
this.setActionArea(this._buttonBox);
|
||||
global.focus_manager.add_group(this._buttonBox);
|
||||
}
|
||||
|
||||
if (this._buttonBox.get_n_children() >= MAX_NOTIFICATION_BUTTONS)
|
||||
return;
|
||||
|
||||
const button = new St.Button({
|
||||
style_class: 'notification-button',
|
||||
x_expand: true,
|
||||
label: action.label,
|
||||
});
|
||||
|
||||
button.connect('clicked', () => action.activate());
|
||||
|
||||
this._actions.set(action, button);
|
||||
this._buttonBox.add_child(button);
|
||||
}
|
||||
|
||||
_removeAction(action) {
|
||||
this._actions.get(action)?.destroy();
|
||||
this._actions.delete(action);
|
||||
}
|
||||
});
|
||||
|
||||
const NotificationSection = GObject.registerClass(
|
||||
|
@ -469,7 +469,7 @@ export const Message = GObject.registerClass({
|
||||
});
|
||||
vbox.add_child(hbox);
|
||||
|
||||
this._actionBin = new St.Widget({
|
||||
this._actionBin = new St.Bin({
|
||||
layout_manager: new ScaleLayout(),
|
||||
visible: false,
|
||||
});
|
||||
@ -557,17 +557,8 @@ export const Message = GObject.registerClass({
|
||||
}
|
||||
|
||||
setActionArea(actor) {
|
||||
if (actor == null) {
|
||||
if (this._actionBin.get_n_children() > 0)
|
||||
this._actionBin.get_child_at_index(0).destroy();
|
||||
return;
|
||||
}
|
||||
|
||||
if (this._actionBin.get_n_children() > 0)
|
||||
throw new Error('Message already has an action area');
|
||||
|
||||
this._actionBin.add_child(actor);
|
||||
this._actionBin.visible = this.expanded;
|
||||
this._actionBin.child = actor;
|
||||
this._actionBin.visible = actor && this.expanded;
|
||||
}
|
||||
|
||||
addMediaControl(iconName, callback) {
|
||||
@ -583,7 +574,7 @@ export const Message = GObject.registerClass({
|
||||
expand(animate) {
|
||||
this.expanded = true;
|
||||
|
||||
this._actionBin.visible = this._actionBin.get_n_children() > 0;
|
||||
this._actionBin.visible = !!this._actionBin.child;
|
||||
|
||||
const duration = animate ? MessageTray.ANIMATION_TIME : 0;
|
||||
this._bodyStack.ease_property('@layout.expansion', 1, {
|
||||
|
@ -27,7 +27,6 @@ const LONGER_HIDE_TIMEOUT = 600;
|
||||
|
||||
const MAX_NOTIFICATIONS_IN_QUEUE = 3;
|
||||
const MAX_NOTIFICATIONS_PER_SOURCE = 3;
|
||||
const MAX_NOTIFICATION_BUTTONS = 3;
|
||||
|
||||
// We delay hiding of the tray if the mouse is within MOUSE_LEFT_ACTOR_THRESHOLD
|
||||
// range from the point where it left the tray.
|
||||
@ -498,7 +497,18 @@ export const Notification = GObject.registerClass({
|
||||
// @label: the label for the action's button
|
||||
// @callback: the callback for the action
|
||||
addAction(label, callback) {
|
||||
const action = new Action(label, callback);
|
||||
const action = new Action(label, () => {
|
||||
callback();
|
||||
|
||||
// We don't hide a resident notification when the user invokes one of its actions,
|
||||
// because it is common for such notifications to update themselves with new
|
||||
// information based on the action. We'd like to display the updated information
|
||||
// in place, rather than pop-up a new notification.
|
||||
if (this.resident)
|
||||
return;
|
||||
|
||||
this.destroy();
|
||||
});
|
||||
this.actions.push(action);
|
||||
this.emit('action-added', action);
|
||||
}
|
||||
@ -557,8 +567,14 @@ export const Notification = GObject.registerClass({
|
||||
activate() {
|
||||
this.emit('activated');
|
||||
|
||||
if (!this.resident)
|
||||
this.destroy();
|
||||
// We don't hide a resident notification when the user invokes one of its actions,
|
||||
// because it is common for such notifications to update themselves with new
|
||||
// information based on the action. We'd like to display the updated information
|
||||
// in place, rather than pop-up a new notification.
|
||||
if (this.resident)
|
||||
return;
|
||||
|
||||
this.destroy();
|
||||
}
|
||||
|
||||
destroy(reason = NotificationDestroyedReason.DISMISSED) {
|
||||
@ -579,10 +595,6 @@ export const NotificationBanner = GObject.registerClass({
|
||||
this.can_focus = false;
|
||||
this.add_style_class_name('notification-banner');
|
||||
|
||||
this._buttonBox = null;
|
||||
|
||||
this._addActions();
|
||||
|
||||
this.notification.connectObject('activated', () => {
|
||||
// We hide all types of notifications once the user clicks on
|
||||
// them because the common outcome of clicking should be the
|
||||
@ -591,64 +603,6 @@ export const NotificationBanner = GObject.registerClass({
|
||||
this.emit('done-displaying');
|
||||
}, this);
|
||||
}
|
||||
|
||||
_onUpdated(n, clear) {
|
||||
super._onUpdated(n, clear);
|
||||
|
||||
if (clear) {
|
||||
this.setActionArea(null);
|
||||
this._buttonBox = null;
|
||||
}
|
||||
|
||||
this._addActions();
|
||||
}
|
||||
|
||||
_addActions() {
|
||||
this.notification.actions.forEach(action => {
|
||||
this.addAction(action.label, () => action.activate());
|
||||
});
|
||||
}
|
||||
|
||||
addButton(button, callback) {
|
||||
if (!this._buttonBox) {
|
||||
this._buttonBox = new St.BoxLayout({
|
||||
style_class: 'notification-actions',
|
||||
x_expand: true,
|
||||
});
|
||||
this.setActionArea(this._buttonBox);
|
||||
global.focus_manager.add_group(this._buttonBox);
|
||||
}
|
||||
|
||||
if (this._buttonBox.get_n_children() >= MAX_NOTIFICATION_BUTTONS)
|
||||
return null;
|
||||
|
||||
this._buttonBox.add_child(button);
|
||||
button.connect('clicked', () => {
|
||||
callback();
|
||||
|
||||
if (!this.notification.resident) {
|
||||
// We don't hide a resident notification when the user invokes one of its actions,
|
||||
// because it is common for such notifications to update themselves with new
|
||||
// information based on the action. We'd like to display the updated information
|
||||
// in place, rather than pop-up a new notification.
|
||||
this.emit('done-displaying');
|
||||
this.notification.destroy();
|
||||
}
|
||||
});
|
||||
|
||||
return button;
|
||||
}
|
||||
|
||||
addAction(label, callback) {
|
||||
const button = new St.Button({
|
||||
style_class: 'notification-button',
|
||||
label,
|
||||
x_expand: true,
|
||||
can_focus: true,
|
||||
});
|
||||
|
||||
return this.addButton(button, callback);
|
||||
}
|
||||
});
|
||||
|
||||
export const Source = GObject.registerClass({
|
||||
|
Loading…
x
Reference in New Issue
Block a user