Some checks failed
CI - Multi-Platform Native / Build iOS (RSSuper) (push) Has been cancelled
CI - Multi-Platform Native / Build macOS (push) Has been cancelled
CI - Multi-Platform Native / Build Android (push) Has been cancelled
CI - Multi-Platform Native / Build Linux (push) Has been cancelled
CI - Multi-Platform Native / Integration Tests (push) Has been cancelled
CI - Multi-Platform Native / Build Summary (push) Has been cancelled
98 lines
3.3 KiB
Swift
98 lines
3.3 KiB
Swift
import SwiftUI
|
|
|
|
struct SearchView: View {
|
|
@StateObject private var viewModel: SearchViewModel
|
|
@State private var searchQuery: String = ""
|
|
@State private var isSearching: Bool = false
|
|
@State private var showError: Bool = false
|
|
@State private var errorMessage: String = ""
|
|
|
|
private let searchService: SearchServiceProtocol
|
|
|
|
init(searchService: SearchServiceProtocol = SearchService()) {
|
|
self.searchService = searchService
|
|
_viewModel = StateObject(wrappedValue: SearchViewModel(searchService: searchService))
|
|
}
|
|
|
|
var body: some View {
|
|
NavigationView {
|
|
VStack {
|
|
HStack {
|
|
Image(systemName: "magnifyingglass")
|
|
TextField("Search feeds...", text: $searchQuery)
|
|
.onSubmit {
|
|
performSearch()
|
|
}
|
|
}
|
|
.padding()
|
|
.background(Color(.systemGray6))
|
|
.cornerRadius(8)
|
|
.padding(.horizontal)
|
|
|
|
if isSearching {
|
|
ProgressView("Searching...")
|
|
.padding()
|
|
}
|
|
|
|
if showError {
|
|
Text(errorMessage)
|
|
.foregroundColor(.red)
|
|
.font(.caption)
|
|
.padding()
|
|
}
|
|
|
|
List {
|
|
ForEach(viewModel.searchResults) { result in
|
|
NavigationLink(destination: FeedDetailView(feedItem: result.item, feedService: searchService)) {
|
|
VStack(alignment: .leading) {
|
|
Text(result.item.title)
|
|
.font(.headline)
|
|
Text(result.item.subscriptionTitle ?? "Unknown")
|
|
.font(.subheadline)
|
|
.foregroundColor(.secondary)
|
|
if let published = result.item.published {
|
|
Text(published, format: Date.FormatStyle(date: .abbreviated, time: .shortened))
|
|
.font(.caption)
|
|
.foregroundColor(.secondary)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
.listStyle(PlainListStyle())
|
|
}
|
|
.navigationTitle("Search")
|
|
.toolbar {
|
|
ToolbarItem(placement: .navigationBarTrailing) {
|
|
Button("Clear") {
|
|
searchQuery = ""
|
|
viewModel.clearSearch()
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private func performSearch() {
|
|
guard !searchQuery.isEmpty else { return }
|
|
|
|
isSearching = true
|
|
showError = false
|
|
|
|
Task {
|
|
do {
|
|
try await viewModel.search(query: searchQuery)
|
|
isSearching = false
|
|
} catch {
|
|
errorMessage = error.localizedDescription
|
|
showError = true
|
|
isSearching = false
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#Preview {
|
|
SearchView()
|
|
}
|