{% macro embed_csrf_token() %} <input type="hidden" name="csrf_token" value="{{ csrf_token }}"> {% endmacro %} {% macro embed_redirect_url(permalink_id=None) %} <input type="hidden" name="redirect_url" value="{{ request.url }}{% if permalink_id %}#{{ permalink_id }}{% endif %}"> {% endmacro %} {% macro admin_block_button(actor) %} <form action="{{ request.url_for("admin_actions_block") }}" method="POST"> {{ embed_csrf_token() }} {{ embed_redirect_url() }} <input type="hidden" name="ap_actor_id" value="{{ actor.ap_id }}"> <input type="submit" value="block"> </form> {% endmacro %} {% macro admin_unblock_button(actor) %} <form action="{{ request.url_for("admin_actions_unblock") }}" method="POST"> {{ embed_csrf_token() }} {{ embed_redirect_url() }} <input type="hidden" name="ap_actor_id" value="{{ actor.ap_id }}"> <input type="submit" value="unblock"> </form> {% endmacro %} {% macro admin_follow_button(actor) %} <form action="{{ request.url_for("admin_actions_follow") }}" method="POST"> {{ embed_csrf_token() }} {{ embed_redirect_url() }} <input type="hidden" name="ap_actor_id" value="{{ actor.ap_id }}"> <input type="submit" value="follow"> </form> {% endmacro %} {% macro admin_accept_incoming_follow_button(notif) %} <form action="{{ request.url_for("admin_actions_accept_incoming_follow") }}" method="POST"> {{ embed_csrf_token() }} {{ embed_redirect_url() }} <input type="hidden" name="notification_id" value="{{ notif.id }}"> <input type="submit" value="accept follow"> </form> {% endmacro %} {% macro admin_reject_incoming_follow_button(notif) %} <form action="{{ request.url_for("admin_actions_reject_incoming_follow") }}" method="POST"> {{ embed_csrf_token() }} {{ embed_redirect_url() }} <input type="hidden" name="notification_id" value="{{ notif.id }}"> <input type="submit" value="reject follow"> </form> {% endmacro %} {% macro admin_like_button(ap_object_id, permalink_id) %} <form action="{{ request.url_for("admin_actions_like") }}" method="POST"> {{ embed_csrf_token() }} {{ embed_redirect_url(permalink_id) }} <input type="hidden" name="ap_object_id" value="{{ ap_object_id }}"> <input type="submit" value="like"> </form> {% endmacro %} {% macro admin_bookmark_button(ap_object_id, permalink_id) %} <form action="{{ request.url_for("admin_actions_bookmark") }}" method="POST"> {{ embed_csrf_token() }} {{ embed_redirect_url(permalink_id) }} <input type="hidden" name="ap_object_id" value="{{ ap_object_id }}"> <input type="submit" value="bookmark"> </form> {% endmacro %} {% macro admin_unbookmark_button(ap_object_id, permalink_id) %} <form action="{{ request.url_for("admin_actions_unbookmark") }}" method="POST"> {{ embed_csrf_token() }} {{ embed_redirect_url(permalink_id) }} <input type="hidden" name="ap_object_id" value="{{ ap_object_id }}"> <input type="submit" value="unbookmark"> </form> {% endmacro %} {% macro admin_pin_button(ap_object_id, permalink_id) %} <form action="{{ request.url_for("admin_actions_pin") }}" method="POST"> {{ embed_csrf_token() }} {{ embed_redirect_url(permalink_id) }} <input type="hidden" name="ap_object_id" value="{{ ap_object_id }}"> <input type="submit" value="pin"> </form> {% endmacro %} {% macro admin_unpin_button(ap_object_id, permalink_id) %} <form action="{{ request.url_for("admin_actions_unpin") }}" method="POST"> {{ embed_csrf_token() }} {{ embed_redirect_url(permalink_id) }} <input type="hidden" name="ap_object_id" value="{{ ap_object_id }}"> <input type="submit" value="unpin"> </form> {% endmacro %} {% macro admin_delete_button(ap_object_id) %} <form action="{{ request.url_for("admin_actions_delete") }}" method="POST" onsubmit="return confirm('Do you really want to delete this object?');"> {{ embed_csrf_token() }} {{ embed_redirect_url() }} <input type="hidden" name="ap_object_id" value="{{ ap_object_id }}"> <input type="submit" value="delete"> </form> {% endmacro %} {% macro admin_announce_button(ap_object_id, disabled=False, permalink_id=None) %} <form action="{{ request.url_for("admin_actions_announce") }}" method="POST"> {{ embed_csrf_token() }} {{ embed_redirect_url(permalink_id) }} <input type="hidden" name="ap_object_id" value="{{ ap_object_id }}"> <input type="submit" value="share" {% if disabled %}title="Cannot share non-public content" disabled{% endif %}> </form> {% endmacro %} {% macro admin_undo_button(ap_object_id, action="undo", permalink_id=None) %} <form action="{{ request.url_for("admin_actions_undo") }}" method="POST"> {{ embed_csrf_token() }} {{ embed_redirect_url(permalink_id) }} <input type="hidden" name="ap_object_id" value="{{ ap_object_id }}"> <input type="submit" value="{{ action }}"> </form> {% endmacro %} {% macro sensitive_button(permalink_id) %} <form action="{{ request.url }}#{{ permalink_id }}" method="GET"> <input type="hidden" name="show_sensitive" value="{{ permalink_id }}"> {% for k, v in request.query_params.items() %} <input type="hidden" name="{{k}}" value="{{v}}"> {% endfor %} <button type="submit" class="show-sensitive-btn">display sensitive content</button> </form> {% endmacro %} {% macro hide_sensitive_button(permalink_id) %} <form action="{{ request.url }}#{{ permalink_id }}" method="GET"> {% for k, v in request.query_params.items() %} {% if not (k == "show_sensitive" and v == permalink_id) %} <input type="hidden" name="{{k}}" value="{{v}}"> {% endif %} {% endfor %} <button type="submit" class="show-sensitive-btn">hide sensitive content</button> </form> {% endmacro %} {% macro show_more_button(permalink_id) %} <form action="{{ request.url }}#{{ permalink_id }}" method="GET"> <input type="hidden" name="show_more" value="{{ permalink_id }}"> {% for k, v in request.query_params.items() %} <input type="hidden" name="{{k}}" value="{{v}}"> {% endfor %} <button type="submit" class="show-more-btn">show more</button> </form> {% endmacro %} {% macro show_less_button(permalink_id) %} <form action="{{ request.url }}#{{ permalink_id }}" method="GET"> {% for k, v in request.query_params.items() %} {% if not (k == "show_more" and v == permalink_id) %} <input type="hidden" name="{{k}}" value="{{v}}"> {% endif %} {% endfor %} <button type="submit" class="show-more-btn">show less</button> </form> {% endmacro %} {% macro admin_reply_button(ap_object_id) %} <form action="/admin/new" method="GET"> <input type="hidden" name="in_reply_to" value="{{ ap_object_id }}"> <button type="submit">reply</button> </form> {% endmacro %} {% macro admin_profile_button(ap_actor_id) %} <form action="{{ url_for("admin_profile") }}" method="GET"> <input type="hidden" name="actor_id" value="{{ ap_actor_id }}"> <button type="submit">profile</button> </form> {% endmacro %} {% macro admin_expand_button(ap_object_id) %} <form action="{{ url_for("admin_object") }}" method="GET"> <input type="hidden" name="ap_id" value="{{ ap_object_id }}"> <button type="submit">expand</button> </form> {% endmacro %} {% macro display_box_filters(route) %} <nav class="flexbox box"> <ul> <li>Filter by</li> {% for ap_type in ["Note", "Article", "Page", "Question", "Like", "Announce", "Follow"] %} <li><a href="{{ url_for(route) }}?filter_by={{ ap_type }}" {% if request.query_params.filter_by == ap_type %}class="active"{% endif %}> {{ ap_type }} </a> </li> {% endfor %} {% if request.query_params.filter_by %} <li> <a href="{{ url_for(route) }}">Reset filter</a> </li> {% endif %} </ul> </nav> {% endmacro %} {% macro actor_action(inbox_object, text) %} <div class="actor-action"> <a href="{{ url_for("admin_profile") }}?actor_id={{ inbox_object.actor.ap_id }}">{{ inbox_object.actor.display_name | clean_html(inbox_object.actor) | safe }}</a> {{ text }} <span title="{{ inbox_object.ap_published_at.isoformat() }}">{{ inbox_object.ap_published_at | timeago }}</span> </div> {% endmacro %} {% macro display_actor(actor, actors_metadata={}, embedded=False, with_details=False, pending_incoming_follow_notif=None) %} {% set metadata = actors_metadata.get(actor.ap_id) %} {% if not embedded %} <div class="ap-object"> {% endif %} <div class="actor-box h-card p-author"> <div class="icon-box"> <img src="{{ actor.resized_icon_url }}" alt="{{ actor.display_name }}'s avatar" class="actor-icon u-photo"> </div> <a href="{{ actor.url }}" class="u-url" style=""> <div><strong>{{ actor.display_name | clean_html(actor) | safe }}</strong></div> <div class="actor-handle p-name">{{ actor.handle }}</div> </a> </div> {% if is_admin and metadata %} <div> <nav class="flexbox actor-metadata"> <ul> {% if metadata.is_following %} <li>already following</li> <li>{{ admin_undo_button(metadata.outbox_follow_ap_id, "unfollow")}}</li> <li>{{ admin_profile_button(actor.ap_id) }}</li> {% elif metadata.is_follow_request_sent %} <li>follow request sent</li> <li>{{ admin_undo_button(metadata.outbox_follow_ap_id, "undo follow") }}</li> {% else %} <li>{{ admin_follow_button(actor) }}</li> {% endif %} {% if metadata.is_follower %} <li>follows you</li> {% if not metadata.is_following %} <li>{{ admin_profile_button(actor.ap_id) }}</li> {% endif %} </li> {% endif %} {% if actor.is_from_db %} {% if actor.is_blocked %} <li>blocked</li> <li>{{ admin_unblock_button(actor) }}</li> {% else %} <li>{{ admin_block_button(actor) }}</li> {% endif %} {% endif %} {% if pending_incoming_follow_notif %} {% if not pending_incoming_follow_notif.is_accepted and not pending_incoming_follow_notif.is_rejected %} <li> {{ admin_accept_incoming_follow_button(pending_incoming_follow_notif) }} </li> <li> {{ admin_reject_incoming_follow_button(pending_incoming_follow_notif) }} </li> {% elif pending_incoming_follow_notif.is_accepted %} <li>accepted</li> {% else %} <li>rejected</li> {% endif %} {% endif %} </ul> </nav> </div> {% endif %} {% if with_details %} {% if actor.summary %} <div class="p-note"> {{ actor.summary | clean_html(actor) | safe }} </div> {% endif %} {% if actor.attachments %} <div id="profile-props"> <dl> {% for prop in actor.attachments %} {% if prop.type == "PropertyValue" %} <dt>{{ prop.name }}</dt> <dd>{{ prop.value | clean_html(actor) | safe }}</dd> {% endif %} {% endfor %} </dl> </div> {% endif %} {% endif %} {% if not embedded %} </div> {% endif %} {% endmacro %} {% macro display_og_meta(object) %} {% if object.og_meta %} {% for og_meta in object.og_meta %} <div class="activity-og-meta" style="display:flex;column-gap: 20px;margin:20px 0;"> {% if og_meta.image %} <div> <img src="{{ og_meta.image | media_proxy_url }}" style="max-width:200px;max-height:100px;"> </div> <div> <a href="{{ og_meta.url }}">{{ og_meta.title }}</a> {% if og_meta.site_name %} <small style="display:block;">{{ og_meta.site_name }}</small> {% endif %} </div> {% endif %} </div> {% endfor %} {% endif %} {% endmacro %} {% macro display_attachments(object) %} {% if object.attachments and object.sensitive and not object.permalink_id in request.query_params.getlist("show_sensitive") %} {{ sensitive_button(object.permalink_id )}} {% endif %} {% if object.attachments and (not object.sensitive or (object.sensitive and object.permalink_id in request.query_params.getlist("show_sensitive"))) %} {% if object.sensitive %} {{ hide_sensitive_button(object.permalink_id) }} {% endif %} {% for attachment in object.attachments %} {% if attachment.type == "Image" or (attachment | has_media_type("image")) %} <img src="{{ attachment.resized_url or attachment.proxied_url }}"{% if attachment.name %} title="{{ attachment.name }}" alt="{{ attachment.name }}"{% endif %} class="attachment"> {% elif attachment.type == "Video" or (attachment | has_media_type("video")) %} <video controls preload="metadata" src="{{ attachment.url | media_proxy_url }}"{% if attachment.name %} title="{{ attachment.name }}"{% endif %} class="attachment"></video> {% elif attachment.type == "Audio" or (attachment | has_media_type("audio")) %} <audio controls preload="metadata" src="{{ attachment.url | media_proxy_url }}"{% if attachment.name%} title="{{ attachment.name }}"{% endif %} style="width:480px;" class="attachment"></audio> {% elif attachment.type == "Link" %} <a href="{{ attachment.url }}" class="attachment" style="display:inline-block;margin-bottom: 15px;">{{ attachment.url }}</a> {% else %} <a href="{{ attachment.url | media_proxy_url }}"{% if attachment.name %} title="{{ attachment.name }}"{% endif %} class="attachment">{{ attachment.url }}</a> {% endif %} {% endfor %} {% endif %} {% endmacro %} {% macro display_object(object, likes=[], shares=[], webmentions=[], expanded=False, actors_metadata={}, is_object_page=False) %} {% set is_article_mode = object.is_from_outbox and object.ap_type == "Article" and is_object_page %} {% if object.ap_type in ["Note", "Article", "Video", "Page", "Question"] %} <div class="ap-object {% if expanded %}ap-object-expanded {% endif %}h-entry" id="{{ object.permalink_id }}"> {% if is_article_mode %} <data class="h-card"> <data class="u-photo" value="{{ local_actor.icon_url }}"></data> <data class="u-url" value="{{ local_actor.url}}"></data> <data class="p-name" value="{{ local_actor.handle }}"></data> </data> {% else %} {{ display_actor(object.actor, actors_metadata, embedded=True) }} {% endif %} {% if object.in_reply_to %} <a href="{% if is_admin %}{{ url_for("get_lookup") }}?query={% endif %}{{ object.in_reply_to }}" title="{{ object.in_reply_to }}" class="in-reply-to" rel="nofollow"> in reply to {{ object.in_reply_to|truncate(64, True) }} </a> {% endif %} {% if object.ap_type == "Article" %} <h2 class="p-name" style="margin-top:0;">{{ object.name }}</h2> {% endif %} {% if is_article_mode %} <time class="dt-published muted" datetime="{{ object.ap_published_at.replace(microsecond=0).isoformat() }}" title="{{ object.ap_published_at.replace(microsecond=0).isoformat() }}">{{ object.ap_published_at.strftime("%b %d, %Y") }}</time> {% endif %} {% if object.summary %} <p class="p-summary">{{ object.summary | clean_html(object) | safe }}</p> {% endif %} {% if object.sensitive and object.permalink_id not in request.query_params.getlist("show_more") %} {{ show_more_button(object.permalink_id) }} {% endif %} {% if not object.sensitive or (object.sensitive and object.permalink_id in request.query_params.getlist("show_more")) %} {% if object.sensitive %} {{ show_less_button(object.permalink_id) }} {% endif %} <div class="e-content"> {{ object.content | clean_html(object) | safe }} </div> {% endif %} {% if object.ap_type == "Question" and (not object.sensitive or (object.sensitive and object.permalink_id in request.query_params.getlist("show_more"))) %} {% set can_vote = is_admin and object.is_from_inbox and not object.is_poll_ended and not object.voted_for_answers %} {% if can_vote %} <form action="{{ request.url_for("admin_actions_vote") }}" method="POST"> {{ embed_csrf_token() }} {{ embed_redirect_url(object.permalink_id) }} <input type="hidden" name="in_reply_to" value="{{ object.ap_id }}"> {% endif %} {% if object.poll_items %} <ul style="list-style-type: none;padding:0;"> {% for item in object.poll_items %} <li style="display:block;"> {% set pct = item | poll_item_pct(object.poll_voters_count) %} <p style="margin:20px 0 10px 0;"> {% if can_vote %} <input type="{% if object.is_one_of_poll %}radio{% else %}checkbox{% endif %}" name="name" value="{{ item.name }}" id="{{object.permalink_id}}-{{item.name}}"> <label for="{{object.permalink_id}}-{{item.name}}"> {% endif %} {{ item.name | clean_html(object) | safe }} {% if object.voted_for_answers and item.name in object.voted_for_answers %} <span class="muted" style="padding-left:20px;">you voted for this answer</span> {% endif %} {% if can_vote %} </label> {% endif %} <span style="float:right;">{{ pct }}% <span class="muted">({{ item.replies.totalItems }} votes)</span></span> </p> <svg class="poll-bar"> <line x1="0" y1="10px" x2="{{ pct or 1 }}%" y2="10px" style="stroke-width: 20px;"></line> </svg> </li> {% endfor %} </ul> {% endif %} {% if can_vote %} <p class="form"> <input type="submit" value="vote"> </p> </form> {% endif %} {% endif %} {{ display_og_meta(object) }} <div class="activity-attachment"> {{ display_attachments(object) }} </div> <nav class="flexbox activity-bar"> <ul> <li> <div><a href="{{ object.url }}"{% if object.is_from_inbox %} rel="nofollow"{% endif %} class="object-permalink u-url u-uid">permalink</a></div> </li> {% if not is_article_mode %} <li> <time class="dt-published" datetime="{{ object.ap_published_at.replace(microsecond=0).isoformat() }}" title="{{ object.ap_published_at.replace(microsecond=0).isoformat() }}">{{ object.ap_published_at | timeago }}</time> </li> {% endif %} {% if object.ap_type == "Question" %} {% if object.poll_end_time %} <li> {% if object.is_poll_ended %}ended{% else %}ends{% endif %} <time title="{{ object.poll_end_time.replace(microsecond=0).isoformat() }}"> {{ object.poll_end_time | timeago }} </time> </li> {% endif %} <li> {{ object.poll_voters_count }} voters </li> {% endif %} {% if is_admin %} <li> {{ object.visibility.value }} </li> {% endif %} {% if object.is_from_outbox %} {% if object.likes_count %} <li> <a href="{{ object.url }}"><strong>{{ object.likes_count }}</strong> like{{ object.likes_count | pluralize }}</a> </li> {% endif %} {% if object.announces_count %} <li> <a href="{{ object.url }}"><strong>{{ object.announces_count }}</strong> share{{ object.announces_count | pluralize }}</a> </li> {% endif %} {% if object.webmentions_count %} <li> <a href="{{ object.url }}"><strong>{{ object.webmentions_count }}</strong> webmention{{ object.webmentions_count | pluralize }}</a> </li> {% endif %} {% endif %} {% if (object.is_from_outbox or is_admin) and object.replies_count %} <li> <a href="{% if is_admin and not object.is_from_outbox %}{{ url_for("admin_object") }}?ap_id={{ object.ap_id }}{% else %}{{ object.url }}{% endif %}"><strong>{{ object.replies_count }}</strong> repl{{ object.replies_count | pluralize("y", "ies") }}</a> </li> {% endif %} </ul> </nav> {% if is_admin and (object.is_from_outbox or object.is_from_inbox) %} <nav class="flexbox activity-bar"> <ul> {% if object.is_from_outbox %} <li> {{ admin_delete_button(object.ap_id) }} </li> <li> {% if object.is_pinned %} {{ admin_unpin_button(object.ap_id, object.permalink_id) }} {% else %} {{ admin_pin_button(object.ap_id, object.permalink) }} {% endif %} </li> {% endif %} <li> {{ admin_reply_button(object.ap_id) }} </li> {% if object.is_from_inbox %} <li> {% if object.liked_via_outbox_object_ap_id %} {{ admin_undo_button(object.liked_via_outbox_object_ap_id, "unlike", object.permalink_id) }} {% else %} {{ admin_like_button(object.ap_id, object.permalink_id) }} {% endif %} </li> <li> {% if object.is_bookmarked %} {{ admin_unbookmark_button(object.ap_id, object.permalink_id) }} {% else %} {{ admin_bookmark_button(object.ap_id, object.permalink_id) }} {% endif %} </li> <li> {% if object.announced_via_outbox_object_ap_id %} {{ admin_undo_button(object.liked_via_outbox_object_ap_id, "unshare") }} {% else %} {{ admin_announce_button(object.ap_id, disabled=object.visibility not in [visibility_enum.PUBLIC, visibility_enum.UNLISTED], permalink_id=object.permalink_id) }} {% endif %} </li> <li> {{ admin_profile_button(object.actor.ap_id) }} </li> {% endif %} <li> {{ admin_expand_button(object.ap_id) }} </li> </ul> </nav> {% endif %} {% if likes or shares or webmentions %} <div style="display: flex;column-gap: 20px;flex-wrap: wrap;margin-top:20px;"> {% if likes %} <div style="flex: 0 1 30%;max-width: 50%;">Likes <div style="display: flex;column-gap: 20px;row-gap:20px;flex-wrap: wrap;margin-top:20px;"> {% for like in likes %} <a href="{% if is_admin %}{{ url_for("admin_profile") }}?actor_id={{ like.actor.ap_id }}{% else %}{{ like.actor.url }}{% endif %}" title="{{ like.actor.handle }}" style="height:50px;" rel="noreferrer"> <img src="{{ like.actor.resized_icon_url }}" alt="{{ like.actor.handle}}" style="max-width:50px;"> </a> {% endfor %} </div> </div> {% endif %} {% if shares %} <div style="flex: 0 1 30%;max-width: 50%;">Shares <div style="display: flex;column-gap: 20px;row-gap:20px;flex-wrap: wrap;margin-top:20px;"> {% for share in shares %} <a href="{% if is_admin %}{{ url_for("admin_profile") }}?actor_id={{ share.actor.ap_id }}{% else %}{{ share.actor.url }}{% endif %}" title="{{ share.actor.handle }}" style="height:50px;" rel="noreferrer"> <img src="{{ share.actor.resized_icon_url }}" alt="{{ share.actor.handle}}" style="max-width:50px;"> </a> {% endfor %} </div> </div> {% endif %} {% if webmentions %} <div style="flex: 0 1 30%;max-width: 50%;">Webmentions <div style="display: flex;column-gap: 20px;row-gap:20px;flex-wrap: wrap;margin-top:20px;"> {% for webmention in webmentions %} {% set wm = webmention.as_facepile_item %} {% if wm %} <a href="{{ wm.url }}" title="{{ wm.actor_name }}" style="height:50px;" rel="noreferrer"> <img src="{{ wm.actor_icon_url | media_proxy_url }}" alt="{{ wm.actor_name }}" style="max-width:50px;"> </a> {% endif %} {% endfor %} </div> </div> {% endif %} </div> {% endif %} </div> {% endif %} {% endmacro %}