From b7feb714908a9826406d5bbc61ea2e653f49bcb0 Mon Sep 17 00:00:00 2001 From: Georges Basile Stavracas Neto Date: Mon, 7 Oct 2019 16:19:30 -0300 Subject: [PATCH] screenShield: Move notification box to UnlockDialog --- js/ui/screenShield.js | 272 ---------------------------------------- js/ui/unlockDialog.js | 280 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 280 insertions(+), 272 deletions(-) diff --git a/js/ui/screenShield.js b/js/ui/screenShield.js index 63032d89c..f37ad346c 100644 --- a/js/ui/screenShield.js +++ b/js/ui/screenShield.js @@ -45,266 +45,6 @@ var STANDARD_FADE_TIME = 10000; var MANUAL_FADE_TIME = 300; var CURTAIN_SLIDE_TIME = 300; -var NotificationsBox = class { - constructor() { - this.actor = new St.BoxLayout({ vertical: true, - name: 'screenShieldNotifications', - style_class: 'screen-shield-notifications-container' }); - - this._scrollView = new St.ScrollView({ x_fill: false, x_align: St.Align.START, - hscrollbar_policy: St.PolicyType.NEVER }); - this._notificationBox = new St.BoxLayout({ vertical: true, - style_class: 'screen-shield-notifications-container' }); - this._scrollView.add_actor(this._notificationBox); - - this.actor.add(this._scrollView, { x_fill: true, x_align: St.Align.START }); - - this._sources = new Map(); - Main.messageTray.getSources().forEach(source => { - this._sourceAdded(Main.messageTray, source, true); - }); - this._updateVisibility(); - - this._sourceAddedId = Main.messageTray.connect('source-added', this._sourceAdded.bind(this)); - } - - destroy() { - if (this._sourceAddedId) { - Main.messageTray.disconnect(this._sourceAddedId); - this._sourceAddedId = 0; - } - - let items = this._sources.entries(); - for (let [source, obj] of items) { - this._removeSource(source, obj); - } - - this.actor.destroy(); - } - - _updateVisibility() { - this._notificationBox.visible = - this._notificationBox.get_children().some(a => a.visible); - - this.actor.visible = this._notificationBox.visible; - } - - _makeNotificationCountText(count, isChat) { - if (isChat) - return ngettext("%d new message", "%d new messages", count).format(count); - else - return ngettext("%d new notification", "%d new notifications", count).format(count); - } - - _makeNotificationSource(source, box) { - let sourceActor = new MessageTray.SourceActor(source, SUMMARY_ICON_SIZE); - box.add(sourceActor, { y_fill: true }); - - let textBox = new St.BoxLayout({ vertical: true }); - box.add(textBox, { y_fill: false, y_align: St.Align.START }); - - let title = new St.Label({ text: source.title, - style_class: 'screen-shield-notification-label' }); - textBox.add(title); - - let count = source.unseenCount; - let countLabel = new St.Label({ text: this._makeNotificationCountText(count, source.isChat), - style_class: 'screen-shield-notification-count-text' }); - textBox.add(countLabel); - - box.visible = count != 0; - return [title, countLabel]; - } - - _makeNotificationDetailedSource(source, box) { - let sourceActor = new MessageTray.SourceActor(source, SUMMARY_ICON_SIZE); - let sourceBin = new St.Bin({ y_align: St.Align.START, - x_align: St.Align.START, - child: sourceActor }); - box.add(sourceBin); - - let textBox = new St.BoxLayout({ vertical: true }); - box.add(textBox, { y_fill: false, y_align: St.Align.START }); - - let title = new St.Label({ text: source.title, - style_class: 'screen-shield-notification-label' }); - textBox.add(title); - - let visible = false; - for (let i = 0; i < source.notifications.length; i++) { - let n = source.notifications[i]; - - if (n.acknowledged) - continue; - - let body = ''; - if (n.bannerBodyText) { - body = n.bannerBodyMarkup - ? n.bannerBodyText - : GLib.markup_escape_text(n.bannerBodyText, -1); - } - - let label = new St.Label({ style_class: 'screen-shield-notification-count-text' }); - label.clutter_text.set_markup('' + n.title + ' ' + body); - textBox.add(label); - - visible = true; - } - - box.visible = visible; - return [title, null]; - } - - _shouldShowDetails(source) { - return source.policy.detailsInLockScreen || - source.narrowestPrivacyScope == MessageTray.PrivacyScope.SYSTEM; - } - - _showSource(source, obj, box) { - if (obj.detailed) { - [obj.titleLabel, obj.countLabel] = this._makeNotificationDetailedSource(source, box); - } else { - [obj.titleLabel, obj.countLabel] = this._makeNotificationSource(source, box); - } - - box.visible = obj.visible && (source.unseenCount > 0); - } - - _sourceAdded(tray, source, initial) { - let obj = { - visible: source.policy.showInLockScreen, - detailed: this._shouldShowDetails(source), - sourceDestroyId: 0, - sourceCountChangedId: 0, - sourceTitleChangedId: 0, - sourceUpdatedId: 0, - sourceBox: null, - titleLabel: null, - countLabel: null, - }; - - obj.sourceBox = new St.BoxLayout({ style_class: 'screen-shield-notification-source', - x_expand: true }); - this._showSource(source, obj, obj.sourceBox); - this._notificationBox.add(obj.sourceBox, { x_fill: false, x_align: St.Align.START }); - - obj.sourceCountChangedId = source.connect('count-updated', source => { - this._countChanged(source, obj); - }); - obj.sourceTitleChangedId = source.connect('title-changed', source => { - this._titleChanged(source, obj); - }); - obj.policyChangedId = source.policy.connect('policy-changed', (policy, key) => { - if (key == 'show-in-lock-screen') - this._visibleChanged(source, obj); - else - this._detailedChanged(source, obj); - }); - obj.sourceDestroyId = source.connect('destroy', source => { - this._onSourceDestroy(source, obj); - }); - - this._sources.set(source, obj); - - if (!initial) { - // block scrollbars while animating, if they're not needed now - let boxHeight = this._notificationBox.height; - if (this._scrollView.height >= boxHeight) - this._scrollView.vscrollbar_policy = St.PolicyType.NEVER; - - let widget = obj.sourceBox; - let [, natHeight] = widget.get_preferred_height(-1); - widget.height = 0; - widget.ease({ - height: natHeight, - mode: Clutter.AnimationMode.EASE_OUT_QUAD, - duration: 250, - onComplete: () => { - this._scrollView.vscrollbar_policy = St.PolicyType.AUTOMATIC; - widget.set_height(-1); - } - }); - - this._updateVisibility(); - if (obj.sourceBox.visible) - this.emit('wake-up-screen'); - } - } - - _titleChanged(source, obj) { - obj.titleLabel.text = source.title; - } - - _countChanged(source, obj) { - // A change in the number of notifications may change whether we show - // details. - let newDetailed = this._shouldShowDetails(source); - let oldDetailed = obj.detailed; - - obj.detailed = newDetailed; - - if (obj.detailed || oldDetailed != newDetailed) { - // A new notification was pushed, or a previous notification was destroyed. - // Give up, and build the list again. - - obj.sourceBox.destroy_all_children(); - obj.titleLabel = obj.countLabel = null; - this._showSource(source, obj, obj.sourceBox); - } else { - let count = source.unseenCount; - obj.countLabel.text = this._makeNotificationCountText(count, source.isChat); - } - - obj.sourceBox.visible = obj.visible && (source.unseenCount > 0); - - this._updateVisibility(); - if (obj.sourceBox.visible) - this.emit('wake-up-screen'); - } - - _visibleChanged(source, obj) { - if (obj.visible == source.policy.showInLockScreen) - return; - - obj.visible = source.policy.showInLockScreen; - obj.sourceBox.visible = obj.visible && source.unseenCount > 0; - - this._updateVisibility(); - if (obj.sourceBox.visible) - this.emit('wake-up-screen'); - } - - _detailedChanged(source, obj) { - let newDetailed = this._shouldShowDetails(source); - if (obj.detailed == newDetailed) - return; - - obj.detailed = newDetailed; - - obj.sourceBox.destroy_all_children(); - obj.titleLabel = obj.countLabel = null; - this._showSource(source, obj, obj.sourceBox); - } - - _onSourceDestroy(source, obj) { - this._removeSource(source, obj); - this._updateVisibility(); - } - - _removeSource(source, obj) { - obj.sourceBox.destroy(); - obj.sourceBox = obj.titleLabel = obj.countLabel = null; - - source.disconnect(obj.sourceDestroyId); - source.disconnect(obj.sourceCountChangedId); - source.disconnect(obj.sourceTitleChangedId); - source.policy.disconnect(obj.policyChangedId); - - this._sources.delete(source); - } -}; -Signals.addSignalMethods(NotificationsBox.prototype); - function clamp(value, min, max) { return Math.max(min, Math.min(max, value)); } @@ -948,12 +688,6 @@ var ScreenShield = class { this._lockScreenContents.add_actor(this._lockScreenContentsBox); - this._notificationsBox = new NotificationsBox(); - this._wakeUpScreenId = this._notificationsBox.connect('wake-up-screen', this._wakeUpScreen.bind(this)); - this._lockScreenContentsBox.add(this._notificationsBox.actor, { x_fill: true, - y_fill: true, - expand: true }); - this._hasLockScreen = true; } @@ -963,12 +697,6 @@ var ScreenShield = class { } _clearLockScreen() { - if (this._notificationsBox) { - this._notificationsBox.disconnect(this._wakeUpScreenId); - this._notificationsBox.destroy(); - this._notificationsBox = null; - } - this._lockScreenContentsBox.destroy(); this._hasLockScreen = false; diff --git a/js/ui/unlockDialog.js b/js/ui/unlockDialog.js index 47ae79c68..d1b496347 100644 --- a/js/ui/unlockDialog.js +++ b/js/ui/unlockDialog.js @@ -6,12 +6,16 @@ const { AccountsService, Atk, Clutter, Gdm, Gio, GLib, const Layout = imports.ui.layout; const Main = imports.ui.main; +const MessageTray = imports.ui.messageTray; +const Signals = imports.signals; const AuthPrompt = imports.gdm.authPrompt; // The timeout before going back automatically to the lock screen (in seconds) const IDLE_TIMEOUT = 2 * 60; +var SUMMARY_ICON_SIZE = 48; + var Clock = class { constructor() { this.actor = new St.BoxLayout({ @@ -47,6 +51,266 @@ var Clock = class { } }; +var NotificationsBox = class { + constructor() { + this.actor = new St.BoxLayout({ vertical: true, + name: 'screenShieldNotifications', + style_class: 'screen-shield-notifications-container' }); + + this._scrollView = new St.ScrollView({ x_fill: false, x_align: St.Align.START, + hscrollbar_policy: St.PolicyType.NEVER }); + this._notificationBox = new St.BoxLayout({ vertical: true, + style_class: 'screen-shield-notifications-container' }); + this._scrollView.add_actor(this._notificationBox); + + this.actor.add(this._scrollView, { x_fill: true, x_align: St.Align.START }); + + this._sources = new Map(); + Main.messageTray.getSources().forEach(source => { + this._sourceAdded(Main.messageTray, source, true); + }); + this._updateVisibility(); + + this._sourceAddedId = Main.messageTray.connect('source-added', this._sourceAdded.bind(this)); + } + + destroy() { + if (this._sourceAddedId) { + Main.messageTray.disconnect(this._sourceAddedId); + this._sourceAddedId = 0; + } + + let items = this._sources.entries(); + for (let [source, obj] of items) { + this._removeSource(source, obj); + } + + this.actor.destroy(); + } + + _updateVisibility() { + this._notificationBox.visible = + this._notificationBox.get_children().some(a => a.visible); + + this.actor.visible = this._notificationBox.visible; + } + + _makeNotificationCountText(count, isChat) { + if (isChat) + return ngettext("%d new message", "%d new messages", count).format(count); + else + return ngettext("%d new notification", "%d new notifications", count).format(count); + } + + _makeNotificationSource(source, box) { + let sourceActor = new MessageTray.SourceActor(source, SUMMARY_ICON_SIZE); + box.add(sourceActor, { y_fill: true }); + + let textBox = new St.BoxLayout({ vertical: true }); + box.add(textBox, { y_fill: false, y_align: St.Align.START }); + + let title = new St.Label({ text: source.title, + style_class: 'screen-shield-notification-label' }); + textBox.add(title); + + let count = source.unseenCount; + let countLabel = new St.Label({ text: this._makeNotificationCountText(count, source.isChat), + style_class: 'screen-shield-notification-count-text' }); + textBox.add(countLabel); + + box.visible = count != 0; + return [title, countLabel]; + } + + _makeNotificationDetailedSource(source, box) { + let sourceActor = new MessageTray.SourceActor(source, SUMMARY_ICON_SIZE); + let sourceBin = new St.Bin({ y_align: St.Align.START, + x_align: St.Align.START, + child: sourceActor }); + box.add(sourceBin); + + let textBox = new St.BoxLayout({ vertical: true }); + box.add(textBox, { y_fill: false, y_align: St.Align.START }); + + let title = new St.Label({ text: source.title, + style_class: 'screen-shield-notification-label' }); + textBox.add(title); + + let visible = false; + for (let i = 0; i < source.notifications.length; i++) { + let n = source.notifications[i]; + + if (n.acknowledged) + continue; + + let body = ''; + if (n.bannerBodyText) { + body = n.bannerBodyMarkup + ? n.bannerBodyText + : GLib.markup_escape_text(n.bannerBodyText, -1); + } + + let label = new St.Label({ style_class: 'screen-shield-notification-count-text' }); + label.clutter_text.set_markup('' + n.title + ' ' + body); + textBox.add(label); + + visible = true; + } + + box.visible = visible; + return [title, null]; + } + + _shouldShowDetails(source) { + return source.policy.detailsInLockScreen || + source.narrowestPrivacyScope == MessageTray.PrivacyScope.SYSTEM; + } + + _showSource(source, obj, box) { + if (obj.detailed) { + [obj.titleLabel, obj.countLabel] = this._makeNotificationDetailedSource(source, box); + } else { + [obj.titleLabel, obj.countLabel] = this._makeNotificationSource(source, box); + } + + box.visible = obj.visible && (source.unseenCount > 0); + } + + _sourceAdded(tray, source, initial) { + let obj = { + visible: source.policy.showInLockScreen, + detailed: this._shouldShowDetails(source), + sourceDestroyId: 0, + sourceCountChangedId: 0, + sourceTitleChangedId: 0, + sourceUpdatedId: 0, + sourceBox: null, + titleLabel: null, + countLabel: null, + }; + + obj.sourceBox = new St.BoxLayout({ style_class: 'screen-shield-notification-source', + x_expand: true }); + this._showSource(source, obj, obj.sourceBox); + this._notificationBox.add(obj.sourceBox, { x_fill: false, x_align: St.Align.START }); + + obj.sourceCountChangedId = source.connect('count-updated', source => { + this._countChanged(source, obj); + }); + obj.sourceTitleChangedId = source.connect('title-changed', source => { + this._titleChanged(source, obj); + }); + obj.policyChangedId = source.policy.connect('policy-changed', (policy, key) => { + if (key == 'show-in-lock-screen') + this._visibleChanged(source, obj); + else + this._detailedChanged(source, obj); + }); + obj.sourceDestroyId = source.connect('destroy', source => { + this._onSourceDestroy(source, obj); + }); + + this._sources.set(source, obj); + + if (!initial) { + // block scrollbars while animating, if they're not needed now + let boxHeight = this._notificationBox.height; + if (this._scrollView.height >= boxHeight) + this._scrollView.vscrollbar_policy = St.PolicyType.NEVER; + + let widget = obj.sourceBox; + let [, natHeight] = widget.get_preferred_height(-1); + widget.height = 0; + widget.ease({ + height: natHeight, + mode: Clutter.AnimationMode.EASE_OUT_QUAD, + duration: 250, + onComplete: () => { + this._scrollView.vscrollbar_policy = St.PolicyType.AUTOMATIC; + widget.set_height(-1); + } + }); + + this._updateVisibility(); + if (obj.sourceBox.visible) + this.emit('wake-up-screen'); + } + } + + _titleChanged(source, obj) { + obj.titleLabel.text = source.title; + } + + _countChanged(source, obj) { + // A change in the number of notifications may change whether we show + // details. + let newDetailed = this._shouldShowDetails(source); + let oldDetailed = obj.detailed; + + obj.detailed = newDetailed; + + if (obj.detailed || oldDetailed != newDetailed) { + // A new notification was pushed, or a previous notification was destroyed. + // Give up, and build the list again. + + obj.sourceBox.destroy_all_children(); + obj.titleLabel = obj.countLabel = null; + this._showSource(source, obj, obj.sourceBox); + } else { + let count = source.unseenCount; + obj.countLabel.text = this._makeNotificationCountText(count, source.isChat); + } + + obj.sourceBox.visible = obj.visible && (source.unseenCount > 0); + + this._updateVisibility(); + if (obj.sourceBox.visible) + this.emit('wake-up-screen'); + } + + _visibleChanged(source, obj) { + if (obj.visible == source.policy.showInLockScreen) + return; + + obj.visible = source.policy.showInLockScreen; + obj.sourceBox.visible = obj.visible && source.unseenCount > 0; + + this._updateVisibility(); + if (obj.sourceBox.visible) + this.emit('wake-up-screen'); + } + + _detailedChanged(source, obj) { + let newDetailed = this._shouldShowDetails(source); + if (obj.detailed == newDetailed) + return; + + obj.detailed = newDetailed; + + obj.sourceBox.destroy_all_children(); + obj.titleLabel = obj.countLabel = null; + this._showSource(source, obj, obj.sourceBox); + } + + _onSourceDestroy(source, obj) { + this._removeSource(source, obj); + this._updateVisibility(); + } + + _removeSource(source, obj) { + obj.sourceBox.destroy(); + obj.sourceBox = obj.titleLabel = obj.countLabel = null; + + source.disconnect(obj.sourceDestroyId); + source.disconnect(obj.sourceCountChangedId); + source.disconnect(obj.sourceTitleChangedId); + source.policy.disconnect(obj.policyChangedId); + + this._sources.delete(source); + } +}; +Signals.addSignalMethods(NotificationsBox.prototype); + var UnlockDialog = GObject.registerClass({ Signals: { 'failed': {} }, }, class UnlockDialog extends St.Widget { @@ -104,6 +368,10 @@ var UnlockDialog = GObject.registerClass({ this._otherUserButton = null; } + this._notificationsBox = new NotificationsBox(); + this._wakeUpScreenId = this._notificationsBox.connect('wake-up-screen', this._wakeUpScreen.bind(this)); + this._mainBox.add_child(this._notificationsBox.actor); + this._authPrompt.reset(); this._updateSensitivity(true); @@ -151,9 +419,21 @@ var UnlockDialog = GObject.registerClass({ this._authPrompt.cancel(); } + _wakeUpScreen() { + // FIXME + //this._onUserBecameActive(); + this.emit('wake-up-screen'); + } + _onDestroy() { this.popModal(); + if (this._notificationsBox) { + this._notificationsBox.disconnect(this._wakeUpScreenId); + this._notificationsBox.destroy(); + this._notificationsBox = null; + } + this._clock.destroy(); this._clock = null;