mirror of
https://github.com/Stirling-Tools/Stirling-PDF.git
synced 2025-08-25 13:49:23 +00:00

# Description of Changes Currently, the `tsconfig.json` file enforces strict type checking, but nothing in CI checks that the code is actually correctly typed. [Vite only transpiles TypeScript code](https://vite.dev/guide/features.html#transpile-only) so doesn't ensure that the TS code we're running is correct. This PR adds running of the type checker to CI and fixes the type errors that have already crept into the codebase. Note that many of the changes I've made to 'fix the types' are just using `any` to disable the type checker because the code is under too much churn to fix anything properly at the moment. I still think enabling the type checker now is the best course of action though because otherwise we'll never be able to fix all of them, and it should at least help us not break things when adding new code. Co-authored-by: James <james@crosscourtanalytics.com>
106 lines
3.6 KiB
TypeScript
106 lines
3.6 KiB
TypeScript
import { useState, useEffect } from "react";
|
|
import { FileWithUrl } from "../types/file";
|
|
import { fileStorage } from "../services/fileStorage";
|
|
import { generateThumbnailForFile } from "../utils/thumbnailUtils";
|
|
|
|
/**
|
|
* Calculate optimal scale for thumbnail generation
|
|
* Ensures high quality while preventing oversized renders
|
|
*/
|
|
function calculateThumbnailScale(pageViewport: { width: number; height: number }): number {
|
|
const maxWidth = 400; // Max thumbnail width
|
|
const maxHeight = 600; // Max thumbnail height
|
|
|
|
const scaleX = maxWidth / pageViewport.width;
|
|
const scaleY = maxHeight / pageViewport.height;
|
|
|
|
// Don't upscale, only downscale if needed
|
|
return Math.min(scaleX, scaleY, 1.0);
|
|
}
|
|
|
|
/**
|
|
* Hook for IndexedDB-aware thumbnail loading
|
|
* Handles thumbnail generation for files not in IndexedDB
|
|
*/
|
|
export function useIndexedDBThumbnail(file: FileWithUrl | undefined | null): {
|
|
thumbnail: string | null;
|
|
isGenerating: boolean
|
|
} {
|
|
const [thumb, setThumb] = useState<string | null>(null);
|
|
const [generating, setGenerating] = useState(false);
|
|
|
|
useEffect(() => {
|
|
let cancelled = false;
|
|
|
|
async function loadThumbnail() {
|
|
if (!file) {
|
|
setThumb(null);
|
|
return;
|
|
}
|
|
|
|
// First priority: use stored thumbnail
|
|
if (file.thumbnail) {
|
|
setThumb(file.thumbnail);
|
|
return;
|
|
}
|
|
|
|
// Second priority: generate thumbnail for any file type
|
|
if (file.size < 100 * 1024 * 1024 && !generating) {
|
|
setGenerating(true);
|
|
try {
|
|
let fileObject: File;
|
|
|
|
// Handle IndexedDB files vs regular File objects
|
|
if (file.storedInIndexedDB && file.id) {
|
|
// For IndexedDB files, recreate File object from stored data
|
|
const storedFile = await fileStorage.getFile(file.id);
|
|
if (!storedFile) {
|
|
throw new Error('File not found in IndexedDB');
|
|
}
|
|
fileObject = new File([storedFile.data], storedFile.name, {
|
|
type: storedFile.type,
|
|
lastModified: storedFile.lastModified
|
|
});
|
|
} else if ((file as any /* Fix me */).file) {
|
|
// For FileWithUrl objects that have a File object
|
|
fileObject = (file as any /* Fix me */).file;
|
|
} else if (file.id) {
|
|
// Fallback: try to get from IndexedDB even if storedInIndexedDB flag is missing
|
|
const storedFile = await fileStorage.getFile(file.id);
|
|
if (!storedFile) {
|
|
throw new Error('File not found in IndexedDB and no File object available');
|
|
}
|
|
fileObject = new File([storedFile.data], storedFile.name, {
|
|
type: storedFile.type,
|
|
lastModified: storedFile.lastModified
|
|
});
|
|
} else {
|
|
throw new Error('File object not available and no ID for IndexedDB lookup');
|
|
}
|
|
|
|
// Use the universal thumbnail generator
|
|
const thumbnail = await generateThumbnailForFile(fileObject);
|
|
if (!cancelled && thumbnail) {
|
|
setThumb(thumbnail);
|
|
} else if (!cancelled) {
|
|
setThumb(null);
|
|
}
|
|
} catch (error) {
|
|
console.warn('Failed to generate thumbnail for file', file.name, error);
|
|
if (!cancelled) setThumb(null);
|
|
} finally {
|
|
if (!cancelled) setGenerating(false);
|
|
}
|
|
} else {
|
|
// Large files - generate placeholder
|
|
setThumb(null);
|
|
}
|
|
}
|
|
|
|
loadThumbnail();
|
|
return () => { cancelled = true; };
|
|
}, [file, file?.thumbnail, file?.id]);
|
|
|
|
return { thumbnail: thumb, isGenerating: generating };
|
|
}
|