From 3bed58d5f07541f2783b59e03572f73ce647ef24 Mon Sep 17 00:00:00 2001
From: Ivan Iskandar <12537387+ivaniskandar@users.noreply.github.com>
Date: Mon, 28 Nov 2022 21:21:18 +0700
Subject: [PATCH] Complete Settings migration to Voyager (#8639)

Now the Controller wrapper can be yeeted anytime

(cherry picked from commit bcc21e55bd226811ba14fbc6c1009a91f5c891fc)
---
 .../eu/kanade/presentation/util/Constants.kt  | 17 ++++
 .../tachiyomi/ui/category/CategoryScreen.kt   | 13 ++-
 .../ui/setting/SettingsMainController.kt      | 84 ++----------------
 .../tachiyomi/ui/setting/SettingsScreen.kt    | 87 +++++++++++++++++++
 4 files changed, 123 insertions(+), 78 deletions(-)
 create mode 100644 app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsScreen.kt

diff --git a/app/src/main/java/eu/kanade/presentation/util/Constants.kt b/app/src/main/java/eu/kanade/presentation/util/Constants.kt
index 651ad0853..c3b0243dc 100644
--- a/app/src/main/java/eu/kanade/presentation/util/Constants.kt
+++ b/app/src/main/java/eu/kanade/presentation/util/Constants.kt
@@ -1,5 +1,10 @@
 package eu.kanade.presentation.util
 
+import androidx.compose.animation.ExitTransition
+import androidx.compose.animation.core.LinearEasing
+import androidx.compose.animation.core.tween
+import androidx.compose.animation.fadeIn
+import androidx.compose.animation.with
 import androidx.compose.foundation.layout.PaddingValues
 import androidx.compose.material3.MaterialTheme
 import androidx.compose.ui.unit.dp
@@ -24,3 +29,15 @@ class Padding {
 
 val MaterialTheme.padding: Padding
     get() = Padding()
+
+object Transition {
+
+    /**
+     * Mimics [eu.kanade.tachiyomi.ui.base.controller.OneWayFadeChangeHandler]
+     */
+    val OneWayFade = fadeIn(
+        animationSpec = tween(
+            easing = LinearEasing,
+        ),
+    ) with ExitTransition.None
+}
diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/category/CategoryScreen.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/category/CategoryScreen.kt
index 4531767f0..62c600734 100644
--- a/app/src/main/java/eu/kanade/tachiyomi/ui/category/CategoryScreen.kt
+++ b/app/src/main/java/eu/kanade/tachiyomi/ui/category/CategoryScreen.kt
@@ -8,6 +8,8 @@ import androidx.compose.ui.platform.LocalContext
 import androidx.compose.ui.res.stringResource
 import cafe.adriel.voyager.core.model.rememberScreenModel
 import cafe.adriel.voyager.core.screen.Screen
+import cafe.adriel.voyager.core.screen.uniqueScreenKey
+import cafe.adriel.voyager.navigator.LocalNavigator
 import cafe.adriel.voyager.navigator.currentOrThrow
 import eu.kanade.presentation.category.CategoryScreen
 import eu.kanade.presentation.category.components.CategoryCreateDialog
@@ -21,10 +23,14 @@ import kotlinx.coroutines.flow.collectLatest
 
 class CategoryScreen : Screen {
 
+    // Fix certain crash when wrapped inside a Controller
+    override val key = uniqueScreenKey
+
     @Composable
     override fun Content() {
         val context = LocalContext.current
         val router = LocalRouter.currentOrThrow
+        val navigator = LocalNavigator.currentOrThrow
         val screenModel = rememberScreenModel { CategoryScreenModel() }
 
         val state by screenModel.state.collectAsState()
@@ -43,7 +49,12 @@ class CategoryScreen : Screen {
             onClickDelete = { screenModel.showDialog(CategoryDialog.Delete(it)) },
             onClickMoveUp = screenModel::moveUp,
             onClickMoveDown = screenModel::moveDown,
-            navigateUp = router::popCurrentController,
+            navigateUp = {
+                when {
+                    navigator.canPop -> navigator.pop()
+                    router.backstackSize > 1 -> router.handleBack()
+                }
+            },
         )
 
         when (val dialog = successState.dialog) {
diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsMainController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsMainController.kt
index 18fbfbbc7..35961763a 100644
--- a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsMainController.kt
+++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsMainController.kt
@@ -1,95 +1,25 @@
 package eu.kanade.tachiyomi.ui.setting
 
 import android.os.Bundle
-import androidx.compose.animation.ExitTransition
-import androidx.compose.animation.core.LinearEasing
-import androidx.compose.animation.core.tween
-import androidx.compose.animation.fadeIn
-import androidx.compose.animation.with
 import androidx.compose.runtime.Composable
-import androidx.compose.runtime.CompositionLocalProvider
-import androidx.compose.runtime.remember
-import androidx.compose.ui.platform.LocalConfiguration
 import androidx.core.os.bundleOf
 import cafe.adriel.voyager.navigator.Navigator
-import cafe.adriel.voyager.transitions.ScreenTransition
-import eu.kanade.presentation.components.TwoPanelBox
-import eu.kanade.presentation.more.settings.screen.AboutScreen
-import eu.kanade.presentation.more.settings.screen.SettingsBackupScreen
-import eu.kanade.presentation.more.settings.screen.SettingsGeneralScreen
-import eu.kanade.presentation.more.settings.screen.SettingsMainScreen
-import eu.kanade.presentation.util.LocalBackPress
-import eu.kanade.presentation.util.LocalRouter
 import eu.kanade.tachiyomi.ui.base.controller.BasicFullComposeController
-import eu.kanade.tachiyomi.util.system.isTabletUi
 
 class SettingsMainController(bundle: Bundle = bundleOf()) : BasicFullComposeController(bundle) {
 
     private val toBackupScreen = args.getBoolean(TO_BACKUP_SCREEN)
     private val toAboutScreen = args.getBoolean(TO_ABOUT_SCREEN)
 
-    /**
-     * Mimics [eu.kanade.tachiyomi.ui.base.controller.OneWayFadeChangeHandler]
-     */
-    private val transition = fadeIn(
-        animationSpec = tween(
-            easing = LinearEasing,
-        ),
-    ) with ExitTransition.None
-
     @Composable
     override fun ComposeContent() {
-        CompositionLocalProvider(LocalRouter provides router) {
-            val configuration = LocalConfiguration.current
-            val isTabletUi = remember { configuration.isTabletUi() } // won't survive config change
-            if (!isTabletUi) {
-                Navigator(
-                    screen = if (toBackupScreen) {
-                        SettingsBackupScreen
-                    } else if (toAboutScreen) {
-                        AboutScreen
-                    } else {
-                        SettingsMainScreen
-                    },
-                    content = {
-                        CompositionLocalProvider(LocalBackPress provides this::back) {
-                            ScreenTransition(
-                                navigator = it,
-                                transition = { transition },
-                            )
-                        }
-                    },
-                )
-            } else {
-                Navigator(
-                    screen = if (toBackupScreen) {
-                        SettingsBackupScreen
-                    } else if (toAboutScreen) {
-                        AboutScreen
-                    } else {
-                        SettingsGeneralScreen
-                    },
-                ) {
-                    TwoPanelBox(
-                        startContent = {
-                            CompositionLocalProvider(LocalBackPress provides this@SettingsMainController::back) {
-                                SettingsMainScreen.Content(twoPane = true)
-                            }
-                        },
-                        endContent = {
-                            ScreenTransition(
-                                navigator = it,
-                                transition = { transition },
-                            )
-                        },
-                    )
-                }
-            }
-        }
-    }
-
-    private fun back() {
-        activity?.onBackPressed()
+        Navigator(
+            screen = when {
+                toBackupScreen -> SettingsScreen.toBackupScreen()
+                toAboutScreen -> SettingsScreen.toAboutScreen()
+                else -> SettingsScreen.toMainScreen()
+            },
+        )
     }
 
     companion object {
diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsScreen.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsScreen.kt
new file mode 100644
index 000000000..efb4b5c94
--- /dev/null
+++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsScreen.kt
@@ -0,0 +1,87 @@
+package eu.kanade.tachiyomi.ui.setting
+
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.CompositionLocalProvider
+import cafe.adriel.voyager.core.screen.Screen
+import cafe.adriel.voyager.navigator.LocalNavigator
+import cafe.adriel.voyager.navigator.Navigator
+import cafe.adriel.voyager.navigator.currentOrThrow
+import cafe.adriel.voyager.transitions.ScreenTransition
+import eu.kanade.presentation.components.TwoPanelBox
+import eu.kanade.presentation.more.settings.screen.AboutScreen
+import eu.kanade.presentation.more.settings.screen.SettingsBackupScreen
+import eu.kanade.presentation.more.settings.screen.SettingsGeneralScreen
+import eu.kanade.presentation.more.settings.screen.SettingsMainScreen
+import eu.kanade.presentation.util.LocalBackPress
+import eu.kanade.presentation.util.LocalRouter
+import eu.kanade.presentation.util.Transition
+import eu.kanade.presentation.util.isTabletUi
+
+class SettingsScreen private constructor(
+    val toBackup: Boolean,
+    val toAbout: Boolean,
+) : Screen {
+
+    @Composable
+    override fun Content() {
+        val router = LocalRouter.currentOrThrow
+        val navigator = LocalNavigator.currentOrThrow
+        if (!isTabletUi()) {
+            val back: () -> Unit = {
+                when {
+                    navigator.canPop -> navigator.pop()
+                    router.backstackSize > 1 -> router.handleBack()
+                }
+            }
+            Navigator(
+                screen = if (toBackup) {
+                    SettingsBackupScreen
+                } else if (toAbout) {
+                    AboutScreen
+                } else {
+                    SettingsMainScreen
+                },
+                content = {
+                    CompositionLocalProvider(LocalBackPress provides back) {
+                        ScreenTransition(
+                            navigator = it,
+                            transition = { Transition.OneWayFade },
+                        )
+                    }
+                },
+            )
+        } else {
+            Navigator(
+                screen = if (toBackup) {
+                    SettingsBackupScreen
+                } else if (toAbout) {
+                    AboutScreen
+                } else {
+                    SettingsGeneralScreen
+                },
+            ) {
+                TwoPanelBox(
+                    startContent = {
+                        CompositionLocalProvider(LocalBackPress provides router::popCurrentController) {
+                            SettingsMainScreen.Content(twoPane = true)
+                        }
+                    },
+                    endContent = {
+                        ScreenTransition(
+                            navigator = it,
+                            transition = { Transition.OneWayFade },
+                        )
+                    },
+                )
+            }
+        }
+    }
+
+    companion object {
+        fun toMainScreen() = SettingsScreen(toBackup = false, toAbout = false)
+
+        fun toBackupScreen() = SettingsScreen(toBackup = true, toAbout = false)
+
+        fun toAboutScreen() = SettingsScreen(toBackup = false, toAbout = true)
+    }
+}