feat: 等级显示 & 楼主提示

This commit is contained in:
HuanCheng65 2023-07-14 13:35:46 +08:00
parent 37e81673c7
commit a3ce72a971
No known key found for this signature in database
GPG Key ID: 5EC9DD60A32C7360
5 changed files with 156 additions and 14 deletions

View File

@ -33,9 +33,15 @@ fun Float.dpToPxFloat(): Float =
fun Float.spToPx(): Int =
(this * App.INSTANCE.resources.displayMetrics.scaledDensity + 0.5f).roundToInt()
fun Float.spToPxFloat(): Float =
this * App.INSTANCE.resources.displayMetrics.scaledDensity + 0.5f
fun Float.pxToDp(): Int =
(this / App.ScreenInfo.DENSITY + 0.5f).roundToInt()
fun Float.pxToDpFloat(): Float =
this / App.ScreenInfo.DENSITY + 0.5f
fun Float.pxToSp(): Int =
(this / App.INSTANCE.resources.displayMetrics.scaledDensity + 0.5f).roundToInt()
@ -47,6 +53,13 @@ fun Int.pxToDp(): Int = this.toFloat().pxToDp()
fun Int.pxToSp(): Int = this.toFloat().pxToSp()
fun Float.pxToSpFloat(): Float = this / App.INSTANCE.resources.displayMetrics.scaledDensity + 0.5f
fun Int.pxToSpFloat(): Float = this.toFloat().pxToSpFloat()
fun Int.pxToDpFloat(): Float =
this.toFloat().pxToDpFloat()
inline fun <reified Data> String.fromJson(): Data {
val type = object : TypeToken<Data>() {}.type
return GsonUtil.getGson().fromJson(this, type)

View File

@ -28,11 +28,11 @@ import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.itemsIndexed
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.text.appendInlineContent
import androidx.compose.foundation.text.selection.SelectionContainer
import androidx.compose.material.ButtonDefaults
import androidx.compose.material.ExperimentalMaterialApi
import androidx.compose.material.Icon
import androidx.compose.material.LocalContentColor
import androidx.compose.material.MaterialTheme
import androidx.compose.material.ModalBottomSheetLayout
import androidx.compose.material.ModalBottomSheetValue
@ -77,6 +77,7 @@ import androidx.compose.ui.draw.clip
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.SpanStyle
import androidx.compose.ui.text.buildAnnotatedString
import androidx.compose.ui.text.font.FontWeight
@ -90,6 +91,7 @@ import com.airbnb.lottie.compose.LottieConstants
import com.airbnb.lottie.compose.rememberLottieComposition
import com.huanchengfly.tieba.post.App
import com.huanchengfly.tieba.post.R
import com.huanchengfly.tieba.post.activities.UserActivity
import com.huanchengfly.tieba.post.api.TiebaApi
import com.huanchengfly.tieba.post.api.booleanToString
import com.huanchengfly.tieba.post.api.models.protos.Post
@ -129,6 +131,7 @@ import com.huanchengfly.tieba.post.ui.widgets.compose.TitleCentredToolbar
import com.huanchengfly.tieba.post.ui.widgets.compose.UserHeader
import com.huanchengfly.tieba.post.ui.widgets.compose.VerticalDivider
import com.huanchengfly.tieba.post.ui.widgets.compose.VerticalGrid
import com.huanchengfly.tieba.post.ui.widgets.compose.buildChipInlineContent
import com.huanchengfly.tieba.post.ui.widgets.compose.rememberDialogState
import com.huanchengfly.tieba.post.ui.widgets.compose.states.StateScreen
import com.huanchengfly.tieba.post.utils.DateTimeUtils.getRelativeTimeString
@ -137,6 +140,7 @@ import com.huanchengfly.tieba.post.utils.StringUtil
import com.huanchengfly.tieba.post.utils.StringUtil.getShortNumString
import com.huanchengfly.tieba.post.utils.ThemeUtil
import com.huanchengfly.tieba.post.utils.TiebaUtil
import com.huanchengfly.tieba.post.utils.Util.getIconColorByLevel
import com.ramcosta.composedestinations.annotation.Destination
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
import kotlinx.collections.immutable.ImmutableList
@ -145,6 +149,7 @@ import kotlinx.collections.immutable.toImmutableList
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.launch
import kotlinx.serialization.Serializable
import kotlin.math.max
private fun getDescText(
time: Long?,
@ -944,7 +949,7 @@ fun ThreadPage(
}
}
item(key = "LoadPreviousBtn") {
if (currentPageMin > 1) {
if (hasPrevious) {
Row(
modifier = Modifier
.fillMaxWidth()
@ -952,7 +957,7 @@ fun ThreadPage(
viewModel.send(
ThreadUiIntent.LoadPrevious(
threadId,
currentPageMax - 1,
max(currentPageMax - 1, 1),
forumId,
postId = data
.first()
@ -989,8 +994,9 @@ fun ThreadPage(
PostCard(
postHolder = item,
contentRenders = contentRenders[index],
immersiveMode = isImmersiveMode,
threadAuthorId = author?.get { id } ?: 0L,
blocked = blocked,
immersiveMode = isImmersiveMode,
onAgree = {
val postHasAgreed =
item.get { agree?.hasAgree == 1 }
@ -1201,6 +1207,7 @@ private fun BottomBar(
fun PostCard(
postHolder: ImmutableHolder<Post>,
contentRenders: ImmutableList<PbContentRender>,
threadAuthorId: Long = 0L,
blocked: Boolean = false,
immersiveMode: Boolean = false,
onAgree: () -> Unit = {},
@ -1279,17 +1286,21 @@ fun PostCard(
)
},
name = {
Text(
text = StringUtil.getUsernameAnnotatedString(
UserNameText(
userName = StringUtil.getUsernameAnnotatedString(
LocalContext.current,
author.name,
author.nameShow,
LocalContentColor.current
)
author.nameShow
),
userLevel = author.level_id,
isLz = author.id == threadAuthorId
)
},
desc = {
Text(text = getDescText(post.time.toLong(), post.floor, author.ip_address))
},
onClick = {
UserActivity.launch(context, author.id.toString())
}
) {
if (post.floor > 1) {
@ -1360,6 +1371,46 @@ fun PostCard(
)
}
@Composable
private fun UserNameText(
userName: AnnotatedString,
userLevel: Int,
modifier: Modifier = Modifier,
isLz: Boolean = false,
bawuType: String? = null,
) {
val text = buildAnnotatedString {
append(userName)
append(" ")
appendInlineContent("Level", alternateText = "$userLevel")
if (!bawuType.isNullOrBlank()) {
append(" ")
appendInlineContent("Bawu", alternateText = bawuType)
}
if (isLz) {
append(" ")
appendInlineContent("Lz")
}
}
Text(
text = text,
inlineContent = mapOf(
"Level" to buildChipInlineContent(
"18",
color = Color(getIconColorByLevel("$userLevel")),
backgroundColor = Color(getIconColorByLevel("$userLevel")).copy(alpha = 0.25f)
),
"Bawu" to buildChipInlineContent(
bawuType ?: "",
color = ExtendedTheme.colors.accent,
backgroundColor = ExtendedTheme.colors.accent.copy(alpha = 0.25f)
),
"Lz" to buildChipInlineContent(stringResource(id = R.string.tip_lz)),
),
modifier = modifier
)
}
@Composable
private fun ThreadMenu(
isSeeLz: Boolean,

View File

@ -269,11 +269,13 @@ private fun StoreItem(
},
onClick = onUserClick,
)
val title = buildAnnotatedString {
append(info.title)
if (hasUpdate) {
append(" ")
appendInlineContent("Update", info.postNo)
val title = remember(info, hasUpdate) {
buildAnnotatedString {
append(info.title)
if (hasUpdate) {
append(" ")
appendInlineContent("Update", info.postNo)
}
}
}
val updateTip = stringResource(

View File

@ -1,7 +1,16 @@
package com.huanchengfly.tieba.post.ui.widgets.compose
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.calculateEndPadding
import androidx.compose.foundation.layout.calculateStartPadding
import androidx.compose.foundation.layout.defaultMinSize
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.text.InlineTextContent
import androidx.compose.material.Icon
import androidx.compose.material.LocalContentAlpha
@ -14,9 +23,12 @@ import androidx.compose.material.icons.rounded.Link
import androidx.compose.material.icons.rounded.SlowMotionVideo
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.takeOrElse
import androidx.compose.ui.platform.LocalLayoutDirection
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.AnnotatedString
import androidx.compose.ui.text.ExperimentalTextApi
@ -28,6 +40,7 @@ import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.font.FontStyle
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.rememberTextMeasurer
import androidx.compose.ui.text.style.LineHeightStyle
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextDecoration
import androidx.compose.ui.text.style.TextOverflow
@ -35,8 +48,11 @@ import androidx.compose.ui.unit.TextUnit
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.huanchengfly.tieba.post.R
import com.huanchengfly.tieba.post.dpToPxFloat
import com.huanchengfly.tieba.post.pxToDp
import com.huanchengfly.tieba.post.pxToSp
import com.huanchengfly.tieba.post.pxToSpFloat
import com.huanchengfly.tieba.post.spToPxFloat
import com.huanchengfly.tieba.post.ui.common.theme.compose.ExtendedTheme
import com.huanchengfly.tieba.post.utils.EmoticonManager
import com.huanchengfly.tieba.post.utils.EmoticonUtil.emoticonString
@ -321,3 +337,61 @@ fun TextWithMinWidth(
style = style
)
}
@OptIn(ExperimentalTextApi::class)
@Composable
fun buildChipInlineContent(
text: String,
padding: PaddingValues = PaddingValues(vertical = 2.dp, horizontal = 4.dp),
textStyle: TextStyle = LocalTextStyle.current,
chipTextStyle: TextStyle = LocalTextStyle.current,
backgroundColor: Color = ExtendedTheme.colors.chip,
color: Color = ExtendedTheme.colors.onChip
): InlineTextContent {
val textMeasurer = rememberTextMeasurer()
val textSize = remember(text, textStyle) { textMeasurer.measure(text, textStyle).size }
val heightPx = textSize.height
val heightSp = heightPx.pxToSpFloat().sp
val textHeightPx = textStyle.fontSize.value.spToPxFloat() -
padding.calculateTopPadding().value.dpToPxFloat() -
padding.calculateBottomPadding().value.dpToPxFloat()
val fontSize = textHeightPx.pxToSpFloat().sp
val textWidthPx = textSize.width
val widthPx = textWidthPx +
padding.calculateStartPadding(LocalLayoutDirection.current).value.dpToPxFloat() +
padding.calculateEndPadding(LocalLayoutDirection.current).value.dpToPxFloat()
val widthSp = widthPx.pxToSpFloat().sp
return InlineTextContent(
placeholder = Placeholder(
width = widthSp,
height = heightSp,
placeholderVerticalAlign = PlaceholderVerticalAlign.TextCenter
),
children = {
Box(
modifier = Modifier
.fillMaxSize(),
contentAlignment = Alignment.Center
) {
Text(
text = it.takeIf { it.isNotBlank() && it != "\uFFFD" } ?: text,
style = chipTextStyle.copy(
fontSize = fontSize,
lineHeight = fontSize,
lineHeightStyle = LineHeightStyle(
alignment = LineHeightStyle.Alignment.Center,
trim = LineHeightStyle.Trim.Both
)
),
textAlign = TextAlign.Center,
color = color,
modifier = Modifier
.fillMaxWidth()
.clip(RoundedCornerShape(100))
.background(backgroundColor)
.padding(padding)
)
}
}
)
}

View File

@ -15,6 +15,7 @@ message User {
int32 type = 7;
int32 userhide = 9;
int32 is_manager = 11;
int32 level_id = 23;
int32 is_bawu = 25;
string bawu_type = 26;
string portraith = 27;
@ -34,5 +35,6 @@ message User {
int32 priv_thread = 92;
int32 isDefaultAvatar = 106;
uint32 total_agree_num = 118;
string level_name = 125;
string ip_address = 127;
}