mirror of
https://github.com/vitorpamplona/amethyst.git
synced 2025-09-19 19:31:43 +02:00
Establishing a scope for each account loaded.
This commit is contained in:
@@ -26,8 +26,6 @@ import android.util.Log
|
||||
import androidx.security.crypto.EncryptedSharedPreferences
|
||||
import coil3.disk.DiskCache
|
||||
import coil3.memory.MemoryCache
|
||||
import com.vitorpamplona.amethyst.model.Account
|
||||
import com.vitorpamplona.amethyst.model.AccountSettings
|
||||
import com.vitorpamplona.amethyst.model.LocalCache
|
||||
import com.vitorpamplona.amethyst.model.accountsCache.AccountCacheState
|
||||
import com.vitorpamplona.amethyst.service.connectivity.ConnectivityManager
|
||||
@@ -54,13 +52,9 @@ import com.vitorpamplona.amethyst.service.relayClient.speedLogger.RelaySpeedLogg
|
||||
import com.vitorpamplona.amethyst.service.uploads.nip95.Nip95CacheFactory
|
||||
import com.vitorpamplona.amethyst.ui.navigation.navs.EmptyNav.scope
|
||||
import com.vitorpamplona.amethyst.ui.tor.TorManager
|
||||
import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
||||
import com.vitorpamplona.quartz.nip01Core.core.toHexKey
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.NostrClient
|
||||
import com.vitorpamplona.quartz.nip01Core.signers.NostrSignerInternal
|
||||
import com.vitorpamplona.quartz.nip03Timestamp.VerificationStateCache
|
||||
import com.vitorpamplona.quartz.nip03Timestamp.ots.okhttp.OtsBlockHeightCache
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.client.NostrSignerExternal
|
||||
import kotlinx.coroutines.CoroutineExceptionHandler
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
@@ -161,13 +155,14 @@ class Amethyst : Application() {
|
||||
// Coordinates all subscriptions for the Nostr Client
|
||||
val sources: RelaySubscriptionsCoordinator = RelaySubscriptionsCoordinator(LocalCache, client, applicationIOScope)
|
||||
|
||||
// keeps all accounts live
|
||||
val accountsCache =
|
||||
AccountCacheState(
|
||||
geolocationFlow = locationManager.geohashStateFlow,
|
||||
nwcFilterAssembler = sources.nwc,
|
||||
contentResolver = contentResolver,
|
||||
cache = cache,
|
||||
client = client,
|
||||
scope = applicationIOScope,
|
||||
)
|
||||
|
||||
// saves the .content of NIP-95 blobs in disk to save memory
|
||||
@@ -242,31 +237,6 @@ class Amethyst : Application() {
|
||||
}
|
||||
}
|
||||
|
||||
fun loadAccount(accountSettings: AccountSettings): Account {
|
||||
val keyPair = accountSettings.keyPair
|
||||
return accountsCache.loadAccount(
|
||||
signer =
|
||||
if (keyPair.privKey != null) {
|
||||
NostrSignerInternal(keyPair)
|
||||
} else {
|
||||
when (val packageName = accountSettings.externalSignerPackageName) {
|
||||
null -> NostrSignerInternal(keyPair)
|
||||
else ->
|
||||
NostrSignerExternal(
|
||||
pubKey = keyPair.pubKey.toHexKey(),
|
||||
packageName = packageName,
|
||||
contentResolver = contentResolver,
|
||||
)
|
||||
}
|
||||
},
|
||||
accountSettings = accountSettings,
|
||||
)
|
||||
}
|
||||
|
||||
fun removeAccount(pubkey: HexKey) {
|
||||
accountsCache.removeAccount(pubkey)
|
||||
}
|
||||
|
||||
companion object {
|
||||
lateinit var instance: Amethyst
|
||||
private set
|
||||
|
@@ -20,6 +20,8 @@
|
||||
*/
|
||||
package com.vitorpamplona.amethyst.model.accountsCache
|
||||
|
||||
import android.content.ContentResolver
|
||||
import android.util.Log
|
||||
import androidx.collection.LruCache
|
||||
import com.vitorpamplona.amethyst.model.Account
|
||||
import com.vitorpamplona.amethyst.model.AccountSettings
|
||||
@@ -27,22 +29,59 @@ import com.vitorpamplona.amethyst.model.LocalCache
|
||||
import com.vitorpamplona.amethyst.service.location.LocationState
|
||||
import com.vitorpamplona.amethyst.service.relayClient.reqCommand.nwc.NWCPaymentFilterAssembler
|
||||
import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
||||
import com.vitorpamplona.quartz.nip01Core.core.toHexKey
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.INostrClient
|
||||
import com.vitorpamplona.quartz.nip01Core.signers.NostrSigner
|
||||
import com.vitorpamplona.quartz.nip01Core.signers.NostrSignerInternal
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.client.NostrSignerExternal
|
||||
import kotlinx.coroutines.CoroutineExceptionHandler
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.SupervisorJob
|
||||
import kotlinx.coroutines.cancel
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
|
||||
class AccountCacheState(
|
||||
val geolocationFlow: StateFlow<LocationState.LocationResult>,
|
||||
val nwcFilterAssembler: NWCPaymentFilterAssembler,
|
||||
val contentResolver: ContentResolver,
|
||||
val cache: LocalCache,
|
||||
val client: INostrClient,
|
||||
val scope: CoroutineScope,
|
||||
) {
|
||||
val accounts = LruCache<HexKey, Account>(20)
|
||||
val accounts =
|
||||
object : LruCache<HexKey, Account>(20) {
|
||||
override fun entryRemoved(
|
||||
evicted: Boolean,
|
||||
key: HexKey,
|
||||
oldValue: Account,
|
||||
newValue: Account?,
|
||||
) {
|
||||
super.entryRemoved(evicted, key, oldValue, newValue)
|
||||
oldValue.scope.cancel()
|
||||
}
|
||||
}
|
||||
|
||||
fun removeAccount(pubkey: HexKey) = accounts.remove(pubkey)
|
||||
|
||||
fun loadAccount(accountSettings: AccountSettings): Account =
|
||||
loadAccount(
|
||||
signer =
|
||||
if (accountSettings.keyPair.privKey != null) {
|
||||
NostrSignerInternal(accountSettings.keyPair)
|
||||
} else {
|
||||
when (val packageName = accountSettings.externalSignerPackageName) {
|
||||
null -> NostrSignerInternal(accountSettings.keyPair)
|
||||
else ->
|
||||
NostrSignerExternal(
|
||||
pubKey = accountSettings.keyPair.pubKey.toHexKey(),
|
||||
packageName = packageName,
|
||||
contentResolver = contentResolver,
|
||||
)
|
||||
}
|
||||
},
|
||||
accountSettings = accountSettings,
|
||||
)
|
||||
|
||||
fun loadAccount(
|
||||
signer: NostrSigner,
|
||||
accountSettings: AccountSettings,
|
||||
@@ -57,7 +96,14 @@ class AccountCacheState(
|
||||
nwcFilterAssembler = nwcFilterAssembler,
|
||||
cache = cache,
|
||||
client = client,
|
||||
scope = scope,
|
||||
scope =
|
||||
CoroutineScope(
|
||||
Dispatchers.Default +
|
||||
SupervisorJob() +
|
||||
CoroutineExceptionHandler { _, throwable ->
|
||||
Log.e("AccountCacheState", "Account ${signer.pubKey} caught exception: ${throwable.message}", throwable)
|
||||
},
|
||||
),
|
||||
).also {
|
||||
accounts.put(signer.pubKey, it)
|
||||
}
|
||||
|
@@ -71,7 +71,7 @@ class EventNotificationConsumer(
|
||||
LocalPreferences.loadAccountConfigFromEncryptedStorage(it.npub)?.let { acc ->
|
||||
Log.d(TAG, "New Notification Testing if for ${it.npub}")
|
||||
try {
|
||||
val account = Amethyst.instance.loadAccount(acc)
|
||||
val account = Amethyst.instance.accountsCache.loadAccount(acc)
|
||||
consumeIfMatchesAccount(event, account)
|
||||
matchAccount = true
|
||||
} catch (e: Exception) {
|
||||
@@ -128,7 +128,7 @@ class EventNotificationConsumer(
|
||||
LocalPreferences.loadAccountConfigFromEncryptedStorage(it.npub)?.let { accountSettings ->
|
||||
Log.d(TAG, "New Notification Testing if for ${it.npub}")
|
||||
try {
|
||||
val account = Amethyst.instance.loadAccount(accountSettings)
|
||||
val account = Amethyst.instance.accountsCache.loadAccount(accountSettings)
|
||||
consumeNotificationEvent(event, account)
|
||||
matchAccount = true
|
||||
} catch (e: Exception) {
|
||||
|
@@ -59,7 +59,7 @@ class RegisterAccounts(
|
||||
}
|
||||
|
||||
return mapNotNullAsync(remainingTos) { info ->
|
||||
val account = Amethyst.instance.loadAccount(info.accountSettings)
|
||||
val account = Amethyst.instance.accountsCache.loadAccount(info.accountSettings)
|
||||
RelayAuthEvent.create(info.relays, notificationToken, account.signer)
|
||||
}
|
||||
}
|
||||
|
@@ -185,7 +185,7 @@ class AccountStateViewModel : ViewModel() {
|
||||
route: Route? = null,
|
||||
) = withContext(Dispatchers.Main) {
|
||||
_accountContent.update {
|
||||
AccountState.LoggedIn(Amethyst.instance.loadAccount(accountSettings), route)
|
||||
AccountState.LoggedIn(Amethyst.instance.accountsCache.loadAccount(accountSettings), route)
|
||||
}
|
||||
|
||||
collectorJob?.cancel()
|
||||
@@ -390,12 +390,12 @@ class AccountStateViewModel : ViewModel() {
|
||||
// log off and relogin with the 0 account
|
||||
prepareLogoutOrSwitch()
|
||||
LocalPreferences.deleteAccount(accountInfo)
|
||||
Amethyst.instance.removeAccount(accountInfo.npub.bechToBytes().toHexKey())
|
||||
Amethyst.instance.accountsCache.removeAccount(accountInfo.npub.bechToBytes().toHexKey())
|
||||
loginWithDefaultAccount()
|
||||
} else {
|
||||
// delete without switching logins
|
||||
LocalPreferences.deleteAccount(accountInfo)
|
||||
Amethyst.instance.removeAccount(accountInfo.npub.bechToBytes().toHexKey())
|
||||
Amethyst.instance.accountsCache.removeAccount(accountInfo.npub.bechToBytes().toHexKey())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user