From f1b606d8e47fe5385562d0f927217e20cd224dfc Mon Sep 17 00:00:00 2001 From: MM20 <15646950+MM2-0@users.noreply.github.com> Date: Fri, 1 Apr 2022 22:42:59 +0200 Subject: [PATCH] Widget picker: Group widgets per app Close #51 --- .../launcher/widgets/picker/AppWidgetList.kt | 24 +++++--- .../widgets/picker/PickAppWidgetActivity.kt | 59 +++++++++++++------ .../widgets/picker/PickAppWidgetVM.kt | 29 ++++++++- 3 files changed, 84 insertions(+), 28 deletions(-) diff --git a/ui/src/main/java/de/mm20/launcher2/ui/launcher/widgets/picker/AppWidgetList.kt b/ui/src/main/java/de/mm20/launcher2/ui/launcher/widgets/picker/AppWidgetList.kt index 66aa16bc..b850b5c0 100644 --- a/ui/src/main/java/de/mm20/launcher2/ui/launcher/widgets/picker/AppWidgetList.kt +++ b/ui/src/main/java/de/mm20/launcher2/ui/launcher/widgets/picker/AppWidgetList.kt @@ -10,7 +10,6 @@ import androidx.compose.foundation.lazy.items import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable -import androidx.compose.runtime.key import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.drawscope.drawIntoCanvas @@ -25,7 +24,7 @@ import de.mm20.launcher2.ui.ktx.toDp @Composable fun AppWidgetList( modifier: Modifier = Modifier, - widgets: List, + widgets: List, onWidgetSelected: (AppWidgetProviderInfo) -> Unit = {} ) { val context = LocalContext.current @@ -33,8 +32,20 @@ fun AppWidgetList( LazyColumn( modifier = modifier ) { - items(widgets) { - key(it.provider.toShortString()) { + for (group in widgets) { + item() { + Text( + modifier = Modifier.padding( + top = 16.dp, + start = 8.dp, + end = 8.dp, + bottom = 8.dp + ), + text = group.appName, + style = MaterialTheme.typography.titleLarge + ) + } + items(group.widgets) { LauncherCard( modifier = Modifier .padding(8.dp) @@ -81,10 +92,6 @@ fun AppWidgetList( modifier = mod ) { drawIntoCanvas { - val aspectRatio = - image.intrinsicWidth / image.intrinsicHeight - - image.setBounds( 0, 0, @@ -106,5 +113,6 @@ fun AppWidgetList( } } } + } } \ No newline at end of file diff --git a/ui/src/main/java/de/mm20/launcher2/ui/launcher/widgets/picker/PickAppWidgetActivity.kt b/ui/src/main/java/de/mm20/launcher2/ui/launcher/widgets/picker/PickAppWidgetActivity.kt index 05242ec0..9b42632d 100644 --- a/ui/src/main/java/de/mm20/launcher2/ui/launcher/widgets/picker/PickAppWidgetActivity.kt +++ b/ui/src/main/java/de/mm20/launcher2/ui/launcher/widgets/picker/PickAppWidgetActivity.kt @@ -10,12 +10,16 @@ import androidx.activity.compose.setContent import androidx.activity.viewModels import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.material3.CircularProgressIndicator +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.rounded.ArrowBack +import androidx.compose.material3.* import androidx.compose.runtime.getValue import androidx.compose.runtime.livedata.observeAsState import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource import de.mm20.launcher2.ui.MdcLauncherTheme +import de.mm20.launcher2.ui.R import de.mm20.launcher2.ui.base.BaseActivity import de.mm20.launcher2.ui.base.ProvideSettings @@ -27,6 +31,7 @@ class PickAppWidgetActivity : BaseActivity() { private lateinit var appWidgetManager: AppWidgetManager + @OptIn(ExperimentalMaterial3Api::class) override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) widgetHost = AppWidgetHost(this, 44203) @@ -37,24 +42,44 @@ class PickAppWidgetActivity : BaseActivity() { setContent { MdcLauncherTheme { ProvideSettings { - val available by availableWidgets.observeAsState() - val selected by selectedAppWidget.observeAsState() - val widgets = available - if (selected == null) { - if (widgets != null) { - AppWidgetList( - modifier = Modifier.fillMaxSize(), - widgets = widgets, - onWidgetSelected = { - selectAppWidget(it) + Scaffold( + topBar = { + CenterAlignedTopAppBar( + title = { + Text(stringResource(R.string.widget_add_widget)) + }, + navigationIcon = { + IconButton(onClick = { finish() }) { + Icon( + imageVector = Icons.Rounded.ArrowBack, + contentDescription = stringResource( + id = R.string.menu_back + ) + ) + } } ) - } else { - Box( - modifier = Modifier.fillMaxSize(), - contentAlignment = Alignment.Center - ) { - CircularProgressIndicator() + } + ) { + val available by availableWidgets.observeAsState() + val selected by selectedAppWidget.observeAsState() + val widgets = available + if (selected == null) { + if (widgets != null) { + AppWidgetList( + modifier = Modifier.fillMaxSize(), + widgets = widgets, + onWidgetSelected = { + selectAppWidget(it) + } + ) + } else { + Box( + modifier = Modifier.fillMaxSize(), + contentAlignment = Alignment.Center + ) { + CircularProgressIndicator() + } } } } diff --git a/ui/src/main/java/de/mm20/launcher2/ui/launcher/widgets/picker/PickAppWidgetVM.kt b/ui/src/main/java/de/mm20/launcher2/ui/launcher/widgets/picker/PickAppWidgetVM.kt index 0f02fcdc..ed6d3bad 100644 --- a/ui/src/main/java/de/mm20/launcher2/ui/launcher/widgets/picker/PickAppWidgetVM.kt +++ b/ui/src/main/java/de/mm20/launcher2/ui/launcher/widgets/picker/PickAppWidgetVM.kt @@ -3,14 +3,24 @@ package de.mm20.launcher2.ui.launcher.widgets.picker import android.appwidget.AppWidgetManager import android.appwidget.AppWidgetProviderInfo import android.content.Context +import android.content.pm.PackageManager +import androidx.compose.ui.text.toLowerCase import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.liveData +import de.mm20.launcher2.crashreporter.CrashReporter import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext -class PickAppWidgetVM: ViewModel() { +typealias AppWidgetGroup = Pair> + +inline val AppWidgetGroup.appName: String + get() = this.first +inline val AppWidgetGroup.widgets: List + get() = this.second + +class PickAppWidgetVM : ViewModel() { var appWidgetId: MutableLiveData = MutableLiveData(null) val selectedAppWidget: MutableLiveData = MutableLiveData(null) @@ -19,11 +29,24 @@ class PickAppWidgetVM: ViewModel() { this.selectedAppWidget.value = appWidget } - fun getAvailableWidgets(context: Context): LiveData?> = liveData { + fun getAvailableWidgets(context: Context): LiveData?> = liveData { emit(null) val appWidgetManager = AppWidgetManager.getInstance(context) val widgets = withContext(Dispatchers.IO) { - appWidgetManager.installedProviders.sortedBy { it.loadLabel(context.packageManager) } + appWidgetManager.installedProviders + .sortedBy { it.loadLabel(context.packageManager).lowercase() } + .groupBy { + val pkg = it.provider.packageName + val appInfo = try { + context.packageManager.getApplicationInfo(pkg, 0) + } catch (e: PackageManager.NameNotFoundException) { + CrashReporter.logException(e) + return@groupBy "" + } + appInfo.loadLabel(context.packageManager).toString() + } + .toList() + .sortedBy { it.first.lowercase() } } emit(widgets) }