From f7a5abaf71f1d7441fd05e97ccf783efbb6fa786 Mon Sep 17 00:00:00 2001 From: LoopingStudio Date: Thu, 12 Feb 2026 17:41:35 +0100 Subject: [PATCH 1/3] Add Sparkle updater --- .../project.pbxproj | 42 ++++++++++++++++-- .../xcshareddata/swiftpm/Package.resolved | 11 ++++- .../ApertureTokensManager.entitlements | 11 +++++ .../App/ApertureTokensManagerApp.swift | 44 +++++++++++++++++++ ApertureTokensManager/Info.plist | 12 +++++ 5 files changed, 115 insertions(+), 5 deletions(-) create mode 100644 ApertureTokensManager/ApertureTokensManager.entitlements create mode 100644 ApertureTokensManager/Info.plist diff --git a/ApertureTokensManager.xcodeproj/project.pbxproj b/ApertureTokensManager.xcodeproj/project.pbxproj index 74f5745..4db1c9a 100644 --- a/ApertureTokensManager.xcodeproj/project.pbxproj +++ b/ApertureTokensManager.xcodeproj/project.pbxproj @@ -7,6 +7,7 @@ objects = { /* Begin PBXBuildFile section */ + 18CCDEB42F3E30D3006FEB50 /* Sparkle in Frameworks */ = {isa = PBXBuildFile; productRef = 18CCDEB32F3E30D3006FEB50 /* Sparkle */; }; 18D87B2B2F28C30100D76485 /* ComposableArchitecture in Frameworks */ = {isa = PBXBuildFile; productRef = 18D87B2A2F28C30100D76485 /* ComposableArchitecture */; }; /* End PBXBuildFile section */ @@ -25,6 +26,16 @@ 18D87B1B2F28C2CF00D76485 /* ApertureTokensManager.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ApertureTokensManager.app; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ +/* Begin PBXFileSystemSynchronizedBuildFileExceptionSet section */ + 18CCDEB62F3E3432006FEB50 /* Exceptions for "ApertureTokensManager" folder in "ApertureTokensManager" target */ = { + isa = PBXFileSystemSynchronizedBuildFileExceptionSet; + membershipExceptions = ( + Info.plist, + ); + target = 18D87B1A2F28C2CF00D76485 /* ApertureTokensManager */; + }; +/* End PBXFileSystemSynchronizedBuildFileExceptionSet section */ + /* Begin PBXFileSystemSynchronizedRootGroup section */ 18610F382F337400005F2E4D /* ApertureTokensManagerTests */ = { isa = PBXFileSystemSynchronizedRootGroup; @@ -33,6 +44,9 @@ }; 18D87B1D2F28C2CF00D76485 /* ApertureTokensManager */ = { isa = PBXFileSystemSynchronizedRootGroup; + exceptions = ( + 18CCDEB62F3E3432006FEB50 /* Exceptions for "ApertureTokensManager" folder in "ApertureTokensManager" target */, + ); path = ApertureTokensManager; sourceTree = ""; }; @@ -51,6 +65,7 @@ buildActionMask = 2147483647; files = ( 18D87B2B2F28C30100D76485 /* ComposableArchitecture in Frameworks */, + 18CCDEB42F3E30D3006FEB50 /* Sparkle in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -119,6 +134,7 @@ name = ApertureTokensManager; packageProductDependencies = ( 18D87B2A2F28C30100D76485 /* ComposableArchitecture */, + 18CCDEB32F3E30D3006FEB50 /* Sparkle */, ); productName = "Aperture Tokens Importer"; productReference = 18D87B1B2F28C2CF00D76485 /* ApertureTokensManager.app */; @@ -154,6 +170,7 @@ minimizedProjectReferenceProxies = 1; packageReferences = ( 18D87B292F28C30100D76485 /* XCRemoteSwiftPackageReference "swift-composable-architecture" */, + 18CCDEB22F3E30D3006FEB50 /* XCRemoteSwiftPackageReference "Sparkle" */, ); preferredProjectObjectVersion = 77; productRefGroup = 18D87B1C2F28C2CF00D76485 /* Products */; @@ -391,6 +408,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = YES; + CODE_SIGN_ENTITLEMENTS = ApertureTokensManager/ApertureTokensManager.entitlements; "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development"; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; @@ -398,8 +416,8 @@ DEVELOPMENT_TEAM = JFTEHE2V9R; ENABLE_APP_SANDBOX = YES; ENABLE_HARDENED_RUNTIME = YES; - ENABLE_INCOMING_NETWORK_CONNECTIONS = NO; - ENABLE_OUTGOING_NETWORK_CONNECTIONS = NO; + ENABLE_INCOMING_NETWORK_CONNECTIONS = YES; + ENABLE_OUTGOING_NETWORK_CONNECTIONS = YES; ENABLE_PREVIEWS = YES; ENABLE_RESOURCE_ACCESS_AUDIO_INPUT = NO; ENABLE_RESOURCE_ACCESS_BLUETOOTH = NO; @@ -411,6 +429,7 @@ ENABLE_RESOURCE_ACCESS_USB = NO; ENABLE_USER_SELECTED_FILES = readwrite; GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_FILE = ApertureTokensManager/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = "Aperture Tokens Manager"; "INFOPLIST_KEY_UIApplicationSceneManifest_Generation[sdk=iphoneos*]" = YES; "INFOPLIST_KEY_UIApplicationSceneManifest_Generation[sdk=iphonesimulator*]" = YES; @@ -449,6 +468,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = YES; + CODE_SIGN_ENTITLEMENTS = ApertureTokensManager/ApertureTokensManager.entitlements; "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development"; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; @@ -456,8 +476,8 @@ DEVELOPMENT_TEAM = JFTEHE2V9R; ENABLE_APP_SANDBOX = YES; ENABLE_HARDENED_RUNTIME = YES; - ENABLE_INCOMING_NETWORK_CONNECTIONS = NO; - ENABLE_OUTGOING_NETWORK_CONNECTIONS = NO; + ENABLE_INCOMING_NETWORK_CONNECTIONS = YES; + ENABLE_OUTGOING_NETWORK_CONNECTIONS = YES; ENABLE_PREVIEWS = YES; ENABLE_RESOURCE_ACCESS_AUDIO_INPUT = NO; ENABLE_RESOURCE_ACCESS_BLUETOOTH = NO; @@ -469,6 +489,7 @@ ENABLE_RESOURCE_ACCESS_USB = NO; ENABLE_USER_SELECTED_FILES = readwrite; GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_FILE = ApertureTokensManager/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = "Aperture Tokens Manager"; "INFOPLIST_KEY_UIApplicationSceneManifest_Generation[sdk=iphoneos*]" = YES; "INFOPLIST_KEY_UIApplicationSceneManifest_Generation[sdk=iphonesimulator*]" = YES; @@ -534,6 +555,14 @@ /* End XCConfigurationList section */ /* Begin XCRemoteSwiftPackageReference section */ + 18CCDEB22F3E30D3006FEB50 /* XCRemoteSwiftPackageReference "Sparkle" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/sparkle-project/Sparkle"; + requirement = { + kind = upToNextMajorVersion; + minimumVersion = 2.8.1; + }; + }; 18D87B292F28C30100D76485 /* XCRemoteSwiftPackageReference "swift-composable-architecture" */ = { isa = XCRemoteSwiftPackageReference; repositoryURL = "https://github.com/pointfreeco/swift-composable-architecture"; @@ -545,6 +574,11 @@ /* End XCRemoteSwiftPackageReference section */ /* Begin XCSwiftPackageProductDependency section */ + 18CCDEB32F3E30D3006FEB50 /* Sparkle */ = { + isa = XCSwiftPackageProductDependency; + package = 18CCDEB22F3E30D3006FEB50 /* XCRemoteSwiftPackageReference "Sparkle" */; + productName = Sparkle; + }; 18D87B2A2F28C30100D76485 /* ComposableArchitecture */ = { isa = XCSwiftPackageProductDependency; package = 18D87B292F28C30100D76485 /* XCRemoteSwiftPackageReference "swift-composable-architecture" */; diff --git a/ApertureTokensManager.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/ApertureTokensManager.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 97fd36c..2e6311d 100644 --- a/ApertureTokensManager.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/ApertureTokensManager.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -1,5 +1,5 @@ { - "originHash" : "e7024a9cd3fa1c40fa4003b3b2b186c00ba720c787de8ba274caf8fc530677e8", + "originHash" : "c74453d4a6f4194ae2e8e31c4e6d760b13a667825437c3739f38a3fa8788d783", "pins" : [ { "identity" : "combine-schedulers", @@ -10,6 +10,15 @@ "version" : "1.1.0" } }, + { + "identity" : "sparkle", + "kind" : "remoteSourceControl", + "location" : "https://github.com/sparkle-project/Sparkle", + "state" : { + "revision" : "5581748cef2bae787496fe6d61139aebe0a451f6", + "version" : "2.8.1" + } + }, { "identity" : "swift-case-paths", "kind" : "remoteSourceControl", diff --git a/ApertureTokensManager/ApertureTokensManager.entitlements b/ApertureTokensManager/ApertureTokensManager.entitlements new file mode 100644 index 0000000..77493f9 --- /dev/null +++ b/ApertureTokensManager/ApertureTokensManager.entitlements @@ -0,0 +1,11 @@ + + + + + com.apple.security.temporary-exception.mach-lookup.global-name + + $(PRODUCT_BUNDLE_IDENTIFIER)-spks + $(PRODUCT_BUNDLE_IDENTIFIER)-spki + + + diff --git a/ApertureTokensManager/App/ApertureTokensManagerApp.swift b/ApertureTokensManager/App/ApertureTokensManagerApp.swift index eef9daf..bcfe753 100644 --- a/ApertureTokensManager/App/ApertureTokensManagerApp.swift +++ b/ApertureTokensManager/App/ApertureTokensManagerApp.swift @@ -1,8 +1,47 @@ +import Combine import SwiftUI import ComposableArchitecture +import Sparkle + +// This view model class publishes when new updates can be checked by the user +final class CheckForUpdatesViewModel: ObservableObject { + @Published var canCheckForUpdates = false + + init(updater: SPUUpdater) { + updater.publisher(for: \.canCheckForUpdates) + .assign(to: &$canCheckForUpdates) + } +} + +// This is the view for the Check for Updates menu item +// Note this intermediate view is necessary for the disabled state on the menu item to work properly before Monterey. +// See https://stackoverflow.com/questions/68553092/menu-not-updating-swiftui-bug for more info +struct CheckForUpdatesView: View { + @ObservedObject private var checkForUpdatesViewModel: CheckForUpdatesViewModel + private let updater: SPUUpdater + + init(updater: SPUUpdater) { + self.updater = updater + + // Create our view model for our CheckForUpdatesView + self.checkForUpdatesViewModel = CheckForUpdatesViewModel(updater: updater) + } + + var body: some View { + Button("Check for Updates…", action: updater.checkForUpdates) + .disabled(!checkForUpdatesViewModel.canCheckForUpdates) + } +} + @main struct ApertureTokensManagerApp: App { + private let updaterController: SPUStandardUpdaterController + init() { + // If you want to start the updater manually, pass false to startingUpdater and call .startUpdater() later + // This is where you can also pass an updater delegate if you need one + updaterController = SPUStandardUpdaterController(startingUpdater: true, updaterDelegate: nil, userDriverDelegate: nil) + } var body: some Scene { WindowGroup { AppView( @@ -12,6 +51,11 @@ struct ApertureTokensManagerApp: App { ) .frame(minWidth: 900, minHeight: 650) } + .commands { + CommandGroup(after: .appInfo) { + CheckForUpdatesView(updater: updaterController.updater) + } + } .defaultSize(width: 1100, height: 750) } } diff --git a/ApertureTokensManager/Info.plist b/ApertureTokensManager/Info.plist new file mode 100644 index 0000000..5a00f1e --- /dev/null +++ b/ApertureTokensManager/Info.plist @@ -0,0 +1,12 @@ + + + + + SUEnableInstallerLauncherService + + SUFeedURL + https://loopingstudio.github.io/ApertureTokenManager/appcast.xml + SUPublicEDKey + AO8KvH4ISg6LNcdRlUJCjRYzHasX7GEhSPee9Y8GA8I= + + From 24bfba977198c33c34fa53b67d1f3714d709bc83 Mon Sep 17 00:00:00 2001 From: LoopingStudio Date: Mon, 16 Feb 2026 10:16:30 +0100 Subject: [PATCH 2/3] appcast --- .../project.pbxproj | 4 ++-- .../xcshareddata/swiftpm/Package.resolved | 2 +- appcast.xml | 22 +++++++++++++++++++ 3 files changed, 25 insertions(+), 3 deletions(-) create mode 100644 appcast.xml diff --git a/ApertureTokensManager.xcodeproj/project.pbxproj b/ApertureTokensManager.xcodeproj/project.pbxproj index 4db1c9a..aa85300 100644 --- a/ApertureTokensManager.xcodeproj/project.pbxproj +++ b/ApertureTokensManager.xcodeproj/project.pbxproj @@ -416,7 +416,7 @@ DEVELOPMENT_TEAM = JFTEHE2V9R; ENABLE_APP_SANDBOX = YES; ENABLE_HARDENED_RUNTIME = YES; - ENABLE_INCOMING_NETWORK_CONNECTIONS = YES; + ENABLE_INCOMING_NETWORK_CONNECTIONS = NO; ENABLE_OUTGOING_NETWORK_CONNECTIONS = YES; ENABLE_PREVIEWS = YES; ENABLE_RESOURCE_ACCESS_AUDIO_INPUT = NO; @@ -476,7 +476,7 @@ DEVELOPMENT_TEAM = JFTEHE2V9R; ENABLE_APP_SANDBOX = YES; ENABLE_HARDENED_RUNTIME = YES; - ENABLE_INCOMING_NETWORK_CONNECTIONS = YES; + ENABLE_INCOMING_NETWORK_CONNECTIONS = NO; ENABLE_OUTGOING_NETWORK_CONNECTIONS = YES; ENABLE_PREVIEWS = YES; ENABLE_RESOURCE_ACCESS_AUDIO_INPUT = NO; diff --git a/ApertureTokensManager.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/ApertureTokensManager.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 2e6311d..99a12ed 100644 --- a/ApertureTokensManager.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/ApertureTokensManager.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -1,5 +1,5 @@ { - "originHash" : "c74453d4a6f4194ae2e8e31c4e6d760b13a667825437c3739f38a3fa8788d783", + "originHash" : "54a13b006cb4109da3ff9bdb4ce037cd8fa6658498640f5dcda011cdc3680d63", "pins" : [ { "identity" : "combine-schedulers", diff --git a/appcast.xml b/appcast.xml new file mode 100644 index 0000000..219886f --- /dev/null +++ b/appcast.xml @@ -0,0 +1,22 @@ + + + + ApertureTokensManager + + 1.0 + Fri, 13 Feb 2026 16:48:35 +0100 + 1 + 1.0 + 15.0 + What's New +
    +
  • Initial release of Aperture Tokens Manager.
  • +
  • Enjoy the first version of the app !
  • +
+ ]]> +
+ +
+
+
From 6e32b5c0f41fddedf30689dd4b627cc5a6d9783a Mon Sep 17 00:00:00 2001 From: LoopingStudio Date: Mon, 16 Feb 2026 10:20:33 +0100 Subject: [PATCH 3/3] Bump version --- ApertureTokensManager.xcodeproj/project.pbxproj | 8 ++++---- appcast.xml | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/ApertureTokensManager.xcodeproj/project.pbxproj b/ApertureTokensManager.xcodeproj/project.pbxproj index aa85300..ff75ac4 100644 --- a/ApertureTokensManager.xcodeproj/project.pbxproj +++ b/ApertureTokensManager.xcodeproj/project.pbxproj @@ -411,7 +411,7 @@ CODE_SIGN_ENTITLEMENTS = ApertureTokensManager/ApertureTokensManager.entitlements; "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; + CURRENT_PROJECT_VERSION = 2; DEAD_CODE_STRIPPING = YES; DEVELOPMENT_TEAM = JFTEHE2V9R; ENABLE_APP_SANDBOX = YES; @@ -445,7 +445,7 @@ LD_RUNPATH_SEARCH_PATHS = "@executable_path/Frameworks"; "LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "@executable_path/../Frameworks"; MACOSX_DEPLOYMENT_TARGET = 15.0; - MARKETING_VERSION = 1.0; + MARKETING_VERSION = 1.0.1; PRODUCT_BUNDLE_IDENTIFIER = "com.looping-studio.ApertureTokensManager"; PRODUCT_NAME = "$(TARGET_NAME)"; REGISTER_APP_GROUPS = YES; @@ -471,7 +471,7 @@ CODE_SIGN_ENTITLEMENTS = ApertureTokensManager/ApertureTokensManager.entitlements; "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; + CURRENT_PROJECT_VERSION = 2; DEAD_CODE_STRIPPING = YES; DEVELOPMENT_TEAM = JFTEHE2V9R; ENABLE_APP_SANDBOX = YES; @@ -505,7 +505,7 @@ LD_RUNPATH_SEARCH_PATHS = "@executable_path/Frameworks"; "LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "@executable_path/../Frameworks"; MACOSX_DEPLOYMENT_TARGET = 15.0; - MARKETING_VERSION = 1.0; + MARKETING_VERSION = 1.0.1; PRODUCT_BUNDLE_IDENTIFIER = "com.looping-studio.ApertureTokensManager"; PRODUCT_NAME = "$(TARGET_NAME)"; REGISTER_APP_GROUPS = YES; diff --git a/appcast.xml b/appcast.xml index 219886f..8e68e3d 100644 --- a/appcast.xml +++ b/appcast.xml @@ -3,10 +3,10 @@ ApertureTokensManager - 1.0 - Fri, 13 Feb 2026 16:48:35 +0100 + 1.0.1 + Fri, 16 Feb 2026 10:19:35 +0100 1 - 1.0 + 1.0.1 15.0 What's New @@ -16,7 +16,7 @@ ]]> - +