diff --git a/app/src/main/java/com/huanchengfly/tieba/post/ui/common/theme/compose/ThemeExtensions.kt b/app/src/main/java/com/huanchengfly/tieba/post/ui/common/theme/compose/ThemeExtensions.kt index 0becb420..ab7cd2b1 100644 --- a/app/src/main/java/com/huanchengfly/tieba/post/ui/common/theme/compose/ThemeExtensions.kt +++ b/app/src/main/java/com/huanchengfly/tieba/post/ui/common/theme/compose/ThemeExtensions.kt @@ -17,6 +17,20 @@ val ExtendedColors.loadMoreIndicator: Color indicator } +val ExtendedColors.threadBottomBar: Color + get() = if (ThemeUtil.isTranslucentTheme(theme)) { + windowBackground + } else { + bottomBar + } + +val ExtendedColors.menuBackground: Color + get() = if (ThemeUtil.isTranslucentTheme(theme)) { + windowBackground + } else { + card + } + val ExtendedColors.invertChipBackground: Color get() = if (ThemeUtil.isNightMode(theme)) primary.copy(alpha = 0.3f) else primary diff --git a/app/src/main/java/com/huanchengfly/tieba/post/ui/page/main/MainPage.kt b/app/src/main/java/com/huanchengfly/tieba/post/ui/page/main/MainPage.kt index a91e08ba..19fef5db 100644 --- a/app/src/main/java/com/huanchengfly/tieba/post/ui/page/main/MainPage.kt +++ b/app/src/main/java/com/huanchengfly/tieba/post/ui/page/main/MainPage.kt @@ -8,7 +8,6 @@ import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.pager.rememberPagerState -import androidx.compose.material.Scaffold import androidx.compose.material.icons.Icons import androidx.compose.material.icons.outlined.AccountCircle import androidx.compose.material.icons.outlined.Inventory2 @@ -52,6 +51,7 @@ import com.huanchengfly.tieba.post.ui.utils.DevicePosture import com.huanchengfly.tieba.post.ui.utils.MainNavigationContentPosition import com.huanchengfly.tieba.post.ui.utils.MainNavigationType import com.huanchengfly.tieba.post.ui.widgets.compose.LazyLoadHorizontalPager +import com.huanchengfly.tieba.post.ui.widgets.compose.MyScaffold import com.huanchengfly.tieba.post.utils.appPreferences import com.ramcosta.composedestinations.annotation.Destination import com.ramcosta.composedestinations.annotation.RootNavGraph @@ -254,7 +254,7 @@ fun MainPage( navigationType = navigationType, navigationContentPosition = navigationContentPosition ) { - Scaffold( + MyScaffold( backgroundColor = Color.Transparent, modifier = Modifier.fillMaxSize(), bottomBar = { diff --git a/app/src/main/java/com/huanchengfly/tieba/post/ui/page/thread/ThreadPage.kt b/app/src/main/java/com/huanchengfly/tieba/post/ui/page/thread/ThreadPage.kt index a40c01c3..5c8e5a15 100644 --- a/app/src/main/java/com/huanchengfly/tieba/post/ui/page/thread/ThreadPage.kt +++ b/app/src/main/java/com/huanchengfly/tieba/post/ui/page/thread/ThreadPage.kt @@ -12,16 +12,18 @@ import androidx.compose.foundation.layout.IntrinsicSize 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.aspectRatio import androidx.compose.foundation.layout.defaultMinSize import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.navigationBarsPadding +import androidx.compose.foundation.layout.navigationBars import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width +import androidx.compose.foundation.layout.windowInsetsBottomHeight import androidx.compose.foundation.lazy.LazyListScope import androidx.compose.foundation.lazy.items import androidx.compose.foundation.lazy.rememberLazyListState @@ -119,6 +121,7 @@ import com.huanchengfly.tieba.post.ui.common.theme.compose.ExtendedTheme import com.huanchengfly.tieba.post.ui.common.theme.compose.invertChipBackground import com.huanchengfly.tieba.post.ui.common.theme.compose.invertChipContent import com.huanchengfly.tieba.post.ui.common.theme.compose.pullRefreshIndicator +import com.huanchengfly.tieba.post.ui.common.theme.compose.threadBottomBar import com.huanchengfly.tieba.post.ui.page.ProvideNavigator import com.huanchengfly.tieba.post.ui.page.destinations.ForumPageDestination import com.huanchengfly.tieba.post.ui.page.destinations.ReplyPageDestination @@ -980,7 +983,65 @@ fun ThreadPage( ) } ) { - Column { + MyScaffold( + scaffoldState = scaffoldState, + topBar = { + TopBar( + forum = forum, + onBack = { navigator.navigateUp() }, + onForumClick = { + val forumName = forum?.get { name } + if (forumName != null) navigator.navigate( + ForumPageDestination( + forumName + ) + ) + } + ) + }, + bottomBar = { + BottomBar( + user = user, + onClickReply = { + navigator.navigate( + ReplyPageDestination( + forumId = curForumId ?: 0, + forumName = forum?.get { name }.orEmpty(), + threadId = threadId, + ) + ) + }, + onAgree = { + val firstPostId = + thread?.get { firstPostId }.takeIf { it != 0L } + ?: firstPost?.get { id } + ?: 0L + if (firstPostId != 0L) viewModel.send( + ThreadUiIntent.AgreeThread( + threadId, + firstPostId, + !hasThreadAgreed + ) + ) + }, + onClickMore = { + if (bottomSheetState.isVisible) { + closeBottomSheet() + } else { + openBottomSheet() + } + }, + hasAgreed = hasThreadAgreed, + agreeNum = threadAgreeNum, + modifier = Modifier + .clickable( + interactionSource = remember { MutableInteractionSource() }, + indication = null, + onClick = {} + ) + ) + }, + ) { ModalBottomSheetLayout( sheetState = bottomSheetState, sheetShape = RoundedCornerShape(topStart = 12.dp, topEnd = 12.dp), @@ -1092,308 +1153,250 @@ fun ThreadPage( .defaultMinSize(minHeight = 1.dp) ) }, - modifier = Modifier.weight(1f) + scrimColor = Color.Transparent, + modifier = Modifier + .fillMaxSize() + .padding(it) ) { - MyScaffold( - scaffoldState = scaffoldState, - topBar = { - TopBar( - forum = forum, - onBack = { navigator.navigateUp() }, - onForumClick = { - val forumName = forum?.get { name } - if (forumName != null) navigator.navigate( - ForumPageDestination( - forumName - ) - ) - } - ) - }, + Box( + modifier = Modifier + .pullRefresh(state = pullRefreshState, enabled = hasPrevious) ) { - Box( - modifier = Modifier.pullRefresh( - state = pullRefreshState, - enabled = hasPrevious - ) - ) { - LoadMoreLayout( - isLoading = isLoadingMore, - onLoadMore = { - viewModel.send( - ThreadUiIntent.LoadMore( - threadId = threadId, - page = if (curSortType == ThreadSortType.SORT_TYPE_DESC) totalPage - currentPageMax - else currentPageMax + 1, - forumId = forumId, - postId = nextPagePostId, - seeLz = isSeeLz, - sortType = curSortType, - postIds = data.map { it.post.get { id } } - ) + LoadMoreLayout( + isLoading = isLoadingMore, + onLoadMore = { + viewModel.send( + ThreadUiIntent.LoadMore( + threadId = threadId, + page = if (curSortType == ThreadSortType.SORT_TYPE_DESC) totalPage - currentPageMax + else currentPageMax + 1, + forumId = forumId, + postId = nextPagePostId, + seeLz = isSeeLz, + sortType = curSortType, + postIds = data.map { it.post.get { id } } ) - }, - loadEnd = !hasMore, - lazyListState = lazyListState, - isEmpty = data.isEmpty() + ) + }, + loadEnd = !hasMore, + lazyListState = lazyListState, + isEmpty = data.isEmpty() + ) { + MyLazyColumn( + state = lazyListState, + modifier = Modifier.fillMaxWidth() ) { - MyLazyColumn( - state = lazyListState, - modifier = Modifier.fillMaxWidth() - ) { - item(key = "FirstPost") { - if (firstPost != null) { - Column { - PostCard( - postHolder = firstPost!!, - contentRenders = firstPostContentRenders, - canDelete = { it.author_id == user.get { id } }, - immersiveMode = isImmersiveMode, - isCollected = { - it.id == thread?.get { collectMarkPid } - ?.toLongOrNull() - }, - showSubPosts = false, - onReplyClick = { - navigator.navigate( - ReplyPageDestination( - forumId = curForumId ?: 0, - forumName = forum?.get { name } - .orEmpty(), - threadId = threadId, - ) + item(key = "FirstPost") { + if (firstPost != null) { + Column { + PostCard( + postHolder = firstPost!!, + contentRenders = firstPostContentRenders, + canDelete = { it.author_id == user.get { id } }, + immersiveMode = isImmersiveMode, + isCollected = { + it.id == thread?.get { collectMarkPid } + ?.toLongOrNull() + }, + showSubPosts = false, + onReplyClick = { + navigator.navigate( + ReplyPageDestination( + forumId = curForumId ?: 0, + forumName = forum?.get { name } + .orEmpty(), + threadId = threadId, ) - }, - onMenuFavoriteClick = { - viewModel.send( - ThreadUiIntent.AddFavorite( - threadId, - it.id, - it.floor - ) + ) + }, + onMenuFavoriteClick = { + viewModel.send( + ThreadUiIntent.AddFavorite( + threadId, + it.id, + it.floor ) - }, - ) { - deletePost = null - confirmDeleteDialogState.show() - } - - VerticalDivider( - modifier = Modifier - .padding(horizontal = 16.dp) - .padding(bottom = 8.dp), - thickness = 2.dp - ) + ) + }, + ) { + deletePost = null + confirmDeleteDialogState.show() } + + VerticalDivider( + modifier = Modifier + .padding(horizontal = 16.dp) + .padding(bottom = 8.dp), + thickness = 2.dp + ) } } - stickyHeader(key = "ThreadHeader") { + } + stickyHeader(key = "ThreadHeader") { + Row( + modifier = Modifier + .background(MaterialTheme.colors.background) + .padding(8.dp), + verticalAlignment = Alignment.CenterVertically + ) { + Text( + text = stringResource( + R.string.title_thread_header, + "${thread?.get { replyNum - 1 } ?: 0}"), + fontSize = 13.sp, + fontWeight = FontWeight.Bold, + color = ExtendedTheme.colors.text, + modifier = Modifier.padding(horizontal = 8.dp), + ) + Spacer(modifier = Modifier.weight(1f)) + Text( + text = stringResource(R.string.text_all), + modifier = Modifier + .padding(horizontal = 8.dp) + .clickable( + interactionSource = remember { MutableInteractionSource() }, + indication = null, + enabled = isSeeLz + ) { + if (isSeeLz) { + viewModel.send( + ThreadUiIntent.LoadFirstPage( + threadId = threadId, + forumId = forumId, + seeLz = false, + sortType = curSortType + ) + ) + } + }, + fontSize = 13.sp, + fontWeight = if (!isSeeLz) FontWeight.SemiBold else FontWeight.Normal, + color = if (!isSeeLz) ExtendedTheme.colors.text else ExtendedTheme.colors.textSecondary, + ) + HorizontalDivider() + Text( + text = stringResource(R.string.title_see_lz), + modifier = Modifier + .padding(horizontal = 8.dp) + .clickable( + interactionSource = remember { MutableInteractionSource() }, + indication = null, + enabled = !isSeeLz + ) { + if (!isSeeLz) { + viewModel.send( + ThreadUiIntent.LoadFirstPage( + threadId = threadId, + forumId = forumId, + seeLz = true, + sortType = curSortType + ) + ) + } + }, + fontSize = 13.sp, + fontWeight = if (isSeeLz) FontWeight.SemiBold else FontWeight.Normal, + color = if (isSeeLz) ExtendedTheme.colors.text else ExtendedTheme.colors.textSecondary, + ) + } + } + if (curSortType == ThreadSortType.SORT_TYPE_DESC) { + latestPosts(true) + } + item(key = "LoadPreviousBtn") { + if (hasPrevious) { Row( modifier = Modifier - .background(MaterialTheme.colors.background) + .fillMaxWidth() + .clickable { + viewModel.send( + ThreadUiIntent.LoadPrevious( + threadId, + max(currentPageMax - 1, 1), + forumId, + postId = data + .first() + .post + .get { id }, + seeLz = isSeeLz, + sortType = curSortType, + postIds = data.map { it.post.get { id } } + ) + ) + } .padding(8.dp), + horizontalArrangement = Arrangement.Center, verticalAlignment = Alignment.CenterVertically ) { + Icon( + imageVector = Icons.Rounded.AlignVerticalTop, + contentDescription = null, + modifier = Modifier.size(16.dp) + ) + Spacer(modifier = Modifier.width(16.dp)) Text( - text = stringResource( - R.string.title_thread_header, - "${thread?.get { replyNum - 1 } ?: 0}"), - fontSize = 13.sp, - fontWeight = FontWeight.Bold, + text = stringResource(id = R.string.btn_load_previous), color = ExtendedTheme.colors.text, - modifier = Modifier.padding(horizontal = 8.dp), - ) - Spacer(modifier = Modifier.weight(1f)) - Text( - text = stringResource(R.string.text_all), - modifier = Modifier - .padding(horizontal = 8.dp) - .clickable( - interactionSource = remember { MutableInteractionSource() }, - indication = null, - enabled = isSeeLz - ) { - if (isSeeLz) { - viewModel.send( - ThreadUiIntent.LoadFirstPage( - threadId = threadId, - forumId = forumId, - seeLz = false, - sortType = curSortType - ) - ) - } - }, - fontSize = 13.sp, - fontWeight = if (!isSeeLz) FontWeight.SemiBold else FontWeight.Normal, - color = if (!isSeeLz) ExtendedTheme.colors.text else ExtendedTheme.colors.textSecondary, - ) - HorizontalDivider() - Text( - text = stringResource(R.string.title_see_lz), - modifier = Modifier - .padding(horizontal = 8.dp) - .clickable( - interactionSource = remember { MutableInteractionSource() }, - indication = null, - enabled = !isSeeLz - ) { - if (!isSeeLz) { - viewModel.send( - ThreadUiIntent.LoadFirstPage( - threadId = threadId, - forumId = forumId, - seeLz = true, - sortType = curSortType - ) - ) - } - }, - fontSize = 13.sp, - fontWeight = if (isSeeLz) FontWeight.SemiBold else FontWeight.Normal, - color = if (isSeeLz) ExtendedTheme.colors.text else ExtendedTheme.colors.textSecondary, + fontSize = 14.sp ) } } - if (curSortType == ThreadSortType.SORT_TYPE_DESC) { - latestPosts(true) - } - item(key = "LoadPreviousBtn") { - if (hasPrevious) { - Row( - modifier = Modifier - .fillMaxWidth() - .clickable { - viewModel.send( - ThreadUiIntent.LoadPrevious( - threadId, - max(currentPageMax - 1, 1), - forumId, - postId = data - .first() - .post - .get { id }, - seeLz = isSeeLz, - sortType = curSortType, - postIds = data.map { it.post.get { id } } - ) - ) - } - .padding(8.dp), - horizontalArrangement = Arrangement.Center, - verticalAlignment = Alignment.CenterVertically - ) { - Icon( - imageVector = Icons.Rounded.AlignVerticalTop, - contentDescription = null, - modifier = Modifier.size(16.dp) - ) - Spacer(modifier = Modifier.width(16.dp)) - Text( - text = stringResource(id = R.string.btn_load_previous), - color = ExtendedTheme.colors.text, - fontSize = 14.sp - ) - } - } - } - if (!isRefreshing && data.isEmpty()) { - item(key = "EmptyTip") { - TipScreen( - title = { Text(text = stringResource(id = R.string.title_empty)) }, - image = { - val composition by rememberLottieComposition( - LottieCompositionSpec.RawRes(R.raw.lottie_empty_box) - ) - LottieAnimation( - composition = composition, - iterations = LottieConstants.IterateForever, - modifier = Modifier - .fillMaxWidth() - .aspectRatio(2f) - ) - }, - actions = { - if (canReload) { - Button(onClick = { reload() }) { - Text(text = stringResource(id = R.string.btn_refresh)) - } - } - }, - modifier = Modifier.fillMaxSize(), - scrollable = false - ) - } - } else { - items( - items = data, - key = { (item) -> "Post_${item.get { id }}" } - ) { (item, blocked, renders, subPosts) -> - PostCard( - item, - renders, - subPosts, - blocked - ) - } - } - if (curSortType != ThreadSortType.SORT_TYPE_DESC) { - latestPosts(false) - } + } + if (!isRefreshing && data.isEmpty()) { + item(key = "EmptyTip") { + TipScreen( + title = { Text(text = stringResource(id = R.string.title_empty)) }, + image = { + val composition by rememberLottieComposition( + LottieCompositionSpec.RawRes(R.raw.lottie_empty_box) + ) + LottieAnimation( + composition = composition, + iterations = LottieConstants.IterateForever, + modifier = Modifier + .fillMaxWidth() + .aspectRatio(2f) + ) + }, + actions = { + if (canReload) { + Button(onClick = { reload() }) { + Text(text = stringResource(id = R.string.btn_refresh)) + } + } + }, + modifier = Modifier.fillMaxSize(), + scrollable = false + ) + } + } else { + items( + items = data, + key = { (item) -> "Post_${item.get { id }}" } + ) { (item, blocked, renders, subPosts) -> + PostCard( + item, + renders, + subPosts, + blocked + ) + } + } + if (curSortType != ThreadSortType.SORT_TYPE_DESC) { + latestPosts(false) } } - - PullRefreshIndicator( - refreshing = isRefreshing, - state = pullRefreshState, - modifier = Modifier.align(Alignment.TopCenter), - backgroundColor = ExtendedTheme.colors.pullRefreshIndicator, - contentColor = ExtendedTheme.colors.primary, - ) } + + PullRefreshIndicator( + refreshing = isRefreshing, + state = pullRefreshState, + modifier = Modifier.align(Alignment.TopCenter), + backgroundColor = ExtendedTheme.colors.pullRefreshIndicator, + contentColor = ExtendedTheme.colors.primary, + ) } } - - BottomBar( - user = user, - onClickReply = { - navigator.navigate( - ReplyPageDestination( - forumId = curForumId ?: 0, - forumName = forum?.get { name }.orEmpty(), - threadId = threadId, - ) - ) - }, - onAgree = { - val firstPostId = - thread?.get { firstPostId }.takeIf { it != 0L } ?: firstPost?.get { id } - ?: 0L - if (firstPostId != 0L) viewModel.send( - ThreadUiIntent.AgreeThread( - threadId, - firstPostId, - !hasThreadAgreed - ) - ) - }, - onClickMore = { - if (bottomSheetState.isVisible) { - closeBottomSheet() - } else { - openBottomSheet() - } - }, - hasAgreed = hasThreadAgreed, - agreeNum = threadAgreeNum, - modifier = Modifier - .navigationBarsPadding() - .clickable( - interactionSource = remember { MutableInteractionSource() }, - indication = null, - onClick = {} - ) - ) } } } @@ -1454,63 +1457,71 @@ private fun BottomBar( hasAgreed: Boolean = false, agreeNum: Long = 0, ) { - Row( - modifier = Modifier - .height(IntrinsicSize.Min) - .background(ExtendedTheme.colors.bottomBar) - .then(modifier) - .padding(horizontal = 16.dp), - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.spacedBy(8.dp) + Column( + modifier = Modifier.background(ExtendedTheme.colors.threadBottomBar) ) { - if (user.get { is_login } == 1 && !LocalContext.current.appPreferences.hideReply) { - Avatar( - data = StringUtil.getAvatarUrl(user.get { portrait }), - size = Sizes.Tiny, - contentDescription = user.get { name }, - modifier = Modifier - .padding(vertical = 8.dp) + Row( + modifier = Modifier + .height(IntrinsicSize.Min) + .then(modifier) + .padding(horizontal = 16.dp), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(8.dp) + ) { + if (user.get { is_login } == 1 && !LocalContext.current.appPreferences.hideReply) { + Avatar( + data = StringUtil.getAvatarUrl(user.get { portrait }), + size = Sizes.Tiny, + contentDescription = user.get { name }, + modifier = Modifier + .padding(vertical = 8.dp) + ) + + Row( + modifier = Modifier + .padding(vertical = 8.dp) + .weight(1f) + .clip(RoundedCornerShape(6.dp)) + .background(ExtendedTheme.colors.bottomBarSurface) + .clickable(onClick = onClickReply) + .padding(8.dp), + ) { + Text( + text = stringResource(id = R.string.tip_reply_thread), + style = MaterialTheme.typography.caption, + color = ExtendedTheme.colors.onBottomBarSurface, + ) + } + } else { + Spacer(modifier = Modifier.weight(1f)) + } + + BottomBarAgreeBtn( + hasAgreed = hasAgreed, + agreeNum = agreeNum, + onClick = onAgree, + modifier = Modifier.fillMaxHeight() ) - Row( + Box( modifier = Modifier - .padding(vertical = 8.dp) - .weight(1f) - .clip(RoundedCornerShape(6.dp)) - .background(ExtendedTheme.colors.bottomBarSurface) - .clickable(onClick = onClickReply) - .padding(8.dp), + .fillMaxHeight() + .clickable(onClick = onClickMore) + .padding(horizontal = 4.dp), + contentAlignment = Alignment.Center ) { - Text( - text = stringResource(id = R.string.tip_reply_thread), - style = MaterialTheme.typography.caption, - color = ExtendedTheme.colors.onBottomBarSurface, + Icon( + imageVector = Icons.Rounded.MoreVert, + contentDescription = stringResource(id = R.string.btn_more), + tint = ExtendedTheme.colors.textSecondary, ) } - } else { - Spacer(modifier = Modifier.weight(1f)) } - BottomBarAgreeBtn( - hasAgreed = hasAgreed, - agreeNum = agreeNum, - onClick = onAgree, - modifier = Modifier.fillMaxHeight() - ) - - Box( + Spacer( modifier = Modifier - .fillMaxHeight() - .clickable(onClick = onClickMore) - .padding(horizontal = 4.dp), - contentAlignment = Alignment.Center - ) { - Icon( - imageVector = Icons.Rounded.MoreVert, - contentDescription = stringResource(id = R.string.btn_more), - tint = ExtendedTheme.colors.textSecondary, - ) - } + .windowInsetsBottomHeight(WindowInsets.navigationBars) + ) } } diff --git a/app/src/main/java/com/huanchengfly/tieba/post/ui/widgets/compose/Menu.kt b/app/src/main/java/com/huanchengfly/tieba/post/ui/widgets/compose/Menu.kt index e3d6175d..fccbaa5a 100644 --- a/app/src/main/java/com/huanchengfly/tieba/post/ui/widgets/compose/Menu.kt +++ b/app/src/main/java/com/huanchengfly/tieba/post/ui/widgets/compose/Menu.kt @@ -31,6 +31,7 @@ import androidx.compose.ui.graphics.Shape import androidx.compose.ui.unit.IntOffset import androidx.compose.ui.unit.dp import com.huanchengfly.tieba.post.ui.common.theme.compose.ExtendedTheme +import com.huanchengfly.tieba.post.ui.common.theme.compose.menuBackground import kotlinx.coroutines.flow.filterIsInstance import kotlinx.coroutines.launch import kotlin.math.roundToInt @@ -160,7 +161,7 @@ fun LongClickMenu( DropdownMenu( expanded = menuState.expanded, onDismissRequest = { menuState.expanded = false }, - modifier = modifier.background(color = MaterialTheme.colors.surface) + modifier = modifier.background(color = ExtendedTheme.colors.menuBackground) ) { ProvideContentColor(color = ExtendedTheme.colors.text) { menuContent()