All files / web/src/lib/vision/opencv useOpenCV.ts

0% Statements 0/114
0% Branches 0/1
0% Functions 0/1
0% Lines 0/114

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                                                                                                                                                                                                                                     
'use client'

import { useCallback, useRef } from 'react'

/**
 * Hook for loading OpenCV - mimics useDocumentDetection structure.
 */
export function useOpenCV() {
  const cvRef = useRef<unknown>(null)
  const loadPromiseRef = useRef<Promise<void> | null>(null)

  const isOpenCVReady = useCallback((): boolean => {
    if (typeof window === 'undefined') return false
    const cv = (window as unknown as { cv?: { imread?: unknown } }).cv
    return !!(cv && typeof cv.imread === 'function')
  }, [])

  const loadOpenCV = useCallback(async (): Promise<unknown> => {
    // Already loaded
    if (cvRef.current) return cvRef.current

    // Already loading - wait for it
    if (loadPromiseRef.current) {
      await loadPromiseRef.current
      return cvRef.current
    }

    // Start loading
    loadPromiseRef.current = (async () => {
      try {
        if (typeof window !== 'undefined') {
          if (!isOpenCVReady()) {
            const existingScript = document.querySelector('script[src="/opencv.js"]')

            if (!existingScript) {
              await new Promise<void>((resolve, reject) => {
                const script = document.createElement('script')
                script.src = '/opencv.js'
                script.async = true

                script.onload = () => {
                  const checkReady = () => {
                    if (isOpenCVReady()) {
                      resolve()
                    } else {
                      const cv = (
                        window as unknown as {
                          cv?: { onRuntimeInitialized?: () => void }
                        }
                      ).cv
                      if (cv) {
                        const previousCallback = cv.onRuntimeInitialized
                        cv.onRuntimeInitialized = () => {
                          previousCallback?.()
                          resolve()
                        }
                      } else {
                        reject(new Error('OpenCV.js loaded but cv not found'))
                      }
                    }
                  }
                  checkReady()
                }

                script.onerror = () => reject(new Error('Failed to load OpenCV.js'))
                document.head.appendChild(script)
              })
            } else {
              await new Promise<void>((resolve, reject) => {
                const maxWait = 30000
                const startTime = Date.now()

                const checkReady = () => {
                  if (isOpenCVReady()) {
                    resolve()
                  } else if (Date.now() - startTime > maxWait) {
                    reject(new Error('OpenCV.js loading timed out'))
                  } else {
                    const cv = (
                      window as unknown as {
                        cv?: { onRuntimeInitialized?: () => void }
                      }
                    ).cv
                    if (cv) {
                      const previousCallback = cv.onRuntimeInitialized
                      cv.onRuntimeInitialized = () => {
                        previousCallback?.()
                        resolve()
                      }
                    } else {
                      setTimeout(checkReady, 100)
                    }
                  }
                }
                checkReady()
              })
            }
          }
        }

        // Store OpenCV reference
        cvRef.current = (window as unknown as { cv: unknown }).cv
      } catch (err) {
        console.error('Failed to load OpenCV:', err)
        throw err
      }
    })()

    await loadPromiseRef.current
    return cvRef.current
  }, [isOpenCVReady])

  return { loadOpenCV, isOpenCVReady }
}