0.3.49
This commit is contained in:
@@ -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}
|
||||
|
||||
Reference in New Issue
Block a user