diff --git a/app/src/main/kotlin/com/hippo/ehviewer/ui/Theme.kt b/app/src/main/kotlin/com/hippo/ehviewer/ui/Theme.kt index 2c4c43133..a6c6b378a 100644 --- a/app/src/main/kotlin/com/hippo/ehviewer/ui/Theme.kt +++ b/app/src/main/kotlin/com/hippo/ehviewer/ui/Theme.kt @@ -12,7 +12,7 @@ import com.hippo.ehviewer.ui.tools.LocalDialogState // To make sure compose theme and legacy view theme are in sync, we only use Mdc3Theme -fun ComposeView.setMD3Content(content: @Composable () -> Unit) = setContent { +inline fun ComposeView.setMD3Content(crossinline content: @Composable () -> Unit) = setContent { Mdc3Theme { val dialogState = remember { DialogState() } dialogState.Intercept() @@ -22,7 +22,7 @@ fun ComposeView.setMD3Content(content: @Composable () -> Unit) = setContent { } } -fun ComponentActivity.setMD3Content(content: @Composable () -> Unit) = setContent { +inline fun ComponentActivity.setMD3Content(crossinline content: @Composable () -> Unit) = setContent { Mdc3Theme { val dialogState = remember { DialogState() } dialogState.Intercept() diff --git a/app/src/main/kotlin/com/hippo/ehviewer/ui/scene/FavoritesScene.kt b/app/src/main/kotlin/com/hippo/ehviewer/ui/scene/FavoritesScene.kt index 3fb9a4cd8..001566c41 100644 --- a/app/src/main/kotlin/com/hippo/ehviewer/ui/scene/FavoritesScene.kt +++ b/app/src/main/kotlin/com/hippo/ehviewer/ui/scene/FavoritesScene.kt @@ -76,7 +76,6 @@ import com.hippo.ehviewer.ui.legacy.FastScroller.OnDragHandlerListener import com.hippo.ehviewer.ui.legacy.HandlerDrawable import com.hippo.ehviewer.ui.legacy.ViewTransition import com.hippo.ehviewer.ui.legacy.WindowInsetsAnimationHelper -import com.hippo.ehviewer.ui.setMD3Content import com.hippo.ehviewer.ui.tools.DialogState import com.hippo.ehviewer.util.ExceptionUtils import com.hippo.ehviewer.util.SimpleHandler @@ -225,7 +224,7 @@ class FavoritesScene : SearchBarScene() { savedInstanceState: Bundle?, ): View { _binding = SceneFavoritesBinding.inflate(inflater, container!!) - container.addView(ComposeWithViewLifecycle().apply { setMD3Content { dialogState.Intercept() } }) + container.addView(ComposeWithMD3 { dialogState.Intercept() }) setOnApplySearch { if (!tracker.isInCustomChoice) { switchFav(urlBuilder.favCat, it) @@ -439,35 +438,33 @@ class FavoritesScene : SearchBarScene() { showNormalFabsJob = null } - override fun onCreateDrawerView(inflater: LayoutInflater) = ComposeWithViewLifecycle().apply { - setMD3Content { - val localFavCount by vm.localFavCount.collectAsState(0) - ElevatedCard { - TopAppBar(title = { Text(text = stringResource(id = R.string.collections)) }) - val scope = currentRecomposeScope - LaunchedEffect(Unit) { - Settings.favChangesFlow.collect { - scope.invalidate() - } + override fun onCreateDrawerView(inflater: LayoutInflater) = ComposeWithMD3 { + val localFavCount by vm.localFavCount.collectAsState(0) + ElevatedCard { + TopAppBar(title = { Text(text = stringResource(id = R.string.collections)) }) + val scope = currentRecomposeScope + LaunchedEffect(Unit) { + Settings.favChangesFlow.collect { + scope.invalidate() } - val localFav = stringResource(id = R.string.local_favorites) to localFavCount - val faves = if (EhCookieStore.hasSignedIn()) { - arrayOf( - localFav, - stringResource(id = R.string.cloud_favorites) to Settings.favCloudCount, - *Settings.favCat.zip(Settings.favCount.toTypedArray()).toTypedArray(), + } + val localFav = stringResource(id = R.string.local_favorites) to localFavCount + val faves = if (EhCookieStore.hasSignedIn()) { + arrayOf( + localFav, + stringResource(id = R.string.cloud_favorites) to Settings.favCloudCount, + *Settings.favCat.zip(Settings.favCount.toTypedArray()).toTypedArray(), + ) + } else { + arrayOf(localFav) + } + LazyColumn { + itemsIndexed(faves) { index, (name, count) -> + ListItem( + headlineContent = { Text(text = name) }, + trailingContent = { Text(text = count.toString(), style = MaterialTheme.typography.bodyLarge) }, + modifier = Modifier.clickable { onItemClick(index) }, ) - } else { - arrayOf(localFav) - } - LazyColumn { - itemsIndexed(faves) { index, (name, count) -> - ListItem( - headlineContent = { Text(text = name) }, - trailingContent = { Text(text = count.toString(), style = MaterialTheme.typography.bodyLarge) }, - modifier = Modifier.clickable { onItemClick(index) }, - ) - } } } } diff --git a/app/src/main/kotlin/com/hippo/ehviewer/ui/scene/GalleryDetailScene.kt b/app/src/main/kotlin/com/hippo/ehviewer/ui/scene/GalleryDetailScene.kt index 10e3c5730..ae5a3414a 100644 --- a/app/src/main/kotlin/com/hippo/ehviewer/ui/scene/GalleryDetailScene.kt +++ b/app/src/main/kotlin/com/hippo/ehviewer/ui/scene/GalleryDetailScene.kt @@ -151,7 +151,6 @@ import com.hippo.ehviewer.ui.modifyFavorites import com.hippo.ehviewer.ui.navToReader import com.hippo.ehviewer.ui.openBrowser import com.hippo.ehviewer.ui.scene.GalleryListScene.Companion.toStartArgs -import com.hippo.ehviewer.ui.setMD3Content import com.hippo.ehviewer.ui.tools.CrystalCard import com.hippo.ehviewer.ui.tools.DialogState import com.hippo.ehviewer.ui.tools.FilledTertiaryIconButton @@ -399,113 +398,111 @@ class GalleryDetailScene : BaseScene() { getDetailError = getString(R.string.error_cannot_find_gallery) } (requireActivity() as MainActivity).mShareUrl = galleryDetailUrl - return ComposeWithViewLifecycle().apply { - setMD3Content { - LaunchedEffect(gid) { - EhDownloadManager.stateFlow(gid).collect { - updateDownloadState() - } + return ComposeWithMD3 { + LaunchedEffect(gid) { + EhDownloadManager.stateFlow(gid).collect { + updateDownloadState() } - dialogState.Intercept() - val scrollBehavior = TopAppBarDefaults.exitUntilCollapsedScrollBehavior() - Scaffold( - topBar = { - LargeTopAppBar( - title = { - composeBindingGI?.let { - Text( - text = EhUtils.getSuitableTitle(it), - maxLines = 2, - overflow = TextOverflow.Ellipsis, - ) - } - }, - navigationIcon = { - IconButton(onClick = { - findNavController().popBackStack() - }) { - Icon( - imageVector = Icons.AutoMirrored.Default.ArrowBack, - contentDescription = null, - ) - } - }, - scrollBehavior = scrollBehavior, - actions = { - IconButton(onClick = ::showArchiveDialog) { - Icon( - imageVector = Icons.Default.FolderZip, - contentDescription = null, - ) - } - IconButton(onClick = ::doShareGallery) { - Icon( - imageVector = Icons.Default.Share, - contentDescription = null, - ) - } - var dropdown by remember { mutableStateOf(false) } - IconButton(onClick = { dropdown = !dropdown }) { - Icon( - imageVector = Icons.Default.MoreVert, - contentDescription = null, - ) - } - DropdownMenu( - expanded = dropdown, - onDismissRequest = { dropdown = false }, - ) { - DropdownMenuItem( - text = { Text(text = stringResource(id = R.string.action_add_tag)) }, - onClick = { - dropdown = false - actionAddTag() - }, - ) - DropdownMenuItem( - text = { Text(text = stringResource(id = R.string.refresh)) }, - onClick = { - dropdown = false - actionRefresh() - }, - ) - DropdownMenuItem( - text = { Text(text = stringResource(id = R.string.clear_image_cache)) }, - onClick = { - dropdown = false - actionClearCache() - }, - ) - DropdownMenuItem( - text = { Text(text = stringResource(id = R.string.open_in_other_app)) }, - onClick = { - dropdown = false - actionOpenInOtherApp() - }, - ) - } - }, - ) - }, - ) { - Surface { - val gi = composeBindingGI - if (gi != null) { - GalleryDetailContent( - galleryInfo = gi, - galleryDetail = composeBindingGD, - contentPadding = it, - modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection), - ) - } else if (getDetailError.isNotBlank()) { - GalleryDetailErrorTip(error = getDetailError, onClick = ::actionRefresh) - } else { - Box( - modifier = Modifier.fillMaxSize(), - contentAlignment = Alignment.Center, - ) { - CircularProgressIndicator() + } + dialogState.Intercept() + val scrollBehavior = TopAppBarDefaults.exitUntilCollapsedScrollBehavior() + Scaffold( + topBar = { + LargeTopAppBar( + title = { + composeBindingGI?.let { + Text( + text = EhUtils.getSuitableTitle(it), + maxLines = 2, + overflow = TextOverflow.Ellipsis, + ) } + }, + navigationIcon = { + IconButton(onClick = { + findNavController().popBackStack() + }) { + Icon( + imageVector = Icons.AutoMirrored.Default.ArrowBack, + contentDescription = null, + ) + } + }, + scrollBehavior = scrollBehavior, + actions = { + IconButton(onClick = ::showArchiveDialog) { + Icon( + imageVector = Icons.Default.FolderZip, + contentDescription = null, + ) + } + IconButton(onClick = ::doShareGallery) { + Icon( + imageVector = Icons.Default.Share, + contentDescription = null, + ) + } + var dropdown by remember { mutableStateOf(false) } + IconButton(onClick = { dropdown = !dropdown }) { + Icon( + imageVector = Icons.Default.MoreVert, + contentDescription = null, + ) + } + DropdownMenu( + expanded = dropdown, + onDismissRequest = { dropdown = false }, + ) { + DropdownMenuItem( + text = { Text(text = stringResource(id = R.string.action_add_tag)) }, + onClick = { + dropdown = false + actionAddTag() + }, + ) + DropdownMenuItem( + text = { Text(text = stringResource(id = R.string.refresh)) }, + onClick = { + dropdown = false + actionRefresh() + }, + ) + DropdownMenuItem( + text = { Text(text = stringResource(id = R.string.clear_image_cache)) }, + onClick = { + dropdown = false + actionClearCache() + }, + ) + DropdownMenuItem( + text = { Text(text = stringResource(id = R.string.open_in_other_app)) }, + onClick = { + dropdown = false + actionOpenInOtherApp() + }, + ) + } + }, + ) + }, + ) { + Surface { + val gi = composeBindingGI + if (gi != null) { + GalleryDetailContent( + galleryInfo = gi, + galleryDetail = composeBindingGD, + contentPadding = it, + modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection), + ) + } else if (getDetailError.isNotBlank()) { + GalleryDetailErrorTip(error = getDetailError, onClick = ::actionRefresh) + } else { + Box( + modifier = Modifier.fillMaxSize(), + contentAlignment = Alignment.Center, + ) { + CircularProgressIndicator() } } } diff --git a/app/src/main/kotlin/com/hippo/ehviewer/ui/scene/GalleryListScene.kt b/app/src/main/kotlin/com/hippo/ehviewer/ui/scene/GalleryListScene.kt index 84895f632..bf88223f0 100644 --- a/app/src/main/kotlin/com/hippo/ehviewer/ui/scene/GalleryListScene.kt +++ b/app/src/main/kotlin/com/hippo/ehviewer/ui/scene/GalleryListScene.kt @@ -92,7 +92,6 @@ import com.hippo.ehviewer.ui.legacy.HandlerDrawable import com.hippo.ehviewer.ui.legacy.LayoutManagerUtils.firstVisibleItemPosition import com.hippo.ehviewer.ui.legacy.ViewTransition import com.hippo.ehviewer.ui.legacy.WindowInsetsAnimationHelper -import com.hippo.ehviewer.ui.setMD3Content import com.hippo.ehviewer.ui.settings.showNewVersion import com.hippo.ehviewer.ui.tools.DialogState import com.hippo.ehviewer.updater.AppUpdater @@ -321,7 +320,7 @@ class GalleryListScene : SearchBarScene() { savedInstanceState: Bundle?, ): View { _binding = SceneGalleryListBinding.inflate(inflater, container!!) - container.addView(ComposeWithViewLifecycle().apply { setMD3Content { dialogState.Intercept() } }) + container.addView(ComposeWithMD3 { dialogState.Intercept() }) checkForUpdates() requireActivity().onBackPressedDispatcher.addCallback(stateBackPressedCallback) mHideActionFabSlop = ViewConfiguration.get(requireContext()).scaledTouchSlop diff --git a/app/src/main/kotlin/com/hippo/ehviewer/ui/scene/HistoryFragment.kt b/app/src/main/kotlin/com/hippo/ehviewer/ui/scene/HistoryFragment.kt index ea0c49511..ee1970891 100644 --- a/app/src/main/kotlin/com/hippo/ehviewer/ui/scene/HistoryFragment.kt +++ b/app/src/main/kotlin/com/hippo/ehviewer/ui/scene/HistoryFragment.kt @@ -17,6 +17,7 @@ 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 @@ -52,7 +53,7 @@ import androidx.compose.ui.unit.dp import androidx.core.os.bundleOf import androidx.lifecycle.viewModelScope import androidx.navigation.NavController -import androidx.navigation.findNavController +import androidx.navigation.fragment.findNavController import androidx.paging.Pager import androidx.paging.PagingConfig import androidx.paging.cachedIn @@ -67,7 +68,6 @@ import com.hippo.ehviewer.icons.big.History import com.hippo.ehviewer.ui.MainActivity import com.hippo.ehviewer.ui.doGalleryInfoAction import com.hippo.ehviewer.ui.main.GalleryInfoListItem -import com.hippo.ehviewer.ui.setMD3Content import com.hippo.ehviewer.ui.tools.CrystalCard import com.hippo.ehviewer.ui.tools.Deferred import com.hippo.ehviewer.ui.tools.FastScrollLazyColumn @@ -203,8 +203,8 @@ class HistoryFragment : BaseScene() { // Disabled for breaking swipe-to-dismiss override val enableDrawerGestures = false - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?) = ComposeWithViewLifecycle().apply { - setMD3Content { + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { + return ComposeWithMD3 { val navController = remember { findNavController() } HistoryScreen(navController) } diff --git a/app/src/main/kotlin/com/hippo/ehviewer/ui/scene/ProgressFragment.kt b/app/src/main/kotlin/com/hippo/ehviewer/ui/scene/ProgressFragment.kt index 6390b643d..234906308 100644 --- a/app/src/main/kotlin/com/hippo/ehviewer/ui/scene/ProgressFragment.kt +++ b/app/src/main/kotlin/com/hippo/ehviewer/ui/scene/ProgressFragment.kt @@ -26,12 +26,11 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import androidx.core.os.bundleOf import androidx.navigation.NavController -import androidx.navigation.findNavController +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.setMD3Content import com.hippo.ehviewer.util.ExceptionUtils import com.ramcosta.composedestinations.annotation.Destination import eu.kanade.tachiyomi.util.lang.withUIContext @@ -93,14 +92,12 @@ fun ProgressScreen(gid: Long, token: String, page: Int, navigator: NavController class ProgressFragment : BaseScene() { override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { - return ComposeWithViewLifecycle().apply { - setMD3Content { - 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) - } + 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) } } diff --git a/app/src/main/kotlin/com/hippo/ehviewer/ui/scene/SceneCompose.kt b/app/src/main/kotlin/com/hippo/ehviewer/ui/scene/SceneCompose.kt index a4824cc1c..d53309c33 100644 --- a/app/src/main/kotlin/com/hippo/ehviewer/ui/scene/SceneCompose.kt +++ b/app/src/main/kotlin/com/hippo/ehviewer/ui/scene/SceneCompose.kt @@ -1,15 +1,13 @@ package com.hippo.ehviewer.ui.scene +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 -/** - * compose view with fragment view lifecycle - * use it after [Fragment.onCreateView] - * also @see [Fragment.getViewLifecycleOwner] - */ @Suppress("FunctionName") -fun Fragment.ComposeWithViewLifecycle() = ComposeView(requireContext()).apply { +inline fun Fragment.ComposeWithMD3(crossinline content: @Composable () -> Unit) = ComposeView(requireContext()).apply { setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnLifecycleDestroyed(viewLifecycleOwner)) + setMD3Content(content) }