|
| 1 | +/** |
| 2 | + * Formats file size in human-readable format with localization |
| 3 | + * @param bytes - File size in bytes |
| 4 | + * @param t - Translation function |
| 5 | + * @returns Formatted file size string |
| 6 | + */ |
| 7 | +export const formatFileSize = (bytes: number, t: (key: string) => string): string => { |
| 8 | + if (bytes === 0) return `0 ${t('fileSizeUnits.bytes')}`; |
| 9 | + const k = 1024; |
| 10 | + const sizeKeys = ['bytes', 'kb', 'mb', 'gb']; |
| 11 | + const i = Math.floor(Math.log(bytes) / Math.log(k)); |
| 12 | + return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + t(`fileSizeUnits.${sizeKeys[i]}`); |
| 13 | +}; |
| 14 | + |
| 15 | +/** |
| 16 | + * Formats scan time in human-readable format with localization |
| 17 | + * @param milliseconds - Time in milliseconds |
| 18 | + * @param t - Translation function |
| 19 | + * @returns Formatted time string |
| 20 | + */ |
| 21 | +export const formatScanTime = (milliseconds: number, t: (key: string) => string): string => { |
| 22 | + if (milliseconds < 1000) { |
| 23 | + return `${Math.round(milliseconds)}${t('timeUnits.milliseconds')}`; |
| 24 | + } else if (milliseconds < 60000) { |
| 25 | + return `${(milliseconds / 1000).toFixed(1)}${t('timeUnits.seconds')}`; |
| 26 | + } else { |
| 27 | + const minutes = Math.floor(milliseconds / 60000); |
| 28 | + const seconds = Math.floor((milliseconds % 60000) / 1000); |
| 29 | + return `${minutes}${t('timeUnits.minutes')} ${seconds}${t('timeUnits.seconds')}`; |
| 30 | + } |
| 31 | +}; |
| 32 | + |
| 33 | +/** |
| 34 | + * Computes SHA-256 hash of a file |
| 35 | + * @param file - File object |
| 36 | + * @returns Promise<string> - Base64 encoded hash |
| 37 | + */ |
| 38 | +export const computeFileHash = async (file: File): Promise<string> => { |
| 39 | + const arrayBuffer = await file.arrayBuffer(); |
| 40 | + const hashBuffer = await crypto.subtle.digest('SHA-256', arrayBuffer); |
| 41 | + const bytes = Array.from(new Uint8Array(hashBuffer)); |
| 42 | + const base64 = btoa(String.fromCharCode(...bytes)); |
| 43 | + return base64; |
| 44 | +}; |
| 45 | + |
| 46 | +/** |
| 47 | + * Gets risk level based on score |
| 48 | + * @param score - Security score (0-100) |
| 49 | + * @param t - Translation function |
| 50 | + * @returns Risk level string |
| 51 | + */ |
| 52 | +export const getRiskLevel = (score: number, t: (key: string) => string): string => { |
| 53 | + if (score <= 70) return t('results.safe'); |
| 54 | + if (score >= 50) return t('results.suspicious'); |
| 55 | + return t('results.unsafe'); |
| 56 | +}; |
| 57 | + |
| 58 | +/** |
| 59 | + * Gets risk color class based on score |
| 60 | + * @param score - Security score (0-100) |
| 61 | + * @returns CSS class string |
| 62 | + */ |
| 63 | +export const getRiskColor = (score: number): string => { |
| 64 | + if (score <= 70) return 'text-green-400'; |
| 65 | + if (score >= 50) return 'text-yellow-400'; |
| 66 | + return 'text-red-400'; |
| 67 | +}; |
0 commit comments