This repository has been archived by the owner on Oct 30, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1
/
arizona_live_view.erl
100 lines (84 loc) · 3.4 KB
/
arizona_live_view.erl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
%% @author William Fank Thomé <[email protected]>
%% @copyright 2023 William Fank Thomé
%% @doc LiveView.
%% Copyright 2023 William Fank Thomé
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
%% You may obtain a copy of the License at
%%
%% http://www.apache.org/licenses/LICENSE-2.0
%%
%% Unless required by applicable law or agreed to in writing, software
%% distributed under the License is distributed on an "AS IS" BASIS,
%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%% See the License for the specific language governing permissions and
%% limitations under the License.
-module(arizona_live_view).
%% API
-export([ init/4, mount/3, render/2, handle_event/4 ]).
%% Types
-export_type([ bindings/0, render_state/0 ]).
-type bindings() :: arizona_template_adapter:bindings().
-type render_state() :: arizona_template_adapter:state().
-type event() :: binary().
-type payload() :: map().
-type params() :: arizona_server_adapter:params().
-type socket() :: arizona_socket:t().
%% Callbacks
-optional_callbacks([ mount/2, handle_event/3 ]).
-callback mount(Params, Socket) -> {ok, Socket}
when Params :: params()
, Socket :: socket()
.
-callback render(Bindings) -> {Bindings, RenderState}
when Bindings :: bindings()
, RenderState :: render_state()
.
-callback handle_event(Event, Payload, Socket) -> {ok, Socket}
when Event :: event()
, Payload :: payload()
, Socket :: socket()
.
%%%=====================================================================
%%% API
%%%=====================================================================
init(View, #{template := Template}, Params, Socket) ->
init_template(Template, View, Params, Socket);
init(View, _Opts, Params, Socket) ->
init_view(View, Params, Socket).
mount(View, Params, Socket) ->
io:format("[LiveView] ~w: ~p~n", [View, [mount, Params]]),
case erlang:function_exported(View, mount, 2) of
true ->
View:mount(Params, Socket);
false ->
{ok, Socket}
end.
render(View, Socket0) ->
Socket = arizona_socket:bind(self, View, Socket0),
Bindings = arizona_socket:get_bindings(Socket),
io:format("[LiveView] ~w: ~p~n", [View, [render, Bindings]]),
View:render(Bindings).
handle_event(View, Event, Payload, Socket) ->
io:format("[LiveView] ~w: ~p~n", [View, [event, Event, Payload]]),
View:handle_event(Event, Payload, Socket).
%%%=====================================================================
%%% Internal functions
%%%=====================================================================
init_view(View, Params, Socket0) ->
{ok, Socket} = mount(View, Params, Socket0),
RenderState = render(View, Socket),
arizona_socket:set_render_state(RenderState, Socket).
init_template(Template, View, Params, Socket0) ->
Socket1 = arizona_socket:bind(parent, Template, Socket0),
Socket2 = init_view(View, Params, Socket1),
ViewRenderState = arizona_socket:get_render_state(Socket2),
InnerContent = arizona_template:render(ViewRenderState),
{ok, Socket3} = mount(Template, Params, Socket2),
Socket = arizona_socket:bind(#{
view => View,
inner_content => InnerContent
}, Socket3),
RenderState = render(Template, Socket),
arizona_socket:set_render_state(RenderState, Socket).