feat: Detection of Setup components and version

This commit is contained in:
X1a0He
2024-11-11 19:16:56 +08:00
parent 6de8104084
commit be2b160a06
22 changed files with 634 additions and 69 deletions

View File

@@ -10,8 +10,21 @@
3CB9FF092CDBAEF200D7A58B /* Sparkle in Frameworks */ = {isa = PBXBuildFile; productRef = 3CB9FF082CDBAEF200D7A58B /* Sparkle */; }; 3CB9FF092CDBAEF200D7A58B /* Sparkle in Frameworks */ = {isa = PBXBuildFile; productRef = 3CB9FF082CDBAEF200D7A58B /* Sparkle */; };
/* End PBXBuildFile section */ /* End PBXBuildFile section */
/* Begin PBXCopyFilesBuildPhase section */
3CE663452CE1FE8600CB9B35 /* CopyFiles */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = /usr/share/man/man1/;
dstSubfolderSpec = 0;
files = (
);
runOnlyForDeploymentPostprocessing = 1;
};
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */ /* Begin PBXFileReference section */
3CCC3AE02CC67B8F006E22B4 /* Adobe Downloader.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Adobe Downloader.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 3CCC3AE02CC67B8F006E22B4 /* Adobe Downloader.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Adobe Downloader.app"; sourceTree = BUILT_PRODUCTS_DIR; };
3CE663472CE1FE8600CB9B35 /* AdobeDownloaderHelper */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = AdobeDownloaderHelper; sourceTree = BUILT_PRODUCTS_DIR; };
/* End PBXFileReference section */ /* End PBXFileReference section */
/* Begin PBXFileSystemSynchronizedBuildFileExceptionSet section */ /* Begin PBXFileSystemSynchronizedBuildFileExceptionSet section */
@@ -49,6 +62,13 @@
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
3CE663442CE1FE8600CB9B35 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */ /* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */ /* Begin PBXGroup section */
@@ -65,6 +85,7 @@
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
3CCC3AE02CC67B8F006E22B4 /* Adobe Downloader.app */, 3CCC3AE02CC67B8F006E22B4 /* Adobe Downloader.app */,
3CE663472CE1FE8600CB9B35 /* AdobeDownloaderHelper */,
); );
name = Products; name = Products;
sourceTree = "<group>"; sourceTree = "<group>";
@@ -96,6 +117,25 @@
productReference = 3CCC3AE02CC67B8F006E22B4 /* Adobe Downloader.app */; productReference = 3CCC3AE02CC67B8F006E22B4 /* Adobe Downloader.app */;
productType = "com.apple.product-type.application"; productType = "com.apple.product-type.application";
}; };
3CE663462CE1FE8600CB9B35 /* AdobeDownloaderHelper */ = {
isa = PBXNativeTarget;
buildConfigurationList = 3CE6634B2CE1FE8600CB9B35 /* Build configuration list for PBXNativeTarget "AdobeDownloaderHelper" */;
buildPhases = (
3CE663432CE1FE8600CB9B35 /* Sources */,
3CE663442CE1FE8600CB9B35 /* Frameworks */,
3CE663452CE1FE8600CB9B35 /* CopyFiles */,
);
buildRules = (
);
dependencies = (
);
name = AdobeDownloaderHelper;
packageProductDependencies = (
);
productName = AdobeDownloaderHelper;
productReference = 3CE663472CE1FE8600CB9B35 /* AdobeDownloaderHelper */;
productType = "com.apple.product-type.tool";
};
/* End PBXNativeTarget section */ /* End PBXNativeTarget section */
/* Begin PBXProject section */ /* Begin PBXProject section */
@@ -103,12 +143,15 @@
isa = PBXProject; isa = PBXProject;
attributes = { attributes = {
BuildIndependentTargetsInParallel = 1; BuildIndependentTargetsInParallel = 1;
LastSwiftUpdateCheck = 1600; LastSwiftUpdateCheck = 1610;
LastUpgradeCheck = 1610; LastUpgradeCheck = 1610;
TargetAttributes = { TargetAttributes = {
3CCC3ADF2CC67B8F006E22B4 = { 3CCC3ADF2CC67B8F006E22B4 = {
CreatedOnToolsVersion = 16.0; CreatedOnToolsVersion = 16.0;
}; };
3CE663462CE1FE8600CB9B35 = {
CreatedOnToolsVersion = 16.1;
};
}; };
}; };
buildConfigurationList = 3CCC3ADB2CC67B8F006E22B4 /* Build configuration list for PBXProject "Adobe Downloader" */; buildConfigurationList = 3CCC3ADB2CC67B8F006E22B4 /* Build configuration list for PBXProject "Adobe Downloader" */;
@@ -129,6 +172,7 @@
projectRoot = ""; projectRoot = "";
targets = ( targets = (
3CCC3ADF2CC67B8F006E22B4 /* Adobe Downloader */, 3CCC3ADF2CC67B8F006E22B4 /* Adobe Downloader */,
3CE663462CE1FE8600CB9B35 /* AdobeDownloaderHelper */,
); );
}; };
/* End PBXProject section */ /* End PBXProject section */
@@ -151,6 +195,13 @@
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
3CE663432CE1FE8600CB9B35 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */ /* End PBXSourcesBuildPhase section */
/* Begin XCBuildConfiguration section */ /* Begin XCBuildConfiguration section */
@@ -286,7 +337,7 @@
CODE_SIGN_ENTITLEMENTS = "Adobe Downloader/Adobe Downloader.entitlements"; CODE_SIGN_ENTITLEMENTS = "Adobe Downloader/Adobe Downloader.entitlements";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES; COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 110; CURRENT_PROJECT_VERSION = 120;
DEAD_CODE_STRIPPING = YES; DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_ASSET_PATHS = "\"Adobe Downloader/Preview Content\""; DEVELOPMENT_ASSET_PATHS = "\"Adobe Downloader/Preview Content\"";
DEVELOPMENT_TEAM = ""; DEVELOPMENT_TEAM = "";
@@ -294,13 +345,14 @@
ENABLE_PREVIEWS = YES; ENABLE_PREVIEWS = YES;
GENERATE_INFOPLIST_FILE = YES; GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_KEY_CFBundleDisplayName = "Adobe Downloader"; INFOPLIST_KEY_CFBundleDisplayName = "Adobe Downloader";
INFOPLIST_KEY_NSDownloadsFolderUsageDescription = "需要访问下载文件夹来保存Adobe安装文件";
INFOPLIST_KEY_NSHumanReadableCopyright = ""; INFOPLIST_KEY_NSHumanReadableCopyright = "";
LD_RUNPATH_SEARCH_PATHS = ( LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)", "$(inherited)",
"@executable_path/../Frameworks", "@executable_path/../Frameworks",
); );
MACOSX_DEPLOYMENT_TARGET = 12.0; MACOSX_DEPLOYMENT_TARGET = 12.0;
MARKETING_VERSION = 1.1.0; MARKETING_VERSION = 1.2;
PRODUCT_BUNDLE_IDENTIFIER = "com.x1a0he.macOS.Adobe-Downloader"; PRODUCT_BUNDLE_IDENTIFIER = "com.x1a0he.macOS.Adobe-Downloader";
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_EMIT_LOC_STRINGS = YES;
@@ -318,7 +370,7 @@
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "-"; "CODE_SIGN_IDENTITY[sdk=macosx*]" = "-";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES; COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 110; CURRENT_PROJECT_VERSION = 120;
DEAD_CODE_STRIPPING = YES; DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_ASSET_PATHS = "\"Adobe Downloader/Preview Content\""; DEVELOPMENT_ASSET_PATHS = "\"Adobe Downloader/Preview Content\"";
DEVELOPMENT_TEAM = ""; DEVELOPMENT_TEAM = "";
@@ -326,13 +378,14 @@
ENABLE_PREVIEWS = YES; ENABLE_PREVIEWS = YES;
GENERATE_INFOPLIST_FILE = YES; GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_KEY_CFBundleDisplayName = "Adobe Downloader"; INFOPLIST_KEY_CFBundleDisplayName = "Adobe Downloader";
INFOPLIST_KEY_NSDownloadsFolderUsageDescription = "需要访问下载文件夹来保存Adobe安装文件";
INFOPLIST_KEY_NSHumanReadableCopyright = ""; INFOPLIST_KEY_NSHumanReadableCopyright = "";
LD_RUNPATH_SEARCH_PATHS = ( LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)", "$(inherited)",
"@executable_path/../Frameworks", "@executable_path/../Frameworks",
); );
MACOSX_DEPLOYMENT_TARGET = 12.0; MACOSX_DEPLOYMENT_TARGET = 12.0;
MARKETING_VERSION = 1.1.0; MARKETING_VERSION = 1.2;
PRODUCT_BUNDLE_IDENTIFIER = "com.x1a0he.macOS.Adobe-Downloader"; PRODUCT_BUNDLE_IDENTIFIER = "com.x1a0he.macOS.Adobe-Downloader";
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_EMIT_LOC_STRINGS = YES;
@@ -340,6 +393,27 @@
}; };
name = Release; name = Release;
}; };
3CE6634C2CE1FE8600CB9B35 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
CODE_SIGN_STYLE = Automatic;
MACOSX_DEPLOYMENT_TARGET = 15.1;
ONLY_ACTIVE_ARCH = YES;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0;
};
name = Debug;
};
3CE6634D2CE1FE8600CB9B35 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
CODE_SIGN_STYLE = Automatic;
MACOSX_DEPLOYMENT_TARGET = 15.1;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0;
};
name = Release;
};
/* End XCBuildConfiguration section */ /* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */ /* Begin XCConfigurationList section */
@@ -361,6 +435,15 @@
defaultConfigurationIsVisible = 0; defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release; defaultConfigurationName = Release;
}; };
3CE6634B2CE1FE8600CB9B35 /* Build configuration list for PBXNativeTarget "AdobeDownloaderHelper" */ = {
isa = XCConfigurationList;
buildConfigurations = (
3CE6634C2CE1FE8600CB9B35 /* Debug */,
3CE6634D2CE1FE8600CB9B35 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */ /* End XCConfigurationList section */
/* Begin XCRemoteSwiftPackageReference section */ /* Begin XCRemoteSwiftPackageReference section */

View File

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

View File

@@ -20,5 +20,21 @@
landmarkType = "7"> landmarkType = "7">
</BreakpointContent> </BreakpointContent>
</BreakpointProxy> </BreakpointProxy>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
uuid = "E5CEF575-C3CE-40C5-8038-C2BE8D9FAEA0"
shouldBeEnabled = "No"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "Adobe Downloader/Utils/InstallManager.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "143"
endingLineNumber = "143"
landmarkName = "install(at:progressHandler:logHandler:)"
landmarkType = "7">
</BreakpointContent>
</BreakpointProxy>
</Breakpoints> </Breakpoints>
</Bucket> </Bucket>

View File

@@ -14,6 +14,11 @@
<key>orderHint</key> <key>orderHint</key>
<integer>0</integer> <integer>0</integer>
</dict> </dict>
<key>AdobeDownloaderHelper.xcscheme_^#shared#^_</key>
<dict>
<key>orderHint</key>
<integer>1</integer>
</dict>
</dict> </dict>
<key>SuppressBuildableAutocreation</key> <key>SuppressBuildableAutocreation</key>
<dict> <dict>

View File

@@ -15,6 +15,9 @@ struct Adobe_DownloaderApp: App {
@AppStorage("confirmRedownload") private var confirmRedownload: Bool = true @AppStorage("confirmRedownload") private var confirmRedownload: Bool = true
@AppStorage("useDefaultDirectory") private var useDefaultDirectory: Bool = true @AppStorage("useDefaultDirectory") private var useDefaultDirectory: Bool = true
@AppStorage("defaultDirectory") private var defaultDirectory: String = "" @AppStorage("defaultDirectory") private var defaultDirectory: String = ""
@State private var showBackupResultAlert = false
@State private var backupResultMessage = ""
@State private var backupSuccess = false
private let updaterController: SPUStandardUpdaterController private let updaterController: SPUStandardUpdaterController
init() { init() {
@@ -61,8 +64,8 @@ struct Adobe_DownloaderApp: App {
networkManager.loadSavedTasks() networkManager.loadSavedTasks()
checkCreativeCloudSetup() checkCreativeCloudSetup()
if ModifySetup.checkSetupBackup() { if !showCreativeCloudAlert && !ModifySetup.isSetupBackup() {
showBackupAlert = true showBackupAlert = true
} }
@@ -71,18 +74,26 @@ struct Adobe_DownloaderApp: App {
UserDefaults.standard.removeObject(forKey: "isFirstLaunch") UserDefaults.standard.removeObject(forKey: "isFirstLaunch")
} }
} }
.sheet(isPresented: $showCreativeCloudAlert) {
ShouldExistsSetUpView()
}
.alert("Setup未备份提示", isPresented: $showBackupAlert) { .alert("Setup未备份提示", isPresented: $showBackupAlert) {
Button("OK") { Button("确定") {
ModifySetup.backupSetupFile { success, message in ModifySetup.backupSetupFile { success, message in
if !success { backupSuccess = success
print(message) backupResultMessage = message
} showBackupResultAlert = true
} }
} }
Button("取消", role: .cancel) {} Button("取消", role: .cancel) {}
} message: { } message: {
Text("检测到Setup文件尚未备份如果你需要安装程序则Setup必须被处理点击确定后你需要输入密码Adobe Downloader将自动处理并备份为Setup.original") Text("检测到Setup文件尚未备份如果你需要安装程序则Setup必须被处理点击确定后你需要输入密码Adobe Downloader将自动处理并备份为Setup.original")
} }
.alert(backupSuccess ? "备份成功" : "备份失败", isPresented: $showBackupResultAlert) {
Button("确定") { }
} message: {
Text(backupResultMessage)
}
.sheet(isPresented: $showTipsSheet) { .sheet(isPresented: $showTipsSheet) {
VStack(spacing: 20) { VStack(spacing: 20) {
Text("Adobe Downloader 已为你默认设定如下值") Text("Adobe Downloader 已为你默认设定如下值")
@@ -161,19 +172,6 @@ struct Adobe_DownloaderApp: App {
} }
} }
} }
.alert("未安装 Adobe Creative Cloud", isPresented: $showCreativeCloudAlert) {
Button("前往下载") {
if let url = URL(string: "https://creativecloud.adobe.com/apps/download/creative-cloud") {
NSWorkspace.shared.open(url)
}
NSApplication.shared.terminate(nil)
}
Button("取消", role: .cancel) {
NSApplication.shared.terminate(nil)
}
} message: {
Text("需要先安装 Adobe Creative Cloud 才能继续使用本程序")
}
} }
.windowStyle(.hiddenTitleBar) .windowStyle(.hiddenTitleBar)
.windowResizabilityContentSize() .windowResizabilityContentSize()

View File

@@ -86,6 +86,16 @@ struct ContentView: View {
.padding(.vertical, 8) .padding(.vertical, 8)
.background(Color(NSColor.windowBackgroundColor)) .background(Color(NSColor.windowBackgroundColor))
HStack() {
Image(systemName: "exclamationmark.triangle.fill")
.foregroundColor(.orange)
Text("Adobe Downloader 完全开源免费: https://github.com/X1a0He/Adobe-Downloader")
}
.frame(maxWidth: .infinity, alignment: .leading)
.padding(.horizontal)
.padding(.bottom, 5)
.background(Color(NSColor.windowBackgroundColor))
ZStack { ZStack {
Color(NSColor.windowBackgroundColor) Color(NSColor.windowBackgroundColor)
.ignoresSafeArea() .ignoresSafeArea()

View File

@@ -2,30 +2,28 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0"> <plist version="1.0">
<dict> <dict>
<key>com.apple.security.network.client</key>
<true/>
<key>com.apple.security.network.server</key>
<true/>
<key>NSAppTransportSecurity</key> <key>NSAppTransportSecurity</key>
<dict> <dict>
<key>NSAllowsArbitraryLoads</key> <key>NSAllowsArbitraryLoads</key>
<true/> <true/>
</dict> </dict>
<key>NSDownloadsFolderUsageDescription</key> <key>SUFeedURL</key>
<string>需要访问下载文件夹来保存Adobe安装文件</string> <string>https://raw.githubusercontent.com/X1a0He/Adobe-Downloader/refs/heads/main/appcast.xml</string>
<key>SUPublicEDKey</key>
<string>gYylad3ybfiyK5ZTS3xRrw+3c/8063mpXdQnPpMB86Q=</string>
<key>com.apple.security.app-sandbox</key> <key>com.apple.security.app-sandbox</key>
<true/> <true/>
<key>com.apple.security.files.downloads.read-write</key> <key>com.apple.security.files.downloads.read-write</key>
<true/> <true/>
<key>com.apple.security.files.user-selected.read-write</key> <key>com.apple.security.files.user-selected.read-write</key>
<true/> <true/>
<key>com.apple.security.network.client</key>
<true/>
<key>com.apple.security.network.server</key>
<true/>
<key>com.apple.security.temporary-exception.files.home-relative-path.read-write</key> <key>com.apple.security.temporary-exception.files.home-relative-path.read-write</key>
<array> <array>
<string>/Downloads/</string> <string>/Downloads/</string>
</array> </array>
<key>SUPublicEDKey</key>
<string>gYylad3ybfiyK5ZTS3xRrw+3c/8063mpXdQnPpMB86Q=</string>
<key>SUFeedURL</key>
<string>https://raw.githubusercontent.com/X1a0He/Adobe-Downloader/refs/heads/main/appcast.xml</string>
</dict> </dict>
</plist> </plist>

View File

@@ -94,7 +94,7 @@ actor InstallManager {
let code = Int32(codeStr) { let code = Int32(codeStr) {
if code != 0 { if code != 0 {
let errorMessage = code == -1 let errorMessage = code == -1
? String(localized: "安装程序调用失败,请联系X1a0He") ? String(localized: "安装程序调用失败,Setup 组件未被处理,请联系开发者")
: String(localized: "(退出代码: \(code))") : String(localized: "(退出代码: \(code))")
installProcess.terminate() installProcess.terminate()
@@ -115,9 +115,7 @@ actor InstallManager {
if installProcess.terminationStatus == 0 { if installProcess.terminationStatus == 0 {
continuation.resume() continuation.resume()
} else { } else {
let errorMessage = withSudo let errorMessage = String(localized: "(退出代码: \(installProcess.terminationStatus))")
? String(localized: "(退出代码: \(installProcess.terminationStatus))")
: String(localized: "重试失败,需要重新输入密码")
continuation.resume(throwing: InstallError.installationFailed(errorMessage)) continuation.resume(throwing: InstallError.installationFailed(errorMessage))
} }
} catch { } catch {
@@ -154,9 +152,11 @@ actor InstallManager {
logHandler: @escaping (String) -> Void logHandler: @escaping (String) -> Void
) async throws { ) async throws {
self.progressHandler = progressHandler self.progressHandler = progressHandler
let password = try await requestPassword()
try await executeInstallation( try await executeInstallation(
at: appPath, at: appPath,
withSudo: false, withSudo: true,
password: password,
progressHandler: progressHandler, progressHandler: progressHandler,
logHandler: logHandler logHandler: logHandler
) )

View File

@@ -9,12 +9,64 @@ import Foundation
import SwiftUI import SwiftUI
class ModifySetup { class ModifySetup {
static func checkSetupBackup() -> Bool { private static var cachedVersion: String?
let setupPath = "/Library/Application Support/Adobe/Adobe Desktop Common/HDBox/Setup"
let backupPath = "/Library/Application Support/Adobe/Adobe Desktop Common/HDBox/Setup.original" static func checkComponentVersion() -> String {
if let cachedVersion = cachedVersion {
return cachedVersion
}
return FileManager.default.fileExists(atPath: setupPath) && let setupPath = "/Library/Application Support/Adobe/Adobe Desktop Common/HDBox/Setup"
!FileManager.default.fileExists(atPath: backupPath)
guard FileManager.default.fileExists(atPath: setupPath) else {
let message = String(localized: "未找到 Setup 组件")
cachedVersion = message
return message
}
let process = Process()
process.executableURL = URL(fileURLWithPath: "/usr/bin/strings")
process.arguments = [setupPath]
let pipe = Pipe()
process.standardOutput = pipe
process.standardError = pipe
do {
try process.run()
process.waitUntilExit()
if let output = try pipe.fileHandleForReading.readToEnd(),
let outputString = String(data: output, encoding: .utf8) {
let lines = outputString.components(separatedBy: .newlines)
for (index, line) in lines.enumerated() {
if line == "Adobe Setup Version: %s" && index + 1 < lines.count {
let version = lines[index + 1].trimmingCharacters(in: .whitespacesAndNewlines)
if version.range(of: "^[0-9.]+$", options: .regularExpression) != nil {
cachedVersion = version
return version
}
}
}
}
let message = String(localized: "未知 Setup 组件版本号")
cachedVersion = message
return message
} catch {
print("Error checking Setup version: \(error)")
let message = String(localized: "未知 Setup 组件版本号")
cachedVersion = message
return message
}
}
static func clearVersionCache() {
cachedVersion = nil
}
static func isSetupBackup() -> Bool {
return FileManager.default.fileExists(atPath: "/Library/Application Support/Adobe/Adobe Desktop Common/HDBox/Setup.original")
} }
static func backupSetupFile(completion: @escaping (Bool, String) -> Void) { static func backupSetupFile(completion: @escaping (Bool, String) -> Void) {
@@ -55,7 +107,7 @@ prep '\(setupPath)'
try shellScript.write(to: tempScriptPath, atomically: true, encoding: .utf8) try shellScript.write(to: tempScriptPath, atomically: true, encoding: .utf8)
let script = """ let script = """
do shell script "chmod +x '\(tempScriptPath.path)' && sudo '\(tempScriptPath.path)'" with administrator privileges do shell script "sudo chmod 777 '\(tempScriptPath.path)' && sudo '\(tempScriptPath.path)'" with administrator privileges
""" """
var scriptError: NSDictionary? var scriptError: NSDictionary?

View File

@@ -10,7 +10,6 @@ class TaskPersistenceManager {
private init() { private init() {
let containerURL = fileManager.urls(for: .applicationSupportDirectory, in: .userDomainMask).first! let containerURL = fileManager.urls(for: .applicationSupportDirectory, in: .userDomainMask).first!
tasksDirectory = containerURL.appendingPathComponent("Adobe Downloader/tasks", isDirectory: true) tasksDirectory = containerURL.appendingPathComponent("Adobe Downloader/tasks", isDirectory: true)
print(tasksDirectory)
try? fileManager.createDirectory(at: tasksDirectory, withIntermediateDirectories: true) try? fileManager.createDirectory(at: tasksDirectory, withIntermediateDirectories: true)
} }

View File

@@ -27,7 +27,7 @@ struct AboutView: View {
} }
} }
.background(Color(NSColor.windowBackgroundColor)) .background(Color(NSColor.windowBackgroundColor))
.frame(width: 500, height: 350) .frame(width: 600)
} }
} }
@@ -40,6 +40,11 @@ struct GeneralSettingsView: View {
@AppStorage("downloadAppleSilicon") private var downloadAppleSilicon: Bool = true @AppStorage("downloadAppleSilicon") private var downloadAppleSilicon: Bool = true
@State private var showLanguagePicker = false @State private var showLanguagePicker = false
@EnvironmentObject private var networkManager: NetworkManager @EnvironmentObject private var networkManager: NetworkManager
@State private var showAlert = false
@State private var alertMessage = ""
@State private var isSuccess = false
@State private var setupVersion: String = ""
private let updater: SPUUpdater private let updater: SPUUpdater
@State private var automaticallyChecksForUpdates: Bool @State private var automaticallyChecksForUpdates: Bool
@@ -106,7 +111,44 @@ struct GeneralSettingsView: View {
} }
.padding(8) .padding(8)
} }
GroupBox(label: Text("其他设置").padding(.bottom, 8)) {
VStack(alignment: .leading, spacing: 12) {
HStack {
Text("Setup 备份状态: ")
if ModifySetup.isSetupBackup() {
Image(systemName: "checkmark.circle.fill")
.foregroundColor(.green)
} else {
Image(systemName: "xmark.circle.fill")
.foregroundColor(.red)
Text("(将导致无法使用安装功能)")
}
Spacer()
Button(action: {
ModifySetup.backupSetupFile { success, message in
self.isSuccess = success
self.alertMessage = message
self.showAlert = true
}
}) {
Text("立即备份")
}
.disabled(ModifySetup.isSetupBackup())
}
Divider()
HStack {
Text("Setup 组件版本: \(setupVersion)")
Spacer()
Button(action: {}) {
Text("下载 Setup 组件")
}
.disabled(setupVersion != String(localized: "未知 Setup 组件版本号"))
}
}.padding(8)
}
.padding(.vertical, 5)
GroupBox(label: Text("更新设置").padding(.bottom, 8)) { GroupBox(label: Text("更新设置").padding(.bottom, 8)) {
VStack(alignment: .leading, spacing: 12) { VStack(alignment: .leading, spacing: 12) {
HStack { HStack {
@@ -136,7 +178,15 @@ struct GeneralSettingsView: View {
showLanguagePicker = false showLanguagePicker = false
} }
} }
.alert(isPresented: $showAlert) {
Alert(
title: Text(isSuccess ? "操作成功" : "操作失败"),
message: Text(alertMessage),
dismissButton: .default(Text("确定"))
)
}
.onAppear { .onAppear {
setupVersion = ModifySetup.checkComponentVersion()
networkManager.updateAllowedPlatform(useAppleSilicon: downloadAppleSilicon) networkManager.updateAllowedPlatform(useAppleSilicon: downloadAppleSilicon)
} }
} }

View File

@@ -19,6 +19,7 @@ struct DownloadProgressView: View {
@State private var isPackageListExpanded: Bool = false @State private var isPackageListExpanded: Bool = false
@State private var expandedProducts: Set<String> = [] @State private var expandedProducts: Set<String> = []
@State private var iconImage: NSImage? = nil @State private var iconImage: NSImage? = nil
@State private var showSetupBackupAlert = false
private var statusLabel: some View { private var statusLabel: some View {
Text(task.status.description) Text(task.status.description)
@@ -116,16 +117,25 @@ struct DownloadProgressView: View {
HStack(spacing: 8) { HStack(spacing: 8) {
if task.displayInstallButton { if task.displayInstallButton {
Button(action: { Button(action: {
showInstallPrompt = false if !ModifySetup.isSetupBackup() {
isInstalling = true showSetupBackupAlert = true
Task { } else {
await networkManager.installProduct(at: task.directory) showInstallPrompt = false
isInstalling = true
Task {
await networkManager.installProduct(at: task.directory)
}
} }
}) { }) {
Label("安装", systemImage: "square.and.arrow.down.on.square") Label("安装", systemImage: "square.and.arrow.down.on.square")
} }
.buttonStyle(.borderedProminent) .buttonStyle(.borderedProminent)
.tint(.green) .tint(.green)
.alert("Setup 组件未处理", isPresented: $showSetupBackupAlert) {
Button("确定") { }
} message: {
Text("未对 Setup 组件进行备份处理,无法使用安装功能\n你可以通过设置页面再次对 Setup 组件进行备份处理")
}
} }
Button(action: onRemove) { Button(action: onRemove) {

View File

@@ -1,3 +1,10 @@
//
// ShouldExistsSetUpView.swift
// Adobe Downloader
//
// Created by X1a0He.
//
import SwiftUI import SwiftUI
struct ExistingFileAlertView: View { struct ExistingFileAlertView: View {

View File

@@ -0,0 +1,125 @@
//
// ShouldExistsSetUpView.swift
// Adobe Downloader
//
// Created by X1a0He on 11/11/24.
//
import SwiftUI
struct ShouldExistsSetUpView: View {
@Environment(\.dismiss) private var dismiss
@State private var showingAlert = false
@State private var isDownloading = false
@State private var downloadProgress: Double = 0
var body: some View {
VStack(spacing: 20) {
Image(systemName: "exclamationmark.triangle.fill")
.font(.system(size: 64))
.foregroundColor(.orange)
.padding(.bottom, 5)
.frame(alignment: .bottomTrailing)
Text("未检测到 Adobe Setup 组件")
.font(.system(size: 24))
.bold()
VStack(spacing: 4) {
Text("程序检测到你的系统中不存在 Adobe Setup 组件")
.multilineTextAlignment(.center)
Text("可能导致无法使用安装功能,请确保是否使用安装功能")
.multilineTextAlignment(.center)
}
VStack(spacing: 16) {
Button(action: {
showingAlert = true
}) {
Label("不使用安装功能", systemImage: "exclamationmark.triangle.fill")
.frame(minWidth: 0,maxWidth: 360)
.frame(height: 32)
.font(.system(size: 14))
}
.buttonStyle(.borderedProminent)
.tint(.orange)
.alert("确认", isPresented: $showingAlert) {
Button("取消", role: .cancel) { }
Button("确定", role: .destructive) {
dismiss()
}
} message: {
Text("你确定不使用安装功能吗?")
}
.disabled(isDownloading)
Button(action: {
isDownloading = true
// TODO
}) {
if isDownloading {
ProgressView(value: downloadProgress) {
Label("正在下载 X1a0He CC \(Int(downloadProgress * 100))%", systemImage: "arrow.down")
.frame(height: 32)
.frame(maxWidth: 360)
.frame(alignment: .center)
.font(.system(size: 14))
}
.progressViewStyle(.linear)
.tint(.green)
.frame(maxWidth: 360)
} else {
Label("下载 X1a0He CC 组件", systemImage: "arrow.down")
.frame(minWidth: 0, maxWidth: 360)
.frame(height: 32)
.font(.system(size: 14))
}
}
.buttonStyle(.borderedProminent)
.tint(.blue)
.disabled(isDownloading)
Button(action: {
if let url = URL(string: "https://creativecloud.adobe.com/apps/download/creative-cloud") {
NSWorkspace.shared.open(url)
dismiss()
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
NSApplication.shared.terminate(nil)
}
}
}) {
Label("前往 Adobe Creative Cloud", systemImage: "cloud.fill")
.frame(minWidth: 0,maxWidth: 360)
.frame(height: 32)
.font(.system(size: 14))
}
.disabled(isDownloading)
Button(action: {
dismiss()
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
NSApplication.shared.terminate(nil)
}
}) {
Label("退出", systemImage: "xmark")
.frame(minWidth: 0, maxWidth: 360)
.frame(height: 32)
.font(.system(size: 14))
}
.buttonStyle(.borderedProminent)
.tint(.red)
.keyboardShortcut(.cancelAction)
.disabled(isDownloading)
}
}
.frame(width: 400)
.padding()
.background(Color(NSColor.windowBackgroundColor))
.cornerRadius(12)
.shadow(radius: 10)
}
}
#Preview {
ShouldExistsSetUpView()
}

View File

@@ -1,6 +1,16 @@
{ {
"sourceLanguage" : "en", "sourceLanguage" : "en",
"strings" : { "strings" : {
"(将导致无法使用安装功能)" : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Unavailable to use install"
}
}
}
},
"(退出代码: %d)" : { "(退出代码: %d)" : {
"localizations" : { "localizations" : {
"en" : { "en" : {
@@ -105,6 +115,16 @@
}, },
"Adobe Downloader %@" : { "Adobe Downloader %@" : {
},
"Adobe Downloader 完全开源免费: https://github.com/X1a0He/Adobe-Downloader" : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Adobe Downloader is completely open source and free: https://github.com/X1a0He/Adobe-Downloader"
}
}
}
}, },
"Adobe Downloader 已为你默认设定如下值" : { "Adobe Downloader 已为你默认设定如下值" : {
"localizations" : { "localizations" : {
@@ -132,8 +152,35 @@
} }
} }
}, },
"OK" : { "Setup 备份状态: " : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Setup backup status:"
}
}
}
},
"Setup 组件未处理" : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Setup component not processed"
}
}
}
},
"Setup 组件版本: %@" : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Setup component version: %@"
}
}
}
}, },
"Setup未备份提示" : { "Setup未备份提示" : {
"localizations" : { "localizations" : {
@@ -165,6 +212,26 @@
} }
} }
}, },
"下载 Setup 组件" : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Download Setup component"
}
}
}
},
"下载 X1a0He CC 组件" : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Download X1a0He CC"
}
}
}
},
"下载中" : { "下载中" : {
"localizations" : { "localizations" : {
"en" : { "en" : {
@@ -238,6 +305,16 @@
} }
} }
}, },
"不使用安装功能" : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "I don't install apps"
}
}
}
},
"产品和包列表" : { "产品和包列表" : {
"localizations" : { "localizations" : {
"en" : { "en" : {
@@ -258,6 +335,16 @@
} }
} }
}, },
"你确定不使用安装功能吗?" : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Are you sure you don't want to install apps?"
}
}
}
},
"使用现有程序" : { "使用现有程序" : {
"localizations" : { "localizations" : {
"en" : { "en" : {
@@ -348,6 +435,16 @@
} }
} }
}, },
"其他设置" : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Other settings"
}
}
}
},
"删除" : { "删除" : {
"localizations" : { "localizations" : {
"en" : { "en" : {
@@ -358,12 +455,12 @@
} }
} }
}, },
"前往下载" : { "前往 Adobe Creative Cloud" : {
"localizations" : { "localizations" : {
"en" : { "en" : {
"stringUnit" : { "stringUnit" : {
"state" : "translated", "state" : "translated",
"value" : "Go to download" "value" : "Go to Adobe Creative Cloud"
} }
} }
} }
@@ -398,6 +495,36 @@
} }
} }
}, },
"可能导致无法使用安装功能,请确保是否使用安装功能" : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "This may result in the inability to use the installation function. Please make sure whether you use the installation function."
}
}
}
},
"备份失败" : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Backup failure"
}
}
}
},
"备份成功" : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Backup success"
}
}
}
},
"复制命令" : { "复制命令" : {
"localizations" : { "localizations" : {
"en" : { "en" : {
@@ -477,8 +604,12 @@
} }
} }
} }
},
"安装程序调用失败Setup 组件未被处理,请联系开发者" : {
}, },
"安装程序调用失败请联系X1a0He" : { "安装程序调用失败请联系X1a0He" : {
"extractionState" : "stale",
"localizations" : { "localizations" : {
"en" : { "en" : {
"stringUnit" : { "stringUnit" : {
@@ -639,6 +770,26 @@
} }
} }
}, },
"操作失败" : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Operation failed"
}
}
}
},
"操作成功" : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Operation successful"
}
}
}
},
"无法将响应数据转换为json字符串" : { "无法将响应数据转换为json字符串" : {
"localizations" : { "localizations" : {
"en" : { "en" : {
@@ -720,15 +871,18 @@
} }
} }
}, },
"未安装 Adobe Creative Cloud" : { "未对 Setup 组件进行备份处理,无法使用安装功能\n你可以通过设置页面再次对 Setup 组件进行备份处理" : {
"localizations" : { "localizations" : {
"en" : { "en" : {
"stringUnit" : { "stringUnit" : {
"state" : "translated", "state" : "translated",
"value" : "Adobe Creative Cloud not installed" "value" : "The Setup component has not been backed up, so the installation function cannot be used. You can back up the Setup component again through the settings page."
} }
} }
} }
},
"未找到 Setup 组件" : {
}, },
"未找到语言" : { "未找到语言" : {
"localizations" : { "localizations" : {
@@ -740,6 +894,26 @@
} }
} }
}, },
"未检测到 Adobe Setup 组件" : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Adobe Setup component not detected"
}
}
}
},
"未知 Setup 组件版本号" : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Unknown Setup component version"
}
}
}
},
"未设置" : { "未设置" : {
"comment" : "Default directory not set", "comment" : "Default directory not set",
"localizations" : { "localizations" : {
@@ -798,6 +972,16 @@
} }
} }
}, },
"正在下载 X1a0He CC %lld%%" : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Downloading X1a0He CC %lld"
}
}
}
},
"正在准备..." : { "正在准备..." : {
"localizations" : { "localizations" : {
"en" : { "en" : {
@@ -989,6 +1173,16 @@
} }
} }
}, },
"程序检测到你的系统中不存在 Adobe Setup 组件" : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Detected that the Adobe Setup component is not present on your system"
}
}
}
},
"程序重启后自动暂停" : { "程序重启后自动暂停" : {
"localizations" : { "localizations" : {
"en" : { "en" : {
@@ -999,6 +1193,16 @@
} }
} }
}, },
"立即备份" : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Backup now"
}
}
}
},
"等待中" : { "等待中" : {
"comment" : "Download status waiting", "comment" : "Download status waiting",
"localizations" : { "localizations" : {
@@ -1216,6 +1420,7 @@
} }
}, },
"重试失败,需要重新输入密码" : { "重试失败,需要重新输入密码" : {
"extractionState" : "stale",
"localizations" : { "localizations" : {
"en" : { "en" : {
"stringUnit" : { "stringUnit" : {
@@ -1234,16 +1439,6 @@
} }
} }
} }
},
"需要先安装 Adobe Creative Cloud 才能继续使用本程序" : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "You need to install Adobe Creative Cloud before you can continue using this program"
}
}
}
} }
}, },
"version" : "1.0" "version" : "1.0"

BIN
X1a0HeCC/HDBox/HDHelper Executable file

Binary file not shown.

BIN
X1a0HeCC/HDBox/HDIM.dylib Executable file

Binary file not shown.

BIN
X1a0HeCC/HDBox/HDPIM.dylib Executable file

Binary file not shown.

BIN
X1a0HeCC/HDBox/HUM.dylib Executable file

Binary file not shown.

BIN
X1a0HeCC/HDBox/Setup Executable file

Binary file not shown.

View File

@@ -4,7 +4,7 @@
# **[English version](readme-en.md)** # **[English version](readme-en.md)**
## 使用须知 ## 使用须知 Q & A
**🍎仅支持 macOS 12.0+** **🍎仅支持 macOS 12.0+**

View File

@@ -1,5 +1,22 @@
# Change Log # Change Log
- 2024-11-11 23:00 更新日志
[//]: # (1.2.0)
```markdown
1. 调整程序启动时 sheet 的弹出顺序
2. 设置中添加了 Setup 组件的检测和版本号检测,支持在设置中重新备份与处理
3. 调整 Setup 组件的检测,不再需要完整安装 Adobe Creative Cloud
4. 增加了安装前 Setup 组件是否已处理的判断,未处理 Setup 组件,无法使用安装功能
5. 调整 Setup 组件检测弹窗界面
PS: Setup 组件的来源均为 Adobe Creative Cloud 官方组件
====================
1.
```
- 2024-11-09 23:00 更新日志 - 2024-11-09 23:00 更新日志
[//]: # (1.1.0) [//]: # (1.1.0)