diff --git a/lawnchair/AndroidManifest.xml b/lawnchair/AndroidManifest.xml index 5d56727bb4b..904818d411a 100644 --- a/lawnchair/AndroidManifest.xml +++ b/lawnchair/AndroidManifest.xml @@ -20,7 +20,7 @@ xmlns:tools="http://schemas.android.com/tools"> - + @@ -29,11 +29,12 @@ - - - - - + + + + + + diff --git a/lawnchair/res/values/strings.xml b/lawnchair/res/values/strings.xml index 8a590ba89ce..d141e29c80d 100644 --- a/lawnchair/res/values/strings.xml +++ b/lawnchair/res/values/strings.xml @@ -558,6 +558,13 @@ Vertical inset (Bottom) + + Pause + Pause %1$s? + Notifications for %1$s will be paused + App paused + %1$s was directly paused from the launcher + Pause app Dock icons Bottom padding diff --git a/lawnchair/src/app/lawnchair/LawnchairLauncher.kt b/lawnchair/src/app/lawnchair/LawnchairLauncher.kt index 63cd9a4fe92..fabcf5e095d 100644 --- a/lawnchair/src/app/lawnchair/LawnchairLauncher.kt +++ b/lawnchair/src/app/lawnchair/LawnchairLauncher.kt @@ -235,7 +235,13 @@ class LawnchairLauncher : QuickstepLauncher() { } override fun getSupportedShortcuts(): Stream> = - Stream.concat(super.getSupportedShortcuts(), Stream.of(LawnchairShortcut.UNINSTALL, LawnchairShortcut.CUSTOMIZE)) + Stream.concat( + super.getSupportedShortcuts(), + Stream.concat( + Stream.of(LawnchairShortcut.UNINSTALL, LawnchairShortcut.CUSTOMIZE), + if (LawnchairApp.isRecentsEnabled) Stream.of(LawnchairShortcut.PAUSE_APPS) else Stream.empty(), + ), + ) override fun updateTheme() { if (themeProvider.colorScheme != colorScheme) { diff --git a/lawnchair/src/app/lawnchair/ui/popup/LawnchairShortcut.kt b/lawnchair/src/app/lawnchair/ui/popup/LawnchairShortcut.kt index 91974dffad6..2e170de3917 100644 --- a/lawnchair/src/app/lawnchair/ui/popup/LawnchairShortcut.kt +++ b/lawnchair/src/app/lawnchair/ui/popup/LawnchairShortcut.kt @@ -1,13 +1,18 @@ package app.lawnchair.ui.popup +import android.annotation.SuppressLint +import android.app.AlertDialog +import android.app.AppGlobals import android.content.ComponentName import android.content.Context import android.content.Intent import android.content.pm.ApplicationInfo import android.content.pm.LauncherActivityInfo import android.content.pm.LauncherApps +import android.content.pm.SuspendDialogInfo import android.net.Uri import android.os.UserHandle +import android.util.Log import android.view.View import android.widget.Toast import androidx.compose.foundation.layout.PaddingValues @@ -65,6 +70,15 @@ class LawnchairShortcut { } UnInstall(activity, itemInfo, view) } + + val PAUSE_APPS = SystemShortcut.Factory { activity: LawnchairLauncher, itemInfo: ItemInfo, originalView: View -> + val targetCmp = itemInfo.targetComponent + val packageName = targetCmp?.packageName ?: return@Factory null + + if (PackageManagerHelper(activity).isAppSuspended(packageName, itemInfo.user)) return@Factory null + + PauseApps(activity, itemInfo, originalView) + } } class Customize( @@ -97,6 +111,59 @@ class LawnchairShortcut { } } + class PauseApps( + target: LawnchairLauncher, + itemInfo: ItemInfo, + originalView: View, + ) : SystemShortcut( + R.drawable.ic_hourglass_top, + R.string.paused_apps_drop_target_label, + target, + itemInfo, + originalView, + ) { + @SuppressLint("NewApi") + override fun onClick(view: View) { + val context = view.context + val appLabel = PackageManagerHelper(context).getApplicationInfo( + mItemInfo.targetComponent?.packageName ?: "", + mItemInfo.user, + 0, + )?.let { + context.packageManager.getApplicationLabel( + it, + ) + } + AlertDialog.Builder(context) + .setIcon(R.drawable.ic_hourglass_top) + .setTitle(context.getString(R.string.pause_apps_dialog_title, appLabel)) + .setMessage(context.getString(R.string.pause_apps_dialog_message, appLabel)) + .setNegativeButton(android.R.string.cancel, null) + .setPositiveButton(R.string.pause) { _, _ -> + try { + AppGlobals.getPackageManager().setPackagesSuspendedAsUser( + arrayOf(mItemInfo.targetComponent?.packageName ?: ""), + true, null, null, + SuspendDialogInfo.Builder() + .setIcon(R.drawable.ic_hourglass_top) + .setTitle(R.string.paused_apps_dialog_title) + .setMessage(R.string.paused_apps_dialog_message) + .setNeutralButtonAction(SuspendDialogInfo.BUTTON_ACTION_UNSUSPEND) + .build(), + 0, + context.opPackageName, + context.userId, + mItemInfo.user.identifier, + ) + } catch (e: Throwable) { + Log.e("LawnchairShortcut", "Failed to pause app", e) + } + } + .show() + AbstractFloatingView.closeAllOpenViews(mTarget) + } + } + class UnInstall(private var target: BaseDraggingActivity?, private var itemInfo: ItemInfo?, originalView: View?) : SystemShortcut( R.drawable.ic_uninstall_no_shadow,