Which messages are native input, and what each one is called outside the screen it was meant for.
Native input never goes through Mob.Event.dispatch/4. The NIF delivers the
legacy tuples listed in Mob.Listener — {:tap, tag}, {:change, tag, value}, {event, tag}, {event, tag, payload} — and the listener forwards
them to the screen as they are. So the two things that observe actions,
Mob.Agent.Receipts and Mob.Event.Trace, have to recognise them where they
land: in Mob.Screen.Server, and in Mob.Listener when the screen is gone.
This module is the one place that says which tuples those are.
Discrete and stream
| Kind | Messages | Receipt | Trace |
|---|---|---|---|
:discrete | :tap (list-row select included), :focus, :blur, :submit, :select, :dismiss, :long_press, :double_tap, :swipe_left/_right/_up/_down, {:swipe, tag, direction}, {:change, tag, value} except a float | yes | yes |
:stream | :scroll, :drag, :pinch, :rotate, :pointer_move, :compose, a float :change, and the scroll lifecycle (:scroll_began, :scroll_ended, :scroll_settled, :top_reached, :scrolled_past) | no | yes |
A stream fires at up to display rate, or several times per gesture. The
receipt store keeps 256, so one scroll would evict the tap an agent is about
to ask about, and a receipt costs an assigns comparison and an ETS write per
frame. A float :change is a slider — the only native sender of a float
value — which reports every step of a drag. Text, toggle and tab changes stay
discrete: one per keystroke or flip is the rate a person acts at.
Naming
An input is named by its canonical address and event atom, from
Mob.Event.Bridge.legacy_to_canonical/3 where the Bridge models the shape.
Where it does not, the same rule applies with the widget kind the event
implies (:text_field for focus, blur and submit, :sheet for dismiss,
:button otherwise, as for a tap). A :change takes its widget from the
value's type, which is all native tells us about the control: a boolean is a
:toggle, a binary a :text_field (anything else keeps the Bridge's
default). A tag that is not a valid address id
(Mob.Event.Address.validate_id/1) is named :opaque.
A receipt carries the name and never the payload: a text field's value is
user data, and a receipt is written to ETS and handed to telemetry. A trace
carries the payload, as Mob.Event.dispatch/4 always has — subscribing is an
explicit debugging act.
Summary
Functions
The canonical {address, event, payload} for a native input message, with
:opaque in place of the address when the tag is not a valid id.
Whether message is discrete native input, a stream, or not native input.
What a receipt records for a native input: {event, address}, or
{event, :opaque}. Never the payload.
Types
Functions
@spec canonical(tuple(), term()) :: {Mob.Event.Address.t() | :opaque, atom(), term()}
The canonical {address, event, payload} for a native input message, with
:opaque in place of the address when the tag is not a valid id.
Whether message is discrete native input, a stream, or not native input.
@spec receipt_event(tuple(), term()) :: {atom(), Mob.Event.Address.t() | :opaque}
What a receipt records for a native input: {event, address}, or
{event, :opaque}. Never the payload.