UI improvements

This commit is contained in:
Thomas Sileo 2022-06-25 10:20:07 +02:00
parent f66e3f3995
commit 4f1b51f7d5
15 changed files with 145 additions and 52 deletions

View file

@ -47,6 +47,10 @@ class Actor:
def preferred_username(self) -> str: def preferred_username(self) -> str:
return self.ap_actor["preferredUsername"] return self.ap_actor["preferredUsername"]
@property
def display_name(self) -> str:
return self.name or self.preferred_username
@property @property
def handle(self) -> str: def handle(self) -> str:
return _handle(self.ap_actor) return _handle(self.ap_actor)

View file

@ -19,6 +19,14 @@ class Object:
def is_from_db(self) -> bool: def is_from_db(self) -> bool:
return False return False
@property
def is_from_outbox(self) -> bool:
return False
@property
def is_from_inbox(self) -> bool:
return False
@property @property
def ap_type(self) -> str: def ap_type(self) -> str:
return self.ap_object["type"] return self.ap_object["type"]

View file

@ -237,6 +237,11 @@ def send_create(
raise ValueError("Object has no context") raise ValueError("Object has no context")
context = in_reply_to_object.ap_context context = in_reply_to_object.ap_context
if in_reply_to_object.is_from_outbox:
db.query(models.OutboxObject).filter(
models.OutboxObject.ap_id == in_reply_to,
).update({"replies_count": models.OutboxObject.replies_count + 1})
for (upload, filename) in uploads: for (upload, filename) in uploads:
attachments.append(upload_to_attachment(upload, filename)) attachments.append(upload_to_attachment(upload, filename))
@ -501,6 +506,11 @@ def _handle_create_activity(
logger.info(f"Invalid tags: {tags}") logger.info(f"Invalid tags: {tags}")
return None return None
if created_object.in_reply_to and created_object.in_reply_to.startswith(BASE_URL):
db.query(models.OutboxObject).filter(
models.OutboxObject.ap_id == created_object.in_reply_to,
).update({"replies_count": models.OutboxObject.replies_count + 1})
for tag in tags: for tag in tags:
if tag.get("name") == LOCAL_ACTOR.handle or tag.get("href") == LOCAL_ACTOR.url: if tag.get("name") == LOCAL_ACTOR.handle or tag.get("href") == LOCAL_ACTOR.url:
notif = models.Notification( notif = models.Notification(

View file

@ -59,9 +59,6 @@ from app.uploads import UPLOAD_DIR
# - inbox/outbox in the admin (as in show every objects) # - inbox/outbox in the admin (as in show every objects)
# - show likes/announces counter for outbox activities # - show likes/announces counter for outbox activities
# - update actor support # - update actor support
# - replies support
# - file upload + place/exif extraction (or not) support
# - custom emoji support
# - hash config/profile to detect when to send Update actor # - hash config/profile to detect when to send Update actor
# #
# - [ ] block support # - [ ] block support
@ -72,13 +69,6 @@ from app.uploads import UPLOAD_DIR
# - [ ] custom emoji # - [ ] custom emoji
# - [ ] poll/questions support # - [ ] poll/questions support
# - [ ] cleanup tasks # - [ ] cleanup tasks
# - notifs:
# - MENTIONED
# - LIKED
# - ANNOUNCED
# - FOLLOWED
# - UNFOLLOWED
# - POLL_ENDED
app = FastAPI(docs_url=None, redoc_url=None) app = FastAPI(docs_url=None, redoc_url=None)
app.mount("/static", StaticFiles(directory="app/static"), name="static") app.mount("/static", StaticFiles(directory="app/static"), name="static")

View file

@ -114,6 +114,14 @@ class InboxObject(Base, BaseObject):
else: else:
return None return None
@property
def is_from_db(self) -> bool:
return True
@property
def is_from_inbox(self) -> bool:
return True
class OutboxObject(Base, BaseObject): class OutboxObject(Base, BaseObject):
__tablename__ = "outbox" __tablename__ = "outbox"
@ -221,6 +229,14 @@ class OutboxObject(Base, BaseObject):
else: else:
return None return None
@property
def is_from_db(self) -> bool:
return True
@property
def is_from_outbox(self) -> bool:
return True
class Follower(Base): class Follower(Base):
__tablename__ = "follower" __tablename__ = "follower"

View file

@ -133,3 +133,10 @@ nav.flexbox {
} }
} }
} }
.actor-action {
padding-left:70px;
margin-top:20px;
span {
float: right;
}
}

View file

@ -183,8 +183,21 @@ def _has_media_type(attachment: Attachment, media_type_prefix: str) -> bool:
return attachment.media_type.startswith(media_type_prefix) return attachment.media_type.startswith(media_type_prefix)
def _format_date(dt: datetime) -> str:
return dt.strftime("%b %d, %Y, %H:%M")
def _pluralize(count: int, singular: str = "", plural: str = "s") -> str:
if count > 1:
return plural
else:
return singular
_templates.env.filters["domain"] = _filter_domain _templates.env.filters["domain"] = _filter_domain
_templates.env.filters["media_proxy_url"] = _media_proxy_url _templates.env.filters["media_proxy_url"] = _media_proxy_url
_templates.env.filters["clean_html"] = _clean_html _templates.env.filters["clean_html"] = _clean_html
_templates.env.filters["timeago"] = _timeago _templates.env.filters["timeago"] = _timeago
_templates.env.filters["format_date"] = _format_date
_templates.env.filters["has_media_type"] = _has_media_type _templates.env.filters["has_media_type"] = _has_media_type
_templates.env.filters["pluralize"] = _pluralize

View file

@ -7,13 +7,8 @@
{{ utils.display_object(inbox_object.relates_to_anybox_object) }} {{ utils.display_object(inbox_object.relates_to_anybox_object) }}
{% elif inbox_object.ap_type in ["Article", "Note", "Video"] %} {% elif inbox_object.ap_type in ["Article", "Note", "Video"] %}
{{ utils.display_object(inbox_object) }} {{ utils.display_object(inbox_object) }}
{% if inbox_object.liked_via_outbox_object_ap_id %} {% elif inbox_object.ap_type == "Follow" %}
{{ utils.admin_undo_button(inbox_object.liked_via_outbox_object_ap_id, "Unlike") }} {{ utils.display_object(inbox_object) }}
{% else %}
{{ utils.admin_like_button(inbox_object.ap_id) }}
{% endif %}
{{ utils.admin_announce_button(inbox_object.ap_id) }}
{{ utils.admin_reply_button(inbox_object.ap_id) }}
{% else %} {% else %}
Implement {{ inbox_object.ap_type }} Implement {{ inbox_object.ap_type }}
{% endif %} {% endif %}

View file

@ -8,13 +8,6 @@
{{ utils.display_object(outbox_object.relates_to_anybox_object) }} {{ utils.display_object(outbox_object.relates_to_anybox_object) }}
{% elif outbox_object.ap_type in ["Article", "Note", "Video"] %} {% elif outbox_object.ap_type in ["Article", "Note", "Video"] %}
{{ utils.display_object(outbox_object) }} {{ utils.display_object(outbox_object) }}
{% if outbox_object.liked_via_outbox_object_ap_id %}
{{ utils.admin_undo_button(outbox_object.liked_via_outbox_object_ap_id, "Unlike") }}
{% else %}
{{ utils.admin_like_button(outbox_object.ap_id) }}
{% endif %}
{{ utils.admin_announce_button(outbox_object.ap_id) }}
{{ utils.admin_reply_button(outbox_object.ap_id) }}
{% else %} {% else %}
Implement {{ outbox_object.ap_type }} Implement {{ outbox_object.ap_type }}
{% endif %} {% endif %}

View file

@ -7,13 +7,6 @@
{{ utils.display_object(inbox_object.relates_to_anybox_object) }} {{ utils.display_object(inbox_object.relates_to_anybox_object) }}
{% elif inbox_object.ap_type in ["Article", "Note", "Video"] %} {% elif inbox_object.ap_type in ["Article", "Note", "Video"] %}
{{ utils.display_object(inbox_object) }} {{ utils.display_object(inbox_object) }}
{% if inbox_object.liked_via_outbox_object_ap_id %}
{{ utils.admin_undo_button(inbox_object.liked_via_outbox_object_ap_id, "Unlike") }}
{% else %}
{{ utils.admin_like_button(inbox_object.ap_id) }}
{% endif %}
{{ utils.admin_announce_button(inbox_object.ap_id) }}
{{ utils.admin_reply_button(inbox_object.ap_id) }}
{% endif %} {% endif %}
{% endfor %} {% endfor %}

View file

@ -1,4 +1,4 @@
{%- import "utils.html" as utils -%} {%- import "utils.html" as utils with context -%}
{% extends "layout.html" %} {% extends "layout.html" %}
{% block content %} {% block content %}
{% include "header.html" %} {% include "header.html" %}

View file

@ -14,8 +14,8 @@
</div> </div>
{%- macro header_link(url, text) -%} {%- macro header_link(url, text) -%}
{% set url_for = request.url_for(url) %} {% set url_for = request.app.router.url_path_for(url) %}
<a href="{{ url_for }}" {% if request.url == url_for %}class="active"{% endif %}>{{ text }}</a> <a href="{{ url_for }}" {% if request.url.path == url_for %}class="active"{% endif %}>{{ text }}</a>
{% endmacro %} {% endmacro %}
<div style="margin:30px 0;"> <div style="margin:30px 0;">

View file

@ -4,8 +4,6 @@
{% include "header.html" %} {% include "header.html" %}
{% for outbox_object in objects %} {% for outbox_object in objects %}
{{ outbox_object.likes_count }}
{{ outbox_object.announces_count }}
{{ utils.display_object(outbox_object) }} {{ utils.display_object(outbox_object) }}
{% endfor %} {% endfor %}

View file

@ -5,7 +5,12 @@
{% macro display_replies_tree(replies_tree_node) %} {% macro display_replies_tree(replies_tree_node) %}
{{ utils.display_object(replies_tree_node.ap_object) }} {% if replies_tree_node.is_requested %}
{{ utils.display_object_expanded(replies_tree_node.ap_object) }}
{% else %}
{{ utils.display_object(replies_tree_node.ap_object) }}
{% endif %}
{% for child in replies_tree_node.children %} {% for child in replies_tree_node.children %}
{{ display_replies_tree(child) }} {{ display_replies_tree(child) }}
{% endfor %} {% endfor %}

View file

@ -60,7 +60,6 @@
{% endmacro %} {% endmacro %}
{% macro display_actor(actor, actors_metadata) %} {% macro display_actor(actor, actors_metadata) %}
{{ actors_metadata }}
{% set metadata = actors_metadata.get(actor.ap_id) %} {% set metadata = actors_metadata.get(actor.ap_id) %}
<div style="display: flex;column-gap: 20px;margin:20px 0 10px 0;" class="actor-box"> <div style="display: flex;column-gap: 20px;margin:20px 0 10px 0;" class="actor-box">
<div style="flex: 0 0 48px;"> <div style="flex: 0 0 48px;">
@ -71,19 +70,20 @@
<div>{{ actor.handle }}</div> <div>{{ actor.handle }}</div>
</a> </a>
</div> </div>
{% if metadata %} {% if is_admin and metadata %}
<div> <div>
<nav class="flexbox"> <nav class="flexbox">
<ul> <ul>
<li> {% if metadata.is_following %}
{% if metadata.is_following %}already following {{ admin_undo_button(metadata.outbox_follow_ap_id, "Unfollow")}} <li>already following</li>
{% elif metadata.is_follow_request_sent %}follow request sent <li>{{ admin_undo_button(metadata.outbox_follow_ap_id, "Unfollow")}}</li>
{% elif metadata.is_follow_request_sent %}
<li>follow request sent</li>
{% else %} {% else %}
{{ admin_follow_button(actor) }} <li>{{ admin_follow_button(actor) }}</li>
{% endif %} {% endif %}
</li> {% if metadata.is_follower %}
<li> <li>follows you</li>
{% if metadata.is_follower %}follows you{% else %}
{% endif %} {% endif %}
</li> </li>
</ul> </ul>
@ -93,6 +93,31 @@
{% endmacro %} {% endmacro %}
{% macro display_object_expanded(object) %}
<div class="activity-expanded">
{{ display_actor(object.actor, {}) }}
<div>
{{ object.content | clean_html | safe }}
</div>
<a href="{{ object.url }}">{{ object.ap_published_at | format_date }}</a>
{{ object.visibility.value }}
{% if object.is_from_outbox %}
{{ object.likes_count }} likes
{% endif %}
{% if object.is_from_outbox %}
{{ object.announces_count }} shares
{% endif %}
</div>
{% endmacro %}
{% macro display_object(object) %} {% macro display_object(object) %}
{% if object.ap_type in ["Note", "Article", "Video"] %} {% if object.ap_type in ["Note", "Article", "Video"] %}
<div class="activity-wrap" id="{{ object.permalink_id }}"> <div class="activity-wrap" id="{{ object.permalink_id }}">
@ -132,21 +157,57 @@
</div> </div>
{% endif %} {% endif %}
<div class="activity-bar"> <div class="activity-bar">
{% if object.is_from_outbox %}
<div class="bar-item"> <div class="bar-item">
<div class="comment-count">33</div> <div class="comment-count">{{ object.likes_count }} like{{ object.likes_count | pluralize }}</div>
</div> </div>
<div class="bar-item"> <div class="bar-item">
<div class="retweet-count">397</div> <div class="retweet-count">{{ object.announces_count }} share{{ object.announces_count | pluralize }}</div>
</div> </div>
<div class="bar-item"> <div class="bar-item">
<div class="likes-count"> <div class="retweet-count">{{ object.replies_count }} repl{{ object.replies_count | pluralize("y", "ies") }}</div>
2.6k
</div>
</div> </div>
{% if is_admin %}
<div class="bar-item">
{{ admin_reply_button(object.ap_id) }}
</div>
{% endif %}
{% endif %}
{% if object.is_from_inbox %}
{% if object.liked_via_outbox_object_ap_id %}
<div class="bar-item">
{{ admin_undo_button(object.liked_via_outbox_object_ap_id, "Unlike") }}
</div>
{% else %}
<div class="bar-item">
{{ admin_like_button(object.ap_id) }}
</div>
{% endif %}
<div class="bar-item">
{{ admin_announce_button(object.ap_id) }}
</div>
<div class="bar-item">
{{ admin_reply_button(object.ap_id) }}
</div>
{% endif %}
</div> </div>
</div> </div>
{% elif object.ap_type == "Follow" %}
{% if object.is_from_inbox %}
<div class="actor-action">
{{ object.actor.display_name }} followed you
<span>{{ object.ap_published_at | timeago }}</span>
</div>
{{ display_actor(object.actor, {}) }}
{% endif %}
{% endif %} {% endif %}
{% endmacro %} {% endmacro %}