feat(multi-account): add account switcher to single-pane layout, scrollable dropdown
- Account switcher now appears at bottom of NavigationRail in single-pane mode (after tor indicator), matching placement in deck sidebar - AddAccountDialog wired in single-pane mode too - Dropdown scrollable with 400dp max height for many accounts Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
+4
@@ -24,8 +24,10 @@ 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.heightIn
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Add
|
||||
import androidx.compose.material.icons.filled.Check
|
||||
@@ -83,6 +85,8 @@ fun AccountSwitcherDropdown(
|
||||
expanded = expanded,
|
||||
onDismissRequest = { expanded = false },
|
||||
offset = DpOffset(x = 48.dp, y = 0.dp),
|
||||
modifier = Modifier.heightIn(max = 400.dp),
|
||||
scrollState = rememberScrollState(),
|
||||
) {
|
||||
allAccounts.forEach { account ->
|
||||
val isActive = account.npub == activeNpub
|
||||
|
||||
+44
-2
@@ -41,7 +41,10 @@ import androidx.compose.material3.VerticalDivider
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.collectAsState
|
||||
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.Modifier
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.unit.dp
|
||||
@@ -55,12 +58,16 @@ import com.vitorpamplona.amethyst.desktop.network.DesktopRelayConnectionManager
|
||||
import com.vitorpamplona.amethyst.desktop.service.highlights.DesktopHighlightStore
|
||||
import com.vitorpamplona.amethyst.desktop.subscriptions.DesktopRelaySubscriptionsCoordinator
|
||||
import com.vitorpamplona.amethyst.desktop.ui.ZapFeedback
|
||||
import com.vitorpamplona.amethyst.desktop.ui.account.AccountSwitcherDropdown
|
||||
import com.vitorpamplona.amethyst.desktop.ui.account.AddAccountDialog
|
||||
import com.vitorpamplona.amethyst.desktop.ui.components.RelayHealthIndicator
|
||||
import com.vitorpamplona.amethyst.desktop.ui.media.LocalIsImmersiveFullscreen
|
||||
import com.vitorpamplona.amethyst.desktop.ui.tor.LocalTorState
|
||||
import com.vitorpamplona.amethyst.desktop.ui.tor.TorStatusIndicator
|
||||
import com.vitorpamplona.quartz.nip47WalletConnect.Nip47WalletConnect.Nip47URINorm
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@Composable
|
||||
fun SinglePaneLayout(
|
||||
@@ -157,7 +164,7 @@ fun SinglePaneLayout(
|
||||
modifier = Modifier.padding(bottom = 4.dp),
|
||||
)
|
||||
|
||||
// Tor status — always last so it's never pushed off screen
|
||||
// Tor status
|
||||
val torState = LocalTorState.current
|
||||
TorStatusIndicator(
|
||||
status = torState.status,
|
||||
@@ -165,8 +172,43 @@ fun SinglePaneLayout(
|
||||
singlePaneState.navigate(DeckColumnType.Settings)
|
||||
navState.clear()
|
||||
},
|
||||
modifier = Modifier.padding(bottom = 12.dp),
|
||||
modifier = Modifier.padding(bottom = 4.dp),
|
||||
)
|
||||
|
||||
// Account switcher — at very bottom of rail
|
||||
val allAccountsState by accountManager.allAccounts.collectAsState()
|
||||
val singlePaneScope = rememberCoroutineScope()
|
||||
var showAddAccountDialog by remember { mutableStateOf(false) }
|
||||
|
||||
AccountSwitcherDropdown(
|
||||
activeNpub = accountManager.currentAccount()?.npub,
|
||||
allAccounts = allAccountsState,
|
||||
onSwitchAccount = { npub ->
|
||||
singlePaneScope.launch(Dispatchers.IO) {
|
||||
accountManager.switchAccount(npub)
|
||||
}
|
||||
},
|
||||
onAddAccount = { showAddAccountDialog = true },
|
||||
onRemoveAccount = { npub ->
|
||||
singlePaneScope.launch(Dispatchers.IO) {
|
||||
accountManager.removeAccountFromStorage(npub)
|
||||
}
|
||||
},
|
||||
modifier = Modifier.padding(bottom = 8.dp),
|
||||
)
|
||||
|
||||
if (showAddAccountDialog) {
|
||||
AddAccountDialog(
|
||||
accountManager = accountManager,
|
||||
onDismiss = { showAddAccountDialog = false },
|
||||
onAccountAdded = {
|
||||
showAddAccountDialog = false
|
||||
singlePaneScope.launch(Dispatchers.IO) {
|
||||
accountManager.refreshAccountList()
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user