/** * The wire shapes Signage's dashboard reads. * * Signage owns both ends of every one of these, which is exactly why they are written down: the * server's route and this file are one contract, and a drift between them is a bug an operator sees * rather than a compiler does. */ export interface SettingsResponse { readonly crossfadeMs: number; readonly moduleVersion: string; readonly nativeImageDurationMs: number; readonly nativePresentation: { readonly backgroundMode: string; readonly backgroundColor: string; readonly backgroundDarkened: boolean; readonly blurPixels: number; }; readonly rendererInputVersion: string; readonly timezone: string; readonly uploads: { readonly batchMaxFiles: number; readonly concurrency: number; readonly maxBytes: number; readonly maxPixels: number; }; } export interface ImageRendition { readonly kind: string; readonly url: string; readonly expiresAt: string; readonly width: number; readonly height: number; } export interface ImageRecord { readonly id: string; readonly displayName: string; readonly originalFilename: string; readonly contentType: string; readonly byteSize: number; readonly width: number; readonly height: number; readonly status: string; readonly expiresAt: string | null; readonly createdAt: string; readonly renditions: readonly ImageRendition[]; } export interface TimelineSummary { readonly id: string; readonly name: string; readonly description: string | null; readonly eligibleFrom: string | null; readonly eligibleUntil: string | null; readonly revision: number; readonly updatedAt: string; } export interface TimelineSource { readonly id: string; readonly label: string; readonly providerId: string; readonly sourceId: string; } export interface TimelineSlot { readonly id: string; readonly position: number; readonly kind: "provider-source" | "pinned-item"; readonly sourceId: string | null; readonly providerId: string | null; readonly itemId: string | null; readonly enabled: boolean; readonly durationOverrideMs: number | null; readonly eligibleFrom: string | null; readonly eligibleUntil: string | null; readonly presentation: { readonly backgroundMode: string | null; readonly backgroundColor: string | null; readonly backgroundDarkened: boolean | null; readonly blurPixels: number | null; readonly foregroundShadow: boolean | null; }; } export interface TimelineDetail { readonly timeline: TimelineSummary; readonly sources: readonly TimelineSource[]; readonly slots: readonly TimelineSlot[]; } export interface ProviderHealth { readonly providerId: string; readonly providerVersion: string; readonly contractVersion: string; readonly renderer: { readonly contributionId: string; readonly contributionVersion: string }; readonly defaultDurationMs: number; readonly registeredAt: string; readonly consecutiveFailures: number; readonly lastFailureCode: string | null; readonly lastFailureAt: string | null; readonly lastSuccessAt: string | null; } export interface ProviderSourceDescriptor { readonly id: string; readonly label: string; readonly description?: string; } export interface ProviderItemDescriptor { readonly id: string; readonly label: string; readonly description?: string; readonly availableUntil?: string | null; } export type TransportState = "idle" | "playing" | "paused" | "static"; export interface PlaybackSnapshotView { readonly groupId: string; readonly revision: number; readonly serverNowMs: number; readonly transport: TransportState; readonly blackout: boolean; readonly activeTimelineId: string | null; readonly pendingTimelineId: string | null; readonly scheduledTimelineId: string | null; readonly scheduledActivationAtMs: number | null; readonly currentSelectionId: string | null; readonly currentSlotId: string | null; readonly startedAtMs: number | null; readonly deadlineAtMs: number | null; readonly remainingMs: number | null; readonly selectionRevision: number | null; readonly staticAssetId: string | null; } export interface ChannelView { readonly id: string; readonly key: string; readonly name: string; readonly isDefault: boolean; } export interface ChannelGroupView { readonly id: string; readonly name: string; readonly revision: number; readonly channels: readonly ChannelView[]; readonly playback: PlaybackSnapshotView; } export interface PlaybackDetailView { readonly snapshot: PlaybackSnapshotView; readonly current: { readonly id: string; readonly itemId: string; readonly itemRevision: string; readonly providerId: string; readonly rendererContributionId: string | null; readonly revision: number; readonly stale: boolean; readonly withdrawn: boolean; readonly durationMs: number; readonly startedAtMs: number | null; readonly deadlineAtMs: number | null; } | null; readonly history: readonly { readonly id: string; readonly itemId: string; readonly providerId: string; readonly sequence: number; readonly startedAtMs: number | null; }[]; } export interface ViewerHealthView { readonly id: string; readonly name: string; readonly online: boolean; readonly channelId: string | null; readonly deviceId: string | null; readonly lastSeenAtMs: number | null; readonly reportedTimelineId: string | null; readonly reportedSelectionId: string | null; readonly reportedProviderId: string | null; readonly reportedContributionId: string | null; readonly offlineReady: boolean; readonly cachedAssetCount: number; readonly lastError: { readonly code: string; readonly detail: string | null; readonly atMs: number; } | null; }