From 1e7e08d5d8f80a53610aa6a6bf03f197148788fd Mon Sep 17 00:00:00 2001 From: greenart7c3 Date: Fri, 29 Nov 2024 07:23:50 -0300 Subject: [PATCH] Fix login screen size when using multiple accounts, fix logout --- .../nostrsigner/LocalPreferences.kt | 7 +- .../nostrsigner/ui/AccountStateViewModel.kt | 11 +- .../greenart7c3/nostrsigner/ui/LoginScreen.kt | 8 ++ .../greenart7c3/nostrsigner/ui/MainScreen.kt | 129 ++++++++++++------ .../ui/actions/AccountsBottomSheet.kt | 76 ++--------- .../nostrsigner/ui/navigation/Route.kt | 7 + 6 files changed, 123 insertions(+), 115 deletions(-) diff --git a/app/src/main/java/com/greenart7c3/nostrsigner/LocalPreferences.kt b/app/src/main/java/com/greenart7c3/nostrsigner/LocalPreferences.kt index b0203a15..d1aea926 100644 --- a/app/src/main/java/com/greenart7c3/nostrsigner/LocalPreferences.kt +++ b/app/src/main/java/com/greenart7c3/nostrsigner/LocalPreferences.kt @@ -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) { diff --git a/app/src/main/java/com/greenart7c3/nostrsigner/ui/AccountStateViewModel.kt b/app/src/main/java/com/greenart7c3/nostrsigner/ui/AccountStateViewModel.kt index 94940cee..9d36a395 100644 --- a/app/src/main/java/com/greenart7c3/nostrsigner/ui/AccountStateViewModel.kt +++ b/app/src/main/java/com/greenart7c3/nostrsigner/ui/AccountStateViewModel.kt @@ -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( diff --git a/app/src/main/java/com/greenart7c3/nostrsigner/ui/LoginScreen.kt b/app/src/main/java/com/greenart7c3/nostrsigner/ui/LoginScreen.kt index 4a3166ff..0b8bf8b4 100644 --- a/app/src/main/java/com/greenart7c3/nostrsigner/ui/LoginScreen.kt +++ b/app/src/main/java/com/greenart7c3/nostrsigner/ui/LoginScreen.kt @@ -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), ) diff --git a/app/src/main/java/com/greenart7c3/nostrsigner/ui/MainScreen.kt b/app/src/main/java/com/greenart7c3/nostrsigner/ui/MainScreen.kt index f5583322..e5d42e34 100644 --- a/app/src/main/java/com/greenart7c3/nostrsigner/ui/MainScreen.kt +++ b/app/src/main/java/com/greenart7c3/nostrsigner/ui/MainScreen.kt @@ -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 = { diff --git a/app/src/main/java/com/greenart7c3/nostrsigner/ui/actions/AccountsBottomSheet.kt b/app/src/main/java/com/greenart7c3/nostrsigner/ui/actions/AccountsBottomSheet.kt index 887f4076..53b9c7ed 100644 --- a/app/src/main/java/com/greenart7c3/nostrsigner/ui/actions/AccountsBottomSheet.kt +++ b/app/src/main/java/com/greenart7c3/nostrsigner/ui/actions/AccountsBottomSheet.kt @@ -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)) + }, + ) } } } diff --git a/app/src/main/java/com/greenart7c3/nostrsigner/ui/navigation/Route.kt b/app/src/main/java/com/greenart7c3/nostrsigner/ui/navigation/Route.kt index 51a71f39..3d4051fd 100644 --- a/app/src/main/java/com/greenart7c3/nostrsigner/ui/navigation/Route.kt +++ b/app/src/main/java/com/greenart7c3/nostrsigner/ui/navigation/Route.kt @@ -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",