diff --git a/core/realtime/compose_ws.py b/core/realtime/compose_ws.py index 860f7d2..0e1b4ee 100644 --- a/core/realtime/compose_ws.py +++ b/core/realtime/compose_ws.py @@ -1,19 +1,16 @@ import asyncio import json import time -from datetime import datetime, timezone as dt_timezone from urllib.parse import parse_qs from asgiref.sync import sync_to_async from django.core import signing -from core.models import ChatSession, Message, PersonIdentifier +from core.models import ChatSession, Message, PersonIdentifier, WorkspaceConversation from core.realtime.typing_state import get_person_typing_state from core.views.compose import ( COMPOSE_WS_TOKEN_SALT, - _image_urls_from_text, - _is_url_only_text, - _looks_like_image_url, + _serialize_messages_with_artifacts, ) @@ -24,39 +21,6 @@ def _safe_int(value, default=0): return default -def _fmt_ts(ts_value): - try: - dt = datetime.fromtimestamp(int(ts_value) / 1000, tz=dt_timezone.utc) - return dt.strftime("%H:%M") - except Exception: - return str(ts_value or "") - - -def _serialize_message(msg): - author = str(msg.custom_author or "").strip() - text_value = str(msg.text or "") - image_urls = _image_urls_from_text(text_value) - image_url = image_urls[0] if image_urls else "" - hide_text = bool( - image_urls - and _is_url_only_text(text_value) - and all(_looks_like_image_url(url) for url in image_urls) - ) - display_text = text_value if text_value.strip() else ("(no text)" if not image_url else "") - return { - "id": str(msg.id), - "ts": int(msg.ts or 0), - "display_ts": _fmt_ts(msg.ts), - "text": text_value, - "display_text": display_text, - "image_url": image_url, - "image_urls": image_urls, - "hide_text": hide_text, - "author": author, - "outgoing": author.upper() in {"USER", "BOT"}, - } - - def _load_since(user_id, service, identifier, person_id, after_ts, limit): person_identifier = None if person_id: @@ -91,11 +55,18 @@ def _load_since(user_id, service, identifier, person_id, after_ts, limit): "person_id": int(person_identifier.person_id), } - qs = Message.objects.filter( - user_id=user_id, - session=session, - ).order_by("ts") + qs = Message.objects.filter(user_id=user_id, session=session).order_by("ts") + seed_previous = None if after_ts > 0: + seed_previous = ( + Message.objects.filter( + user_id=user_id, + session=session, + ts__lte=after_ts, + ) + .order_by("-ts") + .first() + ) qs = qs.filter(ts__gt=after_ts) rows = list(qs[: max(10, min(limit, 200))]) @@ -105,8 +76,30 @@ def _load_since(user_id, service, identifier, person_id, after_ts, limit): .values_list("ts", flat=True) .first() ) + + conversation = ( + WorkspaceConversation.objects.filter( + user_id=user_id, + participants__id=person_identifier.person_id, + ) + .order_by("-last_event_ts", "-created_at") + .first() + ) + counterpart_identifiers = { + str(value or "").strip() + for value in PersonIdentifier.objects.filter( + user_id=user_id, + person_id=person_identifier.person_id, + ).values_list("identifier", flat=True) + if str(value or "").strip() + } return { - "messages": [_serialize_message(row) for row in rows], + "messages": _serialize_messages_with_artifacts( + rows, + counterpart_identifiers=counterpart_identifiers, + conversation=conversation, + seed_previous=seed_previous, + ), "last_ts": int(newest or after_ts or 0), "person_id": int(person_identifier.person_id), } diff --git a/core/templates/base.html b/core/templates/base.html index 6bc8ade..d3860a1 100644 --- a/core/templates/base.html +++ b/core/templates/base.html @@ -296,24 +296,6 @@ Queue - - + {% endif %} + + Install + + + +