diff --git a/.gitignore b/.gitignore index a80a143..e6515f7 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,15 @@ .DS_Store - -Releases +._* +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent +.AppleDB +.AppleDesktop +DownloadFullInstaller-2.0-ES.png +DownloadFullInstaller-2.0.png +Temporary Items +Thumbs.db diff --git a/Download-Full-Installer-Info.plist b/Download-Full-Installer-Info.plist index 250fb9a..0c67376 100644 --- a/Download-Full-Installer-Info.plist +++ b/Download-Full-Installer-Info.plist @@ -1,8 +1,5 @@ - - LSApplicationCategoryType - public.app-category.utilities - + diff --git a/DownloadFullInstaller-1.0-screenshot.png b/DownloadFullInstaller-1.0-screenshot.png deleted file mode 100644 index a7fd9fd..0000000 Binary files a/DownloadFullInstaller-1.0-screenshot.png and /dev/null differ diff --git a/DownloadFullInstaller-2-Tahoe.png b/DownloadFullInstaller-2-Tahoe.png new file mode 100644 index 0000000..8be8529 Binary files /dev/null and b/DownloadFullInstaller-2-Tahoe.png differ diff --git a/DownloadFullInstaller-2.png b/DownloadFullInstaller-2.png new file mode 100644 index 0000000..606cd72 Binary files /dev/null and b/DownloadFullInstaller-2.png differ diff --git a/FetchInstallerPkg.xcodeproj/project.pbxproj b/FetchInstallerPkg.xcodeproj/project.pbxproj index 5b758bc..0ec68bd 100644 --- a/FetchInstallerPkg.xcodeproj/project.pbxproj +++ b/FetchInstallerPkg.xcodeproj/project.pbxproj @@ -7,6 +7,7 @@ objects = { /* Begin PBXBuildFile section */ + 9629D4592D07605C008D0D7A /* OSNames.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9629D4582D07605C008D0D7A /* OSNames.swift */; }; C635B0AA26789DA9001EEA82 /* PreferencesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C635B0A926789DA9001EEA82 /* PreferencesView.swift */; }; C635B0AC26789F5F001EEA82 /* SeedProgram.swift in Sources */ = {isa = PBXBuildFile; fileRef = C635B0AB26789F5F001EEA82 /* SeedProgram.swift */; }; C635B0AE2678AC9F001EEA82 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = C635B0AD2678AC9F001EEA82 /* AppDelegate.swift */; }; @@ -26,10 +27,15 @@ C69C80DB26788C4F00E20E20 /* DownloadView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C69C80DA26788C4F00E20E20 /* DownloadView.swift */; }; C69C80DD26788C7900E20E20 /* InstallerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C69C80DC26788C7900E20E20 /* InstallerView.swift */; }; C6E3CB99267A2AFB007084F6 /* IconView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C6E3CB98267A2AFB007084F6 /* IconView.swift */; }; + D9E6BC5D2D124138002729D4 /* Download-Full-Installer-InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = D9E6BC542D124138002729D4 /* Download-Full-Installer-InfoPlist.strings */; }; + D9E6BC5E2D124138002729D4 /* Download-Full-Installer-InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = D9E6BC592D124138002729D4 /* Download-Full-Installer-InfoPlist.strings */; }; + D9E6BC5F2D124138002729D4 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = D9E6BC5B2D124138002729D4 /* Localizable.strings */; }; + D9E6BC602D124138002729D4 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = D9E6BC562D124138002729D4 /* Localizable.strings */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ - C635B0A926789DA9001EEA82 /* PreferencesView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PreferencesView.swift; sourceTree = ""; }; + 9629D4582D07605C008D0D7A /* OSNames.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OSNames.swift; sourceTree = ""; }; + C635B0A926789DA9001EEA82 /* PreferencesView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PreferencesView.swift; sourceTree = ""; tabWidth = 4; usesTabs = 1; wrapsLines = 1; }; C635B0AB26789F5F001EEA82 /* SeedProgram.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SeedProgram.swift; sourceTree = ""; }; C635B0AD2678AC9F001EEA82 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; C635B0D92678E9C4001EEA82 /* Prefs.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Prefs.swift; sourceTree = ""; }; @@ -51,6 +57,10 @@ C69C80DC26788C7900E20E20 /* InstallerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InstallerView.swift; sourceTree = ""; }; C6B969B92681D3BE005717F1 /* Download-Full-Installer-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = "Download-Full-Installer-Info.plist"; sourceTree = ""; }; C6E3CB98267A2AFB007084F6 /* IconView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IconView.swift; sourceTree = ""; }; + D9E6BC532D124138002729D4 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = "Download-Full-Installer-InfoPlist.strings"; sourceTree = ""; }; + D9E6BC552D124138002729D4 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = Localizable.strings; sourceTree = ""; }; + D9E6BC582D124138002729D4 /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = "Download-Full-Installer-InfoPlist.strings"; sourceTree = ""; }; + D9E6BC5A2D124138002729D4 /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = Localizable.strings; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -84,6 +94,8 @@ C63643602670E1B800301DC8 /* FetchInstallerPkg */ = { isa = PBXGroup; children = ( + D9E6BC572D124138002729D4 /* en.lproj */, + D9E6BC5C2D124138002729D4 /* es.lproj */, C63643712670E82000301DC8 /* FetchInstallerPkg.entitlements */, C63643612670E1B800301DC8 /* FetchInstallerPkgApp.swift */, C635B0AD2678AC9F001EEA82 /* AppDelegate.swift */, @@ -116,6 +128,7 @@ C69C80D326788BA100E20E20 /* Package.swift */, C69C80CF26788B6B00E20E20 /* DistParserDelegate.swift */, C635B0AB26789F5F001EEA82 /* SeedProgram.swift */, + 9629D4582D07605C008D0D7A /* OSNames.swift */, ); path = Model; sourceTree = ""; @@ -132,6 +145,24 @@ path = View; sourceTree = ""; }; + D9E6BC572D124138002729D4 /* en.lproj */ = { + isa = PBXGroup; + children = ( + D9E6BC542D124138002729D4 /* Download-Full-Installer-InfoPlist.strings */, + D9E6BC562D124138002729D4 /* Localizable.strings */, + ); + path = en.lproj; + sourceTree = ""; + }; + D9E6BC5C2D124138002729D4 /* es.lproj */ = { + isa = PBXGroup; + children = ( + D9E6BC592D124138002729D4 /* Download-Full-Installer-InfoPlist.strings */, + D9E6BC5B2D124138002729D4 /* Localizable.strings */, + ); + path = es.lproj; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -161,7 +192,7 @@ attributes = { BuildIndependentTargetsInParallel = 1; LastSwiftUpdateCheck = 1300; - LastUpgradeCheck = 1300; + LastUpgradeCheck = 1520; TargetAttributes = { C636435D2670E1B800301DC8 = { CreatedOnToolsVersion = 13.0; @@ -175,6 +206,7 @@ knownRegions = ( en, Base, + es, ); mainGroup = C63643552670E1B800301DC8; productRefGroup = C636435F2670E1B800301DC8 /* Products */; @@ -193,6 +225,10 @@ files = ( C63643692670E1B900301DC8 /* Preview Assets.xcassets in Resources */, C63643662670E1B900301DC8 /* Assets.xcassets in Resources */, + D9E6BC5D2D124138002729D4 /* Download-Full-Installer-InfoPlist.strings in Resources */, + D9E6BC5E2D124138002729D4 /* Download-Full-Installer-InfoPlist.strings in Resources */, + D9E6BC5F2D124138002729D4 /* Localizable.strings in Resources */, + D9E6BC602D124138002729D4 /* Localizable.strings in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -201,6 +237,7 @@ /* Begin PBXShellScriptBuildPhase section */ C6B969B82681D0A0005717F1 /* Update Build Version */ = { isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; buildActionMask = 12; files = ( ); @@ -232,6 +269,7 @@ C635B0AA26789DA9001EEA82 /* PreferencesView.swift in Sources */, C69C80DD26788C7900E20E20 /* InstallerView.swift in Sources */, C635B0DA2678E9C4001EEA82 /* Prefs.swift in Sources */, + 9629D4592D07605C008D0D7A /* OSNames.swift in Sources */, C69C80CE26788B1400E20E20 /* Product.swift in Sources */, C63643622670E1B800301DC8 /* FetchInstallerPkgApp.swift in Sources */, C635B0AC26789F5F001EEA82 /* SeedProgram.swift in Sources */, @@ -247,6 +285,41 @@ }; /* End PBXSourcesBuildPhase section */ +/* Begin PBXVariantGroup section */ + D9E6BC542D124138002729D4 /* Download-Full-Installer-InfoPlist.strings */ = { + isa = PBXVariantGroup; + children = ( + D9E6BC532D124138002729D4 /* en */, + ); + name = "Download-Full-Installer-InfoPlist.strings"; + sourceTree = ""; + }; + D9E6BC562D124138002729D4 /* Localizable.strings */ = { + isa = PBXVariantGroup; + children = ( + D9E6BC552D124138002729D4 /* en */, + ); + name = Localizable.strings; + sourceTree = ""; + }; + D9E6BC592D124138002729D4 /* Download-Full-Installer-InfoPlist.strings */ = { + isa = PBXVariantGroup; + children = ( + D9E6BC582D124138002729D4 /* es */, + ); + name = "Download-Full-Installer-InfoPlist.strings"; + sourceTree = ""; + }; + D9E6BC5B2D124138002729D4 /* Localizable.strings */ = { + isa = PBXVariantGroup; + children = ( + D9E6BC5A2D124138002729D4 /* es */, + ); + name = Localizable.strings; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + /* Begin XCBuildConfiguration section */ C636436A2670E1B900301DC8 /* Debug */ = { isa = XCBuildConfiguration; @@ -282,9 +355,11 @@ CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COPY_PHASE_STRIP = NO; + DEAD_CODE_STRIPPING = YES; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; + ENABLE_USER_SCRIPT_SANDBOXING = YES; GCC_C_LANGUAGE_STANDARD = gnu11; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; @@ -343,9 +418,11 @@ CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COPY_PHASE_STRIP = NO; + DEAD_CODE_STRIPPING = YES; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = YES; GCC_C_LANGUAGE_STANDARD = gnu11; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; @@ -357,6 +434,7 @@ MACOSX_DEPLOYMENT_TARGET = 11.0; MTL_ENABLE_DEBUG_INFO = NO; MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx; SWIFT_COMPILATION_MODE = wholemodule; SWIFT_OPTIMIZATION_LEVEL = "-O"; @@ -371,29 +449,35 @@ ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = YES; CODE_SIGN_ENTITLEMENTS = FetchInstallerPkg/FetchInstallerPkg.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; + "CODE_SIGN_IDENTITY[sdk=macosx*]" = "-"; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 22; + CURRENT_PROJECT_VERSION = 45; + DEAD_CODE_STRIPPING = YES; DEVELOPMENT_ASSET_PATHS = "\"FetchInstallerPkg/Preview Content\""; - DEVELOPMENT_TEAM = JME5BW3F3R; + DEVELOPMENT_TEAM = ER43ZD2S4U; + DRIVERKIT_DEPLOYMENT_TARGET = 21.4; ENABLE_APP_SANDBOX = YES; ENABLE_HARDENED_RUNTIME = YES; ENABLE_PREVIEWS = YES; + ENABLE_USER_SCRIPT_SANDBOXING = NO; ENABLE_USER_SELECTED_FILES = readonly; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = "Download-Full-Installer-Info.plist"; INFOPLIST_KEY_CFBundleExecutable = "Download Full Installer"; INFOPLIST_KEY_CFBundleName = "Download Full Installer"; INFOPLIST_KEY_CFBundleVersion = 17; - INFOPLIST_KEY_NSHumanReadableCopyright = "©2021 Scripting OS X - Armin Briegel"; + INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities"; + INFOPLIST_KEY_NSHumanReadableCopyright = "©2021 Scripting OS X - Armin Briegel\n@2024 Matxpa (update to version 2.0)"; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 11.0; - MARKETING_VERSION = 1.1; - PRODUCT_BUNDLE_IDENTIFIER = com.scriptingosx.downloadfullinstaller; + MARKETING_VERSION = 2.0.2; + PRODUCT_BUNDLE_IDENTIFIER = None; PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_VERSION = 5.0; }; @@ -407,29 +491,35 @@ ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = YES; CODE_SIGN_ENTITLEMENTS = FetchInstallerPkg/FetchInstallerPkg.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; + "CODE_SIGN_IDENTITY[sdk=macosx*]" = "-"; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 22; + CURRENT_PROJECT_VERSION = 45; + DEAD_CODE_STRIPPING = YES; DEVELOPMENT_ASSET_PATHS = "\"FetchInstallerPkg/Preview Content\""; - DEVELOPMENT_TEAM = JME5BW3F3R; + DEVELOPMENT_TEAM = ER43ZD2S4U; + DRIVERKIT_DEPLOYMENT_TARGET = 21.4; ENABLE_APP_SANDBOX = YES; ENABLE_HARDENED_RUNTIME = YES; ENABLE_PREVIEWS = YES; + ENABLE_USER_SCRIPT_SANDBOXING = NO; ENABLE_USER_SELECTED_FILES = readonly; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = "Download-Full-Installer-Info.plist"; INFOPLIST_KEY_CFBundleExecutable = "Download Full Installer"; INFOPLIST_KEY_CFBundleName = "Download Full Installer"; INFOPLIST_KEY_CFBundleVersion = 17; - INFOPLIST_KEY_NSHumanReadableCopyright = "©2021 Scripting OS X - Armin Briegel"; + INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities"; + INFOPLIST_KEY_NSHumanReadableCopyright = "©2021 Scripting OS X - Armin Briegel\n@2024 Matxpa (update to version 2.0)"; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 11.0; - MARKETING_VERSION = 1.1; - PRODUCT_BUNDLE_IDENTIFIER = com.scriptingosx.downloadfullinstaller; + MARKETING_VERSION = "2.0\U0003.2"; + PRODUCT_BUNDLE_IDENTIFIER = None; PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_VERSION = 5.0; }; diff --git a/FetchInstallerPkg.xcodeproj/project.xcworkspace/xcuserdata/meunier.xcuserdatad/UserInterfaceState.xcuserstate b/FetchInstallerPkg.xcodeproj/project.xcworkspace/xcuserdata/meunier.xcuserdatad/UserInterfaceState.xcuserstate new file mode 100644 index 0000000..8f8614b Binary files /dev/null and b/FetchInstallerPkg.xcodeproj/project.xcworkspace/xcuserdata/meunier.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/FetchInstallerPkg.xcodeproj/project.xcworkspace/xcuserdata/yo.xcuserdatad/UserInterfaceState.xcuserstate b/FetchInstallerPkg.xcodeproj/project.xcworkspace/xcuserdata/yo.xcuserdatad/UserInterfaceState.xcuserstate new file mode 100644 index 0000000..025cc1f Binary files /dev/null and b/FetchInstallerPkg.xcodeproj/project.xcworkspace/xcuserdata/yo.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/FetchInstallerPkg.xcodeproj/xcshareddata/xcschemes/FetchInstallerPkg.xcscheme b/FetchInstallerPkg.xcodeproj/xcshareddata/xcschemes/FetchInstallerPkg.xcscheme index 6a64308..714e7d7 100644 --- a/FetchInstallerPkg.xcodeproj/xcshareddata/xcschemes/FetchInstallerPkg.xcscheme +++ b/FetchInstallerPkg.xcodeproj/xcshareddata/xcschemes/FetchInstallerPkg.xcscheme @@ -1,6 +1,6 @@ + + diff --git a/FetchInstallerPkg/AppDelegate.swift b/FetchInstallerPkg/AppDelegate.swift index 2df0a4f..4746562 100644 --- a/FetchInstallerPkg/AppDelegate.swift +++ b/FetchInstallerPkg/AppDelegate.swift @@ -5,15 +5,20 @@ // Created by Armin Briegel on 2021-06-15. // -import Foundation import AppKit +import Foundation enum DefaultsKeys: String { case seedProgram = "SeedProgram" + case osNameID = "OsNameID" } class AppDelegate: NSObject, NSApplicationDelegate { - func applicationDidFinishLaunching(_ notification: Notification) { + func applicationDidFinishLaunching(_: Notification) { Prefs.registerDefaults() } + + func applicationShouldTerminateAfterLastWindowClosed(_: NSApplication) -> Bool { + return true + } } diff --git a/FetchInstallerPkg/Assets.xcassets/11.imageset/Contents.json b/FetchInstallerPkg/Assets.xcassets/11.imageset/Contents.json new file mode 100644 index 0000000..566aed8 --- /dev/null +++ b/FetchInstallerPkg/Assets.xcassets/11.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "Mac OS X Lion.png", + "idiom" : "mac" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/FetchInstallerPkg/Assets.xcassets/11.imageset/Mac OS X Lion.png b/FetchInstallerPkg/Assets.xcassets/11.imageset/Mac OS X Lion.png new file mode 100644 index 0000000..bb58368 Binary files /dev/null and b/FetchInstallerPkg/Assets.xcassets/11.imageset/Mac OS X Lion.png differ diff --git a/FetchInstallerPkg/Assets.xcassets/12.imageset/Contents.json b/FetchInstallerPkg/Assets.xcassets/12.imageset/Contents.json new file mode 100644 index 0000000..dabbadd --- /dev/null +++ b/FetchInstallerPkg/Assets.xcassets/12.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "OS X Mountain Lion.png", + "idiom" : "mac" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/FetchInstallerPkg/Assets.xcassets/12.imageset/OS X Mountain Lion.png b/FetchInstallerPkg/Assets.xcassets/12.imageset/OS X Mountain Lion.png new file mode 100644 index 0000000..82e4591 Binary files /dev/null and b/FetchInstallerPkg/Assets.xcassets/12.imageset/OS X Mountain Lion.png differ diff --git a/FetchInstallerPkg/Assets.xcassets/13.imageset/Contents.json b/FetchInstallerPkg/Assets.xcassets/13.imageset/Contents.json new file mode 100644 index 0000000..04ca689 --- /dev/null +++ b/FetchInstallerPkg/Assets.xcassets/13.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "OS X Mavericks.png", + "idiom" : "mac" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/FetchInstallerPkg/Assets.xcassets/13.imageset/OS X Mavericks.png b/FetchInstallerPkg/Assets.xcassets/13.imageset/OS X Mavericks.png new file mode 100644 index 0000000..616b71a Binary files /dev/null and b/FetchInstallerPkg/Assets.xcassets/13.imageset/OS X Mavericks.png differ diff --git a/FetchInstallerPkg/Assets.xcassets/14.imageset/Contents.json b/FetchInstallerPkg/Assets.xcassets/14.imageset/Contents.json new file mode 100644 index 0000000..fdc84e4 --- /dev/null +++ b/FetchInstallerPkg/Assets.xcassets/14.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "OS X Yosemite.png", + "idiom" : "mac" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/FetchInstallerPkg/Assets.xcassets/14.imageset/OS X Yosemite.png b/FetchInstallerPkg/Assets.xcassets/14.imageset/OS X Yosemite.png new file mode 100644 index 0000000..cf19839 Binary files /dev/null and b/FetchInstallerPkg/Assets.xcassets/14.imageset/OS X Yosemite.png differ diff --git a/FetchInstallerPkg/Assets.xcassets/15.imageset/Contents.json b/FetchInstallerPkg/Assets.xcassets/15.imageset/Contents.json new file mode 100644 index 0000000..95b9013 --- /dev/null +++ b/FetchInstallerPkg/Assets.xcassets/15.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "OS X El Capitan.png", + "idiom" : "mac" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/FetchInstallerPkg/Assets.xcassets/15.imageset/OS X El Capitan.png b/FetchInstallerPkg/Assets.xcassets/15.imageset/OS X El Capitan.png new file mode 100644 index 0000000..eab9cd2 Binary files /dev/null and b/FetchInstallerPkg/Assets.xcassets/15.imageset/OS X El Capitan.png differ diff --git a/FetchInstallerPkg/Assets.xcassets/16.imageset/Contents.json b/FetchInstallerPkg/Assets.xcassets/16.imageset/Contents.json new file mode 100644 index 0000000..08f83e5 --- /dev/null +++ b/FetchInstallerPkg/Assets.xcassets/16.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "macOS Sierra.png", + "idiom" : "mac" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/FetchInstallerPkg/Assets.xcassets/16.imageset/macOS Sierra.png b/FetchInstallerPkg/Assets.xcassets/16.imageset/macOS Sierra.png new file mode 100644 index 0000000..42b9d92 Binary files /dev/null and b/FetchInstallerPkg/Assets.xcassets/16.imageset/macOS Sierra.png differ diff --git a/FetchInstallerPkg/Assets.xcassets/17.imageset/Contents.json b/FetchInstallerPkg/Assets.xcassets/17.imageset/Contents.json new file mode 100644 index 0000000..1b5918a --- /dev/null +++ b/FetchInstallerPkg/Assets.xcassets/17.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images": [ + { + "filename": "macOS High Sierra.png", + "idiom": "mac" + } + ], + "info": { + "author": "xcode", + "version": 1 + } +} diff --git a/FetchInstallerPkg/Assets.xcassets/17.imageset/macOS High Sierra.png b/FetchInstallerPkg/Assets.xcassets/17.imageset/macOS High Sierra.png new file mode 100644 index 0000000..74cff3f Binary files /dev/null and b/FetchInstallerPkg/Assets.xcassets/17.imageset/macOS High Sierra.png differ diff --git a/FetchInstallerPkg/Assets.xcassets/18.imageset/Contents.json b/FetchInstallerPkg/Assets.xcassets/18.imageset/Contents.json new file mode 100644 index 0000000..b3b0087 --- /dev/null +++ b/FetchInstallerPkg/Assets.xcassets/18.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images": [ + { + "filename": "macOS Mojave Light.png", + "idiom": "mac" + }, + { + "appearances": [ + { + "appearance": "luminosity", + "value": "dark" + } + ], + "filename": "macOS Mojave Dark.png", + "idiom": "mac" + } + ], + "info": { + "author": "xcode", + "version": 1 + } +} diff --git a/FetchInstallerPkg/Assets.xcassets/18.imageset/macOS Mojave Dark.png b/FetchInstallerPkg/Assets.xcassets/18.imageset/macOS Mojave Dark.png new file mode 100644 index 0000000..f226bc1 Binary files /dev/null and b/FetchInstallerPkg/Assets.xcassets/18.imageset/macOS Mojave Dark.png differ diff --git a/FetchInstallerPkg/Assets.xcassets/18.imageset/macOS Mojave Light.png b/FetchInstallerPkg/Assets.xcassets/18.imageset/macOS Mojave Light.png new file mode 100644 index 0000000..1144943 Binary files /dev/null and b/FetchInstallerPkg/Assets.xcassets/18.imageset/macOS Mojave Light.png differ diff --git a/FetchInstallerPkg/Assets.xcassets/19.imageset/Contents.json b/FetchInstallerPkg/Assets.xcassets/19.imageset/Contents.json new file mode 100644 index 0000000..e148991 --- /dev/null +++ b/FetchInstallerPkg/Assets.xcassets/19.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images": [ + { + "filename": "macOS Catalina Light.png", + "idiom": "mac" + }, + { + "appearances": [ + { + "appearance": "luminosity", + "value": "dark" + } + ], + "filename": "macOS Catalina Dark.png", + "idiom": "mac" + } + ], + "info": { + "author": "xcode", + "version": 1 + } +} diff --git a/FetchInstallerPkg/Assets.xcassets/19.imageset/macOS Catalina Dark.png b/FetchInstallerPkg/Assets.xcassets/19.imageset/macOS Catalina Dark.png new file mode 100644 index 0000000..4c9e63e Binary files /dev/null and b/FetchInstallerPkg/Assets.xcassets/19.imageset/macOS Catalina Dark.png differ diff --git a/FetchInstallerPkg/Assets.xcassets/19.imageset/macOS Catalina Light.png b/FetchInstallerPkg/Assets.xcassets/19.imageset/macOS Catalina Light.png new file mode 100644 index 0000000..9f3f3bd Binary files /dev/null and b/FetchInstallerPkg/Assets.xcassets/19.imageset/macOS Catalina Light.png differ diff --git a/FetchInstallerPkg/Assets.xcassets/20.imageset/Contents.json b/FetchInstallerPkg/Assets.xcassets/20.imageset/Contents.json new file mode 100644 index 0000000..a432a84 --- /dev/null +++ b/FetchInstallerPkg/Assets.xcassets/20.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images": [ + { + "filename": "macOS Big Sur Light.png", + "idiom": "mac" + }, + { + "appearances": [ + { + "appearance": "luminosity", + "value": "dark" + } + ], + "filename": "macOS Big Sur Dark.png", + "idiom": "mac" + } + ], + "info": { + "author": "xcode", + "version": 1 + } +} diff --git a/FetchInstallerPkg/Assets.xcassets/20.imageset/macOS Big Sur Dark.png b/FetchInstallerPkg/Assets.xcassets/20.imageset/macOS Big Sur Dark.png new file mode 100755 index 0000000..62d136a Binary files /dev/null and b/FetchInstallerPkg/Assets.xcassets/20.imageset/macOS Big Sur Dark.png differ diff --git a/FetchInstallerPkg/Assets.xcassets/20.imageset/macOS Big Sur Light.png b/FetchInstallerPkg/Assets.xcassets/20.imageset/macOS Big Sur Light.png new file mode 100644 index 0000000..1f7f2ef Binary files /dev/null and b/FetchInstallerPkg/Assets.xcassets/20.imageset/macOS Big Sur Light.png differ diff --git a/FetchInstallerPkg/Assets.xcassets/21.imageset/Contents.json b/FetchInstallerPkg/Assets.xcassets/21.imageset/Contents.json new file mode 100644 index 0000000..b0a271b --- /dev/null +++ b/FetchInstallerPkg/Assets.xcassets/21.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images": [ + { + "filename": "macOS Monterey Light.png", + "idiom": "mac" + }, + { + "appearances": [ + { + "appearance": "luminosity", + "value": "dark" + } + ], + "filename": "macOS Monterey Dark.png", + "idiom": "mac" + } + ], + "info": { + "author": "xcode", + "version": 1 + } +} diff --git a/FetchInstallerPkg/Assets.xcassets/21.imageset/macOS Monterey Dark.png b/FetchInstallerPkg/Assets.xcassets/21.imageset/macOS Monterey Dark.png new file mode 100755 index 0000000..5986944 Binary files /dev/null and b/FetchInstallerPkg/Assets.xcassets/21.imageset/macOS Monterey Dark.png differ diff --git a/FetchInstallerPkg/Assets.xcassets/21.imageset/macOS Monterey Light.png b/FetchInstallerPkg/Assets.xcassets/21.imageset/macOS Monterey Light.png new file mode 100644 index 0000000..26e9980 Binary files /dev/null and b/FetchInstallerPkg/Assets.xcassets/21.imageset/macOS Monterey Light.png differ diff --git a/FetchInstallerPkg/Assets.xcassets/22.imageset/Contents.json b/FetchInstallerPkg/Assets.xcassets/22.imageset/Contents.json new file mode 100644 index 0000000..1789ffa --- /dev/null +++ b/FetchInstallerPkg/Assets.xcassets/22.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images": [ + { + "filename": "macOS Ventura Light.png", + "idiom": "mac" + }, + { + "appearances": [ + { + "appearance": "luminosity", + "value": "dark" + } + ], + "filename": "macOS Ventura Dark.png", + "idiom": "mac" + } + ], + "info": { + "author": "xcode", + "version": 1 + } +} diff --git a/FetchInstallerPkg/Assets.xcassets/22.imageset/macOS Ventura Dark.png b/FetchInstallerPkg/Assets.xcassets/22.imageset/macOS Ventura Dark.png new file mode 100644 index 0000000..ad8fb97 Binary files /dev/null and b/FetchInstallerPkg/Assets.xcassets/22.imageset/macOS Ventura Dark.png differ diff --git a/FetchInstallerPkg/Assets.xcassets/22.imageset/macOS Ventura Light.png b/FetchInstallerPkg/Assets.xcassets/22.imageset/macOS Ventura Light.png new file mode 100644 index 0000000..63e41c4 Binary files /dev/null and b/FetchInstallerPkg/Assets.xcassets/22.imageset/macOS Ventura Light.png differ diff --git a/FetchInstallerPkg/Assets.xcassets/23.imageset/Contents.json b/FetchInstallerPkg/Assets.xcassets/23.imageset/Contents.json new file mode 100644 index 0000000..650c879 --- /dev/null +++ b/FetchInstallerPkg/Assets.xcassets/23.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images": [ + { + "filename": "macOS Sonoma Light.png", + "idiom": "mac" + }, + { + "appearances": [ + { + "appearance": "luminosity", + "value": "dark" + } + ], + "filename": "macOS Sonoma Dark.png", + "idiom": "mac" + } + ], + "info": { + "author": "xcode", + "version": 1 + } +} diff --git a/FetchInstallerPkg/Assets.xcassets/23.imageset/macOS Sonoma Dark.png b/FetchInstallerPkg/Assets.xcassets/23.imageset/macOS Sonoma Dark.png new file mode 100644 index 0000000..83d7b29 Binary files /dev/null and b/FetchInstallerPkg/Assets.xcassets/23.imageset/macOS Sonoma Dark.png differ diff --git a/FetchInstallerPkg/Assets.xcassets/23.imageset/macOS Sonoma Light.png b/FetchInstallerPkg/Assets.xcassets/23.imageset/macOS Sonoma Light.png new file mode 100644 index 0000000..6210220 Binary files /dev/null and b/FetchInstallerPkg/Assets.xcassets/23.imageset/macOS Sonoma Light.png differ diff --git a/FetchInstallerPkg/Assets.xcassets/24.imageset/Contents.json b/FetchInstallerPkg/Assets.xcassets/24.imageset/Contents.json new file mode 100644 index 0000000..7e3e551 --- /dev/null +++ b/FetchInstallerPkg/Assets.xcassets/24.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images": [ + { + "filename": "macOS Sequoia Light.png", + "idiom": "mac" + }, + { + "appearances": [ + { + "appearance": "luminosity", + "value": "dark" + } + ], + "filename": "macOS Sequoia Dark.png", + "idiom": "mac" + } + ], + "info": { + "author": "xcode", + "version": 1 + } +} diff --git a/FetchInstallerPkg/Assets.xcassets/24.imageset/macOS Sequoia Dark.png b/FetchInstallerPkg/Assets.xcassets/24.imageset/macOS Sequoia Dark.png new file mode 100755 index 0000000..c4e7d97 Binary files /dev/null and b/FetchInstallerPkg/Assets.xcassets/24.imageset/macOS Sequoia Dark.png differ diff --git a/FetchInstallerPkg/Assets.xcassets/24.imageset/macOS Sequoia Light.png b/FetchInstallerPkg/Assets.xcassets/24.imageset/macOS Sequoia Light.png new file mode 100644 index 0000000..5a4925f Binary files /dev/null and b/FetchInstallerPkg/Assets.xcassets/24.imageset/macOS Sequoia Light.png differ diff --git a/FetchInstallerPkg/Assets.xcassets/25.imageset/Contents.json b/FetchInstallerPkg/Assets.xcassets/25.imageset/Contents.json new file mode 100644 index 0000000..3e2f462 --- /dev/null +++ b/FetchInstallerPkg/Assets.xcassets/25.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images": [ + { + "filename": "macOS Tahoe.png", + "idiom": "mac" + } + ], + "info": { + "author": "xcode", + "version": 1 + } +} diff --git a/FetchInstallerPkg/Assets.xcassets/25.imageset/macOS Tahoe.png b/FetchInstallerPkg/Assets.xcassets/25.imageset/macOS Tahoe.png new file mode 100644 index 0000000..112966c Binary files /dev/null and b/FetchInstallerPkg/Assets.xcassets/25.imageset/macOS Tahoe.png differ diff --git a/FetchInstallerPkg/Assets.xcassets/99.imageset/Contents.json b/FetchInstallerPkg/Assets.xcassets/99.imageset/Contents.json new file mode 100644 index 0000000..f39974b --- /dev/null +++ b/FetchInstallerPkg/Assets.xcassets/99.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images": [ + { + "filename": "macOS.png", + "idiom": "mac" + } + ], + "info": { + "author": "xcode", + "version": 1 + } +} diff --git a/FetchInstallerPkg/Assets.xcassets/99.imageset/macOS.png b/FetchInstallerPkg/Assets.xcassets/99.imageset/macOS.png new file mode 100644 index 0000000..63776d4 Binary files /dev/null and b/FetchInstallerPkg/Assets.xcassets/99.imageset/macOS.png differ diff --git a/FetchInstallerPkg/Assets.xcassets/Big Sur.imageset/Big Sur 64.png b/FetchInstallerPkg/Assets.xcassets/Big Sur.imageset/Big Sur 64.png deleted file mode 100644 index ecdc5b6..0000000 Binary files a/FetchInstallerPkg/Assets.xcassets/Big Sur.imageset/Big Sur 64.png and /dev/null differ diff --git a/FetchInstallerPkg/Assets.xcassets/Big Sur.imageset/Contents.json b/FetchInstallerPkg/Assets.xcassets/Big Sur.imageset/Contents.json index 11a6d18..a432a84 100644 --- a/FetchInstallerPkg/Assets.xcassets/Big Sur.imageset/Contents.json +++ b/FetchInstallerPkg/Assets.xcassets/Big Sur.imageset/Contents.json @@ -1,21 +1,22 @@ { - "images" : [ + "images": [ { - "idiom" : "universal", - "scale" : "1x" + "filename": "macOS Big Sur Light.png", + "idiom": "mac" }, - { - "filename" : "Big Sur 64.png", - "idiom" : "universal", - "scale" : "2x" - }, - { - "idiom" : "universal", - "scale" : "3x" - } + { + "appearances": [ + { + "appearance": "luminosity", + "value": "dark" + } + ], + "filename": "macOS Big Sur Dark.png", + "idiom": "mac" + } ], - "info" : { - "author" : "xcode", - "version" : 1 + "info": { + "author": "xcode", + "version": 1 } } diff --git a/FetchInstallerPkg/Assets.xcassets/Big Sur.imageset/macOS Big Sur Dark.png b/FetchInstallerPkg/Assets.xcassets/Big Sur.imageset/macOS Big Sur Dark.png new file mode 100755 index 0000000..62d136a Binary files /dev/null and b/FetchInstallerPkg/Assets.xcassets/Big Sur.imageset/macOS Big Sur Dark.png differ diff --git a/FetchInstallerPkg/Assets.xcassets/Big Sur.imageset/macOS Big Sur Light.png b/FetchInstallerPkg/Assets.xcassets/Big Sur.imageset/macOS Big Sur Light.png new file mode 100644 index 0000000..1f7f2ef Binary files /dev/null and b/FetchInstallerPkg/Assets.xcassets/Big Sur.imageset/macOS Big Sur Light.png differ diff --git a/FetchInstallerPkg/Assets.xcassets/Catalina.imageset/Contents.json b/FetchInstallerPkg/Assets.xcassets/Catalina.imageset/Contents.json new file mode 100644 index 0000000..e148991 --- /dev/null +++ b/FetchInstallerPkg/Assets.xcassets/Catalina.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images": [ + { + "filename": "macOS Catalina Light.png", + "idiom": "mac" + }, + { + "appearances": [ + { + "appearance": "luminosity", + "value": "dark" + } + ], + "filename": "macOS Catalina Dark.png", + "idiom": "mac" + } + ], + "info": { + "author": "xcode", + "version": 1 + } +} diff --git a/FetchInstallerPkg/Assets.xcassets/Catalina.imageset/macOS Catalina Dark.png b/FetchInstallerPkg/Assets.xcassets/Catalina.imageset/macOS Catalina Dark.png new file mode 100644 index 0000000..4c9e63e Binary files /dev/null and b/FetchInstallerPkg/Assets.xcassets/Catalina.imageset/macOS Catalina Dark.png differ diff --git a/FetchInstallerPkg/Assets.xcassets/Catalina.imageset/macOS Catalina Light.png b/FetchInstallerPkg/Assets.xcassets/Catalina.imageset/macOS Catalina Light.png new file mode 100644 index 0000000..9f3f3bd Binary files /dev/null and b/FetchInstallerPkg/Assets.xcassets/Catalina.imageset/macOS Catalina Light.png differ diff --git a/FetchInstallerPkg/Assets.xcassets/El Capitan.imageset/Contents.json b/FetchInstallerPkg/Assets.xcassets/El Capitan.imageset/Contents.json new file mode 100644 index 0000000..95b9013 --- /dev/null +++ b/FetchInstallerPkg/Assets.xcassets/El Capitan.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "OS X El Capitan.png", + "idiom" : "mac" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/FetchInstallerPkg/Assets.xcassets/El Capitan.imageset/OS X El Capitan.png b/FetchInstallerPkg/Assets.xcassets/El Capitan.imageset/OS X El Capitan.png new file mode 100644 index 0000000..eab9cd2 Binary files /dev/null and b/FetchInstallerPkg/Assets.xcassets/El Capitan.imageset/OS X El Capitan.png differ diff --git a/FetchInstallerPkg/Assets.xcassets/High Sierra.imageset/Contents.json b/FetchInstallerPkg/Assets.xcassets/High Sierra.imageset/Contents.json new file mode 100644 index 0000000..1b5918a --- /dev/null +++ b/FetchInstallerPkg/Assets.xcassets/High Sierra.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images": [ + { + "filename": "macOS High Sierra.png", + "idiom": "mac" + } + ], + "info": { + "author": "xcode", + "version": 1 + } +} diff --git a/FetchInstallerPkg/Assets.xcassets/High Sierra.imageset/macOS High Sierra.png b/FetchInstallerPkg/Assets.xcassets/High Sierra.imageset/macOS High Sierra.png new file mode 100644 index 0000000..74cff3f Binary files /dev/null and b/FetchInstallerPkg/Assets.xcassets/High Sierra.imageset/macOS High Sierra.png differ diff --git a/FetchInstallerPkg/Assets.xcassets/Lion.imageset/Contents.json b/FetchInstallerPkg/Assets.xcassets/Lion.imageset/Contents.json new file mode 100644 index 0000000..566aed8 --- /dev/null +++ b/FetchInstallerPkg/Assets.xcassets/Lion.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "Mac OS X Lion.png", + "idiom" : "mac" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/FetchInstallerPkg/Assets.xcassets/Lion.imageset/Mac OS X Lion.png b/FetchInstallerPkg/Assets.xcassets/Lion.imageset/Mac OS X Lion.png new file mode 100644 index 0000000..bb58368 Binary files /dev/null and b/FetchInstallerPkg/Assets.xcassets/Lion.imageset/Mac OS X Lion.png differ diff --git a/FetchInstallerPkg/Assets.xcassets/Mavericks.imageset/Contents.json b/FetchInstallerPkg/Assets.xcassets/Mavericks.imageset/Contents.json new file mode 100644 index 0000000..04ca689 --- /dev/null +++ b/FetchInstallerPkg/Assets.xcassets/Mavericks.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "OS X Mavericks.png", + "idiom" : "mac" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/FetchInstallerPkg/Assets.xcassets/Mavericks.imageset/OS X Mavericks.png b/FetchInstallerPkg/Assets.xcassets/Mavericks.imageset/OS X Mavericks.png new file mode 100644 index 0000000..616b71a Binary files /dev/null and b/FetchInstallerPkg/Assets.xcassets/Mavericks.imageset/OS X Mavericks.png differ diff --git a/FetchInstallerPkg/Assets.xcassets/Mojave.imageset/Contents.json b/FetchInstallerPkg/Assets.xcassets/Mojave.imageset/Contents.json new file mode 100644 index 0000000..b3b0087 --- /dev/null +++ b/FetchInstallerPkg/Assets.xcassets/Mojave.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images": [ + { + "filename": "macOS Mojave Light.png", + "idiom": "mac" + }, + { + "appearances": [ + { + "appearance": "luminosity", + "value": "dark" + } + ], + "filename": "macOS Mojave Dark.png", + "idiom": "mac" + } + ], + "info": { + "author": "xcode", + "version": 1 + } +} diff --git a/FetchInstallerPkg/Assets.xcassets/Mojave.imageset/macOS Mojave Dark.png b/FetchInstallerPkg/Assets.xcassets/Mojave.imageset/macOS Mojave Dark.png new file mode 100644 index 0000000..f226bc1 Binary files /dev/null and b/FetchInstallerPkg/Assets.xcassets/Mojave.imageset/macOS Mojave Dark.png differ diff --git a/FetchInstallerPkg/Assets.xcassets/Mojave.imageset/macOS Mojave Light.png b/FetchInstallerPkg/Assets.xcassets/Mojave.imageset/macOS Mojave Light.png new file mode 100644 index 0000000..1144943 Binary files /dev/null and b/FetchInstallerPkg/Assets.xcassets/Mojave.imageset/macOS Mojave Light.png differ diff --git a/FetchInstallerPkg/Assets.xcassets/Monterey.imageset/Contents.json b/FetchInstallerPkg/Assets.xcassets/Monterey.imageset/Contents.json new file mode 100644 index 0000000..b0a271b --- /dev/null +++ b/FetchInstallerPkg/Assets.xcassets/Monterey.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images": [ + { + "filename": "macOS Monterey Light.png", + "idiom": "mac" + }, + { + "appearances": [ + { + "appearance": "luminosity", + "value": "dark" + } + ], + "filename": "macOS Monterey Dark.png", + "idiom": "mac" + } + ], + "info": { + "author": "xcode", + "version": 1 + } +} diff --git a/FetchInstallerPkg/Assets.xcassets/Monterey.imageset/macOS Monterey Dark.png b/FetchInstallerPkg/Assets.xcassets/Monterey.imageset/macOS Monterey Dark.png new file mode 100755 index 0000000..5986944 Binary files /dev/null and b/FetchInstallerPkg/Assets.xcassets/Monterey.imageset/macOS Monterey Dark.png differ diff --git a/FetchInstallerPkg/Assets.xcassets/Monterey.imageset/macOS Monterey Light.png b/FetchInstallerPkg/Assets.xcassets/Monterey.imageset/macOS Monterey Light.png new file mode 100644 index 0000000..26e9980 Binary files /dev/null and b/FetchInstallerPkg/Assets.xcassets/Monterey.imageset/macOS Monterey Light.png differ diff --git a/FetchInstallerPkg/Assets.xcassets/Mountain Lion.imageset/Contents.json b/FetchInstallerPkg/Assets.xcassets/Mountain Lion.imageset/Contents.json new file mode 100644 index 0000000..dabbadd --- /dev/null +++ b/FetchInstallerPkg/Assets.xcassets/Mountain Lion.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "OS X Mountain Lion.png", + "idiom" : "mac" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/FetchInstallerPkg/Assets.xcassets/Mountain Lion.imageset/OS X Mountain Lion.png b/FetchInstallerPkg/Assets.xcassets/Mountain Lion.imageset/OS X Mountain Lion.png new file mode 100644 index 0000000..82e4591 Binary files /dev/null and b/FetchInstallerPkg/Assets.xcassets/Mountain Lion.imageset/OS X Mountain Lion.png differ diff --git a/FetchInstallerPkg/Assets.xcassets/Sequoia.imageset/Contents.json b/FetchInstallerPkg/Assets.xcassets/Sequoia.imageset/Contents.json new file mode 100644 index 0000000..7e3e551 --- /dev/null +++ b/FetchInstallerPkg/Assets.xcassets/Sequoia.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images": [ + { + "filename": "macOS Sequoia Light.png", + "idiom": "mac" + }, + { + "appearances": [ + { + "appearance": "luminosity", + "value": "dark" + } + ], + "filename": "macOS Sequoia Dark.png", + "idiom": "mac" + } + ], + "info": { + "author": "xcode", + "version": 1 + } +} diff --git a/FetchInstallerPkg/Assets.xcassets/Sequoia.imageset/macOS Sequoia Dark.png b/FetchInstallerPkg/Assets.xcassets/Sequoia.imageset/macOS Sequoia Dark.png new file mode 100755 index 0000000..c4e7d97 Binary files /dev/null and b/FetchInstallerPkg/Assets.xcassets/Sequoia.imageset/macOS Sequoia Dark.png differ diff --git a/FetchInstallerPkg/Assets.xcassets/Sequoia.imageset/macOS Sequoia Light.png b/FetchInstallerPkg/Assets.xcassets/Sequoia.imageset/macOS Sequoia Light.png new file mode 100644 index 0000000..5a4925f Binary files /dev/null and b/FetchInstallerPkg/Assets.xcassets/Sequoia.imageset/macOS Sequoia Light.png differ diff --git a/FetchInstallerPkg/Assets.xcassets/Sierra.imageset/Contents.json b/FetchInstallerPkg/Assets.xcassets/Sierra.imageset/Contents.json new file mode 100644 index 0000000..08f83e5 --- /dev/null +++ b/FetchInstallerPkg/Assets.xcassets/Sierra.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "macOS Sierra.png", + "idiom" : "mac" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/FetchInstallerPkg/Assets.xcassets/Sierra.imageset/macOS Sierra.png b/FetchInstallerPkg/Assets.xcassets/Sierra.imageset/macOS Sierra.png new file mode 100644 index 0000000..42b9d92 Binary files /dev/null and b/FetchInstallerPkg/Assets.xcassets/Sierra.imageset/macOS Sierra.png differ diff --git a/FetchInstallerPkg/Assets.xcassets/Sonoma.imageset/Contents.json b/FetchInstallerPkg/Assets.xcassets/Sonoma.imageset/Contents.json new file mode 100644 index 0000000..650c879 --- /dev/null +++ b/FetchInstallerPkg/Assets.xcassets/Sonoma.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images": [ + { + "filename": "macOS Sonoma Light.png", + "idiom": "mac" + }, + { + "appearances": [ + { + "appearance": "luminosity", + "value": "dark" + } + ], + "filename": "macOS Sonoma Dark.png", + "idiom": "mac" + } + ], + "info": { + "author": "xcode", + "version": 1 + } +} diff --git a/FetchInstallerPkg/Assets.xcassets/Sonoma.imageset/macOS Sonoma Dark.png b/FetchInstallerPkg/Assets.xcassets/Sonoma.imageset/macOS Sonoma Dark.png new file mode 100644 index 0000000..83d7b29 Binary files /dev/null and b/FetchInstallerPkg/Assets.xcassets/Sonoma.imageset/macOS Sonoma Dark.png differ diff --git a/FetchInstallerPkg/Assets.xcassets/Sonoma.imageset/macOS Sonoma Light.png b/FetchInstallerPkg/Assets.xcassets/Sonoma.imageset/macOS Sonoma Light.png new file mode 100644 index 0000000..6210220 Binary files /dev/null and b/FetchInstallerPkg/Assets.xcassets/Sonoma.imageset/macOS Sonoma Light.png differ diff --git a/FetchInstallerPkg/Assets.xcassets/Tahoe.imageset/Contents.json b/FetchInstallerPkg/Assets.xcassets/Tahoe.imageset/Contents.json new file mode 100644 index 0000000..3e2f462 --- /dev/null +++ b/FetchInstallerPkg/Assets.xcassets/Tahoe.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images": [ + { + "filename": "macOS Tahoe.png", + "idiom": "mac" + } + ], + "info": { + "author": "xcode", + "version": 1 + } +} diff --git a/FetchInstallerPkg/Assets.xcassets/Tahoe.imageset/macOS Tahoe.png b/FetchInstallerPkg/Assets.xcassets/Tahoe.imageset/macOS Tahoe.png new file mode 100644 index 0000000..112966c Binary files /dev/null and b/FetchInstallerPkg/Assets.xcassets/Tahoe.imageset/macOS Tahoe.png differ diff --git a/FetchInstallerPkg/Assets.xcassets/Ventura.imageset/Contents.json b/FetchInstallerPkg/Assets.xcassets/Ventura.imageset/Contents.json new file mode 100644 index 0000000..1789ffa --- /dev/null +++ b/FetchInstallerPkg/Assets.xcassets/Ventura.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images": [ + { + "filename": "macOS Ventura Light.png", + "idiom": "mac" + }, + { + "appearances": [ + { + "appearance": "luminosity", + "value": "dark" + } + ], + "filename": "macOS Ventura Dark.png", + "idiom": "mac" + } + ], + "info": { + "author": "xcode", + "version": 1 + } +} diff --git a/FetchInstallerPkg/Assets.xcassets/Ventura.imageset/macOS Ventura Dark.png b/FetchInstallerPkg/Assets.xcassets/Ventura.imageset/macOS Ventura Dark.png new file mode 100644 index 0000000..ad8fb97 Binary files /dev/null and b/FetchInstallerPkg/Assets.xcassets/Ventura.imageset/macOS Ventura Dark.png differ diff --git a/FetchInstallerPkg/Assets.xcassets/Ventura.imageset/macOS Ventura Light.png b/FetchInstallerPkg/Assets.xcassets/Ventura.imageset/macOS Ventura Light.png new file mode 100644 index 0000000..63e41c4 Binary files /dev/null and b/FetchInstallerPkg/Assets.xcassets/Ventura.imageset/macOS Ventura Light.png differ diff --git a/FetchInstallerPkg/Assets.xcassets/Yosemite.imageset/Contents.json b/FetchInstallerPkg/Assets.xcassets/Yosemite.imageset/Contents.json new file mode 100644 index 0000000..fdc84e4 --- /dev/null +++ b/FetchInstallerPkg/Assets.xcassets/Yosemite.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "OS X Yosemite.png", + "idiom" : "mac" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/FetchInstallerPkg/Assets.xcassets/Yosemite.imageset/OS X Yosemite.png b/FetchInstallerPkg/Assets.xcassets/Yosemite.imageset/OS X Yosemite.png new file mode 100644 index 0000000..cf19839 Binary files /dev/null and b/FetchInstallerPkg/Assets.xcassets/Yosemite.imageset/OS X Yosemite.png differ diff --git a/FetchInstallerPkg/Assets.xcassets/macOS.imageset/Contents.json b/FetchInstallerPkg/Assets.xcassets/macOS.imageset/Contents.json index 2404aaf..f39974b 100644 --- a/FetchInstallerPkg/Assets.xcassets/macOS.imageset/Contents.json +++ b/FetchInstallerPkg/Assets.xcassets/macOS.imageset/Contents.json @@ -1,21 +1,12 @@ { - "images" : [ + "images": [ { - "idiom" : "universal", - "scale" : "1x" - }, - { - "filename" : "macOS 64.png", - "idiom" : "universal", - "scale" : "2x" - }, - { - "idiom" : "universal", - "scale" : "3x" + "filename": "macOS.png", + "idiom": "mac" } ], - "info" : { - "author" : "xcode", - "version" : 1 + "info": { + "author": "xcode", + "version": 1 } } diff --git a/FetchInstallerPkg/Assets.xcassets/macOS.imageset/macOS 64.png b/FetchInstallerPkg/Assets.xcassets/macOS.imageset/macOS 64.png deleted file mode 100644 index 9ccca86..0000000 Binary files a/FetchInstallerPkg/Assets.xcassets/macOS.imageset/macOS 64.png and /dev/null differ diff --git a/FetchInstallerPkg/Assets.xcassets/macOS.imageset/macOS.png b/FetchInstallerPkg/Assets.xcassets/macOS.imageset/macOS.png new file mode 100644 index 0000000..63776d4 Binary files /dev/null and b/FetchInstallerPkg/Assets.xcassets/macOS.imageset/macOS.png differ diff --git a/FetchInstallerPkg/DownloadManager.swift b/FetchInstallerPkg/DownloadManager.swift index 25b9589..e6e3ae9 100644 --- a/FetchInstallerPkg/DownloadManager.swift +++ b/FetchInstallerPkg/DownloadManager.swift @@ -5,8 +5,8 @@ // Created by Armin Briegel on 2021-06-14. // -import Foundation import AppKit +import Foundation @objc class DownloadManager: NSObject, ObservableObject { @Published var downloadURL: URL? @@ -16,23 +16,24 @@ import AppKit @Published var progressString: String = "" @Published var isComplete = false @Published var filename: String? - + @Published var installerURLFiles: [URL]? + lazy var urlSession = URLSession(configuration: URLSessionConfiguration.default, delegate: self, delegateQueue: nil) - var downloadTask : URLSessionDownloadTask? + var downloadTask: URLSessionDownloadTask? var byteFormatter = ByteCountFormatter() - + static let shared = DownloadManager() - + var fileExists: Bool { let destination = Prefs.downloadURL - if self.filename != nil { + if filename != nil { let file = destination.appendingPathComponent(filename!) return FileManager.default.fileExists(atPath: file.path) } else { return false } } - + func download(url: URL?, replacing: Bool = false) throws { // reset the variables progress = 0.0 @@ -40,22 +41,23 @@ import AppKit localURL = nil downloadURL = url isComplete = false - + byteFormatter.countStyle = .file - + if replacing { let destination = Prefs.downloadURL + // let suggestedFilename: [String] = filename ?? "InstallerAssistant.pkg" let suggestedFilename = filename ?? "InstallerAssistant.pkg" let file = destination.appendingPathComponent(suggestedFilename) try FileManager.default.removeItem(at: file) } - + if url != nil { downloadTask = urlSession.downloadTask(with: url!) downloadTask!.resume() } } - + func cancel() { if isDownloading && downloadTask != nil { downloadTask?.cancel() @@ -65,7 +67,7 @@ import AppKit progress = 0.0 } } - + func revealInFinder() { if isComplete { let destination = Prefs.downloadPath @@ -74,14 +76,14 @@ import AppKit } } -extension DownloadManager : URLSessionDownloadDelegate { - func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL) { +extension DownloadManager: URLSessionDownloadDelegate { + func urlSession(_: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL) { NSLog("urlSession, didFinishDownloading") let destination = Prefs.downloadURL - + // get the suggest file name or create a uuid string let suggestedFilename = filename ?? downloadTask.response?.suggestedFilename ?? UUID().uuidString - + do { let file = destination.appendingPathComponent(suggestedFilename) let newURL = try FileManager.default.replaceItemAt(file, withItemAt: location) @@ -91,13 +93,12 @@ extension DownloadManager : URLSessionDownloadDelegate { self.localURL = newURL self.isComplete = true } - } - catch { + } catch { NSLog(error.localizedDescription) } } - - func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didWriteData bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64) { + + func urlSession(_: URLSession, downloadTask _: URLSessionDownloadTask, didWriteData _: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64) { NSLog("urlSession, didWriteData: \(totalBytesWritten)/\(totalBytesExpectedToWrite)") DispatchQueue.main.async { self.progress = Double(totalBytesWritten) / Double(totalBytesExpectedToWrite) @@ -105,4 +106,3 @@ extension DownloadManager : URLSessionDownloadDelegate { } } } - diff --git a/FetchInstallerPkg/FetchInstallerPkgApp.swift b/FetchInstallerPkg/FetchInstallerPkgApp.swift index 089b754..8f7b32c 100644 --- a/FetchInstallerPkg/FetchInstallerPkgApp.swift +++ b/FetchInstallerPkg/FetchInstallerPkgApp.swift @@ -15,8 +15,8 @@ struct FetchInstallerPkgApp: App { WindowGroup { ContentView().environmentObject(sucatalog).navigationTitle("") } - Settings { - PreferencesView().environmentObject(sucatalog).navigationTitle("Preferences") - } +// Settings { +// PreferencesView().environmentObject(sucatalog).navigationTitle("Program") +// } } } diff --git a/FetchInstallerPkg/Model/Catalog.swift b/FetchInstallerPkg/Model/Catalog.swift index f196b87..35b67e2 100644 --- a/FetchInstallerPkg/Model/Catalog.swift +++ b/FetchInstallerPkg/Model/Catalog.swift @@ -12,7 +12,7 @@ struct Catalog: Codable { let applePostURL: String let indexDate: Date let products: [String: Product] - + enum CodingKeys: String, CodingKey { case catalogVersion = "CatalogVersion" case applePostURL = "ApplePostURL" diff --git a/FetchInstallerPkg/Model/DistParserDelegate.swift b/FetchInstallerPkg/Model/DistParserDelegate.swift index cbb3e19..4d28c99 100644 --- a/FetchInstallerPkg/Model/DistParserDelegate.swift +++ b/FetchInstallerPkg/Model/DistParserDelegate.swift @@ -7,7 +7,7 @@ import Foundation -@objc class DistParserDelegate : NSObject, XMLParserDelegate { +@objc class DistParserDelegate: NSObject, XMLParserDelegate { enum Elements: String { case pkgref = "pkg-ref" case auxinfo @@ -15,52 +15,56 @@ import Foundation case string case title } - + + var osName = String() var title = String() var buildVersion = String() var productVersion = String() var installerVersion = String() - + private var elementName = String() private var parsingAuxinfo = false private var currentKey = String() private var currentString = String() private var keysParsed = 0 - - func parser(_ parser: XMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [String : String] = [:]) { + func parser(_: XMLParser, didStartElement elementName: String, namespaceURI _: String?, qualifiedName _: String?, attributes attributeDict: [String: String] = [:]) { if elementName == Elements.pkgref.rawValue { - if attributeDict["id"] == "InstallAssistant" { + if attributeDict["id"] == "InstallAssistant" || attributeDict["id"] == "InstallESDDmg" { if let version = attributeDict["version"] { - self.installerVersion = version + installerVersion = version + osName = nameOS[String(installerVersion.prefix(2))] ?? "macOS" } } + if attributeDict["id"] == "InstallESDDmg" { + print(attributeDict) + } } - + if elementName == Elements.auxinfo.rawValue { parsingAuxinfo = true } - + if elementName == Elements.key.rawValue { currentKey = String() } - + if elementName == Elements.string.rawValue { currentString = String() } - + self.elementName = elementName } - func parser(_ parser: XMLParser, didEndElement elementName: String, namespaceURI: String?, qualifiedName qName: String?) { + func parser(_: XMLParser, didEndElement elementName: String, namespaceURI _: String?, qualifiedName _: String?) { if elementName == Elements.auxinfo.rawValue { parsingAuxinfo = false } - + if elementName == Elements.key.rawValue { keysParsed += 1 } - + if elementName == Elements.string.rawValue { if currentKey == "BUILD" { buildVersion = currentString @@ -70,15 +74,15 @@ import Foundation } } - func parser(_ parser: XMLParser, foundCharacters string: String) { + func parser(_: XMLParser, foundCharacters string: String) { let data = string.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines) - if (!data.isEmpty) { - if self.elementName == Elements.title.rawValue { + if !data.isEmpty { + if elementName == Elements.title.rawValue { title += data - } else if self.elementName == "key" && parsingAuxinfo { + } else if elementName == "key" && parsingAuxinfo { currentKey += data - } else if self.elementName == "string" && parsingAuxinfo { + } else if elementName == "string" && parsingAuxinfo { currentString += data } } diff --git a/FetchInstallerPkg/Model/MetaInfo.swift b/FetchInstallerPkg/Model/MetaInfo.swift index f6198e5..aed48a3 100644 --- a/FetchInstallerPkg/Model/MetaInfo.swift +++ b/FetchInstallerPkg/Model/MetaInfo.swift @@ -9,26 +9,31 @@ import Foundation struct MetaInfo: Codable { let installAssistantPackageIdentifiers: [String: String]? - + var installInfo: String? { return installAssistantPackageIdentifiers?["InstallInfo"] } + var osInstall: String? { return installAssistantPackageIdentifiers?["OSInstall"] } + var sharedSupport: String? { return installAssistantPackageIdentifiers?["SharedSupport"] } + var info: String? { return installAssistantPackageIdentifiers?["Info"] } + var updateBrain: String? { return installAssistantPackageIdentifiers?["UpdateBrain"] } + var buildManifest: String? { return installAssistantPackageIdentifiers?["BuildManifest"] } - + enum CodingKeys: String, CodingKey { case installAssistantPackageIdentifiers = "InstallAssistantPackageIdentifiers" } diff --git a/FetchInstallerPkg/Model/OSNames.swift b/FetchInstallerPkg/Model/OSNames.swift new file mode 100644 index 0000000..245676e --- /dev/null +++ b/FetchInstallerPkg/Model/OSNames.swift @@ -0,0 +1,46 @@ +// +// OSNames.swift +// OSNames +// +// Created on 09/12/2024. +// + +import Foundation + +// From Short Darwin (2 first chars) -to-> OS Name +// From OS Name -to-> Short Version (2, 4 or 5 first chars) +var nameOS: [String: String] = [ + "11": "Lion", + "12": "Mountain Lion", + "13": "Mavericks", + "14": "Yosemite", + "15": "El Capitan", + "16": "Sierra", + "17": "High Sierra", + "18": "Mojave", + "19": "Catalina", + "20": "Big Sur", + "21": "Monterey", + "22": "Ventura", + "23": "Sonoma", + "24": "Sequoia", + "25": "Tahoe", + "99": "macOS", + "Lion": "10.7", + "Mountain Lion": "10.8", + "Mavericks": "10.9", + "Yosemite": "10.10", + "El Capitan": "10.11", + "Sierra": "10.12", + "High Sierra": "10.13", + "Mojave": "10.14", + "Catalina": "10.15", + "Big Sur": "11", + "Monterey": "12", + "Ventura": "13", + "Sonoma": "14", + "Sequoia": "15", + "Tahoe": "26", + "macOS": "99", + "All OS": "99", +] diff --git a/FetchInstallerPkg/Model/Package.swift b/FetchInstallerPkg/Model/Package.swift index abd512d..c3cfd1e 100644 --- a/FetchInstallerPkg/Model/Package.swift +++ b/FetchInstallerPkg/Model/Package.swift @@ -12,7 +12,7 @@ struct Package: Codable { let url: String let digest: String? let metadataURL: String? - + enum CodingKeys: String, CodingKey { case size = "Size" case url = "URL" diff --git a/FetchInstallerPkg/Model/Product.swift b/FetchInstallerPkg/Model/Product.swift index d9b9bf4..e767594 100644 --- a/FetchInstallerPkg/Model/Product.swift +++ b/FetchInstallerPkg/Model/Product.swift @@ -8,35 +8,39 @@ import Foundation class Product: Codable, Identifiable, ObservableObject { + var thisComponent: String { return String(describing: self) } + let serverMetadataURL: String? let packages: [Package] let postDate: Date let distributions: [String: String] let extendedMetaInfo: MetaInfo? - + + @Published var sucatalog: SUCatalog? @Published var key: String? - + + @Published var osName: String? @Published var title: String? @Published var buildVersion: String? - var id : String { + var id: String { return key ?? "" } - + @Published var productVersion: String? @Published var installerVersion: String? - + @Published var isLoading = false @Published var hasLoaded = false - + var distributionURL: String? { if distributions.keys.contains("English") { return distributions["English"]! - } else if distributions.keys.contains("en"){ + } else if distributions.keys.contains("en") { return distributions["en"]! } return nil } - + var darwinVersion: String { if buildVersion != nil { return String(buildVersion!.prefix(2)) @@ -44,129 +48,148 @@ class Product: Codable, Identifiable, ObservableObject { return "unknown" } } - + var buildManifestURL: String? { - let buildManifest = packages.first { $0.url.hasSuffix("BuildManifest.plist")} + let buildManifest = packages.first { $0.url.hasSuffix("BuildManifest.plist") } return buildManifest?.url } - - var installerPackage: Package? { - return packages.first { $0.url.hasSuffix("InstallAssistant.pkg")} + + var installerASSPackage: Package? { + return packages.first { $0.url.hasSuffix("InstallAssistant.pkg") } } - + + var installerESDPackage: Package? { + return packages.first { $0.url.hasSuffix("InstallESDDmg.pkg") } + } + var installAssistantURL: URL? { - if let installAssistant = self.installerPackage { + if let installAssistant = installerASSPackage { + print("\(thisComponent) : \(installAssistant)") return URL(string: installAssistant.url) } else { - return nil + if let installAssistant = installerESDPackage { + print("\(thisComponent) : \(installAssistant)") + return URL(string: installAssistant.url) + } else { + return nil + } } } - + var installAssistantSize: Int { - return self.installerPackage?.size ?? 0 + if installerASSPackage != nil { + return installerASSPackage?.size ?? 0 + } else { + if installerESDPackage != nil { + return installerESDPackage?.size ?? 0 + } else { + return 0 + } + } } - + func loadBuildManifest() { - guard let urlString = self.buildManifestURL else {return} - guard let url = URL(string: urlString) else {return} - + guard let urlString = buildManifestURL else { return } + guard let url = URL(string: urlString) else { return } + let sessionConfig = URLSessionConfiguration.ephemeral let session = URLSession(configuration: sessionConfig, delegate: nil, delegateQueue: nil) - let task = session.dataTask(with: url) { data, response, error in - + if error != nil { - print(error!.localizedDescription) + print("\(self.thisComponent) : \(error!.localizedDescription)") return } - + let httpResponse = response as! HTTPURLResponse if httpResponse.statusCode != 200 { - print(httpResponse.statusCode) + print("\(self.thisComponent) : \(httpResponse.statusCode)") } else { if data != nil { - //print(String(decoding: data!, as: UTF8.self)) + // print("\(self.thisComponent) : \(String(decoding: data!, as: UTF8.self))") DispatchQueue.main.async { - self.decodeBuildManifest(data: data!) } - } + self.decodeBuildManifest(data: data!) + } + } } } - + isLoading = true hasLoaded = false + osName = nil title = nil buildVersion = nil productVersion = nil installerVersion = nil task.resume() } - + func decodeBuildManifest(data: Data) { - self.isLoading = false - self.hasLoaded = true + isLoading = false + hasLoaded = true let decoder = PropertyListDecoder() if let buildManifest = try? decoder.decode(BuildManifest.self, from: data) { - self.buildVersion = buildManifest.productBuildVersion - self.productVersion = buildManifest.productVersion - //print(" Build Version: \(self.buildVersion ?? "")") + buildVersion = buildManifest.productBuildVersion + productVersion = buildManifest.productVersion + print("\(thisComponent) : Build Version: \(buildVersion ?? "")") } } - + func loadDistribution() { - guard let urlString = self.distributionURL else {return} - guard let url = URL(string: urlString) else {return} - + guard let urlString = distributionURL else { return } + guard let url = URL(string: urlString) else { return } + let sessionConfig = URLSessionConfiguration.ephemeral let session = URLSession(configuration: sessionConfig, delegate: nil, delegateQueue: nil) - let task = session.dataTask(with: url) { data, response, error in - + if error != nil { - print(error!.localizedDescription) + print("\(self.thisComponent) : \(error!.localizedDescription)") return } - + let httpResponse = response as! HTTPURLResponse if httpResponse.statusCode != 200 { - print(httpResponse.statusCode) + print("\(self.thisComponent) : \(httpResponse.statusCode)") } else { if data != nil { - //print(String(decoding: data!, as: UTF8.self)) + // print("\(self.thisComponent) : \(String(decoding: data!, as: UTF8.self))") DispatchQueue.main.async { - self.parseDistXML(data: data!) } - } + self.parseDistXML(data: data!) + } + } } } - + isLoading = true hasLoaded = false - + + osName = nil title = nil buildVersion = nil productVersion = nil installerVersion = nil task.resume() } - + func parseDistXML(data: Data) { let parser = XMLParser(data: data) let delegate = DistParserDelegate() parser.delegate = delegate parser.parse() - - self.title = delegate.title - self.productVersion = delegate.productVersion - self.buildVersion = delegate.buildVersion - self.installerVersion = delegate.installerVersion - self.isLoading = false - self.hasLoaded = true - //print(self.title ?? "") - //print(self.buildVersion ?? "") + + osName = delegate.osName + title = delegate.title + productVersion = delegate.productVersion + buildVersion = delegate.buildVersion + installerVersion = delegate.installerVersion + isLoading = false + hasLoaded = true } - + enum CodingKeys: String, CodingKey { case serverMetadataURL = "ServerMetadataURL" case packages = "Packages" diff --git a/FetchInstallerPkg/Model/SUCatalog.swift b/FetchInstallerPkg/Model/SUCatalog.swift index fa09cfa..0836902 100644 --- a/FetchInstallerPkg/Model/SUCatalog.swift +++ b/FetchInstallerPkg/Model/SUCatalog.swift @@ -8,80 +8,85 @@ import Foundation class SUCatalog: ObservableObject { + var thisComponent: String { return String(describing: self) } + @Published var catalog: Catalog? var products: [String: Product]? { return catalog?.products } - + @Published var installers = [Product]() - + var uniqueInstallersList: [String] = [] + @Published var isLoading = false @Published var hasLoaded = false - + init() { load() } - + func load() { - let catalogURL = catalogURL(for: Prefs.seedProgram) - //print(catalogURL.absoluteString) - - let sessionConfig = URLSessionConfiguration.ephemeral - let session = URLSession(configuration: sessionConfig, delegate: nil, delegateQueue: nil) + uniqueInstallersList = [] + let catalogURLArray: [URL] = catalogURL(for: Prefs.seedProgram, for: Prefs.osNameID) + // print("\(self.thisComponent) : \(String(describing: catalogURL))") - let task = session.dataTask(with: catalogURL) { data, response, error in - - if error != nil { - print(error!.localizedDescription) - return - } - - let httpResponse = response as! HTTPURLResponse - if httpResponse.statusCode != 200 { - print(httpResponse.statusCode) - } else { - if data != nil { - //print(String(decoding: data!, as: UTF8.self)) - DispatchQueue.main.async { - self.decode(data: data!) } - } + catalogURLArray.forEach { + let sessionConfig = URLSessionConfiguration.ephemeral + let session = URLSession(configuration: sessionConfig, delegate: nil, delegateQueue: nil) + + let task = session.dataTask(with: $0) { data, response, error in + + if error != nil { + print("\(self.thisComponent) : \(error!.localizedDescription)") + return + } + + let httpResponse = response as! HTTPURLResponse + if httpResponse.statusCode != 200 { + print("\(self.thisComponent) : \(httpResponse.statusCode)") + } else { + if data != nil { + // print("\(self.thisComponent) : \(String(decoding: data!, as: UTF8.self))") + DispatchQueue.main.async { + self.decode(data: data!) + } + } + } } + isLoading = true + hasLoaded = false + self.catalog = nil + self.installers = [Product]() + task.resume() } - isLoading = true - hasLoaded = false - self.catalog = nil - self.installers = [Product]() - task.resume() } - + private func decode(data: Data) { - self.isLoading = false - self.hasLoaded = true + isLoading = false + hasLoaded = true let decoder = PropertyListDecoder() - self.catalog = try! decoder.decode(Catalog.self, from: data) - - if let products = self.products { - //print("loaded catalog with \(products.count) products") - + catalog = try! decoder.decode(Catalog.self, from: data) + + if let products = products { + print("\(thisComponent) : Installer Nb : loaded \(Prefs.seedProgram) catalog with \(products.count) products") + for (productKey, product) in products { product.key = productKey if let metainfo = product.extendedMetaInfo { if metainfo.sharedSupport != nil { - // this is an installer, add to list - self.installers.append(product) - //print("\(productKey) is an installer") - //print(" BuildManifest: \(product.buildManifestURL ?? "")") - //print(" InstallAssistant: \(String(describing: product.installAssistantURL))") - product.loadDistribution() + if !uniqueInstallersList.contains(productKey) { + // this is an installer, add to list + print("\(thisComponent) : Installer ID : \(productKey)") + uniqueInstallersList.append(productKey) + installers.append(product) + // print("\(self.thisComponent) : BuildManifest: \(product.buildManifestURL ?? "")") + // print("\(self.thisComponent) : InstallAssistant: \(String(describing: product.installAssistantURL))") + product.loadDistribution() + } } } } - //print("found \(self.installers.count) installer pkgs") + // print("\(self.thisComponent) : \(self.installers.count) installer pkgs found") installers.sort { $0.postDate > $1.postDate } } } } - - - - - diff --git a/FetchInstallerPkg/Model/SeedProgram.swift b/FetchInstallerPkg/Model/SeedProgram.swift index b1db570..cea5bfe 100644 --- a/FetchInstallerPkg/Model/SeedProgram.swift +++ b/FetchInstallerPkg/Model/SeedProgram.swift @@ -7,32 +7,67 @@ import Foundation -// Note: this will be different for Monterey -let defaultCatalog = "https://swscan.apple.com/content/catalogs/others/index-12-10.16-10.15-10.14-10.13-10.12-10.11-10.10-10.9-mountainlion-lion-snowleopard-leopard.merged-1.sucatalog" +var thisComponent: String { return String(describing: "Download_Full_Installer.SeedProgram") } + +// Note: this can change in future macOS + +let regularCatalog = "https://swscan.apple.com/content/catalogs/others/index-26-15-14-13-12-10.16-10.15-10.14-10.13-10.12-10.11-10.10-10.9-mountainlion-lion-snowleopard-leopard.merged-1.sucatalog" + +let part1Catalog = "https://swscan.apple.com/content/catalogs/others/index-" +let part3Catalog = "-10.15-10.14-10.13-10.12-10.11-10.10-10.9-mountainlion-lion-snowleopard-leopard.merged-1.sucatalog" + +let allSeedCatalogs: [String: String] = [ + "26": "26?-26-15-14-13-12-10.16", + "15": "15?-15-14-13-12-10.16", + "14": "14?-14-13-12-10.16", + "13": "13?-13-12-10.16", + "12": "12?-12-10.16", + "11": "10.16?-10.16", +] + +let defaultPart2Catalog = "26-15-14-13-12-10.16" + +let seedCatalogID: [String: String] = [ + "CustomerSeed": "customerseed", + "DeveloperSeed": "seed", + "PublicSeed": "beta", +] enum SeedProgram: String, CaseIterable, Identifiable { + case noSeed = "Regular" case customerSeed = "CustomerSeed" case developerSeed = "DeveloperSeed" case publicSeed = "PublicSeed" - case noSeed = "None" - - var id: String {self.rawValue} + + var id: String { rawValue } } - -func catalogURL(for seed: SeedProgram) -> URL { - let seedPath = "/System/Library/PrivateFrameworks/Seeding.framework/Resources/SeedCatalogs.plist" - - var catalogURL = URL(string: defaultCatalog)! - - let seedPathURL = URL(fileURLWithPath: seedPath) - // read plist file - let decoder = PropertyListDecoder() - guard let data = try? Data.init(contentsOf: seedPathURL) else { return catalogURL } - guard let seedURLDict = try? decoder.decode([String:String].self, from: data) else { return catalogURL } - if let seedString = seedURLDict[seed.rawValue] { - if let seedURL = URL(string: seedString) { - catalogURL = seedURL + +enum OsNameID: String, CaseIterable, Identifiable { + case osAll = "All OS" + case osTahoe = "Tahoe" + case osSequoia = "Sequoia" + case osSonoma = "Sonoma" + case osVentura = "Ventura" + case osMonterey = "Monterey" + case osBigSur = "Big Sur" + + var id: String { rawValue } +} + +func catalogURL(for selectedseed: SeedProgram, for selectedosname: OsNameID) -> [URL] { + var catalogURL: [URL] = [] + if selectedseed.rawValue != SeedProgram.noSeed.rawValue { + let shortVersion = nameOS[selectedosname.rawValue] ?? "99" + // "99" = All OS or unknown OS name for SeedProgram (not Regular) + for (keyVersion, part2Catalog) in allSeedCatalogs { + if shortVersion == "99" || (shortVersion != "99" && shortVersion == keyVersion) { + catalogURL.append(URL(string: part1Catalog + part2Catalog.replacingOccurrences(of: "?", with: seedCatalogID[selectedseed.rawValue] ?? defaultPart2Catalog) + part3Catalog)!) + } + if shortVersion != "99", shortVersion == keyVersion { break } } + } else { + catalogURL.append(URL(string: regularCatalog)!) } + print("\(thisComponent) : \(catalogURL)") return catalogURL } diff --git a/FetchInstallerPkg/Prefs.swift b/FetchInstallerPkg/Prefs.swift index 90541f0..6593f0a 100644 --- a/FetchInstallerPkg/Prefs.swift +++ b/FetchInstallerPkg/Prefs.swift @@ -8,23 +8,24 @@ import Foundation struct Prefs { - enum Key: String { case seedProgram = "SeedProgram" + case osNameID = "OsNameID" case downloadPath = "DownloadPath" } - + static func key(_ key: Key) -> String { return key.rawValue } - + static func registerDefaults() { var prefs = [String: Any]() prefs[Prefs.key(.seedProgram)] = SeedProgram.noSeed.rawValue - + prefs[Prefs.key(.osNameID)] = OsNameID.osAll.rawValue + guard let downloadURL = FileManager.default.urls(for: .downloadsDirectory, in: .userDomainMask).first else { return } prefs[Prefs.key(.downloadPath)] = downloadURL.path - + UserDefaults.standard.register(defaults: prefs) } @@ -32,15 +33,20 @@ struct Prefs { let seedValue = UserDefaults.standard.string(forKey: Prefs.key(.seedProgram)) ?? "" return SeedProgram(rawValue: seedValue) ?? .noSeed } - + + static var osNameID: OsNameID { + let osValue = UserDefaults.standard.string(forKey: Prefs.key(.osNameID)) ?? "" + return OsNameID(rawValue: osValue) ?? .osAll + } + static var downloadPath: String { return UserDefaults.standard.string(forKey: Prefs.key(.downloadPath)) ?? "" } - + static var downloadURL: URL { - let downloadURL = URL(fileURLWithPath: self.downloadPath) + let downloadURL = URL(fileURLWithPath: downloadPath) return downloadURL } - + static let byteFormatter = ByteCountFormatter() } diff --git a/FetchInstallerPkg/View/ContentView.swift b/FetchInstallerPkg/View/ContentView.swift index 988ee73..a23af36 100644 --- a/FetchInstallerPkg/View/ContentView.swift +++ b/FetchInstallerPkg/View/ContentView.swift @@ -7,34 +7,55 @@ import SwiftUI - struct ContentView: View { @EnvironmentObject var sucatalog: SUCatalog @AppStorage(Prefs.key(.seedProgram)) var seedProgram: String = "" - + @AppStorage(Prefs.key(.osNameID)) var osNameID: String = "" + var countersText: String = "" + var body: some View { - VStack(alignment: .leading){ - Text("Download Full Installer") - .font(.title) - .multilineTextAlignment(.leading) - - List(sucatalog.installers, id: \.id) { installer in - InstallerView(product: installer) - }.padding(4) + PreferencesView().environmentObject(sucatalog).navigationTitle("Download Full Installer") + VStack(alignment: .center) { + HStack(alignment: .center) { Text("") + Spacer() + } + + // ---> Code for macOS 14 / 15 + if #available(macOS 14.0, *) { + List(sucatalog.installers, id: \.id) { installer in + InstallerView(product: installer) + } + .padding(4) + + // ---> Test, list border + // .border(Color.green, width: 1) + + .contentMargins(.leading, 1, for: .scrollContent) + // ---> Code for macOS 13 + } else { + List(sucatalog.installers, id: \.id) { installer in + InstallerView(product: installer) + } + .padding(4) + } + DownloadView() } - .padding() - .frame(minWidth: 400.0, maxWidth: 600.0, minHeight: 400.0) - + .frame( + minWidth: 400.0, + maxWidth: 600.0, + minHeight: 400.0, + alignment: .center + ) + HStack(alignment: .center) { Text("").padding(1) + } + // ---> count of listed packages, it has issues + // HStack { Text("(\(sucatalog.installers.count) pkg(s) in \(self.seedProgram) catalog)\n") .font(.headline) } } -} -struct ContentView_Previews: PreviewProvider { - static var previews: some View { - ContentView() + struct ContentView_Previews: PreviewProvider { + static var previews: some View { + ContentView() + } } } - - - - diff --git a/FetchInstallerPkg/View/DownloadView.swift b/FetchInstallerPkg/View/DownloadView.swift index 83ad87b..597ac39 100644 --- a/FetchInstallerPkg/View/DownloadView.swift +++ b/FetchInstallerPkg/View/DownloadView.swift @@ -9,7 +9,7 @@ import SwiftUI struct DownloadView: View { @StateObject var downloadManager = DownloadManager.shared - + var body: some View { if downloadManager.isDownloading { VStack(alignment: .leading) { @@ -23,11 +23,11 @@ struct DownloadView: View { } HStack { ProgressView(value: downloadManager.progress) - Button(action: {downloadManager.cancel()}) { + Button(action: { downloadManager.cancel() }) { Image(systemName: "xmark.circle.fill").accentColor(.gray) + .help("Cancel \(downloadManager.filename ?? "InstallAssistant.pkg") download") }.buttonStyle(.borderless) } - } .multilineTextAlignment(.leading) } @@ -46,9 +46,8 @@ struct DownloadView: View { } } -struct DownloadView_Previews : PreviewProvider { +struct DownloadView_Previews: PreviewProvider { static var previews: some View { DownloadView() } } - diff --git a/FetchInstallerPkg/View/IconView.swift b/FetchInstallerPkg/View/IconView.swift index c806c95..45ad2d6 100644 --- a/FetchInstallerPkg/View/IconView.swift +++ b/FetchInstallerPkg/View/IconView.swift @@ -9,33 +9,51 @@ import SwiftUI struct IconView: View { @ObservedObject var product: Product - + + let iconOS: [String: String] = [ + "11": "Lion", + "12": "Mountain Lion", + "13": "Mavericks", + "14": "Yosemite", + "15": "El Capitan", + "16": "Sierra", + "17": "High Sierra", + "18": "Mojave", + "19": "Catalina", + "20": "Big Sur", + "21": "Monterey", + "22": "Ventura", + "23": "Sonoma", + "24": "Sequoia", + "25": "Tahoe", + "99": "macOS", + ] + var body: some View { - ZStack(alignment: .bottomTrailing) { - if product.darwinVersion == "20" { - Image("Big Sur") - .resizable(resizingMode: .stretch) - .aspectRatio(contentMode: .fit) - .foregroundColor(Color.blue) - } else { - Image("macOS") - .resizable(resizingMode: .stretch) - .aspectRatio(contentMode: .fit) - .foregroundColor(Color.blue) - } - if product.title != nil && product.title!.lowercased().contains("beta") { - Text("beta") - .font(.footnote) + // ZStack(alignment: .bottomTrailing) { + ZStack(alignment: .center) { + let iconName = iconOS[product.darwinVersion] ?? "macOS" + Image(iconName) + .resizable(resizingMode: .stretch) + .aspectRatio(contentMode: .fit) + .foregroundColor(Color.blue) + + let isBeta = "beta" + if product.title != nil && product.title!.lowercased().contains(isBeta) { + Text(" " + isBeta + " ") + .font(.headline) .foregroundColor(.white) - .background(Color.gray.opacity(0.8)) - + .background(Color.blue.opacity(0.8)) + .rotationEffect(.degrees(-45)) } - }.frame(width: 48.0, height: 48.0) + }.frame(width: 50.0, height: 50.0, alignment: .center) } } -//struct IconView_Previews: PreviewProvider { -// static var previews: some View { -// //IconView(product: nil) -// } -//} +/* + struct IconView_Previews: PreviewProvider { + static var previews: some View { + IconView(product: nil) + } + } + */ diff --git a/FetchInstallerPkg/View/InstallerView.swift b/FetchInstallerPkg/View/InstallerView.swift index 8dad45c..eb1bb25 100644 --- a/FetchInstallerPkg/View/InstallerView.swift +++ b/FetchInstallerPkg/View/InstallerView.swift @@ -7,108 +7,144 @@ import SwiftUI +class DisplayedCount { + var displayedRows = 0 +} + struct InstallerView: View { @ObservedObject var product: Product @StateObject var downloadManager = DownloadManager.shared @State var isReplacingFile = false @State var failed = false @State var filename = "InstallerAssistant.pkg" - + @State var installerURLFiles: [String] = [] + var body: some View { - if product.isLoading { - Text("Loading...") - } else { - HStack { - IconView(product: product) - - VStack(alignment: .leading) { - HStack { - Text(product.title ?? "") - .font(.headline) - Spacer() - Text(product.productVersion ?? "") - .frame(alignment: .trailing) - } - HStack { - Text(product.postDate, style: .date) - .font(.footnote) - Text(Prefs.byteFormatter.string(fromByteCount: Int64(product.installAssistantSize))) - .font(.footnote) - Spacer() - Text(product.buildVersion ?? "") - .frame(alignment: .trailing) - .font(.footnote) - } - } - - - Button(action: { - filename = "InstallAssistant-\(product.productVersion ?? "V")-\(product.buildVersion ?? "B").pkg" - downloadManager.filename = filename - isReplacingFile = downloadManager.fileExists - - if !isReplacingFile { - do { - try downloadManager.download(url: product.installAssistantURL) - } catch { - failed = true + if product.hasLoaded { + // Filter data on osName if needed + if (Prefs.osNameID.rawValue == OsNameID.osAll.rawValue) || (Prefs.osNameID.rawValue != OsNameID.osAll.rawValue && product.osName == Prefs.osNameID.rawValue) { + HStack { + IconView(product: product) + + VStack(alignment: .leading) { + HStack { + Text(product.title ?? "") + .font(.headline) + Spacer() + Text(product.productVersion ?? "") + .frame(alignment: .trailing) + } + HStack { + Text(product.postDate, style: .date) + .font(.footnote) + Text(Prefs.byteFormatter.string(fromByteCount: Int64(product.installAssistantSize))) + .font(.footnote) + Spacer() + Text(product.buildVersion ?? "") + .frame(alignment: .trailing) + .font(.footnote) } } - - }) { - Image(systemName: "arrow.down.circle").font(.title) - } - .alert(isPresented: $isReplacingFile) { - Alert( - title: Text("“\(filename)” already exists! Do you want to replace it?"), - message: Text("A file with the same name already exists in that location. Replacing it will overwrite its current contents."), - primaryButton: .cancel(Text("Cancel")), - secondaryButton: .destructive( - Text("Replace"), - action: { - do { - try downloadManager.download(url: product.installAssistantURL, replacing: true) - } catch { - failed = true + + Button(action: { + filename = "InstallAssistant-\(product.productVersion ?? "V")-\(product.buildVersion ?? "B").pkg" + downloadManager.filename = filename + isReplacingFile = downloadManager.fileExists + + if !isReplacingFile { + do { + try downloadManager.download(url: product.installAssistantURL) + } catch { + failed = true + } } + + }) { + Image(systemName: "arrow.down.circle").font(.title) } + .help("Download \(product.osName ?? "") \(product.productVersion ?? "") (\(product.buildVersion ?? "")) Installer") + .alert(isPresented: $isReplacingFile) { + Alert( + title: Text("“\(filename)” already exists! Do you want to replace it?"), + message: Text("A file with the same name already exists in that location. Replacing it will overwrite its current contents."), + primaryButton: .cancel(Text("Cancel")), + secondaryButton: .destructive( + Text("Replace"), + action: { + do { + try downloadManager.download(url: product.installAssistantURL, replacing: true) + } catch { + failed = true + } + } + ) ) - ) - } -// .alert(isPresented: $failed) { -// Alert( -// title: Text("An error occured while downloading"), -// message: Text("Please try again or restart the application.") -// ) -// } - .disabled(downloadManager.isDownloading) - .buttonStyle(.borderless) - .controlSize(/*@START_MENU_TOKEN@*/.large/*@END_MENU_TOKEN@*/) - }.contextMenu() { - Button(action: { - if let text = product.installAssistantURL?.absoluteString { - let pb = NSPasteboard.general - pb.clearContents() - pb.setString(text, forType: .string) } - }) { - Image(systemName: "doc.on.clipboard") - Text("Copy Download URL") + .disabled(downloadManager.isDownloading) + .buttonStyle(.borderless) + .controlSize(.mini) + + // Next (commented) code doesn't work, it's for create application instead of get InstallAssistant.pkg + // Button(action: { + // for filename in installerURLFiles { + // downloadManager.filename = filename + // isReplacingFile = downloadManager.fileExists + // if !isReplacingFile { + // do { + // try downloadManager.download(url: product.installAssistantURL) + // } catch { + // failed = true + // } + // } + // } + // }) +// {Image(systemName: "building.columns").font(.title)} + // .help("Create application \(product.osName ?? "") \(product.productVersion ?? "") (\(product.buildVersion ?? ""))") + // .alert(isPresented: $isReplacingFile) { + // Alert( + // title: Text("“\(filename)” already exists! Do you want to replace it?"), + // message: Text("A file with the same name already exists in that location. Replacing it will overwrite its current contents."), + // primaryButton: .cancel(Text("Cancel")), + // secondaryButton: .destructive( + // Text("Replace"), + // action: { + // do { try downloadManager.download(url: product.installAssistantURL, replacing: true) + // } catch { failed = true + // } + // } + // ) + // ) + // } + // .disabled(downloadManager.isDownloading) .buttonStyle(.borderless) .controlSize(.mini) + + // Context menu: copy to clipboard the URL of the specified InstallAssistant.pkg + }.contextMenu { + Button(action: { + if let text = product.installAssistantURL?.absoluteString { + print(text) + let pb = NSPasteboard.general + pb.clearContents() + pb.setString(text, forType: .string) + } + }) { + Image(systemName: "doc.on.clipboard") + let package = (product.installAssistantURL?.absoluteString.components(separatedBy: "/").last ?? "") + Text("Copy \(product.osName ?? "") \(product.productVersion ?? "") (\(product.buildVersion ?? "")) \(package) URL") + } } } } } } +struct InstallerView_Previews: PreviewProvider { + static var previews: some View { + let catalog = SUCatalog() -//struct InstallerView_Previews: PreviewProvider { -// static var previews: some View { -// let catalog = SUCatalog() -// -// if let preview_product = catalog.installers.first { -// InstallerView(product: preview_product) -// } else { -// Text("could not load catalog") -// } -// } -//} + if let preview_product = catalog.installers.first { + InstallerView(product: preview_product) + } else { + Text("could not load catalog") + } + } +} diff --git a/FetchInstallerPkg/View/PreferencesView.swift b/FetchInstallerPkg/View/PreferencesView.swift index 36851ce..a859813 100644 --- a/FetchInstallerPkg/View/PreferencesView.swift +++ b/FetchInstallerPkg/View/PreferencesView.swift @@ -9,32 +9,60 @@ import SwiftUI struct PreferencesView: View { @AppStorage(Prefs.key(.seedProgram)) var seedProgram: String = "" + @AppStorage(Prefs.key(.osNameID)) var osNameID: String = "" @AppStorage(Prefs.key(.downloadPath)) var downloadPath: String = "" @EnvironmentObject var sucatalog: SUCatalog - + let labelWidth = 100.0 var body: some View { Form { - VStack(alignment: .leading) { - HStack { - Picker("Seed Program:", selection: $seedProgram) { - ForEach(SeedProgram.allCases) { program in - Text(program.rawValue) + VStack(alignment: .trailing) { + HStack(alignment: .center) { Text("\n\n") } + + HStack(alignment: .center) { + Picker("", selection: $osNameID) { + ForEach(OsNameID.allCases) { osName in + Text(osName.rawValue).font(.body) } } - .onChange(of: seedProgram) { _ in - sucatalog.load() + + HStack(alignment: .center) { + Text(" in").font(.body) } + // ---> Code for macOS 14 / 15 + if #available(macOS 14.0, *) { + Picker("", selection: $seedProgram) { + ForEach(SeedProgram.allCases) { program in + Text(program.rawValue).font(.body) + } + } + .onChange(of: seedProgram) { sucatalog.load() + } + .onChange(of: osNameID) { sucatalog.load() + } + // ---> Code for macOS 13 + } else { + Picker("", selection: $seedProgram) { + ForEach(SeedProgram.allCases) { program in + Text(program.rawValue).font(.body) + } + } + .onChange(of: seedProgram) { _ in + sucatalog.load() + } + .onChange(of: osNameID) { _ in + sucatalog.load() + } + } } -// HStack { -// Text("Download to:") -// TextField("Download path", text: $downloadPath).environment(\.isEnabled, false) -// } } - .padding() } - .frame(width: 300.0, height: 200.0) + .frame( + width: 370.0, + height: 30.0, + alignment: .center + ) } } diff --git a/FetchInstallerPkg/en.lproj/Download-Full-Installer-InfoPlist.strings b/FetchInstallerPkg/en.lproj/Download-Full-Installer-InfoPlist.strings new file mode 100644 index 0000000..bdd0ded --- /dev/null +++ b/FetchInstallerPkg/en.lproj/Download-Full-Installer-InfoPlist.strings @@ -0,0 +1,4 @@ +/* Bundle name */ +"CFBundleName" = "Download Full Installer"; +/* Copyright (human-readable) */ +"NSHumanReadableCopyright" = "©2021 Scripting OS X - Armin Briegel\n@2024 Matxpa (update to version 2.0)"; diff --git a/FetchInstallerPkg/en.lproj/Localizable.strings b/FetchInstallerPkg/en.lproj/Localizable.strings new file mode 100644 index 0000000..18a2d45 --- /dev/null +++ b/FetchInstallerPkg/en.lproj/Localizable.strings @@ -0,0 +1,44 @@ +/* No comment provided by engineer. */ +"" = ""; + +/* No comment provided by engineer. */ +"\n\n" = "\n\n"; + +/* No comment provided by engineer. */ +" in" = " in"; + +/* No comment provided by engineer. */ +"“%@” already exists! Do you want to replace it?" = "“%@” already exists! Do you want to replace it?"; + +/* No comment provided by engineer. */ +"A file with the same name already exists in that location. Replacing it will overwrite its current contents." = "A file with the same name already exists in that location. Replacing it will overwrite its current contents."; + +/* No comment provided by engineer. */ +"Cancel" = "Cancel"; + +/* No comment provided by engineer. */ +"Copy %@ %@ (%@) %@ URL" = "Copy %@ %@ (%@) %@ URL"; + +/* No comment provided by engineer. */ +"Create application %@ %@ (%@)" = "Create application %@ %@ (%@)"; + +/* No comment provided by engineer. */ +"Download %@ %@ (%@) Installer" = "Download %@ %@ (%@) Installer"; + +/* No comment provided by engineer. */ +"Download Full Installer" = "Download Full Installer"; + +/* No comment provided by engineer. */ +"Downloaded %@" = "Downloaded %@"; + +/* No comment provided by engineer. */ +"Downloading %@" = "Downloading %@"; + +/* No comment provided by engineer. */ +"Replace" = "Replace"; + +/* No comment provided by engineer. */ +"Show in Finder" = "Show in Finder"; + +/* No comment provided by engineer. */ +"Cancel %@ download" = "Cancel %@ download"; diff --git a/FetchInstallerPkg/es.lproj/Download-Full-Installer-InfoPlist.strings b/FetchInstallerPkg/es.lproj/Download-Full-Installer-InfoPlist.strings new file mode 100644 index 0000000..49f06a0 --- /dev/null +++ b/FetchInstallerPkg/es.lproj/Download-Full-Installer-InfoPlist.strings @@ -0,0 +1,4 @@ +/* Bundle name */ +"CFBundleName" = "Download Full Installer"; +/* Copyright (human-readable) */ +"NSHumanReadableCopyright" = "©2021 Scripting OS X - Armin Briegel\n@2024 Matxpa (actualización version 2.0)"; diff --git a/FetchInstallerPkg/es.lproj/Localizable.strings b/FetchInstallerPkg/es.lproj/Localizable.strings new file mode 100644 index 0000000..2d96a46 --- /dev/null +++ b/FetchInstallerPkg/es.lproj/Localizable.strings @@ -0,0 +1,44 @@ +/* No comment provided by engineer. */ +"" = ""; + +/* No comment provided by engineer. */ +"\n\n" = "\n\n"; + +/* No comment provided by engineer. */ +" in" = " en catálogo"; + +/* No comment provided by engineer. */ +"“%@” already exists! Do you want to replace it?" = "¡“%@” ya existe! ¿Quieres reemplazarlo?"; + +/* No comment provided by engineer. */ +"A file with the same name already exists in that location. Replacing it will overwrite its current contents." = "Ya existe un archivo con el mismo nombre en esa ubicación. Si lo reemplaza, se sobrescribirá su contenido actual."; + +/* No comment provided by engineer. */ +"Cancel" = "Cancelar"; + +/* No comment provided by engineer. */ +"Copy %@ %@ (%@) %@ URL" = "Copiar %@ %@ (%@) %@ URL"; + +/* No comment provided by engineer. */ +"Create application %@ %@ (%@)" = "Crear la aplicación %@ %@ (%@)"; + +/* No comment provided by engineer. */ +"Download %@ %@ (%@) Installer" = "Descargar Instalador %@ %@ (%@)"; + +/* No comment provided by engineer. */ +"Download Full Installer" = "Download Full Installer"; + +/* No comment provided by engineer. */ +"Downloaded %@" = "Descargado %@"; + +/* No comment provided by engineer. */ +"Downloading %@" = "Descargando %@"; + +/* No comment provided by engineer. */ +"Replace" = "Reemplazar"; + +/* No comment provided by engineer. */ +"Show in Finder" = "Mostrar en Finder"; + +/* No comment provided by engineer. */ +"Cancel %@ download" = "Cancelar descarga de %@"; diff --git a/README.md b/README.md index 8950fd5..0d94c80 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,34 @@ # Download Full Installer -![](https://img.shields.io/github/v/release/scriptingosx/DownloadFullInstaller) ![](https://img.shields.io/github/downloads/scriptingosx/DownloadFullInstaller/latest/total) ![](https://img.shields.io/badge/macOS-11.0%2B-success) ![](https://img.shields.io/github/license/scriptingosx/DownloadFullInstaller) + -![](DownloadFullInstaller-1.0-screenshot.png) + + +--- + + + +--- This is a Swift UI implementation of my [fetch-installer-pkg](https://github.com/scriptingosx/fetch-installer-pkg) script. It will list the full macOS Big Sur (and later) installer pkgs available for download in Apple's software update catalogs. You can then choose to download one of them. +### Notes about version 2.0 + +GitHub user [matxpa](https://github.com/matxpa) has modified this app by updating it to the most recent versions of macOS, fixing issues and adding improvements, hence the change to version 2.0: + +* Improved Swift code +* Updated up to macOS 15 Sequoia +* Fixed an issue that prevented displaying a beta version of macOS from a system with an older version. Beta versions are now displayed if the correct catalog is selected (Beta word is only applied to the icon of the most recent macOS version) +* Preferences for choosing catalog are no longer a separate dialog but are now at the top of the main window +* A single macOS version or all versions can be displayed at once +* 2 buttons have been added + * Download installer package + * Create app from installer package. + +* Spanish localization and instructions to prevent sleep while downloading ([perez987](https://github.com/perez987)). + ### Motivation You may want to download the installer pkg instead of the installer application directly, because you want to re-deploy the installer application with a management system, such as Jamf. @@ -17,8 +38,8 @@ Since the Big Sur macOS installer application contains a single file larger than ### Extras - Copy the download URL for a given installer pkg from the context menu. - -- Change the seed program in the Preferences window. +- Change the seed program in the Preferences dropdown menu. +- Create the installer without leaving the application. ### Questions @@ -40,6 +61,24 @@ As far as I can tell, this downloads the same pkg as `softwareupdate --fetch-ful The difference is that the other tools then immediately perform the installation so that you get the installer application in the `/Applications` folder. This tool just downloads the pkg, so you can use it in your management system, archive the installer pkg, or manually run the installation. +#### Skip sleep while downloading the installer + +Download Full Installer does not prevent the system from going to sleep while an installer is being downloaded. You can prevent this with the `caffeinate` command: + +- open Terminal +- type `top | grep "Download"` +- stop `top` with Ctrl + C +- the output shows at the beginning of each line the PID of Download Full Installer +- type `caffeinate -w PID`(where PID is a number) +- sleep is blocked until Download Full Installer is closed. + +``` bash +/Users/yo > top | grep "Download" +2233 Download Full In (more text...) +#stop with Ctrl + C +/Users/yo > caffeinate -w 2233 +``` + ### Credit Both [fetch-installer-pkg](https://github.com/scriptingosx/fetch-installer-pkg) and this application are based on [Greg Neagle's installinstallmacos.py](https://github.com/munki/macadmin-scripts/blob/main/installinstallmacos.py) script.