Added auto unzip file limit

This commit is contained in:
Connor Yoh 2025-10-03 13:04:57 +01:00
parent 198beb3b37
commit 04adb8cc2d
5 changed files with 111 additions and 9 deletions

View File

@ -261,7 +261,10 @@
"description": "Configure general application preferences.",
"autoUnzip": "Auto-unzip API responses",
"autoUnzipDescription": "Automatically extract files from ZIP responses",
"autoUnzipTooltip": "Automatically extract ZIP files returned from API operations. Disable to keep ZIP files intact. This does not affect automation workflows."
"autoUnzipTooltip": "Automatically extract ZIP files returned from API operations. Disable to keep ZIP files intact. This does not affect automation workflows.",
"autoUnzipFileLimit": "Auto-unzip file limit",
"autoUnzipFileLimitDescription": "Maximum number of files to extract from ZIP",
"autoUnzipFileLimitTooltip": "Only unzip if the ZIP contains this many files or fewer. Set higher to extract larger ZIPs."
},
"hotkeys": {
"title": "Keyboard Shortcuts",

View File

@ -1,11 +1,19 @@
import React from 'react';
import { Paper, Stack, Switch, Text, Tooltip } from '@mantine/core';
import React, { useState, useEffect } from 'react';
import { Paper, Stack, Switch, Text, Tooltip, NumberInput } from '@mantine/core';
import { useTranslation } from 'react-i18next';
import { usePreferences } from '../../../../contexts/PreferencesContext';
const DEFAULT_AUTO_UNZIP_FILE_LIMIT = 4;
const GeneralSection: React.FC = () => {
const { t } = useTranslation();
const { preferences, updatePreference } = usePreferences();
const [fileLimitInput, setFileLimitInput] = useState<number | string>(preferences.autoUnzipFileLimit);
// Sync local state with preference changes
useEffect(() => {
setFileLimitInput(preferences.autoUnzipFileLimit);
}, [preferences.autoUnzipFileLimit]);
return (
<Stack gap="lg">
@ -39,6 +47,39 @@ const GeneralSection: React.FC = () => {
/>
</div>
</Tooltip>
<Tooltip
label={t('settings.general.autoUnzipFileLimitTooltip', 'Only unzip if the ZIP contains this many files or fewer. Set higher to extract larger ZIPs.')}
multiline
w={300}
withArrow
>
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', cursor: 'help' }}>
<div>
<Text fw={500} size="sm">
{t('settings.general.autoUnzipFileLimit', 'Auto-unzip file limit')}
</Text>
<Text size="xs" c="dimmed" mt={4}>
{t('settings.general.autoUnzipFileLimitDescription', 'Maximum number of files to extract from ZIP')}
</Text>
</div>
<NumberInput
value={fileLimitInput}
onChange={setFileLimitInput}
onBlur={() => {
const numValue = Number(fileLimitInput);
const finalValue = (!fileLimitInput || isNaN(numValue) || numValue < 1 || numValue > 100) ? DEFAULT_AUTO_UNZIP_FILE_LIMIT : numValue;
setFileLimitInput(finalValue);
updatePreference('autoUnzipFileLimit', finalValue);
}}
min={1}
max={100}
step={1}
disabled={!preferences.autoUnzip}
style={{ width: 90 }}
/>
</div>
</Tooltip>
</Stack>
</Paper>
</Stack>

View File

@ -85,8 +85,15 @@ export const useToolResources = () => {
const extractZipFiles = useCallback(async (zipBlob: Blob, skipAutoUnzip = false): Promise<File[]> => {
try {
// Check if auto-unzip is disabled (unless explicitly skipped like in automation)
if (!skipAutoUnzip && !preferences.autoUnzip) {
// Check if we should extract based on preferences
const shouldExtract = await zipFileService.shouldUnzip(
zipBlob,
preferences.autoUnzip,
preferences.autoUnzipFileLimit,
skipAutoUnzip
);
if (!shouldExtract) {
return [new File([zipBlob], 'result.zip', { type: 'application/zip' })];
}
@ -97,12 +104,19 @@ export const useToolResources = () => {
console.error('useToolResources.extractZipFiles - Error:', error);
return [];
}
}, [preferences.autoUnzip]);
}, [preferences.autoUnzip, preferences.autoUnzipFileLimit]);
const extractAllZipFiles = useCallback(async (zipBlob: Blob, skipAutoUnzip = false): Promise<File[]> => {
try {
// Check if auto-unzip is disabled (unless explicitly skipped like in automation)
if (!skipAutoUnzip && !preferences.autoUnzip) {
// Check if we should extract based on preferences
const shouldExtract = await zipFileService.shouldUnzip(
zipBlob,
preferences.autoUnzip,
preferences.autoUnzipFileLimit,
skipAutoUnzip
);
if (!shouldExtract) {
return [new File([zipBlob], 'result.zip', { type: 'application/zip' })];
}
@ -113,7 +127,7 @@ export const useToolResources = () => {
console.error('useToolResources.extractAllZipFiles - Error:', error);
return [];
}
}, [preferences.autoUnzip]);
}, [preferences.autoUnzip, preferences.autoUnzipFileLimit]);
const createDownloadInfo = useCallback(async (
files: File[],

View File

@ -2,10 +2,12 @@ import { indexedDBManager, DATABASE_CONFIGS } from './indexedDBManager';
export interface UserPreferences {
autoUnzip: boolean;
autoUnzipFileLimit: number;
}
export const DEFAULT_PREFERENCES: UserPreferences = {
autoUnzip: true,
autoUnzipFileLimit: 4,
};
class PreferencesService {

View File

@ -324,6 +324,48 @@ export class ZipFileService {
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
}
/**
* Determine if a ZIP file should be extracted based on user preferences
*
* @param zipBlob - The ZIP file to check
* @param autoUnzip - User preference for auto-unzipping
* @param autoUnzipFileLimit - Maximum number of files to auto-extract
* @param skipAutoUnzip - Bypass preference check (for automation)
* @returns true if the ZIP should be extracted, false otherwise
*/
async shouldUnzip(
zipBlob: Blob | File,
autoUnzip: boolean,
autoUnzipFileLimit: number,
skipAutoUnzip: boolean = false
): Promise<boolean> {
try {
// Automation always extracts
if (skipAutoUnzip) {
return true;
}
// Check if auto-unzip is enabled
if (!autoUnzip) {
return false;
}
// Load ZIP and count files
const zip = new JSZip();
const zipContents = await zip.loadAsync(zipBlob);
// Count non-directory entries
const fileCount = Object.values(zipContents.files).filter(entry => !entry.dir).length;
// Only extract if within limit
return fileCount <= autoUnzipFileLimit;
} catch (error) {
console.error('Error checking shouldUnzip:', error);
// On error, default to not extracting (safer)
return false;
}
}
/**
* Extract all files from a ZIP archive (not limited to PDFs)
*/