feat: 楼中楼楼主标识

This commit is contained in:
HuanCheng65 2023-07-24 13:59:25 +08:00
parent 2edb341451
commit 518d99f707
No known key found for this signature in database
GPG Key ID: 5EC9DD60A32C7360
7 changed files with 73 additions and 45 deletions

View File

@ -326,23 +326,23 @@ val User.bawuType: String?
} else null } else null
val Post.subPostContents: ImmutableList<AnnotatedString> val Post.subPostContents: ImmutableList<AnnotatedString>
get() = sub_post_list?.sub_post_list?.map { it.contentText }?.toImmutableList() get() = sub_post_list?.sub_post_list?.map { it.getContentText(origin_thread_info?.author?.id) }
?.toImmutableList()
?: persistentListOf() ?: persistentListOf()
@OptIn(ExperimentalTextApi::class) @OptIn(ExperimentalTextApi::class)
val SubPostList.contentText: AnnotatedString fun SubPostList.getContentText(threadAuthorId: Long? = null): AnnotatedString {
get() {
val context = App.INSTANCE val context = App.INSTANCE
val accentColor = Color(ThemeUtils.getColorByAttr(context, R.attr.colorNewPrimary)) val accentColor = Color(ThemeUtils.getColorByAttr(context, R.attr.colorNewPrimary))
val userNameString = buildAnnotatedString { val userNameString = buildAnnotatedString {
withStyle( val annotation = pushStringAnnotation("user", "${author?.id}")
style = SpanStyle( val style = pushStyle(
SpanStyle(
color = accentColor, color = accentColor,
fontWeight = FontWeight.Bold fontWeight = FontWeight.Bold
) )
) { )
withAnnotation("user", "${author?.id}") {
append( append(
StringUtil.getUsernameAnnotatedString( StringUtil.getUsernameAnnotatedString(
context, context,
@ -350,12 +350,15 @@ val SubPostList.contentText: AnnotatedString
author?.nameShow author?.nameShow
) )
) )
pop(style)
if (author?.id == threadAuthorId) {
appendInlineContent("Lz")
}
append(": ") append(": ")
} pop(annotation)
}
} }
val contentStrings = content.renders.map { it.toAnnotationString() } val contentStrings = content.renders.map { it.toAnnotationString() }
return userNameString + contentStrings.reduce { acc, annotatedString -> acc + annotatedString } return userNameString + contentStrings.reduce { acc, annotatedString -> acc + annotatedString }
} }

View File

@ -1,6 +1,7 @@
package com.huanchengfly.tieba.post.repository package com.huanchengfly.tieba.post.repository
import com.huanchengfly.tieba.post.api.TiebaApi import com.huanchengfly.tieba.post.api.TiebaApi
import com.huanchengfly.tieba.post.api.models.protos.OriginThreadInfo
import com.huanchengfly.tieba.post.api.models.protos.pbPage.PbPageResponse import com.huanchengfly.tieba.post.api.models.protos.pbPage.PbPageResponse
import com.huanchengfly.tieba.post.api.retrofit.exception.TiebaUnknownException import com.huanchengfly.tieba.post.api.retrofit.exception.TiebaUnknownException
import com.huanchengfly.tieba.post.ui.page.thread.ThreadPageFrom import com.huanchengfly.tieba.post.ui.page.thread.ThreadPageFrom
@ -58,6 +59,9 @@ object PbPageRepository {
?: userList.first { user -> user.id == subPost.author_id } ?: userList.first { user -> user.id == subPost.author_id }
) )
} }
),
origin_thread_info = OriginThreadInfo(
author = response.data_.thread.author
) )
) )
} }
@ -79,7 +83,7 @@ object PbPageRepository {
response.copy( response.copy(
data_ = response.data_.copy( data_ = response.data_.copy(
post_list = postList, post_list = postList,
first_floor_post = firstPost first_floor_post = firstPost,
) )
) )
} }

View File

@ -70,7 +70,12 @@ data class TextContentRender(
@Composable @Composable
override fun Render() { override fun Render() {
PbContentText(text = text, fontSize = 15.sp, style = MaterialTheme.typography.body1) PbContentText(
text = text,
fontSize = 15.sp,
style = MaterialTheme.typography.body1,
lineSpacing = 0.8.sp
)
} }
override fun toAnnotationString(): AnnotatedString { override fun toAnnotationString(): AnnotatedString {
@ -220,6 +225,7 @@ fun PbContentText(
textDecoration: TextDecoration? = null, textDecoration: TextDecoration? = null,
textAlign: TextAlign? = null, textAlign: TextAlign? = null,
lineHeight: TextUnit = TextUnit.Unspecified, lineHeight: TextUnit = TextUnit.Unspecified,
lineSpacing: TextUnit = 0.sp,
overflow: TextOverflow = TextOverflow.Clip, overflow: TextOverflow = TextOverflow.Clip,
softWrap: Boolean = true, softWrap: Boolean = true,
maxLines: Int = Int.MAX_VALUE, maxLines: Int = Int.MAX_VALUE,
@ -227,7 +233,7 @@ fun PbContentText(
emoticonSize: Float = 0.9f, emoticonSize: Float = 0.9f,
inlineContent: Map<String, InlineTextContent> = emptyMap(), inlineContent: Map<String, InlineTextContent> = emptyMap(),
onTextLayout: (TextLayoutResult) -> Unit = {}, onTextLayout: (TextLayoutResult) -> Unit = {},
style: TextStyle = LocalTextStyle.current style: TextStyle = LocalTextStyle.current,
) { ) {
val context = LocalContext.current val context = LocalContext.current
@ -271,7 +277,7 @@ fun PbContentText(
textDecoration = textDecoration, textDecoration = textDecoration,
textAlign = textAlign, textAlign = textAlign,
lineHeight = lineHeight, lineHeight = lineHeight,
lineSpacing = 0.8.sp, lineSpacing = lineSpacing,
overflow = overflow, overflow = overflow,
softWrap = softWrap, softWrap = softWrap,
maxLines = maxLines, maxLines = maxLines,

View File

@ -171,6 +171,10 @@ internal fun SubPostsContent(
prop1 = SubPostsUiState::forum, prop1 = SubPostsUiState::forum,
initial = null initial = null
) )
val thread by viewModel.uiState.collectPartialAsState(
prop1 = SubPostsUiState::thread,
initial = null
)
val post by viewModel.uiState.collectPartialAsState( val post by viewModel.uiState.collectPartialAsState(
prop1 = SubPostsUiState::post, prop1 = SubPostsUiState::post,
initial = null initial = null
@ -432,6 +436,7 @@ internal fun SubPostsContent(
subPost = item, subPost = item,
contentRenders = subPostsContentRenders[index], contentRenders = subPostsContentRenders[index],
canDelete = { it.author_id == account?.uid?.toLongOrNull() }, canDelete = { it.author_id == account?.uid?.toLongOrNull() },
threadAuthorId = thread?.get { author?.id },
onAgree = { onAgree = {
val hasAgreed = it.agree?.hasAgree != 0 val hasAgreed = it.agree?.hasAgree != 0
viewModel.send( viewModel.send(
@ -490,7 +495,7 @@ private fun getDescText(
private fun SubPostItem( private fun SubPostItem(
subPost: ImmutableHolder<SubPostList>, subPost: ImmutableHolder<SubPostList>,
contentRenders: ImmutableList<PbContentRender>, contentRenders: ImmutableList<PbContentRender>,
threadAuthorId: Long = 0L, threadAuthorId: Long? = null,
canDelete: (SubPostList) -> Boolean = { false }, canDelete: (SubPostList) -> Boolean = { false },
onAgree: (SubPostList) -> Unit = {}, onAgree: (SubPostList) -> Unit = {},
onReplyClick: (SubPostList) -> Unit = {}, onReplyClick: (SubPostList) -> Unit = {},

View File

@ -8,6 +8,7 @@ import com.huanchengfly.tieba.post.api.models.protos.Anti
import com.huanchengfly.tieba.post.api.models.protos.Post import com.huanchengfly.tieba.post.api.models.protos.Post
import com.huanchengfly.tieba.post.api.models.protos.SimpleForum import com.huanchengfly.tieba.post.api.models.protos.SimpleForum
import com.huanchengfly.tieba.post.api.models.protos.SubPostList import com.huanchengfly.tieba.post.api.models.protos.SubPostList
import com.huanchengfly.tieba.post.api.models.protos.ThreadInfo
import com.huanchengfly.tieba.post.api.models.protos.contentRenders import com.huanchengfly.tieba.post.api.models.protos.contentRenders
import com.huanchengfly.tieba.post.api.models.protos.pbFloor.PbFloorResponse import com.huanchengfly.tieba.post.api.models.protos.pbFloor.PbFloorResponse
import com.huanchengfly.tieba.post.api.models.protos.renders import com.huanchengfly.tieba.post.api.models.protos.renders
@ -74,11 +75,13 @@ class SubPostsViewModel @Inject constructor() :
val post = checkNotNull(response.data_?.post) val post = checkNotNull(response.data_?.post)
val page = checkNotNull(response.data_?.page) val page = checkNotNull(response.data_?.page)
val forum = checkNotNull(response.data_?.forum) val forum = checkNotNull(response.data_?.forum)
val thread = checkNotNull(response.data_?.thread)
val anti = checkNotNull(response.data_?.anti) val anti = checkNotNull(response.data_?.anti)
val subPosts = response.data_?.subpost_list.orEmpty() val subPosts = response.data_?.subpost_list.orEmpty()
SubPostsPartialChange.Load.Success( SubPostsPartialChange.Load.Success(
anti.wrapImmutable(), anti.wrapImmutable(),
forum.wrapImmutable(), forum.wrapImmutable(),
thread.wrapImmutable(),
post.wrapImmutable(), post.wrapImmutable(),
post.contentRenders, post.contentRenders,
subPosts.wrapImmutable(), subPosts.wrapImmutable(),
@ -202,6 +205,7 @@ sealed interface SubPostsPartialChange : PartialChange<SubPostsUiState> {
totalPage = totalPage, totalPage = totalPage,
totalCount = totalCount, totalCount = totalCount,
forum = forum, forum = forum,
thread = thread,
post = post, post = post,
postContentRenders = postContentRenders, postContentRenders = postContentRenders,
subPosts = subPosts, subPosts = subPosts,
@ -217,6 +221,7 @@ sealed interface SubPostsPartialChange : PartialChange<SubPostsUiState> {
data class Success( data class Success(
val anti: ImmutableHolder<Anti>, val anti: ImmutableHolder<Anti>,
val forum: ImmutableHolder<SimpleForum>, val forum: ImmutableHolder<SimpleForum>,
val thread: ImmutableHolder<ThreadInfo>,
val post: ImmutableHolder<Post>, val post: ImmutableHolder<Post>,
val postContentRenders: ImmutableList<PbContentRender>, val postContentRenders: ImmutableList<PbContentRender>,
val subPosts: ImmutableList<ImmutableHolder<SubPostList>>, val subPosts: ImmutableList<ImmutableHolder<SubPostList>>,
@ -374,6 +379,7 @@ data class SubPostsUiState(
val anti: ImmutableHolder<Anti>? = null, val anti: ImmutableHolder<Anti>? = null,
val forum: ImmutableHolder<SimpleForum>? = null, val forum: ImmutableHolder<SimpleForum>? = null,
val thread: ImmutableHolder<ThreadInfo>? = null,
val post: ImmutableHolder<Post>? = null, val post: ImmutableHolder<Post>? = null,
val postContentRenders: ImmutableList<PbContentRender> = persistentListOf(), val postContentRenders: ImmutableList<PbContentRender> = persistentListOf(),
val subPosts: ImmutableList<ImmutableHolder<SubPostList>> = persistentListOf(), val subPosts: ImmutableList<ImmutableHolder<SubPostList>> = persistentListOf(),

View File

@ -1762,16 +1762,24 @@ private fun SubPostItem(
onOpenSubPosts(subPostList.get { id }) onOpenSubPosts(subPostList.get { id })
} }
) { ) {
ProvideTextStyle(value = MaterialTheme.typography.body2.copy(color = ExtendedTheme.colors.text)) {
PbContentText( PbContentText(
text = subPostContent, text = subPostContent,
modifier = modifier, modifier = modifier,
color = ExtendedTheme.colors.text,
fontSize = 13.sp, fontSize = 13.sp,
style = MaterialTheme.typography.body2,
emoticonSize = 0.9f, emoticonSize = 0.9f,
overflow = TextOverflow.Ellipsis, overflow = TextOverflow.Ellipsis,
maxLines = 4, maxLines = 4,
lineSpacing = 0.4.sp,
inlineContent = mapOf(
"Lz" to buildChipInlineContent(
stringResource(id = R.string.tip_lz),
backgroundColor = ExtendedTheme.colors.textSecondary.copy(alpha = 0.1f),
color = ExtendedTheme.colors.textSecondary
),
) )
)
}
} }
} }

View File

@ -184,8 +184,6 @@ class ThreadViewModel @Inject constructor() :
), ),
response.data_.page.has_prev != 0, response.data_.page.has_prev != 0,
firstPost?.contentRenders, firstPost?.contentRenders,
notFirstPosts.map { it.contentRenders },
notFirstPosts.map { it.subPostContents }.toImmutableList(),
postId, postId,
seeLz, seeLz,
sortType, sortType,
@ -653,8 +651,6 @@ sealed interface ThreadPartialChange : PartialChange<ThreadUiState> {
val nextPagePostId: Long, val nextPagePostId: Long,
val hasPrevious: Boolean, val hasPrevious: Boolean,
val firstPostContentRenders: List<PbContentRender>?, val firstPostContentRenders: List<PbContentRender>?,
val contentRenders: List<ImmutableList<PbContentRender>>,
val subPostContents: List<ImmutableList<AnnotatedString>>,
val postId: Long = 0, val postId: Long = 0,
val seeLz: Boolean = false, val seeLz: Boolean = false,
val sortType: Int = 0, val sortType: Int = 0,