mirror of
https://github.com/litruv/AudioSort.git
synced 2026-07-24 02:36:01 +10:00
fix file by id in the parent field
This commit is contained in:
@@ -225,6 +225,9 @@ export class MainApp {
|
||||
|
||||
ipcMain.handle(IPC_CHANNELS.libraryScan, async () => this.requireLibrary().scanLibrary());
|
||||
ipcMain.handle(IPC_CHANNELS.libraryList, async () => this.requireLibrary().listFiles());
|
||||
ipcMain.handle(IPC_CHANNELS.libraryGetById, async (_event: IpcMainInvokeEvent, fileId: number) =>
|
||||
this.requireLibrary().getFileById(fileId)
|
||||
);
|
||||
ipcMain.handle(IPC_CHANNELS.libraryDuplicates, async () => this.requireLibrary().listDuplicates());
|
||||
ipcMain.handle(IPC_CHANNELS.searchQuery, async (_event: IpcMainInvokeEvent, query: string) =>
|
||||
this.requireSearch().search(query)
|
||||
|
||||
@@ -214,6 +214,20 @@ export class LibraryService {
|
||||
return this.database.listFiles();
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to resolve a file summary by id. Returns null when the record no longer exists.
|
||||
*/
|
||||
public getFileById(fileId: number): AudioFileSummary | null {
|
||||
try {
|
||||
return this.database.getFileById(fileId);
|
||||
} catch (error) {
|
||||
if (error instanceof Error) {
|
||||
console.warn(`Failed to resolve file by id ${fileId}:`, error.message);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns groups of files that have identical checksums (potential duplicates).
|
||||
*/
|
||||
|
||||
@@ -29,6 +29,10 @@ const api: RendererApi = {
|
||||
async listAudioFiles(): Promise<AudioFileSummary[]> {
|
||||
return ipcRenderer.invoke(IPC_CHANNELS.libraryList);
|
||||
},
|
||||
/** Retrieves a single audio file summary by id, returning null when the record no longer exists. */
|
||||
async getAudioFileById(fileId: number): Promise<AudioFileSummary | null> {
|
||||
return ipcRenderer.invoke(IPC_CHANNELS.libraryGetById, fileId);
|
||||
},
|
||||
async listDuplicates(): Promise<{ checksum: string; files: AudioFileSummary[] }[]> {
|
||||
return ipcRenderer.invoke(IPC_CHANNELS.libraryDuplicates);
|
||||
},
|
||||
|
||||
@@ -69,7 +69,7 @@ function App(): JSX.Element {
|
||||
[library.files, library.selectedFileId]
|
||||
);
|
||||
|
||||
const parentFile = useMemo(() => {
|
||||
const parentFileFromStore = useMemo(() => {
|
||||
const parentId = selectedFile?.parentFileId ?? null;
|
||||
if (parentId === null) {
|
||||
return null;
|
||||
@@ -77,6 +77,39 @@ function App(): JSX.Element {
|
||||
return library.files.find((file) => file.id === parentId) ?? null;
|
||||
}, [library.files, selectedFile?.parentFileId]);
|
||||
|
||||
const [resolvedParentFile, setResolvedParentFile] = useState<AudioFileSummary | null>(parentFileFromStore);
|
||||
|
||||
useEffect(() => {
|
||||
const parentId = selectedFile?.parentFileId ?? null;
|
||||
if (parentId === null) {
|
||||
setResolvedParentFile(null);
|
||||
return;
|
||||
}
|
||||
if (parentFileFromStore) {
|
||||
setResolvedParentFile(parentFileFromStore);
|
||||
return;
|
||||
}
|
||||
|
||||
let cancelled = false;
|
||||
(async () => {
|
||||
try {
|
||||
const fetched = await window.api.getAudioFileById(parentId);
|
||||
if (!cancelled) {
|
||||
setResolvedParentFile(fetched ?? null);
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn('Unable to resolve parent file details', { parentId, error });
|
||||
if (!cancelled) {
|
||||
setResolvedParentFile(null);
|
||||
}
|
||||
}
|
||||
})();
|
||||
|
||||
return () => {
|
||||
cancelled = true;
|
||||
};
|
||||
}, [parentFileFromStore, selectedFile?.parentFileId]);
|
||||
|
||||
const selectedFiles = useMemo(
|
||||
() => library.files.filter((file) => library.selectedFileIds.has(file.id)),
|
||||
[library.files, library.selectedFileIds]
|
||||
@@ -307,7 +340,7 @@ function App(): JSX.Element {
|
||||
<>
|
||||
<FileDetailPanel
|
||||
file={selectedFile}
|
||||
parentFile={parentFile}
|
||||
parentFile={resolvedParentFile}
|
||||
categories={library.categories}
|
||||
onRename={handleRename}
|
||||
onMove={handleMove}
|
||||
|
||||
@@ -369,7 +369,7 @@ export function FileDetailPanel({ file, parentFile, categories, onRename, onMove
|
||||
onClick={handleOpenParent}
|
||||
title={parentFile ? `Open source file ${parentFile.displayName}` : 'Open source file'}
|
||||
>
|
||||
🔗 {parentFile ? parentFile.customName || parentFile.displayName : `File #${file.parentFileId}`}
|
||||
🔗 {parentFile ? parentFile.customName || parentFile.displayName : `Source missing (#${file.parentFileId})`}
|
||||
</button>
|
||||
) : null}
|
||||
</div>
|
||||
|
||||
@@ -5,6 +5,7 @@ export const IPC_CHANNELS = {
|
||||
dialogSelectLibrary: 'dialog:select-library',
|
||||
libraryScan: 'library:scan',
|
||||
libraryList: 'library:list',
|
||||
libraryGetById: 'library:get-by-id',
|
||||
libraryDuplicates: 'library:duplicates',
|
||||
libraryRename: 'library:rename',
|
||||
libraryMove: 'library:move',
|
||||
@@ -39,6 +40,8 @@ export interface RendererApi {
|
||||
rescanLibrary(): Promise<import('./models').LibraryScanSummary>;
|
||||
/** Fetches the current list of audio files. */
|
||||
listAudioFiles(): Promise<import('./models').AudioFileSummary[]>;
|
||||
/** Retrieves a single audio file summary by id, or null if it cannot be resolved. */
|
||||
getAudioFileById(fileId: number): Promise<import('./models').AudioFileSummary | null>;
|
||||
/** Fetches groups of duplicate files based on checksum. */
|
||||
listDuplicates(): Promise<{ checksum: string; files: import('./models').AudioFileSummary[] }[]>;
|
||||
/** Requests a rename for the target file. */
|
||||
|
||||
Reference in New Issue
Block a user