v0.6.2: order sources by most recent message (recency)

- Sidebar sources ordered by Max(created_at) desc instead of alphabetically;
  "All sources" stays pinned at top (rendered separately).
- Live updates move a source to the top when it gets a new message, so the
  recency order holds without a reload.

152 tests pass; JS re-validated with node --check.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
peter 2026-09-07 21:18:49 +01:00
parent ab3e92268a
commit c1be2face7
4 changed files with 31 additions and 15 deletions

View file

@ -19,7 +19,7 @@ from django.contrib.auth import views as auth_views
from django.contrib.auth.decorators import login_required
from django.contrib.auth.models import User
from django.db import OperationalError, transaction
from django.db.models import Count, Q, Sum
from django.db.models import Count, Max, Q, Sum
from django.http import FileResponse, Http404, HttpResponse, HttpResponseForbidden, JsonResponse
from django.shortcuts import get_object_or_404, redirect, render
from django.template.defaultfilters import date as date_filter, slugify
@ -586,10 +586,12 @@ def feed(request):
source_scoped = apply_feed_filters(
live, "", selected_label, selected_kind, title_query
)
# Sources ordered by most recent message first (Telegram-style); "All
# sources" is rendered separately and stays pinned at the top.
source_counts = (
source_scoped.values("source")
.annotate(count=Count("id", filter=Q(read_at__isnull=True)))
.order_by("source")
.annotate(count=Count("id", filter=Q(read_at__isnull=True)), latest=Max("created_at"))
.order_by("-latest")
)
keep_count = live.filter(is_kept=True).count()
trash_count = Artifact.objects.filter(owner=request.user, deleted_at__isnull=False).count()