mirror of
https://github.com/danny-avila/LibreChat.git
synced 2025-12-18 01:10:14 +01:00
Addressing eslint errors
This commit is contained in:
parent
a77ad276f1
commit
b6de2a8557
4 changed files with 47 additions and 46 deletions
|
|
@ -2,11 +2,11 @@ import { mergeFileConfig } from 'librechat-data-provider';
|
||||||
import { useCallback } from 'react';
|
import { useCallback } from 'react';
|
||||||
import { useGetFileConfig } from '~/data-provider';
|
import { useGetFileConfig } from '~/data-provider';
|
||||||
import {
|
import {
|
||||||
resizeImage,
|
resizeImage,
|
||||||
shouldResizeImage,
|
shouldResizeImage,
|
||||||
supportsClientSideResize,
|
supportsClientSideResize,
|
||||||
type ResizeOptions,
|
type ResizeOptions,
|
||||||
type ResizeResult,
|
type ResizeResult,
|
||||||
} from '~/utils/imageResize';
|
} from '~/utils/imageResize';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -19,6 +19,7 @@ export const useClientSideResize = () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
// Safe access to clientSideImageResize config with fallbacks
|
// Safe access to clientSideImageResize config with fallbacks
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
const config = (fileConfig as any)?.clientSideImageResize ?? {
|
const config = (fileConfig as any)?.clientSideImageResize ?? {
|
||||||
enabled: false,
|
enabled: false,
|
||||||
maxWidth: 1900,
|
maxWidth: 1900,
|
||||||
|
|
@ -66,7 +67,6 @@ export const useClientSideResize = () => {
|
||||||
return { file: result.file, resized: true, result };
|
return { file: result.file, resized: true, result };
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.warn('Client-side image resizing failed:', error);
|
console.warn('Client-side image resizing failed:', error);
|
||||||
// Return original file on error
|
|
||||||
return { file, resized: false };
|
return { file, resized: false };
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -81,4 +81,4 @@ export const useClientSideResize = () => {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export default useClientSideResize;
|
export default useClientSideResize;
|
||||||
|
|
|
||||||
|
|
@ -265,20 +265,20 @@ const useFileHandling = (params?: UseFileHandling) => {
|
||||||
const file_id = v4();
|
const file_id = v4();
|
||||||
try {
|
try {
|
||||||
let processedFile = originalFile;
|
let processedFile = originalFile;
|
||||||
|
|
||||||
// Apply client-side resizing if available and appropriate
|
// Apply client-side resizing if available and appropriate
|
||||||
if (originalFile.type.startsWith('image/')) {
|
if (originalFile.type.startsWith('image/')) {
|
||||||
try {
|
try {
|
||||||
const resizeResult = await resizeImageIfNeeded(originalFile);
|
const resizeResult = await resizeImageIfNeeded(originalFile);
|
||||||
processedFile = resizeResult.file;
|
processedFile = resizeResult.file;
|
||||||
|
|
||||||
// Show toast notification if image was resized
|
// Show toast notification if image was resized
|
||||||
if (resizeResult.resized && resizeResult.result) {
|
if (resizeResult.resized && resizeResult.result) {
|
||||||
const { originalSize, newSize, compressionRatio } = resizeResult.result;
|
const { originalSize, newSize, compressionRatio } = resizeResult.result;
|
||||||
const originalSizeMB = (originalSize / (1024 * 1024)).toFixed(1);
|
const originalSizeMB = (originalSize / (1024 * 1024)).toFixed(1);
|
||||||
const newSizeMB = (newSize / (1024 * 1024)).toFixed(1);
|
const newSizeMB = (newSize / (1024 * 1024)).toFixed(1);
|
||||||
const savedPercent = Math.round((1 - compressionRatio) * 100);
|
const savedPercent = Math.round((1 - compressionRatio) * 100);
|
||||||
|
|
||||||
showToast({
|
showToast({
|
||||||
message: `Image resized: ${originalSizeMB}MB → ${newSizeMB}MB (${savedPercent}% smaller)`,
|
message: `Image resized: ${originalSizeMB}MB → ${newSizeMB}MB (${savedPercent}% smaller)`,
|
||||||
status: 'success',
|
status: 'success',
|
||||||
|
|
|
||||||
|
|
@ -44,10 +44,10 @@ describe('imageResize utility', () => {
|
||||||
const originalCanvas = global.HTMLCanvasElement;
|
const originalCanvas = global.HTMLCanvasElement;
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
delete global.HTMLCanvasElement;
|
delete global.HTMLCanvasElement;
|
||||||
|
|
||||||
const result = supportsClientSideResize();
|
const result = supportsClientSideResize();
|
||||||
expect(result).toBe(false);
|
expect(result).toBe(false);
|
||||||
|
|
||||||
global.HTMLCanvasElement = originalCanvas;
|
global.HTMLCanvasElement = originalCanvas;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
@ -58,7 +58,7 @@ describe('imageResize utility', () => {
|
||||||
type: 'image/jpeg',
|
type: 'image/jpeg',
|
||||||
lastModified: Date.now(),
|
lastModified: Date.now(),
|
||||||
});
|
});
|
||||||
|
|
||||||
// Mock large file size
|
// Mock large file size
|
||||||
Object.defineProperty(largeImageFile, 'size', {
|
Object.defineProperty(largeImageFile, 'size', {
|
||||||
value: 100 * 1024 * 1024, // 100MB
|
value: 100 * 1024 * 1024, // 100MB
|
||||||
|
|
@ -74,7 +74,7 @@ describe('imageResize utility', () => {
|
||||||
type: 'image/jpeg',
|
type: 'image/jpeg',
|
||||||
lastModified: Date.now(),
|
lastModified: Date.now(),
|
||||||
});
|
});
|
||||||
|
|
||||||
// Mock small file size
|
// Mock small file size
|
||||||
Object.defineProperty(smallImageFile, 'size', {
|
Object.defineProperty(smallImageFile, 'size', {
|
||||||
value: 1024, // 1KB
|
value: 1024, // 1KB
|
||||||
|
|
@ -90,7 +90,7 @@ describe('imageResize utility', () => {
|
||||||
type: 'text/plain',
|
type: 'text/plain',
|
||||||
lastModified: Date.now(),
|
lastModified: Date.now(),
|
||||||
});
|
});
|
||||||
|
|
||||||
const result = shouldResizeImage(textFile);
|
const result = shouldResizeImage(textFile);
|
||||||
expect(result).toBe(false);
|
expect(result).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
@ -100,9 +100,9 @@ describe('imageResize utility', () => {
|
||||||
type: 'image/gif',
|
type: 'image/gif',
|
||||||
lastModified: Date.now(),
|
lastModified: Date.now(),
|
||||||
});
|
});
|
||||||
|
|
||||||
const result = shouldResizeImage(gifFile);
|
const result = shouldResizeImage(gifFile);
|
||||||
expect(result).toBe(false);
|
expect(result).toBe(false);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -25,10 +25,10 @@ export interface ResizeResult {
|
||||||
* We use slightly smaller values to ensure no backend resizing is triggered
|
* We use slightly smaller values to ensure no backend resizing is triggered
|
||||||
*/
|
*/
|
||||||
const DEFAULT_RESIZE_OPTIONS: ResizeOptions = {
|
const DEFAULT_RESIZE_OPTIONS: ResizeOptions = {
|
||||||
maxWidth: 1900, // Slightly less than backend maxLongSide=2000
|
maxWidth: 1900, // Slightly less than backend maxLongSide=2000
|
||||||
maxHeight: 1900, // Slightly less than backend maxLongSide=2000
|
maxHeight: 1900, // Slightly less than backend maxLongSide=2000
|
||||||
quality: 0.92, // High quality while reducing file size
|
quality: 0.92, // High quality while reducing file size
|
||||||
format: 'jpeg', // Most compatible format
|
format: 'jpeg', // Most compatible format
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -40,11 +40,11 @@ export function supportsClientSideResize(): boolean {
|
||||||
if (typeof HTMLCanvasElement === 'undefined') return false;
|
if (typeof HTMLCanvasElement === 'undefined') return false;
|
||||||
if (typeof FileReader === 'undefined') return false;
|
if (typeof FileReader === 'undefined') return false;
|
||||||
if (typeof Image === 'undefined') return false;
|
if (typeof Image === 'undefined') return false;
|
||||||
|
|
||||||
// Test canvas creation
|
// Test canvas creation
|
||||||
const canvas = document.createElement('canvas');
|
const canvas = document.createElement('canvas');
|
||||||
const ctx = canvas.getContext('2d');
|
const ctx = canvas.getContext('2d');
|
||||||
|
|
||||||
return !!(ctx && ctx.drawImage && canvas.toBlob);
|
return !!(ctx && ctx.drawImage && canvas.toBlob);
|
||||||
} catch {
|
} catch {
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -60,18 +60,18 @@ function calculateDimensions(
|
||||||
maxWidth: number,
|
maxWidth: number,
|
||||||
maxHeight: number,
|
maxHeight: number,
|
||||||
): { width: number; height: number } {
|
): { width: number; height: number } {
|
||||||
let { width, height } = { width: originalWidth, height: originalHeight };
|
const { width, height } = { width: originalWidth, height: originalHeight };
|
||||||
|
|
||||||
// If image is smaller than max dimensions, don't upscale
|
// If image is smaller than max dimensions, don't upscale
|
||||||
if (width <= maxWidth && height <= maxHeight) {
|
if (width <= maxWidth && height <= maxHeight) {
|
||||||
return { width, height };
|
return { width, height };
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate scaling factor
|
// Calculate scaling factor
|
||||||
const widthRatio = maxWidth / width;
|
const widthRatio = maxWidth / width;
|
||||||
const heightRatio = maxHeight / height;
|
const heightRatio = maxHeight / height;
|
||||||
const scalingFactor = Math.min(widthRatio, heightRatio);
|
const scalingFactor = Math.min(widthRatio, heightRatio);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
width: Math.round(width * scalingFactor),
|
width: Math.round(width * scalingFactor),
|
||||||
height: Math.round(height * scalingFactor),
|
height: Math.round(height * scalingFactor),
|
||||||
|
|
@ -91,19 +91,19 @@ export function resizeImage(
|
||||||
reject(new Error('Browser does not support client-side image resizing'));
|
reject(new Error('Browser does not support client-side image resizing'));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only process image files
|
// Only process image files
|
||||||
if (!file.type.startsWith('image/')) {
|
if (!file.type.startsWith('image/')) {
|
||||||
reject(new Error('File is not an image'));
|
reject(new Error('File is not an image'));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const opts = { ...DEFAULT_RESIZE_OPTIONS, ...options };
|
const opts = { ...DEFAULT_RESIZE_OPTIONS, ...options };
|
||||||
const reader = new FileReader();
|
const reader = new FileReader();
|
||||||
|
|
||||||
reader.onload = (event) => {
|
reader.onload = (event) => {
|
||||||
const img = new Image();
|
const img = new Image();
|
||||||
|
|
||||||
img.onload = () => {
|
img.onload = () => {
|
||||||
try {
|
try {
|
||||||
const originalDimensions = { width: img.width, height: img.height };
|
const originalDimensions = { width: img.width, height: img.height };
|
||||||
|
|
@ -113,7 +113,7 @@ export function resizeImage(
|
||||||
opts.maxWidth!,
|
opts.maxWidth!,
|
||||||
opts.maxHeight!,
|
opts.maxHeight!,
|
||||||
);
|
);
|
||||||
|
|
||||||
// If no resizing needed, return original file
|
// If no resizing needed, return original file
|
||||||
if (
|
if (
|
||||||
newDimensions.width === originalDimensions.width &&
|
newDimensions.width === originalDimensions.width &&
|
||||||
|
|
@ -129,21 +129,21 @@ export function resizeImage(
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create canvas and resize
|
// Create canvas and resize
|
||||||
const canvas = document.createElement('canvas');
|
const canvas = document.createElement('canvas');
|
||||||
const ctx = canvas.getContext('2d')!;
|
const ctx = canvas.getContext('2d')!;
|
||||||
|
|
||||||
canvas.width = newDimensions.width;
|
canvas.width = newDimensions.width;
|
||||||
canvas.height = newDimensions.height;
|
canvas.height = newDimensions.height;
|
||||||
|
|
||||||
// Use high-quality image smoothing
|
// Use high-quality image smoothing
|
||||||
ctx.imageSmoothingEnabled = true;
|
ctx.imageSmoothingEnabled = true;
|
||||||
ctx.imageSmoothingQuality = 'high';
|
ctx.imageSmoothingQuality = 'high';
|
||||||
|
|
||||||
// Draw resized image
|
// Draw resized image
|
||||||
ctx.drawImage(img, 0, 0, newDimensions.width, newDimensions.height);
|
ctx.drawImage(img, 0, 0, newDimensions.width, newDimensions.height);
|
||||||
|
|
||||||
// Convert to blob
|
// Convert to blob
|
||||||
canvas.toBlob(
|
canvas.toBlob(
|
||||||
(blob) => {
|
(blob) => {
|
||||||
|
|
@ -151,17 +151,17 @@ export function resizeImage(
|
||||||
reject(new Error('Failed to create blob from canvas'));
|
reject(new Error('Failed to create blob from canvas'));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create new file with same name but potentially different extension
|
// Create new file with same name but potentially different extension
|
||||||
const extension = opts.format === 'jpeg' ? '.jpg' : `.${opts.format}`;
|
const extension = opts.format === 'jpeg' ? '.jpg' : `.${opts.format}`;
|
||||||
const baseName = file.name.replace(/\.[^/.]+$/, '');
|
const baseName = file.name.replace(/\.[^/.]+$/, '');
|
||||||
const newFileName = `${baseName}${extension}`;
|
const newFileName = `${baseName}${extension}`;
|
||||||
|
|
||||||
const resizedFile = new File([blob], newFileName, {
|
const resizedFile = new File([blob], newFileName, {
|
||||||
type: `image/${opts.format}`,
|
type: `image/${opts.format}`,
|
||||||
lastModified: Date.now(),
|
lastModified: Date.now(),
|
||||||
});
|
});
|
||||||
|
|
||||||
resolve({
|
resolve({
|
||||||
file: resizedFile,
|
file: resizedFile,
|
||||||
originalSize: file.size,
|
originalSize: file.size,
|
||||||
|
|
@ -178,11 +178,11 @@ export function resizeImage(
|
||||||
reject(error);
|
reject(error);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
img.onerror = () => reject(new Error('Failed to load image'));
|
img.onerror = () => reject(new Error('Failed to load image'));
|
||||||
img.src = event.target?.result as string;
|
img.src = event.target?.result as string;
|
||||||
};
|
};
|
||||||
|
|
||||||
reader.onerror = () => reject(new Error('Failed to read file'));
|
reader.onerror = () => reject(new Error('Failed to read file'));
|
||||||
reader.readAsDataURL(file);
|
reader.readAsDataURL(file);
|
||||||
});
|
});
|
||||||
|
|
@ -196,19 +196,20 @@ export function shouldResizeImage(
|
||||||
fileSizeLimit: number = 512 * 1024 * 1024, // 512MB default
|
fileSizeLimit: number = 512 * 1024 * 1024, // 512MB default
|
||||||
): boolean {
|
): boolean {
|
||||||
// Don't resize if file is already small
|
// Don't resize if file is already small
|
||||||
if (file.size < fileSizeLimit * 0.1) { // Less than 10% of limit
|
if (file.size < fileSizeLimit * 0.1) {
|
||||||
|
// Less than 10% of limit
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Don't process non-images
|
// Don't process non-images
|
||||||
if (!file.type.startsWith('image/')) {
|
if (!file.type.startsWith('image/')) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Don't process GIFs (they might be animated)
|
// Don't process GIFs (they might be animated)
|
||||||
if (file.type === 'image/gif') {
|
if (file.type === 'image/gif') {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue