From b7f2e7abe557d25ec314a6673e4cadbfb8c44756 Mon Sep 17 00:00:00 2001 From: rushiiMachine <33725716+rushiiMachine@users.noreply.github.com> Date: Sat, 25 Jan 2025 10:55:48 -0800 Subject: [PATCH] feat: make Aliucord installation update button work Launch a patch opts screen with prefilled options based on the previous install. --- .../manager/ui/screens/home/HomeModel.kt | 28 +++++++++++++++++++ .../manager/ui/screens/home/HomeScreen.kt | 7 +++-- .../ui/screens/patchopts/PatchOptions.kt | 10 +++++++ .../ui/screens/patchopts/PatchOptionsModel.kt | 17 +++++------ .../screens/patchopts/PatchOptionsScreen.kt | 4 ++- .../aliucord/manager/util/ColorSerializer.kt | 2 +- 6 files changed, 55 insertions(+), 13 deletions(-) diff --git a/app/src/main/kotlin/com/aliucord/manager/ui/screens/home/HomeModel.kt b/app/src/main/kotlin/com/aliucord/manager/ui/screens/home/HomeModel.kt index c6e5a1d..ea55663 100644 --- a/app/src/main/kotlin/com/aliucord/manager/ui/screens/home/HomeModel.kt +++ b/app/src/main/kotlin/com/aliucord/manager/ui/screens/home/HomeModel.kt @@ -16,12 +16,15 @@ import androidx.core.graphics.drawable.toBitmap import androidx.core.net.toUri import cafe.adriel.voyager.core.model.ScreenModel import cafe.adriel.voyager.core.model.screenModelScope +import cafe.adriel.voyager.navigator.Navigator import com.aliucord.manager.BuildConfig import com.aliucord.manager.R import com.aliucord.manager.domain.repository.GithubRepository import com.aliucord.manager.network.dto.BuildInfo import com.aliucord.manager.network.utils.fold import com.aliucord.manager.patcher.InstallMetadata +import com.aliucord.manager.ui.screens.patchopts.PatchOptions +import com.aliucord.manager.ui.screens.patchopts.PatchOptionsScreen import com.aliucord.manager.ui.util.DiscordVersion import com.aliucord.manager.util.launchBlock import com.aliucord.manager.util.showToast @@ -153,6 +156,31 @@ class HomeModel( } } + // Launches the patching screen with prefilled options according to the existing APK + fun updateAliucord(data: InstallData, navigator: Navigator) = screenModelScope.launchBlock { + val metadata = try { + val applicationInfo = application.packageManager.getApplicationInfo(data.packageName, 0) + val metadataFile = ZipReader(applicationInfo.publicSourceDir) + .use { it.openEntry("aliucord.json")?.read() } + + @OptIn(ExperimentalSerializationApi::class) + metadataFile?.let { json.decodeFromStream(it.inputStream()) } + } catch (t: Throwable) { + Log.w(BuildConfig.TAG, "Failed to parse Aliucord install metadata from package ${data.packageName}", t) + null + } + + val patchOptions = metadata?.options + ?: PatchOptions.Default.copy(packageName = data.packageName) + + navigator.push( + PatchOptionsScreen( + prefilledOptions = patchOptions, + supportedVersion = supportedVersion, + ) + ) + } + private fun fetchSupportedVersion() = screenModelScope.launchBlock { github.getDataJson().fold( success = { diff --git a/app/src/main/kotlin/com/aliucord/manager/ui/screens/home/HomeScreen.kt b/app/src/main/kotlin/com/aliucord/manager/ui/screens/home/HomeScreen.kt index 0883f6e..414e9ee 100644 --- a/app/src/main/kotlin/com/aliucord/manager/ui/screens/home/HomeScreen.kt +++ b/app/src/main/kotlin/com/aliucord/manager/ui/screens/home/HomeScreen.kt @@ -57,16 +57,17 @@ class HomeScreen : Screen { if (model.isNetworkDangerous()) { showNetworkWarningDialog = true } else { - navigator.push(PatchOptionsScreen(model.supportedVersion)) + navigator.push(PatchOptionsScreen(supportedVersion = model.supportedVersion)) } } } + // TODO: trigger this for updates too? if (showNetworkWarningDialog) { NetworkWarningDialog( onConfirm = { showNetworkWarningDialog = false - navigator.push(PatchOptionsScreen(model.supportedVersion)) + navigator.push(PatchOptionsScreen(supportedVersion = model.supportedVersion)) }, onDismiss = { showNetworkWarningDialog = false @@ -171,7 +172,7 @@ fun PresentInstallsContent( InstalledItemCard( data = it, - onUpdate = ::TODO, // TODO: prefilled install options screen + onUpdate = { model.updateAliucord(it, navigator) }, onOpenApp = { model.launchApp(it.packageName) }, onOpenInfo = { model.openAppInfo(it.packageName) }, onOpenPlugins = { navigator.push(PluginsScreen()) }, // TODO: install-specific plugins diff --git a/app/src/main/kotlin/com/aliucord/manager/ui/screens/patchopts/PatchOptions.kt b/app/src/main/kotlin/com/aliucord/manager/ui/screens/patchopts/PatchOptions.kt index 92d10c9..818775d 100644 --- a/app/src/main/kotlin/com/aliucord/manager/ui/screens/patchopts/PatchOptions.kt +++ b/app/src/main/kotlin/com/aliucord/manager/ui/screens/patchopts/PatchOptions.kt @@ -88,4 +88,14 @@ data class PatchOptions( val Aliucord = CustomColor(Color(0xFF00C853)) } } + + companion object { + val Default = PatchOptions( + appName = "Aliucord", + packageName = "com.aliucord", + debuggable = false, + iconReplacement = IconReplacement.Aliucord, + monochromeIcon = true, + ) + } } diff --git a/app/src/main/kotlin/com/aliucord/manager/ui/screens/patchopts/PatchOptionsModel.kt b/app/src/main/kotlin/com/aliucord/manager/ui/screens/patchopts/PatchOptionsModel.kt index c12c1c1..be615fb 100644 --- a/app/src/main/kotlin/com/aliucord/manager/ui/screens/patchopts/PatchOptionsModel.kt +++ b/app/src/main/kotlin/com/aliucord/manager/ui/screens/patchopts/PatchOptionsModel.kt @@ -10,18 +10,19 @@ import com.aliucord.manager.util.debounce import kotlinx.coroutines.launch class PatchOptionsModel( + prefilledOptions: PatchOptions, private val context: Context, private val prefs: PreferencesManager, ) : ScreenModel { // ---------- Package name state ---------- - var packageName by mutableStateOf("com.aliucord") + var packageName by mutableStateOf(prefilledOptions.packageName) private set var packageNameState by mutableStateOf(PackageNameState.Ok) private set val packageNameIsDefault by derivedStateOf { - packageName == "com.aliucord" + packageName == PatchOptions.Default.packageName } fun changePackageName(newPackageName: String) { @@ -30,18 +31,18 @@ class PatchOptionsModel( } fun resetPackageName() { - changePackageName("com.aliucord") + changePackageName(PatchOptions.Default.packageName) } // ---------- App name state ---------- - var appName by mutableStateOf("Aliucord") + var appName by mutableStateOf(prefilledOptions.appName) private set var appNameIsError by mutableStateOf(false) private set val appNameIsDefault by derivedStateOf { - appName == "Aliucord" + appName == PatchOptions.Default.appName } fun changeAppName(newAppName: String) { @@ -50,11 +51,11 @@ class PatchOptionsModel( } fun resetAppName() { - appName = "Aliucord" + appName = PatchOptions.Default.appName } // ---------- Icon patching state ---------- - var replaceIcon by mutableStateOf(true) + var replaceIcon by mutableStateOf(prefilledOptions.iconReplacement == PatchOptions.IconReplacement.Aliucord) private set fun changeReplaceIcon(value: Boolean) { @@ -62,7 +63,7 @@ class PatchOptionsModel( } // ---------- Debuggable state ---------- - var debuggable by mutableStateOf(false) + var debuggable by mutableStateOf(prefilledOptions.debuggable) private set fun changeDebuggable(value: Boolean) { diff --git a/app/src/main/kotlin/com/aliucord/manager/ui/screens/patchopts/PatchOptionsScreen.kt b/app/src/main/kotlin/com/aliucord/manager/ui/screens/patchopts/PatchOptionsScreen.kt index 1138d98..b9e974a 100644 --- a/app/src/main/kotlin/com/aliucord/manager/ui/screens/patchopts/PatchOptionsScreen.kt +++ b/app/src/main/kotlin/com/aliucord/manager/ui/screens/patchopts/PatchOptionsScreen.kt @@ -29,8 +29,10 @@ import com.aliucord.manager.ui.util.* import com.aliucord.manager.util.isIgnoringBatteryOptimizations import com.aliucord.manager.util.requestNoBatteryOptimizations import kotlinx.coroutines.delay +import org.koin.core.parameter.parametersOf class PatchOptionsScreen( + private val prefilledOptions: PatchOptions = PatchOptions.Default, private val supportedVersion: DiscordVersion = DiscordVersion.None, ) : Screen { override val key = "PatchOptions" @@ -39,7 +41,7 @@ class PatchOptionsScreen( override fun Content() { val context = LocalContext.current val navigator = LocalNavigator.currentOrThrow - val model = getScreenModel() + val model = getScreenModel() { parametersOf(prefilledOptions) } LaunchedEffect(Unit) { // Ensure that when popping this screen off the stack that permission requests don't get triggered diff --git a/app/src/main/kotlin/com/aliucord/manager/util/ColorSerializer.kt b/app/src/main/kotlin/com/aliucord/manager/util/ColorSerializer.kt index 8ce5fcb..71699ec 100644 --- a/app/src/main/kotlin/com/aliucord/manager/util/ColorSerializer.kt +++ b/app/src/main/kotlin/com/aliucord/manager/util/ColorSerializer.kt @@ -23,6 +23,6 @@ object ColorSerializer : KSerializer { override fun deserialize(decoder: Decoder): Color { val string = decoder.decodeString() - return Color(string.toInt(16)) + return Color(string.toLong(16)) } }