refactor(multi-account): in-app overlay dialog for Add Account
Replaced DialogWindow (OS native window with title bar, minimize/maximize) with Dialog composable (in-app overlay with scrim). Matches the ComposeNoteDialog pattern used elsewhere in the desktop app. - Card wrapper with 480dp width, 24dp padding - Title row with 'Add Account' + Close (✕) icon - No OS window chrome — clean in-app feel - Click outside or ✕ to dismiss Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
+65
-81
@@ -20,36 +20,31 @@
|
|||||||
*/
|
*/
|
||||||
package com.vitorpamplona.amethyst.desktop.ui.account
|
package com.vitorpamplona.amethyst.desktop.ui.account
|
||||||
|
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.layout.width
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.automirrored.filled.ArrowBack
|
import androidx.compose.material.icons.filled.Close
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.Card
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.IconButton
|
import androidx.compose.material3.IconButton
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Scaffold
|
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.material3.TopAppBar
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.collectAsState
|
import androidx.compose.runtime.collectAsState
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.rememberCoroutineScope
|
import androidx.compose.runtime.rememberCoroutineScope
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.unit.DpSize
|
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.window.DialogWindow
|
import androidx.compose.ui.window.Dialog
|
||||||
import androidx.compose.ui.window.rememberDialogState
|
|
||||||
import com.vitorpamplona.amethyst.desktop.account.AccountManager
|
import com.vitorpamplona.amethyst.desktop.account.AccountManager
|
||||||
import com.vitorpamplona.amethyst.desktop.ui.auth.LoginCard
|
import com.vitorpamplona.amethyst.desktop.ui.auth.LoginCard
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
|
||||||
@Composable
|
@Composable
|
||||||
fun AddAccountDialog(
|
fun AddAccountDialog(
|
||||||
accountManager: AccountManager,
|
accountManager: AccountManager,
|
||||||
@@ -59,86 +54,75 @@ fun AddAccountDialog(
|
|||||||
val scope = rememberCoroutineScope()
|
val scope = rememberCoroutineScope()
|
||||||
val loginProgress by accountManager.loginProgress.collectAsState()
|
val loginProgress by accountManager.loginProgress.collectAsState()
|
||||||
|
|
||||||
DialogWindow(
|
Dialog(onDismissRequest = onDismiss) {
|
||||||
onCloseRequest = onDismiss,
|
Card(modifier = Modifier.width(480.dp).padding(16.dp)) {
|
||||||
title = "Add Account",
|
Column(modifier = Modifier.padding(24.dp)) {
|
||||||
state = rememberDialogState(size = DpSize(480.dp, 600.dp)),
|
// Header with title + close button
|
||||||
resizable = false,
|
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||||
) {
|
Text(
|
||||||
MaterialTheme {
|
"Add Account",
|
||||||
Scaffold(
|
style = MaterialTheme.typography.headlineSmall,
|
||||||
topBar = {
|
color = MaterialTheme.colorScheme.onSurface,
|
||||||
TopAppBar(
|
modifier = Modifier.weight(1f),
|
||||||
title = { Text("Add Account") },
|
|
||||||
navigationIcon = {
|
|
||||||
IconButton(onClick = onDismiss) {
|
|
||||||
Icon(
|
|
||||||
Icons.AutoMirrored.Filled.ArrowBack,
|
|
||||||
contentDescription = "Back",
|
|
||||||
)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
},
|
IconButton(onClick = onDismiss) {
|
||||||
) { padding ->
|
Icon(
|
||||||
Column(
|
Icons.Default.Close,
|
||||||
modifier = Modifier.fillMaxSize().padding(padding).padding(24.dp),
|
contentDescription = "Close",
|
||||||
horizontalAlignment = Alignment.CenterHorizontally,
|
tint = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||||
verticalArrangement = Arrangement.Center,
|
)
|
||||||
) {
|
}
|
||||||
LoginCard(
|
}
|
||||||
onLogin = { keyInput ->
|
|
||||||
// All steps must be sequential — no fire-and-forget
|
LoginCard(
|
||||||
scope.launch {
|
onLogin = { keyInput ->
|
||||||
withContext(Dispatchers.IO) {
|
scope.launch {
|
||||||
accountManager.ensureCurrentAccountInStorage()
|
withContext(Dispatchers.IO) {
|
||||||
}
|
accountManager.ensureCurrentAccountInStorage()
|
||||||
val result = accountManager.loginWithKey(keyInput)
|
|
||||||
if (result.isSuccess) {
|
|
||||||
withContext(Dispatchers.IO) {
|
|
||||||
accountManager.saveCurrentAccount()
|
|
||||||
}
|
|
||||||
onAccountAdded()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// Return success to dismiss any error in LoginCard
|
val result = accountManager.loginWithKey(keyInput)
|
||||||
Result.success(Unit)
|
if (result.isSuccess) {
|
||||||
},
|
|
||||||
onGenerateNew = {
|
|
||||||
scope.launch {
|
|
||||||
withContext(Dispatchers.IO) {
|
|
||||||
accountManager.ensureCurrentAccountInStorage()
|
|
||||||
}
|
|
||||||
accountManager.generateNewAccount()
|
|
||||||
withContext(Dispatchers.IO) {
|
withContext(Dispatchers.IO) {
|
||||||
accountManager.saveCurrentAccount()
|
accountManager.saveCurrentAccount()
|
||||||
}
|
}
|
||||||
onAccountAdded()
|
onAccountAdded()
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
onLoginBunker = { bunkerUri ->
|
Result.success(Unit)
|
||||||
// ensureCurrentAccountInStorage first, then bunker login
|
},
|
||||||
accountManager.ensureCurrentAccountInStorage()
|
onGenerateNew = {
|
||||||
val result = accountManager.loginWithBunker(bunkerUri)
|
scope.launch {
|
||||||
if (result.isSuccess) {
|
withContext(Dispatchers.IO) {
|
||||||
onAccountAdded()
|
accountManager.ensureCurrentAccountInStorage()
|
||||||
}
|
}
|
||||||
result.map { }
|
accountManager.generateNewAccount()
|
||||||
},
|
withContext(Dispatchers.IO) {
|
||||||
onLoginNostrConnect = { onUriGenerated ->
|
accountManager.saveCurrentAccount()
|
||||||
accountManager.ensureCurrentAccountInStorage()
|
|
||||||
val result = accountManager.loginWithNostrConnect(onUriGenerated)
|
|
||||||
if (result.isSuccess) {
|
|
||||||
onAccountAdded()
|
|
||||||
}
|
}
|
||||||
result.map { }
|
onAccountAdded()
|
||||||
},
|
}
|
||||||
loginProgress = loginProgress,
|
},
|
||||||
cardWidth = 420.dp,
|
onLoginBunker = { bunkerUri ->
|
||||||
title = "Import Account",
|
accountManager.ensureCurrentAccountInStorage()
|
||||||
subtitle = "Paste nsec, npub (view-only), or use a remote signer",
|
val result = accountManager.loginWithBunker(bunkerUri)
|
||||||
)
|
if (result.isSuccess) {
|
||||||
}
|
onAccountAdded()
|
||||||
|
}
|
||||||
|
result.map { }
|
||||||
|
},
|
||||||
|
onLoginNostrConnect = { onUriGenerated ->
|
||||||
|
accountManager.ensureCurrentAccountInStorage()
|
||||||
|
val result = accountManager.loginWithNostrConnect(onUriGenerated)
|
||||||
|
if (result.isSuccess) {
|
||||||
|
onAccountAdded()
|
||||||
|
}
|
||||||
|
result.map { }
|
||||||
|
},
|
||||||
|
loginProgress = loginProgress,
|
||||||
|
cardWidth = 420.dp,
|
||||||
|
title = "Import Account",
|
||||||
|
subtitle = "Paste nsec, npub (view-only), or use a remote signer",
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user