Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 53b6e9dd authored by d34d's avatar d34d Committed by Gerrit Code Review
Browse files

Show apps as unavailable when on unmounted storage

This patch allows shortcuts to apps that are currently unavailable
due to being on unmounted external storage to remain on the workspace
and in folders.  The icons will be disabled and grayed out until
the external storage is mounted.

Change-Id: I971483806b27e3a75ef0d5bb89d8dfb86f97511e
parent c7b06dde
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -86,4 +86,7 @@

    <!-- Search Manager doesn't exist -->
    <string name="search_activity_not_found">A search activity could not be found!</string>

    <!-- App not available toast text -->
    <string name="app_not_available">App not available</string>
</resources>
+38 −2
Original line number Diff line number Diff line
@@ -3080,11 +3080,15 @@ public class Launcher extends Activity
        final Intent intent;
        if (tag instanceof ShortcutInfo) {
            shortcut = (ShortcutInfo) tag;
            if (shortcut.isDisabled) {
                Toast.makeText(this, R.string.app_not_available, Toast.LENGTH_SHORT).show();
                return;
            }
            intent = shortcut.intent;
            int[] pos = new int[2];
            v.getLocationOnScreen(pos);
            intent.setSourceBounds(new Rect(pos[0], pos[1],
                    pos[0] + v.getWidth(), pos[1] + v.getHeight()));
            intent.setSourceBounds(
                    new Rect(pos[0], pos[1], pos[0] + v.getWidth(), pos[1] + v.getHeight()));

        } else if (tag instanceof AppInfo) {
            shortcut = null;
@@ -5536,6 +5540,38 @@ public class Launcher extends Activity
        }
    }

    /**
     * A package has become unavailable.
     *
     * Implementation of the method from LauncherModel.Callbacks.
     */
    public void bindComponentsUnavailable(final ArrayList<String> packageNames,
            final ArrayList<AppInfo> appInfos) {
        if (!packageNames.isEmpty()) {
            mWorkspace.updateUnavailableItemsByPackageName(packageNames);
        }
        // Notify the drag controller
        mDragController.onAppsRemoved(packageNames, appInfos);

        // Update AllApps
        if (!LauncherAppState.isDisableAllApps() &&
                mAppsCustomizeContent != null) {
            mAppsCustomizeContent.removeApps(appInfos);
            mAppDrawerAdapter.removeApps(appInfos);
        }
    }

    /**
     * A package has become unavailable.
     *
     * Implementation of the method from LauncherModel.Callbacks.
     */
    public void bindComponentsAvailable(final ArrayList<ItemInfo> itemInfos) {
        if (!itemInfos.isEmpty()) {
            mWorkspace.updateAvailableItems(itemInfos);
        }
    }

    /**
     * A number of packages were updated.
     */
+46 −19
Original line number Diff line number Diff line
@@ -211,6 +211,9 @@ public class LauncherModel extends BroadcastReceiver
        public void updatePackageBadge(String packageName);
        public void bindComponentsRemoved(ArrayList<String> packageNames,
                        ArrayList<AppInfo> appInfos, UserHandleCompat user);
        public void bindComponentsUnavailable(ArrayList<String> packageNames,
                ArrayList<AppInfo> appInfos);
        public void bindComponentsAvailable(ArrayList<ItemInfo> itemInfos);
        public void bindPackagesUpdated(ArrayList<Object> widgetsAndShortcuts);
        public void bindSearchablesChanged();
        public boolean isAllAppsButtonRank(int rank);
@@ -3367,6 +3370,7 @@ public class LauncherModel extends BroadcastReceiver

            final String[] packages = mPackages;
            final int N = packages.length;
            final ArrayList<String> unavailable = new ArrayList<String>();
            switch (mOp) {
                case OP_ADD:
                    for (int i=0; i<N; i++) {
@@ -3390,6 +3394,9 @@ public class LauncherModel extends BroadcastReceiver
                        mBgAllAppsList.removePackage(packages[i], mUser);
                        WidgetPreviewLoader.removePackageFromDb(
                                mApp.getWidgetPreviewCacheDb(), packages[i]);
                        if (mOp == OP_UNAVAILABLE) {
                            unavailable.add(packages[i]);
                        }
                    }
                    break;
            }
@@ -3418,12 +3425,21 @@ public class LauncherModel extends BroadcastReceiver
            }

            if (added != null) {
                final ArrayList<ItemInfo> addedInfos = new ArrayList<ItemInfo>(added);
                // Ensure that we add all the workspace applications to the db
                if (LauncherAppState.isDisableAllApps()) {
                    final ArrayList<ItemInfo> addedInfos = new ArrayList<ItemInfo>(added);
                    addAndBindAddedWorkspaceApps(context, addedInfos);
                } else {
                    addAppsToAllApps(context, added);
                    mHandler.post(new Runnable() {
                        public void run() {
                            Callbacks cb = mCallbacks != null ? mCallbacks.get() : null;
                            if (callbacks == cb && cb != null) {
                                Log.d(TAG, "bindComponentsAvailable: " + addedInfos.size());
                                callbacks.bindComponentsAvailable(addedInfos);
                            }
                        }
                    });
                }
            }

@@ -3459,15 +3475,6 @@ public class LauncherModel extends BroadcastReceiver
            if (mOp == OP_REMOVE) {
                // Mark all packages in the broadcast to be removed
                removedPackageNames.addAll(Arrays.asList(packages));
            } else if (mOp == OP_UPDATE) {
                // Mark disabled packages in the broadcast to be removed
                final PackageManager pm = context.getPackageManager();
                for (int i=0; i<N; i++) {
                    if (isPackageDisabled(context, packages[i], mUser)) {
                        removedPackageNames.add(packages[i]);
                    }
                }
            }
                // Remove all the components associated with this package
                for (String pn : removedPackageNames) {
                    deletePackageFromDatabase(context, pn, mUser);
@@ -3488,7 +3495,27 @@ public class LauncherModel extends BroadcastReceiver
                        public void run() {
                            Callbacks cb = mCallbacks != null ? mCallbacks.get() : null;
                            if (callbacks == cb && cb != null) {
                            callbacks.bindComponentsRemoved(removedPackageNames, removedApps, mUser);
                                callbacks.bindComponentsRemoved(removedPackageNames, removedApps,
                                        mUser);
                            }
                        }
                    });
                }
            } else if (mOp == OP_UPDATE) {
                // Mark disabled packages in the broadcast to be removed
                final PackageManager pm = context.getPackageManager();
                for (int i=0; i<N; i++) {
                    if (isPackageDisabled(context, packages[i], mUser)) {
                        removedPackageNames.add(packages[i]);
                    }
                }
            } else if (mOp == OP_UNAVAILABLE) {
                // Call the packages-unavailable callback
                mHandler.post(new Runnable() {
                    public void run() {
                        Callbacks cb = mCallbacks != null ? mCallbacks.get() : null;
                        if (callbacks == cb && cb != null) {
                            callbacks.bindComponentsUnavailable(unavailable, removedApps);
                        }
                    }
                });
+84 −0
Original line number Diff line number Diff line
@@ -4954,6 +4954,90 @@ public class Workspace extends SmoothPagedView
        stripEmptyScreens();
    }

    void updateUnvailableItemsInCellLayout(CellLayout parent, ArrayList<String> packages) {
        final HashSet<String> packageNames = new HashSet<String>();
        packageNames.addAll(packages);

        ViewGroup layout = parent.getShortcutsAndWidgets();
        int childCount = layout.getChildCount();
        for (int i = 0; i < childCount; ++i) {
            View view = layout.getChildAt(i);
            if (view instanceof BubbleTextView) {
                ItemInfo info = (ItemInfo) view.getTag();
                if (info instanceof ShortcutInfo) {
                    Intent intent = info.getIntent();
                    ComponentName cn = intent != null ? intent.getComponent() : null;
                    if (cn != null && packageNames.contains(cn.getPackageName())) {
                        ShortcutInfo shortcut = (ShortcutInfo) info;
                        if (!shortcut.isDisabled) {
                            shortcut.isDisabled = true;
                            ((BubbleTextView) view)
                                    .applyFromShortcutInfo(shortcut, mIconCache, true);
                        }
                    }
                }
            } else if (view instanceof FolderIcon) {
                final Folder folder = ((FolderIcon)view).getFolder();
                updateUnvailableItemsInCellLayout(folder.getContent(), packages);
                folder.invalidate();
            }
        }
    }

    void updateUnavailableItemsByPackageName(final ArrayList<String> packages) {
        ArrayList<CellLayout> cellLayouts = getWorkspaceAndHotseatCellLayouts();
        for (CellLayout layoutParent : cellLayouts) {
            updateUnvailableItemsInCellLayout(layoutParent, packages);
        }
    }

    /**
     * Updates shortcuts to an app that was previously unavailable in the given cell layout
     * @param parent CellLayout to check childen for shortcuts to the available app
     * @param appInfos List of item infos.  Items are assumed to be of type AppInfo
     */
    void updateAvailabeItemsInCellLayout(CellLayout parent, final ArrayList<ItemInfo> appInfos) {
        ViewGroup layout = parent.getShortcutsAndWidgets();
        int childCount = layout.getChildCount();
        for (int i = 0; i < childCount; ++i) {
            View view = layout.getChildAt(i);
            if (view instanceof BubbleTextView) {
                ItemInfo info = (ItemInfo) view.getTag();
                if (info instanceof ShortcutInfo) {
                    Intent intent = info.getIntent();
                    ComponentName cn = intent != null ? intent.getComponent() : null;
                    for (ItemInfo itemInfo : appInfos) {
                        AppInfo appInfo = (AppInfo) itemInfo;
                        if (cn != null && cn.getPackageName().equals(
                                appInfo.componentName.getPackageName())) {
                            ShortcutInfo shortcut = (ShortcutInfo) info;
                            if (shortcut.isDisabled) {
                                shortcut.isDisabled = false;
                                ((BubbleTextView) view)
                                        .applyFromShortcutInfo(shortcut, mIconCache, true);
                            }
                        }
                    }
                }
            } else if (view instanceof FolderIcon) {
                final Folder folder = ((FolderIcon)view).getFolder();
                updateAvailabeItemsInCellLayout(folder.getContent(), appInfos);
                folder.invalidate();
            }
        }
    }

    /**
     * Updates shortcuts to an app that was previously unavailable
     * @param appInfos List of item infos.  Items are assumed to be of type AppInfo
     */
    void updateAvailableItems(final ArrayList<ItemInfo> appInfos) {
        ArrayList<CellLayout> cellLayouts = getWorkspaceAndHotseatCellLayouts();
        for (CellLayout layoutParent : cellLayouts) {
            updateAvailabeItemsInCellLayout(layoutParent, appInfos);
        }
    }

    interface ItemOperator {
        /**
         * Process the next itemInfo, possibly with side-effect on {@link ItemOperator#value}.