feat(Views): 增加 login page 和 registration page

增加 login page 和 registration page

Signed-off-by: Ching <loooching@gmail.com>
This commit is contained in:
Ching 2023-05-02 16:17:17 +08:00
parent 3356aec1cd
commit 25dfd09568
11 changed files with 327 additions and 5 deletions

View File

@ -26,6 +26,11 @@
24A59AD62A00CA82009C9E3E /* SideMenuOptionRowView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24A59AD52A00CA82009C9E3E /* SideMenuOptionRowView.swift */; }; 24A59AD62A00CA82009C9E3E /* SideMenuOptionRowView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24A59AD52A00CA82009C9E3E /* SideMenuOptionRowView.swift */; };
24A59ADD2A00DB9F009C9E3E /* NewTweetView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24A59ADC2A00DB9F009C9E3E /* NewTweetView.swift */; }; 24A59ADD2A00DB9F009C9E3E /* NewTweetView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24A59ADC2A00DB9F009C9E3E /* NewTweetView.swift */; };
24A59ADF2A00DCC2009C9E3E /* TextArea.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24A59ADE2A00DCC2009C9E3E /* TextArea.swift */; }; 24A59ADF2A00DCC2009C9E3E /* TextArea.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24A59ADE2A00DCC2009C9E3E /* TextArea.swift */; };
24A59AE42A00EF1F009C9E3E /* LoginView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24A59AE32A00EF1F009C9E3E /* LoginView.swift */; };
24A59AE62A00EF3A009C9E3E /* RegistrationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24A59AE52A00EF3A009C9E3E /* RegistrationView.swift */; };
24A59AE82A00F106009C9E3E /* RoundedShape.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24A59AE72A00F106009C9E3E /* RoundedShape.swift */; };
24A59AEA2A00F672009C9E3E /* CustomInputField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24A59AE92A00F672009C9E3E /* CustomInputField.swift */; };
24A59AED2A00F942009C9E3E /* AuthHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24A59AEC2A00F942009C9E3E /* AuthHeaderView.swift */; };
/* End PBXBuildFile section */ /* End PBXBuildFile section */
/* Begin PBXFileReference section */ /* Begin PBXFileReference section */
@ -50,6 +55,11 @@
24A59AD52A00CA82009C9E3E /* SideMenuOptionRowView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SideMenuOptionRowView.swift; sourceTree = "<group>"; }; 24A59AD52A00CA82009C9E3E /* SideMenuOptionRowView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SideMenuOptionRowView.swift; sourceTree = "<group>"; };
24A59ADC2A00DB9F009C9E3E /* NewTweetView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewTweetView.swift; sourceTree = "<group>"; }; 24A59ADC2A00DB9F009C9E3E /* NewTweetView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewTweetView.swift; sourceTree = "<group>"; };
24A59ADE2A00DCC2009C9E3E /* TextArea.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextArea.swift; sourceTree = "<group>"; }; 24A59ADE2A00DCC2009C9E3E /* TextArea.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextArea.swift; sourceTree = "<group>"; };
24A59AE32A00EF1F009C9E3E /* LoginView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginView.swift; sourceTree = "<group>"; };
24A59AE52A00EF3A009C9E3E /* RegistrationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RegistrationView.swift; sourceTree = "<group>"; };
24A59AE72A00F106009C9E3E /* RoundedShape.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoundedShape.swift; sourceTree = "<group>"; };
24A59AE92A00F672009C9E3E /* CustomInputField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomInputField.swift; sourceTree = "<group>"; };
24A59AEC2A00F942009C9E3E /* AuthHeaderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthHeaderView.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */ /* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */ /* Begin PBXFrameworksBuildPhase section */
@ -106,6 +116,7 @@
2492CC1B2A00228F0086C525 /* Core */ = { 2492CC1B2A00228F0086C525 /* Core */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
24A59AE02A00EEE8009C9E3E /* Authentication */,
24A59AD72A00DB49009C9E3E /* UploadTweet */, 24A59AD72A00DB49009C9E3E /* UploadTweet */,
24A59ACA2A00BDA1009C9E3E /* SideMenu */, 24A59ACA2A00BDA1009C9E3E /* SideMenu */,
2492CC212A0022C30086C525 /* Components */, 2492CC212A0022C30086C525 /* Components */,
@ -152,9 +163,12 @@
2492CC212A0022C30086C525 /* Components */ = { 2492CC212A0022C30086C525 /* Components */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
24A59AEB2A00F92D009C9E3E /* Authentication */,
24A59AC72A00BA6A009C9E3E /* Users */, 24A59AC72A00BA6A009C9E3E /* Users */,
2492CC262A0025A50086C525 /* Tweets */, 2492CC262A0025A50086C525 /* Tweets */,
24A59ADE2A00DCC2009C9E3E /* TextArea.swift */, 24A59ADE2A00DCC2009C9E3E /* TextArea.swift */,
24A59AE72A00F106009C9E3E /* RoundedShape.swift */,
24A59AE92A00F672009C9E3E /* CustomInputField.swift */,
); );
path = Components; path = Components;
sourceTree = "<group>"; sourceTree = "<group>";
@ -314,6 +328,39 @@
path = ViewModels; path = ViewModels;
sourceTree = "<group>"; sourceTree = "<group>";
}; };
24A59AE02A00EEE8009C9E3E /* Authentication */ = {
isa = PBXGroup;
children = (
24A59AE22A00EEF8009C9E3E /* ViewModels */,
24A59AE12A00EEF0009C9E3E /* Views */,
);
path = Authentication;
sourceTree = "<group>";
};
24A59AE12A00EEF0009C9E3E /* Views */ = {
isa = PBXGroup;
children = (
24A59AE32A00EF1F009C9E3E /* LoginView.swift */,
24A59AE52A00EF3A009C9E3E /* RegistrationView.swift */,
);
path = Views;
sourceTree = "<group>";
};
24A59AE22A00EEF8009C9E3E /* ViewModels */ = {
isa = PBXGroup;
children = (
);
path = ViewModels;
sourceTree = "<group>";
};
24A59AEB2A00F92D009C9E3E /* Authentication */ = {
isa = PBXGroup;
children = (
24A59AEC2A00F942009C9E3E /* AuthHeaderView.swift */,
);
path = Authentication;
sourceTree = "<group>";
};
/* End PBXGroup section */ /* End PBXGroup section */
/* Begin PBXNativeTarget section */ /* Begin PBXNativeTarget section */
@ -388,6 +435,7 @@
24A59AC22A003249009C9E3E /* ProfileView.swift in Sources */, 24A59AC22A003249009C9E3E /* ProfileView.swift in Sources */,
2492CC0F2A000EB00086C525 /* ContentView.swift in Sources */, 2492CC0F2A000EB00086C525 /* ContentView.swift in Sources */,
2492CC282A0025DD0086C525 /* TweetRowView.swift in Sources */, 2492CC282A0025DD0086C525 /* TweetRowView.swift in Sources */,
24A59AEA2A00F672009C9E3E /* CustomInputField.swift in Sources */,
24A59AC42A003A52009C9E3E /* TwewtFilterViewModel.swift in Sources */, 24A59AC42A003A52009C9E3E /* TwewtFilterViewModel.swift in Sources */,
2492CC252A0023220086C525 /* FeedView.swift in Sources */, 2492CC252A0023220086C525 /* FeedView.swift in Sources */,
24A59ACE2A00BDCB009C9E3E /* SideMenuView.swift in Sources */, 24A59ACE2A00BDCB009C9E3E /* SideMenuView.swift in Sources */,
@ -396,7 +444,11 @@
24A59AD22A00BE14009C9E3E /* SideMenuViewModel.swift in Sources */, 24A59AD22A00BE14009C9E3E /* SideMenuViewModel.swift in Sources */,
24A59ADF2A00DCC2009C9E3E /* TextArea.swift in Sources */, 24A59ADF2A00DCC2009C9E3E /* TextArea.swift in Sources */,
24A59AD62A00CA82009C9E3E /* SideMenuOptionRowView.swift in Sources */, 24A59AD62A00CA82009C9E3E /* SideMenuOptionRowView.swift in Sources */,
24A59AE42A00EF1F009C9E3E /* LoginView.swift in Sources */,
24A59AE62A00EF3A009C9E3E /* RegistrationView.swift in Sources */,
24A59ADD2A00DB9F009C9E3E /* NewTweetView.swift in Sources */, 24A59ADD2A00DB9F009C9E3E /* NewTweetView.swift in Sources */,
24A59AED2A00F942009C9E3E /* AuthHeaderView.swift in Sources */,
24A59AE82A00F106009C9E3E /* RoundedShape.swift in Sources */,
24A59AC92A00BA81009C9E3E /* UserRowView.swift in Sources */, 24A59AC92A00BA81009C9E3E /* UserRowView.swift in Sources */,
24A59AB42A002EB8009C9E3E /* MainTabView.swift in Sources */, 24A59AB42A002EB8009C9E3E /* MainTabView.swift in Sources */,
24A59ABC2A0030EC009C9E3E /* NotificationsView.swift in Sources */, 24A59ABC2A0030EC009C9E3E /* NotificationsView.swift in Sources */,

View File

@ -13,7 +13,8 @@ struct ContentView: View {
var body: some View { var body: some View {
ZStack(alignment: .topLeading) { ZStack(alignment: .topLeading) {
MainTabView() MainTabView()
.navigationBarHidden(showMenu) // .navigationBarHidden(showMenu)
.toolbar(showMenu ? .hidden : .visible)
if showMenu { if showMenu {
ZStack { ZStack {

View File

@ -0,0 +1,87 @@
//
// LoginView.swift
// dudu-tweet
//
// Created by ching on 2023/5/2.
//
import SwiftUI
struct LoginView: View {
@State private var email = ""
@State private var password = ""
var body: some View {
VStack {
AuthHeaderView(title1: "Hello.", title2: "Welcome Back")
VStack(spacing: 40) {
CustomInputField(imageName: "envelope",
palceholderText: "Email",
text: $email)
CustomInputField(imageName: "lock",
palceholderText: "Password",
text: $password)
}
.padding(.horizontal, 32)
.padding(.top, 44)
HStack {
Spacer()
NavigationLink {
Text("Reset password view")
} label: {
Text("Forgot Password?")
.font(.caption)
.fontWeight(.bold)
.foregroundColor(Color(.systemBlue))
.padding(.top)
.padding(.trailing, 24)
}
}
Button {
print("Sign in here")
} label: {
Text("Sign In")
.font(.headline)
.foregroundColor(.white)
.frame(width: 340, height: 50)
.background(Color(.systemBlue))
.clipShape(Capsule())
.padding()
}
.shadow(color: .gray.opacity(0.5), radius: 10, x:0, y:0)
Spacer()
NavigationLink {
RegistrationView()
// .navigationBarHidden(true)
.toolbar(.hidden)
} label: {
HStack {
Text("Don't have an account?")
.font(.footnote)
Text("Sign Up")
.font(.footnote)
.fontWeight(.semibold)
}
}
.padding(.bottom, 32)
.foregroundColor(Color(.systemBlue))
}
.ignoresSafeArea()
// .navigationBarHidden(true)
.toolbar(.hidden)
}
}
struct LoginView_Previews: PreviewProvider {
static var previews: some View {
LoginView()
}
}

View File

@ -0,0 +1,80 @@
//
// RegistrationView.swift
// dudu-tweet
//
// Created by ching on 2023/5/2.
//
import SwiftUI
struct RegistrationView: View {
@State private var email = ""
@State private var username = ""
@State private var fullname = ""
@State private var password = ""
// @Environment(\.presentationMode) var presentationMode
@Environment(\.dismiss) private var dismiss
var body: some View {
VStack {
AuthHeaderView(title1: "Get started.",
title2: "Create your account")
VStack(spacing: 40) {
CustomInputField(imageName: "envelope",
palceholderText: "Email",
text: $email)
CustomInputField(imageName: "person",
palceholderText: "Username",
text: $username)
CustomInputField(imageName: "person",
palceholderText: "Full Name",
text: $fullname)
CustomInputField(imageName: "lock",
palceholderText: "Password",
text: $password)
}
.padding(32)
Button {
print("Sign up here")
} label: {
Text("Sign Up")
.font(.headline)
.foregroundColor(.white)
.frame(width: 340, height: 50)
.background(Color(.systemBlue))
.clipShape(Capsule())
.padding()
}
.shadow(color: .gray.opacity(0.5), radius: 10, x: 0, y: 0)
Spacer()
Button {
dismiss()
} label: {
HStack {
Text("Already have an account?")
.font(.footnote)
Text("Sign In")
.font(.footnote)
.fontWeight(.semibold)
}
}
.padding(.bottom, 32)
}
.ignoresSafeArea()
}
}
struct RegistrationView_Previews: PreviewProvider {
static var previews: some View {
RegistrationView()
}
}

View File

@ -0,0 +1,40 @@
//
// AuthHeaderView.swift
// dudu-tweet
//
// Created by ching on 2023/5/2.
//
import SwiftUI
struct AuthHeaderView: View {
let title1: String
let title2: String
var body: some View {
VStack(alignment: .leading) {
HStack {Spacer()}
Text(title1)
.font(.largeTitle)
.fontWeight(.semibold)
Text(title2)
.font(.largeTitle)
.fontWeight(.semibold)
}
.frame(height: 260)
.padding(.leading)
.background(Color(.systemBlue))
.foregroundColor(.white)
.clipShape(RoundedShape(corners: [.bottomRight]))
}
}
struct AuthenticationHeader_Previews: PreviewProvider {
static var previews: some View {
AuthHeaderView(title1: "hello,", title2: "world")
}
}

View File

@ -0,0 +1,38 @@
//
// CustomInputField.swift
// dudu-tweet
//
// Created by ching on 2023/5/2.
//
import SwiftUI
struct CustomInputField: View {
let imageName: String
let palceholderText: String
@Binding var text: String
var body: some View {
VStack {
HStack {
Image(systemName: imageName)
.resizable()
.scaledToFit()
.frame(width: 20, height: 20)
.foregroundColor(Color(.darkGray))
TextField(palceholderText, text: $text)
}
Divider()
.background(Color(.darkGray))
}
}
}
struct CustomInputField_Previews: PreviewProvider {
static var previews: some View {
CustomInputField(imageName: "envelope", palceholderText: "Email", text: .constant(""))
}
}

View File

@ -0,0 +1,17 @@
//
// RoundedShape.swift
// dudu-tweet
//
// Created by ching on 2023/5/2.
//
import SwiftUI
struct RoundedShape: Shape {
var corners: UIRectCorner
func path(in rect: CGRect) -> Path {
let path = UIBezierPath(roundedRect: rect, byRoundingCorners: corners, cornerRadii: CGSize(width: 80, height: 80))
return Path(path.cgPath)
}
}

View File

@ -9,7 +9,9 @@ import SwiftUI
struct ProfileView: View { struct ProfileView: View {
@State private var selectedFilter: TweetFilterViewModel = .tweets @State private var selectedFilter: TweetFilterViewModel = .tweets
@Environment(\.presentationMode) var mode // explore // @Environment(\.presentationMode) var mode // explore
@Environment(\.dismiss) private var dismiss
@Namespace var animation @Namespace var animation
var body: some View { var body: some View {
@ -42,7 +44,8 @@ extension ProfileView {
.ignoresSafeArea() .ignoresSafeArea()
VStack { VStack {
Button { Button {
mode.wrappedValue.dismiss() // mode.wrappedValue.dismiss()
dismiss()
} label: { } label: {
Image(systemName: "arrow.left") Image(systemName: "arrow.left")
.resizable() .resizable()

View File

@ -9,12 +9,15 @@ import SwiftUI
struct NewTweetView: View { struct NewTweetView: View {
@State private var caption = "" @State private var caption = ""
@Environment(\.presentationMode) var presentationMode // @Environment(\.presentationMode) var presentationMode
@Environment(\.dismiss) private var dismiss
var body: some View { var body: some View {
VStack { VStack {
HStack { HStack {
Button { Button {
presentationMode.wrappedValue.dismiss() // presentationMode.wrappedValue.dismiss()
dismiss()
} label: { } label: {
Text("Cancel") Text("Cancel")
.foregroundColor(Color(.systemBlue)) .foregroundColor(Color(.systemBlue))

View File

@ -13,6 +13,7 @@ struct dudu_tweetApp: App {
WindowGroup { WindowGroup {
NavigationView { NavigationView {
ContentView() ContentView()
// LoginView()
} }
} }
} }