28
28
import type { DetectedBarcode , BarcodeFormat } from ' @sec-ant/barcode-detector'
29
29
import { nextTick , onUnmounted , computed , onMounted , ref , toRefs , watch , type PropType } from ' vue'
30
30
31
- import { adaptOldFormat , keepScanning , setScanningFormats } from ' ../misc/scanner'
31
+ import { keepScanning , setScanningFormats } from ' ../misc/scanner'
32
32
import * as cameraController from ' ../misc/camera'
33
33
import type { Point } from ' ../types/types'
34
+ import { assert } from ' ../misc/util'
34
35
35
36
const props = defineProps ({
36
37
constraints: {
37
- type: Object ,
38
+ type: Object as PropType < MediaTrackConstraints > ,
38
39
default() {
39
40
return { facingMode: ' environment' }
40
41
}
@@ -72,7 +73,6 @@ const isMounted = ref(false)
72
73
73
74
onMounted (() => {
74
75
isMounted .value = true
75
- setScanningFormats (props .formats )
76
76
})
77
77
78
78
onUnmounted (() => {
@@ -97,9 +97,18 @@ const cameraSettings = computed(() => {
97
97
})
98
98
99
99
watch (cameraSettings , async cameraSettings => {
100
+ const videoEl = videoRef .value
101
+ assert (videoEl !== undefined , ' cameraSettings watcher should never be triggered when component is not mounted. Thus video element should always be defined.' )
102
+
103
+ const canvas = pauseFrameRef .value
104
+ assert (canvas !== undefined , ' cameraSettings watcher should never be triggered when component is not mounted. Thus canvas should always be defined.' )
105
+
106
+ const ctx = canvas .getContext (' 2d' )
107
+ assert (ctx !== null , ' if cavnas is defined, canvas 2d context should also be non-null' )
108
+
100
109
if (cameraSettings .shouldStream ) { // start camera
101
110
try {
102
- const capabilities = await cameraController .start (videoRef . value , cameraSettings )
111
+ const capabilities = await cameraController .start (videoEl , cameraSettings )
103
112
104
113
// if the component is destroyed before `camera.start` resolves the
105
114
// `onBeforeUnmount` hook has no chance to clear the remaining camera
@@ -116,14 +125,10 @@ watch(cameraSettings, async cameraSettings => {
116
125
}
117
126
} else { // stop camera
118
127
// paint pause frame
119
- const canvas = pauseFrameRef .value
120
- const ctx = canvas .getContext (' 2d' )
121
- const video = videoRef .value
122
-
123
- canvas .width = video .videoWidth
124
- canvas .height = video .videoHeight
128
+ canvas .width = videoEl .videoWidth
129
+ canvas .height = videoEl .videoHeight
125
130
126
- ctx ? .drawImage (video , 0 , 0 , video .videoWidth , video .videoHeight )
131
+ ctx .drawImage (videoEl , 0 , 0 , videoEl .videoWidth , videoEl .videoHeight )
127
132
128
133
cameraController .stop ()
129
134
cameraActive .value = false
@@ -146,7 +151,10 @@ const shouldScan = computed(() => cameraSettings.value.shouldStream && cameraAct
146
151
147
152
watch (shouldScan , shouldScan => {
148
153
if (shouldScan ) {
154
+ assert (pauseFrameRef .value !== undefined , ' shouldScan watcher should only be triggered when component is mounted. Thus pause frame canvas is defined' )
149
155
clearCanvas (pauseFrameRef .value )
156
+
157
+ assert (trackingLayerRef .value !== undefined , ' shouldScan watcher should only be triggered when component is mounted. Thus tracking canvas is defined' )
150
158
clearCanvas (trackingLayerRef .value )
151
159
152
160
// Minimum delay in milliseconds between frames to be scanned. Don't scan
@@ -159,8 +167,9 @@ watch(shouldScan, shouldScan => {
159
167
}
160
168
}
161
169
170
+ assert (videoRef .value !== undefined , ' shouldScan watcher should only be triggered when component is mounted. Thus video element is defined' )
162
171
keepScanning (videoRef .value , {
163
- detectHandler : detectedCodes => emit (' detect' , detectedCodes ),
172
+ detectHandler : ( detectedCodes : DetectedBarcode []) => emit (' detect' , detectedCodes ),
164
173
formats: props .formats ,
165
174
locateHandler: onLocate ,
166
175
minDelay: scanInterval ()
@@ -171,23 +180,16 @@ watch(shouldScan, shouldScan => {
171
180
// methods
172
181
const clearCanvas = (canvas : HTMLCanvasElement ) => {
173
182
const ctx = canvas .getContext (' 2d' )
174
-
175
- console .assert (
176
- ctx !== undefined ,
177
- ' tried to clear canvas with undefined 2D context'
178
- )
179
-
183
+ assert (ctx !== null , ' canvas 2d context should always be non-null' )
180
184
ctx .clearRect (0 , 0 , canvas .width , canvas .height )
181
185
}
182
186
183
187
const onLocate = (detectedCodes : DetectedBarcode []) => {
184
188
const canvas = trackingLayerRef .value
185
- const video = videoRef . value
189
+ assert ( canvas !== undefined , ' onLocate handler should only be called when component is mounted. Thus tracking canvas is always defined. ' )
186
190
187
- console .assert (
188
- canvas !== undefined && video !== undefined ,
189
- ' onLocate handler called although component is not mounted'
190
- )
191
+ const video = videoRef .value
192
+ assert (video !== undefined , ' onLocate handler should only be called when component is mounted. Thus video element is always defined.' )
191
193
192
194
if (detectedCodes .length === 0 || props .track === undefined ) {
193
195
clearCanvas (canvas )
0 commit comments