76 lines
2.2 KiB
Elixir
76 lines
2.2 KiB
Elixir
defmodule BDS.Desktop.DeepLink do
|
|
@moduledoc """
|
|
Receives OS URL-scheme events for the `bds2://` scheme and routes them to the
|
|
shell (spec: script.allium `BlogmarkReceived`).
|
|
|
|
On macOS the `BDS2.app` bundle registers `bds2://` as a custom URL scheme via
|
|
the `CFBundleURLTypes` entry in its `Info.plist` (built by `BDS.MacBundle` /
|
|
`mix bds.bundle.macos`). When the browser bookmarklet navigates to
|
|
`bds2://new-post?title=&url=`, the OS launches/raises the app and `Desktop.Env`
|
|
delivers an `{:open_url, [url]}` event. This GenServer subscribes to those
|
|
events and forwards recognised `bds2://` links to the live shell over PubSub,
|
|
where `BDS.Blogmark` turns them into draft posts.
|
|
|
|
The `bds2://` scheme is distinct from the legacy app's `bds://` so the two
|
|
installs do not contend for the same registration.
|
|
"""
|
|
|
|
use GenServer
|
|
|
|
require Logger
|
|
|
|
alias BDS.CliSync.Watcher
|
|
|
|
@scheme "bds2://"
|
|
|
|
def child_spec(opts) do
|
|
%{id: __MODULE__, start: {__MODULE__, :start_link, [opts]}}
|
|
end
|
|
|
|
def start_link(opts \\ []) do
|
|
GenServer.start_link(__MODULE__, opts, name: Keyword.get(opts, :name, __MODULE__))
|
|
end
|
|
|
|
@impl true
|
|
def init(opts) do
|
|
pubsub = Keyword.get(opts, :pubsub, BDS.PubSub)
|
|
topic = Keyword.get(opts, :topic, Watcher.topic())
|
|
|
|
subscribe_to_env()
|
|
|
|
{:ok, %{pubsub: pubsub, topic: topic}}
|
|
end
|
|
|
|
# Desktop.Env delivers OS events as {event_name, args} tuples.
|
|
@impl true
|
|
def handle_info({:open_url, [url | _rest]}, state) when is_binary(url) do
|
|
{:noreply, route(url, state)}
|
|
end
|
|
|
|
def handle_info(_message, state), do: {:noreply, state}
|
|
|
|
defp route(url, state) do
|
|
if String.starts_with?(url, @scheme) do
|
|
Phoenix.PubSub.broadcast(state.pubsub, state.topic, {:blogmark_deep_link, url})
|
|
else
|
|
Logger.debug("ignoring non-bds2 deep link: #{inspect(url)}")
|
|
end
|
|
|
|
state
|
|
end
|
|
|
|
# Desktop.Env is only present when the wx desktop adapter is running. Guard the
|
|
# subscribe so the GenServer can still start in headless/test configurations.
|
|
defp subscribe_to_env do
|
|
if Process.whereis(Desktop.Env) do
|
|
try do
|
|
Desktop.Env.subscribe()
|
|
catch
|
|
:exit, _reason -> :ok
|
|
end
|
|
end
|
|
|
|
:ok
|
|
end
|
|
end
|