-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/@/[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, <>} 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.