diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/model/LocalCache.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/model/LocalCache.kt index 30a1381410..3943dcd820 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/model/LocalCache.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/model/LocalCache.kt @@ -2149,7 +2149,7 @@ object LocalCache : ILocalCache, ICacheProvider { val finds = users.filter { _, user: User -> ( - (user.anyNameStartsWith(username)) || + (user.metadataOrNull()?.anyNameStartsWith(username) == true) || user.pubkeyHex.startsWith(username, true) || user.pubkeyNpub().startsWith(username, true) ) && diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/model/Note.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/model/Note.kt index 1328113779..739f87887a 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/model/Note.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/model/Note.kt @@ -22,6 +22,5 @@ package com.vitorpamplona.amethyst.model // Re-export from commons for backwards compatibility typealias Note = com.vitorpamplona.amethyst.commons.model.Note -typealias NotesGatherer = com.vitorpamplona.amethyst.commons.model.NotesGatherer typealias AddressableNote = com.vitorpamplona.amethyst.commons.model.AddressableNote typealias NoteState = com.vitorpamplona.amethyst.commons.model.NoteState diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/model/Note.kt b/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/model/Note.kt index 26fc111016..b5b02a98ae 100644 --- a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/model/Note.kt +++ b/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/model/Note.kt @@ -108,7 +108,7 @@ class AddressableNote( @Stable open class Note( - val idHex: String, + val idHex: HexKey, ) : NotesGatherer { // These fields are only available after the Text Note event is received. // They are immutable after that. diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/model/User.kt b/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/model/User.kt index e5bfabef6a..fbd1d5e280 100644 --- a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/model/User.kt +++ b/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/model/User.kt @@ -97,33 +97,11 @@ class User( fun toNostrUri() = "nostr:${toNProfile()}" - fun toBestDisplayName(): String = - metadataOrNull() - ?.flow - ?.value - ?.info - ?.bestName() ?: pubkeyDisplayHex() + fun toBestDisplayName(): String = metadataOrNull()?.bestName() ?: pubkeyDisplayHex() - fun nip05(): String? = - metadataOrNull() - ?.flow - ?.value - ?.info - ?.nip05 + fun profilePicture(): String? = metadataOrNull()?.profilePicture() - fun profilePicture(): String? = - metadataOrNull() - ?.flow - ?.value - ?.info - ?.picture - - fun lnAddress(): String? = - metadataOrNull() - ?.flow - ?.value - ?.info - ?.lnAddress() + fun lnAddress(): String? = metadataOrNull()?.lnAddress() fun addZap( zapRequest: Note, @@ -227,52 +205,9 @@ class User( fun containsAny(hiddenWordsCase: List): Boolean { if (hiddenWordsCase.isEmpty()) return false - metadata?.flow?.value?.let { userInfo -> - val info = userInfo.info - - if (info.name?.containsAny(hiddenWordsCase) == true) { - return true - } - - if (info.displayName?.containsAny(hiddenWordsCase) == true) { - return true - } - - if (info.picture?.containsAny(hiddenWordsCase) == true) { - return true - } - - if (info.banner?.containsAny(hiddenWordsCase) == true) { - return true - } - - if (info.about?.containsAny(hiddenWordsCase) == true) { - return true - } - - if (info.lud06?.containsAny(hiddenWordsCase) == true) { - return true - } - - if (info.lud16?.containsAny(hiddenWordsCase) == true) { - return true - } - - if (info.nip05?.containsAny(hiddenWordsCase) == true) { - return true - } - } - - return false + return metadataOrNull()?.containsAny(hiddenWordsCase) == true } - fun anyNameStartsWith(username: String): Boolean = - metadata - ?.flow - ?.value - ?.info - ?.anyNameStartsWith(username) ?: false - @Synchronized fun createOrDestroyFlowSync(create: Boolean) { if (create) { diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/model/nip01Core/UserMetadataCache.kt b/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/model/nip01Core/UserMetadataCache.kt index 00e6f3a16b..943ab1054a 100644 --- a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/model/nip01Core/UserMetadataCache.kt +++ b/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/model/nip01Core/UserMetadataCache.kt @@ -27,6 +27,8 @@ import com.vitorpamplona.quartz.nip01Core.metadata.MetadataEvent import com.vitorpamplona.quartz.nip01Core.metadata.UserMetadata import com.vitorpamplona.quartz.nip39ExtIdentities.IdentityClaimTag import com.vitorpamplona.quartz.nip39ExtIdentities.identityClaims +import com.vitorpamplona.quartz.utils.DualCase +import com.vitorpamplona.quartz.utils.containsAny import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.update @@ -57,4 +59,56 @@ class UserMetadataCache { } fun shouldUpdateWith(event: MetadataEvent) = event.createdAt > (flow.value?.createdAt ?: 0) + + fun anyNameStartsWith(username: String): Boolean = flow.value?.info?.anyNameStartsWith(username) ?: false + + fun containsAny(hiddenWordsCase: List): Boolean { + if (hiddenWordsCase.isEmpty()) return false + + flow.value?.let { userInfo -> + val info = userInfo.info + + if (info.name?.containsAny(hiddenWordsCase) == true) { + return true + } + + if (info.displayName?.containsAny(hiddenWordsCase) == true) { + return true + } + + if (info.picture?.containsAny(hiddenWordsCase) == true) { + return true + } + + if (info.banner?.containsAny(hiddenWordsCase) == true) { + return true + } + + if (info.about?.containsAny(hiddenWordsCase) == true) { + return true + } + + if (info.lud06?.containsAny(hiddenWordsCase) == true) { + return true + } + + if (info.lud16?.containsAny(hiddenWordsCase) == true) { + return true + } + + if (info.nip05?.containsAny(hiddenWordsCase) == true) { + return true + } + } + + return false + } + + fun bestName(): String? = flow.value?.info?.bestName() + + fun nip05(): String? = flow.value?.info?.nip05 + + fun profilePicture(): String? = flow.value?.info?.picture + + fun lnAddress(): String? = flow.value?.info?.lnAddress() } diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/components/UserSearchCard.kt b/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/components/UserSearchCard.kt index d2df0abebc..e5054c2038 100644 --- a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/components/UserSearchCard.kt +++ b/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/components/UserSearchCard.kt @@ -78,7 +78,7 @@ fun UserSearchCard( style = MaterialTheme.typography.titleSmall, color = MaterialTheme.colorScheme.onSurface, ) - val nip05 = user.nip05() + val nip05 = user.metadataOrNull()?.nip05() if (nip05 != null) { Text( nip05, diff --git a/desktopApp/src/jvmMain/kotlin/com/vitorpamplona/amethyst/desktop/cache/DesktopLocalCache.kt b/desktopApp/src/jvmMain/kotlin/com/vitorpamplona/amethyst/desktop/cache/DesktopLocalCache.kt index f2e46f82ef..46a54a2736 100644 --- a/desktopApp/src/jvmMain/kotlin/com/vitorpamplona/amethyst/desktop/cache/DesktopLocalCache.kt +++ b/desktopApp/src/jvmMain/kotlin/com/vitorpamplona/amethyst/desktop/cache/DesktopLocalCache.kt @@ -88,7 +88,7 @@ class DesktopLocalCache : ICacheProvider { // Search by name/displayName/nip05/lud16 return users.values .filter { user -> - user.anyNameStartsWith(prefix) || + user.metadataOrNull()?.anyNameStartsWith(prefix) == true || user.pubkeyHex.startsWith(prefix, ignoreCase = true) || user.pubkeyNpub().startsWith(prefix, ignoreCase = true) }.sortedWith(