Skip to content

Commit

Permalink
feat: No camera access or video stream info in modal
Browse files Browse the repository at this point in the history
  • Loading branch information
aineo committed Jul 18, 2024
1 parent 839aef4 commit 54c09b8
Show file tree
Hide file tree
Showing 6 changed files with 93 additions and 29 deletions.
76 changes: 56 additions & 20 deletions src/components/QrcodeScannerDialog.vue
Original file line number Diff line number Diff line change
Expand Up @@ -46,21 +46,42 @@
</v-col>
</v-row>

<!-- No Camera -->
<!-- No Camera || No access || No stream -->
<v-row
v-if="cameraStatus === 'nocamera'"
v-if="
cameraStatus === 'nocamera' || cameraStatus === 'noaccess' || cameraStatus === 'nostream'
"
justify="center"
align="center"
class="text-center pa-8"
no-gutters
>
<v-col cols="12">
<h3 class="a-text-header">
{{ $t('scan.no_camera_found') }}
</h3>
<p class="a-text-regular mt-1 mb-0">
{{ $t('scan.connect_camera') }}
</p>
<template v-if="cameraStatus === 'nocamera'">
<h3 class="a-text-header">
{{ $t('scan.no_camera_found') }}
</h3>
<p class="a-text-regular mt-1 mb-0">
{{ $t('scan.connect_camera') }}
</p>
</template>
<template v-else-if="cameraStatus === 'noaccess'">
<h3 class="a-text-header">
{{ $t('scan.no_camera_access') }}
</h3>
<p class="a-text-regular mt-1 mb-0">
{{ $t('scan.grant_camera_permissions') }}
</p>
</template>
<template v-else-if="cameraStatus === 'nostream'">
<h3 class="a-text-header">
{{ $t('scan.no_camera_stream') }}
</h3>
<p
class="a-text-regular mt-1 mb-0"
v-html="$t('scan.no_stream_details', { noStreamDetails })"
/>
</template>
</v-col>
</v-row>

Expand Down Expand Up @@ -91,7 +112,7 @@ const classes = {
cameraSelect: `${className}__camera-select`
}
type CameraStatus = 'waiting' | 'active' | 'nocamera'
type CameraStatus = 'waiting' | 'active' | 'nocamera' | 'noaccess' | 'nostream'
export default defineComponent({
props: {
Expand All @@ -110,6 +131,7 @@ export default defineComponent({
const scanner = ref<Scanner | null>(null)
const cameras = ref<MediaDeviceInfo[]>([])
const currentCamera = ref<number | null>(null)
const noStreamDetails = ref<string | null>(null)
const scannerControls = ref<IScannerControls | null>(null)
const show = computed<boolean>({
Expand All @@ -131,10 +153,7 @@ export default defineComponent({
cameras.value = await scanner.value.getCameras()
} catch (error) {
cameraStatus.value = 'nocamera'
store.dispatch('snackbar/show', {
message: t('scan.something_wrong')
})
console.error(error)
onError(error as string)
}
}
Expand All @@ -149,6 +168,13 @@ export default defineComponent({
show.value = false
}
const onError = (error: string) => {
store.dispatch('snackbar/show', {
message: t('scan.something_wrong')
})
console.error(error)
}
watch(cameras, (cameras) => {
if (cameras.length > 0) {
currentCamera.value = cameras.length >= 2 ? 1 : 0
Expand All @@ -160,15 +186,24 @@ export default defineComponent({
})
watch(currentCamera, () => {
void scanner.value?.start(currentCamera.value, (result, _, controls) => {
if (result) {
onScan(result.getText()) // text is private field for zxing/browser
}
void scanner.value?.start(
currentCamera.value,
(result, _, controls) => {
if (result) onScan(result.getText()) // text is private field for zxing/browser
if (controls) {
scannerControls.value = controls
if (controls) scannerControls.value = controls
},
(error) => {
if (error.name === 'NotAllowedError') {
cameraStatus.value = 'noaccess'
} else {
cameraStatus.value = 'nostream'
noStreamDetails.value = error
}
onError(error)
}
})
)
})
onMounted(() => {
Expand All @@ -184,6 +219,7 @@ export default defineComponent({
cameraStatus,
classes,
currentCamera,
noStreamDetails,
props,
show,
videoElement
Expand Down
30 changes: 21 additions & 9 deletions src/lib/zxing/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ type DecodeContinuouslyCallback = (
error?: Exception,
controls?: IScannerControls
) => void

type ModalErrorCallback = (error: any) => void

export class Scanner {
cameraStream!: MediaStream
codeReader!: BrowserQRCodeReader
Expand All @@ -20,19 +23,28 @@ export class Scanner {
this.codeReader = new BrowserQRCodeReader()
}

async start(currentCamera: number | null, decodeCallback: DecodeContinuouslyCallback) {
async start(
currentCamera: number | null,
decodeCallback: DecodeContinuouslyCallback,
modalCallback: ModalErrorCallback,
) {
// Stop all tracks from media stream before camera changing
if (this.cameraStream) this.stopVideoTracks()

// Request new media stream and attach to video element as source object
const facingMode = currentCamera === 1 ? 'environment' : 'user'
this.cameraStream = await navigator.mediaDevices.getUserMedia({
video: { facingMode },
audio: false
})
this.videoElement.srcObject = this.cameraStream
try {
// Request new media stream and attach to video element as source object
const facingMode = currentCamera === 1 ? 'environment' : 'user'
this.cameraStream = await navigator.mediaDevices.getUserMedia({
video: { facingMode },
audio: false
})
this.videoElement.srcObject = this.cameraStream

return this.codeReader.decodeFromVideoElement(this.videoElement, decodeCallback)
this.codeReader.decodeFromVideoElement(this.videoElement, decodeCallback)
} catch (error) {
// If something went wrong, show the reason in modal window
modalCallback(error)
}
}

async getCameras() {
Expand Down
4 changes: 4 additions & 0 deletions src/locales/de.json
Original file line number Diff line number Diff line change
Expand Up @@ -169,14 +169,18 @@
"camera_button": "Camera",
"close_button": "Close",
"connect_camera": "Connect the camera and try again",
"grant_camera_permissions": "Erteilen Sie Kamera Berechtigungen in den Browsereinstellungen und versuchen Sie es erneut",
"hold_your_device": "Hold your device steady for 2-3 seconds towards the QR code you want to scan",
"login": {
"modal_header": "Scan QR code with a passphrase"
},
"new-chat": {
"modal_header": "Scan QR code with ADM wallet address"
},
"no_camera_access": "Kein zugriff auf die kamera",
"no_camera_found": "No camera found",
"no_camera_stream": "Kein Video Stream von Kamera",
"no_stream_details": "Einzelheiten:<br /><code><small>{ noStreamDetails }</small></code>",
"something_wrong": "Unexpected error. Check the adm console application",
"waiting_camera": "Waiting camera"
},
Expand Down
4 changes: 4 additions & 0 deletions src/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -249,14 +249,18 @@
"camera_button": "Camera",
"close_button": "Close",
"connect_camera": "Switch on camera and try again",
"grant_camera_permissions": "Grant camera permissions in browser settings and try again",
"hold_your_device": "Hold your device steady for 2-3 seconds to scan the QR code",
"login": {
"modal_header": "Scan the QR code containing a passphrase"
},
"new-chat": {
"modal_header": "Scan the QR code contain an ADAMANT address"
},
"no_camera_access": "No camera access",
"no_camera_found": "No camera found",
"no_camera_stream": "No camera video stream",
"no_stream_details": "Details:<br /><code><small>{ noStreamDetails }</small></code>",
"something_wrong": "Something went wrong",
"waiting_camera": "Waiting for camera…"
},
Expand Down
4 changes: 4 additions & 0 deletions src/locales/ru.json
Original file line number Diff line number Diff line change
Expand Up @@ -250,14 +250,18 @@
"camera_button": "Камера",
"close_button": "Закрыть",
"connect_camera": "Подключите камеру и попробуйте снова",
"grant_camera_permissions": "Предоставьте разрешения камере в настройках браузера и попробуйте снова",
"hold_your_device": "Наведите камеру на 2-3 секунды на QR-код",
"login": {
"modal_header": "Отсканируйте QR-код с парольной фразой"
},
"new-chat": {
"modal_header": "Отсканируйте QR-код с адресом АДАМАНТа"
},
"no_camera_access": "Нет доступа к камере",
"no_camera_found": "Камера не найдена",
"no_camera_stream": "Нет видеопотока с камеры",
"no_stream_details": "Подробности:<br /><code><small>{ noStreamDetails }</small></code>",
"something_wrong": "Что-то пошло не так",
"waiting_camera": "Включаю камеру…"
},
Expand Down
4 changes: 4 additions & 0 deletions src/locales/zh.json
Original file line number Diff line number Diff line change
Expand Up @@ -249,14 +249,18 @@
"camera_button": "相机",
"close_button": "关闭",
"connect_camera": "打开相机,再试一次",
"grant_camera_permissions": "在浏览器设置中授予相机权限并重试",
"hold_your_device": "保持设备稳定 2-3 秒以扫描二维码",
"login": {
"modal_header": "扫描包含密码短语的二维码"
},
"new-chat": {
"modal_header": "扫描包含ADAMANT地址的二维码"
},
"no_camera_access": "没有相机访问权限",
"no_camera_found": "未找到摄像头",
"no_camera_stream": "没有来自摄像头的视频流",
"no_stream_details": "详情:<br /><code><small>{ noStreamDetails }</small></code>",
"something_wrong": "出了问题",
"waiting_camera": "正在等待相机…"
},
Expand Down

0 comments on commit 54c09b8

Please sign in to comment.