mirror of
https://github.com/Frooodle/Stirling-PDF.git
synced 2025-09-08 17:51:20 +02:00
Merge branch 'V2' into feature/v2/Filewithid-implementation
This commit is contained in:
commit
9a8110a7cb
@ -15,17 +15,16 @@ export default defineConfig(
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
rules: {
|
rules: {
|
||||||
"no-empty": "off", // Temporarily disabled until codebase conformant
|
|
||||||
"no-empty-pattern": "off", // Temporarily disabled until codebase conformant
|
|
||||||
"no-undef": "off", // Temporarily disabled until codebase conformant
|
"no-undef": "off", // Temporarily disabled until codebase conformant
|
||||||
"no-useless-escape": "off", // Temporarily disabled until codebase conformant
|
"@typescript-eslint/no-empty-object-type": [
|
||||||
"no-case-declarations": "off", // Temporarily disabled until codebase conformant
|
"error",
|
||||||
"prefer-const": "off", // Temporarily disabled until codebase conformant
|
{
|
||||||
"@typescript-eslint/ban-ts-comment": "off", // Temporarily disabled until codebase conformant
|
// Allow empty extending interfaces because there's no real reason not to, and it makes it obvious where to put extra attributes in the future
|
||||||
"@typescript-eslint/no-empty-object-type": "off", // Temporarily disabled until codebase conformant
|
allowInterfaces: 'with-single-extends',
|
||||||
|
},
|
||||||
|
],
|
||||||
"@typescript-eslint/no-explicit-any": "off", // Temporarily disabled until codebase conformant
|
"@typescript-eslint/no-explicit-any": "off", // Temporarily disabled until codebase conformant
|
||||||
"@typescript-eslint/no-require-imports": "off", // Temporarily disabled until codebase conformant
|
"@typescript-eslint/no-require-imports": "off", // Temporarily disabled until codebase conformant
|
||||||
"@typescript-eslint/no-unused-expressions": "off", // Temporarily disabled until codebase conformant
|
|
||||||
"@typescript-eslint/no-unused-vars": "off", // Temporarily disabled until codebase conformant
|
"@typescript-eslint/no-unused-vars": "off", // Temporarily disabled until codebase conformant
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -224,7 +224,7 @@ function getLicenseUrl(licenseType) {
|
|||||||
// Handle complex SPDX expressions like "(MIT AND Zlib)" or "(MIT OR CC0-1.0)"
|
// Handle complex SPDX expressions like "(MIT AND Zlib)" or "(MIT OR CC0-1.0)"
|
||||||
if (licenseType.includes('AND') || licenseType.includes('OR')) {
|
if (licenseType.includes('AND') || licenseType.includes('OR')) {
|
||||||
// Extract the first license from compound expressions for URL
|
// Extract the first license from compound expressions for URL
|
||||||
const match = licenseType.match(/\(?\s*([A-Za-z0-9\-\.]+)/);
|
const match = licenseType.match(/\(?\s*([A-Za-z0-9\-.]+)/);
|
||||||
if (match && licenseUrls[match[1]]) {
|
if (match && licenseUrls[match[1]]) {
|
||||||
return licenseUrls[match[1]];
|
return licenseUrls[match[1]];
|
||||||
}
|
}
|
||||||
|
@ -17,8 +17,7 @@ import {
|
|||||||
getActiveNavButton,
|
getActiveNavButton,
|
||||||
} from './quickAccessBar/QuickAccessBar';
|
} from './quickAccessBar/QuickAccessBar';
|
||||||
|
|
||||||
const QuickAccessBar = forwardRef<HTMLDivElement>(({
|
const QuickAccessBar = forwardRef<HTMLDivElement>((_, ref) => {
|
||||||
}, ref) => {
|
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { isRainbowMode } = useRainbowThemeContext();
|
const { isRainbowMode } = useRainbowThemeContext();
|
||||||
const { openFilesModal, isFilesModalOpen } = useFilesModalContext();
|
const { openFilesModal, isFilesModalOpen } = useFilesModalContext();
|
||||||
|
@ -82,8 +82,8 @@ export function adjustFontSizeToFit(
|
|||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
cancelAnimationFrame(raf);
|
cancelAnimationFrame(raf);
|
||||||
try { ro.disconnect(); } catch {}
|
try { ro.disconnect(); } catch { /* Ignore errors */ }
|
||||||
try { mo.disconnect(); } catch {}
|
try { mo.disconnect(); } catch { /* Ignore errors */ }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,8 +3,6 @@ import { Stack, Text, Divider, Card, Group } from '@mantine/core';
|
|||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { useSuggestedTools } from '../../../hooks/useSuggestedTools';
|
import { useSuggestedTools } from '../../../hooks/useSuggestedTools';
|
||||||
|
|
||||||
export interface SuggestedToolsSectionProps {}
|
|
||||||
|
|
||||||
export function SuggestedToolsSection(): React.ReactElement {
|
export function SuggestedToolsSection(): React.ReactElement {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const suggestedTools = useSuggestedTools();
|
const suggestedTools = useSuggestedTools();
|
||||||
|
@ -126,7 +126,7 @@ const ToolSearch = ({
|
|||||||
key={id}
|
key={id}
|
||||||
variant="subtle"
|
variant="subtle"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
onToolSelect && onToolSelect(id);
|
onToolSelect?.(id);
|
||||||
setDropdownOpen(false);
|
setDropdownOpen(false);
|
||||||
}}
|
}}
|
||||||
leftSection={<div style={{ color: "var(--tools-text-and-icon-color)" }}>{tool.icon}</div>}
|
leftSection={<div style={{ color: "var(--tools-text-and-icon-color)" }}>{tool.icon}</div>}
|
||||||
|
@ -347,9 +347,9 @@ describe('useConvertParameters - Auto Detection & Smart Conversion', () => {
|
|||||||
|
|
||||||
const malformedFiles: Array<{name: string}> = [
|
const malformedFiles: Array<{name: string}> = [
|
||||||
{ name: 'valid.pdf' },
|
{ name: 'valid.pdf' },
|
||||||
// @ts-ignore - Testing runtime resilience
|
// @ts-expect-error - Testing runtime resilience
|
||||||
{ name: null },
|
{ name: null },
|
||||||
// @ts-ignore
|
// @ts-expect-error - Testing runtime resilience
|
||||||
{ name: undefined }
|
{ name: undefined }
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -172,7 +172,7 @@ export const useToolOperation = <TParams>(
|
|||||||
const validRegularFiles = extractFiles(validFiles);
|
const validRegularFiles = extractFiles(validFiles);
|
||||||
|
|
||||||
switch (config.toolType) {
|
switch (config.toolType) {
|
||||||
case ToolType.singleFile:
|
case ToolType.singleFile: {
|
||||||
// Individual file processing - separate API call per file
|
// Individual file processing - separate API call per file
|
||||||
const apiCallsConfig: ApiCallsConfig<TParams> = {
|
const apiCallsConfig: ApiCallsConfig<TParams> = {
|
||||||
endpoint: config.endpoint,
|
endpoint: config.endpoint,
|
||||||
@ -188,8 +188,9 @@ export const useToolOperation = <TParams>(
|
|||||||
actions.setStatus
|
actions.setStatus
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case ToolType.multiFile:
|
case ToolType.multiFile: {
|
||||||
// Multi-file processing - single API call with all files
|
// Multi-file processing - single API call with all files
|
||||||
actions.setStatus('Processing files...');
|
actions.setStatus('Processing files...');
|
||||||
const formData = config.buildFormData(params, validRegularFiles);
|
const formData = config.buildFormData(params, validRegularFiles);
|
||||||
@ -217,6 +218,7 @@ export const useToolOperation = <TParams>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case ToolType.custom:
|
case ToolType.custom:
|
||||||
actions.setStatus('Processing files...');
|
actions.setStatus('Processing files...');
|
||||||
@ -319,6 +321,7 @@ export const useToolOperation = <TParams>(
|
|||||||
// Undo the consume operation
|
// Undo the consume operation
|
||||||
await undoConsumeFiles(inputFiles, inputStirlingFileStubs, outputFileIds);
|
await undoConsumeFiles(inputFiles, inputStirlingFileStubs, outputFileIds);
|
||||||
|
|
||||||
|
|
||||||
// Clear results and operation tracking
|
// Clear results and operation tracking
|
||||||
resetResults();
|
resetResults();
|
||||||
lastOperationRef.current = null;
|
lastOperationRef.current = null;
|
||||||
|
@ -35,8 +35,11 @@ function updatePosthogConsent(){
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const optIn = (window.CookieConsent as any).acceptedCategory('analytics');
|
const optIn = (window.CookieConsent as any).acceptedCategory('analytics');
|
||||||
optIn?
|
if (optIn) {
|
||||||
posthog.opt_in_capturing() : posthog.opt_out_capturing();
|
posthog.opt_in_capturing();
|
||||||
|
} else {
|
||||||
|
posthog.opt_out_capturing();
|
||||||
|
}
|
||||||
|
|
||||||
console.log("Updated analytics consent: ", optIn? "opted in" : "opted out");
|
console.log("Updated analytics consent: ", optIn? "opted in" : "opted out");
|
||||||
}
|
}
|
||||||
|
@ -460,13 +460,14 @@ export class EnhancedPDFProcessingService {
|
|||||||
case 'failed':
|
case 'failed':
|
||||||
this.metrics.failedFiles++;
|
this.metrics.failedFiles++;
|
||||||
break;
|
break;
|
||||||
case 'cacheHit':
|
case 'cacheHit': {
|
||||||
// Update cache hit rate
|
// Update cache hit rate
|
||||||
const totalAttempts = this.metrics.totalFiles + 1;
|
const totalAttempts = this.metrics.totalFiles + 1;
|
||||||
this.metrics.cacheHitRate = (this.metrics.cacheHitRate * this.metrics.totalFiles + 1) / totalAttempts;
|
this.metrics.cacheHitRate = (this.metrics.cacheHitRate * this.metrics.totalFiles + 1) / totalAttempts;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get processing metrics
|
* Get processing metrics
|
||||||
@ -520,10 +521,7 @@ export class EnhancedPDFProcessingService {
|
|||||||
this.notifyListeners();
|
this.notifyListeners();
|
||||||
|
|
||||||
// Force memory cleanup hint
|
// Force memory cleanup hint
|
||||||
if (typeof window !== 'undefined' && window.gc) {
|
setTimeout(() => window.gc?.(), 100);
|
||||||
let gc = window.gc;
|
|
||||||
setTimeout(() => gc(), 100);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -148,15 +148,17 @@ export class FileAnalyzer {
|
|||||||
case 'immediate_full':
|
case 'immediate_full':
|
||||||
return pageCount * baseTime;
|
return pageCount * baseTime;
|
||||||
|
|
||||||
case 'priority_pages':
|
case 'priority_pages': {
|
||||||
// Estimate time for priority pages (first 10)
|
// Estimate time for priority pages (first 10)
|
||||||
const priorityPages = Math.min(pageCount, 10);
|
const priorityPages = Math.min(pageCount, 10);
|
||||||
return priorityPages * baseTime;
|
return priorityPages * baseTime;
|
||||||
|
}
|
||||||
|
|
||||||
case 'progressive_chunked':
|
case 'progressive_chunked': {
|
||||||
// Estimate time for first chunk (20 pages)
|
// Estimate time for first chunk (20 pages)
|
||||||
const firstChunk = Math.min(pageCount, 20);
|
const firstChunk = Math.min(pageCount, 20);
|
||||||
return firstChunk * baseTime;
|
return firstChunk * baseTime;
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return pageCount * baseTime;
|
return pageCount * baseTime;
|
||||||
|
@ -92,8 +92,6 @@ class IndexedDBManager {
|
|||||||
|
|
||||||
// Create or update object stores
|
// Create or update object stores
|
||||||
config.stores.forEach(storeConfig => {
|
config.stores.forEach(storeConfig => {
|
||||||
let store: IDBObjectStore;
|
|
||||||
|
|
||||||
if (db.objectStoreNames.contains(storeConfig.name)) {
|
if (db.objectStoreNames.contains(storeConfig.name)) {
|
||||||
// Store exists - for now, just continue (could add migration logic here)
|
// Store exists - for now, just continue (could add migration logic here)
|
||||||
console.log(`Object store '${storeConfig.name}' already exists`);
|
console.log(`Object store '${storeConfig.name}' already exists`);
|
||||||
@ -109,7 +107,7 @@ class IndexedDBManager {
|
|||||||
options.autoIncrement = storeConfig.autoIncrement;
|
options.autoIncrement = storeConfig.autoIncrement;
|
||||||
}
|
}
|
||||||
|
|
||||||
store = db.createObjectStore(storeConfig.name, options);
|
const store = db.createObjectStore(storeConfig.name, options);
|
||||||
console.log(`Created object store '${storeConfig.name}'`);
|
console.log(`Created object store '${storeConfig.name}'`);
|
||||||
|
|
||||||
// Create indexes
|
// Create indexes
|
||||||
|
@ -94,6 +94,7 @@ class PDFWorkerManager {
|
|||||||
try {
|
try {
|
||||||
loadingTask.destroy();
|
loadingTask.destroy();
|
||||||
} catch (destroyError) {
|
} catch (destroyError) {
|
||||||
|
// Ignore errors
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
throw error;
|
throw error;
|
||||||
@ -166,6 +167,7 @@ class PDFWorkerManager {
|
|||||||
try {
|
try {
|
||||||
pdf.destroy();
|
pdf.destroy();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
// Ignore errors
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
// Base parameter interfaces for reusable patterns
|
// Base parameter interfaces for reusable patterns
|
||||||
|
|
||||||
export interface BaseParameters {
|
// Base interface that all tool parameters should extend
|
||||||
// Base interface that all tool parameters should extend
|
// Provides a foundation for adding common properties across all tools
|
||||||
// Provides a foundation for adding common properties across all tools
|
// Examples of future additions: userId, sessionId, commonFlags, etc.
|
||||||
// Examples of future additions: userId, sessionId, commonFlags, etc.
|
export type BaseParameters = object
|
||||||
}
|
|
||||||
|
Loading…
Reference in New Issue
Block a user