Extract shared home and environment settings for product reuse

This commit is contained in:
Codex
2026-09-07 22:54:17 +03:00
parent 26a1bf72a2
commit b10fd5d645
21 changed files with 1431 additions and 13 deletions
+84
View File
@@ -0,0 +1,84 @@
export type EnvironmentMediaKind = "image" | "video";
export type EnvironmentMediaSource = "file" | "url";
export interface EnvironmentMediaItem {
id: string;
source: EnvironmentMediaSource;
url: string | null;
mediaKind: EnvironmentMediaKind | null;
fileName: string | null;
}
export interface EnvironmentBackground {
enabled: boolean;
imageDurationSeconds: number;
items: EnvironmentMediaItem[];
}
export interface EnvironmentPage {
headerLabel: string;
eyebrow: string;
title: string;
description: string;
primaryWorkspaceId: string | null;
secondaryWorkspaceId: string | null;
background: EnvironmentBackground;
}
export interface EnvironmentSettings { revision: number; pages: Record<string, EnvironmentPage> }
export interface UploadedEnvironmentMedia { url: string; fileName: string; mediaKind: EnvironmentMediaKind }
export interface EnvironmentAction { id: string; label: string; description?: string }
export interface EnvironmentSurface { id: string; home?: boolean; description?: string; actions: readonly EnvironmentAction[] }
export const defaultEnvironmentImageDurationSeconds = 10;
export const maxEnvironmentMediaItems = 24;
export function createEnvironmentMediaItem(): EnvironmentMediaItem {
return {
id: `media-${crypto.randomUUID()}`,
source: "file",
url: null,
mediaKind: null,
fileName: null,
};
}
export function appendEnvironmentMediaItem(
background: EnvironmentBackground,
item: EnvironmentMediaItem = createEnvironmentMediaItem(),
): EnvironmentBackground {
if (
background.items.length >= maxEnvironmentMediaItems
|| background.items.some((candidate) => candidate.id === item.id)
) {
return background;
}
return {
...background,
enabled: background.items.length === 0 ? true : background.enabled,
items: [...background.items, item],
};
}
export function removeEnvironmentMediaItem(
background: EnvironmentBackground,
itemId: string,
): EnvironmentBackground {
const items = background.items.filter((item) => item.id !== itemId);
if (items.length === background.items.length) return background;
return {
...background,
enabled: items.length > 0 && background.enabled,
items,
};
}
export function inferEnvironmentMediaKind(url: string): EnvironmentMediaKind {
return /\.(mp4|webm|mov)(?:[?#].*)?$/i.test(url) ? "video" : "image";
}
export function cloneEnvironmentSettings(settings: EnvironmentSettings): EnvironmentSettings {
return { ...settings, pages: Object.fromEntries(Object.entries(settings.pages).map(([id, page]) => [id, {
...page, background: { ...page.background, items: page.background.items.map(item => ({ ...item })) },
}])) };
}