feat(Model): 增加 User model,用获取到的 User 数据替换写死的数据
增加 User model,用获取到的 User 数据替换写死的数据 Signed-off-by: Ching <loooching@gmail.com>
This commit is contained in:
parent
3eb9b13f86
commit
62c6c6d2c5
@ -40,6 +40,9 @@
|
||||
24FA4D992A012A5D002D202A /* ProfilePhotoSelectorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24FA4D982A012A5D002D202A /* ProfilePhotoSelectorView.swift */; };
|
||||
24FA4D9C2A012E1A002D202A /* ImagePicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24FA4D9B2A012E1A002D202A /* ImagePicker.swift */; };
|
||||
24FA4D9E2A0134CB002D202A /* ImageUploader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24FA4D9D2A0134CB002D202A /* ImageUploader.swift */; };
|
||||
24FA4DA02A013B24002D202A /* UserService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24FA4D9F2A013B24002D202A /* UserService.swift */; };
|
||||
24FA4DA22A013D2E002D202A /* User.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24FA4DA12A013D2E002D202A /* User.swift */; };
|
||||
24FA4DA52A0142E2002D202A /* Kingfisher in Frameworks */ = {isa = PBXBuildFile; productRef = 24FA4DA42A0142E2002D202A /* Kingfisher */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
@ -74,6 +77,8 @@
|
||||
24FA4D982A012A5D002D202A /* ProfilePhotoSelectorView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfilePhotoSelectorView.swift; sourceTree = "<group>"; };
|
||||
24FA4D9B2A012E1A002D202A /* ImagePicker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImagePicker.swift; sourceTree = "<group>"; };
|
||||
24FA4D9D2A0134CB002D202A /* ImageUploader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageUploader.swift; sourceTree = "<group>"; };
|
||||
24FA4D9F2A013B24002D202A /* UserService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserService.swift; sourceTree = "<group>"; };
|
||||
24FA4DA12A013D2E002D202A /* User.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = User.swift; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
@ -85,6 +90,7 @@
|
||||
24A59AF82A010411009C9E3E /* FirebaseStorage in Frameworks */,
|
||||
24A59AF42A010411009C9E3E /* FirebaseFirestore in Frameworks */,
|
||||
24A59AF62A010411009C9E3E /* FirebaseFirestoreSwift in Frameworks */,
|
||||
24FA4DA52A0142E2002D202A /* Kingfisher in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@ -154,6 +160,7 @@
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
24FA4D9D2A0134CB002D202A /* ImageUploader.swift */,
|
||||
24FA4D9F2A013B24002D202A /* UserService.swift */,
|
||||
);
|
||||
path = Service;
|
||||
sourceTree = "<group>";
|
||||
@ -161,6 +168,7 @@
|
||||
2492CC1E2A0022970086C525 /* Model */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
24FA4DA12A013D2E002D202A /* User.swift */,
|
||||
);
|
||||
path = Model;
|
||||
sourceTree = "<group>";
|
||||
@ -413,6 +421,7 @@
|
||||
24A59AF32A010411009C9E3E /* FirebaseFirestore */,
|
||||
24A59AF52A010411009C9E3E /* FirebaseFirestoreSwift */,
|
||||
24A59AF72A010411009C9E3E /* FirebaseStorage */,
|
||||
24FA4DA42A0142E2002D202A /* Kingfisher */,
|
||||
);
|
||||
productName = "dudu-tweet";
|
||||
productReference = 2492CC092A000EB00086C525 /* dudu-tweet.app */;
|
||||
@ -444,6 +453,7 @@
|
||||
mainGroup = 2492CC002A000EB00086C525;
|
||||
packageReferences = (
|
||||
24A59AF02A010411009C9E3E /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */,
|
||||
24FA4DA32A0142E2002D202A /* XCRemoteSwiftPackageReference "Kingfisher" */,
|
||||
);
|
||||
productRefGroup = 2492CC0A2A000EB00086C525 /* Products */;
|
||||
projectDirPath = "";
|
||||
@ -474,6 +484,7 @@
|
||||
files = (
|
||||
24A59ABE2A003108009C9E3E /* MessagesView.swift in Sources */,
|
||||
24A59AC22A003249009C9E3E /* ProfileView.swift in Sources */,
|
||||
24FA4DA02A013B24002D202A /* UserService.swift in Sources */,
|
||||
24FA4D9C2A012E1A002D202A /* ImagePicker.swift in Sources */,
|
||||
2492CC0F2A000EB00086C525 /* ContentView.swift in Sources */,
|
||||
2492CC282A0025DD0086C525 /* TweetRowView.swift in Sources */,
|
||||
@ -491,6 +502,7 @@
|
||||
24A59AE42A00EF1F009C9E3E /* LoginView.swift in Sources */,
|
||||
24A59AE62A00EF3A009C9E3E /* RegistrationView.swift in Sources */,
|
||||
24A59ADD2A00DB9F009C9E3E /* NewTweetView.swift in Sources */,
|
||||
24FA4DA22A013D2E002D202A /* User.swift in Sources */,
|
||||
24A59AED2A00F942009C9E3E /* AuthHeaderView.swift in Sources */,
|
||||
24A59AFA2A01081F009C9E3E /* AuthViewModel.swift in Sources */,
|
||||
24A59AE82A00F106009C9E3E /* RoundedShape.swift in Sources */,
|
||||
@ -721,6 +733,14 @@
|
||||
minimumVersion = 9.0.0;
|
||||
};
|
||||
};
|
||||
24FA4DA32A0142E2002D202A /* XCRemoteSwiftPackageReference "Kingfisher" */ = {
|
||||
isa = XCRemoteSwiftPackageReference;
|
||||
repositoryURL = "https://github.com/onevcat/Kingfisher.git";
|
||||
requirement = {
|
||||
kind = upToNextMajorVersion;
|
||||
minimumVersion = 7.0.0;
|
||||
};
|
||||
};
|
||||
/* End XCRemoteSwiftPackageReference section */
|
||||
|
||||
/* Begin XCSwiftPackageProductDependency section */
|
||||
@ -744,6 +764,11 @@
|
||||
package = 24A59AF02A010411009C9E3E /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */;
|
||||
productName = FirebaseStorage;
|
||||
};
|
||||
24FA4DA42A0142E2002D202A /* Kingfisher */ = {
|
||||
isa = XCSwiftPackageProductDependency;
|
||||
package = 24FA4DA32A0142E2002D202A /* XCRemoteSwiftPackageReference "Kingfisher" */;
|
||||
productName = Kingfisher;
|
||||
};
|
||||
/* End XCSwiftPackageProductDependency section */
|
||||
};
|
||||
rootObject = 2492CC012A000EB00086C525 /* Project object */;
|
||||
|
||||
@ -72,6 +72,15 @@
|
||||
"version" : "2.3.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"identity" : "kingfisher",
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/onevcat/Kingfisher.git",
|
||||
"state" : {
|
||||
"revision" : "af4be924ad984cf4d16f4ae4df424e79a443d435",
|
||||
"version" : "7.6.2"
|
||||
}
|
||||
},
|
||||
{
|
||||
"identity" : "leveldb",
|
||||
"kind" : "remoteSourceControl",
|
||||
|
||||
Binary file not shown.
@ -6,6 +6,7 @@
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
import Kingfisher
|
||||
|
||||
struct ContentView: View {
|
||||
@State private var showMenu = false
|
||||
@ -58,16 +59,21 @@ extension ContentView {
|
||||
.navigationBarTitleDisplayMode(.inline)
|
||||
.toolbar {
|
||||
ToolbarItem(placement: .navigationBarLeading) {
|
||||
if let user = viewModel.currentUser {
|
||||
Button {
|
||||
withAnimation(.easeInOut) {
|
||||
showMenu.toggle()
|
||||
}
|
||||
} label: {
|
||||
Circle()
|
||||
KFImage(URL(string: user.profileImageUrl))
|
||||
.resizable()
|
||||
.scaledToFill()
|
||||
.clipShape(Circle())
|
||||
.frame(width: 32, height: 32)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.onAppear {
|
||||
showMenu = false
|
||||
}
|
||||
|
||||
@ -11,11 +11,14 @@ import SwiftUI
|
||||
class AuthViewModel: ObservableObject {
|
||||
@Published var userSession: FirebaseAuth.User?
|
||||
@Published var didAuthenticateUser = false
|
||||
@Published var currentUser: User?
|
||||
private var tempUserSession: FirebaseAuth.User?
|
||||
|
||||
private let service = UserService()
|
||||
|
||||
init() {
|
||||
self.userSession = Auth.auth().currentUser
|
||||
|
||||
self.fetchUser()
|
||||
print("DEBUG: user session is \(self.userSession?.uid)")
|
||||
}
|
||||
|
||||
@ -29,6 +32,7 @@ class AuthViewModel: ObservableObject {
|
||||
|
||||
guard let user = result?.user else { return }
|
||||
self.userSession = user
|
||||
self.fetchUser()
|
||||
|
||||
print("DEBUG: Did log user \(user.uid) in.")
|
||||
}
|
||||
@ -47,8 +51,7 @@ class AuthViewModel: ObservableObject {
|
||||
|
||||
let data = ["email": email,
|
||||
"username": username.lowercased(),
|
||||
"fullname": fullname,
|
||||
"uid": user.uid]
|
||||
"fullname": fullname]
|
||||
Firestore.firestore().collection("users")
|
||||
.document(user.uid)
|
||||
.setData(data) { _ in
|
||||
@ -71,7 +74,15 @@ class AuthViewModel: ObservableObject {
|
||||
.document(uid)
|
||||
.updateData(["profileImageUrl": profileImageUrl]) { _ in
|
||||
self.userSession = self.tempUserSession
|
||||
self.fetchUser()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func fetchUser() {
|
||||
guard let uid = self.userSession?.uid else { return }
|
||||
service.fetchUser(withUid: uid) { user in
|
||||
self.currentUser = user
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -15,7 +15,7 @@ struct ExploreView: View {
|
||||
LazyVStack {
|
||||
ForEach(0...25, id: \.self) { _ in
|
||||
NavigationLink {
|
||||
ProfileView()
|
||||
// ProfileView()
|
||||
} label: {
|
||||
UserRowView()
|
||||
}
|
||||
|
||||
@ -6,14 +6,20 @@
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
import Kingfisher
|
||||
|
||||
struct ProfileView: View {
|
||||
@State private var selectedFilter: TweetFilterViewModel = .tweets
|
||||
// @Environment(\.presentationMode) var mode // 用来从explore 页面跳转过来之后跳转回去
|
||||
@Environment(\.dismiss) private var dismiss
|
||||
private let user: User
|
||||
|
||||
@Namespace var animation
|
||||
|
||||
init(user: User) {
|
||||
self.user = user
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
VStack(alignment: .leading) {
|
||||
headerView
|
||||
@ -28,12 +34,17 @@ struct ProfileView: View {
|
||||
|
||||
Spacer()
|
||||
}
|
||||
.toolbar(.hidden)
|
||||
}
|
||||
}
|
||||
|
||||
struct ProfileView_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
ProfileView()
|
||||
ProfileView(user: User(id: NSUUID().uuidString,
|
||||
username: "zhang3",
|
||||
fullname: "张三",
|
||||
profileImageUrl: "",
|
||||
email: "zhang3@gmail.com"))
|
||||
}
|
||||
}
|
||||
|
||||
@ -51,10 +62,13 @@ extension ProfileView {
|
||||
.resizable()
|
||||
.frame(width: 20, height: 16)
|
||||
.foregroundColor(.white)
|
||||
.offset(x: 16, y: 0)
|
||||
.offset(x: 16, y: -4)
|
||||
}
|
||||
|
||||
Circle()
|
||||
KFImage(URL(string: user.profileImageUrl))
|
||||
.resizable()
|
||||
.scaledToFill()
|
||||
.clipShape(Circle())
|
||||
.frame(width: 72, height: 72)
|
||||
.offset(x: 16, y: 24)
|
||||
}
|
||||
@ -86,12 +100,12 @@ extension ProfileView {
|
||||
var userInfoDetails: some View {
|
||||
VStack(alignment: .leading, spacing: 4) {
|
||||
HStack {
|
||||
Text("Zhang San")
|
||||
Text(user.fullname)
|
||||
.font(.title2).bold()
|
||||
Image(systemName: "checkmark.seal.fill")
|
||||
.foregroundColor(Color(.systemBlue))
|
||||
}
|
||||
Text("@zhang3")
|
||||
Text("@\(user.username)")
|
||||
.font(.subheadline)
|
||||
.foregroundColor(.gray)
|
||||
Text("一个普通人")
|
||||
|
||||
@ -6,21 +6,26 @@
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
import Kingfisher
|
||||
|
||||
struct SideMenuView: View {
|
||||
|
||||
@EnvironmentObject var authViewModel: AuthViewModel
|
||||
|
||||
var body: some View {
|
||||
if let user = authViewModel.currentUser {
|
||||
VStack(alignment: .leading, spacing: 32) {
|
||||
VStack(alignment: .leading) {
|
||||
Circle()
|
||||
KFImage(URL(string: user.profileImageUrl))
|
||||
.resizable()
|
||||
.scaledToFill()
|
||||
.clipShape(Circle())
|
||||
.frame(width: 48, height: 48)
|
||||
|
||||
VStack(alignment: .leading, spacing: 4) {
|
||||
Text("张三")
|
||||
Text(user.fullname)
|
||||
.font(.headline)
|
||||
Text("@zhang3")
|
||||
Text("@\(user.username)")
|
||||
.font(.caption)
|
||||
.foregroundColor(.gray)
|
||||
}
|
||||
@ -33,7 +38,7 @@ struct SideMenuView: View {
|
||||
ForEach(SideMenuViewModel.allCases, id: \.rawValue) { viewModel in
|
||||
if viewModel == .profile {
|
||||
NavigationLink {
|
||||
ProfileView()
|
||||
ProfileView(user: user)
|
||||
} label: {
|
||||
SideMenuOptionRowView(viewModel: viewModel)
|
||||
}
|
||||
@ -53,6 +58,7 @@ struct SideMenuView: View {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct SideMenuView_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
|
||||
16
dudu-tweet/dudu-tweet/Model/User.swift
Normal file
16
dudu-tweet/dudu-tweet/Model/User.swift
Normal file
@ -0,0 +1,16 @@
|
||||
//
|
||||
// User.swift
|
||||
// dudu-tweet
|
||||
//
|
||||
// Created by ching on 2023/5/2.
|
||||
//
|
||||
|
||||
import FirebaseFirestoreSwift
|
||||
|
||||
struct User: Identifiable, Decodable {
|
||||
@DocumentID var id: String?
|
||||
let username: String
|
||||
let fullname: String
|
||||
let profileImageUrl: String
|
||||
let email: String
|
||||
}
|
||||
24
dudu-tweet/dudu-tweet/Service/UserService.swift
Normal file
24
dudu-tweet/dudu-tweet/Service/UserService.swift
Normal file
@ -0,0 +1,24 @@
|
||||
//
|
||||
// UserService.swift
|
||||
// dudu-tweet
|
||||
//
|
||||
// Created by ching on 2023/5/2.
|
||||
//
|
||||
|
||||
import Firebase
|
||||
import FirebaseFirestoreSwift
|
||||
|
||||
struct UserService {
|
||||
func fetchUser(withUid uid: String, completion: @escaping(User) -> Void) {
|
||||
print("DEBUG: Fetching user info..")
|
||||
Firestore.firestore().collection("users")
|
||||
.document(uid)
|
||||
.getDocument { snapshot, _ in
|
||||
guard let snapshot = snapshot else { return }
|
||||
guard let user = try? snapshot.data(as: User.self) else { return }
|
||||
print("DEBUG: Username is \(user.username)")
|
||||
print("DEBUG: User id is \(user.id)")
|
||||
completion(user)
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user