213 lines
6.9 KiB
Swift
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//
// SearchView.swift
// dimensionhub
//
// Created by on 2025/4/1.
//
import SwiftUI
struct SearchView: View {
@Environment(\.modelContext) var modelContext
@Environment(\.userId) private var userId
@Environment(\.dismiss) var dismiss
@State var searchText: String = ""
@State var searchModel = SearchModel()
@State private var isSearching = false
//
@State private var showSearchResult: Bool = false
//
@State private var toolbarID = UUID()
@State private var isFocused: Bool = true
var body: some View {
ScrollView(.vertical, showsIndicators: false) {
LazyVStack(alignment: .center, spacing: 10) {
ForEach(searchModel.dramaGroups, id: \.group_id) { group in
SearchDramaGroupView(group: group)
}
}
.padding(.top, 8)
}
.frame(maxWidth: .infinity, maxHeight: .infinity)
.background(
GestureObserver {
//
if isFocused {
isFocused = false
}
} onGestureCancelled: {
if !isFocused && !showSearchResult {
isFocused = true
}
}
)
.onTapGesture {
isFocused = false
}
.simultaneousGesture(
DragGesture().onChanged{ _ in
isFocused = false
}
)
.overlay(alignment: .center) {
Text("什么都没有找到")
.font(.system(size: 18))
.foregroundColor(Color(hex: "#333333"))
.opacity(showSearchResult && searchModel.dramaGroups.isEmpty ? 1 : 0)
}
.navigationTitle("")
.toolbar {
ToolbarItem(placement: .principal) {
SearchBar(isFirstResponder: $isFocused, searchText: $searchText) {
doSearch()
}
.frame(width: UIScreen.main.bounds.width * 0.8)
.id(toolbarID)
}
}
.onAppear {
toolbarID = UUID()
}
}
private func doSearch() {
let trimmed = searchText.trimmingCharacters(in: .whitespacesAndNewlines)
if !trimmed.isEmpty {
Task.detached {
await searchModel.search(userId: userId, name: trimmed)
DispatchQueue.main.async {
//
self.showSearchResult = true
}
}
//
// let history = SearchHistory(keyword: trimmed, timestamp: Date())
// modelContext.insert(history)
}
}
}
//
struct SearchDramaGroupView: View {
let group: SearchModel.DramaGroup
var body: some View {
LazyVStack(alignment: .center, spacing: 10) {
ForEach(group.items, id: \.id) { item in
NavigationLink(destination: DetailView(id: item.id, channelName: nil)) {
FlexImage(urlString: item.thumb, width: 370, height: 180, placeholder: "ph_img_big")
.frame(width: 370, height: 180)
.overlay(alignment: .topLeading) {
VStack(alignment: .leading, spacing: 8) {
Text(item.name)
.font(.system(size: 16))
.foregroundColor(.white)
.lineLimit(1)
Text(item.status)
.font(.system(size: 12))
.foregroundColor(.white)
.lineLimit(1)
}
.padding(5)
.background(
Color.black.opacity(0.6)
)
.cornerRadius(5)
.padding(8)
}
}
}
}
}
}
struct GestureObserver: UIViewControllerRepresentable {
var onGestureBegin: () -> Void
var onGestureCancelled: () -> Void
func makeUIViewController(context: Context) -> UIViewController {
return context.coordinator
}
func updateUIViewController(_ uiViewController: UIViewController, context: Context) { }
func makeCoordinator() -> Coordinator {
Coordinator(onGestureBegin: onGestureBegin, onGestureCancelled: onGestureCancelled)
}
class Coordinator: UIViewController {
var onGestureBegin: () -> Void
var onGestureCancelled: () -> Void
//
var initialStackCount: Int = 0
//
var cacheNavigationController: UINavigationController?
init(onGestureBegin: @escaping () -> Void, onGestureCancelled: @escaping () -> Void) {
self.onGestureBegin = onGestureBegin
self.onGestureCancelled = onGestureCancelled
super.init(nibName: nil, bundle: nil)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
guard let nav = self.navigationController else {
return
}
initialStackCount = nav.viewControllers.count
self.cacheNavigationController = nav
//
if let gesture = nav.interactivePopGestureRecognizer {
gesture.addTarget(self, action: #selector(handleGesture(_:)))
}
}
@objc func handleGesture(_ gesture: UIScreenEdgePanGestureRecognizer) {
switch gesture.state {
case .began:
onGestureBegin()
case .ended:
if let nav = self.cacheNavigationController {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.8) { [self] in
let afterCount = nav.viewControllers.count
if afterCount < initialStackCount {
// pop
print("pop out")
} else {
//
onGestureCancelled()
}
}
}
case .cancelled, .failed:
onGestureCancelled()
default:
break
}
}
}
}
//
//#Preview {
// SearchView()
//}