Rename Kyoo to Omnyx & add page settings

Rename project branding from "Kyoo" to "Omnyx" across README, index.html, metadata.json, typedoc and various UI components. Add support for page-level settings: pageTitle, favicon (Base64 upload/preview), and customColors (color scheme) — introduced CustomColors type, persisted via API types and converters, and wired into updateSettings/fetchSettings flows. UI: SettingsView adds page settings UI (upload, preview, color pickers) and handlers; App applies pageTitle, favicon and sets CSS variables for customColors; Sidebar and Header now display the configured page title. Also update importer modules and docs to use the new project name in logs/comments.
This commit is contained in:
Lars Behrends
2026-04-20 22:51:33 +02:00
parent 63c5d0a7c0
commit e5cdd6b383
15 changed files with 281 additions and 43 deletions
+11
View File
@@ -170,6 +170,12 @@ export function convertApiToSettings(apiItem: ApiSettingsItem): UserSettings {
language: apiItem.language || 'en',
theme: (apiItem.theme as 'light' | 'dark' | 'system') || 'system',
jellyfinLibraryMappings: apiItem.jellyfin_library_mappings,
// Page Settings
pageTitle: apiItem.page_title,
favicon: apiItem.favicon,
customColors: apiItem.custom_colors ? JSON.parse(apiItem.custom_colors) : undefined,
createdAt: apiItem.created_at,
updatedAt: apiItem.updated_at,
};
@@ -186,5 +192,10 @@ export function convertSettingsToApi(settings: UserSettings): CreateSettingsInpu
language: settings.language,
theme: settings.theme,
jellyfin_library_mappings: settings.jellyfinLibraryMappings,
// Page Settings
page_title: settings.pageTitle,
favicon: settings.favicon,
custom_colors: settings.customColors ? JSON.stringify(settings.customColors) : undefined,
};
}
+11
View File
@@ -193,6 +193,12 @@ export interface ApiSettingsItem {
language: string;
theme: string;
jellyfin_library_mappings?: string;
// Page Settings
page_title?: string;
favicon?: string;
custom_colors?: string; // JSON string of CustomColors
created_at?: string;
updated_at?: string;
}
@@ -207,6 +213,11 @@ export interface CreateSettingsInput {
language?: string;
theme?: string;
jellyfin_library_mappings?: string;
// Page Settings
page_title?: string;
favicon?: string;
custom_colors?: string;
}
export interface UpdateSettingsInput extends Partial<CreateSettingsInput> {}
+10 -10
View File
@@ -1,7 +1,7 @@
/**
* Jellyfin Importer Module
*
* This module provides functionality to import media from a Jellyfin media server into the Kyoo media database.
* This module provides functionality to import media from a Jellyfin media server into the Omnyx media database.
* It supports importing movies, TV series (including episodes), music albums, and cast members.
* The module handles library mapping to categorize content appropriately and supports both new imports
* and updates to existing entries.
@@ -25,7 +25,7 @@ export interface JellyfinConfig {
}
/**
* Mapping configuration for Jellyfin libraries to Kyoo categories
* Mapping configuration for Jellyfin libraries to Omnyx categories
*/
export interface LibraryMapping {
/** Name of the Jellyfin library */
@@ -838,10 +838,10 @@ function convertJellyfinPersonToCast(person: JellyfinPerson, config: JellyfinCon
}
/**
* Imports media from a Jellyfin instance into the Kyoo media database
* Imports media from a Jellyfin instance into the Omnyx media database
*
* This function performs the following steps:
* 1. Fetches existing media and cast from Kyoo to check for duplicates
* 1. Fetches existing media and cast from Omnyx to check for duplicates
* 2. Fetches Jellyfin libraries for category mapping (if library mappings are provided)
* 3. Imports movies (if enabled)
* 4. Imports TV series with episodes (if enabled)
@@ -895,7 +895,7 @@ export async function importFromJellyfin(
logCallback('Starting Jellyfin import...');
// Step 0: Fetch existing media and cast to check for duplicates
logCallback('Fetching existing media from Kyoo API...');
logCallback('Fetching existing media from Omnyx API...');
const existingMediaResponse = await fetch(`${BASE_URL}/api/media?limit=10000`);
const existingMediaData = await existingMediaResponse.json();
const existingMedia = new Map(
@@ -903,7 +903,7 @@ export async function importFromJellyfin(
);
logCallback(`Found ${existingMedia.size} existing media items in database`);
logCallback('Fetching existing cast from Kyoo API...');
logCallback('Fetching existing cast from Omnyx API...');
const existingCastResponse = await fetch(`${BASE_URL}/api/cast`);
const existingCastData = await existingCastResponse.json();
const existingCast = new Map(
@@ -1297,15 +1297,15 @@ export async function cleanupJellyfinMedia(
try {
logCallback('Starting Jellyfin cleanup...');
// Fetch all existing media from Kyoo API
logCallback('Fetching existing media from Kyoo API...');
// Fetch all existing media from Omnyx API
logCallback('Fetching existing media from Omnyx API...');
const existingMediaResponse = await fetch(`${BASE_URL}/api/media?limit=10000`);
const existingMediaData = await existingMediaResponse.json();
const jellyfinMedia = (existingMediaData.data?.items || []).filter((m: Media) => m.source === 'jellyfin');
logCallback(`Found ${jellyfinMedia.length} Jellyfin media items in database`);
// Fetch all existing cast from Kyoo API
logCallback('Fetching existing cast from Kyoo API...');
// Fetch all existing cast from Omnyx API
logCallback('Fetching existing cast from Omnyx API...');
const existingCastResponse = await fetch(`${BASE_URL}/api/cast`);
const existingCastData = await existingCastResponse.json();
const jellyfinCast = (existingCastData.data?.items || []).filter((c: Staff) => c.photo && c.photo.includes(normalizeUrl(config.url)));
+7 -7
View File
@@ -1,8 +1,8 @@
/**
* Playnite Importer Module
*
* This module provides functionality to import games from a Playnite library into the Kyoo media database.
* It fetches game data from the Playnite API, converts it to the Kyoo media format, and handles both
* This module provides functionality to import games from a Playnite library into the Omnyx media database.
* It fetches game data from the Playnite API, converts it to the Omnyx media format, and handles both
* new imports and updates to existing entries.
*
* @module playniteImporter
@@ -216,14 +216,14 @@ async function fetchGameIcon(baseUrl: string, headers: Record<string, string>, g
}
*/
/**
* Imports games from a Playnite library into the Kyoo media database
* Imports games from a Playnite library into the Omnyx media database
*
* This function performs the following steps:
* 1. Fetches existing media from Kyoo to check for duplicates
* 1. Fetches existing media from Omnyx to check for duplicates
* 2. Fetches all games from the Playnite API
* 3. Fetches detailed information for each game
* 4. Converts Playnite game data to Kyoo media format
* 5. Imports or updates each game in the Kyoo database
* 4. Converts Playnite game data to Omnyx media format
* 5. Imports or updates each game in the Omnyx database
*
* @param config - Configuration for connecting to Playnite
* @param logCallback - Callback function for logging progress messages
@@ -264,7 +264,7 @@ export async function importFromPlaynite(
logCallback('Starting Playnite import...');
// Step 0: Fetch existing media to check for duplicates and enable updates
logCallback('Fetching existing media from Kyoo API...');
logCallback('Fetching existing media from Omnyx API...');
const existingMediaResponse = await fetch(`${BASE_URL}/api/media?limit=1000`);
const existingMediaData = await existingMediaResponse.json();
const existingMedia = new Map(
+8 -8
View File
@@ -2,7 +2,7 @@
* StashAPP Importer Module
*
* This module provides functionality to import adult video content and performers from a StashAPP instance
* into the Kyoo media database. It fetches scene and performer data via GraphQL, converts it to the Kyoo
* into the Omnyx media database. It fetches scene and performer data via GraphQL, converts it to the Omnyx
* media format, and handles both new imports and updates to existing entries.
*
* @module stashappImporter
@@ -226,7 +226,7 @@ function isPathBlacklisted(filePath: string, blacklist: string[]): boolean {
* Updates or creates actor entries from StashAPP performers
*
* This function fetches all performers from StashAPP and updates or creates
* corresponding actor entries in the Kyoo database.
* corresponding actor entries in the Omnyx database.
*
* @param config - Configuration for connecting to StashAPP
* @param logCallback - Callback function for logging progress messages
@@ -251,8 +251,8 @@ export async function updateActorsFromStashAPP(
try {
logCallback('Starting StashAPP actor update...');
// Fetch existing cast from Kyoo API
logCallback('Fetching existing cast from Kyoo API...');
// Fetch existing cast from Omnyx API
logCallback('Fetching existing cast from Omnyx API...');
const existingCastResponse = await fetch(`${BASE_URL}/api/cast`);
const existingCastData = await existingCastResponse.json();
const existingActors = new Map<string, Staff>(
@@ -456,10 +456,10 @@ export async function updateActorsFromStashAPP(
}
/**
* Imports scenes and performers from a StashAPP instance into the Kyoo media database
* Imports scenes and performers from a StashAPP instance into the Omnyx media database
*
* This function performs the following steps:
* 1. Fetches existing media and cast from Kyoo to check for duplicates
* 1. Fetches existing media and cast from Omnyx to check for duplicates
* 2. Fetches all scenes from StashAPP via GraphQL
* 3. Extracts unique performers from all scenes
* 4. Imports or updates performers first
@@ -499,7 +499,7 @@ export async function importFromStashAPP(
logCallback('Starting StashAPP import...');
// Step 0: Fetch existing media and cast to check for duplicates
logCallback('Fetching existing media from Kyoo API...');
logCallback('Fetching existing media from Omnyx API...');
const existingMediaResponse = await fetch(`${BASE_URL}/api/media`);
const existingMediaData = await existingMediaResponse.json();
const existingTitles = new Set(
@@ -507,7 +507,7 @@ export async function importFromStashAPP(
);
logCallback(`Found ${existingTitles.size} existing videos in database`);
logCallback('Fetching existing cast from Kyoo API...');
logCallback('Fetching existing cast from Omnyx API...');
const existingCastResponse = await fetch(`${BASE_URL}/api/cast`, {});
const existingCastData = await existingCastResponse.json();
const existingActors = new Map<string, Staff>(
+5 -5
View File
@@ -1,7 +1,7 @@
/**
* XBVR Importer Module
*
* This module provides functionality to import VR adult video content from an XBVR instance into the Kyoo media database.
* This module provides functionality to import VR adult video content from an XBVR instance into the Omnyx media database.
* It fetches scene data from the DeoVR API endpoint, extracts actors and video details, and handles both new imports
* and updates to existing entries. The module specifically filters for content in the 'Recent' scene group.
*
@@ -124,10 +124,10 @@ export type LogCallback = (message: string) => void;
export type ProgressCallback = (progress: Partial<ImportProgress>) => void;
/**
* Imports VR adult videos and actors from an XBVR instance into the Kyoo media database
* Imports VR adult videos and actors from an XBVR instance into the Omnyx media database
*
* This function performs the following steps:
* 1. Fetches existing media and cast from Kyoo to check for duplicates
* 1. Fetches existing media and cast from Omnyx to check for duplicates
* 2. Fetches the scene list from the DeoVR API endpoint
* 3. Extracts videos from the 'Recent' scene group
* 4. Fetches detailed information for each video
@@ -170,7 +170,7 @@ export async function importFromXBVR(
logCallback('Starting DeoVR import...');
// Step 0: Fetch existing media and cast to check for duplicates
logCallback('Fetching existing media from Kyoo API...');
logCallback('Fetching existing media from Omnyx API...');
const existingMediaResponse = await fetch(`${BASE_URL}/api/media?limit=1000`);
const existingMediaData = await existingMediaResponse.json();
const existingTitles = new Set(
@@ -178,7 +178,7 @@ export async function importFromXBVR(
);
logCallback(`Found ${existingTitles.size} existing videos in database`);
logCallback('Fetching existing cast from Kyoo API...');
logCallback('Fetching existing cast from Omnyx API...');
const existingCastResponse = await fetch(`${BASE_URL}/api/cast?limit=1000`);
const existingCastData = await existingCastResponse.json();
const existingActors = new Map(