diff --git a/dudu-tweet/dudu-tweet.xcodeproj/project.pbxproj b/dudu-tweet/dudu-tweet.xcodeproj/project.pbxproj index c319e70..3fe972a 100644 --- a/dudu-tweet/dudu-tweet.xcodeproj/project.pbxproj +++ b/dudu-tweet/dudu-tweet.xcodeproj/project.pbxproj @@ -19,6 +19,11 @@ 24A59ABE2A003108009C9E3E /* MessagesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24A59ABD2A003108009C9E3E /* MessagesView.swift */; }; 24A59AC22A003249009C9E3E /* ProfileView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24A59AC12A003249009C9E3E /* ProfileView.swift */; }; 24A59AC42A003A52009C9E3E /* TwewtFilterViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24A59AC32A003A52009C9E3E /* TwewtFilterViewModel.swift */; }; + 24A59AC92A00BA81009C9E3E /* UserRowView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24A59AC82A00BA81009C9E3E /* UserRowView.swift */; }; + 24A59ACE2A00BDCB009C9E3E /* SideMenuView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24A59ACD2A00BDCB009C9E3E /* SideMenuView.swift */; }; + 24A59AD22A00BE14009C9E3E /* SideMenuViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24A59AD12A00BE14009C9E3E /* SideMenuViewModel.swift */; }; + 24A59AD42A00C07D009C9E3E /* UserStatsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24A59AD32A00C07D009C9E3E /* UserStatsView.swift */; }; + 24A59AD62A00CA82009C9E3E /* SideMenuOptionRowView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24A59AD52A00CA82009C9E3E /* SideMenuOptionRowView.swift */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ @@ -36,6 +41,11 @@ 24A59ABD2A003108009C9E3E /* MessagesView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessagesView.swift; sourceTree = ""; }; 24A59AC12A003249009C9E3E /* ProfileView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileView.swift; sourceTree = ""; }; 24A59AC32A003A52009C9E3E /* TwewtFilterViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TwewtFilterViewModel.swift; sourceTree = ""; }; + 24A59AC82A00BA81009C9E3E /* UserRowView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserRowView.swift; sourceTree = ""; }; + 24A59ACD2A00BDCB009C9E3E /* SideMenuView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SideMenuView.swift; sourceTree = ""; }; + 24A59AD12A00BE14009C9E3E /* SideMenuViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SideMenuViewModel.swift; sourceTree = ""; }; + 24A59AD32A00C07D009C9E3E /* UserStatsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserStatsView.swift; sourceTree = ""; }; + 24A59AD52A00CA82009C9E3E /* SideMenuOptionRowView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SideMenuOptionRowView.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -92,6 +102,7 @@ 2492CC1B2A00228F0086C525 /* Core */ = { isa = PBXGroup; children = ( + 24A59ACA2A00BDA1009C9E3E /* SideMenu */, 2492CC212A0022C30086C525 /* Components */, 24A59AB82A00308E009C9E3E /* Profile */, 24A59AB72A00305E009C9E3E /* Explore */, @@ -136,6 +147,7 @@ 2492CC212A0022C30086C525 /* Components */ = { isa = PBXGroup; children = ( + 24A59AC72A00BA6A009C9E3E /* Users */, 2492CC262A0025A50086C525 /* Tweets */, ); path = Components; @@ -191,7 +203,8 @@ 24A59AB72A00305E009C9E3E /* Explore */ = { isa = PBXGroup; children = ( - 24A59AB92A0030CB009C9E3E /* ExploreView.swift */, + 24A59AC62A00BA47009C9E3E /* Views */, + 24A59AC52A00BA3A009C9E3E /* ViewModels */, ); path = Explore; sourceTree = ""; @@ -221,6 +234,56 @@ path = ViewModels; sourceTree = ""; }; + 24A59AC52A00BA3A009C9E3E /* ViewModels */ = { + isa = PBXGroup; + children = ( + ); + path = ViewModels; + sourceTree = ""; + }; + 24A59AC62A00BA47009C9E3E /* Views */ = { + isa = PBXGroup; + children = ( + 24A59AB92A0030CB009C9E3E /* ExploreView.swift */, + ); + path = Views; + sourceTree = ""; + }; + 24A59AC72A00BA6A009C9E3E /* Users */ = { + isa = PBXGroup; + children = ( + 24A59AC82A00BA81009C9E3E /* UserRowView.swift */, + 24A59AD32A00C07D009C9E3E /* UserStatsView.swift */, + ); + path = Users; + sourceTree = ""; + }; + 24A59ACA2A00BDA1009C9E3E /* SideMenu */ = { + isa = PBXGroup; + children = ( + 24A59ACC2A00BDB7009C9E3E /* ViewModels */, + 24A59ACB2A00BDAF009C9E3E /* Views */, + ); + path = SideMenu; + sourceTree = ""; + }; + 24A59ACB2A00BDAF009C9E3E /* Views */ = { + isa = PBXGroup; + children = ( + 24A59ACD2A00BDCB009C9E3E /* SideMenuView.swift */, + 24A59AD52A00CA82009C9E3E /* SideMenuOptionRowView.swift */, + ); + path = Views; + sourceTree = ""; + }; + 24A59ACC2A00BDB7009C9E3E /* ViewModels */ = { + isa = PBXGroup; + children = ( + 24A59AD12A00BE14009C9E3E /* SideMenuViewModel.swift */, + ); + path = ViewModels; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -297,10 +360,15 @@ 2492CC282A0025DD0086C525 /* TweetRowView.swift in Sources */, 24A59AC42A003A52009C9E3E /* TwewtFilterViewModel.swift in Sources */, 2492CC252A0023220086C525 /* FeedView.swift in Sources */, + 24A59ACE2A00BDCB009C9E3E /* SideMenuView.swift in Sources */, 2492CC0D2A000EB00086C525 /* dudu_tweetApp.swift in Sources */, 24A59ABA2A0030CB009C9E3E /* ExploreView.swift in Sources */, + 24A59AD22A00BE14009C9E3E /* SideMenuViewModel.swift in Sources */, + 24A59AD62A00CA82009C9E3E /* SideMenuOptionRowView.swift in Sources */, + 24A59AC92A00BA81009C9E3E /* UserRowView.swift in Sources */, 24A59AB42A002EB8009C9E3E /* MainTabView.swift in Sources */, 24A59ABC2A0030EC009C9E3E /* NotificationsView.swift in Sources */, + 24A59AD42A00C07D009C9E3E /* UserStatsView.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/dudu-tweet/dudu-tweet.xcodeproj/project.xcworkspace/xcuserdata/ching.xcuserdatad/UserInterfaceState.xcuserstate b/dudu-tweet/dudu-tweet.xcodeproj/project.xcworkspace/xcuserdata/ching.xcuserdatad/UserInterfaceState.xcuserstate index 59eb79c..514da77 100644 Binary files a/dudu-tweet/dudu-tweet.xcodeproj/project.xcworkspace/xcuserdata/ching.xcuserdatad/UserInterfaceState.xcuserstate and b/dudu-tweet/dudu-tweet.xcodeproj/project.xcworkspace/xcuserdata/ching.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/dudu-tweet/dudu-tweet/ContentView.swift b/dudu-tweet/dudu-tweet/ContentView.swift index 85e63e6..3f35151 100644 --- a/dudu-tweet/dudu-tweet/ContentView.swift +++ b/dudu-tweet/dudu-tweet/ContentView.swift @@ -8,14 +8,47 @@ import SwiftUI struct ContentView: View { + @State private var showMenu = false + var body: some View { - VStack { - Image(systemName: "globe") - .imageScale(.large) - .foregroundColor(.accentColor) - Text("Hello, world!") + ZStack(alignment: .topLeading) { + MainTabView() + .navigationBarHidden(showMenu) + + if showMenu { + ZStack { + Color(.black) + .opacity(showMenu ? 0.25 : 0.0) + }.onTapGesture { + withAnimation(.easeInOut) { + showMenu = false + } + } + .ignoresSafeArea() + } + + SideMenuView() + .frame(width: 300) + .offset(x: showMenu ? 0: -300, y: 0) + .background(showMenu ? Color.white: Color.clear) + } + .navigationTitle("Home") + .navigationBarTitleDisplayMode(.inline) + .toolbar { + ToolbarItem(placement: .navigationBarLeading) { + Button { + withAnimation(.easeInOut) { + showMenu.toggle() + } + } label: { + Circle() + .frame(width: 32, height: 32) + } + } + } + .onAppear { + showMenu = false } - .padding() } } diff --git a/dudu-tweet/dudu-tweet/Core/Components/Users/UserRowView.swift b/dudu-tweet/dudu-tweet/Core/Components/Users/UserRowView.swift new file mode 100644 index 0000000..3a807a3 --- /dev/null +++ b/dudu-tweet/dudu-tweet/Core/Components/Users/UserRowView.swift @@ -0,0 +1,34 @@ +// +// UserRowView.swift +// dudu-tweet +// +// Created by ching on 2023/5/2. +// + +import SwiftUI + +struct UserRowView: View { + var body: some View { + HStack(spacing: 12) { + Circle() + .frame(width: 48, height: 48) + VStack(alignment: .leading, spacing: 4) { + Text("Lith") + .font(.subheadline).bold() + .foregroundColor(.black) + Text("李四") + .font(.subheadline) + .foregroundColor(.gray) + } + Spacer() + } + .padding(.horizontal) + .padding(.vertical, 4) + } +} + +struct UserRowView_Previews: PreviewProvider { + static var previews: some View { + UserRowView() + } +} diff --git a/dudu-tweet/dudu-tweet/Core/Components/Users/UserStatsView.swift b/dudu-tweet/dudu-tweet/Core/Components/Users/UserStatsView.swift new file mode 100644 index 0000000..a53cc57 --- /dev/null +++ b/dudu-tweet/dudu-tweet/Core/Components/Users/UserStatsView.swift @@ -0,0 +1,37 @@ +// +// UserStatsView.swift +// dudu-tweet +// +// Created by ching on 2023/5/2. +// + +import SwiftUI + +struct UserStatsView: View { + var body: some View { + HStack(spacing: 24) { + HStack(spacing: 4) { + Text("13214") + .bold() + .font(.subheadline) + Text("Following") + .font(.caption) + .foregroundColor(.gray) + } + HStack(spacing: 4) { + Text("995353") + .bold() + .font(.subheadline) + Text("Followers") + .font(.caption) + .foregroundColor(.gray) + } + } + } +} + +struct UserStatsView_Previews: PreviewProvider { + static var previews: some View { + UserStatsView() + } +} diff --git a/dudu-tweet/dudu-tweet/Core/Explore/ExploreView.swift b/dudu-tweet/dudu-tweet/Core/Explore/ExploreView.swift deleted file mode 100644 index 55c5bd5..0000000 --- a/dudu-tweet/dudu-tweet/Core/Explore/ExploreView.swift +++ /dev/null @@ -1,20 +0,0 @@ -// -// ExploreView.swift -// dudu-tweet -// -// Created by ching on 2023/5/2. -// - -import SwiftUI - -struct ExploreView: View { - var body: some View { - Text("Explore view") - } -} - -struct ExploreView_Previews: PreviewProvider { - static var previews: some View { - ExploreView() - } -} diff --git a/dudu-tweet/dudu-tweet/Core/Explore/Views/ExploreView.swift b/dudu-tweet/dudu-tweet/Core/Explore/Views/ExploreView.swift new file mode 100644 index 0000000..86c6358 --- /dev/null +++ b/dudu-tweet/dudu-tweet/Core/Explore/Views/ExploreView.swift @@ -0,0 +1,37 @@ +// +// ExploreView.swift +// dudu-tweet +// +// Created by ching on 2023/5/2. +// + +import SwiftUI + +struct ExploreView: View { + var body: some View { + NavigationView { + VStack { + ScrollView { + LazyVStack { + ForEach(0...25, id: \.self) { _ in + NavigationLink { + ProfileView() + } label: { + UserRowView() + } + + } + } + } + } + .navigationTitle("Explore") + .navigationBarTitleDisplayMode(.inline) + } + } +} + +struct ExploreView_Previews: PreviewProvider { + static var previews: some View { + ExploreView() + } +} diff --git a/dudu-tweet/dudu-tweet/Core/Profile/Views/ProfileView.swift b/dudu-tweet/dudu-tweet/Core/Profile/Views/ProfileView.swift index 60d6a83..0d2a171 100644 --- a/dudu-tweet/dudu-tweet/Core/Profile/Views/ProfileView.swift +++ b/dudu-tweet/dudu-tweet/Core/Profile/Views/ProfileView.swift @@ -9,6 +9,7 @@ import SwiftUI struct ProfileView: View { @State private var selectedFilter: TweetFilterViewModel = .tweets + @Environment(\.presentationMode) var mode // 用来从explore 页面跳转过来之后跳转回去 @Namespace var animation var body: some View { @@ -41,13 +42,13 @@ extension ProfileView { .ignoresSafeArea() VStack { Button { - // action here + mode.wrappedValue.dismiss() } label: { Image(systemName: "arrow.left") .resizable() .frame(width: 20, height: 16) .foregroundColor(.white) - .offset(x: 16, y: 12) + .offset(x: 16, y: 0) } Circle() @@ -107,25 +108,8 @@ extension ProfileView { .foregroundColor(.gray) .font(.caption) - HStack(spacing: 24) { - HStack(spacing: 4) { - Text("13214") - .bold() - .font(.subheadline) - Text("Following") - .font(.caption) - .foregroundColor(.gray) - } - HStack(spacing: 4) { - Text("995353") - .bold() - .font(.subheadline) - Text("Followers") - .font(.caption) - .foregroundColor(.gray) - } - } - .padding(.vertical) + UserStatsView() + .padding(.vertical) } .padding(.horizontal) } diff --git a/dudu-tweet/dudu-tweet/Core/SideMenu/ViewModels/SideMenuViewModel.swift b/dudu-tweet/dudu-tweet/Core/SideMenu/ViewModels/SideMenuViewModel.swift new file mode 100644 index 0000000..839d86c --- /dev/null +++ b/dudu-tweet/dudu-tweet/Core/SideMenu/ViewModels/SideMenuViewModel.swift @@ -0,0 +1,33 @@ +// +// SideMenuViewModel.swift +// dudu-tweet +// +// Created by ching on 2023/5/2. +// + +import Foundation + +enum SideMenuViewModel: Int, CaseIterable { + case profile + case lists + case bookmarks + case logout + + var title: String { + switch self { + case .profile: return "Profile" + case .lists: return "Lists" + case .bookmarks: return "Bookmarks" + case .logout: return "Logout" + } + } + + var imageName: String { + switch self { + case .profile: return "person" + case .lists: return "list.bullet" + case .bookmarks: return "bookmark" + case .logout: return "arrow.left.square" + } + } +} diff --git a/dudu-tweet/dudu-tweet/Core/SideMenu/Views/SideMenuOptionRowView.swift b/dudu-tweet/dudu-tweet/Core/SideMenu/Views/SideMenuOptionRowView.swift new file mode 100644 index 0000000..f444c80 --- /dev/null +++ b/dudu-tweet/dudu-tweet/Core/SideMenu/Views/SideMenuOptionRowView.swift @@ -0,0 +1,34 @@ +// +// SideMenuOptionRowView.swift +// dudu-tweet +// +// Created by ching on 2023/5/2. +// + +import SwiftUI + +struct SideMenuOptionRowView: View { + let viewModel: SideMenuViewModel + + var body: some View { + HStack(spacing:16) { + Image(systemName: viewModel.imageName) + .font(.headline) + .foregroundColor(.gray) + + Text(viewModel.title) + .font(.subheadline) + .foregroundColor(.black) + + Spacer() + } + .frame(height: 40) + .padding(.horizontal) + } +} + +struct SideMenuOptionRowView_Previews: PreviewProvider { + static var previews: some View { + SideMenuOptionRowView(viewModel: .profile) + } +} diff --git a/dudu-tweet/dudu-tweet/Core/SideMenu/Views/SideMenuView.swift b/dudu-tweet/dudu-tweet/Core/SideMenu/Views/SideMenuView.swift new file mode 100644 index 0000000..9805826 --- /dev/null +++ b/dudu-tweet/dudu-tweet/Core/SideMenu/Views/SideMenuView.swift @@ -0,0 +1,58 @@ +// +// SideMenuView.swift +// dudu-tweet +// +// Created by ching on 2023/5/2. +// + +import SwiftUI + +struct SideMenuView: View { + var body: some View { + VStack(alignment: .leading, spacing: 32) { + VStack(alignment: .leading) { + Circle() + .frame(width: 48, height: 48) + + VStack(alignment: .leading, spacing: 4) { + Text("张三") + .font(.headline) + Text("@zhang3") + .font(.caption) + .foregroundColor(.gray) + } + + UserStatsView() + .padding(.vertical) + } + .padding(.leading) + + ForEach(SideMenuViewModel.allCases, id: \.rawValue) { viewModel in + if viewModel == .profile { + NavigationLink { + ProfileView() + } label: { + SideMenuOptionRowView(viewModel: viewModel) + } + } else if viewModel == .logout { + Button { + print("handle logout here") + } label: { + SideMenuOptionRowView(viewModel: viewModel) + } + + } else { + SideMenuOptionRowView(viewModel: viewModel) + } + } + + Spacer() + } + } +} + +struct SideMenuView_Previews: PreviewProvider { + static var previews: some View { + SideMenuView() + } +} diff --git a/dudu-tweet/dudu-tweet/dudu_tweetApp.swift b/dudu-tweet/dudu-tweet/dudu_tweetApp.swift index fb30812..71deafd 100644 --- a/dudu-tweet/dudu-tweet/dudu_tweetApp.swift +++ b/dudu-tweet/dudu-tweet/dudu_tweetApp.swift @@ -11,7 +11,9 @@ import SwiftUI struct dudu_tweetApp: App { var body: some Scene { WindowGroup { - MainTabView() + NavigationView { + ContentView() + } } } }