diff --git a/android/modules/module_component_manager/build.gradle.kts b/android/modules/module_component_manager/build.gradle.kts index 651c3e3ad..187bbb258 100644 --- a/android/modules/module_component_manager/build.gradle.kts +++ b/android/modules/module_component_manager/build.gradle.kts @@ -75,4 +75,5 @@ dependencies { implementation(libs.glide.landscapist) implementation(libs.glide) kapt(libs.glide.compiler) + implementation(libs.gson) } \ No newline at end of file diff --git a/android/modules/module_component_manager/src/main/java/github/tornaco/thanos/module/component/manager/redesign/ComponentsActivity.kt b/android/modules/module_component_manager/src/main/java/github/tornaco/thanos/module/component/manager/redesign/ComponentsActivity.kt index 68f680cd6..ea167c6a7 100644 --- a/android/modules/module_component_manager/src/main/java/github/tornaco/thanos/module/component/manager/redesign/ComponentsActivity.kt +++ b/android/modules/module_component_manager/src/main/java/github/tornaco/thanos/module/component/manager/redesign/ComponentsActivity.kt @@ -78,8 +78,9 @@ import github.tornaco.android.thanos.module.compose.common.widget.ThanoxSmallApp import github.tornaco.android.thanos.module.compose.common.widget.rememberConfirmDialogState import github.tornaco.android.thanos.module.compose.common.widget.rememberDropdownSelectorState import github.tornaco.android.thanos.module.compose.common.widget.rememberSearchBarState -import github.tornaco.android.thanos.util.BrowserUtils +import github.tornaco.android.thanos.res.R import github.tornaco.android.thanos.util.ToastUtils +import github.tornaco.thanos.module.component.manager.ComponentRule import github.tornaco.thanos.module.component.manager.model.ComponentModel import kotlinx.coroutines.flow.distinctUntilChanged @@ -563,6 +564,15 @@ class ComponentsActivity : ComposeThemeActivity() { isGroupSelected: Boolean, updateGroupSelection: (ComponentGroup, Boolean) -> Unit ) { + var ruleInfoDialogState by remember { mutableStateOf(false) } + if (ruleInfoDialogState) { + BasicAlertDialog(onDismissRequest = { ruleInfoDialogState = false }) { + RuleInfoDialog(rule = group.rule) { + ruleInfoDialogState = false + } + } + } + Row( modifier = Modifier .fillMaxWidth() @@ -583,25 +593,15 @@ class ComponentsActivity : ComposeThemeActivity() { Modifier.weight(1f, fill = false), verticalAlignment = Alignment.CenterVertically, ) { - Icon( - painter = painterResource(group.rule.iconRes.takeIf { it > 0 } - ?: github.tornaco.android.thanos.res.R.drawable.ic_logo_android_line), - contentDescription = null, - tint = if (group.rule.isSimpleColorIcon) { - MaterialTheme.colorScheme.primary - } else { - Color.Unspecified - } - ) + RuleIcon(group.rule) SmallSpacer() Text( text = "${group.rule.label} (${group.components.size})", style = MaterialTheme.typography.titleSmall ) group.rule.descriptionUrl?.let { - val context = LocalContext.current IconButton(onClick = { - BrowserUtils.launch(context, it) + ruleInfoDialogState = true }) { Icon( imageVector = Icons.Outlined.Info, @@ -625,6 +625,21 @@ class ComponentsActivity : ComposeThemeActivity() { } } +@Composable +fun RuleIcon(rule: ComponentRule) { + Icon( + painter = painterResource(rule.iconRes.takeIf { it > 0 } + ?: R.drawable.ic_logo_android_line), + contentDescription = null, + tint = if (rule.isSimpleColorIcon) { + MaterialTheme.colorScheme.primary + } else { + Color.Unspecified + } + ) +} + internal enum class ComponentItemAction { Copy, AddToSmartStandByKeepRules, AddToAppLockAllowList -} \ No newline at end of file +} + diff --git a/android/modules/module_component_manager/src/main/java/github/tornaco/thanos/module/component/manager/redesign/RuleInfoDialog.kt b/android/modules/module_component_manager/src/main/java/github/tornaco/thanos/module/component/manager/redesign/RuleInfoDialog.kt new file mode 100644 index 000000000..e083b7366 --- /dev/null +++ b/android/modules/module_component_manager/src/main/java/github/tornaco/thanos/module/component/manager/redesign/RuleInfoDialog.kt @@ -0,0 +1,137 @@ +@file:OptIn(ExperimentalLayoutApi::class) + +package github.tornaco.thanos.module.component.manager.redesign; + +import androidx.compose.animation.AnimatedContent +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.ExperimentalLayoutApi +import androidx.compose.foundation.layout.FlowRow +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.heightIn +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.wrapContentHeight +import androidx.compose.foundation.layout.wrapContentWidth +import androidx.compose.material3.AlertDialogDefaults +import androidx.compose.material3.Badge +import androidx.compose.material3.CircularProgressIndicator +import androidx.compose.material3.Icon +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Surface +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.dp +import github.tornaco.android.thanos.core.annotation.DoNotStrip +import github.tornaco.android.thanos.core.util.GsonUtils +import github.tornaco.android.thanos.module.compose.common.widget.LargeSpacer +import github.tornaco.android.thanos.module.compose.common.widget.SmallSpacer +import github.tornaco.android.thanos.module.compose.common.widget.StandardSpacer +import github.tornaco.thanos.module.component.manager.ComponentRule +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.withContext +import java.net.URL + +@Composable +internal fun RuleInfoDialog(rule: ComponentRule, dismiss: () -> Unit) { + Surface( + modifier = Modifier + .wrapContentWidth() + .wrapContentHeight(), + shape = MaterialTheme.shapes.large, + tonalElevation = AlertDialogDefaults.TonalElevation + ) { + var description by remember { mutableStateOf(null) } + LaunchedEffect(rule) { + withContext(Dispatchers.IO) { + kotlin.runCatching { + val json = + URL(rule.descriptionUrl.orEmpty()).readText(charset = Charsets.UTF_8) + val model = GsonUtils.GSON.fromJson(json, RuleDescription::class.java) + description = model + }.onFailure { + description = RuleDescription( + description = "${it.message}", + label = "ERROR" + ) + } + } + } + Column( + Modifier + .fillMaxWidth() + .heightIn(min = 200.dp) + .padding(16.dp) + .padding(vertical = 20.dp), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.Center + ) { + Row(verticalAlignment = Alignment.CenterVertically) { + Text( + rule.label, + style = MaterialTheme.typography.titleMedium.copy(fontWeight = FontWeight.W500) + ) + SmallSpacer() + RuleIcon(rule) + } + LargeSpacer() + AnimatedContent(description) { rd -> + if (rd == null) { + CircularProgressIndicator() + } else { + Column { + Text("Team: ${rd.team.orEmpty()}") + StandardSpacer() + FlowRow { + rd.contributors?.forEach { + Badge(containerColor = MaterialTheme.colorScheme.primaryContainer) { + Icon( + painter = painterResource(github.tornaco.android.thanos.icon.remix.R.drawable.ic_remix_user_line), + contentDescription = "Filter", + modifier = Modifier.size(9.dp) + ) + SmallSpacer() + Text(it) + } + SmallSpacer() + } + } + StandardSpacer() + Text( + rd.description.orEmpty(), + style = MaterialTheme.typography.bodySmall + ) + } + } + } + } + } +} + +// { +// "label": "Jetpack Camera", +// "team": "Google", +// "iconUrl": "", +// "contributors": ["Absinthe"], +// "description": "CameraX 是 Jetpack 的新增库。利用该库,可以更轻松地向应用添加相机功能。该库提供了很多兼容性修复程序和解决方法,有助于在众多设备上打造一致的开发者体验。", +// "relativeUrl": "https://developer.android.com/jetpack/androidx/releases/camera" +//} +@DoNotStrip +data class RuleDescription( + val label: String? = null, + val team: String? = null, + val iconUrl: String? = null, + val contributors: List? = null, + val description: String? = null, + val relativeUrl: String? = null +)