Files
andros 78ba61034f Fix theme colors across all screens; fix Discover title on iOS 26
- Remove .toolbarBackground(.visible) from all NavigationStack views:
  this modifier suppresses large title rendering in iOS 26.
- Discover: switch to always-present List + overlay pattern so SwiftUI
  never loses the scroll context during loading transitions.
- Discover, Notifications, Groups: use .inline title mode; the tab bar
  already identifies these screens, large titles are redundant.
- RootView: add .toolbarColorScheme propagation for nav bar foreground.
- Settings sheet: apply theme background and toolbar color to the Form.
2026-05-24 21:10:04 +02:00

112 lines
4.4 KiB
Swift

import SwiftUI
import OrgSocialKit
struct SearchView: View {
@State private var viewModel = SearchViewModel()
@AppStorage("useRelay") private var useRelay = true
@Environment(\.appTheme) private var theme
var body: some View {
NavigationStack {
VStack(spacing: 0) {
searchBar
Divider()
content
}
.background(theme.background)
.navigationTitle("Search")
.navigationBarTitleDisplayMode(.large)
.toolbarBackground(theme.secondaryBackground, for: .navigationBar)
.navigationDestination(for: URL.self) { ProfileView(feedURL: $0) }
.navigationDestination(for: ThreadRoute.self) {
ThreadView(postURL: $0.postURL, relayURL: $0.relayURL)
}
}
}
private var searchBar: some View {
VStack(spacing: 8) {
HStack(spacing: 8) {
HStack(spacing: 6) {
Image(systemName: "magnifyingglass").foregroundStyle(.secondary)
TextField(viewModel.isTagSearch ? "Tag name…" : "Search posts…", text: $viewModel.query)
.autocorrectionDisabled()
.textInputAutocapitalization(.never)
.submitLabel(.search)
.onSubmit { if useRelay { Task { await viewModel.search() } } }
if !viewModel.query.isEmpty {
Button { viewModel.query = "" } label: {
Image(systemName: "xmark.circle.fill").foregroundStyle(.secondary)
}
.buttonStyle(.plain)
}
}
.padding(8)
.background(Color.secondary.opacity(0.1), in: RoundedRectangle(cornerRadius: 10))
Button(viewModel.isTagSearch ? "#Tag" : "Text") {
viewModel.isTagSearch.toggle()
}
.font(.caption.weight(.semibold))
.padding(.horizontal, 10).padding(.vertical, 8)
.background(Color.accentColor.opacity(0.1), in: RoundedRectangle(cornerRadius: 10))
.foregroundStyle(Color.accentColor)
}
Button {
Task { await viewModel.search() }
} label: {
Label("Search", systemImage: "magnifyingglass")
.frame(maxWidth: .infinity)
}
.buttonStyle(.borderedProminent)
.disabled(viewModel.query.trimmingCharacters(in: .whitespaces).isEmpty || viewModel.isLoading || !useRelay)
if !useRelay {
Text("Enable Use Relay in Settings to search.")
.font(.caption)
.foregroundStyle(.secondary)
}
}
.padding()
}
@ViewBuilder
private var content: some View {
if viewModel.isLoading {
ProgressView().frame(maxWidth: .infinity, maxHeight: .infinity)
} else if let error = viewModel.errorMessage {
ContentUnavailableView {
Label("Search failed", systemImage: "exclamationmark.triangle")
} description: {
Text(error)
}
} else if viewModel.results.isEmpty && !viewModel.query.isEmpty {
ContentUnavailableView(
"No results",
systemImage: "magnifyingglass",
description: Text("No posts found for \"\(viewModel.query)\".")
)
} else if viewModel.results.isEmpty {
ContentUnavailableView(
"Search posts",
systemImage: "magnifyingglass",
description: Text("Enter a keyword or tag to search posts on the relay.")
)
} else {
List {
ForEach(viewModel.results, id: \.timestamp) { post in
PostRowView(post: post)
.listRowSeparator(.visible)
.listRowSeparatorTint(Color.secondary.opacity(0.2))
.listRowInsets(EdgeInsets(top: 12, leading: 16, bottom: 12, trailing: 16))
.listRowBackground(theme.background)
}
}
.listStyle(.plain)
.scrollContentBackground(.hidden)
.background(theme.background)
}
}
}