Defers most module creations to when they are needed via lambdas

This commit is contained in:
Vitor Pamplona
2026-03-26 11:11:44 -04:00
parent 7952f558eb
commit 155e57ab11
13 changed files with 103 additions and 79 deletions
@@ -20,7 +20,6 @@
*/ */
package com.vitorpamplona.amethyst package com.vitorpamplona.amethyst
import android.content.ContentResolver
import android.content.Context import android.content.Context
import androidx.security.crypto.EncryptedSharedPreferences import androidx.security.crypto.EncryptedSharedPreferences
import coil3.disk.DiskCache import coil3.disk.DiskCache
@@ -111,29 +110,37 @@ class AppModules(
// Blocking load of UI Preferences to avoid theme/language blinking // Blocking load of UI Preferences to avoid theme/language blinking
val uiPrefs by lazy { val uiPrefs by lazy {
Log.d("AppModules", "UiSharedPreferences Init")
UiSharedPreferences(appContext, applicationIOScope) UiSharedPreferences(appContext, applicationIOScope)
} }
// Blocking load of Tor Settings to avoid connection leaks // Blocking load of Tor Settings to avoid connection leaks
val torPrefs by lazy { val torPrefs by lazy {
Log.d("AppModules", "TorSharedPreferences Init")
TorSharedPreferences(appContext, applicationIOScope) TorSharedPreferences(appContext, applicationIOScope)
} }
// Namecoin ElectrumX server preferences (global, like Tor settings) // Namecoin ElectrumX server preferences (global, like Tor settings)
val namecoinPrefs by lazy { val namecoinPrefs by lazy {
Log.d("AppModules", "NamecoinSharedPreferences Init")
NamecoinSharedPreferences(appContext, applicationIOScope) NamecoinSharedPreferences(appContext, applicationIOScope)
} }
// OTS blockchain explorer preferences (global, like Tor settings) // OTS blockchain explorer preferences (global, like Tor settings)
val otsPrefs by lazy { val otsPrefs by lazy {
Log.d("AppModules", "OtsSharedPreferences Init")
OtsSharedPreferences(appContext, applicationIOScope) OtsSharedPreferences(appContext, applicationIOScope)
} }
// App services that should be run as soon as there are subscribers to their flows // App services that should be run as soon as there are subscribers to their flows
val locationManager = LocationState(appContext, applicationIOScope) val locationManager by lazy {
Log.d("AppModules", "LocationManager Init")
LocationState(appContext, applicationIOScope)
}
val connManager = ConnectivityManager(appContext, applicationIOScope) val connManager = ConnectivityManager(appContext, applicationIOScope)
val uiState by lazy { val uiState by lazy {
Log.d("AppModules", "UiSettingsState Init")
UiSettingsState(uiPrefs.value, connManager.isMobileOrFalse, applicationIOScope) UiSettingsState(uiPrefs.value, connManager.isMobileOrFalse, applicationIOScope)
} }
@@ -178,8 +185,6 @@ class AppModules(
) )
} }
// Application-wide block height request cache
val otsBlockHeightCache by lazy { OtsBlockHeightCache() }
val nip05Client by val nip05Client by
lazy { lazy {
Log.d("AppModules", "NIP05Client Init") Log.d("AppModules", "NIP05Client Init")
@@ -189,16 +194,22 @@ class AppModules(
) )
} }
val otsResolverBuilder: TorAwareOkHttpOtsResolverBuilder = val otsResolverBuilder by
lazy {
Log.d("AppModules", "OtsResolverBuilder Init")
TorAwareOkHttpOtsResolverBuilder( TorAwareOkHttpOtsResolverBuilder(
roleBasedHttpClientBuilder::okHttpClientForMoney, roleBasedHttpClientBuilder::okHttpClientForMoney,
roleBasedHttpClientBuilder::shouldUseTorForMoneyOperations, roleBasedHttpClientBuilder::shouldUseTorForMoneyOperations,
otsBlockHeightCache, OtsBlockHeightCache(),
customExplorerUrl = { otsPrefs.current.normalizedUrl() }, customExplorerUrl = { otsPrefs.current.normalizedUrl() },
) )
}
// Application-wide ots verification cache // Application-wide ots verification cache
val otsVerifCache by lazy { VerificationStateCache(otsResolverBuilder) } val otsVerifCache by lazy {
Log.d("AppModules", "OtsCache Init")
VerificationStateCache(otsResolverBuilder)
}
val torEvaluatorFlow = val torEvaluatorFlow =
TorRelayState( TorRelayState(
@@ -250,7 +261,12 @@ class AppModules(
val authCoordinator = AuthCoordinator(client, applicationIOScope) val authCoordinator = AuthCoordinator(client, applicationIOScope)
// Tries to verify new OTS events when they arrive. // Tries to verify new OTS events when they arrive.
val otsEventVerifier = IncomingOtsEventVerifier(otsVerifCache, cache, applicationIOScope) val otsEventVerifier =
IncomingOtsEventVerifier(
otsVerifCache = { otsVerifCache },
cache = cache,
scope = applicationIOScope,
)
// Tracks if it is possible to connect to relays. // Tracks if it is possible to connect to relays.
val failureTracker = RelayOfflineTracker(client) val failureTracker = RelayOfflineTracker(client)
@@ -276,10 +292,10 @@ class AppModules(
// keeps all accounts live // keeps all accounts live
val accountsCache = val accountsCache =
AccountCacheState( AccountCacheState(
geolocationFlow = locationManager.geohashStateFlow, geolocationFlow = { locationManager.geohashStateFlow },
nwcFilterAssembler = sources.nwc, nwcFilterAssembler = { sources.nwc },
contentResolverFn = ::contentResolverFn, contentResolverFn = { appContext.contentResolver },
otsResolverBuilder = otsResolverBuilder, otsResolverBuilder = { otsResolverBuilder.build() },
cache = cache, cache = cache,
client = client, client = client,
) )
@@ -287,8 +303,8 @@ class AppModules(
val sessionManager = val sessionManager =
AccountSessionManager( AccountSessionManager(
accountsCache = accountsCache, accountsCache = accountsCache,
client = client,
nip05ClientBuilder = { nip05Client }, nip05ClientBuilder = { nip05Client },
clientBuilder = { client },
localPreferences = LocalPreferences, localPreferences = LocalPreferences,
scope = applicationIOScope, scope = applicationIOScope,
) )
@@ -314,7 +330,8 @@ class AppModules(
} }
} }
val blossomResolver = val blossomResolver by lazy {
Log.d("AppModules", "BlossomServerResolver Init")
BlossomServerResolver( BlossomServerResolver(
loggedInUsers = { listOfNotNull(sessionManager.loggedInAccount()?.pubKey) }, loggedInUsers = { listOfNotNull(sessionManager.loggedInAccount()?.pubKey) },
blossomServers = { addressesToSubscribe -> blossomServers = { addressesToSubscribe ->
@@ -330,6 +347,7 @@ class AppModules(
}, },
httpClientBuilder = roleBasedHttpClientBuilder, httpClientBuilder = roleBasedHttpClientBuilder,
) )
}
// Organizes cache clearing // Organizes cache clearing
val trimmingService = MemoryTrimmingService(cache) val trimmingService = MemoryTrimmingService(cache)
@@ -339,36 +357,47 @@ class AppModules(
val accountsTorStateConnector = AccountsTorStateConnector(accountsCache, torEvaluatorFlow, applicationIOScope) val accountsTorStateConnector = AccountsTorStateConnector(accountsCache, torEvaluatorFlow, applicationIOScope)
// saves the .content of NIP-95 blobs in disk to save memory // saves the .content of NIP-95 blobs in disk to save memory
val nip95cache: File by lazy { Nip95CacheFactory.new(appContext) } val nip95cache: File by lazy {
Log.d("AppModules", "NIP95 Cache Init")
Nip95CacheFactory.new(appContext)
}
// local video cache with disk + memory // local video cache with disk + memory
val videoCache: VideoCache by lazy { VideoCacheFactory.new(appContext) } val videoCache: VideoCache by lazy {
Log.d("AppModules", "VideoCache Init")
VideoCacheFactory.new(appContext)
}
// image cache in disk for coil // image cache in disk for coil
val diskCache: DiskCache by lazy { ImageCacheFactory.newDisk(appContext) } val diskCache: DiskCache by lazy {
Log.d("AppModules", "ImageCacheFactory Init")
ImageCacheFactory.newDisk(appContext)
}
// image cache in memory for coil // image cache in memory for coil
val memoryCache: MemoryCache by lazy { ImageCacheFactory.newMemory(appContext) } val memoryCache: MemoryCache by lazy {
Log.d("AppModules", "MemoryCache Init")
ImageCacheFactory.newMemory(appContext)
}
// crash report storage // crash report storage
val crashReportCache: CrashReportCache by lazy { CrashReportCache(appContext) } val crashReportCache = CrashReportCache(appContext)
// cache for NIP-11 documents // cache for NIP-11 documents
val nip11Cache: Nip11CachedRetriever by lazy { val nip11Cache: Nip11CachedRetriever by lazy {
Log.d("AppModules", "Nip11CachedRetriever Init")
Nip11CachedRetriever(torEvaluatorFlow::okHttpClientForRelay) Nip11CachedRetriever(torEvaluatorFlow::okHttpClientForRelay)
} }
fun contentResolverFn(): ContentResolver = appContext.contentResolver
fun setImageLoader() { fun setImageLoader() {
Log.d("AppModules", "ImageLoaderSetup Init")
ImageLoaderSetup.setup( ImageLoaderSetup.setup(
app = appContext, app = appContext,
diskCache = { diskCache }, diskCache = { diskCache },
memoryCache = { memoryCache }, memoryCache = { memoryCache },
blossomServerResolver = blossomResolver, blossomServerResolver = { blossomResolver },
) { url -> callFactory = { okHttpClients.getHttpClient(roleBasedHttpClientBuilder.shouldUseTorForImageDownload(it)) },
okHttpClients.getHttpClient(roleBasedHttpClientBuilder.shouldUseTorForImageDownload(url)) )
}
} }
fun encryptedStorage(npub: String? = null): EncryptedSharedPreferences = EncryptedStorage.preferences(appContext, npub) fun encryptedStorage(npub: String? = null): EncryptedSharedPreferences = EncryptedStorage.preferences(appContext, npub)
@@ -385,12 +414,6 @@ class AppModules(
// forces initialization of uiPrefs in the main thread to avoid blinking themes // forces initialization of uiPrefs in the main thread to avoid blinking themes
uiPrefs uiPrefs
// initializes diskcache on an IO thread.
applicationIOScope.launch {
// preloads tor preferences
torPrefs
}
// initializes diskcache on an IO thread. // initializes diskcache on an IO thread.
applicationIOScope.launch { applicationIOScope.launch {
// Sets Coil - Tor - OkHttp link // Sets Coil - Tor - OkHttp link
@@ -402,15 +425,10 @@ class AppModules(
// initializes diskcache on an IO thread. // initializes diskcache on an IO thread.
applicationIOScope.launch { applicationIOScope.launch {
// Sets Coil - Tor - OkHttp link // Prepares video cache later
delay(3000) delay(10_000)
videoCache videoCache
} }
applicationIOScope.launch {
// Eagerly initialize OtsSharedPreferences off the main thread
otsPrefs
}
} }
fun terminate(appContext: Context) { fun terminate(appContext: Context) {
@@ -143,7 +143,7 @@ import com.vitorpamplona.quartz.nip01Core.signers.NostrSignerInternal
import com.vitorpamplona.quartz.nip01Core.tags.hashtags.hashtags import com.vitorpamplona.quartz.nip01Core.tags.hashtags.hashtags
import com.vitorpamplona.quartz.nip01Core.tags.people.taggedUserIds import com.vitorpamplona.quartz.nip01Core.tags.people.taggedUserIds
import com.vitorpamplona.quartz.nip01Core.tags.references.references import com.vitorpamplona.quartz.nip01Core.tags.references.references
import com.vitorpamplona.quartz.nip03Timestamp.OtsResolverBuilder import com.vitorpamplona.quartz.nip03Timestamp.OtsResolver
import com.vitorpamplona.quartz.nip04Dm.PrivateDMCache import com.vitorpamplona.quartz.nip04Dm.PrivateDMCache
import com.vitorpamplona.quartz.nip04Dm.messages.PrivateDmEvent import com.vitorpamplona.quartz.nip04Dm.messages.PrivateDmEvent
import com.vitorpamplona.quartz.nip09Deletions.DeletionEvent import com.vitorpamplona.quartz.nip09Deletions.DeletionEvent
@@ -235,9 +235,9 @@ import kotlin.coroutines.cancellation.CancellationException
class Account( class Account(
val settings: AccountSettings = AccountSettings(KeyPair()), val settings: AccountSettings = AccountSettings(KeyPair()),
override val signer: NostrSigner, override val signer: NostrSigner,
val geolocationFlow: StateFlow<LocationState.LocationResult>, val geolocationFlow: () -> StateFlow<LocationState.LocationResult>,
val nwcFilterAssembler: NWCPaymentFilterAssembler, val nwcFilterAssembler: () -> NWCPaymentFilterAssembler,
val otsResolverBuilder: OtsResolverBuilder, val otsResolverBuilder: () -> OtsResolver,
val cache: LocalCache, val cache: LocalCache,
val client: INostrClient, val client: INostrClient,
val scope: CoroutineScope, val scope: CoroutineScope,
@@ -2491,7 +2491,7 @@ object LocalCache : ILocalCache, ICacheProvider {
suspend fun findEarliestOtsForNote( suspend fun findEarliestOtsForNote(
note: Note, note: Note,
otsVerifCache: VerificationStateCache, otsVerifCacheBuilder: () -> VerificationStateCache,
): Long? { ): Long? {
checkNotInMainThread() checkNotInMainThread()
@@ -2502,7 +2502,7 @@ object LocalCache : ILocalCache, ICacheProvider {
notes.mapNotNull { _, item -> notes.mapNotNull { _, item ->
val noteEvent = item.event val noteEvent = item.event
if ((noteEvent is OtsEvent && noteEvent.isTaggedEvent(note.idHex) && !noteEvent.isExpirationBefore(time))) { if ((noteEvent is OtsEvent && noteEvent.isTaggedEvent(note.idHex) && !noteEvent.isExpirationBefore(time))) {
val cachedTime = (otsVerifCache.justCache(noteEvent) as? VerificationState.Verified)?.verifiedTime val cachedTime = (otsVerifCacheBuilder().justCache(noteEvent) as? VerificationState.Verified)?.verifiedTime
if (cachedTime != null) { if (cachedTime != null) {
if (minTime == null || cachedTime < (minTime ?: Long.MAX_VALUE)) { if (minTime == null || cachedTime < (minTime ?: Long.MAX_VALUE)) {
minTime = cachedTime minTime = cachedTime
@@ -2518,7 +2518,7 @@ object LocalCache : ILocalCache, ICacheProvider {
} }
candidates.forEach { noteEvent -> candidates.forEach { noteEvent ->
(otsVerifCache.cacheVerify(noteEvent) as? VerificationState.Verified)?.verifiedTime?.let { stampedTime -> (otsVerifCacheBuilder().cacheVerify(noteEvent) as? VerificationState.Verified)?.verifiedTime?.let { stampedTime ->
if (minTime == null || stampedTime < (minTime ?: Long.MAX_VALUE)) { if (minTime == null || stampedTime < (minTime ?: Long.MAX_VALUE)) {
minTime = stampedTime minTime = stampedTime
} }
@@ -31,7 +31,7 @@ import com.vitorpamplona.quartz.nip01Core.core.toHexKey
import com.vitorpamplona.quartz.nip01Core.relay.client.INostrClient import com.vitorpamplona.quartz.nip01Core.relay.client.INostrClient
import com.vitorpamplona.quartz.nip01Core.signers.NostrSigner import com.vitorpamplona.quartz.nip01Core.signers.NostrSigner
import com.vitorpamplona.quartz.nip01Core.signers.NostrSignerInternal import com.vitorpamplona.quartz.nip01Core.signers.NostrSignerInternal
import com.vitorpamplona.quartz.nip03Timestamp.OtsResolverBuilder import com.vitorpamplona.quartz.nip03Timestamp.OtsResolver
import com.vitorpamplona.quartz.nip55AndroidSigner.client.NostrSignerExternal import com.vitorpamplona.quartz.nip55AndroidSigner.client.NostrSignerExternal
import com.vitorpamplona.quartz.nip89AppHandlers.clientTag.NostrSignerWithClientTag import com.vitorpamplona.quartz.nip89AppHandlers.clientTag.NostrSignerWithClientTag
import com.vitorpamplona.quartz.utils.Log import com.vitorpamplona.quartz.utils.Log
@@ -45,10 +45,10 @@ import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.update import kotlinx.coroutines.flow.update
class AccountCacheState( class AccountCacheState(
val geolocationFlow: StateFlow<LocationState.LocationResult>, val geolocationFlow: () -> StateFlow<LocationState.LocationResult>,
val nwcFilterAssembler: NWCPaymentFilterAssembler, val nwcFilterAssembler: () -> NWCPaymentFilterAssembler,
val contentResolverFn: () -> ContentResolver, val contentResolverFn: () -> ContentResolver,
val otsResolverBuilder: OtsResolverBuilder, val otsResolverBuilder: () -> OtsResolver,
val cache: LocalCache, val cache: LocalCache,
val client: INostrClient, val client: INostrClient,
) { ) {
@@ -32,7 +32,7 @@ import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.flow.stateIn
class IncomingOtsEventVerifier( class IncomingOtsEventVerifier(
private val otsVerifCache: VerificationStateCache, private val otsVerifCache: () -> VerificationStateCache,
private val cache: LocalCache, private val cache: LocalCache,
private val scope: CoroutineScope, private val scope: CoroutineScope,
) { ) {
@@ -52,7 +52,7 @@ class IncomingOtsEventVerifier(
suspend fun consume(note: Note) { suspend fun consume(note: Note) {
note.event?.let { event -> note.event?.let { event ->
if (event is OtsEvent) { if (event is OtsEvent) {
otsVerifCache.cacheVerify(event) otsVerifCache().cacheVerify(event)
} }
} }
} }
@@ -26,7 +26,7 @@ import com.vitorpamplona.amethyst.model.Note
import com.vitorpamplona.quartz.nip01Core.core.Event import com.vitorpamplona.quartz.nip01Core.core.Event
import com.vitorpamplona.quartz.nip01Core.signers.NostrSigner import com.vitorpamplona.quartz.nip01Core.signers.NostrSigner
import com.vitorpamplona.quartz.nip03Timestamp.OtsEvent import com.vitorpamplona.quartz.nip03Timestamp.OtsEvent
import com.vitorpamplona.quartz.nip03Timestamp.OtsResolverBuilder import com.vitorpamplona.quartz.nip03Timestamp.OtsResolver
import com.vitorpamplona.quartz.utils.Log import com.vitorpamplona.quartz.utils.Log
import com.vitorpamplona.quartz.utils.TimeUtils import com.vitorpamplona.quartz.utils.TimeUtils
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
@@ -37,7 +37,7 @@ import java.util.Base64
class OtsState( class OtsState(
val signer: NostrSigner, val signer: NostrSigner,
val cache: LocalCache, val cache: LocalCache,
val otsResolver: OtsResolverBuilder, val otsResolver: () -> OtsResolver,
val scope: CoroutineScope, val scope: CoroutineScope,
val settings: AccountSettings, val settings: AccountSettings,
) { ) {
@@ -58,7 +58,7 @@ class OtsState(
Log.d("Pending Attestations", "Updating ${settings.pendingAttestations.value.size} pending attestations") Log.d("Pending Attestations", "Updating ${settings.pendingAttestations.value.size} pending attestations")
return settings.pendingAttestations.value.toList().mapNotNull { (key, value) -> return settings.pendingAttestations.value.toList().mapNotNull { (key, value) ->
val otsState = OtsEvent.upgrade(Base64.getDecoder().decode(value), key, otsResolver.build()) val otsState = OtsEvent.upgrade(Base64.getDecoder().decode(value), key, otsResolver())
if (otsState != null) { if (otsState != null) {
val hint = cache.getNoteIfExists(key)?.toEventHint<Event>() val hint = cache.getNoteIfExists(key)?.toEventHint<Event>()
@@ -96,7 +96,7 @@ class OtsState(
Base64.getEncoder().encodeToString( Base64.getEncoder().encodeToString(
OtsEvent.stamp( OtsEvent.stamp(
id, id,
otsResolver.build(), otsResolver(),
), ),
), ),
) )
@@ -64,7 +64,7 @@ import kotlinx.coroutines.launch
*/ */
class NwcSignerState( class NwcSignerState(
val signer: NostrSigner, val signer: NostrSigner,
val nwcFilterAssembler: NWCPaymentFilterAssembler, val nwcFilterAssembler: () -> NWCPaymentFilterAssembler,
val cache: LocalCache, val cache: LocalCache,
val scope: CoroutineScope, val scope: CoroutineScope,
val nip47Setup: MutableStateFlow<Nip47WalletConnect.Nip47URINorm?>, val nip47Setup: MutableStateFlow<Nip47WalletConnect.Nip47URINorm?>,
@@ -163,11 +163,13 @@ class NwcSignerState(
relay = walletService.relayUri, relay = walletService.relayUri,
) )
nwcFilterAssembler.subscribe(filter) val assembler = nwcFilterAssembler()
assembler.subscribe(filter)
scope.launch(Dispatchers.IO) { scope.launch(Dispatchers.IO) {
delay(60000) delay(60000)
nwcFilterAssembler.unsubscribe(filter) assembler.unsubscribe(filter)
} }
cache.consume(event, null, true, walletService.relayUri) { cache.consume(event, null, true, walletService.relayUri) {
@@ -204,11 +206,13 @@ class NwcSignerState(
relay = walletService.relayUri, relay = walletService.relayUri,
) )
nwcFilterAssembler.subscribe(filter) val assembler = nwcFilterAssembler()
assembler.subscribe(filter)
scope.launch(Dispatchers.IO) { scope.launch(Dispatchers.IO) {
delay(60000) // waits 1 minute to complete payment. delay(60000) // waits 1 minute to complete payment.
nwcFilterAssembler.unsubscribe(filter) assembler.unsubscribe(filter)
} }
cache.consume(event, zappedNote, true, walletService.relayUri) { cache.consume(event, zappedNote, true, walletService.relayUri) {
@@ -51,7 +51,7 @@ class FeedTopNavFilterState(
val feedFilterListName: MutableStateFlow<TopFilter>, val feedFilterListName: MutableStateFlow<TopFilter>,
val kind3Follows: StateFlow<Kind3FollowListState.Kind3Follows>, val kind3Follows: StateFlow<Kind3FollowListState.Kind3Follows>,
val allFollows: StateFlow<MergedFollowListsState.AllFollows>, val allFollows: StateFlow<MergedFollowListsState.AllFollows>,
val locationFlow: StateFlow<LocationState.LocationResult>, val locationFlow: () -> StateFlow<LocationState.LocationResult>,
val followsRelays: StateFlow<Set<NormalizedRelayUrl>>, val followsRelays: StateFlow<Set<NormalizedRelayUrl>>,
val blockedRelays: StateFlow<Set<NormalizedRelayUrl>>, val blockedRelays: StateFlow<Set<NormalizedRelayUrl>>,
val proxyRelays: StateFlow<Set<NormalizedRelayUrl>>, val proxyRelays: StateFlow<Set<NormalizedRelayUrl>>,
@@ -78,7 +78,7 @@ class FeedTopNavFilterState(
} }
TopFilter.AroundMe -> { TopFilter.AroundMe -> {
AroundMeFeedFlow(locationFlow, followsRelays, proxyRelays) AroundMeFeedFlow(locationFlow(), followsRelays, proxyRelays)
} }
TopFilter.Chess -> { TopFilter.Chess -> {
@@ -41,12 +41,12 @@ import kotlin.coroutines.cancellation.CancellationException
class BlossomFetcher( class BlossomFetcher(
private val options: Options, private val options: Options,
private val data: Uri, private val data: Uri,
private val blossomServerResolver: BlossomServerResolver, private val blossomServerResolver: () -> BlossomServerResolver,
private val networkFetcher: (url: String) -> Fetcher, private val networkFetcher: (url: String) -> Fetcher,
) : Fetcher { ) : Fetcher {
override suspend fun fetch(): FetchResult? = override suspend fun fetch(): FetchResult? =
try { try {
val urlResult = blossomServerResolver.findServers(data.toString()) val urlResult = blossomServerResolver().findServers(data.toString())
networkFetcher(urlResult?.serverUrl ?: data.toString()).fetch() networkFetcher(urlResult?.serverUrl ?: data.toString()).fetch()
} catch (e: Exception) { } catch (e: Exception) {
if (e is CancellationException) throw e if (e is CancellationException) throw e
@@ -55,7 +55,7 @@ class BlossomFetcher(
@OptIn(ExperimentalCoilApi::class) @OptIn(ExperimentalCoilApi::class)
class Factory( class Factory(
val blossomServerResolver: BlossomServerResolver, val blossomServerResolver: () -> BlossomServerResolver,
val networkClient: (url: String) -> Call.Factory, val networkClient: (url: String) -> Call.Factory,
) : Fetcher.Factory<Uri> { ) : Fetcher.Factory<Uri> {
private val connectivityCheckerLazy = singleParameterLazy(::ConnectivityChecker) private val connectivityCheckerLazy = singleParameterLazy(::ConnectivityChecker)
@@ -64,7 +64,7 @@ class ImageLoaderSetup {
app: Context, app: Context,
diskCache: () -> DiskCache, diskCache: () -> DiskCache,
memoryCache: () -> MemoryCache, memoryCache: () -> MemoryCache,
blossomServerResolver: BlossomServerResolver, blossomServerResolver: () -> BlossomServerResolver,
callFactory: (url: String) -> Call.Factory, callFactory: (url: String) -> Call.Factory,
) { ) {
SingletonImageLoader.setUnsafe( SingletonImageLoader.setUnsafe(
@@ -123,7 +123,7 @@ fun LoadOts(
withContext(Dispatchers.IO) { withContext(Dispatchers.IO) {
LocalCache.findEarliestOtsForNote( LocalCache.findEarliestOtsForNote(
note = noteStatus?.note ?: note, note = noteStatus?.note ?: note,
otsVerifCache = Amethyst.instance.otsVerifCache, otsVerifCacheBuilder = { Amethyst.instance.otsVerifCache },
) )
} }
@@ -93,8 +93,8 @@ sealed class AccountState {
@Stable @Stable
class AccountSessionManager( class AccountSessionManager(
val accountsCache: AccountCacheState, val accountsCache: AccountCacheState,
val client: INostrClient,
val nip05ClientBuilder: () -> Nip05Client, val nip05ClientBuilder: () -> Nip05Client,
val clientBuilder: () -> INostrClient,
val localPreferences: LocalPreferences, val localPreferences: LocalPreferences,
val scope: CoroutineScope, val scope: CoroutineScope,
) { ) {
@@ -287,6 +287,8 @@ class AccountSessionManager(
val toPost = accountSettings.backupNIP65RelayList?.writeRelaysNorm()?.toSet() ?: DefaultNIP65RelaySet val toPost = accountSettings.backupNIP65RelayList?.writeRelaysNorm()?.toSet() ?: DefaultNIP65RelaySet
val client = clientBuilder()
accountSettings.backupUserMetadata?.let { client.send(it, toPost) } accountSettings.backupUserMetadata?.let { client.send(it, toPost) }
accountSettings.backupContactList?.let { client.send(it, toPost) } accountSettings.backupContactList?.let { client.send(it, toPost) }
accountSettings.backupNIP65RelayList?.let { client.send(it, toPost) } accountSettings.backupNIP65RelayList?.let { client.send(it, toPost) }
@@ -1808,9 +1808,9 @@ fun mockAccountViewModel(): AccountViewModel {
Account( Account(
settings = AccountSettings(keyPair), settings = AccountSettings(keyPair),
signer = NostrSignerInternal(keyPair), signer = NostrSignerInternal(keyPair),
geolocationFlow = MutableStateFlow<LocationState.LocationResult>(LocationState.LocationResult.Loading), geolocationFlow = { MutableStateFlow<LocationState.LocationResult>(LocationState.LocationResult.Loading) },
nwcFilterAssembler = nwcFilters, nwcFilterAssembler = { nwcFilters },
otsResolverBuilder = EmptyOtsResolverBuilder, otsResolverBuilder = { EmptyOtsResolverBuilder.build() },
cache = LocalCache, cache = LocalCache,
client = client, client = client,
scope = scope, scope = scope,
@@ -1859,9 +1859,9 @@ fun mockVitorAccountViewModel(): AccountViewModel {
Account( Account(
settings = AccountSettings(keyPair), settings = AccountSettings(keyPair),
signer = NostrSignerInternal(keyPair), signer = NostrSignerInternal(keyPair),
geolocationFlow = MutableStateFlow<LocationState.LocationResult>(LocationState.LocationResult.Loading), geolocationFlow = { MutableStateFlow<LocationState.LocationResult>(LocationState.LocationResult.Loading) },
nwcFilterAssembler = nwcFilters, nwcFilterAssembler = { nwcFilters },
otsResolverBuilder = EmptyOtsResolverBuilder, otsResolverBuilder = { EmptyOtsResolverBuilder.build() },
cache = LocalCache, cache = LocalCache,
client = EmptyNostrClient(), client = EmptyNostrClient(),
scope = scope, scope = scope,