kopia lustrzana https://github.com/vitorpamplona/amethyst
Improves rendering performance of Chat Screens
rodzic
6fe66986be
commit
cce9d6cf68
|
@ -275,9 +275,10 @@ private fun RenderUserAsClickableText(
|
|||
CreateClickableTextWithEmoji(
|
||||
clickablePart = it,
|
||||
suffix = addedCharts,
|
||||
tags = userTags,
|
||||
maxLines = 1,
|
||||
route = route,
|
||||
nav = nav
|
||||
nav = nav,
|
||||
tags = userTags
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -286,24 +287,38 @@ private fun RenderUserAsClickableText(
|
|||
fun CreateClickableText(
|
||||
clickablePart: String,
|
||||
suffix: String,
|
||||
maxLines: Int = Int.MAX_VALUE,
|
||||
overrideColor: Color? = null,
|
||||
fontWeight: FontWeight = FontWeight.Normal,
|
||||
route: String,
|
||||
nav: (String) -> Unit
|
||||
) {
|
||||
ClickableText(
|
||||
text = buildAnnotatedString {
|
||||
withStyle(
|
||||
LocalTextStyle.current.copy(color = overrideColor ?: MaterialTheme.colors.primary, fontWeight = fontWeight).toSpanStyle()
|
||||
) {
|
||||
val currentStyle = LocalTextStyle.current
|
||||
val primaryColor = MaterialTheme.colors.primary
|
||||
val onBackgroundColor = MaterialTheme.colors.onBackground
|
||||
|
||||
val clickablePartStyle = remember(primaryColor, overrideColor) {
|
||||
currentStyle.copy(color = overrideColor ?: primaryColor, fontWeight = fontWeight).toSpanStyle()
|
||||
}
|
||||
|
||||
val nonClickablePartStyle = remember(onBackgroundColor, overrideColor) {
|
||||
currentStyle.copy(color = overrideColor ?: onBackgroundColor, fontWeight = fontWeight).toSpanStyle()
|
||||
}
|
||||
|
||||
val text = remember(clickablePartStyle, nonClickablePartStyle, clickablePart, suffix) {
|
||||
buildAnnotatedString {
|
||||
withStyle(clickablePartStyle) {
|
||||
append(clickablePart)
|
||||
}
|
||||
withStyle(
|
||||
LocalTextStyle.current.copy(color = overrideColor ?: MaterialTheme.colors.onBackground, fontWeight = fontWeight).toSpanStyle()
|
||||
) {
|
||||
withStyle(nonClickablePartStyle) {
|
||||
append(suffix)
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
ClickableText(
|
||||
text = text,
|
||||
maxLines = maxLines,
|
||||
onClick = { nav(route) }
|
||||
)
|
||||
}
|
||||
|
@ -410,14 +425,17 @@ fun CreateTextWithEmoji(
|
|||
modifier = modifier
|
||||
)
|
||||
} else {
|
||||
val style = LocalTextStyle.current.merge(
|
||||
TextStyle(
|
||||
color = textColor,
|
||||
textAlign = textAlign,
|
||||
fontWeight = fontWeight,
|
||||
fontSize = fontSize
|
||||
)
|
||||
).toSpanStyle()
|
||||
val currentStyle = LocalTextStyle.current
|
||||
val style = remember(currentStyle) {
|
||||
currentStyle.merge(
|
||||
TextStyle(
|
||||
color = textColor,
|
||||
textAlign = textAlign,
|
||||
fontWeight = fontWeight,
|
||||
fontSize = fontSize
|
||||
)
|
||||
).toSpanStyle()
|
||||
}
|
||||
|
||||
InLineIconRenderer(emojiList, style, maxLines, overflow, modifier)
|
||||
}
|
||||
|
@ -426,6 +444,7 @@ fun CreateTextWithEmoji(
|
|||
@Composable
|
||||
fun CreateClickableTextWithEmoji(
|
||||
clickablePart: String,
|
||||
maxLines: Int = Int.MAX_VALUE,
|
||||
tags: ImmutableListOfLists<String>?,
|
||||
style: TextStyle,
|
||||
onClick: (Int) -> Unit
|
||||
|
@ -448,29 +467,37 @@ fun CreateClickableTextWithEmoji(
|
|||
|
||||
if (emojiList.isEmpty()) {
|
||||
ClickableText(
|
||||
AnnotatedString(clickablePart),
|
||||
text = AnnotatedString(clickablePart),
|
||||
style = style,
|
||||
maxLines = maxLines,
|
||||
onClick = onClick
|
||||
)
|
||||
} else {
|
||||
ClickableInLineIconRenderer(emojiList, style.toSpanStyle()) {
|
||||
ClickableInLineIconRenderer(emojiList, maxLines, style.toSpanStyle()) {
|
||||
onClick(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Immutable
|
||||
data class DoubleEmojiList(
|
||||
val part1: ImmutableList<Renderable>,
|
||||
val part2: ImmutableList<Renderable>
|
||||
)
|
||||
|
||||
@Composable
|
||||
fun CreateClickableTextWithEmoji(
|
||||
clickablePart: String,
|
||||
suffix: String,
|
||||
tags: ImmutableListOfLists<String>?,
|
||||
maxLines: Int = Int.MAX_VALUE,
|
||||
overrideColor: Color? = null,
|
||||
fontWeight: FontWeight = FontWeight.Normal,
|
||||
route: String,
|
||||
nav: (String) -> Unit
|
||||
nav: (String) -> Unit,
|
||||
tags: ImmutableListOfLists<String>?
|
||||
) {
|
||||
var emojiLists by remember(clickablePart) {
|
||||
mutableStateOf<Pair<ImmutableList<Renderable>, ImmutableList<Renderable>>?>(null)
|
||||
mutableStateOf<DoubleEmojiList?>(null)
|
||||
}
|
||||
|
||||
LaunchedEffect(key1 = clickablePart) {
|
||||
|
@ -483,20 +510,28 @@ fun CreateClickableTextWithEmoji(
|
|||
val newEmojiList2 = assembleAnnotatedList(suffix, emojis)
|
||||
|
||||
if (newEmojiList1.isNotEmpty() || newEmojiList2.isNotEmpty()) {
|
||||
emojiLists = Pair(newEmojiList1.toImmutableList(), newEmojiList2.toImmutableList())
|
||||
emojiLists = DoubleEmojiList(newEmojiList1.toImmutableList(), newEmojiList2.toImmutableList())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (emojiLists == null) {
|
||||
CreateClickableText(clickablePart, suffix, overrideColor, fontWeight, route, nav)
|
||||
CreateClickableText(clickablePart, suffix, maxLines, overrideColor, fontWeight, route, nav)
|
||||
} else {
|
||||
ClickableInLineIconRenderer(emojiLists!!.first, LocalTextStyle.current.copy(color = overrideColor ?: MaterialTheme.colors.primary, fontWeight = fontWeight).toSpanStyle()) {
|
||||
ClickableInLineIconRenderer(
|
||||
emojiLists!!.part1,
|
||||
maxLines,
|
||||
LocalTextStyle.current.copy(color = overrideColor ?: MaterialTheme.colors.primary, fontWeight = fontWeight).toSpanStyle()
|
||||
) {
|
||||
nav(route)
|
||||
}
|
||||
|
||||
InLineIconRenderer(emojiLists!!.second, LocalTextStyle.current.copy(color = overrideColor ?: MaterialTheme.colors.onBackground, fontWeight = fontWeight).toSpanStyle())
|
||||
InLineIconRenderer(
|
||||
emojiLists!!.part2,
|
||||
LocalTextStyle.current.copy(color = overrideColor ?: MaterialTheme.colors.onBackground, fontWeight = fontWeight).toSpanStyle(),
|
||||
maxLines
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -521,7 +556,12 @@ class TextType(val text: String) : Renderable()
|
|||
class ImageUrlType(val url: String) : Renderable()
|
||||
|
||||
@Composable
|
||||
fun ClickableInLineIconRenderer(wordsInOrder: ImmutableList<Renderable>, style: SpanStyle, onClick: (Int) -> Unit) {
|
||||
fun ClickableInLineIconRenderer(
|
||||
wordsInOrder: ImmutableList<Renderable>,
|
||||
maxLines: Int = Int.MAX_VALUE,
|
||||
style: SpanStyle,
|
||||
onClick: (Int) -> Unit
|
||||
) {
|
||||
val inlineContent = wordsInOrder.mapIndexedNotNull { idx, value ->
|
||||
if (value is ImageUrlType) {
|
||||
Pair(
|
||||
|
@ -574,6 +614,7 @@ fun ClickableInLineIconRenderer(wordsInOrder: ImmutableList<Renderable>, style:
|
|||
text = annotatedText,
|
||||
modifier = pressIndicator,
|
||||
inlineContent = inlineContent,
|
||||
maxLines = maxLines,
|
||||
onTextLayout = {
|
||||
layoutResult.value = it
|
||||
}
|
||||
|
|
|
@ -1041,8 +1041,9 @@ private fun DisplayUserFromTag(
|
|||
CreateClickableTextWithEmoji(
|
||||
clickablePart = displayName,
|
||||
suffix = remember { "$addedChars " },
|
||||
tags = userTags,
|
||||
maxLines = 1,
|
||||
route = route,
|
||||
nav = nav
|
||||
nav = nav,
|
||||
tags = userTags
|
||||
)
|
||||
}
|
||||
|
|
|
@ -52,6 +52,7 @@ import androidx.compose.ui.unit.dp
|
|||
import androidx.compose.ui.unit.sp
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.model.Note
|
||||
import com.vitorpamplona.amethyst.model.User
|
||||
import com.vitorpamplona.amethyst.service.model.ChannelCreateEvent
|
||||
import com.vitorpamplona.amethyst.service.model.ChannelMetadataEvent
|
||||
import com.vitorpamplona.amethyst.service.model.PrivateDmEvent
|
||||
|
@ -72,6 +73,7 @@ import com.vitorpamplona.amethyst.ui.theme.RelayIconFilter
|
|||
import com.vitorpamplona.amethyst.ui.theme.Size13dp
|
||||
import com.vitorpamplona.amethyst.ui.theme.Size15Modifier
|
||||
import com.vitorpamplona.amethyst.ui.theme.Size16dp
|
||||
import com.vitorpamplona.amethyst.ui.theme.Size25dp
|
||||
import com.vitorpamplona.amethyst.ui.theme.StdHorzSpacer
|
||||
import com.vitorpamplona.amethyst.ui.theme.StdVertSpacer
|
||||
import com.vitorpamplona.amethyst.ui.theme.mediumImportanceLink
|
||||
|
@ -261,11 +263,11 @@ fun NormalChatNote(
|
|||
}
|
||||
}
|
||||
|
||||
LaunchedEffect(key1 = routeForLastRead) {
|
||||
routeForLastRead?.let {
|
||||
if (routeForLastRead != null) {
|
||||
LaunchedEffect(key1 = routeForLastRead) {
|
||||
val createdAt = note.createdAt()
|
||||
if (createdAt != null) {
|
||||
accountViewModel.account.markAsRead(it, createdAt)
|
||||
accountViewModel.account.markAsRead(routeForLastRead, createdAt)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -369,43 +371,72 @@ private fun RenderBubble(
|
|||
}
|
||||
|
||||
Column(modifier = bubbleModifier) {
|
||||
if (drawAuthorInfo) {
|
||||
DrawAuthorInfo(
|
||||
baseNote,
|
||||
alignment,
|
||||
nav
|
||||
)
|
||||
} else {
|
||||
Spacer(modifier = StdVertSpacer)
|
||||
}
|
||||
MessageBubbleLines(
|
||||
drawAuthorInfo,
|
||||
baseNote,
|
||||
alignment,
|
||||
nav,
|
||||
innerQuote,
|
||||
backgroundBubbleColor,
|
||||
accountViewModel,
|
||||
onWantsToReply,
|
||||
canPreview,
|
||||
bubbleSize,
|
||||
availableBubbleSize
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
RenderReplyRow(
|
||||
note = baseNote,
|
||||
innerQuote = innerQuote,
|
||||
backgroundBubbleColor = backgroundBubbleColor,
|
||||
@Composable
|
||||
private fun MessageBubbleLines(
|
||||
drawAuthorInfo: Boolean,
|
||||
baseNote: Note,
|
||||
alignment: Arrangement.Horizontal,
|
||||
nav: (String) -> Unit,
|
||||
innerQuote: Boolean,
|
||||
backgroundBubbleColor: MutableState<Color>,
|
||||
accountViewModel: AccountViewModel,
|
||||
onWantsToReply: (Note) -> Unit,
|
||||
canPreview: Boolean,
|
||||
bubbleSize: MutableState<IntSize>,
|
||||
availableBubbleSize: MutableState<IntSize>
|
||||
) {
|
||||
if (drawAuthorInfo) {
|
||||
DrawAuthorInfo(
|
||||
baseNote,
|
||||
alignment,
|
||||
nav
|
||||
)
|
||||
} else {
|
||||
Spacer(modifier = StdVertSpacer)
|
||||
}
|
||||
|
||||
RenderReplyRow(
|
||||
note = baseNote,
|
||||
innerQuote = innerQuote,
|
||||
backgroundBubbleColor = backgroundBubbleColor,
|
||||
accountViewModel = accountViewModel,
|
||||
nav = nav,
|
||||
onWantsToReply = onWantsToReply
|
||||
)
|
||||
|
||||
NoteRow(
|
||||
note = baseNote,
|
||||
canPreview = canPreview,
|
||||
backgroundBubbleColor = backgroundBubbleColor,
|
||||
accountViewModel = accountViewModel,
|
||||
nav = nav
|
||||
)
|
||||
|
||||
ConstrainedStatusRow(
|
||||
bubbleSize = bubbleSize,
|
||||
availableBubbleSize = availableBubbleSize
|
||||
) {
|
||||
StatusRow(
|
||||
baseNote = baseNote,
|
||||
accountViewModel = accountViewModel,
|
||||
nav = nav,
|
||||
onWantsToReply = onWantsToReply
|
||||
)
|
||||
|
||||
NoteRow(
|
||||
note = baseNote,
|
||||
canPreview = canPreview,
|
||||
backgroundBubbleColor = backgroundBubbleColor,
|
||||
accountViewModel = accountViewModel,
|
||||
nav = nav
|
||||
)
|
||||
|
||||
ConstrainedStatusRow(
|
||||
bubbleSize = bubbleSize,
|
||||
availableBubbleSize = availableBubbleSize
|
||||
) {
|
||||
StatusRow(
|
||||
baseNote = baseNote,
|
||||
accountViewModel = accountViewModel,
|
||||
onWantsToReply = onWantsToReply
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -418,25 +449,42 @@ private fun RenderReplyRow(
|
|||
nav: (String) -> Unit,
|
||||
onWantsToReply: (Note) -> Unit
|
||||
) {
|
||||
val replyTo by remember {
|
||||
val hasReply by remember {
|
||||
derivedStateOf {
|
||||
note.replyTo?.lastOrNull()
|
||||
innerQuote && note.replyTo?.lastOrNull() != null
|
||||
}
|
||||
}
|
||||
if (!innerQuote && replyTo != null) {
|
||||
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||
replyTo?.let { note ->
|
||||
ChatroomMessageCompose(
|
||||
note,
|
||||
null,
|
||||
innerQuote = true,
|
||||
parentBackgroundColor = backgroundBubbleColor,
|
||||
accountViewModel = accountViewModel,
|
||||
nav = nav,
|
||||
onWantsToReply = onWantsToReply
|
||||
)
|
||||
|
||||
if (hasReply) {
|
||||
RenderReply(note, backgroundBubbleColor, accountViewModel, nav, onWantsToReply)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun RenderReply(
|
||||
note: Note,
|
||||
backgroundBubbleColor: MutableState<Color>,
|
||||
accountViewModel: AccountViewModel,
|
||||
nav: (String) -> Unit,
|
||||
onWantsToReply: (Note) -> Unit
|
||||
) {
|
||||
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||
val replyTo by remember {
|
||||
derivedStateOf {
|
||||
note.replyTo?.lastOrNull()
|
||||
}
|
||||
}
|
||||
replyTo?.let { note ->
|
||||
ChatroomMessageCompose(
|
||||
note,
|
||||
null,
|
||||
innerQuote = true,
|
||||
parentBackgroundColor = backgroundBubbleColor,
|
||||
accountViewModel = accountViewModel,
|
||||
nav = nav,
|
||||
onWantsToReply = onWantsToReply
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -501,9 +549,7 @@ private fun StatusRow(
|
|||
accountViewModel: AccountViewModel,
|
||||
onWantsToReply: (Note) -> Unit
|
||||
) {
|
||||
val grayTint = MaterialTheme.colors.placeholderText
|
||||
|
||||
Column() {
|
||||
Column {
|
||||
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||
ChatTimeAgo(baseNote)
|
||||
RelayBadges(baseNote)
|
||||
|
@ -511,16 +557,16 @@ private fun StatusRow(
|
|||
}
|
||||
}
|
||||
|
||||
Column() {
|
||||
Column {
|
||||
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||
LikeReaction(baseNote, grayTint, accountViewModel)
|
||||
LikeReaction(baseNote, MaterialTheme.colors.placeholderText, accountViewModel)
|
||||
Spacer(modifier = StdHorzSpacer)
|
||||
ZapReaction(baseNote, grayTint, accountViewModel)
|
||||
ZapReaction(baseNote, MaterialTheme.colors.placeholderText, accountViewModel)
|
||||
Spacer(modifier = StdHorzSpacer)
|
||||
ReplyReaction(
|
||||
baseNote,
|
||||
grayTint,
|
||||
accountViewModel,
|
||||
baseNote = baseNote,
|
||||
grayTint = MaterialTheme.colors.placeholderText,
|
||||
accountViewModel = accountViewModel,
|
||||
showCounter = false,
|
||||
iconSize = Size16dp
|
||||
) {
|
||||
|
@ -644,51 +690,107 @@ private fun DrawAuthorInfo(
|
|||
alignment: Arrangement.Horizontal,
|
||||
nav: (String) -> Unit
|
||||
) {
|
||||
val userState by baseNote.author!!.live().metadata.observeAsState()
|
||||
|
||||
val pubkeyHex = remember { baseNote.author?.pubkeyHex } ?: return
|
||||
val route = remember { "User/$pubkeyHex" }
|
||||
val userDisplayName = remember(userState) { userState?.user?.toBestDisplayName() }
|
||||
val userProfilePicture = remember(userState) { ResizeImage(userState?.user?.profilePicture(), 25.dp) }
|
||||
val userTags = remember(userState) { userState?.user?.info?.latestMetadata?.tags?.toImmutableListOfLists() }
|
||||
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = alignment,
|
||||
modifier = Modifier.padding(top = 5.dp)
|
||||
) {
|
||||
RobohashAsyncImageProxy(
|
||||
robot = pubkeyHex,
|
||||
model = userProfilePicture,
|
||||
contentDescription = stringResource(id = R.string.profile_image),
|
||||
modifier = remember {
|
||||
Modifier
|
||||
.width(25.dp)
|
||||
.height(25.dp)
|
||||
.clip(shape = CircleShape)
|
||||
.clickable(onClick = {
|
||||
nav(route)
|
||||
})
|
||||
}
|
||||
)
|
||||
DisplayAndWatchNoteAuthor(baseNote, nav)
|
||||
}
|
||||
}
|
||||
|
||||
userDisplayName?.let {
|
||||
Spacer(modifier = StdHorzSpacer)
|
||||
@Composable
|
||||
private fun DisplayAndWatchNoteAuthor(
|
||||
baseNote: Note,
|
||||
nav: (String) -> Unit
|
||||
) {
|
||||
val author = remember {
|
||||
baseNote.author
|
||||
}
|
||||
author?.let {
|
||||
WatchAndDisplayUser(it, nav)
|
||||
}
|
||||
}
|
||||
|
||||
CreateClickableTextWithEmoji(
|
||||
clickablePart = it,
|
||||
suffix = "",
|
||||
tags = userTags,
|
||||
fontWeight = FontWeight.Bold,
|
||||
overrideColor = MaterialTheme.colors.onBackground,
|
||||
route = route,
|
||||
nav = nav
|
||||
)
|
||||
@Composable
|
||||
private fun WatchAndDisplayUser(
|
||||
author: User,
|
||||
nav: (String) -> Unit
|
||||
) {
|
||||
val pubkeyHex = remember { author.pubkeyHex }
|
||||
val route = remember { "User/${author.pubkeyHex}" }
|
||||
|
||||
Spacer(modifier = StdHorzSpacer)
|
||||
DrawPlayName(it)
|
||||
val userState by author.live().metadata.observeAsState()
|
||||
|
||||
val userDisplayName by remember(userState) {
|
||||
derivedStateOf {
|
||||
userState?.user?.toBestDisplayName()
|
||||
}
|
||||
}
|
||||
|
||||
val userProfilePicture by remember(userState) {
|
||||
derivedStateOf {
|
||||
ResizeImage(userState?.user?.profilePicture(), Size25dp)
|
||||
}
|
||||
}
|
||||
|
||||
val userTags by remember(userState) {
|
||||
derivedStateOf {
|
||||
userState?.user?.info?.latestMetadata?.tags?.toImmutableListOfLists()
|
||||
}
|
||||
}
|
||||
|
||||
UserIcon(pubkeyHex, userProfilePicture, nav, route)
|
||||
|
||||
userDisplayName?.let {
|
||||
DisplayMessageUsername(it, userTags, route, nav)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun UserIcon(
|
||||
pubkeyHex: String,
|
||||
userProfilePicture: ResizeImage,
|
||||
nav: (String) -> Unit,
|
||||
route: String
|
||||
) {
|
||||
RobohashAsyncImageProxy(
|
||||
robot = pubkeyHex,
|
||||
model = userProfilePicture,
|
||||
contentDescription = stringResource(id = R.string.profile_image),
|
||||
modifier = remember {
|
||||
Modifier
|
||||
.width(Size25dp)
|
||||
.height(Size25dp)
|
||||
.clip(shape = CircleShape)
|
||||
.clickable(onClick = {
|
||||
nav(route)
|
||||
})
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun DisplayMessageUsername(
|
||||
userDisplayName: String,
|
||||
userTags: ImmutableListOfLists<String>?,
|
||||
route: String,
|
||||
nav: (String) -> Unit
|
||||
) {
|
||||
Spacer(modifier = StdHorzSpacer)
|
||||
CreateClickableTextWithEmoji(
|
||||
clickablePart = userDisplayName,
|
||||
suffix = "",
|
||||
maxLines = 1,
|
||||
tags = userTags,
|
||||
fontWeight = FontWeight.Bold,
|
||||
overrideColor = MaterialTheme.colors.onBackground, // we do not want clickable names in purple here.
|
||||
route = route,
|
||||
nav = nav
|
||||
)
|
||||
|
||||
Spacer(modifier = StdHorzSpacer)
|
||||
DrawPlayName(userDisplayName)
|
||||
}
|
||||
|
||||
@Immutable
|
||||
|
|
|
@ -2062,9 +2062,10 @@ private fun LoadAndDisplayUser(
|
|||
CreateClickableTextWithEmoji(
|
||||
clickablePart = userDisplayName,
|
||||
suffix = " ",
|
||||
tags = userTags,
|
||||
maxLines = 1,
|
||||
route = route,
|
||||
nav = nav
|
||||
nav = nav,
|
||||
tags = userTags
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -65,14 +65,16 @@ private fun UserNameDisplay(
|
|||
fontWeight = FontWeight.Bold,
|
||||
maxLines = 1
|
||||
)
|
||||
CreateTextWithEmoji(
|
||||
text = remember { "@$bestUserName" },
|
||||
tags = tags,
|
||||
color = MaterialTheme.colors.placeholderText,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
modifier = modifier
|
||||
)
|
||||
if (bestDisplayName != bestUserName) {
|
||||
CreateTextWithEmoji(
|
||||
text = remember { "@$bestUserName" },
|
||||
tags = tags,
|
||||
color = MaterialTheme.colors.placeholderText,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
modifier = modifier
|
||||
)
|
||||
}
|
||||
Spacer(StdHorzSpacer)
|
||||
DrawPlayName(bestDisplayName)
|
||||
} else if (bestDisplayName != null) {
|
||||
|
@ -88,7 +90,7 @@ private fun UserNameDisplay(
|
|||
DrawPlayName(bestDisplayName)
|
||||
} else if (bestUserName != null) {
|
||||
CreateTextWithEmoji(
|
||||
text = remember { "@$bestUserName" },
|
||||
text = bestUserName,
|
||||
tags = tags,
|
||||
fontWeight = FontWeight.Bold,
|
||||
maxLines = 1,
|
||||
|
@ -99,7 +101,7 @@ private fun UserNameDisplay(
|
|||
DrawPlayName(bestUserName)
|
||||
} else {
|
||||
Text(
|
||||
npubDisplay,
|
||||
text = npubDisplay,
|
||||
fontWeight = FontWeight.Bold,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
|
@ -113,8 +115,15 @@ fun DrawPlayName(name: String) {
|
|||
val context = LocalContext.current
|
||||
val lifecycleOwner = LocalLifecycleOwner.current
|
||||
|
||||
DrawPlayNameIcon {
|
||||
speak(name, context, lifecycleOwner)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun DrawPlayNameIcon(onClick: () -> Unit) {
|
||||
IconButton(
|
||||
onClick = { speak(name, context, lifecycleOwner) },
|
||||
onClick = onClick,
|
||||
modifier = StdButtonSizeModifier
|
||||
) {
|
||||
Icon(
|
||||
|
|
|
@ -99,6 +99,7 @@ import com.vitorpamplona.amethyst.ui.note.ZapReaction
|
|||
import com.vitorpamplona.amethyst.ui.screen.NostrChannelFeedViewModel
|
||||
import com.vitorpamplona.amethyst.ui.screen.RefreshingChatroomFeedView
|
||||
import com.vitorpamplona.amethyst.ui.theme.ButtonBorder
|
||||
import com.vitorpamplona.amethyst.ui.theme.DoubleVertSpacer
|
||||
import com.vitorpamplona.amethyst.ui.theme.Size35dp
|
||||
import com.vitorpamplona.amethyst.ui.theme.SmallBorder
|
||||
import com.vitorpamplona.amethyst.ui.theme.StdHorzSpacer
|
||||
|
@ -236,7 +237,7 @@ fun ChannelScreen(
|
|||
)
|
||||
}
|
||||
|
||||
Spacer(modifier = Modifier.height(10.dp))
|
||||
Spacer(modifier = DoubleVertSpacer)
|
||||
|
||||
replyTo.value?.let {
|
||||
DisplayReplyingToNote(it, accountViewModel, nav) {
|
||||
|
|
|
@ -26,10 +26,12 @@ val StdButtonSizeModifier = Modifier.size(20.dp)
|
|||
val StdHorzSpacer = Modifier.width(5.dp)
|
||||
val StdVertSpacer = Modifier.height(5.dp)
|
||||
val DoubleHorzSpacer = Modifier.width(10.dp)
|
||||
val DoubleVertSpacer = Modifier.width(10.dp)
|
||||
|
||||
val Size35dp = 35.dp
|
||||
val Size13dp = 13.dp
|
||||
val Size16dp = 16.dp
|
||||
val Size25dp = 25.dp
|
||||
val Size35dp = 35.dp
|
||||
|
||||
val StdPadding = Modifier.padding(10.dp)
|
||||
|
||||
|
|
Ładowanie…
Reference in New Issue