-module(illustrious@client). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). -export([perform/1, go_to/1, redirect/1, forward/0, back/0, build_app/1]). -export_type([client_app_builder/3]). -type client_app_builder(OPC, OPD, OPE) :: {client_app_builder, fun((list(binary()), OPD) -> lustre@internals@vdom:element(illustrious@state:illustrious_action(OPE))), OPD, fun((OPD, OPE) -> {OPD, lustre@effect:effect(illustrious@state:illustrious_action(OPE))}), fun((gleam@dynamic:dynamic_()) -> {ok, illustrious@state:illustrious_action(OPE)} | {error, list(gleam@dynamic:decode_error())})} | {gleam_phantom, OPC}. -spec perform(OPF) -> illustrious@state:illustrious_action(OPF). perform(Action) -> {perform, Action}. -spec go_to(binary()) -> illustrious@state:illustrious_action(any()). go_to(Route) -> {go_to, Route}. -spec redirect(binary()) -> illustrious@state:illustrious_action(any()). redirect(Route) -> {redirect, Route}. -spec forward() -> illustrious@state:illustrious_action(any()). forward() -> forward. -spec back() -> illustrious@state:illustrious_action(any()). back() -> back. -spec listen_for_navigation() -> lustre@effect:effect(illustrious@state:illustrious_action(any())). listen_for_navigation() -> lustre@effect:from( fun(Handler) -> illustrious@internal@router:register_callback( fun(Split_path) -> Handler({set_path, Split_path}) end ) end ). -spec build_app(client_app_builder(any(), OPN, OPO)) -> lustre:app(any(), illustrious@state:illustrious_model(OPN), illustrious@state:illustrious_action(OPO)). build_app(Builder) -> Decoder = illustrious@internal@state_priv:wrap_decoder( erlang:element(5, Builder) ), Updater = illustrious@internal@state_priv:wrap_updater( erlang:element(4, Builder), erlang:element(5, Builder) ), New_init = fun(_) -> Split_path = illustrious@internal@router:get_current_path(), Model = {illustrious_model, Split_path, erlang:element(3, Builder)}, Data = case illustrious@internal@api_helpers:get_baked_data() of {ok, Json} -> Decoder(Json); {error, _} -> noop end, Updated_model = Updater(Model, Data), {erlang:element(1, Updated_model), lustre@effect:batch( [erlang:element(2, Updated_model), listen_for_navigation()] )} end, New_view = fun(Illustrious_model) -> (erlang:element(2, Builder))( erlang:element(2, Illustrious_model), erlang:element(3, Illustrious_model) ) end, lustre:application(New_init, Updater, New_view).