perf: navigation, image
Some checks failed
Build-Apk / build (push) Has been cancelled

This commit is contained in:
lisonge 2024-09-13 18:09:27 +08:00
parent 757193d742
commit a9dc129094
32 changed files with 230 additions and 289 deletions

View File

@ -1,4 +1,3 @@
import org.jetbrains.kotlin.compose.compiler.gradle.ComposeFeatureFlag
import java.io.ByteArrayOutputStream import java.io.ByteArrayOutputStream
fun String.runCommand(currentWorkingDir: File = file("./")): String { fun String.runCommand(currentWorkingDir: File = file("./")): String {
@ -175,7 +174,7 @@ configurations.configureEach {
} }
composeCompiler { composeCompiler {
featureFlags.addAll(ComposeFeatureFlag.StrongSkipping) // featureFlags.addAll(ComposeFeatureFlag.StrongSkipping) // default StrongSkipping
reportsDestination = layout.buildDirectory.dir("compose_compiler") reportsDestination = layout.buildDirectory.dir("compose_compiler")
stabilityConfigurationFile = rootProject.layout.projectDirectory.file("stability_config.conf") stabilityConfigurationFile = rootProject.layout.projectDirectory.file("stability_config.conf")
} }

View File

@ -27,6 +27,7 @@ import com.blankj.utilcode.util.ServiceUtils
import com.dylanc.activityresult.launcher.PickContentLauncher import com.dylanc.activityresult.launcher.PickContentLauncher
import com.dylanc.activityresult.launcher.StartActivityLauncher import com.dylanc.activityresult.launcher.StartActivityLauncher
import com.ramcosta.composedestinations.DestinationsNavHost import com.ramcosta.composedestinations.DestinationsNavHost
import com.ramcosta.composedestinations.generated.NavGraphs
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.update import kotlinx.coroutines.flow.update
@ -40,7 +41,6 @@ import li.songe.gkd.service.GkdAbService
import li.songe.gkd.service.ManageService import li.songe.gkd.service.ManageService
import li.songe.gkd.service.fixRestartService import li.songe.gkd.service.fixRestartService
import li.songe.gkd.service.updateLauncherAppId import li.songe.gkd.service.updateLauncherAppId
import li.songe.gkd.ui.NavGraphs
import li.songe.gkd.ui.component.BuildDialog import li.songe.gkd.ui.component.BuildDialog
import li.songe.gkd.ui.theme.AppTheme import li.songe.gkd.ui.theme.AppTheme
import li.songe.gkd.util.LocalNavController import li.songe.gkd.util.LocalNavController
@ -86,8 +86,8 @@ class MainActivity : ComponentActivity() {
LocalNavController provides navController LocalNavController provides navController
) { ) {
DestinationsNavHost( DestinationsNavHost(
navGraph = NavGraphs.root, navController = navController,
navController = navController navGraph = NavGraphs.root
) )
ShizukuErrorDialog(mainVm.shizukuErrorFlow) ShizukuErrorDialog(mainVm.shizukuErrorFlow)
AuthDialog(mainVm.authReasonFlow) AuthDialog(mainVm.authReasonFlow)

View File

@ -22,7 +22,7 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.input.nestedscroll.nestedScroll import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
import com.ramcosta.composedestinations.annotation.Destination import com.ramcosta.composedestinations.annotation.Destination
import com.ramcosta.composedestinations.annotation.RootNavGraph import com.ramcosta.composedestinations.annotation.RootGraph
import li.songe.gkd.META import li.songe.gkd.META
import li.songe.gkd.ui.style.EmptyHeight import li.songe.gkd.ui.style.EmptyHeight
import li.songe.gkd.ui.style.itemPadding import li.songe.gkd.ui.style.itemPadding
@ -32,8 +32,7 @@ import li.songe.gkd.util.REPOSITORY_URL
import li.songe.gkd.util.format import li.songe.gkd.util.format
import li.songe.gkd.util.openUri import li.songe.gkd.util.openUri
@RootNavGraph @Destination<RootGraph>(style = ProfileTransitions::class)
@Destination(style = ProfileTransitions::class)
@Composable @Composable
fun AboutPage() { fun AboutPage() {
val navController = LocalNavController.current val navController = LocalNavController.current

View File

@ -33,7 +33,7 @@ import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.paging.compose.collectAsLazyPagingItems import androidx.paging.compose.collectAsLazyPagingItems
import androidx.paging.compose.itemKey import androidx.paging.compose.itemKey
import com.ramcosta.composedestinations.annotation.Destination import com.ramcosta.composedestinations.annotation.Destination
import com.ramcosta.composedestinations.annotation.RootNavGraph import com.ramcosta.composedestinations.annotation.RootGraph
import li.songe.gkd.MainActivity import li.songe.gkd.MainActivity
import li.songe.gkd.db.DbSet import li.songe.gkd.db.DbSet
import li.songe.gkd.ui.component.EmptyText import li.songe.gkd.ui.component.EmptyText
@ -46,8 +46,7 @@ import li.songe.gkd.util.appInfoCacheFlow
import li.songe.gkd.util.launchAsFn import li.songe.gkd.util.launchAsFn
import li.songe.gkd.util.throttle import li.songe.gkd.util.throttle
@RootNavGraph @Destination<RootGraph>(style = ProfileTransitions::class)
@Destination(style = ProfileTransitions::class)
@Composable @Composable
fun ActivityLogPage() { fun ActivityLogPage() {
val context = LocalContext.current as MainActivity val context = LocalContext.current as MainActivity

View File

@ -59,8 +59,10 @@ import androidx.lifecycle.viewmodel.compose.viewModel
import com.blankj.utilcode.util.LogUtils import com.blankj.utilcode.util.LogUtils
import com.dylanc.activityresult.launcher.launchForResult import com.dylanc.activityresult.launcher.launchForResult
import com.ramcosta.composedestinations.annotation.Destination import com.ramcosta.composedestinations.annotation.Destination
import com.ramcosta.composedestinations.annotation.RootNavGraph import com.ramcosta.composedestinations.annotation.RootGraph
import com.ramcosta.composedestinations.navigation.navigate import com.ramcosta.composedestinations.generated.destinations.ActivityLogPageDestination
import com.ramcosta.composedestinations.generated.destinations.SnapshotPageDestination
import com.ramcosta.composedestinations.utils.toDestinationsNavigator
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.update import kotlinx.coroutines.flow.update
import li.songe.gkd.MainActivity import li.songe.gkd.MainActivity
@ -80,8 +82,6 @@ import li.songe.gkd.ui.component.AuthCard
import li.songe.gkd.ui.component.SettingItem import li.songe.gkd.ui.component.SettingItem
import li.songe.gkd.ui.component.TextSwitch import li.songe.gkd.ui.component.TextSwitch
import li.songe.gkd.ui.component.updateDialogOptions import li.songe.gkd.ui.component.updateDialogOptions
import li.songe.gkd.ui.destinations.ActivityLogPageDestination
import li.songe.gkd.ui.destinations.SnapshotPageDestination
import li.songe.gkd.ui.style.EmptyHeight import li.songe.gkd.ui.style.EmptyHeight
import li.songe.gkd.ui.style.itemPadding import li.songe.gkd.ui.style.itemPadding
import li.songe.gkd.ui.style.titleItemPadding import li.songe.gkd.ui.style.titleItemPadding
@ -100,8 +100,7 @@ import li.songe.gkd.util.throttle
import li.songe.gkd.util.toast import li.songe.gkd.util.toast
import rikka.shizuku.Shizuku import rikka.shizuku.Shizuku
@RootNavGraph @Destination<RootGraph>(style = ProfileTransitions::class)
@Destination(style = ProfileTransitions::class)
@Composable @Composable
fun AdvancedPage() { fun AdvancedPage() {
val context = LocalContext.current as MainActivity val context = LocalContext.current as MainActivity
@ -420,7 +419,7 @@ fun AdvancedPage() {
SettingItem( SettingItem(
title = "快照记录" + (if (snapshotCount > 0) "-$snapshotCount" else ""), title = "快照记录" + (if (snapshotCount > 0) "-$snapshotCount" else ""),
onClick = { onClick = {
navController.navigate(SnapshotPageDestination) navController.toDestinationsNavigator().navigate(SnapshotPageDestination)
} }
) )
@ -543,7 +542,7 @@ fun AdvancedPage() {
SettingItem( SettingItem(
title = "界面记录", title = "界面记录",
onClick = { onClick = {
navController.navigate(ActivityLogPageDestination) navController.toDestinationsNavigator().navigate(ActivityLogPageDestination)
} }
) )

View File

@ -49,8 +49,10 @@ import androidx.compose.ui.unit.dp
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import androidx.lifecycle.viewmodel.compose.viewModel import androidx.lifecycle.viewmodel.compose.viewModel
import com.ramcosta.composedestinations.annotation.Destination import com.ramcosta.composedestinations.annotation.Destination
import com.ramcosta.composedestinations.annotation.RootNavGraph import com.ramcosta.composedestinations.annotation.RootGraph
import com.ramcosta.composedestinations.navigation.navigate import com.ramcosta.composedestinations.generated.destinations.AppItemPageDestination
import com.ramcosta.composedestinations.generated.destinations.GlobalRulePageDestination
import com.ramcosta.composedestinations.utils.toDestinationsNavigator
import kotlinx.coroutines.flow.update import kotlinx.coroutines.flow.update
import li.songe.gkd.MainActivity import li.songe.gkd.MainActivity
import li.songe.gkd.data.ExcludeData import li.songe.gkd.data.ExcludeData
@ -60,8 +62,6 @@ import li.songe.gkd.data.stringify
import li.songe.gkd.db.DbSet import li.songe.gkd.db.DbSet
import li.songe.gkd.ui.component.EmptyText import li.songe.gkd.ui.component.EmptyText
import li.songe.gkd.ui.component.updateDialogOptions import li.songe.gkd.ui.component.updateDialogOptions
import li.songe.gkd.ui.destinations.AppItemPageDestination
import li.songe.gkd.ui.destinations.GlobalRulePageDestination
import li.songe.gkd.ui.style.EmptyHeight import li.songe.gkd.ui.style.EmptyHeight
import li.songe.gkd.ui.style.itemPadding import li.songe.gkd.ui.style.itemPadding
import li.songe.gkd.ui.style.itemVerticalPadding import li.songe.gkd.ui.style.itemVerticalPadding
@ -76,8 +76,7 @@ import li.songe.gkd.util.appInfoCacheFlow
import li.songe.gkd.util.launchTry import li.songe.gkd.util.launchTry
import li.songe.gkd.util.throttle import li.songe.gkd.util.throttle
@RootNavGraph @Destination<RootGraph>(style = ProfileTransitions::class)
@Destination(style = ProfileTransitions::class)
@Composable @Composable
fun AppConfigPage(appId: String) { fun AppConfigPage(appId: String) {
val navController = LocalNavController.current val navController = LocalNavController.current
@ -165,7 +164,7 @@ fun AppConfigPage(appId: String) {
floatingActionButton = { floatingActionButton = {
FloatingActionButton( FloatingActionButton(
onClick = throttle { onClick = throttle {
navController.navigate(AppItemPageDestination(LOCAL_SUBS_ID, appId)) navController.toDestinationsNavigator().navigate(AppItemPageDestination(LOCAL_SUBS_ID, appId))
}, },
content = { content = {
Icon( Icon(
@ -190,7 +189,7 @@ fun AppConfigPage(appId: String) {
group = g.group, group = g.group,
checked = checked, checked = checked,
onClick = throttle { onClick = throttle {
navController.navigate( navController.toDestinationsNavigator().navigate(
GlobalRulePageDestination( GlobalRulePageDestination(
g.subsItem.id, g.subsItem.id,
g.group.key g.group.key
@ -229,7 +228,7 @@ fun AppConfigPage(appId: String) {
group = g.group, group = g.group,
checked = g.enable, checked = g.enable,
onClick = { onClick = {
navController.navigate( navController.toDestinationsNavigator().navigate(
AppItemPageDestination( AppItemPageDestination(
g.subsItem.id, g.subsItem.id,
appId, appId,

View File

@ -3,6 +3,7 @@ package li.songe.gkd.ui
import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.SavedStateHandle
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import com.ramcosta.composedestinations.generated.destinations.AppConfigPageDestination
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.combine
@ -11,7 +12,6 @@ import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.flow.stateIn
import li.songe.gkd.data.SubsConfig import li.songe.gkd.data.SubsConfig
import li.songe.gkd.db.DbSet import li.songe.gkd.db.DbSet
import li.songe.gkd.ui.destinations.AppConfigPageDestination
import li.songe.gkd.util.ResolvedAppGroup import li.songe.gkd.util.ResolvedAppGroup
import li.songe.gkd.util.ResolvedGlobalGroup import li.songe.gkd.util.ResolvedGlobalGroup
import li.songe.gkd.util.RuleSortOption import li.songe.gkd.util.RuleSortOption

View File

@ -56,8 +56,9 @@ import androidx.lifecycle.viewmodel.compose.viewModel
import com.blankj.utilcode.util.ClipboardUtils import com.blankj.utilcode.util.ClipboardUtils
import com.blankj.utilcode.util.LogUtils import com.blankj.utilcode.util.LogUtils
import com.ramcosta.composedestinations.annotation.Destination import com.ramcosta.composedestinations.annotation.Destination
import com.ramcosta.composedestinations.annotation.RootNavGraph import com.ramcosta.composedestinations.annotation.RootGraph
import com.ramcosta.composedestinations.navigation.navigate import com.ramcosta.composedestinations.generated.destinations.ImagePreviewPageDestination
import com.ramcosta.composedestinations.utils.toDestinationsNavigator
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.serialization.json.JsonArray import kotlinx.serialization.json.JsonArray
import kotlinx.serialization.json.jsonObject import kotlinx.serialization.json.jsonObject
@ -70,7 +71,6 @@ import li.songe.gkd.db.DbSet
import li.songe.gkd.ui.component.EmptyText import li.songe.gkd.ui.component.EmptyText
import li.songe.gkd.ui.component.TowLineText import li.songe.gkd.ui.component.TowLineText
import li.songe.gkd.ui.component.waitResult import li.songe.gkd.ui.component.waitResult
import li.songe.gkd.ui.destinations.GroupImagePageDestination
import li.songe.gkd.ui.style.EmptyHeight import li.songe.gkd.ui.style.EmptyHeight
import li.songe.gkd.ui.style.itemPadding import li.songe.gkd.ui.style.itemPadding
import li.songe.gkd.util.LocalNavController import li.songe.gkd.util.LocalNavController
@ -86,8 +86,7 @@ import li.songe.gkd.util.updateSubscription
import li.songe.json5.Json5 import li.songe.json5.Json5
import li.songe.json5.encodeToJson5String import li.songe.json5.encodeToJson5String
@RootNavGraph @Destination<RootGraph>(style = ProfileTransitions::class)
@Destination(style = ProfileTransitions::class)
@Composable @Composable
fun AppItemPage( fun AppItemPage(
subsItemId: Long, subsItemId: Long,
@ -371,11 +370,10 @@ fun AppItemPage(
if (showGroupItemVal.allExampleUrls.isNotEmpty()) { if (showGroupItemVal.allExampleUrls.isNotEmpty()) {
TextButton(onClick = throttle { TextButton(onClick = throttle {
setShowGroupItem(null) setShowGroupItem(null)
navController.navigate( navController.toDestinationsNavigator().navigate(
GroupImagePageDestination( ImagePreviewPageDestination(
subsInt = subsItemId, title = showGroupItemVal.name,
groupKey = showGroupItemVal.key, uris = showGroupItemVal.allExampleUrls.toTypedArray()
appId = appId,
) )
) )
}) { }) {

View File

@ -3,12 +3,12 @@ package li.songe.gkd.ui
import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.SavedStateHandle
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import com.ramcosta.composedestinations.generated.destinations.AppItemPageDestination
import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.flow.stateIn
import li.songe.gkd.data.RawSubscription import li.songe.gkd.data.RawSubscription
import li.songe.gkd.db.DbSet import li.songe.gkd.db.DbSet
import li.songe.gkd.ui.destinations.AppItemPageDestination
import li.songe.gkd.util.map import li.songe.gkd.util.map
import li.songe.gkd.util.subsIdToRawFlow import li.songe.gkd.util.subsIdToRawFlow
import li.songe.gkd.util.subsItemsFlow import li.songe.gkd.util.subsItemsFlow

View File

@ -39,7 +39,7 @@ import androidx.lifecycle.viewmodel.compose.viewModel
import com.blankj.utilcode.util.ClipboardUtils import com.blankj.utilcode.util.ClipboardUtils
import com.blankj.utilcode.util.LogUtils import com.blankj.utilcode.util.LogUtils
import com.ramcosta.composedestinations.annotation.Destination import com.ramcosta.composedestinations.annotation.Destination
import com.ramcosta.composedestinations.annotation.RootNavGraph import com.ramcosta.composedestinations.annotation.RootGraph
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
import li.songe.gkd.META import li.songe.gkd.META
@ -58,8 +58,7 @@ import li.songe.gkd.util.toast
import rikka.shizuku.Shizuku import rikka.shizuku.Shizuku
import java.io.DataOutputStream import java.io.DataOutputStream
@RootNavGraph @Destination<RootGraph>(style = ProfileTransitions::class)
@Destination(style = ProfileTransitions::class)
@Composable @Composable
fun AuthA11yPage() { fun AuthA11yPage() {
val context = LocalContext.current as MainActivity val context = LocalContext.current as MainActivity

View File

@ -45,7 +45,7 @@ import androidx.compose.ui.unit.dp
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import androidx.lifecycle.viewmodel.compose.viewModel import androidx.lifecycle.viewmodel.compose.viewModel
import com.ramcosta.composedestinations.annotation.Destination import com.ramcosta.composedestinations.annotation.Destination
import com.ramcosta.composedestinations.annotation.RootNavGraph import com.ramcosta.composedestinations.annotation.RootGraph
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import li.songe.gkd.MainActivity import li.songe.gkd.MainActivity
import li.songe.gkd.data.CategoryConfig import li.songe.gkd.data.CategoryConfig
@ -66,8 +66,7 @@ import li.songe.gkd.util.throttle
import li.songe.gkd.util.toast import li.songe.gkd.util.toast
import li.songe.gkd.util.updateSubscription import li.songe.gkd.util.updateSubscription
@RootNavGraph @Destination<RootGraph>(style = ProfileTransitions::class)
@Destination(style = ProfileTransitions::class)
@Composable @Composable
fun CategoryPage(subsItemId: Long) { fun CategoryPage(subsItemId: Long) {
val context = LocalContext.current as MainActivity val context = LocalContext.current as MainActivity

View File

@ -3,10 +3,10 @@ package li.songe.gkd.ui
import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.SavedStateHandle
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import com.ramcosta.composedestinations.generated.destinations.CategoryPageDestination
import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.flow.stateIn
import li.songe.gkd.db.DbSet import li.songe.gkd.db.DbSet
import li.songe.gkd.ui.destinations.CategoryPageDestination
import li.songe.gkd.util.map import li.songe.gkd.util.map
import li.songe.gkd.util.subsIdToRawFlow import li.songe.gkd.util.subsIdToRawFlow
import li.songe.gkd.util.subsItemsFlow import li.songe.gkd.util.subsItemsFlow

View File

@ -42,8 +42,10 @@ import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.paging.compose.collectAsLazyPagingItems import androidx.paging.compose.collectAsLazyPagingItems
import androidx.paging.compose.itemKey import androidx.paging.compose.itemKey
import com.ramcosta.composedestinations.annotation.Destination import com.ramcosta.composedestinations.annotation.Destination
import com.ramcosta.composedestinations.annotation.RootNavGraph import com.ramcosta.composedestinations.annotation.RootGraph
import com.ramcosta.composedestinations.navigation.navigate import com.ramcosta.composedestinations.generated.destinations.AppItemPageDestination
import com.ramcosta.composedestinations.generated.destinations.GlobalRulePageDestination
import com.ramcosta.composedestinations.utils.toDestinationsNavigator
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.SharingStarted
@ -60,8 +62,6 @@ import li.songe.gkd.db.DbSet
import li.songe.gkd.ui.component.EmptyText import li.songe.gkd.ui.component.EmptyText
import li.songe.gkd.ui.component.StartEllipsisText import li.songe.gkd.ui.component.StartEllipsisText
import li.songe.gkd.ui.component.waitResult import li.songe.gkd.ui.component.waitResult
import li.songe.gkd.ui.destinations.AppItemPageDestination
import li.songe.gkd.ui.destinations.GlobalRulePageDestination
import li.songe.gkd.ui.style.EmptyHeight import li.songe.gkd.ui.style.EmptyHeight
import li.songe.gkd.util.LocalNavController import li.songe.gkd.util.LocalNavController
import li.songe.gkd.util.ProfileTransitions import li.songe.gkd.util.ProfileTransitions
@ -71,8 +71,7 @@ import li.songe.gkd.util.subsIdToRawFlow
import li.songe.gkd.util.throttle import li.songe.gkd.util.throttle
import li.songe.gkd.util.toast import li.songe.gkd.util.toast
@RootNavGraph @Destination<RootGraph>(style = ProfileTransitions::class)
@Destination(style = ProfileTransitions::class)
@Composable @Composable
fun ClickLogPage() { fun ClickLogPage() {
val context = LocalContext.current as MainActivity val context = LocalContext.current as MainActivity
@ -221,13 +220,13 @@ fun ClickLogPage() {
.clickable(onClick = throttle { .clickable(onClick = throttle {
clickLog.appId ?: return@throttle clickLog.appId ?: return@throttle
if (clickLog.groupType == SubsConfig.AppGroupType) { if (clickLog.groupType == SubsConfig.AppGroupType) {
navController.navigate( navController.toDestinationsNavigator().navigate(
AppItemPageDestination( AppItemPageDestination(
clickLog.subsId, clickLog.appId, clickLog.groupKey clickLog.subsId, clickLog.appId, clickLog.groupKey
) )
) )
} else if (clickLog.groupType == SubsConfig.GlobalGroupType) { } else if (clickLog.groupType == SubsConfig.GlobalGroupType) {
navController.navigate( navController.toDestinationsNavigator().navigate(
GlobalRulePageDestination( GlobalRulePageDestination(
clickLog.subsId, clickLog.groupKey clickLog.subsId, clickLog.groupKey
) )

View File

@ -60,7 +60,7 @@ import androidx.lifecycle.viewModelScope
import androidx.lifecycle.viewmodel.compose.viewModel import androidx.lifecycle.viewmodel.compose.viewModel
import com.google.accompanist.drawablepainter.rememberDrawablePainter import com.google.accompanist.drawablepainter.rememberDrawablePainter
import com.ramcosta.composedestinations.annotation.Destination import com.ramcosta.composedestinations.annotation.Destination
import com.ramcosta.composedestinations.annotation.RootNavGraph import com.ramcosta.composedestinations.annotation.RootGraph
import li.songe.gkd.data.AppInfo import li.songe.gkd.data.AppInfo
import li.songe.gkd.data.ExcludeData import li.songe.gkd.data.ExcludeData
import li.songe.gkd.data.RawSubscription import li.songe.gkd.data.RawSubscription
@ -81,8 +81,7 @@ import li.songe.gkd.util.SortTypeOption
import li.songe.gkd.util.launchTry import li.songe.gkd.util.launchTry
import li.songe.gkd.util.toast import li.songe.gkd.util.toast
@RootNavGraph @Destination<RootGraph>(style = ProfileTransitions::class)
@Destination(style = ProfileTransitions::class)
@Composable @Composable
fun GlobalRuleExcludePage(subsItemId: Long, groupKey: Int) { fun GlobalRuleExcludePage(subsItemId: Long, groupKey: Int) {
val navController = LocalNavController.current val navController = LocalNavController.current

View File

@ -3,6 +3,7 @@ package li.songe.gkd.ui
import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.SavedStateHandle
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import com.ramcosta.composedestinations.generated.destinations.GlobalRuleExcludePageDestination
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.combine
@ -11,7 +12,6 @@ import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.flow.stateIn
import li.songe.gkd.data.ExcludeData import li.songe.gkd.data.ExcludeData
import li.songe.gkd.db.DbSet import li.songe.gkd.db.DbSet
import li.songe.gkd.ui.destinations.GlobalRuleExcludePageDestination
import li.songe.gkd.util.SortTypeOption import li.songe.gkd.util.SortTypeOption
import li.songe.gkd.util.map import li.songe.gkd.util.map
import li.songe.gkd.util.orderedAppInfosFlow import li.songe.gkd.util.orderedAppInfosFlow

View File

@ -57,8 +57,10 @@ import androidx.lifecycle.viewmodel.compose.viewModel
import com.blankj.utilcode.util.ClipboardUtils import com.blankj.utilcode.util.ClipboardUtils
import com.blankj.utilcode.util.LogUtils import com.blankj.utilcode.util.LogUtils
import com.ramcosta.composedestinations.annotation.Destination import com.ramcosta.composedestinations.annotation.Destination
import com.ramcosta.composedestinations.annotation.RootNavGraph import com.ramcosta.composedestinations.annotation.RootGraph
import com.ramcosta.composedestinations.navigation.navigate import com.ramcosta.composedestinations.generated.destinations.GlobalRuleExcludePageDestination
import com.ramcosta.composedestinations.generated.destinations.ImagePreviewPageDestination
import com.ramcosta.composedestinations.utils.toDestinationsNavigator
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import li.songe.gkd.MainActivity import li.songe.gkd.MainActivity
import li.songe.gkd.data.RawSubscription import li.songe.gkd.data.RawSubscription
@ -67,8 +69,6 @@ import li.songe.gkd.db.DbSet
import li.songe.gkd.ui.component.EmptyText import li.songe.gkd.ui.component.EmptyText
import li.songe.gkd.ui.component.TowLineText import li.songe.gkd.ui.component.TowLineText
import li.songe.gkd.ui.component.waitResult import li.songe.gkd.ui.component.waitResult
import li.songe.gkd.ui.destinations.GlobalRuleExcludePageDestination
import li.songe.gkd.ui.destinations.GroupImagePageDestination
import li.songe.gkd.ui.style.EmptyHeight import li.songe.gkd.ui.style.EmptyHeight
import li.songe.gkd.ui.style.itemPadding import li.songe.gkd.ui.style.itemPadding
import li.songe.gkd.util.LocalNavController import li.songe.gkd.util.LocalNavController
@ -81,8 +81,7 @@ import li.songe.gkd.util.toast
import li.songe.gkd.util.updateSubscription import li.songe.gkd.util.updateSubscription
import li.songe.json5.encodeToJson5String import li.songe.json5.encodeToJson5String
@RootNavGraph @Destination<RootGraph>(style = ProfileTransitions::class)
@Destination(style = ProfileTransitions::class)
@Composable @Composable
fun GlobalRulePage(subsItemId: Long, focusGroupKey: Int? = null) { fun GlobalRulePage(subsItemId: Long, focusGroupKey: Int? = null) {
val context = LocalContext.current as MainActivity val context = LocalContext.current as MainActivity
@ -239,7 +238,7 @@ fun GlobalRulePage(subsItemId: Long, focusGroupKey: Int? = null) {
}, },
onClick = throttle { onClick = throttle {
expanded = false expanded = false
navController.navigate( navController.toDestinationsNavigator().navigate(
GlobalRuleExcludePageDestination( GlobalRuleExcludePageDestination(
subsItemId, subsItemId,
group.key group.key
@ -472,10 +471,10 @@ fun GlobalRulePage(subsItemId: Long, focusGroupKey: Int? = null) {
if (showGroupItem.allExampleUrls.isNotEmpty()) { if (showGroupItem.allExampleUrls.isNotEmpty()) {
TextButton(onClick = throttle { TextButton(onClick = throttle {
setShowGroupItem(null) setShowGroupItem(null)
navController.navigate( navController.toDestinationsNavigator().navigate(
GroupImagePageDestination( ImagePreviewPageDestination(
subsInt = subsItemId, title = showGroupItem.name,
groupKey = showGroupItem.key uris = showGroupItem.allExampleUrls.toTypedArray()
) )
) )
}) { }) {

View File

@ -3,10 +3,10 @@ package li.songe.gkd.ui
import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.SavedStateHandle
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import com.ramcosta.composedestinations.generated.destinations.GlobalRulePageDestination
import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.flow.stateIn
import li.songe.gkd.db.DbSet import li.songe.gkd.db.DbSet
import li.songe.gkd.ui.destinations.GlobalRulePageDestination
import li.songe.gkd.util.map import li.songe.gkd.util.map
import li.songe.gkd.util.subsIdToRawFlow import li.songe.gkd.util.subsIdToRawFlow
import li.songe.gkd.util.subsItemsFlow import li.songe.gkd.util.subsItemsFlow

View File

@ -1,119 +0,0 @@
package li.songe.gkd.ui
import androidx.compose.animation.core.AnimationConstants.DefaultDurationMillis
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.pager.HorizontalPager
import androidx.compose.foundation.pager.rememberPagerState
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.ArrowBack
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.dp
import androidx.compose.ui.zIndex
import coil.compose.SubcomposeAsyncImage
import coil.request.ImageRequest
import com.ramcosta.composedestinations.annotation.Destination
import com.ramcosta.composedestinations.annotation.RootNavGraph
import li.songe.gkd.data.RawSubscription
import li.songe.gkd.ui.component.TowLineText
import li.songe.gkd.util.LocalNavController
import li.songe.gkd.util.ProfileTransitions
import li.songe.gkd.util.imageLoader
import li.songe.gkd.util.subsIdToRawFlow
// TODO 在 app debug 模式下存在严重绘制错误问题
@RootNavGraph
@Destination(style = ProfileTransitions::class)
@Composable
fun GroupImagePage(subsInt: Long, groupKey: Int, appId: String? = null) {
val context = LocalContext.current
val navController = LocalNavController.current
val subsIdToRaw by subsIdToRawFlow.collectAsState()
val rawSubs = subsIdToRaw[subsInt]
val rawApp = rawSubs?.apps?.first { a -> a.id == appId }
val group = if (appId == null) {
rawSubs?.globalGroups?.find { g -> g.key == groupKey }
} else {
rawApp?.groups?.find { g -> g.key == groupKey }
}
val allExampleUrls = when (group) {
is RawSubscription.RawAppGroup -> group.allExampleUrls
is RawSubscription.RawGlobalGroup -> group.allExampleUrls
else -> emptyList()
}
Box(modifier = Modifier.fillMaxSize()) {
TopAppBar(
navigationIcon = {
IconButton(onClick = {
navController.popBackStack()
}) {
Icon(
imageVector = Icons.AutoMirrored.Filled.ArrowBack,
contentDescription = null,
)
}
},
title = {
if (group != null) {
TowLineText(
title = rawSubs?.name ?: subsInt.toString(),
subTitle = group.name
)
}
},
modifier = Modifier.zIndex(1f),
colors = TopAppBarDefaults.topAppBarColors(
containerColor = MaterialTheme.colorScheme.background.copy(alpha = 0.5f)
)
)
if (group != null) {
val state = rememberPagerState { allExampleUrls.size }
HorizontalPager(
modifier = Modifier.fillMaxSize(), state = state
) { p ->
val url = allExampleUrls.getOrNull(p)
if (url != null) {
SubcomposeAsyncImage(
model = ImageRequest.Builder(context).data(url)
.crossfade(DefaultDurationMillis).build(),
contentDescription = null,
modifier = Modifier.fillMaxWidth(),
loading = {
Column(
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier.fillMaxWidth()
) {
CircularProgressIndicator(modifier = Modifier.size(50.dp))
}
},
error = {
Column(
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier.fillMaxWidth()
) {
Text(text = "加载失败", color = MaterialTheme.colorScheme.error)
}
},
imageLoader = imageLoader
)
}
}
}
}
}

View File

@ -1,13 +1,19 @@
package li.songe.gkd.ui package li.songe.gkd.ui
import androidx.compose.animation.core.AnimationConstants.DefaultDurationMillis
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.verticalScroll import androidx.compose.foundation.layout.size
import androidx.compose.foundation.pager.HorizontalPager
import androidx.compose.foundation.pager.rememberPagerState
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.ArrowBack import androidx.compose.material.icons.automirrored.filled.ArrowBack
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.Icon import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
@ -15,24 +21,37 @@ import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar import androidx.compose.material3.TopAppBar
import androidx.compose.material3.TopAppBarDefaults import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.dp
import androidx.compose.ui.zIndex import androidx.compose.ui.zIndex
import coil.compose.AsyncImage import coil.compose.SubcomposeAsyncImage
import coil.request.ImageRequest
import com.ramcosta.composedestinations.annotation.Destination import com.ramcosta.composedestinations.annotation.Destination
import com.ramcosta.composedestinations.annotation.RootNavGraph import com.ramcosta.composedestinations.annotation.RootGraph
import li.songe.gkd.util.LocalNavController import li.songe.gkd.util.LocalNavController
import li.songe.gkd.util.ProfileTransitions import li.songe.gkd.util.ProfileTransitions
import li.songe.gkd.util.imageLoader
@RootNavGraph @Destination<RootGraph>(style = ProfileTransitions::class)
@Destination(style = ProfileTransitions::class)
@Composable @Composable
fun ImagePreviewPage( fun ImagePreviewPage(
filePath: String,
title: String? = null, title: String? = null,
uri: String? = null,
uris: Array<String> = emptyArray(),
) { ) {
val navController = LocalNavController.current val navController = LocalNavController.current
Box(modifier = Modifier.fillMaxSize()) { Box(
modifier = Modifier
.background(MaterialTheme.colorScheme.background)
.fillMaxSize()
) {
TopAppBar( TopAppBar(
modifier = Modifier
.zIndex(1f)
.fillMaxWidth(),
navigationIcon = { navigationIcon = {
IconButton(onClick = { IconButton(onClick = {
navController.popBackStack() navController.popBackStack()
@ -48,22 +67,73 @@ fun ImagePreviewPage(
Text(text = title) Text(text = title)
} }
}, },
actions = {},
modifier = Modifier.zIndex(1f),
colors = TopAppBarDefaults.topAppBarColors( colors = TopAppBarDefaults.topAppBarColors(
containerColor = MaterialTheme.colorScheme.background.copy(alpha = 0.5f) containerColor = MaterialTheme.colorScheme.background.copy(alpha = 0.5f)
) )
) )
val showUri = uri ?: if (uris.size == 1) uris.first() else null
Column( if (showUri != null) {
modifier = Modifier UriImage(showUri)
.fillMaxSize() } else if (uris.isNotEmpty()) {
.verticalScroll(rememberScrollState()) val state = rememberPagerState { uris.size }
) { Box(
AsyncImage( modifier = Modifier.fillMaxSize()
model = filePath, contentDescription = null, modifier = Modifier.fillMaxWidth() ) {
) HorizontalPager(
modifier = Modifier.fillMaxSize(),
state = state,
pageContent = { UriImage(uris[it]) }
)
Box(
Modifier
.align(Alignment.BottomCenter)
.fillMaxWidth()
.padding(bottom = 150.dp),
contentAlignment = Alignment.BottomCenter
) {
Text(
text = "${state.currentPage + 1}/${uris.size}",
style = MaterialTheme.typography.titleLarge
)
}
}
} }
} }
}
@Composable
private fun UriImage(uri: String) {
val context = LocalContext.current
val model = remember(uri) {
ImageRequest.Builder(context).data(uri)
.crossfade(DefaultDurationMillis).build()
}
SubcomposeAsyncImage(
modifier = Modifier.fillMaxWidth(),
model = model,
contentDescription = null,
loading = {
Column(
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center,
) {
CircularProgressIndicator(modifier = Modifier.size(40.dp))
}
},
error = {
Column(
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center,
) {
Text(
text = "加载失败",
color = MaterialTheme.colorScheme.error,
style = MaterialTheme.typography.bodyMedium
)
}
},
imageLoader = imageLoader
)
} }

View File

@ -29,13 +29,13 @@ import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.text.style.TextOverflow
import com.ramcosta.composedestinations.annotation.Destination import com.ramcosta.composedestinations.annotation.Destination
import com.ramcosta.composedestinations.annotation.RootNavGraph import com.ramcosta.composedestinations.annotation.RootGraph
import com.ramcosta.composedestinations.navigation.navigate import com.ramcosta.composedestinations.generated.destinations.AppItemPageDestination
import com.ramcosta.composedestinations.generated.destinations.GlobalRulePageDestination
import com.ramcosta.composedestinations.utils.toDestinationsNavigator
import li.songe.gkd.MainActivity import li.songe.gkd.MainActivity
import li.songe.gkd.ui.component.EmptyText import li.songe.gkd.ui.component.EmptyText
import li.songe.gkd.ui.component.updateDialogOptions import li.songe.gkd.ui.component.updateDialogOptions
import li.songe.gkd.ui.destinations.AppItemPageDestination
import li.songe.gkd.ui.destinations.GlobalRulePageDestination
import li.songe.gkd.ui.style.EmptyHeight import li.songe.gkd.ui.style.EmptyHeight
import li.songe.gkd.ui.style.itemPadding import li.songe.gkd.ui.style.itemPadding
import li.songe.gkd.util.LocalNavController import li.songe.gkd.util.LocalNavController
@ -44,8 +44,7 @@ import li.songe.gkd.util.appInfoCacheFlow
import li.songe.gkd.util.ruleSummaryFlow import li.songe.gkd.util.ruleSummaryFlow
import li.songe.gkd.util.throttle import li.songe.gkd.util.throttle
@RootNavGraph @Destination<RootGraph>(style = ProfileTransitions::class)
@Destination(style = ProfileTransitions::class)
@Composable @Composable
fun SlowGroupPage() { fun SlowGroupPage() {
val context = LocalContext.current as MainActivity val context = LocalContext.current as MainActivity
@ -91,7 +90,7 @@ fun SlowGroupPage() {
SlowGroupCard( SlowGroupCard(
modifier = Modifier modifier = Modifier
.clickable(onClick = throttle { .clickable(onClick = throttle {
navController.navigate( navController.toDestinationsNavigator().navigate(
GlobalRulePageDestination( GlobalRulePageDestination(
rule.subsItem.id, rule.subsItem.id,
group.key group.key
@ -110,7 +109,7 @@ fun SlowGroupPage() {
SlowGroupCard( SlowGroupCard(
modifier = Modifier modifier = Modifier
.clickable(onClick = throttle { .clickable(onClick = throttle {
navController.navigate( navController.toDestinationsNavigator().navigate(
AppItemPageDestination( AppItemPageDestination(
rule.subsItem.id, rule.subsItem.id,
rule.app.id, rule.app.id,

View File

@ -43,8 +43,9 @@ import com.blankj.utilcode.util.ClipboardUtils
import com.blankj.utilcode.util.ImageUtils import com.blankj.utilcode.util.ImageUtils
import com.blankj.utilcode.util.UriUtils import com.blankj.utilcode.util.UriUtils
import com.ramcosta.composedestinations.annotation.Destination import com.ramcosta.composedestinations.annotation.Destination
import com.ramcosta.composedestinations.annotation.RootNavGraph import com.ramcosta.composedestinations.annotation.RootGraph
import com.ramcosta.composedestinations.navigation.navigate import com.ramcosta.composedestinations.generated.destinations.ImagePreviewPageDestination
import com.ramcosta.composedestinations.utils.toDestinationsNavigator
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import li.songe.gkd.MainActivity import li.songe.gkd.MainActivity
@ -57,7 +58,6 @@ import li.songe.gkd.permission.requiredPermission
import li.songe.gkd.ui.component.EmptyText import li.songe.gkd.ui.component.EmptyText
import li.songe.gkd.ui.component.StartEllipsisText import li.songe.gkd.ui.component.StartEllipsisText
import li.songe.gkd.ui.component.waitResult import li.songe.gkd.ui.component.waitResult
import li.songe.gkd.ui.destinations.ImagePreviewPageDestination
import li.songe.gkd.ui.style.EmptyHeight import li.songe.gkd.ui.style.EmptyHeight
import li.songe.gkd.util.IMPORT_SHORT_URL import li.songe.gkd.util.IMPORT_SHORT_URL
import li.songe.gkd.util.LocalNavController import li.songe.gkd.util.LocalNavController
@ -69,8 +69,7 @@ import li.songe.gkd.util.snapshotZipDir
import li.songe.gkd.util.throttle import li.songe.gkd.util.throttle
import li.songe.gkd.util.toast import li.songe.gkd.util.toast
@RootNavGraph @Destination<RootGraph>(style = ProfileTransitions::class)
@Destination(style = ProfileTransitions::class)
@Composable @Composable
fun SnapshotPage() { fun SnapshotPage() {
val context = LocalContext.current as MainActivity val context = LocalContext.current as MainActivity
@ -189,12 +188,14 @@ fun SnapshotPage() {
Text( Text(
text = "查看", modifier = Modifier text = "查看", modifier = Modifier
.clickable(onClick = throttle(fn = vm.viewModelScope.launchAsFn { .clickable(onClick = throttle(fn = vm.viewModelScope.launchAsFn {
navController.navigate( navController
ImagePreviewPageDestination( .toDestinationsNavigator()
filePath = snapshotVal.screenshotFile.absolutePath, .navigate(
title = snapshotVal.appName, ImagePreviewPageDestination(
title = snapshotVal.appName,
uri = snapshotVal.screenshotFile.absolutePath,
)
) )
)
selectedSnapshot = null selectedSnapshot = null
})) }))
.then(modifier) .then(modifier)

View File

@ -48,8 +48,9 @@ import androidx.lifecycle.viewModelScope
import androidx.lifecycle.viewmodel.compose.viewModel import androidx.lifecycle.viewmodel.compose.viewModel
import com.blankj.utilcode.util.LogUtils import com.blankj.utilcode.util.LogUtils
import com.ramcosta.composedestinations.annotation.Destination import com.ramcosta.composedestinations.annotation.Destination
import com.ramcosta.composedestinations.annotation.RootNavGraph import com.ramcosta.composedestinations.annotation.RootGraph
import com.ramcosta.composedestinations.navigation.navigate import com.ramcosta.composedestinations.generated.destinations.AppItemPageDestination
import com.ramcosta.composedestinations.utils.toDestinationsNavigator
import li.songe.gkd.MainActivity import li.songe.gkd.MainActivity
import li.songe.gkd.data.RawSubscription import li.songe.gkd.data.RawSubscription
import li.songe.gkd.data.SubsConfig import li.songe.gkd.data.SubsConfig
@ -60,7 +61,6 @@ import li.songe.gkd.ui.component.QueryPkgAuthCard
import li.songe.gkd.ui.component.SubsAppCard import li.songe.gkd.ui.component.SubsAppCard
import li.songe.gkd.ui.component.TowLineText import li.songe.gkd.ui.component.TowLineText
import li.songe.gkd.ui.component.waitResult import li.songe.gkd.ui.component.waitResult
import li.songe.gkd.ui.destinations.AppItemPageDestination
import li.songe.gkd.ui.style.EmptyHeight import li.songe.gkd.ui.style.EmptyHeight
import li.songe.gkd.ui.style.menuPadding import li.songe.gkd.ui.style.menuPadding
import li.songe.gkd.util.LocalNavController import li.songe.gkd.util.LocalNavController
@ -76,8 +76,7 @@ import li.songe.gkd.util.updateSubscription
import li.songe.json5.encodeToJson5String import li.songe.json5.encodeToJson5String
@RootNavGraph @Destination<RootGraph>(style = ProfileTransitions::class)
@Destination(style = ProfileTransitions::class)
@Composable @Composable
fun SubsPage( fun SubsPage(
subsItemId: Long, subsItemId: Long,
@ -253,7 +252,7 @@ fun SubsPage(
subsConfig = subsConfig, subsConfig = subsConfig,
enableSize = enableSize, enableSize = enableSize,
onClick = throttle { onClick = throttle {
navController.navigate(AppItemPageDestination(subsItemId, appRaw.id)) navController.toDestinationsNavigator().navigate(AppItemPageDestination(subsItemId, appRaw.id))
}, },
onValueChange = throttle(fn = vm.viewModelScope.launchAsFn { enable -> onValueChange = throttle(fn = vm.viewModelScope.launchAsFn { enable ->
val newItem = subsConfig?.copy( val newItem = subsConfig?.copy(

View File

@ -3,6 +3,7 @@ package li.songe.gkd.ui
import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.SavedStateHandle
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import com.ramcosta.composedestinations.generated.destinations.SubsPageDestination
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.combine
@ -13,7 +14,6 @@ import li.songe.gkd.data.RawSubscription
import li.songe.gkd.data.SubsConfig import li.songe.gkd.data.SubsConfig
import li.songe.gkd.data.Tuple3 import li.songe.gkd.data.Tuple3
import li.songe.gkd.db.DbSet import li.songe.gkd.db.DbSet
import li.songe.gkd.ui.destinations.SubsPageDestination
import li.songe.gkd.util.SortTypeOption import li.songe.gkd.util.SortTypeOption
import li.songe.gkd.util.appInfoCacheFlow import li.songe.gkd.util.appInfoCacheFlow
import li.songe.gkd.util.collator import li.songe.gkd.util.collator

View File

@ -37,15 +37,15 @@ import androidx.compose.ui.unit.DpOffset
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import com.blankj.utilcode.util.ClipboardUtils import com.blankj.utilcode.util.ClipboardUtils
import com.ramcosta.composedestinations.navigation.navigate import com.ramcosta.composedestinations.generated.destinations.CategoryPageDestination
import com.ramcosta.composedestinations.generated.destinations.GlobalRulePageDestination
import com.ramcosta.composedestinations.generated.destinations.SubsPageDestination
import com.ramcosta.composedestinations.utils.toDestinationsNavigator
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import li.songe.gkd.MainActivity import li.songe.gkd.MainActivity
import li.songe.gkd.data.RawSubscription import li.songe.gkd.data.RawSubscription
import li.songe.gkd.data.SubsItem import li.songe.gkd.data.SubsItem
import li.songe.gkd.data.deleteSubscription import li.songe.gkd.data.deleteSubscription
import li.songe.gkd.ui.destinations.CategoryPageDestination
import li.songe.gkd.ui.destinations.GlobalRulePageDestination
import li.songe.gkd.ui.destinations.SubsPageDestination
import li.songe.gkd.ui.home.HomeVm import li.songe.gkd.ui.home.HomeVm
import li.songe.gkd.util.LOCAL_SUBS_ID import li.songe.gkd.util.LOCAL_SUBS_ID
import li.songe.gkd.util.LocalNavController import li.songe.gkd.util.LocalNavController
@ -237,7 +237,7 @@ private fun SubsMenuItem(
}, },
onClick = throttle { onClick = throttle {
onExpandedChange(false) onExpandedChange(false)
navController.navigate(SubsPageDestination(subItem.id)) navController.toDestinationsNavigator().navigate(SubsPageDestination(subItem.id))
} }
) )
} }
@ -248,7 +248,7 @@ private fun SubsMenuItem(
}, },
onClick = throttle { onClick = throttle {
onExpandedChange(false) onExpandedChange(false)
navController.navigate(CategoryPageDestination(subItem.id)) navController.toDestinationsNavigator().navigate(CategoryPageDestination(subItem.id))
} }
) )
} }
@ -259,7 +259,7 @@ private fun SubsMenuItem(
}, },
onClick = throttle { onClick = throttle {
onExpandedChange(false) onExpandedChange(false)
navController.navigate(GlobalRulePageDestination(subItem.id)) navController.toDestinationsNavigator().navigate(GlobalRulePageDestination(subItem.id))
} }
) )
} }

View File

@ -57,13 +57,13 @@ import androidx.compose.ui.unit.dp
import androidx.lifecycle.viewmodel.compose.viewModel import androidx.lifecycle.viewmodel.compose.viewModel
import com.blankj.utilcode.util.KeyboardUtils import com.blankj.utilcode.util.KeyboardUtils
import com.google.accompanist.drawablepainter.rememberDrawablePainter import com.google.accompanist.drawablepainter.rememberDrawablePainter
import com.ramcosta.composedestinations.navigation.navigate import com.ramcosta.composedestinations.generated.destinations.AppConfigPageDestination
import com.ramcosta.composedestinations.utils.toDestinationsNavigator
import kotlinx.coroutines.flow.update import kotlinx.coroutines.flow.update
import li.songe.gkd.MainActivity import li.songe.gkd.MainActivity
import li.songe.gkd.ui.component.AppBarTextField import li.songe.gkd.ui.component.AppBarTextField
import li.songe.gkd.ui.component.EmptyText import li.songe.gkd.ui.component.EmptyText
import li.songe.gkd.ui.component.QueryPkgAuthCard import li.songe.gkd.ui.component.QueryPkgAuthCard
import li.songe.gkd.ui.destinations.AppConfigPageDestination
import li.songe.gkd.ui.style.EmptyHeight import li.songe.gkd.ui.style.EmptyHeight
import li.songe.gkd.ui.style.appItemPadding import li.songe.gkd.ui.style.appItemPadding
import li.songe.gkd.ui.style.menuPadding import li.songe.gkd.ui.style.menuPadding
@ -265,7 +265,7 @@ fun useAppListPage(): ScaffoldExt {
Row( Row(
modifier = Modifier modifier = Modifier
.clickable(onClick = throttle { .clickable(onClick = throttle {
navController.navigate(AppConfigPageDestination(appInfo.id)) navController.toDestinationsNavigator().navigate(AppConfigPageDestination(appInfo.id))
}) })
.height(IntrinsicSize.Min) .height(IntrinsicSize.Min)
.appItemPadding(), .appItemPadding(),

View File

@ -26,7 +26,11 @@ import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.text.style.TextOverflow
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import androidx.lifecycle.viewmodel.compose.viewModel import androidx.lifecycle.viewmodel.compose.viewModel
import com.ramcosta.composedestinations.navigation.navigate import com.ramcosta.composedestinations.generated.destinations.ActivityLogPageDestination
import com.ramcosta.composedestinations.generated.destinations.AuthA11YPageDestination
import com.ramcosta.composedestinations.generated.destinations.ClickLogPageDestination
import com.ramcosta.composedestinations.generated.destinations.SlowGroupPageDestination
import com.ramcosta.composedestinations.utils.toDestinationsNavigator
import li.songe.gkd.MainActivity import li.songe.gkd.MainActivity
import li.songe.gkd.a11yServiceEnabledFlow import li.songe.gkd.a11yServiceEnabledFlow
import li.songe.gkd.permission.notificationState import li.songe.gkd.permission.notificationState
@ -38,10 +42,6 @@ import li.songe.gkd.service.switchA11yService
import li.songe.gkd.ui.component.AuthCard import li.songe.gkd.ui.component.AuthCard
import li.songe.gkd.ui.component.SettingItem import li.songe.gkd.ui.component.SettingItem
import li.songe.gkd.ui.component.TextSwitch import li.songe.gkd.ui.component.TextSwitch
import li.songe.gkd.ui.destinations.ActivityLogPageDestination
import li.songe.gkd.ui.destinations.AuthA11yPageDestination
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.EmptyHeight
import li.songe.gkd.ui.style.itemPadding import li.songe.gkd.ui.style.itemPadding
import li.songe.gkd.util.HOME_PAGE_URL import li.songe.gkd.util.HOME_PAGE_URL
@ -110,7 +110,7 @@ fun useControlPage(): ScaffoldExt {
title = "无障碍授权", title = "无障碍授权",
desc = if (a11yBroken) "服务故障,请重新授权" else "授权使无障碍服务运行", desc = if (a11yBroken) "服务故障,请重新授权" else "授权使无障碍服务运行",
onAuthClick = { onAuthClick = {
navController.navigate(AuthA11yPageDestination) navController.toDestinationsNavigator().navigate(AuthA11YPageDestination)
}) })
} }
@ -137,7 +137,7 @@ fun useControlPage(): ScaffoldExt {
title = "触发记录", title = "触发记录",
subtitle = "如误触可在此快速定位关闭规则", subtitle = "如误触可在此快速定位关闭规则",
onClick = { onClick = {
navController.navigate(ClickLogPageDestination) navController.toDestinationsNavigator().navigate(ClickLogPageDestination)
} }
) )
@ -146,7 +146,7 @@ fun useControlPage(): ScaffoldExt {
title = "界面记录", title = "界面记录",
subtitle = "记录打开的应用及界面", subtitle = "记录打开的应用及界面",
onClick = { onClick = {
navController.navigate(ActivityLogPageDestination) navController.toDestinationsNavigator().navigate(ActivityLogPageDestination)
} }
) )
} }
@ -156,7 +156,7 @@ fun useControlPage(): ScaffoldExt {
title = "耗时查询-${ruleSummary.slowGroupCount}", title = "耗时查询-${ruleSummary.slowGroupCount}",
subtitle = "可能导致触发缓慢或更多耗电", subtitle = "可能导致触发缓慢或更多耗电",
onClick = { onClick = {
navController.navigate(SlowGroupPageDestination) navController.toDestinationsNavigator().navigate(SlowGroupPageDestination)
} }
) )
} }

View File

@ -16,7 +16,7 @@ import androidx.lifecycle.viewModelScope
import androidx.lifecycle.viewmodel.compose.viewModel import androidx.lifecycle.viewmodel.compose.viewModel
import com.blankj.utilcode.util.LogUtils import com.blankj.utilcode.util.LogUtils
import com.ramcosta.composedestinations.annotation.Destination import com.ramcosta.composedestinations.annotation.Destination
import com.ramcosta.composedestinations.annotation.RootNavGraph import com.ramcosta.composedestinations.annotation.RootGraph
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import li.songe.gkd.MainActivity import li.songe.gkd.MainActivity
import li.songe.gkd.OpenFileActivity import li.songe.gkd.OpenFileActivity
@ -31,8 +31,7 @@ data class BottomNavItem(
val icon: ImageVector, val icon: ImageVector,
) )
@RootNavGraph(start = true) @Destination<RootGraph>(style = ProfileTransitions::class, start = true)
@Destination(style = ProfileTransitions::class)
@Composable @Composable
fun HomePage() { fun HomePage() {
val context = LocalContext.current as MainActivity val context = LocalContext.current as MainActivity

View File

@ -35,7 +35,9 @@ import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextAlign
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import androidx.lifecycle.viewmodel.compose.viewModel import androidx.lifecycle.viewmodel.compose.viewModel
import com.ramcosta.composedestinations.navigation.navigate import com.ramcosta.composedestinations.generated.destinations.AboutPageDestination
import com.ramcosta.composedestinations.generated.destinations.AdvancedPageDestination
import com.ramcosta.composedestinations.utils.toDestinationsNavigator
import kotlinx.coroutines.flow.update import kotlinx.coroutines.flow.update
import li.songe.gkd.META import li.songe.gkd.META
import li.songe.gkd.MainActivity import li.songe.gkd.MainActivity
@ -45,8 +47,6 @@ import li.songe.gkd.ui.component.TextMenu
import li.songe.gkd.ui.component.TextSwitch import li.songe.gkd.ui.component.TextSwitch
import li.songe.gkd.ui.component.updateDialogOptions import li.songe.gkd.ui.component.updateDialogOptions
import li.songe.gkd.ui.component.waitResult import li.songe.gkd.ui.component.waitResult
import li.songe.gkd.ui.destinations.AboutPageDestination
import li.songe.gkd.ui.destinations.AdvancedPageDestination
import li.songe.gkd.ui.style.EmptyHeight import li.songe.gkd.ui.style.EmptyHeight
import li.songe.gkd.ui.style.itemPadding import li.songe.gkd.ui.style.itemPadding
import li.songe.gkd.ui.style.titleItemPadding import li.songe.gkd.ui.style.titleItemPadding
@ -365,11 +365,11 @@ fun useSettingsPage(): ScaffoldExt {
) )
SettingItem(title = "高级设置", onClick = { SettingItem(title = "高级设置", onClick = {
navController.navigate(AdvancedPageDestination) navController.toDestinationsNavigator().navigate(AdvancedPageDestination)
}) })
SettingItem(title = "关于", onClick = { SettingItem(title = "关于", onClick = {
navController.navigate(AboutPageDestination) navController.toDestinationsNavigator().navigate(AboutPageDestination)
}) })
Spacer(modifier = Modifier.height(EmptyHeight)) Spacer(modifier = Modifier.height(EmptyHeight))

View File

@ -9,17 +9,17 @@ val itemHorizontalPadding = 16.dp
val itemVerticalPadding = 12.dp val itemVerticalPadding = 12.dp
val EmptyHeight = 40.dp val EmptyHeight = 40.dp
fun Modifier.itemPadding() = this then padding(itemHorizontalPadding, itemVerticalPadding) fun Modifier.itemPadding() = this.padding(itemHorizontalPadding, itemVerticalPadding)
fun Modifier.titleItemPadding() = fun Modifier.titleItemPadding() = this.padding(
this then padding( itemHorizontalPadding,
itemHorizontalPadding, itemVerticalPadding + itemVerticalPadding / 2,
itemVerticalPadding + itemVerticalPadding / 2, itemHorizontalPadding,
itemHorizontalPadding, itemVerticalPadding - itemVerticalPadding / 2
itemVerticalPadding - itemVerticalPadding / 2 )
)
fun Modifier.appItemPadding() = this then padding(10.dp, 10.dp) fun Modifier.appItemPadding() = this.padding(10.dp, 10.dp)
fun Modifier.menuPadding() = fun Modifier.menuPadding() = this
this then padding(MenuDefaults.DropdownMenuItemContentPadding).padding(vertical = 8.dp) .padding(MenuDefaults.DropdownMenuItemContentPadding)
.padding(vertical = 8.dp)

View File

@ -10,20 +10,23 @@ import androidx.compose.animation.slideOutHorizontally
import androidx.navigation.NavBackStackEntry import androidx.navigation.NavBackStackEntry
import com.ramcosta.composedestinations.spec.DestinationStyle import com.ramcosta.composedestinations.spec.DestinationStyle
object ProfileTransitions : DestinationStyle.Animated { typealias EnterTransitionType = AnimatedContentTransitionScope<NavBackStackEntry>.() -> EnterTransition?
override fun AnimatedContentTransitionScope<NavBackStackEntry>.enterTransition(): EnterTransition? { typealias ExitTransitionType = AnimatedContentTransitionScope<NavBackStackEntry>.() -> ExitTransition?
return slideInHorizontally(tween()) { it }
object ProfileTransitions : DestinationStyle.Animated() {
override val enterTransition: EnterTransitionType = {
slideInHorizontally(tween()) { it }
} }
override fun AnimatedContentTransitionScope<NavBackStackEntry>.exitTransition(): ExitTransition? { override val exitTransition: ExitTransitionType = {
return slideOutHorizontally(tween()) { -it } + fadeOut(tween()) slideOutHorizontally(tween()) { -it } + fadeOut(tween())
} }
override fun AnimatedContentTransitionScope<NavBackStackEntry>.popEnterTransition(): EnterTransition? { override val popEnterTransition: EnterTransitionType = {
return slideInHorizontally(tween()) { -it } slideInHorizontally(tween()) { -it }
} }
override fun AnimatedContentTransitionScope<NavBackStackEntry>.popExitTransition(): ExitTransition? { override val popExitTransition: ExitTransitionType = {
return slideOutHorizontally(tween()) { it } slideOutHorizontally(tween()) { it }
} }
} }

View File

@ -15,8 +15,9 @@ import kotlinx.serialization.json.Json
import li.songe.gkd.app import li.songe.gkd.app
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import java.text.Collator import java.text.Collator
import java.time.Duration
import java.util.Locale import java.util.Locale
import kotlin.time.Duration.Companion.seconds
import kotlin.time.toJavaDuration
val kv by lazy { MMKV.mmkvWithID("kv") } val kv by lazy { MMKV.mmkvWithID("kv") }
@ -50,9 +51,9 @@ val imageLoader by lazy {
ImageLoader.Builder(app) ImageLoader.Builder(app)
.okHttpClient( .okHttpClient(
OkHttpClient.Builder() OkHttpClient.Builder()
.connectTimeout(Duration.ofSeconds(30)) .connectTimeout(30.seconds.toJavaDuration())
.readTimeout(Duration.ofSeconds(30)) .readTimeout(30.seconds.toJavaDuration())
.writeTimeout(Duration.ofSeconds(30)) .writeTimeout(30.seconds.toJavaDuration())
.build() .build()
) )
.components { .components {

View File

@ -2,12 +2,12 @@
kotlin = "2.0.20" kotlin = "2.0.20"
ksp = "2.0.20-1.0.25" ksp = "2.0.20-1.0.25"
android = "8.6.0" android = "8.6.0"
compose = "1.6.8" compose = "1.7.1"
rikka = "4.4.0" rikka = "4.4.0"
room = "2.6.1" room = "2.6.1"
paging = "3.3.2" paging = "3.3.2"
ktor = "2.3.12" ktor = "2.3.12"
destinations = "1.10.2" destinations = "2.1.0-beta12"
coil = "2.7.0" coil = "2.7.0"
shizuku = "13.1.5" shizuku = "13.1.5"
@ -45,7 +45,7 @@ androidx_room_paging = { module = "androidx.room:room-paging", version.ref = "ro
androidx_splashscreen = { module = "androidx.core:core-splashscreen", version = "1.0.1" } androidx_splashscreen = { module = "androidx.core:core-splashscreen", version = "1.0.1" }
androidx_paging_runtime = { module = "androidx.paging:paging-runtime", version.ref = "paging" } androidx_paging_runtime = { module = "androidx.paging:paging-runtime", version.ref = "paging" }
androidx_paging_compose = { module = "androidx.paging:paging-compose", version.ref = "paging" } androidx_paging_compose = { module = "androidx.paging:paging-compose", version.ref = "paging" }
google_accompanist_drawablepainter = { module = "com.google.accompanist:accompanist-drawablepainter", version = "0.34.0" } google_accompanist_drawablepainter = { module = "com.google.accompanist:accompanist-drawablepainter", version = "0.36.0" }
junit = { module = "junit:junit", version = "4.13.2" } junit = { module = "junit:junit", version = "4.13.2" }
ktor_server_core = { module = "io.ktor:ktor-server-core", version.ref = "ktor" } ktor_server_core = { module = "io.ktor:ktor-server-core", version.ref = "ktor" }
ktor_server_cio = { module = "io.ktor:ktor-server-cio", version.ref = "ktor" } ktor_server_cio = { module = "io.ktor:ktor-server-cio", version.ref = "ktor" }