UI improvements
parent
f66e3f3995
commit
4f1b51f7d5
|
@ -47,6 +47,10 @@ class Actor:
|
|||
def preferred_username(self) -> str:
|
||||
return self.ap_actor["preferredUsername"]
|
||||
|
||||
@property
|
||||
def display_name(self) -> str:
|
||||
return self.name or self.preferred_username
|
||||
|
||||
@property
|
||||
def handle(self) -> str:
|
||||
return _handle(self.ap_actor)
|
||||
|
|
|
@ -19,6 +19,14 @@ class Object:
|
|||
def is_from_db(self) -> bool:
|
||||
return False
|
||||
|
||||
@property
|
||||
def is_from_outbox(self) -> bool:
|
||||
return False
|
||||
|
||||
@property
|
||||
def is_from_inbox(self) -> bool:
|
||||
return False
|
||||
|
||||
@property
|
||||
def ap_type(self) -> str:
|
||||
return self.ap_object["type"]
|
||||
|
|
10
app/boxes.py
10
app/boxes.py
|
@ -237,6 +237,11 @@ def send_create(
|
|||
raise ValueError("Object has no 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:
|
||||
attachments.append(upload_to_attachment(upload, filename))
|
||||
|
||||
|
@ -501,6 +506,11 @@ def _handle_create_activity(
|
|||
logger.info(f"Invalid tags: {tags}")
|
||||
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:
|
||||
if tag.get("name") == LOCAL_ACTOR.handle or tag.get("href") == LOCAL_ACTOR.url:
|
||||
notif = models.Notification(
|
||||
|
|
10
app/main.py
10
app/main.py
|
@ -59,9 +59,6 @@ from app.uploads import UPLOAD_DIR
|
|||
# - inbox/outbox in the admin (as in show every objects)
|
||||
# - show likes/announces counter for outbox activities
|
||||
# - 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
|
||||
#
|
||||
# - [ ] block support
|
||||
|
@ -72,13 +69,6 @@ from app.uploads import UPLOAD_DIR
|
|||
# - [ ] custom emoji
|
||||
# - [ ] poll/questions support
|
||||
# - [ ] cleanup tasks
|
||||
# - notifs:
|
||||
# - MENTIONED
|
||||
# - LIKED
|
||||
# - ANNOUNCED
|
||||
# - FOLLOWED
|
||||
# - UNFOLLOWED
|
||||
# - POLL_ENDED
|
||||
|
||||
app = FastAPI(docs_url=None, redoc_url=None)
|
||||
app.mount("/static", StaticFiles(directory="app/static"), name="static")
|
||||
|
|
|
@ -114,6 +114,14 @@ class InboxObject(Base, BaseObject):
|
|||
else:
|
||||
return None
|
||||
|
||||
@property
|
||||
def is_from_db(self) -> bool:
|
||||
return True
|
||||
|
||||
@property
|
||||
def is_from_inbox(self) -> bool:
|
||||
return True
|
||||
|
||||
|
||||
class OutboxObject(Base, BaseObject):
|
||||
__tablename__ = "outbox"
|
||||
|
@ -221,6 +229,14 @@ class OutboxObject(Base, BaseObject):
|
|||
else:
|
||||
return None
|
||||
|
||||
@property
|
||||
def is_from_db(self) -> bool:
|
||||
return True
|
||||
|
||||
@property
|
||||
def is_from_outbox(self) -> bool:
|
||||
return True
|
||||
|
||||
|
||||
class Follower(Base):
|
||||
__tablename__ = "follower"
|
||||
|
|
|
@ -133,3 +133,10 @@ nav.flexbox {
|
|||
}
|
||||
}
|
||||
}
|
||||
.actor-action {
|
||||
padding-left:70px;
|
||||
margin-top:20px;
|
||||
span {
|
||||
float: right;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -183,8 +183,21 @@ def _has_media_type(attachment: Attachment, media_type_prefix: str) -> bool:
|
|||
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["media_proxy_url"] = _media_proxy_url
|
||||
_templates.env.filters["clean_html"] = _clean_html
|
||||
_templates.env.filters["timeago"] = _timeago
|
||||
_templates.env.filters["format_date"] = _format_date
|
||||
_templates.env.filters["has_media_type"] = _has_media_type
|
||||
_templates.env.filters["pluralize"] = _pluralize
|
||||
|
|
|
@ -7,13 +7,8 @@
|
|||
{{ utils.display_object(inbox_object.relates_to_anybox_object) }}
|
||||
{% elif inbox_object.ap_type in ["Article", "Note", "Video"] %}
|
||||
{{ 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) }}
|
||||
{% elif inbox_object.ap_type == "Follow" %}
|
||||
{{ utils.display_object(inbox_object) }}
|
||||
{% else %}
|
||||
Implement {{ inbox_object.ap_type }}
|
||||
{% endif %}
|
||||
|
|
|
@ -8,13 +8,6 @@
|
|||
{{ utils.display_object(outbox_object.relates_to_anybox_object) }}
|
||||
{% elif outbox_object.ap_type in ["Article", "Note", "Video"] %}
|
||||
{{ 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 %}
|
||||
Implement {{ outbox_object.ap_type }}
|
||||
{% endif %}
|
||||
|
|
|
@ -7,13 +7,6 @@
|
|||
{{ utils.display_object(inbox_object.relates_to_anybox_object) }}
|
||||
{% elif inbox_object.ap_type in ["Article", "Note", "Video"] %}
|
||||
{{ 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 %}
|
||||
{% endfor %}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
{%- import "utils.html" as utils -%}
|
||||
{%- import "utils.html" as utils with context -%}
|
||||
{% extends "layout.html" %}
|
||||
{% block content %}
|
||||
{% include "header.html" %}
|
||||
|
|
|
@ -14,8 +14,8 @@
|
|||
</div>
|
||||
|
||||
{%- macro header_link(url, text) -%}
|
||||
{% set url_for = request.url_for(url) %}
|
||||
<a href="{{ url_for }}" {% if request.url == url_for %}class="active"{% endif %}>{{ text }}</a>
|
||||
{% set url_for = request.app.router.url_path_for(url) %}
|
||||
<a href="{{ url_for }}" {% if request.url.path == url_for %}class="active"{% endif %}>{{ text }}</a>
|
||||
{% endmacro %}
|
||||
|
||||
<div style="margin:30px 0;">
|
||||
|
|
|
@ -4,8 +4,6 @@
|
|||
{% include "header.html" %}
|
||||
|
||||
{% for outbox_object in objects %}
|
||||
{{ outbox_object.likes_count }}
|
||||
{{ outbox_object.announces_count }}
|
||||
{{ utils.display_object(outbox_object) }}
|
||||
{% endfor %}
|
||||
|
||||
|
|
|
@ -5,7 +5,12 @@
|
|||
|
||||
{% 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 %}
|
||||
{{ display_replies_tree(child) }}
|
||||
{% endfor %}
|
||||
|
|
|
@ -60,7 +60,6 @@
|
|||
{% endmacro %}
|
||||
|
||||
{% macro display_actor(actor, actors_metadata) %}
|
||||
{{ actors_metadata }}
|
||||
{% 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="flex: 0 0 48px;">
|
||||
|
@ -71,19 +70,20 @@
|
|||
<div>{{ actor.handle }}</div>
|
||||
</a>
|
||||
</div>
|
||||
{% if metadata %}
|
||||
{% if is_admin and metadata %}
|
||||
<div>
|
||||
<nav class="flexbox">
|
||||
<ul>
|
||||
<li>
|
||||
{% if metadata.is_following %}already following {{ admin_undo_button(metadata.outbox_follow_ap_id, "Unfollow")}}
|
||||
{% elif metadata.is_follow_request_sent %}follow request sent
|
||||
{% if metadata.is_following %}
|
||||
<li>already following</li>
|
||||
<li>{{ admin_undo_button(metadata.outbox_follow_ap_id, "Unfollow")}}</li>
|
||||
{% elif metadata.is_follow_request_sent %}
|
||||
<li>follow request sent</li>
|
||||
{% else %}
|
||||
{{ admin_follow_button(actor) }}
|
||||
<li>{{ admin_follow_button(actor) }}</li>
|
||||
{% endif %}
|
||||
</li>
|
||||
<li>
|
||||
{% if metadata.is_follower %}follows you{% else %}
|
||||
{% if metadata.is_follower %}
|
||||
<li>follows you</li>
|
||||
{% endif %}
|
||||
</li>
|
||||
</ul>
|
||||
|
@ -93,6 +93,31 @@
|
|||
|
||||
{% 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) %}
|
||||
{% if object.ap_type in ["Note", "Article", "Video"] %}
|
||||
<div class="activity-wrap" id="{{ object.permalink_id }}">
|
||||
|
@ -132,21 +157,57 @@
|
|||
</div>
|
||||
{% endif %}
|
||||
<div class="activity-bar">
|
||||
{% if object.is_from_outbox %}
|
||||
<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 class="bar-item">
|
||||
<div class="retweet-count">397</div>
|
||||
<div class="retweet-count">{{ object.announces_count }} share{{ object.announces_count | pluralize }}</div>
|
||||
</div>
|
||||
|
||||
<div class="bar-item">
|
||||
<div class="likes-count">
|
||||
2.6k
|
||||
<div class="retweet-count">{{ object.replies_count }} repl{{ object.replies_count | pluralize("y", "ies") }}</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>
|
||||
{% 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 %}
|
||||
{% endmacro %}
|
||||
|
|
Loading…
Reference in New Issue