-module(chilp). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). -define(FILEPATH, "src/chilp.gleam"). -export([bluesky/2, mastodon/2, widget/2, update/2, view/1, register/0]). -export_type([model/0, mastodon/0, bluesky/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. ?MODULEDOC( " \n" " \n" "\n" "\n" "\n" " # Chilp\n" "\n" ). -type model() :: {model, gleam@option:option(mastodon()), list(mastodon_descendant()), {binary(), binary()}, gleam@option:option(bluesky()), list(bsky_thread_reply()), binary(), gleam@option:option(binary()), list(coalesced_view()), integer()}. -opaque mastodon() :: {mastodon, binary(), binary()}. -opaque bluesky() :: {bluesky, binary(), binary()}. -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.gleam", 297). ?DOC( " # Anchor to Bluesky\n" "\n" " An anchor to the Bluesky post you want to \n" " fetch comments from.\n" " | Parameter | Description |\n" " | --------- | ----------- |\n" " | `did` | Your DID, for `@strawmelonjuice.com`, this looks like `\"did:plc:jgtfsmv25thfs4zmydtbccnn\"`.

Not sure how to find your DID? is one of the many places where you can easily find it. |\n" " | `post_id` | A post id to bind to, you'll find this in a post url `https://bsky.app/profile//post/[postid]` |\n" ). -spec bluesky(binary(), binary()) -> bluesky(). bluesky(Did, Postid) -> {bluesky, Did, Postid}. -file("src/chilp.gleam", 311). ?DOC( " # Anchor to Fediverse\n" "\n" " An anchor to the Fediverse post you want to \n" " fetch comments from.\n" " | Parameter | Description |\n" " | ---------- | ----------- |\n" " | `instance` | The instance name, e.g. `\"mastodon.social\"`, this is where your post is stored, and where chilp will attempt to fetch it from. |\n" " | `post_id` | A post id to bind to, you'll find this in a post url `https://instance.social/@/[postid]`. |\n" " | | On Sharkey or Misskey this is a note id, found `https://instance.social/notes/[note-id]` |\n" ). -spec mastodon(binary(), binary()) -> mastodon(). mastodon(Instance, Postid) -> {mastodon, Instance, Postid}. -file("src/chilp.gleam", 342). ?DOC( " # The widget\n" "\n" " Before adding this component make sure to call [`chilp.register()`](#register) to register it!\n" "\n" " After that, use it like this:\n" " ```gleam\n" " chilp.widget(\n" " // We connect to Bluesky...\n" " bluesky: option.Some(chilp.bluesky(\"did:plc:my-did\",\"myPostId\")),\n" " // ...But not to Mastodon? Sure! Make it a None!\n" " mastodon: option.None\n" " )\n" " ```\n" "\n" " ## An example with real values:\n" " ```gleam\n" " html.text(\"I use a cool list of devices!\")\n" " chilp.widget(\n" " bluesky: option.Some(chilp.bluesky(did: \"did:plc:jgtfsmv25thfs4zmydtbccnn\", post_id: \"3mk5u4xwqus2i\")),\n" " mastodon: option.Some(chilp.mastodon(instance: \"pony.social\", post_id: \"116453666510859359\"))\n" " )\n" " ```\n" " Yields you:\n" "\n" " > I use a cool list of devices!\n" " > \n" ). -spec widget(gleam@option:option(mastodon()), gleam@option:option(bluesky())) -> lustre@vdom@vnode:element(any()). widget(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.gleam", 417). -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.gleam", 990). -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.gleam", 1017). -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@element@html:button( [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 chilp-oat-enhance-inset-blueskyreply"/utf8>> ), Icon_link( <<"Blacksky"/utf8>>, <<"blacksky.community"/utf8>>, <<"text-white bg-black chilp-oat-enhance-inset-blackskyreply"/utf8>> ), Icon_link( <<"Witchsky"/utf8>>, <<"witchsky.app"/utf8>>, <<"bg-[#ed5345] text-white chilp-oat-enhance-inset-witchskyreply"/utf8>> )] )] ). -file("src/chilp.gleam", 1158). -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.gleam", 1231). -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.gleam", 1284). -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.gleam", 1389). -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.gleam", 1382). ?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.gleam", 1434). -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.gleam", 777). -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}, _} -> Op@1 =:= erlang:element(3, Comment); {_, _, _} -> 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}, _} -> Op@3 =:= erlang:element(3, Child); {_, _, _} -> false end) of false -> {error, nil}; true -> Content = begin _pipe = lustre@element:to_readable_string( erlang:element(8, Child) ), string:lowercase(_pipe) 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@1 = lustre@element:to_readable_string( erlang:element(8, Comment) ), string:lowercase(_pipe@1) 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:figure( [lustre@attribute:attribute( <<"aria-label"/utf8>>, erlang:element(5, Comment) ), lustre@attribute:class( <<"small"/utf8>> ), lustre@attribute:attribute( <<"data-variant"/utf8>>, <<"avatar"/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 chilp-oat-enhance-inset-1em"/utf8>> )], [lustre@element@html:text( erlang:element( 7, Comment ) ), case erlang:element( 6, Comment ) of <<"Mastodon"/utf8>> -> lustre@element@html:'div'( [lustre@attribute:attribute( <<"data-variant"/utf8>>, <<"secondary"/utf8>> ), 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:attribute( <<"data-variant"/utf8>>, <<"secondary"/utf8>> ), 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:attribute( <<"data-variant"/utf8>>, <<"outline"/utf8>> ), 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@2 = erlang:element( 2, Comment ), gleam@time@timestamp:to_rfc3339( _pipe@2, {duration, 0, 0} ) end )], [lustre@element:text( begin B = begin _pipe@5 = case begin _pipe@3 = gleam@time@timestamp:difference( erlang:element( 2, Comment ), gleam@time@timestamp:system_time( ) ), _pipe@4 = gleam@time@duration:approximate( _pipe@3 ), gleam@pair:map_second( _pipe@4, 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, <>} end, gleam@pair:map_first( _pipe@5, 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 chilp-oat-enhance-inset-2em"/utf8>> )], begin _pipe@6 = gleam@list:sort( erlang:element( 11, Comment ), fun sort_comments/2 ), gleam@list:map( _pipe@6, fun(Child@1) -> lustre@element@html:'div'( [lustre@attribute:class( <<"chilp-oat-enhance-inset-quoteblock"/utf8>> )], [view_rendered_comment( Child@1, Bsky_op_profile, Mastodon_op_profile )] ) end ) end ) end] )] ) end ) end ). -file("src/chilp.gleam", 1442). -spec js_browse(binary()) -> nil. js_browse(_) -> nil. -file("src/chilp.gleam", 1374). -spec browse(binary()) -> lustre@effect:effect(any()). browse(To) -> lustre@effect:from(fun(_) -> js_browse(To) end). -file("src/chilp.gleam", 1477). -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.gleam", 1468). -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.gleam", 1197). -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.gleam", 1548). -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.gleam", 1582). ?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.gleam", 1524). -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.gleam", 1336). -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.gleam", 1625). -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://bsky.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.gleam", 1186). -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.gleam", 453). ?DOC(false). -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.gleam", 1151). -spec placeholder_instance(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.gleam", 1077). -spec view_mastodon_respond_form(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.gleam", 537). -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 chilp-oat-enhance-hide"/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:button( [lustre@attribute:role(<<"tab"/utf8>>), lustre@event:on_click({set_tab, 1}), lustre@attribute:classes( [{<<"tab"/utf8>>, true}, {<<"tab-active outline"/utf8>>, erlang:element(10, Model) =:= 1}] )], [lustre@element@html:text( <<"Mastodon"/utf8>> )] ), lustre@element@html:button( [lustre@attribute:role(<<"tab"/utf8>>), lustre@event:on_click({set_tab, 2}), lustre@attribute:classes( [{<<"tab"/utf8>>, true}, {<<"tab-active outline"/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.gleam", 530). ?DOC(false). -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.gleam", 367). ?DOC( " # Widget activation\n" " \n" " You should run this register function before using the widget component, so that Chilp can\n" " listen for it and load the component contents.\n" ). -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>>).