Widget picker: Group widgets per app

Close #51
This commit is contained in:
MM20 2022-04-01 22:42:59 +02:00
parent 0d1b6fa33b
commit f1b606d8e4
No known key found for this signature in database
GPG Key ID: 0B61A8F2DEAFA389
3 changed files with 84 additions and 28 deletions

View File

@ -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<AppWidgetProviderInfo>,
widgets: List<AppWidgetGroup>,
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(
}
}
}
}
}

View File

@ -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()
}
}
}
}

View File

@ -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<String, List<AppWidgetProviderInfo>>
inline val AppWidgetGroup.appName: String
get() = this.first
inline val AppWidgetGroup.widgets: List<AppWidgetProviderInfo>
get() = this.second
class PickAppWidgetVM : ViewModel() {
var appWidgetId: MutableLiveData<Int?> = MutableLiveData(null)
val selectedAppWidget: MutableLiveData<AppWidgetProviderInfo?> = MutableLiveData(null)
@ -19,11 +29,24 @@ class PickAppWidgetVM: ViewModel() {
this.selectedAppWidget.value = appWidget
}
fun getAvailableWidgets(context: Context): LiveData<List<AppWidgetProviderInfo>?> = liveData {
fun getAvailableWidgets(context: Context): LiveData<List<AppWidgetGroup>?> = 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)
}