feat(Views): 增加 Search bar 到 explore page
增加 Search bar 到 explore page Signed-off-by: Ching <loooching@gmail.com>
This commit is contained in:
parent
62c6c6d2c5
commit
577643d9b1
@ -13,6 +13,8 @@
|
||||
2492CC152A000EB10086C525 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 2492CC142A000EB10086C525 /* Preview Assets.xcassets */; };
|
||||
2492CC252A0023220086C525 /* FeedView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2492CC242A0023220086C525 /* FeedView.swift */; };
|
||||
2492CC282A0025DD0086C525 /* TweetRowView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2492CC272A0025DD0086C525 /* TweetRowView.swift */; };
|
||||
24A07CB02A017D3300F4ECA8 /* ExploreViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24A07CAF2A017D3300F4ECA8 /* ExploreViewModel.swift */; };
|
||||
24A07CB22A01869F00F4ECA8 /* SearchBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24A07CB12A01869F00F4ECA8 /* SearchBar.swift */; };
|
||||
24A59AB42A002EB8009C9E3E /* MainTabView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24A59AB32A002EB8009C9E3E /* MainTabView.swift */; };
|
||||
24A59ABA2A0030CB009C9E3E /* ExploreView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24A59AB92A0030CB009C9E3E /* ExploreView.swift */; };
|
||||
24A59ABC2A0030EC009C9E3E /* NotificationsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24A59ABB2A0030EC009C9E3E /* NotificationsView.swift */; };
|
||||
@ -54,6 +56,8 @@
|
||||
2492CC142A000EB10086C525 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = "<group>"; };
|
||||
2492CC242A0023220086C525 /* FeedView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FeedView.swift; sourceTree = "<group>"; };
|
||||
2492CC272A0025DD0086C525 /* TweetRowView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TweetRowView.swift; sourceTree = "<group>"; };
|
||||
24A07CAF2A017D3300F4ECA8 /* ExploreViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExploreViewModel.swift; sourceTree = "<group>"; };
|
||||
24A07CB12A01869F00F4ECA8 /* SearchBar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchBar.swift; sourceTree = "<group>"; };
|
||||
24A59AB32A002EB8009C9E3E /* MainTabView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainTabView.swift; sourceTree = "<group>"; };
|
||||
24A59AB92A0030CB009C9E3E /* ExploreView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExploreView.swift; sourceTree = "<group>"; };
|
||||
24A59ABB2A0030EC009C9E3E /* NotificationsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationsView.swift; sourceTree = "<group>"; };
|
||||
@ -142,10 +146,10 @@
|
||||
2492CC1B2A00228F0086C525 /* Core */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
2492CC212A0022C30086C525 /* Components */,
|
||||
24A59AE02A00EEE8009C9E3E /* Authentication */,
|
||||
24A59AD72A00DB49009C9E3E /* UploadTweet */,
|
||||
24A59ACA2A00BDA1009C9E3E /* SideMenu */,
|
||||
2492CC212A0022C30086C525 /* Components */,
|
||||
24A59AB82A00308E009C9E3E /* Profile */,
|
||||
24A59AB72A00305E009C9E3E /* Explore */,
|
||||
24A59AB62A00305C009C9E3E /* Notifications */,
|
||||
@ -198,6 +202,7 @@
|
||||
24A59ADE2A00DCC2009C9E3E /* TextArea.swift */,
|
||||
24A59AE72A00F106009C9E3E /* RoundedShape.swift */,
|
||||
24A59AE92A00F672009C9E3E /* CustomInputField.swift */,
|
||||
24A07CB12A01869F00F4ECA8 /* SearchBar.swift */,
|
||||
);
|
||||
path = Components;
|
||||
sourceTree = "<group>";
|
||||
@ -286,6 +291,7 @@
|
||||
24A59AC52A00BA3A009C9E3E /* ViewModels */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
24A07CAF2A017D3300F4ECA8 /* ExploreViewModel.swift */,
|
||||
);
|
||||
path = ViewModels;
|
||||
sourceTree = "<group>";
|
||||
@ -494,10 +500,12 @@
|
||||
2492CC252A0023220086C525 /* FeedView.swift in Sources */,
|
||||
24A59ACE2A00BDCB009C9E3E /* SideMenuView.swift in Sources */,
|
||||
24FA4D992A012A5D002D202A /* ProfilePhotoSelectorView.swift in Sources */,
|
||||
24A07CB02A017D3300F4ECA8 /* ExploreViewModel.swift in Sources */,
|
||||
2492CC0D2A000EB00086C525 /* dudu_tweetApp.swift in Sources */,
|
||||
24A59ABA2A0030CB009C9E3E /* ExploreView.swift in Sources */,
|
||||
24A59AD22A00BE14009C9E3E /* SideMenuViewModel.swift in Sources */,
|
||||
24A59ADF2A00DCC2009C9E3E /* TextArea.swift in Sources */,
|
||||
24A07CB22A01869F00F4ECA8 /* SearchBar.swift in Sources */,
|
||||
24A59AD62A00CA82009C9E3E /* SideMenuOptionRowView.swift in Sources */,
|
||||
24A59AE42A00EF1F009C9E3E /* LoginView.swift in Sources */,
|
||||
24A59AE62A00EF3A009C9E3E /* RegistrationView.swift in Sources */,
|
||||
|
||||
Binary file not shown.
40
dudu-tweet/dudu-tweet/Core/Components/SearchBar.swift
Normal file
40
dudu-tweet/dudu-tweet/Core/Components/SearchBar.swift
Normal file
@ -0,0 +1,40 @@
|
||||
//
|
||||
// SearchBar.swift
|
||||
// dudu-tweet
|
||||
//
|
||||
// Created by ching on 2023/5/3.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct SearchBar: View {
|
||||
@Binding var text: String
|
||||
|
||||
var body: some View {
|
||||
HStack {
|
||||
TextField("Search...", text: $text)
|
||||
.padding(8)
|
||||
.padding(.horizontal, 24)
|
||||
.background(Color(.systemGray6))
|
||||
.cornerRadius(8)
|
||||
.overlay(
|
||||
HStack {
|
||||
Image(systemName: "magnifyingglass")
|
||||
.foregroundColor(.gray)
|
||||
.frame(minWidth: 0, maxWidth: .infinity, alignment: .leading)
|
||||
.padding(.leading, 8)
|
||||
}
|
||||
)
|
||||
|
||||
}
|
||||
.padding(.horizontal, 4)
|
||||
}
|
||||
}
|
||||
|
||||
struct SearchBar_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
SearchBar(text: .constant(""))
|
||||
.previewLayout(.sizeThatFits)
|
||||
}
|
||||
}
|
||||
|
||||
@ -6,17 +6,23 @@
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
import Kingfisher
|
||||
|
||||
struct UserRowView: View {
|
||||
let user: User
|
||||
|
||||
var body: some View {
|
||||
HStack(spacing: 12) {
|
||||
Circle()
|
||||
.frame(width: 48, height: 48)
|
||||
KFImage(URL(string: user.profileImageUrl))
|
||||
.resizable()
|
||||
.scaledToFill()
|
||||
.clipShape(Circle())
|
||||
.frame(width: 56, height: 56)
|
||||
VStack(alignment: .leading, spacing: 4) {
|
||||
Text("Lith")
|
||||
Text(user.username)
|
||||
.font(.subheadline).bold()
|
||||
.foregroundColor(.black)
|
||||
Text("李四")
|
||||
Text(user.fullname)
|
||||
.font(.subheadline)
|
||||
.foregroundColor(.gray)
|
||||
}
|
||||
@ -27,8 +33,8 @@ struct UserRowView: View {
|
||||
}
|
||||
}
|
||||
|
||||
struct UserRowView_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
UserRowView()
|
||||
}
|
||||
}
|
||||
//struct UserRowView_Previews: PreviewProvider {
|
||||
// static var previews: some View {
|
||||
//// UserRowView()
|
||||
// }
|
||||
//}
|
||||
|
||||
@ -0,0 +1,40 @@
|
||||
//
|
||||
// ExploreViewModel.swift
|
||||
// dudu-tweet
|
||||
//
|
||||
// Created by ching on 2023/5/3.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
|
||||
class ExploreViewModel: ObservableObject {
|
||||
@Published var users = [User]()
|
||||
@Published var searchText = ""
|
||||
|
||||
var searchableUsers: [User] {
|
||||
if searchText.isEmpty {
|
||||
return users
|
||||
} else {
|
||||
let lowercasedQuery = searchText.lowercased()
|
||||
|
||||
return users.filter({
|
||||
$0.username.contains(lowercasedQuery) ||
|
||||
$0.fullname.lowercased().contains(lowercasedQuery)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
let service = UserService()
|
||||
|
||||
init() {
|
||||
fetchUsers()
|
||||
}
|
||||
|
||||
func fetchUsers() {
|
||||
service.fetchUsers { users in
|
||||
self.users = users
|
||||
print("DEBUG: users \(users)")
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -8,16 +8,19 @@
|
||||
import SwiftUI
|
||||
|
||||
struct ExploreView: View {
|
||||
@ObservedObject var viewModel = ExploreViewModel()
|
||||
|
||||
var body: some View {
|
||||
NavigationView {
|
||||
VStack {
|
||||
SearchBar(text: $viewModel.searchText)
|
||||
.padding()
|
||||
ScrollView {
|
||||
LazyVStack {
|
||||
ForEach(0...25, id: \.self) { _ in
|
||||
ForEach(viewModel.searchableUsers) { user in
|
||||
NavigationLink {
|
||||
// ProfileView()
|
||||
ProfileView(user: user)
|
||||
} label: {
|
||||
UserRowView()
|
||||
UserRowView(user: user)
|
||||
}
|
||||
|
||||
}
|
||||
@ -28,7 +31,6 @@ struct ExploreView: View {
|
||||
.navigationBarTitleDisplayMode(.inline)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct ExploreView_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
|
||||
@ -21,4 +21,18 @@ struct UserService {
|
||||
completion(user)
|
||||
}
|
||||
}
|
||||
|
||||
func fetchUsers(completion: @escaping ([User]) -> Void) {
|
||||
// var users = [User]()
|
||||
Firestore.firestore().collection("users")
|
||||
.getDocuments { snapshot, _ in
|
||||
guard let documents = snapshot?.documents else { return }
|
||||
// for document in documents {
|
||||
// guard let user = try? document.data(as: User.self) else { return }
|
||||
// users.append(user)
|
||||
// }
|
||||
let users = documents.compactMap({ try? $0.data(as: User.self) })
|
||||
completion(users)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user