punchnet-macos/punchnet/Views/Settings/SettingsAboutView.swift
2026-03-23 14:58:32 +08:00

201 lines
7.4 KiB
Swift
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//
// 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()
}