Current section

Files

Jump to
sprocket src sprocket@socket.erl
Raw

src/sprocket@socket.erl

-module(sprocket@socket).
-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, socket/0]).
-type event_handler() :: {event_handler,
sprocket@internal@utils@unique:unique(),
sprocket@internal@identifiable_callback:callback_fn()}.
-type updater(JYK) :: {updater, fun((JYK) -> {ok, nil} | {error, nil})}.
-type component_wip() :: {component_wip,
sprocket@internal@utils@ordered_map:ordered_map(integer(), sprocket@hooks:hook()),
integer(),
boolean()}.
-type socket() :: {socket,
component_wip(),
list(event_handler()),
gleam@option:option(gleam@erlang@process:subject(glisten@handler:handler_message())),
fun(() -> nil)}.
-spec new(
gleam@option:option(gleam@erlang@process:subject(glisten@handler:handler_message()))
) -> socket().
new(Ws) ->
{socket,
{component_wip, sprocket@internal@utils@ordered_map:new(), 0, true},
[],
Ws,
fun() -> nil end}.
-spec reset_for_render(socket()) -> socket().
reset_for_render(Socket) ->
erlang:setelement(3, Socket, []).
-spec fetch_or_init_hook(socket(), fun(() -> sprocket@hooks:hook())) -> {socket(),
sprocket@hooks:hook(),
integer()}.
fetch_or_init_hook(Socket, Init) ->
Index = erlang:element(3, erlang:element(2, Socket)),
Hooks = erlang:element(2, erlang:element(2, Socket)),
case sprocket@internal@utils@ordered_map:get(Hooks, Index) of
{ok, Hook} ->
{erlang:setelement(
2,
Socket,
erlang:setelement(3, erlang:element(2, Socket), Index + 1)
),
Hook,
Index};
{error, nil} ->
case erlang:element(4, erlang:element(2, Socket)) 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/socket"/utf8>>,
function => <<"fetch_or_init_hook"/utf8>>,
line => 82})
end,
Hook@1 = Init(),
{erlang:setelement(
2,
Socket,
{component_wip,
sprocket@internal@utils@ordered_map:insert(
erlang:element(2, erlang:element(2, Socket)),
Index,
Hook@1
),
Index + 1,
erlang:element(4, erlang:element(2, Socket))}
),
Hook@1,
Index}
end.
-spec update_hook(socket(), sprocket@hooks:hook(), integer()) -> socket().
update_hook(Socket, Hook, Index) ->
erlang:setelement(
2,
Socket,
erlang:setelement(
2,
erlang:element(2, Socket),
sprocket@internal@utils@ordered_map:update(
erlang:element(2, erlang:element(2, Socket)),
Index,
Hook
)
)
).
-spec push_event_handler(
socket(),
sprocket@internal@identifiable_callback:identifiable_callback()
) -> {socket(), sprocket@internal@utils@unique:unique()}.
push_event_handler(Socket, Identifiable_cb) ->
{identifiable_callback, Id, Cb} = Identifiable_cb,
{erlang:setelement(
3,
Socket,
[{event_handler, Id, Cb} | erlang:element(3, Socket)]
),
Id}.
-spec get_event_handler(socket(), sprocket@internal@utils@unique:unique()) -> {socket(),
{ok, event_handler()} | {error, nil}}.
get_event_handler(Socket, Id) ->
Handler = gleam@list:find(
erlang:element(3, Socket),
fun(H) ->
{event_handler, I, _} = H,
I =:= Id
end
),
{Socket, Handler}.