Lists: made on /lists, read as a tab of the feed

A persona's lists (PrivaPub's /api/v1/lists): made, renamed, given a
replies policy and made exclusive on /lists, filled from the accounts it
follows (accounts/search?following=true), and read as the feed's Lists tab.
A followed account's profile has a Lists menu to put it in or take it out.
ListService does the calls; the e2e tests check each step against
PrivaPub's own answer.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LsXgEaXee4GCU1hwYgPJXw
This commit is contained in:
thepraandClaude Opus 5.5 committed 2026-10-05 02:49:51 +02:00
1 parent 011bafb6af
commit e2491de16e
18 files changed
+914 -9

No files matched your search

+7 -2
View File
@@ -16,7 +16,7 @@
</aside>
<section class="flex flex-col gap-3 min-h-0 flex-1 lg:h-full">
<FeedTabs Filter="Filter" Groups="groups" Stats="FeedStats()" IsComposing="isComposing" OnCompose="() => isComposing = !isComposing"
<FeedTabs Filter="Filter" Groups="groups" Lists="lists" Stats="FeedStats()" IsComposing="isComposing" OnCompose="() => isComposing = !isComposing"
OnChanged="ChangeFeed" />
<div class="relative flex-1 min-h-0 neo-inset neo-xs rounded-xl">
@@ -103,6 +103,7 @@
[Inject] IJSRuntime JS { get; set; }
[Inject] TimelineService TimelineService { get; set; }
[Inject] GroupService GroupService { get; set; }
[Inject] ListService ListService { get; set; }
[Inject] InstanceService InstanceService { get; set; }
[Inject] RequestStats RequestStats { get; set; }
@@ -110,6 +111,7 @@
List<FeedPost> posts = [];
List<FeedPost> pending = [];
List<ViewGroup> groups = [];
List<MastodonList> lists = [];
string maxId;
string minId;
string loadError;
@@ -174,7 +176,7 @@
}
FeedQuery Query => new(Filter.TimelineType, CascadingState.PersonaId, Filter.GroupId, groups.FirstOrDefault(g => g.Id == Filter.GroupId)?.IsCommunity == true,
Filter.Tag, position?.Latitude, position?.Longitude);
Filter.Tag, position?.Latitude, position?.Longitude, Filter.ListId);
/// <summary>Reads the first page of the current feed again, and the persona's groups.</summary>
async Task Reload()
@@ -194,10 +196,13 @@
if (CascadingState.PersonaId != loadedPersonaId)
{
groups = await GroupService.List(CascadingState.PersonaId, cancellationToken);
lists = await ListService.All(cancellationToken);
loadedPersonaId = CascadingState.PersonaId;
}
if (Filter.TimelineType is TimelineType.Groups && groups.All(g => g.Id != Filter.GroupId))
Filter.GroupId = groups.FirstOrDefault()?.Id;
if (Filter.TimelineType is TimelineType.Lists && lists.All(l => l.Id != Filter.ListId))
Filter.ListId = lists.FirstOrDefault()?.Id;
lastQuery = Query;
if (Filter.TimelineType is TimelineType.Nearby && position is null)
{