Withhold every account switcher until an account exists to offer

This commit is contained in:
Arkadiusz Fal
2026-09-13 20:16:14 +02:00
parent 5136b79f49
commit 69d22cdc98
8 changed files with 55 additions and 18 deletions

View File

@@ -232,6 +232,35 @@ enum DataContextSwitcherLabels {
}
}
// MARK: - Visibility
/// When the switcher is offered at all.
///
/// One rule for every presentation: no switcher until an account exists to
/// switch to. A user who has never signed in anywhere has only local data, and
/// a menu offering the one context they are already in is chrome with nothing
/// to say. Orphans and accounts still waiting for their instance don't count —
/// neither is a context the switcher would actually list.
enum DataContextSwitcherVisibility {
/// The settings presentations: the accounts screen and the subscriptions
/// settings row. Only the existence of an account gates these — they are
/// where "Show Account Pickers" is explained and turned back on, so the
/// toggle itself must not hide them.
@MainActor
static func showsSwitcher(in appEnvironment: AppEnvironment?) -> Bool {
guard let appEnvironment else { return false }
return !appEnvironment.accountsManager.selectableAccounts.isEmpty
}
/// Everything outside Settings: the toolbar menus, the tvOS buttons, the
/// macOS sidebar row. Same account rule, plus the user's toggle.
@MainActor
static func showsPickers(in appEnvironment: AppEnvironment?) -> Bool {
guard let appEnvironment else { return false }
return appEnvironment.settingsManager.showAccountPickers && showsSwitcher(in: appEnvironment)
}
}
// MARK: - Glyph
/// How the switcher's icon reads.

View File

@@ -289,7 +289,7 @@ struct HistoryListView: View {
}
}
if appEnvironment?.settingsManager.showAccountPickers ?? true {
if DataContextSwitcherVisibility.showsPickers(in: appEnvironment) {
DataContextSwitcherButton()
}
}
@@ -331,7 +331,7 @@ struct HistoryListView: View {
ToolbarSpacer(.flexible, placement: .primaryAction)
}
#endif
if appEnvironment?.settingsManager.showAccountPickers ?? true {
if DataContextSwitcherVisibility.showsPickers(in: appEnvironment) {
ToolbarItem(placement: viewOptionsPlacement) {
DataContextSwitcherMenu()
}

View File

@@ -178,7 +178,7 @@ struct HomeView: View {
#endif
.toolbar {
#if !os(tvOS)
if settingsManager?.showAccountPickers ?? true {
if DataContextSwitcherVisibility.showsPickers(in: appEnvironment) {
ToolbarItem(placement: switcherPlacement) {
DataContextSwitcherMenu()
}

View File

@@ -229,7 +229,7 @@ struct PlaylistsListView: View {
ToolbarSpacer(.flexible, placement: .primaryAction)
}
#endif
if appEnvironment?.settingsManager.showAccountPickers ?? true {
if DataContextSwitcherVisibility.showsPickers(in: appEnvironment) {
ToolbarItem(placement: viewOptionsPlacement) {
DataContextSwitcherMenu()
}
@@ -427,7 +427,7 @@ struct PlaylistsListView: View {
Label(String(localized: "viewOptions.title"), systemImage: "slider.horizontal.3")
}
if appEnvironment?.settingsManager.showAccountPickers ?? true {
if DataContextSwitcherVisibility.showsPickers(in: appEnvironment) {
DataContextSwitcherButton()
}
}

View File

@@ -427,7 +427,7 @@ struct UnifiedTabView: View {
VStack(spacing: 0) {
sidebarList
if settingsManager?.showAccountPickers ?? true {
if DataContextSwitcherVisibility.showsPickers(in: appEnvironment) {
Divider()
// The window has no toolbar of its own to hang this off, and the
// sidebar is the one chrome every tab shares.

View File

@@ -126,11 +126,16 @@ struct AccountsListView: View {
// The switcher lives here rather than beside the Accounts row
// in Settings: which account is current is this screen's
// subject, and the row below names the same account the
// checkmarked row further down is marked as.
Section {
DataContextSwitcherSettingsRow()
} header: {
Text(String(localized: "accounts.switcher.section"))
// checkmarked row further down is marked as. Withheld while
// every listed account is an orphan — there is nothing the
// switcher could offer besides the local data the app is
// already on.
if DataContextSwitcherVisibility.showsSwitcher(in: appEnvironment) {
Section {
DataContextSwitcherSettingsRow()
} header: {
Text(String(localized: "accounts.switcher.section"))
}
}
ForEach(groups, id: \.instance.id) { group in
@@ -229,7 +234,8 @@ struct AccountsListView: View {
/// way: turning the pickers off must leave a place to turn them back on.
@ViewBuilder
private var pickerVisibilitySection: some View {
if let settings = appEnvironment?.settingsManager {
if DataContextSwitcherVisibility.showsSwitcher(in: appEnvironment),
let settings = appEnvironment?.settingsManager {
@Bindable var settings = settings
Section {

View File

@@ -134,10 +134,12 @@ struct SubscriptionsSettingsView: View {
@ViewBuilder
private var accountSection: some View {
Section {
DataContextSwitcherSettingsRow()
} footer: {
Text(String(localized: "settings.subscriptions.account.footer"))
if DataContextSwitcherVisibility.showsSwitcher(in: appEnvironment) {
Section {
DataContextSwitcherSettingsRow()
} footer: {
Text(String(localized: "settings.subscriptions.account.footer"))
}
}
}

View File

@@ -492,7 +492,7 @@ struct SubscriptionsView: View {
.toolbarTitleDisplayMode(.inlineLarge)
#endif
.toolbar {
if appEnvironment?.settingsManager.showAccountPickers ?? true {
if DataContextSwitcherVisibility.showsPickers(in: appEnvironment) {
ToolbarItem(placement: viewOptionsPlacement) {
DataContextSwitcherMenu()
}
@@ -909,7 +909,7 @@ struct SubscriptionsView: View {
}
.buttonStyle(.bordered)
if appEnvironment?.settingsManager.showAccountPickers ?? true {
if DataContextSwitcherVisibility.showsPickers(in: appEnvironment) {
DataContextSwitcherButton()
}
}