This commit is contained in:
2025-11-06 02:27:46 +11:00
commit e5d558fd98
51 changed files with 11385 additions and 0 deletions

80
src/shared/ipc.ts Normal file
View File

@@ -0,0 +1,80 @@
/** Enumerates IPC channels shared between renderer and main. */
export const IPC_CHANNELS = {
settingsGet: 'settings:get',
settingsSetLibrary: 'settings:set-library',
dialogSelectLibrary: 'dialog:select-library',
libraryScan: 'library:scan',
libraryList: 'library:list',
libraryDuplicates: 'library:duplicates',
libraryRename: 'library:rename',
libraryMove: 'library:move',
libraryOrganize: 'library:organize',
libraryCustomName: 'library:custom-name',
libraryOpenFolder: 'library:open-folder',
libraryDelete: 'library:delete',
libraryBuffer: 'library:buffer',
libraryMetadata: 'library:metadata',
libraryMetadataSuggestions: 'library:metadata-suggestions',
libraryUpdateMetadata: 'library:update-metadata',
libraryWaveformPreview: 'library:waveform-preview',
tagsUpdate: 'tags:update',
categoriesList: 'categories:list',
searchQuery: 'search:query'
} as const;
export type IpcChannelKeys = keyof typeof IPC_CHANNELS;
/**
* API surface exposed to the renderer through the preload script.
*/
export interface RendererApi {
/** Retrieves the persisted settings object. */
getSettings(): Promise<import('./models').AppSettings>;
/** Opens a dialog to select a new library path, returning the chosen directory or null. */
selectLibraryDirectory(): Promise<string | null>;
/** Persists the given library path. */
setLibraryPath(path: string): Promise<import('./models').AppSettings>;
/** Triggers a manual rescan of the library. */
rescanLibrary(): Promise<import('./models').LibraryScanSummary>;
/** Fetches the current list of audio files. */
listAudioFiles(): Promise<import('./models').AudioFileSummary[]>;
/** Fetches groups of duplicate files based on checksum. */
listDuplicates(): Promise<{ checksum: string; files: import('./models').AudioFileSummary[] }[]>;
/** Requests a rename for the target file. */
renameFile(fileId: number, newFileName: string): Promise<import('./models').AudioFileSummary>;
/** Moves a file to another subdirectory under the library root. */
moveFile(fileId: number, targetRelativeDirectory: string): Promise<import('./models').AudioFileSummary>;
/** Automatically organizes a file based on its categories. */
organizeFile(fileId: number, metadata: { customName?: string | null; author?: string | null; copyright?: string | null; rating?: number }): Promise<import('./models').AudioFileSummary>;
/** Updates the custom name for a file. */
updateCustomName(fileId: number, customName: string | null): Promise<import('./models').AudioFileSummary>;
/** Opens the file's containing folder in the system file explorer. */
openFileFolder(fileId: number): Promise<void>;
/** Deletes files from disk and database. */
deleteFiles(fileIds: number[]): Promise<void>;
/** Fetches the binary data required for playback. */
getAudioBuffer(fileId: number): Promise<import('./models').AudioBufferPayload>;
/** Returns a lightweight waveform preview for rendering list backgrounds. */
getWaveformPreview(fileId: number, pointCount?: number): Promise<{ samples: number[]; rms: number }>;
/** Updates free-form tags and UCS categories. */
updateTagging(payload: import('./models').TagUpdatePayload): Promise<import('./models').AudioFileSummary>;
/** Returns the catalog of UCS categories. */
listCategories(): Promise<import('./models').CategoryRecord[]>;
/** Runs fuzzy search returning ranked results. */
search(query: string): Promise<import('./models').AudioFileSummary[]>;
/** Reads embedded metadata from a WAV file. */
readFileMetadata(fileId: number): Promise<{ author?: string; copyright?: string; title?: string; rating?: number }>;
/** Lists distinct metadata values gathered from the library for quick suggestions. */
listMetadataSuggestions(): Promise<{ authors: string[]; copyrights: string[] }>;
/** Updates metadata (author, copyright, rating) without organizing the file. */
updateFileMetadata(fileId: number, metadata: { author?: string | null; copyright?: string | null; rating?: number }): Promise<void>;
/** Listens for menu actions from the main process. Returns a cleanup function. */
onMenuAction(channel: string, callback: () => void): () => void;
}
declare global {
interface Window {
/** Bridge API injected by the preload script. */
api: RendererApi;
}
}

109
src/shared/models.ts Normal file
View File

@@ -0,0 +1,109 @@
/**
* Represents a summarized view of an audio file for list displays and searches.
*/
export interface AudioFileSummary {
/** Unique identifier inside the database. */
id: number;
/** Filename with extension. */
fileName: string;
/** User-friendly display name (no extension). */
displayName: string;
/** Absolute path on disk. */
absolutePath: string;
/** Path relative to the configured library root. */
relativePath: string;
/** Last modified timestamp (epoch milliseconds). */
modifiedAt: number;
/** File creation timestamp (epoch milliseconds) if available. */
createdAt: number | null;
/** File size in bytes. */
size: number;
/** Duration in milliseconds if known. */
durationMs: number | null;
/** Sample rate in Hz if known. */
sampleRate: number | null;
/** Bit depth if known. */
bitDepth: number | null;
/** Content checksum used for duplicate detection. */
checksum: string | null;
/** Applied descriptive tags. */
tags: string[];
/** Associated UCS categories. */
categories: string[];
/** Custom name for file organization. */
customName: string | null;
}
/**
* Represents a group of files that share the same checksum.
*/
export interface DuplicateGroup {
/** MD5 checksum shared by all files in the group. */
checksum: string;
/** Files that have identical content. */
files: AudioFileSummary[];
}
/**
* Structure describing a UCS category.
*/
export interface CategoryRecord {
/** Category identifier (CatID from UCS). */
id: string;
/** High level category name. */
category: string;
/** Sub-category label. */
subCategory: string;
/** Short hand for the category. */
shortCode: string;
/** Human readable explanation. */
explanation: string;
/** List of synonym keywords. */
synonyms: string[];
}
/**
* Summary report for a library scan run.
*/
export interface LibraryScanSummary {
/** Number of newly discovered files. */
added: number;
/** Number of existing records refreshed. */
updated: number;
/** Number of database records removed because the files disappeared. */
removed: number;
/** Total records after the scan. */
total: number;
}
/**
* Shape of persisted application settings.
*/
export interface AppSettings {
/** Current library root path. */
libraryPath: string | null;
}
/**
* Payload for tag updates flowing from the renderer to the main process.
*/
export interface TagUpdatePayload {
/** Target audio file id. */
fileId: number;
/** Free-form tag collection. */
tags: string[];
/** UCS category identifiers to attach. */
categories: string[];
}
/**
* Response for playback requests containing file binary data.
*/
export interface AudioBufferPayload {
/** Original file id to trace usage. */
fileId: number;
/** Raw audio data. */
buffer: ArrayBuffer;
/** MIME type for the audio data. */
mimeType: string;
}