# Summary - Adds desktop file tracking: local paths are preserved and save buttons now work as expcted (doing Save/Save As as appropriate) - Adds logic to track whether files are 'dirty' (they've been modified by some tool, and not saved to disk yet). - Improves file state UX (dirty vs saved) and close warnings - Web behaviour should be unaffected by these changes ## Indicators Files now have indicators in desktop mode to tell you their state. ### File up-to-date with disk <img width="318" height="393" alt="image" src="https://github.com/user-attachments/assets/06325f9a-afd7-4c2f-8a5b-6d11e3093115" /> ### File modified by a tool but not saved to disk yet <img width="357" height="385" alt="image" src="https://github.com/user-attachments/assets/1a7716d9-c6f7-4d13-be0d-c1de6493954b" /> ### File not tracked on disk <img width="312" height="379" alt="image" src="https://github.com/user-attachments/assets/9cffe300-bd9a-4e19-97c7-9b98bebefacc" /> # Limitations - It's a bit weird that we still have files stored in indexeddb in the app, which are still loadable. We might want to change this behaviour in the future - Viewer's Save doesn't persist to disk. I've left that out here because it'd need a lot of testing to make sure the logic's right with making sure you can leave the Viewer with applying the changes to the PDF _without_ saving to disk - There's no current way to do Save As on a file that has already been persisted to disk - it's only ever Save. Similarly, there's no way to duplicate a file. --------- Co-authored-by: James Brunton <jbrunton96@gmail.com> Co-authored-by: James Brunton <james@stirlingpdf.com>
88 lines
3.0 KiB
TypeScript
88 lines
3.0 KiB
TypeScript
import { useEffect, useState } from 'react';
|
|
import { useOpenedFile } from '@app/hooks/useOpenedFile';
|
|
import { fileOpenService } from '@app/services/fileOpenService';
|
|
import { useFileManagement } from '@app/contexts/file/fileHooks';
|
|
import { createQuickKey } from '@app/types/fileContext';
|
|
|
|
/**
|
|
* App initialization hook
|
|
* Desktop version: Handles Tauri-specific file initialization
|
|
* Requires FileContext - must be used inside FileContextProvider
|
|
* - Handles files opened with the app (adds directly to FileContext)
|
|
*/
|
|
export function useAppInitialization(): void {
|
|
// Get file management actions
|
|
const { addFiles, updateStirlingFileStub } = useFileManagement();
|
|
|
|
// Handle files opened with app (Tauri mode)
|
|
const { openedFilePaths, loading: openedFileLoading, consumeOpenedFilePaths } = useOpenedFile();
|
|
|
|
// Load opened files and add directly to FileContext
|
|
useEffect(() => {
|
|
if (openedFilePaths.length === 0 || openedFileLoading) {
|
|
return;
|
|
}
|
|
|
|
const loadOpenedFiles = async () => {
|
|
const filePaths = consumeOpenedFilePaths();
|
|
if (filePaths.length === 0) {
|
|
return;
|
|
}
|
|
try {
|
|
const loadedFiles = (
|
|
await Promise.all(
|
|
filePaths.map(async (filePath) => {
|
|
try {
|
|
const fileData = await fileOpenService.readFileAsArrayBuffer(filePath);
|
|
if (!fileData) return null;
|
|
|
|
const file = new File([fileData.arrayBuffer], fileData.fileName, {
|
|
type: 'application/pdf'
|
|
});
|
|
|
|
console.log('[Desktop] Loaded file:', fileData.fileName);
|
|
|
|
return {
|
|
file,
|
|
filePath,
|
|
quickKey: createQuickKey(file),
|
|
};
|
|
} catch (error) {
|
|
console.error('[Desktop] Failed to load file:', filePath, error);
|
|
return null;
|
|
}
|
|
})
|
|
)
|
|
).filter((entry): entry is { file: File; filePath: string; quickKey: string } => Boolean(entry));
|
|
|
|
if (loadedFiles.length > 0) {
|
|
const filesArray = loadedFiles.map(entry => entry.file);
|
|
const quickKeyToPath = new Map(loadedFiles.map(entry => [entry.quickKey, entry.filePath]));
|
|
|
|
const addedFiles = await addFiles(filesArray);
|
|
addedFiles.forEach(file => {
|
|
const localFilePath = quickKeyToPath.get(file.quickKey);
|
|
if (localFilePath) {
|
|
updateStirlingFileStub(file.fileId, { localFilePath });
|
|
}
|
|
});
|
|
|
|
console.log(`[Desktop] ${loadedFiles.length} opened file(s) added to FileContext`);
|
|
}
|
|
} catch (error) {
|
|
console.error('[Desktop] Failed to load opened files:', error);
|
|
}
|
|
};
|
|
|
|
loadOpenedFiles();
|
|
}, [openedFilePaths, openedFileLoading, addFiles, updateStirlingFileStub, consumeOpenedFilePaths]);
|
|
}
|
|
|
|
export function useSetupCompletion(): (completed: boolean) => void {
|
|
const [, setSetupComplete] = useState(false);
|
|
|
|
return (completed: boolean) => {
|
|
setSetupComplete(completed);
|
|
};
|
|
}
|