diff --git a/app/src/main/java/com/huanchengfly/tieba/post/ui/page/forum/ForumPage.kt b/app/src/main/java/com/huanchengfly/tieba/post/ui/page/forum/ForumPage.kt index 2bd2002c..272268f5 100644 --- a/app/src/main/java/com/huanchengfly/tieba/post/ui/page/forum/ForumPage.kt +++ b/app/src/main/java/com/huanchengfly/tieba/post/ui/page/forum/ForumPage.kt @@ -132,8 +132,6 @@ import kotlinx.coroutines.launch import kotlin.math.max import kotlin.math.min -private val TabWidth = 100.dp - fun getSortType( context: Context, forumName: String diff --git a/app/src/main/java/com/huanchengfly/tieba/post/ui/page/main/explore/hot/HotPage.kt b/app/src/main/java/com/huanchengfly/tieba/post/ui/page/main/explore/hot/HotPage.kt index d0673132..ac329999 100644 --- a/app/src/main/java/com/huanchengfly/tieba/post/ui/page/main/explore/hot/HotPage.kt +++ b/app/src/main/java/com/huanchengfly/tieba/post/ui/page/main/explore/hot/HotPage.kt @@ -126,8 +126,8 @@ fun HotPage( item(key = "TopicList") { VerticalGrid( column = 2, - horizontalArrangement = Arrangement.spacedBy(16.dp), - modifier = Modifier.padding(horizontal = 16.dp) + modifier = Modifier.padding(horizontal = 16.dp), + horizontalArrangement = Arrangement.spacedBy(16.dp) ) { itemsIndexed( items = topicList, 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 04246828..5692d574 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 @@ -107,8 +107,8 @@ fun Dislike( bottom.linkTo(parent.bottom) } .padding(horizontal = 16.dp), - horizontalArrangement = Arrangement.spacedBy(4.dp), verticalArrangement = Arrangement.spacedBy(4.dp), + horizontalArrangement = Arrangement.spacedBy(4.dp), ) { items( items = dislikeResource, diff --git a/app/src/main/java/com/huanchengfly/tieba/post/ui/page/main/user/UserPage.kt b/app/src/main/java/com/huanchengfly/tieba/post/ui/page/main/user/UserPage.kt index 7c9091f3..3c2007cb 100644 --- a/app/src/main/java/com/huanchengfly/tieba/post/ui/page/main/user/UserPage.kt +++ b/app/src/main/java/com/huanchengfly/tieba/post/ui/page/main/user/UserPage.kt @@ -60,6 +60,7 @@ import com.huanchengfly.tieba.post.ui.page.destinations.SettingsPageDestination import com.huanchengfly.tieba.post.ui.page.destinations.ThreadStorePageDestination import com.huanchengfly.tieba.post.ui.widgets.compose.Avatar import com.huanchengfly.tieba.post.ui.widgets.compose.HorizontalDivider +import com.huanchengfly.tieba.post.ui.widgets.compose.ListMenuItem import com.huanchengfly.tieba.post.ui.widgets.compose.Sizes import com.huanchengfly.tieba.post.ui.widgets.compose.Switch import com.huanchengfly.tieba.post.ui.widgets.compose.VerticalDivider @@ -377,36 +378,3 @@ fun UserPage( } } } - -@Composable -private fun ListMenuItem( - icon: ImageVector, - text: String, - modifier: Modifier = Modifier, - onClick: (() -> Unit)? = null, - customContent: @Composable (RowScope.() -> Unit)? = null, -) { - val menuModifier = if (onClick != null) { - Modifier.clickable(onClick = onClick) - } else { - Modifier - } - Row( - verticalAlignment = Alignment.CenterVertically, - modifier = modifier - .then(menuModifier) - .padding(horizontal = 16.dp, vertical = 12.dp), - ) { - Icon(imageVector = icon, contentDescription = text, tint = ExtendedTheme.colors.accent) - Spacer(modifier = Modifier.width(16.dp)) - Text( - text = text, - fontSize = 14.sp, - fontWeight = FontWeight.Bold, - maxLines = 1, - modifier = Modifier.weight(1f), - ) - Spacer(modifier = Modifier.width(16.dp)) - customContent?.invoke(this) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/huanchengfly/tieba/post/ui/widgets/compose/Grid.kt b/app/src/main/java/com/huanchengfly/tieba/post/ui/widgets/compose/Grid.kt index a6ca126e..9d4c51d2 100644 --- a/app/src/main/java/com/huanchengfly/tieba/post/ui/widgets/compose/Grid.kt +++ b/app/src/main/java/com/huanchengfly/tieba/post/ui/widgets/compose/Grid.kt @@ -108,6 +108,7 @@ private fun calcRows(column: Int, items: List): List Unit @@ -118,7 +119,8 @@ fun VerticalGrid( rows.forEach { Row( verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = horizontalArrangement + horizontalArrangement = horizontalArrangement, + modifier = rowModifier ) { it.forEach { Box( diff --git a/app/src/main/java/com/huanchengfly/tieba/post/ui/widgets/compose/Lists.kt b/app/src/main/java/com/huanchengfly/tieba/post/ui/widgets/compose/Lists.kt new file mode 100644 index 00000000..c387afa8 --- /dev/null +++ b/app/src/main/java/com/huanchengfly/tieba/post/ui/widgets/compose/Lists.kt @@ -0,0 +1,53 @@ +package com.huanchengfly.tieba.post.ui.widgets.compose + +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.RowScope +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.width +import androidx.compose.material.Icon +import androidx.compose.material.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import com.huanchengfly.tieba.post.ui.common.theme.compose.ExtendedTheme + +@Composable +fun ListMenuItem( + icon: ImageVector, + text: String, + modifier: Modifier = Modifier, + iconColor: Color = ExtendedTheme.colors.accent, + onClick: (() -> Unit)? = null, + customContent: @Composable (RowScope.() -> Unit)? = null, +) { + val menuModifier = if (onClick != null) { + Modifier.clickable(onClick = onClick) + } else { + Modifier + } + Row( + verticalAlignment = Alignment.CenterVertically, + modifier = modifier + .then(menuModifier) + .padding(horizontal = 16.dp, vertical = 12.dp), + ) { + Icon(imageVector = icon, contentDescription = text, tint = iconColor) + Spacer(modifier = Modifier.width(16.dp)) + Text( + text = text, + fontSize = 14.sp, + fontWeight = FontWeight.Bold, + maxLines = 1, + modifier = Modifier.weight(1f), + ) + Spacer(modifier = Modifier.width(16.dp)) + customContent?.invoke(this) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/huanchengfly/tieba/post/ui/widgets/compose/Texts.kt b/app/src/main/java/com/huanchengfly/tieba/post/ui/widgets/compose/Texts.kt index f79d88ad..55b4173b 100644 --- a/app/src/main/java/com/huanchengfly/tieba/post/ui/widgets/compose/Texts.kt +++ b/app/src/main/java/com/huanchengfly/tieba/post/ui/widgets/compose/Texts.kt @@ -1,5 +1,6 @@ package com.huanchengfly.tieba.post.ui.widgets.compose +import androidx.compose.foundation.layout.defaultMinSize import androidx.compose.foundation.layout.size import androidx.compose.foundation.text.InlineTextContent import androidx.compose.material.Icon @@ -10,6 +11,7 @@ import androidx.compose.material.Text import androidx.compose.material.icons.Icons import androidx.compose.material.icons.rounded.AccountCircle 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.Modifier @@ -17,6 +19,7 @@ import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.takeOrElse import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.AnnotatedString +import androidx.compose.ui.text.ExperimentalTextApi import androidx.compose.ui.text.Placeholder import androidx.compose.ui.text.PlaceholderVerticalAlign import androidx.compose.ui.text.TextLayoutResult @@ -24,6 +27,7 @@ import androidx.compose.ui.text.TextStyle 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.TextAlign import androidx.compose.ui.text.style.TextDecoration import androidx.compose.ui.text.style.TextOverflow @@ -38,7 +42,6 @@ import com.huanchengfly.tieba.post.utils.EmoticonManager import com.huanchengfly.tieba.post.utils.EmoticonUtil.emoticonString import com.huanchengfly.tieba.post.utils.getEmoticonHeightPx - @Composable fun EmoticonText( text: String, @@ -100,6 +103,7 @@ fun EmoticonText( softWrap: Boolean = true, maxLines: Int = Int.MAX_VALUE, minLines: Int = 1, + emoticonSize: Float = 0.9f, inlineContent: Map = emptyMap(), onTextLayout: (TextLayoutResult) -> Unit = {}, style: TextStyle = LocalTextStyle.current @@ -122,7 +126,7 @@ fun EmoticonText( letterSpacing = letterSpacing ) ) - val sizePx = getEmoticonHeightPx(mergedStyle) + val sizePx = getEmoticonHeightPx(mergedStyle) * emoticonSize val emoticonInlineContent = remember(sizePx) { EmoticonManager.getEmoticonInlineContent(sizePx) } IconText( @@ -203,7 +207,22 @@ fun IconText( Icons.Rounded.Link, contentDescription = stringResource(id = R.string.link), modifier = Modifier.size(sizeDp), - tint = ExtendedTheme.colors.accent, + tint = ExtendedTheme.colors.primary, + ) + } + ), + "video_icon" to InlineTextContent( + placeholder = Placeholder( + width = sizeSp, + height = sizeSp, + placeholderVerticalAlign = PlaceholderVerticalAlign.TextCenter + ), + children = { + Icon( + Icons.Rounded.SlowMotionVideo, + contentDescription = stringResource(id = R.string.desc_video), + modifier = Modifier.size(sizeDp), + tint = ExtendedTheme.colors.primary, ) } ), @@ -218,7 +237,7 @@ fun IconText( Icons.Rounded.AccountCircle, contentDescription = stringResource(id = R.string.user), modifier = Modifier.size(sizeDp), - tint = ExtendedTheme.colors.accent, + tint = ExtendedTheme.colors.primary, ) } ), @@ -244,4 +263,61 @@ fun IconText( onTextLayout, style ) +} + +/** + * A [Text] composable that supports setting its minimum width to width of the specified number of Chinese characters + */ +@OptIn(ExperimentalTextApi::class) +@Composable +fun TextWithMinWidth( + text: String, + modifier: Modifier = Modifier, + color: Color = Color.Unspecified, + fontSize: TextUnit = TextUnit.Unspecified, + fontStyle: FontStyle? = null, + fontWeight: FontWeight? = null, + fontFamily: FontFamily? = null, + letterSpacing: TextUnit = TextUnit.Unspecified, + textDecoration: TextDecoration? = null, + textAlign: TextAlign? = null, + lineHeight: TextUnit = TextUnit.Unspecified, + overflow: TextOverflow = TextOverflow.Clip, + softWrap: Boolean = true, + maxLines: Int = Int.MAX_VALUE, + minLines: Int = 1, + minLength: Int = 0, + onTextLayout: (TextLayoutResult) -> Unit = {}, + style: TextStyle = LocalTextStyle.current, +) { + val textMeasurer = rememberTextMeasurer() + val singleChar = stringResource(id = R.string.single_chinese_char) + val singleCharWidth = remember(style) { + textMeasurer.measure( + text = singleChar, + style = style + ).size.width.pxToDp().dp + } + + Text( + text = text, + modifier = Modifier + .defaultMinSize(minWidth = singleCharWidth * minLength) + .then(modifier), + color = color, + fontSize = fontSize, + fontStyle = fontStyle, + fontWeight = fontWeight, + fontFamily = fontFamily, + letterSpacing = letterSpacing, + textDecoration = textDecoration, + textAlign = textAlign, + lineHeight = lineHeight, + overflow = overflow, + softWrap = softWrap, + maxLines = maxLines, + minLines = minLines, + onTextLayout = onTextLayout, + style = style + ) } \ No newline at end of file diff --git a/app/src/main/java/com/huanchengfly/tieba/post/ui/widgets/compose/Toolbar.kt b/app/src/main/java/com/huanchengfly/tieba/post/ui/widgets/compose/Toolbar.kt index 9942c15e..26bc8b4b 100644 --- a/app/src/main/java/com/huanchengfly/tieba/post/ui/widgets/compose/Toolbar.kt +++ b/app/src/main/java/com/huanchengfly/tieba/post/ui/widgets/compose/Toolbar.kt @@ -231,6 +231,58 @@ fun TitleCentredToolbar( } } +@Composable +fun TitleCentredToolbar( + title: @Composable () -> Unit, + modifier: Modifier = Modifier, + navigationIcon: @Composable (() -> Unit)? = null, + actions: @Composable (RowScope.() -> Unit) = {}, + content: @Composable (ColumnScope.() -> Unit) = {}, +) { + Column( + modifier = Modifier + .background(ExtendedTheme.colors.topBar) + .then(modifier) + ) { + TopAppBar( + backgroundColor = ExtendedTheme.colors.topBar, + contentColor = ExtendedTheme.colors.onTopBar, + elevation = 0.dp + ) { + Box(modifier = Modifier.fillMaxSize()) { + Row( + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.CenterVertically, + modifier = Modifier.fillMaxHeight() + ) { + navigationIcon?.invoke() + + Spacer(modifier = Modifier.weight(1f)) + + actions() + } + + Row( + Modifier + .fillMaxHeight() + .align(Alignment.Center), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.Center + ) { + title() + } + } + } + Column( + modifier = Modifier + .fillMaxWidth() + .background(color = ExtendedTheme.colors.topBar) + ) { + content() + } + } +} + @Composable fun Toolbar( title: String, diff --git a/app/src/main/java/com/huanchengfly/tieba/post/utils/EmoticonManager.kt b/app/src/main/java/com/huanchengfly/tieba/post/utils/EmoticonManager.kt index 99569a08..3e37f015 100644 --- a/app/src/main/java/com/huanchengfly/tieba/post/utils/EmoticonManager.kt +++ b/app/src/main/java/com/huanchengfly/tieba/post/utils/EmoticonManager.kt @@ -118,7 +118,7 @@ object EmoticonManager { private val coroutineScope: CoroutineScope = CoroutineScope(Dispatchers.IO) fun getEmoticonInlineContent( - sizePx: Int + sizePx: Float ): Map { return emoticonIds.associate { id -> "Emoticon#$id" to InlineTextContent(