notification: Use the same Source for showing system notifications
This drops all subclasses of `MessageTray.Source` that were used to display system notifications. Now the `Source` returned from `MessageTray.getSystemSource()` is used. Ensure also that properties and methods that where set on the `Source` are moved to the `Notification` object itself. Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/3156>
This commit is contained in:
parent
3faf1caead
commit
c1ff00c01b
@ -6,7 +6,6 @@ import GObject from 'gi://GObject';
|
|||||||
import St from 'gi://St';
|
import St from 'gi://St';
|
||||||
|
|
||||||
import * as GnomeSession from '../../misc/gnomeSession.js';
|
import * as GnomeSession from '../../misc/gnomeSession.js';
|
||||||
import * as Main from '../main.js';
|
|
||||||
import * as MessageTray from '../messageTray.js';
|
import * as MessageTray from '../messageTray.js';
|
||||||
|
|
||||||
Gio._promisify(Gio.Mount.prototype, 'guess_content_type');
|
Gio._promisify(Gio.Mount.prototype, 'guess_content_type');
|
||||||
@ -165,7 +164,7 @@ class AutorunManager {
|
|||||||
class AutorunDispatcher {
|
class AutorunDispatcher {
|
||||||
constructor(manager) {
|
constructor(manager) {
|
||||||
this._manager = manager;
|
this._manager = manager;
|
||||||
this._sources = [];
|
this._notifications = new Map();
|
||||||
this._settings = new Gio.Settings({schema_id: SETTINGS_SCHEMA});
|
this._settings = new Gio.Settings({schema_id: SETTINGS_SCHEMA});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -185,26 +184,16 @@ class AutorunDispatcher {
|
|||||||
return AutorunSetting.ASK;
|
return AutorunSetting.ASK;
|
||||||
}
|
}
|
||||||
|
|
||||||
_getSourceForMount(mount) {
|
_addNotification(mount, apps) {
|
||||||
let filtered = this._sources.filter(source => source.mount === mount);
|
// Only show a new notification if there isn't already an existing one
|
||||||
|
if (this._notifications.has(mount))
|
||||||
// we always make sure not to add two sources for the same
|
|
||||||
// mount in addMount(), so it's safe to assume filtered.length
|
|
||||||
// is always either 1 or 0.
|
|
||||||
if (filtered.length === 1)
|
|
||||||
return filtered[0];
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
_addSource(mount, apps) {
|
|
||||||
// if we already have a source showing for this
|
|
||||||
// mount, return
|
|
||||||
if (this._getSourceForMount(mount))
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// add a new source
|
const source = MessageTray.getSystemSource();
|
||||||
this._sources.push(new AutorunSource(this._manager, mount, apps));
|
const notification = new AutorunNotification(source, mount, apps);
|
||||||
|
notification.connect('destroy', () => this._notifications.delete(mount));
|
||||||
|
this._notifications.set(mount, notification);
|
||||||
|
source.showNotification(notification);
|
||||||
}
|
}
|
||||||
|
|
||||||
addMount(mount, apps, contentTypes) {
|
addMount(mount, apps, contentTypes) {
|
||||||
@ -241,58 +230,29 @@ class AutorunDispatcher {
|
|||||||
// we fallback here also in case the settings did not specify 'ask',
|
// we fallback here also in case the settings did not specify 'ask',
|
||||||
// but we failed launching the default app or the default file manager
|
// but we failed launching the default app or the default file manager
|
||||||
if (!success)
|
if (!success)
|
||||||
this._addSource(mount, apps);
|
this._addNotification(mount, apps);
|
||||||
}
|
}
|
||||||
|
|
||||||
removeMount(mount) {
|
removeMount(mount) {
|
||||||
let source = this._getSourceForMount(mount);
|
this._notifications.get(mount)?.destroy();
|
||||||
|
|
||||||
// if we aren't tracking this mount, don't do anything
|
|
||||||
if (!source)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// destroy the notification source
|
|
||||||
source.destroy();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const AutorunSource = GObject.registerClass(
|
|
||||||
class AutorunSource extends MessageTray.Source {
|
|
||||||
constructor(manager, mount, apps) {
|
|
||||||
super({
|
|
||||||
title: mount.get_name(),
|
|
||||||
icon: mount.get_icon(),
|
|
||||||
});
|
|
||||||
|
|
||||||
this._manager = manager;
|
|
||||||
this.mount = mount;
|
|
||||||
this.apps = apps;
|
|
||||||
|
|
||||||
this._notification = new AutorunNotification(this._manager, this);
|
|
||||||
|
|
||||||
// add ourselves as a source, and popup the notification
|
|
||||||
Main.messageTray.add(this);
|
|
||||||
this.showNotification(this._notification);
|
|
||||||
}
|
|
||||||
|
|
||||||
_createPolicy() {
|
|
||||||
return new MessageTray.NotificationApplicationPolicy('org.gnome.Nautilus');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const AutorunNotification = GObject.registerClass(
|
const AutorunNotification = GObject.registerClass(
|
||||||
class AutorunNotification extends MessageTray.Notification {
|
class AutorunNotification extends MessageTray.Notification {
|
||||||
_init(manager, source) {
|
constructor(source, mount, apps) {
|
||||||
super._init(source, source.title);
|
super(source, mount.get_name());
|
||||||
|
|
||||||
this._manager = manager;
|
this.gicon = mount.get_icon();
|
||||||
this._mount = source.mount;
|
|
||||||
|
this._mount = mount;
|
||||||
|
this._apps = apps;
|
||||||
}
|
}
|
||||||
|
|
||||||
createBanner() {
|
createBanner() {
|
||||||
let banner = new MessageTray.NotificationBanner(this);
|
let banner = new MessageTray.NotificationBanner(this);
|
||||||
|
|
||||||
this.source.apps.forEach(app => {
|
this._apps.forEach(app => {
|
||||||
let actor = this._buttonForApp(app);
|
let actor = this._buttonForApp(app);
|
||||||
|
|
||||||
if (actor)
|
if (actor)
|
||||||
|
@ -11,7 +11,6 @@ import St from 'gi://St';
|
|||||||
import * as Signals from '../../misc/signals.js';
|
import * as Signals from '../../misc/signals.js';
|
||||||
|
|
||||||
import * as Dialog from '../dialog.js';
|
import * as Dialog from '../dialog.js';
|
||||||
import * as Main from '../main.js';
|
|
||||||
import * as MessageTray from '../messageTray.js';
|
import * as MessageTray from '../messageTray.js';
|
||||||
import * as ModalDialog from '../modalDialog.js';
|
import * as ModalDialog from '../modalDialog.js';
|
||||||
import * as ShellEntry from '../shellEntry.js';
|
import * as ShellEntry from '../shellEntry.js';
|
||||||
@ -740,12 +739,6 @@ class NetworkAgent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_showNotification(requestId, connection, settingName, hints, flags) {
|
_showNotification(requestId, connection, settingName, hints, flags) {
|
||||||
const source = new MessageTray.Source({
|
|
||||||
title: _('Network Manager'),
|
|
||||||
iconName: 'network-transmit-receive',
|
|
||||||
});
|
|
||||||
source.policy = new MessageTray.NotificationApplicationPolicy('gnome-network-panel');
|
|
||||||
|
|
||||||
let title, body;
|
let title, body;
|
||||||
|
|
||||||
let connectionSetting = connection.get_setting_connection();
|
let connectionSetting = connection.get_setting_connection();
|
||||||
@ -788,7 +781,9 @@ class NetworkAgent {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let notification = new MessageTray.Notification(source, title, body);
|
const source = new MessageTray.getSystemSource();
|
||||||
|
const notification = new MessageTray.Notification(source, title, body);
|
||||||
|
notification.iconName = 'dialog-password-symbolic';
|
||||||
|
|
||||||
notification.connect('activated', () => {
|
notification.connect('activated', () => {
|
||||||
notification.answered = true;
|
notification.answered = true;
|
||||||
@ -802,7 +797,6 @@ class NetworkAgent {
|
|||||||
delete this._notifications[requestId];
|
delete this._notifications[requestId];
|
||||||
});
|
});
|
||||||
|
|
||||||
Main.messageTray.add(source);
|
|
||||||
source.showNotification(notification);
|
source.showNotification(notification);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -274,8 +274,7 @@ async function _initializeUI() {
|
|||||||
if (lookingGlass?.isOpen)
|
if (lookingGlass?.isOpen)
|
||||||
return; // assume user action
|
return; // assume user action
|
||||||
|
|
||||||
const source = new MessageTray.SystemNotificationSource();
|
const source = MessageTray.getSystemSource();
|
||||||
messageTray.add(source);
|
|
||||||
const notification = new MessageTray.Notification(source,
|
const notification = new MessageTray.Notification(source,
|
||||||
_('System was put in unsafe mode'),
|
_('System was put in unsafe mode'),
|
||||||
_('Apps now have unrestricted access'));
|
_('Apps now have unrestricted access'));
|
||||||
@ -615,8 +614,7 @@ export function loadTheme() {
|
|||||||
* @param {string} details Additional information
|
* @param {string} details Additional information
|
||||||
*/
|
*/
|
||||||
export function notify(msg, details) {
|
export function notify(msg, details) {
|
||||||
let source = new MessageTray.SystemNotificationSource();
|
const source = MessageTray.getSystemSource();
|
||||||
messageTray.add(source);
|
|
||||||
let notification = new MessageTray.Notification(source, msg, details);
|
let notification = new MessageTray.Notification(source, msg, details);
|
||||||
notification.setTransient(true);
|
notification.setTransient(true);
|
||||||
source.showNotification(notification);
|
source.showNotification(notification);
|
||||||
|
@ -1348,17 +1348,3 @@ export function getSystemSource() {
|
|||||||
|
|
||||||
return systemNotificationSource;
|
return systemNotificationSource;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const SystemNotificationSource = GObject.registerClass(
|
|
||||||
class SystemNotificationSource extends Source {
|
|
||||||
constructor() {
|
|
||||||
super({
|
|
||||||
title: _('System Information'),
|
|
||||||
iconName: 'dialog-information-symbolic',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
open() {
|
|
||||||
this.destroy();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
@ -28,41 +28,29 @@ const DND_WINDOW_SWITCH_TIMEOUT = 750;
|
|||||||
const OVERVIEW_ACTIVATION_TIMEOUT = 0.5;
|
const OVERVIEW_ACTIVATION_TIMEOUT = 0.5;
|
||||||
|
|
||||||
class ShellInfo {
|
class ShellInfo {
|
||||||
constructor() {
|
|
||||||
this._source = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
setMessage(text, options) {
|
setMessage(text, options) {
|
||||||
options = Params.parse(options, {
|
options = Params.parse(options, {
|
||||||
undoCallback: null,
|
undoCallback: null,
|
||||||
forFeedback: false,
|
forFeedback: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const source = MessageTray.getSystemSource();
|
||||||
let undoCallback = options.undoCallback;
|
let undoCallback = options.undoCallback;
|
||||||
let forFeedback = options.forFeedback;
|
let forFeedback = options.forFeedback;
|
||||||
|
|
||||||
if (this._source == null) {
|
if (!this._notification) {
|
||||||
this._source = new MessageTray.SystemNotificationSource();
|
this._notification = new MessageTray.Notification(source, text, null);
|
||||||
this._source.connect('destroy', () => {
|
this._notification.setTransient(true);
|
||||||
this._source = null;
|
this._notification.setForFeedback(forFeedback);
|
||||||
});
|
this._notification.connect('destroy', () => delete this._notification);
|
||||||
Main.messageTray.add(this._source);
|
|
||||||
}
|
|
||||||
|
|
||||||
let notification = null;
|
|
||||||
if (this._source.notifications.length === 0) {
|
|
||||||
notification = new MessageTray.Notification(this._source, text, null);
|
|
||||||
notification.setTransient(true);
|
|
||||||
notification.setForFeedback(forFeedback);
|
|
||||||
} else {
|
} else {
|
||||||
notification = this._source.notifications[0];
|
this._notification.update(text, null, {clear: true});
|
||||||
notification.update(text, null, {clear: true});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (undoCallback)
|
if (undoCallback)
|
||||||
notification.addAction(_('Undo'), () => undoCallback());
|
this._notification.addAction(_('Undo'), () => undoCallback());
|
||||||
|
|
||||||
this._source.showNotification(notification);
|
source.showNotification(this._notification);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,7 +11,6 @@ import St from 'gi://St';
|
|||||||
import * as Animation from './animation.js';
|
import * as Animation from './animation.js';
|
||||||
import * as CheckBox from './checkBox.js';
|
import * as CheckBox from './checkBox.js';
|
||||||
import * as Dialog from './dialog.js';
|
import * as Dialog from './dialog.js';
|
||||||
import * as Main from './main.js';
|
|
||||||
import * as MessageTray from './messageTray.js';
|
import * as MessageTray from './messageTray.js';
|
||||||
import * as ModalDialog from './modalDialog.js';
|
import * as ModalDialog from './modalDialog.js';
|
||||||
import * as Params from '../misc/params.js';
|
import * as Params from '../misc/params.js';
|
||||||
@ -181,61 +180,44 @@ export class ShellMountOperation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_onShowUnmountProgress(op, message, timeLeft, bytesLeft) {
|
_onShowUnmountProgress(op, message, timeLeft, bytesLeft) {
|
||||||
if (!this._notifier)
|
|
||||||
this._notifier = new ShellUnmountNotifier();
|
|
||||||
|
|
||||||
if (bytesLeft === 0)
|
if (bytesLeft === 0)
|
||||||
this._notifier.done(message);
|
this._showUnmountNotificationDone(message);
|
||||||
else
|
else
|
||||||
this._notifier.show(message);
|
this._showUnmountNotification(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
borrowDialog() {
|
borrowDialog() {
|
||||||
this._dialog?.disconnectObject(this);
|
this._dialog?.disconnectObject(this);
|
||||||
return this._dialog;
|
return this._dialog;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_createNotification(title, body) {
|
||||||
|
this._notification?.destroy();
|
||||||
|
|
||||||
|
const source = MessageTray.getSystemSource();
|
||||||
|
this._notification = new MessageTray.Notification(source, title, body);
|
||||||
|
|
||||||
|
this._notification.setTransient(true);
|
||||||
|
this._notification.iconName = 'media-removable-symbolic';
|
||||||
|
this._notification.connect('destroy', () => delete this._notification);
|
||||||
|
source.showNotification(this._notification);
|
||||||
|
}
|
||||||
|
|
||||||
|
_showUnmountNotificationDone(message) {
|
||||||
|
if (message)
|
||||||
|
this._createNotification(message, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
_showUnmountNotification(message) {
|
||||||
|
const [title, body] = message.split('\n', 2);
|
||||||
|
|
||||||
|
if (!this._notification)
|
||||||
|
this._createNotification(title, body);
|
||||||
|
else
|
||||||
|
this._notification.update(title, body);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const ShellUnmountNotifier = GObject.registerClass(
|
|
||||||
class ShellUnmountNotifier extends MessageTray.Source {
|
|
||||||
constructor() {
|
|
||||||
super({
|
|
||||||
iconName: 'media-removable',
|
|
||||||
});
|
|
||||||
|
|
||||||
this._notification = null;
|
|
||||||
Main.messageTray.add(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
show(message) {
|
|
||||||
let [header, text] = message.split('\n', 2);
|
|
||||||
|
|
||||||
if (!this._notification) {
|
|
||||||
this._notification = new MessageTray.Notification(this, header, text);
|
|
||||||
this._notification.setTransient(true);
|
|
||||||
this._notification.setUrgency(MessageTray.Urgency.CRITICAL);
|
|
||||||
} else {
|
|
||||||
this._notification.update(header, text);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.showNotification(this._notification);
|
|
||||||
}
|
|
||||||
|
|
||||||
done(message) {
|
|
||||||
if (this._notification) {
|
|
||||||
this._notification.destroy();
|
|
||||||
this._notification = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (message) {
|
|
||||||
let notification = new MessageTray.Notification(this, message, null);
|
|
||||||
notification.setTransient(true);
|
|
||||||
|
|
||||||
this.showNotification(notification);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const ShellMountQuestionDialog = GObject.registerClass({
|
const ShellMountQuestionDialog = GObject.registerClass({
|
||||||
Signals: {'response': {param_types: [GObject.TYPE_INT]}},
|
Signals: {'response': {param_types: [GObject.TYPE_INT]}},
|
||||||
}, class ShellMountQuestionDialog extends ModalDialog.ModalDialog {
|
}, class ShellMountQuestionDialog extends ModalDialog.ModalDialog {
|
||||||
|
@ -2036,16 +2036,11 @@ class Indicator extends SystemIndicator {
|
|||||||
_onActivationFailed() {
|
_onActivationFailed() {
|
||||||
this._notification?.destroy();
|
this._notification?.destroy();
|
||||||
|
|
||||||
const source = new MessageTray.Source({
|
const source = MessageTray.getSystemSource();
|
||||||
title: _('Network Manager'),
|
|
||||||
iconName: 'network-error-symbolic',
|
|
||||||
});
|
|
||||||
source.policy =
|
|
||||||
new MessageTray.NotificationApplicationPolicy('gnome-network-panel');
|
|
||||||
|
|
||||||
this._notification = new MessageTray.Notification(source,
|
this._notification = new MessageTray.Notification(source,
|
||||||
_('Connection failed'),
|
_('Connection failed'),
|
||||||
_('Activation of network connection failed'));
|
_('Activation of network connection failed'));
|
||||||
|
this._notification.iconName = 'network-error-symbolic';
|
||||||
this._notification.setUrgency(MessageTray.Urgency.HIGH);
|
this._notification.setUrgency(MessageTray.Urgency.HIGH);
|
||||||
this._notification.setTransient(true);
|
this._notification.setTransient(true);
|
||||||
this._notification.connect('destroy',
|
this._notification.connect('destroy',
|
||||||
|
@ -236,7 +236,6 @@ class Indicator extends SystemIndicator {
|
|||||||
Main.sessionMode.connect('updated', this._sync.bind(this));
|
Main.sessionMode.connect('updated', this._sync.bind(this));
|
||||||
this._sync();
|
this._sync();
|
||||||
|
|
||||||
this._source = null;
|
|
||||||
this._perm = null;
|
this._perm = null;
|
||||||
this._createPermission();
|
this._createPermission();
|
||||||
}
|
}
|
||||||
@ -254,27 +253,13 @@ class Indicator extends SystemIndicator {
|
|||||||
this._client.close();
|
this._client.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
_ensureSource() {
|
|
||||||
if (!this._source) {
|
|
||||||
this._source = new MessageTray.Source({
|
|
||||||
title: _('Thunderbolt'),
|
|
||||||
iconName: 'thunderbolt-symbolic',
|
|
||||||
});
|
|
||||||
this._source.connect('destroy', () => (this._source = null));
|
|
||||||
|
|
||||||
Main.messageTray.add(this._source);
|
|
||||||
}
|
|
||||||
|
|
||||||
return this._source;
|
|
||||||
}
|
|
||||||
|
|
||||||
_notify(title, body) {
|
_notify(title, body) {
|
||||||
if (this._notification)
|
if (this._notification)
|
||||||
this._notification.destroy();
|
this._notification.destroy();
|
||||||
|
|
||||||
let source = this._ensureSource();
|
const source = MessageTray.getSystemSource();
|
||||||
|
|
||||||
this._notification = new MessageTray.Notification(source, title, body);
|
this._notification = new MessageTray.Notification(source, title, body);
|
||||||
|
this._notification.iconName = 'thunderbolt-symbolic';
|
||||||
this._notification.setUrgency(MessageTray.Urgency.HIGH);
|
this._notification.setUrgency(MessageTray.Urgency.HIGH);
|
||||||
this._notification.connect('destroy', () => {
|
this._notification.connect('destroy', () => {
|
||||||
this._notification = null;
|
this._notification = null;
|
||||||
|
@ -50,8 +50,7 @@ export async function run() {
|
|||||||
|
|
||||||
// notification
|
// notification
|
||||||
console.debug('Show notification message');
|
console.debug('Show notification message');
|
||||||
const source = new MessageTray.SystemNotificationSource();
|
const source = new MessageTray.getSystemSource();
|
||||||
Main.messageTray.add(source);
|
|
||||||
|
|
||||||
Scripting.scriptEvent('notificationShowStart');
|
Scripting.scriptEvent('notificationShowStart');
|
||||||
source.connect('notification-show',
|
source.connect('notification-show',
|
||||||
|
Loading…
x
Reference in New Issue
Block a user