fixes imports

This commit is contained in:
nrobi144
2026-01-01 07:55:31 +02:00
parent 3750c7e26e
commit 4bc7e86448
14 changed files with 125 additions and 70 deletions
@@ -108,6 +108,7 @@ import com.vitorpamplona.quartz.experimental.bounties.BountyAddValueEvent
import com.vitorpamplona.quartz.experimental.edits.TextNoteModificationEvent import com.vitorpamplona.quartz.experimental.edits.TextNoteModificationEvent
import com.vitorpamplona.quartz.experimental.interactiveStories.InteractiveStoryBaseEvent import com.vitorpamplona.quartz.experimental.interactiveStories.InteractiveStoryBaseEvent
import com.vitorpamplona.quartz.experimental.interactiveStories.InteractiveStoryPrologueEvent import com.vitorpamplona.quartz.experimental.interactiveStories.InteractiveStoryPrologueEvent
import com.vitorpamplona.quartz.utils.DualCase
import com.vitorpamplona.quartz.experimental.interactiveStories.InteractiveStoryReadingStateEvent import com.vitorpamplona.quartz.experimental.interactiveStories.InteractiveStoryReadingStateEvent
import com.vitorpamplona.quartz.experimental.interactiveStories.InteractiveStorySceneEvent import com.vitorpamplona.quartz.experimental.interactiveStories.InteractiveStorySceneEvent
import com.vitorpamplona.quartz.experimental.interactiveStories.image import com.vitorpamplona.quartz.experimental.interactiveStories.image
@@ -237,14 +238,21 @@ class Account(
val cache: LocalCache, val cache: LocalCache,
val client: INostrClient, val client: INostrClient,
val scope: CoroutineScope, val scope: CoroutineScope,
) { ) : IAccount {
private var userProfileCache: User? = null private var userProfileCache: User? = null
fun userProfile(): User = userProfileCache ?: cache.getOrCreateUser(signer.pubKey).also { userProfileCache = it } override fun userProfile(): User = userProfileCache ?: cache.getOrCreateUser(signer.pubKey).also { userProfileCache = it }
// IAccount interface properties
override val pubKey: String get() = signer.pubKey
override val showSensitiveContent: Boolean? get() = hiddenUsers.flow.value.showSensitiveContent
override val hiddenWordsCase: List<DualCase> get() = hiddenUsers.flow.value.hiddenWordsCase
override val hiddenUsersHashCodes: Set<Int> get() = hiddenUsers.flow.value.hiddenUsersHashCodes
override val spammersHashCodes: Set<Int> get() = hiddenUsers.flow.value.spammersHashCodes
val userMetadata = UserMetadataState(signer, cache, scope, settings) val userMetadata = UserMetadataState(signer, cache, scope, settings)
val nip47SignerState = NwcSignerState(signer, nwcFilterAssembler, cache, scope, settings) override val nip47SignerState = NwcSignerState(signer, nwcFilterAssembler, cache, scope, settings)
val nip65RelayList = Nip65RelayListState(signer, cache, scope, settings) val nip65RelayList = Nip65RelayListState(signer, cache, scope, settings)
val localRelayList = LocalRelayListState(signer, cache, scope, settings) val localRelayList = LocalRelayListState(signer, cache, scope, settings)
@@ -340,7 +348,7 @@ class Account(
val allFollows = MergedFollowListsState(kind3FollowList, peopleLists, followLists, hashtagList, geohashList, communityList, scope) val allFollows = MergedFollowListsState(kind3FollowList, peopleLists, followLists, hashtagList, geohashList, communityList, scope)
val privateDMDecryptionCache = PrivateDMCache(signer) val privateDMDecryptionCache = PrivateDMCache(signer)
val privateZapsDecryptionCache = PrivateZapCache(signer) override val privateZapsDecryptionCache = PrivateZapCache(signer)
val draftsDecryptionCache = DraftEventCache(signer) val draftsDecryptionCache = DraftEventCache(signer)
val chatroomList = cache.getOrCreateChatroomList(signer.pubKey) val chatroomList = cache.getOrCreateChatroomList(signer.pubKey)
@@ -423,7 +431,7 @@ class Account(
val liveNotificationFollowListsPerRelay = OutboxLoaderState(liveNotificationFollowLists, cache, scope).flow val liveNotificationFollowListsPerRelay = OutboxLoaderState(liveNotificationFollowLists, cache, scope).flow
fun isWriteable(): Boolean = settings.isWriteable() override fun isWriteable(): Boolean = settings.isWriteable()
suspend fun updateWarnReports(warnReports: Boolean): Boolean { suspend fun updateWarnReports(warnReports: Boolean): Boolean {
if (settings.updateWarnReports(warnReports)) { if (settings.updateWarnReports(warnReports)) {
@@ -22,9 +22,9 @@ package com.vitorpamplona.amethyst.model
import com.vitorpamplona.amethyst.commons.model.AddressableNote import com.vitorpamplona.amethyst.commons.model.AddressableNote
import com.vitorpamplona.amethyst.commons.model.Note import com.vitorpamplona.amethyst.commons.model.Note
import com.vitorpamplona.amethyst.commons.model.NotesGatherer
import com.vitorpamplona.amethyst.commons.model.User import com.vitorpamplona.amethyst.commons.model.User
import androidx.compose.runtime.Stable import androidx.compose.runtime.Stable
import com.vitorpamplona.amethyst.ui.dal.DefaultFeedOrder import com.vitorpamplona.amethyst.ui.dal.DefaultFeedOrder
import com.vitorpamplona.amethyst.ui.dal.ListChange import com.vitorpamplona.amethyst.ui.dal.ListChange
@@ -24,9 +24,7 @@ import com.vitorpamplona.amethyst.commons.model.AddressableNote
import com.vitorpamplona.amethyst.commons.model.Note import com.vitorpamplona.amethyst.commons.model.Note
import com.vitorpamplona.amethyst.commons.model.User import com.vitorpamplona.amethyst.commons.model.User
import androidx.compose.runtime.Immutable import androidx.compose.runtime.Immutable
import com.vitorpamplona.amethyst.commons.model.User
import com.vitorpamplona.amethyst.commons.model.UserState import com.vitorpamplona.amethyst.commons.model.UserState
import com.vitorpamplona.amethyst.model.AccountSettings import com.vitorpamplona.amethyst.model.AccountSettings
import com.vitorpamplona.amethyst.model.LocalCache import com.vitorpamplona.amethyst.model.LocalCache
@@ -20,6 +20,7 @@
*/ */
package com.vitorpamplona.amethyst.model.nip47WalletConnect package com.vitorpamplona.amethyst.model.nip47WalletConnect
import com.vitorpamplona.amethyst.commons.model.INwcSignerState
import com.vitorpamplona.amethyst.commons.model.Note import com.vitorpamplona.amethyst.commons.model.Note
import com.vitorpamplona.amethyst.model.AccountSettings import com.vitorpamplona.amethyst.model.AccountSettings
import com.vitorpamplona.amethyst.model.LocalCache import com.vitorpamplona.amethyst.model.LocalCache
@@ -66,7 +67,7 @@ class NwcSignerState(
val cache: LocalCache, val cache: LocalCache,
val scope: CoroutineScope, val scope: CoroutineScope,
val settings: AccountSettings, val settings: AccountSettings,
) { ) : INwcSignerState {
/** /**
* Derives a NIP-47 signer from the zap payment request in settings. * Derives a NIP-47 signer from the zap payment request in settings.
* If there's no valid configuration, it defaults to the main signer. * If there's no valid configuration, it defaults to the main signer.
@@ -112,7 +113,7 @@ class NwcSignerState(
fun hasWalletConnectSetup(): Boolean = settings.zapPaymentRequest.value != null fun hasWalletConnectSetup(): Boolean = settings.zapPaymentRequest.value != null
fun isNIP47Author(pubkeyHex: String?): Boolean = nip47Signer.value.pubKey == pubkeyHex override fun isNIP47Author(pubkeyHex: String?): Boolean = nip47Signer.value.pubKey == pubkeyHex
/** /**
* Decrypts a NIP-47 payment request using the current signer. * Decrypts a NIP-47 payment request using the current signer.
@@ -120,7 +121,7 @@ class NwcSignerState(
* @param nwcRequest the NIP-47 payment request event to decrypt * @param nwcRequest the NIP-47 payment request event to decrypt
* @return the decrypted request or null if not set up or decryption fails * @return the decrypted request or null if not set up or decryption fails
*/ */
suspend fun decryptRequest(nwcRequest: LnZapPaymentRequestEvent): Request? { override suspend fun decryptRequest(nwcRequest: LnZapPaymentRequestEvent): Request? {
if (!hasWalletConnectSetup()) return null if (!hasWalletConnectSetup()) return null
return zapPaymentRequestDecryptionCache.value.decryptRequest(nwcRequest) return zapPaymentRequestDecryptionCache.value.decryptRequest(nwcRequest)
} }
@@ -131,7 +132,7 @@ class NwcSignerState(
* @param nwsResponse the NIP-47 payment response event to decrypt * @param nwsResponse the NIP-47 payment response event to decrypt
* @return the decrypted response or null if not set up or decryption fails * @return the decrypted response or null if not set up or decryption fails
*/ */
suspend fun decryptResponse(nwsResponse: LnZapPaymentResponseEvent): Response? { override suspend fun decryptResponse(nwsResponse: LnZapPaymentResponseEvent): Response? {
if (!hasWalletConnectSetup()) return null if (!hasWalletConnectSetup()) return null
return zapPaymentResponseDecryptionCache.value.decryptResponse(nwsResponse) return zapPaymentResponseDecryptionCache.value.decryptResponse(nwsResponse)
} }
@@ -21,6 +21,7 @@
package com.vitorpamplona.amethyst.model.nip51Lists package com.vitorpamplona.amethyst.model.nip51Lists
import com.vitorpamplona.amethyst.commons.model.AddressableNote import com.vitorpamplona.amethyst.commons.model.AddressableNote
import com.vitorpamplona.amethyst.commons.model.LiveHiddenUsers
import com.vitorpamplona.amethyst.commons.model.Note import com.vitorpamplona.amethyst.commons.model.Note
import com.vitorpamplona.amethyst.commons.model.User import com.vitorpamplona.amethyst.commons.model.User
@@ -52,33 +53,25 @@ class HiddenUsersState(
) { ) {
var transientHiddenUsers: MutableStateFlow<Set<String>> = MutableStateFlow(setOf()) var transientHiddenUsers: MutableStateFlow<Set<String>> = MutableStateFlow(setOf())
@Immutable
class LiveHiddenUsers(
val hiddenUsers: Set<String>,
val spammers: Set<String>,
val hiddenWords: Set<String>,
val showSensitiveContent: Boolean?,
) {
// speeds up isHidden calculations
val hiddenUsersHashCodes = hiddenUsers.mapTo(HashSet()) { it.hashCode() }
val spammersHashCodes = spammers.mapTo(HashSet()) { it.hashCode() }
val hiddenWordsCase = hiddenWords.map { DualCase(it.lowercase(), it.uppercase()) }
fun isUserHidden(userHex: HexKey) = hiddenUsers.contains(userHex) || spammers.contains(userHex)
}
suspend fun assembleLiveHiddenUsers( suspend fun assembleLiveHiddenUsers(
blockList: List<MuteTag>, blockList: List<MuteTag>,
muteList: List<MuteTag>, muteList: List<MuteTag>,
transientHiddenUsers: Set<String>, transientHiddenUsers: Set<String>,
showSensitiveContent: Boolean?, showSensitiveContent: Boolean?,
): LiveHiddenUsers = ): LiveHiddenUsers {
LiveHiddenUsers( val hiddenUsers = blockList.mapNotNullTo(mutableSetOf()) { if (it is UserTag) it.pubKey else null } + muteList.mapNotNull { if (it is UserTag) it.pubKey else null }
hiddenUsers = blockList.mapNotNullTo(mutableSetOf()) { if (it is UserTag) it.pubKey else null } + muteList.mapNotNull { if (it is UserTag) it.pubKey else null }, val hiddenWords = blockList.mapNotNullTo(mutableSetOf()) { if (it is WordTag) it.word else null } + muteList.mapNotNull { if (it is WordTag) it.word else null }
hiddenWords = blockList.mapNotNullTo(mutableSetOf()) { if (it is WordTag) it.word else null } + muteList.mapNotNull { if (it is WordTag) it.word else null },
spammers = transientHiddenUsers, return LiveHiddenUsers(
showSensitiveContent = showSensitiveContent, showSensitiveContent = showSensitiveContent,
hiddenWordsCase = hiddenWords.map { DualCase(it.lowercase(), it.uppercase()) },
hiddenUsersHashCodes = hiddenUsers.mapTo(HashSet()) { it.hashCode() },
spammersHashCodes = transientHiddenUsers.mapTo(HashSet()) { it.hashCode() },
hiddenUsers = hiddenUsers,
spammers = transientHiddenUsers,
hiddenWords = hiddenWords,
) )
}
val flow: StateFlow<LiveHiddenUsers> = val flow: StateFlow<LiveHiddenUsers> =
combineTransform( combineTransform(
@@ -102,7 +95,15 @@ class HiddenUsersState(
.stateIn( .stateIn(
scope, scope,
SharingStarted.Eagerly, SharingStarted.Eagerly,
LiveHiddenUsers(emptySet(), emptySet(), emptySet(), null), LiveHiddenUsers(
showSensitiveContent = null,
hiddenWordsCase = emptyList(),
hiddenUsersHashCodes = emptySet(),
spammersHashCodes = emptySet(),
hiddenUsers = emptySet(),
spammers = emptySet(),
hiddenWords = emptySet(),
),
) )
fun resetTransientUsers() { fun resetTransientUsers() {
@@ -24,9 +24,7 @@ import com.vitorpamplona.amethyst.commons.model.AddressableNote
import com.vitorpamplona.amethyst.commons.model.Note import com.vitorpamplona.amethyst.commons.model.Note
import com.vitorpamplona.amethyst.commons.model.User import com.vitorpamplona.amethyst.commons.model.User
import androidx.compose.runtime.Stable import androidx.compose.runtime.Stable
import com.vitorpamplona.amethyst.commons.model.User
import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.toPersistentList import kotlinx.collections.immutable.toPersistentList
@@ -22,6 +22,7 @@ package com.vitorpamplona.amethyst.model.trustedAssertions
import com.vitorpamplona.amethyst.commons.model.Note import com.vitorpamplona.amethyst.commons.model.Note
import com.vitorpamplona.amethyst.commons.model.NoteState import com.vitorpamplona.amethyst.commons.model.NoteState
import com.vitorpamplona.amethyst.commons.model.trustedAssertions.TrustProviderListState as ITrustProviderListState
import com.vitorpamplona.amethyst.model.AccountSettings import com.vitorpamplona.amethyst.model.AccountSettings
import com.vitorpamplona.amethyst.model.LocalCache import com.vitorpamplona.amethyst.model.LocalCache
import com.vitorpamplona.quartz.experimental.trustedAssertions.list.TrustProviderListEvent import com.vitorpamplona.quartz.experimental.trustedAssertions.list.TrustProviderListEvent
@@ -49,7 +50,7 @@ class TrustProviderListState(
val decryptionCache: TrustProviderListDecryptionCache, val decryptionCache: TrustProviderListDecryptionCache,
val scope: CoroutineScope, val scope: CoroutineScope,
val settings: AccountSettings, val settings: AccountSettings,
) { ) : ITrustProviderListState {
// Creates a long-term reference for this note so that the GC doesn't collect the note it self // Creates a long-term reference for this note so that the GC doesn't collect the note it self
val trustProviderListNote = cache.getOrCreateAddressableNote(getTrustProviderListAddress()) val trustProviderListNote = cache.getOrCreateAddressableNote(getTrustProviderListAddress())
@@ -79,7 +80,7 @@ class TrustProviderListState(
) )
@OptIn(ExperimentalCoroutinesApi::class) @OptIn(ExperimentalCoroutinesApi::class)
val liveUserRankProvider: StateFlow<ServiceProviderTag?> = override val liveUserRankProvider: StateFlow<ServiceProviderTag?> =
liveTrustProviderList liveTrustProviderList
.map { .map {
it.firstOrNull { it.service == ProviderTypes.rank } it.firstOrNull { it.service == ProviderTypes.rank }
@@ -97,7 +98,7 @@ class TrustProviderListState(
) )
@OptIn(ExperimentalCoroutinesApi::class) @OptIn(ExperimentalCoroutinesApi::class)
val liveUserFollowerCount: StateFlow<ServiceProviderTag?> = override val liveUserFollowerCount: StateFlow<ServiceProviderTag?> =
liveTrustProviderList liveTrustProviderList
.map { tagList -> .map { tagList ->
tagList.firstOrNull { it.service == ProviderTypes.followerCount } tagList.firstOrNull { it.service == ProviderTypes.followerCount }
@@ -20,7 +20,7 @@
*/ */
package com.vitorpamplona.amethyst.ui.dal package com.vitorpamplona.amethyst.ui.dal
import com.vitorpamplona.amethyst.model.nip51Lists.HiddenUsersState import com.vitorpamplona.amethyst.commons.model.LiveHiddenUsers
import com.vitorpamplona.amethyst.model.topNavFeeds.IFeedTopNavFilter import com.vitorpamplona.amethyst.model.topNavFeeds.IFeedTopNavFilter
import com.vitorpamplona.amethyst.model.topNavFeeds.global.GlobalTopNavFilter import com.vitorpamplona.amethyst.model.topNavFeeds.global.GlobalTopNavFilter
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.muted.MutedAuthorsByOutboxTopNavFilter import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.muted.MutedAuthorsByOutboxTopNavFilter
@@ -36,7 +36,7 @@ import com.vitorpamplona.quartz.utils.TimeUtils
class FilterByListParams( class FilterByListParams(
val isHiddenList: Boolean, val isHiddenList: Boolean,
val followLists: IFeedTopNavFilter?, val followLists: IFeedTopNavFilter?,
val hiddenLists: HiddenUsersState.LiveHiddenUsers, val hiddenLists: LiveHiddenUsers,
val now: Long = TimeUtils.oneMinuteFromNow(), val now: Long = TimeUtils.oneMinuteFromNow(),
) { ) {
fun isNotHidden(userHex: String) = !(hiddenLists.hiddenUsers.contains(userHex) || hiddenLists.spammers.contains(userHex)) fun isNotHidden(userHex: String) = !(hiddenLists.hiddenUsers.contains(userHex) || hiddenLists.spammers.contains(userHex))
@@ -87,7 +87,7 @@ class FilterByListParams(
fun create( fun create(
followLists: IFeedTopNavFilter?, followLists: IFeedTopNavFilter?,
hiddenUsers: HiddenUsersState.LiveHiddenUsers, hiddenUsers: LiveHiddenUsers,
): FilterByListParams = ): FilterByListParams =
FilterByListParams( FilterByListParams(
isHiddenList = followLists is MutedAuthorsByOutboxTopNavFilter || followLists is MutedAuthorsByProxyTopNavFilter, isHiddenList = followLists is MutedAuthorsByOutboxTopNavFilter || followLists is MutedAuthorsByProxyTopNavFilter,
@@ -51,6 +51,7 @@ import com.vitorpamplona.amethyst.model.UiSettingsFlow
import com.vitorpamplona.amethyst.model.UrlCachedPreviewer import com.vitorpamplona.amethyst.model.UrlCachedPreviewer
import com.vitorpamplona.amethyst.model.emphChat.EphemeralChatChannel import com.vitorpamplona.amethyst.model.emphChat.EphemeralChatChannel
import com.vitorpamplona.amethyst.model.nip28PublicChats.PublicChatChannel import com.vitorpamplona.amethyst.model.nip28PublicChats.PublicChatChannel
import com.vitorpamplona.amethyst.commons.model.LiveHiddenUsers
import com.vitorpamplona.amethyst.model.nip51Lists.HiddenUsersState import com.vitorpamplona.amethyst.model.nip51Lists.HiddenUsersState
import com.vitorpamplona.amethyst.model.nip53LiveActivities.LiveActivitiesChannel import com.vitorpamplona.amethyst.model.nip53LiveActivities.LiveActivitiesChannel
import com.vitorpamplona.amethyst.model.observables.CreatedAtComparator import com.vitorpamplona.amethyst.model.observables.CreatedAtComparator
@@ -341,7 +342,7 @@ class AccountViewModel(
fun isNoteAcceptable( fun isNoteAcceptable(
note: Note, note: Note,
accountChoices: HiddenUsersState.LiveHiddenUsers, accountChoices: LiveHiddenUsers,
followUsers: Set<HexKey>, followUsers: Set<HexKey>,
): NoteComposeReportState { ): NoteComposeReportState {
checkNotInMainThread() checkNotInMainThread()
@@ -24,8 +24,7 @@ import com.vitorpamplona.quartz.nip47WalletConnect.LnZapPaymentRequestEvent
import com.vitorpamplona.quartz.nip47WalletConnect.LnZapPaymentResponseEvent import com.vitorpamplona.quartz.nip47WalletConnect.LnZapPaymentResponseEvent
import com.vitorpamplona.quartz.nip47WalletConnect.Request import com.vitorpamplona.quartz.nip47WalletConnect.Request
import com.vitorpamplona.quartz.nip47WalletConnect.Response import com.vitorpamplona.quartz.nip47WalletConnect.Response
import com.vitorpamplona.quartz.nip57Zaps.LnZapPrivateEvent import com.vitorpamplona.quartz.nip57Zaps.IPrivateZapsDecryptionCache
import com.vitorpamplona.quartz.nip57Zaps.LnZapRequestEvent
import com.vitorpamplona.quartz.utils.DualCase import com.vitorpamplona.quartz.utils.DualCase
/** /**
@@ -40,16 +39,6 @@ interface INwcSignerState {
fun isNIP47Author(pubKey: String?): Boolean fun isNIP47Author(pubKey: String?): Boolean
} }
/**
* Interface for private zap decryption cache.
* Used by Note.kt for checking private zap status.
*/
interface IPrivateZapsDecryptionCache {
fun cachedPrivateZap(event: LnZapRequestEvent): LnZapPrivateEvent?
suspend fun decryptPrivateZap(event: LnZapRequestEvent): LnZapPrivateEvent?
}
/** /**
* Hidden content settings for filtering notes. * Hidden content settings for filtering notes.
* Used by Note.isHiddenFor() to check if content should be hidden. * Used by Note.isHiddenFor() to check if content should be hidden.
@@ -59,7 +48,13 @@ data class LiveHiddenUsers(
val hiddenWordsCase: List<DualCase>, val hiddenWordsCase: List<DualCase>,
val hiddenUsersHashCodes: Set<Int>, val hiddenUsersHashCodes: Set<Int>,
val spammersHashCodes: Set<Int>, val spammersHashCodes: Set<Int>,
) // Raw sets for amethyst-specific usage
val hiddenUsers: Set<String> = emptySet(),
val spammers: Set<String> = emptySet(),
val hiddenWords: Set<String> = emptySet(),
) {
fun isUserHidden(userHex: String) = hiddenUsers.contains(userHex) || spammers.contains(userHex)
}
/** /**
* Interface for account operations needed by Note.kt. * Interface for account operations needed by Note.kt.
@@ -0,0 +1,33 @@
/**
* Copyright (c) 2025 Vitor Pamplona
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
* Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.amethyst.commons.model.trustedAssertions
import com.vitorpamplona.quartz.experimental.trustedAssertions.list.tags.ServiceProviderTag
import kotlinx.coroutines.flow.StateFlow
/**
* Interface for trust provider list state.
* Used by UserCardsCache for accessing user rank and follower count providers.
*/
interface TrustProviderListState {
val liveUserRankProvider: StateFlow<ServiceProviderTag?>
val liveUserFollowerCount: StateFlow<ServiceProviderTag?>
}
@@ -136,15 +136,3 @@ class UserCardsCache : UserDependencies {
} }
}.flowOn(Dispatchers.IO) }.flowOn(Dispatchers.IO)
} }
// Placeholder for TrustProviderListState - will be properly extracted later
// For now, this allows UserCardsCache to compile
interface TrustProviderListState {
val liveUserRankProvider: kotlinx.coroutines.flow.StateFlow<ServiceProviderTag?>
val liveUserFollowerCount: kotlinx.coroutines.flow.StateFlow<ServiceProviderTag?>
}
// Placeholder for ServiceProviderTag
interface ServiceProviderTag {
val pubkey: String
}
@@ -0,0 +1,31 @@
/**
* Copyright (c) 2025 Vitor Pamplona
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
* Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.quartz.nip57Zaps
/**
* Interface for private zap decryption cache.
* Used by Note.kt for checking private zap status.
*/
interface IPrivateZapsDecryptionCache {
fun cachedPrivateZap(event: LnZapRequestEvent): LnZapPrivateEvent?
suspend fun decryptPrivateZap(event: LnZapRequestEvent): LnZapPrivateEvent?
}
@@ -26,7 +26,7 @@ import com.vitorpamplona.quartz.nip01Core.signers.caches.DecryptCache
class PrivateZapCache( class PrivateZapCache(
signer: NostrSigner, signer: NostrSigner,
) { ) : IPrivateZapsDecryptionCache {
private val decryptionCache = private val decryptionCache =
object : LruCache<LnZapRequestEvent, PrivateZapDecryptCache>(1000) { object : LruCache<LnZapRequestEvent, PrivateZapDecryptCache>(1000) {
override fun create(key: LnZapRequestEvent): PrivateZapDecryptCache? { override fun create(key: LnZapRequestEvent): PrivateZapDecryptCache? {
@@ -43,9 +43,9 @@ class PrivateZapCache(
decryptionCache.remove(event) decryptionCache.remove(event)
} }
fun cachedPrivateZap(event: LnZapRequestEvent): LnZapPrivateEvent? = decryptionCache[event]?.cached() override fun cachedPrivateZap(event: LnZapRequestEvent): LnZapPrivateEvent? = decryptionCache[event]?.cached()
suspend fun decryptPrivateZap(event: LnZapRequestEvent) = decryptionCache[event]?.decrypt(event) override suspend fun decryptPrivateZap(event: LnZapRequestEvent) = decryptionCache[event]?.decrypt(event)
} }
class PrivateZapDecryptCache( class PrivateZapDecryptCache(