Skip to content

Commit

Permalink
feat: BarcodeDetector Polyfill (#78)
Browse files Browse the repository at this point in the history
* feat: very first implement for qr-code reader

* feat: first implement of polyfill that not has strictly same api for qr-code reader

* fix: BarcodeDetector
  • Loading branch information
Misaka-0x447f authored and Jack-Works committed Aug 2, 2019
1 parent 963c329 commit 84b55c5
Show file tree
Hide file tree
Showing 9 changed files with 2,735 additions and 160 deletions.
2 changes: 2 additions & 0 deletions package.json
Expand Up @@ -24,6 +24,7 @@
"elliptic": "^6.4.1",
"gun": "0.2019.422",
"idb": "^4.0.3",
"jsqr": "^1.2.0",
"lodash-es": "^4.17.11",
"npm-run-all": "^4.1.5",
"pvtsutils": "^1.0.4",
Expand All @@ -38,6 +39,7 @@
"ts-loader": "^6.0.1",
"tslint": "^5.16.0",
"typescript": "^3.5.1",
"web-ext": "^3.1.1",
"web-ext-types": "^3.1.0",
"webcrypto-liner": "0.1.38",
"webextension-polyfill": "^0.4.0",
Expand Down
12 changes: 7 additions & 5 deletions src/components/Welcomes/1b1.tsx
Expand Up @@ -194,11 +194,13 @@ export default function Welcome({ back, restore }: Props) {
width="100%"
onResult={restore}
/>
<div className={qrError ? classes.videoError : ''}>
There is an error occur during the scanning.
<br />
You may try other ways to restore your account.
</div>
{qrError ? (
<div className={classes.videoError}>
There is an error occur during the scanning.
<br />
You may try other ways to restore your account.
</div>
) : null}
</>
)
}
Expand Down
10 changes: 0 additions & 10 deletions src/components/Welcomes/QRScanner/ShapeDetection.d.ts

This file was deleted.

40 changes: 40 additions & 0 deletions src/components/Welcomes/QRScanner/ShapeDetectionPolyfill.ts
@@ -0,0 +1,40 @@
import jsQR from 'jsqr'
import { isNull } from 'lodash-es'
/// <reference path="./ShapeDetectionSpec.d.ts" />

class BarcodeDetectorPolyfill implements BarcodeDetector {
constructor() {}
// noinspection JSMethodCanBeStatic
public async detect(mediaSource: CanvasImageSource) {
const canvas = document.createElement('canvas')
;[canvas.width, canvas.height] = [1920, 1080]
const ctx = canvas.getContext('2d')
if (isNull(ctx)) {
throw new Error('Canvas was not supported')
}
ctx.drawImage(mediaSource, 0, 0)
const d = ctx.getImageData(0, 0, canvas.width, canvas.height)
const res = jsQR(d.data, canvas.width, canvas.height)
if (isNull(res)) {
return []
}
const result = new DetectedBarcodePolyfill()
result.rawValue = res.data
return [result]
}
}
class DetectedBarcodePolyfill implements DetectedBarcode {
get boundingBox(): DOMRectReadOnly {
throw new Error('Not implemented')
}
cornerPoints: { x: number; y: number }[] = []
format = 'qr_code'
rawValue!: string
}

if (!('BarcodeDetector' in window)) {
Object.assign(window, {
BarcodeDetector: BarcodeDetectorPolyfill,
DetectedBarcode: DetectedBarcodePolyfill,
})
}
15 changes: 15 additions & 0 deletions src/components/Welcomes/QRScanner/ShapeDetectionSpec.d.ts
@@ -0,0 +1,15 @@
declare class BarcodeDetector {
constructor(options: { formats: string[] })
public async detect(mediaSource: CanvasImageSource): Promise<DetectedBarcode[]>
}
declare class DetectedBarcode {
boundingBox: DOMRectReadOnly
cornerPoints: { x: number; y: number }[]
format: string
rawValue: string
}

interface Window {
BarcodeDetector: BarcodeDetector
DetectedBarcode: DetectedBarcode
}
7 changes: 5 additions & 2 deletions src/components/Welcomes/QRScanner/index.tsx
@@ -1,13 +1,16 @@
/// <reference path="./ShapeDetection.d.ts" />
/// <reference path="./ShapeDetectionPolyfill.ts" />
import * as React from 'react'
import { useRef, useState } from 'react'
import { useRef} from 'react'
import { useQRCodeScan } from '../../../utils/hooks/useQRCodeScan'

interface Props {
scanning: boolean

onResult(data: string): void

onError(): void
}

export default function QRScanner(
props: Props & React.DetailedHTMLProps<React.VideoHTMLAttributes<HTMLVideoElement>, HTMLVideoElement>,
) {
Expand Down
5 changes: 4 additions & 1 deletion src/utils/hooks/useQRCodeScan.tsx
@@ -1,7 +1,10 @@
/// <reference path="../../components/Welcomes/QRScanner/ShapeDetectionSpec.d.ts" />
/** This file is published under MIT License */
import { useRef, useEffect } from 'react'
import { useRequestCamera, getFrontVideoDevices } from './useRequestCamera'
import { useInterval } from './useInterval'
import '../../components/Welcomes/QRScanner/ShapeDetectionPolyfill'

export function useQRCodeScan(
video: React.MutableRefObject<HTMLVideoElement | null>,
isScanning: boolean,
Expand Down Expand Up @@ -63,6 +66,6 @@ export function useQRCodeScan(
} finally {
lastScanning.current = false
}
}, 20)
}, 100)
}
}
5 changes: 4 additions & 1 deletion src/utils/hooks/useRequestCamera.ts
Expand Up @@ -27,7 +27,10 @@ async function requestPermission(): Promise<unknown> {
if (navigator.permissions.request) return navigator.permissions.request({ name: 'camera' })
const t = await navigator.mediaDevices.getUserMedia({
audio: false,
video: true,
video: {
width: { ideal: 1920 },
height: { ideal: 1080 }
},
})
t.getTracks()[0].stop()
}
Expand Down

0 comments on commit 84b55c5

Please sign in to comment.