Add account, switch account, and logout flows

This commit is contained in:
maxmoney21m 2023-03-12 02:42:50 +08:00
parent 9561261bf4
commit b40bde10a0
3 changed files with 116 additions and 35 deletions

View File

@ -80,18 +80,27 @@ object LocalPreferences {
}
}
fun clearEncryptedStorage(npub: String? = null) {
val encPrefs = encryptedPreferences(npub)
encPrefs.edit().apply {
encPrefs.all.keys.forEach {
remove(it)
fun clearEncryptedStorage(npub: String) {
val userPrefs = encryptedPreferences(npub)
userPrefs.edit().clear().apply()
removeAccount(npub)
if (savedAccounts.isEmpty()) {
val appPrefs = encryptedPreferences()
appPrefs.edit().clear().apply()
} else if (currentAccount == npub) {
currentAccount = savedAccounts.elementAt(0)
}
// encPrefs.edit().apply {
// encPrefs.all.keys.forEach {
// remove(it)
// }
// encryptedPreferences.all.keys.filter {
// it.startsWith(npub)
// }.forEach {
// remove(it)
// }
}.apply()
// }.apply()
}
fun findAllLocalAccounts(): List<AccountInfo> {
@ -132,6 +141,11 @@ object LocalPreferences {
}.apply()
}
fun login(account: Account) {
setCurrentAccount(account)
saveToEncryptedStorage(account)
}
fun loadFromEncryptedStorage(): Account? {
encryptedPreferences(currentAccount).apply {
val pubKey = getString(PrefKeys.NOSTR_PUBKEY, null) ?: return null

View File

@ -1,6 +1,7 @@
package com.vitorpamplona.amethyst.ui.navigation
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
@ -12,8 +13,12 @@ import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.text.ClickableText
import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material.Button
import androidx.compose.material.ButtonDefaults
import androidx.compose.material.ExperimentalMaterialApi
import androidx.compose.material.Icon
import androidx.compose.material.IconButton
@ -48,13 +53,18 @@ import androidx.compose.ui.platform.LocalAutofill
import androidx.compose.ui.platform.LocalAutofillTree
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.AnnotatedString
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.input.ImeAction
import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.text.input.PasswordVisualTransformation
import androidx.compose.ui.text.input.TextFieldValue
import androidx.compose.ui.text.input.VisualTransformation
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextDecoration
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.compose.ui.window.Dialog
import androidx.compose.ui.window.DialogProperties
import com.vitorpamplona.amethyst.LocalPreferences
@ -103,6 +113,11 @@ fun AccountSwitchBottomSheet(
.fillMaxWidth()
.padding(32.dp, 16.dp),
verticalAlignment = Alignment.CenterVertically
) {
Row(
modifier = Modifier.clickable {
accountStateViewModel.login(acc.npub)
}
) {
AsyncImageProxy(
model = ResizeImage(acc.profilePicture, 64.dp),
@ -127,7 +142,11 @@ fun AccountSwitchBottomSheet(
Text("")
}
Spacer(modifier = Modifier.weight(1f))
IconButton(onClick = { /*TODO*/ }) {
}
IconButton(
onClick = { accountStateViewModel.logOff(acc.npub) }
) {
Icon(imageVector = Icons.Default.Logout, "Logout")
}
}
@ -229,6 +248,49 @@ fun AccountSwitchBottomSheet(
style = MaterialTheme.typography.caption
)
}
Spacer(modifier = Modifier.height(16.dp))
Button(
onClick = {
if (key.value.text.isBlank()) {
errorMessage = context.getString(R.string.key_is_required)
}
try {
accountStateViewModel.login(key.value.text)
} catch (e: Exception) {
errorMessage = context.getString(R.string.invalid_key)
}
},
shape = RoundedCornerShape(35.dp),
modifier = Modifier
.fillMaxWidth()
.height(50.dp),
colors = ButtonDefaults
.buttonColors(
backgroundColor = MaterialTheme.colors.primary
)
) {
Text(text = stringResource(R.string.login))
}
Spacer(modifier = Modifier.height(16.dp))
ClickableText(
text = AnnotatedString(stringResource(R.string.generate_a_new_key)),
modifier = Modifier
.padding(20.dp)
.fillMaxWidth(),
onClick = {
accountStateViewModel.newKey()
},
style = TextStyle(
fontSize = 14.sp,
textDecoration = TextDecoration.Underline,
color = MaterialTheme.colors.primary,
textAlign = TextAlign.Center
)
)
}
}
}

View File

@ -26,10 +26,14 @@ class AccountStateViewModel() : ViewModel() {
// Keeps it in the the UI thread to void blinking the login page.
// viewModelScope.launch(Dispatchers.IO) {
tryLoginExistingAccount()
// }
}
private fun tryLoginExistingAccount() {
LocalPreferences.loadFromEncryptedStorage()?.let {
login(it)
}
// }
}
fun login(key: String) {
@ -47,18 +51,18 @@ class AccountStateViewModel() : ViewModel() {
Account(Persona(Hex.decode(key)))
}
LocalPreferences.saveToEncryptedStorage(account)
LocalPreferences.login(account)
login(account)
}
fun newKey() {
val account = Account(Persona())
LocalPreferences.saveToEncryptedStorage(account)
LocalPreferences.login(account)
login(account)
}
fun login(account: Account) {
LocalPreferences.setCurrentAccount(account)
LocalPreferences.login(account)
if (account.loggedIn.privKey != null) {
_accountContent.update { AccountState.LoggedIn(account) }
@ -82,7 +86,7 @@ class AccountStateViewModel() : ViewModel() {
}
}
fun logOff() {
fun logOff(npub: String) {
val state = accountContent.value
when (state) {
@ -101,6 +105,7 @@ class AccountStateViewModel() : ViewModel() {
_accountContent.update { AccountState.LoggedOff }
LocalPreferences.clearEncryptedStorage()
LocalPreferences.clearEncryptedStorage(npub)
tryLoginExistingAccount()
}
}