From 5a9889b562583c0112b90e1c5b2622336965963d Mon Sep 17 00:00:00 2001 From: arkon Date: Sun, 21 May 2023 11:11:33 -0400 Subject: [PATCH] Upgrade Compose Co-authored-by: ivaniskandar --- .../presentation/components/AdaptiveSheet.kt | 6 +- .../kanade/presentation/components/AppBar.kt | 8 +- .../presentation/components/TabbedDialog.kt | 3 +- .../presentation/components/TabbedScreen.kt | 3 +- .../library/components/LibraryContent.kt | 3 +- .../library/components/LibraryPager.kt | 2 - .../track/TrackInfoDialogSelector.kt | 5 +- .../eu/kanade/presentation/util/Navigator.kt | 24 +++++- .../webview/WebViewScreenContent.kt | 2 +- .../java/eu/kanade/tachiyomi/Migrations.kt | 2 - .../eu/kanade/tachiyomi/ui/home/HomeScreen.kt | 4 +- .../ui/manga/track/TrackInfoDialog.kt | 85 +++++++++++++------ gradle/compose.versions.toml | 4 +- gradle/libs.versions.toml | 2 +- .../presentation/core/components/Pager.kt | 10 +-- 15 files changed, 104 insertions(+), 59 deletions(-) diff --git a/app/src/main/java/eu/kanade/presentation/components/AdaptiveSheet.kt b/app/src/main/java/eu/kanade/presentation/components/AdaptiveSheet.kt index 3589b8fa62..a97b508f56 100644 --- a/app/src/main/java/eu/kanade/presentation/components/AdaptiveSheet.kt +++ b/app/src/main/java/eu/kanade/presentation/components/AdaptiveSheet.kt @@ -4,7 +4,7 @@ import androidx.activity.compose.BackHandler import androidx.compose.animation.core.tween import androidx.compose.animation.fadeIn import androidx.compose.animation.fadeOut -import androidx.compose.animation.with +import androidx.compose.animation.togetherWith import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.WindowInsets import androidx.compose.foundation.layout.WindowInsetsSides @@ -20,7 +20,7 @@ import cafe.adriel.voyager.core.annotation.InternalVoyagerApi import cafe.adriel.voyager.core.lifecycle.DisposableEffectIgnoringConfiguration import cafe.adriel.voyager.core.screen.Screen import cafe.adriel.voyager.navigator.Navigator -import cafe.adriel.voyager.transitions.ScreenTransition +import eu.kanade.presentation.util.ScreenTransition import eu.kanade.presentation.util.isTabletUi import tachiyomi.presentation.core.components.AdaptiveSheet as AdaptiveSheetImpl @@ -43,7 +43,7 @@ fun NavigatorAdaptiveSheet( ScreenTransition( navigator = sheetNavigator, transition = { - fadeIn(animationSpec = tween(220, delayMillis = 90)) with + fadeIn(animationSpec = tween(220, delayMillis = 90)) togetherWith fadeOut(animationSpec = tween(90)) }, ) diff --git a/app/src/main/java/eu/kanade/presentation/components/AppBar.kt b/app/src/main/java/eu/kanade/presentation/components/AppBar.kt index 614281684f..e2ca263c27 100644 --- a/app/src/main/java/eu/kanade/presentation/components/AppBar.kt +++ b/app/src/main/java/eu/kanade/presentation/components/AppBar.kt @@ -188,7 +188,7 @@ fun AppBarActions( IconButton( onClick = it.onClick, enabled = it.enabled, - modifier = Modifier.tooltipAnchor(), + modifier = Modifier.tooltipTrigger(), ) { Icon( imageVector = it.icon, @@ -206,7 +206,7 @@ fun AppBarActions( ) { IconButton( onClick = { showMenu = !showMenu }, - modifier = Modifier.tooltipAnchor(), + modifier = Modifier.tooltipTrigger(), ) { Icon( Icons.Outlined.MoreVert, @@ -325,7 +325,7 @@ fun SearchToolbar( ) { IconButton( onClick = onClick, - modifier = Modifier.tooltipAnchor(), + modifier = Modifier.tooltipTrigger(), ) { Icon( Icons.Outlined.Search, @@ -342,7 +342,7 @@ fun SearchToolbar( onClick() focusRequester.requestFocus() }, - modifier = Modifier.tooltipAnchor(), + modifier = Modifier.tooltipTrigger(), ) { Icon( Icons.Outlined.Close, diff --git a/app/src/main/java/eu/kanade/presentation/components/TabbedDialog.kt b/app/src/main/java/eu/kanade/presentation/components/TabbedDialog.kt index 698916caba..2e0ff985e3 100644 --- a/app/src/main/java/eu/kanade/presentation/components/TabbedDialog.kt +++ b/app/src/main/java/eu/kanade/presentation/components/TabbedDialog.kt @@ -49,7 +49,7 @@ fun TabbedDialog( onDismissRequest = onDismissRequest, ) { contentPadding -> val scope = rememberCoroutineScope() - val pagerState = rememberPagerState() + val pagerState = rememberPagerState { tabTitles.size } Column { Row { @@ -84,7 +84,6 @@ fun TabbedDialog( HorizontalPager( modifier = Modifier.animateContentSize(), - pageCount = tabTitles.size, state = pagerState, verticalAlignment = Alignment.Top, ) { page -> diff --git a/app/src/main/java/eu/kanade/presentation/components/TabbedScreen.kt b/app/src/main/java/eu/kanade/presentation/components/TabbedScreen.kt index 3b40008473..422b1f7dc6 100644 --- a/app/src/main/java/eu/kanade/presentation/components/TabbedScreen.kt +++ b/app/src/main/java/eu/kanade/presentation/components/TabbedScreen.kt @@ -36,7 +36,7 @@ fun TabbedScreen( onChangeSearchQuery: (String?) -> Unit = {}, ) { val scope = rememberCoroutineScope() - val state = rememberPagerState() + val state = rememberPagerState { tabs.size } val snackbarHostState = remember { SnackbarHostState() } LaunchedEffect(startIndex) { @@ -82,7 +82,6 @@ fun TabbedScreen( } HorizontalPager( - pageCount = tabs.size, modifier = Modifier.fillMaxSize(), state = state, verticalAlignment = Alignment.Top, diff --git a/app/src/main/java/eu/kanade/presentation/library/components/LibraryContent.kt b/app/src/main/java/eu/kanade/presentation/library/components/LibraryContent.kt index a444790487..f4bb3908d6 100644 --- a/app/src/main/java/eu/kanade/presentation/library/components/LibraryContent.kt +++ b/app/src/main/java/eu/kanade/presentation/library/components/LibraryContent.kt @@ -54,7 +54,7 @@ fun LibraryContent( ), ) { val coercedCurrentPage = remember { currentPage().coerceAtMost(categories.lastIndex) } - val pagerState = rememberPagerState(coercedCurrentPage) + val pagerState = rememberPagerState(coercedCurrentPage) { categories.size } val scope = rememberCoroutineScope() var isRefreshing by remember(pagerState.currentPage) { mutableStateOf(false) } @@ -98,7 +98,6 @@ fun LibraryContent( LibraryPager( state = pagerState, contentPadding = PaddingValues(bottom = contentPadding.calculateBottomPadding()), - pageCount = categories.size, hasActiveFilters = hasActiveFilters, selectedManga = selection, searchQuery = searchQuery, diff --git a/app/src/main/java/eu/kanade/presentation/library/components/LibraryPager.kt b/app/src/main/java/eu/kanade/presentation/library/components/LibraryPager.kt index c27723ba24..763587eb61 100644 --- a/app/src/main/java/eu/kanade/presentation/library/components/LibraryPager.kt +++ b/app/src/main/java/eu/kanade/presentation/library/components/LibraryPager.kt @@ -30,7 +30,6 @@ import tachiyomi.presentation.core.util.plus fun LibraryPager( state: PagerState, contentPadding: PaddingValues, - pageCount: Int, hasActiveFilters: Boolean, selectedManga: List, searchQuery: String?, @@ -43,7 +42,6 @@ fun LibraryPager( onClickContinueReading: ((LibraryManga) -> Unit)?, ) { HorizontalPager( - pageCount = pageCount, modifier = Modifier.fillMaxSize(), state = state, verticalAlignment = Alignment.Top, diff --git a/app/src/main/java/eu/kanade/presentation/track/TrackInfoDialogSelector.kt b/app/src/main/java/eu/kanade/presentation/track/TrackInfoDialogSelector.kt index 0822247a9d..c41f074023 100644 --- a/app/src/main/java/eu/kanade/presentation/track/TrackInfoDialogSelector.kt +++ b/app/src/main/java/eu/kanade/presentation/track/TrackInfoDialogSelector.kt @@ -18,6 +18,7 @@ import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.DatePicker import androidx.compose.material3.MaterialTheme import androidx.compose.material3.RadioButton +import androidx.compose.material3.SelectableDates import androidx.compose.material3.Text import androidx.compose.material3.TextButton import androidx.compose.material3.minimumInteractiveComponentSize @@ -136,13 +137,14 @@ fun TrackScoreSelector( fun TrackDateSelector( title: String, initialSelectedDateMillis: Long, - dateValidator: (Long) -> Boolean, + selectableDates: SelectableDates, onConfirm: (Long) -> Unit, onRemove: (() -> Unit)?, onDismissRequest: () -> Unit, ) { val pickerState = rememberDatePickerState( initialSelectedDateMillis = initialSelectedDateMillis, + selectableDates = selectableDates, ) AlertDialogContent( modifier = Modifier.windowInsetsPadding(WindowInsets.systemBars), @@ -151,7 +153,6 @@ fun TrackDateSelector( Column { DatePicker( state = pickerState, - dateValidator = dateValidator, title = null, headline = null, showModeToggle = false, diff --git a/app/src/main/java/eu/kanade/presentation/util/Navigator.kt b/app/src/main/java/eu/kanade/presentation/util/Navigator.kt index d9df3f0a1c..bcbf7110f5 100644 --- a/app/src/main/java/eu/kanade/presentation/util/Navigator.kt +++ b/app/src/main/java/eu/kanade/presentation/util/Navigator.kt @@ -1,8 +1,12 @@ package eu.kanade.presentation.util +import androidx.compose.animation.AnimatedContent +import androidx.compose.animation.AnimatedContentTransitionScope +import androidx.compose.animation.ContentTransform import androidx.compose.runtime.Composable import androidx.compose.runtime.ProvidableCompositionLocal import androidx.compose.runtime.staticCompositionLocalOf +import androidx.compose.ui.Modifier import cafe.adriel.voyager.core.model.ScreenModel import cafe.adriel.voyager.core.model.ScreenModelStore import cafe.adriel.voyager.core.screen.Screen @@ -10,7 +14,7 @@ import cafe.adriel.voyager.core.screen.ScreenKey import cafe.adriel.voyager.core.screen.uniqueScreenKey import cafe.adriel.voyager.core.stack.StackEvent import cafe.adriel.voyager.navigator.Navigator -import cafe.adriel.voyager.transitions.ScreenTransition +import cafe.adriel.voyager.transitions.ScreenTransitionContent import kotlinx.coroutines.CoroutineName import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers @@ -63,3 +67,21 @@ fun DefaultNavigatorScreenTransition(navigator: Navigator) { }, ) } + +@Composable +fun ScreenTransition( + navigator: Navigator, + transition: AnimatedContentTransitionScope.() -> ContentTransform, + modifier: Modifier = Modifier, + content: ScreenTransitionContent = { it.Content() }, +) { + AnimatedContent( + targetState = navigator.lastItem, + transitionSpec = transition, + modifier = modifier, + ) { screen -> + navigator.saveableState("transition", screen) { + content(screen) + } + } +} diff --git a/app/src/main/java/eu/kanade/presentation/webview/WebViewScreenContent.kt b/app/src/main/java/eu/kanade/presentation/webview/WebViewScreenContent.kt index 661ae3fc89..5b607b8a2c 100644 --- a/app/src/main/java/eu/kanade/presentation/webview/WebViewScreenContent.kt +++ b/app/src/main/java/eu/kanade/presentation/webview/WebViewScreenContent.kt @@ -114,7 +114,7 @@ fun WebViewScreenContent( ) { contentPadding -> val webClient = remember { object : AccompanistWebViewClient() { - override fun onPageStarted(view: WebView?, url: String?, favicon: Bitmap?) { + override fun onPageStarted(view: WebView, url: String?, favicon: Bitmap?) { super.onPageStarted(view, url, favicon) url?.let { onUrlChange(it) } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/Migrations.kt b/app/src/main/java/eu/kanade/tachiyomi/Migrations.kt index ab5d641dbd..cc9bd506e4 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/Migrations.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/Migrations.kt @@ -26,7 +26,6 @@ import tachiyomi.domain.backup.service.BackupPreferences import tachiyomi.domain.library.service.LibraryPreferences import tachiyomi.domain.library.service.LibraryPreferences.Companion.MANGA_NON_COMPLETED import tachiyomi.domain.manga.model.TriStateFilter -import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get import java.io.File @@ -136,7 +135,6 @@ object Migrations { // Force MAL log out due to login flow change // v52: switched from scraping to WebView // v53: switched from WebView to OAuth - val trackManager = Injekt.get() if (trackManager.myAnimeList.isLogged) { trackManager.myAnimeList.logout() context.toast(R.string.myanimelist_relogin) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/home/HomeScreen.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/home/HomeScreen.kt index e75375b5d1..6890bfa06f 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/home/HomeScreen.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/home/HomeScreen.kt @@ -5,7 +5,7 @@ import androidx.compose.animation.AnimatedContent import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.expandVertically import androidx.compose.animation.shrinkVertically -import androidx.compose.animation.with +import androidx.compose.animation.togetherWith import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.RowScope import androidx.compose.foundation.layout.WindowInsets @@ -121,7 +121,7 @@ object HomeScreen : Screen() { AnimatedContent( targetState = tabNavigator.current, transitionSpec = { - materialFadeThroughIn(initialScale = 1f, durationMillis = TabFadeDuration) with + materialFadeThroughIn(initialScale = 1f, durationMillis = TabFadeDuration) togetherWith materialFadeThroughOut(durationMillis = TabFadeDuration) }, content = { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/track/TrackInfoDialog.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/track/TrackInfoDialog.kt index 568fddbd33..deb3a1a1e9 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/track/TrackInfoDialog.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/track/TrackInfoDialog.kt @@ -14,6 +14,7 @@ import androidx.compose.material3.ButtonDefaults import androidx.compose.material3.FilledTonalButton import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.SelectableDates import androidx.compose.material3.Text import androidx.compose.material3.TextButton import androidx.compose.runtime.Composable @@ -423,6 +424,62 @@ private data class TrackDateSelectorScreen( private val start: Boolean, ) : Screen() { + private val selectableDates = object : SelectableDates { + override fun isSelectableDate(utcTimeMillis: Long): Boolean { + val dateToCheck = Instant.ofEpochMilli(utcTimeMillis) + .atZone(ZoneOffset.systemDefault()) + .toLocalDate() + + if (dateToCheck > LocalDate.now()) { + // Disallow future dates + return false + } + + return if (start && track.finishDate > 0) { + // Disallow start date to be set later than finish date + val dateFinished = Instant.ofEpochMilli(track.finishDate) + .atZone(ZoneId.systemDefault()) + .toLocalDate() + dateToCheck <= dateFinished + } else if (!start && track.startDate > 0) { + // Disallow end date to be set earlier than start date + val dateStarted = Instant.ofEpochMilli(track.startDate) + .atZone(ZoneId.systemDefault()) + .toLocalDate() + dateToCheck >= dateStarted + } else { + // Nothing set before + true + } + } + + override fun isSelectableYear(year: Int): Boolean { + if (year > LocalDate.now().year) { + // Disallow future dates + return false + } + + return if (start && track.finishDate > 0) { + // Disallow start date to be set later than finish date + val dateFinished = Instant.ofEpochMilli(track.finishDate) + .atZone(ZoneId.systemDefault()) + .toLocalDate() + .year + year <= dateFinished + } else if (!start && track.startDate > 0) { + // Disallow end date to be set earlier than start date + val dateStarted = Instant.ofEpochMilli(track.startDate) + .atZone(ZoneId.systemDefault()) + .toLocalDate() + .year + year >= dateStarted + } else { + // Nothing set before + true + } + } + } + @Composable override fun Content() { val navigator = LocalNavigator.currentOrThrow @@ -446,33 +503,7 @@ private data class TrackDateSelectorScreen( stringResource(R.string.track_finished_reading_date) }, initialSelectedDateMillis = sm.initialSelection, - dateValidator = { utcMillis -> - val dateToCheck = Instant.ofEpochMilli(utcMillis) - .atZone(ZoneOffset.systemDefault()) - .toLocalDate() - - if (dateToCheck > LocalDate.now()) { - // Disallow future dates - return@TrackDateSelector false - } - - if (start && track.finishDate > 0) { - // Disallow start date to be set later than finish date - val dateFinished = Instant.ofEpochMilli(track.finishDate) - .atZone(ZoneId.systemDefault()) - .toLocalDate() - dateToCheck <= dateFinished - } else if (!start && track.startDate > 0) { - // Disallow end date to be set earlier than start date - val dateStarted = Instant.ofEpochMilli(track.startDate) - .atZone(ZoneId.systemDefault()) - .toLocalDate() - dateToCheck >= dateStarted - } else { - // Nothing set before - true - } - }, + selectableDates = selectableDates, onConfirm = { sm.setDate(it); navigator.pop() }, onRemove = { sm.confirmRemoveDate(navigator) }.takeIf { canRemove }, onDismissRequest = navigator::pop, diff --git a/gradle/compose.versions.toml b/gradle/compose.versions.toml index 3264abb3e6..76520c36d9 100644 --- a/gradle/compose.versions.toml +++ b/gradle/compose.versions.toml @@ -1,7 +1,7 @@ [versions] compiler = "1.4.7" -compose-bom = "2023.03.00" -accompanist = "0.30.1" +compose-bom = "2023.04.00-alpha04" +accompanist = "0.31.2-alpha" [libraries] activity = "androidx.activity:activity-compose:1.7.1" diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index d0c6f00e00..da70f0a7b4 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -60,7 +60,7 @@ flexible-adapter-ui = "com.github.arkon.FlexibleAdapter:flexible-adapter-ui:c801 photoview = "com.github.chrisbanes:PhotoView:2.3.0" directionalviewpager = "com.github.tachiyomiorg:DirectionalViewPager:1.0.0" insetter = "dev.chrisbanes.insetter:insetter:0.6.1" -compose-materialmotion = "io.github.fornewid:material-motion-compose-core:0.12.3" +compose-materialmotion = "io.github.fornewid:material-motion-compose-core:1.0.2" compose-simpleicons = "br.com.devsrsouza.compose.icons.android:simple-icons:1.0.0" logcat = "com.squareup.logcat:logcat:0.1" diff --git a/presentation-core/src/main/java/tachiyomi/presentation/core/components/Pager.kt b/presentation-core/src/main/java/tachiyomi/presentation/core/components/Pager.kt index 1f6ead704b..65802c8e62 100644 --- a/presentation-core/src/main/java/tachiyomi/presentation/core/components/Pager.kt +++ b/presentation-core/src/main/java/tachiyomi/presentation/core/components/Pager.kt @@ -4,9 +4,9 @@ import androidx.compose.foundation.gestures.Orientation import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.pager.PageSize import androidx.compose.foundation.pager.PagerDefaults +import androidx.compose.foundation.pager.PagerScope import androidx.compose.foundation.pager.PagerSnapDistance import androidx.compose.foundation.pager.PagerState -import androidx.compose.foundation.pager.rememberPagerState import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier @@ -19,9 +19,8 @@ import androidx.compose.ui.unit.dp */ @Composable fun HorizontalPager( - pageCount: Int, + state: PagerState, modifier: Modifier = Modifier, - state: PagerState = rememberPagerState(), contentPadding: PaddingValues = PaddingValues(0.dp), pageSize: PageSize = PageSize.Fill, beyondBoundsPageCount: Int = 0, @@ -33,12 +32,11 @@ fun HorizontalPager( pageNestedScrollConnection: NestedScrollConnection = PagerDefaults.pageNestedScrollConnection( Orientation.Horizontal, ), - pageContent: @Composable (page: Int) -> Unit, + pageContent: @Composable PagerScope.(page: Int) -> Unit, ) { androidx.compose.foundation.pager.HorizontalPager( - pageCount = pageCount, - modifier = modifier, state = state, + modifier = modifier, contentPadding = contentPadding, pageSize = pageSize, beyondBoundsPageCount = beyondBoundsPageCount,