Faster logout processing without closing the account switcher dialog.
This commit is contained in:
@@ -57,6 +57,7 @@ import kotlinx.collections.immutable.toImmutableList
|
||||
import kotlinx.coroutines.CancellationException
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.filter
|
||||
import kotlinx.coroutines.sync.Mutex
|
||||
import kotlinx.coroutines.sync.withLock
|
||||
import kotlinx.coroutines.withContext
|
||||
@@ -74,7 +75,7 @@ data class AccountInfo(
|
||||
val npub: String,
|
||||
val hasPrivKey: Boolean,
|
||||
val loggedInWithExternalSigner: Boolean,
|
||||
val isTransient: Boolean = false,
|
||||
val isTransient: Boolean,
|
||||
)
|
||||
|
||||
private object PrefKeys {
|
||||
@@ -126,7 +127,7 @@ object LocalPreferences {
|
||||
private const val COMMA = ","
|
||||
|
||||
private var currentAccount: String? = null
|
||||
private var savedAccounts: List<AccountInfo>? = null
|
||||
private var savedAccounts: MutableStateFlow<List<AccountInfo>?> = MutableStateFlow(null)
|
||||
private var cachedAccounts: MutableMap<String, AccountSettings?> = mutableMapOf()
|
||||
|
||||
suspend fun currentAccount(): String? {
|
||||
@@ -156,7 +157,7 @@ object LocalPreferences {
|
||||
}
|
||||
|
||||
private suspend fun savedAccounts(): List<AccountInfo> {
|
||||
if (savedAccounts == null) {
|
||||
if (savedAccounts.value == null) {
|
||||
withContext(Dispatchers.IO) {
|
||||
with(encryptedPreferences()) {
|
||||
val newSystemOfAccounts =
|
||||
@@ -165,7 +166,7 @@ object LocalPreferences {
|
||||
}
|
||||
|
||||
if (!newSystemOfAccounts.isNullOrEmpty()) {
|
||||
savedAccounts = newSystemOfAccounts
|
||||
savedAccounts.emit(newSystemOfAccounts)
|
||||
} else {
|
||||
val oldAccounts = getString(PrefKeys.SAVED_ACCOUNTS, null)?.split(COMMA) ?: listOf()
|
||||
|
||||
@@ -174,27 +175,28 @@ object LocalPreferences {
|
||||
AccountInfo(
|
||||
npub,
|
||||
encryptedPreferences(npub).getBoolean(PrefKeys.LOGIN_WITH_EXTERNAL_SIGNER, false),
|
||||
(encryptedPreferences(npub).getString(PrefKeys.NOSTR_PRIVKEY, "") ?: "")
|
||||
.isNotBlank(),
|
||||
(encryptedPreferences(npub).getString(PrefKeys.NOSTR_PRIVKEY, "") ?: "").isNotBlank(),
|
||||
false,
|
||||
)
|
||||
}
|
||||
|
||||
savedAccounts = migrated
|
||||
savedAccounts.emit(migrated)
|
||||
|
||||
edit().apply { putString(PrefKeys.ALL_ACCOUNT_INFO, Event.mapper.writeValueAsString(savedAccounts)) }.apply()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return savedAccounts!!
|
||||
// it's always not null when it gets here.
|
||||
return savedAccounts.value!!
|
||||
}
|
||||
|
||||
fun cachedAccounts() = savedAccounts
|
||||
fun accountsFlow() = savedAccounts
|
||||
|
||||
private suspend fun updateSavedAccounts(accounts: List<AccountInfo>) =
|
||||
withContext(Dispatchers.IO) {
|
||||
if (savedAccounts != accounts) {
|
||||
savedAccounts = accounts
|
||||
savedAccounts.emit(accounts)
|
||||
|
||||
encryptedPreferences()
|
||||
.edit()
|
||||
@@ -269,7 +271,7 @@ object LocalPreferences {
|
||||
*/
|
||||
@SuppressLint("ApplySharedPref")
|
||||
suspend fun updatePrefsForLogout(accountInfo: AccountInfo) {
|
||||
Log.d("LocalPreferences", "Saving to encrypted storage updatePrefsForLogout")
|
||||
Log.d("LocalPreferences", "Saving to encrypted storage updatePrefsForLogout ${accountInfo.npub}")
|
||||
withContext(Dispatchers.IO) {
|
||||
encryptedPreferences(accountInfo.npub).edit().clear().commit()
|
||||
removeAccount(accountInfo)
|
||||
|
||||
+13
-11
@@ -47,7 +47,6 @@ import androidx.compose.runtime.derivedStateOf
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.livedata.observeAsState
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.produceState
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
@@ -55,6 +54,7 @@ import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import com.vitorpamplona.amethyst.AccountInfo
|
||||
import com.vitorpamplona.amethyst.LocalPreferences
|
||||
import com.vitorpamplona.amethyst.R
|
||||
@@ -73,6 +73,7 @@ import com.vitorpamplona.amethyst.ui.theme.Size10dp
|
||||
import com.vitorpamplona.amethyst.ui.theme.Size55dp
|
||||
import com.vitorpamplona.quartz.encoders.decodePublicKeyAsHexOrNull
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.forEach
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@@ -81,14 +82,6 @@ fun AccountSwitchBottomSheet(
|
||||
accountViewModel: AccountViewModel,
|
||||
accountStateViewModel: AccountStateViewModel,
|
||||
) {
|
||||
@Suppress("ProduceStateDoesNotAssignValue")
|
||||
val accounts by
|
||||
produceState(initialValue = LocalPreferences.cachedAccounts()) {
|
||||
if (value == null) {
|
||||
value = LocalPreferences.allSavedAccounts()
|
||||
}
|
||||
}
|
||||
|
||||
var popupExpanded by remember { mutableStateOf(false) }
|
||||
val scrollState = rememberScrollState()
|
||||
|
||||
@@ -103,7 +96,7 @@ fun AccountSwitchBottomSheet(
|
||||
) {
|
||||
Text(stringRes(R.string.account_switch_select_account), fontWeight = FontWeight.Bold)
|
||||
}
|
||||
accounts?.forEach { acc -> DisplayAccount(acc, accountViewModel, accountStateViewModel) }
|
||||
DisplayAllAccounts(accountViewModel, accountStateViewModel)
|
||||
Row(
|
||||
modifier =
|
||||
Modifier
|
||||
@@ -123,13 +116,22 @@ fun AccountSwitchBottomSheet(
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun DisplayAllAccounts(
|
||||
accountViewModel: AccountViewModel,
|
||||
accountStateViewModel: AccountStateViewModel,
|
||||
) {
|
||||
val accounts by LocalPreferences.accountsFlow().collectAsStateWithLifecycle()
|
||||
accounts?.forEach { acc -> DisplayAccount(acc, accountViewModel, accountStateViewModel) }
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun DisplayAccount(
|
||||
acc: AccountInfo,
|
||||
accountViewModel: AccountViewModel,
|
||||
accountStateViewModel: AccountStateViewModel,
|
||||
) {
|
||||
var baseUser by remember {
|
||||
var baseUser by remember(acc) {
|
||||
mutableStateOf<User?>(
|
||||
decodePublicKeyAsHexOrNull(acc.npub)?.let {
|
||||
LocalCache.getUserIfExists(it)
|
||||
|
||||
+23
-3
@@ -27,6 +27,7 @@ import androidx.lifecycle.viewModelScope
|
||||
import com.vitorpamplona.amethyst.AccountInfo
|
||||
import com.vitorpamplona.amethyst.Amethyst
|
||||
import com.vitorpamplona.amethyst.LocalPreferences
|
||||
import com.vitorpamplona.amethyst.LocalPreferences.currentAccount
|
||||
import com.vitorpamplona.amethyst.model.AccountSettings
|
||||
import com.vitorpamplona.amethyst.model.DefaultChannels
|
||||
import com.vitorpamplona.amethyst.model.DefaultDMRelayList
|
||||
@@ -321,11 +322,30 @@ class AccountStateViewModel : ViewModel() {
|
||||
}
|
||||
}
|
||||
|
||||
fun currentAccount() =
|
||||
when (val state = _accountContent.value) {
|
||||
is AccountState.LoggedIn ->
|
||||
state.accountSettings.keyPair.pubKey
|
||||
.toNpub()
|
||||
|
||||
is AccountState.LoggedInViewOnly ->
|
||||
state.accountSettings.keyPair.pubKey
|
||||
.toNpub()
|
||||
|
||||
else -> null
|
||||
}
|
||||
|
||||
fun logOff(accountInfo: AccountInfo) {
|
||||
viewModelScope.launch(Dispatchers.IO) {
|
||||
prepareLogoutOrSwitch()
|
||||
LocalPreferences.updatePrefsForLogout(accountInfo)
|
||||
tryLoginExistingAccount()
|
||||
if (accountInfo.npub == currentAccount()) {
|
||||
// log off and relogin with the 0 account
|
||||
prepareLogoutOrSwitch()
|
||||
LocalPreferences.updatePrefsForLogout(accountInfo)
|
||||
tryLoginExistingAccount()
|
||||
} else {
|
||||
// delete without login off
|
||||
LocalPreferences.updatePrefsForLogout(accountInfo)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user