diff --git a/app/src/main/java/com/huanchengfly/tieba/post/api/Utils.kt b/app/src/main/java/com/huanchengfly/tieba/post/api/Utils.kt index f47e89dc..a467e520 100644 --- a/app/src/main/java/com/huanchengfly/tieba/post/api/Utils.kt +++ b/app/src/main/java/com/huanchengfly/tieba/post/api/Utils.kt @@ -111,7 +111,8 @@ val List.renders: List 0, 9, 27 -> { val lastRender = renders.lastOrNull() if (lastRender is TextContentRender) { - lastRender.append(it.text) + renders.removeLast() + renders.add(lastRender + it.text) } else renders.add(TextContentRender(it.text)) } @@ -136,7 +137,8 @@ val List.renders: List } val lastRender = renders.lastOrNull() if (lastRender is TextContentRender) { - lastRender.append(text) + renders.removeLast() + renders.add(lastRender + text) } else renders.add(TextContentRender(text)) } @@ -149,7 +151,8 @@ val List.renders: List val emoticonText = "#(${it.c})".emoticonString val lastRender = renders.lastOrNull() if (lastRender is TextContentRender) { - lastRender.append(emoticonText) + renders.removeLast() + renders.add(lastRender + emoticonText) } else renders.add(TextContentRender(emoticonText)) } @@ -190,7 +193,8 @@ val List.renders: List } val lastRender = renders.lastOrNull() if (lastRender is TextContentRender) { - lastRender.append(text) + renders.removeLast() + renders.add(lastRender + text) } else renders.add(TextContentRender(text)) } diff --git a/app/src/main/java/com/huanchengfly/tieba/post/ui/common/PbContentRender.kt b/app/src/main/java/com/huanchengfly/tieba/post/ui/common/PbContentRender.kt index e55c1dbd..8ccece5a 100644 --- a/app/src/main/java/com/huanchengfly/tieba/post/ui/common/PbContentRender.kt +++ b/app/src/main/java/com/huanchengfly/tieba/post/ui/common/PbContentRender.kt @@ -26,22 +26,22 @@ interface PbContentRender { } data class TextContentRender( - var text: AnnotatedString + val text: AnnotatedString ) : PbContentRender { constructor(text: String) : this(AnnotatedString(text)) - fun append(text: String) { - append(AnnotatedString(text)) - } - - fun append(text: AnnotatedString) { - this.text += text - } - @Composable override fun Render() { EmoticonText(text = text, fontSize = 15.sp, style = MaterialTheme.typography.body1) } + + operator fun plus(text: String): TextContentRender { + return TextContentRender(this.text + AnnotatedString(text)) + } + + operator fun plus(text: AnnotatedString): TextContentRender { + return TextContentRender(this.text + text) + } } data class PicContentRender( diff --git a/app/src/main/java/com/huanchengfly/tieba/post/ui/page/main/explore/personalized/DislikeBtn.kt b/app/src/main/java/com/huanchengfly/tieba/post/ui/page/main/explore/personalized/DislikeBtn.kt index 89eab0a7..04246828 100644 --- a/app/src/main/java/com/huanchengfly/tieba/post/ui/page/main/explore/personalized/DislikeBtn.kt +++ b/app/src/main/java/com/huanchengfly/tieba/post/ui/page/main/explore/personalized/DislikeBtn.kt @@ -36,6 +36,7 @@ import androidx.constraintlayout.compose.ConstraintLayout import com.huanchengfly.tieba.post.R import com.huanchengfly.tieba.post.api.models.protos.personalized.DislikeReason import com.huanchengfly.tieba.post.api.models.protos.personalized.ThreadPersonalized +import com.huanchengfly.tieba.post.arch.ImmutableHolder import com.huanchengfly.tieba.post.ui.common.theme.compose.ExtendedTheme import com.huanchengfly.tieba.post.ui.widgets.compose.ClickMenu import com.huanchengfly.tieba.post.ui.widgets.compose.VerticalGrid @@ -44,12 +45,13 @@ import com.huanchengfly.tieba.post.ui.widgets.compose.rememberMenuState @Composable fun Dislike( - personalized: ThreadPersonalized, - onDislike: (clickTime: Long, reasons: List) -> Unit, + personalized: ImmutableHolder, + onDislike: (clickTime: Long, reasons: List>) -> Unit, ) { var clickTime by remember { mutableStateOf(0L) } - val selectedReasons = remember { mutableStateListOf() } + val selectedReasons = remember { mutableStateListOf>() } val menuState = rememberMenuState() + val dislikeResource = personalized.getImmutableList { dislikeResource } ClickMenu( menuState = menuState, menuContent = { @@ -109,8 +111,8 @@ fun Dislike( verticalArrangement = Arrangement.spacedBy(4.dp), ) { items( - items = personalized.dislikeResource, - span = { if (it.dislikeId == 7) 2 else 1 } + items = dislikeResource, + span = { if (it.get { dislikeId } == 7) 2 else 1 } ) { val backgroundColor by animateColorAsState( targetValue = if (selectedReasons.contains(it)) ExtendedTheme.colors.accent else ExtendedTheme.colors.chip @@ -119,7 +121,7 @@ fun Dislike( targetValue = if (selectedReasons.contains(it)) ExtendedTheme.colors.onAccent else ExtendedTheme.colors.onChip ) Text( - text = it.dislikeReason, + text = it.get { dislikeReason }, modifier = Modifier .fillMaxWidth() .clip(RoundedCornerShape(6.dp)) diff --git a/app/src/main/java/com/huanchengfly/tieba/post/ui/page/main/explore/personalized/PersonalizedPage.kt b/app/src/main/java/com/huanchengfly/tieba/post/ui/page/main/explore/personalized/PersonalizedPage.kt index fc9027d0..2671256c 100644 --- a/app/src/main/java/com/huanchengfly/tieba/post/ui/page/main/explore/personalized/PersonalizedPage.kt +++ b/app/src/main/java/com/huanchengfly/tieba/post/ui/page/main/explore/personalized/PersonalizedPage.kt @@ -216,12 +216,12 @@ fun PersonalizedPage( @Composable private fun FeedList( dataProvider: () -> List>, - personalizedDataProvider: () -> List, + personalizedDataProvider: () -> List>, refreshPositionProvider: () -> Int, hiddenThreadIdsProvider: () -> List, onItemClick: (ThreadInfo) -> Unit, onAgree: (ThreadInfo) -> Unit, - onDislike: (ThreadInfo, Long, List) -> Unit, + onDislike: (ThreadInfo, Long, List>) -> Unit, onRefresh: () -> Unit, state: LazyStaggeredGridState, ) { diff --git a/app/src/main/java/com/huanchengfly/tieba/post/ui/page/main/explore/personalized/PersonalizedViewModel.kt b/app/src/main/java/com/huanchengfly/tieba/post/ui/page/main/explore/personalized/PersonalizedViewModel.kt index e7737479..200477e6 100644 --- a/app/src/main/java/com/huanchengfly/tieba/post/ui/page/main/explore/personalized/PersonalizedViewModel.kt +++ b/app/src/main/java/com/huanchengfly/tieba/post/ui/page/main/explore/personalized/PersonalizedViewModel.kt @@ -62,7 +62,8 @@ class PersonalizedViewModel @Inject constructor() : .map { PersonalizedPartialChange.Refresh.Success( data = it.toData(), - threadPersonalizedData = it.data_?.thread_personalized ?: emptyList(), + threadPersonalizedData = (it.data_?.thread_personalized + ?: emptyList()).wrapImmutable(), ) } .onStart { emit(PersonalizedPartialChange.Refresh.Start) } @@ -74,7 +75,8 @@ class PersonalizedViewModel @Inject constructor() : PersonalizedPartialChange.LoadMore.Success( currentPage = page, data = it.toData(), - threadPersonalizedData = it.data_?.thread_personalized ?: emptyList(), + threadPersonalizedData = (it.data_?.thread_personalized + ?: emptyList()).wrapImmutable(), ) } .onStart { emit(PersonalizedPartialChange.LoadMore.Start) } @@ -84,10 +86,10 @@ class PersonalizedViewModel @Inject constructor() : TiebaApi.getInstance().submitDislikeFlow( DislikeBean( threadId.toString(), - reasons.joinToString(",") { it.dislikeId.toString() }, + reasons.joinToString(",") { it.get { dislikeId }.toString() }, forumId?.toString(), clickTime, - reasons.joinToString(",") { it.extra }, + reasons.joinToString(",") { it.get { extra } }, ) ).map { PersonalizedPartialChange.Dislike.Success(threadId) } .catch { emit(PersonalizedPartialChange.Dislike.Failure(threadId, it)) } @@ -125,7 +127,7 @@ sealed interface PersonalizedUiIntent : UiIntent { data class Dislike( val forumId: Long?, val threadId: Long, - val reasons: List, + val reasons: List>, val clickTime: Long ) : PersonalizedUiIntent } @@ -256,7 +258,7 @@ sealed interface PersonalizedPartialChange : PartialChange data class Success( val data: List>, - val threadPersonalizedData: List, + val threadPersonalizedData: List>, ) : Refresh() data class Failure( @@ -282,7 +284,7 @@ sealed interface PersonalizedPartialChange : PartialChange data class Success( val currentPage: Int, val data: List>, - val threadPersonalizedData: List, + val threadPersonalizedData: List>, ) : LoadMore() data class Failure( @@ -297,7 +299,7 @@ data class PersonalizedUiState( val isLoadingMore: Boolean = false, val currentPage: Int = 1, val data: List> = emptyList(), - val threadPersonalizedData: List = emptyList(), + val threadPersonalizedData: List> = emptyList(), val hiddenThreadIds: List = emptyList(), val refreshPosition: Int = 0, ): UiState diff --git a/app/src/main/java/com/huanchengfly/tieba/post/ui/widgets/compose/FeedCard.kt b/app/src/main/java/com/huanchengfly/tieba/post/ui/widgets/compose/FeedCard.kt index f4d8fc70..78630d53 100644 --- a/app/src/main/java/com/huanchengfly/tieba/post/ui/widgets/compose/FeedCard.kt +++ b/app/src/main/java/com/huanchengfly/tieba/post/ui/widgets/compose/FeedCard.kt @@ -85,7 +85,7 @@ private val ImmutableHolder.url: String @Composable private fun DefaultUserHeader( - user: User, + user: ImmutableHolder, time: Int, content: @Composable RowScope.() -> Unit ) { @@ -93,7 +93,7 @@ private fun DefaultUserHeader( UserHeader( avatar = { Avatar( - data = StringUtil.getAvatarUrl(user.portrait), + data = user.get { StringUtil.getAvatarUrl(portrait) }, size = Sizes.Small, contentDescription = null ) @@ -102,8 +102,8 @@ private fun DefaultUserHeader( Text( text = StringUtil.getUsernameAnnotatedString( context = LocalContext.current, - username = user.name, - nickname = user.nameShow, + username = user.get { name }, + nickname = user.get { nameShow }, color = LocalContentColor.current ), color = ExtendedTheme.colors.text @@ -112,8 +112,8 @@ private fun DefaultUserHeader( onClick = { UserActivity.launch( context, - user.id.toString(), - StringUtil.getAvatarUrl(user.portrait) + user.get { id }.toString(), + user.get { StringUtil.getAvatarUrl(portrait) } ) }, desc = { @@ -315,8 +315,8 @@ fun FeedCard( ) { Card( header = { - val author = item.get { author } - if (author != null) { + if (item.isNotNull { author }) { + val author = item.getImmutable { author!! } DefaultUserHeader( user = author, time = item.get { lastTimeInt }) { dislikeAction() } diff --git a/app/src/main/java/com/huanchengfly/tieba/post/utils/StringUtil.kt b/app/src/main/java/com/huanchengfly/tieba/post/utils/StringUtil.kt index 0957d0aa..4c70d57e 100644 --- a/app/src/main/java/com/huanchengfly/tieba/post/utils/StringUtil.kt +++ b/app/src/main/java/com/huanchengfly/tieba/post/utils/StringUtil.kt @@ -8,6 +8,7 @@ import android.text.Spanned import android.text.TextUtils import android.text.style.ForegroundColorSpan import android.widget.TextView +import androidx.compose.runtime.Stable import androidx.compose.ui.graphics.Color import androidx.compose.ui.text.AnnotatedString import androidx.compose.ui.text.SpanStyle @@ -90,6 +91,7 @@ object StringUtil { return nickname ?: "" } + @Stable fun getUsernameAnnotatedString( context: Context, username: String, @@ -110,6 +112,7 @@ object StringUtil { } @JvmStatic + @Stable fun getAvatarUrl(portrait: String?): String { if (portrait.isNullOrEmpty()) { return "" diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 8ff5586e..6b8cef6a 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -175,7 +175,8 @@ 播放失败 抱歉,当前暂时无法浏览本吧 第 %1$s 楼 %2$s - 来自%1$s + 来自%s + 第 %d 楼 查看更多回复(%1$s) 发现新版本 %1$s(%2$s) 更新 · %1$s