fix search view
This commit is contained in:
parent
010ee0d38c
commit
4445296da3
@ -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)
|
||||||
|
|||||||
@ -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()
|
Spacer()
|
||||||
|
|
||||||
SearchBar(searchText: $searchText, placeholder: "搜索...") {
|
SearchBar(searchText: $searchText, placeholder: "搜索...") {
|
||||||
Task {
|
let trimmedSearchText = searchText.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||||
let trimmedSearchText = searchText.trimmingCharacters(in: .whitespacesAndNewlines)
|
if !trimmedSearchText.isEmpty {
|
||||||
|
UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
|
||||||
if !trimmedSearchText.isEmpty {
|
Task {
|
||||||
UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
|
let dramaGroups = await self.search(userId: userId, name: trimmedSearchText)
|
||||||
|
DispatchQueue.main.async {
|
||||||
await model.search(userId: userId, name: trimmedSearchText)
|
self.dramaGroups = dramaGroups
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.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 = []
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user