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 } 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 })) }, }])) }; }