mirror of
https://github.com/X1a0He/Adobe-Downloader.git
synced 2025-11-25 03:14:57 +08:00
feat(CustomSettings): Added custom settings View.
This commit is contained in:
@@ -9,6 +9,7 @@ struct Adobe_DownloaderApp: App {
|
||||
@State private var showLanguagePicker = false
|
||||
@State private var showCreativeCloudAlert = false
|
||||
@State private var showBackupResultAlert = false
|
||||
@State private var showSettingsView = false
|
||||
|
||||
@StateObject private var backupResult = BackupResult()
|
||||
|
||||
@@ -61,7 +62,7 @@ struct Adobe_DownloaderApp: App {
|
||||
BlurView()
|
||||
.ignoresSafeArea()
|
||||
|
||||
ContentView()
|
||||
ContentView(showSettingsView: $showSettingsView)
|
||||
.environmentObject(globalNetworkManager)
|
||||
.frame(minWidth: 792, minHeight: 600)
|
||||
.tint(.blue)
|
||||
@@ -105,6 +106,10 @@ struct Adobe_DownloaderApp: App {
|
||||
}
|
||||
}
|
||||
}
|
||||
.sheet(isPresented: $showSettingsView) {
|
||||
CustomSettingsView(updater: updaterController.updater)
|
||||
.interactiveDismissDisabled(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
.windowStyle(.hiddenTitleBar)
|
||||
@@ -112,12 +117,15 @@ struct Adobe_DownloaderApp: App {
|
||||
.commands {
|
||||
CommandGroup(after: .appInfo) {
|
||||
CheckForUpdatesView(updater: updaterController.updater)
|
||||
|
||||
Divider()
|
||||
|
||||
Button("设置...") {
|
||||
showSettingsView = true
|
||||
}
|
||||
.keyboardShortcut(",", modifiers: .command)
|
||||
}
|
||||
}
|
||||
|
||||
Settings {
|
||||
AboutView(updater: updaterController.updater)
|
||||
}
|
||||
}
|
||||
|
||||
private func setupApplication() async {
|
||||
|
||||
@@ -7,6 +7,7 @@ struct ContentView: View {
|
||||
@State private var showDownloadManager = false
|
||||
@State private var searchText = ""
|
||||
@State private var currentApiVersion = StorageData.shared.apiVersion
|
||||
@Binding var showSettingsView: Bool
|
||||
|
||||
private var filteredProducts: [UniqueProduct] {
|
||||
if searchText.isEmpty { return globalUniqueProducts }
|
||||
@@ -17,7 +18,7 @@ struct ContentView: View {
|
||||
}
|
||||
|
||||
private func openSettings() {
|
||||
NSApp.sendAction(Selector(("showSettingsWindow:")), to: nil, from: nil)
|
||||
showSettingsView = true
|
||||
}
|
||||
|
||||
private func refreshData() {
|
||||
|
||||
@@ -63,7 +63,7 @@ class NetworkManager: ObservableObject {
|
||||
}
|
||||
func startDownload(productId: String, selectedVersion: String, language: String, destinationURL: URL) async throws {
|
||||
// 从 globalCcmResult 中获取 productId 对应的 ProductInfo
|
||||
guard let productInfo = globalCcmResult.products.first(where: { $0.id == productId }) else {
|
||||
guard let productInfo = globalCcmResult.products.first(where: { $0.id == productId && $0.version == selectedVersion }) else {
|
||||
throw NetworkError.productNotFound
|
||||
}
|
||||
|
||||
@@ -289,7 +289,7 @@ class NetworkManager: ObservableObject {
|
||||
!$0.status.isCompleted
|
||||
}) { return task.directory }
|
||||
|
||||
let platform = globalProducts.first(where: { $0.id == productId })?.platforms.first?.id ?? "unknown"
|
||||
let platform = globalProducts.first(where: { $0.id == productId && $0.version == version })?.platforms.first?.id ?? "unknown"
|
||||
let fileName = productId == "APRO"
|
||||
? "Adobe Downloader \(productId)_\(version)_\(platform).dmg"
|
||||
: "Adobe Downloader \(productId)_\(version)-\(language)-\(platform)"
|
||||
|
||||
@@ -165,12 +165,12 @@ class NewDownloadUtils {
|
||||
let isCore = packageType == "core"
|
||||
|
||||
let condition = package["Condition"] as? String ?? ""
|
||||
|
||||
let targetArchitecture = StorageData.shared.downloadAppleSilicon ? "arm64" : "x64"
|
||||
if isCore {
|
||||
if condition.isEmpty {
|
||||
shouldKeep = true
|
||||
} else {
|
||||
if condition.contains("[OSArchitecture]==\(AppStatics.architectureSymbol)") {
|
||||
if condition.contains("[OSArchitecture]==\(targetArchitecture)") {
|
||||
shouldKeep = true
|
||||
}
|
||||
if condition.contains("[installLanguage]==\(task.language)") || task.language == "ALL" {
|
||||
@@ -266,8 +266,9 @@ class NewDownloadUtils {
|
||||
|
||||
if dependencyToDownload.sapCode == productInfo.id {
|
||||
if isCore {
|
||||
let targetArchitecture = StorageData.shared.downloadAppleSilicon ? "arm64" : "x64"
|
||||
shouldDownload = condition.isEmpty ||
|
||||
condition.contains("[OSArchitecture]==\(AppStatics.architectureSymbol)") ||
|
||||
condition.contains("[OSArchitecture]==\(targetArchitecture)") ||
|
||||
condition.contains(installLanguage) || task.language == "ALL"
|
||||
} else {
|
||||
shouldDownload = condition.contains(installLanguage) || task.language == "ALL"
|
||||
@@ -715,8 +716,8 @@ class NewDownloadUtils {
|
||||
|
||||
func generateDriverXML(version: String, language: String, productInfo: Product, displayName: String) -> String {
|
||||
// 获取匹配的 platform 和 languageSet
|
||||
guard let platform = globalProducts.first(where: { $0.id == productInfo.id })?.platforms.first?.id,
|
||||
let languageSet = globalProducts.first(where: { $0.id == productInfo.id })?.platforms.first?.languageSet else {
|
||||
guard let platform = globalProducts.first(where: { $0.id == productInfo.id && $0.version == version })?.platforms.first?.id,
|
||||
let languageSet = globalProducts.first(where: { $0.id == productInfo.id && $0.version == version })?.platforms.first?.languageSet else {
|
||||
return ""
|
||||
}
|
||||
|
||||
|
||||
@@ -284,8 +284,7 @@ class NewJSONParser {
|
||||
let baseVersion = dep["baseVersion"] as? String else {
|
||||
return Product.Platform.LanguageSet.Dependency(sapCode: "",baseVersion: "",productVersion: "",buildGuid: "")
|
||||
}
|
||||
|
||||
let targetPlatform = AppStatics.isAppleSilicon ? "macarm64" : "osx10-64"
|
||||
let targetPlatform = StorageData.shared.downloadAppleSilicon ? "macarm64" : "osx10-64"
|
||||
let cacheKey = DependencyCacheKey(sapCode: sapCode, targetPlatform: targetPlatform)
|
||||
|
||||
if let cachedDependency = globalDependencyCache[cacheKey] {
|
||||
|
||||
@@ -127,7 +127,7 @@ final class AppCardViewModel: ObservableObject {
|
||||
}
|
||||
|
||||
func getDestinationURL(version: String, language: String) async throws -> URL {
|
||||
let platform = globalProducts.first(where: { $0.id == uniqueProduct.id })?.platforms.first?.id ?? "unknown"
|
||||
let platform = globalProducts.first(where: { $0.id == uniqueProduct.id && $0.version == version })?.platforms.first?.id ?? "unknown"
|
||||
let installerName = uniqueProduct.id == "APRO"
|
||||
? "Adobe Downloader \(uniqueProduct.id)_\(version)_\(platform).dmg"
|
||||
: "Adobe Downloader \(uniqueProduct.id)_\(version)-\(language)-\(platform)"
|
||||
|
||||
177
Adobe Downloader/Views/CustomSettingsView.swift
Normal file
177
Adobe Downloader/Views/CustomSettingsView.swift
Normal file
@@ -0,0 +1,177 @@
|
||||
//
|
||||
// CleanupView.swift
|
||||
// Adobe Downloader
|
||||
//
|
||||
// Created by X1a0He on 4/6/25.
|
||||
//
|
||||
import SwiftUI
|
||||
import Sparkle
|
||||
|
||||
struct CustomSettingsView: View {
|
||||
@State private var selectedTab = "general_settings"
|
||||
@Environment(\.presentationMode) var presentationMode
|
||||
@Environment(\.colorScheme) var colorScheme
|
||||
|
||||
private let updater: SPUUpdater
|
||||
|
||||
init(updater: SPUUpdater) {
|
||||
self.updater = updater
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
ZStack {
|
||||
BlurView()
|
||||
.ignoresSafeArea()
|
||||
|
||||
ZStack(alignment: .topTrailing) {
|
||||
VStack(spacing: 0) {
|
||||
HStack {
|
||||
HStack(spacing: 0) {
|
||||
SquareTabButton(
|
||||
imageName: "gear",
|
||||
title: "通用",
|
||||
isSelected: selectedTab == "general_settings"
|
||||
) {
|
||||
withAnimation(.easeInOut(duration: 0.15)) {
|
||||
selectedTab = "general_settings"
|
||||
}
|
||||
}
|
||||
.accessibilityLabel("通用")
|
||||
|
||||
SquareTabButton(
|
||||
imageName: "trash",
|
||||
title: "清理工具",
|
||||
isSelected: selectedTab == "cleanup_view"
|
||||
) {
|
||||
withAnimation(.easeInOut(duration: 0.15)) {
|
||||
selectedTab = "cleanup_view"
|
||||
}
|
||||
}
|
||||
.accessibilityLabel("清理工具")
|
||||
|
||||
SquareTabButton(
|
||||
imageName: "questionmark.circle",
|
||||
title: "常见问题",
|
||||
isSelected: selectedTab == "qa_view"
|
||||
) {
|
||||
withAnimation(.easeInOut(duration: 0.15)) {
|
||||
selectedTab = "qa_view"
|
||||
}
|
||||
}
|
||||
.accessibilityLabel("常见问题")
|
||||
|
||||
SquareTabButton(
|
||||
imageName: "info.circle",
|
||||
title: "关于",
|
||||
isSelected: selectedTab == "about_app"
|
||||
) {
|
||||
withAnimation(.easeInOut(duration: 0.15)) {
|
||||
selectedTab = "about_app"
|
||||
}
|
||||
}
|
||||
.accessibilityLabel("关于")
|
||||
}
|
||||
.padding(.leading, 8)
|
||||
|
||||
Spacer()
|
||||
}
|
||||
.padding(.top, 10)
|
||||
.padding(.bottom, 6)
|
||||
|
||||
Divider()
|
||||
.opacity(0.6)
|
||||
|
||||
ScrollView {
|
||||
ZStack {
|
||||
if selectedTab == "general_settings" {
|
||||
GeneralSettingsView(updater: updater)
|
||||
.transition(contentTransition)
|
||||
.id("general_settings")
|
||||
} else if selectedTab == "cleanup_view" {
|
||||
CleanupView()
|
||||
.transition(contentTransition)
|
||||
.id("cleanup_view")
|
||||
} else if selectedTab == "qa_view" {
|
||||
QAView()
|
||||
.transition(contentTransition)
|
||||
.id("qa_view")
|
||||
} else if selectedTab == "about_app" {
|
||||
AboutAppView()
|
||||
.transition(contentTransition)
|
||||
.id("about_app")
|
||||
}
|
||||
}
|
||||
.frame(maxWidth: .infinity)
|
||||
}
|
||||
.background(Color.clear)
|
||||
}
|
||||
|
||||
Button(action: {
|
||||
withAnimation {
|
||||
presentationMode.wrappedValue.dismiss()
|
||||
}
|
||||
}) {
|
||||
Image(systemName: "xmark")
|
||||
.font(.system(size: 11, weight: .bold))
|
||||
.foregroundColor(.gray)
|
||||
.frame(width: 20, height: 20)
|
||||
.background(
|
||||
Circle()
|
||||
.fill(colorScheme == .dark ?
|
||||
Color.gray.opacity(0.3) :
|
||||
Color.gray.opacity(0.15))
|
||||
)
|
||||
.help("关闭")
|
||||
}
|
||||
.buttonStyle(PlainButtonStyle())
|
||||
.keyboardShortcut(.escape, modifiers: [])
|
||||
.padding(.top, 10)
|
||||
.padding(.trailing, 10)
|
||||
}
|
||||
}
|
||||
.frame(width: 600, height: 830)
|
||||
.onAppear {
|
||||
selectedTab = "general_settings"
|
||||
}
|
||||
}
|
||||
|
||||
private var contentTransition: AnyTransition {
|
||||
.asymmetric(
|
||||
insertion: .opacity.combined(with: .scale(scale: 0.98)).animation(.easeInOut(duration: 0.2)),
|
||||
removal: .opacity.animation(.easeInOut(duration: 0.1))
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
struct SquareTabButton: View {
|
||||
let imageName: String
|
||||
let title: String
|
||||
let isSelected: Bool
|
||||
let action: () -> Void
|
||||
@Environment(\.colorScheme) var colorScheme
|
||||
|
||||
var body: some View {
|
||||
Button(action: action) {
|
||||
VStack(spacing: 4) {
|
||||
ZStack {
|
||||
if isSelected {
|
||||
RoundedRectangle(cornerRadius: 6)
|
||||
.fill(Color.blue.opacity(0.2))
|
||||
.frame(width: 40, height: 40)
|
||||
}
|
||||
|
||||
Image(systemName: imageName)
|
||||
.font(.system(size: isSelected ? 18 : 17))
|
||||
.foregroundColor(isSelected ? .blue : colorScheme == .dark ? .white : .black)
|
||||
}
|
||||
|
||||
Text(title)
|
||||
.font(.system(size: 12, weight: isSelected ? .medium : .regular))
|
||||
.foregroundColor(isSelected ? .blue : colorScheme == .dark ? .white : .primary)
|
||||
}
|
||||
.frame(width: 70)
|
||||
.contentShape(Rectangle())
|
||||
}
|
||||
.buttonStyle(PlainButtonStyle())
|
||||
}
|
||||
}
|
||||
@@ -148,33 +148,18 @@ struct ToolbarView: View {
|
||||
BeautifulSearchField(text: $searchText)
|
||||
.frame(maxWidth: 200)
|
||||
|
||||
if #available(macOS 14.0, *) {
|
||||
SettingsLink {
|
||||
ZStack {
|
||||
Circle()
|
||||
.fill(Color.secondary.opacity(0.1))
|
||||
.frame(width: 34, height: 34)
|
||||
|
||||
Image(systemName: "gearshape")
|
||||
.font(.system(size: 15, weight: .medium))
|
||||
.foregroundColor(.secondary)
|
||||
}
|
||||
Button(action: openSettings) {
|
||||
ZStack {
|
||||
Circle()
|
||||
.fill(Color.secondary.opacity(0.1))
|
||||
.frame(width: 34, height: 34)
|
||||
|
||||
Image(systemName: "gearshape")
|
||||
.font(.system(size: 15, weight: .medium))
|
||||
.foregroundColor(.secondary)
|
||||
}
|
||||
.buttonStyle(.plain)
|
||||
} else {
|
||||
Button(action: openSettings) {
|
||||
ZStack {
|
||||
Circle()
|
||||
.fill(Color.secondary.opacity(0.1))
|
||||
.frame(width: 34, height: 34)
|
||||
|
||||
Image(systemName: "gearshape")
|
||||
.font(.system(size: 15, weight: .medium))
|
||||
.foregroundColor(.secondary)
|
||||
}
|
||||
}
|
||||
.buttonStyle(.plain)
|
||||
}
|
||||
.buttonStyle(.plain)
|
||||
|
||||
Button(action: onRefresh) {
|
||||
ZStack {
|
||||
|
||||
@@ -1065,6 +1065,17 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"可选模块" : {
|
||||
"extractionState" : "stale",
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Modules"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"命令已复制到剪贴板" : {
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
@@ -2078,6 +2089,17 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"未对 Setup 组件进行处理或者 Setup 组件不存在,无法使用安装功能\n你可以通过设置页面再次对 Setup 组件进行处理" : {
|
||||
"extractionState" : "stale",
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "The Setup component has not been processed or does not exist, so the installation function cannot be used. You can process the Setup component again through the settings page."
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"未对 Setup 组件进行处理或者 Setup 组件不存在,无法使用安装功能\n你可以通过设置页面对 Setup 组件进行处理" : {
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
@@ -2175,6 +2197,17 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"查看持久化文件" : {
|
||||
"extractionState" : "stale",
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "View persistent files"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"检查中" : {
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
@@ -2975,6 +3008,16 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"设置..." : {
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Settings…"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"请求超时,请检查网络连接后重试" : {
|
||||
"comment" : "Network timeout",
|
||||
"localizations" : {
|
||||
|
||||
Reference in New Issue
Block a user