diff --git a/wake/Assets/Svg/AboutIP.svg b/wake/Assets/Svg/AboutIP.svg new file mode 100644 index 0000000..ee67e5e --- /dev/null +++ b/wake/Assets/Svg/AboutIP.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/wake/Utils/Router.swift b/wake/Utils/Router.swift index 0230790..5f5064b 100644 --- a/wake/Utils/Router.swift +++ b/wake/Utils/Router.swift @@ -12,6 +12,8 @@ enum AppRoute: Hashable { case memories case subscribe case userInfo + case account + case about @ViewBuilder var view: some View { @@ -36,6 +38,10 @@ enum AppRoute: Hashable { SubscribeView() case .userInfo: UserInfo() + case .account: + AccountView() + case .about: + AboutUsView() } } } diff --git a/wake/View/Owner/AboutUsView.swift b/wake/View/Owner/AboutUsView.swift new file mode 100644 index 0000000..16f3140 --- /dev/null +++ b/wake/View/Owner/AboutUsView.swift @@ -0,0 +1,157 @@ +import SwiftUI + +struct AboutUsView: View { + // MARK: - Properties + + private let appVersion = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String ?? "1.0.0" + private let buildNumber = Bundle.main.infoDictionary?["CFBundleVersion"] as? String ?? "1" + + // MARK: - Body + + var body: some View { + ZStack { + // Background color + Color.themeTextWhiteSecondary + .edgesIgnoringSafeArea(.all) + + VStack(spacing: 0) { + // Navigation Header + SimpleNaviHeader(title: "About Us") { + Router.shared.pop() + } + .padding(.top, UIApplication.shared.windows.first?.safeAreaInsets.top ?? 0) + + // Main Content + VStack(spacing: 0) { + // IP Address Section + VStack(spacing: 12) { + SVGImage(svgName: "AboutIP") + .frame(width: 102, height: 102) + } + .frame(maxWidth: .infinity) + .padding(.vertical, 32) + + // Version & ICP Info + VStack(spacing: 12) { + Text("Version : 1.1.1") + .font(.system(size: 12)) + .foregroundColor(.themeTextMessageMain) + + Text("ICP 备案号: 京ICP备XXXXXXXX号") + .font(.system(size: 12)) + .foregroundColor(.themeTextMessageMain) + } + .padding(.bottom, 32) + // Legal Links + VStack(spacing: 0) { + settingRow( + title: "Terms of Service", + action: { + withAnimation { + if let url = URL(string: "https://example.com/terms") { + UIApplication.shared.open(url) + } + } + } + ) + .padding() + settingRow( + title: "Privacy Policy", + action: { + withAnimation { + if let url = URL(string: "https://example.com/terms") { + UIApplication.shared.open(url) + } + } + } + ) + .padding() + settingRow( + title: "AI Usage Guidelines", + action: { + withAnimation { + if let url = URL(string: "https://example.com/terms") { + UIApplication.shared.open(url) + } + } + } + ) + .padding() + } + } + .frame(maxWidth: .infinity) + .background(Color.white) + .cornerRadius(16) + .padding() + Spacer() + } + } + .navigationBarHidden(true) + .edgesIgnoringSafeArea(.all) + } + + private func settingRow(title: String, action: @escaping () -> Void) -> some View { + Button(action: action) { + HStack { + // 标题 + Text(title) + .foregroundColor(.primary) + + Spacer() + + // 右侧箭头 + Image(systemName: "chevron.right") + .font(.system(size: 14)) + .foregroundColor(.gray) + } + .padding(.vertical, 12) // 增加垂直内边距 + .background(Color.white) + } + .buttonStyle(PlainButtonStyle()) + .listRowBackground(Color.white) + .listRowSeparator(.hidden) + } + // MARK: - Private Methods + + private func getIPAddress() -> String? { + var address: String? + var ifaddr: UnsafeMutablePointer? + + if getifaddrs(&ifaddr) == 0 { + var ptr = ifaddr + while ptr != nil { + defer { ptr = ptr?.pointee.ifa_next } + + let interface = ptr?.pointee + let addrFamily = interface?.ifa_addr.pointee.sa_family + + if addrFamily == UInt8(AF_INET) || addrFamily == UInt8(AF_INET6), + let name = interface?.ifa_name, + String(cString: name) == "en0", + let addr = interface?.ifa_addr { + + var hostname = [CChar](repeating: 0, count: Int(NI_MAXHOST)) + getnameinfo(addr, socklen_t(addr.pointee.sa_len), + &hostname, socklen_t(hostname.count), + nil, socklen_t(0), + NI_NUMERICHOST) + address = String(cString: hostname) + } + } + freeifaddrs(ifaddr) + } + + return address + } +} + +// MARK: - Preview +#Preview { + AboutUsView() +} + +// MARK: - Dependencies +import Foundation +import SystemConfiguration +import Network +import Darwin diff --git a/wake/View/Owner/Account.swift b/wake/View/Owner/Account.swift deleted file mode 100644 index c8b7aa8..0000000 --- a/wake/View/Owner/Account.swift +++ /dev/null @@ -1,112 +0,0 @@ -import SwiftUI - -/// 设置页面视图 -struct AccountView: View { - // MARK: - 属性 - - /// 环境变量 - 用于dismiss视图 - @Environment(\.dismiss) private var dismiss - - /// 状态 - 控制视图显示/隐藏 - @Binding var isAccountPresented: Bool - - // MARK: - 动画配置 - - /// 动画配置 - private let animation = Animation.spring( - response: 0.6, // 响应时间 - dampingFraction: 0.9, // 阻尼系数 - blendDuration: 0.8 // 混合时间 - ) - - // MARK: - 主体视图 - - var body: some View { - ZStack { - // Theme background color - Color.themeTextWhiteSecondary.edgesIgnoringSafeArea(.all) - - VStack(spacing: 0) { - // 简洁导航头 - SimpleNaviHeader(title: "Account & Security") { - withAnimation(animation) { - isAccountPresented = false - } - } - - // 设置项列表 - List { - // 账号与安全 - settingRow( - icon: "Account", - title: "Account & Security", - action: {} - ) - - - } - .background(Color.white) - .cornerRadius(12) - .padding() - .listStyle(PlainListStyle()) - .listRowSeparator(.hidden) - .listRowInsets(EdgeInsets()) - } - } - .background(Color.themeTextWhiteSecondary.edgesIgnoringSafeArea(.all)) - .environment(\.horizontalSizeClass, .regular) - } - - // MARK: - 私有方法 - - /// 配置TableView外观 - private func configureTableView() { - // 移除列表底部分隔线 - UITableView.appearance().tableFooterView = UIView() - // 移除列表顶部分隔线 - UITableView.appearance().tableHeaderView = UIView(frame: CGRect(x: 0, y: 0, width: 0, height: CGFloat.leastNonzeroMagnitude)) - // 移除分隔线缩进 - UITableView.appearance().separatorInset = .zero - // 移除列表顶部额外间距 - UITableView.appearance().contentInset = .zero - } - - /// 创建设置项行视图 - /// - Parameters: - /// - icon: 图标名称 - /// - title: 标题 - /// - action: 点击动作 - /// - Returns: 返回设置项行视图 - private func settingRow(icon: String, title: String, action: @escaping () -> Void) -> some View { - Button(action: action) { - HStack { - // 左侧图标 - SVGImage(svgName: icon) - .frame(width: 24, height: 24) - - // 标题 - Text(title) - .foregroundColor(.primary) - - Spacer() - - // 右侧箭头 - Image(systemName: "chevron.right") - .font(.system(size: 14)) - .foregroundColor(.gray) - } - .padding(.vertical, 12) // 增加垂直内边距 - .background(Color.white) - } - .buttonStyle(PlainButtonStyle()) - .listRowBackground(Color.white) - .listRowSeparator(.hidden) - } -} - -// MARK: - 预览 -#Preview { - NavigationView { - AccountView(isAccountPresented: .constant(true)) - } -} diff --git a/wake/View/Owner/AccountView.swift b/wake/View/Owner/AccountView.swift new file mode 100644 index 0000000..25c6517 --- /dev/null +++ b/wake/View/Owner/AccountView.swift @@ -0,0 +1,187 @@ +import SwiftUI + +/// 设置页面视图 +struct AccountView: View { + // MARK: - 属性 + + /// 环境变量 - 用于dismiss视图 + @Environment(\.dismiss) private var dismiss + + /// 控制删除确认弹窗显示 + @State private var showDeleteConfirmation = false + + // MARK: - 动画配置 + + /// 动画配置 + private let animation = Animation.spring( + response: 0.6, // 响应时间 + dampingFraction: 0.9, // 阻尼系数 + blendDuration: 0.8 // 混合时间 + ) + + // MARK: - 主体视图 + + var body: some View { + ZStack { + // Theme background color + Color.themeTextWhiteSecondary + .edgesIgnoringSafeArea(.all) + + VStack(spacing: 0) { + // 自定义导航头 + SimpleNaviHeader(title: "Account & Security") { + withAnimation(animation) { + Router.shared.pop() + } + } + .padding(.top, UIApplication.shared.windows.first?.safeAreaInsets.top) + + // 内容区域 + ScrollView { + VStack(spacing: 0) { + // 删除账号 + settingRow( + title: "Delete Account", + action: { + withAnimation { + showDeleteConfirmation = true + } + } + ) + .padding() + } + .background(Color.white) + .cornerRadius(12) + .padding(.horizontal) + } + .background(Color.themeTextWhiteSecondary) + } + .frame(maxWidth: .infinity, maxHeight: .infinity) + .edgesIgnoringSafeArea(.top) + } + .edgesIgnoringSafeArea(.all) + .frame(maxWidth: .infinity, maxHeight: .infinity) + .overlay( + // 删除确认弹窗 + Group { + if showDeleteConfirmation { + ZStack { + // 半透明黑色遮罩 + Color.black.opacity(0.6) + .edgesIgnoringSafeArea(.all) + .onTapGesture { + withAnimation { + showDeleteConfirmation = false + } + } + + // 确认弹窗内容 + VStack(spacing: 20) { + Text("Are you sure you want to delete this account?") + .font(.headline) + .font(.system(size: 14, weight: .medium)) + .foregroundColor(.themeTextMessageMain) + + + Text("Once deleted, you can’t get it back.") + .multilineTextAlignment(.center) + .font(.subheadline) + .font(.system(size: 12)) + .foregroundColor(.themeTextMessage) + + HStack(spacing: 20) { + Button(action: { + withAnimation { + showDeleteConfirmation = false + } + }) { + Text("Cancel") + .font(Typography.font(for: .subtitle, family: .quicksandBold)) + .foregroundColor(.themeTextMessageMain) + .frame(maxWidth: .infinity) + .padding() + .background(Color.themePrimary) + .cornerRadius(32) + } + + Button(action: { + // 处理删除账号逻辑 + withAnimation { + showDeleteConfirmation = false + } + // TODO: 调用删除账号的API + }) { + Text("Confirm") + .foregroundColor(.themeTextMessage) + .font(.system(size: 12)) + .frame(maxWidth: .infinity) + .padding() + .background(Color.white) + .cornerRadius(32) + } + } + } + .padding() + .frame(width: 300) + .background(Color.white) + .cornerRadius(12) + .shadow(radius: 10) + } + .transition(.opacity) + } + } + ) + .navigationBarBackButtonHidden(true) // 隐藏默认返回按钮 + .navigationBarHidden(true) // 隐藏导航栏 + } + + // MARK: - 私有方法 + + /// 配置TableView外观 + private func configureTableView() { + // 移除列表底部分隔线 + UITableView.appearance().tableFooterView = UIView() + // 移除列表顶部分隔线 + UITableView.appearance().tableHeaderView = UIView(frame: CGRect(x: 0, y: 0, width: 0, height: CGFloat.leastNonzeroMagnitude)) + // 移除分隔线缩进 + UITableView.appearance().separatorInset = .zero + // 移除列表顶部额外间距 + UITableView.appearance().contentInset = .zero + } + + /// 创建设置项行视图 + /// - Parameters: + /// - icon: 图标名称 + /// - title: 标题 + /// - action: 点击动作 + /// - Returns: 返回设置项行视图 + private func settingRow(title: String, action: @escaping () -> Void) -> some View { + Button(action: action) { + HStack { + + // 标题 + Text(title) + .foregroundColor(.primary) + + Spacer() + + // 右侧箭头 + Image(systemName: "chevron.right") + .font(.system(size: 14)) + .foregroundColor(.gray) + } + .padding(.vertical, 12) // 增加垂直内边距 + .background(Color.white) + } + .buttonStyle(PlainButtonStyle()) + .listRowBackground(Color.white) + .listRowSeparator(.hidden) + } +} + +// MARK: - 预览 +#Preview { + NavigationView { + AccountView() + } +} diff --git a/wake/View/Owner/SettingsView.swift b/wake/View/Owner/SettingsView.swift index a856115..803390f 100644 --- a/wake/View/Owner/SettingsView.swift +++ b/wake/View/Owner/SettingsView.swift @@ -9,8 +9,7 @@ struct SettingsView: View { /// 状态 - 控制视图显示/隐藏 @Binding var isPresented: Bool - - @State private var showAccountView = false + @State private var isShowingAccountView = false // MARK: - 动画配置 @@ -43,8 +42,8 @@ struct SettingsView: View { settingRow( icon: "Account", title: "Account & Security", - action: { - // Action will be handled by NavigationLink + action: { + Router.shared.navigate(to: .account) } ) @@ -66,7 +65,9 @@ struct SettingsView: View { settingRow( icon: "AboutUs", title: "About Us", - action: {} + action: { + Router.shared.navigate(to: .about) + } ) } .background(Color.white) @@ -80,6 +81,7 @@ struct SettingsView: View { Spacer() } } + .navigationBarHidden(true) } }