201 lines
7.4 KiB
Swift
201 lines
7.4 KiB
Swift
//
|
||
// SettingsAboutView.swift
|
||
// punchnet
|
||
//
|
||
// Created by 安礼成 on 2026/1/19.
|
||
//
|
||
import SwiftUI
|
||
|
||
struct SettingsAboutView: View {
|
||
@Environment(\.openURL) private var openURL
|
||
|
||
@State private var isShowingFeedbackSheet = false
|
||
@State private var appPoliciesInfo: SDLAPIClient.AppPoliciesInfo?
|
||
|
||
// 检查更新逻辑
|
||
@State private var updateManager = AppUpdateManager.shared
|
||
@State private var showNoUpdateAlert = false
|
||
@State private var manualUpdateInfo: SDLAPIClient.AppUpgradeInfo?
|
||
|
||
var body: some View {
|
||
ScrollView(.vertical, showsIndicators: false) {
|
||
VStack(alignment: .leading, spacing: 32) {
|
||
|
||
// MARK: - 品牌展示区 (左对齐)
|
||
HStack(spacing: 20) {
|
||
// App Icon 保持精致的圆角和阴影
|
||
ZStack {
|
||
RoundedRectangle(cornerRadius: 16, style: .continuous)
|
||
.fill(Color.blue.gradient)
|
||
.frame(width: 64, height: 64)
|
||
.shadow(color: .blue.opacity(0.2), radius: 8, x: 0, y: 4)
|
||
|
||
Image(systemName: "bolt.shield.fill")
|
||
.font(.system(size: 32))
|
||
.foregroundColor(.white)
|
||
}
|
||
|
||
VStack(alignment: .leading, spacing: 4) {
|
||
Text("PunchNet")
|
||
.font(.system(size: 22, weight: .bold))
|
||
|
||
Text("版本 \(SystemConfig.version_name)")
|
||
.font(.subheadline)
|
||
.foregroundColor(.secondary)
|
||
|
||
Text(SystemConfig.systemInfo)
|
||
.font(.caption2)
|
||
.padding(.horizontal, 6)
|
||
.padding(.vertical, 2)
|
||
.background(Color.primary.opacity(0.05))
|
||
.cornerRadius(4)
|
||
}
|
||
}
|
||
.padding(.top, 10)
|
||
|
||
// MARK: - 核心操作卡片
|
||
VStack(alignment: .leading, spacing: 0) {
|
||
AboutRow(title: "检查更新", icon: "arrow.clockwise.circle") {
|
||
Button("立即检查") {
|
||
// 检查更新逻辑
|
||
Task {@MainActor in
|
||
await self.checkAppUpgrade()
|
||
}
|
||
}
|
||
.buttonStyle(.plain)
|
||
.foregroundColor(.blue)
|
||
.font(.subheadline.bold())
|
||
.disabled(updateManager.isChecking)
|
||
}
|
||
|
||
Divider().padding(.leading, 44)
|
||
|
||
AboutRow(title: "用户反馈", icon: "bubble.left.and.exclamationmark.bubble.right") {
|
||
Image(systemName: "chevron.right")
|
||
.font(.caption)
|
||
.foregroundColor(.secondary)
|
||
}
|
||
.onTapGesture {
|
||
self.isShowingFeedbackSheet = true
|
||
}
|
||
}
|
||
.background(Color.primary.opacity(0.03))
|
||
.cornerRadius(12)
|
||
.overlay(RoundedRectangle(cornerRadius: 12).stroke(Color.primary.opacity(0.05), lineWidth: 1))
|
||
|
||
// MARK: - 法律文档卡片
|
||
VStack(alignment: .leading, spacing: 0) {
|
||
AboutRow(title: "隐私政策", icon: "doc.text.magnifyingglass") {
|
||
Image(systemName: "arrow.up.right")
|
||
.font(.caption)
|
||
.foregroundColor(.secondary)
|
||
}
|
||
.onTapGesture {
|
||
if let privacyPolicyUrl = self.appPoliciesInfo?.privacyPolicyUrl, let privacyUrl = URL(string: privacyPolicyUrl) {
|
||
openURL(privacyUrl)
|
||
}
|
||
}
|
||
|
||
Divider().padding(.leading, 44)
|
||
|
||
AboutRow(title: "服务条款", icon: "scroll") {
|
||
Image(systemName: "arrow.up.right")
|
||
.font(.caption)
|
||
.foregroundColor(.secondary)
|
||
}
|
||
.onTapGesture {
|
||
if let termsOfServiceUrl = self.appPoliciesInfo?.termsOfServiceUrl, let termsUrl = URL(string: termsOfServiceUrl) {
|
||
openURL(termsUrl)
|
||
}
|
||
}
|
||
}
|
||
.background(Color.primary.opacity(0.03))
|
||
.cornerRadius(12)
|
||
|
||
// MARK: - 底部版权
|
||
VStack(alignment: .leading, spacing: 4) {
|
||
Text("© 2024-2026 PunchNet Inc.")
|
||
Text("保留所有权利。")
|
||
}
|
||
.font(.caption2)
|
||
.foregroundColor(.secondary)
|
||
.padding(.leading, 4)
|
||
}
|
||
.padding(32)
|
||
.frame(maxWidth: 600, alignment: .leading)
|
||
}
|
||
.sheet(isPresented: $isShowingFeedbackSheet) {
|
||
VStack {
|
||
HStack {
|
||
Spacer()
|
||
Button {
|
||
isShowingFeedbackSheet = false
|
||
} label: {
|
||
Text("关闭")
|
||
}
|
||
.buttonStyle(.plain)
|
||
.padding()
|
||
}
|
||
// 复用你写的反馈视图
|
||
SettingsUserIssueView()
|
||
}
|
||
.frame(width: 500, height: 600) // 设置弹窗大小
|
||
}
|
||
// 手动检查的 Sheet 弹出
|
||
.sheet(item: $manualUpdateInfo) { info in
|
||
AppUpdateView(info: info) {
|
||
self.manualUpdateInfo = nil
|
||
}
|
||
}
|
||
.alert(isPresented: $showNoUpdateAlert) {
|
||
Alert(title: Text("检查更新"), message: Text("您当前使用的是最新版本。"))
|
||
}
|
||
.task {
|
||
self.appPoliciesInfo = try? await SDLAPIClient.appPolicies()
|
||
|
||
_ = try? await SDLAPIClient.appCheckUpdate()
|
||
}
|
||
}
|
||
|
||
private func checkAppUpgrade() async {
|
||
let hasUpdate = await updateManager.checkUpdate(isManual: true)
|
||
if hasUpdate {
|
||
// 手动检查发现更新,赋值给 sheet 绑定的变量
|
||
self.manualUpdateInfo = updateManager.updateInfo
|
||
} else {
|
||
self.showNoUpdateAlert = true
|
||
}
|
||
}
|
||
|
||
}
|
||
|
||
// MARK: - 复用之前的行组件
|
||
struct AboutRow<Content: View>: View {
|
||
let title: String
|
||
let icon: String
|
||
let trailingContent: () -> Content
|
||
|
||
var body: some View {
|
||
HStack(spacing: 12) {
|
||
Image(systemName: icon)
|
||
.foregroundColor(.blue)
|
||
.font(.system(size: 14))
|
||
.frame(width: 20)
|
||
|
||
Text(title)
|
||
.font(.system(size: 14, weight: .medium))
|
||
|
||
Spacer()
|
||
|
||
trailingContent()
|
||
}
|
||
.padding(.horizontal, 16)
|
||
.padding(.vertical, 14)
|
||
.contentShape(Rectangle())
|
||
}
|
||
}
|
||
|
||
#Preview {
|
||
SettingsAboutView()
|
||
}
|