refactor: AboutView, AppCardView, VersionPickerView

1. AboutView: Subdivided some Views
2. AboutView: Added the display of system version number and specific chip model
3. AppCardView: Added the display of the minimum system version and module display
4. AppCardView: Optimized the display of the number of available versions and the number of dependent components
5. VersionPickerView: Added the product icon display in the Header part
6. VersionPickerView: Optimized the download architecture prompt
7. VersionPickerView: Optimized the display of product version, provided the display of productVersion and buildGuid
8. VersionPickerView: Optimized the display of dependent components, added the display of total number of dependencies and buildGuid
9. VersionPickerView: In DEBUG mode, you can check whether the dependent component hits the correct version, the selected version, and the reason for not hitting, and added the selected version icon
10. VersionPickerView: Adjusted the version display of dependent components, and no longer displayed baseVersion by default
11. VersionPickerView: Added optional module display and information
This commit is contained in:
X1a0He
2025-03-06 01:40:01 +08:00
parent 4b9dc3d417
commit 83abcc7316
11 changed files with 803 additions and 335 deletions

2
.gitignore vendored
View File

@@ -26,13 +26,11 @@ DerivedData/
!default.mode2v3
*.perspectivev3
!default.perspectivev3
xcuserdata/
## Other
*.moved-aside
*.xccheckout
*.xcscmblueprint
*.xcuserstate
.xcuserstate
## Obj-C/Swift specific

View File

@@ -31,7 +31,7 @@
shouldAutocreateTestPlan = "YES">
</TestAction>
<LaunchAction
buildConfiguration = "Release"
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"

View File

@@ -16,6 +16,25 @@ private var _globalNetworkManager: NetworkManager?
private var _globalNewDownloadUtils: NewDownloadUtils?
private var _globalCancelTracker: CancelTracker?
struct DependencyCacheKey: Hashable {
let sapCode: String
let targetPlatform: String
}
private var _globalDependencyCache: [DependencyCacheKey: Product.Platform.LanguageSet.Dependency]?
var globalDependencyCache: [DependencyCacheKey: Product.Platform.LanguageSet.Dependency] {
get {
if _globalDependencyCache == nil {
_globalDependencyCache = [:]
}
return _globalDependencyCache!
}
set {
_globalDependencyCache = newValue
}
}
//
var globalStiResult: NewParseResult {
get {

View File

@@ -59,6 +59,21 @@ struct Product: Codable, Equatable {
var baseVersion: String
var productVersion: String
var buildGuid: String
var isMatchPlatform: Bool
var targetPlatform: String
var selectedPlatform: String
var selectedReason: String
init(sapCode: String, baseVersion: String, productVersion: String, buildGuid: String, isMatchPlatform: Bool = false, targetPlatform: String = "", selectedPlatform: String = "", selectedReason: String = "") {
self.sapCode = sapCode
self.baseVersion = baseVersion
self.productVersion = productVersion
self.buildGuid = buildGuid
self.isMatchPlatform = isMatchPlatform
self.targetPlatform = targetPlatform
self.selectedPlatform = selectedPlatform
self.selectedReason = selectedReason
}
}
}

View File

@@ -1,20 +1,13 @@
import SwiftUI
struct ContentView: View {
@StateObject private var networkManager = globalNetworkManager
@State private var isRefreshing = false
@State private var errorMessage: String?
@State private var showDownloadManager = false
@State private var searchText = ""
@State private var currentApiVersion = StorageData.shared.apiVersion
private var apiVersion: String {
get { StorageData.shared.apiVersion }
set {
StorageData.shared.apiVersion = newValue
refreshData()
}
}
private var filteredProducts: [UniqueProduct] {
if searchText.isEmpty { return globalUniqueProducts }
@@ -32,7 +25,7 @@ struct ContentView: View {
errorMessage = nil
Task {
await globalNetworkManager.fetchProducts()
await networkManager.fetchProducts()
await MainActor.run { isRefreshing = false }
}
}
@@ -45,7 +38,7 @@ struct ContentView: View {
set: { newValue in
StorageData.shared.downloadAppleSilicon = newValue
Task {
await globalNetworkManager.fetchProducts()
await networkManager.fetchProducts()
}
}
)) { Text("Apple Silicon") }
@@ -102,8 +95,8 @@ struct ContentView: View {
.buttonStyle(.borderless)
.overlay(
Group {
if !globalNetworkManager.downloadTasks.isEmpty {
Text("\(globalNetworkManager.downloadTasks.count)")
if !networkManager.downloadTasks.isEmpty {
Text("\(networkManager.downloadTasks.count)")
.font(.caption2)
.padding(3)
.background(Color.blue)
@@ -134,7 +127,7 @@ struct ContentView: View {
Color(NSColor.windowBackgroundColor)
.ignoresSafeArea()
switch globalNetworkManager.loadingState {
switch networkManager.loadingState {
case .idle, .loading:
ProgressView("正在加载...")
.frame(maxWidth: .infinity, maxHeight: .infinity)
@@ -156,7 +149,7 @@ struct ContentView: View {
.padding(.bottom, 10)
Button(action: {
globalNetworkManager.retryFetchData()
networkManager.retryFetchData()
}) {
HStack() {
Image(systemName: "arrow.clockwise")

View File

@@ -7,7 +7,7 @@
Adobe Exit Code
107:
103:
182:
182:
133:
*/
import Foundation
@@ -115,15 +115,15 @@ actor InstallManager {
let errorMessage: String
switch exitCode {
case 107:
errorMessage = String(localized: "安装失败: 架构或版本不一致 (退出代码: \(exitCode))")
errorMessage = String(localized: "架构或版本不一致 (退出代码: \(exitCode))")
case 103:
errorMessage = String(localized: "安装失败: 权限问题 (退出代码: \(exitCode))")
errorMessage = String(localized: "权限问题 (退出代码: \(exitCode))")
case 182:
errorMessage = String(localized: "安装失败: 安装文件不完整或损坏 (退出代码: \(exitCode))")
errorMessage = String(localized: "安装文件不完整或损坏 (退出代码: \(exitCode))")
case -1:
errorMessage = String(localized: "安装失败: Setup 组件未被处理 (退出代码: \(exitCode))")
errorMessage = String(localized: "Setup 组件未被处理 (退出代码: \(exitCode))")
default:
errorMessage = String(localized: "安装失败 (退出代码: \(exitCode))")
errorMessage = String(localized: "(退出代码: \(exitCode))")
}
progressHandler(0.0, errorMessage)
continuation.resume(throwing: InstallError.installationFailed(errorMessage))

View File

@@ -283,31 +283,69 @@ class NewJSONParser {
return Product.Platform.LanguageSet.Dependency(sapCode: "",baseVersion: "",productVersion: "",buildGuid: "")
}
let targetPlatform = AppStatics.isAppleSilicon ? "macarm64" : "osx10-64"
let cacheKey = DependencyCacheKey(sapCode: sapCode, targetPlatform: targetPlatform)
if let cachedDependency = globalDependencyCache[cacheKey] {
return cachedDependency
}
var productVersion = ""
var buildGuid = ""
var isMatchPlatform = false
var selectedPlatform = ""
var selectedReason = ""
if !globalStiResult.products.isEmpty {
let matchingProducts = globalStiResult.products.filter { $0.id == sapCode }
if let latestProduct = matchingProducts.sorted(by: {
return AppStatics.compareVersions($0.version, $1.version) < 0
}).last {
let targetPlatformId = AppStatics.isAppleSilicon ? "macarm64" : "osx10-64"
let _ = latestProduct.platforms.map { $0.id }
if let matchingPlatform = latestProduct.platforms.first(where: { $0.id == targetPlatformId }),
return AppStatics.compareVersions($0.version, $1.version) > 0
}).first {
if let matchingPlatform = latestProduct.platforms.first(where: { platform in
platform.id == targetPlatform || platform.id == "macuniversal"
}),
let firstLanguageSet = matchingPlatform.languageSet.first {
productVersion = firstLanguageSet.productVersion
buildGuid = firstLanguageSet.buildGuid
isMatchPlatform = true
selectedPlatform = matchingPlatform.id
selectedReason = matchingPlatform.id == "macuniversal" ?
"成功匹配通用平台 macuniversal支持所有 Mac 平台)" :
"成功匹配目标平台"
} else {
if let firstAvailablePlatform = latestProduct.platforms.first,
let firstLanguageSet = firstAvailablePlatform.languageSet.first {
productVersion = firstLanguageSet.productVersion
buildGuid = firstLanguageSet.buildGuid
isMatchPlatform = false
selectedPlatform = firstAvailablePlatform.id
selectedReason = "当前依赖所有版本中无匹配平台,使用可用平台: \(firstAvailablePlatform.id)"
} else {
selectedReason = "未找到任何可用平台"
}
}
} else {
selectedReason = "未找到最新版本产品"
}
} else {
selectedReason = "globalStiResult.products 为空"
}
return Product.Platform.LanguageSet.Dependency(
let dependency = Product.Platform.LanguageSet.Dependency(
sapCode: sapCode,
baseVersion: baseVersion,
productVersion: productVersion,
buildGuid: buildGuid
buildGuid: buildGuid,
isMatchPlatform: isMatchPlatform,
targetPlatform: targetPlatform,
selectedPlatform: selectedPlatform,
selectedReason: selectedReason
)
globalDependencyCache[cacheKey] = dependency
return dependency
}
newLanguageSet.dependencies.append(contentsOf: dependencies)
}

File diff suppressed because it is too large Load Diff

View File

@@ -369,13 +369,54 @@ private struct ProductInfoView: View {
.lineLimit(2)
.multilineTextAlignment(.center)
HStack(spacing: 4) {
let product = findProduct(id: viewModel.uniqueProduct.id)
let versions = Set(product?.platforms.first?.languageSet.map { $0.productVersion } ?? [])
let dependenciesCount = product?.platforms.first?.languageSet.first?.dependencies.count ?? 0
Text("可用版本: \(versions.count)")
Text("|")
Text("依赖包: \(dependenciesCount)")
let products = findProducts(id: viewModel.uniqueProduct.id)
let versions = products.compactMap { product -> String? in
let platforms = product.platforms.filter { platform in
StorageData.shared.allowedPlatform.contains(platform.id)
}
return platforms.isEmpty ? nil : product.version
}
let uniqueVersions = Set(versions)
let dependenciesCount = products.first?.platforms.first?.languageSet.first?.dependencies.count ?? 0
let minOSVersion = products.first?.platforms.first?.range.first?.min ?? ""
let modulesCount = products.first?.platforms.first?.modules.count ?? 0
HStack(spacing: 12) {
HStack(spacing: 2) {
Image(systemName: "tag")
Text("\(uniqueVersions.count)")
}
if dependenciesCount > 0 {
Text("")
.foregroundColor(.gray)
HStack(spacing: 2) {
Image(systemName: "shippingbox")
Text("\(dependenciesCount)")
}
}
if !minOSVersion.isEmpty {
Text("")
.foregroundColor(.gray)
HStack(spacing: 2) {
Image(systemName: "macwindow")
Text(minOSVersion.replacingOccurrences(of: "-", with: ""))
}
}
if modulesCount > 0 {
Text("")
.foregroundColor(.gray)
HStack(spacing: 2) {
Image(systemName: "square.stack.3d.up")
Text("\(modulesCount)")
}
}
}
.font(.caption)
.foregroundColor(.secondary)
@@ -431,7 +472,7 @@ private struct SheetModifier: ViewModifier {
content
.sheet(isPresented: $viewModel.showVersionPicker) {
if let product = findProduct(id: viewModel.uniqueProduct.id) {
VersionPickerView(product: product) { version in
VersionPickerView(productId: viewModel.uniqueProduct.id) { version in
Task {
await viewModel.handleDownloadRequest(
version,

View File

@@ -8,8 +8,8 @@ import SwiftUI
private enum VersionPickerConstants {
static let headerPadding: CGFloat = 5
static let viewWidth: CGFloat = 400
static let viewHeight: CGFloat = 500
static let viewWidth: CGFloat = 500
static let viewHeight: CGFloat = 600
static let iconSize: CGFloat = 32
static let verticalSpacing: CGFloat = 8
static let horizontalSpacing: CGFloat = 12
@@ -26,19 +26,19 @@ struct VersionPickerView: View {
@StorageValue(\.downloadAppleSilicon) private var downloadAppleSilicon
@State private var expandedVersions: Set<String> = []
private let product: Product
private let productId: String
private let onSelect: (String) -> Void
init(product: Product, onSelect: @escaping (String) -> Void) {
self.product = product
init(productId: String, onSelect: @escaping (String) -> Void) {
self.productId = productId
self.onSelect = onSelect
}
var body: some View {
VStack(spacing: 0) {
VersionPickerHeaderView(product: product, downloadAppleSilicon: downloadAppleSilicon)
VersionPickerHeaderView(productId: productId, downloadAppleSilicon: downloadAppleSilicon)
VersionListView(
product: product,
productId: productId,
expandedVersions: $expandedVersions,
onSelect: onSelect,
dismiss: dismiss
@@ -49,16 +49,32 @@ struct VersionPickerView: View {
}
private struct VersionPickerHeaderView: View {
let product: Product
let productId: String
let downloadAppleSilicon: Bool
@Environment(\.dismiss) private var dismiss
@EnvironmentObject private var networkManager: NetworkManager
var body: some View {
VStack {
HStack {
Text("\(product.displayName)")
.font(.headline)
if let product = findProduct(id: productId) {
if let icon = product.getBestIcon() {
AsyncImage(url: URL(string: icon.value)) { image in
image
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: 24, height: 24)
} placeholder: {
Image(systemName: "app.fill")
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: 24, height: 24)
.foregroundColor(.blue)
}
}
Text("\(product.displayName)")
.font(.headline)
}
Text("选择版本")
.foregroundColor(.secondary)
Spacer()
@@ -68,10 +84,20 @@ private struct VersionPickerHeaderView: View {
}
.padding(.bottom, VersionPickerConstants.headerPadding)
Text("🔔 即将下载 \(downloadAppleSilicon ? "Apple Silicon" : "Intel") (\(platformText)) 版本 🔔")
.font(.caption)
.frame(maxWidth: .infinity, alignment: .leading)
.padding(.bottom, 10)
HStack(spacing: 6) {
Image(systemName: downloadAppleSilicon ? "m.square" : "x.square")
.foregroundColor(.blue)
Text(downloadAppleSilicon ? "Apple Silicon" : "Intel")
.font(.caption)
.fontWeight(.medium)
Text("")
.foregroundColor(.secondary)
Text(platformText)
.font(.caption)
.foregroundColor(.secondary)
}
.frame(maxWidth: .infinity, alignment: .leading)
.padding(.bottom, 10)
}
.padding(.horizontal)
.padding(.top)
@@ -84,51 +110,64 @@ private struct VersionPickerHeaderView: View {
}
private struct VersionListView: View {
@EnvironmentObject private var networkManager: NetworkManager
let product: Product
let productId: String
@Binding var expandedVersions: Set<String>
let onSelect: (String) -> Void
let dismiss: DismissAction
var body: some View {
ScrollView(showsIndicators: false) {
LazyVStack(spacing: VersionPickerConstants.verticalSpacing) {
ForEach(filteredVersions, id: \.key) { version, info in
VersionRow(
product: product,
version: version,
info: info,
isExpanded: expandedVersions.contains(version),
onSelect: handleVersionSelect,
onToggle: handleVersionToggle
)
VStack(spacing: 0) {
LazyVStack(spacing: VersionPickerConstants.verticalSpacing) {
ForEach(filteredVersions, id: \.key) { version, info in
VersionRow(
productId: productId,
version: version,
info: info,
isExpanded: expandedVersions.contains(version),
onSelect: handleVersionSelect,
onToggle: handleVersionToggle
)
}
}
.padding()
HStack(spacing: 8) {
Capsule()
.fill(Color.secondary.opacity(0.2))
.frame(width: 6, height: 6)
Text("获取到 \(filteredVersions.count) 个版本")
.font(.system(size: 12))
.foregroundColor(.secondary)
}
.padding(.bottom, 16)
}
.padding()
}
.background(Color(NSColor.windowBackgroundColor))
}
private var filteredVersions: [(key: String, value: Product.Platform)] {
//
let platforms = product.platforms.filter { platform in
StorageData.shared.allowedPlatform.contains(platform.id) &&
platform.languageSet.first != nil
}
//
if platforms.isEmpty {
let products = findProducts(id: productId)
if products.isEmpty {
return []
}
var versionPlatformMap: [String: Product.Platform] = [:]
//
return platforms.map { platform in
// 使 productVersion
(key: platform.languageSet.first?.productVersion ?? "", value: platform)
}.sorted { pair1, pair2 in
//
AppStatics.compareVersions(pair1.key, pair2.key) > 0
for product in products {
let platforms = product.platforms.filter { platform in
StorageData.shared.allowedPlatform.contains(platform.id)
}
if let firstPlatform = platforms.first {
versionPlatformMap[product.version] = firstPlatform
}
}
return versionPlatformMap.map { (key: $0.key, value: $0.value) }
.sorted { pair1, pair2 in
AppStatics.compareVersions(pair1.key, pair2.key) > 0
}
}
private func handleVersionSelect(_ version: String) {
@@ -150,7 +189,7 @@ private struct VersionListView: View {
private struct VersionRow: View {
@StorageValue(\.defaultLanguage) private var defaultLanguage
let product: Product
let productId: String
let version: String
let info: Product.Platform
let isExpanded: Bool
@@ -159,7 +198,7 @@ private struct VersionRow: View {
private var existingPath: URL? {
globalNetworkManager.isVersionDownloaded(
productId: product.id,
productId: productId,
version: version,
language: defaultLanguage
)
@@ -172,7 +211,7 @@ private struct VersionRow: View {
info: info,
isExpanded: isExpanded,
hasExistingPath: existingPath != nil,
onSelect: handleSelect,
onSelect: { onToggle(version) },
onToggle: { onToggle(version) }
)
@@ -188,15 +227,6 @@ private struct VersionRow: View {
.background(Color(NSColor.controlBackgroundColor))
.cornerRadius(VersionPickerConstants.cornerRadius)
}
private func handleSelect() {
let dependencies = info.languageSet.first?.dependencies ?? []
if dependencies.isEmpty {
onSelect(version)
} else {
onToggle(version)
}
}
}
private struct VersionHeader: View {
@@ -207,16 +237,20 @@ private struct VersionHeader: View {
let onSelect: () -> Void
let onToggle: () -> Void
private var hasDependencies: Bool {
!(info.languageSet.first?.dependencies.isEmpty ?? true)
}
var body: some View {
Button(action: onSelect) {
HStack {
VersionInfo(version: version, platform: info.id)
VersionInfo(version: version, platform: info.id, info: info)
Spacer()
ExistingPathButton(isVisible: hasExistingPath)
ExpandButton(
isExpanded: isExpanded,
onToggle: onToggle,
hasDependencies: !(info.languageSet.first?.dependencies.isEmpty ?? true)
hasDependencies: hasDependencies
)
}
.padding(.vertical, VersionPickerConstants.buttonPadding)
@@ -229,14 +263,46 @@ private struct VersionHeader: View {
private struct VersionInfo: View {
let version: String
let platform: String
let info: Product.Platform
private var productVersion: String? {
info.languageSet.first?.productVersion
}
private var buildGuid: String? {
info.languageSet.first?.buildGuid
}
var body: some View {
VStack(alignment: .leading, spacing: 4) {
Text(version)
.font(.headline)
Text(platform)
.font(.caption)
.foregroundColor(.secondary)
HStack(spacing: 6) {
Text(version)
.font(.headline)
if let pv = productVersion, pv != version {
Text("")
.foregroundColor(.secondary)
Text("v\(pv)")
.font(.caption)
.foregroundColor(.blue)
}
}
HStack(spacing: 4) {
Text(platform)
.font(.caption)
.foregroundColor(.secondary)
if let guid = buildGuid {
Text("")
.font(.caption)
.foregroundColor(.secondary)
Text(guid)
.font(.caption2)
.foregroundColor(.secondary)
.textSelection(.enabled)
}
}
}
}
}
@@ -263,17 +329,10 @@ private struct ExpandButton: View {
let hasDependencies: Bool
var body: some View {
Button(action: onToggle) {
Image(systemName: iconName)
.foregroundColor(.secondary)
}
}
private var iconName: String {
if !hasDependencies {
return "chevron.right"
}
return isExpanded ? "chevron.down" : "chevron.right"
Image(systemName: isExpanded ? "chevron.down" : "chevron.right")
.foregroundColor(.secondary)
.contentShape(Rectangle())
.onTapGesture(perform: onToggle)
}
}
@@ -282,15 +341,56 @@ private struct VersionDetails: View {
let version: String
let onSelect: (String) -> Void
private var hasDependencies: Bool {
!(info.languageSet.first?.dependencies.isEmpty ?? true)
}
private var hasModules: Bool {
!(info.modules.isEmpty)
}
var body: some View {
VStack(alignment: .leading, spacing: VersionPickerConstants.verticalSpacing) {
Text("依赖包:")
.font(.caption)
.foregroundColor(.secondary)
.padding(.top, 8)
.padding(.leading, 16)
DependenciesList(dependencies: info.languageSet.first?.dependencies ?? [])
if hasDependencies || hasModules {
VStack(alignment: .leading, spacing: 8) {
if hasDependencies {
HStack(spacing: 4) {
Image(systemName: "shippingbox")
.foregroundColor(.blue)
Text("依赖组件")
.font(.caption)
.foregroundColor(.secondary)
Text("(\(info.languageSet.first?.dependencies.count ?? 0))")
.font(.caption)
.foregroundColor(.blue)
}
DependenciesList(dependencies: info.languageSet.first?.dependencies ?? [])
.padding(.leading, 8)
}
if hasModules {
if hasDependencies {
Divider()
.padding(.vertical, 4)
}
HStack(spacing: 4) {
Image(systemName: "square.stack.3d.up")
.foregroundColor(.blue)
Text("可选模块")
.font(.caption)
.foregroundColor(.secondary)
Text("(\(info.modules.count))")
.font(.caption)
.foregroundColor(.blue)
}
ModulesList(modules: info.modules)
.padding(.leading, 8)
}
}
.background(Color(NSColor.controlBackgroundColor).opacity(0.5))
.cornerRadius(6)
}
DownloadButton(version: version, onSelect: onSelect)
}
@@ -304,15 +404,118 @@ private struct DependenciesList: View {
var body: some View {
ForEach(dependencies, id: \.sapCode) { dependency in
HStack(spacing: 8) {
Image(systemName: "cube.box")
.foregroundColor(.blue)
.frame(width: 16)
Text("\(dependency.sapCode) (\(dependency.baseVersion))")
VStack(alignment: .leading, spacing: 4) {
HStack(spacing: 6) {
getPlatformIcon(for: dependency.selectedPlatform)
.foregroundColor(.blue)
.frame(width: 16)
Text(dependency.sapCode)
.font(.caption)
.fontWeight(.medium)
Text("v\(dependency.productVersion)")
.font(.caption)
.foregroundColor(.blue)
}
HStack(spacing: 8) {
if dependency.baseVersion != dependency.productVersion {
Text("base: \(dependency.baseVersion)")
.font(.caption2)
.foregroundColor(.secondary)
}
if !dependency.buildGuid.isEmpty {
HStack(spacing: 4) {
Text("buildGuid:")
.font(.caption2)
.foregroundColor(.secondary)
Text(dependency.buildGuid)
.font(.caption2)
.foregroundColor(.secondary)
.textSelection(.enabled)
}
}
}
.padding(.leading, 22)
// DEBUG
#if DEBUG
VStack(alignment: .leading, spacing: 2) {
HStack(spacing: 4) {
Text("Match:")
.font(.caption2)
.foregroundColor(.secondary)
Text(dependency.isMatchPlatform ? "" : "")
.font(.caption2)
Text("")
.font(.caption2)
.foregroundColor(.secondary)
Text("Target:")
.font(.caption2)
.foregroundColor(.secondary)
Text(dependency.targetPlatform)
.font(.caption2)
.foregroundColor(.blue)
}
if !dependency.selectedReason.isEmpty {
HStack(spacing: 4) {
Text("Reason:")
.font(.caption2)
.foregroundColor(.secondary)
Text(dependency.selectedReason)
.font(.caption2)
.foregroundColor(.orange)
}
}
}
.padding(.leading, 22)
#endif
}
.padding(.vertical, 4)
}
}
private func getPlatformIcon(for platform: String) -> Image {
switch platform {
case "macarm64":
return Image(systemName: "m.square")
case "macuniversal":
return Image(systemName: "m.circle")
case "osx10", "osx10-64":
return Image(systemName: "x.square")
default:
return Image(systemName: "questionmark.square")
}
}
}
private struct ModulesList: View {
let modules: [Product.Platform.Module]
var body: some View {
ForEach(modules, id: \.id) { module in
HStack(spacing: 6) {
Circle()
.fill(Color.blue.opacity(0.2))
.frame(width: 6, height: 6)
Text(module.displayName)
.font(.caption)
if !module.deploymentType.isEmpty {
Text("(\(module.deploymentType))")
.font(.caption)
.foregroundColor(.secondary)
}
Spacer()
}
.padding(.leading, 24)
.padding(.vertical, 2)
}
}
}
@@ -322,11 +525,10 @@ private struct DownloadButton: View {
let onSelect: (String) -> Void
var body: some View {
Button("下载此版本") {
Button("下载") {
onSelect(version)
}
.buttonStyle(.borderedProminent)
.padding(.top, 8)
.padding(.leading, 16)
}
}

View File

@@ -3,14 +3,15 @@
"strings" : {
"" : {
},
" [%@]" : {
},
"(%@)" : {
},
"(%lld)" : {
},
"(可能导致处理 Setup 组件失败)" : {
"extractionState" : "stale",
"localizations" : {
"en" : {
"stringUnit" : {
@@ -21,6 +22,7 @@
}
},
"(将导致无法使用安装功能)" : {
"extractionState" : "stale",
"localizations" : {
"en" : {
"stringUnit" : {
@@ -29,6 +31,12 @@
}
}
}
},
"(退出代码: %lld)" : {
},
"[%@]" : {
},
"/" : {
@@ -126,6 +134,9 @@
}
}
}
},
"•" : {
},
"• 错误 2700不太可能会出现除非 Setup 组件处理失败了\n• 错误 107所下载的文件架构与系统架构不一致或者安装文件被损坏\n• 错误 103出现权限问题请确保 Helper 状态正常\n• 错误 182文件不齐全或文件被损坏或者你的Setup组件不一致请重新下载 X1a0He CC\n• 错误 133系统磁盘空间不足\n• 错误 -1Setup 组件未处理或处理失败,请联系开发者\n• 错误 195所下载的产品不支持你当前的系统\n• 错误 146请在 Mac 系统设置中给予 Adobe Downloader 全磁盘权限\n• 错误 255Setup 组件需要更新,请联系开发者解决" : {
"localizations" : {
@@ -137,10 +148,14 @@
}
}
},
"|" : {
"" : {
},
"❌" : {
},
"🔔 即将下载 %@ (%@) 版本 🔔" : {
"extractionState" : "stale",
"localizations" : {
"en" : {
"stringUnit" : {
@@ -285,12 +300,17 @@
},
"Apple Silicon" : {
},
"base: %@" : {
},
"buildGuid:" : {
},
"By X1a0He. ❤️ Love from China. 🇨🇳" : {
},
"Debug 模式" : {
"extractionState" : "stale",
"localizations" : {
"en" : {
"stringUnit" : {
@@ -420,9 +440,21 @@
}
}
}
},
"Intel" : {
},
"macOS %@" : {
},
"Match:" : {
},
"OK" : {
},
"Reason:" : {
},
"Setup 组件安装成功" : {
"extractionState" : "stale",
@@ -454,6 +486,9 @@
}
}
}
},
"Setup 组件未被处理 (退出代码: %lld)" : {
},
"Setup未备份提示" : {
"localizations" : {
@@ -464,6 +499,12 @@
}
}
}
},
"Target:" : {
},
"v%@" : {
},
"v4" : {
@@ -478,6 +519,7 @@
},
"X1a0He CC 下载并处理成功" : {
"extractionState" : "stale",
"localizations" : {
"en" : {
"stringUnit" : {
@@ -488,6 +530,7 @@
}
},
"X1a0He CC 下载成功" : {
"extractionState" : "stale",
"localizations" : {
"en" : {
"stringUnit" : {
@@ -640,6 +683,7 @@
},
"下载此版本" : {
"comment" : "版本选择页面",
"extractionState" : "stale",
"localizations" : {
"en" : {
"stringUnit" : {
@@ -837,6 +881,7 @@
}
},
"依赖包:" : {
"extractionState" : "stale",
"localizations" : {
"en" : {
"stringUnit" : {
@@ -847,6 +892,7 @@
}
},
"依赖包: %lld" : {
"extractionState" : "stale",
"localizations" : {
"en" : {
"stringUnit" : {
@@ -855,6 +901,9 @@
}
}
}
},
"依赖组件" : {
},
"修改 Setup 组件失败" : {
"localizations" : {
@@ -1088,6 +1137,7 @@
}
},
"可用版本: %lld" : {
"extractionState" : "stale",
"localizations" : {
"en" : {
"stringUnit" : {
@@ -1116,6 +1166,9 @@
}
}
}
},
"可选模块" : {
},
"命令行安装" : {
"localizations" : {
@@ -1270,6 +1323,7 @@
}
},
"安装失败 (退出代码: %lld)" : {
"extractionState" : "stale",
"localizations" : {
"en" : {
"stringUnit" : {
@@ -1290,6 +1344,7 @@
}
},
"安装失败: Setup 组件未被处理 (退出代码: %lld)" : {
"extractionState" : "stale",
"localizations" : {
"en" : {
"stringUnit" : {
@@ -1300,6 +1355,7 @@
}
},
"安装失败: 安装文件不完整或损坏 (退出代码: %lld)" : {
"extractionState" : "stale",
"localizations" : {
"en" : {
"stringUnit" : {
@@ -1310,6 +1366,7 @@
}
},
"安装失败: 权限问题 (退出代码: %lld)" : {
"extractionState" : "stale",
"localizations" : {
"en" : {
"stringUnit" : {
@@ -1320,6 +1377,7 @@
}
},
"安装失败: 架构或版本不一致 (退出代码: %lld)" : {
"extractionState" : "stale",
"localizations" : {
"en" : {
"stringUnit" : {
@@ -1348,6 +1406,9 @@
}
}
}
},
"安装文件不完整或损坏 (退出代码: %lld)" : {
},
"安装程序已存在" : {
"localizations" : {
@@ -1392,7 +1453,6 @@
}
},
"将执行的命令:" : {
"extractionState" : "stale",
"localizations" : {
"en" : {
"stringUnit" : {
@@ -1433,7 +1493,6 @@
}
},
"展开全部" : {
"extractionState" : "stale",
"localizations" : {
"en" : {
"stringUnit" : {
@@ -1454,6 +1513,7 @@
}
},
"已处理" : {
"extractionState" : "stale",
"localizations" : {
"en" : {
"stringUnit" : {
@@ -1464,6 +1524,7 @@
}
},
"已备份" : {
"extractionState" : "stale",
"localizations" : {
"en" : {
"stringUnit" : {
@@ -1669,7 +1730,6 @@
}
},
"折叠全部" : {
"extractionState" : "stale",
"localizations" : {
"en" : {
"stringUnit" : {
@@ -2107,6 +2167,15 @@
}
}
}
},
"权限问题 (退出代码: %lld)" : {
},
"架构或版本不一致 (退出代码: %lld)" : {
},
"查看持久化文件" : {
},
"检查中" : {
"localizations" : {
@@ -2672,6 +2741,9 @@
}
}
}
},
"系统信息" : {
},
"继续" : {
"localizations" : {
@@ -2745,6 +2817,9 @@
}
}
}
},
"获取到 %lld 个版本" : {
},
"获取到 %lld 款产品" : {
"localizations" : {