From 7139bb134b9f8ec5f837ac16efb64f38aaf0803c Mon Sep 17 00:00:00 2001 From: HuanCheng65 <22636177+HuanCheng65@users.noreply.github.com> Date: Fri, 21 Jul 2023 15:15:52 +0800 Subject: [PATCH] =?UTF-8?q?pref:=20=E6=A5=BC=E4=B8=AD=E6=A5=BC=E5=86=85?= =?UTF-8?q?=E5=AE=B9=E8=AE=A1=E7=AE=97=E5=9C=A8=20ViewModel=20=E8=BF=9B?= =?UTF-8?q?=E8=A1=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../post/api/models/protos/Extensions.kt | 41 +++++++- .../tieba/post/repository/PbPageRepository.kt | 13 ++- .../tieba/post/ui/page/thread/ThreadPage.kt | 43 ++------- .../post/ui/page/thread/ThreadViewModel.kt | 95 ++++++++++--------- 4 files changed, 106 insertions(+), 86 deletions(-) diff --git a/app/src/main/java/com/huanchengfly/tieba/post/api/models/protos/Extensions.kt b/app/src/main/java/com/huanchengfly/tieba/post/api/models/protos/Extensions.kt index e4c0cda6..98b829d6 100644 --- a/app/src/main/java/com/huanchengfly/tieba/post/api/models/protos/Extensions.kt +++ b/app/src/main/java/com/huanchengfly/tieba/post/api/models/protos/Extensions.kt @@ -2,9 +2,11 @@ package com.huanchengfly.tieba.post.api.models.protos import androidx.compose.foundation.text.appendInlineContent import androidx.compose.ui.graphics.Color +import androidx.compose.ui.text.AnnotatedString import androidx.compose.ui.text.ExperimentalTextApi import androidx.compose.ui.text.SpanStyle import androidx.compose.ui.text.buildAnnotatedString +import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.withAnnotation import androidx.compose.ui.text.withStyle import com.huanchengfly.tieba.post.App @@ -20,7 +22,9 @@ import com.huanchengfly.tieba.post.ui.utils.getPhotoViewData import com.huanchengfly.tieba.post.utils.EmoticonManager import com.huanchengfly.tieba.post.utils.EmoticonUtil.emoticonString import com.huanchengfly.tieba.post.utils.ImageUtil +import com.huanchengfly.tieba.post.utils.StringUtil import kotlinx.collections.immutable.ImmutableList +import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.toImmutableList val ThreadInfo.abstractText: String @@ -324,4 +328,39 @@ val Post.contentRenders: ImmutableList val User.bawuType: String? get() = if (is_bawu == 1) { if (bawu_type == "manager") "吧主" else "小吧主" - } else null \ No newline at end of file + } else null + +val Post.subPostContents: ImmutableList + get() = sub_post_list?.sub_post_list?.map { it.contentText }?.toImmutableList() + ?: persistentListOf() + +@OptIn(ExperimentalTextApi::class) +val SubPostList.contentText: AnnotatedString + get() { + val context = App.INSTANCE + val accentColor = Color(ThemeUtils.getColorByAttr(context, R.attr.colorNewAccent)) + + val userNameString = buildAnnotatedString { + withStyle( + style = SpanStyle( + color = accentColor, + fontWeight = FontWeight.Bold + ) + ) { + withAnnotation("user", "${author?.id}") { + append( + StringUtil.getUsernameAnnotatedString( + context, + author?.name ?: "", + author?.nameShow + ) + ) + append(": ") + } + } + } + + val contentStrings = content.renders.map { it.toAnnotationString() } + + return userNameString + contentStrings.reduce { acc, annotatedString -> acc + annotatedString } + } \ No newline at end of file diff --git a/app/src/main/java/com/huanchengfly/tieba/post/repository/PbPageRepository.kt b/app/src/main/java/com/huanchengfly/tieba/post/repository/PbPageRepository.kt index 6dd8123a..8f5e86d3 100644 --- a/app/src/main/java/com/huanchengfly/tieba/post/repository/PbPageRepository.kt +++ b/app/src/main/java/com/huanchengfly/tieba/post/repository/PbPageRepository.kt @@ -1,9 +1,8 @@ package com.huanchengfly.tieba.post.repository import com.huanchengfly.tieba.post.api.TiebaApi -import com.huanchengfly.tieba.post.api.models.CommonResponse import com.huanchengfly.tieba.post.api.models.protos.pbPage.PbPageResponse -import com.huanchengfly.tieba.post.api.retrofit.exception.TiebaApiException +import com.huanchengfly.tieba.post.api.retrofit.exception.TiebaUnknownException import com.huanchengfly.tieba.post.ui.page.thread.ThreadPageFrom import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.map @@ -38,7 +37,7 @@ object PbPageRepository { || response.data_.forum == null || response.data_.anti == null ) { - throw TiebaApiException(CommonResponse(-1, "未知错误")) + throw TiebaUnknownException } val userList = response.data_.user_list val postList = response.data_.post_list.map { @@ -62,6 +61,14 @@ object PbPageRepository { author = response.data_.thread.author, from_forum = response.data_.forum, tid = response.data_.thread.id, + sub_post_list = response.data_.first_floor_post.sub_post_list?.copy( + sub_post_list = response.data_.first_floor_post.sub_post_list.sub_post_list.map { subPost -> + subPost.copy( + author = subPost.author + ?: userList.first { user -> user.id == subPost.author_id } + ) + } + ) ) response.copy( 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 128bee69..9a62bce8 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 @@ -76,14 +76,10 @@ import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.AnnotatedString -import androidx.compose.ui.text.ExperimentalTextApi -import androidx.compose.ui.text.SpanStyle import androidx.compose.ui.text.buildAnnotatedString import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextOverflow -import androidx.compose.ui.text.withAnnotation -import androidx.compose.ui.text.withStyle import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import com.airbnb.lottie.compose.LottieAnimation @@ -100,7 +96,6 @@ import com.huanchengfly.tieba.post.api.models.protos.SimpleForum import com.huanchengfly.tieba.post.api.models.protos.ThreadInfo import com.huanchengfly.tieba.post.api.models.protos.User import com.huanchengfly.tieba.post.api.models.protos.bawuType -import com.huanchengfly.tieba.post.api.models.protos.renders import com.huanchengfly.tieba.post.api.retrofit.exception.getErrorMessage import com.huanchengfly.tieba.post.arch.ImmutableHolder import com.huanchengfly.tieba.post.arch.collectPartialAsState @@ -435,6 +430,10 @@ fun ThreadPage( prop1 = ThreadUiState::contentRenders, initial = persistentListOf() ) + val subPostContents by viewModel.uiState.collectPartialAsState( + prop1 = ThreadUiState::subPostContents, + initial = persistentListOf() + ) val author by viewModel.uiState.collectPartialAsState( prop1 = ThreadUiState::author, initial = null @@ -1035,6 +1034,7 @@ fun ThreadPage( PostCard( postHolder = item, contentRenders = contentRenders[index], + subPostContents = subPostContents[index], threadAuthorId = author?.get { id } ?: 0L, blocked = blocked, immersiveMode = isImmersiveMode, @@ -1285,11 +1285,11 @@ private fun BottomBar( } } -@OptIn(ExperimentalTextApi::class) @Composable fun PostCard( postHolder: ImmutableHolder, contentRenders: ImmutableList, + subPostContents: ImmutableList = persistentListOf(), threadAuthorId: Long = 0L, blocked: Boolean = false, immersiveMode: Boolean = false, @@ -1324,7 +1324,6 @@ fun PostCard( postHolder.get { floor > 1 } && !immersiveMode } val paddingModifier = Modifier.padding(start = if (hasPadding) Sizes.Small + 8.dp else 0.dp) - val accentColor = ExtendedTheme.colors.accent val author = postHolder.get { author!! } val showTitle = remember(postHolder) { post.title.isNotBlank() && post.floor <= 1 @@ -1338,32 +1337,6 @@ fun PostCard( val subPosts = remember(postHolder) { post.sub_post_list?.sub_post_list?.toImmutableList() ?: persistentListOf() } - val subPostContents = remember(key1 = subPosts, key2 = accentColor) { - subPosts.map { subPostList -> - val userNameString = buildAnnotatedString { - withStyle( - style = SpanStyle( - color = accentColor, - fontWeight = FontWeight.Bold - ) - ) { - withAnnotation("user", "${subPostList.author?.id}") { - append( - StringUtil.getUsernameAnnotatedString( - context, - subPostList.author?.name ?: "", - subPostList.author?.nameShow - ) - ) - append(": ") - } - } - } - val contentStrings = subPostList.content.renders.map { it.toAnnotationString() } - - userNameString + contentStrings.reduce { acc, annotatedString -> acc + annotatedString } - } - } Card( header = { if (!immersiveMode) { @@ -1429,7 +1402,7 @@ fun PostCard( } } - if (showSubPosts && post.sub_post_number > 0 && !immersiveMode) { + if (showSubPosts && post.sub_post_number > 0 && subPostContents.isNotEmpty() && !immersiveMode) { Column( modifier = Modifier .fillMaxWidth() @@ -1513,7 +1486,7 @@ fun UserNameText( "Bawu" to buildChipInlineContent( bawuType ?: "", color = ExtendedTheme.colors.accent, - backgroundColor = ExtendedTheme.colors.accent.copy(alpha = 0.25f) + backgroundColor = ExtendedTheme.colors.accent.copy(alpha = 0.1f) ), "Lz" to buildChipInlineContent(stringResource(id = R.string.tip_lz)), ), diff --git a/app/src/main/java/com/huanchengfly/tieba/post/ui/page/thread/ThreadViewModel.kt b/app/src/main/java/com/huanchengfly/tieba/post/ui/page/thread/ThreadViewModel.kt index 94e21de6..433fb389 100644 --- a/app/src/main/java/com/huanchengfly/tieba/post/ui/page/thread/ThreadViewModel.kt +++ b/app/src/main/java/com/huanchengfly/tieba/post/ui/page/thread/ThreadViewModel.kt @@ -2,6 +2,7 @@ package com.huanchengfly.tieba.post.ui.page.thread import androidx.compose.runtime.Immutable import androidx.compose.runtime.Stable +import androidx.compose.ui.text.AnnotatedString import com.huanchengfly.tieba.post.api.TiebaApi import com.huanchengfly.tieba.post.api.models.AgreeBean import com.huanchengfly.tieba.post.api.models.protos.Anti @@ -10,7 +11,9 @@ import com.huanchengfly.tieba.post.api.models.protos.SimpleForum import com.huanchengfly.tieba.post.api.models.protos.ThreadInfo import com.huanchengfly.tieba.post.api.models.protos.User import com.huanchengfly.tieba.post.api.models.protos.contentRenders +import com.huanchengfly.tieba.post.api.models.protos.pbPage.PbPageResponse import com.huanchengfly.tieba.post.api.models.protos.renders +import com.huanchengfly.tieba.post.api.models.protos.subPostContents import com.huanchengfly.tieba.post.api.models.protos.updateAgreeStatus import com.huanchengfly.tieba.post.api.models.protos.updateCollectStatus import com.huanchengfly.tieba.post.api.retrofit.exception.TiebaUnknownException @@ -125,49 +128,35 @@ class ThreadViewModel @Inject constructor() : threadId, page, postId, forumId, seeLz, sortType, from = from.takeIf { it == ThreadPageFrom.FROM_STORE }.orEmpty() ) - .map { response -> - if ( - response.data_?.page != null - && response.data_.thread?.author != null - && response.data_.forum != null - && response.data_.anti != null - ) { - val userList = response.data_.user_list - val postList = response.data_.post_list.map { - it.copy( - author = it.author - ?: userList.first { user -> user.id == it.author_id }, - from_forum = response.data_.forum, - tid = response.data_.thread.id, - ) - } - val firstPost = postList.firstOrNull { it.floor == 1 } - ?: response.data_.first_floor_post?.copy(author = response.data_.thread.author) - val notFirstPosts = postList.filterNot { it.floor == 1 } - ThreadPartialChange.Load.Success( - response.data_.thread.title, - response.data_.thread.author, - response.data_.user ?: User(), - firstPost, - notFirstPosts.map { PostItemData(it.wrapImmutable()) }, - response.data_.thread, - response.data_.forum, - response.data_.anti, - response.data_.page.current_page, - response.data_.page.new_total_page, - response.data_.page.has_more != 0, - response.data_.thread.getNextPagePostId( - postList.map { it.id }, - sortType - ), - response.data_.page.has_prev != 0, - firstPost?.contentRenders, - notFirstPosts.map { it.contentRenders }, - postId, - seeLz, - sortType, - ) - } else ThreadPartialChange.Load.Failure(TiebaUnknownException) + .map { response -> + if (response.data_?.page == null || response.data_.thread?.author == null || response.data_.forum == null || response.data_.anti == null) throw TiebaUnknownException + val postList = response.data_.post_list + val firstPost = response.data_.first_floor_post + val notFirstPosts = postList.filterNot { it.floor == 1 } + ThreadPartialChange.Load.Success( + response.data_.thread.title, + response.data_.thread.author, + response.data_.user ?: User(), + firstPost, + notFirstPosts.map { PostItemData(it.wrapImmutable()) }, + response.data_.thread, + response.data_.forum, + response.data_.anti, + response.data_.page.current_page, + response.data_.page.new_total_page, + response.data_.page.has_more != 0, + response.data_.thread.getNextPagePostId( + postList.map { it.id }, + sortType + ), + response.data_.page.has_prev != 0, + firstPost?.contentRenders, + notFirstPosts.map { it.contentRenders }, + notFirstPosts.map { it.subPostContents }.toImmutableList(), + postId, + seeLz, + sortType, + ) } .onStart { emit(ThreadPartialChange.Load.Start) } .catch { emit(ThreadPartialChange.Load.Failure(it)) } @@ -206,6 +195,7 @@ class ThreadViewModel @Inject constructor() : response.data_.page.has_prev != 0, firstPost?.contentRenders ?: emptyList(), notFirstPosts.map { it.contentRenders }, + notFirstPosts.map { it.subPostContents }.toImmutableList(), postId = 0, seeLz, sortType, @@ -241,7 +231,8 @@ class ThreadViewModel @Inject constructor() : postIds + posts.map { it.id }, sortType ), - posts.map { it.contentRenders } + posts.map { it.contentRenders }, + posts.map { it.subPostContents }.toImmutableList(), ) } else ThreadPartialChange.LoadMore.Failure(-1, "未知错误") } @@ -277,7 +268,8 @@ class ThreadViewModel @Inject constructor() : response.data_.page.current_page, response.data_.page.new_total_page, response.data_.page.has_prev != 0, - posts.map { it.contentRenders } + posts.map { it.contentRenders }, + posts.map { it.subPostContents }.toImmutableList(), ) } else ThreadPartialChange.LoadPrevious.Failure(-1, "未知错误") } @@ -537,6 +529,7 @@ sealed interface ThreadPartialChange : PartialChange { firstPostContentRenders = firstPostContentRenders?.toImmutableList() ?: oldState.firstPostContentRenders, contentRenders = contentRenders.toImmutableList(), + subPostContents = subPostContents.toImmutableList(), postId = postId, seeLz = seeLz, sortType = sortType, @@ -567,6 +560,7 @@ sealed interface ThreadPartialChange : PartialChange { val hasPrevious: Boolean, val firstPostContentRenders: List?, val contentRenders: List>, + val subPostContents: List>, val postId: Long = 0, val seeLz: Boolean = false, val sortType: Int = 0, @@ -596,6 +590,7 @@ sealed interface ThreadPartialChange : PartialChange { hasPrevious = hasPrevious, firstPostContentRenders = firstPostContentRenders.toImmutableList(), contentRenders = contentRenders.toImmutableList(), + subPostContents = subPostContents.toImmutableList(), postId = postId, seeLz = seeLz, sortType = sortType, @@ -622,6 +617,7 @@ sealed interface ThreadPartialChange : PartialChange { val hasPrevious: Boolean, val firstPostContentRenders: List, val contentRenders: List>, + val subPostContents: List>, val postId: Long, val seeLz: Boolean, val sortType: Int, @@ -644,7 +640,8 @@ sealed interface ThreadPartialChange : PartialChange { totalPage = totalPage, hasMore = hasMore, nextPagePostId = nextPagePostId, - contentRenders = (oldState.contentRenders + contentRenders).toImmutableList() + contentRenders = (oldState.contentRenders + contentRenders).toImmutableList(), + subPostContents = (oldState.subPostContents + subPostContents).toImmutableList() ) is Failure -> oldState.copy(isLoadingMore = false) @@ -661,6 +658,7 @@ sealed interface ThreadPartialChange : PartialChange { val hasMore: Boolean, val nextPagePostId: Long, val contentRenders: List>, + val subPostContents: List>, ) : LoadMore() data class Failure( @@ -680,7 +678,8 @@ sealed interface ThreadPartialChange : PartialChange { currentPageMin = currentPage, totalPage = totalPage, hasPrevious = hasPrevious, - contentRenders = (contentRenders + oldState.contentRenders).toImmutableList() + contentRenders = (contentRenders + oldState.contentRenders).toImmutableList(), + subPostContents = (subPostContents + oldState.subPostContents).toImmutableList() ) is Failure -> oldState.copy(isRefreshing = false) @@ -696,6 +695,7 @@ sealed interface ThreadPartialChange : PartialChange { val totalPage: Int, val hasPrevious: Boolean, val contentRenders: List>, + val subPostContents: List>, ) : LoadPrevious() data class Failure( @@ -888,6 +888,7 @@ data class ThreadUiState( val data: ImmutableList = persistentListOf(), val firstPostContentRenders: ImmutableList = persistentListOf(), val contentRenders: ImmutableList> = persistentListOf(), + val subPostContents: ImmutableList> = persistentListOf(), val isImmersiveMode: Boolean = false, ) : UiState