diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 8e0c20a..73f2a7a 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -160,6 +160,7 @@ dependencies { implementation(libs.microg) implementation(libs.smali) implementation(libs.baksmali) + implementation(libs.compose.pipette) implementation(libs.compose.shimmer) implementation(variantOf(libs.zip) { artifactType("aar") }) } diff --git a/app/src/main/kotlin/com/aliucord/manager/MainActivity.kt b/app/src/main/kotlin/com/aliucord/manager/MainActivity.kt index bb2defe..573986b 100644 --- a/app/src/main/kotlin/com/aliucord/manager/MainActivity.kt +++ b/app/src/main/kotlin/com/aliucord/manager/MainActivity.kt @@ -22,6 +22,7 @@ import com.aliucord.manager.manager.PreferencesManager import com.aliucord.manager.ui.components.* import com.aliucord.manager.ui.components.dialogs.StoragePermissionsDialog import com.aliucord.manager.ui.screens.home.HomeScreen +import com.aliucord.manager.ui.screens.iconopts.IconOptionsScreen import com.aliucord.manager.ui.screens.patching.PatchingScreen import com.aliucord.manager.ui.screens.patchopts.PatchOptionsScreen import com.aliucord.manager.ui.widgets.updater.UpdaterDialog @@ -77,6 +78,12 @@ class MainActivity : ComponentActivity() { // Going from InstallOptions -> Install initialState is PatchOptionsScreen && targetState is PatchingScreen -> slideInHorizontally { it * 2 } + fadeIn togetherWith fadeOut + // Going from PatchOptions -> IconOptions + initialState is PatchOptionsScreen && targetState is IconOptionsScreen -> + slideInHorizontally { it * 2 } + fadeIn togetherWith fadeOut + // Going from IconOptions -> PatchOptions + initialState is IconOptionsScreen && targetState is PatchOptionsScreen -> + fadeIn togetherWith slideOutHorizontally { it * 2 } + fadeOut // Going from Install -> InstallOptions initialState is PatchingScreen && targetState is PatchOptionsScreen -> fadeIn togetherWith slideOutHorizontally { it * 2 } + fadeOut diff --git a/app/src/main/kotlin/com/aliucord/manager/ui/previews/screens/PatchOptionsScreenPreview.kt b/app/src/main/kotlin/com/aliucord/manager/ui/previews/screens/PatchOptionsScreenPreview.kt index 0a821da..b5dd7bb 100644 --- a/app/src/main/kotlin/com/aliucord/manager/ui/previews/screens/PatchOptionsScreenPreview.kt +++ b/app/src/main/kotlin/com/aliucord/manager/ui/previews/screens/PatchOptionsScreenPreview.kt @@ -21,8 +21,7 @@ private fun PatchOptionsScreenPreview( isDevMode = parameters.isDevMode, debuggable = parameters.debuggable, setDebuggable = {}, - replaceIcon = parameters.replaceIcon, - setReplaceIcon = {}, + onOpenIconOptions = {}, appName = parameters.appName, appNameIsError = parameters.appNameIsError, setAppName = {}, @@ -39,7 +38,6 @@ private data class PatchOptionsParameters( val isUpdate: Boolean, val isDevMode: Boolean, val debuggable: Boolean, - val replaceIcon: Boolean, val appName: String, val appNameIsError: Boolean, val packageName: String, @@ -54,7 +52,6 @@ private class PatchOptionsParametersProvider : PreviewParameterProvider Unit, +) { + Scaffold( + topBar = { IconOptionsAppBar() }, + ) { paddingValues -> + Column( + verticalArrangement = Arrangement.spacedBy(20.dp), + horizontalAlignment = Alignment.CenterHorizontally, + modifier = Modifier + .fillMaxSize() + .verticalScroll(rememberScrollState()) + .padding(paddingValues) + .padding(horizontal = 20.dp, vertical = 20.dp) + ) { + CircularColorPicker( + color = selectedColor, + onColorChange = setSelectedColor, + modifier = Modifier.size(250.dp) + ) + } + } +} diff --git a/app/src/main/kotlin/com/aliucord/manager/ui/screens/iconopts/components/IconOptionsAppBar.kt b/app/src/main/kotlin/com/aliucord/manager/ui/screens/iconopts/components/IconOptionsAppBar.kt new file mode 100644 index 0000000..a60dc03 --- /dev/null +++ b/app/src/main/kotlin/com/aliucord/manager/ui/screens/iconopts/components/IconOptionsAppBar.kt @@ -0,0 +1,29 @@ +package com.aliucord.manager.ui.screens.iconopts.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 IconOptionsAppBar() { + TopAppBar( + navigationIcon = { BackButton() }, + title = { Text(stringResource(R.string.iconopts_screen_title)) }, + 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/patching/PatchingScreen.kt b/app/src/main/kotlin/com/aliucord/manager/ui/screens/patching/PatchingScreen.kt index c50beec..571c395 100644 --- a/app/src/main/kotlin/com/aliucord/manager/ui/screens/patching/PatchingScreen.kt +++ b/app/src/main/kotlin/com/aliucord/manager/ui/screens/patching/PatchingScreen.kt @@ -59,7 +59,7 @@ class PatchingScreen(private val data: PatchOptions) : Screen, Parcelable { val state by model.state.collectAsState() val listState = rememberLazyListState() - val showMinimizationWarning = remember { !context.isIgnoringBatteryOptimizations() } + val showMinimizationWarning = rememberSaveable { !context.isIgnoringBatteryOptimizations() } // Exit warning dialog (dismiss itself if install process state changes, esp. for Success) var showAbortWarning by rememberSaveable(model.state.collectAsState().value) { mutableStateOf(false) } 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 956c95b..3558f40 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 @@ -41,14 +41,6 @@ class PatchOptionsModel( appNameIsError = newAppName.length !in (1..150) } - // ---------- Icon patching state ---------- - var replaceIcon by mutableStateOf(prefilledOptions.iconReplacement == PatchOptions.IconReplacement.Aliucord) - private set - - fun changeReplaceIcon(value: Boolean) { - replaceIcon = value - } - // ---------- Debuggable state ---------- var debuggable by mutableStateOf(prefilledOptions.debuggable) private set @@ -75,7 +67,7 @@ class PatchOptionsModel( packageName = packageName, debuggable = debuggable, // TODO: advanced icon options - iconReplacement = if (replaceIcon) PatchOptions.IconReplacement.Aliucord else PatchOptions.IconReplacement.Original, + iconReplacement = PatchOptions.IconReplacement.Aliucord, ) } 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 ba46288..0e0c336 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 @@ -1,16 +1,18 @@ package com.aliucord.manager.ui.screens.patchopts import android.os.Parcelable +import androidx.compose.foundation.* +import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.layout.* -import androidx.compose.foundation.rememberScrollState -import androidx.compose.foundation.verticalScroll import androidx.compose.material3.* import androidx.compose.runtime.* +import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource +import androidx.compose.ui.semantics.Role import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import cafe.adriel.voyager.core.screen.Screen @@ -21,12 +23,13 @@ import com.aliucord.manager.R import com.aliucord.manager.ui.components.TextDivider import com.aliucord.manager.ui.components.dialogs.NetworkWarningDialog import com.aliucord.manager.ui.components.dialogs.UnknownSourcesPermissionDialog +import com.aliucord.manager.ui.screens.iconopts.IconOptionsScreen import com.aliucord.manager.ui.screens.patching.PatchingScreen import com.aliucord.manager.ui.screens.patchopts.components.PackageNameStateLabel import com.aliucord.manager.ui.screens.patchopts.components.PatchOptionsAppBar -import com.aliucord.manager.ui.screens.patchopts.components.options.SwitchPatchOption -import com.aliucord.manager.ui.screens.patchopts.components.options.TextPatchOption -import com.aliucord.manager.ui.util.* +import com.aliucord.manager.ui.screens.patchopts.components.options.* +import com.aliucord.manager.ui.util.InstallNotifications +import com.aliucord.manager.ui.util.spacedByLastAtBottom import com.aliucord.manager.util.isIgnoringBatteryOptimizations import com.aliucord.manager.util.requestNoBatteryOptimizations import kotlinx.coroutines.delay @@ -58,7 +61,7 @@ class PatchOptionsScreen( context.requestNoBatteryOptimizations() } - var showNetworkWarningDialog by remember { mutableStateOf(model.isNetworkDangerous()) } + var showNetworkWarningDialog by rememberSaveable { mutableStateOf(model.isNetworkDangerous()) } if (showNetworkWarningDialog) { NetworkWarningDialog( onConfirm = { showNetworkWarningDialog = false }, @@ -78,8 +81,8 @@ class PatchOptionsScreen( debuggable = model.debuggable, setDebuggable = model::changeDebuggable, - replaceIcon = model.replaceIcon, - setReplaceIcon = model::changeReplaceIcon, + // TODO: actual filled in options + onOpenIconOptions = { navigator.push(IconOptionsScreen(PatchOptions.Default.iconReplacement)) }, appName = model.appName, appNameIsError = model.appNameIsError, @@ -103,8 +106,7 @@ fun PatchOptionsScreenContent( debuggable: Boolean, setDebuggable: (Boolean) -> Unit, - replaceIcon: Boolean, - setReplaceIcon: (Boolean) -> Unit, + onOpenIconOptions: () -> Unit, appName: String, appNameIsError: Boolean, @@ -137,14 +139,29 @@ fun PatchOptionsScreenContent( TextDivider(text = stringResource(R.string.patchopts_divider_basic)) - SwitchPatchOption( + IconPatchOption( icon = painterResource(R.drawable.ic_app_shortcut), name = stringResource(R.string.patchopts_icon_title), description = stringResource(R.string.patchopts_icon_desc), - value = replaceIcon, - onValueChange = setReplaceIcon, - modifier = Modifier.padding(bottom = 8.dp) - ) + modifier = Modifier + .fillMaxWidth() + .clickable( + interactionSource = remember(::MutableInteractionSource), + onClick = onOpenIconOptions, + indication = null, + role = Role.Switch, + ) + .padding(bottom = 8.dp), + ) { + // TODO: selected icon options preview + // Icon( + // painter = painterResource(R.drawable.ic_discord), + // contentDescription = null, + // modifier = Modifier + // .padding(start = 4.dp, end = 14.dp) + // .size(26.dp), + // ) + } val appNameIsDefault by remember { derivedStateOf { diff --git a/app/src/main/kotlin/com/aliucord/manager/ui/screens/patchopts/components/options/IconPatchOption.kt b/app/src/main/kotlin/com/aliucord/manager/ui/screens/patchopts/components/options/IconPatchOption.kt new file mode 100644 index 0000000..4da3296 --- /dev/null +++ b/app/src/main/kotlin/com/aliucord/manager/ui/screens/patchopts/components/options/IconPatchOption.kt @@ -0,0 +1,50 @@ +package com.aliucord.manager.ui.screens.patchopts.components.options + +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.painter.Painter +import androidx.compose.ui.unit.dp + +@Composable +fun IconPatchOption( + icon: Painter, + name: String, + description: String, + modifier: Modifier = Modifier, + content: @Composable RowScope.() -> Unit, +) { + Row( + horizontalArrangement = Arrangement.spacedBy(12.dp), + verticalAlignment = Alignment.CenterVertically, + modifier = modifier, + ) { + 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) + ) + } + + content() + } +} diff --git a/app/src/main/kotlin/com/aliucord/manager/ui/screens/patchopts/components/options/SwitchPatchOption.kt b/app/src/main/kotlin/com/aliucord/manager/ui/screens/patchopts/components/options/SwitchPatchOption.kt index a01f0c9..8dba945 100644 --- a/app/src/main/kotlin/com/aliucord/manager/ui/screens/patchopts/components/options/SwitchPatchOption.kt +++ b/app/src/main/kotlin/com/aliucord/manager/ui/screens/patchopts/components/options/SwitchPatchOption.kt @@ -2,13 +2,12 @@ package com.aliucord.manager.ui.screens.patchopts.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.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.Switch 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 @@ -26,9 +25,10 @@ fun SwitchPatchOption( val interactionSource = remember(::MutableInteractionSource) val onClick = remember(value) { { onValueChange(!value) } } - Row( - horizontalArrangement = Arrangement.spacedBy(12.dp), - verticalAlignment = Alignment.CenterVertically, + IconPatchOption( + icon = icon, + name = name, + description = description, modifier = modifier .fillMaxWidth() .clickable( @@ -39,29 +39,6 @@ fun SwitchPatchOption( 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, diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index a79a376..6dfaf1d 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -16,8 +16,8 @@ Dismiss Install Uninstall - New install - Update install + New Install + Update Install Update Clear Launch @@ -160,10 +160,12 @@ 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. + Change the app\'s icon to Aliucord\'s icon (or a custom one) instead of Discord\'s. Basic Advanced + Icon Replacement + Active installation Progress notifications sent during a minimized installation Aliucord installation ready! diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 9102890..7d291aa 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -13,6 +13,7 @@ coil = "3.1.0" compose = "1.7.7" compose-tracing = "1.7.7" compose-material3 = "1.3.1" +compose-pipette = "1.0.0-beta01" #diff = "4.12" koin = "4.0.2" kotlin = "2.1.10" @@ -53,6 +54,10 @@ compose-material3 = { module = "androidx.compose.material3:material3", version.r compose-ui-tooling-preview = { module = "androidx.compose.ui:ui-tooling-preview", version.ref = "compose" } compose-runtime-tracing = { module = "androidx.compose.runtime:runtime-tracing", version.ref = "compose-tracing" } +# Extra compose libs +compose-pipette = { module = "dev.zt64.compose.pipette:compose-pipette", version.ref = "compose-pipette" } +compose-shimmer = { module = "com.valentinilk.shimmer:compose-shimmer", version.ref = "shimmer" } + # Koin koin-android = { module = "io.insert-koin:koin-android", version.ref = "koin" } koin-compose = { module = "io.insert-koin:koin-androidx-compose", version.ref = "koin" } @@ -86,7 +91,6 @@ zip = { module = "io.github.diamondminer88:zip-android", version.ref = "zip" } # # Other microg = { module = "org.microg.gms:play-services-safetynet", version.ref = "microg" } -compose-shimmer = { module = "com.valentinilk.shimmer:compose-shimmer", version.ref = "shimmer" } [bundles] accompanist = [