diff --git a/.DS_Store b/.DS_Store
index b7b5d2b..c9ef09f 100644
Binary files a/.DS_Store and b/.DS_Store differ
diff --git a/wake.xcodeproj/project.xcworkspace/xcuserdata/elliwood.xcuserdatad/UserInterfaceState.xcuserstate b/wake.xcodeproj/project.xcworkspace/xcuserdata/elliwood.xcuserdatad/UserInterfaceState.xcuserstate
index d860fb8..4a53c9a 100644
Binary files a/wake.xcodeproj/project.xcworkspace/xcuserdata/elliwood.xcuserdatad/UserInterfaceState.xcuserstate and b/wake.xcodeproj/project.xcworkspace/xcuserdata/elliwood.xcuserdatad/UserInterfaceState.xcuserstate differ
diff --git a/wake.xcodeproj/xcuserdata/elliwood.xcuserdatad/xcschemes/xcschememanagement.plist b/wake.xcodeproj/xcuserdata/elliwood.xcuserdatad/xcschemes/xcschememanagement.plist
index a4c98a3..62e325e 100644
--- a/wake.xcodeproj/xcuserdata/elliwood.xcuserdatad/xcschemes/xcschememanagement.plist
+++ b/wake.xcodeproj/xcuserdata/elliwood.xcuserdatad/xcschemes/xcschememanagement.plist
@@ -7,7 +7,7 @@
wake.xcscheme_^#shared#^_
orderHint
- 0
+ 3
diff --git a/wake/.DS_Store b/wake/.DS_Store
index b3853f3..efa3987 100644
Binary files a/wake/.DS_Store and b/wake/.DS_Store differ
diff --git a/wake/ContentView.swift b/wake/ContentView.swift
index 976c126..f0f25a5 100644
--- a/wake/ContentView.swift
+++ b/wake/ContentView.swift
@@ -70,7 +70,9 @@ struct ContentView: View {
}
}
// 登录按钮
- NavigationLink(destination: LoginView()) {
+ Button(action: {
+ showLogin = true
+ }) {
Text("登录")
.font(.headline)
.padding(.horizontal, 16)
@@ -80,6 +82,9 @@ struct ContentView: View {
.cornerRadius(8)
}
.padding(.trailing)
+ .fullScreenCover(isPresented: $showLogin) {
+ LoginView()
+ }
}
Spacer()
diff --git a/wake/Info.plist b/wake/Info.plist
index 23b998e..92853ab 100644
--- a/wake/Info.plist
+++ b/wake/Info.plist
@@ -22,8 +22,8 @@
Sign in with Apple is used to authenticate your account
UIAppFonts
- Quicksand x.ttf
- SankeiCutePopanime.ttf
+ Inter.ttf
+ Quicksand X.ttf
Quicksand-Regular.ttf
Quicksand-Bold.ttf
Quicksand-SemiBold.ttf
diff --git a/wake/Resources/.DS_Store b/wake/Resources/.DS_Store
new file mode 100644
index 0000000..99b4c6a
Binary files /dev/null and b/wake/Resources/.DS_Store differ
diff --git a/wake/Resources/Fonts/Inter.ttf b/wake/Resources/Fonts/Inter.ttf
new file mode 100644
index 0000000..e31b51e
Binary files /dev/null and b/wake/Resources/Fonts/Inter.ttf differ
diff --git a/wake/Resources/Quicksand x.ttf b/wake/Resources/Fonts/Quicksand x.ttf
similarity index 100%
rename from wake/Resources/Quicksand x.ttf
rename to wake/Resources/Fonts/Quicksand x.ttf
diff --git a/wake/Resources/SankeiCutePopanime.ttf b/wake/Resources/SankeiCutePopanime.ttf
deleted file mode 100644
index 5f31eeb..0000000
Binary files a/wake/Resources/SankeiCutePopanime.ttf and /dev/null differ
diff --git a/wake/Theme.swift b/wake/Theme.swift
index 7a3f307..a6c3457 100644
--- a/wake/Theme.swift
+++ b/wake/Theme.swift
@@ -32,6 +32,8 @@ struct Theme {
static let textSecondary = Color(hex: "6B7280") // 次级文本色
static let textTertiary = Color(hex: "9CA3AF") // 三级文本色
static let textInverse = Color.white // 反色文本
+ static let textMessage = Color(hex: "7B7B7B") // 注释颜色
+ static let textMessageMain = Color(hex: "000000") // 注释主要颜色
// MARK: - 状态色
static let success = Color(hex: "10B981") // 成功色
@@ -115,6 +117,8 @@ extension Color {
static var themeSurface: Color { Theme.Colors.surface }
static var themeTextPrimary: Color { Theme.Colors.textPrimary }
static var themeTextSecondary: Color { Theme.Colors.textSecondary }
+ static var themeTextMessage: Color { Theme.Colors.textMessage }
+ static var themeTextMessageMain: Color { Theme.Colors.textMessageMain }
}
// MARK: - 预览
diff --git a/wake/Typography.swift b/wake/Typography.swift
index 27f7b98..ecdc952 100644
--- a/wake/Typography.swift
+++ b/wake/Typography.swift
@@ -3,12 +3,10 @@ import SwiftUI
// MARK: - 字体库枚举
/// 定义应用中可用的字体库
enum FontFamily: String, CaseIterable {
- case sankeiCute = "SankeiCutePopanime" // 可爱风格字体
- case quicksand = "Quicksand x" // 主题字体
+ case quicksand = "Quicksand x"
case quicksandBold = "Quicksand-Bold"
case quicksandRegular = "Quicksand-Regular"
- // 后续添加新字体库时在这里添加新 case
- // 例如: case anotherFont = "AnotherFontName"
+ case inter = "Inter"
/// 获取字体名称
var name: String {
@@ -19,6 +17,7 @@ enum FontFamily: String, CaseIterable {
// MARK: - 文本样式枚举
/// 定义应用中使用的文本样式类型
enum TypographyStyle {
+ case largeTitle // 大标题
case headline // 大标题
case title // 标题
case body // 正文
@@ -44,11 +43,12 @@ struct Typography {
/// 文本样式配置表
private static let styleConfig: [TypographyStyle: TypographyConfig] = [
+ .largeTitle: TypographyConfig(size: 32, weight: .heavy, textStyle: .largeTitle),
.headline: TypographyConfig(size: 24, weight: .bold, textStyle: .headline),
.title: TypographyConfig(size: 20, weight: .semibold, textStyle: .title2),
.body: TypographyConfig(size: 16, weight: .regular, textStyle: .body),
.subtitle: TypographyConfig(size: 14, weight: .medium, textStyle: .subheadline),
- .caption: TypographyConfig(size: 12, weight: .light, textStyle: .caption1),
+ .caption: TypographyConfig(size: 12, weight: .regular, textStyle: .caption1),
.footnote: TypographyConfig(size: 11, weight: .regular, textStyle: .footnote),
.small: TypographyConfig(size: 10, weight: .regular, textStyle: .headline)
]
diff --git a/wake/View/Components/AppleSignInButton.swift b/wake/View/Components/AppleSignInButton.swift
new file mode 100644
index 0000000..cd61af0
--- /dev/null
+++ b/wake/View/Components/AppleSignInButton.swift
@@ -0,0 +1,95 @@
+import SwiftUI
+import AuthenticationServices
+import CryptoKit
+
+/// 自定义的 Apple 登录按钮组件
+struct AppleSignInButton: View {
+ // MARK: - 属性
+
+ /// 授权请求回调
+ let onRequest: (ASAuthorizationAppleIDRequest) -> Void
+
+ /// 授权完成回调
+ let onCompletion: (Result) -> Void
+
+ /// 按钮文字
+ let buttonText: String
+
+ // MARK: - 初始化方法
+
+ init(buttonText: String = "Continue with Apple",
+ onRequest: @escaping (ASAuthorizationAppleIDRequest) -> Void,
+ onCompletion: @escaping (Result) -> Void) {
+ self.buttonText = buttonText
+ self.onRequest = onRequest
+ self.onCompletion = onCompletion
+ }
+
+ // MARK: - 视图主体
+
+ var body: some View {
+ Button(action: handleSignIn) {
+ HStack(alignment: .center, spacing: 8) {
+ Image(systemName: "applelogo")
+ .font(.system(size: 20, weight: .regular))
+ Text(buttonText)
+ .font(.system(size: 18, weight: .regular))
+ }
+ .frame(maxWidth: .infinity)
+ .frame(height: 60)
+ .background(Color.white)
+ .foregroundColor(.black)
+ .cornerRadius(30)
+ .overlay(
+ RoundedRectangle(cornerRadius: 30)
+ .stroke(Color.black, lineWidth: 1) // 使用黑色边框
+ )
+ }
+ }
+
+ // MARK: - 私有方法
+
+ private func handleSignIn() {
+ let provider = ASAuthorizationAppleIDProvider()
+ let request = provider.createRequest()
+ request.requestedScopes = [.fullName, .email]
+
+ // 创建 nonce 用于安全验证
+ let nonce = String.randomURLSafeString(length: 32)
+ request.nonce = sha256(nonce)
+
+ // 调用请求回调
+ onRequest(request)
+
+ // 创建并显示授权控制器
+ let controller = ASAuthorizationController(authorizationRequests: [request])
+ controller.delegate = Coordinator(onCompletion: onCompletion)
+ controller.performRequests()
+ }
+
+ private func sha256(_ input: String) -> String {
+ let inputData = Data(input.utf8)
+ let hashedData = SHA256.hash(data: inputData)
+ return hashedData.compactMap { String(format: "%02x", $0) }.joined()
+ }
+
+ // MARK: - 协调器
+
+ private class Coordinator: NSObject, ASAuthorizationControllerDelegate {
+ let onCompletion: (Result) -> Void
+
+ init(onCompletion: @escaping (Result) -> Void) {
+ self.onCompletion = onCompletion
+ }
+
+ // 授权成功回调
+ func authorizationController(controller: ASAuthorizationController, didCompleteWithAuthorization authorization: ASAuthorization) {
+ onCompletion(.success(authorization))
+ }
+
+ // 授权失败回调
+ func authorizationController(controller: ASAuthorizationController, didCompleteWithError error: Error) {
+ onCompletion(.failure(error))
+ }
+ }
+}
\ No newline at end of file
diff --git a/wake/View/Login/Login.swift b/wake/View/Login/Login.swift
index 4069ecd..0a736b3 100644
--- a/wake/View/Login/Login.swift
+++ b/wake/View/Login/Login.swift
@@ -16,56 +16,54 @@ struct LoginView: View {
// MARK: - Body
var body: some View {
- NavigationStack {
- ZStack {
- // Background
- Color(red: 1.0, green: 0.67, blue: 0.15)
- .edgesIgnoringSafeArea(.all)
+ ZStack {
+ // Background
+ Color(red: 1.0, green: 0.67, blue: 0.15)
+ .ignoresSafeArea()
+
+ VStack(alignment: .leading, spacing: 4) {
+ Text("Hi, I'm MeMo!")
+ .font(Typography.font(for: .largeTitle))
+ .foregroundColor(.black)
+ .frame(maxWidth: .infinity, alignment: .leading)
+ .padding(.horizontal, 24)
+ .padding(.top, 44)
- VStack(alignment: .leading, spacing: 4) {
- Text("Hi, I'm MeMo!")
- .font(.largeTitle)
- .fontWeight(.semibold)
- .foregroundColor(.black)
- .frame(maxWidth: .infinity, alignment: .leading)
- .padding(.leading, 24)
- .padding(.top, 44)
-
- Text("Welcome~")
- .font(.largeTitle)
- .fontWeight(.semibold)
- .foregroundColor(.black)
- .frame(maxWidth: .infinity, alignment: .leading)
- .padding(.leading, 24)
- .padding(.bottom, 20)
-
- Spacer()
- }
- .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topLeading)
+ Text("Welcome~")
+ .font(Typography.font(for: .largeTitle))
+ .foregroundColor(.black)
+ .frame(maxWidth: .infinity, alignment: .leading)
+ .padding(.horizontal, 24)
+ .padding(.bottom, 20)
- VStack(spacing: 16) {
- Spacer()
- signInButton()
- termsAndPrivacyView()
- }
- .padding()
- .alert(isPresented: $showError) {
- Alert(
- title: Text("Error"),
- message: Text(errorMessage),
- dismissButton: .default(Text("OK"))
- )
- }
-
- if isLoading {
- loadingView()
- }
+ Spacer()
}
- .navigationBarHidden(true)
- .fullScreenCover(isPresented: $isLoggedIn) {
- NavigationStack {
- UserInfo()
- }
+ .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topLeading)
+
+ VStack(spacing: 16) {
+ Spacer()
+ signInButton()
+ .padding(.horizontal, 24)
+ termsAndPrivacyView()
+ }
+ .frame(maxWidth: .infinity)
+ .alert(isPresented: $showError) {
+ Alert(
+ title: Text("Error"),
+ message: Text(errorMessage),
+ dismissButton: .default(Text("OK"))
+ )
+ }
+
+ if isLoading {
+ loadingView()
+ }
+ }
+ .navigationBarBackButtonHidden(true)
+ .navigationBarHidden(true)
+ .fullScreenCover(isPresented: $isLoggedIn) {
+ NavigationStack {
+ UserInfo()
}
}
}
@@ -73,22 +71,22 @@ struct LoginView: View {
// MARK: - Views
private func signInButton() -> some View {
- SignInWithAppleButton(
- onRequest: { request in
- let nonce = String.randomURLSafeString(length: 32)
- self.currentNonce = nonce
- request.requestedScopes = [.fullName, .email]
- request.nonce = self.sha256(nonce)
- },
- onCompletion: handleAppleSignIn
- )
- .signInWithAppleButtonStyle(.white)
- .frame(height: 50)
- .cornerRadius(25)
- .overlay(
- RoundedRectangle(cornerRadius: 25)
- .stroke(Color.black, lineWidth: 1)
- )
+ AppleSignInButton { request in
+ let nonce = String.randomURLSafeString(length: 32)
+ self.currentNonce = nonce
+ request.nonce = self.sha256(nonce)
+ } onCompletion: { result in
+ switch result {
+ case .success(let authResults):
+ print("✅ [Apple Sign In] 登录授权成功")
+ if let appleIDCredential = authResults.credential as? ASAuthorizationAppleIDCredential {
+ self.processAppleIDCredential(appleIDCredential)
+ }
+ case .failure(let error):
+ print("❌ [Apple Sign In] 登录失败: \(error.localizedDescription)")
+ self.handleSignInError(error)
+ }
+ }
}
private func termsAndPrivacyView() -> some View {
@@ -96,13 +94,13 @@ struct LoginView: View {
HStack {
Text("By continuing, you agree to our")
.font(.caption)
- .foregroundColor(.secondary)
+ .foregroundColor(.themeTextMessage)
Button("Terms of") {
openURL("https://yourwebsite.com/terms")
}
.font(.caption2)
- .foregroundColor(.blue)
+ .foregroundColor(.themeTextMessageMain)
}
.multilineTextAlignment(.center)
.padding(.horizontal, 24)
@@ -112,24 +110,24 @@ struct LoginView: View {
openURL("https://yourwebsite.com/terms")
}
.font(.caption2)
- .foregroundColor(.blue)
+ .foregroundColor(.themeTextMessageMain)
Text("and")
- .foregroundColor(.secondary)
+ .foregroundColor(.themeTextMessage)
.font(.caption)
Button("Privacy Policy") {
openURL("https://yourwebsite.com/privacy")
}
.font(.caption2)
- .foregroundColor(.blue)
+ .foregroundColor(.themeTextMessageMain)
}
.padding(.top, 4)
}
.fixedSize(horizontal: false, vertical: true)
.frame(maxWidth: .infinity)
.padding(.horizontal, 24)
- .padding(.bottom, 24)
+ .padding(.vertical, 12)
}
private func loadingView() -> some View {
diff --git a/wake/WakeApp.swift b/wake/WakeApp.swift
index 3c17ecd..3d1766c 100644
--- a/wake/WakeApp.swift
+++ b/wake/WakeApp.swift
@@ -44,9 +44,7 @@ struct WakeApp: App {
// 根据登录状态显示不同视图
if authState.isAuthenticated {
// 已登录:显示userInfo页面
- // UserInfo()
- // .environmentObject(authState)
- MediaUploadDemo()
+ UserInfo()
.environmentObject(authState)
} else {
// 未登录:显示登录界面