The Garage SDKs, in the open

garage_auth, garage_entitlements, garage_iap and garage_ui, moved out of
Garage-Services and Metro-Map-Maker into one public repo. MIT, one readme,
docs under docs/.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013F4NWNvYcdeSgqbWMT1VQ7
This commit is contained in:
ImBenji
2026-09-23 18:49:21 +01:00
co-authored by Claude Opus 5.5
commit b269201919
117 changed files with 26944 additions and 0 deletions
@@ -0,0 +1,58 @@
import Cocoa
import FlutterMacOS
// Entry point Flutter calls into via RegisterGeneratedPlugins - this is what
// makes CursorLock and the eyedropper "just work" for any app that depends
// on garage_ui, without that app having to hand-wire the channels itself in
// its own MainFlutterWindow.swift. Used to be duplicated per-app, which is
// exactly how it silently went stale (renamed channel on one side, not the
// other) and why a brand new app (no Runner wiring at all) got a
// MissingPluginException out of the box.
public class GarageUiPlugin: NSObject, FlutterPlugin {
public static func register(with registrar: FlutterPluginRegistrar) {
let instance = GarageUiPlugin()
let cursorLockChannel = FlutterMethodChannel(
name: "garage/cursor_lock",
binaryMessenger: registrar.messenger
)
// CursorLock needs to hang on to the channel itself so it can push
// scrubDelta calls back to dart - see its own header for why a plain
// local var here isnt enough (it needs a home that outlives this fn)
CursorLock.shared.attach(channel: cursorLockChannel)
registrar.addMethodCallDelegate(instance, channel: cursorLockChannel)
let eyedropperChannel = FlutterMethodChannel(
name: "garage/eyedropper",
binaryMessenger: registrar.messenger
)
registrar.addMethodCallDelegate(instance, channel: eyedropperChannel)
}
public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
switch call.method {
case "lock":
CursorLock.shared.lock()
result(nil)
case "unlock":
CursorLock.shared.unlock()
result(nil)
case "isAvailable":
if #available(macOS 10.15, *) {
result(true)
} else {
result(false)
}
case "pick":
if #available(macOS 10.15, *) {
ScreenColorSampler.shared.show(result: result)
} else {
// dart reads nil as a cancel, which is close enough - it only ever
// asks for a pick after isAvailable said yes anyway
result(nil)
}
default:
result(FlutterMethodNotImplemented)
}
}
}