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

Commit 480563c4 authored by Abhishek Aggarwal's avatar Abhishek Aggarwal Committed by Sahil Sonar
Browse files

feat(multimode): Add initial no Drawer Mode



add preferences, utils and all apps task

Co-authored-by: Yash Garg's avatarYash Garg <yash.garg.ext@murena.com>
parent 6ce93b85
Loading
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -6,4 +6,6 @@
        <item>@string/quickstep_component</item>
        <item>@string/launcher_component</item>
    </string-array>

    <bool name="default_single_mode">true</bool>
</resources>
+13 −7
Original line number Diff line number Diff line
@@ -27,7 +27,6 @@ import com.android.launcher3.LauncherPrefs;
import com.android.launcher3.model.data.AppInfo;
import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.Launcher;
import com.android.launcher3.Utilities;
import com.android.launcher3.util.MainThreadInitializedObject;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -35,6 +34,8 @@ import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;

import foundation.e.bliss.multimode.MultiModeController;

public class LauncherAppMonitor extends LauncherApps.Callback
        implements
            SharedPreferences.OnSharedPreferenceChangeListener,
@@ -49,7 +50,7 @@ public class LauncherAppMonitor extends LauncherApps.Callback

    private Launcher mLauncher;

    // private MultiModeController mMultiModeController = null;
    private MultiModeController mMultiModeController = null;

    public static LauncherAppMonitor getInstance(final Context context) {
        return INSTANCE.get(context.getApplicationContext());
@@ -94,9 +95,10 @@ public class LauncherAppMonitor extends LauncherApps.Callback
        }
    }

    private LauncherAppMonitor(Context context) {
        LauncherPrefs.get(context).addListener(this);
        // mMultiModeController = new MultiModeController(context, this);
    public LauncherAppMonitor(Context context) {
        context.getSystemService(LauncherApps.class).registerCallback(this);
        LauncherPrefs.getPrefs(context).registerOnSharedPreferenceChangeListener(this);
        mMultiModeController = new MultiModeController(context, this);
    }

    @Override
@@ -470,4 +472,8 @@ public class LauncherAppMonitor extends LauncherApps.Callback
    @Override
    public void onAppSharedPreferenceChanged(@Nullable String key) {
    }

    public MultiModeController getMultiModeController() {
        return mMultiModeController;
    }
}
 No newline at end of file
+112 −0
Original line number Diff line number Diff line
/*
 * Copyright © MURENA SAS 2023.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the GNU Public License v3.0
 * which accompanies this distribution, and is available at
 * http://www.gnu.org/licenses/gpl.html
 */
package foundation.e.bliss.multimode

import android.content.Context
import android.content.SharedPreferences
import android.content.res.Resources
import android.util.Log
import com.android.launcher3.InvariantDeviceProfile
import com.android.launcher3.LauncherPrefs
import com.android.launcher3.R
import com.android.launcher3.model.data.AppInfo
import com.android.launcher3.util.Executors.MODEL_EXECUTOR
import foundation.e.bliss.BaseController
import foundation.e.bliss.LauncherAppMonitor
import foundation.e.bliss.LauncherAppMonitorCallback
import foundation.e.bliss.preferences.BlissPrefs
import java.io.FileDescriptor
import java.io.PrintWriter

class MultiModeController(val context: Context, val monitor: LauncherAppMonitor) : BaseController {

    private val idp by lazy { InvariantDeviceProfile.INSTANCE.get(context) }
    private val mAppMonitorCallback: LauncherAppMonitorCallback =
        object : LauncherAppMonitorCallback {
            override fun onLoadAllAppsEnd(apps: ArrayList<AppInfo?>?) {
                MODEL_EXECUTOR.submit(
                    VerifyIdleAppTask(
                        context,
                        apps,
                        null,
                        null,
                        false,
                        monitor.launcher.model.mBgDataModel
                    )
                )
            }

            override fun onAppSharedPreferenceChanged(key: String?) {
                when (key) {
                    BlissPrefs.PREF_SINGLE_LAYER_MODE -> {
                        monitor.launcher.model.forceReload()
                    }
                    else -> Unit
                }
            }

            override fun dump(
                prefix: String?,
                fd: FileDescriptor?,
                w: PrintWriter?,
                dumpAll: Boolean
            ) {
                w?.let {
                    println()
                    println("$prefix $TAG: ${this@MultiModeController}")
                }
            }
        }

    init {
        sharedPreferences = LauncherPrefs.getPrefs(context)
        resources = context.resources
        monitor.registerCallback(mAppMonitorCallback)
        Log.d(TAG, this.toString())
    }

    override fun dumpState(
        prefix: String?,
        fd: FileDescriptor?,
        writer: PrintWriter?,
        dumpAll: Boolean
    ) {
        writer?.let {
            println()
            println("$prefix $TAG: ${this@MultiModeController}")
        }
    }

    companion object {
        private const val TAG = "MultiModeController"
        @JvmField var sharedPreferences: SharedPreferences? = null
        @JvmField var resources: Resources? = null

        private fun throwIfControllerNotInit() {
            val launcherAppMonitor = LauncherAppMonitor.getInstanceNoCreate()
            if (launcherAppMonitor == null || launcherAppMonitor.multiModeController == null) {
                throw RuntimeException("MultiModeController is not init.")
            }
        }

        @JvmStatic
        val isSingleLayerMode: Boolean
            get() {
                throwIfControllerNotInit()
                return sharedPreferences!!
                    .getBoolean(
                        BlissPrefs.PREF_SINGLE_LAYER_MODE,
                        resources!!.getBoolean(R.bool.default_single_mode)
                    )
                    .apply {
                        Log.d(TAG, "Single Layer Mode (getter): $this")
                        return@apply
                    }
            }
    }
}
+124 −0
Original line number Diff line number Diff line
/*
 * Copyright © MURENA SAS 2023.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the GNU Public License v3.0
 * which accompanies this distribution, and is available at
 * http://www.gnu.org/licenses/gpl.html
 */
package foundation.e.bliss.multimode;

import android.content.ComponentName;
import android.content.Context;
import android.content.pm.LauncherActivityInfo;
import android.content.pm.LauncherApps;
import android.os.UserHandle;
import android.util.Log;
import android.util.Pair;

import androidx.annotation.WorkerThread;

import com.android.launcher3.LauncherAppState;
import com.android.launcher3.model.BgDataModel;
import com.android.launcher3.model.ItemInstallQueue;
import com.android.launcher3.model.data.AppInfo;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.util.ComponentKey;
import com.android.launcher3.util.ItemInfoMatcher;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.function.Predicate;

@WorkerThread
public class VerifyIdleAppTask implements Runnable {
    private static final String TAG = "VerifyIdleAppTask";

    private final Context mContext;
    private final Collection<AppInfo> mApps;
    private final String mPackageNames;
    private final UserHandle mUser;
    private final boolean mIsAddPackage;
    private boolean mIgnoreLoaded;

    private BgDataModel mBgdataModel;

    public VerifyIdleAppTask(Context context, Collection<AppInfo> apps, String packageNames, UserHandle user,
            boolean isAdd, BgDataModel bgDataModel) {
        mContext = context;
        mApps = apps;
        mPackageNames = packageNames;
        mUser = user;
        mIsAddPackage = isAdd;
        mBgdataModel = bgDataModel;
    }

    private static void verifyShortcutHighRes(Context context, AppInfo appInfo) {
        if (appInfo != null) {
            if (appInfo.usingLowResIcon()) {
                LauncherAppState.getInstance(context).getIconCache().getTitleAndIcon(appInfo, false);
            }
        }
    }

    @Override
    public void run() {
        if (!MultiModeController.isSingleLayerMode()) {
            return;
        }

        final Map<ComponentKey, Object> map = new HashMap<>();
        if (mApps != null && mApps.size() > 0) {
            // All apps loading, we ignore loaded.
            mIgnoreLoaded = true;
            for (AppInfo app : mApps) {
                map.put(new ComponentKey(app.componentName, app.user), app);
            }
        } else if (mPackageNames != null && mUser != null) {
            // App add or update, should not ignore loaded.
            mIgnoreLoaded = false;
            final LauncherApps launcherApps = mContext.getSystemService(LauncherApps.class);
            if (mIsAddPackage || launcherApps.isPackageEnabled(mPackageNames, mUser)) {
                final List<LauncherActivityInfo> infos = launcherApps.getActivityList(mPackageNames, mUser);
                for (LauncherActivityInfo info : infos) {
                    map.put(new ComponentKey(info.getComponentName(), info.getUser()), info);
                }
            }
        }

        verifyAllApps(mContext, map, mIsAddPackage);
    }

    List<Pair<ItemInfo, Object>> verifyAllApps(Context context, Map<ComponentKey, Object> map, boolean animated) {
        List<Pair<ItemInfo, Object>> newItems = new ArrayList<>();
        synchronized (mBgdataModel) {
            for (Map.Entry<ComponentKey, Object> entry : map.entrySet()) {
                ComponentKey componentKey = entry.getKey();
                HashSet<ComponentName> components = new HashSet<>(1);
                components.add(componentKey.componentName);
                Predicate<ItemInfo> matcher = ItemInfoMatcher.ofComponents(components, componentKey.user);
                if (mBgdataModel.workspaceItems.stream().noneMatch(matcher)) {
                    Object obj = entry.getValue();
                    if (obj instanceof AppInfo) {
                        verifyShortcutHighRes(context, (AppInfo) obj);
                        newItems.add(Pair.create((AppInfo) obj, null));
                    } else if (obj instanceof LauncherActivityInfo) {
                        LauncherActivityInfo info = (LauncherActivityInfo) obj;
                        newItems.add(new ItemInstallQueue.PendingInstallShortcutInfo(
                                info.getApplicationInfo().packageName, info.getUser()).getItemInfo(context));
                    }
                    Log.d(TAG, "will bind " + componentKey.componentName + " to workspace.");
                }
            }
        }

        LauncherAppState appState = LauncherAppState.getInstanceNoCreate();
        if (appState != null && newItems.size() > 0) {
            appState.getModel().addAndBindAddedWorkspaceItems(newItems, animated, mIgnoreLoaded);
        }
        return newItems;
    }
}
 No newline at end of file
+12 −0
Original line number Diff line number Diff line
/*
 * Copyright © MURENA SAS 2023.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the GNU Public License v3.0
 * which accompanies this distribution, and is available at
 * http://www.gnu.org/licenses/gpl.html
 */
package foundation.e.bliss.preferences

object BlissPrefs {
    const val PREF_SINGLE_LAYER_MODE = "pref_single_layer"
}
Loading