diff --git a/app/src/main/java/me/ash/reader/ui/page/home/reading/BottomBar.kt b/app/src/main/java/me/ash/reader/ui/page/home/reading/BottomBar.kt index 78b3be02..8eeac121 100644 --- a/app/src/main/java/me/ash/reader/ui/page/home/reading/BottomBar.kt +++ b/app/src/main/java/me/ash/reader/ui/page/home/reading/BottomBar.kt @@ -1,6 +1,13 @@ package me.ash.reader.ui.page.home.reading import android.view.HapticFeedbackConstants +import androidx.compose.animation.AnimatedVisibility +import androidx.compose.animation.core.VisibilityThreshold +import androidx.compose.animation.expandVertically +import androidx.compose.animation.fadeIn +import androidx.compose.animation.fadeOut +import androidx.compose.animation.shrinkVertically +import androidx.compose.foundation.layout.* import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Row @@ -18,6 +25,7 @@ import androidx.compose.material.icons.outlined.Headphones import androidx.compose.material.icons.rounded.ExpandMore import androidx.compose.material.icons.rounded.Star import androidx.compose.material.icons.rounded.StarOutline +import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Surface import androidx.compose.runtime.Composable @@ -25,6 +33,7 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalView import androidx.compose.ui.res.stringResource +import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import androidx.compose.ui.zIndex import me.ash.reader.R @@ -59,113 +68,120 @@ fun BottomBar( .zIndex(1f), contentAlignment = Alignment.BottomCenter ) { - RYExtensibleVisibility(visible = isShow) { + AnimatedVisibility( + visible = isShow, + enter = expandVertically(), + exit = shrinkVertically() + ) { val view = LocalView.current - - Surface( - tonalElevation = tonalElevation.value.dp, - ) { - // TODO: Component styles await refactoring - Row( - modifier = Modifier - .navigationBarsPadding() - .fillMaxWidth() - .height(60.dp), - horizontalArrangement = Arrangement.SpaceAround, - verticalAlignment = Alignment.CenterVertically, - ) { - CanBeDisabledIconButton( - modifier = Modifier.size(40.dp), - disabled = false, - imageVector = if (isUnread) { - Icons.Filled.FiberManualRecord - } else { - Icons.Outlined.FiberManualRecord - }, - contentDescription = stringResource(if (isUnread) R.string.mark_as_read else R.string.mark_as_unread), - tint = if (isUnread) { - MaterialTheme.colorScheme.onSecondaryContainer - } else { - MaterialTheme.colorScheme.outline - }, + Column { + HorizontalDivider( + color = MaterialTheme.colorScheme.surfaceContainerHighest, + thickness = 0.5f.dp + ) + Surface() { + // TODO: Component styles await refactoring + Row( + modifier = Modifier + .navigationBarsPadding() + .fillMaxWidth() + .height(60.dp), + horizontalArrangement = Arrangement.SpaceAround, + verticalAlignment = Alignment.CenterVertically, ) { - view.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP) - onUnread(!isUnread) - } - CanBeDisabledIconButton( - modifier = Modifier.size(40.dp), - disabled = false, - imageVector = if (isStarred) { - Icons.Rounded.Star - } else { - Icons.Rounded.StarOutline - }, - contentDescription = stringResource(if (isStarred) R.string.mark_as_unstar else R.string.mark_as_starred), - tint = if (isStarred) { - MaterialTheme.colorScheme.onSecondaryContainer - } else { - MaterialTheme.colorScheme.outline - }, - ) { - view.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP) - onStarred(!isStarred) - } - CanBeDisabledIconButton( - disabled = !isNextArticleAvailable, - modifier = Modifier.size(40.dp), - imageVector = Icons.Rounded.ExpandMore, - contentDescription = "Next Article", - tint = MaterialTheme.colorScheme.outline, - ) { - view.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP) - onNextArticle() - } - CanBeDisabledIconButton( - modifier = Modifier.size(36.dp), - disabled = false, - imageVector = if (renderer == ReadingRendererPreference.WebView) null else Icons.Outlined.Headphones, - contentDescription = if (renderer == ReadingRendererPreference.WebView) { - stringResource(R.string.bionic_reading) - } else { - stringResource(R.string.read_aloud) - }, - tint = MaterialTheme.colorScheme.outline, - icon = { - BionicReadingIcon( - filled = isBionicReading, - size = 24.dp, - tint = if (renderer == ReadingRendererPreference.WebView) { - MaterialTheme.colorScheme.onSecondaryContainer - } else { - MaterialTheme.colorScheme.outline - } - ) - }, - ) { - view.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP) - if (renderer == ReadingRendererPreference.WebView) { - onBionicReading() - } else { - onReadAloud() + CanBeDisabledIconButton( + modifier = Modifier.size(40.dp), + disabled = false, + imageVector = if (isUnread) { + Icons.Filled.FiberManualRecord + } else { + Icons.Outlined.FiberManualRecord + }, + contentDescription = stringResource(if (isUnread) R.string.mark_as_read else R.string.mark_as_unread), + tint = if (isUnread) { + MaterialTheme.colorScheme.onSecondaryContainer + } else { + MaterialTheme.colorScheme.outline + }, + ) { + view.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP) + onUnread(!isUnread) + } + CanBeDisabledIconButton( + modifier = Modifier.size(40.dp), + disabled = false, + imageVector = if (isStarred) { + Icons.Rounded.Star + } else { + Icons.Rounded.StarOutline + }, + contentDescription = stringResource(if (isStarred) R.string.mark_as_unstar else R.string.mark_as_starred), + tint = if (isStarred) { + MaterialTheme.colorScheme.onSecondaryContainer + } else { + MaterialTheme.colorScheme.outline + }, + ) { + view.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP) + onStarred(!isStarred) + } + CanBeDisabledIconButton( + disabled = !isNextArticleAvailable, + modifier = Modifier.size(40.dp), + imageVector = Icons.Rounded.ExpandMore, + contentDescription = "Next Article", + tint = MaterialTheme.colorScheme.outline, + ) { + view.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP) + onNextArticle() + } + CanBeDisabledIconButton( + modifier = Modifier.size(36.dp), + disabled = false, + imageVector = if (renderer == ReadingRendererPreference.WebView) null else Icons.Outlined.Headphones, + contentDescription = if (renderer == ReadingRendererPreference.WebView) { + stringResource(R.string.bionic_reading) + } else { + stringResource(R.string.read_aloud) + }, + tint = MaterialTheme.colorScheme.outline, + icon = { + BionicReadingIcon( + filled = isBionicReading, + size = 24.dp, + tint = if (renderer == ReadingRendererPreference.WebView) { + MaterialTheme.colorScheme.onSecondaryContainer + } else { + MaterialTheme.colorScheme.outline + } + ) + }, + ) { + view.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP) + if (renderer == ReadingRendererPreference.WebView) { + onBionicReading() + } else { + onReadAloud() + } + } + CanBeDisabledIconButton( + disabled = false, + modifier = Modifier.size(40.dp), + imageVector = if (isFullContent) { + Icons.AutoMirrored.Rounded.Article + } else { + Icons.AutoMirrored.Outlined.Article + }, + contentDescription = stringResource(R.string.parse_full_content), + tint = if (isFullContent) { + MaterialTheme.colorScheme.onSecondaryContainer + } else { + MaterialTheme.colorScheme.outline + }, + ) { + view.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP) + onFullContent(!isFullContent) } - } - CanBeDisabledIconButton( - disabled = false, - modifier = Modifier.size(40.dp), - imageVector = if (isFullContent) { - Icons.AutoMirrored.Rounded.Article - } else { - Icons.AutoMirrored.Outlined.Article - }, - contentDescription = stringResource(R.string.parse_full_content), - tint = if (isFullContent) { - MaterialTheme.colorScheme.onSecondaryContainer - } else { - MaterialTheme.colorScheme.outline - }, - ) { - view.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP) - onFullContent(!isFullContent) } } } diff --git a/app/src/main/java/me/ash/reader/ui/page/home/reading/Content.kt b/app/src/main/java/me/ash/reader/ui/page/home/reading/Content.kt index f7ba366e..7555b2a5 100644 --- a/app/src/main/java/me/ash/reader/ui/page/home/reading/Content.kt +++ b/app/src/main/java/me/ash/reader/ui/page/home/reading/Content.kt @@ -68,6 +68,7 @@ fun Content( } } else { + when (renderer) { ReadingRendererPreference.WebView -> { Column( @@ -81,8 +82,7 @@ fun Content( Spacer(modifier = Modifier.height(64.dp)) // padding Column( - modifier = Modifier - .padding(horizontal = 12.dp) + modifier = Modifier.padding(horizontal = 12.dp) ) { DisableSelection { Metadata( diff --git a/app/src/main/java/me/ash/reader/ui/page/home/reading/ReadingPage.kt b/app/src/main/java/me/ash/reader/ui/page/home/reading/ReadingPage.kt index 72419bce..539b7c0f 100644 --- a/app/src/main/java/me/ash/reader/ui/page/home/reading/ReadingPage.kt +++ b/app/src/main/java/me/ash/reader/ui/page/home/reading/ReadingPage.kt @@ -21,6 +21,7 @@ import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue +import androidx.compose.runtime.snapshotFlow import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext @@ -73,6 +74,10 @@ fun ReadingPage( true } + var showTopDivider by remember { + mutableStateOf(false) + } + val pagingItems = homeUiState.pagingData.collectAsLazyPagingItems().itemSnapshotList LaunchedEffect(Unit) { @@ -97,23 +102,22 @@ fun ReadingPage( Scaffold( containerColor = MaterialTheme.colorScheme.surface, -// topBarTonalElevation = tonalElevation.value.dp, -// containerTonalElevation = tonalElevation.value.dp, content = { paddings -> Log.i("RLog", "TopBar: recomposition") Box(modifier = Modifier.fillMaxSize()) { - // Top Bar - TopBar( - navController = navController, - isShow = isShowToolBar, - windowInsets = WindowInsets(top = paddings.calculateTopPadding()), - title = readerState.title, - link = readerState.link, - onClose = { - navController.popBackStack() - }, - ) + if (readerState.articleId != null) { + TopBar( + navController = navController, + isShow = isShowToolBar, + showDivider = showTopDivider, + title = readerState.title, + link = readerState.link, + onClose = { + navController.popBackStack() + }, + ) + } val isNextArticleAvailable = !readerState.nextArticleId.isNullOrEmpty() val isPreviousArticleAvailable = !readerState.previousArticleId.isNullOrEmpty() @@ -163,6 +167,9 @@ fun ReadingPage( saver = LazyListState.Saver ) { LazyListState() } + showTopDivider = snapshotFlow { + listState.firstVisibleItemIndex != 0 + }.collectAsStateValue(initial = false) CompositionLocalProvider( LocalOverscrollConfiguration provides diff --git a/app/src/main/java/me/ash/reader/ui/page/home/reading/TopBar.kt b/app/src/main/java/me/ash/reader/ui/page/home/reading/TopBar.kt index c589a264..138befb1 100644 --- a/app/src/main/java/me/ash/reader/ui/page/home/reading/TopBar.kt +++ b/app/src/main/java/me/ash/reader/ui/page/home/reading/TopBar.kt @@ -1,15 +1,27 @@ package me.ash.reader.ui.page.home.reading +import androidx.compose.animation.AnimatedVisibility +import androidx.compose.animation.expandVertically +import androidx.compose.animation.shrinkVertically import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.WindowInsets +import androidx.compose.foundation.layout.asPaddingValues import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.statusBars +import androidx.compose.foundation.layout.statusBarsPadding import androidx.compose.material.icons.Icons import androidx.compose.material.icons.outlined.Palette import androidx.compose.material.icons.outlined.Share import androidx.compose.material.icons.rounded.Close import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Surface import androidx.compose.material3.TopAppBar import androidx.compose.material3.TopAppBarDefaults import androidx.compose.runtime.Composable @@ -17,6 +29,7 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource +import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import androidx.compose.ui.zIndex import androidx.navigation.NavHostController @@ -24,7 +37,6 @@ import me.ash.reader.R import me.ash.reader.infrastructure.preference.LocalReadingPageTonalElevation import me.ash.reader.infrastructure.preference.LocalSharedContent import me.ash.reader.ui.component.base.FeedbackIconButton -import me.ash.reader.ui.component.base.RYExtensibleVisibility import me.ash.reader.ui.ext.surfaceColorAtElevation import me.ash.reader.ui.page.common.RouteName @@ -33,7 +45,7 @@ import me.ash.reader.ui.page.common.RouteName fun TopBar( navController: NavHostController, isShow: Boolean, - windowInsets: WindowInsets = WindowInsets(0.dp), + showDivider: Boolean = false, title: String? = "", link: String? = "", onClose: () -> Unit = {}, @@ -48,43 +60,65 @@ fun TopBar( .zIndex(1f), contentAlignment = Alignment.TopCenter ) { - RYExtensibleVisibility(visible = isShow) { - TopAppBar( - title = {}, - modifier = Modifier, - windowInsets = windowInsets, - navigationIcon = { - FeedbackIconButton( - imageVector = Icons.Rounded.Close, - contentDescription = stringResource(R.string.close), - tint = MaterialTheme.colorScheme.onSurface - ) { - onClose() - } - }, - actions = { - FeedbackIconButton( - modifier = Modifier.size(22.dp), - imageVector = Icons.Outlined.Palette, - contentDescription = stringResource(R.string.style), - tint = MaterialTheme.colorScheme.onSurface - ) { - navController.navigate(RouteName.READING_PAGE_STYLE) { - launchSingleTop = true + Column { + Surface( + modifier = Modifier + .fillMaxWidth() + .height( + WindowInsets.statusBars + .asPaddingValues() + .calculateTopPadding() + ) + ) {} + AnimatedVisibility( + visible = isShow, + enter = expandVertically(expandFrom = Alignment.Top), + exit = shrinkVertically(shrinkTowards = Alignment.Top) + ) { + TopAppBar( + title = {}, + modifier = Modifier, + windowInsets = WindowInsets(0.dp), + navigationIcon = { + FeedbackIconButton( + imageVector = Icons.Rounded.Close, + contentDescription = stringResource(R.string.close), + tint = MaterialTheme.colorScheme.onSurface + ) { + onClose() } - } - FeedbackIconButton( - modifier = Modifier.size(20.dp), - imageVector = Icons.Outlined.Share, - contentDescription = stringResource(R.string.share), - tint = MaterialTheme.colorScheme.onSurface, - ) { - sharedContent.share(context, title, link) - } - }, colors = TopAppBarDefaults.topAppBarColors( - containerColor = MaterialTheme.colorScheme.surfaceColorAtElevation(tonalElevation.value.dp), + }, actions = { + FeedbackIconButton( + modifier = Modifier.size(22.dp), + imageVector = Icons.Outlined.Palette, + contentDescription = stringResource(R.string.style), + tint = MaterialTheme.colorScheme.onSurface + ) { + navController.navigate(RouteName.READING_PAGE_STYLE) { + launchSingleTop = true + } + } + FeedbackIconButton( + modifier = Modifier.size(20.dp), + imageVector = Icons.Outlined.Share, + contentDescription = stringResource(R.string.share), + tint = MaterialTheme.colorScheme.onSurface, + ) { + sharedContent.share(context, title, link) + } + }, colors = TopAppBarDefaults.topAppBarColors( + containerColor = MaterialTheme.colorScheme.surfaceColorAtElevation( + tonalElevation.value.dp + ), + ) ) - ) + } + if (showDivider) { + HorizontalDivider( + color = MaterialTheme.colorScheme.surfaceContainerHighest, + thickness = 0.5f.dp + ) + } } } -} +} \ No newline at end of file