Current section
Files
Jump to
Current section
Files
src/sprocket@context.erl
-module(sprocket@context).
-compile([no_auto_import, nowarn_unused_vars]).
-export([new/1, reset_for_render/1, fetch_or_init_hook/2, update_hook/3, push_event_handler/2, get_event_handler/2]).
-export_type([event_handler/0, updater/1, component_wip/0, context/0]).
-type event_handler() :: {event_handler,
sprocket@internal@utils@unique:unique(),
sprocket@internal@identifiable_callback:callback_fn()}.
-type updater(JXZ) :: {updater, fun((JXZ) -> {ok, nil} | {error, nil})}.
-type component_wip() :: {component_wip,
sprocket@internal@utils@ordered_map:ordered_map(integer(), sprocket@hooks:hook()),
integer(),
boolean()}.
-type context() :: {context,
component_wip(),
list(event_handler()),
gleam@option:option(gleam@erlang@process:subject(glisten@handler:handler_message())),
fun(() -> nil),
fun((sprocket@internal@utils@unique:unique(), fun((sprocket@hooks:hook()) -> sprocket@hooks:hook())) -> nil)}.
-spec new(
gleam@option:option(gleam@erlang@process:subject(glisten@handler:handler_message()))
) -> context().
new(Ws) ->
{context,
{component_wip, sprocket@internal@utils@ordered_map:new(), 0, true},
[],
Ws,
fun() -> nil end,
fun(_, _) -> nil end}.
-spec reset_for_render(context()) -> context().
reset_for_render(Ctx) ->
erlang:setelement(3, Ctx, []).
-spec fetch_or_init_hook(context(), fun(() -> sprocket@hooks:hook())) -> {context(),
sprocket@hooks:hook(),
integer()}.
fetch_or_init_hook(Ctx, Init) ->
Index = erlang:element(3, erlang:element(2, Ctx)),
Hooks = erlang:element(2, erlang:element(2, Ctx)),
case sprocket@internal@utils@ordered_map:get(Hooks, Index) of
{ok, Hook} ->
{erlang:setelement(
2,
Ctx,
erlang:setelement(3, erlang:element(2, Ctx), Index + 1)
),
Hook,
Index};
{error, nil} ->
case erlang:element(4, erlang:element(2, Ctx)) of
true ->
nil;
false ->
sprocket@internal@logger:error(
<<<<"
Hook not found for index: "/utf8,
(gleam@int:to_string(Index))/binary>>/binary,
". This indicates a hook was dynamically
created since first render which is not allowed.
"/utf8>>
),
erlang:error(#{gleam_error => panic,
message => <<"panic expression evaluated"/utf8>>,
module => <<"sprocket/context"/utf8>>,
function => <<"fetch_or_init_hook"/utf8>>,
line => 84})
end,
Hook@1 = Init(),
{erlang:setelement(
2,
Ctx,
{component_wip,
sprocket@internal@utils@ordered_map:insert(
erlang:element(2, erlang:element(2, Ctx)),
Index,
Hook@1
),
Index + 1,
erlang:element(4, erlang:element(2, Ctx))}
),
Hook@1,
Index}
end.
-spec update_hook(context(), sprocket@hooks:hook(), integer()) -> context().
update_hook(Ctx, Hook, Index) ->
erlang:setelement(
2,
Ctx,
erlang:setelement(
2,
erlang:element(2, Ctx),
sprocket@internal@utils@ordered_map:update(
erlang:element(2, erlang:element(2, Ctx)),
Index,
Hook
)
)
).
-spec push_event_handler(
context(),
sprocket@internal@identifiable_callback:identifiable_callback()
) -> {context(), sprocket@internal@utils@unique:unique()}.
push_event_handler(Ctx, Identifiable_cb) ->
{identifiable_callback, Id, Cb} = Identifiable_cb,
{erlang:setelement(
3,
Ctx,
[{event_handler, Id, Cb} | erlang:element(3, Ctx)]
),
Id}.
-spec get_event_handler(context(), sprocket@internal@utils@unique:unique()) -> {context(),
{ok, event_handler()} | {error, nil}}.
get_event_handler(Ctx, Id) ->
Handler = gleam@list:find(
erlang:element(3, Ctx),
fun(H) ->
{event_handler, I, _} = H,
I =:= Id
end
),
{Ctx, Handler}.