manager: Refactoring data refresh management

New AppData object to optimize data fetching and state management.
This commit is contained in:
ShirkNeko
2025-06-02 17:49:34 +08:00
parent c0e839dd8e
commit b772c8ece1
2 changed files with 120 additions and 29 deletions

View File

@@ -32,11 +32,13 @@ import com.ramcosta.composedestinations.utils.rememberDestinationsNavigator
import io.sukisu.ultra.UltraToolInstall import io.sukisu.ultra.UltraToolInstall
import com.sukisu.ultra.Natives import com.sukisu.ultra.Natives
import com.sukisu.ultra.ksuApp import com.sukisu.ultra.ksuApp
import com.sukisu.ultra.ui.data.AppData
import com.sukisu.ultra.ui.screen.BottomBarDestination import com.sukisu.ultra.ui.screen.BottomBarDestination
import com.sukisu.ultra.ui.theme.* import com.sukisu.ultra.ui.theme.*
import com.sukisu.ultra.ui.theme.CardConfig.cardAlpha import com.sukisu.ultra.ui.theme.CardConfig.cardAlpha
import com.sukisu.ultra.ui.util.* import com.sukisu.ultra.ui.util.*
import androidx.core.content.edit import androidx.core.content.edit
import com.sukisu.ultra.ui.data.AppData.DataRefreshManager
import com.sukisu.ultra.ui.theme.CardConfig.cardElevation import com.sukisu.ultra.ui.theme.CardConfig.cardElevation
import com.sukisu.ultra.ui.webui.initPlatform import com.sukisu.ultra.ui.webui.initPlatform
import java.util.Locale import java.util.Locale
@@ -45,33 +47,14 @@ import androidx.compose.animation.slideInVertically
import androidx.compose.animation.slideOutVertically import androidx.compose.animation.slideOutVertically
import androidx.navigation.compose.currentBackStackEntryAsState import androidx.navigation.compose.currentBackStackEntryAsState
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import com.sukisu.ultra.ui.data.AppData.getKpmVersionUse
import com.sukisu.ultra.ui.viewmodel.HomeViewModel import com.sukisu.ultra.ui.viewmodel.HomeViewModel
import com.sukisu.ultra.ui.viewmodel.SuperUserViewModel import com.sukisu.ultra.ui.viewmodel.SuperUserViewModel
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.isActive import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
// 数据刷新管理
object DataRefreshManager {
private val _superuserCount = MutableStateFlow(0)
private val _moduleCount = MutableStateFlow(0)
private val _kpmModuleCount = MutableStateFlow(0)
val superuserCount: StateFlow<Int> = _superuserCount.asStateFlow()
val moduleCount: StateFlow<Int> = _moduleCount.asStateFlow()
val kpmModuleCount: StateFlow<Int> = _kpmModuleCount.asStateFlow()
fun refreshData() {
_superuserCount.value = getSuperuserCount()
_moduleCount.value = getModuleCount()
_kpmModuleCount.value = getKpmModuleCount()
}
}
class MainActivity : ComponentActivity() { class MainActivity : ComponentActivity() {
private lateinit var superUserViewModel: SuperUserViewModel private lateinit var superUserViewModel: SuperUserViewModel
private lateinit var homeViewModel: HomeViewModel private lateinit var homeViewModel: HomeViewModel
@@ -197,7 +180,7 @@ class MainActivity : ComponentActivity() {
contentResolver.unregisterContentObserver(contentObserver) contentResolver.unregisterContentObserver(contentObserver)
} }
val isManager = Natives.becomeManager(ksuApp.packageName) val isManager = AppData.isManager(ksuApp.packageName)
if (isManager) { if (isManager) {
install() install()
UltraToolInstall.tryToInstall() UltraToolInstall.tryToInstall()
@@ -218,7 +201,7 @@ class MainActivity : ComponentActivity() {
LaunchedEffect(Unit) { LaunchedEffect(Unit) {
initPlatform() initPlatform()
} }
CompositionLocalProvider( CompositionLocalProvider(
LocalSnackbarHost provides snackBarHostState LocalSnackbarHost provides snackBarHostState
) { ) {
@@ -327,9 +310,8 @@ class MainActivity : ComponentActivity() {
@Composable @Composable
private fun BottomBar(navController: NavHostController) { private fun BottomBar(navController: NavHostController) {
val navigator = navController.rememberDestinationsNavigator() val navigator = navController.rememberDestinationsNavigator()
val isManager = Natives.becomeManager(ksuApp.packageName) val isFullFeatured = AppData.isFullFeatured(ksuApp.packageName)
val fullFeatured = isManager && !Natives.requireNewKernel() && rootAvailable() val kpmVersion = getKpmVersionUse()
val kpmVersion = getKpmVersion()
val cardColor = MaterialTheme.colorScheme.surfaceContainer val cardColor = MaterialTheme.colorScheme.surfaceContainer
val context = LocalContext.current val context = LocalContext.current
@@ -355,7 +337,7 @@ private fun BottomBar(navController: NavHostController) {
BottomBarDestination.entries.forEach { destination -> BottomBarDestination.entries.forEach { destination ->
if (destination == BottomBarDestination.Kpm) { if (destination == BottomBarDestination.Kpm) {
if (kpmVersion.isNotEmpty() && !kpmVersion.startsWith("Error") && showKpmInfo && Natives.version >= Natives.MINIMAL_SUPPORTED_KPM) { if (kpmVersion.isNotEmpty() && !kpmVersion.startsWith("Error") && showKpmInfo && Natives.version >= Natives.MINIMAL_SUPPORTED_KPM) {
if (!fullFeatured && destination.rootRequired) return@forEach if (!isFullFeatured && destination.rootRequired) return@forEach
val isCurrentDestOnBackStack by navController.isRouteOnBackStackAsState(destination.direction) val isCurrentDestOnBackStack by navController.isRouteOnBackStackAsState(destination.direction)
NavigationBarItem( NavigationBarItem(
selected = isCurrentDestOnBackStack, selected = isCurrentDestOnBackStack,
@@ -398,7 +380,7 @@ private fun BottomBar(navController: NavHostController) {
) )
} }
} else if (destination == BottomBarDestination.SuperUser) { } else if (destination == BottomBarDestination.SuperUser) {
if (!fullFeatured && destination.rootRequired) return@forEach if (!isFullFeatured && destination.rootRequired) return@forEach
val isCurrentDestOnBackStack by navController.isRouteOnBackStackAsState(destination.direction) val isCurrentDestOnBackStack by navController.isRouteOnBackStackAsState(destination.direction)
NavigationBarItem( NavigationBarItem(
@@ -441,7 +423,7 @@ private fun BottomBar(navController: NavHostController) {
alwaysShowLabel = false alwaysShowLabel = false
) )
} else if (destination == BottomBarDestination.Module) { } else if (destination == BottomBarDestination.Module) {
if (!fullFeatured && destination.rootRequired) return@forEach if (!isFullFeatured && destination.rootRequired) return@forEach
val isCurrentDestOnBackStack by navController.isRouteOnBackStackAsState(destination.direction) val isCurrentDestOnBackStack by navController.isRouteOnBackStackAsState(destination.direction)
NavigationBarItem( NavigationBarItem(
@@ -483,7 +465,7 @@ private fun BottomBar(navController: NavHostController) {
alwaysShowLabel = false alwaysShowLabel = false
) )
} else { } else {
if (!fullFeatured && destination.rootRequired) return@forEach if (!isFullFeatured && destination.rootRequired) return@forEach
val isCurrentDestOnBackStack by navController.isRouteOnBackStackAsState(destination.direction) val isCurrentDestOnBackStack by navController.isRouteOnBackStackAsState(destination.direction)
NavigationBarItem( NavigationBarItem(

View File

@@ -0,0 +1,109 @@
package com.sukisu.ultra.ui.data
import com.sukisu.ultra.Natives
import com.sukisu.ultra.ui.util.getKpmModuleCount
import com.sukisu.ultra.ui.util.getKpmVersion
import com.sukisu.ultra.ui.util.rootAvailable
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.withContext
import com.sukisu.ultra.ui.util.getModuleCount
import com.sukisu.ultra.ui.util.getSuperuserCount
object AppData {
object DataRefreshManager {
// 私有状态流
private val _superuserCount = MutableStateFlow(0)
private val _moduleCount = MutableStateFlow(0)
private val _kpmModuleCount = MutableStateFlow(0)
// 公开的只读状态流
val superuserCount: StateFlow<Int> = _superuserCount.asStateFlow()
val moduleCount: StateFlow<Int> = _moduleCount.asStateFlow()
val kpmModuleCount: StateFlow<Int> = _kpmModuleCount.asStateFlow()
/**
* 刷新所有数据计数
*/
fun refreshData() {
_superuserCount.value = getSuperuserCountUse()
_moduleCount.value = getModuleCountUse()
_kpmModuleCount.value = getKpmModuleCountUse()
}
/**
* 异步刷新所有数据
*/
suspend fun refreshDataAsync() = withContext(Dispatchers.IO) {
refreshData()
}
}
/**
* 获取超级用户应用计数
*/
fun getSuperuserCountUse(): Int {
return try {
if (!rootAvailable()) return 0
getSuperuserCount()
} catch (_: Exception) {
0
}
}
/**
* 获取模块计数
*/
fun getModuleCountUse(): Int {
return try {
if (!rootAvailable()) return 0
getModuleCount()
} catch (_: Exception) {
0
}
}
/**
* 获取KPM模块计数
*/
fun getKpmModuleCountUse(): Int {
return try {
if (!rootAvailable()) return 0
val kpmVersion = getKpmVersionUse()
if (kpmVersion.isEmpty() || kpmVersion.startsWith("Error")) return 0
getKpmModuleCount()
} catch (_: Exception) {
0
}
}
/**
* 获取KPM版本
*/
fun getKpmVersionUse(): String {
return try {
if (!rootAvailable()) return ""
val version = getKpmVersion()
if (version.isEmpty()) "" else version
} catch (e: Exception) {
"Error: ${e.message}"
}
}
/**
* 检查是否具有管理员权限
*/
fun isManager(packageName: String): Boolean {
return Natives.becomeManager(packageName)
}
/**
* 检查是否是完整功能模式
*/
fun isFullFeatured(packageName: String): Boolean {
val isManager = Natives.becomeManager(packageName)
return isManager && !Natives.requireNewKernel() && rootAvailable()
}
}