Current section

Files

Jump to
chilp src chilp@widget.erl
Raw

src/chilp@widget.erl

-module(chilp@widget).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/chilp/widget.gleam").
-export([element/2, register/0]).
-export_type([model/0, msg/0, bsky_thread_view/0, bsky_thread_reply/0, mastodon_status_context/0, mastodon_descendant/0, coalesced_view/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.
-type model() :: {model,
gleam@option:option(chilp@widget@anchors:mastodon()),
list(mastodon_descendant()),
{binary(), binary()},
gleam@option:option(chilp@widget@anchors:bluesky()),
list(bsky_thread_reply()),
binary(),
gleam@option:option(binary()),
list(coalesced_view()),
integer()}.
-type msg() :: mastodon_un_anchored |
{mastodon_anchored, binary(), binary()} |
bsky_un_anchored |
{bsky_anchored, binary(), binary()} |
{all_stopping_error, binary()} |
{bsky_incoming_thread_view, bsky_thread_view()} |
{incoming_coalesced_view, list(coalesced_view())} |
{mastodon_incoming_status, mastodon_status_context()} |
{mastodon_incoming_op_username, {binary(), binary()}} |
{set_tab, integer()} |
{mastodon_answer, binary()} |
mastodon_error_fetching_op_username_retry_for_misskey.
-type bsky_thread_view() :: {bsky_thread_view,
binary(),
list(bsky_thread_reply())}.
-type bsky_thread_reply() :: {bsky_thread_reply,
binary(),
integer(),
gleam@time@timestamp:timestamp(),
binary(),
binary(),
binary(),
binary(),
binary(),
list(bsky_thread_reply())}.
-type mastodon_status_context() :: {mastodon_status_context,
list(mastodon_descendant())}.
-type mastodon_descendant() :: {mastodon_descendant,
binary(),
binary(),
lustre@vdom@vnode:element(msg()),
gleam@time@timestamp:timestamp(),
integer(),
list(mastodon_descendant()),
binary(),
binary(),
binary(),
binary()}.
-type coalesced_view() :: {coalesced_view,
gleam@time@timestamp:timestamp(),
binary(),
binary(),
binary(),
binary(),
binary(),
lustre@vdom@vnode:element(msg()),
binary(),
integer(),
list(coalesced_view())}.
-file("src/chilp/widget.gleam", 52).
-spec element(
gleam@option:option(chilp@widget@anchors:mastodon()),
gleam@option:option(chilp@widget@anchors:bluesky())
) -> lustre@vdom@vnode:element(any()).
element(Mastodon_anchor, Bsky_anchor) ->
lustre@element:element(
<<"comment-widget"/utf8>>,
[lustre@attribute:attribute(
<<"mastodon-anchor"/utf8>>,
case Mastodon_anchor of
{some, Anchor} ->
<<<<(erlang:element(2, Anchor))/binary, "\\"/utf8>>/binary,
(erlang:element(3, Anchor))/binary>>;
none ->
<<""/utf8>>
end
),
lustre@attribute:attribute(
<<"bluesky-anchor"/utf8>>,
case Bsky_anchor of
{some, Anchor@1} ->
<<<<(erlang:element(2, Anchor@1))/binary, "\\"/utf8>>/binary,
(erlang:element(3, Anchor@1))/binary>>;
none ->
<<""/utf8>>
end
)],
[]
).
-file("src/chilp/widget.gleam", 91).
-spec init(any()) -> {model(), lustre@effect:effect(msg())}.
init(_) ->
{{model,
none,
[],
{<<""/utf8>>, <<""/utf8>>},
none,
[],
<<""/utf8>>,
none,
[],
begin
_pipe = [1, 2],
_pipe@1 = gleam@list:shuffle(_pipe),
_pipe@2 = gleam@list:first(_pipe@1),
gleam@result:unwrap(_pipe@2, 1)
end},
lustre@effect:none()}.
-file("src/chilp/widget.gleam", 660).
-spec view_about_chilp() -> lustre@vdom@vnode:element(msg()).
view_about_chilp() ->
lustre@element@html:'div'(
[lustre@attribute:class(<<"my-5 px-5 pb-5 "/utf8>>)],
[lustre@element@html:p(
[],
[lustre@element:text(
<<"This widget is powered by Chilp! 💬 By MLC Bloeiman"/utf8>>
)]
),
lustre@element@html:p(
[],
[lustre@element:text(<<"Want to read "/utf8>>),
lustre@element@html:a(
[lustre@attribute:href(
<<"https://strawmelonjuice.com/post/chilpv2"/utf8>>
),
lustre@attribute:class(
<<"link link-primary-content"/utf8>>
)],
[lustre@element:text(<<"more about Chilp"/utf8>>)]
),
lustre@element:text(<<" on "/utf8>>),
lustre@element@html:img(
[lustre@attribute:src(
<<"https://strawmelonjuice.com/strawmelonjuice.svg"/utf8>>
),
lustre@attribute:width(34),
lustre@attribute:class(
<<"inline bg-white/65 rounded-lg"/utf8>>
)]
),
lustre@element:text(<<" strawmelonjuice.com?"/utf8>>)]
)]
).
-file("src/chilp/widget.gleam", 687).
-spec view_respond_on_bsky(binary()) -> lustre@vdom@vnode:element(msg()).
view_respond_on_bsky(Bskylink) ->
Icon_link = fun(Label, New_base, Color_class) ->
lustre@element@html:a(
[lustre@attribute:href(
gleam@string:replace(
Bskylink,
<<"bsky.app"/utf8>>,
New_base
)
),
lustre@attribute:target(<<"_blank"/utf8>>),
lustre@attribute:class(
<<"btn btn-circle btn-sm btn-ghost tooltip "/utf8,
Color_class/binary>>
),
lustre@attribute:attribute(<<"data-tip"/utf8>>, Label)],
[lustre@element:text(gleam@string:slice(Label, 0, 1))]
)
end,
lustre@element@html:'div'(
[lustre@attribute:class(<<"my-5 px-5 pb-5 "/utf8>>)],
[lustre@element:text(
<<"Respond to this post on Bluesky to have it show up here!"/utf8>>
),
lustre@element@html:'div'(
[lustre@attribute:class(<<"flex gap-2 items-center"/utf8>>)],
[lustre@element@html:span(
[lustre@attribute:class(
<<"text-xs mr-2 opacity-50"/utf8>>
)],
[lustre@element:text(<<"Open in:"/utf8>>)]
),
Icon_link(
<<"Bluesky"/utf8>>,
<<"bsky.app"/utf8>>,
<<"text-[#006aff] bg-white"/utf8>>
),
Icon_link(
<<"Blacksky"/utf8>>,
<<"blacksky.community"/utf8>>,
<<"text-white bg-black"/utf8>>
),
Icon_link(
<<"Witchsky"/utf8>>,
<<"witchsky.app"/utf8>>,
<<"bg-[#ed5345] text-white"/utf8>>
)]
)]
).
-file("src/chilp/widget.gleam", 809).
-spec error_view(binary()) -> lustre@vdom@vnode:element(any()).
error_view(Error) ->
lustre@element@html:'div'(
[lustre@attribute:class(<<"alert alert-error"/utf8>>),
lustre@attribute:role(<<"alert"/utf8>>)],
[lustre@element@svg:svg(
[lustre@attribute:attribute(
<<"viewBox"/utf8>>,
<<"0 0 24 24"/utf8>>
),
lustre@attribute:attribute(<<"fill"/utf8>>, <<"none"/utf8>>),
lustre@attribute:class(
<<"h-6 w-6 shrink-0 stroke-current"/utf8>>
),
lustre@attribute:attribute(
<<"xmlns"/utf8>>,
<<"http://www.w3.org/2000/svg"/utf8>>
)],
[lustre@element@svg:path(
[lustre@attribute:attribute(
<<"d"/utf8>>,
<<"M10 14l2-2m0 0l2-2m-2 2l-2-2m2 2l2 2m7-2a9 9 0 11-18 0 9 9 0 0118 0z"/utf8>>
),
lustre@attribute:attribute(
<<"stroke-width"/utf8>>,
<<"2"/utf8>>
),
lustre@attribute:attribute(
<<"stroke-linejoin"/utf8>>,
<<"round"/utf8>>
),
lustre@attribute:attribute(
<<"stroke-linecap"/utf8>>,
<<"round"/utf8>>
)]
)]
),
lustre@element@html:span(
[],
[lustre@element@html:text(
<<"AN ERROR OCCURED:"/utf8, Error/binary>>
)]
)]
).
-file("src/chilp/widget.gleam", 882).
-spec get_username_mastodon(model()) -> lustre@effect:effect(msg()).
get_username_mastodon(Model) ->
case erlang:element(2, Model) of
{some, Anchor} ->
Url = <<<<<<"https://"/utf8, (erlang:element(2, Anchor))/binary>>/binary,
"/api/v1/statuses/"/utf8>>/binary,
(erlang:element(3, Anchor))/binary>>,
Handler = rsvp:expect_json(
begin
gleam@dynamic@decode:subfield(
[<<"account"/utf8>>, <<"username"/utf8>>],
{decoder, fun gleam@dynamic@decode:decode_string/1},
fun(User) -> gleam@dynamic@decode:success(User) end
)
end,
fun(Response) -> case Response of
{ok, Username} ->
{mastodon_incoming_op_username,
{Username,
<<<<<<<<<<"https://"/utf8,
(erlang:element(
2,
Anchor
))/binary>>/binary,
"/@"/utf8>>/binary,
Username/binary>>/binary,
"/"/utf8>>/binary,
(erlang:element(3, Anchor))/binary>>}};
{error, Rsvperror} ->
case Rsvperror of
{unhandled_response, _} ->
{all_stopping_error,
<<"The response body we got back from Mastodon was misformed."/utf8>>};
{json_error, _} ->
{all_stopping_error,
<<"The response body we got back from Mastodon was misformed."/utf8>>};
bad_body ->
{all_stopping_error,
<<"The response body we got back from Mastodon was misformed."/utf8>>};
{bad_url, _} ->
{all_stopping_error,
<<"The API call to Mastodon failed. Did you enter the instance and post id correctly?"/utf8>>};
{http_error, _} ->
mastodon_error_fetching_op_username_retry_for_misskey;
network_error ->
{all_stopping_error,
<<"Could not fetch comments from Mastodon. (NetworkError)"/utf8>>}
end
end end
),
rsvp:get(Url, Handler);
none ->
lustre@effect:none()
end.
-file("src/chilp/widget.gleam", 935).
-spec get_username_miskey(model()) -> lustre@effect:effect(msg()).
get_username_miskey(Model) ->
case erlang:element(2, Model) of
{some, Anchor} ->
Url = <<<<"https://"/utf8, (erlang:element(2, Anchor))/binary>>/binary,
"/api/notes/show"/utf8>>,
Handler = rsvp:expect_json(
begin
gleam@dynamic@decode:subfield(
[<<"user"/utf8>>, <<"username"/utf8>>],
{decoder, fun gleam@dynamic@decode:decode_string/1},
fun(User) -> gleam@dynamic@decode:success(User) end
)
end,
fun(Response) -> case Response of
{ok, Username} ->
{mastodon_incoming_op_username,
{Username,
<<<<<<"https://"/utf8,
(erlang:element(2, Anchor))/binary>>/binary,
"/notes/"/utf8>>/binary,
(erlang:element(3, Anchor))/binary>>}};
{error, Rsvperror} ->
case Rsvperror of
{unhandled_response, _} ->
{all_stopping_error,
<<"The response body we got back from Misskey/Sharkey was misformed."/utf8>>};
{json_error, _} ->
{all_stopping_error,
<<"The response body we got back from Misskey/Sharkey was misformed."/utf8>>};
bad_body ->
{all_stopping_error,
<<"The response body we got back from Misskey/Sharkey was misformed."/utf8>>};
{bad_url, _} ->
{all_stopping_error,
<<"The API call to Misskey/Sharkey failed. Did you enter the instance and post id correctly?"/utf8>>};
{http_error, _} ->
{all_stopping_error,
<<"Could not fetch comments from Mastodon/Misskey/Sharkey. (HttpError)"/utf8>>};
network_error ->
{all_stopping_error,
<<"Could not fetch comments from Misskey/Sharkey. (NetworkError)"/utf8>>}
end
end end
),
rsvp:post(
Url,
gleam@json:object(
[{<<"noteId"/utf8>>,
gleam@json:string(erlang:element(3, Anchor))}]
),
Handler
);
none ->
lustre@effect:none()
end.
-file("src/chilp/widget.gleam", 1040).
-spec sanitise_reconstruct_ls(html_parser:element()) -> lustre@vdom@vnode:element(any()).
sanitise_reconstruct_ls(El) ->
case El of
empty_element ->
lustre@element:none();
{start_element, Name, Attributes, Children} ->
Attribs = gleam@list:map(Attributes, fun(Attrib) -> case Attrib of
{attribute, <<"href"/utf8>>, Link} ->
lustre@attribute:href(Link);
{attribute, <<"class"/utf8>>, Classes} ->
lustre@attribute:class(Classes);
{attribute, <<"target"/utf8>>, Target} ->
lustre@attribute:target(Target);
{attribute, _, _} ->
lustre@attribute:none()
end end),
_pipe@1 = [begin
_pipe = gleam@list:map(
Children,
fun sanitise_reconstruct_ls/1
),
case Name of
<<"b"/utf8>> ->
fun(_capture) ->
lustre@element@html:b(Attribs, _capture)
end;
<<"i"/utf8>> ->
fun(_capture@1) ->
lustre@element@html:i(Attribs, _capture@1)
end;
<<"em"/utf8>> ->
fun(_capture@2) ->
lustre@element@html:em(Attribs, _capture@2)
end;
<<"strong"/utf8>> ->
fun(_capture@3) ->
lustre@element@html:strong(Attribs, _capture@3)
end;
<<"a"/utf8>> ->
fun(_capture@4) ->
lustre@element@html:a(
[lustre@attribute:class(
<<"link link-secondary-content"/utf8>>
) |
Attribs],
_capture@4
)
end;
<<"p"/utf8>> ->
fun(_capture@5) ->
lustre@element@html:p(Attribs, _capture@5)
end;
<<"br"/utf8>> ->
fun(_) -> lustre@element@html:br(Attribs) end;
<<"span"/utf8>> ->
fun(_capture@6) ->
lustre@element@html:span(Attribs, _capture@6)
end;
_ ->
fun lustre@element:fragment/1
end(_pipe)
end,
lustre@element:text(<<" "/utf8>>)],
lustre@element:fragment(_pipe@1);
{end_element, _} ->
lustre@element:text(
<<"ERROR: Did not expect an element end here!"/utf8>>
);
{content, Cnt} ->
lustre@element:text(Cnt)
end.
-file("src/chilp/widget.gleam", 1033).
?DOC(" Attempts to do what DOMpurify does... ...while lustre-ifying it!\n").
-spec sanitise_ls(binary()) -> lustre@vdom@vnode:element(any()).
sanitise_ls(Html) ->
_pipe = html_parser:as_tree(Html),
sanitise_reconstruct_ls(_pipe).
-file("src/chilp/widget.gleam", 1085).
-spec sort_comments(coalesced_view(), coalesced_view()) -> gleam@order:order().
sort_comments(C1, C2) ->
case gleam@int:compare(erlang:element(10, C1), erlang:element(10, C2)) of
eq ->
gleam@time@timestamp:compare(
erlang:element(2, C1),
erlang:element(2, C2)
);
Measure ->
Measure
end.
-file("src/chilp/widget.gleam", 452).
-spec view_rendered_comment(
coalesced_view(),
gleam@option:option(binary()),
gleam@option:option(binary())
) -> lustre@vdom@vnode:element(msg()).
view_rendered_comment(Comment, Bsky_op_profile, Mastodon_op_profile) ->
Is_by_op = (case {erlang:element(6, Comment),
Bsky_op_profile,
Mastodon_op_profile} of
{<<"Mastodon"/utf8>>, _, {some, Op}} ->
Op =:= erlang:element(3, Comment);
{<<"Bluesky"/utf8>>, {some, Op@1}, _} ->
begin
_pipe = Op@1,
_pipe@1 = gleam@string:replace(
_pipe,
<<"https://bsky.app"/utf8>>,
<<""/utf8>>
),
gleam@string:replace(
_pipe@1,
<<"https://bluesky.app"/utf8>>,
<<""/utf8>>
)
end
=:= begin
_pipe@2 = erlang:element(3, Comment),
_pipe@3 = gleam@string:replace(
_pipe@2,
<<"https://bsky.app"/utf8>>,
<<""/utf8>>
),
gleam@string:replace(
_pipe@3,
<<"https://bluesky.app"/utf8>>,
<<""/utf8>>
)
end;
{_, _, _} ->
false
end),
Commands = gleam@list:filter_map(
erlang:element(11, Comment),
fun(Child) ->
case (case {erlang:element(6, Comment),
Bsky_op_profile,
Mastodon_op_profile} of
{<<"Mastodon"/utf8>>, _, {some, Op@2}} ->
Op@2 =:= erlang:element(3, Child);
{<<"Bluesky"/utf8>>, {some, Op@3}, _} ->
begin
_pipe@4 = Op@3,
_pipe@5 = gleam@string:replace(
_pipe@4,
<<"https://bsky.app"/utf8>>,
<<""/utf8>>
),
gleam@string:replace(
_pipe@5,
<<"https://bluesky.app"/utf8>>,
<<""/utf8>>
)
end
=:= begin
_pipe@6 = erlang:element(3, Child),
_pipe@7 = gleam@string:replace(
_pipe@6,
<<"https://bsky.app"/utf8>>,
<<""/utf8>>
),
gleam@string:replace(
_pipe@7,
<<"https://bluesky.app"/utf8>>,
<<""/utf8>>
)
end;
{_, _, _} ->
false
end) of
false ->
{error, nil};
true ->
Content = begin
_pipe@8 = lustre@element:to_readable_string(
erlang:element(8, Child)
),
string:lowercase(_pipe@8)
end,
case gleam_stdlib:string_starts_with(
Content,
<<"-chilp "/utf8>>
) of
true ->
{ok, Content};
false ->
{error, nil}
end
end
end
),
Is_hidden = gleam@list:any(
Commands,
fun(_capture) ->
gleam_stdlib:string_starts_with(_capture, <<"-chilp hide"/utf8>>)
end
),
Is_silenced = gleam@list:any(
Commands,
fun(_capture@1) ->
gleam_stdlib:string_starts_with(
_capture@1,
<<"-chilp silence"/utf8>>
)
end
),
Is_command = (gleam_stdlib:string_starts_with(
begin
_pipe@9 = lustre@element:to_readable_string(
erlang:element(8, Comment)
),
string:lowercase(_pipe@9)
end,
<<"-chilp "/utf8>>
)),
gleam@bool:guard(
Is_hidden,
lustre@element:none(),
fun() ->
gleam@bool:guard(
Is_command,
lustre@element:none(),
fun() ->
lustre@element@html:article(
[lustre@attribute:class(<<"comment mt-2"/utf8>>)],
[lustre@element@html:header(
[lustre@attribute:class(<<"flex"/utf8>>)],
[lustre@element@html:img(
[lustre@attribute:src(
erlang:element(4, Comment)
),
lustre@attribute:class(
<<"avatar w-[45px] h-[45px] mask mask-squircle flex-none"/utf8>>
),
lustre@attribute:alt(<<"@"/utf8>>)]
),
lustre@element@html:'div'(
[lustre@attribute:class(
<<"meta pl-4 max-h-[45px]"/utf8>>
)],
[lustre@element@html:span(
[lustre@attribute:class(
<<"display-name"/utf8>>
)],
[lustre@element@html:text(
erlang:element(
7,
Comment
)
),
case erlang:element(
6,
Comment
) of
<<"Mastodon"/utf8>> ->
lustre@element@html:'div'(
[lustre@attribute:class(
<<"badge badge-sm badge-info ms-2 bg-[#595aff] text-white"/utf8>>
)],
[lustre@element:text(
<<"Fediverse"/utf8>>
)]
);
<<"Bluesky"/utf8>> ->
lustre@element@html:'div'(
[lustre@attribute:class(
<<"badge badge-sm badge-info ms-2 bg-[#006aff] text-white"/utf8>>
)],
[lustre@element:text(
<<"Bluesky"/utf8>>
)]
);
_ ->
lustre@element:none(
)
end,
case Is_by_op of
true ->
lustre@element@html:'div'(
[lustre@attribute:class(
<<"badge badge-sm badge-accent ms-2"/utf8>>
)],
[lustre@element:text(
<<"Author"/utf8>>
)]
);
false ->
lustre@element:none(
)
end]
),
lustre@element@html:p(
[lustre@attribute:class(
<<"text-xs"/utf8>>
)],
[lustre@element@html:a(
[lustre@attribute:href(
erlang:element(
3,
Comment
)
),
lustre@attribute:class(
<<"link link-secondary-content link-sm"/utf8>>
)],
[lustre@element:text(
<<"@"/utf8,
(erlang:element(
5,
Comment
))/binary>>
)]
),
lustre@element:text(
<<" • "/utf8>>
),
lustre@element@html:time(
[lustre@attribute:attribute(
<<"datetime"/utf8>>,
begin
_pipe@10 = erlang:element(
2,
Comment
),
gleam@time@timestamp:to_rfc3339(
_pipe@10,
{duration,
0,
0}
)
end
)],
[lustre@element:text(
begin
B = begin
_pipe@13 = case begin
_pipe@11 = gleam@time@timestamp:difference(
erlang:element(
2,
Comment
),
gleam@time@timestamp:system_time(
)
),
_pipe@12 = gleam@time@duration:approximate(
_pipe@11
),
gleam@pair:map_second(
_pipe@12,
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@13,
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(
[lustre@attribute:class(<<"content mt-5"/utf8>>)],
[lustre@element@html:span(
[],
[erlang:element(8, Comment)]
)]
),
lustre@element@html:footer(
[],
[lustre@element@html:'div'(
[lustre@attribute:class(<<"my-5"/utf8>>)],
[lustre@element@html:a(
[lustre@attribute:class(
<<"btn btn-sm absolute right-8"/utf8>>
),
lustre@attribute:href(
erlang:element(
9,
Comment
)
),
lustre@attribute:target(
<<"_blank"/utf8>>
)],
[lustre@element@html:text(
<<"View comment on "/utf8,
(erlang:element(
6,
Comment
))/binary>>
)]
)]
),
lustre@element@html:br(
[lustre@attribute:class(
<<"border-b-2 border-dotted"/utf8>>
)]
),
case {erlang:element(11, Comment),
Is_silenced} of
{[], _} ->
lustre@element:none();
{_, true} ->
lustre@element:none();
{_, false} ->
lustre@element@html:section(
[lustre@attribute:class(
<<"pl-5 border-s-4 border-default bg-neutral-secondary-soft"/utf8>>
)],
begin
_pipe@14 = gleam@list:sort(
erlang:element(
11,
Comment
),
fun sort_comments/2
),
gleam@list:map(
_pipe@14,
fun(_capture@2) ->
view_rendered_comment(
_capture@2,
Bsky_op_profile,
Mastodon_op_profile
)
end
)
end
)
end]
)]
)
end
)
end
).
-file("src/chilp/widget.gleam", 1093).
-spec js_browse(binary()) -> nil.
js_browse(_) ->
nil.
-file("src/chilp/widget.gleam", 1025).
-spec browse(binary()) -> lustre@effect:effect(any()).
browse(To) ->
lustre@effect:from(fun(_) -> js_browse(To) end).
-file("src/chilp/widget.gleam", 1126).
-spec bsky_thread_reply_decoder() -> gleam@dynamic@decode:decoder(bsky_thread_reply()).
bsky_thread_reply_decoder() ->
gleam@dynamic@decode:subfield(
[<<"post"/utf8>>, <<"record"/utf8>>, <<"createdAt"/utf8>>],
gleam@dynamic@decode:map(
{decoder, fun gleam@dynamic@decode:decode_string/1},
fun(Stringstamp) ->
gleam@result:unwrap(
gleam@time@timestamp:parse_rfc3339(Stringstamp),
{timestamp, 0, 0}
)
end
),
fun(Created_at) ->
gleam@dynamic@decode:subfield(
[<<"post"/utf8>>, <<"uri"/utf8>>],
{decoder, fun gleam@dynamic@decode:decode_string/1},
fun(At_uri) ->
gleam@dynamic@decode:subfield(
[<<"post"/utf8>>, <<"record"/utf8>>, <<"text"/utf8>>],
{decoder, fun gleam@dynamic@decode:decode_string/1},
fun(Body_text) ->
gleam@dynamic@decode:subfield(
[<<"post"/utf8>>,
<<"author"/utf8>>,
<<"did"/utf8>>],
{decoder,
fun gleam@dynamic@decode:decode_string/1},
fun(Author_did) ->
gleam@dynamic@decode:subfield(
[<<"post"/utf8>>,
<<"author"/utf8>>,
<<"handle"/utf8>>],
{decoder,
fun gleam@dynamic@decode:decode_string/1},
fun(Author_handle) ->
gleam@dynamic@decode:subfield(
[<<"post"/utf8>>,
<<"author"/utf8>>,
<<"displayName"/utf8>>],
{decoder,
fun gleam@dynamic@decode:decode_string/1},
fun(Author_displayname) ->
gleam@dynamic@decode:subfield(
[<<"post"/utf8>>,
<<"author"/utf8>>,
<<"avatar"/utf8>>],
{decoder,
fun gleam@dynamic@decode:decode_string/1},
fun(Author_avatar) ->
gleam@dynamic@decode:subfield(
[<<"post"/utf8>>,
<<"likeCount"/utf8>>],
{decoder,
fun gleam@dynamic@decode:decode_int/1},
fun(Like_count) ->
gleam@dynamic@decode:field(
<<"replies"/utf8>>,
gleam@dynamic@decode:list(
bsky_thread_reply_decoder(
)
),
fun(
Children
) ->
gleam@dynamic@decode:success(
{bsky_thread_reply,
At_uri,
Like_count,
Created_at,
Body_text,
Author_did,
Author_handle,
Author_displayname,
Author_avatar,
Children}
)
end
)
end
)
end
)
end
)
end
)
end
)
end
)
end
)
end
).
-file("src/chilp/widget.gleam", 1117).
-spec bsky_thread_view_decoder() -> gleam@dynamic@decode:decoder(bsky_thread_view()).
bsky_thread_view_decoder() ->
gleam@dynamic@decode:subfield(
[<<"thread"/utf8>>, <<"post"/utf8>>, <<"uri"/utf8>>],
{decoder, fun gleam@dynamic@decode:decode_string/1},
fun(At_uri) ->
gleam@dynamic@decode:subfield(
[<<"thread"/utf8>>, <<"replies"/utf8>>],
gleam@dynamic@decode:list(bsky_thread_reply_decoder()),
fun(Replies) ->
gleam@dynamic@decode:success(
{bsky_thread_view, At_uri, Replies}
)
end
)
end
).
-file("src/chilp/widget.gleam", 848).
-spec refresh_bsky(model()) -> lustre@effect:effect(msg()).
refresh_bsky(Model) ->
case erlang:element(5, Model) of
{some, Anchor} ->
Url = <<<<<<"https://public.api.bsky.app/xrpc/app.bsky.feed.getPostThread?uri=at://"/utf8,
(erlang:element(2, Anchor))/binary>>/binary,
"/app.bsky.feed.post/"/utf8>>/binary,
(erlang:element(3, Anchor))/binary>>,
Handler = rsvp:expect_json(
bsky_thread_view_decoder(),
fun(Response) -> case Response of
{ok, Threadview} ->
{bsky_incoming_thread_view, Threadview};
{error, Rsvperror} ->
case Rsvperror of
{unhandled_response, _} ->
{all_stopping_error,
<<"The response body we got back from Bluesky was misformed."/utf8>>};
{json_error, _} ->
{all_stopping_error,
<<"The response body we got back from Bluesky was misformed."/utf8>>};
bad_body ->
{all_stopping_error,
<<"The response body we got back from Bluesky was misformed."/utf8>>};
{bad_url, _} ->
{all_stopping_error,
<<"The API call to Bluesky failed. Did you enter the DID and post id correctly?"/utf8>>};
{http_error, _} ->
{all_stopping_error,
<<"Could not fetch comments from Bluesky."/utf8>>};
network_error ->
{all_stopping_error,
<<"Could not fetch comments from Bluesky."/utf8>>}
end
end end
),
rsvp:get(Url, Handler);
none ->
lustre@effect:none()
end.
-file("src/chilp/widget.gleam", 1196).
-spec mastodon_decendant_inflater(
mastodon_descendant(),
list({mastodon_descendant(), binary()})
) -> mastodon_descendant().
mastodon_decendant_inflater(Parent, All_children) ->
{mastodon_descendant,
erlang:element(2, Parent),
erlang:element(3, Parent),
erlang:element(4, Parent),
erlang:element(5, Parent),
erlang:element(6, Parent),
gleam@list:filter_map(
All_children,
fun(C) -> case erlang:element(2, C) =:= erlang:element(2, Parent) of
true ->
{ok, erlang:element(1, C)};
false ->
{error, nil}
end end
),
erlang:element(8, Parent),
erlang:element(9, Parent),
erlang:element(10, Parent),
erlang:element(11, Parent)}.
-file("src/chilp/widget.gleam", 1229).
?DOC(" Decodes #(MastodonDescendant, ReplyingTo), to enable the parent decoder to make this into a recursive three.\n").
-spec mastodon_descendant_decoder() -> gleam@dynamic@decode:decoder({mastodon_descendant(),
binary()}).
mastodon_descendant_decoder() ->
gleam@dynamic@decode:field(
<<"in_reply_to_id"/utf8>>,
{decoder, fun gleam@dynamic@decode:decode_string/1},
fun(Replying_to) ->
gleam@dynamic@decode:field(
<<"id"/utf8>>,
{decoder, fun gleam@dynamic@decode:decode_string/1},
fun(Id) ->
gleam@dynamic@decode:field(
<<"uri"/utf8>>,
{decoder, fun gleam@dynamic@decode:decode_string/1},
fun(Uri) ->
gleam@dynamic@decode:field(
<<"created_at"/utf8>>,
gleam@dynamic@decode:map(
{decoder,
fun gleam@dynamic@decode:decode_string/1},
fun(Stringstamp) ->
gleam@result:unwrap(
gleam@time@timestamp:parse_rfc3339(
Stringstamp
),
{timestamp, 0, 0}
)
end
),
fun(Created_at) ->
gleam@dynamic@decode:field(
<<"favourites_count"/utf8>>,
{decoder,
fun gleam@dynamic@decode:decode_int/1},
fun(Favourite_count) ->
gleam@dynamic@decode:field(
<<"content"/utf8>>,
{decoder,
fun gleam@dynamic@decode:decode_string/1},
fun(Unescaped_html_content) ->
Content = sanitise_ls(
Unescaped_html_content
),
Children = [],
gleam@dynamic@decode:subfield(
[<<"account"/utf8>>,
<<"url"/utf8>>],
{decoder,
fun gleam@dynamic@decode:decode_string/1},
fun(Author_url) ->
gleam@dynamic@decode:subfield(
[<<"account"/utf8>>,
<<"avatar"/utf8>>],
{decoder,
fun gleam@dynamic@decode:decode_string/1},
fun(
Author_avatar_url
) ->
gleam@dynamic@decode:subfield(
[<<"account"/utf8>>,
<<"display_name"/utf8>>],
{decoder,
fun gleam@dynamic@decode:decode_string/1},
fun(
Author_displayname
) ->
gleam@dynamic@decode:subfield(
[<<"account"/utf8>>,
<<"acct"/utf8>>],
{decoder,
fun gleam@dynamic@decode:decode_string/1},
fun(
Author_username
) ->
gleam@dynamic@decode:success(
{{mastodon_descendant,
Id,
Uri,
Content,
Created_at,
Favourite_count,
Children,
Author_url,
Author_avatar_url,
Author_username,
Author_displayname},
Replying_to}
)
end
)
end
)
end
)
end
)
end
)
end
)
end
)
end
)
end
)
end
).
-file("src/chilp/widget.gleam", 1172).
-spec mastodon_status_context_decoder(binary()) -> gleam@dynamic@decode:decoder(mastodon_status_context()).
mastodon_status_context_decoder(Original_id) ->
gleam@dynamic@decode:field(
<<"descendants"/utf8>>,
gleam@dynamic@decode:list(mastodon_descendant_decoder()),
fun(Flat_descendants) ->
Descendants = gleam@list:filter_map(
Flat_descendants,
fun(Desc) -> case erlang:element(2, Desc) =:= Original_id of
true ->
_pipe = mastodon_decendant_inflater(
erlang:element(1, Desc),
Flat_descendants
),
{ok, _pipe};
false ->
{error, nil}
end end
),
gleam@dynamic@decode:success({mastodon_status_context, Descendants})
end
).
-file("src/chilp/widget.gleam", 987).
-spec refresh_mastodon(model()) -> lustre@effect:effect(msg()).
refresh_mastodon(Model) ->
case erlang:element(2, Model) of
{some, Anchor} ->
Url = <<<<<<<<"https://"/utf8, (erlang:element(2, Anchor))/binary>>/binary,
"/api/v1/statuses/"/utf8>>/binary,
(erlang:element(3, Anchor))/binary>>/binary,
"/context"/utf8>>,
Handler = rsvp:expect_json(
mastodon_status_context_decoder(erlang:element(3, Anchor)),
fun(Response) -> case Response of
{ok, Status} ->
{mastodon_incoming_status, Status};
{error, Rsvperror} ->
case Rsvperror of
{unhandled_response, _} ->
{all_stopping_error,
<<"The response body we got back from Mastodon was misformed."/utf8>>};
{json_error, _} ->
{all_stopping_error,
<<"The response body we got back from Mastodon was misformed."/utf8>>};
bad_body ->
{all_stopping_error,
<<"The response body we got back from Mastodon was misformed."/utf8>>};
{bad_url, _} ->
{all_stopping_error,
<<"The API call to Mastodon failed. Did you enter the instance and post id correctly?"/utf8>>};
{http_error, _} ->
{all_stopping_error,
<<"Could not fetch comments from Mastodon."/utf8>>};
network_error ->
{all_stopping_error,
<<"Could not fetch comments from Mastodon."/utf8>>}
end
end end
),
rsvp:get(Url, Handler);
none ->
lustre@effect:none()
end.
-file("src/chilp/widget.gleam", 1272).
-spec coalesce_views(list(bsky_thread_reply()), list(mastodon_descendant())) -> list(coalesced_view()).
coalesce_views(Bsky, Mastodon) ->
Mixed = begin
_pipe = lists:append(
gleam@list:map(Bsky, fun(M) -> {ok, M} end),
gleam@list:map(Mastodon, fun(M@1) -> {error, M@1} end)
),
gleam@list:shuffle(_pipe)
end,
gleam@list:map(Mixed, fun(Item) -> case Item of
{ok,
{bsky_thread_reply,
At_uri,
Like_count,
Created_at,
Body_text,
Author_did,
Author_handle,
Author_displayname,
Author_avatar,
Children}} ->
{coalesced_view,
Created_at,
<<"https://bluesky.app/profile/"/utf8,
Author_did/binary>>,
Author_avatar,
Author_handle,
<<"Bluesky"/utf8>>,
Author_displayname,
lustre@element:text(Body_text),
<<"https://bsky.app/profile/"/utf8,
(begin
_pipe@1 = gleam@string:replace(
At_uri,
<<"/app.bsky.feed.post/"/utf8>>,
<<"/post/"/utf8>>
),
gleam@string:replace(
_pipe@1,
<<"at://"/utf8>>,
<<""/utf8>>
)
end)/binary>>,
Like_count,
(coalesce_views(Children, []))};
{error,
{mastodon_descendant,
_,
Uri,
Content,
Created_at@1,
Favourite_count,
Children@1,
Author_url,
Author_avatar_url,
Author_username,
Author_displayname@1}} ->
{coalesced_view,
Created_at@1,
Author_url,
Author_avatar_url,
Author_username,
<<"Mastodon"/utf8>>,
Author_displayname@1,
Content,
Uri,
Favourite_count,
(coalesce_views([], Children@1))}
end end).
-file("src/chilp/widget.gleam", 837).
-spec new_coalesced_view(list(bsky_thread_reply()), list(mastodon_descendant())) -> lustre@effect:effect(msg()).
new_coalesced_view(Bsky_replies, Mastodon_descendants) ->
lustre@effect:from(
fun(Dispatch) ->
Dispatch(
{incoming_coalesced_view,
coalesce_views(Bsky_replies, Mastodon_descendants)}
)
end
).
-file("src/chilp/widget.gleam", 125).
-spec update(model(), msg()) -> {model(), lustre@effect:effect(msg())}.
update(Model, Msg) ->
case Msg of
{all_stopping_error, Msg@1} ->
{{model,
erlang:element(2, Model),
erlang:element(3, Model),
erlang:element(4, Model),
erlang:element(5, Model),
erlang:element(6, Model),
erlang:element(7, Model),
{some, Msg@1},
erlang:element(9, Model),
erlang:element(10, Model)},
lustre@effect:none()};
mastodon_un_anchored ->
{{model,
none,
erlang:element(3, Model),
erlang:element(4, Model),
erlang:element(5, Model),
erlang:element(6, Model),
erlang:element(7, Model),
erlang:element(8, Model),
erlang:element(9, Model),
erlang:element(10, Model)},
lustre@effect:none()};
{mastodon_answer, Instance} ->
case erlang:element(2, Model) of
{some, _} when Instance =/= <<""/utf8>> ->
{Model,
browse(
(<<<<<<"https://"/utf8, Instance/binary>>/binary,
"/authorize_interaction?uri="/utf8>>/binary,
(gleam_stdlib:percent_encode(
erlang:element(2, erlang:element(4, Model))
))/binary>>)
)};
_ ->
{Model, lustre@effect:none()}
end;
{mastodon_anchored, Instance@1, Post} ->
Model@1 = {model,
{some, {mastodon, Instance@1, Post}},
erlang:element(3, Model),
erlang:element(4, Model),
erlang:element(5, Model),
erlang:element(6, Model),
erlang:element(7, Model),
erlang:element(8, Model),
erlang:element(9, Model),
erlang:element(10, Model)},
{Model@1,
lustre@effect:batch(
[get_username_mastodon(Model@1), refresh_mastodon(Model@1)]
)};
{mastodon_incoming_op_username, Mastodon_op_username_and_posturl} ->
{{model,
erlang:element(2, Model),
erlang:element(3, Model),
Mastodon_op_username_and_posturl,
erlang:element(5, Model),
erlang:element(6, Model),
erlang:element(7, Model),
erlang:element(8, Model),
erlang:element(9, Model),
erlang:element(10, Model)},
lustre@effect:none()};
{mastodon_incoming_status, Status} ->
{{model,
erlang:element(2, Model),
erlang:element(2, Status),
erlang:element(4, Model),
erlang:element(5, Model),
erlang:element(6, Model),
erlang:element(7, Model),
erlang:element(8, Model),
erlang:element(9, Model),
erlang:element(10, Model)},
new_coalesced_view(
erlang:element(6, Model),
erlang:element(2, Status)
)};
bsky_un_anchored ->
{{model,
erlang:element(2, Model),
erlang:element(3, Model),
erlang:element(4, Model),
none,
erlang:element(6, Model),
erlang:element(7, Model),
erlang:element(8, Model),
erlang:element(9, Model),
erlang:element(10, Model)},
lustre@effect:none()};
{bsky_anchored, Did, Post@1} ->
Model@2 = {model,
erlang:element(2, Model),
erlang:element(3, Model),
erlang:element(4, Model),
{some, {bluesky, Did, Post@1}},
erlang:element(6, Model),
erlang:element(7, Model),
erlang:element(8, Model),
erlang:element(9, Model),
erlang:element(10, Model)},
{Model@2, lustre@effect:batch([refresh_bsky(Model@2)])};
{bsky_incoming_thread_view, Threadview} ->
{{model,
erlang:element(2, Model),
erlang:element(3, Model),
erlang:element(4, Model),
erlang:element(5, Model),
erlang:element(3, Threadview),
erlang:element(7, Model),
erlang:element(8, Model),
erlang:element(9, Model),
erlang:element(10, Model)},
new_coalesced_view(
erlang:element(3, Threadview),
erlang:element(3, Model)
)};
{set_tab, Open_tab} ->
{{model,
erlang:element(2, Model),
erlang:element(3, Model),
erlang:element(4, Model),
erlang:element(5, Model),
erlang:element(6, Model),
erlang:element(7, Model),
erlang:element(8, Model),
erlang:element(9, Model),
Open_tab},
lustre@effect:none()};
{incoming_coalesced_view, New} ->
{{model,
erlang:element(2, Model),
erlang:element(3, Model),
erlang:element(4, Model),
erlang:element(5, Model),
erlang:element(6, Model),
erlang:element(7, Model),
erlang:element(8, Model),
New,
erlang:element(10, Model)},
lustre@effect:none()};
mastodon_error_fetching_op_username_retry_for_misskey ->
{Model, get_username_miskey(Model)}
end.
-file("src/chilp/widget.gleam", 802).
-spec placeholder_instance(chilp@widget@anchors:mastodon()) -> binary().
placeholder_instance(Mastodon_anchor) ->
_pipe = [erlang:element(2, Mastodon_anchor) |
[<<"mastodon.social"/utf8>>,
<<"pony.social"/utf8>>,
<<"todon.nl"/utf8>>,
<<"mstdn.social"/utf8>>,
<<"infosec.exchange"/utf8>>,
<<"woem.space"/utf8>>,
<<"shitpost.trade"/utf8>>,
<<"procial.tchncs.de"/utf8>>]],
_pipe@1 = gleam@list:shuffle(_pipe),
_pipe@2 = gleam@list:first(_pipe@1),
gleam@result:unwrap(_pipe@2, erlang:element(2, Mastodon_anchor)).
-file("src/chilp/widget.gleam", 728).
-spec view_mastodon_respond_form(chilp@widget@anchors:mastodon()) -> lustre@vdom@vnode:element(msg()).
view_mastodon_respond_form(Mastodon_anchor) ->
lustre@element@html:'div'(
[lustre@attribute:class(<<"my-5 px-5 pb-5 "/utf8>>)],
[lustre@element@html:form(
[lustre@attribute:class(<<"mb-8 w-full"/utf8>>),
lustre@event:on_submit(
fun(N) ->
Value = begin
_pipe = gleam@list:key_find(
N,
<<"userinstance"/utf8>>
),
gleam@result:unwrap(_pipe, <<""/utf8>>)
end,
{mastodon_answer, Value}
end
)],
[lustre@element@html:'div'(
[lustre@attribute:class(<<"flex flex-col gap-2"/utf8>>)],
[lustre@element@html:label(
[lustre@attribute:for(<<"userinstance"/utf8>>),
lustre@attribute:class(
<<"text-sm font-semibold text-base-content/80"/utf8>>
)],
[lustre@element@html:text(
<<"Enter your instance address to reply or "/utf8>>
),
lustre@element@html:a(
[lustre@attribute:href(
<<<<"https://"/utf8,
(placeholder_instance(
Mastodon_anchor
))/binary>>/binary,
"/auth/sign_up"/utf8>>
),
lustre@attribute:class(
<<"link link-primary-content"/utf8>>
)],
[lustre@element@html:text(
<<"create an account"/utf8>>
)]
),
lustre@element@html:text(<<"!"/utf8>>)]
),
lustre@element@html:p(
[lustre@attribute:class(
<<"text-xs italic opacity-50 -mt-1 mb-2 ml-1"/utf8>>
)],
[lustre@element@html:text(
<<"on the instance recommended by this widget... or one you pick yourself!"/utf8>>
)]
),
lustre@element@html:'div'(
[lustre@attribute:class(
<<"join w-full shadow-sm"/utf8>>
)],
[lustre@element@html:input(
[lustre@attribute:type_(<<"text"/utf8>>),
lustre@attribute:required(true),
lustre@attribute:placeholder(
placeholder_instance(
Mastodon_anchor
)
),
lustre@attribute:pattern(
<<"^([a-z0-9]+(-[a-z0-9]+)*\\.)+[a-z]{2,}$"/utf8>>
),
lustre@attribute:name(
<<"userinstance"/utf8>>
),
lustre@attribute:class(
<<"input input-bordered join-item flex-1 focus:outline-primary"/utf8>>
)]
),
lustre@element@html:button(
[lustre@attribute:type_(
<<"submit"/utf8>>
),
lustre@attribute:class(
<<"btn btn-primary join-item"/utf8>>
)],
[lustre@element@html:text(
<<"Go reply"/utf8>>
)]
)]
)]
)]
)]
).
-file("src/chilp/widget.gleam", 214).
-spec view_normal(model()) -> lustre@vdom@vnode:element(msg()).
view_normal(Model) ->
About_linkie = lustre@element@html:'div'(
[],
[lustre@element@html:a(
[lustre@attribute:class(
<<"float-right link link-secondary-content/40 text-xs"/utf8>>
) |
case {gleam@bool:exclusive_or(
gleam@option:is_some(erlang:element(5, Model)),
gleam@option:is_some(erlang:element(2, Model))
),
erlang:element(10, Model) =:= 3} of
{true, true} ->
[lustre@event:on_click({set_tab, 1})];
{true, false} ->
[lustre@event:on_click({set_tab, 3})];
{false, false} ->
[lustre@event:on_click({set_tab, 3}),
lustre@attribute:class(
<<"absolute right-2 top-1"/utf8>>
)];
{false, true} ->
[lustre@attribute:class(<<"hidden"/utf8>>)]
end],
[lustre@element@html:text(
case erlang:element(10, Model) =:= 3 of
false ->
<<"About"/utf8>>;
true ->
<<"×"/utf8>>
end
)]
)]
),
{Linkedto, Respond_here} = case {erlang:element(5, Model),
erlang:element(2, Model)} of
{{some, Bsky}, {some, Masto}} ->
{begin
_pipe@1 = [lustre@element@html:text(<<"Linked to "/utf8>>),
case begin
_pipe = erlang:element(2, erlang:element(4, Model)),
gleam_stdlib:contains_string(
_pipe,
<<"/notes/"/utf8>>
)
end of
true ->
lustre@element@html:a(
[lustre@attribute:href(
erlang:element(
2,
erlang:element(4, Model)
)
),
lustre@attribute:class(
<<"link text-[#3da0c8]"/utf8>>
)],
[lustre@element@html:text(
<<"this note on Sharkey"/utf8>>
)]
);
false ->
lustre@element@html:a(
[lustre@attribute:href(
erlang:element(
2,
erlang:element(4, Model)
)
),
lustre@attribute:class(
<<"link text-[#595aff]"/utf8>>
)],
[lustre@element@html:text(
<<"this post on Mastodon"/utf8>>
)]
)
end,
lustre@element@html:text(<<", and to "/utf8>>),
lustre@element@html:a(
[lustre@attribute:href(
<<<<<<"https://bsky.app/profile/"/utf8,
(erlang:element(2, Bsky))/binary>>/binary,
"/post/"/utf8>>/binary,
(erlang:element(3, Bsky))/binary>>
),
lustre@attribute:class(
<<"link text-[#006aff]"/utf8>>
)],
[lustre@element@html:text(
<<"this post on Bluesky"/utf8>>
)]
),
lustre@element@html:text(<<"."/utf8>>)],
lustre@element:fragment(_pipe@1)
end,
begin
_pipe@2 = [lustre@element@html:'div'(
[lustre@attribute:class(
<<"tabs tabs-box border-b-2 border-base-300 h-full"/utf8>>
),
lustre@attribute:role(<<"tablist"/utf8>>)],
[lustre@element@html:a(
[lustre@attribute:role(<<"tab"/utf8>>),
lustre@event:on_click({set_tab, 1}),
lustre@attribute:classes(
[{<<"tab"/utf8>>, true},
{<<"tab-active"/utf8>>,
erlang:element(10, Model)
=:= 1}]
)],
[lustre@element@html:text(
<<"Mastodon"/utf8>>
)]
),
lustre@element@html:a(
[lustre@attribute:role(<<"tab"/utf8>>),
lustre@event:on_click({set_tab, 2}),
lustre@attribute:classes(
[{<<"tab"/utf8>>, true},
{<<"tab-active"/utf8>>,
erlang:element(10, Model)
=:= 2}]
)],
[lustre@element@html:text(
<<"Bluesky"/utf8>>
)]
)]
),
lustre@element@html:br([]),
case erlang:element(10, Model) of
2 ->
view_respond_on_bsky(
<<<<<<"https://bsky.app/profile/"/utf8,
(erlang:element(2, Bsky))/binary>>/binary,
"/post/"/utf8>>/binary,
(erlang:element(3, Bsky))/binary>>
);
3 ->
view_about_chilp();
_ ->
view_mastodon_respond_form(Masto)
end],
lustre@element:fragment(_pipe@2)
end};
{none, {some, Masto@1}} ->
{case erlang:element(10, Model) of
3 ->
view_about_chilp();
_ ->
_pipe@4 = [lustre@element@html:text(
<<"Linked to "/utf8>>
),
case begin
_pipe@3 = erlang:element(
2,
erlang:element(4, Model)
),
gleam_stdlib:contains_string(
_pipe@3,
<<"/notes/"/utf8>>
)
end of
true ->
lustre@element@html:a(
[lustre@attribute:href(
erlang:element(
2,
erlang:element(4, Model)
)
),
lustre@attribute:class(
<<"link text-[#3da0c8]"/utf8>>
)],
[lustre@element@html:text(
<<"this note on Sharkey"/utf8>>
)]
);
false ->
lustre@element@html:a(
[lustre@attribute:href(
erlang:element(
2,
erlang:element(4, Model)
)
),
lustre@attribute:class(
<<"link text-[#595aff]"/utf8>>
)],
[lustre@element@html:text(
<<"this post on Mastodon"/utf8>>
)]
)
end,
lustre@element@html:text(<<"."/utf8>>)],
lustre@element:fragment(_pipe@4)
end, view_mastodon_respond_form(Masto@1)};
{{some, Bsky@1}, none} ->
{case erlang:element(10, Model) of
3 ->
view_about_chilp();
_ ->
_pipe@5 = [lustre@element@html:text(
<<"Linked to "/utf8>>
),
lustre@element@html:a(
[lustre@attribute:href(
<<<<<<"https://bsky.app/profile/"/utf8,
(erlang:element(2, Bsky@1))/binary>>/binary,
"/post/"/utf8>>/binary,
(erlang:element(3, Bsky@1))/binary>>
),
lustre@attribute:class(
<<"link link-[#006aff]"/utf8>>
)],
[lustre@element@html:text(
<<"this post on Bluesky"/utf8>>
)]
),
lustre@element@html:text(<<"."/utf8>>)],
lustre@element:fragment(_pipe@5)
end, view_respond_on_bsky(
<<<<<<"https://bsky.app/profile/"/utf8,
(erlang:element(2, Bsky@1))/binary>>/binary,
"/post/"/utf8>>/binary,
(erlang:element(3, Bsky@1))/binary>>
)};
{none, none} ->
{error_view(
<<"No comment backends are configured for this widget."/utf8>>
),
lustre@element:none()}
end,
lustre@element@html:'div'(
[lustre@attribute:class(<<"comment-widget"/utf8>>)],
[lustre@element@html:'div'(
[lustre@attribute:class(
<<"widget card bg-base-100 shadow-xl border border-base-200 p-10"/utf8>>
)],
[lustre@element@html:h1(
[lustre@attribute:class(
<<"text-2xl font-extrabold text-base-content"/utf8>>
)],
[lustre@element@html:text(<<"Comments"/utf8>>)]
),
lustre@element@html:p(
[lustre@attribute:class(
<<"text-sm text-base-content/70"/utf8>>
)],
[About_linkie, Linkedto]
),
lustre@element@html:'div'(
[lustre@attribute:class(
<<"card card-dash bg-base-200/70 border-base-300"/utf8>>
)],
[Respond_here]
),
lustre@element@html:section(
[lustre@attribute:class(<<"pt-5 space-y-10"/utf8>>)],
begin
_pipe@6 = gleam@list:sort(
erlang:element(9, Model),
fun sort_comments/2
),
gleam@list:map(
_pipe@6,
fun(_capture) ->
view_rendered_comment(
_capture,
gleam@option:map(
erlang:element(5, Model),
fun(Bsky@2) ->
<<"https://bsky.app/profile/"/utf8,
(erlang:element(2, Bsky@2))/binary>>
end
),
gleam@option:map(
erlang:element(2, Model),
fun(Masto@2) ->
<<<<<<"https://"/utf8,
(erlang:element(
2,
Masto@2
))/binary>>/binary,
"/@"/utf8>>/binary,
(erlang:element(
1,
erlang:element(4, Model)
))/binary>>
end
)
)
end
)
end
)]
)]
).
-file("src/chilp/widget.gleam", 207).
-spec view(model()) -> lustre@vdom@vnode:element(msg()).
view(Model) ->
case erlang:element(8, Model) of
none ->
view_normal(Model);
{some, Error} ->
error_view(Error)
end.
-file("src/chilp/widget.gleam", 30).
-spec register() -> {ok, nil} | {error, lustre:error()}.
register() ->
Component = lustre:component(
fun init/1,
fun update/2,
fun view/1,
[lustre@component:on_attribute_change(
<<"mastodon-anchor"/utf8>>,
fun(Value) ->
gleam@bool:guard(
Value =:= <<""/utf8>>,
{ok, mastodon_un_anchored},
fun() -> _pipe = Value,
_pipe@1 = gleam@string:split_once(
_pipe,
<<"\\"/utf8>>
),
gleam@result:map(
_pipe@1,
fun(A) ->
{mastodon_anchored,
erlang:element(1, A),
erlang:element(2, A)}
end
) end
)
end
),
lustre@component:on_attribute_change(
<<"bluesky-anchor"/utf8>>,
fun(Value@1) ->
gleam@bool:guard(
Value@1 =:= <<""/utf8>>,
{ok, bsky_un_anchored},
fun() -> _pipe@2 = Value@1,
_pipe@3 = gleam@string:split_once(
_pipe@2,
<<"\\"/utf8>>
),
gleam@result:map(
_pipe@3,
fun(A@1) ->
{bsky_anchored,
erlang:element(1, A@1),
erlang:element(2, A@1)}
end
) end
)
end
)]
),
lustre:register(Component, <<"comment-widget"/utf8>>).