Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 | /** * OpenCV.js Lazy Loader * * Handles lazy loading of OpenCV.js (~8MB) with caching and error handling. * Non-React module - can be used directly or wrapped in a hook. */ import type { CV, WindowWithOpenCV } from './types' /** Singleton state for OpenCV loading */ let cvInstance: CV | null = null let loadPromise: Promise<CV> | null = null let loadError: Error | null = null /** * Check if OpenCV is fully initialized and ready to use */ export function isOpenCVReady(): boolean { const win = window as unknown as WindowWithOpenCV return !!(win.cv && typeof win.cv.imread === 'function') } /** * Get the OpenCV instance if already loaded */ export function getOpenCV(): CV | null { return cvInstance } /** * Get any error that occurred during loading */ export function getOpenCVError(): Error | null { return loadError } /** * Check if OpenCV is currently loading */ export function isOpenCVLoading(): boolean { return loadPromise !== null && cvInstance === null && loadError === null } /** * Load OpenCV.js lazily. Returns a promise that resolves to the CV instance. * Subsequent calls return the same promise/instance. * * @param scriptUrl - URL to load OpenCV.js from (default: '/opencv.js') * @param timeout - Maximum time to wait for OpenCV to initialize (default: 30000ms) */ export async function loadOpenCV( scriptUrl: string = '/opencv.js', timeout: number = 30000 ): Promise<CV> { // Already loaded if (cvInstance) return cvInstance // Already loading if (loadPromise) return loadPromise // Start loading loadPromise = (async () => { if (typeof window === 'undefined') { throw new Error('OpenCV.js can only be loaded in a browser environment') } const win = window as unknown as WindowWithOpenCV // Check if already initialized if (isOpenCVReady()) { cvInstance = win.cv as CV return cvInstance } // Check if script is already in DOM const existingScript = document.querySelector(`script[src="${scriptUrl}"]`) if (!existingScript) { // Load the script await new Promise<void>((resolve, reject) => { const script = document.createElement('script') script.src = scriptUrl script.async = true const timeoutId = setTimeout(() => { reject(new Error(`OpenCV.js loading timed out after ${timeout}ms`)) }, timeout) script.onload = () => { clearTimeout(timeoutId) waitForInitialization(resolve, reject, timeout) } script.onerror = () => { clearTimeout(timeoutId) reject(new Error(`Failed to load OpenCV.js from ${scriptUrl}`)) } document.head.appendChild(script) }) } else { // Script exists, wait for initialization await new Promise<void>((resolve, reject) => { waitForInitialization(resolve, reject, timeout) }) } cvInstance = win.cv as CV return cvInstance })() try { return await loadPromise } catch (err) { loadError = err instanceof Error ? err : new Error('Failed to load OpenCV') loadPromise = null throw loadError } } /** * Wait for OpenCV runtime to initialize */ function waitForInitialization( resolve: () => void, reject: (err: Error) => void, timeout: number ): void { const startTime = Date.now() const checkReady = () => { if (isOpenCVReady()) { resolve() return } if (Date.now() - startTime > timeout) { reject(new Error(`OpenCV.js initialization timed out after ${timeout}ms`)) return } const win = window as unknown as WindowWithOpenCV if (win.cv) { // OpenCV object exists but not fully initialized - hook into callback const previousCallback = win.cv.onRuntimeInitialized win.cv.onRuntimeInitialized = () => { previousCallback?.() resolve() } } else { // Keep polling setTimeout(checkReady, 100) } } checkReady() } /** * Reset the loader state (for testing) */ export function resetOpenCVLoader(): void { cvInstance = null loadPromise = null loadError = null } |