mirror of
https://github.com/gkd-kit/gkd.git
synced 2024-11-15 19:22:26 +08:00
This commit is contained in:
parent
a60ecdf3e8
commit
8adbf711ca
|
@ -26,6 +26,7 @@ import com.ramcosta.composedestinations.annotation.Destination
|
|||
import com.ramcosta.composedestinations.annotation.RootNavGraph
|
||||
import li.songe.gkd.BuildConfig
|
||||
import li.songe.gkd.channel
|
||||
import li.songe.gkd.ui.style.EmptyHeight
|
||||
import li.songe.gkd.ui.style.itemPadding
|
||||
import li.songe.gkd.util.GIT_COMMIT_URL
|
||||
import li.songe.gkd.util.LocalNavController
|
||||
|
@ -167,7 +168,7 @@ fun AboutPage() {
|
|||
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
)
|
||||
}
|
||||
Spacer(modifier = Modifier.height(40.dp))
|
||||
Spacer(modifier = Modifier.height(EmptyHeight))
|
||||
}
|
||||
}
|
||||
}
|
|
@ -84,10 +84,12 @@ import li.songe.gkd.util.appInfoCacheFlow
|
|||
import li.songe.gkd.util.json
|
||||
import li.songe.gkd.util.launchAsFn
|
||||
import li.songe.gkd.util.launchTry
|
||||
import li.songe.gkd.util.navigate
|
||||
import com.ramcosta.composedestinations.navigation.navigate
|
||||
import li.songe.gkd.ui.style.EmptyHeight
|
||||
import li.songe.gkd.util.openApp
|
||||
import li.songe.gkd.util.openUri
|
||||
import li.songe.gkd.util.storeFlow
|
||||
import li.songe.gkd.util.throttle
|
||||
import li.songe.gkd.util.toast
|
||||
import rikka.shizuku.Shizuku
|
||||
|
||||
|
@ -368,7 +370,7 @@ fun AdvancedPage() {
|
|||
)
|
||||
})
|
||||
|
||||
Spacer(modifier = Modifier.height(40.dp))
|
||||
Spacer(modifier = Modifier.height(EmptyHeight))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -71,7 +71,9 @@ import li.songe.gkd.util.ResolvedGroup
|
|||
import li.songe.gkd.util.RuleSortOption
|
||||
import li.songe.gkd.util.appInfoCacheFlow
|
||||
import li.songe.gkd.util.launchTry
|
||||
import li.songe.gkd.util.navigate
|
||||
import com.ramcosta.composedestinations.navigation.navigate
|
||||
import li.songe.gkd.ui.style.EmptyHeight
|
||||
import li.songe.gkd.util.throttle
|
||||
|
||||
@RootNavGraph
|
||||
@Destination(style = ProfileTransitions::class)
|
||||
|
@ -161,7 +163,7 @@ fun AppConfigPage(appId: String) {
|
|||
},
|
||||
floatingActionButton = {
|
||||
FloatingActionButton(
|
||||
onClick = {
|
||||
onClick = throttle {
|
||||
navController.navigate(AppItemPageDestination(LOCAL_SUBS_ID, appId))
|
||||
},
|
||||
content = {
|
||||
|
@ -187,7 +189,7 @@ fun AppConfigPage(appId: String) {
|
|||
vm = vm,
|
||||
group = g.group,
|
||||
checked = checked,
|
||||
onClick = {
|
||||
onClick = throttle {
|
||||
navController.navigate(
|
||||
GlobalRulePageDestination(
|
||||
g.subsItem.id,
|
||||
|
@ -252,7 +254,7 @@ fun AppConfigPage(appId: String) {
|
|||
}
|
||||
}
|
||||
item {
|
||||
Spacer(modifier = Modifier.height(40.dp))
|
||||
Spacer(modifier = Modifier.height(EmptyHeight))
|
||||
if (globalGroups.size + appGroups.size == 0) {
|
||||
Text(
|
||||
text = "暂无规则",
|
||||
|
@ -261,7 +263,7 @@ fun AppConfigPage(appId: String) {
|
|||
)
|
||||
} else {
|
||||
// 避免被 floatingActionButton 遮挡
|
||||
Spacer(modifier = Modifier.height(40.dp))
|
||||
Spacer(modifier = Modifier.height(EmptyHeight))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -80,7 +80,9 @@ import li.songe.gkd.util.json
|
|||
import li.songe.gkd.util.json5ToJson
|
||||
import li.songe.gkd.util.launchAsFn
|
||||
import li.songe.gkd.util.launchTry
|
||||
import li.songe.gkd.util.navigate
|
||||
import com.ramcosta.composedestinations.navigation.navigate
|
||||
import li.songe.gkd.ui.style.EmptyHeight
|
||||
import li.songe.gkd.util.throttle
|
||||
import li.songe.gkd.util.toast
|
||||
import li.songe.gkd.util.updateSubscription
|
||||
|
||||
|
@ -327,7 +329,7 @@ fun AppItemPage(
|
|||
}
|
||||
|
||||
item {
|
||||
Spacer(modifier = Modifier.height(40.dp))
|
||||
Spacer(modifier = Modifier.height(EmptyHeight))
|
||||
if (appRaw.groups.isEmpty()) {
|
||||
Text(
|
||||
text = "暂无规则",
|
||||
|
@ -335,7 +337,7 @@ fun AppItemPage(
|
|||
textAlign = TextAlign.Center
|
||||
)
|
||||
} else if (editable) {
|
||||
Spacer(modifier = Modifier.height(40.dp))
|
||||
Spacer(modifier = Modifier.height(EmptyHeight))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -357,7 +359,7 @@ fun AppItemPage(
|
|||
},
|
||||
confirmButton = {
|
||||
if (showGroupItemVal.allExampleUrls.isNotEmpty()) {
|
||||
TextButton(onClick = {
|
||||
TextButton(onClick = throttle {
|
||||
setShowGroupItem(null)
|
||||
navController.navigate(
|
||||
GroupImagePageDestination(
|
||||
|
|
|
@ -51,6 +51,7 @@ import li.songe.gkd.data.RawSubscription
|
|||
import li.songe.gkd.db.DbSet
|
||||
import li.songe.gkd.ui.component.TowLineText
|
||||
import li.songe.gkd.ui.component.getDialogResult
|
||||
import li.songe.gkd.ui.style.EmptyHeight
|
||||
import li.songe.gkd.ui.style.itemPadding
|
||||
import li.songe.gkd.util.EnableGroupOption
|
||||
import li.songe.gkd.util.LocalNavController
|
||||
|
@ -226,7 +227,7 @@ fun CategoryPage(subsItemId: Long) {
|
|||
}
|
||||
}
|
||||
item {
|
||||
Spacer(modifier = Modifier.height(40.dp))
|
||||
Spacer(modifier = Modifier.height(EmptyHeight))
|
||||
if (categories.isEmpty()) {
|
||||
Text(
|
||||
text = "暂无类别",
|
||||
|
@ -234,7 +235,7 @@ fun CategoryPage(subsItemId: Long) {
|
|||
modifier = Modifier.fillMaxWidth()
|
||||
)
|
||||
} else if (editable) {
|
||||
Spacer(modifier = Modifier.height(40.dp))
|
||||
Spacer(modifier = Modifier.height(EmptyHeight))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -64,8 +64,10 @@ import li.songe.gkd.util.LocalNavController
|
|||
import li.songe.gkd.util.ProfileTransitions
|
||||
import li.songe.gkd.util.appInfoCacheFlow
|
||||
import li.songe.gkd.util.launchAsFn
|
||||
import li.songe.gkd.util.navigate
|
||||
import com.ramcosta.composedestinations.navigation.navigate
|
||||
import li.songe.gkd.ui.style.EmptyHeight
|
||||
import li.songe.gkd.util.subsIdToRawFlow
|
||||
import li.songe.gkd.util.throttle
|
||||
import li.songe.gkd.util.toast
|
||||
|
||||
@RootNavGraph
|
||||
|
@ -182,7 +184,7 @@ fun ClickLogPage() {
|
|||
HorizontalDivider()
|
||||
}
|
||||
item {
|
||||
Spacer(modifier = Modifier.height(40.dp))
|
||||
Spacer(modifier = Modifier.height(EmptyHeight))
|
||||
if (clickLogCount == 0) {
|
||||
Text(
|
||||
text = "暂无记录",
|
||||
|
@ -209,8 +211,8 @@ fun ClickLogPage() {
|
|||
val appInfo = appInfoCache[clickLog.appId]
|
||||
|
||||
Text(text = "查看规则组", modifier = Modifier
|
||||
.clickable {
|
||||
clickLog.appId ?: return@clickable
|
||||
.clickable(onClick = throttle {
|
||||
clickLog.appId ?: return@throttle
|
||||
if (clickLog.groupType == SubsConfig.AppGroupType) {
|
||||
navController.navigate(
|
||||
AppItemPageDestination(
|
||||
|
@ -225,7 +227,7 @@ fun ClickLogPage() {
|
|||
)
|
||||
}
|
||||
previewClickLog = null
|
||||
}
|
||||
})
|
||||
.fillMaxWidth()
|
||||
.padding(16.dp))
|
||||
if (clickLog.groupType == SubsConfig.GlobalGroupType && clickLog.appId != null) {
|
||||
|
|
|
@ -70,6 +70,7 @@ import li.songe.gkd.db.DbSet
|
|||
import li.songe.gkd.service.launcherAppId
|
||||
import li.songe.gkd.ui.component.AppBarTextField
|
||||
import li.songe.gkd.ui.component.TowLineText
|
||||
import li.songe.gkd.ui.style.EmptyHeight
|
||||
import li.songe.gkd.ui.style.appItemPadding
|
||||
import li.songe.gkd.ui.style.menuPadding
|
||||
import li.songe.gkd.util.LocalNavController
|
||||
|
@ -344,14 +345,14 @@ fun GlobalRuleExcludePage(subsItemId: Long, groupKey: Int) {
|
|||
}
|
||||
}
|
||||
item {
|
||||
Spacer(modifier = Modifier.height(40.dp))
|
||||
Spacer(modifier = Modifier.height(EmptyHeight))
|
||||
if (showAppInfos.isEmpty()) {
|
||||
Column(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
) {
|
||||
Text(text = "暂无搜索结果")
|
||||
Spacer(modifier = Modifier.height(40.dp))
|
||||
Spacer(modifier = Modifier.height(EmptyHeight))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -74,7 +74,9 @@ import li.songe.gkd.util.encodeToJson5String
|
|||
import li.songe.gkd.util.json
|
||||
import li.songe.gkd.util.launchAsFn
|
||||
import li.songe.gkd.util.launchTry
|
||||
import li.songe.gkd.util.navigate
|
||||
import com.ramcosta.composedestinations.navigation.navigate
|
||||
import li.songe.gkd.ui.style.EmptyHeight
|
||||
import li.songe.gkd.util.throttle
|
||||
import li.songe.gkd.util.toast
|
||||
import li.songe.gkd.util.updateSubscription
|
||||
|
||||
|
@ -233,7 +235,7 @@ fun GlobalRulePage(subsItemId: Long, focusGroupKey: Int? = null) {
|
|||
text = {
|
||||
Text(text = "编辑禁用")
|
||||
},
|
||||
onClick = {
|
||||
onClick = throttle {
|
||||
expanded = false
|
||||
navController.navigate(
|
||||
GlobalRuleExcludePageDestination(
|
||||
|
@ -295,7 +297,7 @@ fun GlobalRulePage(subsItemId: Long, focusGroupKey: Int? = null) {
|
|||
}
|
||||
}
|
||||
item {
|
||||
Spacer(modifier = Modifier.height(40.dp))
|
||||
Spacer(modifier = Modifier.height(EmptyHeight))
|
||||
if (globalGroups.isEmpty()) {
|
||||
Text(
|
||||
text = "暂无规则",
|
||||
|
@ -303,7 +305,7 @@ fun GlobalRulePage(subsItemId: Long, focusGroupKey: Int? = null) {
|
|||
textAlign = TextAlign.Center
|
||||
)
|
||||
} else if (editable) {
|
||||
Spacer(modifier = Modifier.height(40.dp))
|
||||
Spacer(modifier = Modifier.height(EmptyHeight))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -465,7 +467,7 @@ fun GlobalRulePage(subsItemId: Long, focusGroupKey: Int? = null) {
|
|||
},
|
||||
confirmButton = {
|
||||
if (showGroupItem.allExampleUrls.isNotEmpty()) {
|
||||
TextButton(onClick = {
|
||||
TextButton(onClick = throttle {
|
||||
setShowGroupItem(null)
|
||||
navController.navigate(
|
||||
GroupImagePageDestination(
|
||||
|
|
|
@ -43,8 +43,10 @@ import li.songe.gkd.ui.style.itemPadding
|
|||
import li.songe.gkd.util.LocalNavController
|
||||
import li.songe.gkd.util.ProfileTransitions
|
||||
import li.songe.gkd.util.appInfoCacheFlow
|
||||
import li.songe.gkd.util.navigate
|
||||
import com.ramcosta.composedestinations.navigation.navigate
|
||||
import li.songe.gkd.ui.style.EmptyHeight
|
||||
import li.songe.gkd.util.ruleSummaryFlow
|
||||
import li.songe.gkd.util.throttle
|
||||
|
||||
@RootNavGraph
|
||||
@Destination(style = ProfileTransitions::class)
|
||||
|
@ -91,14 +93,14 @@ fun SlowGroupPage() {
|
|||
) { (group, rule) ->
|
||||
SlowGroupCard(
|
||||
modifier = Modifier
|
||||
.clickable {
|
||||
.clickable(onClick = throttle {
|
||||
navController.navigate(
|
||||
GlobalRulePageDestination(
|
||||
rule.subsItem.id,
|
||||
group.key
|
||||
)
|
||||
)
|
||||
}
|
||||
})
|
||||
.itemPadding(),
|
||||
title = group.name,
|
||||
desc = "${rule.rawSubs.name}/全局规则"
|
||||
|
@ -110,7 +112,7 @@ fun SlowGroupPage() {
|
|||
) { (group, rule) ->
|
||||
SlowGroupCard(
|
||||
modifier = Modifier
|
||||
.clickable {
|
||||
.clickable(onClick = throttle {
|
||||
navController.navigate(
|
||||
AppItemPageDestination(
|
||||
rule.subsItem.id,
|
||||
|
@ -118,14 +120,14 @@ fun SlowGroupPage() {
|
|||
group.key
|
||||
)
|
||||
)
|
||||
}
|
||||
})
|
||||
.itemPadding(),
|
||||
title = group.name,
|
||||
desc = "${rule.rawSubs.name}/应用规则/${appInfoCache[rule.app.id]?.name ?: rule.app.name ?: rule.app.id}"
|
||||
)
|
||||
}
|
||||
item {
|
||||
Spacer(modifier = Modifier.height(40.dp))
|
||||
Spacer(modifier = Modifier.height(EmptyHeight))
|
||||
if (ruleSummary.slowGroupCount == 0) {
|
||||
Text(
|
||||
text = "暂无规则",
|
||||
|
|
|
@ -65,9 +65,11 @@ import li.songe.gkd.util.LocalNavController
|
|||
import li.songe.gkd.util.LocalPickContentLauncher
|
||||
import li.songe.gkd.util.ProfileTransitions
|
||||
import li.songe.gkd.util.launchAsFn
|
||||
import li.songe.gkd.util.navigate
|
||||
import com.ramcosta.composedestinations.navigation.navigate
|
||||
import li.songe.gkd.ui.style.EmptyHeight
|
||||
import li.songe.gkd.util.shareFile
|
||||
import li.songe.gkd.util.snapshotZipDir
|
||||
import li.songe.gkd.util.throttle
|
||||
import li.songe.gkd.util.toast
|
||||
|
||||
@RootNavGraph
|
||||
|
@ -156,7 +158,7 @@ fun SnapshotPage() {
|
|||
HorizontalDivider()
|
||||
}
|
||||
item {
|
||||
Spacer(modifier = Modifier.height(40.dp))
|
||||
Spacer(modifier = Modifier.height(EmptyHeight))
|
||||
if (snapshots.isEmpty()) {
|
||||
Text(
|
||||
text = "暂无记录",
|
||||
|
@ -182,7 +184,7 @@ fun SnapshotPage() {
|
|||
.padding(16.dp)
|
||||
Text(
|
||||
text = "查看", modifier = Modifier
|
||||
.clickable(onClick = scope.launchAsFn {
|
||||
.clickable(onClick = throttle(fn = scope.launchAsFn {
|
||||
navController.navigate(
|
||||
ImagePreviewPageDestination(
|
||||
filePath = snapshotVal.screenshotFile.absolutePath,
|
||||
|
@ -190,7 +192,7 @@ fun SnapshotPage() {
|
|||
)
|
||||
)
|
||||
selectedSnapshot = null
|
||||
})
|
||||
}))
|
||||
.then(modifier)
|
||||
)
|
||||
HorizontalDivider()
|
||||
|
|
|
@ -45,12 +45,12 @@ import androidx.compose.ui.focus.FocusRequester
|
|||
import androidx.compose.ui.focus.focusRequester
|
||||
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.hilt.navigation.compose.hiltViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.blankj.utilcode.util.LogUtils
|
||||
import com.ramcosta.composedestinations.annotation.Destination
|
||||
import com.ramcosta.composedestinations.annotation.RootNavGraph
|
||||
import com.ramcosta.composedestinations.navigation.navigate
|
||||
import li.songe.gkd.data.RawSubscription
|
||||
import li.songe.gkd.data.SubsConfig
|
||||
import li.songe.gkd.db.DbSet
|
||||
|
@ -59,6 +59,7 @@ import li.songe.gkd.ui.component.SubsAppCard
|
|||
import li.songe.gkd.ui.component.TowLineText
|
||||
import li.songe.gkd.ui.component.getDialogResult
|
||||
import li.songe.gkd.ui.destinations.AppItemPageDestination
|
||||
import li.songe.gkd.ui.style.EmptyHeight
|
||||
import li.songe.gkd.ui.style.menuPadding
|
||||
import li.songe.gkd.util.LocalNavController
|
||||
import li.songe.gkd.util.ProfileTransitions
|
||||
|
@ -68,7 +69,7 @@ import li.songe.gkd.util.encodeToJson5String
|
|||
import li.songe.gkd.util.json
|
||||
import li.songe.gkd.util.launchAsFn
|
||||
import li.songe.gkd.util.launchTry
|
||||
import li.songe.gkd.util.navigate
|
||||
import li.songe.gkd.util.throttle
|
||||
import li.songe.gkd.util.toast
|
||||
import li.songe.gkd.util.updateSubscription
|
||||
|
||||
|
@ -249,10 +250,10 @@ fun SubsPage(
|
|||
appInfo = appInfoCache[appRaw.id],
|
||||
subsConfig = subsConfig,
|
||||
enableSize = enableSize,
|
||||
onClick = {
|
||||
onClick = throttle {
|
||||
navController.navigate(AppItemPageDestination(subsItemId, appRaw.id))
|
||||
},
|
||||
onValueChange = scope.launchAsFn { enable ->
|
||||
onValueChange = throttle(fn = scope.launchAsFn { enable ->
|
||||
val newItem = subsConfig?.copy(
|
||||
enable = enable
|
||||
) ?: SubsConfig(
|
||||
|
@ -262,9 +263,9 @@ fun SubsPage(
|
|||
appId = appRaw.id,
|
||||
)
|
||||
DbSet.subsConfigDao.insert(newItem)
|
||||
},
|
||||
}),
|
||||
showMenu = editable,
|
||||
onDelClick = vm.viewModelScope.launchAsFn {
|
||||
onDelClick = throttle(fn = vm.viewModelScope.launchAsFn {
|
||||
val result = getDialogResult(
|
||||
"删除规则组",
|
||||
"确定删除 ${appInfoCache[appRaw.id]?.name ?: appRaw.name ?: appRaw.id} 下所有规则组?"
|
||||
|
@ -277,9 +278,10 @@ fun SubsPage(
|
|||
toast("删除成功")
|
||||
}
|
||||
})
|
||||
)
|
||||
}
|
||||
item {
|
||||
Spacer(modifier = Modifier.height(40.dp))
|
||||
Spacer(modifier = Modifier.height(EmptyHeight))
|
||||
if (appAndConfigs.isEmpty()) {
|
||||
Text(
|
||||
text = if (searchStr.isNotEmpty()) "暂无搜索结果" else "暂无规则",
|
||||
|
@ -287,7 +289,7 @@ fun SubsPage(
|
|||
textAlign = TextAlign.Center
|
||||
)
|
||||
} else if (editable) {
|
||||
Spacer(modifier = Modifier.height(40.dp))
|
||||
Spacer(modifier = Modifier.height(EmptyHeight))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ import androidx.compose.ui.Alignment
|
|||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.dp
|
||||
import li.songe.gkd.ui.style.itemPadding
|
||||
import li.songe.gkd.util.throttle
|
||||
|
||||
@Composable
|
||||
fun AuthCard(
|
||||
|
@ -36,7 +37,7 @@ fun AuthCard(
|
|||
)
|
||||
}
|
||||
Spacer(modifier = Modifier.width(10.dp))
|
||||
OutlinedButton(onClick = onAuthClick) {
|
||||
OutlinedButton(onClick = throttle(fn = onAuthClick)) {
|
||||
Text(text = "授权")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@ import androidx.compose.ui.Alignment
|
|||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import li.songe.gkd.ui.style.itemPadding
|
||||
import li.songe.gkd.util.throttle
|
||||
|
||||
@Composable
|
||||
fun SettingItem(
|
||||
|
@ -24,7 +25,7 @@ fun SettingItem(
|
|||
Row(
|
||||
modifier = Modifier
|
||||
.clickable(
|
||||
onClick = onClick
|
||||
onClick = throttle(fn = onClick)
|
||||
)
|
||||
.fillMaxWidth()
|
||||
.itemPadding(),
|
||||
|
|
|
@ -187,8 +187,8 @@ fun SubsAppCard(
|
|||
}
|
||||
|
||||
Switch(
|
||||
subsConfig?.enable ?: (appInfo != null),
|
||||
onValueChange,
|
||||
checked = subsConfig?.enable ?: (appInfo != null),
|
||||
onCheckedChange = onValueChange,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -45,11 +45,12 @@ import li.songe.gkd.util.LocalNavController
|
|||
import li.songe.gkd.util.formatTimeAgo
|
||||
import li.songe.gkd.util.launchTry
|
||||
import li.songe.gkd.util.map
|
||||
import li.songe.gkd.util.navigate
|
||||
import com.ramcosta.composedestinations.navigation.navigate
|
||||
import li.songe.gkd.util.openUri
|
||||
import li.songe.gkd.util.subsLoadErrorsFlow
|
||||
import li.songe.gkd.util.subsRefreshErrorsFlow
|
||||
import li.songe.gkd.util.subsRefreshingFlow
|
||||
import li.songe.gkd.util.throttle
|
||||
import li.songe.gkd.util.toast
|
||||
|
||||
|
||||
|
@ -206,7 +207,7 @@ private fun SubsMenuItem(
|
|||
text = {
|
||||
Text(text = "应用规则")
|
||||
},
|
||||
onClick = {
|
||||
onClick = throttle {
|
||||
onExpandedChange(false)
|
||||
navController.navigate(SubsPageDestination(subItem.id))
|
||||
}
|
||||
|
@ -217,7 +218,7 @@ private fun SubsMenuItem(
|
|||
text = {
|
||||
Text(text = "规则类别")
|
||||
},
|
||||
onClick = {
|
||||
onClick = throttle {
|
||||
onExpandedChange(false)
|
||||
navController.navigate(CategoryPageDestination(subItem.id))
|
||||
}
|
||||
|
@ -228,7 +229,7 @@ private fun SubsMenuItem(
|
|||
text = {
|
||||
Text(text = "全局规则")
|
||||
},
|
||||
onClick = {
|
||||
onClick = throttle {
|
||||
onExpandedChange(false)
|
||||
navController.navigate(GlobalRulePageDestination(subItem.id))
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ import androidx.compose.ui.Alignment
|
|||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.dp
|
||||
import li.songe.gkd.ui.style.itemPadding
|
||||
import li.songe.gkd.util.throttle
|
||||
|
||||
@Composable
|
||||
fun TextSwitch(
|
||||
|
@ -48,7 +49,7 @@ fun TextSwitch(
|
|||
Switch(
|
||||
checked = checked,
|
||||
enabled = enabled,
|
||||
onCheckedChange = onCheckedChange,
|
||||
onCheckedChange = onCheckedChange?.let { throttle(fn = it) },
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -74,9 +74,11 @@ import li.songe.gkd.util.LocalNavController
|
|||
import li.songe.gkd.util.SortTypeOption
|
||||
import li.songe.gkd.util.appRefreshingFlow
|
||||
import li.songe.gkd.util.launchAsFn
|
||||
import li.songe.gkd.util.navigate
|
||||
import com.ramcosta.composedestinations.navigation.navigate
|
||||
import li.songe.gkd.ui.style.EmptyHeight
|
||||
import li.songe.gkd.util.ruleSummaryFlow
|
||||
import li.songe.gkd.util.storeFlow
|
||||
import li.songe.gkd.util.throttle
|
||||
|
||||
val appListNav = BottomNavItem(
|
||||
label = "应用", icon = Icons.Default.Apps
|
||||
|
@ -288,9 +290,9 @@ fun useAppListPage(): ScaffoldExt {
|
|||
items(orderedAppInfos, { it.id }) { appInfo ->
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.clickable {
|
||||
.clickable(onClick = throttle {
|
||||
navController.navigate(AppConfigPageDestination(appInfo.id))
|
||||
}
|
||||
})
|
||||
.height(IntrinsicSize.Min)
|
||||
.appItemPadding(),
|
||||
horizontalArrangement = Arrangement.SpaceBetween,
|
||||
|
@ -388,7 +390,7 @@ fun useAppListPage(): ScaffoldExt {
|
|||
}
|
||||
}
|
||||
item {
|
||||
Spacer(modifier = Modifier.height(40.dp))
|
||||
Spacer(modifier = Modifier.height(EmptyHeight))
|
||||
if (orderedAppInfos.isEmpty() && searchStr.isNotEmpty()) {
|
||||
Text(
|
||||
text = "暂无搜索结果",
|
||||
|
@ -405,7 +407,7 @@ fun useAppListPage(): ScaffoldExt {
|
|||
.fillMaxWidth(),
|
||||
horizontalAlignment = Alignment.CenterHorizontally
|
||||
) {
|
||||
Spacer(modifier = Modifier.height(40.dp))
|
||||
Spacer(modifier = Modifier.height(EmptyHeight))
|
||||
CircularProgressIndicator()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,9 +31,9 @@ import androidx.compose.ui.Modifier
|
|||
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.hilt.navigation.compose.hiltViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.ramcosta.composedestinations.navigation.navigate
|
||||
import li.songe.gkd.MainActivity
|
||||
import li.songe.gkd.permission.checkOrRequestPermission
|
||||
import li.songe.gkd.permission.notificationState
|
||||
|
@ -43,14 +43,15 @@ import li.songe.gkd.ui.component.AuthCard
|
|||
import li.songe.gkd.ui.component.TextSwitch
|
||||
import li.songe.gkd.ui.destinations.ClickLogPageDestination
|
||||
import li.songe.gkd.ui.destinations.SlowGroupPageDestination
|
||||
import li.songe.gkd.ui.style.EmptyHeight
|
||||
import li.songe.gkd.ui.style.itemPadding
|
||||
import li.songe.gkd.util.HOME_PAGE_URL
|
||||
import li.songe.gkd.util.LocalNavController
|
||||
import li.songe.gkd.util.launchAsFn
|
||||
import li.songe.gkd.util.navigate
|
||||
import li.songe.gkd.util.openUri
|
||||
import li.songe.gkd.util.ruleSummaryFlow
|
||||
import li.songe.gkd.util.storeFlow
|
||||
import li.songe.gkd.util.throttle
|
||||
import li.songe.gkd.util.tryStartActivity
|
||||
|
||||
val controlNav = BottomNavItem(label = "主页", icon = Icons.Outlined.Home)
|
||||
|
@ -77,7 +78,7 @@ fun useControlPage(): ScaffoldExt {
|
|||
text = controlNav.label,
|
||||
)
|
||||
}, actions = {
|
||||
IconButton(onClick = { context.openUri(HOME_PAGE_URL) }) {
|
||||
IconButton(onClick = throttle { context.openUri(HOME_PAGE_URL) }) {
|
||||
Icon(
|
||||
imageVector = Icons.AutoMirrored.Outlined.HelpOutline,
|
||||
contentDescription = null,
|
||||
|
@ -138,9 +139,9 @@ fun useControlPage(): ScaffoldExt {
|
|||
horizontalArrangement = Arrangement.SpaceBetween,
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
modifier = Modifier
|
||||
.clickable {
|
||||
.clickable(onClick = throttle {
|
||||
navController.navigate(ClickLogPageDestination)
|
||||
}
|
||||
})
|
||||
.itemPadding(),
|
||||
) {
|
||||
Column(modifier = Modifier.weight(1f)) {
|
||||
|
@ -165,9 +166,9 @@ fun useControlPage(): ScaffoldExt {
|
|||
horizontalArrangement = Arrangement.SpaceBetween,
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
modifier = Modifier
|
||||
.clickable {
|
||||
.clickable(onClick = throttle {
|
||||
navController.navigate(SlowGroupPageDestination)
|
||||
}
|
||||
})
|
||||
.itemPadding(),
|
||||
) {
|
||||
Column(modifier = Modifier.weight(1f)) {
|
||||
|
@ -209,7 +210,7 @@ fun useControlPage(): ScaffoldExt {
|
|||
}
|
||||
}
|
||||
|
||||
Spacer(modifier = Modifier.height(40.dp))
|
||||
Spacer(modifier = Modifier.height(EmptyHeight))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ import androidx.compose.ui.unit.dp
|
|||
|
||||
val itemHorizontalPadding = 16.dp
|
||||
val itemVerticalPadding = 12.dp
|
||||
val EmptyHeight = 40.dp
|
||||
|
||||
fun Modifier.itemPadding() = this then padding(itemHorizontalPadding, itemVerticalPadding)
|
||||
|
||||
|
|
|
@ -1,21 +1,8 @@
|
|||
package li.songe.gkd.util
|
||||
|
||||
import androidx.compose.runtime.compositionLocalOf
|
||||
import androidx.navigation.NavController
|
||||
import androidx.navigation.NavHostController
|
||||
import androidx.navigation.NavOptionsBuilder
|
||||
import com.ramcosta.composedestinations.spec.Direction
|
||||
|
||||
|
||||
val LocalNavController =
|
||||
compositionLocalOf<NavHostController> { error("not found DestinationsNavigator") }
|
||||
|
||||
private val navThrottle = useThrottle()
|
||||
fun NavController.navigate(
|
||||
direction: Direction,
|
||||
navOptionsBuilder: NavOptionsBuilder.() -> Unit = {},
|
||||
) {
|
||||
navThrottle {
|
||||
navigate(direction.route, navOptionsBuilder)
|
||||
}
|
||||
}
|
|
@ -36,13 +36,31 @@ fun Long.format(formatStr: String): String {
|
|||
return df.format(this)
|
||||
}
|
||||
|
||||
fun useThrottle(interval: Long = 500L): (fn: () -> Unit) -> Unit {
|
||||
var lastTriggerTime = 0L
|
||||
return { fn ->
|
||||
private var globalThrottleLastTriggerTime = 0L
|
||||
private const val defaultThrottleInterval = 1000L
|
||||
|
||||
fun throttle(
|
||||
interval: Long = defaultThrottleInterval,
|
||||
fn: (() -> Unit)?,
|
||||
): (() -> Unit) {
|
||||
return {
|
||||
val t = System.currentTimeMillis()
|
||||
if (t - lastTriggerTime > interval) {
|
||||
lastTriggerTime = t
|
||||
fn()
|
||||
if (t - globalThrottleLastTriggerTime > interval) {
|
||||
globalThrottleLastTriggerTime = t
|
||||
fn?.invoke()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun <T> throttle(
|
||||
interval: Long = defaultThrottleInterval,
|
||||
fn: ((T) -> Unit)?,
|
||||
): ((T) -> Unit) {
|
||||
return {
|
||||
val t = System.currentTimeMillis()
|
||||
if (t - globalThrottleLastTriggerTime > interval) {
|
||||
globalThrottleLastTriggerTime = t
|
||||
fn?.invoke(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user