fix search view

This commit is contained in:
anlicheng 2025-04-02 15:10:40 +08:00
parent 010ee0d38c
commit 4445296da3
2 changed files with 79 additions and 89 deletions

View File

@ -100,8 +100,8 @@ struct API {
} }
print("request url: \(request.url!.absoluteString)") print("request url: \(request.url!.absoluteString)")
let x = String(data: data, encoding: .utf8)! // let x = String(data: data, encoding: .utf8)!
print("url: \(request.url!.path()), data is: \(x)") // print("url: \(request.url!.path()), data is: \(x)")
do { do {
let result = try JSONDecoder().decode(APISuccessResponse<T>.self, from: data) let result = try JSONDecoder().decode(APISuccessResponse<T>.self, from: data)
return .result(result.result) return .result(result.result)

View File

@ -11,36 +11,48 @@ import Observation
struct SearchView: View { struct SearchView: View {
@AppStorage("userId") private var userId: String = Utils.defaultUserId() @AppStorage("userId") private var userId: String = Utils.defaultUserId()
@Environment(\.dismiss) var dismiss @Environment(\.dismiss) var dismiss
@State var model = SearchModel()
@State var searchText: String = "" @State var searchText: String = ""
//
struct DramaGroup: Codable {
struct Item: Codable {
let id: Int
let name: String
let time: Int
let thumb: String
let status: String
}
let group_id: String
let group_name: String
let items: [Item]
}
@State var dramaGroups: [DramaGroup] = []
var body: some View { var body: some View {
VStack { VStack {
HStack(alignment: .center) { HStack(alignment: .center, spacing: 0) {
Color.clear Button(action: { dismiss() }) {
.overlay { Image(systemName: "chevron.left")
HStack(alignment: .center, spacing: 0) { .font(.system(size: 20, weight: .medium))
Button(action: { dismiss() }) { .foregroundColor(.black)
Image(systemName: "chevron.left") }
.font(.system(size: 20, weight: .medium))
.foregroundColor(.black) Spacer()
}
SearchBar(searchText: $searchText, placeholder: "搜索...") {
Spacer() let trimmedSearchText = searchText.trimmingCharacters(in: .whitespacesAndNewlines)
if !trimmedSearchText.isEmpty {
SearchBar(searchText: $searchText, placeholder: "搜索...") { UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
Task { Task {
let trimmedSearchText = searchText.trimmingCharacters(in: .whitespacesAndNewlines) let dramaGroups = await self.search(userId: userId, name: trimmedSearchText)
DispatchQueue.main.async {
if !trimmedSearchText.isEmpty { self.dramaGroups = dramaGroups
UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
await model.search(userId: userId, name: trimmedSearchText)
}
}
} }
} }
} }
}
} }
.frame(height: 50) .frame(height: 50)
.padding([.top, .bottom], 8) .padding([.top, .bottom], 8)
@ -48,7 +60,7 @@ struct SearchView: View {
ScrollView(.vertical, showsIndicators: false) { ScrollView(.vertical, showsIndicators: false) {
// //
LazyVStack(alignment: .center, spacing: 10) { LazyVStack(alignment: .center, spacing: 10) {
ForEach(model.dramaGroups, id: \.group_id) { group in ForEach(dramaGroups, id: \.group_id) { group in
DramaGroupView(group: group) DramaGroupView(group: group)
} }
} }
@ -60,16 +72,31 @@ struct SearchView: View {
.navigationBarBackButtonHidden(true) .navigationBarBackButtonHidden(true)
.padding(8) .padding(8)
.ignoresSafeArea(edges: .bottom) .ignoresSafeArea(edges: .bottom)
.task { }
await model.search(userId: userId, name: "第二季")
//
func search(userId: String, name: String) async -> [DramaGroup] {
guard let encodeName = name.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) else {
return []
}
let response = await API.searchDrama(userId: userId, name: encodeName, as: [DramaGroup].self)
switch response {
case .result(let dramaGroups):
return dramaGroups
case .error(let int32, let string):
print("error_code: \(int32), message: \(string)")
return []
} }
} }
} }
extension SearchView { extension SearchView {
// //
struct DramaGroupView: View { struct DramaGroupView: View {
let group: SearchModel.DramaGroup let group: DramaGroup
var body: some View { var body: some View {
VStack(alignment: .center, spacing: 10) { VStack(alignment: .center, spacing: 10) {
@ -119,11 +146,6 @@ extension SearchView {
} }
} }
}
extension SearchView {
struct SearchBar: View { struct SearchBar: View {
@State private var isSearching = false @State private var isSearching = false
@ -131,21 +153,26 @@ extension SearchView {
var placeholder: String var placeholder: String
var onTap: () -> Void var onTap: () -> Void
@FocusState private var isFocused
var body: some View { var body: some View {
// //
HStack(alignment: .center, spacing: 8) { HStack(alignment: .center, spacing: 8) {
//
TextField(placeholder, text: $searchText) TextField(placeholder, text: $searchText)
.textFieldStyle(PlainTextFieldStyle())
.keyboardType(.emailAddress)
.focused($isFocused)
.submitLabel(.search)
.onSubmit {
onTap()
}
.contentShape(Rectangle())
.padding(8) .padding(8)
//.padding(.horizontal, 30)
.background(Color(.systemGray6)) .background(Color(.systemGray6))
.cornerRadius(8) .cornerRadius(8)
.overlay(alignment: .trailing) { .overlay(alignment: .trailing) {
HStack { HStack {
// Image(systemName: "magnifyingglass")
// .foregroundColor(.gray)
// .frame(minWidth: 0, maxWidth: .infinity, alignment: .leading)
// .padding(.leading, 8)
if isSearching { if isSearching {
Button(action: { Button(action: {
searchText = "" searchText = ""
@ -156,68 +183,31 @@ extension SearchView {
} }
} }
} }
.border(Color.red)
} }
.frame(maxWidth: .infinity) .frame(maxWidth: .infinity)
.onChange(of: searchText) {
if searchText.trimmingCharacters(in: .whitespaces).isEmpty {
isSearching = false
} else {
isSearching = true
}
}
//
Button { Button {
onTap() onTap()
} label: { } label: {
Text("搜索") Text("搜索")
.font(.system(size: 18)) .font(.system(size: 18))
.foregroundColor(.gray) .foregroundColor(.gray)
} }
.padding(.trailing, 10) .padding(.trailing, 10)
.disabled(searchText.isEmpty)
} }
} .onChange(of: searchText) {
} if searchText.trimmingCharacters(in: .whitespaces).isEmpty {
} isSearching = false
} else {
@Observable isSearching = true
final class SearchModel { }
struct DramaGroup: Codable {
struct Item: Codable {
let id: Int
let name: String
let time: Int
let thumb: String
let status: String
}
let group_id: String
let group_name: String
let items: [Item]
}
var dramaGroups: [DramaGroup] = []
func search(userId: String, name: String) async {
guard let encodeName = name.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) else {
self.dramaGroups = []
return
}
let response = await API.searchDrama(userId: userId, name: encodeName, as: [DramaGroup].self)
switch response {
case .result(let dramaGroups):
await MainActor.run {
self.dramaGroups = dramaGroups
} }
case .error(let int32, let string): .onAppear {
print("error_code: \(int32), message: \(string)") DispatchQueue.main.async {
await MainActor.run { isFocused = true
self.dramaGroups = [] }
} }
} }
} }