Fixing some of the old display name structure

pull/806/head
Vitor Pamplona 2024-03-12 17:51:27 -04:00
rodzic e094b56b72
commit 0dbd58d8d7
17 zmienionych plików z 91 dodań i 217 usunięć

Wyświetl plik

@ -81,7 +81,7 @@ class User(val pubkeyHex: String) {
override fun toString(): String = pubkeyHex
fun toBestShortFirstName(): String {
val fullName = bestDisplayName() ?: bestUsername() ?: return pubkeyDisplayHex()
val fullName = toBestDisplayName()
val names = fullName.split(' ')
@ -97,23 +97,14 @@ class User(val pubkeyHex: String) {
}
fun toBestDisplayName(): String {
return bestDisplayName() ?: bestUsername() ?: pubkeyDisplayHex()
}
fun bestUsername(): String? {
return info?.name?.ifBlank { null } ?: info?.username?.ifBlank { null }
}
fun bestDisplayName(): String? {
return info?.displayName?.ifBlank { null }
return info?.bestName() ?: pubkeyDisplayHex()
}
fun nip05(): String? {
return info?.nip05?.ifBlank { null }
return info?.nip05
}
fun profilePicture(): String? {
if (info?.picture.isNullOrBlank()) info?.picture = null
return info?.picture
}

Wyświetl plik

@ -35,7 +35,7 @@ object NostrSingleUserDataSource : NostrDataSource("SingleUserFeed") {
fun createUserMetadataFilter(): List<TypedFilter>? {
if (usersToWatch.isEmpty()) return null
val firstTimers = usersToWatch.filter { it.info?.latestMetadata == null }.map { it.pubkeyHex }
val firstTimers = usersToWatch.filter { it.latestMetadata == null }.map { it.pubkeyHex }
if (firstTimers.isEmpty()) return null
@ -54,7 +54,7 @@ object NostrSingleUserDataSource : NostrDataSource("SingleUserFeed") {
fun createUserMetadataStatusReportFilter(): List<TypedFilter>? {
if (usersToWatch.isEmpty()) return null
val secondTimers = usersToWatch.filter { it.info?.latestMetadata != null }
val secondTimers = usersToWatch.filter { it.latestMetadata != null }
if (secondTimers.isEmpty()) return null
@ -91,7 +91,7 @@ object NostrSingleUserDataSource : NostrDataSource("SingleUserFeed") {
checkNotInMainThread()
usersToWatch.forEach {
if (it.info?.latestMetadata != null) {
if (it.latestMetadata != null) {
val eose = it.latestEOSEs[relayUrl]
if (eose == null) {
it.latestEOSEs = it.latestEOSEs + Pair(relayUrl, EOSETime(time))

Wyświetl plik

@ -168,7 +168,6 @@ import com.vitorpamplona.amethyst.ui.theme.placeholderText
import com.vitorpamplona.amethyst.ui.theme.replyModifier
import com.vitorpamplona.amethyst.ui.theme.subtleBorder
import com.vitorpamplona.quartz.events.ClassifiedsEvent
import com.vitorpamplona.quartz.events.toImmutableListOfLists
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.toImmutableList
import kotlinx.coroutines.CancellationException
@ -1256,8 +1255,7 @@ fun Notifying(
mentions.forEachIndexed { idx, user ->
val innerUserState by user.live().metadata.observeAsState()
innerUserState?.user?.let { myUser ->
val tags =
remember(innerUserState) { myUser.info?.latestMetadata?.tags?.toImmutableListOfLists() }
val tags = myUser.info?.tags
Button(
shape = ButtonBorder,

Wyświetl plik

@ -68,7 +68,7 @@ class NewUserMetadataViewModel : ViewModel() {
account.userProfile().let {
// userName.value = it.bestUsername() ?: ""
displayName.value = it.bestDisplayName() ?: ""
displayName.value = it.info?.bestName() ?: ""
about.value = it.info?.about ?: ""
picture.value = it.info?.picture ?: ""
banner.value = it.info?.banner ?: ""
@ -82,7 +82,7 @@ class NewUserMetadataViewModel : ViewModel() {
mastodon.value = ""
// TODO: Validate Telegram input, somehow.
it.info?.latestMetadata?.identityClaims()?.forEach {
it.latestMetadata?.identityClaims()?.forEach {
when (it) {
is TwitterIdentity -> twitter.value = it.toProofUrl()
is GitHubIdentity -> github.value = it.toProofUrl()

Wyświetl plik

@ -65,10 +65,10 @@ import com.vitorpamplona.quartz.encoders.HexKey
import com.vitorpamplona.quartz.encoders.Nip19Bech32
import com.vitorpamplona.quartz.encoders.Nip30CustomEmoji
import com.vitorpamplona.quartz.events.ChannelCreateEvent
import com.vitorpamplona.quartz.events.EmptyTagList
import com.vitorpamplona.quartz.events.Event
import com.vitorpamplona.quartz.events.ImmutableListOfLists
import com.vitorpamplona.quartz.events.PrivateDmEvent
import com.vitorpamplona.quartz.events.toImmutableListOfLists
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.ImmutableMap
@ -286,25 +286,16 @@ private fun RenderUserAsClickableText(
additionalChars: String,
nav: (String) -> Unit,
) {
val userState by baseUser.live().metadata.observeAsState()
val route = remember { "User/${baseUser.pubkeyHex}" }
val userState by baseUser.live().userMetadataInfo.observeAsState()
val userDisplayName by
remember(userState) { derivedStateOf { userState?.user?.toBestDisplayName() } }
val userTags by
remember(userState) {
derivedStateOf { userState?.user?.info?.latestMetadata?.tags?.toImmutableListOfLists() }
}
userDisplayName?.let {
userState?.bestName()?.let {
CreateClickableTextWithEmoji(
clickablePart = it,
suffix = additionalChars.ifBlank { null },
maxLines = 1,
route = route,
route = "User/${baseUser.pubkeyHex}",
nav = nav,
tags = userTags,
tags = userState?.tags ?: EmptyTagList,
)
}
}
@ -661,7 +652,10 @@ fun ClickableInLineIconRenderer(
AsyncImage(
model = value.url,
contentDescription = null,
modifier = Modifier.fillMaxSize().padding(1.dp),
modifier =
Modifier
.fillMaxSize()
.padding(1.dp),
)
},
)
@ -743,7 +737,10 @@ fun InLineIconRenderer(
AsyncImage(
model = value.url,
contentDescription = null,
modifier = Modifier.fillMaxSize().padding(horizontal = 0.dp),
modifier =
Modifier
.fillMaxSize()
.padding(horizontal = 0.dp),
)
},
)

Wyświetl plik

@ -858,18 +858,14 @@ private fun DisplayUserFromTag(
baseUser: User,
nav: (String) -> Unit,
) {
val route = remember { "User/${baseUser.pubkeyHex}" }
val hex = remember { baseUser.pubkeyDisplayHex() }
val meta by baseUser.live().userMetadataInfo.observeAsState(baseUser.info)
Crossfade(targetState = meta, label = "DisplayUserFromTag") {
Row {
val displayName = remember(it) { it?.bestDisplayName() ?: it?.bestUsername() ?: hex }
CreateClickableTextWithEmoji(
clickablePart = displayName,
clickablePart = remember(meta) { it?.bestName() ?: baseUser.pubkeyDisplayHex() },
maxLines = 1,
route = route,
route = "User/${baseUser.pubkeyHex}",
nav = nav,
tags = it?.tags,
)

Wyświetl plik

@ -61,7 +61,6 @@ import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.Dialog
import androidx.compose.ui.window.DialogProperties
import androidx.lifecycle.map
import com.vitorpamplona.amethyst.AccountInfo
import com.vitorpamplona.amethyst.LocalPreferences
import com.vitorpamplona.amethyst.R
@ -78,7 +77,6 @@ import com.vitorpamplona.amethyst.ui.theme.AccountPictureModifier
import com.vitorpamplona.amethyst.ui.theme.Size10dp
import com.vitorpamplona.amethyst.ui.theme.Size55dp
import com.vitorpamplona.quartz.encoders.decodePublicKeyAsHexOrNull
import com.vitorpamplona.quartz.events.toImmutableListOfLists
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
@ -95,7 +93,10 @@ fun AccountSwitchBottomSheet(
Column(modifier = Modifier.verticalScroll(scrollState)) {
Row(
modifier = Modifier.fillMaxWidth().padding(Size10dp),
modifier =
Modifier
.fillMaxWidth()
.padding(Size10dp),
horizontalArrangement = Arrangement.Center,
verticalAlignment = Alignment.CenterVertically,
) {
@ -103,7 +104,10 @@ fun AccountSwitchBottomSheet(
}
accounts.forEach { acc -> DisplayAccount(acc, accountViewModel, accountStateViewModel) }
Row(
modifier = Modifier.fillMaxWidth().padding(top = Size10dp, bottom = Size55dp),
modifier =
Modifier
.fillMaxWidth()
.padding(top = Size10dp, bottom = Size55dp),
horizontalArrangement = Arrangement.Center,
verticalAlignment = Alignment.CenterVertically,
) {
@ -167,7 +171,8 @@ fun DisplayAccount(
baseUser?.let {
Row(
modifier =
Modifier.fillMaxWidth()
Modifier
.fillMaxWidth()
.clickable { accountStateViewModel.switchUser(acc) }
.padding(16.dp, 16.dp),
verticalAlignment = Alignment.CenterVertically,
@ -181,7 +186,10 @@ fun DisplayAccount(
verticalAlignment = Alignment.CenterVertically,
) {
Box(
modifier = Modifier.width(55.dp).padding(0.dp),
modifier =
Modifier
.width(55.dp)
.padding(0.dp),
) {
val automaticallyShowProfilePicture =
remember {
@ -241,22 +249,17 @@ private fun AccountName(
acc: AccountInfo,
user: User,
) {
val displayName by user.live().metadata.map { user.bestDisplayName() }.observeAsState()
val info by user.live().userMetadataInfo.observeAsState()
val tags by
user
.live()
.metadata
.map { user.info?.latestMetadata?.tags?.toImmutableListOfLists() }
.observeAsState()
displayName?.let {
CreateTextWithEmoji(
text = it,
tags = tags,
maxLines = 1,
overflow = TextOverflow.Ellipsis,
)
info?.let {
it.bestName()?.let { name ->
CreateTextWithEmoji(
text = name,
tags = it.tags,
maxLines = 1,
overflow = TextOverflow.Ellipsis,
)
}
}
Text(

Wyświetl plik

@ -189,7 +189,7 @@ fun ProfileContent(
profilePubHex = baseAccountUser.pubkeyHex,
profileBanner = userInfo?.banner,
profilePicture = userInfo?.profilePicture(),
bestDisplayName = userInfo?.bestDisplayName(),
bestDisplayName = userInfo?.bestName(),
tags = userInfo?.tags,
modifier = modifier,
accountViewModel = accountViewModel,

Wyświetl plik

@ -374,11 +374,13 @@ private fun RenderBubble(
val bubbleModifier =
remember {
Modifier.padding(start = 10.dp, end = 5.dp, bottom = 5.dp).onSizeChanged {
if (bubbleSize.intValue != it.width) {
bubbleSize.intValue = it.width
Modifier
.padding(start = 10.dp, end = 5.dp, bottom = 5.dp)
.onSizeChanged {
if (bubbleSize.intValue != it.width) {
bubbleSize.intValue = it.width
}
}
}
}
Column(modifier = bubbleModifier) {
@ -555,7 +557,8 @@ private fun ConstrainedStatusRow(
horizontalArrangement = Arrangement.SpaceBetween,
modifier =
with(LocalDensity.current) {
Modifier.padding(top = Size5dp)
Modifier
.padding(top = Size5dp)
.height(Size20dp)
.widthIn(
bubbleSize.value.toDp(),
@ -589,7 +592,10 @@ fun IncognitoBadge(baseNote: Note) {
Icon(
painter = painterResource(id = R.drawable.incognito),
null,
modifier = Modifier.padding(top = 1.dp).size(14.dp),
modifier =
Modifier
.padding(top = 1.dp)
.size(14.dp),
tint = MaterialTheme.colorScheme.placeholderText,
)
Spacer(modifier = StdHorzSpacer)
@ -597,7 +603,10 @@ fun IncognitoBadge(baseNote: Note) {
Icon(
painter = painterResource(id = R.drawable.incognito_off),
null,
modifier = Modifier.padding(top = 1.dp).size(14.dp),
modifier =
Modifier
.padding(top = 1.dp)
.size(14.dp),
tint = MaterialTheme.colorScheme.placeholderText,
)
Spacer(modifier = StdHorzSpacer)
@ -678,7 +687,7 @@ private fun RenderChangeChannelMetadataNote(note: Note) {
CreateTextWithEmoji(
text = text,
tags = remember { note.author?.info?.latestMetadata?.tags?.toImmutableListOfLists() },
tags = note.author?.info?.tags,
)
}
@ -699,7 +708,7 @@ private fun RenderCreateChannelNote(note: Note) {
CreateTextWithEmoji(
text = text,
tags = remember { note.author?.info?.latestMetadata?.tags?.toImmutableListOfLists() },
tags = note.author?.info?.tags,
)
}
@ -735,25 +744,17 @@ private fun WatchAndDisplayUser(
loadProfilePicture: Boolean,
nav: (String) -> Unit,
) {
val pubkeyHex = remember { author.pubkeyHex }
val route = remember { "User/${author.pubkeyHex}" }
val route = "User/${author.pubkeyHex}"
val userState by author.live().metadata.observeAsState()
val userState by author.live().userMetadataInfo.observeAsState()
val userDisplayName by
remember(userState) { derivedStateOf { userState?.user?.toBestDisplayName() } }
UserIcon(author.pubkeyHex, userState?.picture, loadProfilePicture, nav, route)
val userProfilePicture by
remember(userState) { derivedStateOf { userState?.user?.profilePicture() } }
val userTags by
remember(userState) {
derivedStateOf { userState?.user?.info?.latestMetadata?.tags?.toImmutableListOfLists() }
userState?.let {
it.bestName()?.let { name ->
DisplayMessageUsername(name, it.tags, route, nav)
}
UserIcon(pubkeyHex, userProfilePicture, loadProfilePicture, nav, route)
userDisplayName?.let { DisplayMessageUsername(it, userTags, route, nav) }
}
}
@Composable
@ -771,7 +772,8 @@ private fun UserIcon(
loadProfilePicture = loadProfilePicture,
modifier =
remember {
Modifier.width(Size25dp)
Modifier
.width(Size25dp)
.height(Size25dp)
.clip(shape = CircleShape)
.clickable(onClick = { nav(route) })

Wyświetl plik

@ -23,7 +23,6 @@ package com.vitorpamplona.amethyst.ui.note
import androidx.compose.foundation.layout.ExperimentalLayoutApi
import androidx.compose.foundation.layout.FlowRow
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.text.ClickableText
import androidx.compose.material3.LocalTextStyle
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
@ -35,10 +34,8 @@ import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.AnnotatedString
import androidx.compose.ui.unit.sp
import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.model.LocalCache
import com.vitorpamplona.amethyst.model.Note
import com.vitorpamplona.amethyst.model.User
import com.vitorpamplona.amethyst.ui.components.CreateClickableTextWithEmoji
@ -46,112 +43,8 @@ import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
import com.vitorpamplona.amethyst.ui.theme.StdVertSpacer
import com.vitorpamplona.amethyst.ui.theme.lessImportantLink
import com.vitorpamplona.amethyst.ui.theme.placeholderText
import com.vitorpamplona.quartz.events.toImmutableListOfLists
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.persistentListOf
import kotlinx.collections.immutable.toImmutableList
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
@Composable
fun ReplyInformation(
replyTo: ImmutableList<Note>?,
mentions: ImmutableList<String>,
accountViewModel: AccountViewModel,
nav: (String) -> Unit,
) {
var sortedMentions by remember { mutableStateOf<ImmutableList<User>?>(null) }
LaunchedEffect(Unit) {
launch(Dispatchers.IO) {
sortedMentions =
mentions
.mapNotNull { LocalCache.checkGetOrCreateUser(it) }
.toSet()
.sortedBy { !accountViewModel.account.userProfile().isFollowingCached(it) }
.toImmutableList()
}
}
if (sortedMentions != null) {
ReplyInformation(replyTo, sortedMentions) { nav("User/${it.pubkeyHex}") }
}
}
@OptIn(ExperimentalLayoutApi::class)
@Composable
private fun ReplyInformation(
replyTo: ImmutableList<Note>?,
sortedMentions: ImmutableList<User>?,
prefix: String = "",
onUserTagClick: (User) -> Unit,
) {
var expanded by remember { mutableStateOf((sortedMentions?.size ?: 0) <= 2) }
FlowRow {
if (sortedMentions != null && sortedMentions.isNotEmpty()) {
if (replyTo != null && replyTo.isNotEmpty()) {
val repliesToDisplay = if (expanded) sortedMentions else sortedMentions.take(2)
Text(
stringResource(R.string.replying_to),
fontSize = 13.sp,
color = MaterialTheme.colorScheme.placeholderText,
)
repliesToDisplay.forEachIndexed { idx, user ->
ReplyInfoMention(user, prefix, onUserTagClick)
if (expanded) {
if (idx < repliesToDisplay.size - 2) {
Text(
", ",
fontSize = 13.sp,
color = MaterialTheme.colorScheme.placeholderText,
)
} else if (idx < repliesToDisplay.size - 1) {
Text(
stringResource(R.string.and),
fontSize = 13.sp,
color = MaterialTheme.colorScheme.placeholderText,
)
}
} else {
if (idx < repliesToDisplay.size - 1) {
Text(
", ",
fontSize = 13.sp,
color = MaterialTheme.colorScheme.placeholderText,
)
} else if (idx < repliesToDisplay.size) {
Text(
stringResource(R.string.and),
fontSize = 13.sp,
color = MaterialTheme.colorScheme.placeholderText,
)
ClickableText(
AnnotatedString("${sortedMentions.size - 2}"),
style =
LocalTextStyle.current.copy(
color = MaterialTheme.colorScheme.lessImportantLink,
fontSize = 13.sp,
),
onClick = { expanded = true },
)
Text(
" ${stringResource(R.string.others)}",
fontSize = 13.sp,
color = MaterialTheme.colorScheme.placeholderText,
)
}
}
}
}
}
}
}
@Composable
fun ReplyInformationChannel(
@ -225,15 +118,11 @@ private fun ReplyInfoMention(
prefix: String,
onUserTagClick: (User) -> Unit,
) {
val innerUserState by user.live().metadata.observeAsState()
val innerUserState by user.live().userMetadataInfo.observeAsState()
CreateClickableTextWithEmoji(
clickablePart =
remember(innerUserState) { "$prefix${innerUserState?.user?.toBestDisplayName()}" },
tags =
remember(innerUserState) {
innerUserState?.user?.info?.latestMetadata?.tags?.toImmutableListOfLists()
},
clickablePart = "$prefix${innerUserState?.bestName()}",
tags = innerUserState?.tags,
style =
LocalTextStyle.current.copy(
color = MaterialTheme.colorScheme.lessImportantLink,

Wyświetl plik

@ -336,7 +336,7 @@ fun LoadUserProfilePicture(
) {
val userProfile by baseUser.live().userMetadataInfo.observeAsState(baseUser.info)
innerContent(userProfile?.profilePicture(), userProfile?.bestDisplayName() ?: userProfile?.bestDisplayName())
innerContent(userProfile?.profilePicture(), userProfile?.bestName())
}
@Composable

Wyświetl plik

@ -70,9 +70,9 @@ fun UsernameDisplay(
val userMetadata by baseUser.live().userMetadataInfo.observeAsState(baseUser.info)
Crossfade(targetState = userMetadata, modifier = weight, label = "UsernameDisplay") {
val name = it?.bestDisplayName() ?: it?.bestUsername()
val name = it?.bestName()
if (name != null) {
UserDisplay(name, it?.tags, weight, showPlayButton, fontWeight, textColor)
UserDisplay(name, it.tags, weight, showPlayButton, fontWeight, textColor)
} else {
NPubDisplay(baseUser, weight, fontWeight, textColor)
}

Wyświetl plik

@ -132,18 +132,20 @@ fun ForkInformationRow(
) {
val noteState by originalVersion.live().metadata.observeAsState()
val note = noteState?.note ?: return
val author = note.author ?: return
val route = remember(note) { routeFor(note, accountViewModel.userProfile()) }
if (route != null) {
Row(modifier) {
val author = note.author ?: return
val meta by author.live().userMetadataInfo.observeAsState(author.info)
Text(stringResource(id = R.string.forked_from))
Spacer(modifier = StdHorzSpacer)
val userMetadata by author.live().userMetadataInfo.observeAsState()
CreateClickableTextWithEmoji(
clickablePart = userMetadata?.bestDisplayName() ?: userMetadata?.bestUsername() ?: author.pubkeyDisplayHex(),
clickablePart = remember(meta) { meta?.bestName() ?: author.pubkeyDisplayHex() },
maxLines = 1,
route = route,
nav = nav,

Wyświetl plik

@ -144,7 +144,7 @@ private fun DisplayQuoteAuthor(
val userMetadata by userBase.live().userMetadataInfo.observeAsState()
CreateClickableTextWithEmoji(
clickablePart = userMetadata?.bestDisplayName() ?: userMetadata?.bestUsername() ?: userBase.pubkeyDisplayHex(),
clickablePart = userMetadata?.bestName() ?: userBase.pubkeyDisplayHex(),
maxLines = 1,
route = "User/${userBase.pubkeyHex}",
nav = nav,

Wyświetl plik

@ -133,7 +133,7 @@ fun ShowQRDialog(
modifier = Modifier.fillMaxWidth().padding(top = 5.dp),
) {
CreateTextWithEmoji(
text = user.bestDisplayName() ?: user.bestUsername() ?: "",
text = user.info?.bestName() ?: "",
tags = user.info?.tags,
fontWeight = FontWeight.Bold,
fontSize = 18.sp,

Wyświetl plik

@ -757,7 +757,7 @@ private fun RenderClassifiedsReaderForThread(
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically,
) {
val sellerName = note.author?.bestDisplayName() ?: note.author?.bestUsername()
val sellerName = note.author?.info?.bestName()
val msg =
if (sellerName != null) {

Wyświetl plik

@ -431,12 +431,8 @@ class UserMetadata {
return lud16 ?: lud06
}
fun bestUsername(): String? {
return name ?: username
}
fun bestDisplayName(): String? {
return displayName
fun bestName(): String? {
return displayName ?: name ?: username
}
fun nip05(): String? {