Skip to content

Commit

Permalink
feat(QrcodeStream): throw timeout error when camera won't load
Browse files Browse the repository at this point in the history
On iOS devices in PWA mode, QrcodeStream works initially, but after
killing and restarting the PWA, all video elements fail to display
camera streams. Looks like this is related to this WebKit issue:

  https://bugs.webkit.org/show_bug.cgi?id=252465

No workarounds at the time of writing. But as suggested in the
thread we can put a timeout on the video elements to start loading.
That way we can at least detect when the error occurs and throw an
error event.

Also this commit:

 1. Makes the demo page PWA installable to reproduce this problem.
 2. Renames the "DecodeAll" demo to "HandleErrors". The demo already
    is focused on error handling because it renders the error message
    instead of just printing to the console, which is particularly
    useful on mobile devices. Renaming the demo emphasizes that and
    hints user to use this demo for debugging.

See #298
  • Loading branch information
gruhn committed Jul 18, 2023
1 parent 9fd8e7b commit a8d5da0
Show file tree
Hide file tree
Showing 18 changed files with 2,568 additions and 127 deletions.
2 changes: 1 addition & 1 deletion .github/ISSUE_TEMPLATE/bug_report.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ assignees: ''
---

**Describe the bug**
A clear and concise description of what the bug is. Can you reproduce this issue with [one of the demos](https://vue-qrcode-reader.netlify.app/demos/DecodeAll.html)?
A clear and concise description of what the bug is. Can you reproduce this issue with [one of the demos](https://vue-qrcode-reader.netlify.app/demos/HandleErrors.html)?

**To Reproduce**
Please provide a link to a minimal reproduction of the bug. For example on jsFiddle, CodePen, etc. Please don't attach a ZIP file with your entire code base. I know this is additional effort but if it takes too much time to reproduce your issue you'll likely won't get help at all.
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ out
# Nuxt.js build / generate output
.nuxt
dist
dev-dist

# Gatsby files
.cache/
Expand Down
4 changes: 2 additions & 2 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@ Clone the repository and run
npm install
```

We use a locally served version of the [demo page](https://vue-qrcode-reader.netlify.app/demos/DecodeAll.html) during development.
We use a locally served version of the [demo page](https://vue-qrcode-reader.netlify.app/) during development.
To get that started run

```
npm run dev
npm run docs:dev
```

### Commit Messages
Expand Down
10 changes: 6 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@

<br>
<br>
<a href="https://vue-qrcode-reader.netlify.app/demos/DecodeAll.html">live demos</a> |
<a href="https://vue-qrcode-reader.netlify.app/demos/CustomTracking.html">live demos</a> |
<a href="https://vue-qrcode-reader.netlify.app/api/QrcodeStream.html">api reference</a>
</p>

Expand Down Expand Up @@ -147,9 +147,11 @@ Use kebab-case to reference them in your templates:
#### I don't see the camera when using `QrcodeStream`.
- Check if it works on the demo page. Especially the [Decode All](https://vue-qrcode-reader.netlify.app/demos/DecodeAll.html) demo, since it renders error messages. If you see errors, consult the docs to understand their meaning.
- The demo works but it doesn't work in my project: Listen for the `init` event to investigate errors.
- The demo doesn't work: Carefully review the Browser Support section above. Maybe your device is just not supported.
- Check if it works on the demo page. Especially the [Handle Errors](https://vue-qrcode-reader.netlify.app/demos/HandleErrors.html) demo,
since it renders error messages.
- The demo works but it doesn't work in my project: Listen for the `error` event to investigate errors.
- The demo doesn't work: Carefully review the Browser Support section above.
Maybe your device is just not supported.
#### I'm running a dev server on localhost. How to test on my mobile device without HTTPS?
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,23 +28,24 @@ const onDetect = detectedCodes => {
}
const onError = err => {
error.value = `[${err.name}]: `
if (err.name === 'NotAllowedError') {
error.value = 'ERROR: you need to grant camera access permission'
error.value += 'you need to grant camera access permission'
} else if (err.name === 'NotFoundError') {
error.value = 'ERROR: no camera on this device'
error.value += 'no camera on this device'
} else if (err.name === 'NotSupportedError') {
error.value = 'ERROR: secure context required (HTTPS, localhost)'
error.value += 'secure context required (HTTPS, localhost)'
} else if (err.name === 'NotReadableError') {
error.value = 'ERROR: is the camera already in use?'
error.value += 'is the camera already in use?'
} else if (err.name === 'OverconstrainedError') {
error.value = 'ERROR: installed cameras are not suitable'
error.value += 'installed cameras are not suitable'
} else if (err.name === 'StreamApiNotSupportedError') {
error.value = 'ERROR: Stream API is not supported in this browser'
error.value += 'Stream API is not supported in this browser'
} else if (err.name === 'InsecureContextError') {
error.value =
'ERROR: Camera access is only permitted in secure context. Use HTTPS or localhost rather than HTTP.'
error.value += 'Camera access is only permitted in secure context. Use HTTPS or localhost rather than HTTP.'
} else {
error.value = `ERROR: Camera error (${err.name})`
error.value += err.message
}
}
</script>
Expand Down
2 changes: 1 addition & 1 deletion docs/.vitepress/components/demos/SwitchCamera.vue
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ button {
top: 10px;
}
button img {
with: 50px;
width: 50px;
height: 50px;
}
.error {
Expand Down
2 changes: 1 addition & 1 deletion docs/.vitepress/components/demos/Torch.vue
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ button {
top: 10px;
}
button img {
with: 50px;
width: 50px;
height: 50px;
}
.error {
Expand Down
45 changes: 39 additions & 6 deletions docs/.vitepress/config.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { defineConfig } from 'vitepress'
import { withPwa } from '@vite-pwa/vitepress'

export default defineConfig({
// base: '/vue-qrcode-reader/',
export default withPwa(defineConfig({
description: 'A set of Vue.js components for detecting and decoding QR codes.',
lang: 'en-US',
lastUpdated: true,
Expand All @@ -27,8 +27,8 @@ export default defineConfig({
link: '/demos/Simple'
},
{
text: 'Decode Continuously',
link: '/demos/DecodeAll'
text: 'Handle Errors',
link: '/demos/HandleErrors'
},
{
text: 'Visual Tracking',
Expand Down Expand Up @@ -105,5 +105,38 @@ export default defineConfig({
'@': __dirname
}
}
}
})
},
pwa: {
mode: 'development',
base: '/',
scope: '/',
registerType: 'autoUpdate',
// injectRegister: 'inline',
includeAssets: ['favicon.svg'],
manifest: {
name: 'Vue Qrcode Reader',
short_name: 'Vue QR',
theme_color: '#10b981',
icons: [
{
src: 'pwa-192x192.png',
sizes: '192x192',
type: 'image/png',
},
{
src: 'pwa-512x512.png',
sizes: '512x512',
type: 'image/png',
}
],
},
workbox: {
globPatterns: ['**/*.{css,js,html,svg,png,ico,txt,woff2}'],
},
devOptions: {
enabled: true,
suppressWarnings: true,
navigateFallback: '/',
},
},
}))
8 changes: 4 additions & 4 deletions docs/demos/DecodeAll.md → docs/demos/HandleErrors.md
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
# Decode Continuously
# Handle Errors

Hold a QR code in the camera and see what happens. Note, you can't scan the same
QR code multiple time in a row.

<ClientOnly>
<DemoWrapper :component="DecodeAll" />
<DemoWrapper :component="HandleErrors" />
</ClientOnly>

<script setup lang="ts">
import DemoWrapper from '@/components/DemoWrapper.vue'
import DecodeAll from '@/components/demos/DecodeAll.vue'
import HandleErrors from '@/components/demos/HandleErrors.vue'
</script>

### Source

<<< @/.vitepress/components/demos/DecodeAll.vue
<<< @/.vitepress/components/demos/HandleErrors.vue
Binary file added docs/public/pwa-192x192.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/public/pwa-512x512.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
"devDependencies": {
"@tsconfig/node20": "1.0.1",
"@types/node": "20.3.1",
"@vite-pwa/vitepress": "^0.2.0",
"@vitejs/plugin-vue": "4.2.3",
"@vue/compiler-sfc": "3.3.4",
"@vue/eslint-config-prettier": "7.1.0",
Expand All @@ -60,7 +61,8 @@
"vite-plugin-dts": "2.3.0",
"vitepress": "1.0.0-beta.2",
"vue": "3.3.4",
"vue-tsc": "1.6.5"
"vue-tsc": "1.6.5",
"workbox-window": "^7.0.0"
},
"bugs": "https://github.com/gruhn/vue-qrcode-reader/issues",
"homepage": "https://vue-qrcode-reader.netlify.app",
Expand Down
Loading

0 comments on commit a8d5da0

Please sign in to comment.