diff --git a/manager/app/build.gradle.kts b/manager/app/build.gradle.kts index 0fc2b32a..e368d2a2 100644 --- a/manager/app/build.gradle.kts +++ b/manager/app/build.gradle.kts @@ -108,6 +108,7 @@ android { } dependencies { + implementation(libs.gson) implementation(libs.androidx.activity.compose) implementation(libs.androidx.navigation.compose) diff --git a/manager/app/src/main/java/com/sukisu/ultra/ui/screen/Home.kt b/manager/app/src/main/java/com/sukisu/ultra/ui/screen/Home.kt index 4206b491..40f96ec5 100644 --- a/manager/app/src/main/java/com/sukisu/ultra/ui/screen/Home.kt +++ b/manager/app/src/main/java/com/sukisu/ultra/ui/screen/Home.kt @@ -361,8 +361,8 @@ private fun StatusCard( val workingModeText = when { systemStatus.lkmMode == true -> "LKM" - systemStatus.lkmMode == null && systemStatus.kernelVersion.isGKI1() -> "GKI1.0" - systemStatus.lkmMode == false || systemStatus.kernelVersion.isGKI() -> "GKI2.0" + systemStatus.lkmMode == null && systemStatus.kernelVersion.isGKI1() -> "GKI-1.0" + systemStatus.lkmMode == false || systemStatus.kernelVersion.isGKI() -> "GKI-2.0" else -> "N-GKI" } @@ -775,7 +775,7 @@ private fun InfoCard( InfoCardItem( stringResource(R.string.home_manager_version), - "${systemInfo.managerVersion.first} (${systemInfo.managerVersion.second})", + "${systemInfo.managerVersion.first} (${systemInfo.managerVersion.second.toInt()})", icon = Icons.Default.SettingsSuggest, ) diff --git a/manager/app/src/main/java/com/sukisu/ultra/ui/viewmodel/HomeViewModel.kt b/manager/app/src/main/java/com/sukisu/ultra/ui/viewmodel/HomeViewModel.kt index ca618655..44f425c4 100644 --- a/manager/app/src/main/java/com/sukisu/ultra/ui/viewmodel/HomeViewModel.kt +++ b/manager/app/src/main/java/com/sukisu/ultra/ui/viewmodel/HomeViewModel.kt @@ -11,34 +11,28 @@ import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.setValue import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope +import com.dergoogler.mmrl.platform.Platform.Companion.context +import com.google.gson.Gson import com.sukisu.ultra.KernelVersion import com.sukisu.ultra.Natives import com.sukisu.ultra.getKernelVersion import com.sukisu.ultra.ksuApp -import com.sukisu.ultra.ui.util.checkNewVersion -import com.sukisu.ultra.ui.util.getKpmModuleCount -import com.sukisu.ultra.ui.util.getKpmVersion -import com.sukisu.ultra.ui.util.getModuleCount -import com.sukisu.ultra.ui.util.getSELinuxStatus -import com.sukisu.ultra.ui.util.getSuSFS -import com.sukisu.ultra.ui.util.getSuSFSFeatures -import com.sukisu.ultra.ui.util.getSuSFSVariant -import com.sukisu.ultra.ui.util.getSuSFSVersion -import com.sukisu.ultra.ui.util.getSuperuserCount +import com.sukisu.ultra.ui.util.* import com.sukisu.ultra.ui.util.module.LatestVersionInfo -import com.sukisu.ultra.ui.util.rootAvailable -import com.sukisu.ultra.ui.util.susfsSUS_SU_Mode import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import kotlinx.coroutines.withContext -import com.topjohnwu.superuser.internal.Utils.context +import androidx.core.content.edit class HomeViewModel : ViewModel() { companion object { private const val TAG = "HomeViewModel" - private val systemStatusCache = mutableMapOf() - private val systemInfoCache = mutableMapOf() - private val versionInfoCache = mutableMapOf() + private const val CACHE_DURATION = 12 * 60 * 60 * 1000L + private const val PREFS_NAME = "home_cache" + private const val KEY_SYSTEM_STATUS = "system_status" + private const val KEY_SYSTEM_INFO = "system_info" + private const val KEY_VERSION_INFO = "version_info" + private const val KEY_LAST_UPDATE = "last_update_time" } // 系统状态 @@ -70,23 +64,21 @@ class HomeViewModel : ViewModel() { val kpmModuleCount: Int = 0 ) - // UI状态 + private val gson = Gson() + private val prefs by lazy { ksuApp.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE) } + var isRefreshing by mutableStateOf(false) private set - // 系统状态信息 var systemStatus by mutableStateOf(SystemStatus()) private set - // 系统详细信息 var systemInfo by mutableStateOf(SystemInfo()) private set - // 更新信息 var latestVersionInfo by mutableStateOf(LatestVersionInfo()) private set - // 用户设置 var isSimpleMode by mutableStateOf(false) private set var isHideVersion by mutableStateOf(false) @@ -100,7 +92,6 @@ class HomeViewModel : ViewModel() { var showKpmInfo by mutableStateOf(true) private set - // 加载用户设置 fun loadUserSettings(context: Context) { viewModelScope.launch(Dispatchers.IO) { val prefs = context.getSharedPreferences("settings", Context.MODE_PRIVATE) @@ -113,27 +104,45 @@ class HomeViewModel : ViewModel() { } } - // 初始化数据 fun initializeData() { viewModelScope.launch { - val cachedStatus = systemStatusCache["status"] - val cachedInfo = systemInfoCache["info"] + val currentTime = System.currentTimeMillis() + val lastUpdateTime = prefs.getLong(KEY_LAST_UPDATE, 0) + val shouldRefresh = currentTime - lastUpdateTime > CACHE_DURATION - if (cachedStatus != null) { - systemStatus = cachedStatus + if (!shouldRefresh) { + loadCachedData() } else { - fetchSystemStatus() - } - - if (cachedInfo != null) { - systemInfo = cachedInfo - } else { - fetchSystemInfo() + fetchAndSaveData() + } + } + } + + private fun loadCachedData() { + prefs.getString(KEY_SYSTEM_STATUS, null)?.let { + systemStatus = gson.fromJson(it, SystemStatus::class.java) + } + prefs.getString(KEY_SYSTEM_INFO, null)?.let { + systemInfo = gson.fromJson(it, SystemInfo::class.java) + } + prefs.getString(KEY_VERSION_INFO, null)?.let { + latestVersionInfo = gson.fromJson(it, LatestVersionInfo::class.java) + } + } + + private suspend fun fetchAndSaveData() { + fetchSystemStatus() + fetchSystemInfo() + withContext(Dispatchers.IO) { + prefs.edit { + putString(KEY_SYSTEM_STATUS, gson.toJson(systemStatus)) + putString(KEY_SYSTEM_INFO, gson.toJson(systemInfo)) + putString(KEY_VERSION_INFO, gson.toJson(latestVersionInfo)) + putLong(KEY_LAST_UPDATE, System.currentTimeMillis()) } } } - // 检查更新 fun checkForUpdates(context: Context) { viewModelScope.launch(Dispatchers.IO) { try { @@ -141,18 +150,17 @@ class HomeViewModel : ViewModel() { .getBoolean("check_update", true) if (checkUpdate) { - val cachedVersion = versionInfoCache["version"] + val currentTime = System.currentTimeMillis() + val lastUpdateTime = prefs.getLong(KEY_LAST_UPDATE, 0) + val shouldRefresh = currentTime - lastUpdateTime > CACHE_DURATION - if (cachedVersion != null) { - latestVersionInfo = cachedVersion - return@launch + if (shouldRefresh) { + val start = SystemClock.elapsedRealtime() + val newVersionInfo = checkNewVersion() + latestVersionInfo = newVersionInfo + prefs.edit { putString(KEY_VERSION_INFO, gson.toJson(newVersionInfo)) } + Log.i(TAG, "Update check completed in ${SystemClock.elapsedRealtime() - start}ms") } - - val start = SystemClock.elapsedRealtime() - val newVersionInfo = checkNewVersion() - latestVersionInfo = newVersionInfo - versionInfoCache["version"] = newVersionInfo - Log.i(TAG, "Update check completed in ${SystemClock.elapsedRealtime() - start}ms") } } catch (e: Exception) { Log.e(TAG, "Error checking for updates", e) @@ -160,16 +168,11 @@ class HomeViewModel : ViewModel() { } } - // 刷新所有数据 fun refreshAllData(context: Context) { isRefreshing = true viewModelScope.launch { try { - systemStatusCache.clear() - systemInfoCache.clear() - versionInfoCache.clear() - fetchSystemStatus() - fetchSystemInfo() + fetchAndSaveData() checkForUpdates(context) } finally { isRefreshing = false @@ -177,7 +180,6 @@ class HomeViewModel : ViewModel() { } } - // 获取系统状态 private suspend fun fetchSystemStatus() { withContext(Dispatchers.IO) { try { @@ -188,7 +190,7 @@ class HomeViewModel : ViewModel() { if (it >= Natives.MINIMAL_SUPPORTED_KERNEL_LKM && kernelVersion.isGKI()) Natives.isLkmMode else null } - val newStatus = SystemStatus( + systemStatus = SystemStatus( isManager = isManager, ksuVersion = ksuVersion, lkmMode = lkmMode, @@ -197,16 +199,12 @@ class HomeViewModel : ViewModel() { isKpmConfigured = Natives.isKPMEnabled(), requireNewKernel = isManager && Natives.requireNewKernel() ) - - systemStatus = newStatus - systemStatusCache["status"] = newStatus } catch (e: Exception) { Log.e(TAG, "Error fetching system status", e) } } } - // 获取系统信息 @SuppressLint("RestrictedApi") private suspend fun fetchSystemInfo() { withContext(Dispatchers.IO) { @@ -235,7 +233,7 @@ class HomeViewModel : ViewModel() { } } - val newInfo = SystemInfo( + systemInfo = SystemInfo( kernelRelease = uname.release, androidVersion = Build.VERSION.RELEASE, deviceModel = getDeviceModel(), @@ -251,16 +249,12 @@ class HomeViewModel : ViewModel() { moduleCount = getModuleCount(), kpmModuleCount = getKpmModuleCount() ) - - systemInfo = newInfo - systemInfoCache["info"] = newInfo } catch (e: Exception) { Log.e(TAG, "Error fetching system info", e) } } } - // 获取设备型号 @SuppressLint("PrivateApi") private fun getDeviceModel(): String { return try { @@ -287,7 +281,6 @@ class HomeViewModel : ViewModel() { } } - // 获取管理器版本 private fun getManagerVersion(context: Context): Pair { return try { val packageInfo = context.packageManager.getPackageInfo(context.packageName, 0)!! diff --git a/manager/gradle/libs.versions.toml b/manager/gradle/libs.versions.toml index 75a2bfc9..b2e5ca03 100644 --- a/manager/gradle/libs.versions.toml +++ b/manager/gradle/libs.versions.toml @@ -1,5 +1,6 @@ [versions] agp = "8.10.1" +gson = "2.11.0" kotlin = "2.1.20" ksp = "2.1.20-2.0.0" compose-bom = "2025.05.01" @@ -62,6 +63,7 @@ com-github-topjohnwu-libsu-io = { group = "com.github.topjohnwu.libsu", name = " dev-rikka-rikkax-parcelablelist = { module = "dev.rikka.rikkax.parcelablelist:parcelablelist", version.ref = "parcelablelist" } +gson = { module = "com.google.code.gson:gson", version.ref = "gson" } io-coil-kt-coil-compose = { group = "io.coil-kt", name = "coil-compose", version.ref = "coil-compose" } kotlinx-coroutines-core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "kotlinx-coroutines" }