Skip to main content

Blink: add a ScriptHelper enum for running AppleScript

ID
e154ddb
date
2026-06-28 19:47:59+00:00
author
Alex Chan <alex@alexwlchan.net>
parent
37d01fd
message
Blink: add a ScriptHelper enum for running AppleScript
changed files
4 files, 50 additions, 13 deletions

Changed files

Blink.xcodeproj/project.pbxproj (35415) → Blink.xcodeproj/project.pbxproj (35857)

diff --git a/Blink.xcodeproj/project.pbxproj b/Blink.xcodeproj/project.pbxproj
index e4a5958..b306942 100644
--- a/Blink.xcodeproj/project.pbxproj
+++ b/Blink.xcodeproj/project.pbxproj
@@ -10,6 +10,7 @@
 		940331732A336B5100200C5D /* DeferredRendering.swift in Sources */ = {isa = PBXBuildFile; fileRef = 940331722A336B5100200C5D /* DeferredRendering.swift */; };
 		9404B57D2A3EEBBA00068FA8 /* SettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9404B57C2A3EEBBA00068FA8 /* SettingsView.swift */; };
 		941E18FA2A35362600A2EA98 /* Info.swift in Sources */ = {isa = PBXBuildFile; fileRef = 941E18F92A35362600A2EA98 /* Info.swift */; };
+		944EB0DF2FF1AF01002C81C3 /* ScriptHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 944EB0DE2FF1AEFE002C81C3 /* ScriptHelper.swift */; };
 		945F17B02A33D167004FC479 /* ThumbnailImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 945F17AF2A33D167004FC479 /* ThumbnailImage.swift */; };
 		945F17B22A33D69B004FC479 /* FavoriteOverlay.swift in Sources */ = {isa = PBXBuildFile; fileRef = 945F17B12A33D69B004FC479 /* FavoriteOverlay.swift */; };
 		945F17B42A33D726004FC479 /* ReviewStateIcon.swift in Sources */ = {isa = PBXBuildFile; fileRef = 945F17B32A33D726004FC479 /* ReviewStateIcon.swift */; };
@@ -61,6 +62,7 @@
 		940331722A336B5100200C5D /* DeferredRendering.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeferredRendering.swift; sourceTree = "<group>"; };
 		9404B57C2A3EEBBA00068FA8 /* SettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsView.swift; sourceTree = "<group>"; };
 		941E18F92A35362600A2EA98 /* Info.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Info.swift; sourceTree = "<group>"; };
+		944EB0DE2FF1AEFE002C81C3 /* ScriptHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScriptHelper.swift; sourceTree = "<group>"; };
 		945F17AF2A33D167004FC479 /* ThumbnailImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThumbnailImage.swift; sourceTree = "<group>"; };
 		945F17B12A33D69B004FC479 /* FavoriteOverlay.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FavoriteOverlay.swift; sourceTree = "<group>"; };
 		945F17B32A33D726004FC479 /* ReviewStateIcon.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReviewStateIcon.swift; sourceTree = "<group>"; };
@@ -145,6 +147,7 @@
 		9492C96E2A3C37FA002E44EC /* Helpers */ = {
 			isa = PBXGroup;
 			children = (
+				944EB0DE2FF1AEFE002C81C3 /* ScriptHelper.swift */,
 				9492C96F2A3C3803002E44EC /* Timer.swift */,
 			);
 			path = Helpers;
@@ -433,6 +436,7 @@
 				945F17B62A33D7AA004FC479 /* ReviewStateBorder.swift in Sources */,
 				94A083612A33E98000238964 /* AlbumInfoOverlay.swift in Sources */,
 				94C5FFF22A33ADD4004ADDF5 /* PHFetchResultCollection.swift in Sources */,
+				944EB0DF2FF1AF01002C81C3 /* ScriptHelper.swift in Sources */,
 				94A083662A33F50900238964 /* Debug.swift in Sources */,
 				94A083682A33F6E900238964 /* ThumbnailList.swift in Sources */,
 				94D750F02A31A796005859E7 /* BlinkApp.swift in Sources */,
@@ -604,7 +608,7 @@
 				CODE_SIGN_ENTITLEMENTS = Blink/Blink.entitlements;
 				CODE_SIGN_STYLE = Automatic;
 				COMBINE_HIDPI_IMAGES = YES;
-				CURRENT_PROJECT_VERSION = 130;
+				CURRENT_PROJECT_VERSION = 136;
 				DEVELOPMENT_ASSET_PATHS = "\"Blink/Preview Content\"";
 				ENABLE_HARDENED_RUNTIME = YES;
 				ENABLE_PREVIEWS = YES;
@@ -633,7 +637,7 @@
 				CODE_SIGN_ENTITLEMENTS = Blink/Blink.entitlements;
 				CODE_SIGN_STYLE = Automatic;
 				COMBINE_HIDPI_IMAGES = YES;
-				CURRENT_PROJECT_VERSION = 130;
+				CURRENT_PROJECT_VERSION = 136;
 				DEVELOPMENT_ASSET_PATHS = "\"Blink/Preview Content\"";
 				ENABLE_HARDENED_RUNTIME = YES;
 				ENABLE_PREVIEWS = YES;
@@ -660,7 +664,7 @@
 				ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
 				BUNDLE_LOADER = "$(TEST_HOST)";
 				CODE_SIGN_STYLE = Automatic;
-				CURRENT_PROJECT_VERSION = 130;
+				CURRENT_PROJECT_VERSION = 136;
 				GENERATE_INFOPLIST_FILE = YES;
 				MACOSX_DEPLOYMENT_TARGET = 13.3;
 				MARKETING_VERSION = 1.0;
@@ -678,7 +682,7 @@
 				ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
 				BUNDLE_LOADER = "$(TEST_HOST)";
 				CODE_SIGN_STYLE = Automatic;
-				CURRENT_PROJECT_VERSION = 130;
+				CURRENT_PROJECT_VERSION = 136;
 				GENERATE_INFOPLIST_FILE = YES;
 				MACOSX_DEPLOYMENT_TARGET = 13.3;
 				MARKETING_VERSION = 1.0;
@@ -695,7 +699,7 @@
 			buildSettings = {
 				ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
 				CODE_SIGN_STYLE = Automatic;
-				CURRENT_PROJECT_VERSION = 130;
+				CURRENT_PROJECT_VERSION = 136;
 				GENERATE_INFOPLIST_FILE = YES;
 				MARKETING_VERSION = 1.0;
 				PRODUCT_BUNDLE_IDENTIFIER = net.alexwlchan.BlinkReviewerUITests;
@@ -711,7 +715,7 @@
 			buildSettings = {
 				ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
 				CODE_SIGN_STYLE = Automatic;
-				CURRENT_PROJECT_VERSION = 130;
+				CURRENT_PROJECT_VERSION = 136;
 				GENERATE_INFOPLIST_FILE = YES;
 				MARKETING_VERSION = 1.0;
 				PRODUCT_BUNDLE_IDENTIFIER = net.alexwlchan.BlinkReviewerUITests;

Blink/Helpers/ScriptHelper.swift (0) → Blink/Helpers/ScriptHelper.swift (976)

diff --git a/Blink/Helpers/ScriptHelper.swift b/Blink/Helpers/ScriptHelper.swift
new file mode 100644
index 0000000..3e45e4a
--- /dev/null
+++ b/Blink/Helpers/ScriptHelper.swift
@@ -0,0 +1,33 @@
+import Foundation
+
+/// ScriptHelper is a helper for invoking AppleScript.
+///
+/// This allows
+enum ScriptHelper {
+    
+    /// Execute an AppleScript via osascript with the provided arguments.
+    /// Returns the output or throws an error.
+    @discardableResult
+    static func runAppleScript(_ script: String, arguments: [String]) throws -> String {
+        let task = Process()
+        task.launchPath = "/usr/bin/osascript"
+        
+        var args = ["-e", script]
+        args.append(contentsOf: arguments)
+        task.arguments = args
+        
+        let pipe = Pipe()
+        task.standardOutput = pipe
+        task.standardError = Pipe()
+        
+        try task.run()
+        task.waitUntilExit()
+        
+        let data = pipe.fileHandleForReading.readDataToEndOfFile()
+        guard let output = String(data: data, encoding: .utf8) else {
+            return ""
+        }
+        
+        return output.trimmingCharacters(in: .whitespacesAndNewlines)
+    }
+}

Blink/Views/FocusedImage/CaptionOverlay.swift (0) → Blink/Views/FocusedImage/CaptionOverlay.swift (0)

diff --git a/Blink/Views/FocusedImage/CaptionOverlay.swift b/Blink/Views/FocusedImage/CaptionOverlay.swift
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Blink/Views/FocusedImage/CaptionOverlay.swift

Blink/Views/PhotoReviewer.swift (14265) → Blink/Views/PhotoReviewer.swift (14287)

diff --git a/Blink/Views/PhotoReviewer.swift b/Blink/Views/PhotoReviewer.swift
index c9ab339..314936a 100644
--- a/Blink/Views/PhotoReviewer.swift
+++ b/Blink/Views/PhotoReviewer.swift
@@ -319,16 +319,16 @@ struct PhotoReviewer: View {
                 return nil
             
             case let e where e.characters == "o":
-                let task = Process()
-                task.launchPath = "/usr/bin/osascript"
-                task.arguments = ["-e", """
+                let script = """
+                on run argv
+                    set targetId to item 1 of argv
                     tell application "Photos"
-                        spotlight media item id \"\(focusedAsset.localIdentifier)\"
+                        spotlight media item id targetId
                         activate
                     end tell
-                """]
-                 
-                try! task.run()
+                end run
+                """
+                try! ScriptHelper.runAppleScript(script, arguments: [focusedAsset.localIdentifier])
                 return nil
 
             default: