Enable ESLint no-unused-vars rule (#4367)

# Description of Changes
Enable ESLint [no-unused-vars
rule](https://typescript-eslint.io/rules/no-unused-vars/)
This commit is contained in:
James Brunton
2025-09-05 11:16:17 +00:00
committed by GitHub
parent 87c63efcec
commit bd13f6bf57
102 changed files with 303 additions and 825 deletions
@@ -1,7 +1,7 @@
import { describe, expect, test, vi, beforeEach, MockedFunction } from 'vitest';
import { describe, expect, test, vi, beforeEach } from 'vitest';
import { renderHook } from '@testing-library/react';
import { useAddPasswordOperation } from './useAddPasswordOperation';
import type { AddPasswordFullParameters, AddPasswordParameters } from './useAddPasswordParameters';
import type { AddPasswordFullParameters } from './useAddPasswordParameters';
// Mock the useToolOperation hook
vi.mock('../shared/useToolOperation', async () => {
@@ -3,7 +3,6 @@ import { useCallback } from 'react';
import { executeAutomationSequence } from '../../../utils/automationExecutor';
import { useFlatToolRegistry } from '../../../data/useTranslatedToolRegistry';
import { AutomateParameters } from '../../../types/automation';
import { AUTOMATION_CONSTANTS } from '../../../constants/automation';
export function useAutomateOperation() {
const toolRegistry = useFlatToolRegistry();
@@ -44,9 +44,9 @@ export function useSavedAutomations() {
const copyFromSuggested = useCallback(async (suggestedAutomation: SuggestedAutomation) => {
try {
const { automationStorage } = await import('../../../services/automationStorage');
// Map suggested automation icons to MUI icon keys
const getIconKey = (suggestedIcon: {id: string}): string => {
const getIconKey = (_suggestedIcon: {id: string}): string => {
// Check the automation ID or name to determine the appropriate icon
switch (suggestedAutomation.id) {
case 'secure-pdf-ingestion':
@@ -60,7 +60,7 @@ export function useSavedAutomations() {
return 'SettingsIcon'; // Default fallback
}
};
// Convert suggested automation to saved automation format
const savedAutomation = {
name: suggestedAutomation.name,
@@ -68,7 +68,7 @@ export function useSavedAutomations() {
icon: getIconKey(suggestedAutomation.icon),
operations: suggestedAutomation.operations
};
await automationStorage.saveAutomation(savedAutomation);
// Refresh the list after saving
refreshAutomations();
@@ -91,4 +91,4 @@ export function useSavedAutomations() {
deleteAutomation,
copyFromSuggested
};
}
}
@@ -6,7 +6,6 @@ import { SuggestedAutomation } from '../../../types/automation';
// Create icon components
const CompressIcon = () => React.createElement(LocalIcon, { icon: 'compress', width: '1.5rem', height: '1.5rem' });
const TextFieldsIcon = () => React.createElement(LocalIcon, { icon: 'text-fields', width: '1.5rem', height: '1.5rem' });
const SecurityIcon = () => React.createElement(LocalIcon, { icon: 'security', width: '1.5rem', height: '1.5rem' });
const StarIcon = () => React.createElement(LocalIcon, { icon: 'star', width: '1.5rem', height: '1.5rem' });
@@ -1,5 +1,5 @@
import { useTranslation } from 'react-i18next';
import { useToolOperation, ToolOperationConfig, ToolType } from '../shared/useToolOperation';
import { useToolOperation, ToolType } from '../shared/useToolOperation';
import { createStandardErrorHandler } from '../../../utils/toolErrorHandler';
import { CompressParameters, defaultParameters } from './useCompressParameters';
@@ -2,9 +2,8 @@ import { useCallback } from 'react';
import axios from 'axios';
import { useTranslation } from 'react-i18next';
import { ConvertParameters, defaultParameters } from './useConvertParameters';
import { detectFileExtension } from '../../../utils/fileUtils';
import { createFileFromApiResponse } from '../../../utils/fileResponseUtils';
import { useToolOperation, ToolOperationConfig, ToolType } from '../shared/useToolOperation';
import { useToolOperation, ToolType } from '../shared/useToolOperation';
import { getEndpointUrl, isImageFormat, isWebFormat } from '../../../utils/convertUtils';
// Static function that can be used by both the hook and automation executor
@@ -2,7 +2,6 @@ import {
COLOR_TYPES,
OUTPUT_OPTIONS,
FIT_OPTIONS,
TO_FORMAT_OPTIONS,
CONVERSION_MATRIX,
type ColorType,
type OutputOption,
@@ -127,7 +126,7 @@ export const useConvertParameters = (): ConvertParametersHook => {
endpointName: getEndpointName,
validateFn: validateParameters,
}), []);
const baseHook = useBaseParameters(config);
const getEndpoint = () => {
@@ -166,7 +165,7 @@ export const useConvertParameters = (): ConvertParametersHook => {
if (prev.isSmartDetection === false && prev.smartDetectionType === 'none') {
return prev; // No change needed
}
return {
...prev,
isSmartDetection: false,
@@ -290,13 +289,13 @@ export const useConvertParameters = (): ConvertParametersHook => {
// All files are images - use image-to-pdf conversion
baseHook.setParameters(prev => {
// Only update if something actually changed
if (prev.isSmartDetection === true &&
prev.smartDetectionType === 'images' &&
prev.fromExtension === 'image' &&
if (prev.isSmartDetection === true &&
prev.smartDetectionType === 'images' &&
prev.fromExtension === 'image' &&
prev.toExtension === 'pdf') {
return prev; // No change needed
}
return {
...prev,
isSmartDetection: true,
@@ -309,13 +308,13 @@ export const useConvertParameters = (): ConvertParametersHook => {
// All files are web files - use html-to-pdf conversion
baseHook.setParameters(prev => {
// Only update if something actually changed
if (prev.isSmartDetection === true &&
prev.smartDetectionType === 'web' &&
prev.fromExtension === 'html' &&
if (prev.isSmartDetection === true &&
prev.smartDetectionType === 'web' &&
prev.fromExtension === 'html' &&
prev.toExtension === 'pdf') {
return prev; // No change needed
}
return {
...prev,
isSmartDetection: true,
@@ -328,13 +327,13 @@ export const useConvertParameters = (): ConvertParametersHook => {
// Mixed non-image types - use file-to-pdf conversion
baseHook.setParameters(prev => {
// Only update if something actually changed
if (prev.isSmartDetection === true &&
prev.smartDetectionType === 'mixed' &&
prev.fromExtension === 'any' &&
if (prev.isSmartDetection === true &&
prev.smartDetectionType === 'mixed' &&
prev.fromExtension === 'any' &&
prev.toExtension === 'pdf') {
return prev; // No change needed
}
return {
...prev,
isSmartDetection: true,
@@ -4,7 +4,7 @@
*/
import { describe, test, expect } from 'vitest';
import { renderHook, act, waitFor } from '@testing-library/react';
import { renderHook, act } from '@testing-library/react';
import { useConvertParameters } from './useConvertParameters';
describe('useConvertParameters - Auto Detection & Smart Conversion', () => {
@@ -4,7 +4,7 @@ import { createStandardErrorHandler } from '../../../utils/toolErrorHandler';
import { RemoveCertificateSignParameters, defaultParameters } from './useRemoveCertificateSignParameters';
// Static function that can be used by both the hook and automation executor
export const buildRemoveCertificateSignFormData = (parameters: RemoveCertificateSignParameters, file: File): FormData => {
export const buildRemoveCertificateSignFormData = (_parameters: RemoveCertificateSignParameters, file: File): FormData => {
const formData = new FormData();
formData.append("fileInput", file);
return formData;
@@ -4,7 +4,7 @@ import { createStandardErrorHandler } from '../../../utils/toolErrorHandler';
import { RepairParameters, defaultParameters } from './useRepairParameters';
// Static function that can be used by both the hook and automation executor
export const buildRepairFormData = (parameters: RepairParameters, file: File): FormData => {
export const buildRepairFormData = (_parameters: RepairParameters, file: File): FormData => {
const formData = new FormData();
formData.append("fileInput", file);
return formData;
@@ -128,7 +128,7 @@ export const useToolOperation = <TParams>(
config: ToolOperationConfig<TParams>
): ToolOperationHook<TParams> => {
const { t } = useTranslation();
const { addFiles, consumeFiles, undoConsumeFiles, actions: fileActions, selectors } = useFileContext();
const { addFiles, consumeFiles, undoConsumeFiles, selectors } = useFileContext();
// Composed hooks
const { state, actions } = useToolState();
@@ -243,7 +243,7 @@ export const useToolOperation = <TParams>(
// Replace input files with processed files (consumeFiles handles pinning)
const inputFileIds: FileId[] = [];
const inputStirlingFileStubs: StirlingFileStub[] = [];
// Build parallel arrays of IDs and records for undo tracking
for (const file of validFiles) {
const fileId = file.fileId;
@@ -320,7 +320,7 @@ export const useToolOperation = <TParams>(
try {
// Undo the consume operation
await undoConsumeFiles(inputFiles, inputStirlingFileStubs, outputFileIds);
// Clear results and operation tracking
resetResults();
@@ -4,7 +4,7 @@ import { createStandardErrorHandler } from '../../../utils/toolErrorHandler';
import { SingleLargePageParameters, defaultParameters } from './useSingleLargePageParameters';
// Static function that can be used by both the hook and automation executor
export const buildSingleLargePageFormData = (parameters: SingleLargePageParameters, file: File): FormData => {
export const buildSingleLargePageFormData = (_parameters: SingleLargePageParameters, file: File): FormData => {
const formData = new FormData();
formData.append("fileInput", file);
return formData;
@@ -71,7 +71,7 @@ export const useSplitOperation = () => {
// Custom response handler that extracts ZIP files
// Can't add to exported config because it requires access to the zip code so must be part of the hook
const responseHandler = useCallback(async (blob: Blob, originalFiles: File[]): Promise<File[]> => {
const responseHandler = useCallback(async (blob: Blob, _originalFiles: File[]): Promise<File[]> => {
// Split operations return ZIP files with multiple PDF pages
return await extractZipFiles(blob);
}, [extractZipFiles]);
@@ -4,7 +4,7 @@ import { createStandardErrorHandler } from '../../../utils/toolErrorHandler';
import { UnlockPdfFormsParameters, defaultParameters } from './useUnlockPdfFormsParameters';
// Static function that can be used by both the hook and automation executor
export const buildUnlockPdfFormsFormData = (parameters: UnlockPdfFormsParameters, file: File): FormData => {
export const buildUnlockPdfFormsFormData = (_parameters: UnlockPdfFormsParameters, file: File): FormData => {
const formData = new FormData();
formData.append("fileInput", file);
return formData;
-5
View File
@@ -184,11 +184,6 @@ export const useCookieConsent = ({ analyticsEnabled = false }: CookieConsentConf
// Force show after initialization
setTimeout(() => {
window.CookieConsent.show();
// Debug: Check if modal elements exist
const ccMain = document.getElementById('cc-main');
const consentModal = document.querySelector('.cm-wrapper');
}, 200);
} catch (error) {
+11 -12
View File
@@ -19,17 +19,17 @@ export function useEndpointEnabled(endpoint: string): {
setLoading(false);
return;
}
try {
setLoading(true);
setError(null);
const response = await fetch(`/api/v1/config/endpoint-enabled?endpoint=${encodeURIComponent(endpoint)}`);
if (!response.ok) {
throw new Error(`Failed to check endpoint: ${response.status} ${response.statusText}`);
}
const isEnabled: boolean = await response.json();
setEnabled(isEnabled);
} catch (err) {
@@ -72,27 +72,27 @@ export function useMultipleEndpointsEnabled(endpoints: string[]): {
setLoading(false);
return;
}
try {
setLoading(true);
setError(null);
// Use batch API for efficiency
const endpointsParam = endpoints.join(',');
const response = await fetch(`/api/v1/config/endpoints-enabled?endpoints=${encodeURIComponent(endpointsParam)}`);
if (!response.ok) {
throw new Error(`Failed to check endpoints: ${response.status} ${response.statusText}`);
}
const statusMap: Record<string, boolean> = await response.json();
setEndpointStatus(statusMap);
} catch (err) {
const errorMessage = err instanceof Error ? err.message : 'Unknown error occurred';
setError(errorMessage);
console.error('Failed to check multiple endpoints:', err);
// Fallback: assume all endpoints are disabled on error
const fallbackStatus = endpoints.reduce((acc, endpoint) => {
acc[endpoint] = false;
@@ -105,7 +105,6 @@ export function useMultipleEndpointsEnabled(endpoints: string[]): {
};
useEffect(() => {
const endpointsKey = endpoints.join(',');
fetchAllEndpointStatuses();
}, [endpoints.join(',')]); // Re-run when endpoints array changes
@@ -115,4 +114,4 @@ export function useMultipleEndpointsEnabled(endpoints: string[]): {
error,
refetch: fetchAllEndpointStatuses,
};
}
}
+21 -21
View File
@@ -49,7 +49,7 @@ export function useEnhancedProcessedFiles(
// Process files when activeFiles changes
useEffect(() => {
console.log('useEnhancedProcessedFiles: activeFiles changed', activeFiles.length, 'files');
if (activeFiles.length === 0) {
console.log('useEnhancedProcessedFiles: No active files, clearing processed cache');
setProcessedFiles(new Map());
@@ -60,15 +60,15 @@ export function useEnhancedProcessedFiles(
const processFiles = async () => {
const newProcessedFiles = new Map<File, ProcessedFile>();
for (const file of activeFiles) {
// Generate hash for this file
const fileHash = await FileHasher.generateHybridHash(file);
fileHashMapRef.current.set(file, fileHash);
// First, check if we have this exact File object cached
let existing = processedFiles.get(file);
// If not found by File object, try to find by hash in case File was recreated
if (!existing) {
for (const [cachedFile, processed] of processedFiles.entries()) {
@@ -79,7 +79,7 @@ export function useEnhancedProcessedFiles(
}
}
}
if (existing) {
newProcessedFiles.set(file, existing);
continue;
@@ -94,11 +94,11 @@ export function useEnhancedProcessedFiles(
console.error(`Failed to start processing for ${file.name}:`, error);
}
}
// Only update if the content actually changed
const hasChanged = newProcessedFiles.size !== processedFiles.size ||
Array.from(newProcessedFiles.keys()).some(file => !processedFiles.has(file));
if (hasChanged) {
setProcessedFiles(newProcessedFiles);
}
@@ -112,20 +112,20 @@ export function useEnhancedProcessedFiles(
const checkForCompletedFiles = async () => {
let hasNewFiles = false;
const updatedFiles = new Map(processedFiles);
// Generate file keys for all files first
const fileKeyPromises = activeFiles.map(async (file) => ({
file,
key: await FileHasher.generateHybridHash(file)
}));
const fileKeyPairs = await Promise.all(fileKeyPromises);
for (const { file, key } of fileKeyPairs) {
// Only check files that don't have processed results yet
if (!updatedFiles.has(file)) {
const processingState = processingStates.get(key);
// Check for both processing and recently completed files
// This ensures we catch completed files before they're cleaned up
if (processingState?.status === 'processing' || processingState?.status === 'completed') {
@@ -135,13 +135,13 @@ export function useEnhancedProcessedFiles(
updatedFiles.set(file, processed);
hasNewFiles = true;
}
} catch (error) {
} catch {
// Ignore errors in completion check
}
}
}
}
if (hasNewFiles) {
setProcessedFiles(updatedFiles);
}
@@ -158,11 +158,11 @@ export function useEnhancedProcessedFiles(
const currentFiles = new Set(activeFiles);
const previousFiles = Array.from(processedFiles.keys());
const removedFiles = previousFiles.filter(file => !currentFiles.has(file));
if (removedFiles.length > 0) {
// Clean up processing service cache
enhancedPDFProcessingService.cleanup(removedFiles);
// Update local state
setProcessedFiles(prev => {
const updated = new Map();
@@ -179,10 +179,10 @@ export function useEnhancedProcessedFiles(
// Calculate derived state
const isProcessing = processingStates.size > 0;
const hasProcessingErrors = Array.from(processingStates.values()).some(state => state.status === 'error');
// Calculate overall progress
const processingProgress = calculateProcessingProgress(processingStates);
// Get cache stats and metrics
const cacheStats = enhancedPDFProcessingService.getCacheStats();
const metrics = enhancedPDFProcessingService.getMetrics();
@@ -192,7 +192,7 @@ export function useEnhancedProcessedFiles(
cancelProcessing: (fileKey: string) => {
enhancedPDFProcessingService.cancelProcessing(fileKey);
},
retryProcessing: async (file: File) => {
try {
await enhancedPDFProcessingService.processFile(file, config);
@@ -200,7 +200,7 @@ export function useEnhancedProcessedFiles(
console.error(`Failed to retry processing for ${file.name}:`, error);
}
},
clearCache: () => {
enhancedPDFProcessingService.clearAll();
}
@@ -279,7 +279,7 @@ export function useEnhancedProcessedFile(
};
} {
const result = useEnhancedProcessedFiles(file ? [file] : [], config);
const processedFile = file ? result.processedFiles.get(file) || null : null;
// Note: This is async but we can't await in hook return - consider refactoring if needed
const fileKey = file ? '' : '';
@@ -309,4 +309,4 @@ export function useEnhancedProcessedFile(
canRetry,
actions
};
}
}
-1
View File
@@ -1,7 +1,6 @@
import { useState, useCallback } from 'react';
import { useIndexedDB } from '../contexts/IndexedDBContext';
import { FileMetadata } from '../types/file';
import { generateThumbnailForFile } from '../utils/thumbnailUtils';
import { FileId } from '../types/fileContext';
export const useFileManager = () => {
+1 -15
View File
@@ -4,20 +4,6 @@ import { useIndexedDB } from "../contexts/IndexedDBContext";
import { generateThumbnailForFile } from "../utils/thumbnailUtils";
import { FileId } from "../types/fileContext";
/**
* 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
@@ -67,7 +53,7 @@ export function useIndexedDBThumbnail(file: FileMetadata | undefined | null): {
const thumbnail = await generateThumbnailForFile(fileObject);
if (!cancelled) {
setThumb(thumbnail);
// Save thumbnail to IndexedDB for persistence
if (file.id && indexedDB && thumbnail) {
try {
@@ -1,5 +1,4 @@
import { useState, useEffect } from 'react';
import * as pdfjsLib from 'pdfjs-dist';
import { pdfWorkerManager } from '../services/pdfWorkerManager';
import { StirlingFile } from '../types/fileContext';
@@ -26,7 +25,7 @@ export const usePdfSignatureDetection = (files: StirlingFile[]): PdfSignatureDet
for (const file of files) {
const arrayBuffer = await file.arrayBuffer();
try {
const pdf = await pdfWorkerManager.createDocument(arrayBuffer);
@@ -42,7 +41,7 @@ export const usePdfSignatureDetection = (files: StirlingFile[]): PdfSignatureDet
if (foundSignature) break;
}
// Clean up PDF document using worker manager
pdfWorkerManager.destroyDocument(pdf);
} catch (error) {
@@ -66,4 +65,4 @@ export const usePdfSignatureDetection = (files: StirlingFile[]): PdfSignatureDet
hasDigitalSignatures,
isChecking
};
};
};
+1 -1
View File
@@ -1,4 +1,4 @@
import { useCallback, useRef } from 'react';
import { useCallback } from 'react';
import { thumbnailGenerationService } from '../services/thumbnailGenerationService';
import { createQuickKey } from '../types/fileContext';
import { FileId } from '../types/file';
+1 -10
View File
@@ -1,4 +1,4 @@
import React, { useState, useCallback, useMemo, useEffect } from 'react';
import { useState, useCallback, useMemo } from 'react';
import { useTranslation } from 'react-i18next';
import { useFlatToolRegistry } from "../data/useTranslatedToolRegistry";
import { getAllEndpoints, type ToolRegistryEntry } from "../data/toolsTaxonomy";
@@ -20,15 +20,6 @@ export const useToolManagement = (): ToolManagementResult => {
// Build endpoints list from registry entries with fallback to legacy mapping
const baseRegistry = useFlatToolRegistry();
const registryDerivedEndpoints = useMemo(() => {
const endpointsByTool: Record<string, string[]> = {};
Object.entries(baseRegistry).forEach(([key, entry]) => {
if (entry.endpoints && entry.endpoints.length > 0) {
endpointsByTool[key] = entry.endpoints;
}
});
return endpointsByTool;
}, [baseRegistry]);
const allEndpoints = useMemo(() => getAllEndpoints(baseRegistry), [baseRegistry]);
const { endpointStatus, loading: endpointsLoading } = useMultipleEndpointsEnabled(allEndpoints);
+5 -5
View File
@@ -10,8 +10,8 @@ type ToolParameterValues = Record<string, any>;
* Register tool parameters and get current values
*/
export function useToolParameters(
toolName: string,
parameters: Record<string, any>
_toolName: string,
_parameters: Record<string, any>
): [ToolParameterValues, (updates: Partial<ToolParameterValues>) => void] {
// Return empty values and noop updater
@@ -30,9 +30,9 @@ export function useToolParameter<T = any>(
definition: any
): [T, (value: T) => void] {
const [allParams, updateParams] = useToolParameters(toolName, { [paramName]: definition });
const value = allParams[paramName] as T;
const setValue = useCallback((newValue: T) => {
updateParams({ [paramName]: newValue });
}, [paramName, updateParams]);
@@ -48,4 +48,4 @@ export function useGlobalParameters() {
const updateParameters = useCallback(() => {}, []);
return [currentValues, updateParameters];
}
}
+6 -6
View File
@@ -1,4 +1,4 @@
import { useState, useEffect, useMemo } from 'react';
import { useState, useEffect } from 'react';
import { clamp } from '../utils/genericUtils';
import { getSidebarInfo } from '../utils/sidebarUtils';
import { SidebarRefs, SidebarState } from '../types/sidebar';
@@ -65,10 +65,10 @@ export function useTooltipPosition({
sidebarRefs?: SidebarRefs;
sidebarState?: SidebarState;
}): PositionState {
const [coords, setCoords] = useState<{ top: number; left: number; arrowOffset: number | null }>({
top: 0,
left: 0,
arrowOffset: null
const [coords, setCoords] = useState<{ top: number; left: number; arrowOffset: number | null }>({
top: 0,
left: 0,
arrowOffset: null
});
const [positionReady, setPositionReady] = useState(false);
@@ -174,4 +174,4 @@ export function useTooltipPosition({
}, [open, sidebarLeft, position, gap, sidebarTooltip]);
return { coords, positionReady };
}
}