Compose Era!!! (#346)

* Initial Kill Fragment!

* Cleanup

* Cleanup

* Convert to use Compose ModalBottomSheet

* Ignore insets

* Navigate

* Fixes

* Cleanup

* Fix navToWebview

* Fix navToWebview

* showtip

* Refine

* Fixes

---------

Co-authored-by: GG Bond <whatever@tagkong.com>
This commit is contained in:
Vladimir DostoyevskiyandGG Bond authored and GitHub committed 2023-11-26 15:02:03 +00:00
1 parent f292f31ac1
commit 6c926419e9
18 files changed
+305 -752

No files matched your search

@@ -1,38 +0,0 @@
package androidx.navigation.ui
import android.annotation.SuppressLint
import androidx.annotation.IdRes
import androidx.navigation.ActivityNavigator
import androidx.navigation.NavController
import androidx.navigation.NavDestination
import androidx.navigation.NavDestination.Companion.hierarchy
import androidx.navigation.NavOptions
@SuppressLint("PrivateResource")
fun onNavDestinationSelected2(@IdRes id: Int, navController: NavController): Boolean {
if (navController.currentDestination?.matchDestination(id) == true) return true
val builder = NavOptions.Builder().setLaunchSingleTop(true)
if (navController.currentDestination!!.parent!!.findNode(id) is ActivityNavigator.Destination) {
builder.setEnterAnim(R.anim.nav_default_enter_anim)
.setExitAnim(R.anim.nav_default_exit_anim)
.setPopEnterAnim(R.anim.nav_default_pop_enter_anim)
.setPopExitAnim(R.anim.nav_default_pop_exit_anim)
} else {
builder.setEnterAnim(androidx.fragment.R.animator.fragment_open_enter)
.setExitAnim(androidx.fragment.R.animator.fragment_open_exit)
.setPopEnterAnim(androidx.fragment.R.animator.fragment_close_enter)
.setPopExitAnim(androidx.fragment.R.animator.fragment_close_exit)
}
val options = builder.build()
return try {
// TODO provide proper API instead of using Exceptions as Control-Flow.
navController.navigate(id, null, options)
// Return true only if the destination we've navigated to matches the MenuItem
navController.currentDestination?.matchDestination(id) == true
} catch (e: IllegalArgumentException) {
false
}
}
fun NavDestination.matchDestination(@IdRes destId: Int): Boolean =
hierarchy.any { it.id == destId }
@@ -1,8 +1,5 @@
package com.hippo.ehviewer.ui
import android.os.Bundle
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
@@ -14,6 +11,7 @@ import androidx.compose.foundation.lazy.itemsIndexed
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.ProvideTextStyle
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
@@ -21,8 +19,6 @@ import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.dimensionResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.navigation.fragment.findNavController
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
import com.hippo.ehviewer.R
import com.hippo.ehviewer.Settings
import com.hippo.ehviewer.client.EhUrl
@@ -30,9 +26,9 @@ import com.hippo.ehviewer.client.EhUtils
import com.hippo.ehviewer.client.data.GalleryDetail
import com.hippo.ehviewer.client.data.GalleryInfo.Companion.LOCAL_FAVORITED
import com.hippo.ehviewer.client.thumbUrl
import com.hippo.ehviewer.databinding.InfoSheetBinding
import com.hippo.ehviewer.ui.scene.navWithUrl
import com.hippo.ehviewer.util.addTextToClipboard
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
private const val INDEX_URL = 2
private const val INDEX_PARENT = 9
@@ -61,43 +57,39 @@ private fun GalleryDetail.generateContent() = arrayOf(
R.string.favorite_name to favoriteName,
)
class GalleryInfoBottomSheet(private val detail: GalleryDetail) : BottomSheetDialogFragment() {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?) = InfoSheetBinding.inflate(layoutInflater, container, false).apply {
content.setMD3Content {
Column(modifier = Modifier.fillMaxWidth()) {
val context = LocalContext.current
val navController = remember { findNavController() }
Text(
text = stringResource(id = R.string.gallery_info),
modifier = Modifier.align(Alignment.CenterHorizontally),
style = MaterialTheme.typography.titleLarge,
)
val data = remember(detail) { detail.generateContent() }
ProvideTextStyle(MaterialTheme.typography.labelLarge) {
LazyColumn {
itemsIndexed(data) { index, (key, content) ->
Row(
modifier = Modifier.padding(horizontal = dimensionResource(id = R.dimen.keyline_margin)).clickable {
if (index == INDEX_PARENT) {
if (content != null) {
navController.navWithUrl(content)
}
} else {
context.addTextToClipboard(content, true)
if (index == INDEX_URL) {
// Save it to avoid detect the gallery
Settings.clipboardTextHashCode = data[index].hashCode()
}
}
}.fillMaxWidth(),
) {
Text(stringResource(id = key), modifier = Modifier.width(90.dp).padding(8.dp))
Text(content.orEmpty(), modifier = Modifier.padding(8.dp))
@Composable
fun GalleryInfoBottomSheet(detail: GalleryDetail, navigator: DestinationsNavigator) {
Column(modifier = Modifier.fillMaxWidth()) {
val context = LocalContext.current
Text(
text = stringResource(id = R.string.gallery_info),
modifier = Modifier.align(Alignment.CenterHorizontally),
style = MaterialTheme.typography.titleLarge,
)
val data = remember(detail) { detail.generateContent() }
ProvideTextStyle(MaterialTheme.typography.labelLarge) {
LazyColumn {
itemsIndexed(data) { index, (key, content) ->
Row(
modifier = Modifier.padding(horizontal = dimensionResource(id = R.dimen.keyline_margin)).clickable {
if (index == INDEX_PARENT) {
if (content != null) {
navigator.navWithUrl(content)
}
} else {
context.addTextToClipboard(content, true)
if (index == INDEX_URL) {
// Save it to avoid detect the gallery
Settings.clipboardTextHashCode = data[index].hashCode()
}
}
}
}.fillMaxWidth(),
) {
Text(stringResource(id = key), modifier = Modifier.width(90.dp).padding(8.dp))
Text(content.orEmpty(), modifier = Modifier.padding(8.dp))
}
}
}
}
}.root
}
}
@@ -15,6 +15,7 @@
*/
package com.hippo.ehviewer.ui
import android.annotation.SuppressLint
import android.app.assist.AssistContent
import android.content.DialogInterface
import android.content.Intent
@@ -34,12 +35,9 @@ import androidx.compose.foundation.layout.ColumnScope
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.WindowInsetsSides
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.ime
import androidx.compose.foundation.layout.navigationBars
import androidx.compose.foundation.layout.navigationBarsPadding
import androidx.compose.foundation.layout.only
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.statusBars
import androidx.compose.foundation.layout.systemBars
import androidx.compose.foundation.layout.widthIn
import androidx.compose.foundation.rememberScrollState
@@ -59,17 +57,20 @@ import androidx.compose.material3.Icon
import androidx.compose.material3.ModalDrawerSheet
import androidx.compose.material3.ModalNavigationDrawer
import androidx.compose.material3.NavigationDrawerItem
import androidx.compose.material3.Scaffold
import androidx.compose.material3.ShapeDefaults
import androidx.compose.material3.SideDrawer
import androidx.compose.material3.SnackbarHost
import androidx.compose.material3.SnackbarHostState
import androidx.compose.material3.Text
import androidx.compose.material3.rememberDrawerState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.currentRecomposeScope
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.rememberUpdatedState
import androidx.compose.runtime.setValue
@@ -79,37 +80,37 @@ import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.compose.ui.viewinterop.AndroidViewBinding
import androidx.core.os.bundleOf
import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import androidx.lifecycle.lifecycleScope
import androidx.navigation.NavController
import androidx.navigation.fragment.NavHostFragment
import androidx.navigation.ui.onNavDestinationSelected2
import androidx.navigation.compose.rememberNavController
import com.google.android.material.snackbar.Snackbar
import com.hippo.ehviewer.R
import com.hippo.ehviewer.Settings
import com.hippo.ehviewer.Settings.launchPage
import com.hippo.ehviewer.client.data.ListUrlBuilder
import com.hippo.ehviewer.client.parser.GalleryDetailUrlParser
import com.hippo.ehviewer.client.parser.GalleryPageUrlParser
import com.hippo.ehviewer.databinding.ActivityMainBinding
import com.hippo.ehviewer.download.DownloadService
import com.hippo.ehviewer.download.downloadLocation
import com.hippo.ehviewer.icons.EhIcons
import com.hippo.ehviewer.icons.filled.Subscriptions
import com.hippo.ehviewer.image.Image.Companion.decodeBitmap
import com.hippo.ehviewer.ui.destinations.DownloadScreenDestination
import com.hippo.ehviewer.ui.destinations.FavouritesScreenDestination
import com.hippo.ehviewer.ui.destinations.GalleryDetailScreenDestination
import com.hippo.ehviewer.ui.destinations.GalleryListScreenDestination
import com.hippo.ehviewer.ui.destinations.HistoryScreenDestination
import com.hippo.ehviewer.ui.destinations.HomePageScreenDestination
import com.hippo.ehviewer.ui.destinations.ProgressScreenDestination
import com.hippo.ehviewer.ui.destinations.SubscriptionScreenDestination
import com.hippo.ehviewer.ui.destinations.ToplistScreenDestination
import com.hippo.ehviewer.ui.destinations.WhatshotScreenDestination
import com.hippo.ehviewer.ui.legacy.BaseDialogBuilder
import com.hippo.ehviewer.ui.legacy.EditTextDialogBuilder
import com.hippo.ehviewer.ui.scene.BaseScene
import com.hippo.ehviewer.ui.scene.GalleryDetailFragment
import com.hippo.ehviewer.ui.scene.GalleryListFragment.Companion.toStartArgs
import com.hippo.ehviewer.ui.scene.ProgressFragment
import com.hippo.ehviewer.ui.scene.TokenArgs
import com.hippo.ehviewer.ui.scene.navAnimated
import com.hippo.ehviewer.ui.scene.navWithUrl
import com.hippo.ehviewer.ui.scene.navigate
import com.hippo.ehviewer.ui.settings.showNewVersion
import com.hippo.ehviewer.ui.tools.LocalDialogState
import com.hippo.ehviewer.ui.tools.LocalTouchSlopProvider
@@ -117,10 +118,12 @@ import com.hippo.ehviewer.updater.AppUpdater
import com.hippo.ehviewer.util.AppConfig
import com.hippo.ehviewer.util.ExceptionUtils
import com.hippo.ehviewer.util.addTextToClipboard
import com.hippo.ehviewer.util.buildWindowInsets
import com.hippo.ehviewer.util.getParcelableExtraCompat
import com.hippo.ehviewer.util.getUrlFromClipboard
import com.hippo.ehviewer.util.set
import com.ramcosta.composedestinations.DestinationsNavHost
import com.ramcosta.composedestinations.animations.defaults.RootNavGraphDefaultAnimations
import com.ramcosta.composedestinations.rememberNavHostEngine
import com.ramcosta.composedestinations.utils.currentDestinationAsState
import eu.kanade.tachiyomi.util.lang.launchUI
import eu.kanade.tachiyomi.util.lang.withIOContext
import eu.kanade.tachiyomi.util.lang.withUIContext
@@ -137,20 +140,16 @@ import splitties.systemservices.clipboardManager
import splitties.systemservices.connectivityManager
private val navItems = arrayOf(
Triple(R.id.nav_homepage, R.string.homepage, Icons.Default.Home),
Triple(R.id.nav_subscription, R.string.subscription, EhIcons.Default.Subscriptions),
Triple(R.id.nav_whats_hot, R.string.whats_hot, Icons.Default.Whatshot),
Triple(R.id.nav_toplist, R.string.toplist, Icons.Default.FormatListNumbered),
Triple(R.id.nav_favourite, R.string.favourite, Icons.Default.Favorite),
Triple(R.id.nav_history, R.string.history, Icons.Default.History),
Triple(R.id.nav_downloads, R.string.downloads, Icons.Default.Download),
Triple(R.id.nav_settings, R.string.settings, Icons.Default.Settings),
Triple(HomePageScreenDestination, R.string.homepage, Icons.Default.Home),
Triple(SubscriptionScreenDestination, R.string.subscription, EhIcons.Default.Subscriptions),
Triple(WhatshotScreenDestination, R.string.whats_hot, Icons.Default.Whatshot),
Triple(ToplistScreenDestination, R.string.toplist, Icons.Default.FormatListNumbered),
Triple(FavouritesScreenDestination, R.string.favourite, Icons.Default.Favorite),
Triple(HistoryScreenDestination, R.string.history, Icons.Default.History),
Triple(DownloadScreenDestination, R.string.downloads, Icons.Default.Download),
)
class MainActivity : EhActivity() {
private lateinit var navController: NavController
private val isInitializedFlow = MutableStateFlow(false)
private var sideSheet = mutableStateListOf<@Composable ColumnScope.(DrawerState2) -> Unit>()
@Composable
@@ -212,7 +211,7 @@ class MainActivity : EhActivity() {
when (intent?.action) {
Intent.ACTION_VIEW -> {
val uri = intent.data ?: return false
return navController.navWithUrl(uri.toString())
return navigator?.navWithUrl(uri.toString()) ?: false
}
Intent.ACTION_SEND -> {
@@ -220,10 +219,7 @@ class MainActivity : EhActivity() {
if ("text/plain" == type) {
val builder = ListUrlBuilder()
builder.keyword = intent.getStringExtra(Intent.EXTRA_TEXT)
navController.navAnimated(
R.id.galleryListScene,
builder.toStartArgs(),
)
navigator?.navigate(GalleryListScreenDestination(builder))
return true
} else if (type != null && type.startsWith("image/")) {
val uri = intent.getParcelableExtraCompat<Uri>(Intent.EXTRA_STREAM)
@@ -234,10 +230,7 @@ class MainActivity : EhActivity() {
builder.mode = ListUrlBuilder.MODE_IMAGE_SEARCH
builder.imagePath = temp.path
builder.isUseSimilarityScan = true
navController.navAnimated(
R.id.galleryListScene,
builder.toStartArgs(),
)
navigator?.navigate(GalleryListScreenDestination(builder))
return true
}
}
@@ -246,7 +239,7 @@ class MainActivity : EhActivity() {
DownloadService.ACTION_START_DOWNLOADSCENE -> {
val args = intent.getBundleExtra(DownloadService.ACTION_START_DOWNLOADSCENE_ARGS)
navController.navAnimated(R.id.nav_downloads, args)
navigator?.navigate(DownloadScreenDestination)
}
}
@@ -256,12 +249,11 @@ class MainActivity : EhActivity() {
var drawerLocked by mutableStateOf(false)
private var openDrawerFlow = MutableSharedFlow<Unit>(extraBufferCapacity = 1)
private var openSideSheetFlow = MutableSharedFlow<Unit>(extraBufferCapacity = 1)
private var recomposeFlow = MutableSharedFlow<Unit>(extraBufferCapacity = 1)
fun recompose() {
recomposeFlow.tryEmit(Unit)
}
private var tipFlow = MutableSharedFlow<String>(extraBufferCapacity = 1)
private var navigator: NavController? = null
private val isInitializedFlow = MutableStateFlow(false)
@SuppressLint("UnusedMaterial3ScaffoldPaddingParameter")
override fun onCreate(savedInstanceState: Bundle?) {
installSplashScreen()
super.onCreate(savedInstanceState)
@@ -270,8 +262,13 @@ class MainActivity : EhActivity() {
val dialogState = LocalDialogState.current
val drawerState = rememberDrawerState(DrawerValue.Closed)
val scope = rememberCoroutineScope()
val recomposeScope = currentRecomposeScope
fun isSelected(id: Int) = ::navController.isInitialized && id == navController.currentDestination?.id
val navController = rememberNavController()
DisposableEffect(navController) {
navigator = navController
onDispose {
navigator = null
}
}
fun closeDrawer(callback: () -> Unit = {}) = scope.launch {
drawerState.close()
callback()
@@ -293,105 +290,94 @@ class MainActivity : EhActivity() {
drawerState.open()
}
}
val snackbarState = remember { SnackbarHostState() }
LaunchedEffect(Unit) {
recomposeFlow.collect {
recomposeScope.invalidate()
tipFlow.collectLatest {
snackbarState.showSnackbar(it)
}
}
LocalTouchSlopProvider(Settings.touchSlopFactor.toFloat()) {
ModalNavigationDrawer(
drawerContent = {
ModalDrawerSheet(
modifier = Modifier.widthIn(max = (configuration.screenWidthDp - 56).dp),
windowInsets = WindowInsets(0, 0, 0, 0),
) {
val scrollState = rememberScrollState()
Column(
modifier = Modifier.verticalScroll(scrollState).navigationBarsPadding(),
val currentDestination by navController.currentDestinationAsState()
Scaffold(snackbarHost = { SnackbarHost(snackbarState) }) {
LocalTouchSlopProvider(Settings.touchSlopFactor.toFloat()) {
ModalNavigationDrawer(
drawerContent = {
ModalDrawerSheet(
modifier = Modifier.widthIn(max = (configuration.screenWidthDp - 56).dp),
windowInsets = WindowInsets(0, 0, 0, 0),
) {
Image(
painter = painterResource(id = R.drawable.sadpanda_low_poly),
contentDescription = null,
modifier = Modifier.fillMaxWidth().padding(bottom = 8.dp),
contentScale = ContentScale.FillWidth,
)
navItems.forEach { (id, stringId, icon) ->
val scrollState = rememberScrollState()
Column(
modifier = Modifier.verticalScroll(scrollState).navigationBarsPadding(),
) {
Image(
painter = painterResource(id = R.drawable.sadpanda_low_poly),
contentDescription = null,
modifier = Modifier.fillMaxWidth().padding(bottom = 8.dp),
contentScale = ContentScale.FillWidth,
)
navItems.forEach { (direction, stringId, icon) ->
NavigationDrawerItem(
label = {
Text(text = stringResource(id = stringId))
},
selected = currentDestination === direction,
onClick = {
navController.navigate(direction.route)
closeDrawer()
},
modifier = Modifier.padding(horizontal = 12.dp),
icon = {
Icon(imageVector = icon, contentDescription = null)
},
)
}
NavigationDrawerItem(
label = {
Text(text = stringResource(id = stringId))
Text(text = stringResource(id = R.string.settings))
},
selected = isSelected(id),
selected = false,
onClick = {
if (id == R.id.nav_settings) {
closeDrawer {
onNavDestinationSelected2(id, navController)
}
} else {
closeDrawer()
onNavDestinationSelected2(id, navController)
}
closeDrawer { startActivity(Intent(applicationContext, ConfigureActivity::class.java)) }
},
modifier = Modifier.padding(horizontal = 12.dp),
icon = {
Icon(imageVector = icon, contentDescription = null)
Icon(imageVector = Icons.Default.Settings, contentDescription = null)
},
)
}
}
}
},
drawerState = drawerState,
gesturesEnabled = !drawerLocked || drawerState.isOpen,
) {
val sheet = sideSheet.firstOrNull()
val sideDrawerState = rememberDrawerState(DrawerValue.Closed)
LaunchedEffect(Unit) {
openSideSheetFlow.collectLatest {
sideDrawerState.open()
}
}
SideDrawer(
drawerContent = {
if (sheet != null) {
ModalDrawerSheet(
modifier = Modifier.widthIn(max = (configuration.screenWidthDp - 112).dp),
drawerShape = ShapeDefaults.Large.copy(topEnd = CornerSize(0), bottomEnd = CornerSize(0)),
windowInsets = WindowInsets.systemBars.only(WindowInsetsSides.Top + WindowInsetsSides.End),
) {
sheet(sideDrawerState)
}
}
},
drawerState = sideDrawerState,
gesturesEnabled = sheet != null && !drawerLocked,
drawerState = drawerState,
gesturesEnabled = !drawerLocked || drawerState.isOpen,
) {
val insets = buildWindowInsets {
set(
WindowInsetsCompat.Type.statusBars(),
WindowInsets.statusBars,
)
set(
WindowInsetsCompat.Type.navigationBars(),
WindowInsets.navigationBars,
)
set(
WindowInsetsCompat.Type.ime(),
WindowInsets.ime,
)
val sheet = sideSheet.firstOrNull()
val sideDrawerState = rememberDrawerState(DrawerValue.Closed)
LaunchedEffect(Unit) {
openSideSheetFlow.collectLatest {
sideDrawerState.open()
}
}
AndroidViewBinding(factory = { inflater, parent, attachToParent ->
ActivityMainBinding.inflate(inflater, parent, attachToParent).apply {
val navHostFragment = fragmentContainer.getFragment<NavHostFragment>()
navController = navHostFragment.navController.apply {
graph = navInflater.inflate(R.navigation.nav_graph).apply {
check(launchPage in 0..3)
setStartDestination(navItems[launchPage].first)
SideDrawer(
drawerContent = {
if (sheet != null) {
ModalDrawerSheet(
modifier = Modifier.widthIn(max = (configuration.screenWidthDp - 112).dp),
drawerShape = ShapeDefaults.Large.copy(topEnd = CornerSize(0), bottomEnd = CornerSize(0)),
windowInsets = WindowInsets.systemBars.only(WindowInsetsSides.Top + WindowInsetsSides.End),
) {
sheet(sideDrawerState)
}
}
isInitializedFlow.value = true
}
}) {
ViewCompat.dispatchApplyWindowInsets(root, insets)
},
drawerState = sideDrawerState,
gesturesEnabled = sheet != null && !drawerLocked,
) {
DestinationsNavHost(
navGraph = NavGraphs.root,
startRoute = navItems[Settings.launchPage].first,
engine = rememberNavHostEngine(rootDefaultAnimations = RootNavGraphDefaultAnimations.ACCOMPANIST_FADING),
navController = navController,
)
}
}
}
@@ -469,7 +455,7 @@ class MainActivity : EhActivity() {
if (connectivityManager.isActiveNetworkMetered) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
Snackbar.make(
findViewById(R.id.fragment_container),
findViewById(R.id.content),
R.string.metered_network_warning,
Snackbar.LENGTH_LONG,
)
@@ -504,25 +490,16 @@ class MainActivity : EhActivity() {
val result1 = GalleryDetailUrlParser.parse(text, false)
var launch: (() -> Unit)? = null
if (result1 != null) {
launch = {
navController.navAnimated(
R.id.galleryDetailScene,
bundleOf(GalleryDetailFragment.KEY_ARGS to TokenArgs(result1.gid, result1.token)),
)
}
launch = { navigator?.navigate(GalleryDetailScreenDestination(TokenArgs(result1.gid, result1.token))) }
}
val result2 = GalleryPageUrlParser.parse(text, false)
if (result2 != null) {
val args = Bundle()
args.putLong(ProgressFragment.KEY_GID, result2.gid)
args.putString(ProgressFragment.KEY_PTOKEN, result2.pToken)
args.putInt(ProgressFragment.KEY_PAGE, result2.page)
launch = { navController.navAnimated(R.id.progressScene, args) }
launch = { navigator?.navigate(ProgressScreenDestination(result2.gid, result2.pToken, result2.page)) }
}
launch?.let {
withUIContext {
val snackbar = Snackbar.make(
findViewById(R.id.fragment_container),
findViewById(R.id.content),
R.string.clipboard_gallery_url_snack_message,
Snackbar.LENGTH_SHORT,
)
@@ -548,22 +525,9 @@ class MainActivity : EhActivity() {
showTip(getString(id), length, useToast)
}
/**
* If activity is running, show snack bar, otherwise show toast
*/
fun showTip(message: CharSequence, length: Int, useToast: Boolean = false) {
if (!useToast) {
Snackbar.make(
findViewById(R.id.fragment_container),
message,
if (length == BaseScene.LENGTH_LONG) Snackbar.LENGTH_LONG else Snackbar.LENGTH_SHORT,
).show()
} else {
Toast.makeText(
this,
message,
if (length == BaseScene.LENGTH_LONG) Toast.LENGTH_LONG else Toast.LENGTH_SHORT,
).show()
if (useToast || tipFlow.tryEmit(message.toString())) {
Toast.makeText(this, message, if (length == BaseScene.LENGTH_LONG) Toast.LENGTH_LONG else Toast.LENGTH_SHORT).show()
}
}
@@ -1,5 +1,6 @@
package com.hippo.ehviewer.ui.main
import android.content.Intent
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
@@ -38,13 +39,12 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalLayoutDirection
import androidx.compose.ui.res.dimensionResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.core.os.bundleOf
import androidx.navigation.NavController
import androidx.paging.LoadState
import androidx.paging.compose.LazyPagingItems
import androidx.paging.compose.itemContentType
@@ -59,7 +59,6 @@ import com.hippo.ehviewer.icons.EhIcons
import com.hippo.ehviewer.icons.big.SadAndroid
import com.hippo.ehviewer.ui.WebViewActivity
import com.hippo.ehviewer.ui.scene.collectDetailSizeAsState
import com.hippo.ehviewer.ui.scene.navAnimated
import com.hippo.ehviewer.ui.tools.FastScrollLazyVerticalGrid
import com.hippo.ehviewer.ui.tools.FastScrollLazyVerticalStaggeredGrid
import com.hippo.ehviewer.ui.tools.LocalDialogState
@@ -80,8 +79,8 @@ fun GalleryList(
refreshState: PullToRefreshState,
onRefresh: suspend CoroutineScope.() -> Unit,
onLoading: suspend CoroutineScope.() -> Unit,
navigator: NavController,
) {
val context = LocalContext.current
val layoutDirection = LocalLayoutDirection.current
val marginH = dimensionResource(id = R.dimen.gallery_list_margin_h)
val marginV = dimensionResource(id = R.dimen.gallery_list_margin_v)
@@ -205,7 +204,11 @@ fun GalleryList(
dialogState.awaitPermissionOrCancel(title = R.string.cloudflare_bypass_failed) {
Text(text = stringResource(id = R.string.open_in_webview))
}
navigator.navAnimated(R.id.webView, bundleOf(WebViewActivity.KEY_URL to EhUrl.host))
context.startActivity(
Intent(context, WebViewActivity::class.java).apply {
putExtra(WebViewActivity.KEY_URL, EhUrl.host)
},
)
}
}
Box(
@@ -1,53 +1,6 @@
/*
* Copyright 2016 Hippo Seven
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.hippo.ehviewer.ui.scene
import android.content.res.Resources.Theme
import android.os.Bundle
import android.view.View
import androidx.core.view.SoftwareKeyboardControllerCompat
import androidx.fragment.app.Fragment
import com.hippo.ehviewer.ui.MainActivity
import rikka.core.res.resolveDrawable
abstract class BaseScene : Fragment() {
open val enableDrawerGestures = false
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
view.background = requireActivity().theme.resolveDrawable(android.R.attr.windowBackground)
// Update left drawer locked state
mainActivity?.drawerLocked = !enableDrawerGestures
hideSoftInput()
mainActivity?.recompose()
}
private val mainActivity: MainActivity?
get() = activity as? MainActivity
private fun hideSoftInput() = activity?.window?.decorView?.run {
SoftwareKeyboardControllerCompat(this)
}?.hide()
val theme: Theme
get() = requireActivity().theme
companion object {
const val LENGTH_SHORT = 0
const val LENGTH_LONG = 1
}
object BaseScene {
const val LENGTH_SHORT = 0
const val LENGTH_LONG = 1
}
@@ -1,10 +1,6 @@
package com.hippo.ehviewer.ui.scene
import android.content.Intent
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.compose.animation.core.animateDpAsState
import androidx.compose.foundation.Image
import androidx.compose.foundation.clickable
@@ -71,9 +67,6 @@ import androidx.compose.ui.res.stringArrayResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.core.content.ContextCompat
import androidx.core.os.bundleOf
import androidx.navigation.NavController
import androidx.navigation.fragment.findNavController
import com.hippo.ehviewer.EhDB
import com.hippo.ehviewer.R
import com.hippo.ehviewer.Settings
@@ -84,6 +77,7 @@ import com.hippo.ehviewer.icons.EhIcons
import com.hippo.ehviewer.icons.big.Download
import com.hippo.ehviewer.ui.MainActivity
import com.hippo.ehviewer.ui.confirmRemoveDownloadRange
import com.hippo.ehviewer.ui.destinations.GalleryDetailScreenDestination
import com.hippo.ehviewer.ui.main.DownloadCard
import com.hippo.ehviewer.ui.main.FabLayout
import com.hippo.ehviewer.ui.navToReader
@@ -98,6 +92,7 @@ import com.hippo.ehviewer.util.containsIgnoreCase
import com.hippo.ehviewer.util.findActivity
import com.hippo.ehviewer.util.mapToLongArray
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 kotlin.math.roundToInt
@@ -109,7 +104,7 @@ import sh.calvin.reorderable.rememberReorderableLazyColumnState
@Destination
@Composable
fun DownloadsScreen(navigator: NavController) {
fun DownloadsScreen(navigator: DestinationsNavigator) {
var label by rememberSaveable { mutableStateOf<String?>(null) }
var keyword by rememberSaveable { mutableStateOf<String?>(null) }
var filterType by rememberSaveable { mutableStateOf(-1) }
@@ -436,10 +431,7 @@ fun DownloadsScreen(navigator: NavController) {
}
},
onThumbClick = {
navigator.navAnimated(
R.id.galleryDetailScene,
bundleOf(GalleryDetailFragment.KEY_ARGS to GalleryInfoArgs(info.galleryInfo)),
)
navigator.navigate(GalleryDetailScreenDestination(GalleryInfoArgs(info.galleryInfo)))
},
onLongClick = {
checkedInfoMap[info.gid] = info
@@ -521,16 +513,7 @@ fun DownloadsScreen(navigator: NavController) {
}
}
class DownloadsFragment : BaseScene() {
override val enableDrawerGestures = true
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
val navController = findNavController()
return ComposeWithMD3 {
DownloadsScreen(navController)
}
}
class DownloadsFragment {
companion object {
const val KEY_GID = "gid"
const val KEY_ACTION = "action"
@@ -1,9 +1,5 @@
package com.hippo.ehviewer.ui.scene
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.WindowInsets
@@ -49,10 +45,7 @@ import androidx.compose.ui.input.nestedscroll.NestedScrollSource
import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.core.os.bundleOf
import androidx.lifecycle.viewModelScope
import androidx.navigation.NavController
import androidx.navigation.fragment.findNavController
import androidx.paging.LoadState
import androidx.paging.Pager
import androidx.paging.PagingConfig
@@ -76,6 +69,7 @@ import com.hippo.ehviewer.collectAsState
import com.hippo.ehviewer.icons.EhIcons
import com.hippo.ehviewer.icons.filled.GoTo
import com.hippo.ehviewer.ui.MainActivity
import com.hippo.ehviewer.ui.destinations.GalleryDetailScreenDestination
import com.hippo.ehviewer.ui.main.FabLayout
import com.hippo.ehviewer.ui.main.GalleryInfoGridItem
import com.hippo.ehviewer.ui.main.GalleryInfoListItem
@@ -86,6 +80,7 @@ import com.hippo.ehviewer.ui.tools.rememberInVM
import com.hippo.ehviewer.util.findActivity
import com.hippo.ehviewer.util.mapToLongArray
import com.ramcosta.composedestinations.annotation.Destination
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
import eu.kanade.tachiyomi.util.lang.withIOContext
import java.time.Instant
import java.time.LocalDateTime
@@ -100,7 +95,7 @@ import moe.tarsin.coroutines.runSuspendCatching
@Destination
@Composable
fun FavouritesScreen(navigator: NavController) {
fun FavouritesScreen(navigator: DestinationsNavigator) {
// Meta State
var urlBuilder by rememberSaveable { mutableStateOf(FavListUrlBuilder(favCat = Settings.recentFavCat)) }
var searchBarOffsetY by remember { mutableStateOf(0) }
@@ -276,10 +271,7 @@ fun FavouritesScreen(navigator: NavController) {
checkedInfoMap[info.gid] = info
}
} else {
navigator.navAnimated(
R.id.galleryDetailScene,
bundleOf(GalleryDetailFragment.KEY_ARGS to GalleryInfoArgs(info)),
)
navigator.navigate(GalleryDetailScreenDestination(GalleryInfoArgs(info)))
}
},
onLongClick = {
@@ -305,10 +297,7 @@ fun FavouritesScreen(navigator: NavController) {
checkedInfoMap[info.gid] = info
}
} else {
navigator.navAnimated(
R.id.galleryDetailScene,
bundleOf(GalleryDetailFragment.KEY_ARGS to GalleryInfoArgs(info)),
)
navigator.navigate(GalleryDetailScreenDestination(GalleryInfoArgs(info)))
}
},
onLongClick = {
@@ -322,7 +311,6 @@ fun FavouritesScreen(navigator: NavController) {
refreshState = refreshState,
onRefresh = { refresh() },
onLoading = { searchBarOffsetY = 0 },
navigator = navigator,
)
}
@@ -427,14 +415,3 @@ fun FavouritesScreen(navigator: NavController) {
}
}
}
class FavoritesFragment : BaseScene() {
override val enableDrawerGestures = true
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
return ComposeWithMD3 {
val navController = remember { findNavController() }
FavouritesScreen(navController)
}
}
}
@@ -3,14 +3,10 @@ package com.hippo.ehviewer.ui.scene
import android.annotation.SuppressLint
import android.content.Context
import android.graphics.Typeface
import android.os.Bundle
import android.text.SpannableStringBuilder
import android.text.style.ForegroundColorSpan
import android.text.style.RelativeSizeSpan
import android.text.style.StyleSpan
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.foundation.layout.Arrangement
@@ -79,8 +75,6 @@ import androidx.compose.ui.unit.max
import androidx.compose.ui.util.lerp
import androidx.core.text.inSpans
import androidx.core.text.parseAsHtml
import androidx.navigation.NavController
import androidx.navigation.fragment.findNavController
import com.hippo.ehviewer.R
import com.hippo.ehviewer.client.EhEngine
import com.hippo.ehviewer.client.EhFilter.remember
@@ -91,11 +85,11 @@ import com.hippo.ehviewer.client.data.ListUrlBuilder
import com.hippo.ehviewer.dao.Filter
import com.hippo.ehviewer.dao.FilterMode
import com.hippo.ehviewer.ui.MainActivity
import com.hippo.ehviewer.ui.destinations.GalleryListScreenDestination
import com.hippo.ehviewer.ui.jumpToReaderByPage
import com.hippo.ehviewer.ui.legacy.CoilImageGetter
import com.hippo.ehviewer.ui.main.GalleryCommentCard
import com.hippo.ehviewer.ui.openBrowser
import com.hippo.ehviewer.ui.scene.GalleryListFragment.Companion.toStartArgs
import com.hippo.ehviewer.ui.tools.LocalDialogState
import com.hippo.ehviewer.ui.tools.animateFloatMergePredictiveBackAsState
import com.hippo.ehviewer.ui.tools.normalizeSpan
@@ -108,8 +102,8 @@ import com.hippo.ehviewer.util.ReadableTime
import com.hippo.ehviewer.util.TextUrl
import com.hippo.ehviewer.util.addTextToClipboard
import com.hippo.ehviewer.util.findActivity
import com.hippo.ehviewer.util.getParcelableCompat
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.withIOContext
import eu.kanade.tachiyomi.util.lang.withUIContext
@@ -157,7 +151,7 @@ private val MinimumContentPaddingEditText = 88.dp
@Destination
@Composable
fun GalleryCommentsScreen(galleryDetail: GalleryDetail, navigator: NavController) {
fun GalleryCommentsScreen(galleryDetail: GalleryDetail, navigator: DestinationsNavigator) {
val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior()
val dialogState = LocalDialogState.current
val coroutineScope = rememberCoroutineScope()
@@ -374,7 +368,7 @@ fun GalleryCommentsScreen(galleryDetail: GalleryDetail, navigator: NavController
mode = ListUrlBuilder.MODE_UPLOADER,
mKeyword = item.user,
)
navigator.navAnimated(R.id.galleryListScene, lub.toStartArgs(), true)
navigator.navigate(GalleryListScreenDestination(lub))
},
onCardClick = {
coroutineScope.launch {
@@ -480,21 +474,3 @@ fun GalleryCommentsScreen(galleryDetail: GalleryDetail, navigator: NavController
}
}
}
class GalleryCommentsFragment : BaseScene() {
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?,
): View {
return ComposeWithMD3 {
val galleryDetail = remember { requireArguments().getParcelableCompat<GalleryDetail>(KEY_GALLERY_DETAIL)!! }
val navController = remember { findNavController() }
GalleryCommentsScreen(galleryDetail = galleryDetail, navigator = navController)
}
}
companion object {
const val KEY_GALLERY_DETAIL = "gallery_detail"
}
}
@@ -5,13 +5,10 @@ import android.app.Dialog
import android.app.DownloadManager
import android.content.DialogInterface
import android.net.Uri
import android.os.Bundle
import android.os.Environment
import android.os.Parcelable
import android.text.TextUtils.TruncateAt.END
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ArrayAdapter
import androidx.annotation.StringRes
import androidx.compose.foundation.clickable
@@ -22,6 +19,7 @@ import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
@@ -51,6 +49,7 @@ import androidx.compose.material3.FilledTonalButton
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.LargeTopAppBar
import androidx.compose.material3.ModalBottomSheet
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
@@ -77,10 +76,7 @@ import androidx.compose.ui.res.dimensionResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import androidx.core.os.bundleOf
import androidx.core.text.parseAsHtml
import androidx.navigation.NavController
import androidx.navigation.fragment.findNavController
import arrow.core.partially1
import coil.imageLoader
import com.google.android.material.snackbar.Snackbar
@@ -125,6 +121,10 @@ import com.hippo.ehviewer.spider.SpiderQueen.Companion.MODE_READ
import com.hippo.ehviewer.ui.GalleryInfoBottomSheet
import com.hippo.ehviewer.ui.MainActivity
import com.hippo.ehviewer.ui.confirmRemoveDownload
import com.hippo.ehviewer.ui.destinations.GalleryCommentsScreenDestination
import com.hippo.ehviewer.ui.destinations.GalleryDetailScreenDestination
import com.hippo.ehviewer.ui.destinations.GalleryListScreenDestination
import com.hippo.ehviewer.ui.destinations.GalleryPreviewScreenDestination
import com.hippo.ehviewer.ui.getFavoriteIcon
import com.hippo.ehviewer.ui.jumpToReaderByPage
import com.hippo.ehviewer.ui.legacy.BaseDialogBuilder
@@ -138,7 +138,6 @@ import com.hippo.ehviewer.ui.main.GalleryTags
import com.hippo.ehviewer.ui.modifyFavorites
import com.hippo.ehviewer.ui.navToReader
import com.hippo.ehviewer.ui.openBrowser
import com.hippo.ehviewer.ui.scene.GalleryListFragment.Companion.toStartArgs
import com.hippo.ehviewer.ui.startDownload
import com.hippo.ehviewer.ui.tools.CrystalCard
import com.hippo.ehviewer.ui.tools.FilledTertiaryIconButton
@@ -152,10 +151,10 @@ import com.hippo.ehviewer.util.FavouriteStatusRouter
import com.hippo.ehviewer.util.FileUtils
import com.hippo.ehviewer.util.addTextToClipboard
import com.hippo.ehviewer.util.findActivity
import com.hippo.ehviewer.util.getParcelableCompat
import com.hippo.ehviewer.util.isAtLeastQ
import com.hippo.ehviewer.util.requestPermission
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.launchUI
import eu.kanade.tachiyomi.util.lang.withIOContext
@@ -215,7 +214,7 @@ private fun List<GalleryTagGroup>.getArtist(): String? {
@Destination
@Composable
fun GalleryDetailScreen(args: GalleryDetailScreenArgs, navigator: NavController) {
fun GalleryDetailScreen(args: GalleryDetailScreenArgs, navigator: DestinationsNavigator) {
var galleryInfo by rememberSaveable {
val casted = args as? GalleryInfoArgs
mutableStateOf<GalleryInfo?>(casted?.galleryInfo)
@@ -234,7 +233,7 @@ fun GalleryDetailScreen(args: GalleryDetailScreenArgs, navigator: NavController)
val gi = galleryInfo
if (page != 0 && gi != null) {
Snackbar.make(
activity.findViewById(R.id.fragment_container),
activity.findViewById(R.id.content),
context.getString(R.string.read_from, page),
Snackbar.LENGTH_LONG,
).setAction(R.string.read) { context.navToReader(gi.findBaseInfo(), page) }.show()
@@ -430,13 +429,7 @@ fun GalleryDetailScreen(args: GalleryDetailScreenArgs, navigator: NavController)
fun navigateToPreview(nextPage: Boolean = false) {
(galleryInfo as? GalleryDetail)?.let {
navigator.navAnimated(
R.id.galleryPreviewsScene,
bundleOf(
KEY_GALLERY_DETAIL to it,
KEY_NEXT_PAGE to nextPage,
),
)
navigator.navigate(GalleryPreviewScreenDestination(it, nextPage))
}
}
@@ -489,10 +482,7 @@ fun GalleryDetailScreen(args: GalleryDetailScreenArgs, navigator: NavController)
else -> stringResource(R.string.more_comment)
}
fun onNavigateToCommentScene() {
navigator.navAnimated(
R.id.galleryCommentsScene,
bundleOf(GalleryCommentsFragment.KEY_GALLERY_DETAIL to galleryDetail),
)
navigator.navigate(GalleryCommentsScreenDestination(galleryDetail))
}
CrystalCard {
commentsList.take(maxShowCount).forEach { item ->
@@ -533,10 +523,7 @@ fun GalleryDetailScreen(args: GalleryDetailScreenArgs, navigator: NavController)
it.title,
it.posted,
) to {
navigator.navAnimated(
R.id.galleryDetailScene,
bundleOf(GalleryDetailFragment.KEY_ARGS to TokenArgs(it.gid, it.token!!)),
)
navigator.navigate(GalleryDetailScreenDestination(TokenArgs(it.gid, it.token!!)))
}
}.toTypedArray()
val navAction = dialogState.showSelectItem(*items)
@@ -610,31 +597,31 @@ fun GalleryDetailScreen(args: GalleryDetailScreenArgs, navigator: NavController)
val keyword = EhUtils.extractTitle(galleryDetail.title)
val artist = galleryDetail.tags.getArtist()
if (null != keyword) {
navigator.navAnimated(
R.id.galleryListScene,
ListUrlBuilder(
mode = ListUrlBuilder.MODE_NORMAL,
mKeyword = "\"" + keyword + "\"",
).toStartArgs(),
true,
navigator.navigate(
GalleryListScreenDestination(
ListUrlBuilder(
mode = ListUrlBuilder.MODE_NORMAL,
mKeyword = "\"" + keyword + "\"",
),
),
)
} else if (artist != null) {
navigator.navAnimated(
R.id.galleryListScene,
ListUrlBuilder(
mode = ListUrlBuilder.MODE_TAG,
mKeyword = "artist:$artist",
).toStartArgs(),
true,
navigator.navigate(
GalleryListScreenDestination(
ListUrlBuilder(
mode = ListUrlBuilder.MODE_TAG,
mKeyword = "artist:$artist",
),
),
)
} else if (null != galleryDetail.uploader) {
navigator.navAnimated(
R.id.galleryListScene,
ListUrlBuilder(
mode = ListUrlBuilder.MODE_UPLOADER,
mKeyword = galleryDetail.uploader,
).toStartArgs(),
true,
navigator.navigate(
GalleryListScreenDestination(
ListUrlBuilder(
mode = ListUrlBuilder.MODE_UPLOADER,
mKeyword = galleryDetail.uploader,
),
),
)
}
},
@@ -644,12 +631,13 @@ fun GalleryDetailScreen(args: GalleryDetailScreenArgs, navigator: NavController)
text = stringResource(id = R.string.search_cover),
onClick = {
val key = galleryDetail.thumbKey.orEmpty()
navigator.navAnimated(
R.id.galleryListScene,
ListUrlBuilder(
mode = ListUrlBuilder.MODE_NORMAL,
hash = key.substringAfterLast('/').substringBefore('-'),
).toStartArgs(),
navigator.navigate(
GalleryListScreenDestination(
ListUrlBuilder(
mode = ListUrlBuilder.MODE_NORMAL,
hash = key.substringAfterLast('/').substringBefore('-'),
),
),
)
},
)
@@ -851,7 +839,7 @@ fun GalleryDetailScreen(args: GalleryDetailScreenArgs, navigator: NavController)
val lub = ListUrlBuilder()
lub.mode = ListUrlBuilder.MODE_TAG
lub.keyword = it
navigator.navAnimated(R.id.galleryListScene, lub.toStartArgs(), true)
navigator.navigate(GalleryListScreenDestination(lub))
},
onTagLongClick = { translated, tag ->
val index = tag.indexOf(':')
@@ -943,7 +931,7 @@ fun GalleryDetailScreen(args: GalleryDetailScreenArgs, navigator: NavController)
return
}
val lub = ListUrlBuilder(category = category)
navigator.navAnimated(R.id.galleryListScene, lub.toStartArgs(), true)
navigator.navigate(GalleryListScreenDestination(lub))
}
fun onUploaderChipClick() {
val uploader = galleryInfo.uploader
@@ -954,12 +942,24 @@ fun GalleryDetailScreen(args: GalleryDetailScreenArgs, navigator: NavController)
val lub = ListUrlBuilder()
lub.mode = ListUrlBuilder.MODE_UPLOADER
lub.keyword = uploader
navigator.navAnimated(R.id.galleryListScene, lub.toStartArgs(), true)
navigator.navigate(GalleryListScreenDestination(lub))
}
var showBottomSheet by remember { mutableStateOf(false) }
if (showBottomSheet && galleryDetail != null) {
ModalBottomSheet(
onDismissRequest = { showBottomSheet = false },
windowInsets = WindowInsets(0, 0, 0, 0),
) {
GalleryInfoBottomSheet(galleryDetail, navigator)
}
}
fun onGalleryInfoCardClick() {
galleryDetail ?: return
GalleryInfoBottomSheet(galleryDetail).show(activity.supportFragmentManager, "GalleryInfoBottomSheet")
showBottomSheet = true
}
fun showFilterUploaderDialog() {
val uploader = galleryInfo.uploader
val disowned = uploader == "(Disowned)"
@@ -1232,18 +1232,3 @@ fun GalleryDetailScreen(args: GalleryDetailScreenArgs, navigator: NavController)
}
}
}
class GalleryDetailFragment : BaseScene() {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
val args = requireNotNull(arguments)
val composeArgs = requireNotNull(args.getParcelableCompat<GalleryDetailScreenArgs>(KEY_ARGS))
return ComposeWithMD3 {
val navigator = remember { findNavController() }
GalleryDetailScreen(composeArgs, navigator)
}
}
companion object {
const val KEY_ARGS = "args"
}
}
@@ -2,11 +2,7 @@ package com.hippo.ehviewer.ui.scene
import android.graphics.Bitmap
import android.net.Uri
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewConfiguration
import android.view.ViewGroup
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.core.animateDpAsState
@@ -93,10 +89,7 @@ import androidx.compose.ui.unit.dp
import androidx.compose.ui.util.fastAny
import androidx.compose.ui.util.fastForEach
import androidx.compose.ui.util.lerp
import androidx.core.os.bundleOf
import androidx.lifecycle.viewModelScope
import androidx.navigation.NavController
import androidx.navigation.fragment.findNavController
import androidx.paging.LoadState
import androidx.paging.Pager
import androidx.paging.PagingConfig
@@ -133,6 +126,9 @@ import com.hippo.ehviewer.icons.EhIcons
import com.hippo.ehviewer.icons.filled.GoTo
import com.hippo.ehviewer.image.Image.Companion.decodeBitmap
import com.hippo.ehviewer.ui.MainActivity
import com.hippo.ehviewer.ui.destinations.GalleryDetailScreenDestination
import com.hippo.ehviewer.ui.destinations.GalleryListScreenDestination
import com.hippo.ehviewer.ui.destinations.ProgressScreenDestination
import com.hippo.ehviewer.ui.doGalleryInfoAction
import com.hippo.ehviewer.ui.legacy.BaseDialogBuilder
import com.hippo.ehviewer.ui.main.AdvancedSearchOption
@@ -144,7 +140,6 @@ import com.hippo.ehviewer.ui.main.GalleryList
import com.hippo.ehviewer.ui.main.ImageSearch
import com.hippo.ehviewer.ui.main.NormalSearch
import com.hippo.ehviewer.ui.main.SearchAdvanced
import com.hippo.ehviewer.ui.scene.GalleryListFragment.Companion.toStartArgs
import com.hippo.ehviewer.ui.tools.Deferred
import com.hippo.ehviewer.ui.tools.DragHandle
import com.hippo.ehviewer.ui.tools.LocalDialogState
@@ -155,9 +150,10 @@ import com.hippo.ehviewer.ui.tools.observed
import com.hippo.ehviewer.ui.tools.rememberInVM
import com.hippo.ehviewer.util.AppConfig
import com.hippo.ehviewer.util.findActivity
import com.hippo.ehviewer.util.getParcelableCompat
import com.hippo.ehviewer.util.pickVisualMedia
import com.ramcosta.composedestinations.annotation.Destination
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
import com.ramcosta.composedestinations.spec.Direction
import eu.kanade.tachiyomi.util.lang.launchIO
import eu.kanade.tachiyomi.util.lang.withIOContext
import eu.kanade.tachiyomi.util.lang.withUIContext
@@ -177,7 +173,27 @@ import sh.calvin.reorderable.rememberReorderableLazyColumnState
@Destination
@Composable
fun GalleryListScreen(lub: ListUrlBuilder, navigator: NavController) {
fun HomePageScreen(navigator: DestinationsNavigator) =
GalleryListScreen(ListUrlBuilder(), navigator)
@Destination
@Composable
fun SubscriptionScreen(navigator: DestinationsNavigator) =
GalleryListScreen(ListUrlBuilder(MODE_SUBSCRIPTION), navigator)
@Destination
@Composable
fun WhatshotScreen(navigator: DestinationsNavigator) =
GalleryListScreen(ListUrlBuilder(MODE_WHATS_HOT), navigator)
@Destination
@Composable
fun ToplistScreen(navigator: DestinationsNavigator) =
GalleryListScreen(ListUrlBuilder(MODE_TOPLIST, mKeyword = Settings.recentToplist), navigator)
@Destination
@Composable
fun GalleryListScreen(lub: ListUrlBuilder, navigator: DestinationsNavigator) {
val searchFieldState = rememberTextFieldState()
var urlBuilder by rememberSaveable(lub) { mutableStateOf(lub) }
var searchBarOffsetY by remember { mutableStateOf(0) }
@@ -453,7 +469,7 @@ fun GalleryListScreen(lub: ListUrlBuilder, navigator: NavController) {
ListItem(
modifier = Modifier.clickable {
if (urlBuilder.mode == MODE_WHATS_HOT) {
navigator.navAnimated(R.id.galleryListScene, ListUrlBuilder(item).toStartArgs())
navigator.navigate(GalleryListScreenDestination(ListUrlBuilder(item)))
} else {
urlBuilder = ListUrlBuilder(item)
data.refresh()
@@ -513,19 +529,17 @@ fun GalleryListScreen(lub: ListUrlBuilder, navigator: NavController) {
override val keyword = openGalleryKeyword
override val canOpenDirectly = true
override fun onClick() {
navigator.navAnimated(destination, args)
navigator.navigate(destination)
showSearchLayout = false
}
abstract val destination: Int
abstract val args: Bundle
abstract val destination: Direction
}
class GalleryDetailUrlSuggestion(
gid: Long,
token: String,
) : UrlSuggestion() {
override val destination = R.id.galleryDetailScene
override val args = bundleOf(GalleryDetailFragment.KEY_ARGS to TokenArgs(gid, token))
override val destination = GalleryDetailScreenDestination(TokenArgs(gid, token))
}
class GalleryPageUrlSuggestion(
@@ -533,12 +547,7 @@ fun GalleryListScreen(lub: ListUrlBuilder, navigator: NavController) {
pToken: String,
page: Int,
) : UrlSuggestion() {
override val destination = R.id.progressScene
override val args = bundleOf(
ProgressFragment.KEY_GID to gid,
ProgressFragment.KEY_PTOKEN to pToken,
ProgressFragment.KEY_PAGE to page,
)
override val destination = ProgressScreenDestination(gid, pToken, page)
}
var expanded by remember { mutableStateOf(false) }
@@ -603,7 +612,7 @@ fun GalleryListScreen(lub: ListUrlBuilder, navigator: NavController) {
MODE_TOPLIST, MODE_WHATS_HOT -> {
// Wait for search view to hide
delay(300)
withUIContext { navigator.navAnimated(R.id.galleryListScene, builder.toStartArgs()) }
withUIContext { navigator.navigate(GalleryListScreenDestination(builder)) }
}
else -> {
urlBuilder = builder
@@ -754,10 +763,7 @@ fun GalleryListScreen(lub: ListUrlBuilder, navigator: NavController) {
detailItemContent = { info ->
GalleryInfoListItem(
onClick = {
navigator.navAnimated(
R.id.galleryDetailScene,
bundleOf(GalleryDetailFragment.KEY_ARGS to GalleryInfoArgs(info)),
)
navigator.navigate(GalleryDetailScreenDestination(GalleryInfoArgs(info)))
},
onLongClick = {
coroutineScope.launch {
@@ -774,10 +780,7 @@ fun GalleryListScreen(lub: ListUrlBuilder, navigator: NavController) {
thumbItemContent = { info ->
GalleryInfoGridItem(
onClick = {
navigator.navAnimated(
R.id.galleryDetailScene,
bundleOf(GalleryDetailFragment.KEY_ARGS to GalleryInfoArgs(info)),
)
navigator.navigate(GalleryDetailScreenDestination(GalleryInfoArgs(info)))
},
onLongClick = {
coroutineScope.launch {
@@ -793,7 +796,6 @@ fun GalleryListScreen(lub: ListUrlBuilder, navigator: NavController) {
data.refresh()
},
onLoading = { searchBarOffsetY = 0 },
navigator = navigator,
)
}
@@ -865,37 +867,6 @@ fun GalleryListScreen(lub: ListUrlBuilder, navigator: NavController) {
}
}
class GalleryListFragment : BaseScene() {
override val enableDrawerGestures = true
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
val navController = findNavController()
val args = when (arguments?.getString(KEY_ACTION) ?: ACTION_HOMEPAGE) {
ACTION_HOMEPAGE -> ListUrlBuilder()
ACTION_SUBSCRIPTION -> ListUrlBuilder(MODE_SUBSCRIPTION)
ACTION_WHATS_HOT -> ListUrlBuilder(MODE_WHATS_HOT)
ACTION_TOP_LIST -> ListUrlBuilder(MODE_TOPLIST, mKeyword = Settings.recentToplist)
ACTION_LIST_URL_BUILDER -> arguments?.getParcelableCompat<ListUrlBuilder>(KEY_LIST_URL_BUILDER)?.copy() ?: ListUrlBuilder()
else -> error("Wrong KEY_ACTION:${arguments?.getString(KEY_ACTION)} when handle args!")
}
return ComposeWithMD3 { GalleryListScreen(args, navController) }
}
companion object {
const val KEY_ACTION = "action"
const val ACTION_HOMEPAGE = "action_homepage"
const val ACTION_SUBSCRIPTION = "action_subscription"
const val ACTION_WHATS_HOT = "action_whats_hot"
const val ACTION_TOP_LIST = "action_top_list"
const val ACTION_LIST_URL_BUILDER = "action_list_url_builder"
const val KEY_LIST_URL_BUILDER = "list_url_builder"
fun ListUrlBuilder.toStartArgs() = bundleOf(
KEY_ACTION to ACTION_LIST_URL_BUILDER,
KEY_LIST_URL_BUILDER to this,
)
}
}
private const val TOPLIST_PAGES = 200
@Composable
@@ -1,9 +1,5 @@
package com.hippo.ehviewer.ui.scene
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.grid.GridCells
@@ -20,7 +16,6 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
@@ -30,10 +25,8 @@ import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.dimensionResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.fragment.app.Fragment
import androidx.lifecycle.viewModelScope
import androidx.navigation.NavController
import androidx.navigation.fragment.findNavController
import androidx.paging.Pager
import androidx.paging.PagingConfig
import androidx.paging.PagingSource
@@ -56,13 +49,10 @@ import com.hippo.ehviewer.client.data.GalleryPreview
import com.hippo.ehviewer.coil.justDownload
import com.hippo.ehviewer.collectAsState
import com.hippo.ehviewer.ktbuilder.imageRequest
import com.hippo.ehviewer.ui.MainActivity
import com.hippo.ehviewer.ui.main.EhPreviewItem
import com.hippo.ehviewer.ui.navToReader
import com.hippo.ehviewer.ui.tools.FastScrollLazyVerticalGrid
import com.hippo.ehviewer.ui.tools.rememberInVM
import com.hippo.ehviewer.util.findActivity
import com.hippo.ehviewer.util.getParcelableCompat
import com.ramcosta.composedestinations.annotation.Destination
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
@@ -157,22 +147,3 @@ fun GalleryPreviewScreen(galleryDetail: GalleryDetail, toNextPageArg: Boolean, n
}
}
}
class GalleryPreviewFragment : Fragment() {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
return ComposeWithMD3 {
val galleryDetail = remember { requireArguments().getParcelableCompat<GalleryDetail>(KEY_GALLERY_DETAIL)!! }
val toNextPage = remember { requireArguments().getBoolean(KEY_NEXT_PAGE) }
val navController = remember { findNavController() }
GalleryPreviewScreen(galleryDetail, toNextPage, navController)
}
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
requireContext().findActivity<MainActivity>().recompose()
}
}
const val KEY_GALLERY_DETAIL = "gallery_detail"
const val KEY_NEXT_PAGE = "next_page"
@@ -1,9 +1,5 @@
package com.hippo.ehviewer.ui.scene
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
@@ -27,7 +23,6 @@ import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.material3.rememberDismissState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
@@ -36,10 +31,7 @@ import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.dimensionResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.core.os.bundleOf
import androidx.lifecycle.viewModelScope
import androidx.navigation.NavController
import androidx.navigation.fragment.findNavController
import androidx.paging.Pager
import androidx.paging.PagingConfig
import androidx.paging.cachedIn
@@ -51,6 +43,7 @@ import com.hippo.ehviewer.R
import com.hippo.ehviewer.icons.EhIcons
import com.hippo.ehviewer.icons.big.History
import com.hippo.ehviewer.ui.MainActivity
import com.hippo.ehviewer.ui.destinations.GalleryDetailScreenDestination
import com.hippo.ehviewer.ui.doGalleryInfoAction
import com.hippo.ehviewer.ui.main.GalleryInfoListItem
import com.hippo.ehviewer.ui.tools.Deferred
@@ -60,12 +53,13 @@ import com.hippo.ehviewer.ui.tools.SwipeToDismissBox2
import com.hippo.ehviewer.ui.tools.rememberInVM
import com.hippo.ehviewer.util.findActivity
import com.ramcosta.composedestinations.annotation.Destination
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
import eu.kanade.tachiyomi.util.lang.launchIO
import kotlinx.coroutines.delay
@Destination
@Composable
fun HistoryScreen(navigator: NavController) {
fun HistoryScreen(navigator: DestinationsNavigator) {
val context = LocalContext.current
val dialogState = LocalDialogState.current
val coroutineScope = rememberCoroutineScope()
@@ -133,10 +127,7 @@ fun HistoryScreen(navigator: NavController) {
) {
GalleryInfoListItem(
onClick = {
navigator.navAnimated(
R.id.galleryDetailScene,
bundleOf(GalleryDetailFragment.KEY_ARGS to GalleryInfoArgs(info)),
)
navigator.navigate(GalleryDetailScreenDestination(GalleryInfoArgs(info)))
},
onLongClick = {
coroutineScope.launchIO {
@@ -173,14 +164,3 @@ fun HistoryScreen(navigator: NavController) {
}
}
}
class HistoryFragment : BaseScene() {
override val enableDrawerGestures = true
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
return ComposeWithMD3 {
val navController = remember { findNavController() }
HistoryScreen(navController)
}
}
}
@@ -1,65 +1,55 @@
package com.hippo.ehviewer.ui.scene
import android.annotation.SuppressLint
import android.os.Bundle
import androidx.annotation.MainThread
import androidx.core.os.bundleOf
import androidx.fragment.app.Fragment
import androidx.navigation.NavController
import androidx.navigation.NavOptions
import androidx.navigation.fragment.findNavController
import com.hippo.ehviewer.R
import com.hippo.ehviewer.client.parser.GalleryDetailUrlParser
import com.hippo.ehviewer.client.parser.GalleryListUrlParser
import com.hippo.ehviewer.client.parser.GalleryPageUrlParser
import com.hippo.ehviewer.ui.destinations.GalleryDetailScreenDestination
import com.hippo.ehviewer.ui.destinations.GalleryListScreenDestination
import com.hippo.ehviewer.ui.destinations.ProgressScreenDestination
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
import com.ramcosta.composedestinations.spec.Direction
@MainThread
@SuppressLint("PrivateResource")
fun NavController.navAnimated(id: Int, args: Bundle?, singleTop: Boolean = false) {
val options: NavOptions = NavOptions.Builder().setLaunchSingleTop(singleTop)
.setEnterAnim(androidx.fragment.R.animator.fragment_open_enter)
.setExitAnim(androidx.fragment.R.animator.fragment_open_exit)
.setPopEnterAnim(androidx.fragment.R.animator.fragment_close_enter)
.setPopExitAnim(androidx.fragment.R.animator.fragment_close_exit)
.build()
navigate(id, args, options)
}
@MainThread
fun NavController.navWithUrl(url: String): Boolean {
fun DestinationsNavigator.navWithUrl(url: String): Boolean {
if (url.isEmpty()) return false
GalleryListUrlParser.parse(url)?.let {
navAnimated(
R.id.galleryListScene,
bundleOf(
GalleryListFragment.KEY_ACTION to GalleryListFragment.ACTION_LIST_URL_BUILDER,
GalleryListFragment.KEY_LIST_URL_BUILDER to it,
),
)
navigate(GalleryListScreenDestination(it))
return true
}
GalleryDetailUrlParser.parse(url)?.apply {
navAnimated(
R.id.galleryDetailScene,
bundleOf(GalleryDetailFragment.KEY_ARGS to TokenArgs(gid, token)),
)
navigate(GalleryDetailScreenDestination(TokenArgs(gid, token)))
return true
}
GalleryPageUrlParser.parse(url)?.apply {
navAnimated(
R.id.progressScene,
bundleOf(
ProgressFragment.KEY_GID to gid,
ProgressFragment.KEY_PTOKEN to pToken,
ProgressFragment.KEY_PAGE to page,
),
)
navigate(ProgressScreenDestination(gid, pToken, page))
return true
}
return false
}
@MainThread
fun Fragment.navAnimated(id: Int, args: Bundle?, singleTop: Boolean = false) = findNavController().navAnimated(id, args, singleTop)
fun NavController.navWithUrl(url: String): Boolean {
if (url.isEmpty()) return false
GalleryListUrlParser.parse(url)?.let {
navigate(GalleryListScreenDestination(it))
return true
}
GalleryDetailUrlParser.parse(url)?.apply {
navigate(GalleryDetailScreenDestination(TokenArgs(gid, token)))
return true
}
GalleryPageUrlParser.parse(url)?.apply {
navigate(ProgressScreenDestination(gid, pToken, page))
return true
}
return false
}
@MainThread
fun NavController.navigate(direction: Direction) = navigate(direction.route)
@@ -1,9 +1,5 @@
package com.hippo.ehviewer.ui.scene
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.compose.foundation.Image
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
@@ -17,33 +13,31 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.core.os.bundleOf
import androidx.navigation.NavController
import androidx.navigation.fragment.findNavController
import com.hippo.ehviewer.R
import com.hippo.ehviewer.client.EhEngine
import com.hippo.ehviewer.icons.EhIcons
import com.hippo.ehviewer.icons.big.SadAndroid
import com.hippo.ehviewer.ui.destinations.GalleryDetailScreenDestination
import com.hippo.ehviewer.util.ExceptionUtils
import com.ramcosta.composedestinations.annotation.Destination
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
import eu.kanade.tachiyomi.util.lang.withUIContext
import moe.tarsin.coroutines.runSuspendCatching
@Destination
@Composable
fun ProgressScreen(gid: Long, token: String, page: Int, navigator: NavController) {
fun ProgressScreen(gid: Long, token: String, page: Int, navigator: DestinationsNavigator) {
val wrong = stringResource(id = R.string.error_something_wrong_happened)
var error by rememberSaveable { mutableStateOf("") }
LaunchedEffect(error) {
if (error.isEmpty()) {
if (gid == -1L || token == ProgressFragment.INVALID || page == -1) {
if (gid == -1L || token == "invalid" || page == -1) {
error = wrong
} else {
runSuspendCatching {
@@ -51,10 +45,7 @@ fun ProgressScreen(gid: Long, token: String, page: Int, navigator: NavController
}.onSuccess {
withUIContext {
navigator.popBackStack()
navigator.navAnimated(
R.id.galleryDetailScene,
bundleOf(GalleryDetailFragment.KEY_ARGS to TokenArgs(gid, it, page)),
)
navigator.navigate(GalleryDetailScreenDestination(TokenArgs(gid, it, page)))
}
}.onFailure {
error = ExceptionUtils.getReadableString(it)
@@ -84,22 +75,3 @@ fun ProgressScreen(gid: Long, token: String, page: Int, navigator: NavController
}
}
}
class ProgressFragment : BaseScene() {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
return ComposeWithMD3 {
val gid = remember { requireArguments().getLong(KEY_GID, -1) }
val token = remember { requireArguments().getString(KEY_PTOKEN, INVALID) }
val page = remember { requireArguments().getInt(KEY_PAGE, -1) }
val navController = remember { findNavController() }
ProgressScreen(gid, token, page, navController)
}
}
companion object {
const val KEY_GID = "gid"
const val KEY_PTOKEN = "ptoken"
const val KEY_PAGE = "page"
const val INVALID = "invalid"
}
}
@@ -1,15 +0,0 @@
package com.hippo.ehviewer.ui.scene
import androidx.compose.foundation.layout.consumeWindowInsets
import androidx.compose.runtime.Composable
import androidx.compose.ui.platform.ComposeView
import androidx.compose.ui.platform.ViewCompositionStrategy
import androidx.fragment.app.Fragment
import com.hippo.ehviewer.ui.setMD3Content
@Suppress("FunctionName")
inline fun Fragment.ComposeWithMD3(crossinline content: @Composable () -> Unit) = ComposeView(requireContext()).apply {
consumeWindowInsets = false
setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnLifecycleDestroyed(viewLifecycleOwner))
setMD3Content(content)
}
-23
View File
@@ -1,23 +0,0 @@
<?xml version="1.0" encoding="utf-8"?><!--
~ Copyright 2016 Hippo Seven
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<androidx.fragment.app.FragmentContainerView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/fragment_container"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:defaultNavHost="true" />
-87
View File
@@ -1,87 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/nav_graph">
<fragment
android:id="@+id/galleryListScene"
android:name="com.hippo.ehviewer.ui.scene.GalleryListFragment"
android:label="GalleryListScene" />
<fragment
android:id="@+id/nav_homepage"
android:name="com.hippo.ehviewer.ui.scene.GalleryListFragment"
android:label="GalleryListScene">
<argument
android:name="action"
android:defaultValue="action_homepage"
app:argType="string" />
</fragment>
<fragment
android:id="@+id/nav_subscription"
android:name="com.hippo.ehviewer.ui.scene.GalleryListFragment"
android:label="GalleryListScene">
<argument
android:name="action"
android:defaultValue="action_subscription"
app:argType="string" />
</fragment>
<fragment
android:id="@+id/nav_whats_hot"
android:name="com.hippo.ehviewer.ui.scene.GalleryListFragment"
android:label="GalleryListScene">
<argument
android:name="action"
android:defaultValue="action_whats_hot"
app:argType="string" />
</fragment>
<fragment
android:id="@+id/nav_toplist"
android:name="com.hippo.ehviewer.ui.scene.GalleryListFragment"
android:label="GalleryListScene">
<argument
android:name="action"
android:defaultValue="action_top_list"
app:argType="string" />
</fragment>
<fragment
android:id="@+id/galleryDetailScene"
android:name="com.hippo.ehviewer.ui.scene.GalleryDetailFragment"
android:label="GalleryDetailScene" />
<fragment
android:id="@+id/galleryCommentsScene"
android:name="com.hippo.ehviewer.ui.scene.GalleryCommentsFragment"
android:label="GalleryCommentsScene" />
<fragment
android:id="@+id/galleryPreviewsScene"
android:name="com.hippo.ehviewer.ui.scene.GalleryPreviewFragment"
android:label="GalleryPreviewsScene" />
<fragment
android:id="@+id/nav_favourite"
android:name="com.hippo.ehviewer.ui.scene.FavoritesFragment"
android:label="FavoritesScene" />
<fragment
android:id="@+id/nav_history"
android:name="com.hippo.ehviewer.ui.scene.HistoryFragment"
android:label="HistoryScene" />
<fragment
android:id="@+id/nav_downloads"
android:name="com.hippo.ehviewer.ui.scene.DownloadsFragment"
android:label="DownloadsScene" />
<activity
android:id="@+id/nav_settings"
android:name="com.hippo.ehviewer.ui.ConfigureActivity"
android:label="SettingsActivity" />
<fragment
android:id="@+id/progressScene"
android:name="com.hippo.ehviewer.ui.scene.ProgressFragment"
android:label="ProgressScene" />
<activity
android:id="@+id/webView"
android:name="com.hippo.ehviewer.ui.WebViewActivity"
android:label="WebViewActivity">
<argument
android:name="url"
android:defaultValue="@null"
app:argType="string" />
</activity>
</navigation>
+1 -2
View File
@@ -56,7 +56,6 @@ androidx-lifecycle-process = { module = "androidx.lifecycle:lifecycle-process",
androidx-lifecycle-compose = { module = "androidx.lifecycle:lifecycle-viewmodel-compose", version.ref = "androidx-lifecycle" }
androidx-navigation-compose = { module = "androidx.navigation:navigation-compose", version.ref = "androidx-navigation" }
androidx-navigation-fragment = { module = "androidx.navigation:navigation-fragment-ktx", version.ref = "androidx-navigation" }
androidx-navigation-ui = { module = "androidx.navigation:navigation-ui-ktx", version.ref = "androidx-navigation" }
androidx-paging-compose = { module = "androidx.paging:paging-compose", version.ref = "androidx-paging" }
@@ -134,7 +133,7 @@ splitties-systemservices = { module = "com.louiscad.splitties:splitties-systemse
[bundles]
accompanist = ["accompanist-themeadapter-material3", "accompanist-webview"]
androidx-navigation = ["androidx-navigation-compose", "androidx-navigation-fragment", "androidx-navigation-ui"]
androidx-navigation = ["androidx-navigation-compose", "androidx-navigation-ui"]
androidx-paging = ["androidx-paging-compose", "androidx-paging-runtime"]
androidx-recyclerview = ["androidx-recyclerview", "androidx-recyclerview-selection"]
coil = ["coil-compose", "coil-gif"]