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:
@@ -11,6 +11,7 @@ import { InnerInput } from "./Input";
|
||||
import { DismissibleChip } from "./Chip";
|
||||
import { fieldClass } from "./fieldStyles";
|
||||
import { SURFACE } from "./surfaces";
|
||||
import { ChipLabelPending } from "./Skeleton";
|
||||
|
||||
// The universal combobox: a react-select / Overseerr-style "combi input" — selected values are
|
||||
// removable chips that live INSIDE a text field you type into, and a checklist of options opens below.
|
||||
@@ -72,6 +73,9 @@ export interface ComboboxProps {
|
||||
/** Chip/label text for a selected value whose option is not in the current (e.g. server-narrowed)
|
||||
* list — the collection picker passes the stored title here so a reloaded filter still names itself. */
|
||||
selectedLabels?: Record<string, string>;
|
||||
/** The labels are still on their way: a selected value with none yet draws a placeholder chip
|
||||
* instead of its raw value (a channel filter's UC… id after a reload). */
|
||||
labelsPending?: boolean;
|
||||
}
|
||||
|
||||
export default function Combobox({
|
||||
@@ -93,6 +97,7 @@ export default function Combobox({
|
||||
maxVisible = 50,
|
||||
renderOption,
|
||||
selectedLabels,
|
||||
labelsPending = false,
|
||||
}: ComboboxProps) {
|
||||
const { t } = useTranslation();
|
||||
const [open, setOpen] = useState(false);
|
||||
@@ -113,7 +118,8 @@ export default function Combobox({
|
||||
useEffect(() => {
|
||||
for (const o of options) if (o.label != null) labelCache.current[o.value] = o.label;
|
||||
}, [options]);
|
||||
const labelFor = (v: string) => selectedLabels?.[v] ?? labelCache.current[v] ?? v;
|
||||
const knownLabel = (v: string) => selectedLabels?.[v] ?? labelCache.current[v];
|
||||
const labelFor = (v: string) => knownLabel(v) ?? v;
|
||||
|
||||
const setOpenAnd = (next: boolean) => {
|
||||
if (next && disabled) return;
|
||||
@@ -210,7 +216,11 @@ export default function Combobox({
|
||||
onDismiss={() => !disabled && onChange(selected.filter((x) => x !== v))}
|
||||
dismissLabel={t("common.removeNamed", { name: labelFor(v) })}
|
||||
>
|
||||
{labelFor(v)}
|
||||
{labelsPending && knownLabel(v) === undefined ? (
|
||||
<ChipLabelPending value={v} />
|
||||
) : (
|
||||
labelFor(v)
|
||||
)}
|
||||
</DismissibleChip>
|
||||
))}
|
||||
<InnerInput
|
||||
|
||||
Reference in New Issue
Block a user