diff --git a/app/src/main/kotlin/li/songe/gkd/ui/AppConfigPage.kt b/app/src/main/kotlin/li/songe/gkd/ui/AppConfigPage.kt index d2e81d529..132b4bb49 100644 --- a/app/src/main/kotlin/li/songe/gkd/ui/AppConfigPage.kt +++ b/app/src/main/kotlin/li/songe/gkd/ui/AppConfigPage.kt @@ -184,9 +184,7 @@ private fun AppGroupCard( Row( modifier = Modifier .clickable(onClick = onClick) - .padding(10.dp, 6.dp) - .fillMaxWidth() - .height(45.dp), + .padding(10.dp, 6.dp), horizontalArrangement = Arrangement.SpaceBetween, verticalAlignment = Alignment.CenterVertically, ) { diff --git a/app/src/main/kotlin/li/songe/gkd/ui/AppItemPage.kt b/app/src/main/kotlin/li/songe/gkd/ui/AppItemPage.kt index e1485e7a0..a31e1b1d7 100644 --- a/app/src/main/kotlin/li/songe/gkd/ui/AppItemPage.kt +++ b/app/src/main/kotlin/li/songe/gkd/ui/AppItemPage.kt @@ -163,9 +163,7 @@ fun AppItemPage( if (group.key == focusGroupKey) MaterialTheme.colorScheme.inversePrimary else Color.Transparent ) .clickable { setShowGroupItem(group) } - .padding(10.dp, 6.dp) - .fillMaxWidth() - .height(45.dp), + .padding(10.dp, 6.dp), horizontalArrangement = Arrangement.SpaceBetween, verticalAlignment = Alignment.CenterVertically, ) { @@ -460,6 +458,7 @@ fun AppItemPage( ) }, maxLines = 10, + textStyle = MaterialTheme.typography.bodySmall.copy(fontSize = 12.sp) ) }, onDismissRequest = { setExcludeGroupRaw(null) }, diff --git a/app/src/main/kotlin/li/songe/gkd/ui/CategoryPage.kt b/app/src/main/kotlin/li/songe/gkd/ui/CategoryPage.kt index d4d6454b5..7c53c9c66 100644 --- a/app/src/main/kotlin/li/songe/gkd/ui/CategoryPage.kt +++ b/app/src/main/kotlin/li/songe/gkd/ui/CategoryPage.kt @@ -252,7 +252,7 @@ fun CategoryPage(subsItemId: Long) { }, confirmButton = { TextButton( - enabled = source.isNotEmpty() && source != editNameCategory.name, + enabled = source.isNotBlank() && source != editNameCategory.name, onClick = { if (categories.any { c -> c.key != editNameCategory.key && c.name == source }) { toast("不可添加同名类别") @@ -274,7 +274,8 @@ fun CategoryPage(subsItemId: Long) { toast("修改成功") setEditNameCategory(null) } - }) { + } + ) { Text(text = "确认") } } diff --git a/app/src/main/kotlin/li/songe/gkd/ui/DebugPage.kt b/app/src/main/kotlin/li/songe/gkd/ui/DebugPage.kt index 74d8efcac..5e009f5c4 100644 --- a/app/src/main/kotlin/li/songe/gkd/ui/DebugPage.kt +++ b/app/src/main/kotlin/li/songe/gkd/ui/DebugPage.kt @@ -353,17 +353,20 @@ fun DebugPage() { }, ) }, onDismissRequest = { showPortDlg = false }, confirmButton = { - TextButton(onClick = { - val newPort = value.toIntOrNull() - if (newPort == null || !(5000 <= newPort && newPort <= 65535)) { - toast("请输入在 5000~65535 的任意数字") - return@TextButton + TextButton( + enabled = value.isNotEmpty(), + onClick = { + val newPort = value.toIntOrNull() + if (newPort == null || !(5000 <= newPort && newPort <= 65535)) { + toast("请输入在 5000~65535 的任意数字") + return@TextButton + } + storeFlow.value = store.copy( + httpServerPort = newPort + ) + showPortDlg = false } - storeFlow.value = store.copy( - httpServerPort = newPort - ) - showPortDlg = false - }) { + ) { Text( text = "确认", modifier = Modifier ) diff --git a/app/src/main/kotlin/li/songe/gkd/ui/GlobalRuleExcludePage.kt b/app/src/main/kotlin/li/songe/gkd/ui/GlobalRuleExcludePage.kt index f446ca331..df822c0e0 100644 --- a/app/src/main/kotlin/li/songe/gkd/ui/GlobalRuleExcludePage.kt +++ b/app/src/main/kotlin/li/songe/gkd/ui/GlobalRuleExcludePage.kt @@ -4,13 +4,14 @@ import androidx.compose.foundation.Image import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.IntrinsicSize import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.aspectRatio import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.wrapContentSize import androidx.compose.foundation.lazy.LazyColumn @@ -235,24 +236,32 @@ fun GlobalRuleExcludePage(subsItemId: Long, groupKey: Int) { items(showAppInfos, { it.id }) { appInfo -> Row( modifier = Modifier - .height(60.dp) - .padding(4.dp), + .height(IntrinsicSize.Min) + .padding(10.dp, 6.dp), horizontalArrangement = Arrangement.SpaceBetween, verticalAlignment = Alignment.CenterVertically, ) { if (appInfo.icon != null) { - Image( - painter = rememberDrawablePainter(appInfo.icon), - contentDescription = null, + Box( modifier = Modifier - .size(52.dp) - ) + .fillMaxHeight() + .aspectRatio(1f) + ) { + Image( + painter = rememberDrawablePainter(appInfo.icon), + contentDescription = null, + modifier = Modifier + .matchParentSize() + .padding(4.dp) + ) + } } else { Icon( imageVector = Icons.Default.Android, contentDescription = null, modifier = Modifier - .size(52.dp) + .aspectRatio(1f) + .fillMaxHeight() .padding(4.dp) ) } diff --git a/app/src/main/kotlin/li/songe/gkd/ui/GlobalRulePage.kt b/app/src/main/kotlin/li/songe/gkd/ui/GlobalRulePage.kt index c2f675475..d124d45b2 100644 --- a/app/src/main/kotlin/li/songe/gkd/ui/GlobalRulePage.kt +++ b/app/src/main/kotlin/li/songe/gkd/ui/GlobalRulePage.kt @@ -132,9 +132,7 @@ fun GlobalRulePage(subsItemId: Long, focusGroupKey: Int? = null) { if (group.key == focusGroupKey) MaterialTheme.colorScheme.inversePrimary else Color.Transparent ) .clickable { setShowGroupItem(group) } - .padding(10.dp, 6.dp) - .fillMaxWidth() - .height(45.dp), + .padding(10.dp, 6.dp), horizontalArrangement = Arrangement.SpaceBetween, verticalAlignment = Alignment.CenterVertically, ) { diff --git a/app/src/main/kotlin/li/songe/gkd/ui/SubsPage.kt b/app/src/main/kotlin/li/songe/gkd/ui/SubsPage.kt index 681dbb053..09844833d 100644 --- a/app/src/main/kotlin/li/songe/gkd/ui/SubsPage.kt +++ b/app/src/main/kotlin/li/songe/gkd/ui/SubsPage.kt @@ -115,8 +115,13 @@ fun SubsPage( val showUninstallApp by vm.showUninstallAppFlow.collectAsState() val sortType by vm.sortTypeFlow.collectAsState() val listState = rememberLazyListState() + var isFirstVisit by remember { mutableStateOf(false) } LaunchedEffect(key1 = appAndConfigs, block = { - listState.scrollToItem(0) + if (isFirstVisit) { + listState.scrollToItem(0) + } else { + isFirstVisit = true + } }) Scaffold( diff --git a/app/src/main/kotlin/li/songe/gkd/ui/component/SubsAppCard.kt b/app/src/main/kotlin/li/songe/gkd/ui/component/SubsAppCard.kt index 5825b05d1..83c40266b 100644 --- a/app/src/main/kotlin/li/songe/gkd/ui/component/SubsAppCard.kt +++ b/app/src/main/kotlin/li/songe/gkd/ui/component/SubsAppCard.kt @@ -5,13 +5,14 @@ import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.IntrinsicSize import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.aspectRatio import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.wrapContentSize import androidx.compose.material.icons.Icons @@ -58,27 +59,35 @@ fun SubsAppCard( var expanded by remember { mutableStateOf(false) } Row( modifier = Modifier - .height(60.dp) .clickable { onClick?.invoke() } - .padding(4.dp), + .height(IntrinsicSize.Min) + .padding(10.dp, 6.dp), horizontalArrangement = Arrangement.SpaceBetween, verticalAlignment = Alignment.CenterVertically, ) { if (appInfo?.icon != null) { - Image( - painter = rememberDrawablePainter(appInfo.icon), - contentDescription = null, + Box( modifier = Modifier - .size(52.dp) - ) + .fillMaxHeight() + .aspectRatio(1f) + ) { + Image( + painter = rememberDrawablePainter(appInfo.icon), + contentDescription = null, + modifier = Modifier + .matchParentSize() + .padding(4.dp) + ) + } } else { Icon( imageVector = Icons.Default.Android, contentDescription = null, modifier = Modifier - .size(52.dp) + .aspectRatio(1f) + .fillMaxHeight() .padding(4.dp) ) } diff --git a/app/src/main/kotlin/li/songe/gkd/ui/home/AppListPage.kt b/app/src/main/kotlin/li/songe/gkd/ui/home/AppListPage.kt index 25111b508..8f099cf15 100644 --- a/app/src/main/kotlin/li/songe/gkd/ui/home/AppListPage.kt +++ b/app/src/main/kotlin/li/songe/gkd/ui/home/AppListPage.kt @@ -5,13 +5,14 @@ import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.IntrinsicSize import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.aspectRatio import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.wrapContentSize import androidx.compose.foundation.lazy.LazyColumn @@ -97,8 +98,14 @@ fun useAppListPage(): ScaffoldExt { } }) val listState = rememberLazyListState() + + var isFirstVisit by remember { mutableStateOf(false) } LaunchedEffect(key1 = orderedAppInfos, block = { - listState.scrollToItem(0) + if (isFirstVisit) { + listState.scrollToItem(0) + } else { + isFirstVisit = true + } }) val scrollBehavior = TopAppBarDefaults.enterAlwaysScrollBehavior() return ScaffoldExt(navItem = appListNav, @@ -222,37 +229,41 @@ fun useAppListPage(): ScaffoldExt { items(orderedAppInfos, { it.id }) { appInfo -> Row( modifier = Modifier - .height(60.dp) .clickable { navController.navigate(AppConfigPageDestination(appInfo.id)) } + .height(IntrinsicSize.Min) .padding(4.dp), horizontalArrangement = Arrangement.SpaceBetween, verticalAlignment = Alignment.CenterVertically, ) { if (appInfo.icon != null) { - Image( - painter = rememberDrawablePainter(appInfo.icon), - contentDescription = null, + Box( modifier = Modifier - .size(52.dp) - ) + .fillMaxHeight() + .aspectRatio(1f) + ) { + Image( + painter = rememberDrawablePainter(appInfo.icon), + contentDescription = null, + modifier = Modifier + .matchParentSize() + .padding(4.dp) + ) + } } else { Icon( imageVector = Icons.Default.Android, contentDescription = null, modifier = Modifier - .size(52.dp) + .aspectRatio(1f) + .fillMaxHeight() .padding(4.dp) ) } Spacer(modifier = Modifier.width(10.dp)) Column( - modifier = Modifier - .padding(2.dp) - .fillMaxHeight() - .weight(1f), - verticalArrangement = Arrangement.SpaceBetween + modifier = Modifier.weight(1f), ) { Text( text = appInfo.name, diff --git a/app/src/main/kotlin/li/songe/gkd/ui/home/ControlPage.kt b/app/src/main/kotlin/li/songe/gkd/ui/home/ControlPage.kt index 4af144330..8468a0679 100644 --- a/app/src/main/kotlin/li/songe/gkd/ui/home/ControlPage.kt +++ b/app/src/main/kotlin/li/songe/gkd/ui/home/ControlPage.kt @@ -132,7 +132,7 @@ fun useControlPage(): ScaffoldExt { TextSwitch( name = "常驻通知", - desc = "在通知栏显示服务运行状态及统计数据", + desc = "通知栏显示运行状态及统计数据", checked = manageRunning && store.enableStatusService, onCheckedChange = { if (it) { diff --git a/app/src/main/kotlin/li/songe/gkd/ui/home/SettingsPage.kt b/app/src/main/kotlin/li/songe/gkd/ui/home/SettingsPage.kt index 4a608e854..2a9ed6f88 100644 --- a/app/src/main/kotlin/li/songe/gkd/ui/home/SettingsPage.kt +++ b/app/src/main/kotlin/li/songe/gkd/ui/home/SettingsPage.kt @@ -186,20 +186,23 @@ fun useSettingsPage(): ScaffoldExt { }, ) }, onDismissRequest = { showToastInputDlg = false }, confirmButton = { - TextButton(onClick = { - storeFlow.value = store.copy( - clickToast = value - ) - showToastInputDlg = false - }) { + TextButton( + enabled = value.isNotEmpty(), + onClick = { + storeFlow.value = store.copy( + clickToast = value + ) + showToastInputDlg = false + } + ) { Text( - text = "确认", modifier = Modifier + text = "确认", ) } }, dismissButton = { TextButton(onClick = { showToastInputDlg = false }) { Text( - text = "取消", modifier = Modifier + text = "取消", ) } }) diff --git a/app/src/main/kotlin/li/songe/gkd/ui/home/SubsManagePage.kt b/app/src/main/kotlin/li/songe/gkd/ui/home/SubsManagePage.kt index 5060a477f..c1c05405a 100644 --- a/app/src/main/kotlin/li/songe/gkd/ui/home/SubsManagePage.kt +++ b/app/src/main/kotlin/li/songe/gkd/ui/home/SubsManagePage.kt @@ -209,27 +209,29 @@ fun useSubsManagePage(): ScaffoldExt { modifier = Modifier.fillMaxWidth() ) }, onDismissRequest = { showAddLinkDialog = false }, confirmButton = { - TextButton(onClick = { - if (!URLUtil.isNetworkUrl(link)) { - toast("非法链接") - return@TextButton - } - if (subItems.any { s -> s.updateUrl == link }) { - toast("链接已存在") - return@TextButton - } - vm.viewModelScope.launch { - if (!isSafeUrl(link)) { - val result = getDialogResult( - "未知来源", - "你正在添加一个未验证的远程订阅\n\n这可能含有恶意的规则\n\n是否仍然确认添加?" - ) - if (!result) return@launch + TextButton( + enabled = link.isNotBlank(), + onClick = { + if (!URLUtil.isNetworkUrl(link)) { + toast("非法链接") + return@TextButton } - showAddLinkDialog = false - vm.addSubsFromUrl(url = link) - } - }) { + if (subItems.any { s -> s.updateUrl == link }) { + toast("链接已存在") + return@TextButton + } + vm.viewModelScope.launchTry { + if (!isSafeUrl(link)) { + val result = getDialogResult( + "未知来源", + "你正在添加一个未验证的远程订阅\n\n这可能含有恶意的规则\n\n是否仍然确认添加?" + ) + if (!result) return@launchTry + } + showAddLinkDialog = false + vm.addSubsFromUrl(url = link) + } + }) { Text(text = "添加") } })