- User Metadata clean up upon receipt instead of in every rendering.
- Simpler/Faster UserDisplay renderings - Removes co-routing use for Hashtags.
This commit is contained in:
@@ -310,6 +310,7 @@ class User(val pubkeyHex: String) {
|
|||||||
info?.latestMetadata = latestMetadata
|
info?.latestMetadata = latestMetadata
|
||||||
info?.updatedMetadataAt = latestMetadata.createdAt
|
info?.updatedMetadataAt = latestMetadata.createdAt
|
||||||
info?.tags = latestMetadata.tags.toImmutableListOfLists()
|
info?.tags = latestMetadata.tags.toImmutableListOfLists()
|
||||||
|
info?.cleanBlankNames()
|
||||||
|
|
||||||
if (newUserInfo.lud16.isNullOrBlank()) {
|
if (newUserInfo.lud16.isNullOrBlank()) {
|
||||||
info?.lud06?.let {
|
info?.lud06?.let {
|
||||||
|
|||||||
@@ -76,6 +76,7 @@ import com.vitorpamplona.amethyst.ui.note.elements.DisplayZapSplits
|
|||||||
import com.vitorpamplona.amethyst.ui.note.elements.MoreOptionsButton
|
import com.vitorpamplona.amethyst.ui.note.elements.MoreOptionsButton
|
||||||
import com.vitorpamplona.amethyst.ui.note.elements.Reward
|
import com.vitorpamplona.amethyst.ui.note.elements.Reward
|
||||||
import com.vitorpamplona.amethyst.ui.note.elements.ShowForkInformation
|
import com.vitorpamplona.amethyst.ui.note.elements.ShowForkInformation
|
||||||
|
import com.vitorpamplona.amethyst.ui.note.elements.TimeAgo
|
||||||
import com.vitorpamplona.amethyst.ui.note.types.BadgeDisplay
|
import com.vitorpamplona.amethyst.ui.note.types.BadgeDisplay
|
||||||
import com.vitorpamplona.amethyst.ui.note.types.CommunityHeader
|
import com.vitorpamplona.amethyst.ui.note.types.CommunityHeader
|
||||||
import com.vitorpamplona.amethyst.ui.note.types.DisplayPeopleList
|
import com.vitorpamplona.amethyst.ui.note.types.DisplayPeopleList
|
||||||
@@ -1121,11 +1122,8 @@ fun FirstUserInfoRow(
|
|||||||
accountViewModel: AccountViewModel,
|
accountViewModel: AccountViewModel,
|
||||||
nav: (String) -> Unit,
|
nav: (String) -> Unit,
|
||||||
) {
|
) {
|
||||||
Row(verticalAlignment = CenterVertically, modifier = remember { UserNameRowHeight }) {
|
Row(verticalAlignment = CenterVertically, modifier = UserNameRowHeight) {
|
||||||
val isRepost by
|
val isRepost = baseNote.event is RepostEvent || baseNote.event is GenericRepostEvent
|
||||||
remember(baseNote) {
|
|
||||||
derivedStateOf { baseNote.event is RepostEvent || baseNote.event is GenericRepostEvent }
|
|
||||||
}
|
|
||||||
|
|
||||||
val isCommunityPost by
|
val isCommunityPost by
|
||||||
remember(baseNote) {
|
remember(baseNote) {
|
||||||
@@ -1139,9 +1137,9 @@ fun FirstUserInfoRow(
|
|||||||
if (showAuthorPicture) {
|
if (showAuthorPicture) {
|
||||||
NoteAuthorPicture(baseNote, nav, accountViewModel, Size25dp)
|
NoteAuthorPicture(baseNote, nav, accountViewModel, Size25dp)
|
||||||
Spacer(HalfPadding)
|
Spacer(HalfPadding)
|
||||||
NoteUsernameDisplay(baseNote, remember { Modifier.weight(1f) }, textColor = textColor)
|
NoteUsernameDisplay(baseNote, Modifier.weight(1f), textColor = textColor)
|
||||||
} else {
|
} else {
|
||||||
NoteUsernameDisplay(baseNote, remember { Modifier.weight(1f) }, textColor = textColor)
|
NoteUsernameDisplay(baseNote, Modifier.weight(1f), textColor = textColor)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isRepost) {
|
if (isRepost) {
|
||||||
@@ -1158,7 +1156,7 @@ fun FirstUserInfoRow(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
com.vitorpamplona.amethyst.ui.note.elements.TimeAgo(baseNote)
|
TimeAgo(baseNote)
|
||||||
|
|
||||||
MoreOptionsButton(baseNote, editState, accountViewModel, nav)
|
MoreOptionsButton(baseNote, editState, accountViewModel, nav)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,7 +29,6 @@ import androidx.compose.material3.IconButton
|
|||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.derivedStateOf
|
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.livedata.observeAsState
|
import androidx.compose.runtime.livedata.observeAsState
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
@@ -72,67 +71,27 @@ fun UsernameDisplay(
|
|||||||
fontWeight: FontWeight = FontWeight.Bold,
|
fontWeight: FontWeight = FontWeight.Bold,
|
||||||
textColor: Color = Color.Unspecified,
|
textColor: Color = Color.Unspecified,
|
||||||
) {
|
) {
|
||||||
val npubDisplay by remember { derivedStateOf { baseUser.pubkeyDisplayHex() } }
|
|
||||||
|
|
||||||
val userMetadata by baseUser.live().userMetadataInfo.observeAsState(baseUser.info)
|
val userMetadata by baseUser.live().userMetadataInfo.observeAsState(baseUser.info)
|
||||||
|
|
||||||
Crossfade(targetState = userMetadata, modifier = weight, label = "UsernameDisplay") {
|
Crossfade(targetState = userMetadata, modifier = weight, label = "UsernameDisplay") {
|
||||||
if (it != null) {
|
val name = it?.bestDisplayName() ?: it?.bestUsername()
|
||||||
UserNameDisplay(
|
if (name != null) {
|
||||||
it.bestUsername(),
|
UserDisplay(name, it?.tags, weight, showPlayButton, fontWeight, textColor)
|
||||||
it.bestDisplayName(),
|
|
||||||
npubDisplay,
|
|
||||||
it.tags,
|
|
||||||
weight,
|
|
||||||
showPlayButton,
|
|
||||||
fontWeight,
|
|
||||||
textColor,
|
|
||||||
)
|
|
||||||
} else {
|
} else {
|
||||||
NPubDisplay(npubDisplay, weight, fontWeight, textColor)
|
NPubDisplay(baseUser, weight, fontWeight, textColor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun UserNameDisplay(
|
private fun NPubDisplay(
|
||||||
bestUserName: String?,
|
user: User,
|
||||||
bestDisplayName: String?,
|
|
||||||
npubDisplay: String,
|
|
||||||
tags: ImmutableListOfLists<String>?,
|
|
||||||
modifier: Modifier,
|
|
||||||
showPlayButton: Boolean = true,
|
|
||||||
fontWeight: FontWeight = FontWeight.Bold,
|
|
||||||
textColor: Color = Color.Unspecified,
|
|
||||||
) {
|
|
||||||
if (bestUserName != null && bestDisplayName != null && bestDisplayName != bestUserName) {
|
|
||||||
UserAndUsernameDisplay(
|
|
||||||
bestDisplayName.trim(),
|
|
||||||
tags,
|
|
||||||
bestUserName.trim(),
|
|
||||||
modifier,
|
|
||||||
showPlayButton,
|
|
||||||
fontWeight,
|
|
||||||
textColor,
|
|
||||||
)
|
|
||||||
} else if (bestDisplayName != null) {
|
|
||||||
UserDisplay(bestDisplayName.trim(), tags, modifier, showPlayButton, fontWeight, textColor)
|
|
||||||
} else if (bestUserName != null) {
|
|
||||||
UserDisplay(bestUserName.trim(), tags, modifier, showPlayButton, fontWeight, textColor)
|
|
||||||
} else {
|
|
||||||
NPubDisplay(npubDisplay, modifier, fontWeight, textColor)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
fun NPubDisplay(
|
|
||||||
npubDisplay: String,
|
|
||||||
modifier: Modifier,
|
modifier: Modifier,
|
||||||
fontWeight: FontWeight = FontWeight.Bold,
|
fontWeight: FontWeight = FontWeight.Bold,
|
||||||
textColor: Color = Color.Unspecified,
|
textColor: Color = Color.Unspecified,
|
||||||
) {
|
) {
|
||||||
Text(
|
Text(
|
||||||
text = npubDisplay,
|
text = remember { user.pubkeyDisplayHex() },
|
||||||
fontWeight = fontWeight,
|
fontWeight = fontWeight,
|
||||||
modifier = modifier,
|
modifier = modifier,
|
||||||
maxLines = 1,
|
maxLines = 1,
|
||||||
@@ -160,41 +119,7 @@ private fun UserDisplay(
|
|||||||
modifier = modifier,
|
modifier = modifier,
|
||||||
color = textColor,
|
color = textColor,
|
||||||
)
|
)
|
||||||
if (showPlayButton) {
|
|
||||||
Spacer(StdHorzSpacer)
|
|
||||||
DrawPlayName(bestDisplayName)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
private fun UserAndUsernameDisplay(
|
|
||||||
bestDisplayName: String,
|
|
||||||
tags: ImmutableListOfLists<String>?,
|
|
||||||
bestUserName: String,
|
|
||||||
modifier: Modifier,
|
|
||||||
showPlayButton: Boolean = true,
|
|
||||||
fontWeight: FontWeight = FontWeight.Bold,
|
|
||||||
textColor: Color = Color.Unspecified,
|
|
||||||
) {
|
|
||||||
Row(modifier = modifier, verticalAlignment = Alignment.CenterVertically) {
|
|
||||||
CreateTextWithEmoji(
|
|
||||||
text = bestDisplayName,
|
|
||||||
tags = tags,
|
|
||||||
fontWeight = fontWeight,
|
|
||||||
maxLines = 1,
|
|
||||||
modifier = modifier,
|
|
||||||
color = textColor,
|
|
||||||
)
|
|
||||||
/*
|
|
||||||
CreateTextWithEmoji(
|
|
||||||
text = remember { "@$bestUserName" },
|
|
||||||
tags = tags,
|
|
||||||
color = MaterialTheme.colorScheme.placeholderText,
|
|
||||||
maxLines = 1,
|
|
||||||
overflow = TextOverflow.Ellipsis,
|
|
||||||
|
|
||||||
)*/
|
|
||||||
if (showPlayButton) {
|
if (showPlayButton) {
|
||||||
Spacer(StdHorzSpacer)
|
Spacer(StdHorzSpacer)
|
||||||
DrawPlayName(bestDisplayName)
|
DrawPlayName(bestDisplayName)
|
||||||
@@ -207,12 +132,7 @@ fun DrawPlayName(name: String) {
|
|||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
val lifecycleOwner = LocalLifecycleOwner.current
|
val lifecycleOwner = LocalLifecycleOwner.current
|
||||||
|
|
||||||
DrawPlayNameIcon { speak(name, context, lifecycleOwner) }
|
IconButton(onClick = { speak(name, context, lifecycleOwner) }, modifier = StdButtonSizeModifier) {
|
||||||
}
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
fun DrawPlayNameIcon(onClick: () -> Unit) {
|
|
||||||
IconButton(onClick = onClick, modifier = StdButtonSizeModifier) {
|
|
||||||
PlayIcon(
|
PlayIcon(
|
||||||
modifier = StdButtonSizeModifier,
|
modifier = StdButtonSizeModifier,
|
||||||
tint = MaterialTheme.colorScheme.placeholderText,
|
tint = MaterialTheme.colorScheme.placeholderText,
|
||||||
|
|||||||
@@ -37,8 +37,6 @@ import androidx.compose.ui.Alignment
|
|||||||
import androidx.compose.ui.text.AnnotatedString
|
import androidx.compose.ui.text.AnnotatedString
|
||||||
import com.vitorpamplona.amethyst.model.Note
|
import com.vitorpamplona.amethyst.model.Note
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun DisplayFollowingHashtagsInPost(
|
fun DisplayFollowingHashtagsInPost(
|
||||||
@@ -50,13 +48,11 @@ fun DisplayFollowingHashtagsInPost(
|
|||||||
var firstTag by remember(baseNote) { mutableStateOf<String?>(null) }
|
var firstTag by remember(baseNote) { mutableStateOf<String?>(null) }
|
||||||
|
|
||||||
LaunchedEffect(key1 = userFollowState) {
|
LaunchedEffect(key1 = userFollowState) {
|
||||||
launch(Dispatchers.Default) {
|
val followingTags = userFollowState?.user?.cachedFollowingTagSet() ?: emptySet()
|
||||||
val followingTags = userFollowState?.user?.cachedFollowingTagSet() ?: emptySet()
|
val newFirstTag = baseNote.event?.firstIsTaggedHashes(followingTags)
|
||||||
val newFirstTag = baseNote.event?.firstIsTaggedHashes(followingTags)
|
|
||||||
|
|
||||||
if (firstTag != newFirstTag) {
|
if (firstTag != newFirstTag) {
|
||||||
launch(Dispatchers.Main) { firstTag = newFirstTag }
|
firstTag = newFirstTag
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -429,25 +429,50 @@ class UserMetadata {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun lnAddress(): String? {
|
fun lnAddress(): String? {
|
||||||
return (lud16?.trim() ?: lud06?.trim())?.ifBlank { null }
|
return lud16 ?: lud06
|
||||||
}
|
}
|
||||||
|
|
||||||
fun bestUsername(): String? {
|
fun bestUsername(): String? {
|
||||||
return name?.ifBlank { null } ?: username?.ifBlank { null }
|
return name ?: username
|
||||||
}
|
}
|
||||||
|
|
||||||
fun bestDisplayName(): String? {
|
fun bestDisplayName(): String? {
|
||||||
return displayName?.ifBlank { null }
|
return displayName
|
||||||
}
|
}
|
||||||
|
|
||||||
fun nip05(): String? {
|
fun nip05(): String? {
|
||||||
return nip05?.ifBlank { null }
|
return nip05
|
||||||
}
|
}
|
||||||
|
|
||||||
fun profilePicture(): String? {
|
fun profilePicture(): String? {
|
||||||
if (picture.isNullOrBlank()) picture = null
|
|
||||||
return picture
|
return picture
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun cleanBlankNames() {
|
||||||
|
if (picture?.isNotEmpty() == true) picture = picture?.trim()
|
||||||
|
if (nip05?.isNotEmpty() == true) nip05 = nip05?.trim()
|
||||||
|
if (displayName?.isNotEmpty() == true) displayName = displayName?.trim()
|
||||||
|
if (name?.isNotEmpty() == true) name = name?.trim()
|
||||||
|
if (username?.isNotEmpty() == true) username = username?.trim()
|
||||||
|
if (lud06?.isNotEmpty() == true) lud06 = lud06?.trim()
|
||||||
|
if (lud16?.isNotEmpty() == true) lud16 = lud16?.trim()
|
||||||
|
|
||||||
|
if (banner?.isNotEmpty() == true) banner = banner?.trim()
|
||||||
|
if (website?.isNotEmpty() == true) website = website?.trim()
|
||||||
|
if (domain?.isNotEmpty() == true) domain = domain?.trim()
|
||||||
|
|
||||||
|
if (picture?.isBlank() == true) picture = null
|
||||||
|
if (nip05?.isBlank() == true) nip05 = null
|
||||||
|
if (displayName?.isBlank() == true) displayName = null
|
||||||
|
if (name?.isBlank() == true) name = null
|
||||||
|
if (username?.isBlank() == true) username = null
|
||||||
|
if (lud06?.isBlank() == true) lud06 = null
|
||||||
|
if (lud16?.isBlank() == true) lud16 = null
|
||||||
|
|
||||||
|
if (banner?.isBlank() == true) banner = null
|
||||||
|
if (website?.isBlank() == true) website = null
|
||||||
|
if (domain?.isBlank() == true) domain = null
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Stable class ImmutableListOfLists<T>(val lists: Array<Array<T>>)
|
@Stable class ImmutableListOfLists<T>(val lists: Array<Array<T>>)
|
||||||
|
|||||||
Reference in New Issue
Block a user