Improve DM threads

This commit is contained in:
Thomas Sileo 2022-08-12 10:01:35 +02:00
parent 23afd31bff
commit abfb6355aa
4 changed files with 22 additions and 4 deletions

View file

@ -393,6 +393,9 @@ async def admin_direct_messages(
db_session: AsyncSession = Depends(get_db_session), db_session: AsyncSession = Depends(get_db_session),
cursor: str | None = None, cursor: str | None = None,
) -> templates.TemplateResponse: ) -> templates.TemplateResponse:
# The process for building DMs thread is a bit compex in term of query
# but it does not require an extra tables to index/manage threads
inbox_convos = ( inbox_convos = (
( (
await db_session.execute( await db_session.execute(
@ -407,6 +410,8 @@ async def admin_direct_messages(
.where( .where(
models.InboxObject.visibility == ap.VisibilityEnum.DIRECT, models.InboxObject.visibility == ap.VisibilityEnum.DIRECT,
models.InboxObject.ap_context.is_not(None), models.InboxObject.ap_context.is_not(None),
# Skip transient object like poll relies
models.InboxObject.is_transient.is_(False),
) )
.group_by(models.InboxObject.ap_context, models.InboxObject.actor_id) .group_by(models.InboxObject.ap_context, models.InboxObject.actor_id)
) )
@ -427,6 +432,8 @@ async def admin_direct_messages(
.where( .where(
models.OutboxObject.visibility == ap.VisibilityEnum.DIRECT, models.OutboxObject.visibility == ap.VisibilityEnum.DIRECT,
models.OutboxObject.ap_context.is_not(None), models.OutboxObject.ap_context.is_not(None),
# Skip transient object like poll relies
models.OutboxObject.is_transient.is_(False),
) )
.group_by(models.OutboxObject.ap_context) .group_by(models.OutboxObject.ap_context)
) )
@ -435,6 +442,7 @@ async def admin_direct_messages(
.all() .all()
) )
# Build a "threads index" by combining objects from the inbox and outbox
convos = {} convos = {}
for inbox_convo in inbox_convos: for inbox_convo in inbox_convos:
if inbox_convo.ap_context not in convos: if inbox_convo.ap_context not in convos:
@ -467,6 +475,7 @@ async def admin_direct_messages(
convos[outbox_convo.ap_context]["most_recent_from_outbox"], convos[outbox_convo.ap_context]["most_recent_from_outbox"],
) )
# Fetch the latest object for each threads
convos_with_last_from_inbox = [] convos_with_last_from_inbox = []
convos_with_last_from_outbox = [] convos_with_last_from_outbox = []
for context, convo in convos.items(): for context, convo in convos.items():
@ -514,6 +523,8 @@ async def admin_direct_messages(
.unique() .unique()
.all() .all()
) )
# Build the template response
threads = [] threads = []
for anybox_object in sorted( for anybox_object in sorted(
last_from_inbox + last_from_outbox, last_from_inbox + last_from_outbox,

View file

@ -154,6 +154,12 @@ async def send_announce(db_session: AsyncSession, ap_object_id: str) -> None:
if not inbox_object: if not inbox_object:
raise ValueError(f"{ap_object_id} not found in the inbox") raise ValueError(f"{ap_object_id} not found in the inbox")
if inbox_object.visibility not in [
ap.VisibilityEnum.PUBLIC,
ap.VisibilityEnum.UNLISTED,
]:
raise ValueError("Cannot announce non-public object")
announce_id = allocate_outbox_id() announce_id = allocate_outbox_id()
announce = { announce = {
"@context": ap.AS_CTX, "@context": ap.AS_CTX,

View file

@ -76,7 +76,6 @@ _RESIZED_CACHE: MutableMapping[tuple[str, int], tuple[bytes, str, Any]] = LFUCac
# TODO(ts): # TODO(ts):
# #
# Next: # Next:
# - Add a TTL cache for the LD sig (no need to re-compute)
# - only show 10 most recent threads in DMs # - only show 10 most recent threads in DMs
# - custom CSS for disabled button (e.g. sharing on a direct post) # - custom CSS for disabled button (e.g. sharing on a direct post)
# - prevent double accept/double follow # - prevent double accept/double follow

View file

@ -105,12 +105,12 @@
</form> </form>
{% endmacro %} {% endmacro %}
{% macro admin_announce_button(ap_object_id, disabled=False, permalink_id=None) %} {% macro admin_announce_button(ap_object_id, permalink_id=None) %}
<form action="{{ request.url_for("admin_actions_announce") }}" method="POST"> <form action="{{ request.url_for("admin_actions_announce") }}" method="POST">
{{ embed_csrf_token() }} {{ embed_csrf_token() }}
{{ embed_redirect_url(permalink_id) }} {{ embed_redirect_url(permalink_id) }}
<input type="hidden" name="ap_object_id" value="{{ ap_object_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 %}> <input type="submit" value="share">
</form> </form>
{% endmacro %} {% endmacro %}
@ -574,13 +574,15 @@
{% endif %} {% endif %}
</li> </li>
{% if object.visibility in [visibility_enum.PUBLIC, visibility_enum.UNLISTED] %}
<li> <li>
{% if object.announced_via_outbox_object_ap_id %} {% if object.announced_via_outbox_object_ap_id %}
{{ admin_undo_button(object.liked_via_outbox_object_ap_id, "unshare") }} {{ admin_undo_button(object.liked_via_outbox_object_ap_id, "unshare") }}
{% else %} {% else %}
{{ admin_announce_button(object.ap_id, disabled=object.visibility not in [visibility_enum.PUBLIC, visibility_enum.UNLISTED], permalink_id=object.permalink_id) }} {{ admin_announce_button(object.ap_id, permalink_id=object.permalink_id) }}
{% endif %} {% endif %}
</li> </li>
{% endif %}
<li> <li>
{{ admin_profile_button(object.actor.ap_id) }} {{ admin_profile_button(object.actor.ap_id) }}