frontend: align types to backend, playout HLS, rm Jellyfin proxy (#12)
This commit is contained in:
@@ -1,5 +1,3 @@
|
||||
// API response and request types matching the backend DTOs
|
||||
|
||||
export interface ActivityEvent {
|
||||
id: string;
|
||||
timestamp: string;
|
||||
@@ -17,11 +15,11 @@ export interface LogLine {
|
||||
|
||||
export type ContentType = "movie" | "episode" | "short";
|
||||
|
||||
export type AccessMode = "public" | "password_protected" | "account_required" | "owner_only";
|
||||
export type AccessMode = "public" | "private";
|
||||
|
||||
export type LogoPosition = "top_left" | "top_right" | "bottom_left" | "bottom_right";
|
||||
|
||||
export type FillStrategy = "best_fit" | "sequential" | "random";
|
||||
export type FillStrategy = "best_fit" | "sequential" | "random" | "alternating" | "weighted" | "marathon";
|
||||
|
||||
export interface MediaFilter {
|
||||
content_type?: ContentType | null;
|
||||
@@ -31,9 +29,7 @@ export interface MediaFilter {
|
||||
min_duration_secs?: number | null;
|
||||
max_duration_secs?: number | null;
|
||||
collections: string[];
|
||||
/** Filter to one or more TV series by name. OR-combined: any listed show is eligible. */
|
||||
series_names?: string[];
|
||||
/** Free-text search, used for library browsing only. */
|
||||
search_term?: string | null;
|
||||
}
|
||||
|
||||
@@ -55,22 +51,43 @@ export interface SeriesResponse {
|
||||
|
||||
export interface LibraryItemResponse {
|
||||
id: string;
|
||||
provider_id: string;
|
||||
external_id: string;
|
||||
title: string;
|
||||
content_type: ContentType;
|
||||
content_type: string;
|
||||
duration_secs: number;
|
||||
series_name?: string | null;
|
||||
season_number?: number | null;
|
||||
episode_number?: number | null;
|
||||
year?: number | null;
|
||||
genres: string[];
|
||||
tags: string[];
|
||||
collection_id?: string | null;
|
||||
collection_name?: string | null;
|
||||
collection_type?: string | null;
|
||||
thumbnail_url?: string | null;
|
||||
synced_at?: string | null;
|
||||
}
|
||||
|
||||
export interface RecyclePolicy {
|
||||
export interface RotationPolicy {
|
||||
cooldown_days?: number | null;
|
||||
cooldown_generations?: number | null;
|
||||
min_available_ratio: number;
|
||||
}
|
||||
|
||||
export interface InterstitialRule {
|
||||
pool_filter: MediaFilter;
|
||||
strategy: FillStrategy;
|
||||
min_gap_secs: number;
|
||||
}
|
||||
|
||||
export interface MidRollRule {
|
||||
prefer_chapters: boolean;
|
||||
fallback_interval_mins: number;
|
||||
break_duration_secs: number;
|
||||
pool_filter: MediaFilter;
|
||||
}
|
||||
|
||||
export type BlockContent =
|
||||
| { type: "algorithmic"; filter: MediaFilter; strategy: FillStrategy; provider_id?: string }
|
||||
| { type: "manual"; items: string[]; provider_id?: string };
|
||||
@@ -78,16 +95,14 @@ export type BlockContent =
|
||||
export interface ProgrammingBlock {
|
||||
id: string;
|
||||
name: string;
|
||||
/** "HH:MM:SS" */
|
||||
start_time: string;
|
||||
duration_mins: number;
|
||||
content: BlockContent;
|
||||
/** Sequential only: loop back to episode 1 after the last episode. Default true on backend. */
|
||||
loop_on_finish?: boolean;
|
||||
/** When true, skip the channel-level recycle policy for this block. Default false on backend. */
|
||||
ignore_recycle_policy?: boolean;
|
||||
ignore_rotation_policy?: boolean;
|
||||
interstitial_rule?: InterstitialRule | null;
|
||||
mid_roll_rule?: MidRollRule | null;
|
||||
access_mode?: AccessMode;
|
||||
/** Plain-text password sent to API; hashed server-side. Only set on write operations. */
|
||||
access_password?: string;
|
||||
}
|
||||
|
||||
@@ -154,9 +169,7 @@ export interface ProviderInfo {
|
||||
|
||||
export interface ConfigResponse {
|
||||
allow_registration: boolean;
|
||||
/** All registered providers. Added in multi-provider update. */
|
||||
providers: ProviderInfo[];
|
||||
/** Primary provider capabilities — kept for backward compat. */
|
||||
provider_capabilities: ProviderCapabilities;
|
||||
available_provider_types: string[];
|
||||
}
|
||||
@@ -198,14 +211,14 @@ export interface ChannelResponse {
|
||||
description?: string | null;
|
||||
timezone: string;
|
||||
schedule_config: ScheduleConfig;
|
||||
recycle_policy: RecyclePolicy;
|
||||
rotation_policy: RotationPolicy;
|
||||
auto_schedule: boolean;
|
||||
access_mode: AccessMode;
|
||||
access_mode: string;
|
||||
logo?: string | null;
|
||||
logo_position: LogoPosition;
|
||||
logo_position: string;
|
||||
logo_opacity: number;
|
||||
webhook_url?: string | null;
|
||||
webhook_poll_interval_secs?: number;
|
||||
webhook_poll_interval_secs: number;
|
||||
webhook_body_template?: string | null;
|
||||
webhook_headers?: string | null;
|
||||
created_at: string;
|
||||
@@ -229,21 +242,15 @@ export interface UpdateChannelRequest {
|
||||
description?: string;
|
||||
timezone?: string;
|
||||
schedule_config?: ScheduleConfig;
|
||||
recycle_policy?: RecyclePolicy;
|
||||
rotation_policy?: RotationPolicy;
|
||||
auto_schedule?: boolean;
|
||||
access_mode?: AccessMode;
|
||||
/** Empty string clears the password. */
|
||||
access_password?: string;
|
||||
/** null = clear logo */
|
||||
access_mode?: string;
|
||||
logo?: string | null;
|
||||
logo_position?: LogoPosition;
|
||||
logo_position?: string;
|
||||
logo_opacity?: number;
|
||||
/** null = clear webhook */
|
||||
webhook_url?: string | null;
|
||||
webhook_poll_interval_secs?: number;
|
||||
/** null = clear template */
|
||||
webhook_body_template?: string | null;
|
||||
/** null = clear headers */
|
||||
webhook_headers?: string | null;
|
||||
}
|
||||
|
||||
@@ -252,56 +259,40 @@ export interface UpdateChannelRequest {
|
||||
export interface MediaItemResponse {
|
||||
id: string;
|
||||
title: string;
|
||||
content_type: ContentType;
|
||||
content_type: string;
|
||||
duration_secs: number;
|
||||
description?: string | null;
|
||||
genres: string[];
|
||||
tags: string[];
|
||||
year?: number | null;
|
||||
/** Episodes only: the parent TV show name. */
|
||||
series_name?: string | null;
|
||||
/** Episodes only: season number (1-based). */
|
||||
season_number?: number | null;
|
||||
/** Episodes only: episode number within the season (1-based). */
|
||||
episode_number?: number | null;
|
||||
}
|
||||
|
||||
export interface ScheduledSlotResponse {
|
||||
id: string;
|
||||
block_id: string;
|
||||
item: MediaItemResponse;
|
||||
/** RFC3339 */
|
||||
start_at: string;
|
||||
/** RFC3339 */
|
||||
end_at: string;
|
||||
block_access_mode: AccessMode;
|
||||
item: MediaItemResponse;
|
||||
source_block_id: string;
|
||||
}
|
||||
|
||||
export interface ScheduleResponse {
|
||||
id: string;
|
||||
channel_id: string;
|
||||
generation: number;
|
||||
generated_at: string;
|
||||
valid_from: string;
|
||||
valid_until: string;
|
||||
generation: number;
|
||||
slots: ScheduledSlotResponse[];
|
||||
}
|
||||
|
||||
export interface CurrentBroadcastResponse {
|
||||
slot: ScheduledSlotResponse;
|
||||
offset_secs: number;
|
||||
block_access_mode: AccessMode;
|
||||
}
|
||||
|
||||
// Library management
|
||||
// Note: LibraryItemResponse is already defined in this file (search for it above).
|
||||
// LibraryItemFull extends it with the extra fields returned by the DB-backed endpoint.
|
||||
|
||||
export interface LibraryItemFull extends LibraryItemResponse {
|
||||
thumbnail_url?: string | null;
|
||||
collection_id?: string | null;
|
||||
collection_name?: string | null;
|
||||
}
|
||||
export type LibraryItemFull = LibraryItemResponse;
|
||||
|
||||
export interface ShowSummary {
|
||||
series_name: string;
|
||||
|
||||
Reference in New Issue
Block a user