[gnome-shell/eos3.8: 87/255] discoveryFeed: Add Discovery Feed Button



commit 69af69f5975d5da968d493670b133b92b7d1f37c
Author: Mario Sanchez Prada <mario endlessm com>
Date:   Wed Feb 14 16:01:25 2018 +0000

    discoveryFeed: Add Discovery Feed Button
    
    Also, make sure the feed is disabled on < 1024 screen widths,
    and that it responds to resolution changes.
    
    Finally, enable the discovery feed for English and Indonesian only,
    as we don't have enough content for it in other languages.
    
    Last, this includes the latest design changes implemented for
    EOS 3.3 squashed in. Please check the eos3.3 branch for details.
    
    2019-09-24: squash da3fa53ea "discoveryFeed: Tell the Discovery
                    Feed when its window is fully hidden"
    
    https://phabricator.endlessm.com/T17773
    https://phabricator.endlessm.com/T17840
    https://phabricator.endlessm.com/T18017
    https://phabricator.endlessm.com/T18546
    https://phabricator.endlessm.com/T18850
    https://phabricator.endlessm.com/T19354
    https://phabricator.endlessm.com/T20602

 .../dbus-interfaces/com.endlessm.DiscoveryFeed.xml |   1 +
 data/gnome-shell-theme.gresource.xml               |   4 +
 data/org.gnome.shell.gschema.xml.in                |   9 ++
 data/theme/discovery-feed-bar-hover.png            | Bin 0 -> 774 bytes
 data/theme/discovery-feed-bar-normal.png           | Bin 0 -> 758 bytes
 data/theme/discovery-feed-tile-hover.png           | Bin 0 -> 1684 bytes
 data/theme/discovery-feed-tile-normal.png          | Bin 0 -> 1642 bytes
 data/theme/gnome-shell-sass/_endless.scss          |  22 ++++
 js/js-resources.gresource.xml                      |   1 +
 js/ui/components/discoveryFeed.js                  |   4 +
 js/ui/discoveryFeedButton.js                       | 117 +++++++++++++++++++++
 js/ui/viewSelector.js                              |  39 ++++++-
 js/ui/windowManager.js                             |   5 +
 13 files changed, 197 insertions(+), 5 deletions(-)
---
diff --git a/data/dbus-interfaces/com.endlessm.DiscoveryFeed.xml 
b/data/dbus-interfaces/com.endlessm.DiscoveryFeed.xml
index 2df0c9756c..6b6d4c5ac4 100644
--- a/data/dbus-interfaces/com.endlessm.DiscoveryFeed.xml
+++ b/data/dbus-interfaces/com.endlessm.DiscoveryFeed.xml
@@ -1,5 +1,6 @@
 <node>
   <interface name="com.endlessm.DiscoveryFeed">
+    <method name="notifyHideAnimationCompleted" />
     <method name="show">
       <arg type="u" direction="in" name="timestamp"/>
     </method>
diff --git a/data/gnome-shell-theme.gresource.xml b/data/gnome-shell-theme.gresource.xml
index 1c3520582d..63673241a1 100644
--- a/data/gnome-shell-theme.gresource.xml
+++ b/data/gnome-shell-theme.gresource.xml
@@ -38,6 +38,10 @@
     <file>corner-ripple-br.png</file>
     <file>corner-ripple-tl.png</file>
     <file>corner-ripple-tr.png</file>
+    <file>discovery-feed-bar-normal.png</file>
+    <file>discovery-feed-bar-hover.png</file>
+    <file>discovery-feed-tile-normal.png</file>
+    <file>discovery-feed-tile-hover.png</file>
     <file>endless-button-symbolic.svg</file>
     <file>endless-help-symbolic.svg</file>
     <file>feedback-symbolic.svg</file>
diff --git a/data/org.gnome.shell.gschema.xml.in b/data/org.gnome.shell.gschema.xml.in
index 6211310ebd..c4948be379 100644
--- a/data/org.gnome.shell.gschema.xml.in
+++ b/data/org.gnome.shell.gschema.xml.in
@@ -175,6 +175,15 @@
         This key specifies the exact order of the icons shown in the applications launcher view.
       </description>
     </key>
+    <key name="discovery-feed-languages" type="as">
+      <default>['en', 'id']</default>
+      <summary>
+        Languages for which the discovery feed feature is enabled.
+      </summary>
+      <description>
+        If the system language matches any of these languages, the discovery feed will be enabled. You will 
need to restart the shell for changes to this setting to take effect.
+      </description>
+    </key>
     <child name="keybindings" schema="org.gnome.shell.keybindings"/>
   </schema>
 
diff --git a/data/theme/discovery-feed-bar-hover.png b/data/theme/discovery-feed-bar-hover.png
new file mode 100644
index 0000000000..22e0358701
Binary files /dev/null and b/data/theme/discovery-feed-bar-hover.png differ
diff --git a/data/theme/discovery-feed-bar-normal.png b/data/theme/discovery-feed-bar-normal.png
new file mode 100644
index 0000000000..0b0a35d443
Binary files /dev/null and b/data/theme/discovery-feed-bar-normal.png differ
diff --git a/data/theme/discovery-feed-tile-hover.png b/data/theme/discovery-feed-tile-hover.png
new file mode 100644
index 0000000000..20fb3aa152
Binary files /dev/null and b/data/theme/discovery-feed-tile-hover.png differ
diff --git a/data/theme/discovery-feed-tile-normal.png b/data/theme/discovery-feed-tile-normal.png
new file mode 100644
index 0000000000..d30afe3cff
Binary files /dev/null and b/data/theme/discovery-feed-tile-normal.png differ
diff --git a/data/theme/gnome-shell-sass/_endless.scss b/data/theme/gnome-shell-sass/_endless.scss
index d26926ab06..4b9a53447d 100644
--- a/data/theme/gnome-shell-sass/_endless.scss
+++ b/data/theme/gnome-shell-sass/_endless.scss
@@ -365,3 +365,25 @@ popup-separator-menu-item {
         padding-right: 0px;
     }
 }
+
+// Discovery Feed
+
+.discovery-feed-bar-icon {
+    background-image: url("resource:///org/gnome/shell/theme/discovery-feed-bar-normal.png");
+    height: 18px;
+    width: 1004px;
+
+    &:highlighted {
+        background-image: url("resource:///org/gnome/shell/theme/discovery-feed-bar-hover.png");
+    }
+}
+
+.discovery-feed-tile-icon {
+    background-image: url("resource:///org/gnome/shell/theme/discovery-feed-tile-normal.png");
+    height: 27px;
+    width: 62px;
+
+    &:highlighted {
+        background-image: url("resource:///org/gnome/shell/theme/discovery-feed-tile-hover.png");
+    }
+}
diff --git a/js/js-resources.gresource.xml b/js/js-resources.gresource.xml
index 67ec3ec414..404134d0c2 100644
--- a/js/js-resources.gresource.xml
+++ b/js/js-resources.gresource.xml
@@ -145,6 +145,7 @@
     <file>ui/appIconBar.js</file>
     <file>ui/components/appStore.js</file>
     <file>ui/components/discoveryFeed.js</file>
+    <file>ui/discoveryFeedButton.js</file>
     <file>ui/endlessButton.js</file>
     <file>ui/forceAppExitDialog.js</file>
     <file>ui/hotCorner.js</file>
diff --git a/js/ui/components/discoveryFeed.js b/js/ui/components/discoveryFeed.js
index b37e864af4..c114c16c38 100644
--- a/js/ui/components/discoveryFeed.js
+++ b/js/ui/components/discoveryFeed.js
@@ -28,6 +28,10 @@ class DiscoveryFeed extends SideComponent.SideComponent {
         Main.discoveryFeed = null;
     }
 
+    notifyHideAnimationCompleted() {
+        this.proxy.notifyHideAnimationCompletedRemote();
+    }
+
     callShow(timestamp) {
         this.proxy.showRemote(timestamp);
     }
diff --git a/js/ui/discoveryFeedButton.js b/js/ui/discoveryFeedButton.js
new file mode 100644
index 0000000000..29a6f2f360
--- /dev/null
+++ b/js/ui/discoveryFeedButton.js
@@ -0,0 +1,117 @@
+// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
+
+/* exported maybeCreateInactiveButton, maybeCreateButton, determineAllocationWithinBox */
+
+const { Clutter, GLib, GObject, St } = imports.gi;
+
+const Main = imports.ui.main;
+
+function maybeCreateInactiveButton() {
+    if (_checkIfDiscoveryFeedEnabled()) {
+        let discoveryFeed = new DiscoveryFeedButton();
+        discoveryFeed.reactive = false;
+        return discoveryFeed;
+    }
+
+    return null;
+}
+
+const DISCOVERY_FEED_PRIMARY_MONITOR_WIDTH_THRESHOLD = 1024;
+
+function _primaryMonitorWidthPassesThreshold() {
+    return Main.layoutManager.primaryMonitor.width >= DISCOVERY_FEED_PRIMARY_MONITOR_WIDTH_THRESHOLD;
+}
+
+function _checkIfDiscoveryFeedEnabled() {
+    let supportedLanguages = global.settings.get_value('discovery-feed-languages').deep_unpack();
+    let systemLanguages = GLib.get_language_names();
+
+    let isEnabled = supportedLanguages.some(lang => systemLanguages.indexOf(lang) !== -1);
+
+    return isEnabled;
+}
+
+function maybeCreateButton() {
+    if (_checkIfDiscoveryFeedEnabled())
+        return new DiscoveryFeedButton();
+
+    return null;
+}
+
+/** DiscoveryFeedButton:
+ *
+ * This class handles the button to launch the discovery feed application
+ */
+var DiscoveryFeedButton = GObject.registerClass(
+class DiscoveryFeedButton extends St.BoxLayout {
+    _init() {
+        super._init({
+            vertical: true,
+            visible: _primaryMonitorWidthPassesThreshold(),
+        });
+
+        this._bar = new St.Button({
+            name: 'discovery-feed-bar',
+            child: new St.Icon({ style_class: 'discovery-feed-bar-icon' }),
+            style_class: 'discovery-feed-bar',
+        });
+        this.add_child(this._bar);
+
+        this._tile = new St.Button({
+            name: 'discovery-feed-tile',
+            child: new St.Icon({ style_class: 'discovery-feed-tile-icon' }),
+            style_class: 'discovery-feed-tile',
+            x_expand: true,
+            x_align: Clutter.ActorAlign.CENTER,
+        });
+        this.add_child(this._tile);
+
+        this._bar.connect('clicked', () => {
+            Main.discoveryFeed.show(global.get_current_time());
+        });
+        this._tile.connect('clicked', () => {
+            Main.discoveryFeed.show(global.get_current_time());
+        });
+
+        this._bar.connect('notify::hover', this._onHoverChanged.bind(this));
+        this._tile.connect('notify::hover', this._onHoverChanged.bind(this));
+
+        Main.layoutManager.connect('monitors-changed', () => {
+            this.visible = _primaryMonitorWidthPassesThreshold();
+        });
+    }
+
+    _onHoverChanged(actor) {
+        if (actor.get_hover()) {
+            this._bar.child.add_style_pseudo_class('highlighted');
+            this._tile.child.add_style_pseudo_class('highlighted');
+        } else {
+            this._bar.child.remove_style_pseudo_class('highlighted');
+            this._tile.child.remove_style_pseudo_class('highlighted');
+        }
+    }
+
+    changeVisbilityState(value) {
+        // Helper function to ensure that visibility is set correctly,
+        // consumers of this button should use this function as opposed
+        // to mutating 'visible' directly, since it prevents the
+        // button from appearing in cases where it should not.
+        this.visible = value && _primaryMonitorWidthPassesThreshold();
+    }
+});
+
+function determineAllocationWithinBox(discoveryFeedButton, box, availWidth) {
+    // If we would not show the feed button because the monitor
+    // is too small, just return box directly
+    if (!_primaryMonitorWidthPassesThreshold())
+        return box;
+
+    let discoveryFeedButtonHeight = discoveryFeedButton.get_preferred_height(availWidth)[1];
+    let discoveryFeedButtonBox = box.copy();
+    let x1 = (availWidth - discoveryFeedButton.get_width()) * 0.5;
+    discoveryFeedButtonBox.y1 = 0;
+    discoveryFeedButtonBox.y2 = discoveryFeedButtonBox.y1 + discoveryFeedButtonHeight;
+    discoveryFeedButtonBox.x1 = x1;
+    discoveryFeedButtonBox.x2 = x1 + discoveryFeedButton.get_width();
+    return discoveryFeedButtonBox;
+}
diff --git a/js/ui/viewSelector.js b/js/ui/viewSelector.js
index 02720172c2..542465240d 100644
--- a/js/ui/viewSelector.js
+++ b/js/ui/viewSelector.js
@@ -6,6 +6,7 @@ const { EosMetrics, Clutter, Gio,
 const Signals = imports.signals;
 
 const AppDisplay = imports.ui.appDisplay;
+const DiscoveryFeedButton = imports.ui.discoveryFeedButton;
 const LayoutManager = imports.ui.layout;
 const Main = imports.ui.main;
 const OverviewControls = imports.ui.overviewControls;
@@ -154,10 +155,11 @@ var ViewsDisplayLayout = GObject.registerClass({
             0, 1, 0),
     },
 }, class ViewsDisplayLayout extends Clutter.BoxLayout {
-    _init(entry, appDisplay, searchResultsActor) {
+    _init(entry, discoveryFeedButton, appDisplay, searchResultsActor) {
         super._init();
 
         this._entry = entry;
+        this._discoveryFeedButton = discoveryFeedButton;
         this._appDisplay = appDisplay;
         this._searchResultsActor = searchResultsActor;
 
@@ -216,6 +218,13 @@ var ViewsDisplayLayout = GObject.registerClass({
         entryBox.y1 = this._heightAboveEntry + entryTopMargin;
         entryBox.y2 = entryBox.y1 + entryHeight;
 
+        let discoveryFeedButtonBox = allocation.copy();
+        if (this._discoveryFeedButton) {
+            discoveryFeedButtonBox =
+                DiscoveryFeedButton.determineAllocationWithinBox(
+                    this._discoveryFeedButton, allocation, availWidth);
+        }
+
         let appDisplayBox = allocation.copy();
         // The grid container box should have the dimensions of this container but start
         // after the search entry and according to the calculated xplacement policies
@@ -235,14 +244,18 @@ var ViewsDisplayLayout = GObject.registerClass({
         // Step 2: pre-allocate to a smaller, but realistic, size
         this._appDisplay.adaptToSize(availWidth, appDisplayBox.get_height());
 
-        return [entryBox, appDisplayBox, searchResultsBox];
+        return [entryBox, discoveryFeedButtonBox, appDisplayBox, searchResultsBox];
     }
 
     vfunc_allocate(actor, box, flags) {
-        let [entryBox, appDisplayBox, searchResultsBox] = this._computeChildrenAllocation(box);
+        let [entryBox, discoveryFeedButtonBox, appDisplayBox, searchResultsBox] =
+            this._computeChildrenAllocation(box);
 
         this._entry.allocate(entryBox, flags);
 
+        if (this._discoveryFeedButton)
+            this._discoveryFeedButton.allocate(discoveryFeedButtonBox, flags);
+
         // Step 3: actually allocate the grid
         this._appDisplay.allocate(appDisplayBox, flags);
 
@@ -260,6 +273,11 @@ var ViewsDisplayLayout = GObject.registerClass({
         this._appDisplay.opacity = (1 - v) * 255;
         this._searchResultsActor.opacity = v * 255;
 
+        if (this._discoveryFeedButton) {
+            this._discoveryFeedButton.changeVisbilityState(v !== 1);
+            this._discoveryFeedButton.opacity = (1 - v) * 255;
+        }
+
         let entryTranslation = -this._heightAboveEntry * v;
         this._entry.translation_y = entryTranslation;
 
@@ -301,7 +319,8 @@ class ViewsClone extends St.Widget {
         const appDisplayClone = new AppDisplay.AppDisplay();
         appDisplayClone._eventBlocker.visible = true;
 
-        let layoutManager = new ViewsDisplayLayout(entry, appDisplayClone, null);
+        let discoveryFeedButton = DiscoveryFeedButton.maybeCreateInactiveButton();
+        let layoutManager = new ViewsDisplayLayout(entry, discoveryFeedButton, appDisplayClone, null);
         super._init({
             layout_manager: layoutManager,
             x_expand: true,
@@ -318,6 +337,8 @@ class ViewsClone extends St.Widget {
         let cloneAdjustment = appDisplayClone.scrollView.vscroll.adjustment;
         originalAdjustment.bind_property('value', cloneAdjustment, 'value', 
GObject.BindingFlags.SYNC_CREATE);
 
+        if (discoveryFeedButton)
+            this.add_child(discoveryFeedButton);
         this.add_child(entry);
         this.add_child(appDisplayClone);
 
@@ -420,13 +441,21 @@ class ViewsDisplay extends St.Widget {
         this._searchResults.bind_property('mapped', clickAction,
             'enabled', GObject.BindingFlags.SYNC_CREATE);
 
+        let discoveryFeedButton = DiscoveryFeedButton.maybeCreateButton();
+
         super._init({
-            layout_manager: new ViewsDisplayLayout(this._entry, this._appDisplay, this._searchResults),
+            layout_manager: new ViewsDisplayLayout(
+                this._entry,
+                discoveryFeedButton,
+                this._appDisplay,
+                this._searchResults),
             x_expand: true,
             y_expand: true,
         });
 
         this.add_child(this._entry);
+        if (discoveryFeedButton)
+            this.add_child(discoveryFeedButton);
         this.add_actor(this._appDisplay);
         this.add_child(this._searchResults);
     }
diff --git a/js/ui/windowManager.js b/js/ui/windowManager.js
index a30566a299..09f6a844ea 100644
--- a/js/ui/windowManager.js
+++ b/js/ui/windowManager.js
@@ -2056,6 +2056,11 @@ var WindowManager = class {
                     this._showOtherWindows(actor, false);
             }
 
+            // If this is the Discovery Feed, notify it that it has
+            // finished closing now
+            if (SideComponent.isDiscoveryFeedWindow(actor.meta_window))
+                Main.discoveryFeed.notifyHideAnimationCompleted();
+
             shellwm.completed_destroy(actor);
         }
     }


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]