macOS: carrier:// URL scheme for automation
Facebook Messenger on your desktop, without the Facebook clutter
Brought to you by:
kristoffer-r
Originally created by: kristofferR
CFBundleURLTypes and RunEvent::Opened are completely unused today. A carrier:// scheme enables Shortcuts/Raycast/browser automation: carrier://t/<id> (open thread), carrier://compose, carrier://settings.
RunEvent::Opened, no plugin. tauri-plugin-deep-link's value is Windows/Linux runtime registration and a JS API — not needed for macOS-only scope. Tauri core already delivers application:openURLs: as RunEvent::Opened { urls } on macOS. Add CFBundleURLTypes (scheme carrier, role Viewer) to the hand-maintained src-tauri/Info.plist. Launch Services routes opens to the running instance directly — single-instance/argv is not involved.src-tauri/src/actions.rs: AppAction { NewConversation, Settings, OpenThread(String) } + parse_carrier_url(&Url) -> Option<AppAction>. Reject any URL with query/fragment/userinfo/port; thread ids are 1–32 ASCII digits, validated via one consolidated helper — validated_thread_path already exists in notifications.rs and the digits check is currently duplicated in menu.rs; consolidate to one pub(crate) fn rather than adding a fourth copy. Nothing from the URL is ever eval'd except the validated digits, JSON-encoded (same discipline as open_recent_thread). Invalid URLs → warn log (truncated, never echoed verbatim).run_app_action(app, action) — the same shape as [#170]'s CLI-flags design; [#170]'s CliAction should become this shared enum (Ref [#170]). Settings runs immediately; NewConversation/OpenThread need the injected page hooks, so: add a pending_action slot + messenger_loaded flag to AppState, drained by the existing on_page_load closure in window.rs (Finished on a Messenger URL). Warm path evals immediately with a bounded page-side retry IIFE (~500 ms × 20, hooks may still be registering); cold start (Launch Services starts the app with a URL) stores into the slot, last-writer-wins. Best-effort, documented — same stance as [#170].lib.rs next to the existing Reopen arm: on Opened { urls }, dispatch the first valid URL, ignore the rest (any app can hand us an arbitrary vector).parse_carrier_url (trailing slash, non-numeric, >32 digits, query/fragment, empty id, wrong scheme/host); manual — open "carrier://t/<real id>" warm and cold, compose, settings, malformed URLs do nothing.Part of [#179].
Originally posted by: kristofferR
Shipped in [#230], released in v1.9.0.
carrier://compose,carrier://settings, andcarrier://t/<id>are handled throughRunEvent::OpenedwithCFBundleURLTypesin the hand-maintained Info.plist — no deep-link plugin. Parsing lives inactions.rsand rejects query, fragment, userinfo, port, and non-digit or over-long ids; only validated digits reach the page, JSON-encoded. Cold starts store the action in the pending slot and the page-load callback drains it, which is also what keeps an action alive across a window recreation.Related
Tickets:
#230Ticket changed by: kristofferR