From 9d6cdf24da3745c866abd4f67e92857761dbe800 Mon Sep 17 00:00:00 2001 From: rushii <33725716+rushiiMachine@users.noreply.github.com> Date: Fri, 9 Feb 2024 18:28:32 -0800 Subject: [PATCH] feat: add install options screen (#70) --- .../aliucord/manager/ManagerApplication.kt | 2 + .../installer/steps/KotlinInstallRunner.kt | 12 +- .../steps/patch/PatchManifestStep.kt | 14 +- .../installer/steps/patch/ReplaceIconStep.kt | 9 +- .../steps/prepare/DowngradeCheckStep.kt | 9 +- .../manager/manager/PreferencesManager.kt | 6 - .../ui/components/AnimatedVersionDisplay.kt | 36 +++++ .../ui/components/ResetToDefaultButton.kt | 28 ++++ .../manager/ui/components/TextDivider.kt | 33 +++++ .../home => }/components/VersionDisplay.kt | 2 +- .../ui/components/dialogs/InstallerDialog.kt | 109 -------------- .../manager/ui/screens/home/HomeModel.kt | 5 - .../manager/ui/screens/home/HomeScreen.kt | 54 ++----- .../home/components/InstalledItemCard.kt | 1 + .../ui/screens/install/InstallModel.kt | 4 +- .../ui/screens/install/InstallScreen.kt | 6 +- .../ui/screens/installopts/InstallOptions.kt | 11 ++ .../installopts/InstallOptionsModel.kt | 128 +++++++++++++++++ .../installopts/InstallOptionsScreen.kt | 135 ++++++++++++++++++ .../components/InstallOptionsAppBar.kt | 29 ++++ .../components/PackageNameState.kt | 65 +++++++++ .../components/options/InstallOption.kt | 39 +++++ .../components/options/SwitchInstallOption.kt | 73 ++++++++++ .../components/options/TextInstallOption.kt | 53 +++++++ .../ui/screens/settings/SettingsModel.kt | 38 ----- .../ui/screens/settings/SettingsScreen.kt | 54 ------- .../com/aliucord/manager/ui/util/Utils.kt | 9 ++ .../com/aliucord/manager/util/Debounce.kt | 55 +++++++ app/src/main/res/drawable/ic_copy_file.xml | 9 -- app/src/main/res/drawable/ic_refresh.xml | 9 ++ app/src/main/res/drawable/ic_warning.xml | 9 ++ app/src/main/res/values-af-rZA/strings.xml | 10 -- app/src/main/res/values-ar-rSA/strings.xml | 10 -- app/src/main/res/values-ca-rES/strings.xml | 10 -- app/src/main/res/values-cs-rCZ/strings.xml | 10 -- app/src/main/res/values-da-rDK/strings.xml | 10 -- app/src/main/res/values-de-rDE/strings.xml | 10 -- app/src/main/res/values-el-rGR/strings.xml | 10 -- app/src/main/res/values-es-rES/strings.xml | 10 -- app/src/main/res/values-fi-rFI/strings.xml | 10 -- app/src/main/res/values-fr-rFR/strings.xml | 10 -- app/src/main/res/values-hi-rIN/strings.xml | 10 -- app/src/main/res/values-hu-rHU/strings.xml | 10 -- app/src/main/res/values-in-rID/strings.xml | 10 -- app/src/main/res/values-it-rIT/strings.xml | 10 -- app/src/main/res/values-iw-rIL/strings.xml | 10 -- app/src/main/res/values-ja-rJP/strings.xml | 10 -- app/src/main/res/values-kaa/strings.xml | 10 -- app/src/main/res/values-ko-rKR/strings.xml | 10 -- app/src/main/res/values-nl-rNL/strings.xml | 10 -- app/src/main/res/values-no-rNO/strings.xml | 10 -- app/src/main/res/values-pl-rPL/strings.xml | 10 -- app/src/main/res/values-pt-rBR/strings.xml | 10 -- app/src/main/res/values-pt-rPT/strings.xml | 10 -- app/src/main/res/values-ro-rRO/strings.xml | 10 -- app/src/main/res/values-ru-rRU/strings.xml | 10 -- app/src/main/res/values-sr-rSP/strings.xml | 10 -- app/src/main/res/values-sv-rSE/strings.xml | 10 -- app/src/main/res/values-tr-rTR/strings.xml | 10 -- app/src/main/res/values-uk-rUA/strings.xml | 10 -- app/src/main/res/values-vi-rVN/strings.xml | 10 -- app/src/main/res/values-zh-rCN/strings.xml | 10 -- app/src/main/res/values-zh-rTW/strings.xml | 10 -- app/src/main/res/values/strings.xml | 30 ++-- 64 files changed, 771 insertions(+), 625 deletions(-) create mode 100644 app/src/main/kotlin/com/aliucord/manager/ui/components/AnimatedVersionDisplay.kt create mode 100644 app/src/main/kotlin/com/aliucord/manager/ui/components/ResetToDefaultButton.kt create mode 100644 app/src/main/kotlin/com/aliucord/manager/ui/components/TextDivider.kt rename app/src/main/kotlin/com/aliucord/manager/ui/{screens/home => }/components/VersionDisplay.kt (93%) delete mode 100644 app/src/main/kotlin/com/aliucord/manager/ui/components/dialogs/InstallerDialog.kt create mode 100644 app/src/main/kotlin/com/aliucord/manager/ui/screens/installopts/InstallOptions.kt create mode 100644 app/src/main/kotlin/com/aliucord/manager/ui/screens/installopts/InstallOptionsModel.kt create mode 100644 app/src/main/kotlin/com/aliucord/manager/ui/screens/installopts/InstallOptionsScreen.kt create mode 100644 app/src/main/kotlin/com/aliucord/manager/ui/screens/installopts/components/InstallOptionsAppBar.kt create mode 100644 app/src/main/kotlin/com/aliucord/manager/ui/screens/installopts/components/PackageNameState.kt create mode 100644 app/src/main/kotlin/com/aliucord/manager/ui/screens/installopts/components/options/InstallOption.kt create mode 100644 app/src/main/kotlin/com/aliucord/manager/ui/screens/installopts/components/options/SwitchInstallOption.kt create mode 100644 app/src/main/kotlin/com/aliucord/manager/ui/screens/installopts/components/options/TextInstallOption.kt create mode 100644 app/src/main/kotlin/com/aliucord/manager/util/Debounce.kt delete mode 100644 app/src/main/res/drawable/ic_copy_file.xml create mode 100644 app/src/main/res/drawable/ic_refresh.xml create mode 100644 app/src/main/res/drawable/ic_warning.xml diff --git a/app/src/main/kotlin/com/aliucord/manager/ManagerApplication.kt b/app/src/main/kotlin/com/aliucord/manager/ManagerApplication.kt index 5694d27f..d5f561d6 100644 --- a/app/src/main/kotlin/com/aliucord/manager/ManagerApplication.kt +++ b/app/src/main/kotlin/com/aliucord/manager/ManagerApplication.kt @@ -10,6 +10,7 @@ import com.aliucord.manager.network.service.* import com.aliucord.manager.ui.screens.about.AboutModel import com.aliucord.manager.ui.screens.home.HomeModel import com.aliucord.manager.ui.screens.install.InstallModel +import com.aliucord.manager.ui.screens.installopts.InstallOptionsModel import com.aliucord.manager.ui.screens.plugins.PluginsModel import com.aliucord.manager.ui.screens.settings.SettingsModel import com.aliucord.manager.ui.widgets.updater.UpdaterViewModel @@ -54,6 +55,7 @@ class ManagerApplication : Application() { factoryOf(::AboutModel) factoryOf(::InstallModel) factoryOf(::SettingsModel) + factoryOf(::InstallOptionsModel) viewModelOf(::UpdaterViewModel) }) diff --git a/app/src/main/kotlin/com/aliucord/manager/installer/steps/KotlinInstallRunner.kt b/app/src/main/kotlin/com/aliucord/manager/installer/steps/KotlinInstallRunner.kt index 6a6430fd..fb8b445b 100644 --- a/app/src/main/kotlin/com/aliucord/manager/installer/steps/KotlinInstallRunner.kt +++ b/app/src/main/kotlin/com/aliucord/manager/installer/steps/KotlinInstallRunner.kt @@ -1,21 +1,21 @@ package com.aliucord.manager.installer.steps -import com.aliucord.manager.installer.steps.base.Step import com.aliucord.manager.installer.steps.download.* import com.aliucord.manager.installer.steps.install.* import com.aliucord.manager.installer.steps.patch.* import com.aliucord.manager.installer.steps.prepare.DowngradeCheckStep import com.aliucord.manager.installer.steps.prepare.FetchInfoStep +import com.aliucord.manager.ui.screens.installopts.InstallOptions import kotlinx.collections.immutable.persistentListOf /** * Used for installing the old Kotlin Discord app. */ -class KotlinInstallRunner : StepRunner() { - override val steps = persistentListOf( +class KotlinInstallRunner(options: InstallOptions) : StepRunner() { + override val steps = persistentListOf( // Prepare FetchInfoStep(), - DowngradeCheckStep(), + DowngradeCheckStep(options), // Download DownloadDiscordStep(), @@ -25,8 +25,8 @@ class KotlinInstallRunner : StepRunner() { // Patch CopyDependenciesStep(), - ReplaceIconStep(), - PatchManifestStep(), + ReplaceIconStep(options), + PatchManifestStep(options), AddInjectorStep(), AddAliuhookStep(), diff --git a/app/src/main/kotlin/com/aliucord/manager/installer/steps/patch/PatchManifestStep.kt b/app/src/main/kotlin/com/aliucord/manager/installer/steps/patch/PatchManifestStep.kt index 4f50ada3..ae7d608d 100644 --- a/app/src/main/kotlin/com/aliucord/manager/installer/steps/patch/PatchManifestStep.kt +++ b/app/src/main/kotlin/com/aliucord/manager/installer/steps/patch/PatchManifestStep.kt @@ -5,18 +5,14 @@ import com.aliucord.manager.installer.steps.StepGroup import com.aliucord.manager.installer.steps.StepRunner import com.aliucord.manager.installer.steps.base.Step import com.aliucord.manager.installer.util.ManifestPatcher -import com.aliucord.manager.manager.PreferencesManager +import com.aliucord.manager.ui.screens.installopts.InstallOptions import com.github.diamondminer88.zip.ZipReader import com.github.diamondminer88.zip.ZipWriter -import org.koin.core.component.KoinComponent -import org.koin.core.component.inject /** * Patch the APK's AndroidManifest.xml */ -class PatchManifestStep : Step(), KoinComponent { - private val prefs: PreferencesManager by inject() - +class PatchManifestStep(private val options: InstallOptions) : Step() { override val group = StepGroup.Patch override val localizedName = R.string.install_step_patch_manifests @@ -29,9 +25,9 @@ class PatchManifestStep : Step(), KoinComponent { val patchedManifest = ManifestPatcher.patchManifest( manifestBytes = manifest, - packageName = prefs.packageName, - appName = prefs.appName, - debuggable = prefs.debuggable, + packageName = options.packageName, + appName = options.appName, + debuggable = options.debuggable, ) ZipWriter(apk, /* append = */ true).use { diff --git a/app/src/main/kotlin/com/aliucord/manager/installer/steps/patch/ReplaceIconStep.kt b/app/src/main/kotlin/com/aliucord/manager/installer/steps/patch/ReplaceIconStep.kt index 90597035..1afe19e1 100644 --- a/app/src/main/kotlin/com/aliucord/manager/installer/steps/patch/ReplaceIconStep.kt +++ b/app/src/main/kotlin/com/aliucord/manager/installer/steps/patch/ReplaceIconStep.kt @@ -7,7 +7,7 @@ import com.aliucord.manager.installer.steps.StepGroup import com.aliucord.manager.installer.steps.StepRunner import com.aliucord.manager.installer.steps.base.Step import com.aliucord.manager.installer.steps.base.StepState -import com.aliucord.manager.manager.PreferencesManager +import com.aliucord.manager.ui.screens.installopts.InstallOptions import com.github.diamondminer88.zip.ZipWriter import org.koin.core.component.KoinComponent import org.koin.core.component.inject @@ -17,15 +17,14 @@ import java.io.InputStream * Replace icons */ @Stable -class ReplaceIconStep : Step(), KoinComponent { +class ReplaceIconStep(private val options: InstallOptions) : Step(), KoinComponent { private val context: Context by inject() - private val prefs: PreferencesManager by inject() override val group = StepGroup.Patch - override val localizedName = R.string.setting_replace_icon + override val localizedName = R.string.install_step_patch_icon override suspend fun execute(container: StepRunner) { - if (!prefs.replaceIcon) { + if (!options.replaceIcon) { state = StepState.Skipped return } diff --git a/app/src/main/kotlin/com/aliucord/manager/installer/steps/prepare/DowngradeCheckStep.kt b/app/src/main/kotlin/com/aliucord/manager/installer/steps/prepare/DowngradeCheckStep.kt index 223af6f6..fe743079 100644 --- a/app/src/main/kotlin/com/aliucord/manager/installer/steps/prepare/DowngradeCheckStep.kt +++ b/app/src/main/kotlin/com/aliucord/manager/installer/steps/prepare/DowngradeCheckStep.kt @@ -7,7 +7,7 @@ import com.aliucord.manager.installer.steps.StepRunner import com.aliucord.manager.installer.steps.base.Step import com.aliucord.manager.installer.steps.base.StepState import com.aliucord.manager.installer.util.uninstallApk -import com.aliucord.manager.manager.PreferencesManager +import com.aliucord.manager.ui.screens.installopts.InstallOptions import com.aliucord.manager.util.getPackageVersion import com.aliucord.manager.util.showToast import kotlinx.coroutines.Dispatchers @@ -19,16 +19,15 @@ import org.koin.core.component.inject * Prompt the user to uninstall a previous version of Aliucord if it has a larger version code. * (Prevent conflicts from downgrading) */ -class DowngradeCheckStep : Step(), KoinComponent { +class DowngradeCheckStep(private val options: InstallOptions) : Step(), KoinComponent { private val context: Context by inject() - private val prefs: PreferencesManager by inject() override val group = StepGroup.Prepare override val localizedName = R.string.install_step_downgrade_check override suspend fun execute(container: StepRunner) { val (_, currentVersion) = try { - context.getPackageVersion(prefs.packageName) + context.getPackageVersion(options.packageName) } // Package is not installed catch (_: Throwable) { @@ -42,7 +41,7 @@ class DowngradeCheckStep : Step(), KoinComponent { ?: throw IllegalArgumentException("Invalid fetched Aliucord target Discord version") if (currentVersion > targetVersion) { - context.uninstallApk(prefs.packageName) + context.uninstallApk(options.packageName) withContext(Dispatchers.Main) { context.showToast(R.string.installer_uninstall_new) diff --git a/app/src/main/kotlin/com/aliucord/manager/manager/PreferencesManager.kt b/app/src/main/kotlin/com/aliucord/manager/manager/PreferencesManager.kt index f49d71fb..4212d5f9 100644 --- a/app/src/main/kotlin/com/aliucord/manager/manager/PreferencesManager.kt +++ b/app/src/main/kotlin/com/aliucord/manager/manager/PreferencesManager.kt @@ -7,13 +7,7 @@ import com.aliucord.manager.ui.components.Theme class PreferencesManager(preferences: SharedPreferences) : BasePreferenceManager(preferences) { var theme by enumPreference("theme", Theme.SYSTEM) var dynamicColor by booleanPreference("dynamic_color", true) - var replaceIcon by booleanPreference("replace_icon", true) var devMode by booleanPreference("dev_mode", false) var installer by enumPreference("installer", InstallerSetting.PM) - var debuggable by booleanPreference("debuggable", false) - var appName by stringPreference("app_name", "Aliucord") - var packageName by stringPreference("package_name", "com.aliucord") - var version by stringPreference("version", "146108") - var hermesReplaceLibCpp by booleanPreference("hermes_replace_libcpp", false) var keepPatchedApks by booleanPreference("keep_patched_apks", false) } diff --git a/app/src/main/kotlin/com/aliucord/manager/ui/components/AnimatedVersionDisplay.kt b/app/src/main/kotlin/com/aliucord/manager/ui/components/AnimatedVersionDisplay.kt new file mode 100644 index 00000000..fad66448 --- /dev/null +++ b/app/src/main/kotlin/com/aliucord/manager/ui/components/AnimatedVersionDisplay.kt @@ -0,0 +1,36 @@ +package com.aliucord.manager.ui.components + +import androidx.compose.animation.* +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.alpha +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.SpanStyle +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.withStyle +import com.aliucord.manager.R +import com.aliucord.manager.ui.util.DiscordVersion + +@Composable +fun AnimatedVersionDisplay( + version: DiscordVersion, + modifier: Modifier = Modifier, +) { + AnimatedVisibility( + enter = fadeIn() + slideInVertically { it * -2 }, + exit = fadeOut() + slideOutVertically { it * -2 }, + visible = version !is DiscordVersion.None, + modifier = modifier, + ) { + VersionDisplay( + version = version, + prefix = { + withStyle(SpanStyle(fontWeight = FontWeight.Bold)) { + append(stringResource(R.string.version_supported)) + append(" ") + } + }, + modifier = Modifier.alpha(.5f), + ) + } +} diff --git a/app/src/main/kotlin/com/aliucord/manager/ui/components/ResetToDefaultButton.kt b/app/src/main/kotlin/com/aliucord/manager/ui/components/ResetToDefaultButton.kt new file mode 100644 index 00000000..46508301 --- /dev/null +++ b/app/src/main/kotlin/com/aliucord/manager/ui/components/ResetToDefaultButton.kt @@ -0,0 +1,28 @@ +package com.aliucord.manager.ui.components + +import androidx.compose.animation.AnimatedVisibility +import androidx.compose.material3.* +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource +import com.aliucord.manager.R +import com.aliucord.manager.ui.util.mirrorVertically + +@Composable +fun ResetToDefaultButton( + enabled: Boolean, + onClick: () -> Unit, + modifier: Modifier = Modifier, +) { + AnimatedVisibility(visible = enabled, modifier = modifier) { + IconButton(onClick = onClick) { + Icon( + painter = painterResource(R.drawable.ic_refresh), + tint = MaterialTheme.colorScheme.secondary, + contentDescription = stringResource(R.string.action_reset_default), + modifier = Modifier.mirrorVertically(), + ) + } + } +} diff --git a/app/src/main/kotlin/com/aliucord/manager/ui/components/TextDivider.kt b/app/src/main/kotlin/com/aliucord/manager/ui/components/TextDivider.kt new file mode 100644 index 00000000..7c0128ca --- /dev/null +++ b/app/src/main/kotlin/com/aliucord/manager/ui/components/TextDivider.kt @@ -0,0 +1,33 @@ +package com.aliucord.manager.ui.components + +import androidx.compose.foundation.layout.* +import androidx.compose.material3.* +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.dp + +@Composable +fun TextDivider( + text: String, + modifier: Modifier = Modifier, +) { + Row( + horizontalArrangement = Arrangement.spacedBy(6.dp, Alignment.CenterHorizontally), + verticalAlignment = Alignment.CenterVertically, + modifier = modifier + .fillMaxWidth(), + ) { + HorizontalDivider(Modifier.weight(1f)) + + Text( + text = text, + style = MaterialTheme.typography.bodySmall, + color = MaterialTheme.colorScheme.outline, + fontWeight = FontWeight.SemiBold, + ) + + HorizontalDivider(Modifier.weight(1f)) + } +} diff --git a/app/src/main/kotlin/com/aliucord/manager/ui/screens/home/components/VersionDisplay.kt b/app/src/main/kotlin/com/aliucord/manager/ui/components/VersionDisplay.kt similarity index 93% rename from app/src/main/kotlin/com/aliucord/manager/ui/screens/home/components/VersionDisplay.kt rename to app/src/main/kotlin/com/aliucord/manager/ui/components/VersionDisplay.kt index b532f08f..e7516f29 100644 --- a/app/src/main/kotlin/com/aliucord/manager/ui/screens/home/components/VersionDisplay.kt +++ b/app/src/main/kotlin/com/aliucord/manager/ui/components/VersionDisplay.kt @@ -1,4 +1,4 @@ -package com.aliucord.manager.ui.screens.home.components +package com.aliucord.manager.ui.components import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text diff --git a/app/src/main/kotlin/com/aliucord/manager/ui/components/dialogs/InstallerDialog.kt b/app/src/main/kotlin/com/aliucord/manager/ui/components/dialogs/InstallerDialog.kt deleted file mode 100644 index 08534d19..00000000 --- a/app/src/main/kotlin/com/aliucord/manager/ui/components/dialogs/InstallerDialog.kt +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright (c) 2022 Juby210 & zt - * Licensed under the Open Software License version 3.0 - */ - -package com.aliucord.manager.ui.components.dialogs - -import androidx.compose.runtime.Composable -import androidx.compose.runtime.SideEffect - -@Composable -fun InstallerDialog( - onDismiss: () -> Unit, - onConfirm: () -> Unit, -) { - SideEffect(onConfirm) - - // TODO: local install option - // TODO: mobile data warning - - // Dialog( - // onDismissRequest = onDismiss, - // ) { - // Surface( - // color = AlertDialogDefaults.containerColor, - // tonalElevation = AlertDialogDefaults.TonalElevation, - // shape = AlertDialogDefaults.shape, - // ) { - // Column( - // modifier = Modifier - // .sizeIn(minWidth = 380.dp) - // .padding(24.dp) - // ) { - // // Icon - // Box( - // Modifier - // .align(Alignment.CenterHorizontally) - // .padding(bottom = 16.dp) - // ) { - // Icon( - // imageVector = Icons.Default.Check, // TODO: move away from icon lib - // tint = AlertDialogDefaults.iconContentColor, - // contentDescription = null - // ) - // } - // - // // Title - // Box( - // modifier = Modifier - // .align(Alignment.CenterHorizontally) - // .padding(bottom = 30.dp) - // ) { - // Text( - // stringResource(R.string.selector_discord_type), - // color = AlertDialogDefaults.titleContentColor, - // style = MaterialTheme.typography.headlineSmall - // ) - // } - // - // // Body - // Box( - // modifier = Modifier - // .padding(bottom = 30.dp) - // ) { - // Text( - // stringResource(R.string.selector_discord_type_body), - // textAlign = TextAlign.Center, - // color = AlertDialogDefaults.textContentColor, - // style = MaterialTheme.typography.bodyMedium - // ) - // } - // - // Buttons - // Column( - // verticalArrangement = Arrangement.spacedBy(4.dp), - // modifier = Modifier.clip(MaterialTheme.shapes.large) - // ) { - // ProvideTextStyle(MaterialTheme.typography.labelMedium) { - // Button( - // shape = MaterialTheme.shapes.extraSmall, - // enabled = BuildConfig.RN_ENABLED, - // onClick = { - // discordType = DiscordType.REACT_NATIVE - // triggerConfirm() - // }, - // modifier = Modifier - // .fillMaxWidth() - // .height(50.dp) - // ) { - // Text(stringResource(R.string.selector_discord_type_kotlin)) - // } - // Button( - // shape = MaterialTheme.shapes.extraSmall, - // onClick = { - // discordType = DiscordType.KOTLIN - // triggerConfirm() - // }, - // modifier = Modifier - // .fillMaxWidth() - // .height(50.dp) - // ) { - // Text(stringResource(R.string.selector_discord_type_old)) - // } - // } - // } - // } - // } - // } -} 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 d6997d40..e3c9e2e0 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 @@ -7,7 +7,6 @@ import android.net.ConnectivityManager import android.provider.Settings import android.telephony.TelephonyManager import android.util.Log -import android.widget.Toast import androidx.compose.runtime.* import androidx.compose.ui.graphics.asImageBitmap import androidx.compose.ui.graphics.painter.BitmapPainter @@ -59,10 +58,6 @@ class HomeModel( application.startActivity(launchIntent) } - fun showMultiInstallToast() { - Toast.makeText(application, "Multi-install support is coming soon!", Toast.LENGTH_SHORT).show() - } - /** * Check whether the device is connected on a metered WIFI connection or through any type of mobile data, * to avoid unknowingly downloading a lot of stuff through a potentially metered network. 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 7e4e84f3..0a2a22c1 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 @@ -14,23 +14,17 @@ import androidx.compose.material3.Scaffold import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.alpha -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.text.SpanStyle -import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.text.withStyle import androidx.compose.ui.unit.dp import androidx.lifecycle.compose.LifecycleResumeEffect import cafe.adriel.voyager.core.screen.Screen import cafe.adriel.voyager.koin.getScreenModel import cafe.adriel.voyager.navigator.LocalNavigator import cafe.adriel.voyager.navigator.currentOrThrow -import com.aliucord.manager.R +import com.aliucord.manager.ui.components.AnimatedVersionDisplay import com.aliucord.manager.ui.components.ProjectHeader -import com.aliucord.manager.ui.components.dialogs.InstallerDialog import com.aliucord.manager.ui.components.dialogs.NetworkWarningDialog import com.aliucord.manager.ui.screens.home.components.* -import com.aliucord.manager.ui.screens.install.InstallScreen +import com.aliucord.manager.ui.screens.installopts.InstallOptionsScreen import com.aliucord.manager.ui.screens.plugins.PluginsScreen import com.aliucord.manager.ui.util.DiscordVersion import com.aliucord.manager.ui.util.paddings.PaddingValuesSides @@ -52,16 +46,12 @@ class HomeScreen : Screen { } var showNetworkWarningDialog by remember { mutableStateOf(false) } - var showInstallerDialog by remember { mutableStateOf(false) } - val onClickInstall: () -> Unit = remember { { - if ((model.installations as? InstallsState.Fetched)?.data?.isNotEmpty() == true) { - model.showMultiInstallToast() - } else if (model.isNetworkDangerous()) { + if (model.isNetworkDangerous()) { showNetworkWarningDialog = true } else { - showInstallerDialog = true + navigator.push(InstallOptionsScreen(model.supportedVersion)) } } } @@ -70,7 +60,7 @@ class HomeScreen : Screen { NetworkWarningDialog( onConfirm = { showNetworkWarningDialog = false - showInstallerDialog = true + navigator.push(InstallOptionsScreen(model.supportedVersion)) }, onDismiss = { showNetworkWarningDialog = false @@ -78,16 +68,6 @@ class HomeScreen : Screen { ) } - if (showInstallerDialog) { - InstallerDialog( - onDismiss = { showInstallerDialog = false }, - onConfirm = { - showInstallerDialog = false - navigator.push(InstallScreen()) - } - ) - } - Scaffold( topBar = { HomeAppBar() }, ) { paddingValues -> @@ -115,24 +95,10 @@ class HomeScreen : Screen { } item(key = "SUPPORTED_VERSION") { - AnimatedVisibility( - enter = fadeIn() + slideInVertically { it * -2 }, - exit = fadeOut() + slideOutVertically { it * -2 }, - visible = model.supportedVersion !is DiscordVersion.None, - ) { - VersionDisplay( - version = model.supportedVersion, - prefix = { - withStyle(SpanStyle(fontWeight = FontWeight.Bold)) { - append(stringResource(R.string.version_supported)) - append(" ") - } - }, - modifier = Modifier - .alpha(.5f) - .padding(bottom = 22.dp), - ) - } + AnimatedVersionDisplay( + version = model.supportedVersion, + modifier = Modifier.padding(bottom = 22.dp), + ) } val installations = (model.installations as? InstallsState.Fetched)?.data @@ -146,7 +112,7 @@ class HomeScreen : Screen { ) { InstalledItemCard( data = it, - onUpdate = { showInstallerDialog = true }, // TODO: prefilled install options screen + onUpdate = ::TODO, // TODO: prefilled install options screen 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/home/components/InstalledItemCard.kt b/app/src/main/kotlin/com/aliucord/manager/ui/screens/home/components/InstalledItemCard.kt index 417a2b5e..170c41a7 100644 --- a/app/src/main/kotlin/com/aliucord/manager/ui/screens/home/components/InstalledItemCard.kt +++ b/app/src/main/kotlin/com/aliucord/manager/ui/screens/home/components/InstalledItemCard.kt @@ -17,6 +17,7 @@ import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp import com.aliucord.manager.R import com.aliucord.manager.ui.components.SegmentedButton +import com.aliucord.manager.ui.components.VersionDisplay import com.aliucord.manager.ui.screens.home.InstallData @Composable diff --git a/app/src/main/kotlin/com/aliucord/manager/ui/screens/install/InstallModel.kt b/app/src/main/kotlin/com/aliucord/manager/ui/screens/install/InstallModel.kt index 37d30fd9..4347a2b9 100644 --- a/app/src/main/kotlin/com/aliucord/manager/ui/screens/install/InstallModel.kt +++ b/app/src/main/kotlin/com/aliucord/manager/ui/screens/install/InstallModel.kt @@ -15,6 +15,7 @@ import com.aliucord.manager.installer.steps.base.Step import com.aliucord.manager.installer.steps.base.StepState import com.aliucord.manager.installer.steps.install.InstallStep import com.aliucord.manager.manager.PathManager +import com.aliucord.manager.ui.screens.installopts.InstallOptions import com.aliucord.manager.ui.util.toUnsafeImmutable import com.aliucord.manager.util.* import kotlinx.collections.immutable.ImmutableList @@ -26,6 +27,7 @@ import java.util.Date class InstallModel( private val application: Application, private val paths: PathManager, + private val options: InstallOptions, ) : StateScreenModel(InstallScreenState.Pending) { private lateinit var startTime: Date private var installJob: Job? = null @@ -69,7 +71,7 @@ class InstallModel( mutableState.value = InstallScreenState.Working val newInstallJob = screenModelScope.launch { - val runner = KotlinInstallRunner() + val runner = KotlinInstallRunner(options) installSteps = runner.steps.groupBy { it.group } .mapValues { it.value.toUnsafeImmutable() } diff --git a/app/src/main/kotlin/com/aliucord/manager/ui/screens/install/InstallScreen.kt b/app/src/main/kotlin/com/aliucord/manager/ui/screens/install/InstallScreen.kt index 3822d169..99e8634a 100644 --- a/app/src/main/kotlin/com/aliucord/manager/ui/screens/install/InstallScreen.kt +++ b/app/src/main/kotlin/com/aliucord/manager/ui/screens/install/InstallScreen.kt @@ -28,14 +28,16 @@ import com.aliucord.manager.installer.steps.StepGroup import com.aliucord.manager.ui.components.back import com.aliucord.manager.ui.components.dialogs.InstallerAbortDialog import com.aliucord.manager.ui.screens.install.components.StepGroupCard +import com.aliucord.manager.ui.screens.installopts.InstallOptions +import org.koin.core.parameter.parametersOf -class InstallScreen : Screen { +class InstallScreen(private val data: InstallOptions) : Screen { override val key = "Install" @Composable override fun Content() { val navigator = LocalNavigator.currentOrThrow - val model = getScreenModel() + val model = getScreenModel { parametersOf(data) } val state = model.state.collectAsState() LaunchedEffect(state.value) { diff --git a/app/src/main/kotlin/com/aliucord/manager/ui/screens/installopts/InstallOptions.kt b/app/src/main/kotlin/com/aliucord/manager/ui/screens/installopts/InstallOptions.kt new file mode 100644 index 00000000..5a6c88d2 --- /dev/null +++ b/app/src/main/kotlin/com/aliucord/manager/ui/screens/installopts/InstallOptions.kt @@ -0,0 +1,11 @@ +package com.aliucord.manager.ui.screens.installopts + +import androidx.compose.runtime.Immutable + +@Immutable +data class InstallOptions( + val appName: String, + val packageName: String, + val debuggable: Boolean, + val replaceIcon: Boolean, +) diff --git a/app/src/main/kotlin/com/aliucord/manager/ui/screens/installopts/InstallOptionsModel.kt b/app/src/main/kotlin/com/aliucord/manager/ui/screens/installopts/InstallOptionsModel.kt new file mode 100644 index 00000000..31136bde --- /dev/null +++ b/app/src/main/kotlin/com/aliucord/manager/ui/screens/installopts/InstallOptionsModel.kt @@ -0,0 +1,128 @@ +package com.aliucord.manager.ui.screens.installopts + +import android.content.Context +import android.content.pm.PackageManager.NameNotFoundException +import androidx.compose.runtime.* +import cafe.adriel.voyager.core.model.ScreenModel +import cafe.adriel.voyager.core.model.screenModelScope +import com.aliucord.manager.manager.PreferencesManager +import com.aliucord.manager.util.debounce +import kotlinx.coroutines.launch + +class InstallOptionsModel( + private val context: Context, + private val prefs: PreferencesManager, +) : ScreenModel { + // ---------- Package name state ---------- + var packageName by mutableStateOf("com.aliucord") + private set + + var packageNameState by mutableStateOf(PackageNameState.Ok) + private set + + val packageNameIsDefault by derivedStateOf { + packageName == "com.aliucord" + } + + fun changePackageName(newPackageName: String) { + packageName = newPackageName + fetchPkgNameStateDebounced() + } + + fun resetPackageName() { + changePackageName("com.aliucord") + } + + // ---------- App name state ---------- + var appName by mutableStateOf("Aliucord") + private set + + var appNameIsError by mutableStateOf(false) + private set + + val appNameIsDefault by derivedStateOf { + appName == "Aliucord" + } + + fun changeAppName(newAppName: String) { + appName = newAppName + appNameIsError = newAppName.length !in (1..150) + } + + fun resetAppName() { + appName = "Aliucord" + } + + // ---------- Icon patching state ---------- + var replaceIcon by mutableStateOf(true) + private set + + fun changeReplaceIcon(value: Boolean) { + replaceIcon = value + } + + // ---------- Debuggable state ---------- + var debuggable by mutableStateOf(false) + private set + + fun changeDebuggable(value: Boolean) { + debuggable = value + } + + // ---------- Config generation ---------- + val isConfigValid by derivedStateOf { + val invalidChecks = arrayOf( + packageNameState == PackageNameState.Invalid, + appNameIsError, + ) + + invalidChecks.none { it } + } + + fun generateConfig(): InstallOptions { + if (!isConfigValid) error("invalid config state") + + return InstallOptions( + appName = appName, + packageName = packageName, + debuggable = debuggable, + replaceIcon = replaceIcon, // TODO: advanced icon patchers + ) + } + + // ---------- Other ---------- + val isDevMode: Boolean + get() = prefs.devMode + + // A throttled variant of fetchPkgNameState() + private val fetchPkgNameStateDebounced: () -> Unit = + screenModelScope.debounce(100L, function = ::fetchPkgNameState) + + private fun fetchPkgNameState() { + if (packageName.length !in (3..150) || !PACKAGE_REGEX.matches(this.packageName)) { + packageNameState = PackageNameState.Invalid + } else { + try { + context.packageManager.getPackageInfo(packageName, 0) + packageNameState = PackageNameState.Taken + } catch (_: NameNotFoundException) { + packageNameState = PackageNameState.Ok + } + } + } + + init { + screenModelScope.launch { fetchPkgNameState() } + } + + companion object { + private val PACKAGE_REGEX = """^[a-z]\w*(\.[a-z]\w*)+$""" + .toRegex(RegexOption.IGNORE_CASE) + } +} + +enum class PackageNameState { + Ok, + Invalid, + Taken, +} diff --git a/app/src/main/kotlin/com/aliucord/manager/ui/screens/installopts/InstallOptionsScreen.kt b/app/src/main/kotlin/com/aliucord/manager/ui/screens/installopts/InstallOptionsScreen.kt new file mode 100644 index 00000000..6cc5a60a --- /dev/null +++ b/app/src/main/kotlin/com/aliucord/manager/ui/screens/installopts/InstallOptionsScreen.kt @@ -0,0 +1,135 @@ +package com.aliucord.manager.ui.screens.installopts + +import androidx.compose.foundation.layout.* +import androidx.compose.material3.* +import androidx.compose.runtime.* +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.alpha +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.dp +import cafe.adriel.voyager.core.screen.Screen +import cafe.adriel.voyager.koin.getScreenModel +import cafe.adriel.voyager.navigator.LocalNavigator +import cafe.adriel.voyager.navigator.currentOrThrow +import com.aliucord.manager.R +import com.aliucord.manager.ui.components.AnimatedVersionDisplay +import com.aliucord.manager.ui.components.TextDivider +import com.aliucord.manager.ui.screens.install.InstallScreen +import com.aliucord.manager.ui.screens.installopts.components.InstallOptionsAppBar +import com.aliucord.manager.ui.screens.installopts.components.PackageNameState +import com.aliucord.manager.ui.screens.installopts.components.options.SwitchInstallOption +import com.aliucord.manager.ui.screens.installopts.components.options.TextInstallOption +import com.aliucord.manager.ui.util.DiscordVersion +import com.aliucord.manager.ui.util.thenIf + +class InstallOptionsScreen( + private val supportedVersion: DiscordVersion = DiscordVersion.None, +) : Screen { + override val key = "InstallOptions" + + @Composable + override fun Content() { + val navigator = LocalNavigator.currentOrThrow + val model = getScreenModel() + + Scaffold( + topBar = { InstallOptionsAppBar() }, + ) { paddingValues -> + Column( + verticalArrangement = Arrangement.spacedBy(20.dp), + modifier = Modifier + .fillMaxSize() + .padding(paddingValues) + .padding(horizontal = 20.dp, vertical = 10.dp) + ) { + Text( + text = stringResource(R.string.installopts_title), + style = MaterialTheme.typography.bodyMedium, + color = MaterialTheme.colorScheme.onSurfaceVariant, + textAlign = TextAlign.Center, + ) + + var animatedVersion by remember { mutableStateOf(DiscordVersion.None) } + LaunchedEffect(Unit) { + animatedVersion = supportedVersion + } + AnimatedVersionDisplay( + version = animatedVersion, + modifier = Modifier + .align(Alignment.CenterHorizontally) + .offset(y = (-10).dp), + ) + + TextDivider(text = stringResource(R.string.installopts_divider_basic)) + + SwitchInstallOption( + icon = painterResource(R.drawable.ic_app_shortcut), + name = stringResource(R.string.installopts_icon_title), + description = stringResource(R.string.installopts_icon_desc), + value = model.replaceIcon, + onValueChange = model::changeReplaceIcon, + modifier = Modifier.padding(bottom = 8.dp) + ) + + TextInstallOption( + name = stringResource(R.string.installopts_appname_title), + description = stringResource(R.string.installopts_appname_desc), + value = model.appName, + valueIsError = model.appNameIsError, + valueIsDefault = model.appNameIsDefault, + onValueChange = model::changeAppName, + onValueReset = model::resetAppName + ) + + TextInstallOption( + name = stringResource(R.string.installopts_pkgname_title), + description = stringResource(R.string.installopts_pkgname_desc), + value = model.packageName, + valueIsError = model.packageNameState == PackageNameState.Invalid, + valueIsDefault = model.packageNameIsDefault, + onValueChange = model::changePackageName, + onValueReset = model::resetPackageName, + ) { + PackageNameState( + state = model.packageNameState, + modifier = Modifier.padding(start = 4.dp), + ) + } + + TextDivider( + text = stringResource(R.string.installopts_divider_advanced), + modifier = Modifier.padding(top = 12.dp), + ) + + SwitchInstallOption( + icon = painterResource(R.drawable.ic_bug), + name = stringResource(R.string.installopts_debuggable_title), + description = stringResource(R.string.installopts_debuggable_desc), + value = model.debuggable, + onValueChange = model::changeDebuggable, + enabled = model.isDevMode, + modifier = Modifier + .thenIf(!model.isDevMode) { alpha(.6f) } + ) + + Spacer(Modifier.weight(1f)) + + FilledTonalButton( + enabled = model.isConfigValid, + onClick = { navigator replace InstallScreen(model.generateConfig()) }, + colors = ButtonDefaults.filledTonalButtonColors( + contentColor = MaterialTheme.colorScheme.primary, + ), + modifier = Modifier + .padding(bottom = 10.dp) + .align(Alignment.End), + ) { + Text(stringResource(R.string.action_install)) + } + } + } + } +} diff --git a/app/src/main/kotlin/com/aliucord/manager/ui/screens/installopts/components/InstallOptionsAppBar.kt b/app/src/main/kotlin/com/aliucord/manager/ui/screens/installopts/components/InstallOptionsAppBar.kt new file mode 100644 index 00000000..4ac9a281 --- /dev/null +++ b/app/src/main/kotlin/com/aliucord/manager/ui/screens/installopts/components/InstallOptionsAppBar.kt @@ -0,0 +1,29 @@ +package com.aliucord.manager.ui.screens.installopts.components + +import androidx.compose.material3.* +import androidx.compose.runtime.Composable +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource +import cafe.adriel.voyager.navigator.LocalNavigator +import cafe.adriel.voyager.navigator.currentOrThrow +import com.aliucord.manager.R +import com.aliucord.manager.ui.components.BackButton +import com.aliucord.manager.ui.screens.settings.SettingsScreen + +@Composable +fun InstallOptionsAppBar() { + TopAppBar( + navigationIcon = { BackButton() }, + title = { Text(stringResource(R.string.action_add_install)) }, + actions = { + val navigator = LocalNavigator.currentOrThrow + + IconButton(onClick = { navigator.push(SettingsScreen()) }) { + Icon( + painter = painterResource(R.drawable.ic_settings), + contentDescription = stringResource(R.string.navigation_settings) + ) + } + } + ) +} diff --git a/app/src/main/kotlin/com/aliucord/manager/ui/screens/installopts/components/PackageNameState.kt b/app/src/main/kotlin/com/aliucord/manager/ui/screens/installopts/components/PackageNameState.kt new file mode 100644 index 00000000..f0054454 --- /dev/null +++ b/app/src/main/kotlin/com/aliucord/manager/ui/screens/installopts/components/PackageNameState.kt @@ -0,0 +1,65 @@ +package com.aliucord.manager.ui.screens.installopts.components + +import androidx.compose.animation.Crossfade +import androidx.compose.foundation.layout.* +import androidx.compose.material3.* +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.alpha +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.unit.dp +import com.aliucord.manager.R +import com.aliucord.manager.ui.screens.installopts.PackageNameState + +@Composable +fun PackageNameState( + state: PackageNameState, + modifier: Modifier = Modifier, +) { + Crossfade( + targetState = state, + label = "PackageNameStateLabel CrossFade" + ) { animatedState -> + val (label, icon, tint) = when (animatedState) { + PackageNameState.Invalid -> Triple( + R.string.installopts_pkgname_invalid, + R.drawable.ic_canceled, + MaterialTheme.colorScheme.error, + ) + + PackageNameState.Taken -> Triple( + R.string.installopts_pkgname_taken, + R.drawable.ic_warning, + Color(0xFFFFCC00), + ) + + PackageNameState.Ok -> Triple( + R.string.installopts_pkgname_ok, + R.drawable.ic_check_circle, + Color(0xFF59B463), + ) + } + + Row( + horizontalArrangement = Arrangement.spacedBy(4.dp), + verticalAlignment = Alignment.CenterVertically, + modifier = modifier, + ) { + Icon( + painter = painterResource(icon), + contentDescription = null, + tint = tint, + modifier = Modifier.size(20.dp), + ) + + Text( + text = stringResource(label), + style = MaterialTheme.typography.bodySmall, + modifier = Modifier.alpha(.7f), + ) + } + } +} diff --git a/app/src/main/kotlin/com/aliucord/manager/ui/screens/installopts/components/options/InstallOption.kt b/app/src/main/kotlin/com/aliucord/manager/ui/screens/installopts/components/options/InstallOption.kt new file mode 100644 index 00000000..0228ca67 --- /dev/null +++ b/app/src/main/kotlin/com/aliucord/manager/ui/screens/installopts/components/options/InstallOption.kt @@ -0,0 +1,39 @@ +package com.aliucord.manager.ui.screens.installopts.components.options + +import androidx.compose.foundation.layout.* +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.alpha +import androidx.compose.ui.unit.dp + +@Composable +fun InstallOption( + name: String, + description: String?, + modifier: Modifier = Modifier, + content: @Composable ColumnScope.() -> Unit, +) { + Column( + verticalArrangement = Arrangement.spacedBy(4.dp), + horizontalAlignment = Alignment.Start, + modifier = modifier, + ) { + Text( + text = name, + style = MaterialTheme.typography.titleMedium, + ) + + if (description != null) { + Text( + text = description, + style = MaterialTheme.typography.bodySmall, + modifier = Modifier.alpha(.7f), + ) + } + + content() + } +} diff --git a/app/src/main/kotlin/com/aliucord/manager/ui/screens/installopts/components/options/SwitchInstallOption.kt b/app/src/main/kotlin/com/aliucord/manager/ui/screens/installopts/components/options/SwitchInstallOption.kt new file mode 100644 index 00000000..42e90c46 --- /dev/null +++ b/app/src/main/kotlin/com/aliucord/manager/ui/screens/installopts/components/options/SwitchInstallOption.kt @@ -0,0 +1,73 @@ +package com.aliucord.manager.ui.screens.installopts.components.options + +import androidx.compose.foundation.clickable +import androidx.compose.foundation.interaction.MutableInteractionSource +import androidx.compose.foundation.layout.* +import androidx.compose.material3.* +import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.alpha +import androidx.compose.ui.graphics.painter.Painter +import androidx.compose.ui.semantics.Role +import androidx.compose.ui.unit.dp + +@Composable +fun SwitchInstallOption( + icon: Painter, + name: String, + description: String, + value: Boolean, + onValueChange: (Boolean) -> Unit, + enabled: Boolean = true, + modifier: Modifier = Modifier, +) { + val interactionSource = remember(::MutableInteractionSource) + val onClick = remember(value) { { onValueChange(!value) } } + + Row( + horizontalArrangement = Arrangement.spacedBy(12.dp), + verticalAlignment = Alignment.CenterVertically, + modifier = modifier + .fillMaxWidth() + .clickable( + onClick = onClick, + enabled = enabled, + interactionSource = interactionSource, + indication = null, + role = Role.Switch, + ), + ) { + Icon( + painter = icon, + contentDescription = null, + modifier = Modifier.size(26.dp), + ) + + Column( + verticalArrangement = Arrangement.spacedBy(2.dp), + modifier = Modifier.weight(1f) + ) { + Text( + text = name, + style = MaterialTheme.typography.titleMedium, + ) + + Text( + text = description, + style = MaterialTheme.typography.bodySmall, + modifier = Modifier + .alpha(.7f) + ) + } + + Switch( + checked = value, + enabled = enabled, + onCheckedChange = onValueChange, + interactionSource = interactionSource, + modifier = Modifier.padding(start = 6.dp), + ) + } +} diff --git a/app/src/main/kotlin/com/aliucord/manager/ui/screens/installopts/components/options/TextInstallOption.kt b/app/src/main/kotlin/com/aliucord/manager/ui/screens/installopts/components/options/TextInstallOption.kt new file mode 100644 index 00000000..89e25e79 --- /dev/null +++ b/app/src/main/kotlin/com/aliucord/manager/ui/screens/installopts/components/options/TextInstallOption.kt @@ -0,0 +1,53 @@ +package com.aliucord.manager.ui.screens.installopts.components.options + +import androidx.compose.foundation.layout.* +import androidx.compose.material3.* +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp +import com.aliucord.manager.ui.components.ResetToDefaultButton + +@Composable +fun TextInstallOption( + name: String, + description: String, + value: String, + valueIsError: Boolean, + valueIsDefault: Boolean, + onValueChange: (String) -> Unit, + onValueReset: () -> Unit, + modifier: Modifier = Modifier, + extra: (@Composable ColumnScope.() -> Unit)? = null, +) { + InstallOption( + name = name, + description = description, + modifier = modifier, + ) { + val containerColor = MaterialTheme.colorScheme + .surfaceColorAtElevation(LocalAbsoluteTonalElevation.current + .5.dp) + + OutlinedTextField( + value = value, + onValueChange = onValueChange, + isError = valueIsError, + singleLine = true, + colors = OutlinedTextFieldDefaults.colors( + unfocusedContainerColor = containerColor, + focusedContainerColor = containerColor, + errorContainerColor = containerColor, + ), + trailingIcon = { + ResetToDefaultButton( + enabled = !valueIsDefault, + onClick = onValueReset, + ) + }, + modifier = Modifier + .fillMaxWidth() + .padding(vertical = 4.dp), + ) + + extra?.invoke(this) + } +} diff --git a/app/src/main/kotlin/com/aliucord/manager/ui/screens/settings/SettingsModel.kt b/app/src/main/kotlin/com/aliucord/manager/ui/screens/settings/SettingsModel.kt index caa721c9..edc3f02b 100644 --- a/app/src/main/kotlin/com/aliucord/manager/ui/screens/settings/SettingsModel.kt +++ b/app/src/main/kotlin/com/aliucord/manager/ui/screens/settings/SettingsModel.kt @@ -3,27 +3,18 @@ package com.aliucord.manager.ui.screens.settings import android.app.Application import androidx.compose.runtime.* import cafe.adriel.voyager.core.model.ScreenModel -import cafe.adriel.voyager.core.model.screenModelScope import com.aliucord.manager.R import com.aliucord.manager.manager.PreferencesManager import com.aliucord.manager.ui.components.Theme import com.aliucord.manager.util.showToast -import com.aliucord.manager.util.throttle class SettingsModel( private val application: Application, val preferences: PreferencesManager, ) : ScreenModel { - private val checkPackageNameThrottled = throttle(50L, screenModelScope) { - packageNameError = !PACKAGE_REGEX.matches(preferences.packageName) - } - var showThemeDialog by mutableStateOf(false) private set - var packageNameError by mutableStateOf(false) - private set - fun showThemeDialog() { showThemeDialog = true } @@ -32,41 +23,12 @@ class SettingsModel( showThemeDialog = false } - fun setPackageName(packageName: String) { - preferences.packageName = packageName - checkPackageNameThrottled() - } - - fun setAppName(appName: String) { - if (appName.isNotBlank()) preferences.appName = appName - } - fun setTheme(theme: Theme) { preferences.theme = theme } - fun setVersion(version: String) { - if (version.isNotBlank()) preferences.version = version - } - fun clearCacheDir() { application.externalCacheDir?.deleteRecursively() application.showToast(R.string.action_cleared_cache) } - - init { - checkPackageNameThrottled() - } - - override fun onDispose() { - if (!PACKAGE_REGEX.matches(preferences.packageName)) { - preferences.packageName = "com.aliucord" - application.showToast(R.string.settings_invalid_package_name) - } - } - - companion object { - private val PACKAGE_REGEX = "^[a-z]\\w*(\\.[a-z]\\w*)+\$" - .toRegex(RegexOption.IGNORE_CASE) - } } diff --git a/app/src/main/kotlin/com/aliucord/manager/ui/screens/settings/SettingsScreen.kt b/app/src/main/kotlin/com/aliucord/manager/ui/screens/settings/SettingsScreen.kt index 051c775f..8adce29f 100644 --- a/app/src/main/kotlin/com/aliucord/manager/ui/screens/settings/SettingsScreen.kt +++ b/app/src/main/kotlin/com/aliucord/manager/ui/screens/settings/SettingsScreen.kt @@ -5,7 +5,6 @@ package com.aliucord.manager.ui.screens.settings -import androidx.compose.animation.* import androidx.compose.foundation.* import androidx.compose.foundation.layout.* import androidx.compose.material3.* @@ -76,22 +75,8 @@ class SettingsScreen : Screen { SettingsHeader(stringResource(R.string.settings_advanced)) - SettingsTextField( - label = stringResource(R.string.setting_app_name), - pref = preferences.appName, - onPrefChange = model::setAppName - ) Spacer(modifier = Modifier.height(4.dp)) - SettingsSwitch( - label = stringResource(R.string.setting_replace_icon), - secondaryLabel = stringResource(R.string.setting_replace_icon_desc), - pref = preferences.replaceIcon, - icon = { Icon(painterResource(R.drawable.ic_app_shortcut), null) } - ) { - preferences.replaceIcon = it - } - SettingsSwitch( label = stringResource(R.string.setting_keep_patched_apks), secondaryLabel = stringResource(R.string.setting_keep_patched_apks_desc), @@ -110,45 +95,6 @@ class SettingsScreen : Screen { preferences.devMode = it } - AnimatedVisibility( - visible = preferences.devMode, - enter = expandVertically(), - exit = shrinkVertically() - ) { - Column( - verticalArrangement = Arrangement.spacedBy(6.dp) - ) { - SettingsTextField( - label = stringResource(R.string.setting_package_name), - pref = preferences.packageName, - onPrefChange = model::setPackageName, - error = model.packageNameError - ) - - SettingsTextField( - label = stringResource(R.string.setting_target_version), - pref = preferences.version, - onPrefChange = model::setVersion - ) - - SettingsSwitch( - label = stringResource(R.string.setting_debuggable), - secondaryLabel = stringResource(R.string.setting_debuggable_desc), - pref = preferences.debuggable, - icon = { Icon(painterResource(R.drawable.ic_bug), null) }, - onPrefChange = { preferences.debuggable = it }, - ) - - SettingsSwitch( - label = stringResource(R.string.setting_hermes_replace_libcpp), - secondaryLabel = stringResource(R.string.setting_hermes_replace_libcpp_desc), - icon = { Icon(painterResource(R.drawable.ic_copy_file), null) }, - pref = preferences.hermesReplaceLibCpp, - onPrefChange = { preferences.hermesReplaceLibCpp = it }, - ) - } - } - Button( modifier = Modifier .fillMaxWidth() diff --git a/app/src/main/kotlin/com/aliucord/manager/ui/util/Utils.kt b/app/src/main/kotlin/com/aliucord/manager/ui/util/Utils.kt index 70cb77cb..34650fe8 100644 --- a/app/src/main/kotlin/com/aliucord/manager/ui/util/Utils.kt +++ b/app/src/main/kotlin/com/aliucord/manager/ui/util/Utils.kt @@ -1,7 +1,12 @@ +@file:Suppress("NOTHING_TO_INLINE") + package com.aliucord.manager.ui.util import androidx.annotation.StringRes import androidx.compose.runtime.Composable +import androidx.compose.runtime.Stable +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.scale import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.* import kotlinx.collections.immutable.ImmutableList @@ -75,3 +80,7 @@ inline fun annotatingStringResource( append(string.substring(lastIndex)) } } + +@Stable +inline fun Modifier.mirrorVertically(): Modifier = + scale(scaleX = -1f, scaleY = 1f) diff --git a/app/src/main/kotlin/com/aliucord/manager/util/Debounce.kt b/app/src/main/kotlin/com/aliucord/manager/util/Debounce.kt new file mode 100644 index 00000000..5e21cfdd --- /dev/null +++ b/app/src/main/kotlin/com/aliucord/manager/util/Debounce.kt @@ -0,0 +1,55 @@ +package com.aliucord.manager.util + +import kotlinx.coroutines.* +import java.util.concurrent.atomic.AtomicBoolean + +/** + * Returns a function that when called any number of times, only executes [function] after + * [waitMs] has passed after the last call, using the last call's passed in param(s). + * This is for things like "throttling" search text input to reduce the amount of actual + * calls to only when the user stops typing for example. + * + * @param waitMs Milliseconds to wait for additional calls before executing [function] + * @param waitCompletion If true, then ignore any calls while [function] is executing instead of + * cancelling it and restarting the debouncing job. + * @param function The target function to debounce. + * @return Refer to the general description + */ +fun CoroutineScope.debounce( + waitMs: Long, + waitCompletion: Boolean = false, + function: suspend (P1, P2) -> Unit, +): (P1, P2) -> Unit { + var job: Job? = null + val executing = AtomicBoolean(false) + + return block@{ p1: P1, p2: P2 -> + if (waitCompletion && !executing.get()) { + return@block + } else if (job?.isActive == true) { + job?.cancel() + } + + job = launch { + delay(waitMs) + + try { + executing.set(true) + function(p1, p2) + } finally { + executing.set(false) + } + } + } +} + +// Re-binding the same function but with different amount of params +// Yes this is ugly but there isn't really a better way to do this efficiently afaik + +inline fun CoroutineScope.debounce(waitMs: Long, waitCompletion: Boolean = false, crossinline function: suspend () -> Unit) = + debounce(waitMs, waitCompletion) { _, _ -> function() } + .let { { it(null, null) } } + +inline fun CoroutineScope.debounce(waitMs: Long, waitCompletion: Boolean = false, crossinline function: suspend (T) -> Unit) = + debounce(waitMs, waitCompletion) { p1, _ -> function(p1) } + .let { { p1: T -> it(p1, null) } } diff --git a/app/src/main/res/drawable/ic_copy_file.xml b/app/src/main/res/drawable/ic_copy_file.xml deleted file mode 100644 index 03968138..00000000 --- a/app/src/main/res/drawable/ic_copy_file.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/app/src/main/res/drawable/ic_refresh.xml b/app/src/main/res/drawable/ic_refresh.xml new file mode 100644 index 00000000..fa51cfb7 --- /dev/null +++ b/app/src/main/res/drawable/ic_refresh.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_warning.xml b/app/src/main/res/drawable/ic_warning.xml new file mode 100644 index 00000000..d725cd58 --- /dev/null +++ b/app/src/main/res/drawable/ic_warning.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/values-af-rZA/strings.xml b/app/src/main/res/values-af-rZA/strings.xml index f1bbaa9b..0baf2700 100644 --- a/app/src/main/res/values-af-rZA/strings.xml +++ b/app/src/main/res/values-af-rZA/strings.xml @@ -35,19 +35,9 @@ Appearance Developer options Clear cache - Replace app icon - Uses the Aliucord variant as opposed to Discord\'s own icon - Debuggable - Enable debuggable flag - App Name - Package Name - Download Version Dynamic color - Replace libc++ (RN only) - Downloads and uses libc++ from patched hermes Keep patched APKs Don\'t delete patched APKs after installing (for installing manually) - Invalid package name, reset to com.aliucord System Dark Light diff --git a/app/src/main/res/values-ar-rSA/strings.xml b/app/src/main/res/values-ar-rSA/strings.xml index f1bbaa9b..0baf2700 100644 --- a/app/src/main/res/values-ar-rSA/strings.xml +++ b/app/src/main/res/values-ar-rSA/strings.xml @@ -35,19 +35,9 @@ Appearance Developer options Clear cache - Replace app icon - Uses the Aliucord variant as opposed to Discord\'s own icon - Debuggable - Enable debuggable flag - App Name - Package Name - Download Version Dynamic color - Replace libc++ (RN only) - Downloads and uses libc++ from patched hermes Keep patched APKs Don\'t delete patched APKs after installing (for installing manually) - Invalid package name, reset to com.aliucord System Dark Light diff --git a/app/src/main/res/values-ca-rES/strings.xml b/app/src/main/res/values-ca-rES/strings.xml index f1bbaa9b..0baf2700 100644 --- a/app/src/main/res/values-ca-rES/strings.xml +++ b/app/src/main/res/values-ca-rES/strings.xml @@ -35,19 +35,9 @@ Appearance Developer options Clear cache - Replace app icon - Uses the Aliucord variant as opposed to Discord\'s own icon - Debuggable - Enable debuggable flag - App Name - Package Name - Download Version Dynamic color - Replace libc++ (RN only) - Downloads and uses libc++ from patched hermes Keep patched APKs Don\'t delete patched APKs after installing (for installing manually) - Invalid package name, reset to com.aliucord System Dark Light diff --git a/app/src/main/res/values-cs-rCZ/strings.xml b/app/src/main/res/values-cs-rCZ/strings.xml index f1bbaa9b..0baf2700 100644 --- a/app/src/main/res/values-cs-rCZ/strings.xml +++ b/app/src/main/res/values-cs-rCZ/strings.xml @@ -35,19 +35,9 @@ Appearance Developer options Clear cache - Replace app icon - Uses the Aliucord variant as opposed to Discord\'s own icon - Debuggable - Enable debuggable flag - App Name - Package Name - Download Version Dynamic color - Replace libc++ (RN only) - Downloads and uses libc++ from patched hermes Keep patched APKs Don\'t delete patched APKs after installing (for installing manually) - Invalid package name, reset to com.aliucord System Dark Light diff --git a/app/src/main/res/values-da-rDK/strings.xml b/app/src/main/res/values-da-rDK/strings.xml index f1bbaa9b..0baf2700 100644 --- a/app/src/main/res/values-da-rDK/strings.xml +++ b/app/src/main/res/values-da-rDK/strings.xml @@ -35,19 +35,9 @@ Appearance Developer options Clear cache - Replace app icon - Uses the Aliucord variant as opposed to Discord\'s own icon - Debuggable - Enable debuggable flag - App Name - Package Name - Download Version Dynamic color - Replace libc++ (RN only) - Downloads and uses libc++ from patched hermes Keep patched APKs Don\'t delete patched APKs after installing (for installing manually) - Invalid package name, reset to com.aliucord System Dark Light diff --git a/app/src/main/res/values-de-rDE/strings.xml b/app/src/main/res/values-de-rDE/strings.xml index dbe41ed4..98cef19a 100644 --- a/app/src/main/res/values-de-rDE/strings.xml +++ b/app/src/main/res/values-de-rDE/strings.xml @@ -35,19 +35,9 @@ Appearance Developer options Clear cache - Replace app icon - Uses the Aliucord variant as opposed to Discord\'s own icon - Debuggable - Enable debuggable flag - App Name - Package Name - Download Version Dynamic color - Replace libc++ (RN only) - Downloads and uses libc++ from patched hermes Keep patched APKs Don\'t delete patched APKs after installing (for installing manually) - Invalid package name, reset to com.aliucord System Dark Light diff --git a/app/src/main/res/values-el-rGR/strings.xml b/app/src/main/res/values-el-rGR/strings.xml index b4850946..46cb4aac 100644 --- a/app/src/main/res/values-el-rGR/strings.xml +++ b/app/src/main/res/values-el-rGR/strings.xml @@ -35,19 +35,9 @@ Εμφάνιση Επιλογές προγραμματιστών Εκκαθάριση προσωρινής μνήμης - Αντικατάσταση εικονιδίου εφαρμογής - Χρησιμοποιεί την παραλλαγή του Aliucord σε αντίθεση με το εικονίδιο του Discord - Αποσφαλματώσιμο - Ενεργοποίηση επισήμανσης αποσφαλμάτωσης - Όνομα εφαρμογής - Όνομα Πακέτου - Λήψη έκδοσης Δυναμικό χρώμα - Replace libc++ (RN only) - Downloads and uses libc++ from patched hermes Keep patched APKs Don\'t delete patched APKs after installing (for installing manually) - Άκυρο όνομα πακέτου, επαναφορά σε com.aliucord Σύστημα Σκοτεινό Φωτεινό diff --git a/app/src/main/res/values-es-rES/strings.xml b/app/src/main/res/values-es-rES/strings.xml index f4315e85..935bc7b5 100644 --- a/app/src/main/res/values-es-rES/strings.xml +++ b/app/src/main/res/values-es-rES/strings.xml @@ -35,19 +35,9 @@ Apariencia Opciones de Desarrollador Limpiar caché - Reemplazar el icono de la app - Usa la variante de Aliucord en vez de el icono de Discord - Depurable - Activa el modo de Depuración - Nombre de la App - Nombre del Paquete - Versión a descargar (solo RN) Colores dinámicos - Reemplazar libc++ (solo RN) - Descargar y usar libc++ de hermes parcheado Mantener APKs parcheados No eliminar APKs parcheados después de la instalación (para instalar manualmente) - Nombre de paquete inválido, restableciendo a com.aliucord Sistema Oscuro Claro diff --git a/app/src/main/res/values-fi-rFI/strings.xml b/app/src/main/res/values-fi-rFI/strings.xml index f1bbaa9b..0baf2700 100644 --- a/app/src/main/res/values-fi-rFI/strings.xml +++ b/app/src/main/res/values-fi-rFI/strings.xml @@ -35,19 +35,9 @@ Appearance Developer options Clear cache - Replace app icon - Uses the Aliucord variant as opposed to Discord\'s own icon - Debuggable - Enable debuggable flag - App Name - Package Name - Download Version Dynamic color - Replace libc++ (RN only) - Downloads and uses libc++ from patched hermes Keep patched APKs Don\'t delete patched APKs after installing (for installing manually) - Invalid package name, reset to com.aliucord System Dark Light diff --git a/app/src/main/res/values-fr-rFR/strings.xml b/app/src/main/res/values-fr-rFR/strings.xml index 7a6e9d30..156b18f3 100644 --- a/app/src/main/res/values-fr-rFR/strings.xml +++ b/app/src/main/res/values-fr-rFR/strings.xml @@ -35,19 +35,9 @@ Apparence Options de développeur Vider le cache - Remplacer l\'icône de l\'application - Utiliser le logo d\'Aliucord à la place de celui de Discord - Debuggable - Activer le drapeau de débogage - Nom de l\'application - Nom du paquet - Download Version Couleurs dynamiques - Remplacer libc++ (RN seulement) - Télécharger et utiliser libc++ à partir des hermes patchés Garder les APKs patchés Ne pas supprimer les APKs patchés après l\'installation (pour les installer manuellement) - Nom de paquet invalide, réinitialiser à com.aliucord Système Sombre Clair diff --git a/app/src/main/res/values-hi-rIN/strings.xml b/app/src/main/res/values-hi-rIN/strings.xml index 806a48c2..15c3c9ef 100644 --- a/app/src/main/res/values-hi-rIN/strings.xml +++ b/app/src/main/res/values-hi-rIN/strings.xml @@ -35,19 +35,9 @@ Appearance Developer options Clear cache - Replace app icon - Uses the Aliucord variant as opposed to Discord\'s own icon - Debuggable - Enable debuggable flag - App Name - Package Name - Download Version Dynamic color - Replace libc++ (RN only) - Downloads and uses libc++ from patched hermes Keep patched APKs Don\'t delete patched APKs after installing (for installing manually) - Invalid package name, reset to com.aliucord System Dark Light diff --git a/app/src/main/res/values-hu-rHU/strings.xml b/app/src/main/res/values-hu-rHU/strings.xml index 09d742d6..5726bb33 100644 --- a/app/src/main/res/values-hu-rHU/strings.xml +++ b/app/src/main/res/values-hu-rHU/strings.xml @@ -35,19 +35,9 @@ Appearance Developer options Clear cache - Replace app icon - Uses the Aliucord variant as opposed to Discord\'s own icon - Debuggable - Enable debuggable flag - App Name - Package Name - Download Version Dynamic color - Replace libc++ (RN only) - Downloads and uses libc++ from patched hermes Keep patched APKs Don\'t delete patched APKs after installing (for installing manually) - Invalid package name, reset to com.aliucord System Dark Light diff --git a/app/src/main/res/values-in-rID/strings.xml b/app/src/main/res/values-in-rID/strings.xml index 50c68044..d3976e33 100644 --- a/app/src/main/res/values-in-rID/strings.xml +++ b/app/src/main/res/values-in-rID/strings.xml @@ -35,19 +35,9 @@ Tampilan Opsi Pengembang Bersihkan cache - Ganti ikon aplikasi - Menggunakan varian Aliucord daripada ikon Discord sendiri - Dapat di-debug - Aktifkan flag debuggable - Nama Aplikasi - Nama Paket - Unduh Versi Warna dinamis - Gantikan libc++ (Untuk RN) - Unduh dan pakai libc++ dari hermes yang ditambal Simpan APK yang ditambal Jangan hapus APK yang sudah ditambal setelah memasang (untuk memasang secara manual) - Nama paket tidak valid, atur ulang ke com.aliucord Sistem Gelap Terang diff --git a/app/src/main/res/values-it-rIT/strings.xml b/app/src/main/res/values-it-rIT/strings.xml index ca79a7a0..c4e71546 100644 --- a/app/src/main/res/values-it-rIT/strings.xml +++ b/app/src/main/res/values-it-rIT/strings.xml @@ -35,19 +35,9 @@ Aspetto Opzioni sviluppatore Pulisci cache - Replace app icon - Uses the Aliucord variant as opposed to Discord\'s own icon - Debuggabile - Enable debuggable flag - App Name - Package Name - Download Version Dynamic color - Replace libc++ (RN only) - Downloads and uses libc++ from patched hermes Keep patched APKs Don\'t delete patched APKs after installing (for installing manually) - Invalid package name, reset to com.aliucord Sistema Scuro Chiaro diff --git a/app/src/main/res/values-iw-rIL/strings.xml b/app/src/main/res/values-iw-rIL/strings.xml index f1bbaa9b..0baf2700 100644 --- a/app/src/main/res/values-iw-rIL/strings.xml +++ b/app/src/main/res/values-iw-rIL/strings.xml @@ -35,19 +35,9 @@ Appearance Developer options Clear cache - Replace app icon - Uses the Aliucord variant as opposed to Discord\'s own icon - Debuggable - Enable debuggable flag - App Name - Package Name - Download Version Dynamic color - Replace libc++ (RN only) - Downloads and uses libc++ from patched hermes Keep patched APKs Don\'t delete patched APKs after installing (for installing manually) - Invalid package name, reset to com.aliucord System Dark Light diff --git a/app/src/main/res/values-ja-rJP/strings.xml b/app/src/main/res/values-ja-rJP/strings.xml index 4dbe8b21..0016ec82 100644 --- a/app/src/main/res/values-ja-rJP/strings.xml +++ b/app/src/main/res/values-ja-rJP/strings.xml @@ -36,19 +36,9 @@ 外観 開発者向けオプション キャッシュを消去 - アプリのアイコンを置き換える - DiscordのアイコンではなくAliucordのものを使用します - デバッグ - デバッグ可能フラグを有効にする - アプリ名 - パッケージ名 - ダウンロードバージョン ダイナミックカラー - libc++ を置き換え (RN のみ) - パッチを適用したヘルメスから libc++ をダウンロードして使用します パッチを適用した APK を維持 インストール後にパッチ適用された APK を削除しないでください(手動でインストールする場合) - 無効なパッケージ名です。com.aliucordにリセットしてください。 システム ダーク ライト diff --git a/app/src/main/res/values-kaa/strings.xml b/app/src/main/res/values-kaa/strings.xml index f2b98521..ba5aacbd 100644 --- a/app/src/main/res/values-kaa/strings.xml +++ b/app/src/main/res/values-kaa/strings.xml @@ -35,19 +35,9 @@ Sırtqı kórinis Developer options Clear cache - Replace app icon - Uses the Aliucord variant as opposed to Discord\'s own icon - Debuggable - Enable debuggable flag - Qosımsha ataması - Package Name - Download Version (RN only) Dynamic color - Replace libc++ (RN only) - Downloads and uses libc++ from patched hermes Keep patched APKs Don\'t delete patched APKs after installing (for installing manually) - Invalid package name, reset to com.aliucord System Qarańǵı Jaqtı diff --git a/app/src/main/res/values-ko-rKR/strings.xml b/app/src/main/res/values-ko-rKR/strings.xml index 46ae8c66..9d7c29e9 100644 --- a/app/src/main/res/values-ko-rKR/strings.xml +++ b/app/src/main/res/values-ko-rKR/strings.xml @@ -35,19 +35,9 @@ 외관 개발자 옵션 캐시 지우기 - 앱 아이콘 재배치 - Discord의 아이콘 대신 Aliucord의 아이콘을 사용해요 - 디버그 가능 - 디버그 가능 플래그를 사용해요 - 앱 이름 - 패키지 이름 - 다운로드 버전 동적 색상 - libc++ 대체(RN 전용) - 패치한 Herms에서 libc++를 다운로드하고 사용해요 패치된 APK 유지 설치 후 패치된 APK를 삭제하지 않아요 (수동 설치용) - 잘못된 패키지 이름이에요. com.aliucord로 초기화할게요 시스템 어두운 테마 밝은 테마 diff --git a/app/src/main/res/values-nl-rNL/strings.xml b/app/src/main/res/values-nl-rNL/strings.xml index 417cb5e8..e614496e 100644 --- a/app/src/main/res/values-nl-rNL/strings.xml +++ b/app/src/main/res/values-nl-rNL/strings.xml @@ -35,19 +35,9 @@ Appearance Developer options Clear cache - Replace app icon - Uses the Aliucord variant as opposed to Discord\'s own icon - Debuggable - Enable debuggable flag - App Name - Package Name - Download Versie (Alleen RN) Dynamic color - Replace libc++ (RN only) - Downloads and uses libc++ from patched hermes Keep patched APKs Don\'t delete patched APKs after installing (for installing manually) - Invalid package name, reset to com.aliucord System Dark Light diff --git a/app/src/main/res/values-no-rNO/strings.xml b/app/src/main/res/values-no-rNO/strings.xml index f1bbaa9b..0baf2700 100644 --- a/app/src/main/res/values-no-rNO/strings.xml +++ b/app/src/main/res/values-no-rNO/strings.xml @@ -35,19 +35,9 @@ Appearance Developer options Clear cache - Replace app icon - Uses the Aliucord variant as opposed to Discord\'s own icon - Debuggable - Enable debuggable flag - App Name - Package Name - Download Version Dynamic color - Replace libc++ (RN only) - Downloads and uses libc++ from patched hermes Keep patched APKs Don\'t delete patched APKs after installing (for installing manually) - Invalid package name, reset to com.aliucord System Dark Light diff --git a/app/src/main/res/values-pl-rPL/strings.xml b/app/src/main/res/values-pl-rPL/strings.xml index e0bb5162..cc1af7c7 100644 --- a/app/src/main/res/values-pl-rPL/strings.xml +++ b/app/src/main/res/values-pl-rPL/strings.xml @@ -35,19 +35,9 @@ Wygląd Opcje dla programistów Wyczyść pamięć podręczną - Zastąp ikonę aplikacji - Używa wariantu Aliucord w przeciwieństwie do ikony Discorda - Debugowalny - Włącz flagę debugowania - Nazwa aplikacji - Nazwa pakietu - Wersja do pobrania Kolor dynamiczny - Zastąp libc++ (tylko RN) - Downloads and uses libc++ from patched hermes Zachowaj zpatchowane APK Nie usuwaj skasowanych APK po instalacji (dla instalacji ręcznej) - Nieprawidłowa nazwa pakietu, przywrócono do com.aliucord System Ciemny Jasny diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml index abb07649..bf192c80 100644 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -35,19 +35,9 @@ Aparência Opções de desenvolvedor Limpar cache - Mudar ícone do aplicativo - Usa a logo do Aliucord ao invés do próprio ícone do Discord - Depurável - Habilitar sinal de depurável - Nome do App - Nome do pacote - Versão para download Cor dinâmica - Substituir libc++ (apenas RN) - Baixa e usa libc++ do pacote hermes Manter APKs patched Não excluir APKs patched após a instalação (para instalação manualmente) - Nome do pacote inválido, resetar para com.aliucord Sistema Escuro Claro diff --git a/app/src/main/res/values-pt-rPT/strings.xml b/app/src/main/res/values-pt-rPT/strings.xml index 35718526..205dfdd2 100644 --- a/app/src/main/res/values-pt-rPT/strings.xml +++ b/app/src/main/res/values-pt-rPT/strings.xml @@ -35,19 +35,9 @@ Aparência Opções de programador Limpar cache - Substituir ícone da aplicação - Uses the Aliucord variant as opposed to Discord\'s own icon - Debuggable - Enable debuggable flag - Nome da aplicação - Package Name - Download Version Cor dinâmica - Replace libc++ (RN only) - Downloads and uses libc++ from patched hermes Keep patched APKs Não apague APKs modificados após a sua instalação (para instalação manualmente) - Invalid package name, reset to com.aliucord Sistema Escuro Claro diff --git a/app/src/main/res/values-ro-rRO/strings.xml b/app/src/main/res/values-ro-rRO/strings.xml index e1fe8bbe..5b962971 100644 --- a/app/src/main/res/values-ro-rRO/strings.xml +++ b/app/src/main/res/values-ro-rRO/strings.xml @@ -35,19 +35,9 @@ Appearance Developer options Clear cache - Replace app icon - Uses the Aliucord variant as opposed to Discord\'s own icon - Debuggable - Enable debuggable flag - App Name - Package Name - Download Version Dynamic color - Replace libc++ (RN only) - Downloads and uses libc++ from patched hermes Keep patched APKs Don\'t delete patched APKs after installing (for installing manually) - Invalid package name, reset to com.aliucord System Dark Light diff --git a/app/src/main/res/values-ru-rRU/strings.xml b/app/src/main/res/values-ru-rRU/strings.xml index 37fb40e7..92987882 100644 --- a/app/src/main/res/values-ru-rRU/strings.xml +++ b/app/src/main/res/values-ru-rRU/strings.xml @@ -35,19 +35,9 @@ Внешний вид Настройки для разработчиков Очистить кеш - Заменить иконку приложения - Использовать вариант Aliucord вместо Discord - Отладка - Включение флага для откладки - Название приложения - Название пакета - Загружаемая версия Динамические цвета - Заменить libc++ (только RN) - Скачивает и использует libc++ из пропатченного hermes Сохранять пропатченные пакеты Не удалять пропатченные пакеты после установки (для ручной установки) - Неправильное название пакета, сброс на com.aliucord Системная Тёмная Светлая diff --git a/app/src/main/res/values-sr-rSP/strings.xml b/app/src/main/res/values-sr-rSP/strings.xml index f1bbaa9b..0baf2700 100644 --- a/app/src/main/res/values-sr-rSP/strings.xml +++ b/app/src/main/res/values-sr-rSP/strings.xml @@ -35,19 +35,9 @@ Appearance Developer options Clear cache - Replace app icon - Uses the Aliucord variant as opposed to Discord\'s own icon - Debuggable - Enable debuggable flag - App Name - Package Name - Download Version Dynamic color - Replace libc++ (RN only) - Downloads and uses libc++ from patched hermes Keep patched APKs Don\'t delete patched APKs after installing (for installing manually) - Invalid package name, reset to com.aliucord System Dark Light diff --git a/app/src/main/res/values-sv-rSE/strings.xml b/app/src/main/res/values-sv-rSE/strings.xml index f1bbaa9b..0baf2700 100644 --- a/app/src/main/res/values-sv-rSE/strings.xml +++ b/app/src/main/res/values-sv-rSE/strings.xml @@ -35,19 +35,9 @@ Appearance Developer options Clear cache - Replace app icon - Uses the Aliucord variant as opposed to Discord\'s own icon - Debuggable - Enable debuggable flag - App Name - Package Name - Download Version Dynamic color - Replace libc++ (RN only) - Downloads and uses libc++ from patched hermes Keep patched APKs Don\'t delete patched APKs after installing (for installing manually) - Invalid package name, reset to com.aliucord System Dark Light diff --git a/app/src/main/res/values-tr-rTR/strings.xml b/app/src/main/res/values-tr-rTR/strings.xml index e92d1272..279941b4 100644 --- a/app/src/main/res/values-tr-rTR/strings.xml +++ b/app/src/main/res/values-tr-rTR/strings.xml @@ -35,19 +35,9 @@ Görünüm Geliştirici seçenekleri Önbelleği temizle - Uygulama simgesini değiştir - Discord\'un simgesi yerine Aliucord varyant\'ını kullanır - Hata ayıklanabilir - Hata ayıklanabilir seçeneğini etkinleştir - Uygulama Adı - Paket İsmi - Sürümü İndir Dinamik renk - Replace libc++ (RN only) - Downloads and uses libc++ from patched hermes Keep patched APKs Don\'t delete patched APKs after installing (for installing manually) - Geçersiz paket ismi, com.aliucord\'a sıfırlayın Sistem Koyu Açık diff --git a/app/src/main/res/values-uk-rUA/strings.xml b/app/src/main/res/values-uk-rUA/strings.xml index f1bbaa9b..0baf2700 100644 --- a/app/src/main/res/values-uk-rUA/strings.xml +++ b/app/src/main/res/values-uk-rUA/strings.xml @@ -35,19 +35,9 @@ Appearance Developer options Clear cache - Replace app icon - Uses the Aliucord variant as opposed to Discord\'s own icon - Debuggable - Enable debuggable flag - App Name - Package Name - Download Version Dynamic color - Replace libc++ (RN only) - Downloads and uses libc++ from patched hermes Keep patched APKs Don\'t delete patched APKs after installing (for installing manually) - Invalid package name, reset to com.aliucord System Dark Light diff --git a/app/src/main/res/values-vi-rVN/strings.xml b/app/src/main/res/values-vi-rVN/strings.xml index 29f63d0a..6126117a 100644 --- a/app/src/main/res/values-vi-rVN/strings.xml +++ b/app/src/main/res/values-vi-rVN/strings.xml @@ -35,19 +35,9 @@ Giao diện Tùy chọn nhà phát triển Xoá bộ nhớ đệm - Thay thế biểu tượng ứng dụng - Sử dụng biểu tượng Aliucord thay thế biểu tượng riêng của Discord - Gỡ lỗi - Kích hoạt tùy chọn gỡ lỗi - Tên ứng dụng - Tên gói - Tải xuống phiên bản Màu động - Thay thế libc++ (Dành cho RN) - Tải xuống và sử dụng libc++ từ hermes Giữ lại các bản vá APKs Không xóa bỏ các bản vá APKs sau khi cài đặt (dành cho cài đặt thủ công) - Tên gói không hợp lệ, đặt lại thành com.aliucord Hệ thống Tối Sáng diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index dd2176bc..314679ef 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -35,19 +35,9 @@ 外觀 開發人員選項 清除快取 - 更換應用程示圖示 - 使用 Aliucord 樣式而不是 Discord 自己的圖示 - 除錯 - 開啟除錯模式 - 應用程式名稱 - Package 名稱 - 下載版本 動態色彩 - 代替 libc++(僅限 RN) - 從安裝補丁的 hermes 下載並使用 libc++ 保持補丁 APKs 安裝後不刪除已安裝補丁的 APK(用於手動安裝) - 無效的 Package 名稱,將重設為 com.aliucord 跟隨系統 深色模式 淺色模式 diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index 7decc1f2..d70bc764 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -35,19 +35,9 @@ 外觀 開發人員選項 清除快取 - 更換應用程示圖示 - 使用 Aliucord 樣式而不是 Discord 自己的圖示 - 除錯 - 開啟除錯模式 - 應用程式名稱 - Package 名稱 - 下載版本 動態色彩 - 代替 libc++(僅限 RN) - 從安裝補丁的 hermes 下載並使用 libc++ 保持補丁 APKs 安裝後不刪除已安裝補丁的 APK(用於手動安裝) - 無效的 Package 名稱,將重設為 com.aliucord 跟隨系統 深色模式 淺色模式 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 0de92053..8da966f7 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -13,11 +13,12 @@ Apply Confirm Dismiss + Install + Uninstall Add Installation Update Clear Launch - Uninstall Close Open settings Search @@ -28,6 +29,7 @@ Cleared cache! Exit anyways Open info + Reset to default Grant Permissions In order for Aliucord Manager to function, file permissions are required. Since shared data is stored in ~/Aliucord, permissions are required in order to access it. @@ -39,19 +41,9 @@ Appearance Developer options Clear cache - Replace app icon - Uses the Aliucord variant as opposed to Discord\'s own icon - Debuggable - Enable debuggable flag - App Name - Package Name - Download Version (RN only) Dynamic color - Replace libc++ (RN only) - Downloads and uses libc++ from patched hermes Keep patched APKs Don\'t delete patched APKs after installing (for installing manually) - Invalid package name, reset to com.aliucord System Dark @@ -114,6 +106,7 @@ Downloading Aliuhook library Copying dependencies Patching apk manifests + Patching app icon Adding Aliucord injector Adding Aliuhook library Aligning APKs @@ -137,4 +130,19 @@ Download failed (Invalid response) Download failed (File exists) Download failed (Insufficient space) + + Aliucord provides several customizations at installation time that are not able to be changed once installed. + Package Name + The package name is a unique identifier for all apps. Using different ones can allow for multiple installations of Aliucord. + Invalid package name! + Target app will be overwritten! + Valid package name! + App Name + The app name is what\'s displayed in your home launcher. This should be changed on secondary installations for ease of use. + Debuggable + Enable the debuggable manifest flag. Only use this if you know what you are doing! + Replace app icon + Changes the app\'s icon to use Aliucord branding instead of Discord\'s own. + Basic + Advanced