From b9471f8d995134ab163b62958613f5de1e82084a Mon Sep 17 00:00:00 2001 From: rushiiMachine <33725716+rushiiMachine@users.noreply.github.com> Date: Fri, 7 Feb 2025 17:31:01 -0800 Subject: [PATCH] fix(Navigation): make all screens parcelizable This is to ensure state can be saved when minimizing the activity. --- .../com/aliucord/manager/MainActivity.kt | 71 ++++++++++--------- .../manager/ui/screens/about/AboutScreen.kt | 7 +- .../manager/ui/screens/home/HomeScreen.kt | 7 +- .../screens/patchopts/PatchOptionsScreen.kt | 7 +- .../ui/screens/plugins/PluginsScreen.kt | 7 +- .../ui/screens/settings/SettingsScreen.kt | 7 +- .../manager/ui/util/DiscordVersion.kt | 12 +++- 7 files changed, 78 insertions(+), 40 deletions(-) diff --git a/app/src/main/kotlin/com/aliucord/manager/MainActivity.kt b/app/src/main/kotlin/com/aliucord/manager/MainActivity.kt index ae6af91..bb2defe 100644 --- a/app/src/main/kotlin/com/aliucord/manager/MainActivity.kt +++ b/app/src/main/kotlin/com/aliucord/manager/MainActivity.kt @@ -12,9 +12,11 @@ import androidx.activity.compose.setContent import androidx.compose.animation.* import androidx.compose.animation.core.tween import androidx.compose.foundation.isSystemInDarkTheme +import androidx.compose.runtime.CompositionLocalProvider import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen import androidx.core.view.WindowCompat -import cafe.adriel.voyager.navigator.Navigator +import cafe.adriel.voyager.core.annotation.ExperimentalVoyagerApi +import cafe.adriel.voyager.navigator.* import cafe.adriel.voyager.transitions.ScreenTransition import com.aliucord.manager.manager.PreferencesManager import com.aliucord.manager.ui.components.* @@ -47,38 +49,43 @@ class MainActivity : ComponentActivity() { UpdaterDialog() } - Navigator( - screen = HomeScreen(), - onBackPressed = null, - ) { navigator -> - BackHandler { - navigator.back(this@MainActivity) - } - - ScreenTransition( - navigator = navigator, - transition = block@{ - val fadeIn = fadeIn(tween(durationMillis = 300)) - val fadeOut = fadeOut(tween(durationMillis = 750, delayMillis = 200)) - - when { - // Going from Home -> InstallOptions - initialState is HomeScreen && targetState is PatchOptionsScreen -> - slideInVertically { (it * 1.5).toInt() } + fadeIn togetherWith fadeOut - // Going from InstallOptions -> Home - initialState is PatchOptionsScreen && targetState is HomeScreen -> - fadeIn togetherWith slideOutVertically { it * 2 } + fadeOut - // Going from InstallOptions -> Install - initialState is PatchOptionsScreen && targetState is PatchingScreen -> - slideInHorizontally { it * 2 } + fadeIn togetherWith fadeOut - // Going from Install -> InstallOptions - initialState is PatchingScreen && targetState is PatchOptionsScreen -> - fadeIn togetherWith slideOutHorizontally { it * 2 } + fadeOut - - else -> fadeIn togetherWith fadeOut - } + @OptIn(ExperimentalVoyagerApi::class) + CompositionLocalProvider( + LocalNavigatorSaver provides parcelableNavigatorSaver(), + ) { + Navigator( + screen = HomeScreen(), + onBackPressed = null, + ) { navigator -> + BackHandler { + navigator.back(this@MainActivity) } - ) + + ScreenTransition( + navigator = navigator, + transition = block@{ + val fadeIn = fadeIn(tween(durationMillis = 300)) + val fadeOut = fadeOut(tween(durationMillis = 750, delayMillis = 200)) + + when { + // Going from Home -> InstallOptions + initialState is HomeScreen && targetState is PatchOptionsScreen -> + slideInVertically { (it * 1.5).toInt() } + fadeIn togetherWith fadeOut + // Going from InstallOptions -> Home + initialState is PatchOptionsScreen && targetState is HomeScreen -> + fadeIn togetherWith slideOutVertically { it * 2 } + fadeOut + // Going from InstallOptions -> Install + initialState is PatchOptionsScreen && targetState is PatchingScreen -> + slideInHorizontally { it * 2 } + fadeIn togetherWith fadeOut + // Going from Install -> InstallOptions + initialState is PatchingScreen && targetState is PatchOptionsScreen -> + fadeIn togetherWith slideOutHorizontally { it * 2 } + fadeOut + + else -> fadeIn togetherWith fadeOut + } + } + ) + } } } } diff --git a/app/src/main/kotlin/com/aliucord/manager/ui/screens/about/AboutScreen.kt b/app/src/main/kotlin/com/aliucord/manager/ui/screens/about/AboutScreen.kt index bdc8de6..44362a8 100644 --- a/app/src/main/kotlin/com/aliucord/manager/ui/screens/about/AboutScreen.kt +++ b/app/src/main/kotlin/com/aliucord/manager/ui/screens/about/AboutScreen.kt @@ -5,6 +5,7 @@ package com.aliucord.manager.ui.screens.about +import android.os.Parcelable import androidx.compose.foundation.clickable import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.layout.* @@ -28,8 +29,12 @@ import com.aliucord.manager.R import com.aliucord.manager.ui.components.* import com.aliucord.manager.ui.util.paddings.PaddingValuesSides import com.aliucord.manager.ui.util.paddings.exclude +import kotlinx.parcelize.IgnoredOnParcel +import kotlinx.parcelize.Parcelize -class AboutScreen : Screen { +@Parcelize +class AboutScreen : Screen, Parcelable { + @IgnoredOnParcel override val key = "About" @Composable 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 ce02a40..5a6724c 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 @@ -6,6 +6,7 @@ package com.aliucord.manager.ui.screens.home +import android.os.Parcelable import androidx.compose.animation.* import androidx.compose.foundation.layout.* import androidx.compose.foundation.lazy.LazyColumn @@ -33,9 +34,13 @@ import com.aliucord.manager.ui.screens.plugins.PluginsScreen import com.aliucord.manager.ui.util.DiscordVersion import com.aliucord.manager.ui.util.paddings.PaddingValuesSides import com.aliucord.manager.ui.util.paddings.exclude +import kotlinx.parcelize.IgnoredOnParcel +import kotlinx.parcelize.Parcelize import kotlin.math.* -class HomeScreen : Screen { +@Parcelize +class HomeScreen : Screen, Parcelable { + @IgnoredOnParcel override val key = "Home" @Composable 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 b4d4ccb..119403d 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,5 +1,6 @@ package com.aliucord.manager.ui.screens.patchopts +import android.os.Parcelable import androidx.compose.foundation.layout.* import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.verticalScroll @@ -31,12 +32,16 @@ import com.aliucord.manager.ui.util.* import com.aliucord.manager.util.isIgnoringBatteryOptimizations import com.aliucord.manager.util.requestNoBatteryOptimizations import kotlinx.coroutines.delay +import kotlinx.parcelize.IgnoredOnParcel +import kotlinx.parcelize.Parcelize import org.koin.core.parameter.parametersOf +@Parcelize class PatchOptionsScreen( private val prefilledOptions: PatchOptions = PatchOptions.Default, private val supportedVersion: DiscordVersion = DiscordVersion.None, -) : Screen { +) : Screen, Parcelable { + @IgnoredOnParcel override val key = "PatchOptions" @Composable diff --git a/app/src/main/kotlin/com/aliucord/manager/ui/screens/plugins/PluginsScreen.kt b/app/src/main/kotlin/com/aliucord/manager/ui/screens/plugins/PluginsScreen.kt index 1cbc006..e652802 100644 --- a/app/src/main/kotlin/com/aliucord/manager/ui/screens/plugins/PluginsScreen.kt +++ b/app/src/main/kotlin/com/aliucord/manager/ui/screens/plugins/PluginsScreen.kt @@ -5,6 +5,7 @@ package com.aliucord.manager.ui.screens.plugins +import android.os.Parcelable import androidx.compose.foundation.layout.* import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items @@ -29,8 +30,12 @@ import com.aliucord.manager.R import com.aliucord.manager.ui.components.BackButton import com.aliucord.manager.ui.screens.plugins.components.Changelog import com.aliucord.manager.ui.screens.plugins.components.PluginCard +import kotlinx.parcelize.IgnoredOnParcel +import kotlinx.parcelize.Parcelize -class PluginsScreen : Screen { +@Parcelize +class PluginsScreen : Screen, Parcelable { + @IgnoredOnParcel override val key = "Plugins" @Composable 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 dbad758..99b40c0 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,6 +5,7 @@ package com.aliucord.manager.ui.screens.settings +import android.os.Parcelable import androidx.compose.foundation.* import androidx.compose.foundation.layout.* import androidx.compose.material3.* @@ -23,8 +24,12 @@ import com.aliucord.manager.di.DownloaderSetting import com.aliucord.manager.ui.components.BackButton import com.aliucord.manager.ui.components.Theme import com.aliucord.manager.ui.components.settings.* +import kotlinx.parcelize.IgnoredOnParcel +import kotlinx.parcelize.Parcelize -class SettingsScreen : Screen { +@Parcelize +class SettingsScreen : Screen, Parcelable { + @IgnoredOnParcel override val key = "Settings" @Composable diff --git a/app/src/main/kotlin/com/aliucord/manager/ui/util/DiscordVersion.kt b/app/src/main/kotlin/com/aliucord/manager/ui/util/DiscordVersion.kt index 4327240..07f12e4 100644 --- a/app/src/main/kotlin/com/aliucord/manager/ui/util/DiscordVersion.kt +++ b/app/src/main/kotlin/com/aliucord/manager/ui/util/DiscordVersion.kt @@ -1,21 +1,27 @@ package com.aliucord.manager.ui.util +import android.os.Parcelable import androidx.compose.runtime.Composable import androidx.compose.runtime.Immutable import androidx.compose.ui.res.stringResource import com.aliucord.manager.R -import java.io.Serializable +import kotlinx.parcelize.Parcelize +@Parcelize @Immutable -sealed interface DiscordVersion : Comparable { +sealed interface DiscordVersion : Comparable, Parcelable { + @Parcelize data object Error : DiscordVersion + + @Parcelize data object None : DiscordVersion + @Parcelize data class Existing( val type: Type, val name: String, val code: Int, - ) : DiscordVersion, Serializable { + ) : DiscordVersion { val rawCode: Int get() = (code / 1000 * 100) + code % 100 }