mirror of
https://github.com/vitorpamplona/amethyst.git
synced 2025-04-09 04:18:11 +02:00
If already logged in and an NFC tag shows up with ncryptsec, logs in as a transient account
This commit is contained in:
parent
2457429470
commit
9ee28e28b8
@ -26,7 +26,6 @@ import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.width
|
||||
@ -40,11 +39,8 @@ import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Surface
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TextButton
|
||||
import androidx.compose.material3.TopAppBar
|
||||
import androidx.compose.material3.TopAppBarDefaults
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.derivedStateOf
|
||||
@ -59,8 +55,6 @@ 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.compose.ui.window.Dialog
|
||||
import androidx.compose.ui.window.DialogProperties
|
||||
import com.vitorpamplona.amethyst.AccountInfo
|
||||
import com.vitorpamplona.amethyst.LocalPreferences
|
||||
import com.vitorpamplona.amethyst.R
|
||||
@ -69,11 +63,10 @@ import com.vitorpamplona.amethyst.model.LocalCache
|
||||
import com.vitorpamplona.amethyst.model.User
|
||||
import com.vitorpamplona.amethyst.ui.components.CreateTextWithEmoji
|
||||
import com.vitorpamplona.amethyst.ui.components.RobohashFallbackAsyncImage
|
||||
import com.vitorpamplona.amethyst.ui.note.ArrowBackIcon
|
||||
import com.vitorpamplona.amethyst.ui.note.toShortenHex
|
||||
import com.vitorpamplona.amethyst.ui.screen.AccountStateViewModel
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedOff.LoginOrSignupScreen
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedOff.AddAccountDialog
|
||||
import com.vitorpamplona.amethyst.ui.stringRes
|
||||
import com.vitorpamplona.amethyst.ui.theme.AccountPictureModifier
|
||||
import com.vitorpamplona.amethyst.ui.theme.Size10dp
|
||||
@ -125,28 +118,7 @@ fun AccountSwitchBottomSheet(
|
||||
}
|
||||
|
||||
if (popupExpanded) {
|
||||
Dialog(
|
||||
onDismissRequest = { popupExpanded = false },
|
||||
properties = DialogProperties(usePlatformDefaultWidth = false),
|
||||
) {
|
||||
Surface(modifier = Modifier.fillMaxSize()) {
|
||||
Box {
|
||||
LoginOrSignupScreen(accountStateViewModel, isFirstLogin = false)
|
||||
TopAppBar(
|
||||
title = {
|
||||
Text(text = stringRes(R.string.account_switch_add_account_dialog_title))
|
||||
},
|
||||
navigationIcon = {
|
||||
IconButton(onClick = { popupExpanded = false }) { ArrowBackIcon() }
|
||||
},
|
||||
colors =
|
||||
TopAppBarDefaults.topAppBarColors(
|
||||
containerColor = MaterialTheme.colorScheme.surface,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
AddAccountDialog(null, accountStateViewModel) { popupExpanded = false }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -41,7 +41,6 @@ import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.core.util.Consumer
|
||||
import androidx.navigation.NavBackStackEntry
|
||||
import androidx.navigation.NavHostController
|
||||
import androidx.navigation.compose.NavHost
|
||||
import androidx.navigation.compose.composable
|
||||
import com.vitorpamplona.amethyst.R
|
||||
@ -72,7 +71,9 @@ import com.vitorpamplona.amethyst.ui.screen.loggedIn.settings.SecurityFiltersScr
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.settings.SettingsScreen
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.threadview.ThreadScreen
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.video.VideoScreen
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedOff.AddAccountDialog
|
||||
import com.vitorpamplona.amethyst.ui.uriToRoute
|
||||
import com.vitorpamplona.quartz.encoders.Nip19Bech32
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
import java.net.URLDecoder
|
||||
@ -284,7 +285,7 @@ fun AppNavigation(
|
||||
}
|
||||
}
|
||||
|
||||
NavigateIfIntentRequested(nav.controller, accountViewModel)
|
||||
NavigateIfIntentRequested(nav, accountViewModel, accountStateViewModel)
|
||||
|
||||
DisplayErrorMessages(accountViewModel)
|
||||
DisplayNotifyMessages(accountViewModel, nav)
|
||||
@ -292,10 +293,12 @@ fun AppNavigation(
|
||||
|
||||
@Composable
|
||||
private fun NavigateIfIntentRequested(
|
||||
navController: NavHostController,
|
||||
nav: Nav,
|
||||
accountViewModel: AccountViewModel,
|
||||
accountStateViewModel: AccountStateViewModel,
|
||||
) {
|
||||
val activity = LocalContext.current.getActivity()
|
||||
var newAccount by remember { mutableStateOf<String?>(null) }
|
||||
|
||||
var currentIntentNextPage by remember {
|
||||
mutableStateOf(
|
||||
@ -314,15 +317,19 @@ private fun NavigateIfIntentRequested(
|
||||
LaunchedEffect(intentNextPage) {
|
||||
if (actionableNextPage != null) {
|
||||
actionableNextPage?.let {
|
||||
val currentRoute = getRouteWithArguments(navController)
|
||||
val currentRoute = getRouteWithArguments(nav.controller)
|
||||
if (!isSameRoute(currentRoute, it)) {
|
||||
navController.navigate(it) {
|
||||
popUpTo(Route.Home.route)
|
||||
launchSingleTop = true
|
||||
}
|
||||
nav.newStack(it)
|
||||
}
|
||||
actionableNextPage = null
|
||||
}
|
||||
} else if (intentNextPage.contains("ncryptsec1")) {
|
||||
// login functions
|
||||
Nip19Bech32.tryParseAndClean(intentNextPage)?.let {
|
||||
newAccount = it
|
||||
}
|
||||
|
||||
actionableNextPage = null
|
||||
} else {
|
||||
accountViewModel.toast(
|
||||
R.string.invalid_nip19_uri,
|
||||
@ -342,15 +349,18 @@ private fun NavigateIfIntentRequested(
|
||||
Consumer<Intent> { intent ->
|
||||
val uri = intent?.data?.toString()
|
||||
if (!uri.isNullOrBlank()) {
|
||||
// navigation functions
|
||||
val newPage = uriToRoute(uri)
|
||||
|
||||
if (newPage != null) {
|
||||
val currentRoute = getRouteWithArguments(navController)
|
||||
val currentRoute = getRouteWithArguments(nav.controller)
|
||||
if (!isSameRoute(currentRoute, newPage)) {
|
||||
navController.navigate(newPage) {
|
||||
popUpTo(Route.Home.route)
|
||||
launchSingleTop = true
|
||||
}
|
||||
nav.newStack(newPage)
|
||||
}
|
||||
} else if (uri.contains("ncryptsec")) {
|
||||
// login functions
|
||||
Nip19Bech32.tryParseAndClean(uri)?.let {
|
||||
newAccount = it
|
||||
}
|
||||
} else {
|
||||
scope.launch {
|
||||
@ -367,6 +377,10 @@ private fun NavigateIfIntentRequested(
|
||||
activity.addOnNewIntentListener(consumer)
|
||||
onDispose { activity.removeOnNewIntentListener(consumer) }
|
||||
}
|
||||
|
||||
if (newAccount != null) {
|
||||
AddAccountDialog(newAccount, accountStateViewModel) { newAccount = null }
|
||||
}
|
||||
}
|
||||
|
||||
fun Context.getActivity(): MainActivity {
|
||||
|
@ -88,7 +88,7 @@ fun AccountScreen(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
color = MaterialTheme.colorScheme.background,
|
||||
) {
|
||||
LoginOrSignupScreen(accountStateViewModel, isFirstLogin = true)
|
||||
LoginOrSignupScreen(null, accountStateViewModel, isFirstLogin = true)
|
||||
}
|
||||
}
|
||||
is AccountState.LoggedIn -> {
|
||||
|
@ -0,0 +1,70 @@
|
||||
/**
|
||||
* Copyright (c) 2024 Vitor Pamplona
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.amethyst.ui.screen.loggedOff
|
||||
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Surface
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TopAppBar
|
||||
import androidx.compose.material3.TopAppBarDefaults
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.window.Dialog
|
||||
import androidx.compose.ui.window.DialogProperties
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.ui.note.ArrowBackIcon
|
||||
import com.vitorpamplona.amethyst.ui.screen.AccountStateViewModel
|
||||
import com.vitorpamplona.amethyst.ui.stringRes
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun AddAccountDialog(
|
||||
newAccountKey: String?,
|
||||
accountStateViewModel: AccountStateViewModel,
|
||||
onClose: () -> Unit,
|
||||
) {
|
||||
Dialog(
|
||||
onDismissRequest = onClose,
|
||||
properties = DialogProperties(usePlatformDefaultWidth = false),
|
||||
) {
|
||||
Surface(modifier = Modifier.fillMaxSize()) {
|
||||
Box {
|
||||
LoginOrSignupScreen(newAccountKey, accountStateViewModel, isFirstLogin = false)
|
||||
TopAppBar(
|
||||
title = {
|
||||
Text(text = stringRes(R.string.account_switch_add_account_dialog_title))
|
||||
},
|
||||
navigationIcon = {
|
||||
IconButton(onClick = onClose) { ArrowBackIcon() }
|
||||
},
|
||||
colors =
|
||||
TopAppBarDefaults.topAppBarColors(
|
||||
containerColor = MaterialTheme.colorScheme.surface,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -30,7 +30,8 @@ import com.vitorpamplona.amethyst.ui.screen.AccountStateViewModel
|
||||
|
||||
@Composable
|
||||
fun LoginOrSignupScreen(
|
||||
accountViewModel: AccountStateViewModel,
|
||||
newAccountKey: String?,
|
||||
accountStateViewModel: AccountStateViewModel,
|
||||
isFirstLogin: Boolean,
|
||||
) {
|
||||
var wantsNewUser by remember {
|
||||
@ -39,11 +40,11 @@ fun LoginOrSignupScreen(
|
||||
|
||||
Crossfade(wantsNewUser, label = "LoginOrSignupScreen") {
|
||||
if (it) {
|
||||
SignUpPage(accountStateViewModel = accountViewModel) {
|
||||
SignUpPage(accountStateViewModel) {
|
||||
wantsNewUser = false
|
||||
}
|
||||
} else {
|
||||
LoginPage(accountStateViewModel = accountViewModel, isFirstLogin = isFirstLogin) {
|
||||
LoginPage(accountStateViewModel, isFirstLogin, newAccountKey) {
|
||||
wantsNewUser = true
|
||||
}
|
||||
}
|
||||
|
@ -129,9 +129,10 @@ fun LoginPage() {
|
||||
fun LoginPage(
|
||||
accountStateViewModel: AccountStateViewModel,
|
||||
isFirstLogin: Boolean,
|
||||
newAccountKey: String? = null,
|
||||
onWantsToLogin: () -> Unit,
|
||||
) {
|
||||
val key = remember { mutableStateOf(TextFieldValue("")) }
|
||||
val key = remember { mutableStateOf(TextFieldValue(newAccountKey ?: "")) }
|
||||
var errorMessage by remember { mutableStateOf("") }
|
||||
val acceptedTerms = remember { mutableStateOf(!isFirstLogin) }
|
||||
var termsAcceptanceIsRequired by remember { mutableStateOf("") }
|
||||
|
Loading…
x
Reference in New Issue
Block a user