Current section
Files
Jump to
Current section
Files
src/chilp@widget@base.erl
-module(chilp@widget@base).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/chilp/widget/base.gleam").
-export([construct_new/3, new/3, show/2, trigger/2, init/1, force/2, update/3]).
-export_type([mastodon_post/0, comment_widget/1, chilp_data_in_your_model/1, chilp_model/0, chilp_msg/0]).
-if(?OTP_RELEASE >= 27).
-define(MODULEDOC(Str), -moduledoc(Str)).
-define(DOC(Str), -doc(Str)).
-else.
-define(MODULEDOC(Str), -compile([])).
-define(DOC(Str), -compile([])).
-endif.
?MODULEDOC(
" No-component widget\n"
" This is the Mastodon Widget except much more customisable. This version might also influence your application logic a bit much.\n"
" If you really want to customise, use this module, otherwise default to\n"
).
-opaque mastodon_post() :: {mastodon_post, binary(), binary()}.
-type comment_widget(RNW) :: {comment_widget,
mastodon_post(),
integer(),
boolean(),
{binary(), list(lustre@vdom@vattr:attribute(RNW))},
list(lustre@vdom@vattr:attribute(RNW)),
list(lustre@vdom@vattr:attribute(RNW)),
list(lustre@vdom@vattr:attribute(RNW)),
list(lustre@vdom@vattr:attribute(RNW)),
list(lustre@vdom@vattr:attribute(RNW)),
list(lustre@vdom@vattr:attribute(RNW)),
list(lustre@vdom@vattr:attribute(RNW)),
list(lustre@vdom@vattr:attribute(RNW)),
list(lustre@vdom@vattr:attribute(RNW)),
list(lustre@vdom@vattr:attribute(RNW)),
list(lustre@vdom@vattr:attribute(RNW)),
list(lustre@vdom@vattr:attribute(RNW)),
list(lustre@vdom@vattr:attribute(RNW)),
list(lustre@vdom@vattr:attribute(RNW)),
list(lustre@vdom@vattr:attribute(RNW)),
list(lustre@vdom@vattr:attribute(RNW)),
list(lustre@vdom@vattr:attribute(RNW)),
list(lustre@vdom@vattr:attribute(RNW)),
list(lustre@vdom@vattr:attribute(RNW)),
list(lustre@vdom@vattr:attribute(RNW)),
list(lustre@vdom@vattr:attribute(RNW)),
list(lustre@vdom@vattr:attribute(RNW)),
list(lustre@vdom@vattr:attribute(RNW)),
list(lustre@vdom@vattr:attribute(RNW)),
list(binary())}.
-opaque chilp_data_in_your_model(RNX) :: {chilp_data_in_your_model,
fun((chilp_msg()) -> RNX),
chilp_model()}.
-opaque chilp_model() :: {chilp_model,
gleam@dict:dict(mastodon_post(), chilp@api_typing:status()),
gleam@dict:dict(mastodon_post(), {chilp@api_typing:status_context(),
float()}),
gleam@dict:dict(mastodon_post(), gleam@option:option(binary()))}.
-opaque chilp_msg() :: {get, mastodon_post()} |
{save, chilp_model()} |
{go_answer, binary(), mastodon_post()}.
-file("src/chilp/widget/base.gleam", 44).
?DOC(false).
-spec construct_new(binary(), binary(), fun((chilp_msg()) -> ROB)) -> comment_widget(ROB).
construct_new(Instance, Postid, Message_wrap) ->
Instancelist = [Instance,
<<"mastodon.social"/utf8>>,
Instance,
<<"pony.social"/utf8>>,
Instance,
<<"todon.nl"/utf8>>,
Instance,
<<"mstdn.social"/utf8>>,
Instance],
Instanceplaceholder = begin
_pipe = Instancelist,
_pipe@1 = gleam@list:shuffle(_pipe),
_pipe@2 = gleam@list:first(_pipe@1),
gleam@result:unwrap(_pipe@2, <<"myinstance.social"/utf8>>)
end,
Post = {mastodon_post, Instance, Postid},
Set_message_get = begin
_pipe@3 = {get, Post},
Message_wrap(_pipe@3)
end,
Go_answer = fun(N) ->
Value = begin
_pipe@4 = gleam@list:key_find(N, <<"userinstance"/utf8>>),
gleam@result:unwrap(_pipe@4, Instanceplaceholder)
end,
_pipe@5 = {go_answer, Value, Post},
Message_wrap(_pipe@5)
end,
{comment_widget,
Post,
3,
true,
{<<"Comments"/utf8>>,
[lustre@attribute:classes([{<<"widget-header h1"/utf8>>, true}])]},
[lustre@attribute:classes([{<<"widget"/utf8>>, true}])],
[lustre@event:on_click(Set_message_get),
lustre@attribute:classes([{<<"btn-get-comments"/utf8>>, true}])],
[],
[],
[lustre@event:on_submit(Go_answer),
lustre@attribute:classes([{<<"go-reply-form"/utf8>>, true}])],
[lustre@attribute:class(<<"go-reply-label"/utf8>>),
lustre@attribute:for(<<"userinstance"/utf8>>)],
[lustre@attribute:type_(<<"text"/utf8>>),
lustre@attribute:placeholder(Instanceplaceholder),
lustre@attribute:name(<<"userinstance"/utf8>>),
lustre@attribute:classes([{<<"go-reply-form-input"/utf8>>, true}]),
lustre@attribute:pattern(
<<"^([a-z0-9]+(-[a-z0-9]+)*\\.)+[a-z]{2,}$"/utf8>>
),
lustre@attribute:required(true)],
[lustre@attribute:type_(<<"submit"/utf8>>),
lustre@attribute:classes([{<<"go-reply-form-button"/utf8>>, true}])],
[lustre@attribute:class(<<"comment"/utf8>>)],
[lustre@attribute:class(<<"comment comment-by-op"/utf8>>)],
[],
[],
[lustre@attribute:class(<<"avatar"/utf8>>),
lustre@attribute:alt(<<"@"/utf8>>)],
[lustre@attribute:class(<<"chilp-error"/utf8>>)],
[lustre@attribute:class(<<"meta"/utf8>>)],
[lustre@attribute:class(<<"display-name"/utf8>>)],
[],
[lustre@attribute:class(<<"content"/utf8>>)],
[],
[],
[lustre@attribute:classes([{<<"subheader"/utf8>>, true}])],
[lustre@attribute:classes([{<<"post-link"/utf8>>, true}])],
[lustre@attribute:classes([{<<"post-link"/utf8>>, true}])],
[lustre@attribute:class(<<"or-create-an-account-disclaimer"/utf8>>),
lustre@attribute:for(<<"userinstance"/utf8>>)],
Instancelist}.
-file("src/chilp/widget/base.gleam", 35).
?DOC(
" Creates a comment widget, this is where you should probably start!\n"
"\n"
" This function takes three arguments:\n"
" - `instance`: The instance name, e.g. mastodon.social\n"
" - `postid`: A post id to bind to, you'll find this in a post url `https://mastodon.social/@<username>/[postid]`.\n"
" - `messages`: Some messages that chilp needs to be able to send\n"
" The resulting comment widget can be edited however you'd like, but is\n"
).
-spec new(binary(), binary(), chilp_data_in_your_model(RNY)) -> comment_widget(RNY).
new(Instance, Postid, Model) ->
construct_new(Instance, Postid, erlang:element(2, Model)).
-file("src/chilp/widget/base.gleam", 387).
-spec sanitize(binary()) -> binary().
sanitize(Html) ->
Html.
-file("src/chilp/widget/base.gleam", 309).
-spec view_comment(
chilp@api_typing:status(),
boolean(),
comment_widget(ROO),
list(lustre@vdom@vnode:element(ROO))
) -> lustre@vdom@vnode:element(ROO).
view_comment(Comment, Is_authors, Attribs, Children) ->
lustre@element@html:article(case Is_authors of
true ->
erlang:element(15, Attribs);
_ ->
erlang:element(14, Attribs)
end, [lustre@element@html:header(
erlang:element(16, Attribs),
[lustre@element@html:img(
lists:append(
erlang:element(18, Attribs),
[lustre@attribute:src(
erlang:element(
15,
erlang:element(17, Comment)
)
)]
)
),
lustre@element@html:'div'(
erlang:element(20, Attribs),
[lustre@element@html:span(
erlang:element(21, Attribs),
[lustre@element:text(
erlang:element(
5,
erlang:element(17, Comment)
)
)]
),
lustre@element@html:time(
begin
_pipe = [lustre@attribute:attribute(
<<"datetime"/utf8>>,
erlang:element(3, Comment)
)],
lists:append(
_pipe,
erlang:element(22, Attribs)
)
end,
[lustre@element:text(
begin
B = begin
_pipe@4 = case begin
_pipe@2 = gleam@time@timestamp:difference(
begin
_pipe@1 = gleam@time@timestamp:parse_rfc3339(
erlang:element(
3,
Comment
)
),
gleam@result:unwrap(
_pipe@1,
gleam@time@timestamp:system_time(
)
)
end,
gleam@time@timestamp:system_time(
)
),
_pipe@3 = gleam@time@duration:approximate(
_pipe@2
),
gleam@pair:map_second(
_pipe@3,
fun(D) -> case D of
nanosecond ->
<<"nanosecond"/utf8>>;
microsecond ->
<<"microsecond"/utf8>>;
millisecond ->
<<"millisecond"/utf8>>;
second ->
<<"second"/utf8>>;
minute ->
<<"minute"/utf8>>;
hour ->
<<"hour"/utf8>>;
day ->
<<"day"/utf8>>;
week ->
<<"week"/utf8>>;
month ->
<<"month"/utf8>>;
year ->
<<"year"/utf8>>
end end
)
end of
{1, X} ->
{1, X};
{X@1, D@1} ->
{X@1,
<<D@1/binary,
"s"/utf8>>}
end,
gleam@pair:map_first(
_pipe@4,
fun erlang:integer_to_binary/1
)
end,
<<<<<<(erlang:element(1, B))/binary,
" "/utf8>>/binary,
(erlang:element(2, B))/binary>>/binary,
" ago."/utf8>>
end
)]
)]
)]
),
lustre@element@html:section(
erlang:element(23, Attribs),
[lustre@element:unsafe_raw_html(
<<""/utf8>>,
<<"span"/utf8>>,
[],
begin
_pipe@5 = erlang:element(16, Comment),
sanitize(_pipe@5)
end
)]
),
lustre@element@html:footer(
[],
[lustre@element@html:a(
begin
_pipe@6 = [lustre@attribute:href(
erlang:element(10, Comment)
)],
lists:append(_pipe@6, erlang:element(24, Attribs))
end,
[lustre@element:text(
<<"View comment on Mastodon"/utf8>>
)]
),
lustre@element@html:section(
erlang:element(9, Attribs),
Children
)]
)]).
-file("src/chilp/widget/base.gleam", 269).
-spec render_comment(
comment_widget(ROK),
binary(),
integer(),
chilp@api_typing:status(),
chilp@api_typing:status(),
list(chilp@api_typing:status())
) -> lustre@vdom@vnode:element(ROK).
render_comment(
Attribs,
Comm_id,
Recursion,
Parent,
Original_parent,
Descendants
) ->
Comm_result = gleam@list:find(
Descendants,
fun(Comm_) -> erlang:element(2, Comm_) =:= Comm_id end
),
case {Comm_result, Recursion =< erlang:element(3, Attribs)} of
{{ok, Comm}, true} when erlang:element(4, Comm) =:= erlang:element(
2,
Parent
) ->
Children = case erlang:element(11, Comm) =:= 0 of
true ->
[];
false ->
_pipe = gleam@list:filter(
Descendants,
fun(Comm_@1) ->
erlang:element(4, Comm_@1) =:= erlang:element(
2,
Comm
)
end
),
gleam@list:map(
_pipe,
fun(C) ->
render_comment(
Attribs,
erlang:element(2, C),
Recursion + 1,
Comm,
Original_parent,
Descendants
)
end
)
end,
view_comment(
Comm,
(erlang:element(2, erlang:element(17, Original_parent)) =:= erlang:element(
2,
erlang:element(17, Comm)
))
andalso (erlang:element(12, erlang:element(17, Comm)) =:= erlang:element(
12,
erlang:element(17, Parent)
)),
Attribs,
Children
);
{_, _} ->
lustre@element:none()
end.
-file("src/chilp/widget/base.gleam", 233).
-spec view_commentlist(
comment_widget(ROH),
chilp@api_typing:status(),
chilp@api_typing:status_context()
) -> lustre@vdom@vnode:element(ROH).
view_commentlist(Attributes, Status, Context) ->
Sorted_descendants = begin
_pipe = erlang:element(3, Context),
_pipe@1 = gleam@list:sort(
_pipe,
fun(A, B) ->
case {gleam@time@timestamp:parse_rfc3339(erlang:element(3, A)),
gleam@time@timestamp:parse_rfc3339(erlang:element(3, B))} of
{{ok, A@1}, {ok, B@1}} ->
gleam@time@timestamp:compare(A@1, B@1);
{_, _} ->
eq
end
end
),
gleam@list:sort(
_pipe@1,
fun(A@2, B@2) ->
gleam@int:compare(
erlang:element(13, A@2),
erlang:element(13, B@2)
)
end
)
end,
lustre@element@html:section(
erlang:element(8, Attributes),
gleam@list:map(
Sorted_descendants,
fun(Comm) ->
render_comment(
Attributes,
erlang:element(2, Comm),
1,
Status,
Status,
Sorted_descendants
)
end
)
).
-file("src/chilp/widget/base.gleam", 151).
?DOC(" This is what will show your comment block.\n").
-spec show(comment_widget(ROD), chilp_data_in_your_model(ROD)) -> lustre@vdom@vnode:element(ROD).
show(Attributes, Model) ->
Model@1 = erlang:element(3, Model),
lustre@element@html:'div'(
[lustre@attribute:class(<<"chilp-widget"/utf8>>)],
[lustre@element@html:'div'(
erlang:element(6, Attributes),
[lustre@element@html:h1(
erlang:element(2, erlang:element(5, Attributes)),
[lustre@element:text(
erlang:element(1, erlang:element(5, Attributes))
)]
),
case gleam_stdlib:map_get(
erlang:element(2, Model@1),
erlang:element(2, Attributes)
) of
{ok, Status} ->
lustre@element@html:p(
erlang:element(26, Attributes),
[lustre@element:text(<<"Linked to "/utf8>>),
lustre@element@html:a(
begin
_pipe = erlang:element(
27,
Attributes
),
lists:append(
_pipe,
[lustre@attribute:href(
erlang:element(
10,
Status
)
)]
)
end,
[lustre@element:text(
<<"this post"/utf8>>
)]
),
lustre@element:text(
<<" on Mastodon."/utf8>>
)]
);
{error, _} ->
lustre@element:none()
end,
lustre@element@html:form(
erlang:element(10, Attributes),
[lustre@element@html:'div'(
[lustre@attribute:class(<<"input-group"/utf8>>)],
[lustre@element@html:label(
erlang:element(11, Attributes),
[lustre@element@html:text(
<<"Enter your instance adress to reply or "/utf8>>
),
lustre@element@html:a(
begin
_pipe@4 = [lustre@attribute:href(
<<<<"https://"/utf8,
(begin
_pipe@1 = erlang:element(
30,
Attributes
),
_pipe@2 = gleam@list:shuffle(
_pipe@1
),
_pipe@3 = gleam@list:first(
_pipe@2
),
gleam@result:unwrap(
_pipe@3,
erlang:element(
2,
erlang:element(
2,
Attributes
)
)
)
end)/binary>>/binary,
"/auth/sign_up"/utf8>>
)],
lists:append(
_pipe@4,
erlang:element(
28,
Attributes
)
)
end,
[lustre@element:text(
<<"create an account"/utf8>>
)]
),
lustre@element:text(<<"!"/utf8>>)]
),
lustre@element@html:p(
erlang:element(29, Attributes),
[lustre@element:text(
<<"on an instance reccommended by this site... or one you pick yourself!"/utf8>>
)]
),
lustre@element@html:'div'(
[lustre@attribute:class(
<<"form-controls"/utf8>>
)],
[lustre@element@html:input(
erlang:element(12, Attributes)
),
lustre@element@html:button(
erlang:element(13, Attributes),
[lustre@element:text(
<<"Go reply"/utf8>>
)]
)]
)]
)]
),
case {gleam_stdlib:map_get(
erlang:element(4, Model@1),
erlang:element(2, Attributes)
),
gleam_stdlib:map_get(
erlang:element(2, Model@1),
erlang:element(2, Attributes)
),
gleam_stdlib:map_get(
erlang:element(3, Model@1),
erlang:element(2, Attributes)
)} of
{_, {ok, Status@1}, {ok, Context}} ->
view_commentlist(
Attributes,
Status@1,
erlang:element(1, Context)
);
{{ok, none}, {error, _}, _} ->
lustre@element@html:span(
erlang:element(17, Attributes),
[lustre@element:text(
<<"Loading comments..."/utf8>>
)]
);
{{ok, none}, _, {error, _}} ->
lustre@element@html:span(
erlang:element(17, Attributes),
[lustre@element:text(
<<"Loading comments..."/utf8>>
)]
);
{{ok, {some, Errorvalue}}, {error, _}, _} when erlang:element(
4,
Attributes
) =:= true ->
lustre@element@html:pre(
erlang:element(19, Attributes),
[lustre@element:text(Errorvalue)]
);
{{ok, {some, Errorvalue}}, _, {error, _}} when erlang:element(
4,
Attributes
) =:= true ->
lustre@element@html:pre(
erlang:element(19, Attributes),
[lustre@element:text(Errorvalue)]
);
{_, _, _} ->
lustre@element@html:button(
erlang:element(7, Attributes),
[lustre@element:text(<<"Load comments"/utf8>>)]
)
end]
)]
).
-file("src/chilp/widget/base.gleam", 442).
?DOC(
" Trigger forces the widget to load in data before the user clicked the button.\n"
" This is something you'll want if you know beforehand which post comments to display.\n"
).
-spec trigger(comment_widget(ROT), chilp_data_in_your_model(ROT)) -> ROT.
trigger(On, Model) ->
(erlang:element(2, Model))({get, erlang:element(2, On)}).
-file("src/chilp/widget/base.gleam", 473).
-spec init(fun((chilp_msg()) -> RPA)) -> chilp_data_in_your_model(RPA).
init(Message) ->
{chilp_data_in_your_model,
Message,
{chilp_model, maps:new(), maps:new(), maps:new()}}.
-file("src/chilp/widget/base.gleam", 512).
-spec get_post(mastodon_post(), fun((chilp_model()) -> RPF)) -> lustre@effect:effect(RPF).
get_post(Post, Message) ->
Url = <<<<<<"https://"/utf8, (erlang:element(2, Post))/binary>>/binary,
"/api/v1/statuses/"/utf8>>/binary,
(erlang:element(3, Post))/binary>>,
Handle_response = fun(S) -> _pipe = case S of
{ok, Status} ->
{chilp_model,
maps:from_list([{Post, Status}]),
maps:new(),
maps:new()};
{error, E} ->
{chilp_model,
maps:new(),
maps:new(),
maps:from_list(
[{Post,
{some,
<<<<(gleam@string:inspect(E))/binary,
"\n\nWhile looking at: "/utf8>>/binary,
Url/binary>>}}]
)}
end,
Message(_pipe) end,
Handler = rsvp:expect_json(
chilp@api_typing:status_decoder(),
Handle_response
),
rsvp:get(Url, Handler).
-file("src/chilp/widget/base.gleam", 544).
-spec get_context(mastodon_post(), fun((chilp_model()) -> RPH)) -> lustre@effect:effect(RPH).
get_context(Post, Message) ->
Url = <<<<<<<<"https://"/utf8, (erlang:element(2, Post))/binary>>/binary,
"/api/v1/statuses/"/utf8>>/binary,
(erlang:element(3, Post))/binary>>/binary,
"/context"/utf8>>,
Handle_response = fun(C) -> _pipe@1 = case C of
{ok, Context} ->
Now = begin
_pipe = gleam@time@timestamp:system_time(),
gleam@time@timestamp:to_unix_seconds(_pipe)
end,
{chilp_model,
maps:new(),
maps:from_list([{Post, {Context, Now}}]),
maps:new()};
{error, E} ->
{chilp_model,
maps:new(),
maps:new(),
maps:from_list(
[{Post,
{some,
<<<<<<(gleam@string:inspect(E))/binary,
"\n\nWhile looking at: "/utf8>>/binary,
Url/binary>>/binary,
"\n\nWant to report this? File an issue "/utf8>>}}]
)}
end,
Message(_pipe@1) end,
Handler = rsvp:expect_json(
chilp@api_typing:status_context_decoder(),
Handle_response
),
rsvp:get(Url, Handler).
-file("src/chilp/widget/base.gleam", 488).
?DOC(" Gets all the metadata to work with in order to show your comments!\n").
-spec get(mastodon_post(), chilp_data_in_your_model(RPC)) -> lustre@effect:effect(RPC).
get(Post, Data) ->
Handles = fun(M) -> (erlang:element(2, Data))({save, M}) end,
Notify = fun() ->
lustre@effect:from(
fun(Dispatch) ->
Dispatch(
Handles(
{chilp_model,
maps:new(),
maps:new(),
maps:from_list([{Post, none}])}
)
)
end
)
end,
lustre@effect:batch(
[Notify(), get_post(Post, Handles), get_context(Post, Handles)]
).
-file("src/chilp/widget/base.gleam", 451).
?DOC(
" Force is like `trigger`, except returns the Effect instead of the message, allowing you to embed it in your init or update function instead of in your view.\n"
" This is something you'll want if you know beforehand which post comments to display.\n"
).
-spec force(comment_widget(ROW), chilp_data_in_your_model(ROW)) -> lustre@effect:effect(ROW).
force(On, Model) ->
get(erlang:element(2, On), Model).
-file("src/chilp/widget/base.gleam", 639).
-spec uncloth(chilp_model()) -> {list({mastodon_post(),
chilp@api_typing:status()}),
list({mastodon_post(), {chilp@api_typing:status_context(), float()}})}.
uncloth(M) ->
case M of
{chilp_model, Stati, Context, _} ->
{maps:to_list(Stati), maps:to_list(Context)}
end.
-file("src/chilp/widget/base.gleam", 595).
?DOC(
" The update handler for chilp-specific messages!\n"
"\n"
" It takes in three values:\n"
" - `message`: The message it handles\n"
" - `model`: the chilp data from your model\n"
" - `change_url`: A side-effect! This may not ever be called, but when it does, know that it should take that string, and browse the user to it.\n"
).
-spec update(
chilp_msg(),
chilp_data_in_your_model(RPJ),
fun((binary()) -> lustre@effect:effect(RPJ))
) -> {chilp_data_in_your_model(RPJ), lustre@effect:effect(RPJ)}.
update(Message, Model, Change_url) ->
case Message of
{get, Post} ->
{Model, get(Post, Model)};
{save, Addedmodel} ->
{O_stati, O_context} = uncloth(erlang:element(3, Model)),
{N_stati, N_context} = uncloth(Addedmodel),
Stati = begin
_pipe = lists:append(O_stati, N_stati),
maps:from_list(_pipe)
end,
Context = begin
_pipe@1 = lists:append(O_context, N_context),
maps:from_list(_pipe@1)
end,
Busy = gleam@dict:combine(
erlang:element(4, Addedmodel),
erlang:element(4, erlang:element(3, Model)),
fun gleam@option:'or'/2
),
{{chilp_data_in_your_model,
erlang:element(2, Model),
{chilp_model, Stati, Context, Busy}},
lustre@effect:none()};
{go_answer, Instance, To} ->
S = gleam_stdlib:map_get(
erlang:element(2, erlang:element(3, Model)),
To
),
case S of
{ok, Post@1} ->
Change_url(
(<<<<<<"https://"/utf8, Instance/binary>>/binary,
"/authorize_interaction?uri="/utf8>>/binary,
(begin
_pipe@2 = erlang:element(10, Post@1),
gleam_stdlib:percent_encode(_pipe@2)
end)/binary>>)
),
{Model, lustre@effect:none()};
{error, _} ->
{Model, lustre@effect:none()}
end
end.