[gnome-shell/T27795: 58/138] iconGridLayout: Add ReplaceApplication method to ShellAppStore



commit 10a9255efe09411a20b0373837415ad0bdba0ac2
Author: Sam Spilsbury <sam endlessm com>
Date:   Sun Aug 6 22:58:57 2017 +0800

    iconGridLayout: Add ReplaceApplication method to ShellAppStore
    
    This removes the old icon and inserts the new one in its place. We'll
    use this from the app store in order to replace the "Get X" launchers
    with the actual application once installed.
    
    Also, make sure not to report a metric on ReplaceApplication if app
    the app was already installed.
    
    https://phabricator.endlessm.com/T18657
    https://phabricator.endlessm.com/T19717

 data/dbus-interfaces/org.gnome.Shell.AppStore.xml |  4 +++
 js/ui/iconGridLayout.js                           | 25 ++++++++++++++++
 js/ui/shellDBus.js                                | 36 ++++++++++++++++++-----
 3 files changed, 57 insertions(+), 8 deletions(-)
---
diff --git a/data/dbus-interfaces/org.gnome.Shell.AppStore.xml 
b/data/dbus-interfaces/org.gnome.Shell.AppStore.xml
index bf9c848039..477d7525cf 100644
--- a/data/dbus-interfaces/org.gnome.Shell.AppStore.xml
+++ b/data/dbus-interfaces/org.gnome.Shell.AppStore.xml
@@ -6,6 +6,10 @@
     <method name="AddAppIfNotVisible">
       <arg type="s" direction="in" name="id" />
     </method>
+    <method name="ReplaceApplication">
+      <arg type="s" direction="in" name="originalId" />
+      <arg type="s" direction="in" name="replacementId" />
+    </method>
     <method name="RemoveApplication">
       <arg type="s" direction="in" name="id" />
     </method>
diff --git a/js/ui/iconGridLayout.js b/js/ui/iconGridLayout.js
index dde2e76f25..fb7c3e49be 100644
--- a/js/ui/iconGridLayout.js
+++ b/js/ui/iconGridLayout.js
@@ -25,6 +25,14 @@ const APPEND_CONFIG_NAME_BASE = 'icon-grid-append';
  */
 const SHELL_APP_REMOVED_EVENT = '683b40a7-cac0-4f9a-994c-4b274693a0a0';
 
+function findInArray(array, func) {
+    for (let i = 0; i < array.length; ++i)
+        if (func(array[i]))
+            return array[i];
+
+    return null;
+}
+
 var IconGridLayout = GObject.registerClass({
     Signals: { 'changed': {} },
 }, class IconGridLayout extends GObject.Object {
@@ -213,6 +221,23 @@ var IconGridLayout = GObject.registerClass({
         this.repositionIcon(id, null, folderId);
     }
 
+    // Two operations, first insert the new icon
+    // to the left of the old one, then remove
+    // the old one
+    //
+    // defaultFolderId here refers to the folder id
+    // to insert the icon into if the icon is not already
+    // in a folder. Otherwise, we use the folder that
+    // the icon is in already.
+    replaceIcon(originalId, replacementId, defaultFolderId) {
+        let folderId = findInArray(Object.keys(this._iconTree), (key) => {
+            return this._iconTree[key].indexOf(originalId) !== -1;
+        }) || defaultFolderId;
+
+        this.repositionIcon(replacementId, originalId, folderId);
+        this.removeIcon(originalId, false);
+    }
+
     removeIcon(id, interactive) {
         if (!this.hasIcon(id))
             return;
diff --git a/js/ui/shellDBus.js b/js/ui/shellDBus.js
index 81a170519f..6728e45b62 100644
--- a/js/ui/shellDBus.js
+++ b/js/ui/shellDBus.js
@@ -379,6 +379,17 @@ var ScreenSaverDBus = class {
     }
 };
 
+function _iconIsVisibleOnDesktop(id) {
+    let visibleIcons = IconGridLayout.layout.getIcons(IconGridLayout.DESKTOP_GRID_ID);
+    return visibleIcons.indexOf(id) !== -1;
+}
+
+function _reportAppAddedMetric(id) {
+    let eventRecorder = EosMetrics.EventRecorder.get_default();
+    let appId = new GLib.Variant('s', id);
+    eventRecorder.record_event(SHELL_APP_ADDED_EVENT, appId);
+}
+
 const AppStoreIface = loadInterfaceXML('org.gnome.Shell.AppStore');
 
 var AppStoreService = class {
@@ -399,19 +410,28 @@ var AppStoreService = class {
     }
 
     AddAppIfNotVisible(id) {
-        let visibleIcons = IconGridLayout.layout.getIcons(IconGridLayout.DESKTOP_GRID_ID);
-        let isIconVisible = visibleIcons.indexOf(id) !== -1;
+        if (IconGridLayout.layout.iconIsFolder(id))
+            return;
 
-        if (!isIconVisible) {
-            let eventRecorder = EosMetrics.EventRecorder.get_default();
-            let appId = new GLib.Variant('s', id);
-            eventRecorder.record_event(SHELL_APP_ADDED_EVENT, appId);
+        if (!_iconIsVisibleOnDesktop(id)) {
+            IconGridLayout.layout.appendIcon(id, IconGridLayout.DESKTOP_GRID_ID);
+            _reportAppAddedMetric(id);
         }
+    }
 
-        if (IconGridLayout.layout.iconIsFolder(id))
+    ReplaceApplication(originalId, replacementId) {
+        // Can't replace a folder
+        if (IconGridLayout.layout.iconIsFolder(originalId))
             return;
 
-        IconGridLayout.layout.appendIcon(id, IconGridLayout.DESKTOP_GRID_ID);
+        // We can just replace the app icon directly now,
+        // since the replace operation degenerates to
+        // append if the source icon was not available
+        IconGridLayout.layout.replaceIcon(originalId, replacementId, IconGridLayout.DESKTOP_GRID_ID);
+
+        // We only care about reporting a metric if the replacement id was visible
+        if (!_iconIsVisibleOnDesktop(replacementId))
+            _reportAppAddedMetric(replacementId);
     }
 
     RemoveApplication(id) {


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