Migrate ConfigureActivity to compose-destinations (#178)

* Add compose-destinations lib, prepare to drop fragment

* Move ConfigureActivity to compose destinations

* Restore navAnims

---------

Co-authored-by: Lokesh Gidra <lokeshgidra@google.com>
This commit is contained in:
nullArrayListandLokesh Gidra authored and GitHub committed 2023-11-02 11:40:13 +08:00
1 parent 9a220f89d9
commit 19e5636dd2
19 files changed
+187 -198

No files matched your search

+3
View File
@@ -209,6 +209,9 @@ dependencies {
api(platform(libs.compose.bom))
implementation(libs.bundles.compose)
implementation(libs.compose.destinations.core)
ksp(libs.compose.destinations.compiler)
implementation(libs.androidx.core)
implementation(libs.androidx.core.splashscreen)
@@ -1,5 +1,6 @@
package com.hippo.ehviewer.ui
import android.app.Activity
import android.os.Bundle
import androidx.compose.animation.AnimatedContentTransitionScope
import androidx.compose.animation.core.tween
@@ -7,120 +8,57 @@ import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.foundation.layout.imePadding
import androidx.compose.material3.windowsizeclass.calculateWindowSizeClass
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.SideEffect
import androidx.compose.runtime.compositionLocalOf
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.core.view.WindowCompat
import androidx.navigation.NavController
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.rememberNavController
import com.hippo.ehviewer.Settings
import com.hippo.ehviewer.client.EhCookieStore
import com.hippo.ehviewer.ui.login.CookieSignInScene
import com.hippo.ehviewer.ui.login.SelectSiteScreen
import com.hippo.ehviewer.ui.login.SignInScreen
import com.hippo.ehviewer.ui.login.WebViewSignInScreen
import com.hippo.ehviewer.ui.settings.AboutScreen
import com.hippo.ehviewer.ui.settings.AdvancedScreen
import com.hippo.ehviewer.ui.settings.BaseScreen
import com.hippo.ehviewer.ui.settings.DownloadScreen
import com.hippo.ehviewer.ui.settings.EhScreen
import com.hippo.ehviewer.ui.settings.FilterScreen
import com.hippo.ehviewer.ui.settings.LicenseScreen
import com.hippo.ehviewer.ui.settings.MyTagsScreen
import com.hippo.ehviewer.ui.settings.PrivacyScreen
import com.hippo.ehviewer.ui.settings.UConfigScreen
import com.hippo.ehviewer.ui.destinations.BaseScreenDestination
import com.hippo.ehviewer.ui.destinations.SelectSiteScreenDestination
import com.hippo.ehviewer.ui.destinations.SignInScreenDestination
import com.hippo.ehviewer.ui.tools.LocalWindowSizeClass
import com.hippo.ehviewer.util.findActivity
import com.ramcosta.composedestinations.DestinationsNavHost
import com.ramcosta.composedestinations.animations.defaults.RootNavGraphDefaultAnimations
import com.ramcosta.composedestinations.annotation.Destination
import com.ramcosta.composedestinations.rememberNavHostEngine
class ConfigureActivity : EhActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
WindowCompat.setDecorFitsSystemWindows(window, false)
val rootNavGraphDefaultAnimations = RootNavGraphDefaultAnimations(
enterTransition = { slideIntoContainer(AnimatedContentTransitionScope.SlideDirection.Up, tween(200)) },
exitTransition = { fadeOut(tween(200)) },
popEnterTransition = { fadeIn(tween(200)) },
popExitTransition = { slideOutOfContainer(AnimatedContentTransitionScope.SlideDirection.Down, tween(200)) },
)
setMD3Content {
val navController = rememberNavController()
val windowSizeClass = calculateWindowSizeClass(this)
CompositionLocalProvider(LocalNavController provides navController) {
NavHost(
navController = navController,
startDestination = if (Settings.needSignIn) {
if (EhCookieStore.hasSignedIn()) SELECT_SITE_ROUTE_NAME else SIGN_IN_ROUTE_NAME
} else {
BASE_SETTINGS_SCREEN
},
CompositionLocalProvider(LocalWindowSizeClass provides windowSizeClass) {
DestinationsNavHost(
navGraph = NavGraphs.root,
modifier = Modifier.imePadding(),
enterTransition = { slideIntoContainer(AnimatedContentTransitionScope.SlideDirection.Up, tween(200)) },
exitTransition = { fadeOut(tween(200)) },
popEnterTransition = { fadeIn(tween(200)) },
popExitTransition = { slideOutOfContainer(AnimatedContentTransitionScope.SlideDirection.Down, tween(200)) },
) {
composable(SIGN_IN_ROUTE_NAME) {
SignInScreen(windowSizeClass)
}
composable(WEBVIEW_SIGN_IN_ROUTE_NAME) {
WebViewSignInScreen()
}
composable(COOKIE_SIGN_IN_ROUTE_NAME) {
CookieSignInScene(windowSizeClass)
}
composable(SELECT_SITE_ROUTE_NAME) {
SelectSiteScreen()
}
composable(BASE_SETTINGS_SCREEN) {
BaseScreen()
}
composable(ABOUT_SETTINGS_SCREEN) {
AboutScreen()
}
composable(LICENSE_SCREEN) {
LicenseScreen()
}
composable(PRIVACY_SETTINGS_SCREEN) {
PrivacyScreen()
}
composable(ADVANCED_SETTINGS_SCREEN) {
AdvancedScreen()
}
composable(DOWNLOAD_SETTINGS_SCREEN) {
DownloadScreen()
}
composable(EH_SETTINGS_SCREEN) {
EhScreen()
}
composable(UCONFIG_SCREEN) {
UConfigScreen()
}
composable(MYTAGS_SCREEN) {
MyTagsScreen()
}
composable(FILTER_SCREEN) {
FilterScreen()
}
composable(FINISH_ROUTE_NAME) {
SideEffect {
finish()
}
}
}
startRoute = if (Settings.needSignIn) {
if (EhCookieStore.hasSignedIn()) SelectSiteScreenDestination else SignInScreenDestination
} else {
BaseScreenDestination
},
engine = rememberNavHostEngine(rootDefaultAnimations = rootNavGraphDefaultAnimations),
)
}
}
}
}
val LocalNavController = compositionLocalOf<NavController> { error("CompositionLocal LocalNavController not present!") }
const val BASE_SETTINGS_SCREEN = "Base"
const val EH_SETTINGS_SCREEN = "Eh"
const val DOWNLOAD_SETTINGS_SCREEN = "Download"
const val PRIVACY_SETTINGS_SCREEN = "Privacy"
const val ADVANCED_SETTINGS_SCREEN = "Advanced"
const val ABOUT_SETTINGS_SCREEN = "About"
const val LICENSE_SCREEN = "License"
const val UCONFIG_SCREEN = "UConfig"
const val MYTAGS_SCREEN = "Mytags"
const val FILTER_SCREEN = "Filter"
const val SIGN_IN_ROUTE_NAME = "SignIn"
const val WEBVIEW_SIGN_IN_ROUTE_NAME = "WebViewSignIn"
const val COOKIE_SIGN_IN_ROUTE_NAME = "CookieSignIn"
const val SELECT_SITE_ROUTE_NAME = "SelectSite"
const val FINISH_ROUTE_NAME = "Finish"
@Destination
@Composable
fun Finish() {
val context = LocalContext.current
SideEffect {
context.findActivity<Activity>().finish()
}
}
@@ -28,7 +28,6 @@ import androidx.compose.material3.SnackbarHost
import androidx.compose.material3.SnackbarHostState
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.material3.windowsizeclass.WindowSizeClass
import androidx.compose.material3.windowsizeclass.WindowWidthSizeClass
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
@@ -56,11 +55,13 @@ import com.hippo.ehviewer.client.EhCookieStore
import com.hippo.ehviewer.client.EhEngine
import com.hippo.ehviewer.client.EhUrl
import com.hippo.ehviewer.client.EhUtils
import com.hippo.ehviewer.ui.FINISH_ROUTE_NAME
import com.hippo.ehviewer.ui.LocalNavController
import com.hippo.ehviewer.ui.SELECT_SITE_ROUTE_NAME
import com.hippo.ehviewer.ui.destinations.FinishDestination
import com.hippo.ehviewer.ui.destinations.SelectSiteScreenDestination
import com.hippo.ehviewer.ui.tools.LocalDialogState
import com.hippo.ehviewer.ui.tools.LocalWindowSizeClass
import com.hippo.ehviewer.util.ExceptionUtils
import com.ramcosta.composedestinations.annotation.Destination
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
import eu.kanade.tachiyomi.util.lang.launchIO
import eu.kanade.tachiyomi.util.lang.withNonCancellableContext
import eu.kanade.tachiyomi.util.lang.withUIContext
@@ -69,9 +70,10 @@ import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
import okhttp3.Cookie
@Destination
@Composable
fun CookieSignInScene(windowSizeClass: WindowSizeClass) {
val navController = LocalNavController.current
fun CookieSignInScene(navigator: DestinationsNavigator) {
val windowSizeClass = LocalWindowSizeClass.current
val clipboardManager = LocalClipboardManager.current
val focusManager = LocalFocusManager.current
val snackbarHostState = remember { SnackbarHostState() }
@@ -124,7 +126,7 @@ fun CookieSignInScene(windowSizeClass: WindowSizeClass) {
EhEngine.getProfile()
}.onSuccess {
val canEx = withNonCancellableContext { postLogin() }
withUIContext { navController.navigate(if (canEx) SELECT_SITE_ROUTE_NAME else FINISH_ROUTE_NAME) }
withUIContext { navigator.navigate(if (canEx) SelectSiteScreenDestination else FinishDestination) }
}.onFailure {
EhCookieStore.signOut()
dialogState.awaitPermissionOrCancel(
@@ -29,13 +29,14 @@ import androidx.compose.ui.unit.dp
import com.hippo.ehviewer.R
import com.hippo.ehviewer.Settings
import com.hippo.ehviewer.client.EhUrl
import com.hippo.ehviewer.ui.FINISH_ROUTE_NAME
import com.hippo.ehviewer.ui.LocalNavController
import com.hippo.ehviewer.ui.destinations.FinishDestination
import com.ramcosta.composedestinations.annotation.Destination
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
@Destination
@Composable
fun SelectSiteScreen() {
fun SelectSiteScreen(navigator: DestinationsNavigator) {
var siteEx by remember { mutableStateOf(true) }
val navController = LocalNavController.current
val context = LocalContext.current
BackHandler {
@@ -70,7 +71,7 @@ fun SelectSiteScreen() {
// Gallery site was set to ex in sad panda check
if (!siteEx) Settings.gallerySite = EhUrl.SITE_E
Settings.needSignIn = false
navController.navigate(FINISH_ROUTE_NAME)
navigator.navigate(FinishDestination)
},
modifier = Modifier.fillMaxWidth(),
) {
@@ -32,7 +32,6 @@ import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.material3.windowsizeclass.WindowSizeClass
import androidx.compose.material3.windowsizeclass.WindowWidthSizeClass
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
@@ -62,22 +61,25 @@ import com.hippo.ehviewer.Settings
import com.hippo.ehviewer.client.EhEngine
import com.hippo.ehviewer.client.EhUrl
import com.hippo.ehviewer.client.EhUtils
import com.hippo.ehviewer.ui.COOKIE_SIGN_IN_ROUTE_NAME
import com.hippo.ehviewer.ui.FINISH_ROUTE_NAME
import com.hippo.ehviewer.ui.LocalNavController
import com.hippo.ehviewer.ui.SELECT_SITE_ROUTE_NAME
import com.hippo.ehviewer.ui.WEBVIEW_SIGN_IN_ROUTE_NAME
import com.hippo.ehviewer.ui.destinations.CookieSignInSceneDestination
import com.hippo.ehviewer.ui.destinations.FinishDestination
import com.hippo.ehviewer.ui.destinations.SelectSiteScreenDestination
import com.hippo.ehviewer.ui.destinations.WebViewSignInScreenDestination
import com.hippo.ehviewer.ui.openBrowser
import com.hippo.ehviewer.ui.tools.LocalDialogState
import com.hippo.ehviewer.ui.tools.LocalWindowSizeClass
import com.hippo.ehviewer.util.ExceptionUtils
import com.ramcosta.composedestinations.annotation.Destination
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
import eu.kanade.tachiyomi.util.lang.launchIO
import eu.kanade.tachiyomi.util.lang.withNonCancellableContext
import eu.kanade.tachiyomi.util.lang.withUIContext
import kotlinx.coroutines.Job
@Destination
@Composable
fun SignInScreen(windowSizeClass: WindowSizeClass) {
val navController = LocalNavController.current
fun SignInScreen(navigator: DestinationsNavigator) {
val windowSizeClass = LocalWindowSizeClass.current
val coroutineScope = rememberCoroutineScope()
val focusManager = LocalFocusManager.current
var isProgressIndicatorVisible by rememberSaveable { mutableStateOf(false) }
@@ -134,7 +136,7 @@ fun SignInScreen(windowSizeClass: WindowSizeClass) {
}
}.onSuccess {
val canEx = withNonCancellableContext { postLogin() }
withUIContext { navController.navigate(if (canEx) SELECT_SITE_ROUTE_NAME else FINISH_ROUTE_NAME) }
withUIContext { navigator.navigate(if (canEx) SelectSiteScreenDestination else FinishDestination) }
}
}
}
@@ -216,7 +218,7 @@ fun SignInScreen(windowSizeClass: WindowSizeClass) {
}
Row(modifier = Modifier.padding(horizontal = 4.dp)) {
TextButton(
onClick = { navController.navigate(WEBVIEW_SIGN_IN_ROUTE_NAME) },
onClick = { navigator.navigate(WebViewSignInScreenDestination) },
modifier = Modifier.padding(horizontal = 8.dp),
) {
Text(
@@ -230,7 +232,7 @@ fun SignInScreen(windowSizeClass: WindowSizeClass) {
)
}
TextButton(
onClick = { navController.navigate(COOKIE_SIGN_IN_ROUTE_NAME) },
onClick = { navigator.navigate(CookieSignInSceneDestination) },
modifier = Modifier.padding(horizontal = 8.dp),
) {
Text(
@@ -248,7 +250,7 @@ fun SignInScreen(windowSizeClass: WindowSizeClass) {
onClick = {
Settings.needSignIn = false
Settings.gallerySite = EhUrl.SITE_E
navController.navigate(FINISH_ROUTE_NAME)
navigator.navigate(FinishDestination)
},
) {
Text(
@@ -312,7 +314,7 @@ fun SignInScreen(windowSizeClass: WindowSizeClass) {
Spacer(modifier = Modifier.height(8.dp))
Row(horizontalArrangement = Arrangement.Center) {
TextButton(
onClick = { navController.navigate(COOKIE_SIGN_IN_ROUTE_NAME) },
onClick = { navigator.navigate(CookieSignInSceneDestination) },
modifier = Modifier.padding(horizontal = 4.dp),
) {
Text(
@@ -326,7 +328,7 @@ fun SignInScreen(windowSizeClass: WindowSizeClass) {
)
}
TextButton(
onClick = { navController.navigate(WEBVIEW_SIGN_IN_ROUTE_NAME) },
onClick = { navigator.navigate(WebViewSignInScreenDestination) },
modifier = Modifier.padding(horizontal = 4.dp),
) {
Text(
@@ -344,7 +346,7 @@ fun SignInScreen(windowSizeClass: WindowSizeClass) {
onClick = {
Settings.needSignIn = false
Settings.gallerySite = EhUrl.SITE_E
navController.navigate(FINISH_ROUTE_NAME)
navigator.navigate(FinishDestination)
},
modifier = Modifier.padding(horizontal = 4.dp),
) {
@@ -14,18 +14,19 @@ import com.google.accompanist.web.rememberWebViewState
import com.hippo.ehviewer.client.EhCookieStore
import com.hippo.ehviewer.client.EhUrl
import com.hippo.ehviewer.client.EhUtils
import com.hippo.ehviewer.ui.FINISH_ROUTE_NAME
import com.hippo.ehviewer.ui.LocalNavController
import com.hippo.ehviewer.ui.SELECT_SITE_ROUTE_NAME
import com.hippo.ehviewer.ui.destinations.FinishDestination
import com.hippo.ehviewer.ui.destinations.SelectSiteScreenDestination
import com.hippo.ehviewer.util.setDefaultSettings
import com.ramcosta.composedestinations.annotation.Destination
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
import eu.kanade.tachiyomi.util.lang.launchIO
import eu.kanade.tachiyomi.util.lang.withNonCancellableContext
import eu.kanade.tachiyomi.util.lang.withUIContext
import okhttp3.HttpUrl.Companion.toHttpUrl
@Destination
@Composable
fun WebViewSignInScreen() {
val navController = LocalNavController.current
fun WebViewSignInScreen(navigator: DestinationsNavigator) {
val coroutineScope = rememberCoroutineScope()
val state = rememberWebViewState(url = EhUrl.URL_SIGN_IN)
val client = remember {
@@ -49,7 +50,7 @@ fun WebViewSignInScreen() {
present = true
coroutineScope.launchIO {
val canEx = withNonCancellableContext { postLogin() }
withUIContext { navController.navigate(if (canEx) SELECT_SITE_ROUTE_NAME else FINISH_ROUTE_NAME) }
withUIContext { navigator.navigate(if (canEx) SelectSiteScreenDestination else FinishDestination) }
}
}
}
@@ -31,8 +31,7 @@ import androidx.core.text.parseAsHtml
import com.hippo.ehviewer.BuildConfig
import com.hippo.ehviewer.R
import com.hippo.ehviewer.Settings
import com.hippo.ehviewer.ui.LICENSE_SCREEN
import com.hippo.ehviewer.ui.LocalNavController
import com.hippo.ehviewer.ui.destinations.LicenseScreenDestination
import com.hippo.ehviewer.ui.tools.DialogState
import com.hippo.ehviewer.ui.tools.LocalDialogState
import com.hippo.ehviewer.ui.tools.observed
@@ -42,6 +41,8 @@ import com.hippo.ehviewer.updater.Release
import com.hippo.ehviewer.util.AppConfig
import com.hippo.ehviewer.util.ExceptionUtils
import com.hippo.ehviewer.util.installPackage
import com.ramcosta.composedestinations.annotation.Destination
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
import eu.kanade.tachiyomi.util.lang.withUIContext
import java.io.File
import kotlinx.coroutines.Dispatchers
@@ -59,10 +60,10 @@ private fun versionCode() = "${BuildConfig.VERSION_NAME} (${BuildConfig.COMMIT_S
@Stable
private fun author() = stringResource(R.string.settings_about_author_summary).replace('$', '@').parseAsHtml().toAnnotatedString()
@Destination
@Composable
fun AboutScreen() {
fun AboutScreen(navigator: DestinationsNavigator) {
val context = LocalContext.current
val navController = LocalNavController.current
val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior()
val snackbarHostState = remember { SnackbarHostState() }
val coroutineScope = rememberCoroutineScope { Dispatchers.IO }
@@ -73,7 +74,7 @@ fun AboutScreen() {
TopAppBar(
title = { Text(text = stringResource(id = R.string.settings_about)) },
navigationIcon = {
IconButton(onClick = { navController.popBackStack() }) {
IconButton(onClick = { navigator.popBackStack() }) {
Icon(imageVector = Icons.AutoMirrored.Default.ArrowBack, contentDescription = null)
}
},
@@ -100,7 +101,7 @@ fun AboutScreen() {
url = REPO_URL,
)
Preference(title = stringResource(id = R.string.license)) {
navController.navigate(LICENSE_SCREEN)
navigator.navigate(LicenseScreenDestination)
}
Preference(
title = stringResource(id = R.string.settings_about_version),
@@ -37,11 +37,12 @@ import com.hippo.ehviewer.client.CHROME_USER_AGENT
import com.hippo.ehviewer.client.EhCookieStore
import com.hippo.ehviewer.client.EhEngine
import com.hippo.ehviewer.client.data.FavListUrlBuilder
import com.hippo.ehviewer.ui.LocalNavController
import com.hippo.ehviewer.ui.tools.LocalDialogState
import com.hippo.ehviewer.ui.tools.observed
import com.hippo.ehviewer.util.AppConfig
import com.hippo.ehviewer.util.ReadableTime
import com.ramcosta.composedestinations.annotation.Destination
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
import java.io.File
import java.util.zip.ZipEntry
import java.util.zip.ZipOutputStream
@@ -50,9 +51,9 @@ import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import moe.tarsin.coroutines.runSuspendCatching
@Destination
@Composable
fun AdvancedScreen() {
val navController = LocalNavController.current
fun AdvancedScreen(navigator: DestinationsNavigator) {
val context = LocalContext.current
val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior()
val snackbarHostState = remember { SnackbarHostState() }
@@ -64,7 +65,7 @@ fun AdvancedScreen() {
TopAppBar(
title = { Text(text = stringResource(id = R.string.settings_advanced)) },
navigationIcon = {
IconButton(onClick = { navController.popBackStack() }) {
IconButton(onClick = { navigator.popBackStack() }) {
Icon(imageVector = Icons.AutoMirrored.Default.ArrowBack, contentDescription = null)
}
},
@@ -21,24 +21,27 @@ import androidx.compose.ui.res.stringResource
import com.hippo.ehviewer.R
import com.hippo.ehviewer.icons.EhIcons
import com.hippo.ehviewer.icons.filled.SadPanda
import com.hippo.ehviewer.ui.ABOUT_SETTINGS_SCREEN
import com.hippo.ehviewer.ui.ADVANCED_SETTINGS_SCREEN
import com.hippo.ehviewer.ui.DOWNLOAD_SETTINGS_SCREEN
import com.hippo.ehviewer.ui.EH_SETTINGS_SCREEN
import com.hippo.ehviewer.ui.FINISH_ROUTE_NAME
import com.hippo.ehviewer.ui.LocalNavController
import com.hippo.ehviewer.ui.PRIVACY_SETTINGS_SCREEN
import com.hippo.ehviewer.ui.destinations.AboutScreenDestination
import com.hippo.ehviewer.ui.destinations.AdvancedScreenDestination
import com.hippo.ehviewer.ui.destinations.DownloadScreenDestination
import com.hippo.ehviewer.ui.destinations.EhScreenDestination
import com.hippo.ehviewer.ui.destinations.FinishDestination
import com.hippo.ehviewer.ui.destinations.PrivacyScreenDestination
import com.ramcosta.composedestinations.annotation.Destination
import com.ramcosta.composedestinations.annotation.RootNavGraph
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
@RootNavGraph(start = true)
@Destination
@Composable
fun BaseScreen() {
val navController = LocalNavController.current
fun BaseScreen(navigator: DestinationsNavigator) {
val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior()
Scaffold(
topBar = {
TopAppBar(
title = { Text(text = stringResource(id = R.string.settings)) },
navigationIcon = {
IconButton(onClick = { navController.navigate(FINISH_ROUTE_NAME) }) {
IconButton(onClick = { navigator.navigate(FinishDestination) }) {
Icon(imageVector = Icons.AutoMirrored.Default.ArrowBack, contentDescription = null)
}
},
@@ -50,27 +53,32 @@ fun BaseScreen() {
PreferenceHeader(
icon = EhIcons.Default.SadPanda,
title = R.string.settings_eh,
childRouteName = EH_SETTINGS_SCREEN,
childRoute = EhScreenDestination,
navigator = navigator,
)
PreferenceHeader(
icon = Icons.Default.Download,
title = R.string.settings_download,
childRouteName = DOWNLOAD_SETTINGS_SCREEN,
childRoute = DownloadScreenDestination,
navigator = navigator,
)
PreferenceHeader(
icon = Icons.Default.Security,
title = R.string.settings_privacy,
childRouteName = PRIVACY_SETTINGS_SCREEN,
childRoute = PrivacyScreenDestination,
navigator = navigator,
)
PreferenceHeader(
icon = Icons.Default.Adb,
title = R.string.settings_advanced,
childRouteName = ADVANCED_SETTINGS_SCREEN,
childRoute = AdvancedScreenDestination,
navigator = navigator,
)
PreferenceHeader(
icon = Icons.Default.Info,
title = R.string.settings_about,
childRouteName = ABOUT_SETTINGS_SCREEN,
childRoute = AboutScreenDestination,
navigator = navigator,
)
}
}
@@ -38,22 +38,23 @@ import com.hippo.ehviewer.download.DownloadManager
import com.hippo.ehviewer.download.downloadLocation
import com.hippo.ehviewer.spider.SpiderQueen
import com.hippo.ehviewer.spider.readCompatFromUniFile
import com.hippo.ehviewer.ui.LocalNavController
import com.hippo.ehviewer.ui.keepNoMediaFileStatus
import com.hippo.ehviewer.ui.legacy.BaseDialogBuilder
import com.hippo.ehviewer.ui.tools.observed
import com.hippo.ehviewer.ui.tools.rememberedAccessor
import com.hippo.ehviewer.util.AppConfig
import com.hippo.unifile.UniFile
import com.ramcosta.composedestinations.annotation.Destination
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
import eu.kanade.tachiyomi.util.lang.launchNonCancellable
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import moe.tarsin.coroutines.runSuspendCatching
import splitties.init.appCtx
@Destination
@Composable
fun DownloadScreen() {
val navController = LocalNavController.current
fun DownloadScreen(navigator: DestinationsNavigator) {
val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior()
val context = LocalContext.current
val coroutineScope = rememberCoroutineScope { Dispatchers.IO }
@@ -64,7 +65,7 @@ fun DownloadScreen() {
TopAppBar(
title = { Text(text = stringResource(id = R.string.settings_download)) },
navigationIcon = {
IconButton(onClick = { navController.popBackStack() }) {
IconButton(onClick = { navigator.popBackStack() }) {
Icon(imageVector = Icons.AutoMirrored.Default.ArrowBack, contentDescription = null)
}
},
@@ -43,17 +43,18 @@ import com.hippo.ehviewer.client.parser.HomeParser
import com.hippo.ehviewer.dailycheck.schedHour
import com.hippo.ehviewer.dailycheck.schedMinute
import com.hippo.ehviewer.dailycheck.updateDailyCheckWork
import com.hippo.ehviewer.ui.FILTER_SCREEN
import com.hippo.ehviewer.ui.LocalNavController
import com.hippo.ehviewer.ui.MYTAGS_SCREEN
import com.hippo.ehviewer.ui.SIGN_IN_ROUTE_NAME
import com.hippo.ehviewer.ui.UCONFIG_SCREEN
import com.hippo.ehviewer.ui.destinations.FilterScreenDestination
import com.hippo.ehviewer.ui.destinations.MyTagsScreenDestination
import com.hippo.ehviewer.ui.destinations.SignInScreenDestination
import com.hippo.ehviewer.ui.destinations.UConfigScreenDestination
import com.hippo.ehviewer.ui.legacy.BaseDialogBuilder
import com.hippo.ehviewer.ui.tools.LocalDialogState
import com.hippo.ehviewer.ui.tools.TimePickerDialog
import com.hippo.ehviewer.ui.tools.observed
import com.hippo.ehviewer.ui.tools.rememberedAccessor
import com.hippo.ehviewer.util.copyTextToClipboard
import com.ramcosta.composedestinations.annotation.Destination
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
import eu.kanade.tachiyomi.util.lang.withUIContext
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
@@ -61,9 +62,9 @@ import kotlinx.coroutines.launch
import moe.tarsin.coroutines.runSuspendCatching
import okhttp3.HttpUrl.Companion.toHttpUrl
@Destination
@Composable
fun EhScreen() {
val navController = LocalNavController.current
fun EhScreen(navigator: DestinationsNavigator) {
val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior()
val snackbarHostState = remember { SnackbarHostState() }
val coroutineScope = rememberCoroutineScope { Dispatchers.IO }
@@ -76,7 +77,7 @@ fun EhScreen() {
TopAppBar(
title = { Text(text = stringResource(id = R.string.settings_eh)) },
navigationIcon = {
IconButton(onClick = { navController.popBackStack() }) {
IconButton(onClick = { navigator.popBackStack() }) {
Icon(imageVector = Icons.AutoMirrored.Default.ArrowBack, contentDescription = null)
}
},
@@ -119,7 +120,7 @@ fun EhScreen() {
}
setPositiveButton(R.string.settings_eh_sign_out) { _, _ ->
EhUtils.signOut()
navController.navigate(SIGN_IN_ROUTE_NAME)
navigator.navigate(SignInScreenDestination)
}
}.show()
}
@@ -184,11 +185,11 @@ fun EhScreen() {
Preference(
title = stringResource(id = R.string.settings_u_config),
summary = stringResource(id = R.string.settings_u_config_summary),
) { navController.navigate(UCONFIG_SCREEN) }
) { navigator.navigate(UConfigScreenDestination) }
Preference(
title = stringResource(id = R.string.settings_my_tags),
summary = stringResource(id = R.string.settings_my_tags_summary),
) { navController.navigate(MYTAGS_SCREEN) }
) { navigator.navigate(MyTagsScreenDestination) }
}
var defaultFavSlot by Settings::defaultFavSlot.observed
val disabled = stringResource(id = R.string.disabled_nav)
@@ -306,7 +307,7 @@ fun EhScreen() {
Preference(
title = stringResource(id = R.string.settings_eh_filter),
summary = stringResource(id = R.string.settings_eh_filter_summary),
) { navController.navigate(FILTER_SCREEN) }
) { navigator.navigate(FilterScreenDestination) }
SwitchPreference(
title = stringResource(id = R.string.settings_eh_metered_network_warning),
value = Settings::meteredNetworkWarning,
@@ -46,19 +46,20 @@ import com.hippo.ehviewer.client.EhFilter.trigger
import com.hippo.ehviewer.dao.Filter
import com.hippo.ehviewer.dao.FilterMode
import com.hippo.ehviewer.databinding.DialogAddFilterBinding
import com.hippo.ehviewer.ui.LocalNavController
import com.hippo.ehviewer.ui.legacy.BaseDialogBuilder
import com.hippo.ehviewer.ui.tools.Deferred
import com.hippo.ehviewer.ui.tools.LocalDialogState
import com.ramcosta.composedestinations.annotation.Destination
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
import eu.kanade.tachiyomi.util.lang.withUIContext
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.launch
import moe.tarsin.coroutines.groupByToObserved
@Destination
@Composable
fun FilterScreen() {
val navController = LocalNavController.current
fun FilterScreen(navigator: DestinationsNavigator) {
val context = LocalContext.current
val scope = rememberCoroutineScope { Dispatchers.IO }
val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior()
@@ -112,7 +113,7 @@ fun FilterScreen() {
TopAppBar(
title = { Text(text = stringResource(id = R.string.filter)) },
navigationIcon = {
IconButton(onClick = { navController.popBackStack() }) {
IconButton(onClick = { navigator.popBackStack() }) {
Icon(imageVector = Icons.AutoMirrored.Default.ArrowBack, contentDescription = null)
}
},
@@ -13,19 +13,20 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.res.stringResource
import com.hippo.ehviewer.R
import com.hippo.ehviewer.ui.LocalNavController
import com.mikepenz.aboutlibraries.ui.compose.LibrariesContainer
import com.ramcosta.composedestinations.annotation.Destination
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
@Destination
@Composable
fun LicenseScreen() {
val navController = LocalNavController.current
fun LicenseScreen(navigator: DestinationsNavigator) {
val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior()
Scaffold(
topBar = {
TopAppBar(
title = { Text(text = stringResource(id = R.string.license)) },
navigationIcon = {
IconButton(onClick = { navController.popBackStack() }) {
IconButton(onClick = { navigator.popBackStack() }) {
Icon(imageVector = Icons.AutoMirrored.Default.ArrowBack, contentDescription = null)
}
},
@@ -16,19 +16,20 @@ import com.google.accompanist.web.WebView
import com.google.accompanist.web.rememberWebViewState
import com.hippo.ehviewer.R
import com.hippo.ehviewer.client.EhUrl
import com.hippo.ehviewer.ui.LocalNavController
import com.hippo.ehviewer.util.setDefaultSettings
import com.ramcosta.composedestinations.annotation.Destination
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
@Destination
@Composable
fun MyTagsScreen() {
val navController = LocalNavController.current
fun MyTagsScreen(navigator: DestinationsNavigator) {
val url = EhUrl.myTagsUrl
Scaffold(
topBar = {
TopAppBar(
title = { Text(text = stringResource(id = R.string.my_tags)) },
navigationIcon = {
IconButton(onClick = { navController.popBackStack() }) {
IconButton(onClick = { navigator.popBackStack() }) {
Icon(imageVector = Icons.AutoMirrored.Default.ArrowBack, contentDescription = null)
}
},
@@ -41,7 +41,7 @@ import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.DialogProperties
import arrow.atomic.Atomic
import com.hippo.ehviewer.R
import com.hippo.ehviewer.ui.LocalNavController
import com.hippo.ehviewer.ui.destinations.DirectionDestination
import com.hippo.ehviewer.ui.openBrowser
import com.hippo.ehviewer.ui.settings.PreferenceTokens.PreferenceTextPadding
import com.jamal.composeprefs3.ui.prefs.DropDownPref
@@ -50,6 +50,7 @@ import com.jamal.composeprefs3.ui.prefs.SliderPref
import com.jamal.composeprefs3.ui.prefs.SpannedTextPref
import com.jamal.composeprefs3.ui.prefs.SwitchPref
import com.jamal.composeprefs3.ui.prefs.TextPref
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
import kotlin.coroutines.resume
import kotlin.coroutines.suspendCoroutine
import kotlin.math.roundToInt
@@ -66,10 +67,14 @@ object PreferenceTokens {
}
@Composable
fun PreferenceHeader(icon: Painter, @StringRes title: Int, childRouteName: String) {
val navController = LocalNavController.current
fun PreferenceHeader(
icon: Painter,
@StringRes title: Int,
childRoute: DirectionDestination,
navigator: DestinationsNavigator,
) {
Row(
modifier = Modifier.clickable { navController.navigate(childRouteName) }.fillMaxWidth().height(PreferenceTokens.PreferenceHeaderHeight),
modifier = Modifier.clickable { navigator.navigate(childRoute) }.fillMaxWidth().height(PreferenceTokens.PreferenceHeaderHeight),
verticalAlignment = Alignment.CenterVertically,
) {
Spacer(modifier = Modifier.size(PreferenceTokens.PreferenceIconPadding))
@@ -80,7 +85,17 @@ fun PreferenceHeader(icon: Painter, @StringRes title: Int, childRouteName: Strin
}
@Composable
fun PreferenceHeader(icon: ImageVector, @StringRes title: Int, childRouteName: String) = PreferenceHeader(icon = rememberVectorPainter(image = icon), title = title, childRouteName = childRouteName)
fun PreferenceHeader(
icon: ImageVector,
@StringRes title: Int,
childRoute: DirectionDestination,
navigator: DestinationsNavigator,
) = PreferenceHeader(
icon = rememberVectorPainter(image = icon),
title = title,
childRoute = childRoute,
navigator = navigator,
)
@Composable
fun Preference(title: String, summary: String? = null, onClick: () -> Unit = {}) {
@@ -22,17 +22,18 @@ import androidx.compose.ui.res.stringResource
import com.hippo.ehviewer.EhApplication.Companion.searchDatabase
import com.hippo.ehviewer.R
import com.hippo.ehviewer.Settings
import com.hippo.ehviewer.ui.LocalNavController
import com.hippo.ehviewer.ui.isAuthenticationSupported
import com.hippo.ehviewer.ui.tools.LocalDialogState
import com.hippo.ehviewer.ui.tools.observed
import com.hippo.ehviewer.ui.tools.rememberedAccessor
import com.ramcosta.composedestinations.annotation.Destination
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
@Destination
@Composable
fun PrivacyScreen() {
val navController = LocalNavController.current
fun PrivacyScreen(navigator: DestinationsNavigator) {
val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior()
val snackbarHostState = remember { SnackbarHostState() }
val coroutineScope = rememberCoroutineScope { Dispatchers.IO }
@@ -43,7 +44,7 @@ fun PrivacyScreen() {
TopAppBar(
title = { Text(text = stringResource(id = R.string.settings_privacy)) },
navigationIcon = {
IconButton(onClick = { navController.popBackStack() }) {
IconButton(onClick = { navigator.popBackStack() }) {
Icon(imageVector = Icons.AutoMirrored.Default.ArrowBack, contentDescription = null)
}
},
@@ -25,14 +25,15 @@ import com.google.accompanist.web.rememberWebViewState
import com.hippo.ehviewer.R
import com.hippo.ehviewer.client.EhCookieStore
import com.hippo.ehviewer.client.EhUrl
import com.hippo.ehviewer.ui.LocalNavController
import com.hippo.ehviewer.util.setDefaultSettings
import com.ramcosta.composedestinations.annotation.Destination
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
private const val APPLY_JS = "javascript:(function(){var apply = document.getElementById(\"apply\").children[0];apply.click();})();"
@Destination
@Composable
fun UConfigScreen() {
val navController = LocalNavController.current
fun UConfigScreen(navigator: DestinationsNavigator) {
val url = EhUrl.uConfigUrl
val webview = remember { Atomic<WebView?>(null) }
val snackbarHostState = remember { SnackbarHostState() }
@@ -41,7 +42,7 @@ fun UConfigScreen() {
TopAppBar(
title = { Text(text = stringResource(id = R.string.u_config)) },
navigationIcon = {
IconButton(onClick = { navController.popBackStack() }) {
IconButton(onClick = { navigator.popBackStack() }) {
Icon(imageVector = Icons.AutoMirrored.Default.ArrowBack, contentDescription = null)
}
},
@@ -49,7 +50,7 @@ fun UConfigScreen() {
IconButton(
onClick = {
webview.get()?.loadUrl(APPLY_JS)
navController.popBackStack()
navigator.popBackStack()
},
) {
Icon(imageVector = Icons.Default.Check, contentDescription = null)
@@ -0,0 +1,6 @@
package com.hippo.ehviewer.ui.tools
import androidx.compose.material3.windowsizeclass.WindowSizeClass
import androidx.compose.runtime.compositionLocalOf
val LocalWindowSizeClass = compositionLocalOf<WindowSizeClass> { error("CompositionLocal LocalWindowSizeClass not present!") }
+4
View File
@@ -25,6 +25,7 @@ chucker = "4.0.0"
coil = "2.5.0"
compose-bom = "2023.11.00-alpha01"
compose-compiler = "1.5.4-dev-k1.9.20-50f08dfa4b4"
compose-destinations = "1.9.54"
google-accompanist = "0.32.0"
google-android-material = "1.11.0-beta01"
kotlin = "1.9.20"
@@ -91,6 +92,9 @@ compose-material3-windowsizeclass = { module = "androidx.compose.material3:mater
compose-ui-util = { module = "androidx.compose.ui:ui-util" }
compose-ui-viewbinding = { module = "androidx.compose.ui:ui-viewbinding" }
compose-destinations-core = { module = "io.github.raamcosta.compose-destinations:core", version.ref = "compose-destinations" }
compose-destinations-compiler = { module = "io.github.raamcosta.compose-destinations:ksp", version.ref = "compose-destinations" }
cronet-api = "org.chromium.net:cronet-api:113.5672.61"
cronet-gms = "com.google.android.gms:play-services-cronet:18.0.1"