Fix login screen size when using multiple accounts, fix logout

This commit is contained in:
greenart7c3
2024-11-29 07:23:50 -03:00
parent fcafeb5b56
commit 1e7e08d5d8
6 changed files with 123 additions and 115 deletions
@@ -289,7 +289,7 @@ object LocalPreferences {
* condition and the file will probably not be deleted
*/
@SuppressLint("ApplySharedPref")
fun updatePrefsForLogout(npub: String, context: Context) {
fun updatePrefsForLogout(npub: String, context: Context): Boolean {
accountCache.remove(npub)
val userPrefs = encryptedPreferences(context, npub)
userPrefs.edit().clear().commit()
@@ -298,10 +298,13 @@ object LocalPreferences {
if (savedAccounts(context).isEmpty()) {
val appPrefs = encryptedPreferences(context)
appPrefs.edit().clear().apply()
appPrefs.edit().clear().commit()
return true
} else if (currentAccount(context) == npub) {
updateCurrentAccount(context, savedAccounts(context).elementAt(0))
return false
}
return false
}
fun updatePrefsForLogin(context: Context, account: Account) {
@@ -82,11 +82,16 @@ class AccountStateViewModel(npub: String?) : ViewModel() {
private fun tryLoginExistingAccount(
route: String?,
npub: String?,
forceLogout: Boolean = false,
) {
var currentUser = npub ?: LocalPreferences.currentAccount(NostrSigner.getInstance())
if (currentUser != null && !LocalPreferences.containsAccount(NostrSigner.getInstance(), currentUser)) {
val allAccounts = LocalPreferences.allSavedAccounts(NostrSigner.getInstance())
if (currentUser != null && !LocalPreferences.containsAccount(NostrSigner.getInstance(), currentUser) && allAccounts.any { it.npub == currentUser }) {
currentUser = LocalPreferences.currentAccount(NostrSigner.getInstance())
}
if (forceLogout) {
currentUser = null
}
LocalPreferences.loadFromEncryptedStorage(NostrSigner.getInstance(), currentUser)?.let {
startUI(it, route)
}
@@ -111,8 +116,8 @@ class AccountStateViewModel(npub: String?) : ViewModel() {
fun logOff(npub: String) {
prepareLogoutOrSwitch()
LocalPreferences.updatePrefsForLogout(npub, NostrSigner.getInstance())
tryLoginExistingAccount(null, null)
val shouldLogout = LocalPreferences.updatePrefsForLogout(npub, NostrSigner.getInstance())
tryLoginExistingAccount(null, null, forceLogout = shouldLogout)
}
fun switchUser(
@@ -238,6 +238,7 @@ fun MainLoginPage(
scope = scope,
navController = navController,
storageHelper = storageHelper,
onFinish = {},
)
},
)
@@ -248,6 +249,7 @@ fun MainLoginPage(
LoginPage(
accountViewModel = accountViewModel,
navController = navController,
onFinish = {},
)
},
)
@@ -261,6 +263,7 @@ fun SignUpPage(
scope: CoroutineScope,
navController: NavController,
storageHelper: SimpleStorageHelper,
onFinish: () -> Unit,
) {
var loading by remember { mutableStateOf(false) }
val configuration = LocalConfiguration.current
@@ -785,6 +788,8 @@ fun SignUpPage(
seedWords = seedWords,
name = nickname.text,
)
onFinish()
},
text = stringResource(R.string.finish),
)
@@ -801,6 +806,7 @@ fun SignUpPage(
fun LoginPage(
accountViewModel: AccountStateViewModel,
navController: NavController,
onFinish: () -> Unit,
) {
val configuration = LocalConfiguration.current
val screenWidthDp = configuration.screenWidthDp.dp
@@ -1261,6 +1267,8 @@ fun LoginPage(
signPolicy = selectedOption,
proxyPort = proxyPort.text.toInt(),
)
onFinish()
},
text = stringResource(R.string.finish),
)
@@ -557,7 +557,6 @@ fun MainScreen(
sheetState = sheetState,
account = account,
accountStateViewModel = accountStateViewModel,
storageHelper = storageHelper,
navController = navController,
onClose = {
scope.launch {
@@ -570,53 +569,55 @@ fun MainScreen(
Scaffold(
topBar = {
CenterAlignedTopAppBar(
title = {
var title by remember { mutableStateOf(routes.find { it.route.startsWith(destinationRoute) }?.title ?: "") }
LaunchedEffect(destinationRoute) {
if (destinationRoute.startsWith("Permission/") || destinationRoute.startsWith("Activity/") || destinationRoute.startsWith("RelayLogScreen/")) {
launch(Dispatchers.IO) {
navBackStackEntry?.arguments?.getString("packageName")?.let { packageName ->
val application = database.applicationDao().getByKey(packageName)?.application
title = if (destinationRoute.startsWith("Activity/")) {
"${application?.name?.ifBlank { application.key.toShortenHex() } ?: packageName} - ${routes.find { it.route.startsWith(destinationRoute) }?.title}"
} else {
application?.name?.ifBlank { application.key.toShortenHex() } ?: packageName
if (destinationRoute != "login" && destinationRoute != "create" && destinationRoute != "loginPage") {
CenterAlignedTopAppBar(
title = {
var title by remember { mutableStateOf(routes.find { it.route.startsWith(destinationRoute) }?.title ?: "") }
LaunchedEffect(destinationRoute) {
if (destinationRoute.startsWith("Permission/") || destinationRoute.startsWith("Activity/") || destinationRoute.startsWith("RelayLogScreen/")) {
launch(Dispatchers.IO) {
navBackStackEntry?.arguments?.getString("packageName")?.let { packageName ->
val application = database.applicationDao().getByKey(packageName)?.application
title = if (destinationRoute.startsWith("Activity/")) {
"${application?.name?.ifBlank { application.key.toShortenHex() } ?: packageName} - ${routes.find { it.route.startsWith(destinationRoute) }?.title}"
} else {
application?.name?.ifBlank { application.key.toShortenHex() } ?: packageName
}
}
navBackStackEntry?.arguments?.getString("key")?.let { packageName ->
val application = database.applicationDao().getByKey(packageName)?.application
title = if (destinationRoute.startsWith("Activity/")) {
"${application?.name?.ifBlank { application.key.toShortenHex() } ?: packageName} - ${routes.find { it.route.startsWith(destinationRoute) }?.title}"
} else {
application?.name?.ifBlank { application.key.toShortenHex() } ?: packageName
}
}
navBackStackEntry?.arguments?.getString("url")?.let { url ->
val localUrl = Base64.getDecoder().decode(url).toString(Charsets.UTF_8)
title = localUrl
}
}
navBackStackEntry?.arguments?.getString("key")?.let { packageName ->
val application = database.applicationDao().getByKey(packageName)?.application
title = if (destinationRoute.startsWith("Activity/")) {
"${application?.name?.ifBlank { application.key.toShortenHex() } ?: packageName} - ${routes.find { it.route.startsWith(destinationRoute) }?.title}"
} else {
launch(Dispatchers.IO) {
if (destinationRoute == Route.IncomingRequest.route && intents.isNotEmpty()) {
val application = database.applicationDao().getByKey(intents.first().bunkerRequest?.localKey ?: packageName ?: "")?.application
val titleTemp = application?.name?.ifBlank { application.key.toShortenHex() } ?: packageName ?: ""
title = if (titleTemp.isBlank()) {
routes.find { it.route == destinationRoute }?.title ?: ""
} else {
"$titleTemp - Request"
}
} else {
application?.name?.ifBlank { application.key.toShortenHex() } ?: packageName
title = routes.find { it.route == destinationRoute }?.title ?: ""
}
}
navBackStackEntry?.arguments?.getString("url")?.let { url ->
val localUrl = Base64.getDecoder().decode(url).toString(Charsets.UTF_8)
title = localUrl
}
}
} else {
launch(Dispatchers.IO) {
if (destinationRoute == Route.IncomingRequest.route && intents.isNotEmpty()) {
val application = database.applicationDao().getByKey(intents.first().bunkerRequest?.localKey ?: packageName ?: "")?.application
val titleTemp = application?.name?.ifBlank { application.key.toShortenHex() } ?: packageName ?: ""
title = if (titleTemp.isBlank()) {
routes.find { it.route == destinationRoute }?.title ?: ""
} else {
"$titleTemp - Request"
}
} else {
title = routes.find { it.route == destinationRoute }?.title ?: ""
}
}
}
}
Text(title)
},
)
Text(title)
},
)
}
},
bottomBar = {
if (destinationRoute in items.map { it.route }) {
@@ -681,13 +682,15 @@ fun MainScreen(
}
}
}
} else {
} else if (destinationRoute != "create" && destinationRoute != "loginPage") {
val localBackButtonTitle = routes.find { it.route == navController.previousBackStackEntry?.destination?.route }?.title ?: ""
if (localBackButtonTitle.isNotBlank()) {
BottomAppBar {
IconRow(
center = true,
title = if (destinationRoute.startsWith("NewNsecBunkerCreated/")) {
title = if (destinationRoute.startsWith("login")) {
stringResource(R.string.go_back)
} else if (destinationRoute.startsWith("NewNsecBunkerCreated/")) {
stringResource(R.string.back_to, localBackButtonTitle)
} else {
if (destinationRoute == "NewNsecBunker") {
@@ -753,6 +756,48 @@ fun MainScreen(
enterTransition = { fadeIn(animationSpec = tween(200)) },
exitTransition = { fadeOut(animationSpec = tween(200)) },
) {
composable(
"login",
content = {
MainPage(
scope = scope,
navController = navController,
)
},
)
composable(
"create",
content = {
SignUpPage(
accountViewModel = accountStateViewModel,
scope = scope,
navController = navController,
storageHelper = storageHelper,
onFinish = {
navController.navigate(Route.Applications.route) {
popUpTo(0)
}
},
)
},
)
composable(
"loginPage",
content = {
LoginPage(
accountViewModel = accountStateViewModel,
navController = navController,
onFinish = {
navController.navigate(Route.Applications.route) {
popUpTo(0)
}
},
)
},
)
composable(
Route.IncomingRequest.route,
content = {
@@ -3,28 +3,22 @@ package com.greenart7c3.nostrsigner.ui.actions
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.requiredWidth
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ContentCopy
import androidx.compose.material.icons.filled.Edit
import androidx.compose.material3.BottomAppBar
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.ModalBottomSheet
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Scaffold
import androidx.compose.material3.SheetState
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
@@ -33,38 +27,28 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.platform.LocalClipboardManager
import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.res.vectorResource
import androidx.compose.ui.text.AnnotatedString
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.input.TextFieldValue
import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.Dialog
import androidx.navigation.NavController
import androidx.navigation.compose.currentBackStackEntryAsState
import androidx.navigation.compose.rememberNavController
import com.anggrayudi.storage.SimpleStorageHelper
import com.greenart7c3.nostrsigner.LocalPreferences
import com.greenart7c3.nostrsigner.R
import com.greenart7c3.nostrsigner.models.Account
import com.greenart7c3.nostrsigner.service.toShortenHex
import com.greenart7c3.nostrsigner.ui.AccountStateViewModel
import com.greenart7c3.nostrsigner.ui.MainLoginPage
import com.greenart7c3.nostrsigner.ui.components.ActiveMarker
import com.greenart7c3.nostrsigner.ui.components.CloseButton
import com.greenart7c3.nostrsigner.ui.components.IconRow
import com.greenart7c3.nostrsigner.ui.components.PostButton
import com.greenart7c3.nostrsigner.ui.navigation.Route
import com.vitorpamplona.quartz.encoders.toNpub
import kotlinx.coroutines.launch
@OptIn(ExperimentalMaterial3Api::class)
@Composable
@@ -72,14 +56,10 @@ fun AccountsBottomSheet(
sheetState: SheetState,
account: Account,
accountStateViewModel: AccountStateViewModel,
storageHelper: SimpleStorageHelper,
navController: NavController,
onClose: () -> Unit,
) {
val clipboardManager = LocalClipboardManager.current
val scope = rememberCoroutineScope()
val newNavController = rememberNavController()
val navBackStackEntry by newNavController.currentBackStackEntryAsState()
ModalBottomSheet(
sheetState = sheetState,
@@ -89,7 +69,6 @@ fun AccountsBottomSheet(
) {
val context = LocalContext.current
val accounts = LocalPreferences.allSavedAccounts(context)
var popupExpanded by remember { mutableStateOf(false) }
val scrollState = rememberScrollState()
var showNameDialog by remember { mutableStateOf(false) }
var currentNpub by remember { mutableStateOf("") }
@@ -182,54 +161,15 @@ fun AccountsBottomSheet(
horizontalArrangement = Arrangement.Center,
verticalAlignment = Alignment.CenterVertically,
) {
TextButton(onClick = { popupExpanded = true }) {
Text(stringResource(R.string.add_new_account))
}
}
}
if (popupExpanded) {
val configuration = LocalConfiguration.current
val screenWidthDp = configuration.screenWidthDp.dp
val screenHeightDp = configuration.screenHeightDp.dp
Dialog(
onDismissRequest = { popupExpanded = false },
) {
Scaffold(
bottomBar = {
if (navBackStackEntry?.destination?.route == "login") {
BottomAppBar {
IconRow(
center = true,
title = stringResource(R.string.go_back),
icon = ImageVector.vectorResource(R.drawable.back),
onClick = {
scope.launch {
popupExpanded = false
}
},
tint = MaterialTheme.colorScheme.onSurfaceVariant,
)
}
}
TextButton(
onClick = {
onClose()
navController.navigate(Route.Login.route)
},
modifier = Modifier
.requiredWidth(screenWidthDp)
.height(screenHeightDp),
) {
Box(
modifier = Modifier
.fillMaxSize()
.padding(it),
) {
MainLoginPage(
accountStateViewModel,
storageHelper = storageHelper,
navController = newNavController,
)
}
}
content = {
Text(stringResource(R.string.add_new_account))
},
)
}
}
}
@@ -12,6 +12,13 @@ sealed class Route(
@DrawableRes val icon: Int,
@DrawableRes val selectedIcon: Int,
) {
data object Login : Route(
title = "",
route = "login",
icon = R.drawable.incoming_request,
selectedIcon = R.drawable.incoming_request,
)
data object IncomingRequest : Route(
title = NostrSigner.getInstance().getString(R.string.incoming_request),
route = "IncomingRequest",