Rework tvOS PeerTube browse and discovery sheets for sidebar layout

Drop nested NavigationStack, .searchable, and close button from the
PeerTube explore view on tvOS; use an inline search field plus Filters
button so focus separates cleanly and the sidebar title is no longer
overlapped. Keep the header visible across empty/error states so the
query can be cleared. Hide the filters and scan-network sheet toolbars
on tvOS, apply filter changes immediately, and add padding plus
scrollClipDisabled so focused rows aren't clipped.
This commit is contained in:
Arkadiusz Fal
2026-04-17 01:51:25 +02:00
parent 6d3bea7678
commit e583aa3fd7
3 changed files with 74 additions and 8 deletions

View File

@@ -65,18 +65,27 @@ struct PeerTubeInstancesExploreView: View {
}
var body: some View {
NavigationStack {
Group {
#if os(tvOS)
content
.navigationTitle(String(localized: "peertube.explore.title"))
#if os(iOS)
.navigationBarTitleDisplayMode(.inline)
#endif
.toolbar { toolbarContent }
.searchable(text: $searchText, prompt: Text(String(localized: "peertube.explore.search")))
.onChange(of: searchText) { _, _ in
// Reset display limit when search changes
displayLimit = pageSize
}
#else
NavigationStack {
content
.navigationTitle(String(localized: "peertube.explore.title"))
#if os(iOS)
.navigationBarTitleDisplayMode(.inline)
#endif
.toolbar { toolbarContent }
.searchable(text: $searchText, prompt: Text(String(localized: "peertube.explore.search")))
.onChange(of: searchText) { _, _ in
// Reset display limit when search changes
displayLimit = pageSize
}
}
#endif
}
#if os(macOS)
.frame(minWidth: 500, minHeight: 400)
@@ -101,6 +110,20 @@ struct PeerTubeInstancesExploreView: View {
@ViewBuilder
private var content: some View {
#if os(tvOS)
VStack(spacing: 0) {
if !allInstances.isEmpty {
tvOSSearchHeader
}
contentBody
}
#else
contentBody
#endif
}
@ViewBuilder
private var contentBody: some View {
if isLoading && allInstances.isEmpty {
ProgressView()
.frame(maxWidth: .infinity, maxHeight: .infinity)
@@ -130,6 +153,33 @@ struct PeerTubeInstancesExploreView: View {
}
}
#if os(tvOS)
@ViewBuilder
private var tvOSSearchHeader: some View {
HStack(spacing: 16) {
TextField(
"",
text: $searchText,
prompt: Text(String(localized: "peertube.explore.search"))
)
.textFieldStyle(.plain)
.focusSection()
Button {
showFiltersSheet = true
} label: {
Label(
String(localized: "peertube.explore.filters"),
systemImage: filters.isDefault ? "line.3.horizontal.decrease.circle" : "line.3.horizontal.decrease.circle.fill"
)
}
.focusSection()
}
.padding(.horizontal, 16)
.padding(.vertical, 8)
}
#endif
private var instancesList: some View {
List {
// Instances
@@ -164,6 +214,7 @@ struct PeerTubeInstancesExploreView: View {
@ToolbarContentBuilder
private var toolbarContent: some ToolbarContent {
#if !os(tvOS)
ToolbarItem(placement: .confirmationAction) {
Button(role: .cancel) {
dismiss()
@@ -172,6 +223,7 @@ struct PeerTubeInstancesExploreView: View {
.labelStyle(.iconOnly)
}
}
#endif
ToolbarItem(placement: .primaryAction) {
Button {