Add Show Sidebar toggle to Subscriptions view options

Adds a Show Sidebar toggle (iPad regular and macOS) that controls
channels sidebar visibility. When the sidebar is shown, the channel
strip picker is disabled and the redundant channel header link above
the feed is hidden. Layout picker now uses inline menu style for
consistency with other options.
This commit is contained in:
Arkadiusz Fal
2026-04-19 18:03:53 +02:00
parent 88a7c713fa
commit 31b244880b
2 changed files with 37 additions and 10 deletions

View File

@@ -17720,6 +17720,16 @@
} }
} }
}, },
"viewOptions.showSidebar" : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Show Sidebar"
}
}
}
},
"viewOptions.layout" : { "viewOptions.layout" : {
"localizations" : { "localizations" : {
"en" : { "en" : {

View File

@@ -30,6 +30,7 @@ struct SubscriptionsView: View {
@AppStorage("subscriptionsGridColumns") private var gridColumns = 2 @AppStorage("subscriptionsGridColumns") private var gridColumns = 2
@AppStorage("subscriptionsHideWatched") private var hideWatched = false @AppStorage("subscriptionsHideWatched") private var hideWatched = false
@AppStorage("subscriptionsChannelStripSize") private var channelStripSize: ChannelStripSize = .normal @AppStorage("subscriptionsChannelStripSize") private var channelStripSize: ChannelStripSize = .normal
@AppStorage("subscriptionsShowSidebar") private var showSidebar = true
/// List style from centralized settings. /// List style from centralized settings.
private var listStyle: VideoListStyle { private var listStyle: VideoListStyle {
@@ -226,7 +227,7 @@ struct SubscriptionsView: View {
.padding(.top, 20) .padding(.top, 20)
#elseif os(macOS) #elseif os(macOS)
HSplitView { HSplitView {
if subscriptionsLoaded && subscriptions.count > 1 { if showSidebar && subscriptionsLoaded && subscriptions.count > 1 {
macOSChannelsSidebar macOSChannelsSidebar
.frame(minWidth: 180, idealWidth: 240, maxWidth: 400) .frame(minWidth: 180, idealWidth: 240, maxWidth: 400)
} }
@@ -242,7 +243,7 @@ struct SubscriptionsView: View {
.frame(minWidth: 300, maxWidth: .infinity, maxHeight: .infinity) .frame(minWidth: 300, maxWidth: .infinity, maxHeight: .infinity)
} }
#else #else
if isIPadRegular && subscriptionsLoaded && subscriptions.count > 1 { if isIPadRegular && showSidebar && subscriptionsLoaded && subscriptions.count > 1 {
HStack(spacing: 0) { HStack(spacing: 0) {
iOSChannelsSidebar iOSChannelsSidebar
.frame(width: 260) .frame(width: 260)
@@ -276,7 +277,7 @@ struct SubscriptionsView: View {
VStack { VStack {
Spacer() Spacer()
if subscriptionsLoaded && subscriptions.count > 1 && channelStripSize != .disabled && !isShowingFullScreenError && !isIPadRegular { if subscriptionsLoaded && subscriptions.count > 1 && channelStripSize != .disabled && !isShowingFullScreenError && !(isIPadRegular && showSidebar) {
bottomFloatingFilterStrip bottomFloatingFilterStrip
.transition(.move(edge: .bottom).combined(with: .opacity)) .transition(.move(edge: .bottom).combined(with: .opacity))
} }
@@ -305,18 +306,21 @@ struct SubscriptionsView: View {
NavigationStack { NavigationStack {
Form { Form {
Section { Section {
// Layout picker (segmented) // Layout picker (inline menu)
Picker(selection: $layout) { PlatformMenuPicker(String(localized: "viewOptions.layout"), selection: $layout) {
ForEach(VideoListLayout.allCases, id: \.self) { option in ForEach(VideoListLayout.allCases, id: \.self) { option in
Label(option.displayName, systemImage: option.systemImage) Label(option.displayName, systemImage: option.systemImage)
.tag(option) .tag(option)
} }
} label: {
Text("viewOptions.layout")
} }
.pickerStyle(.segmented)
.listRowBackground(Color.clear) #if os(macOS)
.listRowInsets(EdgeInsets(top: 8, leading: 0, bottom: 8, trailing: 0)) Toggle("viewOptions.showSidebar", isOn: $showSidebar)
#elseif os(iOS)
if isIPadRegular {
Toggle("viewOptions.showSidebar", isOn: $showSidebar)
}
#endif
// List-specific options // List-specific options
if layout == .list { if layout == .list {
@@ -353,6 +357,7 @@ struct SubscriptionsView: View {
Text(size.displayName).tag(size) Text(size.displayName).tag(size)
} }
} }
.disabled(isIPadRegular && showSidebar)
#endif #endif
} }
@@ -832,6 +837,16 @@ struct SubscriptionsView: View {
} }
#endif #endif
private var isSidebarVisible: Bool {
#if os(macOS)
return showSidebar && subscriptionsLoaded && subscriptions.count > 1
#elseif os(iOS)
return isIPadRegular && showSidebar && subscriptionsLoaded && subscriptions.count > 1
#else
return false
#endif
}
#if os(iOS) #if os(iOS)
private var isIPadRegular: Bool { private var isIPadRegular: Bool {
UIDevice.current.userInterfaceIdiom == .pad && horizontalSizeClass == .regular UIDevice.current.userInterfaceIdiom == .pad && horizontalSizeClass == .regular
@@ -1005,6 +1020,8 @@ struct SubscriptionsView: View {
Text("subscriptions.updatingChannels \(progress.loaded) \(progress.total)") Text("subscriptions.updatingChannels \(progress.loaded) \(progress.total)")
.monospacedDigit() .monospacedDigit()
.foregroundStyle(.secondary) .foregroundStyle(.secondary)
} else if isSidebarVisible {
EmptyView()
} else if let subscription = selectedSubscription { } else if let subscription = selectedSubscription {
Button { Button {
appEnvironment?.navigationCoordinator.navigate( appEnvironment?.navigationCoordinator.navigate(