// composables/useFileHash.ts import { ref } from 'vue' export const useFileHash = () => { const isCalculating = ref(false) const error = ref(null) const calculateHash = async (file: File): Promise => { try { if (!process.client) { throw new Error('This function can only run in browser') } if (!window.crypto || !window.crypto.subtle) { throw new Error('Crypto API is not supported in this browser') } isCalculating.value = true return await new Promise((resolve, reject) => { const reader = new FileReader() reader.readAsArrayBuffer(file) reader.onload = async (event) => { try { const buffer = event.target?.result as ArrayBuffer if (!buffer) { throw new Error('Failed to read file buffer') } const hashBuffer = await window.crypto.subtle.digest('SHA-256', buffer) const hashArray = Array.from(new Uint8Array(hashBuffer)) const hashHex = hashArray.map(b => b.toString(16).padStart(2, '0')).join('') resolve(hashHex) } catch (err) { reject(err) } } reader.onerror = () => { reject(new Error('Failed to read file')) } }) } catch (err) { error.value = err as Error throw err } finally { isCalculating.value = false } } return { calculateHash, isCalculating, error } }