This commit is contained in:
ponzischeme89
2026-08-28 23:00:02 +12:00
parent 3e89036f7b
commit d5632e844a
66 changed files with 2870 additions and 689 deletions
+31 -1
View File
@@ -53,6 +53,11 @@ function describeRow(row: RemoteSectionDefinition, rowTypes: RowTypeDefinition[]
return row.type ? `Custom · ${row.type}` : 'Custom';
}
const LAYOUT_LABEL: Record<string, string> = {
poster: 'Poster cards',
thumb: 'Thumbnail cards',
};
export function RowsEditor({
page,
rows,
@@ -142,7 +147,7 @@ export function RowsEditor({
isNew: true,
row: {
id: '', type: availableTypes[0]?.type ?? 'custom', title: '', enabled: true,
position: 0, dataSource: '', component: '', maxItems: 20, destination: '',
position: 0, dataSource: '', component: '', maxItems: 20, destination: '', layout: '',
},
})}
>
@@ -165,6 +170,7 @@ export function RowsEditor({
<div className="chips">
<Chip>{describeRow(row, rowTypes)}</Chip>
{row.maxItems ? <Chip>{row.maxItems} items</Chip> : null}
{row.layout && LAYOUT_LABEL[row.layout] ? <Chip tone="note">{LAYOUT_LABEL[row.layout]}</Chip> : null}
{row.destination ? <Chip tone="note">{row.destination}</Chip> : null}
</div>
</div>
@@ -290,6 +296,7 @@ function RowEditorDialog({
const [customDataSource, setCustomDataSource] = useState(row.dataSource);
const [customComponent, setCustomComponent] = useState(row.component || 'mediaRow');
const [customDestination, setCustomDestination] = useState(row.destination ?? '');
const [layout, setLayout] = useState(row.layout ?? '');
// A row saved by an older console, or through the raw JSON view, can carry a type this
// page's catalogue does not offer (moved off this page, or never catalogued at all). It
@@ -306,6 +313,12 @@ function RowEditorDialog({
const valid = trimmedTitle.length > 0 && validMaxItems &&
(!isCustom || (customDataSource.trim().length > 0 && customComponent.trim().length > 0));
// Layout only means something for a horizontal card row. A genre browser or a paged
// library grid draws neither poster nor thumbnail cards, so the control is hidden and any
// stray value is dropped on save.
const resolvedComponent = isCustom ? customComponent.trim() : rowType?.component ?? '';
const layoutApplies = resolvedComponent === 'mediaRow';
const submit = () => {
if (!valid) return;
const resolvedType = rowType?.type ?? 'custom';
@@ -324,6 +337,7 @@ function RowEditorDialog({
component: isCustom ? customComponent.trim() : rowType!.component,
maxItems,
destination,
...(layoutApplies && (layout === 'poster' || layout === 'thumb') ? { layout } : {}),
});
};
@@ -359,6 +373,22 @@ function RowEditorDialog({
</div>
{rowType?.description ? <p className="hint">{rowType.description}</p> : null}
{layoutApplies ? (
<div className="fields">
<Field
label="Card layout"
hint="Automatic shows episodes as wide thumbnails and everything else as upright posters. Override to force one shape — thumbnails are the same wide cards Continue Watching uses."
grow
>
<select value={layout} onChange={(event) => setLayout(event.target.value)}>
<option value="">Automatic</option>
<option value="poster">Poster cards</option>
<option value="thumb">Thumbnail cards</option>
</select>
</Field>
</div>
) : null}
{rowType?.requiresMatchingDestination ? (
<Note>Browses the {PAGE_LABEL[page]} catalogue this row can only ever point at the page it lives on.</Note>
) : null}