Behaviour for pluggable application runtime backends.
A runtime backend adapts an application style to Drafter's event loop: how an app produces its initial state, and how it turns the loop's messages — input events, named callbacks, timers, lifecycle hooks — into new state and effects. The loop, renderer, transport and timer machinery are the same whichever backend is in use.
An app selects one with use Drafter.App, runtime: MyBackend. Two ship with
Drafter: Drafter.Runtime.Callback, the default, taking mount/1 and
handle_event/2,3; and Drafter.Runtime.Reducer, taking init/1 and update/2.
render/1 is not part of this behaviour. The renderer calls the app's render/1
directly, so every backend requires the app to define it.
Summary
Types
A frame-pacing specification, as accepted by Drafter.Runtime.FrameClock.interval_for/1.
What a backend returns from handle_input/3 and handle_message/4.
Callbacks
Handle a raw input/framework event tuple, returning the app's event result.
Handle a named application message with its payload, returning the app's event result.
Produce the app's initial state from mount props (callback mount, reducer init).
Handle an out-of-band process message delivered to the loop.
Run the post-mount ready hook, returning possibly-updated state.
The app's preferred frame pacing, or nil to let the loop choose.
Hook invoked while scrolling is active (for scroll-driven state).
Hook invoked once scrolling settles.
Handle a fired timer.
Functions
Resolve the runtime backend module for an app module.
The mount props carried by opts, as a map.
Normalize a backend shorthand or module to a backend module.
Types
@type app() :: module()
@type refresh_rate() :: pos_integer() | String.t() | :unlimited | nil
A frame-pacing specification, as accepted by Drafter.Runtime.FrameClock.interval_for/1.
nil means "no preference"; the loop then falls back to its own default.
@type result() :: term()
What a backend returns from handle_input/3 and handle_message/4.
Drafter.EventResult.parse/2 turns any of these into {state, actions, control},
so a backend may return a bare state, {:ok, state}, {:ok, state, actions},
{:noreply, state}, :handled, :unhandled, or {:stop, reason}.
@type state() :: term()
Callbacks
Handle a raw input/framework event tuple, returning the app's event result.
Handle a named application message with its payload, returning the app's event result.
Produce the app's initial state from mount props (callback mount, reducer init).
Handle an out-of-band process message delivered to the loop.
Run the post-mount ready hook, returning possibly-updated state.
@callback refresh_rate(app()) :: refresh_rate()
The app's preferred frame pacing, or nil to let the loop choose.
The value is passed to Drafter.Runtime.FrameClock.interval_for/1, so it may be a
millisecond integer, an fps string such as "30fps", "unlimited", or :unlimited.
Hook invoked while scrolling is active (for scroll-driven state).
Hook invoked once scrolling settles.
Handle a fired timer.
Functions
Resolve the runtime backend module for an app module.
The first of these that is set wins: the calling process's
:drafter_runtime_override process-dictionary entry, which a shared session sets;
the app's own __runtime__/0, defined by use Drafter.App, runtime: ...; then
Drafter.Runtime.Callback. The result is passed through normalize/1, so
shorthand atoms are accepted in either place.
The mount props carried by opts, as a map.
Every entry point that starts an app — Drafter.run/2, a pushed nested session,
and Drafter.run_session/3 behind the ssh and telnet transports — carries mount
props under the single :props key. opts is that keyword list, or a map, which
is returned as the props themselves.
Returns %{} when :props is absent. The surrounding options are never treated
as props.
Examples
iex> Drafter.Runtime.mount_props(props: %{user_id: 7})
%{user_id: 7}
iex> Drafter.Runtime.mount_props(refresh_rate: "60fps")
%{}
iex> Drafter.Runtime.mount_props(props: [a: 1, b: 2])
%{a: 1, b: 2}
iex> Drafter.Runtime.mount_props(%{already: :props})
%{already: :props}
Normalize a backend shorthand or module to a backend module.
Recognised shorthands are :callback, :reducer and :shared. Any other atom is
returned unchanged, so a backend module may be given directly.
Examples
iex> Drafter.Runtime.normalize(:callback)
Drafter.Runtime.Callback
iex> Drafter.Runtime.normalize(:reducer)
Drafter.Runtime.Reducer
iex> Drafter.Runtime.normalize(:shared)
Drafter.Runtime.Shared
iex> Drafter.Runtime.normalize(Drafter.Runtime.Callback)
Drafter.Runtime.Callback