diff --git a/Yattee/Views/Components/DataContextSwitcherMenu.swift b/Yattee/Views/Components/DataContextSwitcherMenu.swift index 06d9833c..b2cd8728 100644 --- a/Yattee/Views/Components/DataContextSwitcherMenu.swift +++ b/Yattee/Views/Components/DataContextSwitcherMenu.swift @@ -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. diff --git a/Yattee/Views/Home/HistoryListView.swift b/Yattee/Views/Home/HistoryListView.swift index 0bb89ada..3cd2a6b7 100644 --- a/Yattee/Views/Home/HistoryListView.swift +++ b/Yattee/Views/Home/HistoryListView.swift @@ -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() } diff --git a/Yattee/Views/Home/HomeView.swift b/Yattee/Views/Home/HomeView.swift index 9fd3944a..16397752 100644 --- a/Yattee/Views/Home/HomeView.swift +++ b/Yattee/Views/Home/HomeView.swift @@ -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() } diff --git a/Yattee/Views/Home/PlaylistsListView.swift b/Yattee/Views/Home/PlaylistsListView.swift index fe57b987..921b9757 100644 --- a/Yattee/Views/Home/PlaylistsListView.swift +++ b/Yattee/Views/Home/PlaylistsListView.swift @@ -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() } } diff --git a/Yattee/Views/Navigation/UnifiedTabView.swift b/Yattee/Views/Navigation/UnifiedTabView.swift index 6aa19f82..1deb00e5 100644 --- a/Yattee/Views/Navigation/UnifiedTabView.swift +++ b/Yattee/Views/Navigation/UnifiedTabView.swift @@ -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. diff --git a/Yattee/Views/Settings/AccountsListView.swift b/Yattee/Views/Settings/AccountsListView.swift index 6cdf87d4..1ace6f42 100644 --- a/Yattee/Views/Settings/AccountsListView.swift +++ b/Yattee/Views/Settings/AccountsListView.swift @@ -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 { diff --git a/Yattee/Views/Settings/SubscriptionsSettingsView.swift b/Yattee/Views/Settings/SubscriptionsSettingsView.swift index 0450ebc1..45b4c582 100644 --- a/Yattee/Views/Settings/SubscriptionsSettingsView.swift +++ b/Yattee/Views/Settings/SubscriptionsSettingsView.swift @@ -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")) + } } } diff --git a/Yattee/Views/Subscriptions/SubscriptionsView.swift b/Yattee/Views/Subscriptions/SubscriptionsView.swift index 3ef6d6d1..7c488a7d 100644 --- a/Yattee/Views/Subscriptions/SubscriptionsView.swift +++ b/Yattee/Views/Subscriptions/SubscriptionsView.swift @@ -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() } }