fix(feed): a channel filter's chips name their channels from the first paint

After a reload the chips (filter panel and the row above the feed) read as
raw UC… ids until the subscription list landed. The names seen last time
are now kept per account (useChannelNames) and name the chips at once; the
list then replaces the copy, so a renamed or dropped channel heals. A
channel never named on this browser draws a placeholder bone while the
list loads; a failed list still falls back to the id.
This commit is contained in:
2026-10-03 03:29:54 +02:00
parent 6edb22988c
commit e9c15baae0
8 changed files with 227 additions and 32 deletions
+6 -11
View File
@@ -1,7 +1,6 @@
import { useTranslation } from "react-i18next";
import { useQuery } from "@tanstack/react-query";
import { qk } from "../lib/queryKeys";
import { api, type FeedFilters } from "../lib/api";
import type { FeedFilters } from "../lib/api";
import { useChannelNames } from "../lib/useChannelNames";
import Combobox, { type ComboboxOption } from "./ui/Combobox";
// Pick channels to narrow the feed to — several OR together, so every other filter then applies
@@ -19,18 +18,13 @@ export default function ChannelPicker({
setFilters: (f: FeedFilters) => void;
}) {
const { t } = useTranslation();
const channelsQuery = useQuery({
queryKey: qk.channels(),
queryFn: api.channels,
staleTime: 5 * 60_000,
});
const { query: channelsQuery, names, pending } = useChannelNames();
const all = channelsQuery.data ?? [];
// The list order isn't alphabetical — it's the user's channel priority — and Combobox preserves the
// options order, so it stays meaningful. selectedLabels keeps a picked channel named even if a later
// narrowing ever drops it from the visible rows.
// narrowing ever drops it from the visible rows, and names a reloaded filter before the list lands.
const options: ComboboxOption[] = all.map((c) => ({ value: c.id, label: c.title ?? c.id }));
const selectedLabels = Object.fromEntries(all.map((c) => [c.id, c.title ?? c.id]));
return (
<Combobox
@@ -43,7 +37,8 @@ export default function ChannelPicker({
error={channelsQuery.isError && !channelsQuery.data ? t("common.loadError") : undefined}
onRetry={() => void channelsQuery.refetch()}
emptyText={t("sidebar.noChannelMatch")}
selectedLabels={selectedLabels}
selectedLabels={names}
labelsPending={pending}
/>
);
}