Fix issues with multiplatform conversation displays

This commit is contained in:
2026-02-16 11:42:53 +00:00
parent 15af8af6b2
commit 908516bc94
10 changed files with 489 additions and 78 deletions

View File

@@ -1308,7 +1308,7 @@ def _context_base(user, service, identifier, person):
).first()
or PersonIdentifier.objects.filter(user=user, person=person).first()
)
if person_identifier is None and identifier:
if person_identifier is None and identifier and person is None:
person_identifier = PersonIdentifier.objects.filter(
user=user,
service=service,
@@ -1553,10 +1553,34 @@ def _recent_manual_contacts(
if not all_rows:
return []
current_service_key = _default_service(current_service)
current_identifier_value = str(current_identifier or "").strip()
current_person_id = str(current_person.id) if current_person else ""
row_by_key = {
(str(row.get("service") or "").strip().lower(), str(row.get("identifier") or "").strip()): row
for row in all_rows
}
by_person_service = {}
person_links = (
PersonIdentifier.objects.filter(user=user)
.select_related("person")
.order_by("person__name", "service", "identifier")
)
for link in person_links:
person_id = str(link.person_id or "")
if not person_id:
continue
service_key = _default_service(link.service)
identifier_value = str(link.identifier or "").strip()
if not identifier_value:
continue
by_person_service.setdefault(person_id, {})
if service_key not in by_person_service[person_id]:
by_person_service[person_id][service_key] = {
"identifier": identifier_value,
"person_name": str(link.person.name or "").strip() or identifier_value,
}
ordered_keys = []
seen_keys = set()
recent_values = (
@@ -1582,15 +1606,15 @@ def _recent_manual_contacts(
if len(ordered_keys) >= limit:
break
current_key = (_default_service(current_service), str(current_identifier or "").strip())
current_key = (current_service_key, current_identifier_value)
if current_key[1]:
if current_key in ordered_keys:
ordered_keys.remove(current_key)
ordered_keys.insert(0, current_key)
if len(ordered_keys) > limit:
ordered_keys = ordered_keys[:limit]
rows = []
seen_people = set()
seen_unknown = set()
for service_key, identifier_value in ordered_keys:
row = dict(row_by_key.get((service_key, identifier_value)) or {})
if not row:
@@ -1611,13 +1635,86 @@ def _recent_manual_contacts(
"linked_person": False,
"source": "recent",
}
row["service_label"] = _service_label(service_key)
row["person_id"] = str(row.get("person_id") or "")
person_id = row["person_id"]
if person_id:
if person_id in seen_people:
continue
seen_people.add(person_id)
service_map = dict(by_person_service.get(person_id) or {})
if service_key not in service_map and identifier_value:
service_map[service_key] = {
"identifier": identifier_value,
"person_name": str(row.get("person_name") or "").strip()
or identifier_value,
}
selected_service = service_key
selected_identifier = identifier_value
if person_id == current_person_id and current_service_key in service_map:
selected_service = current_service_key
selected_identifier = str(
(service_map.get(current_service_key) or {}).get("identifier") or ""
).strip()
elif selected_service not in service_map:
for fallback_service in ("whatsapp", "signal", "instagram", "xmpp"):
if fallback_service in service_map:
selected_service = fallback_service
selected_identifier = str(
(service_map.get(fallback_service) or {}).get("identifier")
or ""
).strip()
break
selected_identifier = selected_identifier or identifier_value
selected_urls = _compose_urls(
selected_service,
selected_identifier,
person_id,
)
row["service"] = selected_service
row["service_label"] = _service_label(selected_service)
row["identifier"] = selected_identifier
row["compose_url"] = selected_urls["page_url"]
row["compose_widget_url"] = selected_urls["widget_url"]
row["person_name"] = (
str(row.get("linked_person_name") or "").strip()
or str(row.get("person_name") or "").strip()
or selected_identifier
)
for svc in ("signal", "whatsapp", "instagram", "xmpp"):
svc_identifier = str(
(service_map.get(svc) or {}).get("identifier") or ""
).strip()
row[f"{svc}_identifier"] = svc_identifier
if svc_identifier:
svc_urls = _compose_urls(svc, svc_identifier, person_id)
row[f"{svc}_compose_url"] = svc_urls["page_url"]
row[f"{svc}_compose_widget_url"] = svc_urls["widget_url"]
else:
row[f"{svc}_compose_url"] = ""
row[f"{svc}_compose_widget_url"] = ""
else:
unknown_key = (service_key, identifier_value)
if unknown_key in seen_unknown:
continue
seen_unknown.add(unknown_key)
row["service_label"] = _service_label(service_key)
for svc in ("signal", "whatsapp", "instagram", "xmpp"):
row[f"{svc}_identifier"] = identifier_value if svc == service_key else ""
row[f"{svc}_compose_url"] = row.get("compose_url") if svc == service_key else ""
row[f"{svc}_compose_widget_url"] = (
row.get("compose_widget_url") if svc == service_key else ""
)
row["is_active"] = (
service_key == _default_service(current_service)
and identifier_value == str(current_identifier or "").strip()
row.get("service") == current_service_key
and str(row.get("identifier") or "").strip() == current_identifier_value
)
rows.append(row)
if len(rows) >= limit:
break
return rows
@@ -2127,7 +2224,7 @@ class ComposeThread(LoginRequiredMixin, View):
session_ids = ComposeHistorySync._session_ids_for_scope(
user=request.user,
person=base["person"],
service=service,
service=base["service"],
person_identifier=base["person_identifier"],
explicit_identifier=base["identifier"],
)
@@ -2241,15 +2338,14 @@ class ComposeHistorySync(LoginRequiredMixin, View):
)
variants = cls._identifier_variants(service, explicit_identifier)
if variants:
identifiers.extend(
list(
PersonIdentifier.objects.filter(
user=user,
service=service,
identifier__in=variants,
)
)
variant_qs = PersonIdentifier.objects.filter(
user=user,
service=service,
identifier__in=variants,
)
if person is not None:
variant_qs = variant_qs.filter(person=person)
identifiers.extend(list(variant_qs))
unique_ids = []
seen = set()
for row in identifiers: