Continues the migration to use full parsed Addresses instead of just addressIds on the Local Cache. Moves the community route to take a full address.

This commit is contained in:
Vitor Pamplona
2025-07-08 08:54:13 -04:00
parent 0fe8f6c78c
commit 2c90aa4b1e
12 changed files with 23 additions and 44 deletions

View File

@@ -313,7 +313,7 @@ object LocalCache : ILocalCache {
fun getAddressableNoteIfExists(key: String): AddressableNote? = Address.parse(key)?.let { addressables.get(it) } fun getAddressableNoteIfExists(key: String): AddressableNote? = Address.parse(key)?.let { addressables.get(it) }
fun getAddressableNoteIfExists(address: Address): AddressableNote? = getAddressableNoteIfExists(address) fun getAddressableNoteIfExists(address: Address): AddressableNote? = addressables.get(address)
fun getNoteIfExists(key: String): Note? = if (key.length == 64) notes.get(key) else Address.parse(key)?.let { addressables.get(it) } fun getNoteIfExists(key: String): Note? = if (key.length == 64) notes.get(key) else Address.parse(key)?.let { addressables.get(it) }
@@ -2968,7 +2968,7 @@ object LocalCache : ILocalCache {
if (event is AddressableEvent && relay != null) { if (event is AddressableEvent && relay != null) {
// updates relay with a new event. // updates relay with a new event.
getAddressableNoteIfExists(event.addressTag())?.let { note -> getAddressableNoteIfExists(event.address())?.let { note ->
note.event?.let { existingEvent -> note.event?.let { existingEvent ->
if (existingEvent.createdAt > event.createdAt && !note.hasRelay(relay.url)) { if (existingEvent.createdAt > event.createdAt && !note.hasRelay(relay.url)) {
Log.d("LocalCache", "Updating ${relay.url.url} with a new version of ${event.toJson()} to ${existingEvent.toJson()}") Log.d("LocalCache", "Updating ${relay.url.url} with a new version of ${event.toJson()} to ${existingEvent.toJson()}")

View File

@@ -180,7 +180,7 @@ fun uriToRoute(
is NAddress -> { is NAddress -> {
if (nip19.kind == CommunityDefinitionEvent.KIND) { if (nip19.kind == CommunityDefinitionEvent.KIND) {
Route.Community(nip19.aTag()) Route.Community(nip19.kind, nip19.author, nip19.dTag)
} else if (nip19.kind == LiveActivitiesEvent.KIND) { } else if (nip19.kind == LiveActivitiesEvent.KIND) {
Route.Channel(nip19.aTag()) Route.Channel(nip19.aTag())
} else { } else {

View File

@@ -91,6 +91,7 @@ import com.vitorpamplona.amethyst.ui.screen.loggedOff.AddAccountDialog
import com.vitorpamplona.amethyst.ui.uriToRoute import com.vitorpamplona.amethyst.ui.uriToRoute
import com.vitorpamplona.quartz.experimental.ephemChat.chat.RoomId import com.vitorpamplona.quartz.experimental.ephemChat.chat.RoomId
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.RelayUrlNormalizer import com.vitorpamplona.quartz.nip01Core.relay.normalizer.RelayUrlNormalizer
import com.vitorpamplona.quartz.nip01Core.tags.addressables.Address
import com.vitorpamplona.quartz.nip19Bech32.Nip19Parser import com.vitorpamplona.quartz.nip19Bech32.Nip19Parser
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@@ -134,7 +135,7 @@ fun AppNavigation(
composableFromEndArgs<Route.Note> { ThreadScreen(it.id, accountViewModel, nav) } composableFromEndArgs<Route.Note> { ThreadScreen(it.id, accountViewModel, nav) }
composableFromEndArgs<Route.Hashtag> { HashtagScreen(it, accountViewModel, nav) } composableFromEndArgs<Route.Hashtag> { HashtagScreen(it, accountViewModel, nav) }
composableFromEndArgs<Route.Geohash> { GeoHashScreen(it, accountViewModel, nav) } composableFromEndArgs<Route.Geohash> { GeoHashScreen(it, accountViewModel, nav) }
composableFromEndArgs<Route.Community> { CommunityScreen(it.id, accountViewModel, nav) } composableFromEndArgs<Route.Community> { CommunityScreen(Address(it.kind, it.pubKeyHex, it.dTag), accountViewModel, nav) }
composableFromEndArgs<Route.Room> { ChatroomScreen(it.id.toString(), it.message, it.replyId, it.draftId, accountViewModel, nav) } composableFromEndArgs<Route.Room> { ChatroomScreen(it.id.toString(), it.message, it.replyId, it.draftId, accountViewModel, nav) }
composableFromEndArgs<Route.RoomByAuthor> { ChatroomByAuthorScreen(it.id, null, accountViewModel, nav) } composableFromEndArgs<Route.RoomByAuthor> { ChatroomByAuthorScreen(it.id, null, accountViewModel, nav) }
composableFromEndArgs<Route.Channel> { ChannelScreen(it.id, accountViewModel, nav) } composableFromEndArgs<Route.Channel> { ChannelScreen(it.id, accountViewModel, nav) }

View File

@@ -102,7 +102,7 @@ fun routeFor(
loggedIn.createChatroom(room) loggedIn.createChatroom(room)
return Route.Room(room.hashCode()) return Route.Room(room.hashCode())
} else if (noteEvent is CommunityDefinitionEvent) { } else if (noteEvent is CommunityDefinitionEvent) {
return Route.Community(noteEvent.aTag().toTag()) return Route.Community(noteEvent.kind, noteEvent.pubKey, noteEvent.dTag())
} else if (noteEvent is AddressableEvent) { } else if (noteEvent is AddressableEvent) {
return Route.Note(noteEvent.aTag().toTag()) return Route.Note(noteEvent.aTag().toTag())
} else { } else {

View File

@@ -80,7 +80,9 @@ sealed class Route {
) : Route() ) : Route()
@Serializable data class Community( @Serializable data class Community(
val id: String, val kind: Int,
val pubKeyHex: HexKey,
val dTag: String,
) : Route() ) : Route()
@Serializable data class Channel( @Serializable data class Channel(

View File

@@ -88,30 +88,6 @@ fun LoadDecryptedContentOrNull(
inner(decryptedContent) inner(decryptedContent)
} }
@Composable
fun LoadAddressableNote(
aTagHex: String,
accountViewModel: AccountViewModel,
content: @Composable (AddressableNote?) -> Unit,
) {
var note by
remember(aTagHex) {
mutableStateOf<AddressableNote?>(accountViewModel.getAddressableNoteIfExists(aTagHex))
}
if (note == null) {
LaunchedEffect(key1 = aTagHex) {
accountViewModel.checkGetOrCreateAddressableNote(aTagHex) { newNote ->
if (newNote != note) {
note = newNote
}
}
}
}
content(note)
}
@Composable @Composable
fun LoadAddressableNote( fun LoadAddressableNote(
address: Address, address: Address,
@@ -120,7 +96,7 @@ fun LoadAddressableNote(
) { ) {
var note by var note by
remember(address) { remember(address) {
mutableStateOf(accountViewModel.getAddressableNoteIfExists(address.toValue())) mutableStateOf(accountViewModel.getAddressableNoteIfExists(address))
} }
if (note == null) { if (note == null) {

View File

@@ -93,6 +93,7 @@ import com.vitorpamplona.amethyst.ui.theme.ButtonBorder
import com.vitorpamplona.amethyst.ui.theme.StdHorzSpacer import com.vitorpamplona.amethyst.ui.theme.StdHorzSpacer
import com.vitorpamplona.amethyst.ui.theme.StdVertSpacer import com.vitorpamplona.amethyst.ui.theme.StdVertSpacer
import com.vitorpamplona.amethyst.ui.theme.placeholderText import com.vitorpamplona.amethyst.ui.theme.placeholderText
import com.vitorpamplona.quartz.nip01Core.tags.addressables.Address
import com.vitorpamplona.quartz.nip30CustomEmoji.CustomEmoji import com.vitorpamplona.quartz.nip30CustomEmoji.CustomEmoji
import com.vitorpamplona.quartz.nip30CustomEmoji.EmojiUrlTag import com.vitorpamplona.quartz.nip30CustomEmoji.EmojiUrlTag
import com.vitorpamplona.quartz.nip30CustomEmoji.selection.EmojiPackSelectionEvent import com.vitorpamplona.quartz.nip30CustomEmoji.selection.EmojiPackSelectionEvent
@@ -386,7 +387,7 @@ private fun EmojiSelector(
) { emptyNote -> ) { emptyNote ->
emptyNote?.let { usersEmojiList -> emptyNote?.let { usersEmojiList ->
val collections by observeNoteEventAndMap(usersEmojiList, accountViewModel) { event: EmojiPackSelectionEvent -> val collections by observeNoteEventAndMap(usersEmojiList, accountViewModel) { event: EmojiPackSelectionEvent ->
event.emojiPackIds().toImmutableList() event.emojiPacks().toImmutableList()
} }
collections?.let { EmojiCollectionGallery(it, accountViewModel, nav, onClick) } collections?.let { EmojiCollectionGallery(it, accountViewModel, nav, onClick) }
@@ -396,7 +397,7 @@ private fun EmojiSelector(
@Composable @Composable
fun EmojiCollectionGallery( fun EmojiCollectionGallery(
emojiCollections: ImmutableList<String>, emojiCollections: ImmutableList<Address>,
accountViewModel: AccountViewModel, accountViewModel: AccountViewModel,
nav: INav, nav: INav,
onClick: ((EmojiUrlTag) -> Unit)? = null, onClick: ((EmojiUrlTag) -> Unit)? = null,

View File

@@ -102,7 +102,7 @@ fun ObserveRelayListForDMs(
inner: @Composable (relayListEvent: ChatMessageRelayListEvent?) -> Unit, inner: @Composable (relayListEvent: ChatMessageRelayListEvent?) -> Unit,
) { ) {
LoadAddressableNote( LoadAddressableNote(
ChatMessageRelayListEvent.createAddressTag(pubkey), ChatMessageRelayListEvent.createAddress(pubkey),
accountViewModel, accountViewModel,
) { relayList -> ) { relayList ->
if (relayList != null) { if (relayList != null) {

View File

@@ -59,7 +59,7 @@ private fun DisplayCommunity(
val displayTag = val displayTag =
remember(note) { remember(note) {
buildLinkString(getCommunityShortName(communityTag)) { nav.nav(Route.Community(communityTag.toTag())) } buildLinkString(getCommunityShortName(communityTag)) { nav.nav(Route.Community(communityTag.kind, communityTag.pubKeyHex, communityTag.dTag)) }
} }
Text( Text(

View File

@@ -170,7 +170,7 @@ class FollowListState(
"Community/${communityNote.idHex}", "Community/${communityNote.idHex}",
CommunityName(communityNote), CommunityName(communityNote),
CodeNameType.ROUTE, CodeNameType.ROUTE,
route = Route.Community(communityNote.idHex), route = Route.Community(communityNote.address.kind, communityNote.address.pubKeyHex, communityNote.address.dTag),
kinds = DEFAULT_COMMUNITY_FEEDS, kinds = DEFAULT_COMMUNITY_FEEDS,
aTags = listOf(communityNote.idHex), aTags = listOf(communityNote.idHex),
) )

View File

@@ -42,16 +42,15 @@ import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
import com.vitorpamplona.amethyst.ui.screen.loggedIn.communities.dal.CommunityFeedViewModel import com.vitorpamplona.amethyst.ui.screen.loggedIn.communities.dal.CommunityFeedViewModel
import com.vitorpamplona.amethyst.ui.screen.loggedIn.communities.datasource.CommunityFilterAssemblerSubscription import com.vitorpamplona.amethyst.ui.screen.loggedIn.communities.datasource.CommunityFilterAssemblerSubscription
import com.vitorpamplona.amethyst.ui.theme.BottomTopHeight import com.vitorpamplona.amethyst.ui.theme.BottomTopHeight
import com.vitorpamplona.quartz.nip01Core.tags.addressables.Address
@Composable @Composable
fun CommunityScreen( fun CommunityScreen(
aTagHex: String?, aTagHex: Address,
accountViewModel: AccountViewModel, accountViewModel: AccountViewModel,
nav: INav, nav: INav,
) { ) {
if (aTagHex == null) return LoadAddressableNote(aTagHex, accountViewModel) {
LoadAddressableNote(aTagHex = aTagHex, accountViewModel) {
it?.let { it?.let {
PrepareViewModelsCommunityScreen( PrepareViewModelsCommunityScreen(
note = it, note = it,
@@ -94,7 +93,7 @@ fun CommunityScreen(
DisappearingScaffold( DisappearingScaffold(
isInvertedLayout = false, isInvertedLayout = false,
topBar = { topBar = {
CommunityTopBar(note.idHex, accountViewModel, nav) CommunityTopBar(note.address, accountViewModel, nav)
}, },
floatingButton = { floatingButton = {
NewCommunityNoteButton(note.idHex, accountViewModel, nav) NewCommunityNoteButton(note.idHex, accountViewModel, nav)
@@ -116,11 +115,11 @@ fun CommunityScreen(
@Composable @Composable
fun CommunityTopBar( fun CommunityTopBar(
id: String, id: Address,
accountViewModel: AccountViewModel, accountViewModel: AccountViewModel,
nav: INav, nav: INav,
) { ) {
LoadAddressableNote(aTagHex = id, accountViewModel) { baseNote -> LoadAddressableNote(id, accountViewModel) { baseNote ->
if (baseNote != null) { if (baseNote != null) {
TopBarExtensibleWithBackButton( TopBarExtensibleWithBackButton(
title = { ShortCommunityHeader(baseNote, accountViewModel, nav) }, title = { ShortCommunityHeader(baseNote, accountViewModel, nav) },

View File

@@ -101,7 +101,7 @@ fun ObserveRelayListForSearch(
inner: @Composable (relayListEvent: SearchRelayListEvent?) -> Unit, inner: @Composable (relayListEvent: SearchRelayListEvent?) -> Unit,
) { ) {
LoadAddressableNote( LoadAddressableNote(
SearchRelayListEvent.createAddressTag(pubkey), SearchRelayListEvent.createAddress(pubkey),
accountViewModel, accountViewModel,
) { relayList -> ) { relayList ->
if (relayList != null) { if (relayList != null) {