From fa14ec8ef8b1c3ecbb5070a7d1857ee3f7e35708 Mon Sep 17 00:00:00 2001 From: Dynamsoft-Shen <62587615+Shen-wb@users.noreply.github.com> Date: Tue, 21 Apr 2026 13:50:54 +0800 Subject: [PATCH] 11.4.2000 * feat(templates): update templates & add debug tool link * fix: update canonical links in HTML files for accurate routing * UPDATE * fix: update script path for local SDK loading in HTML files * fix: correct spelling of launchBarcodeScanner function * fix: update license initialization and update read-an-image.html * UPDATE VERSION * docs: update README with sample list and descriptions; add comments to hello-world example * refactor: clean up comments in hello-world example for clarity * Update hello-world.html comment * fix: update script source paths and decode template for consistency * docs: update README files to correct SDK links and enhance clarity; add new READMEs for ES6 and RequireJS * docs: enhance README for clarity and structure; add sections on sample folders and API choices * Fix secure context note structure and expand RTU acronym - Move file:/// exception note to cover both camera access and license (was previously nested under camera bullet only) - Expand "RTU" to "Ready-To-Use (RTU)" on first mention * Improve README clarity and structure - Promote "Running the Samples Locally" to its own section - Separate framework (npm) vs standalone/scenario (double-click or Five Server) instructions - Mention index.html as the sample gallery entry point - Remove redundant "API reference" line in Documentation section - Fix VIN spacing and de-duplicate Official Demo description * feat: add sample for scanning Direct Part Mark (DPM) codes * UPDATE * Update package.json * add rtu sample * Update app.vue * feat: update documentation for Next.js and Nuxt.js * Update read-an-image.html * UPDATE * Delete frameworks/nuxt/scan-using-rtu-api/curl.txt * Delete frameworks/nuxt/scan-using-rtu-api/response.html * Delete frameworks/nuxt/scan-using-rtu-api/dev.err * Update .gitignore * Update scan-a-single-barcode.html * UPDATE * Update README and index.html to enhance sample descriptions and add new section for Hello World samples * Update user guide link in index.html * Add scanMode configuration for multi-unique scanning in various scenarios * Refactor license initialization to use promise for loading code specifications * UPDATE * REMOVE FRAMEWORKS RTU * Fix formatting inconsistencies in README files across various READMEs * UPDATE * UPDATE * Update index.html * UPDATE * UPDATE * Remove redundant hello-world example links from README.md * Update demo links and README files for consistency; rename index.html for Show Result Texts on Video scenario * Refine README and demo links for clarity; update paths in index.html and scenario README * UPDATE * UPDATE * UPDATE * UPDATE * Remove unused canonical links from HTML files for various frameworks * Update ImageCapture.vue * Update Chrome version requirement in README.md * UPDATE * UPDATE * Update app.vue * Update SDK loading instructions for local hosting in index.html files * Update package.json * PWA UPDATE * remove executeNow * Update service-worker.js * Add customize-the-ui * UPDATE * Fix typo in variable name 'reusltView' to 'resultView' across multiple HTML files * UPDATE * Comment out demo GitHub badge span in index.html * Update browser compatibility versions in README.md * Update package.json * Update README.md * Update model names in JSON configuration for 1D barcode scanning scenarios * Update read-an-image.html --------- Co-authored-by: Justin Co-authored-by: Justin-dynamsoft <117710848+Justin-dynamsoft@users.noreply.github.com> Co-authored-by: Tom Kent --- README.md | 40 +- frameworks/README.md | 4 +- .../.editorconfig | 0 .../.gitignore | 0 frameworks/angular/README.md | 427 ++++++++- .../angular.json | 0 .../package.json | 24 +- .../scan-using-foundational-api/README.md | 422 --------- .../angular/scan-using-rtu-api/.editorconfig | 17 - .../angular/scan-using-rtu-api/.gitignore | 42 - .../angular/scan-using-rtu-api/README.md | 33 - .../angular/scan-using-rtu-api/angular.json | 100 --- .../angular/scan-using-rtu-api/package.json | 37 - .../src/app/app.component.css | 23 - .../src/app/app.component.html | 7 - .../src/app/app.component.ts | 63 -- .../scan-using-rtu-api/src/app/app.config.ts | 8 - .../scan-using-rtu-api/src/app/app.routes.ts | 3 - .../angular/scan-using-rtu-api/src/index.html | 12 - .../angular/scan-using-rtu-api/src/main.ts | 6 - .../angular/scan-using-rtu-api/src/styles.css | 16 - .../scan-using-rtu-api/tsconfig.app.json | 15 - .../angular/scan-using-rtu-api/tsconfig.json | 27 - .../scan-using-rtu-api/tsconfig.spec.json | 15 - .../src/app/app.component.css | 0 .../src/app/app.component.html | 0 .../src/app/app.component.ts | 0 .../src/app/dynamsoft.config.ts | 4 +- .../image-capture/image-capture.component.css | 0 .../image-capture.component.html | 0 .../image-capture/image-capture.component.ts | 0 .../video-capture/video-capture.component.css | 0 .../video-capture.component.html | 0 .../video-capture/video-capture.component.ts | 2 +- .../src/assets/.gitkeep | 0 .../src/favicon.ico | Bin .../src/index.html | 1 - .../src/main.ts | 0 .../src/styles.css | 0 .../tsconfig.app.json | 0 .../tsconfig.json | 0 .../tsconfig.spec.json | 0 .../.gitignore | 0 frameworks/blazor/README.md | 377 +++++++- .../hello-world-blazor/BlazorApp/App.razor | 0 .../BlazorApp/BlazorApp.csproj | 0 .../BlazorApp/Layout/MainLayout.razor | 0 .../BlazorApp/Layout/MainLayout.razor.css | 0 .../BlazorApp/Layout/NavMenu.razor | 0 .../BlazorApp/Layout/NavMenu.razor.css | 0 .../BlazorApp/Pages/DecodeImage.razor | 0 .../BlazorApp/Pages/DecodeVideo.razor | 0 .../BlazorApp/Pages/Home.razor | 0 .../hello-world-blazor/BlazorApp/Program.cs | 0 .../BlazorApp/Properties/launchSettings.json | 0 .../BlazorApp/_Imports.razor | 0 .../BlazorApp/wwwroot/css/app.css | 0 .../wwwroot/css/bootstrap/bootstrap.min.css | 0 .../css/bootstrap/bootstrap.min.css.map | 0 .../BlazorApp/wwwroot/decodeImage.js | 0 .../BlazorApp/wwwroot/decodeVideo.js | 2 +- .../BlazorApp/wwwroot/favicon.png | Bin .../BlazorApp/wwwroot/icon-192.png | Bin .../BlazorApp/wwwroot/index.html | 4 +- .../scan-using-foundational-api/README.md | 372 -------- .../blazor/scan-using-rtu-api/.gitignore | 486 ----------- .../blazor/scan-using-rtu-api/App.razor | 12 - .../scan-using-rtu-api/BlazorApp.csproj | 18 - .../Layout/MainLayout.razor | 4 - .../scan-using-rtu-api/Pages/Home.razor | 25 - .../blazor/scan-using-rtu-api/Program.cs | 11 - .../Properties/launchSettings.json | 41 - .../blazor/scan-using-rtu-api/README.md | 17 - .../blazor/scan-using-rtu-api/_Imports.razor | 10 - .../scan-using-rtu-api/wwwroot/index.html | 73 -- frameworks/capacitor/README.md | 49 +- .../android/.gitignore | 0 .../android/app/.gitignore | 0 .../android/app/build.gradle | 0 .../android/app/capacitor.build.gradle | 0 .../android/app/proguard-rules.pro | 0 .../myapp/ExampleInstrumentedTest.java | 0 .../android/app/src/main/AndroidManifest.xml | 0 .../com/dynamsoft/dbrjs/MainActivity.java | 0 .../main/res/drawable-land-hdpi/splash.png | Bin .../main/res/drawable-land-mdpi/splash.png | Bin .../main/res/drawable-land-xhdpi/splash.png | Bin .../main/res/drawable-land-xxhdpi/splash.png | Bin .../main/res/drawable-land-xxxhdpi/splash.png | Bin .../main/res/drawable-port-hdpi/splash.png | Bin .../main/res/drawable-port-mdpi/splash.png | Bin .../main/res/drawable-port-xhdpi/splash.png | Bin .../main/res/drawable-port-xxhdpi/splash.png | Bin .../main/res/drawable-port-xxxhdpi/splash.png | Bin .../drawable-v24/ic_launcher_foreground.xml | 0 .../res/drawable/ic_launcher_background.xml | 0 .../app/src/main/res/drawable/splash.png | Bin .../app/src/main/res/layout/activity_main.xml | 0 .../res/mipmap-anydpi-v26/ic_launcher.xml | 0 .../mipmap-anydpi-v26/ic_launcher_round.xml | 0 .../src/main/res/mipmap-hdpi/ic_launcher.png | Bin .../mipmap-hdpi/ic_launcher_foreground.png | Bin .../res/mipmap-hdpi/ic_launcher_round.png | Bin .../src/main/res/mipmap-mdpi/ic_launcher.png | Bin .../mipmap-mdpi/ic_launcher_foreground.png | Bin .../res/mipmap-mdpi/ic_launcher_round.png | Bin .../src/main/res/mipmap-xhdpi/ic_launcher.png | Bin .../mipmap-xhdpi/ic_launcher_foreground.png | Bin .../res/mipmap-xhdpi/ic_launcher_round.png | Bin .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin .../mipmap-xxhdpi/ic_launcher_foreground.png | Bin .../res/mipmap-xxhdpi/ic_launcher_round.png | Bin .../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin .../mipmap-xxxhdpi/ic_launcher_foreground.png | Bin .../res/mipmap-xxxhdpi/ic_launcher_round.png | Bin .../res/values/ic_launcher_background.xml | 0 .../app/src/main/res/values/strings.xml | 0 .../app/src/main/res/values/styles.xml | 0 .../app/src/main/res/xml/file_paths.xml | 0 .../getcapacitor/myapp/ExampleUnitTest.java | 0 .../android/build.gradle | 0 .../android/capacitor.settings.gradle | 0 .../android/gradle.properties | 0 .../android/gradle/wrapper/gradle-wrapper.jar | Bin .../gradle/wrapper/gradle-wrapper.properties | 0 .../{scan-using-rtu-api => }/android/gradlew | 0 .../android/gradlew.bat | 0 .../android/settings.gradle | 0 .../android/variables.gradle | 0 .../capacitor.config.json | 0 frameworks/capacitor/index.ts | 30 + .../{scan-using-rtu-api => }/ios/.gitignore | 0 .../ios/App/App.xcodeproj/project.pbxproj | 0 .../xcshareddata/IDEWorkspaceChecks.plist | 0 .../ios/App/App/AppDelegate.swift | 0 .../AppIcon.appiconset/AppIcon-512@2x.png | Bin .../AppIcon.appiconset/Contents.json | 0 .../ios/App/App/Assets.xcassets/Contents.json | 0 .../Splash.imageset/Contents.json | 0 .../Splash.imageset/splash-2732x2732-1.png | Bin .../Splash.imageset/splash-2732x2732-2.png | Bin .../Splash.imageset/splash-2732x2732.png | Bin .../App/Base.lproj/LaunchScreen.storyboard | 0 .../ios/App/App/Base.lproj/Main.storyboard | 0 .../ios/App/App/Info.plist | 0 .../{scan-using-rtu-api => }/ios/App/Podfile | 0 .../{scan-using-rtu-api => }/package.json | 2 +- .../public/index.html | 0 .../rollup.config.mjs | 0 .../capacitor/scan-using-rtu-api/README.md | 43 - .../capacitor/scan-using-rtu-api/index.ts | 35 - .../{scan-using-rtu-api => }/tsconfig.json | 0 frameworks/electron/README.md | 246 +++++- .../action.js | 6 +- .../index.html | 0 .../{scan-using-foundational-api => }/main.js | 0 .../package.json | 6 +- .../scan-using-foundational-api/README.md | 241 ------ .../electron/scan-using-rtu-api/README.md | 31 - .../electron/scan-using-rtu-api/action.js | 34 - .../electron/scan-using-rtu-api/index.html | 61 -- .../electron/scan-using-rtu-api/main.js | 29 - .../electron/scan-using-rtu-api/package.json | 26 - .../electron/scan-using-rtu-api/style.css | 6 - .../style.css | 0 frameworks/es6/README.md | 71 +- .../es6.html | 10 +- frameworks/es6/scan-using-rtu-api/es6.html | 100 --- frameworks/native-ts/README.md | 23 - .../index.ts | 2 +- .../package.json | 2 +- .../index.html | 3 +- .../rollup.config.mjs | 2 +- .../rollup.config.mjs | 27 - .../native-ts/scan-using-rtu-api/README.md | 26 - .../native-ts/scan-using-rtu-api/index.ts | 44 - .../native-ts/scan-using-rtu-api/package.json | 20 - .../scan-using-rtu-api/public/index.html | 17 - .../scan-using-rtu-api/tsconfig.json | 21 - .../tsconfig.json | 1 + .../.eslintrc.json | 0 .../.gitignore | 0 frameworks/next/README.md | 438 +++++++++- .../app/favicon.ico | Bin .../app/globals.css | 0 .../app/layout.tsx | 0 .../app/page.css | 0 .../app/page.tsx | 0 .../components/ImageCapture/ImageCapture.css | 0 .../components/ImageCapture/ImageCapture.tsx | 0 .../components/VideoCapture/VideoCapture.css | 0 .../components/VideoCapture/VideoCapture.tsx | 2 +- .../src => next}/dynamsoft.config.ts | 4 +- .../next.config.mjs | 0 .../package.json | 6 +- .../public/next.svg | 0 .../public/vercel.svg | 0 .../scan-using-foundational-api/README.md | 434 ---------- .../tsconfig.json | 27 +- .../.gitignore | 0 frameworks/nuxt/README.md | 388 ++++++++- .../{scan-using-foundational-api => }/app.vue | 11 +- .../assets/logo.svg | 0 frameworks/nuxt/assets/main.css | 5 + .../components/ImageCapture.client.vue | 3 +- .../components/VideoCapture.client.vue | 5 +- .../dynamsoft.config.ts | 2 +- .../nuxt.config.ts | 2 +- .../package.json | 2 +- .../public/favicon.ico | Bin .../scan-using-foundational-api/README.md | 383 -------- .../assets/main.css | 7 - .../tsconfig.json | 0 frameworks/pwa/README.md | 312 ++++++- .../dynamsoft-192x192.png | Bin .../dynamsoft-512x512.png | Bin .../helloworld-pwa.html | 11 +- .../helloworld-pwa.json | 0 .../pwa/scan-using-foundational-api/README.md | 307 ------- .../service-worker.js | 92 -- frameworks/pwa/scan-using-rtu-api/README.md | 17 - .../scan-using-rtu-api/dynamsoft-192x192.png | Bin 6638 -> 0 bytes .../scan-using-rtu-api/dynamsoft-512x512.png | Bin 9938 -> 0 bytes .../scan-using-rtu-api/helloworld-pwa.html | 109 --- .../scan-using-rtu-api/helloworld-pwa.json | 22 - .../pwa/scan-using-rtu-api/service-worker.js | 92 -- frameworks/pwa/service-worker.js | 95 ++ .../.gitignore | 0 frameworks/react/README.md | 401 ++++++++- .../package.json | 2 +- .../public/favicon.ico | Bin .../public/index.html | 1 - .../public/logo192.png | Bin .../public/logo512.png | Bin .../public/manifest.json | 0 .../scan-using-foundational-api/README.md | 396 --------- .../react/scan-using-rtu-api/.gitignore | 26 - frameworks/react/scan-using-rtu-api/README.md | 33 - .../react/scan-using-rtu-api/index.html | 12 - .../react/scan-using-rtu-api/package.json | 29 - .../react/scan-using-rtu-api/src/App.tsx | 68 -- .../react/scan-using-rtu-api/src/main.tsx | 9 - .../scan-using-rtu-api/tsconfig.app.json | 27 - .../react/scan-using-rtu-api/tsconfig.json | 7 - .../scan-using-rtu-api/tsconfig.node.json | 25 - .../react/scan-using-rtu-api/vite.config.ts | 7 - .../src/App.css | 0 .../src/App.tsx | 0 .../src/assets/logo.svg | 0 .../components/ImageCapture/ImageCapture.css | 0 .../components/ImageCapture/ImageCapture.tsx | 0 .../components/VideoCapture/VideoCapture.css | 0 .../components/VideoCapture/VideoCapture.tsx | 2 +- .../src}/dynamsoft.config.ts | 2 +- .../src/index.css | 0 .../src/index.tsx | 0 .../src/react-app-env.d.ts | 0 .../tsconfig.json | 0 frameworks/requirejs/README.md | 75 +- .../requirejs.html | 9 +- .../scan-using-rtu-api/requirejs.html | 105 --- .../.gitignore | 0 frameworks/svelte/README.md | 356 +++++++- .../index.html | 0 .../logo.svg | 0 .../package.json | 4 +- .../scan-using-foundational-api/README.md | 351 -------- .../svelte/scan-using-rtu-api/.gitignore | 26 - .../svelte/scan-using-rtu-api/README.md | 33 - .../svelte/scan-using-rtu-api/index.html | 12 - .../svelte/scan-using-rtu-api/package.json | 24 - .../svelte/scan-using-rtu-api/src/App.svelte | 67 -- .../svelte/scan-using-rtu-api/src/main.ts | 7 - .../scan-using-rtu-api/src/vite-env.d.ts | 2 - .../scan-using-rtu-api/svelte.config.js | 7 - .../svelte/scan-using-rtu-api/tsconfig.json | 20 - .../scan-using-rtu-api/tsconfig.node.json | 10 - .../svelte/scan-using-rtu-api/vite.config.ts | 8 - .../src/App.svelte | 0 .../src/components/ImageCapture.svelte | 0 .../src/components/VideoCapture.svelte | 2 +- .../src/dynamsoft.config.ts | 2 +- .../src/main.ts | 0 .../src/vite-env.d.ts | 0 .../svelte.config.js | 0 .../tsconfig.json | 0 .../tsconfig.node.json | 0 .../vite.config.ts | 0 .../.gitignore | 0 frameworks/vue/README.md | 387 ++++++++- .../env.d.ts | 0 .../index.html | 1 - .../package.json | 4 +- .../public/favicon.ico | Bin .../vue/scan-using-foundational-api/README.md | 379 -------- frameworks/vue/scan-using-rtu-api/.gitignore | 26 - frameworks/vue/scan-using-rtu-api/README.md | 33 - frameworks/vue/scan-using-rtu-api/index.html | 12 - .../vue/scan-using-rtu-api/package.json | 22 - frameworks/vue/scan-using-rtu-api/src/App.vue | 61 -- frameworks/vue/scan-using-rtu-api/src/main.ts | 4 - .../vue/scan-using-rtu-api/src/vite-env.d.ts | 1 - .../vue/scan-using-rtu-api/tsconfig.app.json | 15 - .../vue/scan-using-rtu-api/tsconfig.json | 7 - .../vue/scan-using-rtu-api/tsconfig.node.json | 25 - .../vue/scan-using-rtu-api/vite.config.ts | 7 - .../src/App.vue | 1 + .../src/assets/logo.svg | 0 .../src/assets/main.css | 1 - .../src/components/ImageCapture.vue | 1 + .../src/components/VideoCapture.vue | 5 +- .../src/dynamsoft.config.ts | 2 +- .../src/main.ts | 0 .../tsconfig.config.json | 0 .../tsconfig.json | 0 .../vite.config.ts | 0 frameworks/webview/README.md | 23 - .../android/.gitignore | 0 .../android/README.md | 0 .../android/app/.gitignore | 0 .../android/app/build.gradle | 0 .../android/app/proguard-rules.pro | 0 .../android/app/src/main/AndroidManifest.xml | 0 .../src/main/assets/decodeBarcodeInVideo.html | 7 +- .../dynamsoft/dbrjswebview/MainActivity.kt | 0 .../drawable-v24/ic_launcher_foreground.xml | 0 .../res/drawable/ic_launcher_background.xml | 0 .../app/src/main/res/layout/activity_main.xml | 0 .../res/mipmap-anydpi-v26/ic_launcher.xml | 0 .../mipmap-anydpi-v26/ic_launcher_round.xml | 0 .../res/mipmap-anydpi-v33/ic_launcher.xml | 0 .../src/main/res/mipmap-hdpi/ic_launcher.webp | Bin .../res/mipmap-hdpi/ic_launcher_round.webp | Bin .../src/main/res/mipmap-mdpi/ic_launcher.webp | Bin .../res/mipmap-mdpi/ic_launcher_round.webp | Bin .../main/res/mipmap-xhdpi/ic_launcher.webp | Bin .../res/mipmap-xhdpi/ic_launcher_round.webp | Bin .../main/res/mipmap-xxhdpi/ic_launcher.webp | Bin .../res/mipmap-xxhdpi/ic_launcher_round.webp | Bin .../main/res/mipmap-xxxhdpi/ic_launcher.webp | Bin .../res/mipmap-xxxhdpi/ic_launcher_round.webp | Bin .../app/src/main/res/values-night/themes.xml | 0 .../app/src/main/res/values/colors.xml | 0 .../app/src/main/res/values/strings.xml | 0 .../app/src/main/res/values/themes.xml | 0 .../app/src/main/res/xml/backup_rules.xml | 0 .../main/res/xml/data_extraction_rules.xml | 0 .../android/build.gradle | 0 .../android/gradle.properties | 0 .../android/gradle/wrapper/gradle-wrapper.jar | Bin .../gradle/wrapper/gradle-wrapper.properties | 0 .../android/gradlew | 0 .../android/gradlew.bat | 0 .../android/settings.gradle | 0 .../ios/.gitignore | 0 .../ios/README.md | 0 .../dbrjswebview.xcodeproj/project.pbxproj | 0 .../contents.xcworkspacedata | 0 .../xcshareddata/IDEWorkspaceChecks.plist | 0 .../ios/dbrjswebview/AppDelegate.swift | 0 .../AccentColor.colorset/Contents.json | 0 .../AppIcon.appiconset/Contents.json | 0 .../Assets.xcassets/Contents.json | 0 .../Base.lproj/LaunchScreen.storyboard | 0 .../dbrjswebview/Base.lproj/Main.storyboard | 0 .../ios/dbrjswebview/Info.plist | 0 .../ios/dbrjswebview/SceneDelegate.swift | 0 .../ios/dbrjswebview/ViewController.swift | 0 .../dbrjswebview/html/decodeFileInVideo.html | 7 +- .../scan-using-rtu-api/android/.gitignore | 15 - .../scan-using-rtu-api/android/README.md | 128 --- .../scan-using-rtu-api/android/app/.gitignore | 1 - .../android/app/build.gradle | 45 - .../android/app/proguard-rules.pro | 21 - .../android/app/src/main/AndroidManifest.xml | 28 - .../src/main/assets/decodeBarcodeInVideo.html | 85 -- .../dynamsoft/dbrjswebview/MainActivity.kt | 105 --- .../drawable-v24/ic_launcher_foreground.xml | 30 - .../res/drawable/ic_launcher_background.xml | 170 ---- .../app/src/main/res/layout/activity_main.xml | 15 - .../res/mipmap-anydpi-v26/ic_launcher.xml | 5 - .../mipmap-anydpi-v26/ic_launcher_round.xml | 5 - .../res/mipmap-anydpi-v33/ic_launcher.xml | 6 - .../src/main/res/mipmap-hdpi/ic_launcher.webp | Bin 1404 -> 0 bytes .../res/mipmap-hdpi/ic_launcher_round.webp | Bin 2898 -> 0 bytes .../src/main/res/mipmap-mdpi/ic_launcher.webp | Bin 982 -> 0 bytes .../res/mipmap-mdpi/ic_launcher_round.webp | Bin 1772 -> 0 bytes .../main/res/mipmap-xhdpi/ic_launcher.webp | Bin 1900 -> 0 bytes .../res/mipmap-xhdpi/ic_launcher_round.webp | Bin 3918 -> 0 bytes .../main/res/mipmap-xxhdpi/ic_launcher.webp | Bin 2884 -> 0 bytes .../res/mipmap-xxhdpi/ic_launcher_round.webp | Bin 5914 -> 0 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.webp | Bin 3844 -> 0 bytes .../res/mipmap-xxxhdpi/ic_launcher_round.webp | Bin 7778 -> 0 bytes .../app/src/main/res/values-night/themes.xml | 16 - .../app/src/main/res/values/colors.xml | 10 - .../app/src/main/res/values/strings.xml | 3 - .../app/src/main/res/values/themes.xml | 16 - .../app/src/main/res/xml/backup_rules.xml | 13 - .../main/res/xml/data_extraction_rules.xml | 19 - .../scan-using-rtu-api/android/build.gradle | 6 - .../android/gradle.properties | 23 - .../android/gradle/wrapper/gradle-wrapper.jar | Bin 59203 -> 0 bytes .../gradle/wrapper/gradle-wrapper.properties | 6 - .../scan-using-rtu-api/android/gradlew | 185 ---- .../scan-using-rtu-api/android/gradlew.bat | 89 -- .../android/settings.gradle | 16 - .../webview/scan-using-rtu-api/ios/.gitignore | 90 -- .../webview/scan-using-rtu-api/ios/README.md | 141 --- .../dbrjswebview.xcodeproj/project.pbxproj | 373 -------- .../contents.xcworkspacedata | 7 - .../xcshareddata/IDEWorkspaceChecks.plist | 8 - .../ios/dbrjswebview/AppDelegate.swift | 36 - .../AccentColor.colorset/Contents.json | 11 - .../AppIcon.appiconset/Contents.json | 13 - .../Assets.xcassets/Contents.json | 6 - .../Base.lproj/LaunchScreen.storyboard | 25 - .../dbrjswebview/Base.lproj/Main.storyboard | 33 - .../ios/dbrjswebview/Info.plist | 27 - .../ios/dbrjswebview/SceneDelegate.swift | 52 -- .../ios/dbrjswebview/ViewController.swift | 116 --- .../dbrjswebview/html/decodeFileInVideo.html | 85 -- hello-world.html | 89 +- index.html | 12 +- read-an-image.html | 27 +- scan-a-single-barcode.html | 91 +- scenarios/batch-inventory/README.md | 2 +- scenarios/batch-inventory/index.css | 101 +++ scenarios/batch-inventory/index.html | 129 ++- scenarios/cart-builder/README.md | 5 +- scenarios/cart-builder/index.css | 85 ++ .../{cart-builder.html => index.html} | 183 ++-- scenarios/debug/public/index.html | 6 +- .../locate-an-item-with-barcode/README.md | 2 +- .../locate-an-item-with-barcode/index.css | 227 +++++ .../locate-an-item-with-barcode/index.html | 818 ++++++------------ scenarios/pick-one-to-fill/README.md | 4 +- scenarios/pick-one-to-fill/index.html | 81 +- scenarios/read-a-drivers-license/README.md | 2 +- scenarios/read-a-drivers-license/index.html | 196 +++-- scenarios/read-a-drivers-license/style.css | 5 + scenarios/read-and-parse-GS1-AI/README.md | 14 +- .../index.css | 0 .../index.html | 10 +- .../read_and_parse_gs1.json | 0 .../scan-using-rtu-api/convert-GS1AI-title.js | 386 --------- .../scan-using-rtu-api/index.html | 287 ------ .../scan-using-rtu-api/info.svg | 11 - ...logo-dynamsoft-blackBg-190x47-DZ66W3xz.png | Bin 5449 -> 0 bytes .../scan-using-rtu-api/rtu_gs1.json | 163 ---- .../scan-using-rtu-api/style.css | 200 ----- scenarios/read-vin/README.md | 2 +- scenarios/read-vin/index.html | 166 ++-- scenarios/read-vin/style.css | 7 +- scenarios/scan-1D-Industrial/README.md | 2 +- .../ReadOneDIndustrial.json | 2 +- scenarios/scan-1D-Industrial/index.html | 112 ++- scenarios/scan-1D-Retail/README.md | 2 +- scenarios/scan-1D-Retail/ReadOneDRetail.json | 2 +- scenarios/scan-1D-Retail/index.html | 112 ++- scenarios/scan-and-search/README.md | 4 +- scenarios/scan-and-search/index.css | 194 +++++ scenarios/scan-and-search/index.html | 91 ++ .../scan-and-search/scan-and-search.html | 268 ------ scenarios/scan-common-1D-and-2D/README.md | 2 +- scenarios/scan-common-1D-and-2D/index.html | 112 ++- scenarios/scan-common-2D-codes/README.md | 2 +- scenarios/scan-common-2D-codes/index.html | 112 ++- scenarios/scan-datamatrix-code/README.md | 2 +- scenarios/scan-datamatrix-code/index.html | 112 ++- scenarios/scan-dpm-codes/index.html | 112 ++- scenarios/scan-from-distance/README.md | 2 +- scenarios/scan-from-distance/index.html | 113 ++- scenarios/scan-qr-code/README.md | 2 +- scenarios/scan-qr-code/index.html | 112 ++- .../show-result-texts-on-the-video/README.md | 4 +- ...ult-texts-on-the-video.html => index.html} | 53 +- 476 files changed, 5533 insertions(+), 11379 deletions(-) rename frameworks/angular/{scan-using-foundational-api => }/.editorconfig (100%) rename frameworks/angular/{scan-using-foundational-api => }/.gitignore (100%) rename frameworks/angular/{scan-using-foundational-api => }/angular.json (100%) rename frameworks/angular/{scan-using-foundational-api => }/package.json (56%) delete mode 100644 frameworks/angular/scan-using-foundational-api/README.md delete mode 100644 frameworks/angular/scan-using-rtu-api/.editorconfig delete mode 100644 frameworks/angular/scan-using-rtu-api/.gitignore delete mode 100644 frameworks/angular/scan-using-rtu-api/README.md delete mode 100644 frameworks/angular/scan-using-rtu-api/angular.json delete mode 100644 frameworks/angular/scan-using-rtu-api/package.json delete mode 100644 frameworks/angular/scan-using-rtu-api/src/app/app.component.css delete mode 100644 frameworks/angular/scan-using-rtu-api/src/app/app.component.html delete mode 100644 frameworks/angular/scan-using-rtu-api/src/app/app.component.ts delete mode 100644 frameworks/angular/scan-using-rtu-api/src/app/app.config.ts delete mode 100644 frameworks/angular/scan-using-rtu-api/src/app/app.routes.ts delete mode 100644 frameworks/angular/scan-using-rtu-api/src/index.html delete mode 100644 frameworks/angular/scan-using-rtu-api/src/main.ts delete mode 100644 frameworks/angular/scan-using-rtu-api/src/styles.css delete mode 100644 frameworks/angular/scan-using-rtu-api/tsconfig.app.json delete mode 100644 frameworks/angular/scan-using-rtu-api/tsconfig.json delete mode 100644 frameworks/angular/scan-using-rtu-api/tsconfig.spec.json rename frameworks/angular/{scan-using-foundational-api => }/src/app/app.component.css (100%) rename frameworks/angular/{scan-using-foundational-api => }/src/app/app.component.html (100%) rename frameworks/angular/{scan-using-foundational-api => }/src/app/app.component.ts (100%) rename frameworks/angular/{scan-using-foundational-api => }/src/app/dynamsoft.config.ts (92%) rename frameworks/angular/{scan-using-foundational-api => }/src/app/image-capture/image-capture.component.css (100%) rename frameworks/angular/{scan-using-foundational-api => }/src/app/image-capture/image-capture.component.html (100%) rename frameworks/angular/{scan-using-foundational-api => }/src/app/image-capture/image-capture.component.ts (100%) rename frameworks/angular/{scan-using-foundational-api => }/src/app/video-capture/video-capture.component.css (100%) rename frameworks/angular/{scan-using-foundational-api => }/src/app/video-capture/video-capture.component.html (100%) rename frameworks/angular/{scan-using-foundational-api => }/src/app/video-capture/video-capture.component.ts (98%) rename frameworks/angular/{scan-using-foundational-api => }/src/assets/.gitkeep (100%) rename frameworks/angular/{scan-using-foundational-api => }/src/favicon.ico (100%) rename frameworks/angular/{scan-using-foundational-api => }/src/index.html (82%) rename frameworks/angular/{scan-using-foundational-api => }/src/main.ts (100%) rename frameworks/angular/{scan-using-foundational-api => }/src/styles.css (100%) rename frameworks/angular/{scan-using-foundational-api => }/tsconfig.app.json (100%) rename frameworks/angular/{scan-using-foundational-api => }/tsconfig.json (100%) rename frameworks/angular/{scan-using-foundational-api => }/tsconfig.spec.json (100%) rename frameworks/blazor/{scan-using-foundational-api => }/.gitignore (100%) rename frameworks/blazor/{scan-using-foundational-api => }/hello-world-blazor/BlazorApp/App.razor (100%) rename frameworks/blazor/{scan-using-foundational-api => }/hello-world-blazor/BlazorApp/BlazorApp.csproj (100%) rename frameworks/blazor/{scan-using-foundational-api => }/hello-world-blazor/BlazorApp/Layout/MainLayout.razor (100%) rename frameworks/blazor/{scan-using-foundational-api => }/hello-world-blazor/BlazorApp/Layout/MainLayout.razor.css (100%) rename frameworks/blazor/{scan-using-foundational-api => }/hello-world-blazor/BlazorApp/Layout/NavMenu.razor (100%) rename frameworks/blazor/{scan-using-foundational-api => }/hello-world-blazor/BlazorApp/Layout/NavMenu.razor.css (100%) rename frameworks/blazor/{scan-using-foundational-api => }/hello-world-blazor/BlazorApp/Pages/DecodeImage.razor (100%) rename frameworks/blazor/{scan-using-foundational-api => }/hello-world-blazor/BlazorApp/Pages/DecodeVideo.razor (100%) rename frameworks/blazor/{scan-using-foundational-api => }/hello-world-blazor/BlazorApp/Pages/Home.razor (100%) rename frameworks/blazor/{scan-using-foundational-api => }/hello-world-blazor/BlazorApp/Program.cs (100%) rename frameworks/blazor/{scan-using-foundational-api => }/hello-world-blazor/BlazorApp/Properties/launchSettings.json (100%) rename frameworks/blazor/{scan-using-foundational-api => }/hello-world-blazor/BlazorApp/_Imports.razor (100%) rename frameworks/blazor/{scan-using-foundational-api => }/hello-world-blazor/BlazorApp/wwwroot/css/app.css (100%) rename frameworks/blazor/{scan-using-foundational-api => }/hello-world-blazor/BlazorApp/wwwroot/css/bootstrap/bootstrap.min.css (100%) rename frameworks/blazor/{scan-using-foundational-api => }/hello-world-blazor/BlazorApp/wwwroot/css/bootstrap/bootstrap.min.css.map (100%) rename frameworks/blazor/{scan-using-foundational-api => }/hello-world-blazor/BlazorApp/wwwroot/decodeImage.js (100%) rename frameworks/blazor/{scan-using-foundational-api => }/hello-world-blazor/BlazorApp/wwwroot/decodeVideo.js (98%) rename frameworks/blazor/{scan-using-foundational-api => }/hello-world-blazor/BlazorApp/wwwroot/favicon.png (100%) rename frameworks/blazor/{scan-using-foundational-api => }/hello-world-blazor/BlazorApp/wwwroot/icon-192.png (100%) rename frameworks/blazor/{scan-using-foundational-api => }/hello-world-blazor/BlazorApp/wwwroot/index.html (95%) delete mode 100644 frameworks/blazor/scan-using-foundational-api/README.md delete mode 100644 frameworks/blazor/scan-using-rtu-api/.gitignore delete mode 100644 frameworks/blazor/scan-using-rtu-api/App.razor delete mode 100644 frameworks/blazor/scan-using-rtu-api/BlazorApp.csproj delete mode 100644 frameworks/blazor/scan-using-rtu-api/Layout/MainLayout.razor delete mode 100644 frameworks/blazor/scan-using-rtu-api/Pages/Home.razor delete mode 100644 frameworks/blazor/scan-using-rtu-api/Program.cs delete mode 100644 frameworks/blazor/scan-using-rtu-api/Properties/launchSettings.json delete mode 100644 frameworks/blazor/scan-using-rtu-api/README.md delete mode 100644 frameworks/blazor/scan-using-rtu-api/_Imports.razor delete mode 100644 frameworks/blazor/scan-using-rtu-api/wwwroot/index.html rename frameworks/capacitor/{scan-using-rtu-api => }/android/.gitignore (100%) rename frameworks/capacitor/{scan-using-rtu-api => }/android/app/.gitignore (100%) rename frameworks/capacitor/{scan-using-rtu-api => }/android/app/build.gradle (100%) rename frameworks/capacitor/{scan-using-rtu-api => }/android/app/capacitor.build.gradle (100%) rename frameworks/capacitor/{scan-using-rtu-api => }/android/app/proguard-rules.pro (100%) rename frameworks/capacitor/{scan-using-rtu-api => }/android/app/src/androidTest/java/com/getcapacitor/myapp/ExampleInstrumentedTest.java (100%) rename frameworks/capacitor/{scan-using-rtu-api => }/android/app/src/main/AndroidManifest.xml (100%) rename frameworks/capacitor/{scan-using-rtu-api => }/android/app/src/main/java/com/dynamsoft/dbrjs/MainActivity.java (100%) rename frameworks/capacitor/{scan-using-rtu-api => }/android/app/src/main/res/drawable-land-hdpi/splash.png (100%) rename frameworks/capacitor/{scan-using-rtu-api => }/android/app/src/main/res/drawable-land-mdpi/splash.png (100%) rename frameworks/capacitor/{scan-using-rtu-api => }/android/app/src/main/res/drawable-land-xhdpi/splash.png (100%) rename frameworks/capacitor/{scan-using-rtu-api => }/android/app/src/main/res/drawable-land-xxhdpi/splash.png (100%) rename frameworks/capacitor/{scan-using-rtu-api => }/android/app/src/main/res/drawable-land-xxxhdpi/splash.png (100%) rename frameworks/capacitor/{scan-using-rtu-api => }/android/app/src/main/res/drawable-port-hdpi/splash.png (100%) rename frameworks/capacitor/{scan-using-rtu-api => }/android/app/src/main/res/drawable-port-mdpi/splash.png (100%) rename frameworks/capacitor/{scan-using-rtu-api => }/android/app/src/main/res/drawable-port-xhdpi/splash.png (100%) rename frameworks/capacitor/{scan-using-rtu-api => }/android/app/src/main/res/drawable-port-xxhdpi/splash.png (100%) rename frameworks/capacitor/{scan-using-rtu-api => }/android/app/src/main/res/drawable-port-xxxhdpi/splash.png (100%) rename frameworks/capacitor/{scan-using-rtu-api => }/android/app/src/main/res/drawable-v24/ic_launcher_foreground.xml (100%) rename frameworks/capacitor/{scan-using-rtu-api => }/android/app/src/main/res/drawable/ic_launcher_background.xml (100%) rename frameworks/capacitor/{scan-using-rtu-api => }/android/app/src/main/res/drawable/splash.png (100%) rename frameworks/capacitor/{scan-using-rtu-api => }/android/app/src/main/res/layout/activity_main.xml (100%) rename frameworks/capacitor/{scan-using-rtu-api => }/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml (100%) rename frameworks/capacitor/{scan-using-rtu-api => }/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml (100%) rename frameworks/capacitor/{scan-using-rtu-api => }/android/app/src/main/res/mipmap-hdpi/ic_launcher.png (100%) rename frameworks/capacitor/{scan-using-rtu-api => }/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png (100%) rename frameworks/capacitor/{scan-using-rtu-api => }/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png (100%) rename frameworks/capacitor/{scan-using-rtu-api => }/android/app/src/main/res/mipmap-mdpi/ic_launcher.png (100%) rename frameworks/capacitor/{scan-using-rtu-api => }/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png (100%) rename frameworks/capacitor/{scan-using-rtu-api => }/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png (100%) rename frameworks/capacitor/{scan-using-rtu-api => }/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png (100%) rename frameworks/capacitor/{scan-using-rtu-api => }/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png (100%) rename frameworks/capacitor/{scan-using-rtu-api => }/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png (100%) rename frameworks/capacitor/{scan-using-rtu-api => }/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png (100%) rename frameworks/capacitor/{scan-using-rtu-api => }/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png (100%) rename frameworks/capacitor/{scan-using-rtu-api => }/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png (100%) rename frameworks/capacitor/{scan-using-rtu-api => }/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png (100%) rename frameworks/capacitor/{scan-using-rtu-api => }/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png (100%) rename frameworks/capacitor/{scan-using-rtu-api => }/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png (100%) rename frameworks/capacitor/{scan-using-rtu-api => }/android/app/src/main/res/values/ic_launcher_background.xml (100%) rename frameworks/capacitor/{scan-using-rtu-api => }/android/app/src/main/res/values/strings.xml (100%) rename frameworks/capacitor/{scan-using-rtu-api => }/android/app/src/main/res/values/styles.xml (100%) rename frameworks/capacitor/{scan-using-rtu-api => }/android/app/src/main/res/xml/file_paths.xml (100%) rename frameworks/capacitor/{scan-using-rtu-api => }/android/app/src/test/java/com/getcapacitor/myapp/ExampleUnitTest.java (100%) rename frameworks/capacitor/{scan-using-rtu-api => }/android/build.gradle (100%) rename frameworks/capacitor/{scan-using-rtu-api => }/android/capacitor.settings.gradle (100%) rename frameworks/capacitor/{scan-using-rtu-api => }/android/gradle.properties (100%) rename frameworks/capacitor/{scan-using-rtu-api => }/android/gradle/wrapper/gradle-wrapper.jar (100%) rename frameworks/capacitor/{scan-using-rtu-api => }/android/gradle/wrapper/gradle-wrapper.properties (100%) rename frameworks/capacitor/{scan-using-rtu-api => }/android/gradlew (100%) rename frameworks/capacitor/{scan-using-rtu-api => }/android/gradlew.bat (100%) rename frameworks/capacitor/{scan-using-rtu-api => }/android/settings.gradle (100%) rename frameworks/capacitor/{scan-using-rtu-api => }/android/variables.gradle (100%) rename frameworks/capacitor/{scan-using-rtu-api => }/capacitor.config.json (100%) create mode 100644 frameworks/capacitor/index.ts rename frameworks/capacitor/{scan-using-rtu-api => }/ios/.gitignore (100%) rename frameworks/capacitor/{scan-using-rtu-api => }/ios/App/App.xcodeproj/project.pbxproj (100%) rename frameworks/capacitor/{scan-using-rtu-api => }/ios/App/App.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist (100%) rename frameworks/capacitor/{scan-using-rtu-api => }/ios/App/App/AppDelegate.swift (100%) rename frameworks/capacitor/{scan-using-rtu-api => }/ios/App/App/Assets.xcassets/AppIcon.appiconset/AppIcon-512@2x.png (100%) rename frameworks/capacitor/{scan-using-rtu-api => }/ios/App/App/Assets.xcassets/AppIcon.appiconset/Contents.json (100%) rename frameworks/capacitor/{scan-using-rtu-api => }/ios/App/App/Assets.xcassets/Contents.json (100%) rename frameworks/capacitor/{scan-using-rtu-api => }/ios/App/App/Assets.xcassets/Splash.imageset/Contents.json (100%) rename frameworks/capacitor/{scan-using-rtu-api => }/ios/App/App/Assets.xcassets/Splash.imageset/splash-2732x2732-1.png (100%) rename frameworks/capacitor/{scan-using-rtu-api => }/ios/App/App/Assets.xcassets/Splash.imageset/splash-2732x2732-2.png (100%) rename frameworks/capacitor/{scan-using-rtu-api => }/ios/App/App/Assets.xcassets/Splash.imageset/splash-2732x2732.png (100%) rename frameworks/capacitor/{scan-using-rtu-api => }/ios/App/App/Base.lproj/LaunchScreen.storyboard (100%) rename frameworks/capacitor/{scan-using-rtu-api => }/ios/App/App/Base.lproj/Main.storyboard (100%) rename frameworks/capacitor/{scan-using-rtu-api => }/ios/App/App/Info.plist (100%) rename frameworks/capacitor/{scan-using-rtu-api => }/ios/App/Podfile (100%) rename frameworks/capacitor/{scan-using-rtu-api => }/package.json (91%) rename frameworks/capacitor/{scan-using-rtu-api => }/public/index.html (100%) rename frameworks/capacitor/{scan-using-rtu-api => }/rollup.config.mjs (100%) delete mode 100644 frameworks/capacitor/scan-using-rtu-api/README.md delete mode 100644 frameworks/capacitor/scan-using-rtu-api/index.ts rename frameworks/capacitor/{scan-using-rtu-api => }/tsconfig.json (100%) rename frameworks/electron/{scan-using-foundational-api => }/action.js (95%) rename frameworks/electron/{scan-using-foundational-api => }/index.html (100%) rename frameworks/electron/{scan-using-foundational-api => }/main.js (100%) rename frameworks/electron/{scan-using-foundational-api => }/package.json (89%) delete mode 100644 frameworks/electron/scan-using-foundational-api/README.md delete mode 100644 frameworks/electron/scan-using-rtu-api/README.md delete mode 100644 frameworks/electron/scan-using-rtu-api/action.js delete mode 100644 frameworks/electron/scan-using-rtu-api/index.html delete mode 100644 frameworks/electron/scan-using-rtu-api/main.js delete mode 100644 frameworks/electron/scan-using-rtu-api/package.json delete mode 100644 frameworks/electron/scan-using-rtu-api/style.css rename frameworks/electron/{scan-using-foundational-api => }/style.css (100%) rename frameworks/es6/{scan-using-foundational-api => }/es6.html (92%) delete mode 100644 frameworks/es6/scan-using-rtu-api/es6.html delete mode 100644 frameworks/native-ts/README.md rename frameworks/native-ts/{scan-using-foundational-api => }/index.ts (98%) rename frameworks/native-ts/{scan-using-foundational-api => }/package.json (90%) rename frameworks/native-ts/{scan-using-foundational-api => public}/index.html (78%) rename frameworks/native-ts/{scan-using-rtu-api => }/rollup.config.mjs (99%) delete mode 100644 frameworks/native-ts/scan-using-foundational-api/rollup.config.mjs delete mode 100644 frameworks/native-ts/scan-using-rtu-api/README.md delete mode 100644 frameworks/native-ts/scan-using-rtu-api/index.ts delete mode 100644 frameworks/native-ts/scan-using-rtu-api/package.json delete mode 100644 frameworks/native-ts/scan-using-rtu-api/public/index.html delete mode 100644 frameworks/native-ts/scan-using-rtu-api/tsconfig.json rename frameworks/native-ts/{scan-using-foundational-api => }/tsconfig.json (95%) rename frameworks/next/{scan-using-foundational-api => }/.eslintrc.json (100%) rename frameworks/next/{scan-using-foundational-api => }/.gitignore (100%) rename frameworks/next/{scan-using-foundational-api => }/app/favicon.ico (100%) rename frameworks/next/{scan-using-foundational-api => }/app/globals.css (100%) rename frameworks/next/{scan-using-foundational-api => }/app/layout.tsx (100%) rename frameworks/next/{scan-using-foundational-api => }/app/page.css (100%) rename frameworks/next/{scan-using-foundational-api => }/app/page.tsx (100%) rename frameworks/next/{scan-using-foundational-api => }/components/ImageCapture/ImageCapture.css (100%) rename frameworks/next/{scan-using-foundational-api => }/components/ImageCapture/ImageCapture.tsx (100%) rename frameworks/next/{scan-using-foundational-api => }/components/VideoCapture/VideoCapture.css (100%) rename frameworks/next/{scan-using-foundational-api => }/components/VideoCapture/VideoCapture.tsx (98%) rename frameworks/{react/scan-using-foundational-api/src => next}/dynamsoft.config.ts (92%) rename frameworks/next/{scan-using-foundational-api => }/next.config.mjs (100%) rename frameworks/next/{scan-using-foundational-api => }/package.json (85%) rename frameworks/next/{scan-using-foundational-api => }/public/next.svg (100%) rename frameworks/next/{scan-using-foundational-api => }/public/vercel.svg (100%) delete mode 100644 frameworks/next/scan-using-foundational-api/README.md rename frameworks/next/{scan-using-foundational-api => }/tsconfig.json (53%) rename frameworks/nuxt/{scan-using-foundational-api => }/.gitignore (100%) rename frameworks/nuxt/{scan-using-foundational-api => }/app.vue (80%) rename frameworks/nuxt/{scan-using-foundational-api => }/assets/logo.svg (100%) create mode 100644 frameworks/nuxt/assets/main.css rename frameworks/nuxt/{scan-using-foundational-api => }/components/ImageCapture.client.vue (97%) rename frameworks/nuxt/{scan-using-foundational-api => }/components/VideoCapture.client.vue (96%) rename frameworks/{next/scan-using-foundational-api => nuxt}/dynamsoft.config.ts (94%) rename frameworks/nuxt/{scan-using-foundational-api => }/nuxt.config.ts (82%) rename frameworks/nuxt/{scan-using-foundational-api => }/package.json (85%) rename frameworks/nuxt/{scan-using-foundational-api => }/public/favicon.ico (100%) delete mode 100644 frameworks/nuxt/scan-using-foundational-api/README.md delete mode 100644 frameworks/nuxt/scan-using-foundational-api/assets/main.css rename frameworks/nuxt/{scan-using-foundational-api => }/tsconfig.json (100%) rename frameworks/pwa/{scan-using-foundational-api => }/dynamsoft-192x192.png (100%) rename frameworks/pwa/{scan-using-foundational-api => }/dynamsoft-512x512.png (100%) rename frameworks/pwa/{scan-using-foundational-api => }/helloworld-pwa.html (92%) rename frameworks/pwa/{scan-using-foundational-api => }/helloworld-pwa.json (100%) delete mode 100644 frameworks/pwa/scan-using-foundational-api/README.md delete mode 100644 frameworks/pwa/scan-using-foundational-api/service-worker.js delete mode 100644 frameworks/pwa/scan-using-rtu-api/README.md delete mode 100644 frameworks/pwa/scan-using-rtu-api/dynamsoft-192x192.png delete mode 100644 frameworks/pwa/scan-using-rtu-api/dynamsoft-512x512.png delete mode 100644 frameworks/pwa/scan-using-rtu-api/helloworld-pwa.html delete mode 100644 frameworks/pwa/scan-using-rtu-api/helloworld-pwa.json delete mode 100644 frameworks/pwa/scan-using-rtu-api/service-worker.js create mode 100644 frameworks/pwa/service-worker.js rename frameworks/react/{scan-using-foundational-api => }/.gitignore (100%) rename frameworks/react/{scan-using-foundational-api => }/package.json (95%) rename frameworks/react/{scan-using-foundational-api => }/public/favicon.ico (100%) rename frameworks/react/{scan-using-foundational-api => }/public/index.html (93%) rename frameworks/react/{scan-using-foundational-api => }/public/logo192.png (100%) rename frameworks/react/{scan-using-foundational-api => }/public/logo512.png (100%) rename frameworks/react/{scan-using-foundational-api => }/public/manifest.json (100%) delete mode 100644 frameworks/react/scan-using-foundational-api/README.md delete mode 100644 frameworks/react/scan-using-rtu-api/.gitignore delete mode 100644 frameworks/react/scan-using-rtu-api/README.md delete mode 100644 frameworks/react/scan-using-rtu-api/index.html delete mode 100644 frameworks/react/scan-using-rtu-api/package.json delete mode 100644 frameworks/react/scan-using-rtu-api/src/App.tsx delete mode 100644 frameworks/react/scan-using-rtu-api/src/main.tsx delete mode 100644 frameworks/react/scan-using-rtu-api/tsconfig.app.json delete mode 100644 frameworks/react/scan-using-rtu-api/tsconfig.json delete mode 100644 frameworks/react/scan-using-rtu-api/tsconfig.node.json delete mode 100644 frameworks/react/scan-using-rtu-api/vite.config.ts rename frameworks/react/{scan-using-foundational-api => }/src/App.css (100%) rename frameworks/react/{scan-using-foundational-api => }/src/App.tsx (100%) rename frameworks/react/{scan-using-foundational-api => }/src/assets/logo.svg (100%) rename frameworks/react/{scan-using-foundational-api => }/src/components/ImageCapture/ImageCapture.css (100%) rename frameworks/react/{scan-using-foundational-api => }/src/components/ImageCapture/ImageCapture.tsx (100%) rename frameworks/react/{scan-using-foundational-api => }/src/components/VideoCapture/VideoCapture.css (100%) rename frameworks/react/{scan-using-foundational-api => }/src/components/VideoCapture/VideoCapture.tsx (98%) rename frameworks/{nuxt/scan-using-foundational-api => react/src}/dynamsoft.config.ts (94%) rename frameworks/react/{scan-using-foundational-api => }/src/index.css (100%) rename frameworks/react/{scan-using-foundational-api => }/src/index.tsx (100%) rename frameworks/react/{scan-using-foundational-api => }/src/react-app-env.d.ts (100%) rename frameworks/react/{scan-using-foundational-api => }/tsconfig.json (100%) rename frameworks/requirejs/{scan-using-foundational-api => }/requirejs.html (93%) delete mode 100644 frameworks/requirejs/scan-using-rtu-api/requirejs.html rename frameworks/svelte/{scan-using-foundational-api => }/.gitignore (100%) rename frameworks/svelte/{scan-using-foundational-api => }/index.html (100%) rename frameworks/svelte/{scan-using-foundational-api => }/logo.svg (100%) rename frameworks/svelte/{scan-using-foundational-api => }/package.json (90%) delete mode 100644 frameworks/svelte/scan-using-foundational-api/README.md delete mode 100644 frameworks/svelte/scan-using-rtu-api/.gitignore delete mode 100644 frameworks/svelte/scan-using-rtu-api/README.md delete mode 100644 frameworks/svelte/scan-using-rtu-api/index.html delete mode 100644 frameworks/svelte/scan-using-rtu-api/package.json delete mode 100644 frameworks/svelte/scan-using-rtu-api/src/App.svelte delete mode 100644 frameworks/svelte/scan-using-rtu-api/src/main.ts delete mode 100644 frameworks/svelte/scan-using-rtu-api/src/vite-env.d.ts delete mode 100644 frameworks/svelte/scan-using-rtu-api/svelte.config.js delete mode 100644 frameworks/svelte/scan-using-rtu-api/tsconfig.json delete mode 100644 frameworks/svelte/scan-using-rtu-api/tsconfig.node.json delete mode 100644 frameworks/svelte/scan-using-rtu-api/vite.config.ts rename frameworks/svelte/{scan-using-foundational-api => }/src/App.svelte (100%) rename frameworks/svelte/{scan-using-foundational-api => }/src/components/ImageCapture.svelte (100%) rename frameworks/svelte/{scan-using-foundational-api => }/src/components/VideoCapture.svelte (98%) rename frameworks/svelte/{scan-using-foundational-api => }/src/dynamsoft.config.ts (94%) rename frameworks/svelte/{scan-using-foundational-api => }/src/main.ts (100%) rename frameworks/svelte/{scan-using-foundational-api => }/src/vite-env.d.ts (100%) rename frameworks/svelte/{scan-using-foundational-api => }/svelte.config.js (100%) rename frameworks/svelte/{scan-using-foundational-api => }/tsconfig.json (100%) rename frameworks/svelte/{scan-using-foundational-api => }/tsconfig.node.json (100%) rename frameworks/svelte/{scan-using-foundational-api => }/vite.config.ts (100%) rename frameworks/vue/{scan-using-foundational-api => }/.gitignore (100%) rename frameworks/vue/{scan-using-foundational-api => }/env.d.ts (100%) rename frameworks/vue/{scan-using-foundational-api => }/index.html (83%) rename frameworks/vue/{scan-using-foundational-api => }/package.json (91%) rename frameworks/vue/{scan-using-foundational-api => }/public/favicon.ico (100%) delete mode 100644 frameworks/vue/scan-using-foundational-api/README.md delete mode 100644 frameworks/vue/scan-using-rtu-api/.gitignore delete mode 100644 frameworks/vue/scan-using-rtu-api/README.md delete mode 100644 frameworks/vue/scan-using-rtu-api/index.html delete mode 100644 frameworks/vue/scan-using-rtu-api/package.json delete mode 100644 frameworks/vue/scan-using-rtu-api/src/App.vue delete mode 100644 frameworks/vue/scan-using-rtu-api/src/main.ts delete mode 100644 frameworks/vue/scan-using-rtu-api/src/vite-env.d.ts delete mode 100644 frameworks/vue/scan-using-rtu-api/tsconfig.app.json delete mode 100644 frameworks/vue/scan-using-rtu-api/tsconfig.json delete mode 100644 frameworks/vue/scan-using-rtu-api/tsconfig.node.json delete mode 100644 frameworks/vue/scan-using-rtu-api/vite.config.ts rename frameworks/vue/{scan-using-foundational-api => }/src/App.vue (98%) rename frameworks/vue/{scan-using-foundational-api => }/src/assets/logo.svg (100%) rename frameworks/vue/{scan-using-foundational-api => }/src/assets/main.css (72%) rename frameworks/vue/{scan-using-foundational-api => }/src/components/ImageCapture.vue (99%) rename frameworks/vue/{scan-using-foundational-api => }/src/components/VideoCapture.vue (96%) rename frameworks/vue/{scan-using-foundational-api => }/src/dynamsoft.config.ts (94%) rename frameworks/vue/{scan-using-foundational-api => }/src/main.ts (100%) rename frameworks/vue/{scan-using-foundational-api => }/tsconfig.config.json (100%) rename frameworks/vue/{scan-using-foundational-api => }/tsconfig.json (100%) rename frameworks/vue/{scan-using-foundational-api => }/vite.config.ts (100%) delete mode 100644 frameworks/webview/README.md rename frameworks/webview/{scan-using-foundational-api => }/android/.gitignore (100%) rename frameworks/webview/{scan-using-foundational-api => }/android/README.md (100%) rename frameworks/webview/{scan-using-foundational-api => }/android/app/.gitignore (100%) rename frameworks/webview/{scan-using-foundational-api => }/android/app/build.gradle (100%) rename frameworks/webview/{scan-using-foundational-api => }/android/app/proguard-rules.pro (100%) rename frameworks/webview/{scan-using-foundational-api => }/android/app/src/main/AndroidManifest.xml (100%) rename frameworks/webview/{scan-using-foundational-api => }/android/app/src/main/assets/decodeBarcodeInVideo.html (91%) rename frameworks/webview/{scan-using-foundational-api => }/android/app/src/main/java/com/dynamsoft/dbrjswebview/MainActivity.kt (100%) rename frameworks/webview/{scan-using-foundational-api => }/android/app/src/main/res/drawable-v24/ic_launcher_foreground.xml (100%) rename frameworks/webview/{scan-using-foundational-api => }/android/app/src/main/res/drawable/ic_launcher_background.xml (100%) rename frameworks/webview/{scan-using-foundational-api => }/android/app/src/main/res/layout/activity_main.xml (100%) rename frameworks/webview/{scan-using-foundational-api => }/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml (100%) rename frameworks/webview/{scan-using-foundational-api => }/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml (100%) rename frameworks/webview/{scan-using-foundational-api => }/android/app/src/main/res/mipmap-anydpi-v33/ic_launcher.xml (100%) rename frameworks/webview/{scan-using-foundational-api => }/android/app/src/main/res/mipmap-hdpi/ic_launcher.webp (100%) rename frameworks/webview/{scan-using-foundational-api => }/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp (100%) rename frameworks/webview/{scan-using-foundational-api => }/android/app/src/main/res/mipmap-mdpi/ic_launcher.webp (100%) rename frameworks/webview/{scan-using-foundational-api => }/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp (100%) rename frameworks/webview/{scan-using-foundational-api => }/android/app/src/main/res/mipmap-xhdpi/ic_launcher.webp (100%) rename frameworks/webview/{scan-using-foundational-api => }/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp (100%) rename frameworks/webview/{scan-using-foundational-api => }/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp (100%) rename frameworks/webview/{scan-using-foundational-api => }/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp (100%) rename frameworks/webview/{scan-using-foundational-api => }/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp (100%) rename frameworks/webview/{scan-using-foundational-api => }/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp (100%) rename frameworks/webview/{scan-using-foundational-api => }/android/app/src/main/res/values-night/themes.xml (100%) rename frameworks/webview/{scan-using-foundational-api => }/android/app/src/main/res/values/colors.xml (100%) rename frameworks/webview/{scan-using-foundational-api => }/android/app/src/main/res/values/strings.xml (100%) rename frameworks/webview/{scan-using-foundational-api => }/android/app/src/main/res/values/themes.xml (100%) rename frameworks/webview/{scan-using-foundational-api => }/android/app/src/main/res/xml/backup_rules.xml (100%) rename frameworks/webview/{scan-using-foundational-api => }/android/app/src/main/res/xml/data_extraction_rules.xml (100%) rename frameworks/webview/{scan-using-foundational-api => }/android/build.gradle (100%) rename frameworks/webview/{scan-using-foundational-api => }/android/gradle.properties (100%) rename frameworks/webview/{scan-using-foundational-api => }/android/gradle/wrapper/gradle-wrapper.jar (100%) rename frameworks/webview/{scan-using-foundational-api => }/android/gradle/wrapper/gradle-wrapper.properties (100%) rename frameworks/webview/{scan-using-foundational-api => }/android/gradlew (100%) rename frameworks/webview/{scan-using-foundational-api => }/android/gradlew.bat (100%) rename frameworks/webview/{scan-using-foundational-api => }/android/settings.gradle (100%) rename frameworks/webview/{scan-using-foundational-api => }/ios/.gitignore (100%) rename frameworks/webview/{scan-using-foundational-api => }/ios/README.md (100%) rename frameworks/webview/{scan-using-foundational-api => }/ios/dbrjswebview.xcodeproj/project.pbxproj (100%) rename frameworks/webview/{scan-using-foundational-api => }/ios/dbrjswebview.xcodeproj/project.xcworkspace/contents.xcworkspacedata (100%) rename frameworks/webview/{scan-using-foundational-api => }/ios/dbrjswebview.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist (100%) rename frameworks/webview/{scan-using-foundational-api => }/ios/dbrjswebview/AppDelegate.swift (100%) rename frameworks/webview/{scan-using-foundational-api => }/ios/dbrjswebview/Assets.xcassets/AccentColor.colorset/Contents.json (100%) rename frameworks/webview/{scan-using-foundational-api => }/ios/dbrjswebview/Assets.xcassets/AppIcon.appiconset/Contents.json (100%) rename frameworks/webview/{scan-using-foundational-api => }/ios/dbrjswebview/Assets.xcassets/Contents.json (100%) rename frameworks/webview/{scan-using-foundational-api => }/ios/dbrjswebview/Base.lproj/LaunchScreen.storyboard (100%) rename frameworks/webview/{scan-using-foundational-api => }/ios/dbrjswebview/Base.lproj/Main.storyboard (100%) rename frameworks/webview/{scan-using-foundational-api => }/ios/dbrjswebview/Info.plist (100%) rename frameworks/webview/{scan-using-foundational-api => }/ios/dbrjswebview/SceneDelegate.swift (100%) rename frameworks/webview/{scan-using-foundational-api => }/ios/dbrjswebview/ViewController.swift (100%) rename frameworks/webview/{scan-using-foundational-api => }/ios/dbrjswebview/html/decodeFileInVideo.html (91%) delete mode 100644 frameworks/webview/scan-using-rtu-api/android/.gitignore delete mode 100644 frameworks/webview/scan-using-rtu-api/android/README.md delete mode 100644 frameworks/webview/scan-using-rtu-api/android/app/.gitignore delete mode 100644 frameworks/webview/scan-using-rtu-api/android/app/build.gradle delete mode 100644 frameworks/webview/scan-using-rtu-api/android/app/proguard-rules.pro delete mode 100644 frameworks/webview/scan-using-rtu-api/android/app/src/main/AndroidManifest.xml delete mode 100644 frameworks/webview/scan-using-rtu-api/android/app/src/main/assets/decodeBarcodeInVideo.html delete mode 100644 frameworks/webview/scan-using-rtu-api/android/app/src/main/java/com/dynamsoft/dbrjswebview/MainActivity.kt delete mode 100644 frameworks/webview/scan-using-rtu-api/android/app/src/main/res/drawable-v24/ic_launcher_foreground.xml delete mode 100644 frameworks/webview/scan-using-rtu-api/android/app/src/main/res/drawable/ic_launcher_background.xml delete mode 100644 frameworks/webview/scan-using-rtu-api/android/app/src/main/res/layout/activity_main.xml delete mode 100644 frameworks/webview/scan-using-rtu-api/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml delete mode 100644 frameworks/webview/scan-using-rtu-api/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml delete mode 100644 frameworks/webview/scan-using-rtu-api/android/app/src/main/res/mipmap-anydpi-v33/ic_launcher.xml delete mode 100644 frameworks/webview/scan-using-rtu-api/android/app/src/main/res/mipmap-hdpi/ic_launcher.webp delete mode 100644 frameworks/webview/scan-using-rtu-api/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp delete mode 100644 frameworks/webview/scan-using-rtu-api/android/app/src/main/res/mipmap-mdpi/ic_launcher.webp delete mode 100644 frameworks/webview/scan-using-rtu-api/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp delete mode 100644 frameworks/webview/scan-using-rtu-api/android/app/src/main/res/mipmap-xhdpi/ic_launcher.webp delete mode 100644 frameworks/webview/scan-using-rtu-api/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp delete mode 100644 frameworks/webview/scan-using-rtu-api/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp delete mode 100644 frameworks/webview/scan-using-rtu-api/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp delete mode 100644 frameworks/webview/scan-using-rtu-api/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp delete mode 100644 frameworks/webview/scan-using-rtu-api/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp delete mode 100644 frameworks/webview/scan-using-rtu-api/android/app/src/main/res/values-night/themes.xml delete mode 100644 frameworks/webview/scan-using-rtu-api/android/app/src/main/res/values/colors.xml delete mode 100644 frameworks/webview/scan-using-rtu-api/android/app/src/main/res/values/strings.xml delete mode 100644 frameworks/webview/scan-using-rtu-api/android/app/src/main/res/values/themes.xml delete mode 100644 frameworks/webview/scan-using-rtu-api/android/app/src/main/res/xml/backup_rules.xml delete mode 100644 frameworks/webview/scan-using-rtu-api/android/app/src/main/res/xml/data_extraction_rules.xml delete mode 100644 frameworks/webview/scan-using-rtu-api/android/build.gradle delete mode 100644 frameworks/webview/scan-using-rtu-api/android/gradle.properties delete mode 100644 frameworks/webview/scan-using-rtu-api/android/gradle/wrapper/gradle-wrapper.jar delete mode 100644 frameworks/webview/scan-using-rtu-api/android/gradle/wrapper/gradle-wrapper.properties delete mode 100644 frameworks/webview/scan-using-rtu-api/android/gradlew delete mode 100644 frameworks/webview/scan-using-rtu-api/android/gradlew.bat delete mode 100644 frameworks/webview/scan-using-rtu-api/android/settings.gradle delete mode 100644 frameworks/webview/scan-using-rtu-api/ios/.gitignore delete mode 100644 frameworks/webview/scan-using-rtu-api/ios/README.md delete mode 100644 frameworks/webview/scan-using-rtu-api/ios/dbrjswebview.xcodeproj/project.pbxproj delete mode 100644 frameworks/webview/scan-using-rtu-api/ios/dbrjswebview.xcodeproj/project.xcworkspace/contents.xcworkspacedata delete mode 100644 frameworks/webview/scan-using-rtu-api/ios/dbrjswebview.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist delete mode 100644 frameworks/webview/scan-using-rtu-api/ios/dbrjswebview/AppDelegate.swift delete mode 100644 frameworks/webview/scan-using-rtu-api/ios/dbrjswebview/Assets.xcassets/AccentColor.colorset/Contents.json delete mode 100644 frameworks/webview/scan-using-rtu-api/ios/dbrjswebview/Assets.xcassets/AppIcon.appiconset/Contents.json delete mode 100644 frameworks/webview/scan-using-rtu-api/ios/dbrjswebview/Assets.xcassets/Contents.json delete mode 100644 frameworks/webview/scan-using-rtu-api/ios/dbrjswebview/Base.lproj/LaunchScreen.storyboard delete mode 100644 frameworks/webview/scan-using-rtu-api/ios/dbrjswebview/Base.lproj/Main.storyboard delete mode 100644 frameworks/webview/scan-using-rtu-api/ios/dbrjswebview/Info.plist delete mode 100644 frameworks/webview/scan-using-rtu-api/ios/dbrjswebview/SceneDelegate.swift delete mode 100644 frameworks/webview/scan-using-rtu-api/ios/dbrjswebview/ViewController.swift delete mode 100644 frameworks/webview/scan-using-rtu-api/ios/dbrjswebview/html/decodeFileInVideo.html create mode 100644 scenarios/cart-builder/index.css rename scenarios/cart-builder/{cart-builder.html => index.html} (57%) create mode 100644 scenarios/locate-an-item-with-barcode/index.css rename scenarios/read-and-parse-GS1-AI/{scan-using-foundational-api => }/index.css (100%) rename scenarios/read-and-parse-GS1-AI/{scan-using-foundational-api => }/index.html (97%) rename scenarios/read-and-parse-GS1-AI/{scan-using-foundational-api => }/read_and_parse_gs1.json (100%) delete mode 100644 scenarios/read-and-parse-GS1-AI/scan-using-rtu-api/convert-GS1AI-title.js delete mode 100644 scenarios/read-and-parse-GS1-AI/scan-using-rtu-api/index.html delete mode 100644 scenarios/read-and-parse-GS1-AI/scan-using-rtu-api/info.svg delete mode 100644 scenarios/read-and-parse-GS1-AI/scan-using-rtu-api/logo-dynamsoft-blackBg-190x47-DZ66W3xz.png delete mode 100644 scenarios/read-and-parse-GS1-AI/scan-using-rtu-api/rtu_gs1.json delete mode 100644 scenarios/read-and-parse-GS1-AI/scan-using-rtu-api/style.css create mode 100644 scenarios/scan-and-search/index.css create mode 100644 scenarios/scan-and-search/index.html delete mode 100644 scenarios/scan-and-search/scan-and-search.html rename scenarios/show-result-texts-on-the-video/{show-result-texts-on-the-video.html => index.html} (90%) diff --git a/README.md b/README.md index 3e0a568f..ec2811c8 100644 --- a/README.md +++ b/README.md @@ -21,12 +21,10 @@ The following table is a list of supported browsers based on the above requireme | Browser Name | Version | | :----------: | :--------------: | -| Chrome | v78+1 | -| Firefox | v68+1 | -| Edge | v79+ | -| Safari | v14.5+ | - -1 Devices running iOS need to be on iOS 14.5+ for camera video streaming to work in Chrome, Firefox or other apps using webviews. +| Chrome | v88+ | +| Firefox | v89+ | +| Edge | v88+ | +| Safari | v15+ | Apart from the browsers, the operating systems may impose some limitations of their own that could restrict the use of the SDK. @@ -78,36 +76,17 @@ If you need a web server for standalone or scenario samples (for example, to ser The repository includes two main sample directories: -- **`frameworks/`** - Framework-specific examples demonstrating how to integrate Dynamsoft Barcode Reader into common web and hybrid frameworks. Each framework folder contains one or more runnable sub-examples (such as `scan-using-foundational-api` and/or `scan-using-rtu-api`) showing practical integration patterns. +- **`frameworks/`** - Framework-specific examples demonstrating how to integrate Dynamsoft Barcode Reader into common web and hybrid frameworks. - **`scenarios/`** - Focused scenario samples that show common real-world uses of Dynamsoft Barcode Reader. --- -## Choosing an API - -The SDK provides two approaches for integrating barcode scanning capabilities: - -### Ready-To-Use (RTU) API — BarcodeScanner - -The RTU API offers the quickest path to a working barcode scanner (**Recommended for most users**): - -- **One-line integration** – Launch a full scanner with a single API call -- **Built-in UI** – Pre-designed viewfinder and scan region highlighting -- **Simple configuration** – Customize behavior through intuitive config objects - -### Foundational APIs - -If you are looking for a fully customizable barcode decoding library with complete control over the scanning process and UI, you are welcome to use the Foundational APIs. - ---- - ## Documentation -For the developer guide and full API reference of Dynamsoft Barcode Reader JavaScript library, please check out the [documentation](https://www.dynamsoft.com/barcode-reader/docs/web/programming/javascript/?ver=11.2.4000&utm_source=sampleReadme). +For the developer guide and full API reference of Dynamsoft Barcode Reader JavaScript library, please check out the [documentation](https://www.dynamsoft.com/barcode-reader/docs/web/programming/javascript/?ver=11.4.2000&utm_source=sampleReadme). -- [Barcode Scanner API Docs](https://www.dynamsoft.com/barcode-reader/docs/web/programming/javascript/api-reference/barcode-scanner.html?utm_source=sampleReadme) -- [Foundational API Docs](https://www.dynamsoft.com/barcode-reader/docs/web/programming/javascript/api-reference/index.html?utm_source=sampleReadme) +- [API Docs](https://www.dynamsoft.com/barcode-reader/docs/web/programming/javascript/api-reference/index.html?utm_source=sampleReadme) --- @@ -125,11 +104,6 @@ If you have any questions, feel free to [contact Dynamsoft support](https://www. - [scan-a-single-barcode.html](./scan-a-single-barcode.html) — Demonstrates single-barcode scanning: stops and returns as soon as the first barcode is detected. - [read-an-image.html](./read-an-image.html) — Demonstrates how to decode and read barcodes from uploaded image files. -### Hello-world - -- [hello-world.html](./hello-world.html) — The simplest example to get started with single barcode scanning. -- [read-an-image.html](./read-an-image.html) — Demonstrates how to decode and read barcodes from uploaded image files. - ### Frameworks - [angular/](./frameworks/angular/) — Angular examples. diff --git a/frameworks/README.md b/frameworks/README.md index c7812e62..8638768e 100644 --- a/frameworks/README.md +++ b/frameworks/README.md @@ -1,6 +1,6 @@ # Frameworks samples -This directory contains framework-specific examples demonstrating how to integrate the Dynamsoft Barcode Reader (JavaScript edition) into common web and hybrid frameworks. Each framework folder contains one or more runnable sub-examples (for example, scan-using-foundational-api and/or scan-using-rtu-api) showing practical integration patterns. +This directory contains framework-specific examples demonstrating how to integrate the Dynamsoft Barcode Reader (JavaScript edition) into common web and hybrid frameworks. ## Sample list @@ -23,7 +23,7 @@ This directory contains framework-specific examples demonstrating how to integra 1. Browse into a framework subfolder and choose a subexample, e.g.: ```cmd - cd react/scan-using-rtu-api + cd react ``` 1. Follow the subexample README for exact steps. Typical commands: ```cmd diff --git a/frameworks/angular/scan-using-foundational-api/.editorconfig b/frameworks/angular/.editorconfig similarity index 100% rename from frameworks/angular/scan-using-foundational-api/.editorconfig rename to frameworks/angular/.editorconfig diff --git a/frameworks/angular/scan-using-foundational-api/.gitignore b/frameworks/angular/.gitignore similarity index 100% rename from frameworks/angular/scan-using-foundational-api/.gitignore rename to frameworks/angular/.gitignore diff --git a/frameworks/angular/README.md b/frameworks/angular/README.md index 97e5d706..0bf17895 100644 --- a/frameworks/angular/README.md +++ b/frameworks/angular/README.md @@ -1,23 +1,422 @@ -# Angular samples +# Hello World Sample for Angular -This directory contains Angular-based examples demonstrating how to use the Dynamsoft Barcode Reader (JavaScript edition) in Angular projects. +[Angular](https://angular.dev/) is one of the most popular and mature JavaScript frameworks. Follow this guide to learn how to implement [Dynamsoft Barcode Reader JavaScript SDK](https://www.dynamsoft.com/barcode-reader/sdk-javascript/) (hereafter called "the library") into an Angular application. Note that in this sample, `TypeScript` is used. -**Included examples** +In this guide, we will be using [`dynamsoft-barcode-reader-bundle 11.4.2000`](https://www.npmjs.com/package/dynamsoft-barcode-reader-bundle/v/11.4.2000). -- scan-using-foundational-api/ — Example using the foundational API. -- scan-using-rtu-api/ — Example using the RTU API. +> Note: +> +> If you're looking to integrate DBR-JS into a framework that we don't yet have a sample, don't worry! We have a [comprehensive guide](https://www.dynamsoft.com/barcode-reader/docs/web/programming/javascript/user-guide/use-in-framework.html) that provides detailed instruction and best practices for a seamless integration into any frameworks! +> +> Additionally, we're here to help! Please don't hesitate to [contact us](#Support) for any support or questions you might have. -## Quick start +## Official sample -1. Change to a subexample directory, e.g.: +* Hello World in Angular - Source Code - ```bash - cd scan-using-foundational-api - ``` +## Preparation +Make sure you have [node](https://nodejs.org/) and [Angular CLI](https://cli.angular.io/) installed. -2. Follow the subexample README for exact steps (typically: npm install && npm run start or ng serve). +This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 17.3.7. -## Notes +## Quick Start -- Run examples via the framework dev server. Opening files directly may break module loading or camera access. -- See the repository root README.md for general usage and license information. \ No newline at end of file +1. Install project dependencies + +```cmd +npm install +``` + +2. Build and serve the Angular app + +```cmd +ng serve +``` + +Then open `https://localhost:4200/` to view the sample app. + +## Creating the sample project + +In this section, we will be creating an Angular application utilizing the Dynamsoft Barcode Reader bundle sdk. + +We'll be exploring how you could create a page that not only enables barcode scanning via a webcam or a built-in camera, but also decode barcodes from local images. + +By the end of this guide, you'll have a good understanding of the SDK and be ready to discover more ways to use it! + +### Create an [Angular](https://angular.dev) Application bootstrapped with [Angular CLI](https://cli.angular.io/) +```cmd +ng new my-app +``` + +On installation, you will be prompted to configure your project.\ +You can customize these options according to your preferences.\ +Below is the configuration used for this sample. + +``` +? Which stylesheet format would you like to use? CSS +? Do you want to enable Server-Side Rendering (SSR) and Static Site Generation (SSG/Prerendering)? No +``` + +### **CD** to the root directory of the application and install necessary libraries + +```cmd +cd my-app +npm install dynamsoft-barcode-reader-bundle@11.4.2000 -E +``` + +## Start to implement + +### Add file "dynamsoft.config.ts" at the root of the app to configure libraries + +```typescript +/* /dynamsoft.config.ts */ +import { CoreModule } from 'dynamsoft-core'; +import { LicenseManager } from 'dynamsoft-license'; +import 'dynamsoft-barcode-reader'; + +// Configures the paths where the .wasm files and other necessary resources for modules are located. +CoreModule.engineResourcePaths.rootDirectory = "https://cdn.jsdelivr.net/npm/"; + +/** LICENSE ALERT - README + * To use the library, you need to first specify a license key using the API "initLicense()" as shown below. + */ + +LicenseManager.initLicense('DLS2eyJvcmdhbml6YXRpb25JRCI6IjIwMDAwMSJ9', true); + +/** + * You can visit https://www.dynamsoft.com/customer/license/trialLicense?utm_source=samples&product=dbr&package=js to get your own trial license good for 30 days. + * Note that if you downloaded this sample from Dynamsoft while logged in, the above license key may already be your own 30-day trial license. + * For more information, see https://www.dynamsoft.com/barcode-reader/docs/web/programming/javascript/user-guide/index.html?ver=11.4.2000&cVer=true#specify-the-license&utm_source=samples or contact support@dynamsoft.com. + * LICENSE ALERT - THE END + */ + +// Optional. Preload .wasm file for reading barcodes. It will save time on the initial decoding by skipping the resource loading. +CoreModule.loadWasm(); +``` + +> Note: +> +> * `initLicense()` specify a license key to use the library. You can visit https://www.dynamsoft.com/customer/license/trialLicense?utm_source=sample&product=dbr&package=js to get your own trial license good for 30 days. +> * `engineResourcePaths` tells the library where to get the necessary resources at runtime. + +### Generate and edit the `video-capture` component + +* Generate the `video-capture`. The `video-capture` component helps decode barcodes via camera. + +```cmd +ng generate component video-capture +``` + +* In `video-capture.component.html`, add code to setup the component's HTML + +```html + +
+
+Results: +
{{resultText}}
+``` + +* In `video-capture.component.ts`, add code for initializing and destroying some instances. For our stylesheet (CSS) specification, please refer to our [source code](#Official-Sample). + +```ts +/* /src/app/video-capture/video-capture.component.ts */ +import { Component, ElementRef, ViewChild } from '@angular/core'; +import '../dynamsoft.config'; +import { CameraEnhancer, CameraView } from 'dynamsoft-camera-enhancer'; +import { CaptureVisionRouter } from 'dynamsoft-capture-vision-router'; +import { MultiFrameResultCrossFilter } from 'dynamsoft-utility'; + +const componentDestroyedErrorMsg = 'VideoCapture Component Destroyed'; + +@Component({ + selector: 'app-video-capture', + templateUrl: './video-capture.component.html', + styleUrls: ['./video-capture.component.css'], + standalone: true, +}) +export class VideoCaptureComponent { + @ViewChild('cameraViewContainer') cameraViewContainer?: ElementRef; + resultText = ""; + + resolveInit?: () => void; + pInit: Promise = new Promise((r) => { + this.resolveInit = r; + }); + isDestroyed = false; + + cvRouter?: CaptureVisionRouter; + cameraEnhancer?: CameraEnhancer; + + async ngAfterViewInit(): Promise { + try { + // Create a `CameraEnhancer` instance for camera control and a `CameraView` instance for UI control. + const cameraView = await CameraView.createInstance(); + if (this.isDestroyed) { + throw Error(componentDestroyedErrorMsg); + } // Check if component is destroyed after every async + this.cameraEnhancer = await CameraEnhancer.createInstance(cameraView); + if (this.isDestroyed) { + throw Error(componentDestroyedErrorMsg); + } + + // Get default UI and append it to DOM. + this.cameraViewContainer!.nativeElement.append(cameraView.getUIElement()); + + // Create a `CaptureVisionRouter` instance and set `CameraEnhancer` instance as its image source. + this.cvRouter = await CaptureVisionRouter.createInstance(); + if (this.isDestroyed) { + throw Error(componentDestroyedErrorMsg); + } + this.cvRouter.setInput(this.cameraEnhancer); + + // Define a callback for results. + this.cvRouter.addResultReceiver({ + onDecodedBarcodesReceived: (result) => { + if (!result.barcodeResultItems.length) return; + + this.resultText = ''; + console.log(result); + for (let item of result.barcodeResultItems) { + this.resultText += `${item.formatString}: ${item.text}\n\n`; + } + }, + }); + + // Filter out unchecked and duplicate results. + const filter = new MultiFrameResultCrossFilter(); + // Filter out unchecked barcodes. + filter.enableResultCrossVerification('barcode', true); + // Filter out duplicate barcodes within 3 seconds. + filter.enableResultDeduplication('barcode', true); + await this.cvRouter.addResultFilter(filter); + if (this.isDestroyed) { + throw Error(componentDestroyedErrorMsg); + } + + // Open camera and start scanning single barcode. + await this.cameraEnhancer.open(); + cameraView.setScanLaserVisible(true); + if (this.isDestroyed) { + throw Error(componentDestroyedErrorMsg); + } + await this.cvRouter.startCapturing('ReadSingleBarcode'); + if (this.isDestroyed) { + throw Error(componentDestroyedErrorMsg); + } + } catch (ex: any) { + if ((ex as Error)?.message === componentDestroyedErrorMsg) { + console.log(componentDestroyedErrorMsg); + } else { + let errMsg = ex.message || ex; + console.error(ex); + alert(errMsg); + } + } + + // Resolve pInit promise once initialization is complete. + this.resolveInit!(); + } + + // dispose cvRouter when it's no longer needed + async ngOnDestroy() { + this.isDestroyed = true; + try { + // Wait for the pInit to complete before disposing resources. + await this.pInit; + this.cvRouter?.dispose(); + this.cameraEnhancer?.dispose(); + } catch (_) {} + } +} +``` +> Note: +> +> If you're looking to customize the UI, the UI customization feature are provided by the auxiliary SDK "Dynamsoft Camera Enhancer". For more details, refer to our [User Guide](https://www.dynamsoft.com/barcode-reader/docs/web/programming/javascript/user-guide/index.html#customizing-the-ui) + + +### Generate and edit the `image-capture` component + +* Generate the `image-capture`. The `image-capture` component helps decode barcodes in an image. + +```cmd +ng generate component image-capture +``` + +* In `image-capture.component.html`, add code to setup the component's HTML + +```html + +
+
+ +
+
{{resultText}}
+
+``` + +* In `image-capture.component.ts`, add code for initializing and destroying some instances. For our stylesheet (CSS) specification, please refer to our [source code](#Official-Sample). + +```ts +/* /src/app/image-capture/image-capture.component.ts */ +import { Component, ViewChild, ElementRef } from '@angular/core'; +import '../dynamsoft.config'; +import { EnumCapturedResultItemType } from 'dynamsoft-core'; +import type { BarcodeResultItem } from 'dynamsoft-barcode-reader'; +import { CaptureVisionRouter } from 'dynamsoft-capture-vision-router'; + +@Component({ + selector: 'app-image-capture', + templateUrl: './image-capture.component.html', + styleUrls: ['./image-capture.component.css'], + standalone: true, +}) +export class ImageCaptureComponent { + resultText = ""; + + pCvRouter?: Promise; + isDestroyed = false; + + captureImage = async (e: Event) => { + let files = [...((e.target! as HTMLInputElement).files as any as File[])]; + (e.target! as HTMLInputElement).value = ''; // reset input + this.resultText = ''; + try { + // ensure cvRouter is created only once + const cvRouter = await (this.pCvRouter = + this.pCvRouter || CaptureVisionRouter.createInstance()); + if (this.isDestroyed) return; + + for (let file of files) { + // Decode selected image with 'ReadBarcodes_ReadRateFirst' template. + const result = await cvRouter.capture(file, 'ReadBarcodes_ReadRateFirst'); + console.log(result); + if (this.isDestroyed) return; + + // Print file name if there's multiple files + if (files.length > 1) { + this.resultText += `\n${file.name}:\n`; + } + for (let _item of result.items) { + if (_item.type !== EnumCapturedResultItemType.CRIT_BARCODE) { + continue; // check if captured result item is a barcode + } + let item = _item as BarcodeResultItem; + this.resultText += item.text + '\n'; // output the decoded barcode text + } + // If no items are found, display that no barcode was detected + if (!result.items.length) + this.resultText += + 'No barcode found\n'; + } + } catch (ex: any) { + let errMsg = ex.message || ex; + console.error(ex); + alert(errMsg); + } + }; + + // dispose cvRouter when it's no longer needed + async ngOnDestroy() { + this.isDestroyed = true; + if (this.pCvRouter) { + try { + (await this.pCvRouter).dispose(); + } catch (_) {} + } + } +} +``` + +### Add the `video-capture` and `image-capture` component to the `app` component + +* On the `app` component, we will edit the component so that it offers buttons to switch components between `video-capture` and `image-capture`. + +* In `app.component.html`, add the following code. + +```html + +
+
+

Hello World for Angular

+
+
+ + +
+ @if (mode === 'video') { + + } @else { + + } +
+``` + +* In `app.component.ts`, add the following code. For our stylesheet (CSS) specification, please refer to our [source code](#Official-Sample). + +```ts +/* /src/app/app.component.ts */ +import { Component } from '@angular/core'; +import { NgStyle } from '@angular/common'; + +import { ImageCaptureComponent } from './image-capture/image-capture.component'; +import { VideoCaptureComponent } from './video-capture/video-capture.component'; + +@Component({ + selector: 'app-root', + standalone: true, + templateUrl: './app.component.html', + styleUrl: './app.component.css', + imports: [NgStyle, ImageCaptureComponent, VideoCaptureComponent], +}) +export class AppComponent { + title = 'dbrjs-angular-sample'; + + mode: string = 'video'; + + switchMode(value: string) { + this.mode = value; + } +} +``` + +* Try running the project. + +```cmd +ng serve +``` + +If you followed all the steps correctly, you will have a working page that turns one of the cameras hooked to or built in your computer or mobile device into a barcode scanner. Also, if you want to decode a local image, just click the `Decode Image` button and select the image you want to decode. Once barcodes are found, the results will show in a dialog. + +## Code scaffolding + +Run `ng generate component component-name` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module`. + +## Build + +Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory. + +## Running unit tests + +Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io). + +## Running end-to-end tests + +Run `ng e2e` to execute the end-to-end tests via a platform of your choice. To use this command, you need to first add a package that implements end-to-end testing capabilities. + +## Further help - Angular + +To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI Overview and Command Reference](https://angular.io/cli) page. + +## Support + +If you have any questions, feel free to [contact Dynamsoft Support](https://www.dynamsoft.com/company/contact?utm_source=sampleReadme). diff --git a/frameworks/angular/scan-using-foundational-api/angular.json b/frameworks/angular/angular.json similarity index 100% rename from frameworks/angular/scan-using-foundational-api/angular.json rename to frameworks/angular/angular.json diff --git a/frameworks/angular/scan-using-foundational-api/package.json b/frameworks/angular/package.json similarity index 56% rename from frameworks/angular/scan-using-foundational-api/package.json rename to frameworks/angular/package.json index 5a5a398d..a9333437 100644 --- a/frameworks/angular/scan-using-foundational-api/package.json +++ b/frameworks/angular/package.json @@ -10,23 +10,23 @@ }, "private": true, "dependencies": { - "@angular/animations": "19.2.19", - "@angular/common": "19.2.19", - "@angular/compiler": "19.2.19", - "@angular/core": "19.2.19", - "@angular/forms": "19.2.19", - "@angular/platform-browser": "19.2.19", - "@angular/platform-browser-dynamic": "19.2.19", - "@angular/router": "19.2.19", - "dynamsoft-barcode-reader-bundle": "11.2.4000", + "@angular/animations": "19.2.20", + "@angular/common": "19.2.20", + "@angular/compiler": "19.2.20", + "@angular/core": "19.2.20", + "@angular/forms": "19.2.20", + "@angular/platform-browser": "19.2.20", + "@angular/platform-browser-dynamic": "19.2.20", + "@angular/router": "19.2.20", + "dynamsoft-barcode-reader-bundle": "11.4.2000", "rxjs": "~7.8.0", "tslib": "^2.3.0", "zone.js": "~0.15.0" }, "devDependencies": { - "@angular-devkit/build-angular": "19.2.19", - "@angular/cli": "19.2.19", - "@angular/compiler-cli": "19.2.19", + "@angular-devkit/build-angular": "19.2.20", + "@angular/cli": "19.2.20", + "@angular/compiler-cli": "19.2.20", "@types/jasmine": "~5.1.0", "jasmine-core": "~5.1.0", "karma": "~6.4.0", diff --git a/frameworks/angular/scan-using-foundational-api/README.md b/frameworks/angular/scan-using-foundational-api/README.md deleted file mode 100644 index 7a922945..00000000 --- a/frameworks/angular/scan-using-foundational-api/README.md +++ /dev/null @@ -1,422 +0,0 @@ -# Hello World Sample for Angular - -[Angular](https://angular.dev/) is one of the most popular and mature JavaScript frameworks. Follow this guide to learn how to implement [Dynamsoft Barcode Reader JavaScript SDK](https://www.dynamsoft.com/barcode-reader/sdk-javascript/) (hereafter called "the library") into an Angular application. Note that in this sample, `TypeScript` is used. - -In this guide, we will be using [`dynamsoft-barcode-reader-bundle 11.2.4000`](https://www.npmjs.com/package/dynamsoft-barcode-reader-bundle/v/11.2.4000). - -> Note: -> -> If you’re looking to integrate DBR-JS into a framework that we don't yet have a sample, don't worry! We have a [comprehensive guide](https://www.dynamsoft.com/barcode-reader/docs/web/programming/javascript/user-guide/use-in-framework.html) that provides detailed instruction and best practices for a seamless integration into any frameworks! -> -> Additionally, we're here to help! Please don't hesitate to [contact us](#Support) for any support or questions you might have. - -## Official sample - -* Hello World in Angular - Source Code - -## Preparation -Make sure you have [node](https://nodejs.org/) and [Angular CLI](https://cli.angular.io/) installed. - -This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 17.3.7. - -## Quick Start - -1. Install project dependencies - -```cmd -npm install -``` - -2. Build and serve the Angular app - -```cmd -ng serve -``` - -Then open `https://localhost:4200/` to view the sample app. - -## Creating the sample project - -In this section, we will be creating an Angular application utilizing the Dynamsoft Barcode Reader bundle sdk. - -We'll be exploring how you could create a page that not only enables barcode scanning via a webcam or a built-in camera, but also decode barcodes from local images. - -By the end of this guide, you'll have a good understanding of the SDK and be ready to discover more ways to use it! - -### Create an [Angular](https://angular.dev) Application bootstrapped with [Angular CLI](https://cli.angular.io/) -```cmd -ng new my-app -``` - -On installation, you will be prompted to configure your project.\ -You can customize these options according to your preferences.\ -Below is the configuration used for this sample. - -``` -? Which stylesheet format would you like to use? CSS -? Do you want to enable Server-Side Rendering (SSR) and Static Site Generation (SSG/Prerendering)? No -``` - -### **CD** to the root directory of the application and install necessary libraries - -```cmd -cd my-app -npm install dynamsoft-barcode-reader-bundle@11.2.4000 -E -``` - -## Start to implement - -### Add file "dynamsoft.config.ts" at the root of the app to configure libraries - -```typescript -/* /dynamsoft.config.ts */ -import { CoreModule } from 'dynamsoft-core'; -import { LicenseManager } from 'dynamsoft-license'; -import 'dynamsoft-barcode-reader'; - -// Configures the paths where the .wasm files and other necessary resources for modules are located. -CoreModule.engineResourcePaths.rootDirectory = "https://cdn.jsdelivr.net/npm/"; - -/** LICENSE ALERT - README - * To use the library, you need to first specify a license key using the API "initLicense()" as shown below. - */ - -LicenseManager.initLicense('DLS2eyJvcmdhbml6YXRpb25JRCI6IjIwMDAwMSJ9', true); - -/** - * You can visit https://www.dynamsoft.com/customer/license/trialLicense?utm_source=samples&product=dbr&package=js to get your own trial license good for 30 days. - * Note that if you downloaded this sample from Dynamsoft while logged in, the above license key may already be your own 30-day trial license. - * For more information, see https://www.dynamsoft.com/barcode-reader/docs/web/programming/javascript/user-guide/index.html?ver=11.2.4000&cVer=true#specify-the-license&utm_source=samples or contact support@dynamsoft.com. - * LICENSE ALERT - THE END - */ - -// Optional. Preload .wasm file for reading barcodes. It will save time on the initial decoding by skipping the resource loading. -CoreModule.loadWasm(); -``` - -> Note: -> -> * `initLicense()` specify a license key to use the library. You can visit https://www.dynamsoft.com/customer/license/trialLicense?utm_source=sample&product=dbr&package=js to get your own trial license good for 30 days. -> * `engineResourcePaths` tells the library where to get the necessary resources at runtime. - -### Generate and edit the `video-capture` component - -* Generate the `video-capture`. The `video-capture` component helps decode barcodes via camera. - -```cmd -ng generate component video-capture -``` - -* In `video-capture.component.html`, add code to setup the component's HTML - -```html - -
-
-Results: -
{{resultText}}
-``` - -* In `video-capture.component.ts`, add code for initializing and destroying some instances. For our stylesheet (CSS) specification, please refer to our [source code](#Official-Sample). - -```ts -/* /src/app/video-capture/video-capture.component.ts */ -import { Component, ElementRef, ViewChild } from '@angular/core'; -import '../dynamsoft.config'; -import { CameraEnhancer, CameraView } from 'dynamsoft-camera-enhancer'; -import { CaptureVisionRouter } from 'dynamsoft-capture-vision-router'; -import { MultiFrameResultCrossFilter } from 'dynamsoft-utility'; - -const componentDestroyedErrorMsg = 'VideoCapture Component Destroyed'; - -@Component({ - selector: 'app-video-capture', - templateUrl: './video-capture.component.html', - styleUrls: ['./video-capture.component.css'], - standalone: true, -}) -export class VideoCaptureComponent { - @ViewChild('cameraViewContainer') cameraViewContainer?: ElementRef; - resultText = ""; - - resolveInit?: () => void; - pInit: Promise = new Promise((r) => { - this.resolveInit = r; - }); - isDestroyed = false; - - cvRouter?: CaptureVisionRouter; - cameraEnhancer?: CameraEnhancer; - - async ngAfterViewInit(): Promise { - try { - // Create a `CameraEnhancer` instance for camera control and a `CameraView` instance for UI control. - const cameraView = await CameraView.createInstance(); - if (this.isDestroyed) { - throw Error(componentDestroyedErrorMsg); - } // Check if component is destroyed after every async - this.cameraEnhancer = await CameraEnhancer.createInstance(cameraView); - if (this.isDestroyed) { - throw Error(componentDestroyedErrorMsg); - } - - // Get default UI and append it to DOM. - this.cameraViewContainer!.nativeElement.append(cameraView.getUIElement()); - - // Create a `CaptureVisionRouter` instance and set `CameraEnhancer` instance as its image source. - this.cvRouter = await CaptureVisionRouter.createInstance(); - if (this.isDestroyed) { - throw Error(componentDestroyedErrorMsg); - } - this.cvRouter.setInput(this.cameraEnhancer); - - // Define a callback for results. - this.cvRouter.addResultReceiver({ - onDecodedBarcodesReceived: (result) => { - if (!result.barcodeResultItems.length) return; - - this.resultText = ''; - console.log(result); - for (let item of result.barcodeResultItems) { - this.resultText += `${item.formatString}: ${item.text}\n\n`; - } - }, - }); - - // Filter out unchecked and duplicate results. - const filter = new MultiFrameResultCrossFilter(); - // Filter out unchecked barcodes. - filter.enableResultCrossVerification('barcode', true); - // Filter out duplicate barcodes within 3 seconds. - filter.enableResultDeduplication('barcode', true); - await this.cvRouter.addResultFilter(filter); - if (this.isDestroyed) { - throw Error(componentDestroyedErrorMsg); - } - - // Open camera and start scanning single barcode. - await this.cameraEnhancer.open(); - cameraView.setScanLaserVisible(true); - if (this.isDestroyed) { - throw Error(componentDestroyedErrorMsg); - } - await this.cvRouter.startCapturing('ReadSingleBarcode'); - if (this.isDestroyed) { - throw Error(componentDestroyedErrorMsg); - } - } catch (ex: any) { - if ((ex as Error)?.message === componentDestroyedErrorMsg) { - console.log(componentDestroyedErrorMsg); - } else { - let errMsg = ex.message || ex; - console.error(ex); - alert(errMsg); - } - } - - // Resolve pInit promise once initialization is complete. - this.resolveInit!(); - } - - // dispose cvRouter when it's no longer needed - async ngOnDestroy() { - this.isDestroyed = true; - try { - // Wait for the pInit to complete before disposing resources. - await this.pInit; - this.cvRouter?.dispose(); - this.cameraEnhancer?.dispose(); - } catch (_) {} - } -} -``` -> Note: -> -> If you're looking to customize the UI, the UI customization feature are provided by the auxiliary SDK "Dynamsoft Camera Enhancer". For more details, refer to our [User Guide](https://www.dynamsoft.com/barcode-reader/docs/web/programming/javascript/user-guide/index.html#customizing-the-ui) - - -### Generate and edit the `image-capture` component - -* Generate the `image-capture`. The `image-capture` component helps decode barcodes in an image. - -```cmd -ng generate component image-capture -``` - -* In `image-capture.component.html`, add code to setup the component's HTML - -```html - -
-
- -
-
{{resultText}}
-
-``` - -* In `image-capture.component.ts`, add code for initializing and destroying some instances. For our stylesheet (CSS) specification, please refer to our [source code](#Official-Sample). - -```ts -/* /src/app/image-capture/image-capture.component.ts */ -import { Component, ViewChild, ElementRef } from '@angular/core'; -import '../dynamsoft.config'; -import { EnumCapturedResultItemType } from 'dynamsoft-core'; -import type { BarcodeResultItem } from 'dynamsoft-barcode-reader'; -import { CaptureVisionRouter } from 'dynamsoft-capture-vision-router'; - -@Component({ - selector: 'app-image-capture', - templateUrl: './image-capture.component.html', - styleUrls: ['./image-capture.component.css'], - standalone: true, -}) -export class ImageCaptureComponent { - resultText = ""; - - pCvRouter?: Promise; - isDestroyed = false; - - captureImage = async (e: Event) => { - let files = [...((e.target! as HTMLInputElement).files as any as File[])]; - (e.target! as HTMLInputElement).value = ''; // reset input - this.resultText = ''; - try { - // ensure cvRouter is created only once - const cvRouter = await (this.pCvRouter = - this.pCvRouter || CaptureVisionRouter.createInstance()); - if (this.isDestroyed) return; - - for (let file of files) { - // Decode selected image with 'ReadBarcodes_ReadRateFirst' template. - const result = await cvRouter.capture(file, 'ReadBarcodes_ReadRateFirst'); - console.log(result); - if (this.isDestroyed) return; - - // Print file name if there's multiple files - if (files.length > 1) { - this.resultText += `\n${file.name}:\n`; - } - for (let _item of result.items) { - if (_item.type !== EnumCapturedResultItemType.CRIT_BARCODE) { - continue; // check if captured result item is a barcode - } - let item = _item as BarcodeResultItem; - this.resultText += item.text + '\n'; // output the decoded barcode text - } - // If no items are found, display that no barcode was detected - if (!result.items.length) - this.resultText += - 'No barcode found\n'; - } - } catch (ex: any) { - let errMsg = ex.message || ex; - console.error(ex); - alert(errMsg); - } - }; - - // dispose cvRouter when it's no longer needed - async ngOnDestroy() { - this.isDestroyed = true; - if (this.pCvRouter) { - try { - (await this.pCvRouter).dispose(); - } catch (_) {} - } - } -} -``` - -### Add the `video-capture` and `image-capture` component to the `app` component - -* On the `app` component, we will edit the component so that it offers buttons to switch components between `video-capture` and `image-capture`. - -* In `app.component.html`, add the following code. - -```html - -
-
-

Hello World for Angular

-
-
- - -
- @if (mode === 'video') { - - } @else { - - } -
-``` - -* In `app.component.ts`, add the following code. For our stylesheet (CSS) specification, please refer to our [source code](#Official-Sample). - -```ts -/* /src/app/app.component.ts */ -import { Component } from '@angular/core'; -import { NgStyle } from '@angular/common'; - -import { ImageCaptureComponent } from './image-capture/image-capture.component'; -import { VideoCaptureComponent } from './video-capture/video-capture.component'; - -@Component({ - selector: 'app-root', - standalone: true, - templateUrl: './app.component.html', - styleUrl: './app.component.css', - imports: [NgStyle, ImageCaptureComponent, VideoCaptureComponent], -}) -export class AppComponent { - title = 'dbrjs-angular-sample'; - - mode: string = 'video'; - - switchMode(value: string) { - this.mode = value; - } -} -``` - -* Try running the project. - -```cmd -ng serve -``` - -If you followed all the steps correctly, you will have a working page that turns one of the cameras hooked to or built in your computer or mobile device into a barcode scanner. Also, if you want to decode a local image, just click the `Decode Image` button and select the image you want to decode. Once barcodes are found, the results will show in a dialog. - -## Code scaffolding - -Run `ng generate component component-name` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module`. - -## Build - -Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory. - -## Running unit tests - -Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io). - -## Running end-to-end tests - -Run `ng e2e` to execute the end-to-end tests via a platform of your choice. To use this command, you need to first add a package that implements end-to-end testing capabilities. - -## Further help - Angular - -To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI Overview and Command Reference](https://angular.io/cli) page. - -## Support - -If you have any questions, feel free to [contact Dynamsoft Support](https://www.dynamsoft.com/company/contact?utm_source=sampleReadme). diff --git a/frameworks/angular/scan-using-rtu-api/.editorconfig b/frameworks/angular/scan-using-rtu-api/.editorconfig deleted file mode 100644 index f166060d..00000000 --- a/frameworks/angular/scan-using-rtu-api/.editorconfig +++ /dev/null @@ -1,17 +0,0 @@ -# Editor configuration, see https://editorconfig.org -root = true - -[*] -charset = utf-8 -indent_style = space -indent_size = 2 -insert_final_newline = true -trim_trailing_whitespace = true - -[*.ts] -quote_type = single -ij_typescript_use_double_quotes = false - -[*.md] -max_line_length = off -trim_trailing_whitespace = false diff --git a/frameworks/angular/scan-using-rtu-api/.gitignore b/frameworks/angular/scan-using-rtu-api/.gitignore deleted file mode 100644 index cc7b1413..00000000 --- a/frameworks/angular/scan-using-rtu-api/.gitignore +++ /dev/null @@ -1,42 +0,0 @@ -# See https://docs.github.com/get-started/getting-started-with-git/ignoring-files for more about ignoring files. - -# Compiled output -/dist -/tmp -/out-tsc -/bazel-out - -# Node -/node_modules -npm-debug.log -yarn-error.log - -# IDEs and editors -.idea/ -.project -.classpath -.c9/ -*.launch -.settings/ -*.sublime-workspace - -# Visual Studio Code -.vscode/* -!.vscode/settings.json -!.vscode/tasks.json -!.vscode/launch.json -!.vscode/extensions.json -.history/* - -# Miscellaneous -/.angular/cache -.sass-cache/ -/connect.lock -/coverage -/libpeerconnection.log -testem.log -/typings - -# System files -.DS_Store -Thumbs.db diff --git a/frameworks/angular/scan-using-rtu-api/README.md b/frameworks/angular/scan-using-rtu-api/README.md deleted file mode 100644 index 2e7d55c7..00000000 --- a/frameworks/angular/scan-using-rtu-api/README.md +++ /dev/null @@ -1,33 +0,0 @@ -# 📦 Scan Single Barcode - Angular - -This sample shows how to integrate the `BarcodeScanner` from the [Dynamsoft Barcode Reader JavaScript SDK](https://www.dynamsoft.com/barcode-reader/sdk-javascript/) in an **Angular** project for scanning a single barcode from live video. - -## ✨ Features - -- Easy integration with pre-built UI -- BarcodeScanner initialized in Angular component -- Scans one barcode at a time from video - -## 🚀 Quick Start - -### 1. Install Dependencies - -```bash -npm install -``` - -### 2. Run the App - -```bash -npm run start -``` - -Then open your browser at http://localhost:4200 to view the sample app. - -## 📌 Customization - -Please check the official [documentation](https://dynamsoft.com/barcode-reader/docs/web/programming/javascript/user-guide/barcode-scanner-customization.html). - -## 📄 Support - -If you have any questions, feel free to [contact Dynamsoft Support](https://www.dynamsoft.com/company/contact?utm_source=sampleReadme). diff --git a/frameworks/angular/scan-using-rtu-api/angular.json b/frameworks/angular/scan-using-rtu-api/angular.json deleted file mode 100644 index 60a82d23..00000000 --- a/frameworks/angular/scan-using-rtu-api/angular.json +++ /dev/null @@ -1,100 +0,0 @@ -{ - "$schema": "./node_modules/@angular/cli/lib/config/schema.json", - "version": 1, - "newProjectRoot": "projects", - "projects": { - "angular": { - "projectType": "application", - "schematics": {}, - "root": "", - "sourceRoot": "src", - "prefix": "app", - "architect": { - "build": { - "builder": "@angular-devkit/build-angular:application", - "options": { - "outputPath": "dist/angular", - "index": "src/index.html", - "browser": "src/main.ts", - "polyfills": [ - "zone.js" - ], - "tsConfig": "tsconfig.app.json", - "assets": [ - { - "glob": "**/*", - "input": "public" - } - ], - "styles": [ - "src/styles.css" - ], - "scripts": [], - "baseHref": "./" - }, - "configurations": { - "production": { - "budgets": [ - { - "type": "initial", - "maximumWarning": "1000kb", - "maximumError": "1MB" - }, - { - "type": "anyComponentStyle", - "maximumWarning": "4kB", - "maximumError": "8kB" - } - ], - "outputHashing": "all" - }, - "development": { - "optimization": false, - "extractLicenses": false, - "sourceMap": true - } - }, - "defaultConfiguration": "production" - }, - "serve": { - "builder": "@angular-devkit/build-angular:dev-server", - "configurations": { - "production": { - "buildTarget": "angular:build:production" - }, - "development": { - "buildTarget": "angular:build:development" - } - }, - "defaultConfiguration": "development" - }, - "extract-i18n": { - "builder": "@angular-devkit/build-angular:extract-i18n" - }, - "test": { - "builder": "@angular-devkit/build-angular:karma", - "options": { - "polyfills": [ - "zone.js", - "zone.js/testing" - ], - "tsConfig": "tsconfig.spec.json", - "assets": [ - { - "glob": "**/*", - "input": "public" - } - ], - "styles": [ - "src/styles.css" - ], - "scripts": [] - } - } - } - } - }, - "cli": { - "analytics": false - } -} diff --git a/frameworks/angular/scan-using-rtu-api/package.json b/frameworks/angular/scan-using-rtu-api/package.json deleted file mode 100644 index 63ed4f23..00000000 --- a/frameworks/angular/scan-using-rtu-api/package.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "name": "angular", - "version": "0.0.0", - "scripts": { - "ng": "ng", - "start": "ng serve", - "build": "ng build", - "watch": "ng build --watch --configuration development" - }, - "private": true, - "dependencies": { - "@angular/common": "19.2.18", - "@angular/compiler": "19.2.18", - "@angular/core": "19.2.18", - "@angular/forms": "19.2.18", - "@angular/platform-browser": "19.2.18", - "@angular/platform-browser-dynamic": "19.2.18", - "@angular/router": "19.2.18", - "dynamsoft-barcode-reader-bundle": "11.2.4000", - "rxjs": "~7.8.0", - "tslib": "^2.3.0", - "zone.js": "~0.15.0" - }, - "devDependencies": { - "@angular-devkit/build-angular": "19.2.8", - "@angular/cli": "19.2.8", - "@angular/compiler-cli": "19.2.18", - "@types/jasmine": "~5.1.0", - "jasmine-core": "~5.6.0", - "karma": "~6.4.0", - "karma-chrome-launcher": "~3.2.0", - "karma-coverage": "~2.2.0", - "karma-jasmine": "~5.1.0", - "karma-jasmine-html-reporter": "~2.1.0", - "typescript": "~5.7.2" - } -} diff --git a/frameworks/angular/scan-using-rtu-api/src/app/app.component.css b/frameworks/angular/scan-using-rtu-api/src/app/app.component.css deleted file mode 100644 index 517d4fd3..00000000 --- a/frameworks/angular/scan-using-rtu-api/src/app/app.component.css +++ /dev/null @@ -1,23 +0,0 @@ -.barcode-scanner-hello-world-page { - width: 100%; - height: 100%; -} - -.barcode-scanner-title { - height: 90px; - display: flex; - justify-content: center; - align-items: center; - padding: 20px 0; -} - -.barcode-scanner-title .barcode-scanner-title-logo { - width: 40px; - height: 40px; - margin-left: 10px; -} - -.barcode-scanner-view { - width: 100%; - height: calc(100% - 90px); -} diff --git a/frameworks/angular/scan-using-rtu-api/src/app/app.component.html b/frameworks/angular/scan-using-rtu-api/src/app/app.component.html deleted file mode 100644 index 1e505568..00000000 --- a/frameworks/angular/scan-using-rtu-api/src/app/app.component.html +++ /dev/null @@ -1,7 +0,0 @@ -
-
-

Hello World for Angular

-
- -
-
diff --git a/frameworks/angular/scan-using-rtu-api/src/app/app.component.ts b/frameworks/angular/scan-using-rtu-api/src/app/app.component.ts deleted file mode 100644 index 81a700ed..00000000 --- a/frameworks/angular/scan-using-rtu-api/src/app/app.component.ts +++ /dev/null @@ -1,63 +0,0 @@ -import { Component, ElementRef, ViewChild } from '@angular/core'; -import { BarcodeScanner, BarcodeScannerConfig, EnumScanMode } from 'dynamsoft-barcode-reader-bundle'; - -@Component({ - selector: 'app-root', - templateUrl: './app.component.html', - styleUrl: './app.component.css' -}) - -export class AppComponent { - title = 'angular'; - barcodeScanner: BarcodeScanner | null = null; - - @ViewChild('barcodeScannerViewRef') barcodeScannerViewRef!: ElementRef; - - async ngAfterViewInit(): Promise { - // Configuration object for initializing the BarcodeScanner instance - const config: BarcodeScannerConfig = { - license: "DLS2eyJvcmdhbml6YXRpb25JRCI6IjIwMDAwMSJ9", // Replace with your Dynamsoft license key - - // Specify where to render the scanner UI - // If container is not specified, the UI will take up the full screen - container: this.barcodeScannerViewRef.nativeElement, - - // Specify the path for the definition file "barcode-scanner.ui.xml" for the scanner view. - uiPath: "https://cdn.jsdelivr.net/npm/dynamsoft-barcode-reader-bundle@11.2.4000/dist/ui/barcode-scanner.ui.xml", - - /* - scanMode controls the scanning behavior: - - SM_MULTI_UNIQUE: Continuously scans and collects each unique barcode. - - SM_SINGLE: Stops scanning after the first barcode is detected. - */ - scanMode: EnumScanMode.SM_MULTI_UNIQUE, - - // showUploadImageButton: true, - // scannerViewConfig: { - // showFlashButton: true, - // cameraSwitchControl: "toggleFrontBack", - // }, - - // Specify custom paths for the engine resources - engineResourcePaths: { - rootDirectory: "https://cdn.jsdelivr.net/npm/", - }, - - // The watermark can be removed via showPoweredByDynamsoft configuration option. - // showPoweredByDynamsoft: false, - } - - // Create an instance of the BarcodeScanner with the provided configuration - this.barcodeScanner = new BarcodeScanner(config); - - // Launch the scanner; once a barcode is detected, display its text in an alert - let result = await this.barcodeScanner.launch(); - if (result.barcodeResults.length) { - alert(result.barcodeResults[0].text); - } - } - async ngOnDestroy(): Promise { - // Dispose of the barcode scanner when the component unmounts - this.barcodeScanner?.dispose(); - } -} diff --git a/frameworks/angular/scan-using-rtu-api/src/app/app.config.ts b/frameworks/angular/scan-using-rtu-api/src/app/app.config.ts deleted file mode 100644 index a1e7d6f8..00000000 --- a/frameworks/angular/scan-using-rtu-api/src/app/app.config.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { ApplicationConfig, provideZoneChangeDetection } from '@angular/core'; -import { provideRouter } from '@angular/router'; - -import { routes } from './app.routes'; - -export const appConfig: ApplicationConfig = { - providers: [provideZoneChangeDetection({ eventCoalescing: true }), provideRouter(routes)] -}; diff --git a/frameworks/angular/scan-using-rtu-api/src/app/app.routes.ts b/frameworks/angular/scan-using-rtu-api/src/app/app.routes.ts deleted file mode 100644 index dc39edb5..00000000 --- a/frameworks/angular/scan-using-rtu-api/src/app/app.routes.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { Routes } from '@angular/router'; - -export const routes: Routes = []; diff --git a/frameworks/angular/scan-using-rtu-api/src/index.html b/frameworks/angular/scan-using-rtu-api/src/index.html deleted file mode 100644 index bae20c6b..00000000 --- a/frameworks/angular/scan-using-rtu-api/src/index.html +++ /dev/null @@ -1,12 +0,0 @@ - - - - - Dynamsoft Barcode Reader Sample - Hello World (Decode via Camera) - - - - - - - diff --git a/frameworks/angular/scan-using-rtu-api/src/main.ts b/frameworks/angular/scan-using-rtu-api/src/main.ts deleted file mode 100644 index 35b00f34..00000000 --- a/frameworks/angular/scan-using-rtu-api/src/main.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { bootstrapApplication } from '@angular/platform-browser'; -import { appConfig } from './app/app.config'; -import { AppComponent } from './app/app.component'; - -bootstrapApplication(AppComponent, appConfig) - .catch((err) => console.error(err)); diff --git a/frameworks/angular/scan-using-rtu-api/src/styles.css b/frameworks/angular/scan-using-rtu-api/src/styles.css deleted file mode 100644 index a0583309..00000000 --- a/frameworks/angular/scan-using-rtu-api/src/styles.css +++ /dev/null @@ -1,16 +0,0 @@ -* { - margin: 0; - padding: 0; - box-sizing: border-box; -} - -html, -body { - width: 100%; - height: 100%; -} - -#root { - width: 100%; - height: 100%; -} diff --git a/frameworks/angular/scan-using-rtu-api/tsconfig.app.json b/frameworks/angular/scan-using-rtu-api/tsconfig.app.json deleted file mode 100644 index 3775b37e..00000000 --- a/frameworks/angular/scan-using-rtu-api/tsconfig.app.json +++ /dev/null @@ -1,15 +0,0 @@ -/* To learn more about Typescript configuration file: https://www.typescriptlang.org/docs/handbook/tsconfig-json.html. */ -/* To learn more about Angular compiler options: https://angular.dev/reference/configs/angular-compiler-options. */ -{ - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "./out-tsc/app", - "types": [] - }, - "files": [ - "src/main.ts" - ], - "include": [ - "src/**/*.d.ts" - ] -} diff --git a/frameworks/angular/scan-using-rtu-api/tsconfig.json b/frameworks/angular/scan-using-rtu-api/tsconfig.json deleted file mode 100644 index 5525117c..00000000 --- a/frameworks/angular/scan-using-rtu-api/tsconfig.json +++ /dev/null @@ -1,27 +0,0 @@ -/* To learn more about Typescript configuration file: https://www.typescriptlang.org/docs/handbook/tsconfig-json.html. */ -/* To learn more about Angular compiler options: https://angular.dev/reference/configs/angular-compiler-options. */ -{ - "compileOnSave": false, - "compilerOptions": { - "outDir": "./dist/out-tsc", - "strict": true, - "noImplicitOverride": true, - "noPropertyAccessFromIndexSignature": true, - "noImplicitReturns": true, - "noFallthroughCasesInSwitch": true, - "skipLibCheck": true, - "isolatedModules": true, - "esModuleInterop": true, - "experimentalDecorators": true, - "moduleResolution": "bundler", - "importHelpers": true, - "target": "ES2022", - "module": "ES2022" - }, - "angularCompilerOptions": { - "enableI18nLegacyMessageIdFormat": false, - "strictInjectionParameters": true, - "strictInputAccessModifiers": true, - "strictTemplates": true - } -} diff --git a/frameworks/angular/scan-using-rtu-api/tsconfig.spec.json b/frameworks/angular/scan-using-rtu-api/tsconfig.spec.json deleted file mode 100644 index 5fb748d9..00000000 --- a/frameworks/angular/scan-using-rtu-api/tsconfig.spec.json +++ /dev/null @@ -1,15 +0,0 @@ -/* To learn more about Typescript configuration file: https://www.typescriptlang.org/docs/handbook/tsconfig-json.html. */ -/* To learn more about Angular compiler options: https://angular.dev/reference/configs/angular-compiler-options. */ -{ - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "./out-tsc/spec", - "types": [ - "jasmine" - ] - }, - "include": [ - "src/**/*.spec.ts", - "src/**/*.d.ts" - ] -} diff --git a/frameworks/angular/scan-using-foundational-api/src/app/app.component.css b/frameworks/angular/src/app/app.component.css similarity index 100% rename from frameworks/angular/scan-using-foundational-api/src/app/app.component.css rename to frameworks/angular/src/app/app.component.css diff --git a/frameworks/angular/scan-using-foundational-api/src/app/app.component.html b/frameworks/angular/src/app/app.component.html similarity index 100% rename from frameworks/angular/scan-using-foundational-api/src/app/app.component.html rename to frameworks/angular/src/app/app.component.html diff --git a/frameworks/angular/scan-using-foundational-api/src/app/app.component.ts b/frameworks/angular/src/app/app.component.ts similarity index 100% rename from frameworks/angular/scan-using-foundational-api/src/app/app.component.ts rename to frameworks/angular/src/app/app.component.ts diff --git a/frameworks/angular/scan-using-foundational-api/src/app/dynamsoft.config.ts b/frameworks/angular/src/app/dynamsoft.config.ts similarity index 92% rename from frameworks/angular/scan-using-foundational-api/src/app/dynamsoft.config.ts rename to frameworks/angular/src/app/dynamsoft.config.ts index e4246de0..dec0617b 100644 --- a/frameworks/angular/scan-using-foundational-api/src/app/dynamsoft.config.ts +++ b/frameworks/angular/src/app/dynamsoft.config.ts @@ -7,12 +7,12 @@ CoreModule.engineResourcePaths.rootDirectory = 'https://cdn.jsdelivr.net/npm/'; * To use the library, you need to first specify a license key using the API "initLicense()" as shown below. */ -LicenseManager.initLicense('DLS2eyJvcmdhbml6YXRpb25JRCI6IjIwMDAwMSJ9', { executeNow: true }); +LicenseManager.initLicense('DLS2eyJvcmdhbml6YXRpb25JRCI6IjIwMDAwMSJ9'); /** * You can visit https://www.dynamsoft.com/customer/license/trialLicense?utm_source=samples&product=dbr&package=js to get your own trial license good for 30 days. * Note that if you downloaded this sample from Dynamsoft while logged in, the above license key may already be your own 30-day trial license. - * For more information, see https://www.dynamsoft.com/barcode-reader/docs/web/programming/javascript/user-guide/index.html?ver=11.2.4000&cVer=true#specify-the-license&utm_source=samples or contact support@dynamsoft.com. + * For more information, see https://www.dynamsoft.com/barcode-reader/docs/web/programming/javascript/user-guide/index.html?ver=11.4.2000&cVer=true#specify-the-license&utm_source=samples or contact support@dynamsoft.com. * LICENSE ALERT - THE END */ diff --git a/frameworks/angular/scan-using-foundational-api/src/app/image-capture/image-capture.component.css b/frameworks/angular/src/app/image-capture/image-capture.component.css similarity index 100% rename from frameworks/angular/scan-using-foundational-api/src/app/image-capture/image-capture.component.css rename to frameworks/angular/src/app/image-capture/image-capture.component.css diff --git a/frameworks/angular/scan-using-foundational-api/src/app/image-capture/image-capture.component.html b/frameworks/angular/src/app/image-capture/image-capture.component.html similarity index 100% rename from frameworks/angular/scan-using-foundational-api/src/app/image-capture/image-capture.component.html rename to frameworks/angular/src/app/image-capture/image-capture.component.html diff --git a/frameworks/angular/scan-using-foundational-api/src/app/image-capture/image-capture.component.ts b/frameworks/angular/src/app/image-capture/image-capture.component.ts similarity index 100% rename from frameworks/angular/scan-using-foundational-api/src/app/image-capture/image-capture.component.ts rename to frameworks/angular/src/app/image-capture/image-capture.component.ts diff --git a/frameworks/angular/scan-using-foundational-api/src/app/video-capture/video-capture.component.css b/frameworks/angular/src/app/video-capture/video-capture.component.css similarity index 100% rename from frameworks/angular/scan-using-foundational-api/src/app/video-capture/video-capture.component.css rename to frameworks/angular/src/app/video-capture/video-capture.component.css diff --git a/frameworks/angular/scan-using-foundational-api/src/app/video-capture/video-capture.component.html b/frameworks/angular/src/app/video-capture/video-capture.component.html similarity index 100% rename from frameworks/angular/scan-using-foundational-api/src/app/video-capture/video-capture.component.html rename to frameworks/angular/src/app/video-capture/video-capture.component.html diff --git a/frameworks/angular/scan-using-foundational-api/src/app/video-capture/video-capture.component.ts b/frameworks/angular/src/app/video-capture/video-capture.component.ts similarity index 98% rename from frameworks/angular/scan-using-foundational-api/src/app/video-capture/video-capture.component.ts rename to frameworks/angular/src/app/video-capture/video-capture.component.ts index 26690ed3..7ac4f50e 100644 --- a/frameworks/angular/scan-using-foundational-api/src/app/video-capture/video-capture.component.ts +++ b/frameworks/angular/src/app/video-capture/video-capture.component.ts @@ -48,7 +48,7 @@ export class VideoCaptureComponent { this.cvRouter.setInput(this.cameraEnhancer); // Define a callback for results. - this.cvRouter.addResultReceiver({ + await this.cvRouter.addResultReceiver({ onDecodedBarcodesReceived: (result) => { if (!result.barcodeResultItems.length) return; console.log(result); diff --git a/frameworks/angular/scan-using-foundational-api/src/assets/.gitkeep b/frameworks/angular/src/assets/.gitkeep similarity index 100% rename from frameworks/angular/scan-using-foundational-api/src/assets/.gitkeep rename to frameworks/angular/src/assets/.gitkeep diff --git a/frameworks/angular/scan-using-foundational-api/src/favicon.ico b/frameworks/angular/src/favicon.ico similarity index 100% rename from frameworks/angular/scan-using-foundational-api/src/favicon.ico rename to frameworks/angular/src/favicon.ico diff --git a/frameworks/angular/scan-using-foundational-api/src/index.html b/frameworks/angular/src/index.html similarity index 82% rename from frameworks/angular/scan-using-foundational-api/src/index.html rename to frameworks/angular/src/index.html index bce6b22f..4e212223 100644 --- a/frameworks/angular/scan-using-foundational-api/src/index.html +++ b/frameworks/angular/src/index.html @@ -11,7 +11,6 @@ content="Dynamsoft Barcode Reader in an Angular Application, helps read barcodes from camera or images." /> - diff --git a/frameworks/angular/scan-using-foundational-api/src/main.ts b/frameworks/angular/src/main.ts similarity index 100% rename from frameworks/angular/scan-using-foundational-api/src/main.ts rename to frameworks/angular/src/main.ts diff --git a/frameworks/angular/scan-using-foundational-api/src/styles.css b/frameworks/angular/src/styles.css similarity index 100% rename from frameworks/angular/scan-using-foundational-api/src/styles.css rename to frameworks/angular/src/styles.css diff --git a/frameworks/angular/scan-using-foundational-api/tsconfig.app.json b/frameworks/angular/tsconfig.app.json similarity index 100% rename from frameworks/angular/scan-using-foundational-api/tsconfig.app.json rename to frameworks/angular/tsconfig.app.json diff --git a/frameworks/angular/scan-using-foundational-api/tsconfig.json b/frameworks/angular/tsconfig.json similarity index 100% rename from frameworks/angular/scan-using-foundational-api/tsconfig.json rename to frameworks/angular/tsconfig.json diff --git a/frameworks/angular/scan-using-foundational-api/tsconfig.spec.json b/frameworks/angular/tsconfig.spec.json similarity index 100% rename from frameworks/angular/scan-using-foundational-api/tsconfig.spec.json rename to frameworks/angular/tsconfig.spec.json diff --git a/frameworks/blazor/scan-using-foundational-api/.gitignore b/frameworks/blazor/.gitignore similarity index 100% rename from frameworks/blazor/scan-using-foundational-api/.gitignore rename to frameworks/blazor/.gitignore diff --git a/frameworks/blazor/README.md b/frameworks/blazor/README.md index f2dc0dec..e49456e1 100644 --- a/frameworks/blazor/README.md +++ b/frameworks/blazor/README.md @@ -1,23 +1,372 @@ -# Blazor samples +# Hello World Sample for Blazor -This directory contains Blazor examples demonstrating how to integrate the Dynamsoft Barcode Reader (JavaScript edition) into Blazor apps. +[Blazor](https://dotnet.microsoft.com/en-us/apps/aspnet/web-apps/blazor) is a framework for building interactive client-side web apps with .NET and C#. Follow this guide to learn how to implement [Dynamsoft Barcode Reader JavaScript SDK](https://www.dynamsoft.com/barcode-reader/sdk-javascript/) (hereafter called "the library") into a Blazor application using [JavaScript Interlop](https://learn.microsoft.com/en-us/aspnet/core/blazor/javascript-interoperability/call-javascript-from-dotnet?view=aspnetcore-8.0#invoke-js-functions). -**Included examples** +In this guide, we will be using [`dynamsoft-barcode-reader-bundle 11.4.2000`](https://www.npmjs.com/package/dynamsoft-barcode-reader-bundle/v/11.4.2000). We also used .NET 8.0 (version 8.0.8) to develop this sample. To ensure the sample app runs properly, please refer to this guide to update your .NET installation - https://learn.microsoft.com/en-us/dotnet/core/install/upgrade. -- scan-using-foundational-api/ — Blazor example with JS interop for video/image decoding. -- scan-using-rtu-api/ — RTU API demo for Blazor. +> Note: +> +> If you're looking to integrate DBR-JS into a framework that we don't yet have a sample, don't worry! We have a [comprehensive guide](https://www.dynamsoft.com/barcode-reader/docs/web/programming/javascript/user-guide/use-in-framework.html) that provides detailed instruction and best practices for a seamless integration into any frameworks! +> +> Additionally, we're here to help! Please don't hesitate to [contact us](#Support) for any support or questions you might have. -## Quick start +## Official Sample -1. Change to a subexample directory, e.g.: +* Hello World in Blazor - Source Code - ```bash - cd scan-using-foundational-api - ``` +## Preparation -2. Follow the subexample README for exact steps (may require dotnet/SDK commands or npm for static assets). +This sample was developed using Visual Studio 2022. For a more in-depth guide on creating a Blazor web application with Visual Studio 2022, please follow Microsoft's tutorial on [Building your first web app with ASP.NET Core using Blazor](https://dotnet.microsoft.com/en-us/learn/aspnet/blazor-tutorial/intro). -## Notes +## Quick Start -- Some examples use JS interop; run the app via dotnet or the provided launch configuration. -- See the repository root README.md for general usage and license information. \ No newline at end of file +1. **Open the application** in Visual Studio 2022 by clicking the `Open a Project or Solution` button, and choosing on the `BlazorApp.csproj` file. + +2. **Run the application** by clicking the `Start Debugging` button (a green arrow) in the Debug Toolbar. + +3. A window should open to view the sample application + +> Note: +> +> This sample uses the packages `Microsoft.AspNetCore.Components.WebAssembly` v8.0.8 and `Microsoft.AspNetCore.Components.WebAssembly.DevServer` v8.0.8 which require .NET v8.0.8. +> Refer to the `BlazorApp.csproj` file to change the versions as needed. + +## Creating the sample project + +In this section, we will be creating a Blazor application utilizing the Dynamsoft Barcode Reader bundle sdk. + +We'll be exploring how you could create a page that not only enables barcode scanning via a webcam or a built-in camera, but also decode barcodes from local images. + +By the end of this guide, you'll have a good understanding of the SDK and be ready to discover more ways to use it! + +### Initialize project + +Please follow the guide created by Microsoft on [Building your first web app with ASP.NET Code using Blazor](https://dotnet.microsoft.com/en-us/learn/aspnet/blazor-tutorial/intro). + +This tutorial will guide you through downloading Visual Studio, and set up needed to create a Blazor Web Application. + +**IMPORTANT**: When creating a new project, please select **"Blazor WebAssembly Standalone App"** instead of "Blazor Web App". + +## Start to implement + +### Create a `DecodeVideo.razor` component under the `Pages\` folder + +In `Pages\DecodeVideo.razor`, we will modify the component to enable barcode decoding via camera. This page will be accessible at the `/video` URL. + +```razor +@page "/video" +@inject IJSRuntime JS + +Dynamsoft Barcode Reader Hello World - Blazor + +

Decode Video

+ + +

Results:

+
+ + +@code { + // reference: https://learn.microsoft.com/en-us/aspnet/core/blazor/javascript-interoperability/call-javascript-from-dotnet?view=aspnetcore-8.0#invoke-js-functions + private string mode = "stop"; + private string videoDecodeBtn = "Decode Video"; + + private async Task ToggleVideoTask() + { + await JS.InvokeVoidAsync("loadDecodeVideoModule"); + + if (mode == "videoDecode") + { + await StopDecodeVideoTask(); + } + else if (mode == "stop") + { + await DecodeVideoTask(); + + } + } + + private async Task DecodeVideoTask() + { + mode = "videoDecode"; + videoDecodeBtn = "Stop Decode"; + await JS.InvokeAsync("startVideoDecode"); + } + + private async Task StopDecodeVideoTask() + { + mode = "stop"; + videoDecodeBtn = "Decode Video"; + await JS.InvokeAsync("stopVideoDecode"); + } +} +``` + +> Note: +> +> We can significantly improve the initial load speed and performance when we dynamically import Dynamsoft's Barcode Scanning component on-demand. In the sample code above, we dynamically imported the decode video module through the line `await JS.InvokeVoidAsync("loadDecodeVideoModule");`. + +### Create a `wwwroot\decodeVideo.js` file + +In `wwwroot\decodeVideo.js`, we will instantiate `cvRouter` and `cameraEnhancer` to start decoding barcodes through the camera. + +Additionally, we'll include a function to clean up `cvRouter` and `cameraEnhancer` when they are no longer needed. + +These functions will be called by the Blazor components through JavaScript Interop. + +Reference: https://learn.microsoft.com/en-us/aspnet/core/blazor/javascript-interoperability/call-javascript-from-dotnet?view=aspnetcore-8.0#invoke-js-functions + +```javascript +// Create JS function "startVideoDecode" +window.startVideoDecode = async () => { + const cameraViewContainer = document.getElementById("camera-view-container"); + const resultsContainer = document.getElementById("results"); + + try { + // Create a `CameraEnhancer` instance for camera control and a `CameraView` instance for UI control. + const cameraView = await Dynamsoft.DCE.CameraView.createInstance(); + cameraEnhancer = await Dynamsoft.DCE.CameraEnhancer.createInstance(cameraView); + // Get default UI and append it to DOM. + cameraViewContainer.style.display = "block" + cameraViewContainer.append(cameraView.getUIElement()); + + // Create a `CaptureVisionRouter` instance and set `CameraEnhancer` instance as its image source. + cvRouter = await Dynamsoft.CVR.CaptureVisionRouter.createInstance(); + cvRouter.setInput(cameraEnhancer); + + // Define a callback for results. + cvRouter.addResultReceiver({ + onDecodedBarcodesReceived: (result) => { + if (!result.barcodeResultItems.length) return; + + resultsContainer.textContent = ""; + for (let item of result.barcodeResultItems) { + resultsContainer.textContent += `${item.formatString}: ${item.text}\n\n`; + } + }, + }); + + // Filter out unchecked and duplicate results. + const filter = new Dynamsoft.Utility.MultiFrameResultCrossFilter(); + // Filter out unchecked barcodes. + filter.enableResultCrossVerification("barcode", true); + // Filter out duplicate barcodes within 3 seconds. + filter.enableResultDeduplication("barcode", true); + await cvRouter.addResultFilter(filter); + + // Open camera and start scanning single barcode. + await cameraEnhancer.open(); + + cameraView.setScanLaserVisible(true); + await cvRouter.startCapturing("ReadSingleBarcode"); + } catch (ex) { + let errMsg = ex.message || ex; + console.error(ex); + } +} + +// Create JS function "stopVideoDecode" +window.stopVideoDecode = async () => { + const cameraViewContainer = document.getElementById("camera-view-container"); + const resultsContainer = document.getElementById("results"); + + try { + if (!cvRouter?.disposed) { + await cvRouter?.dispose(); + } + if (!cameraEnhancer?.disposed) { + await cameraEnhancer?.dispose(); + } + + // Reset components + cameraViewContainer.style.display = "none"; + cameraViewContainer.innerHTML = ""; + resultsContainer.textContent = ""; + } catch (ex) { + let errMsg = ex.message || ex; + console.error(ex); + } +} +``` + +### Create a `Pages\DecodeImage.razor` component + +In `Pages\DecodeImage.razor`, we will modify the component to enable barcode decoding through an image. This page will be accessible at the `/image` URL. + +```razor +@page "/image" +@inject IJSRuntime JS + +Dynamsoft Barcode Reader Hello World - Blazor + +

Decode Image

+ +

Results:

+
+ +@code { + // reference: https://learn.microsoft.com/en-us/aspnet/core/blazor/javascript-interoperability/call-javascript-from-dotnet?view=aspnetcore-8.0#invoke-js-functions + +private async Task DecodeImageTask() + { + // Dynamically load decode image module + await JS.InvokeVoidAsync("loadDecodeImageModule"); + await JS.InvokeAsync("startImageDecode"); + } + + public void Dispose() + { + JS.InvokeAsync("cleanUpImageDecode"); + } +} +``` + +> Note: +> +> We can significantly improve the initial load speed and performance when we dynamically import Dynamsoft's Barcode Scanning component on-demand. In the sample code above, we dynamically imported the decode image module through the line `await JS.InvokeVoidAsync("loadDecodeImageModule");`. + +### Create a `wwwroot\decodeImage.js` file + +In `wwwroot\decodeImage.js`, we will instantiate `cvRouter` to decode barcodes in images. + +These functions will be called by the Blazor components through JavaScript Interop. + +Reference: https://learn.microsoft.com/en-us/aspnet/core/blazor/javascript-interoperability/call-javascript-from-dotnet?view=aspnetcore-8.0#invoke-js-functions + +```javascript +// Create JS function "startImageDecode" +window.startImageDecode = async () => { + const inputElement = document.getElementById("inputElement"); + const resultsContainer = document.getElementById("results"); + resultsContainer.innerText = ""; // Reset results container + + const { files } = inputElement; + + try { + for (let file of files) { + cvRouter = await Dynamsoft.CVR.CaptureVisionRouter.createInstance(); + // Decode selected image with 'ReadBarcodes_SpeedFirst' template. + const result = await cvRouter.capture(file, "ReadBarcodes_SpeedFirst"); + if (files.length > 1) { + resultsContainer.innerText += `\nFile: ${file.name}\n`; + } + for (let item of result.items) { + if (item.type !== Dynamsoft.Core.EnumCapturedResultItemType.CRIT_BARCODE) { + continue; + } + resultsContainer.innerText += item.text + "\n"; + console.log(item.text); + } + if (!result.items.length) resultsContainer.innerText += "No barcode found\n"; + } + } catch (ex) { + let errMsg = ex.message || ex; + console.error(ex); + alert(errMsg); + } finally { + inputElement.value = ""; + await cvRouter?.dispose(); + } +}; +``` + +### Modify the `wwwroot\index.html` file + +Inside the `wwwroot\index.html` file, we will initialize the license and necessary modules for Dynamsoft Barcode Reader and create functions to dynamically load the video and image modules. + +```html + + +... + +
+ ... + + + + + + +``` + +> Note: +> +> * `initLicense()` specify a license key to use the library. You can visit https://www.dynamsoft.com/customer/license/trialLicense?utm_source=sample&product=dbr&package=js to get your own trial license good for 30 days. + + +### Modify the `Layout\NavMenu.razor` and `Layout\NavMenu.razor.css` file + +To make sure the `Decode Video` and `Decode Image` pages are accessible from the sidebar, add the following code block to `Layout\NavMenu.razor`. + +```html +... + + +... +``` + +We'll also add the following CSS code to include the icons for `Decode Video` and `Decode Image` in the `Layout\NavMenu.razor.css` file. + +```css +.bi-video-fill-nav-menu { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='white' class='bi bi-camera-video-fill' viewBox='0 0 16 16'%3E%3Cpath d='M0 5a2 2 0 0 1 2-2h7.5a2 2 0 0 1 1.983 1.738l3.11-1.382A1 1 0 0 1 16 4.269v7.462a1 1 0 0 1-1.406.913l-3.111-1.382A2 2 0 0 1 9.5 13H2a2 2 0 0 1-2-2z'/%3E%3C/svg%3E"); +} + +.bi-image-fill-nav-menu { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='white' class='bi bi-camera-fill' viewBox='0 0 16 16'%3E%3Cpath d='M1.5 2A1.5 1.5 0 0 0 0 3.5v9A1.5 1.5 0 0 0 1.5 14h13a1.5 1.5 0 0 0 1.5-1.5v-9A1.5 1.5 0 0 0 14.5 2zm13 1a.5.5 0 0 1 .5.5v6l-3.775-1.947a.5.5 0 0 0-.577.093l-3.71 3.71-2.66-1.772a.5.5 0 0 0-.63.062L1.002 12v.54L1 12.5v-9a.5.5 0 0 1 .5-.5z'/%3E%3C/svg%3E"); +} +``` + +## Run the application + +We can run the application by clicking the `Start Debugging` button (a green arrow) in the Debug Toolbar. + +If you followed all the steps correctly, you will have a working page that turns one of the cameras hooked to or built in your computer or mobile device into a barcode scanner. Also, if you want to decode a local image, just click the `Decode Image` button and select the image you want to decode. + +## Support + +If you have any questions, feel free to [contact Dynamsoft support](https://www.dynamsoft.com/company/contact?utm_source=sampleReadme). diff --git a/frameworks/blazor/scan-using-foundational-api/hello-world-blazor/BlazorApp/App.razor b/frameworks/blazor/hello-world-blazor/BlazorApp/App.razor similarity index 100% rename from frameworks/blazor/scan-using-foundational-api/hello-world-blazor/BlazorApp/App.razor rename to frameworks/blazor/hello-world-blazor/BlazorApp/App.razor diff --git a/frameworks/blazor/scan-using-foundational-api/hello-world-blazor/BlazorApp/BlazorApp.csproj b/frameworks/blazor/hello-world-blazor/BlazorApp/BlazorApp.csproj similarity index 100% rename from frameworks/blazor/scan-using-foundational-api/hello-world-blazor/BlazorApp/BlazorApp.csproj rename to frameworks/blazor/hello-world-blazor/BlazorApp/BlazorApp.csproj diff --git a/frameworks/blazor/scan-using-foundational-api/hello-world-blazor/BlazorApp/Layout/MainLayout.razor b/frameworks/blazor/hello-world-blazor/BlazorApp/Layout/MainLayout.razor similarity index 100% rename from frameworks/blazor/scan-using-foundational-api/hello-world-blazor/BlazorApp/Layout/MainLayout.razor rename to frameworks/blazor/hello-world-blazor/BlazorApp/Layout/MainLayout.razor diff --git a/frameworks/blazor/scan-using-foundational-api/hello-world-blazor/BlazorApp/Layout/MainLayout.razor.css b/frameworks/blazor/hello-world-blazor/BlazorApp/Layout/MainLayout.razor.css similarity index 100% rename from frameworks/blazor/scan-using-foundational-api/hello-world-blazor/BlazorApp/Layout/MainLayout.razor.css rename to frameworks/blazor/hello-world-blazor/BlazorApp/Layout/MainLayout.razor.css diff --git a/frameworks/blazor/scan-using-foundational-api/hello-world-blazor/BlazorApp/Layout/NavMenu.razor b/frameworks/blazor/hello-world-blazor/BlazorApp/Layout/NavMenu.razor similarity index 100% rename from frameworks/blazor/scan-using-foundational-api/hello-world-blazor/BlazorApp/Layout/NavMenu.razor rename to frameworks/blazor/hello-world-blazor/BlazorApp/Layout/NavMenu.razor diff --git a/frameworks/blazor/scan-using-foundational-api/hello-world-blazor/BlazorApp/Layout/NavMenu.razor.css b/frameworks/blazor/hello-world-blazor/BlazorApp/Layout/NavMenu.razor.css similarity index 100% rename from frameworks/blazor/scan-using-foundational-api/hello-world-blazor/BlazorApp/Layout/NavMenu.razor.css rename to frameworks/blazor/hello-world-blazor/BlazorApp/Layout/NavMenu.razor.css diff --git a/frameworks/blazor/scan-using-foundational-api/hello-world-blazor/BlazorApp/Pages/DecodeImage.razor b/frameworks/blazor/hello-world-blazor/BlazorApp/Pages/DecodeImage.razor similarity index 100% rename from frameworks/blazor/scan-using-foundational-api/hello-world-blazor/BlazorApp/Pages/DecodeImage.razor rename to frameworks/blazor/hello-world-blazor/BlazorApp/Pages/DecodeImage.razor diff --git a/frameworks/blazor/scan-using-foundational-api/hello-world-blazor/BlazorApp/Pages/DecodeVideo.razor b/frameworks/blazor/hello-world-blazor/BlazorApp/Pages/DecodeVideo.razor similarity index 100% rename from frameworks/blazor/scan-using-foundational-api/hello-world-blazor/BlazorApp/Pages/DecodeVideo.razor rename to frameworks/blazor/hello-world-blazor/BlazorApp/Pages/DecodeVideo.razor diff --git a/frameworks/blazor/scan-using-foundational-api/hello-world-blazor/BlazorApp/Pages/Home.razor b/frameworks/blazor/hello-world-blazor/BlazorApp/Pages/Home.razor similarity index 100% rename from frameworks/blazor/scan-using-foundational-api/hello-world-blazor/BlazorApp/Pages/Home.razor rename to frameworks/blazor/hello-world-blazor/BlazorApp/Pages/Home.razor diff --git a/frameworks/blazor/scan-using-foundational-api/hello-world-blazor/BlazorApp/Program.cs b/frameworks/blazor/hello-world-blazor/BlazorApp/Program.cs similarity index 100% rename from frameworks/blazor/scan-using-foundational-api/hello-world-blazor/BlazorApp/Program.cs rename to frameworks/blazor/hello-world-blazor/BlazorApp/Program.cs diff --git a/frameworks/blazor/scan-using-foundational-api/hello-world-blazor/BlazorApp/Properties/launchSettings.json b/frameworks/blazor/hello-world-blazor/BlazorApp/Properties/launchSettings.json similarity index 100% rename from frameworks/blazor/scan-using-foundational-api/hello-world-blazor/BlazorApp/Properties/launchSettings.json rename to frameworks/blazor/hello-world-blazor/BlazorApp/Properties/launchSettings.json diff --git a/frameworks/blazor/scan-using-foundational-api/hello-world-blazor/BlazorApp/_Imports.razor b/frameworks/blazor/hello-world-blazor/BlazorApp/_Imports.razor similarity index 100% rename from frameworks/blazor/scan-using-foundational-api/hello-world-blazor/BlazorApp/_Imports.razor rename to frameworks/blazor/hello-world-blazor/BlazorApp/_Imports.razor diff --git a/frameworks/blazor/scan-using-foundational-api/hello-world-blazor/BlazorApp/wwwroot/css/app.css b/frameworks/blazor/hello-world-blazor/BlazorApp/wwwroot/css/app.css similarity index 100% rename from frameworks/blazor/scan-using-foundational-api/hello-world-blazor/BlazorApp/wwwroot/css/app.css rename to frameworks/blazor/hello-world-blazor/BlazorApp/wwwroot/css/app.css diff --git a/frameworks/blazor/scan-using-foundational-api/hello-world-blazor/BlazorApp/wwwroot/css/bootstrap/bootstrap.min.css b/frameworks/blazor/hello-world-blazor/BlazorApp/wwwroot/css/bootstrap/bootstrap.min.css similarity index 100% rename from frameworks/blazor/scan-using-foundational-api/hello-world-blazor/BlazorApp/wwwroot/css/bootstrap/bootstrap.min.css rename to frameworks/blazor/hello-world-blazor/BlazorApp/wwwroot/css/bootstrap/bootstrap.min.css diff --git a/frameworks/blazor/scan-using-foundational-api/hello-world-blazor/BlazorApp/wwwroot/css/bootstrap/bootstrap.min.css.map b/frameworks/blazor/hello-world-blazor/BlazorApp/wwwroot/css/bootstrap/bootstrap.min.css.map similarity index 100% rename from frameworks/blazor/scan-using-foundational-api/hello-world-blazor/BlazorApp/wwwroot/css/bootstrap/bootstrap.min.css.map rename to frameworks/blazor/hello-world-blazor/BlazorApp/wwwroot/css/bootstrap/bootstrap.min.css.map diff --git a/frameworks/blazor/scan-using-foundational-api/hello-world-blazor/BlazorApp/wwwroot/decodeImage.js b/frameworks/blazor/hello-world-blazor/BlazorApp/wwwroot/decodeImage.js similarity index 100% rename from frameworks/blazor/scan-using-foundational-api/hello-world-blazor/BlazorApp/wwwroot/decodeImage.js rename to frameworks/blazor/hello-world-blazor/BlazorApp/wwwroot/decodeImage.js diff --git a/frameworks/blazor/scan-using-foundational-api/hello-world-blazor/BlazorApp/wwwroot/decodeVideo.js b/frameworks/blazor/hello-world-blazor/BlazorApp/wwwroot/decodeVideo.js similarity index 98% rename from frameworks/blazor/scan-using-foundational-api/hello-world-blazor/BlazorApp/wwwroot/decodeVideo.js rename to frameworks/blazor/hello-world-blazor/BlazorApp/wwwroot/decodeVideo.js index b0b380fc..d50df083 100644 --- a/frameworks/blazor/scan-using-foundational-api/hello-world-blazor/BlazorApp/wwwroot/decodeVideo.js +++ b/frameworks/blazor/hello-world-blazor/BlazorApp/wwwroot/decodeVideo.js @@ -19,7 +19,7 @@ window.startVideoDecode = async () => { cvRouter.setInput(cameraEnhancer); // Define a callback for results. - cvRouter.addResultReceiver({ + await cvRouter.addResultReceiver({ onDecodedBarcodesReceived: (result) => { if (!result.barcodeResultItems.length) return; diff --git a/frameworks/blazor/scan-using-foundational-api/hello-world-blazor/BlazorApp/wwwroot/favicon.png b/frameworks/blazor/hello-world-blazor/BlazorApp/wwwroot/favicon.png similarity index 100% rename from frameworks/blazor/scan-using-foundational-api/hello-world-blazor/BlazorApp/wwwroot/favicon.png rename to frameworks/blazor/hello-world-blazor/BlazorApp/wwwroot/favicon.png diff --git a/frameworks/blazor/scan-using-foundational-api/hello-world-blazor/BlazorApp/wwwroot/icon-192.png b/frameworks/blazor/hello-world-blazor/BlazorApp/wwwroot/icon-192.png similarity index 100% rename from frameworks/blazor/scan-using-foundational-api/hello-world-blazor/BlazorApp/wwwroot/icon-192.png rename to frameworks/blazor/hello-world-blazor/BlazorApp/wwwroot/icon-192.png diff --git a/frameworks/blazor/scan-using-foundational-api/hello-world-blazor/BlazorApp/wwwroot/index.html b/frameworks/blazor/hello-world-blazor/BlazorApp/wwwroot/index.html similarity index 95% rename from frameworks/blazor/scan-using-foundational-api/hello-world-blazor/BlazorApp/wwwroot/index.html rename to frameworks/blazor/hello-world-blazor/BlazorApp/wwwroot/index.html index fd4d7ef1..701cc861 100644 --- a/frameworks/blazor/scan-using-foundational-api/hello-world-blazor/BlazorApp/wwwroot/index.html +++ b/frameworks/blazor/hello-world-blazor/BlazorApp/wwwroot/index.html @@ -28,7 +28,7 @@
- + - - - - - -``` - -> Note: -> -> * `initLicense()` specify a license key to use the library. You can visit https://www.dynamsoft.com/customer/license/trialLicense?utm_source=sample&product=dbr&package=js to get your own trial license good for 30 days. - - -### Modify the `Layout\NavMenu.razor` and `Layout\NavMenu.razor.css` file - -To make sure the `Decode Video` and `Decode Image` pages are accessible from the sidebar, add the following code block to `Layout\NavMenu.razor`. - -```html -... - - -... -``` - -We'll also add the following CSS code to include the icons for `Decode Video` and `Decode Image` in the `Layout\NavMenu.razor.css` file. - -```css -.bi-video-fill-nav-menu { - background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='white' class='bi bi-camera-video-fill' viewBox='0 0 16 16'%3E%3Cpath d='M0 5a2 2 0 0 1 2-2h7.5a2 2 0 0 1 1.983 1.738l3.11-1.382A1 1 0 0 1 16 4.269v7.462a1 1 0 0 1-1.406.913l-3.111-1.382A2 2 0 0 1 9.5 13H2a2 2 0 0 1-2-2z'/%3E%3C/svg%3E"); -} - -.bi-image-fill-nav-menu { - background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='white' class='bi bi-camera-fill' viewBox='0 0 16 16'%3E%3Cpath d='M1.5 2A1.5 1.5 0 0 0 0 3.5v9A1.5 1.5 0 0 0 1.5 14h13a1.5 1.5 0 0 0 1.5-1.5v-9A1.5 1.5 0 0 0 14.5 2zm13 1a.5.5 0 0 1 .5.5v6l-3.775-1.947a.5.5 0 0 0-.577.093l-3.71 3.71-2.66-1.772a.5.5 0 0 0-.63.062L1.002 12v.54L1 12.5v-9a.5.5 0 0 1 .5-.5z'/%3E%3C/svg%3E"); -} -``` - -## Run the application - -We can run the application by clicking the `Start Debugging` button (a green arrow) in the Debug Toolbar. - -If you followed all the steps correctly, you will have a working page that turns one of the cameras hooked to or built in your computer or mobile device into a barcode scanner. Also, if you want to decode a local image, just click the `Decode Image` button and select the image you want to decode. - -## Support - -If you have any questions, feel free to [contact Dynamsoft support](https://www.dynamsoft.com/company/contact?utm_source=sampleReadme). diff --git a/frameworks/blazor/scan-using-rtu-api/.gitignore b/frameworks/blazor/scan-using-rtu-api/.gitignore deleted file mode 100644 index e6c4e46a..00000000 --- a/frameworks/blazor/scan-using-rtu-api/.gitignore +++ /dev/null @@ -1,486 +0,0 @@ -## Ignore Visual Studio temporary files, build results, and -## files generated by popular Visual Studio add-ons. -## -## Get latest from `dotnet new gitignore` - -# dotenv files -.env - -# User-specific files -*.rsuser -*.suo -*.user -*.userosscache -*.sln.docstates - -# User-specific files (MonoDevelop/Xamarin Studio) -*.userprefs - -# Mono auto generated files -mono_crash.* - -# Build results -[Dd]ebug/ -[Dd]ebugPublic/ -[Rr]elease/ -[Rr]eleases/ -x64/ -x86/ -[Ww][Ii][Nn]32/ -[Aa][Rr][Mm]/ -[Aa][Rr][Mm]64/ -bld/ -[Bb]in/ -[Oo]bj/ -[Ll]og/ -[Ll]ogs/ - -# Visual Studio 2015/2017 cache/options directory -.vs/ -# Uncomment if you have tasks that create the project's static files in wwwroot -#wwwroot/ - -# Visual Studio 2017 auto generated files -Generated\ Files/ - -# MSTest test Results -[Tt]est[Rr]esult*/ -[Bb]uild[Ll]og.* - -# NUnit -*.VisualState.xml -TestResult.xml -nunit-*.xml - -# Build Results of an ATL Project -[Dd]ebugPS/ -[Rr]eleasePS/ -dlldata.c - -# Benchmark Results -BenchmarkDotNet.Artifacts/ - -# .NET -project.lock.json -project.fragment.lock.json -artifacts/ - -# Tye -.tye/ - -# ASP.NET Scaffolding -ScaffoldingReadMe.txt - -# StyleCop -StyleCopReport.xml - -# Files built by Visual Studio -*_i.c -*_p.c -*_h.h -*.ilk -*.meta -*.obj -*.iobj -*.pch -*.pdb -*.ipdb -*.pgc -*.pgd -*.rsp -*.sbr -*.tlb -*.tli -*.tlh -*.tmp -*.tmp_proj -*_wpftmp.csproj -*.log -*.tlog -*.vspscc -*.vssscc -.builds -*.pidb -*.svclog -*.scc - -# Chutzpah Test files -_Chutzpah* - -# Visual C++ cache files -ipch/ -*.aps -*.ncb -*.opendb -*.opensdf -*.sdf -*.cachefile -*.VC.db -*.VC.VC.opendb - -# Visual Studio profiler -*.psess -*.vsp -*.vspx -*.sap - -# Visual Studio Trace Files -*.e2e - -# TFS 2012 Local Workspace -$tf/ - -# Guidance Automation Toolkit -*.gpState - -# ReSharper is a .NET coding add-in -_ReSharper*/ -*.[Rr]e[Ss]harper -*.DotSettings.user - -# TeamCity is a build add-in -_TeamCity* - -# DotCover is a Code Coverage Tool -*.dotCover - -# AxoCover is a Code Coverage Tool -.axoCover/* -!.axoCover/settings.json - -# Coverlet is a free, cross platform Code Coverage Tool -coverage*.json -coverage*.xml -coverage*.info - -# Visual Studio code coverage results -*.coverage -*.coveragexml - -# NCrunch -_NCrunch_* -.*crunch*.local.xml -nCrunchTemp_* - -# MightyMoose -*.mm.* -AutoTest.Net/ - -# Web workbench (sass) -.sass-cache/ - -# Installshield output folder -[Ee]xpress/ - -# DocProject is a documentation generator add-in -DocProject/buildhelp/ -DocProject/Help/*.HxT -DocProject/Help/*.HxC -DocProject/Help/*.hhc -DocProject/Help/*.hhk -DocProject/Help/*.hhp -DocProject/Help/Html2 -DocProject/Help/html - -# Click-Once directory -publish/ - -# Publish Web Output -*.[Pp]ublish.xml -*.azurePubxml -# Note: Comment the next line if you want to checkin your web deploy settings, -# but database connection strings (with potential passwords) will be unencrypted -*.pubxml -*.publishproj - -# Microsoft Azure Web App publish settings. Comment the next line if you want to -# checkin your Azure Web App publish settings, but sensitive information contained -# in these scripts will be unencrypted -PublishScripts/ - -# NuGet Packages -*.nupkg -# NuGet Symbol Packages -*.snupkg -# The packages folder can be ignored because of Package Restore -**/[Pp]ackages/* -# except build/, which is used as an MSBuild target. -!**/[Pp]ackages/build/ -# Uncomment if necessary however generally it will be regenerated when needed -#!**/[Pp]ackages/repositories.config -# NuGet v3's project.json files produces more ignorable files -*.nuget.props -*.nuget.targets - -# Microsoft Azure Build Output -csx/ -*.build.csdef - -# Microsoft Azure Emulator -ecf/ -rcf/ - -# Windows Store app package directories and files -AppPackages/ -BundleArtifacts/ -Package.StoreAssociation.xml -_pkginfo.txt -*.appx -*.appxbundle -*.appxupload - -# Visual Studio cache files -# files ending in .cache can be ignored -*.[Cc]ache -# but keep track of directories ending in .cache -!?*.[Cc]ache/ - -# Others -ClientBin/ -~$* -*~ -*.dbmdl -*.dbproj.schemaview -*.jfm -*.pfx -*.publishsettings -orleans.codegen.cs - -# Including strong name files can present a security risk -# (https://github.com/github/gitignore/pull/2483#issue-259490424) -#*.snk - -# Since there are multiple workflows, uncomment next line to ignore bower_components -# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) -#bower_components/ - -# RIA/Silverlight projects -Generated_Code/ - -# Backup & report files from converting an old project file -# to a newer Visual Studio version. Backup files are not needed, -# because we have git ;-) -_UpgradeReport_Files/ -Backup*/ -UpgradeLog*.XML -UpgradeLog*.htm -ServiceFabricBackup/ -*.rptproj.bak - -# SQL Server files -*.mdf -*.ldf -*.ndf - -# Business Intelligence projects -*.rdl.data -*.bim.layout -*.bim_*.settings -*.rptproj.rsuser -*- [Bb]ackup.rdl -*- [Bb]ackup ([0-9]).rdl -*- [Bb]ackup ([0-9][0-9]).rdl - -# Microsoft Fakes -FakesAssemblies/ - -# GhostDoc plugin setting file -*.GhostDoc.xml - -# Node.js Tools for Visual Studio -.ntvs_analysis.dat -node_modules/ - -# Visual Studio 6 build log -*.plg - -# Visual Studio 6 workspace options file -*.opt - -# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) -*.vbw - -# Visual Studio 6 auto-generated project file (contains which files were open etc.) -*.vbp - -# Visual Studio 6 workspace and project file (working project files containing files to include in project) -*.dsw -*.dsp - -# Visual Studio 6 technical files -*.ncb -*.aps - -# Visual Studio LightSwitch build output -**/*.HTMLClient/GeneratedArtifacts -**/*.DesktopClient/GeneratedArtifacts -**/*.DesktopClient/ModelManifest.xml -**/*.Server/GeneratedArtifacts -**/*.Server/ModelManifest.xml -_Pvt_Extensions - -# Paket dependency manager -.paket/paket.exe -paket-files/ - -# FAKE - F# Make -.fake/ - -# CodeRush personal settings -.cr/personal - -# Python Tools for Visual Studio (PTVS) -__pycache__/ -*.pyc - -# Cake - Uncomment if you are using it -# tools/** -# !tools/packages.config - -# Tabs Studio -*.tss - -# Telerik's JustMock configuration file -*.jmconfig - -# BizTalk build output -*.btp.cs -*.btm.cs -*.odx.cs -*.xsd.cs - -# OpenCover UI analysis results -OpenCover/ - -# Azure Stream Analytics local run output -ASALocalRun/ - -# MSBuild Binary and Structured Log -*.binlog - -# NVidia Nsight GPU debugger configuration file -*.nvuser - -# MFractors (Xamarin productivity tool) working folder -.mfractor/ - -# Local History for Visual Studio -.localhistory/ - -# Visual Studio History (VSHistory) files -.vshistory/ - -# BeatPulse healthcheck temp database -healthchecksdb - -# Backup folder for Package Reference Convert tool in Visual Studio 2017 -MigrationBackup/ - -# Ionide (cross platform F# VS Code tools) working folder -.ionide/ - -# Fody - auto-generated XML schema -FodyWeavers.xsd - -# VS Code files for those working on multiple tools -.vscode/* -!.vscode/settings.json -!.vscode/tasks.json -!.vscode/launch.json -!.vscode/extensions.json -*.code-workspace - -# Local History for Visual Studio Code -.history/ - -# Windows Installer files from build outputs -*.cab -*.msi -*.msix -*.msm -*.msp - -# JetBrains Rider -*.sln.iml -.idea - -## -## Visual studio for Mac -## - - -# globs -Makefile.in -*.userprefs -*.usertasks -config.make -config.status -aclocal.m4 -install-sh -autom4te.cache/ -*.tar.gz -tarballs/ -test-results/ - -# Mac bundle stuff -*.dmg -*.app - -# content below from: https://github.com/github/gitignore/blob/master/Global/macOS.gitignore -# General -.DS_Store -.AppleDouble -.LSOverride - -# Icon must end with two \r -Icon - - -# Thumbnails -._* - -# Files that might appear in the root of a volume -.DocumentRevisions-V100 -.fseventsd -.Spotlight-V100 -.TemporaryItems -.Trashes -.VolumeIcon.icns -.com.apple.timemachine.donotpresent - -# Directories potentially created on remote AFP share -.AppleDB -.AppleDesktop -Network Trash Folder -Temporary Items -.apdisk - -# content below from: https://github.com/github/gitignore/blob/master/Global/Windows.gitignore -# Windows thumbnail cache files -Thumbs.db -ehthumbs.db -ehthumbs_vista.db - -# Dump file -*.stackdump - -# Folder config file -[Dd]esktop.ini - -# Recycle Bin used on file shares -$RECYCLE.BIN/ - -# Windows Installer files -*.cab -*.msi -*.msix -*.msm -*.msp - -# Windows shortcuts -*.lnk - -# Vim temporary swap files -*.swp - -PublishProfiles diff --git a/frameworks/blazor/scan-using-rtu-api/App.razor b/frameworks/blazor/scan-using-rtu-api/App.razor deleted file mode 100644 index 6fd3ed1b..00000000 --- a/frameworks/blazor/scan-using-rtu-api/App.razor +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - Not found - -

Sorry, there's nothing at this address.

-
-
-
diff --git a/frameworks/blazor/scan-using-rtu-api/BlazorApp.csproj b/frameworks/blazor/scan-using-rtu-api/BlazorApp.csproj deleted file mode 100644 index 8e50d8dc..00000000 --- a/frameworks/blazor/scan-using-rtu-api/BlazorApp.csproj +++ /dev/null @@ -1,18 +0,0 @@ - - - - net8.0 - enable - enable - - - - - - - - - - - - diff --git a/frameworks/blazor/scan-using-rtu-api/Layout/MainLayout.razor b/frameworks/blazor/scan-using-rtu-api/Layout/MainLayout.razor deleted file mode 100644 index 5a584b18..00000000 --- a/frameworks/blazor/scan-using-rtu-api/Layout/MainLayout.razor +++ /dev/null @@ -1,4 +0,0 @@ -@inherits LayoutComponentBase -
- @Body -
diff --git a/frameworks/blazor/scan-using-rtu-api/Pages/Home.razor b/frameworks/blazor/scan-using-rtu-api/Pages/Home.razor deleted file mode 100644 index c94ddbd7..00000000 --- a/frameworks/blazor/scan-using-rtu-api/Pages/Home.razor +++ /dev/null @@ -1,25 +0,0 @@ -@page "/" -@inject IJSRuntime JS - -Dynamsoft Barcode Reader Sample - Hello World (Decode via Camera) - -

Barcode Scanner for Svelte

-
-
- -@code { - // reference: https://learn.microsoft.com/en-us/aspnet/core/blazor/javascript-interoperability/call-javascript-from-dotnet?view=aspnetcore-8.0#invoke-js-functions - - - protected override async Task OnAfterRenderAsync(bool firstRender) - { - if (firstRender) - { - // This code will only run once after the component has rendered. - // It's the ideal place to call JavaScript functions that - // need access to the rendered HTML. - var resultTxt = await JS.InvokeAsync("decodeBarcodeViaCamera"); - await JS.InvokeVoidAsync("alert", resultTxt); - } - } -} diff --git a/frameworks/blazor/scan-using-rtu-api/Program.cs b/frameworks/blazor/scan-using-rtu-api/Program.cs deleted file mode 100644 index e6ef32a3..00000000 --- a/frameworks/blazor/scan-using-rtu-api/Program.cs +++ /dev/null @@ -1,11 +0,0 @@ -using BlazorApp; -using Microsoft.AspNetCore.Components.Web; -using Microsoft.AspNetCore.Components.WebAssembly.Hosting; - -var builder = WebAssemblyHostBuilder.CreateDefault(args); -builder.RootComponents.Add("#app"); -builder.RootComponents.Add("head::after"); - -builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) }); - -await builder.Build().RunAsync(); diff --git a/frameworks/blazor/scan-using-rtu-api/Properties/launchSettings.json b/frameworks/blazor/scan-using-rtu-api/Properties/launchSettings.json deleted file mode 100644 index e25d8f48..00000000 --- a/frameworks/blazor/scan-using-rtu-api/Properties/launchSettings.json +++ /dev/null @@ -1,41 +0,0 @@ -{ - "$schema": "http://json.schemastore.org/launchsettings.json", - "iisSettings": { - "windowsAuthentication": false, - "anonymousAuthentication": true, - "iisExpress": { - "applicationUrl": "http://localhost:17951", - "sslPort": 44366 - } - }, - "profiles": { - "http": { - "commandName": "Project", - "dotnetRunMessages": true, - "launchBrowser": true, - "inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}", - "applicationUrl": "http://localhost:5244", - "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" - } - }, - "https": { - "commandName": "Project", - "dotnetRunMessages": true, - "launchBrowser": true, - "inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}", - "applicationUrl": "https://localhost:7074;http://localhost:5244", - "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" - } - }, - "IIS Express": { - "commandName": "IISExpress", - "launchBrowser": true, - "inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}", - "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" - } - } - } -} diff --git a/frameworks/blazor/scan-using-rtu-api/README.md b/frameworks/blazor/scan-using-rtu-api/README.md deleted file mode 100644 index 0cea6a03..00000000 --- a/frameworks/blazor/scan-using-rtu-api/README.md +++ /dev/null @@ -1,17 +0,0 @@ -# 📦 Scan Single Barcode - Blazor - -This sample demonstrates how to use the `BarcodeScanner` API from the [Dynamsoft Barcode Reader JavaScript SDK](https://www.dynamsoft.com/barcode-reader/sdk-javascript/) in a **Blazor** app to scan a single barcode using the camera. - -## ✨ Features - -- Easy integration with pre-built UI -- Renders barcodeScanner inside a container -- Scans one barcode at a time from video - -## 📌 Customization - -Please refer check the official [documentation](https://dynamsoft.com/barcode-reader/docs/web/programming/javascript/user-guide/barcode-scanner-customization.html). - -## 📄 Support - -If you have any questions, feel free to [contact Dynamsoft Support](https://www.dynamsoft.com/company/contact?utm_source=sampleReadme). diff --git a/frameworks/blazor/scan-using-rtu-api/_Imports.razor b/frameworks/blazor/scan-using-rtu-api/_Imports.razor deleted file mode 100644 index 2c3956ad..00000000 --- a/frameworks/blazor/scan-using-rtu-api/_Imports.razor +++ /dev/null @@ -1,10 +0,0 @@ -@using System.Net.Http -@using System.Net.Http.Json -@using Microsoft.AspNetCore.Components.Forms -@using Microsoft.AspNetCore.Components.Routing -@using Microsoft.AspNetCore.Components.Web -@using Microsoft.AspNetCore.Components.Web.Virtualization -@using Microsoft.AspNetCore.Components.WebAssembly.Http -@using Microsoft.JSInterop -@using BlazorApp -@using BlazorApp.Layout diff --git a/frameworks/blazor/scan-using-rtu-api/wwwroot/index.html b/frameworks/blazor/scan-using-rtu-api/wwwroot/index.html deleted file mode 100644 index 529961ba..00000000 --- a/frameworks/blazor/scan-using-rtu-api/wwwroot/index.html +++ /dev/null @@ -1,73 +0,0 @@ - - - - - - - BlazorApp - - - - -
-
- - - - - - - \ No newline at end of file diff --git a/frameworks/capacitor/README.md b/frameworks/capacitor/README.md index 4b3e675c..7b3a62b7 100644 --- a/frameworks/capacitor/README.md +++ b/frameworks/capacitor/README.md @@ -1,22 +1,43 @@ -# Capacitor samples +# 📦 Scan Single Barcode - Capacitor -This directory contains Capacitor examples showing how to use the Dynamsoft Barcode Reader in hybrid mobile apps (Android / iOS) via Capacitor. +This sample demonstrates how to use the `BarcodeScanner` API from the [Dynamsoft Barcode Reader JavaScript SDK](https://www.dynamsoft.com/barcode-reader/sdk-javascript/) in a **Capacitor** app to scan a single barcode using the camera. -**Included example** +We use typescript and rollup inside capacitor for demonstration. You can use any framework you like, or even vanilla javascript. -- scan-using-rtu-api/ — Capacitor project illustrating RTU API usage. +## ✨ Features -## Quick start +- Easy integration with pre-built UI +- Renders barcodeScanner inside a Capacitor container +- Scans one barcode at a time from video -1. Change to the example directory, e.g.: - - ```bash - cd scan-using-rtu-api - ``` +## 🚀 Quick Start -2. Follow the subexample README for platform-specific setup (npm install, capacitor sync, open Android Studio/Xcode). +```bash +npm install +npm run build +npx cap sync +``` -## Notes +Then build your app in Android Studio and Xcode. -- Mobile platform setup is required to run native apps. See the subexample README for exact steps. -- See the repository root README.md for general usage and license information. \ No newline at end of file +## 👓 Camera Permission + +Notice we add camera permission in `AndroidManifest.xml` and `Info.plist`. + +[android/app/src/main/AndroidManifest.xml](android/app/src/main/AndroidManifest.xml): +```xml + +``` +[ios/App/App/Info.plist](ios/App/App/Info.plist): +```xml +NSCameraUsageDescription +Decoding barcodes from video needs to access your camera. +``` + +## 📌 Customization + +Please check the official [documentation](https://dynamsoft.com/barcode-reader/docs/web/programming/javascript/user-guide/barcode-scanner-customization.html). + +## 📄 Support + +If you have any questions, feel free to [contact Dynamsoft Support](https://www.dynamsoft.com/company/contact?utm_source=sampleReadme). diff --git a/frameworks/capacitor/scan-using-rtu-api/android/.gitignore b/frameworks/capacitor/android/.gitignore similarity index 100% rename from frameworks/capacitor/scan-using-rtu-api/android/.gitignore rename to frameworks/capacitor/android/.gitignore diff --git a/frameworks/capacitor/scan-using-rtu-api/android/app/.gitignore b/frameworks/capacitor/android/app/.gitignore similarity index 100% rename from frameworks/capacitor/scan-using-rtu-api/android/app/.gitignore rename to frameworks/capacitor/android/app/.gitignore diff --git a/frameworks/capacitor/scan-using-rtu-api/android/app/build.gradle b/frameworks/capacitor/android/app/build.gradle similarity index 100% rename from frameworks/capacitor/scan-using-rtu-api/android/app/build.gradle rename to frameworks/capacitor/android/app/build.gradle diff --git a/frameworks/capacitor/scan-using-rtu-api/android/app/capacitor.build.gradle b/frameworks/capacitor/android/app/capacitor.build.gradle similarity index 100% rename from frameworks/capacitor/scan-using-rtu-api/android/app/capacitor.build.gradle rename to frameworks/capacitor/android/app/capacitor.build.gradle diff --git a/frameworks/capacitor/scan-using-rtu-api/android/app/proguard-rules.pro b/frameworks/capacitor/android/app/proguard-rules.pro similarity index 100% rename from frameworks/capacitor/scan-using-rtu-api/android/app/proguard-rules.pro rename to frameworks/capacitor/android/app/proguard-rules.pro diff --git a/frameworks/capacitor/scan-using-rtu-api/android/app/src/androidTest/java/com/getcapacitor/myapp/ExampleInstrumentedTest.java b/frameworks/capacitor/android/app/src/androidTest/java/com/getcapacitor/myapp/ExampleInstrumentedTest.java similarity index 100% rename from frameworks/capacitor/scan-using-rtu-api/android/app/src/androidTest/java/com/getcapacitor/myapp/ExampleInstrumentedTest.java rename to frameworks/capacitor/android/app/src/androidTest/java/com/getcapacitor/myapp/ExampleInstrumentedTest.java diff --git a/frameworks/capacitor/scan-using-rtu-api/android/app/src/main/AndroidManifest.xml b/frameworks/capacitor/android/app/src/main/AndroidManifest.xml similarity index 100% rename from frameworks/capacitor/scan-using-rtu-api/android/app/src/main/AndroidManifest.xml rename to frameworks/capacitor/android/app/src/main/AndroidManifest.xml diff --git a/frameworks/capacitor/scan-using-rtu-api/android/app/src/main/java/com/dynamsoft/dbrjs/MainActivity.java b/frameworks/capacitor/android/app/src/main/java/com/dynamsoft/dbrjs/MainActivity.java similarity index 100% rename from frameworks/capacitor/scan-using-rtu-api/android/app/src/main/java/com/dynamsoft/dbrjs/MainActivity.java rename to frameworks/capacitor/android/app/src/main/java/com/dynamsoft/dbrjs/MainActivity.java diff --git a/frameworks/capacitor/scan-using-rtu-api/android/app/src/main/res/drawable-land-hdpi/splash.png b/frameworks/capacitor/android/app/src/main/res/drawable-land-hdpi/splash.png similarity index 100% rename from frameworks/capacitor/scan-using-rtu-api/android/app/src/main/res/drawable-land-hdpi/splash.png rename to frameworks/capacitor/android/app/src/main/res/drawable-land-hdpi/splash.png diff --git a/frameworks/capacitor/scan-using-rtu-api/android/app/src/main/res/drawable-land-mdpi/splash.png b/frameworks/capacitor/android/app/src/main/res/drawable-land-mdpi/splash.png similarity index 100% rename from frameworks/capacitor/scan-using-rtu-api/android/app/src/main/res/drawable-land-mdpi/splash.png rename to frameworks/capacitor/android/app/src/main/res/drawable-land-mdpi/splash.png diff --git a/frameworks/capacitor/scan-using-rtu-api/android/app/src/main/res/drawable-land-xhdpi/splash.png b/frameworks/capacitor/android/app/src/main/res/drawable-land-xhdpi/splash.png similarity index 100% rename from frameworks/capacitor/scan-using-rtu-api/android/app/src/main/res/drawable-land-xhdpi/splash.png rename to frameworks/capacitor/android/app/src/main/res/drawable-land-xhdpi/splash.png diff --git a/frameworks/capacitor/scan-using-rtu-api/android/app/src/main/res/drawable-land-xxhdpi/splash.png b/frameworks/capacitor/android/app/src/main/res/drawable-land-xxhdpi/splash.png similarity index 100% rename from frameworks/capacitor/scan-using-rtu-api/android/app/src/main/res/drawable-land-xxhdpi/splash.png rename to frameworks/capacitor/android/app/src/main/res/drawable-land-xxhdpi/splash.png diff --git a/frameworks/capacitor/scan-using-rtu-api/android/app/src/main/res/drawable-land-xxxhdpi/splash.png b/frameworks/capacitor/android/app/src/main/res/drawable-land-xxxhdpi/splash.png similarity index 100% rename from frameworks/capacitor/scan-using-rtu-api/android/app/src/main/res/drawable-land-xxxhdpi/splash.png rename to frameworks/capacitor/android/app/src/main/res/drawable-land-xxxhdpi/splash.png diff --git a/frameworks/capacitor/scan-using-rtu-api/android/app/src/main/res/drawable-port-hdpi/splash.png b/frameworks/capacitor/android/app/src/main/res/drawable-port-hdpi/splash.png similarity index 100% rename from frameworks/capacitor/scan-using-rtu-api/android/app/src/main/res/drawable-port-hdpi/splash.png rename to frameworks/capacitor/android/app/src/main/res/drawable-port-hdpi/splash.png diff --git a/frameworks/capacitor/scan-using-rtu-api/android/app/src/main/res/drawable-port-mdpi/splash.png b/frameworks/capacitor/android/app/src/main/res/drawable-port-mdpi/splash.png similarity index 100% rename from frameworks/capacitor/scan-using-rtu-api/android/app/src/main/res/drawable-port-mdpi/splash.png rename to frameworks/capacitor/android/app/src/main/res/drawable-port-mdpi/splash.png diff --git a/frameworks/capacitor/scan-using-rtu-api/android/app/src/main/res/drawable-port-xhdpi/splash.png b/frameworks/capacitor/android/app/src/main/res/drawable-port-xhdpi/splash.png similarity index 100% rename from frameworks/capacitor/scan-using-rtu-api/android/app/src/main/res/drawable-port-xhdpi/splash.png rename to frameworks/capacitor/android/app/src/main/res/drawable-port-xhdpi/splash.png diff --git a/frameworks/capacitor/scan-using-rtu-api/android/app/src/main/res/drawable-port-xxhdpi/splash.png b/frameworks/capacitor/android/app/src/main/res/drawable-port-xxhdpi/splash.png similarity index 100% rename from frameworks/capacitor/scan-using-rtu-api/android/app/src/main/res/drawable-port-xxhdpi/splash.png rename to frameworks/capacitor/android/app/src/main/res/drawable-port-xxhdpi/splash.png diff --git a/frameworks/capacitor/scan-using-rtu-api/android/app/src/main/res/drawable-port-xxxhdpi/splash.png b/frameworks/capacitor/android/app/src/main/res/drawable-port-xxxhdpi/splash.png similarity index 100% rename from frameworks/capacitor/scan-using-rtu-api/android/app/src/main/res/drawable-port-xxxhdpi/splash.png rename to frameworks/capacitor/android/app/src/main/res/drawable-port-xxxhdpi/splash.png diff --git a/frameworks/capacitor/scan-using-rtu-api/android/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/frameworks/capacitor/android/app/src/main/res/drawable-v24/ic_launcher_foreground.xml similarity index 100% rename from frameworks/capacitor/scan-using-rtu-api/android/app/src/main/res/drawable-v24/ic_launcher_foreground.xml rename to frameworks/capacitor/android/app/src/main/res/drawable-v24/ic_launcher_foreground.xml diff --git a/frameworks/capacitor/scan-using-rtu-api/android/app/src/main/res/drawable/ic_launcher_background.xml b/frameworks/capacitor/android/app/src/main/res/drawable/ic_launcher_background.xml similarity index 100% rename from frameworks/capacitor/scan-using-rtu-api/android/app/src/main/res/drawable/ic_launcher_background.xml rename to frameworks/capacitor/android/app/src/main/res/drawable/ic_launcher_background.xml diff --git a/frameworks/capacitor/scan-using-rtu-api/android/app/src/main/res/drawable/splash.png b/frameworks/capacitor/android/app/src/main/res/drawable/splash.png similarity index 100% rename from frameworks/capacitor/scan-using-rtu-api/android/app/src/main/res/drawable/splash.png rename to frameworks/capacitor/android/app/src/main/res/drawable/splash.png diff --git a/frameworks/capacitor/scan-using-rtu-api/android/app/src/main/res/layout/activity_main.xml b/frameworks/capacitor/android/app/src/main/res/layout/activity_main.xml similarity index 100% rename from frameworks/capacitor/scan-using-rtu-api/android/app/src/main/res/layout/activity_main.xml rename to frameworks/capacitor/android/app/src/main/res/layout/activity_main.xml diff --git a/frameworks/capacitor/scan-using-rtu-api/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/frameworks/capacitor/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml similarity index 100% rename from frameworks/capacitor/scan-using-rtu-api/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml rename to frameworks/capacitor/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml diff --git a/frameworks/capacitor/scan-using-rtu-api/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/frameworks/capacitor/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml similarity index 100% rename from frameworks/capacitor/scan-using-rtu-api/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml rename to frameworks/capacitor/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml diff --git a/frameworks/capacitor/scan-using-rtu-api/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/frameworks/capacitor/android/app/src/main/res/mipmap-hdpi/ic_launcher.png similarity index 100% rename from frameworks/capacitor/scan-using-rtu-api/android/app/src/main/res/mipmap-hdpi/ic_launcher.png rename to frameworks/capacitor/android/app/src/main/res/mipmap-hdpi/ic_launcher.png diff --git a/frameworks/capacitor/scan-using-rtu-api/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png b/frameworks/capacitor/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png similarity index 100% rename from frameworks/capacitor/scan-using-rtu-api/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png rename to frameworks/capacitor/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png diff --git a/frameworks/capacitor/scan-using-rtu-api/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/frameworks/capacitor/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png similarity index 100% rename from frameworks/capacitor/scan-using-rtu-api/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png rename to frameworks/capacitor/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png diff --git a/frameworks/capacitor/scan-using-rtu-api/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/frameworks/capacitor/android/app/src/main/res/mipmap-mdpi/ic_launcher.png similarity index 100% rename from frameworks/capacitor/scan-using-rtu-api/android/app/src/main/res/mipmap-mdpi/ic_launcher.png rename to frameworks/capacitor/android/app/src/main/res/mipmap-mdpi/ic_launcher.png diff --git a/frameworks/capacitor/scan-using-rtu-api/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png b/frameworks/capacitor/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png similarity index 100% rename from frameworks/capacitor/scan-using-rtu-api/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png rename to frameworks/capacitor/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png diff --git a/frameworks/capacitor/scan-using-rtu-api/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/frameworks/capacitor/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png similarity index 100% rename from frameworks/capacitor/scan-using-rtu-api/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png rename to frameworks/capacitor/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png diff --git a/frameworks/capacitor/scan-using-rtu-api/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/frameworks/capacitor/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png similarity index 100% rename from frameworks/capacitor/scan-using-rtu-api/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png rename to frameworks/capacitor/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png diff --git a/frameworks/capacitor/scan-using-rtu-api/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png b/frameworks/capacitor/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png similarity index 100% rename from frameworks/capacitor/scan-using-rtu-api/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png rename to frameworks/capacitor/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png diff --git a/frameworks/capacitor/scan-using-rtu-api/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/frameworks/capacitor/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png similarity index 100% rename from frameworks/capacitor/scan-using-rtu-api/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png rename to frameworks/capacitor/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png diff --git a/frameworks/capacitor/scan-using-rtu-api/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/frameworks/capacitor/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png similarity index 100% rename from frameworks/capacitor/scan-using-rtu-api/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png rename to frameworks/capacitor/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png diff --git a/frameworks/capacitor/scan-using-rtu-api/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png b/frameworks/capacitor/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png similarity index 100% rename from frameworks/capacitor/scan-using-rtu-api/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png rename to frameworks/capacitor/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png diff --git a/frameworks/capacitor/scan-using-rtu-api/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/frameworks/capacitor/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png similarity index 100% rename from frameworks/capacitor/scan-using-rtu-api/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png rename to frameworks/capacitor/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png diff --git a/frameworks/capacitor/scan-using-rtu-api/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/frameworks/capacitor/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png similarity index 100% rename from frameworks/capacitor/scan-using-rtu-api/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png rename to frameworks/capacitor/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png diff --git a/frameworks/capacitor/scan-using-rtu-api/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png b/frameworks/capacitor/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png similarity index 100% rename from frameworks/capacitor/scan-using-rtu-api/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png rename to frameworks/capacitor/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png diff --git a/frameworks/capacitor/scan-using-rtu-api/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/frameworks/capacitor/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png similarity index 100% rename from frameworks/capacitor/scan-using-rtu-api/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png rename to frameworks/capacitor/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png diff --git a/frameworks/capacitor/scan-using-rtu-api/android/app/src/main/res/values/ic_launcher_background.xml b/frameworks/capacitor/android/app/src/main/res/values/ic_launcher_background.xml similarity index 100% rename from frameworks/capacitor/scan-using-rtu-api/android/app/src/main/res/values/ic_launcher_background.xml rename to frameworks/capacitor/android/app/src/main/res/values/ic_launcher_background.xml diff --git a/frameworks/capacitor/scan-using-rtu-api/android/app/src/main/res/values/strings.xml b/frameworks/capacitor/android/app/src/main/res/values/strings.xml similarity index 100% rename from frameworks/capacitor/scan-using-rtu-api/android/app/src/main/res/values/strings.xml rename to frameworks/capacitor/android/app/src/main/res/values/strings.xml diff --git a/frameworks/capacitor/scan-using-rtu-api/android/app/src/main/res/values/styles.xml b/frameworks/capacitor/android/app/src/main/res/values/styles.xml similarity index 100% rename from frameworks/capacitor/scan-using-rtu-api/android/app/src/main/res/values/styles.xml rename to frameworks/capacitor/android/app/src/main/res/values/styles.xml diff --git a/frameworks/capacitor/scan-using-rtu-api/android/app/src/main/res/xml/file_paths.xml b/frameworks/capacitor/android/app/src/main/res/xml/file_paths.xml similarity index 100% rename from frameworks/capacitor/scan-using-rtu-api/android/app/src/main/res/xml/file_paths.xml rename to frameworks/capacitor/android/app/src/main/res/xml/file_paths.xml diff --git a/frameworks/capacitor/scan-using-rtu-api/android/app/src/test/java/com/getcapacitor/myapp/ExampleUnitTest.java b/frameworks/capacitor/android/app/src/test/java/com/getcapacitor/myapp/ExampleUnitTest.java similarity index 100% rename from frameworks/capacitor/scan-using-rtu-api/android/app/src/test/java/com/getcapacitor/myapp/ExampleUnitTest.java rename to frameworks/capacitor/android/app/src/test/java/com/getcapacitor/myapp/ExampleUnitTest.java diff --git a/frameworks/capacitor/scan-using-rtu-api/android/build.gradle b/frameworks/capacitor/android/build.gradle similarity index 100% rename from frameworks/capacitor/scan-using-rtu-api/android/build.gradle rename to frameworks/capacitor/android/build.gradle diff --git a/frameworks/capacitor/scan-using-rtu-api/android/capacitor.settings.gradle b/frameworks/capacitor/android/capacitor.settings.gradle similarity index 100% rename from frameworks/capacitor/scan-using-rtu-api/android/capacitor.settings.gradle rename to frameworks/capacitor/android/capacitor.settings.gradle diff --git a/frameworks/capacitor/scan-using-rtu-api/android/gradle.properties b/frameworks/capacitor/android/gradle.properties similarity index 100% rename from frameworks/capacitor/scan-using-rtu-api/android/gradle.properties rename to frameworks/capacitor/android/gradle.properties diff --git a/frameworks/capacitor/scan-using-rtu-api/android/gradle/wrapper/gradle-wrapper.jar b/frameworks/capacitor/android/gradle/wrapper/gradle-wrapper.jar similarity index 100% rename from frameworks/capacitor/scan-using-rtu-api/android/gradle/wrapper/gradle-wrapper.jar rename to frameworks/capacitor/android/gradle/wrapper/gradle-wrapper.jar diff --git a/frameworks/capacitor/scan-using-rtu-api/android/gradle/wrapper/gradle-wrapper.properties b/frameworks/capacitor/android/gradle/wrapper/gradle-wrapper.properties similarity index 100% rename from frameworks/capacitor/scan-using-rtu-api/android/gradle/wrapper/gradle-wrapper.properties rename to frameworks/capacitor/android/gradle/wrapper/gradle-wrapper.properties diff --git a/frameworks/capacitor/scan-using-rtu-api/android/gradlew b/frameworks/capacitor/android/gradlew similarity index 100% rename from frameworks/capacitor/scan-using-rtu-api/android/gradlew rename to frameworks/capacitor/android/gradlew diff --git a/frameworks/capacitor/scan-using-rtu-api/android/gradlew.bat b/frameworks/capacitor/android/gradlew.bat similarity index 100% rename from frameworks/capacitor/scan-using-rtu-api/android/gradlew.bat rename to frameworks/capacitor/android/gradlew.bat diff --git a/frameworks/capacitor/scan-using-rtu-api/android/settings.gradle b/frameworks/capacitor/android/settings.gradle similarity index 100% rename from frameworks/capacitor/scan-using-rtu-api/android/settings.gradle rename to frameworks/capacitor/android/settings.gradle diff --git a/frameworks/capacitor/scan-using-rtu-api/android/variables.gradle b/frameworks/capacitor/android/variables.gradle similarity index 100% rename from frameworks/capacitor/scan-using-rtu-api/android/variables.gradle rename to frameworks/capacitor/android/variables.gradle diff --git a/frameworks/capacitor/scan-using-rtu-api/capacitor.config.json b/frameworks/capacitor/capacitor.config.json similarity index 100% rename from frameworks/capacitor/scan-using-rtu-api/capacitor.config.json rename to frameworks/capacitor/capacitor.config.json diff --git a/frameworks/capacitor/index.ts b/frameworks/capacitor/index.ts new file mode 100644 index 00000000..a20e7bf0 --- /dev/null +++ b/frameworks/capacitor/index.ts @@ -0,0 +1,30 @@ +import { LicenseManager, CameraView, CameraEnhancer, CaptureVisionRouter, CapturedResultReceiver, MultiFrameResultCrossFilter } from "dynamsoft-barcode-reader-bundle"; + +LicenseManager.initLicense("DLS2eyJvcmdhbml6YXRpb25JRCI6IjIwMDAwMSJ9"); +(async () => { + const cameraView = await CameraView.createInstance(); + const cameraEnhancer = await CameraEnhancer.createInstance(cameraView); + const cvRouter = await CaptureVisionRouter.createInstance(); + + cvRouter.setInput(cameraEnhancer); + + const resultReceiver = new CapturedResultReceiver(); + resultReceiver.onDecodedBarcodesReceived = (result) => { + alert(result.barcodeResultItems[0].text); + }; + await cvRouter.addResultReceiver(resultReceiver); + + // Filter out unchecked and duplicate results. + const filter = new MultiFrameResultCrossFilter(); + // Filter out unchecked barcodes. + filter.enableResultCrossVerification("barcode", true); + // Filter out duplicate barcodes within 3 seconds. + filter.enableResultDeduplication("barcode", true); + await cvRouter.addResultFilter(filter); + + const uiElement = cameraView.getUIElement(); + document.querySelector(".barcode-scanner-view")!.append(uiElement); + + await cameraEnhancer.open(); + await cvRouter.startCapturing("ReadBarcodes_SpeedFirst"); +})(); \ No newline at end of file diff --git a/frameworks/capacitor/scan-using-rtu-api/ios/.gitignore b/frameworks/capacitor/ios/.gitignore similarity index 100% rename from frameworks/capacitor/scan-using-rtu-api/ios/.gitignore rename to frameworks/capacitor/ios/.gitignore diff --git a/frameworks/capacitor/scan-using-rtu-api/ios/App/App.xcodeproj/project.pbxproj b/frameworks/capacitor/ios/App/App.xcodeproj/project.pbxproj similarity index 100% rename from frameworks/capacitor/scan-using-rtu-api/ios/App/App.xcodeproj/project.pbxproj rename to frameworks/capacitor/ios/App/App.xcodeproj/project.pbxproj diff --git a/frameworks/capacitor/scan-using-rtu-api/ios/App/App.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/frameworks/capacitor/ios/App/App.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist similarity index 100% rename from frameworks/capacitor/scan-using-rtu-api/ios/App/App.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist rename to frameworks/capacitor/ios/App/App.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist diff --git a/frameworks/capacitor/scan-using-rtu-api/ios/App/App/AppDelegate.swift b/frameworks/capacitor/ios/App/App/AppDelegate.swift similarity index 100% rename from frameworks/capacitor/scan-using-rtu-api/ios/App/App/AppDelegate.swift rename to frameworks/capacitor/ios/App/App/AppDelegate.swift diff --git a/frameworks/capacitor/scan-using-rtu-api/ios/App/App/Assets.xcassets/AppIcon.appiconset/AppIcon-512@2x.png b/frameworks/capacitor/ios/App/App/Assets.xcassets/AppIcon.appiconset/AppIcon-512@2x.png similarity index 100% rename from frameworks/capacitor/scan-using-rtu-api/ios/App/App/Assets.xcassets/AppIcon.appiconset/AppIcon-512@2x.png rename to frameworks/capacitor/ios/App/App/Assets.xcassets/AppIcon.appiconset/AppIcon-512@2x.png diff --git a/frameworks/capacitor/scan-using-rtu-api/ios/App/App/Assets.xcassets/AppIcon.appiconset/Contents.json b/frameworks/capacitor/ios/App/App/Assets.xcassets/AppIcon.appiconset/Contents.json similarity index 100% rename from frameworks/capacitor/scan-using-rtu-api/ios/App/App/Assets.xcassets/AppIcon.appiconset/Contents.json rename to frameworks/capacitor/ios/App/App/Assets.xcassets/AppIcon.appiconset/Contents.json diff --git a/frameworks/capacitor/scan-using-rtu-api/ios/App/App/Assets.xcassets/Contents.json b/frameworks/capacitor/ios/App/App/Assets.xcassets/Contents.json similarity index 100% rename from frameworks/capacitor/scan-using-rtu-api/ios/App/App/Assets.xcassets/Contents.json rename to frameworks/capacitor/ios/App/App/Assets.xcassets/Contents.json diff --git a/frameworks/capacitor/scan-using-rtu-api/ios/App/App/Assets.xcassets/Splash.imageset/Contents.json b/frameworks/capacitor/ios/App/App/Assets.xcassets/Splash.imageset/Contents.json similarity index 100% rename from frameworks/capacitor/scan-using-rtu-api/ios/App/App/Assets.xcassets/Splash.imageset/Contents.json rename to frameworks/capacitor/ios/App/App/Assets.xcassets/Splash.imageset/Contents.json diff --git a/frameworks/capacitor/scan-using-rtu-api/ios/App/App/Assets.xcassets/Splash.imageset/splash-2732x2732-1.png b/frameworks/capacitor/ios/App/App/Assets.xcassets/Splash.imageset/splash-2732x2732-1.png similarity index 100% rename from frameworks/capacitor/scan-using-rtu-api/ios/App/App/Assets.xcassets/Splash.imageset/splash-2732x2732-1.png rename to frameworks/capacitor/ios/App/App/Assets.xcassets/Splash.imageset/splash-2732x2732-1.png diff --git a/frameworks/capacitor/scan-using-rtu-api/ios/App/App/Assets.xcassets/Splash.imageset/splash-2732x2732-2.png b/frameworks/capacitor/ios/App/App/Assets.xcassets/Splash.imageset/splash-2732x2732-2.png similarity index 100% rename from frameworks/capacitor/scan-using-rtu-api/ios/App/App/Assets.xcassets/Splash.imageset/splash-2732x2732-2.png rename to frameworks/capacitor/ios/App/App/Assets.xcassets/Splash.imageset/splash-2732x2732-2.png diff --git a/frameworks/capacitor/scan-using-rtu-api/ios/App/App/Assets.xcassets/Splash.imageset/splash-2732x2732.png b/frameworks/capacitor/ios/App/App/Assets.xcassets/Splash.imageset/splash-2732x2732.png similarity index 100% rename from frameworks/capacitor/scan-using-rtu-api/ios/App/App/Assets.xcassets/Splash.imageset/splash-2732x2732.png rename to frameworks/capacitor/ios/App/App/Assets.xcassets/Splash.imageset/splash-2732x2732.png diff --git a/frameworks/capacitor/scan-using-rtu-api/ios/App/App/Base.lproj/LaunchScreen.storyboard b/frameworks/capacitor/ios/App/App/Base.lproj/LaunchScreen.storyboard similarity index 100% rename from frameworks/capacitor/scan-using-rtu-api/ios/App/App/Base.lproj/LaunchScreen.storyboard rename to frameworks/capacitor/ios/App/App/Base.lproj/LaunchScreen.storyboard diff --git a/frameworks/capacitor/scan-using-rtu-api/ios/App/App/Base.lproj/Main.storyboard b/frameworks/capacitor/ios/App/App/Base.lproj/Main.storyboard similarity index 100% rename from frameworks/capacitor/scan-using-rtu-api/ios/App/App/Base.lproj/Main.storyboard rename to frameworks/capacitor/ios/App/App/Base.lproj/Main.storyboard diff --git a/frameworks/capacitor/scan-using-rtu-api/ios/App/App/Info.plist b/frameworks/capacitor/ios/App/App/Info.plist similarity index 100% rename from frameworks/capacitor/scan-using-rtu-api/ios/App/App/Info.plist rename to frameworks/capacitor/ios/App/App/Info.plist diff --git a/frameworks/capacitor/scan-using-rtu-api/ios/App/Podfile b/frameworks/capacitor/ios/App/Podfile similarity index 100% rename from frameworks/capacitor/scan-using-rtu-api/ios/App/Podfile rename to frameworks/capacitor/ios/App/Podfile diff --git a/frameworks/capacitor/scan-using-rtu-api/package.json b/frameworks/capacitor/package.json similarity index 91% rename from frameworks/capacitor/scan-using-rtu-api/package.json rename to frameworks/capacitor/package.json index 592e4268..0f5a0e2d 100644 --- a/frameworks/capacitor/scan-using-rtu-api/package.json +++ b/frameworks/capacitor/package.json @@ -16,7 +16,7 @@ "@capacitor/ios": "^7.4.2", "@rollup/plugin-node-resolve": "^15.3.0", "@rollup/plugin-typescript": "^12.1.1", - "dynamsoft-barcode-reader-bundle": "11.2.4000", + "dynamsoft-barcode-reader-bundle": "11.4.2000", "rollup": "^4.24.0", "tslib": "^2.8.0", "typescript": "^5.6.3" diff --git a/frameworks/capacitor/scan-using-rtu-api/public/index.html b/frameworks/capacitor/public/index.html similarity index 100% rename from frameworks/capacitor/scan-using-rtu-api/public/index.html rename to frameworks/capacitor/public/index.html diff --git a/frameworks/capacitor/scan-using-rtu-api/rollup.config.mjs b/frameworks/capacitor/rollup.config.mjs similarity index 100% rename from frameworks/capacitor/scan-using-rtu-api/rollup.config.mjs rename to frameworks/capacitor/rollup.config.mjs diff --git a/frameworks/capacitor/scan-using-rtu-api/README.md b/frameworks/capacitor/scan-using-rtu-api/README.md deleted file mode 100644 index 7b3a62b7..00000000 --- a/frameworks/capacitor/scan-using-rtu-api/README.md +++ /dev/null @@ -1,43 +0,0 @@ -# 📦 Scan Single Barcode - Capacitor - -This sample demonstrates how to use the `BarcodeScanner` API from the [Dynamsoft Barcode Reader JavaScript SDK](https://www.dynamsoft.com/barcode-reader/sdk-javascript/) in a **Capacitor** app to scan a single barcode using the camera. - -We use typescript and rollup inside capacitor for demonstration. You can use any framework you like, or even vanilla javascript. - -## ✨ Features - -- Easy integration with pre-built UI -- Renders barcodeScanner inside a Capacitor container -- Scans one barcode at a time from video - -## 🚀 Quick Start - -```bash -npm install -npm run build -npx cap sync -``` - -Then build your app in Android Studio and Xcode. - -## 👓 Camera Permission - -Notice we add camera permission in `AndroidManifest.xml` and `Info.plist`. - -[android/app/src/main/AndroidManifest.xml](android/app/src/main/AndroidManifest.xml): -```xml - -``` -[ios/App/App/Info.plist](ios/App/App/Info.plist): -```xml -NSCameraUsageDescription -Decoding barcodes from video needs to access your camera. -``` - -## 📌 Customization - -Please check the official [documentation](https://dynamsoft.com/barcode-reader/docs/web/programming/javascript/user-guide/barcode-scanner-customization.html). - -## 📄 Support - -If you have any questions, feel free to [contact Dynamsoft Support](https://www.dynamsoft.com/company/contact?utm_source=sampleReadme). diff --git a/frameworks/capacitor/scan-using-rtu-api/index.ts b/frameworks/capacitor/scan-using-rtu-api/index.ts deleted file mode 100644 index 50ff24a0..00000000 --- a/frameworks/capacitor/scan-using-rtu-api/index.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { BarcodeScanner, BarcodeScannerConfig } from "dynamsoft-barcode-reader-bundle"; - -// Configuration object for initializing the BarcodeScanner instance -const config: BarcodeScannerConfig = { - license: "DLS2eyJvcmdhbml6YXRpb25JRCI6IjIwMDAwMSJ9", // Replace with your Dynamsoft license key - - // Specify where to render the scanner UI - // If container is not specified, the UI will take up the full screen - container: document.querySelector(".barcode-scanner-view") as HTMLElement, // Specify where to render the scanner UI - - // Specify the path for the definition file "barcode-scanner.ui.xml" for the scanner view. - uiPath: "https://cdn.jsdelivr.net/npm/dynamsoft-barcode-reader-bundle@11.2.4000/dist/ui/barcode-scanner.ui.xml", - - // showUploadImageButton: true, - // scannerViewConfig: { - // showFlashButton: true, - // cameraSwitchControl: "toggleFrontBack", - // }, - - // Specify custom paths for the engine resources - engineResourcePaths: { - rootDirectory: "https://cdn.jsdelivr.net/npm/", - }, -}; - -// Create a new instance of the Dynamsoft Barcode Scanner -const barcodeScanner = new BarcodeScanner(config); - -(async()=>{ - // Launch the scanner; once a barcode is detected, display its text in an alert - let result = await barcodeScanner.launch(); - if (result.barcodeResults.length) { - alert(result.barcodeResults[0].text); - } -})(); diff --git a/frameworks/capacitor/scan-using-rtu-api/tsconfig.json b/frameworks/capacitor/tsconfig.json similarity index 100% rename from frameworks/capacitor/scan-using-rtu-api/tsconfig.json rename to frameworks/capacitor/tsconfig.json diff --git a/frameworks/electron/README.md b/frameworks/electron/README.md index b07a6f7d..bbaf190e 100644 --- a/frameworks/electron/README.md +++ b/frameworks/electron/README.md @@ -1,23 +1,241 @@ -# Electron samples +# Hello World Sample for Electron -This directory contains Electron examples demonstrating desktop apps using the Dynamsoft Barcode Reader (JavaScript edition). +[Electron](https://www.electronjs.org/) is a framework for creating native applications with web technologies. Follow this guide to learn how to implement [Dynamsoft Barcode Reader JavaScript SDK](https://www.dynamsoft.com/barcode-reader/sdk-javascript/) (hereafter called "the library") into an Electron application. -**Included examples** +In this guide, we will be using [`dynamsoft-barcode-reader-bundle 11.4.2000`](https://www.npmjs.com/package/dynamsoft-barcode-reader-bundle/v/11.4.2000). -- scan-using-foundational-api/ — Electron demo using foundational API. -- scan-using-rtu-api/ — Electron demo using RTU API. +> Note: +> +> If you're looking to integrate DBR-JS into a framework that we don't yet have a sample, don't worry! We have a [comprehensive guide](https://www.dynamsoft.com/barcode-reader/docs/web/programming/javascript/user-guide/use-in-framework.html) that provides detailed instruction and best practices for a seamless integration into any frameworks! +> +> Additionally, we're here to help! Please don't hesitate to [contact us](#Support) for any support or questions you might have. -## Quick start +## Official Sample -1. Change to a subexample directory, e.g.: +* Hello World in Electron - Source Code - ```bash - cd scan-using-foundational-api - ``` +## Preparation -2. Follow the subexample README for exact steps (typically: npm install && npm run start or npm run electron). +Make sure you have [node](https://nodejs.org/) installed. `node 16.20.1` and `electron 26.4.1` are used in this article. -## Notes +## Quick Start -- Desktop examples may require additional native build steps for packaging. Run via the provided dev command. -- See the repository root README.md for general usage and license information. \ No newline at end of file +```cmd +npm install +npm start +``` + +A window should open to view the sample application + +## Creating the sample project + +In this section, we will be creating an Electron application utilizing the Dynamsoft Barcode Reader bundle sdk. + +We'll be exploring how you could create a page that not only enables barcode scanning via a webcam or a built-in camera, but also decode barcodes from local images. + +By the end of this guide, you'll have a good understanding of the SDK and be ready to discover more ways to use it! + +### Initialize project + +```cmd +mkdir my-app && cd my-app +npm init +``` + +`npm init` will prompt you to configure some fields in your `package.json`. Note that the `entry point` should be `main.js` (it will be created later). + +### Install the necessary libraries + +```cmd +npm install electron --save-dev +npm install dynamsoft-capture-vision-std@1.4.10 -E +npm install dynamsoft-image-processing@2.4.20 -E +npm install dynamsoft-barcode-reader-bundle@11.4.2000 -E +``` + +## Start to implement + +### Create a main.js file + +As defined in the `package.json` file, `main.js` is the entry point of the application. + +Create a `main.js` file at the root folder, and define it like this: + +```javascript +/* /main.js */ +const { app, BrowserWindow } = require("electron"); + +function createWindow() { + const win = new BrowserWindow({ + width: 800, + height: 600, + webPreferences: { + nativeWindowOpen: true, + }, + }); + + win.loadFile("index.html"); +} + +app.whenReady().then(() => { + createWindow(); + + app.on("activate", () => { + if (BrowserWindow.getAllWindows().length === 0) { + createWindow(); + } + }); +}); + +app.on("window-all-closed", () => { + if (process.platform !== "darwin") { + app.quit(); + } +}); +``` + +Two modules are imported in this file: + +* `app`: controls the application's event lifecycle. +* `BrowserWindow`: creates and manages application windows. + +The code basically opens `index.html` in a window. For more information, check out [Electron Quick Start](https://www.electronjs.org/docs/latest/tutorial/quick-start). + +### Create an `index.html` file + +As defined above, `index.html` is the file that will be loaded into the crated window. + +Create an `index.html` file at the root folder, and define it like this: + +```html + + + + + + + + Dynamsoft Barcode Reader Sample - Electron + + + + +

Hello World for Electron

+
+
+ Results: +
+ + + +``` + +### Create an `action.js` file + +`index.html` will load `action.js`, which makes use of libraries to read barcodes from a video input. + +Create the `action.js` file at the root folder, and define it like this: + +```javascript +/* /action.js */ +// Configures the paths where the .wasm files and other necessary resources for modules are located. +Dynamsoft.Core.CoreModule.engineResourcePaths = { + dbrBundle: "./node_modules/dynamsoft-barcode-reader-bundle/dist/", +}; + +/** LICENSE ALERT - README + * To use the library, you need to first specify a license key using the API "initLicense()" as shown below. + */ + +Dynamsoft.License.LicenseManager.initLicense("DLS2eyJvcmdhbml6YXRpb25JRCI6IjIwMDAwMSJ9", { + executeNow: true, +}); + +/** + * You can visit https://www.dynamsoft.com/customer/license/trialLicense?utm_source=samples&product=dbr&package=js to get your own trial license good for 30 days. + * Note that if you downloaded this sample from Dynamsoft while logged in, the above license key may already be your own 30-day trial license. + * For more information, see https://www.dynamsoft.com/barcode-reader/docs/web/programming/javascript/user-guide/index.html?ver=11.4.2000&cVer=true#specify-the-license&utm_source=samples or contact support@dynamsoft.com. + * LICENSE ALERT - THE END + */ + +// Optional. Preload .wasm file for reading barcodes. It will save time on the initial decoding by skipping the resource loading. +Dynamsoft.Core.CoreModule.loadWasm(); + +(async () => { + // Defined globally for easy debugging. + let cameraEnhancer, cvRouter; + + try { + // Create a `CameraView` instance for UI control and a `CameraEnhancer` instance for camera control. + const cameraView = await Dynamsoft.DCE.CameraView.createInstance(); + cameraEnhancer = await Dynamsoft.DCE.CameraEnhancer.createInstance(cameraView); + // Get default UI and append it to DOM. + document.querySelector("#camera-view-container").append(cameraView.getUIElement()); + + // Create a `CaptureVisionRouter` instance and set `CameraEnhancer` instance as its image source. + cvRouter = await Dynamsoft.CVR.CaptureVisionRouter.createInstance(); + cvRouter.setInput(cameraEnhancer); + + // Define a callback for results. + cvRouter.addResultReceiver({ + onDecodedBarcodesReceived: (result) => { + if (!result.barcodeResultItems.length) return; + + const resultsContainer = document.querySelector("#results"); + resultsContainer.textContent = ""; + console.log(result); + for (let item of result.barcodeResultItems) { + resultsContainer.textContent += `${item.formatString}: ${item.text}\n\n`; + } + }, + }); + + // Filter out unchecked and duplicate results. + const filter = new Dynamsoft.Utility.MultiFrameResultCrossFilter(); + // Filter out unchecked barcodes. + filter.enableResultCrossVerification("barcode", true); + // Filter out duplicate barcodes within 3 seconds. + filter.enableResultDeduplication("barcode", true); + await cvRouter.addResultFilter(filter); + + // Open camera and start scanning single barcode. + await cameraEnhancer.open(); + cameraView.setScanLaserVisible(true); + await cvRouter.startCapturing("ReadSingleBarcode"); + } catch (ex) { + let errMsg = ex.message || ex; + console.error(ex); + alert(errMsg); + } +})(); +``` + +### Create an `style.css` file + +`index.html` will load `style.css`, which defines the styles for the UI. + +Create the `style.css` file at the root folder. Note that this is customizable! + +```css +#results { + width: 100%; + height: 10vh; + overflow: auto; + white-space: pre-wrap; +} +``` + +## Run the application + +Run the application with the following command and see how it goes. + +```cmd +npm start +``` + +## Support + +If you have any questions, feel free to [contact Dynamsoft support](https://www.dynamsoft.com/company/contact?utm_source=sampleReadme). diff --git a/frameworks/electron/scan-using-foundational-api/action.js b/frameworks/electron/action.js similarity index 95% rename from frameworks/electron/scan-using-foundational-api/action.js rename to frameworks/electron/action.js index 8c70bb15..9b4bb76a 100644 --- a/frameworks/electron/scan-using-foundational-api/action.js +++ b/frameworks/electron/action.js @@ -7,12 +7,12 @@ Dynamsoft.Core.CoreModule.engineResourcePaths = { * To use the library, you need to first specify a license key using the API "initLicense()" as shown below. */ -Dynamsoft.License.LicenseManager.initLicense("DLS2eyJvcmdhbml6YXRpb25JRCI6IjIwMDAwMSJ9", { executeNow: true }); +Dynamsoft.License.LicenseManager.initLicense("DLS2eyJvcmdhbml6YXRpb25JRCI6IjIwMDAwMSJ9"); /** * You can visit https://www.dynamsoft.com/customer/license/trialLicense?utm_source=samples&product=dbr&package=js to get your own trial license good for 30 days. * Note that if you downloaded this sample from Dynamsoft while logged in, the above license key may already be your own 30-day trial license. - * For more information, see https://www.dynamsoft.com/barcode-reader/docs/web/programming/javascript/user-guide/index.html?ver=11.2.4000&cVer=true#specify-the-license&utm_source=samples or contact support@dynamsoft.com. + * For more information, see https://www.dynamsoft.com/barcode-reader/docs/web/programming/javascript/user-guide/index.html?ver=11.4.2000&cVer=true#specify-the-license&utm_source=samples or contact support@dynamsoft.com. * LICENSE ALERT - THE END */ @@ -38,7 +38,7 @@ Dynamsoft.Core.CoreModule.loadWasm(); cvRouter.setInput(cameraEnhancer); // Define a callback for results. - cvRouter.addResultReceiver({ + await cvRouter.addResultReceiver({ onDecodedBarcodesReceived: (result) => { if (!result.barcodeResultItems.length) return; diff --git a/frameworks/electron/scan-using-foundational-api/index.html b/frameworks/electron/index.html similarity index 100% rename from frameworks/electron/scan-using-foundational-api/index.html rename to frameworks/electron/index.html diff --git a/frameworks/electron/scan-using-foundational-api/main.js b/frameworks/electron/main.js similarity index 100% rename from frameworks/electron/scan-using-foundational-api/main.js rename to frameworks/electron/main.js diff --git a/frameworks/electron/scan-using-foundational-api/package.json b/frameworks/electron/package.json similarity index 89% rename from frameworks/electron/scan-using-foundational-api/package.json rename to frameworks/electron/package.json index 5f6d1d80..bdd9c1c8 100644 --- a/frameworks/electron/scan-using-foundational-api/package.json +++ b/frameworks/electron/package.json @@ -18,9 +18,9 @@ }, "homepage": "https://github.com/Dynamsoft/barcode-reader-javascript-samples#readme", "devDependencies": { - "electron": "^33.2.0" + "electron": "39.8.5" }, "dependencies": { - "dynamsoft-barcode-reader-bundle": "11.2.4000" + "dynamsoft-barcode-reader-bundle": "11.4.2000" } -} +} \ No newline at end of file diff --git a/frameworks/electron/scan-using-foundational-api/README.md b/frameworks/electron/scan-using-foundational-api/README.md deleted file mode 100644 index a6dd47ed..00000000 --- a/frameworks/electron/scan-using-foundational-api/README.md +++ /dev/null @@ -1,241 +0,0 @@ -# Hello World Sample for Electron - -[Electron](https://www.electronjs.org/) is a framework for creating native applications with web technologies. Follow this guide to learn how to implement [Dynamsoft Barcode Reader JavaScript SDK](https://www.dynamsoft.com/barcode-reader/sdk-javascript/) (hereafter called "the library") into an Electron application. - -In this guide, we will be using [`dynamsoft-barcode-reader-bundle 11.2.4000`](https://www.npmjs.com/package/dynamsoft-barcode-reader-bundle/v/11.2.4000). - -> Note: -> -> If you’re looking to integrate DBR-JS into a framework that we don't yet have a sample, don't worry! We have a [comprehensive guide](https://www.dynamsoft.com/barcode-reader/docs/web/programming/javascript/user-guide/use-in-framework.html) that provides detailed instruction and best practices for a seamless integration into any frameworks! -> -> Additionally, we're here to help! Please don't hesitate to [contact us](#Support) for any support or questions you might have. - -## Official Sample - -* Hello World in Electron - Source Code - -## Preparation - -Make sure you have [node](https://nodejs.org/) installed. `node 16.20.1` and `electron 26.4.1` are used in this article. - -## Quick Start - -```cmd -npm install -npm start -``` - -A window should open to view the sample application - -## Creating the sample project - -In this section, we will be creating an Electron application utilizing the Dynamsoft Barcode Reader bundle sdk. - -We'll be exploring how you could create a page that not only enables barcode scanning via a webcam or a built-in camera, but also decode barcodes from local images. - -By the end of this guide, you'll have a good understanding of the SDK and be ready to discover more ways to use it! - -### Initialize project - -```cmd -mkdir my-app && cd my-app -npm init -``` - -`npm init` will prompt you to configure some fields in your `package.json`. Note that the `entry point` should be `main.js` (it will be created later). - -### Install the necessary libraries - -```cmd -npm install electron --save-dev -npm install dynamsoft-capture-vision-std@1.4.10 -E -npm install dynamsoft-image-processing@2.4.20 -E -npm install dynamsoft-barcode-reader-bundle@11.2.4000 -E -``` - -## Start to implement - -### Create a main.js file - -As defined in the `package.json` file, `main.js` is the entry point of the application. - -Create a `main.js` file at the root folder, and define it like this: - -```javascript -/* /main.js */ -const { app, BrowserWindow } = require("electron"); - -function createWindow() { - const win = new BrowserWindow({ - width: 800, - height: 600, - webPreferences: { - nativeWindowOpen: true, - }, - }); - - win.loadFile("index.html"); -} - -app.whenReady().then(() => { - createWindow(); - - app.on("activate", () => { - if (BrowserWindow.getAllWindows().length === 0) { - createWindow(); - } - }); -}); - -app.on("window-all-closed", () => { - if (process.platform !== "darwin") { - app.quit(); - } -}); -``` - -Two modules are imported in this file: - -* `app`: controls the application's event lifecycle. -* `BrowserWindow`: creates and manages application windows. - -The code basically opens `index.html` in a window. For more information, check out [Electron Quick Start](https://www.electronjs.org/docs/latest/tutorial/quick-start). - -### Create an `index.html` file - -As defined above, `index.html` is the file that will be loaded into the crated window. - -Create an `index.html` file at the root folder, and define it like this: - -```html - - - - - - - - Dynamsoft Barcode Reader Sample - Electron - - - - -

Hello World for Electron

-
-
- Results: -
- - - -``` - -### Create an `action.js` file - -`index.html` will load `action.js`, which makes use of libraries to read barcodes from a video input. - -Create the `action.js` file at the root folder, and define it like this: - -```javascript -/* /action.js */ -// Configures the paths where the .wasm files and other necessary resources for modules are located. -Dynamsoft.Core.CoreModule.engineResourcePaths = { - dbrBundle: "./node_modules/dynamsoft-barcode-reader-bundle/dist/", -}; - -/** LICENSE ALERT - README - * To use the library, you need to first specify a license key using the API "initLicense()" as shown below. - */ - -Dynamsoft.License.LicenseManager.initLicense("DLS2eyJvcmdhbml6YXRpb25JRCI6IjIwMDAwMSJ9", { - executeNow: true, -}); - -/** - * You can visit https://www.dynamsoft.com/customer/license/trialLicense?utm_source=samples&product=dbr&package=js to get your own trial license good for 30 days. - * Note that if you downloaded this sample from Dynamsoft while logged in, the above license key may already be your own 30-day trial license. - * For more information, see https://www.dynamsoft.com/barcode-reader/docs/web/programming/javascript/user-guide/index.html?ver=11.2.4000&cVer=true#specify-the-license&utm_source=samples or contact support@dynamsoft.com. - * LICENSE ALERT - THE END - */ - -// Optional. Preload .wasm file for reading barcodes. It will save time on the initial decoding by skipping the resource loading. -Dynamsoft.Core.CoreModule.loadWasm(); - -(async () => { - // Defined globally for easy debugging. - let cameraEnhancer, cvRouter; - - try { - // Create a `CameraView` instance for UI control and a `CameraEnhancer` instance for camera control. - const cameraView = await Dynamsoft.DCE.CameraView.createInstance(); - cameraEnhancer = await Dynamsoft.DCE.CameraEnhancer.createInstance(cameraView); - // Get default UI and append it to DOM. - document.querySelector("#camera-view-container").append(cameraView.getUIElement()); - - // Create a `CaptureVisionRouter` instance and set `CameraEnhancer` instance as its image source. - cvRouter = await Dynamsoft.CVR.CaptureVisionRouter.createInstance(); - cvRouter.setInput(cameraEnhancer); - - // Define a callback for results. - cvRouter.addResultReceiver({ - onDecodedBarcodesReceived: (result) => { - if (!result.barcodeResultItems.length) return; - - const resultsContainer = document.querySelector("#results"); - resultsContainer.textContent = ""; - console.log(result); - for (let item of result.barcodeResultItems) { - resultsContainer.textContent += `${item.formatString}: ${item.text}\n\n`; - } - }, - }); - - // Filter out unchecked and duplicate results. - const filter = new Dynamsoft.Utility.MultiFrameResultCrossFilter(); - // Filter out unchecked barcodes. - filter.enableResultCrossVerification("barcode", true); - // Filter out duplicate barcodes within 3 seconds. - filter.enableResultDeduplication("barcode", true); - await cvRouter.addResultFilter(filter); - - // Open camera and start scanning single barcode. - await cameraEnhancer.open(); - cameraView.setScanLaserVisible(true); - await cvRouter.startCapturing("ReadSingleBarcode"); - } catch (ex) { - let errMsg = ex.message || ex; - console.error(ex); - alert(errMsg); - } -})(); -``` - -### Create an `style.css` file - -`index.html` will load `style.css`, which defines the styles for the UI. - -Create the `style.css` file at the root folder. Note that this is customizable! - -```css -#results { - width: 100%; - height: 10vh; - overflow: auto; - white-space: pre-wrap; -} -``` - -## Run the application - -Run the application with the following command and see how it goes. - -```cmd -npm start -``` - -## Support - -If you have any questions, feel free to [contact Dynamsoft support](https://www.dynamsoft.com/company/contact?utm_source=sampleReadme). diff --git a/frameworks/electron/scan-using-rtu-api/README.md b/frameworks/electron/scan-using-rtu-api/README.md deleted file mode 100644 index 072cdc2f..00000000 --- a/frameworks/electron/scan-using-rtu-api/README.md +++ /dev/null @@ -1,31 +0,0 @@ -# 📦 Scan Single Barcode - Electron - -This sample demonstrates how to use the `BarcodeScanner` API from the [Dynamsoft Barcode Reader JavaScript SDK](https://www.dynamsoft.com/barcode-reader/sdk-javascript/) in a **Electron** app to scan a single barcode using the camera. - -## ✨ Features - -- Easy integration with pre-built UI -- Renders barcodeScanner inside a container -- Scans one barcode at a time from video - -## 🚀 Quick Start - -### 1. Install Dependencies - -```bash -npm install -``` - -### 2. Start the App - -```bash -npm run start -``` - -## 📌 Customization - -Please check the official [documentation](https://dynamsoft.com/barcode-reader/docs/web/programming/javascript/user-guide/barcode-scanner-customization.html). - -## 📄 Support - -If you have any questions, feel free to [contact Dynamsoft Support](https://www.dynamsoft.com/company/contact?utm_source=sampleReadme). diff --git a/frameworks/electron/scan-using-rtu-api/action.js b/frameworks/electron/scan-using-rtu-api/action.js deleted file mode 100644 index 3c1d2cd7..00000000 --- a/frameworks/electron/scan-using-rtu-api/action.js +++ /dev/null @@ -1,34 +0,0 @@ -// Configuration object for initializing the BarcodeScanner instance. Refer to https://www.dynamsoft.com/barcode-reader/docs/web/programming/javascript/api-reference/barcode-scanner.html#barcodescannerconfig -let config = { - license: "DLS2eyJvcmdhbml6YXRpb25JRCI6IjIwMDAwMSJ9", // Replace with your Dynamsoft license key - container: document.querySelector(".barcode-scanner-view"), // Specify where to render the scanner UI - - /* - scanMode controls the scanning behavior: - - SM_MULTI_UNIQUE: Continuously scans and collects each unique barcode. - - SM_SINGLE: Stops scanning after the first barcode is detected. - */ - scanMode: Dynamsoft.EnumScanMode.SM_MULTI_UNIQUE, - - // showUploadImageButton: true, - // scannerViewConfig: { - // showFlashButton: true, - // cameraSwitchControl: "toggleFrontBack", - // }, - - // The watermark can be removed via showPoweredByDynamsoft configuration option. - // showPoweredByDynamsoft: false, -}; - -// Create a new instance of the Dynamsoft Barcode Scanner -const barcodeScanner = new Dynamsoft.BarcodeScanner(config); - -// Launch the scanner and handle the scanned result -barcodeScanner.launch().then((result) => { - // Display the first detected barcode's text in an alert - if (result.barcodeResults.length) { - alert(result.barcodeResults[0].text); - } -}).catch((err) => { - alert(err.message || err); -});; diff --git a/frameworks/electron/scan-using-rtu-api/index.html b/frameworks/electron/scan-using-rtu-api/index.html deleted file mode 100644 index d887df60..00000000 --- a/frameworks/electron/scan-using-rtu-api/index.html +++ /dev/null @@ -1,61 +0,0 @@ - - - - - - - - Dynamsoft Barcode Scanner Sample - Hello World (Decode via Camera) - - - - -

- Hello World (Scan One Single Barcode via Camera) -

- -
- - - - - - - - - - - - diff --git a/frameworks/electron/scan-using-rtu-api/main.js b/frameworks/electron/scan-using-rtu-api/main.js deleted file mode 100644 index 452d42f9..00000000 --- a/frameworks/electron/scan-using-rtu-api/main.js +++ /dev/null @@ -1,29 +0,0 @@ -const { app, BrowserWindow } = require("electron"); - -function createWindow() { - const win = new BrowserWindow({ - width: 800, - height: 600, - webPreferences: { - nativeWindowOpen: true, - }, - }); - - win.loadFile("index.html"); -} - -app.whenReady().then(() => { - createWindow(); - - app.on("activate", () => { - if (BrowserWindow.getAllWindows().length === 0) { - createWindow(); - } - }); -}); - -app.on("window-all-closed", () => { - if (process.platform !== "darwin") { - app.quit(); - } -}); diff --git a/frameworks/electron/scan-using-rtu-api/package.json b/frameworks/electron/scan-using-rtu-api/package.json deleted file mode 100644 index 9cbd8e51..00000000 --- a/frameworks/electron/scan-using-rtu-api/package.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "name": "dbrjs-electron-rtu", - "version": "1.2.0", - "description": "How to read barcodes from a video input in an Electron App", - "main": "main.js", - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1", - "start": "electron ." - }, - "repository": { - "type": "git", - "url": "git+https://github.com/Dynamsoft/barcode-reader-javascript-samples.git" - }, - "author": "Dynamsoft", - "license": "ISC", - "bugs": { - "url": "https://github.com/Dynamsoft/barcode-reader-javascript-samples/issues" - }, - "homepage": "https://github.com/Dynamsoft/barcode-reader-javascript-samples#readme", - "devDependencies": { - "electron": "^33.2.0" - }, - "dependencies": { - "dynamsoft-barcode-reader-bundle": "11.2.4000" - } -} diff --git a/frameworks/electron/scan-using-rtu-api/style.css b/frameworks/electron/scan-using-rtu-api/style.css deleted file mode 100644 index 917e0cc1..00000000 --- a/frameworks/electron/scan-using-rtu-api/style.css +++ /dev/null @@ -1,6 +0,0 @@ -#results { - width: 100%; - height: 10vh; - overflow: auto; - white-space: pre-wrap; -} diff --git a/frameworks/electron/scan-using-foundational-api/style.css b/frameworks/electron/style.css similarity index 100% rename from frameworks/electron/scan-using-foundational-api/style.css rename to frameworks/electron/style.css diff --git a/frameworks/es6/README.md b/frameworks/es6/README.md index b6f0e81a..84474249 100644 --- a/frameworks/es6/README.md +++ b/frameworks/es6/README.md @@ -1,18 +1,67 @@ -# ES6 samples +# Hello World Sample for ES6 (Decode via Camera) -This directory contains plain ES6 module examples demonstrating basic usage of the Dynamsoft Barcode Reader in vanilla JavaScript (ES6 modules). +[ES6 modules](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules) allow you to use modern JavaScript features with native import/export syntax. Follow this guide to learn how to implement [Dynamsoft Barcode Reader JavaScript SDK](https://www.dynamsoft.com/barcode-reader/sdk-javascript/) (hereafter called "the library") into an ES6 application using the foundational API to decode barcodes from a live camera stream. -**Included examples** +In this guide, we will be using [`dynamsoft-barcode-reader-bundle 11.4.2000`](https://www.npmjs.com/package/dynamsoft-barcode-reader-bundle/v/11.4.2000). -- scan-using-foundational-api/ — Plain ES6 page using foundational API. -- scan-using-rtu-api/ — ES6 page using RTU API. +> Note: +> +> If you're looking to integrate DBR-JS into a framework that we don't yet have a sample, don't worry! We have a [comprehensive guide](https://www.dynamsoft.com/barcode-reader/docs/web/programming/javascript/user-guide/use-in-framework.html) that provides detailed instruction and best practices for a seamless integration into any frameworks! +> +> Additionally, we're here to help! Please don't hesitate to [contact us](#Support) for any support or questions you might have. -## Quick start +## Official Sample -1. Change to the example directory (or open repository root). -2. Serve files with a local static server and open the HTML page (e.g., python -m http.server or npx http-server). +* Hello World in ES6 (Decode via Camera) - Source Code -## Notes +## Usage -- ES6 modules require serving over HTTP; opening files directly in the browser may not work. -- See the repository root README.md for general usage and license information. \ No newline at end of file +Open `es6.html` in a web browser (via `http://` or `https://` protocol, not `file://`). + +## Features + +This sample demonstrates: +- Using ES6 module imports to load the Dynamsoft Barcode Reader bundle +- Creating a `CameraEnhancer` instance for camera control +- Creating a `CaptureVisionRouter` instance for barcode scanning +- Implementing result filtering to remove duplicates and unchecked results +- Displaying decoded barcode results in real-time + +## Implementation Highlights + +### ES6 Module Import + +```javascript +import { + CoreModule, + LicenseManager, + CaptureVisionRouter, + CameraView, + CameraEnhancer, + MultiFrameResultCrossFilter, +} from "https://cdn.jsdelivr.net/npm/dynamsoft-barcode-reader-bundle@11.4.2000/dist/dbr.bundle.mjs"; +``` + +### Camera Setup + +```javascript +const cameraView = await CameraView.createInstance(); +const cameraEnhancer = await CameraEnhancer.createInstance(cameraView); +document.querySelector("#camera-view-container").append(cameraView.getUIElement()); +``` + +### Barcode Scanning + +```javascript +const cvRouter = await CaptureVisionRouter.createInstance(); +cvRouter.setInput(cameraEnhancer); +await cvRouter.startCapturing("ReadSingleBarcode"); +``` + +## 📌 Customization + +For more advanced customization options, please check the official [documentation](https://www.dynamsoft.com/barcode-reader/docs/web/programming/javascript/user-guide/index.html). + +## 📄 Support + +If you have any questions, feel free to [contact Dynamsoft Support](https://www.dynamsoft.com/company/contact?utm_source=sampleReadme). diff --git a/frameworks/es6/scan-using-foundational-api/es6.html b/frameworks/es6/es6.html similarity index 92% rename from frameworks/es6/scan-using-foundational-api/es6.html rename to frameworks/es6/es6.html index b75fa4c9..adfa97b2 100644 --- a/frameworks/es6/scan-using-foundational-api/es6.html +++ b/frameworks/es6/es6.html @@ -6,7 +6,6 @@ - Dynamsoft Barcode Reader Sample - Hello World for ES6 (Decode via Camera) @@ -23,18 +22,18 @@

Hello World for ES6 (Decode via Camera)

CameraView, CameraEnhancer, MultiFrameResultCrossFilter, - } from "https://cdn.jsdelivr.net/npm/dynamsoft-barcode-reader-bundle@11.2.4000/dist/dbr.bundle.mjs"; + } from "https://cdn.jsdelivr.net/npm/dynamsoft-barcode-reader-bundle@11.4.2000/dist/dbr.bundle.mjs"; /** LICENSE ALERT - README * To use the library, you need to first specify a license key using the API "initLicense()" as shown below. */ - LicenseManager.initLicense("DLS2eyJvcmdhbml6YXRpb25JRCI6IjIwMDAwMSJ9", { executeNow: true }); + LicenseManager.initLicense("DLS2eyJvcmdhbml6YXRpb25JRCI6IjIwMDAwMSJ9"); /** * You can visit https://www.dynamsoft.com/customer/license/trialLicense?utm_source=samples&product=dbr&package=js to get your own trial license good for 30 days. * Note that if you downloaded this sample from Dynamsoft while logged in, the above license key may already be your own 30-day trial license. - * For more information, see https://www.dynamsoft.com/barcode-reader/docs/web/programming/javascript/user-guide/index.html?ver=11.2.4000&cVer=true#specify-the-license&utm_source=samples or contact support@dynamsoft.com. + * For more information, see https://www.dynamsoft.com/barcode-reader/docs/web/programming/javascript/user-guide/index.html?ver=11.4.2000&cVer=true#specify-the-license&utm_source=samples or contact support@dynamsoft.com. * LICENSE ALERT - THE END */ @@ -53,13 +52,12 @@

Hello World for ES6 (Decode via Camera)

// Hide the "Powered by Message" overlay on the scanner view // cameraView.setPowerByMessageVisible(false); - // Create a `CaptureVisionRouter` instance and set `CameraEnhancer` instance as its image source. const cvRouter = await CaptureVisionRouter.createInstance(); cvRouter.setInput(cameraEnhancer); // Define a callback for results. - cvRouter.addResultReceiver({ + await cvRouter.addResultReceiver({ onDecodedBarcodesReceived: (result) => { if (!result.barcodeResultItems.length) return; diff --git a/frameworks/es6/scan-using-rtu-api/es6.html b/frameworks/es6/scan-using-rtu-api/es6.html deleted file mode 100644 index 07a8dbf8..00000000 --- a/frameworks/es6/scan-using-rtu-api/es6.html +++ /dev/null @@ -1,100 +0,0 @@ - - - - - - - - Dynamsoft Barcode Scanner Sample - Hello World (Decode via Camera) - - - - -

- Hello World (Scan One Single Barcode via Camera) -

- -
- - - - - - - - \ No newline at end of file diff --git a/frameworks/native-ts/README.md b/frameworks/native-ts/README.md deleted file mode 100644 index 558d624b..00000000 --- a/frameworks/native-ts/README.md +++ /dev/null @@ -1,23 +0,0 @@ -# Native TypeScript samples - -This directory contains TypeScript-based native examples demonstrating how to use the Dynamsoft Barcode Reader in TypeScript projects. - -**Included examples** - -- scan-using-foundational-api/ — TypeScript example with build config. -- scan-using-rtu-api/ — RTU API example in TypeScript. - -## Quick start - -1. Change to a subexample directory, e.g.: - - ```bash - cd scan-using-foundational-api - ``` - -2. Follow the subexample README for build/run steps (typically: npm install && npm run build / npm run dev). - -## Notes - -- Use the included build tooling (rollup/tsconfig) as described in each subexample. -- See the repository root README.md for general usage and license information. \ No newline at end of file diff --git a/frameworks/native-ts/scan-using-foundational-api/index.ts b/frameworks/native-ts/index.ts similarity index 98% rename from frameworks/native-ts/scan-using-foundational-api/index.ts rename to frameworks/native-ts/index.ts index 217f27d1..eab0f4cb 100644 --- a/frameworks/native-ts/scan-using-foundational-api/index.ts +++ b/frameworks/native-ts/index.ts @@ -38,7 +38,7 @@ let cvRouter: CaptureVisionRouter; cvRouter.setInput(cameraEnhancer); // Define a callback for results. - cvRouter.addResultReceiver({ + await cvRouter.addResultReceiver({ onDecodedBarcodesReceived: (result: DecodedBarcodesResult) => { if (!result.barcodeResultItems.length) return; diff --git a/frameworks/native-ts/scan-using-foundational-api/package.json b/frameworks/native-ts/package.json similarity index 90% rename from frameworks/native-ts/scan-using-foundational-api/package.json rename to frameworks/native-ts/package.json index 8cf816e8..71c7fba2 100644 --- a/frameworks/native-ts/scan-using-foundational-api/package.json +++ b/frameworks/native-ts/package.json @@ -11,7 +11,7 @@ "license": "ISC", "description": "", "dependencies": { - "dynamsoft-barcode-reader-bundle": "11.2.4000" + "dynamsoft-barcode-reader-bundle": "11.4.2000" }, "devDependencies": { "@rollup/plugin-node-resolve": "^15.3.0", diff --git a/frameworks/native-ts/scan-using-foundational-api/index.html b/frameworks/native-ts/public/index.html similarity index 78% rename from frameworks/native-ts/scan-using-foundational-api/index.html rename to frameworks/native-ts/public/index.html index 6abae2bc..2d1346b9 100644 --- a/frameworks/native-ts/scan-using-foundational-api/index.html +++ b/frameworks/native-ts/public/index.html @@ -6,7 +6,6 @@ - Dynamsoft Barcode Reader Sample - Hello World (Decode via Camera) @@ -15,7 +14,7 @@

Hello World (Decode via Camera)

Results:
- + \ No newline at end of file diff --git a/frameworks/native-ts/scan-using-rtu-api/rollup.config.mjs b/frameworks/native-ts/rollup.config.mjs similarity index 99% rename from frameworks/native-ts/scan-using-rtu-api/rollup.config.mjs rename to frameworks/native-ts/rollup.config.mjs index dab19334..027f6c96 100644 --- a/frameworks/native-ts/scan-using-rtu-api/rollup.config.mjs +++ b/frameworks/native-ts/rollup.config.mjs @@ -25,4 +25,4 @@ export default async() => { ], }, ]; -}; +}; \ No newline at end of file diff --git a/frameworks/native-ts/scan-using-foundational-api/rollup.config.mjs b/frameworks/native-ts/scan-using-foundational-api/rollup.config.mjs deleted file mode 100644 index d78fbc65..00000000 --- a/frameworks/native-ts/scan-using-foundational-api/rollup.config.mjs +++ /dev/null @@ -1,27 +0,0 @@ -import typescript from "@rollup/plugin-typescript"; -import { nodeResolve } from "@rollup/plugin-node-resolve"; - -// https://rollupjs.org/guide/en/#configuration-files -export default () => { - // cvr.js: Only use for - - - \ No newline at end of file diff --git a/frameworks/native-ts/scan-using-rtu-api/tsconfig.json b/frameworks/native-ts/scan-using-rtu-api/tsconfig.json deleted file mode 100644 index 35e8318a..00000000 --- a/frameworks/native-ts/scan-using-rtu-api/tsconfig.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "compilerOptions": { - "target": "es2017", - "lib": [ - "dom", - "dom.iterable", - "esnext" - ], - "allowJs": true, - "esModuleInterop": true, - "allowSyntheticDefaultImports": true, - "strict": true, - "forceConsistentCasingInFileNames": true, - "noFallthroughCasesInSwitch": true, - "module": "ESNext", - "moduleResolution": "node", - "resolveJsonModule": true, - "isolatedModules": true, - "noEmit": true, - } -} diff --git a/frameworks/native-ts/scan-using-foundational-api/tsconfig.json b/frameworks/native-ts/tsconfig.json similarity index 95% rename from frameworks/native-ts/scan-using-foundational-api/tsconfig.json rename to frameworks/native-ts/tsconfig.json index 35e8318a..a27ff72d 100644 --- a/frameworks/native-ts/scan-using-foundational-api/tsconfig.json +++ b/frameworks/native-ts/tsconfig.json @@ -17,5 +17,6 @@ "resolveJsonModule": true, "isolatedModules": true, "noEmit": true, + "outDir": "dist" } } diff --git a/frameworks/next/scan-using-foundational-api/.eslintrc.json b/frameworks/next/.eslintrc.json similarity index 100% rename from frameworks/next/scan-using-foundational-api/.eslintrc.json rename to frameworks/next/.eslintrc.json diff --git a/frameworks/next/scan-using-foundational-api/.gitignore b/frameworks/next/.gitignore similarity index 100% rename from frameworks/next/scan-using-foundational-api/.gitignore rename to frameworks/next/.gitignore diff --git a/frameworks/next/README.md b/frameworks/next/README.md index f7d70cf5..15b8aea4 100644 --- a/frameworks/next/README.md +++ b/frameworks/next/README.md @@ -1,24 +1,434 @@ -# Next.js samples +# Hello World Sample for Next.js -This directory contains Next.js examples demonstrating how to integrate the Dynamsoft Barcode Reader into Next.js apps. +[Next.js](https://nextjs.org/) is a react framework that enables functionalities such as server-side rendering and generating static websites for react-based web applications. Follow this guide to learn how to implement [Dynamsoft Barcode Reader JavaScript SDK](https://www.dynamsoft.com/barcode-reader/sdk-javascript/) (hereafter called "the library") into a Next.js application. Note that in this sample, `TypeScript` is used. -**Included examples** +In this guide, we will be using [`dynamsoft-barcode-reader-bundle 11.4.2000`](https://www.npmjs.com/package/dynamsoft-barcode-reader-bundle/v/11.4.2000). -- `scan-using-foundational-api/` — Next.js example using the foundational API. -- `scan-using-rtu-api/` — Next.js example using the RTU API. (**Recommended for most users**) +> Note: +> +> If you're looking to integrate DBR-JS into a framework that we don't yet have a sample, don't worry! We have a [comprehensive guide](https://www.dynamsoft.com/barcode-reader/docs/web/programming/javascript/user-guide/use-in-framework.html) that provides detailed instruction and best practices for a seamless integration into any frameworks! +> +> Additionally, we're here to help! Please don't hesitate to [contact us](#Support) for any support or questions you might have. -## Quick start +## Official Sample -1. Change to the example directory, e.g.: +* Hello World in Next.js - Source Code - ```bash - cd scan-using-foundational-api +## Preparation - ``` +Make sure you have [node](https://nodejs.org/) installed. `node 18.17.1` and `next 14.2.3` are used in the example below. -2. Follow the subexample README for exact steps (typically: npm install && npm run dev). +## Quick Start -## Notes +```cmd +npm install +npm run dev +``` +Then open http://localhost:3000/ to view the sample app. -- Run via the framework dev server to ensure module loading and camera access work correctly. -- See the repository root README.md for general usage and license information. \ No newline at end of file +## Creating the sample project + +In this section, we will be creating a Next.js application utilizing the Dynamsoft Barcode Reader bundle sdk. + +We'll be exploring how you could create a page that not only enables barcode scanning via a webcam or a built-in camera, but also decode barcodes from local images. + +By the end of this guide, you'll have a good understanding of the SDK and be ready to discover more ways to use it! + +### Create a [Next.js](https://nextjs.org/) Application bootstrapped with [create-next-app](https://github.com/vercel/next.js/tree/canary/packages/create-next-app) with TypeScript. + +```cmd +npx create-next-app@latest +``` + +On installation, you will be prompted to configure your project.\ +You can customize these options according to your preferences.\ +Below is the configuration used for this sample. + +``` +√ What is your project named? ... my-app +√ Would you like to use TypeScript? ... Yes +√ Would you like to use ESLint? ... Yes +√ Would you like to use Tailwind CSS? ... No +√ Would you like to use `src/` directory? ... No +√ Would you like to use App Router? (recommended) ... Yes +√ Would you like to customize the default import alias (@/*)? ... Yes +√ What import alias would you like configured? ... @/* +``` + +### **CD** to the root directory of the application and install necessary libraries + +```cmd +cd my-app +npm install dynamsoft-barcode-reader-bundle@11.4.2000 -E +``` + +## Start to implement + +### Add file "dynamsoft.config.ts" at the root of the app to configure libraries + +```typescript +/* /dynamsoft.config.ts */ +import { CoreModule } from "dynamsoft-core"; +import { LicenseManager } from "dynamsoft-license"; +import "dynamsoft-barcode-reader"; + +// Configures the paths where the .wasm files and other necessary resources for modules are located. +CoreModule.engineResourcePaths.rootDirectory = "https://cdn.jsdelivr.net/npm/"; + +/** LICENSE ALERT - README + * To use the library, you need to first specify a license key using the API "initLicense()" as shown below. + */ + +LicenseManager.initLicense("DLS2eyJvcmdhbml6YXRpb25JRCI6IjIwMDAwMSJ9", { + executeNow: true, +}); + +/** + * You can visit https://www.dynamsoft.com/customer/license/trialLicense?utm_source=samples&product=dbr&package=js to get your own trial license good for 30 days. + * Note that if you downloaded this sample from Dynamsoft while logged in, the above license key may already be your own 30-day trial license. + * For more information, see https://www.dynamsoft.com/barcode-reader/docs/web/programming/javascript/user-guide/index.html?ver=11.4.2000&cVer=true#specify-the-license&utm_source=samples or contact support@dynamsoft.com. + * LICENSE ALERT - THE END + */ + +// Optional. Preload .wasm file for reading barcodes. It will save time on the initial decoding by skipping the resource loading. +CoreModule.loadWasm(); +``` + +> Note: +> +> * `initLicense()` specify a license key to use the library. You can visit https://www.dynamsoft.com/customer/license/trialLicense?utm_source=sample&product=dbr&package=js to get your own trial license good for 30 days. +> * `engineResourcePaths` tells the library where to get the necessary resources at runtime. + +### Build directory structure + +* Create a directory `components` on the root directory, and then create another two directories, `VideoCapture` and `ImageCapture` under `/components/`. + +### Create and edit the `VideoCapture` component + +* Create `VideoCapture.tsx` under `/components/VideoCapture/`. The `VideoCapture` component helps decode barcodes via camera. + +* In `VideoCapture.tsx`, add code for initializing and destroying some instances. For our stylesheet (CSS) specification, please refer to our [source code](#Official-Sample). + +```tsx +/* /components/VideoCapture/VideoCapture.tsx */ +import React, { useEffect, useRef, useState } from "react"; +import "../../dynamsoft.config"; // import side effects. The license, engineResourcePath, so on. +import { CameraEnhancer, CameraView } from "dynamsoft-camera-enhancer"; +import { CaptureVisionRouter } from "dynamsoft-capture-vision-router"; +import { MultiFrameResultCrossFilter } from "dynamsoft-utility"; +import "./VideoCapture.css"; + +const componentDestroyedErrorMsg = "VideoCapture Component Destroyed"; + +function VideoCapture() { + const cameraViewContainer = useRef(null); + const [resultsText, setResultText] = useState(""); + + useEffect((): any => { + let resolveInit: () => void; + const pInit: Promise = new Promise((r) => { + resolveInit = r; + }); + let isDestroyed = false; + + let cvRouter: CaptureVisionRouter; + let cameraEnhancer: CameraEnhancer; + + (async () => { + try { + // Create a `CameraEnhancer` instance for camera control and a `CameraView` instance for UI control. + const cameraView = await CameraView.createInstance(); + if (isDestroyed) { + throw Error(componentDestroyedErrorMsg); + } // Check if component is destroyed after every async + cameraEnhancer = await CameraEnhancer.createInstance(cameraView); + if (isDestroyed) { + throw Error(componentDestroyedErrorMsg); + } + + // Get default UI and append it to DOM. + cameraViewContainer.current!.append(cameraView.getUIElement()); + + // Create a `CaptureVisionRouter` instance and set `CameraEnhancer` instance as its image source. + cvRouter = await CaptureVisionRouter.createInstance(); + if (isDestroyed) { + throw Error(componentDestroyedErrorMsg); + } + cvRouter.setInput(cameraEnhancer); + + // Define a callback for results. + cvRouter.addResultReceiver({ + onDecodedBarcodesReceived: (result) => { + if (!result.barcodeResultItems.length) return; + + let _resultText = ""; + console.log(result); + for (let item of result.barcodeResultItems) { + _resultText += `${item.formatString}: ${item.text}\n\n`; + } + setResultText(_resultText); + }, + }); + + // Filter out unchecked and duplicate results. + const filter = new MultiFrameResultCrossFilter(); + // Filter out unchecked barcodes. + filter.enableResultCrossVerification("barcode", true); + // Filter out duplicate barcodes within 3 seconds. + filter.enableResultDeduplication("barcode", true); + await cvRouter.addResultFilter(filter); + if (isDestroyed) { + throw Error(componentDestroyedErrorMsg); + } + + // Open camera and start scanning single barcode. + await cameraEnhancer.open(); + cameraView.setScanLaserVisible(true); + if (isDestroyed) { + throw Error(componentDestroyedErrorMsg); + } + await cvRouter.startCapturing("ReadSingleBarcode"); + if (isDestroyed) { + throw Error(componentDestroyedErrorMsg); + } + } catch (ex: any) { + if ((ex as Error)?.message === componentDestroyedErrorMsg) { + console.log(componentDestroyedErrorMsg); + } else { + let errMsg = ex.message || ex; + console.error(ex); + alert(errMsg); + } + } + })(); + + // Resolve pInit promise once initialization is complete. + resolveInit!(); + + // componentWillUnmount. dispose cvRouter when it's no longer needed + return async () => { + isDestroyed = true; + try { + // Wait for the pInit to complete before disposing resources. + await pInit; + cvRouter?.dispose(); + cameraEnhancer?.dispose(); + } catch (_) {} + }; + }, []); + + return ( +
+
+
+ Results: +
{resultsText}
+
+ ); +} + +export default VideoCapture; +``` + +> Note: +> +> * The component should never update so that events bound to the UI stay valid. In this component, the useEffect() hook is used to handle the component's mount and unmount lifecycle events, and there are no state updates that would cause a re-render. +> * If you're looking to customize the UI, the UI customization feature are provided by the auxiliary SDK "Dynamsoft Camera Enhancer". For more details, refer to our [User Guide](https://www.dynamsoft.com/barcode-reader/docs/web/programming/javascript/user-guide/index.html#customizing-the-ui) + +### Create and edit the `ImageCapture` component + +* Create `ImageCapture.tsx` under `/components/ImageCapture/`. The `ImageCapture` component helps decode barcodes in an image. + +* In `ImageCapture.tsx`, add code for initializing and destroying the `CaptureVisionRouter` instance. For our stylesheet (CSS) specification, please refer to our [source code](#Official-Sample). + +```tsx +/* /components/ImageCapture/ImageCapture.tsx */ +import React, { useRef, useEffect, MutableRefObject, useState } from "react"; +import "../../dynamsoft.config"; // import side effects. The license, engineResourcePath, so on. +import { EnumCapturedResultItemType } from "dynamsoft-core"; +import { BarcodeResultItem } from "dynamsoft-barcode-reader"; +import { CaptureVisionRouter } from "dynamsoft-capture-vision-router"; +import "./ImageCapture.css"; + +function ImageCapture() { + const [resultText, setResultText] = useState(""); + + let pCvRouter: MutableRefObject | null> = useRef(null); + let isDestroyed = useRef(false); + + const captureImage = async (e: React.ChangeEvent) => { + let files = [...(e.target.files as any as File[])]; + e.target.value = ""; // reset input + let _resultText = ""; + + try { + // ensure cvRouter is created only once + const cvRouter = await (pCvRouter.current = pCvRouter.current || CaptureVisionRouter.createInstance()); + if (isDestroyed.current) return; + + for (let file of files) { + // Decode selected image with 'ReadBarcodes_ReadRateFirst' template. + const result = await cvRouter.capture(file, "ReadBarcodes_ReadRateFirst"); + console.log(result); + if (isDestroyed.current) return; + + let _resultText = ""; + // Print file name if there's multiple files + if (files.length > 1) { + _resultText += `\n${file.name}:\n`; + } + for (let _item of result.items) { + if (_item.type !== EnumCapturedResultItemType.CRIT_BARCODE) { + continue; // check if captured result item is a barcode + } + let item = _item as BarcodeResultItem; + _resultText += item.text + "\n"; // output the decoded barcode text + } + // If no items are found, display that no barcode was detected + if (!result.items.length) _resultText = "No barcode found"; + setResultText(_resultText); + } + } catch (ex: any) { + let errMsg = ex.message || ex; + console.error(ex); + alert(errMsg); + } + }; + + useEffect((): any => { + // In 'development', React runs setup and cleanup one extra time before the actual setup in Strict Mode. + isDestroyed.current = false; + + // componentWillUnmount. dispose cvRouter when it's no longer needed + return () => { + isDestroyed.current = true; + if (pCvRouter.current) { + pCvRouter.current.then((cvRouter) => { + cvRouter.dispose(); + }).catch((_) => { }) + } + }; + }, []); + + return ( +
+
+ +
+
{resultText}
+
+ ); +} + +export default ImageCapture; +``` + +### Add the `VideoCapture` and `ImageCapture` component to `page.tsx` + +* On `/app/page.tsx`, we will edit the component so that it offers buttons to switch components between `VideoCapture` and `ImageCapture`. + +* Add following code to `page.tsx`. For our stylesheet (CSS) specification, please refer to our [source code](#Official-Sample). + +```tsx +/* /app/page.tsx */ +"use client"; + +import dynamic from "next/dynamic"; +import { useState } from "react"; +import "./page.css"; + +const VideoCapture = dynamic(() => import("../components/VideoCapture/VideoCapture"), { + ssr: false, +}); +const ImageCapture = dynamic(() => import("../components/ImageCapture/ImageCapture"), { + ssr: false, +}); + +enum Modes { + VIDEO_CAPTURE = "video", + IMAGE_CAPTURE = "image", +} + +export default function Home() { + const [mode, setMode] = useState(Modes.VIDEO_CAPTURE); + + const showVideoCapture = () => setMode(Modes.VIDEO_CAPTURE); + const showImageCapture = () => setMode(Modes.IMAGE_CAPTURE); + + return ( +
+
+

Hello World for Next.js

+
+
+ + +
+
{mode === Modes.VIDEO_CAPTURE ? : }
+
+ ); +} +``` +> Note: +> +> With Next.js' dynamic `import()`, we can significantly improve the initial load speed and performance when we dynamically import Dynamsoft's Barcode Scanning component on-demand. +> +> Additionally, we need to set `{ ssr: false }` since the component is client-side only and could not be rendered server-side. +> +> Read more: [https://nextjs.org/learn-pages-router/seo/improve/dynamic-import-components](https://nextjs.org/learn-pages-router/seo/improve/dynamic-import-components) + +* Try running the project. + +```cmd +npm run dev +``` + +If you followed all the steps correctly, you will have a working page that turns one of the cameras hooked to or built in your computer or mobile device into a barcode scanner. Also, if you want to decode a local image, just click the `Image Decode` button and select the image you want to decode. Once barcodes are found, the results will show in a dialog. + +## Development server + +Runs the app in the development mode.\ +Open [http://localhost:3000](http://localhost:3000) to view it in the browser. + +The page will reload if you make edits.\ +You will also see any lint errors in the console. + +## Learn More + +To learn more about Next.js, take a look at the following resources: + +- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. +- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. + +You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome! + +## Deploy on Vercel + +The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. + +Check out [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details. + +## Support + +If you have any questions, feel free to [contact Dynamsoft Support](https://www.dynamsoft.com/company/contact?utm_source=sampleReadme). diff --git a/frameworks/next/scan-using-foundational-api/app/favicon.ico b/frameworks/next/app/favicon.ico similarity index 100% rename from frameworks/next/scan-using-foundational-api/app/favicon.ico rename to frameworks/next/app/favicon.ico diff --git a/frameworks/next/scan-using-foundational-api/app/globals.css b/frameworks/next/app/globals.css similarity index 100% rename from frameworks/next/scan-using-foundational-api/app/globals.css rename to frameworks/next/app/globals.css diff --git a/frameworks/next/scan-using-foundational-api/app/layout.tsx b/frameworks/next/app/layout.tsx similarity index 100% rename from frameworks/next/scan-using-foundational-api/app/layout.tsx rename to frameworks/next/app/layout.tsx diff --git a/frameworks/next/scan-using-foundational-api/app/page.css b/frameworks/next/app/page.css similarity index 100% rename from frameworks/next/scan-using-foundational-api/app/page.css rename to frameworks/next/app/page.css diff --git a/frameworks/next/scan-using-foundational-api/app/page.tsx b/frameworks/next/app/page.tsx similarity index 100% rename from frameworks/next/scan-using-foundational-api/app/page.tsx rename to frameworks/next/app/page.tsx diff --git a/frameworks/next/scan-using-foundational-api/components/ImageCapture/ImageCapture.css b/frameworks/next/components/ImageCapture/ImageCapture.css similarity index 100% rename from frameworks/next/scan-using-foundational-api/components/ImageCapture/ImageCapture.css rename to frameworks/next/components/ImageCapture/ImageCapture.css diff --git a/frameworks/next/scan-using-foundational-api/components/ImageCapture/ImageCapture.tsx b/frameworks/next/components/ImageCapture/ImageCapture.tsx similarity index 100% rename from frameworks/next/scan-using-foundational-api/components/ImageCapture/ImageCapture.tsx rename to frameworks/next/components/ImageCapture/ImageCapture.tsx diff --git a/frameworks/next/scan-using-foundational-api/components/VideoCapture/VideoCapture.css b/frameworks/next/components/VideoCapture/VideoCapture.css similarity index 100% rename from frameworks/next/scan-using-foundational-api/components/VideoCapture/VideoCapture.css rename to frameworks/next/components/VideoCapture/VideoCapture.css diff --git a/frameworks/next/scan-using-foundational-api/components/VideoCapture/VideoCapture.tsx b/frameworks/next/components/VideoCapture/VideoCapture.tsx similarity index 98% rename from frameworks/next/scan-using-foundational-api/components/VideoCapture/VideoCapture.tsx rename to frameworks/next/components/VideoCapture/VideoCapture.tsx index f0443a20..065cc4e9 100644 --- a/frameworks/next/scan-using-foundational-api/components/VideoCapture/VideoCapture.tsx +++ b/frameworks/next/components/VideoCapture/VideoCapture.tsx @@ -45,7 +45,7 @@ function VideoCapture() { cvRouter.setInput(cameraEnhancer); // Define a callback for results. - cvRouter.addResultReceiver({ + await cvRouter.addResultReceiver({ onDecodedBarcodesReceived: (result) => { if (!result.barcodeResultItems.length) return; diff --git a/frameworks/react/scan-using-foundational-api/src/dynamsoft.config.ts b/frameworks/next/dynamsoft.config.ts similarity index 92% rename from frameworks/react/scan-using-foundational-api/src/dynamsoft.config.ts rename to frameworks/next/dynamsoft.config.ts index b25d65cb..0061db7a 100644 --- a/frameworks/react/scan-using-foundational-api/src/dynamsoft.config.ts +++ b/frameworks/next/dynamsoft.config.ts @@ -7,12 +7,12 @@ CoreModule.engineResourcePaths.rootDirectory = "https://cdn.jsdelivr.net/npm/"; * To use the library, you need to first specify a license key using the API "initLicense()" as shown below. */ -LicenseManager.initLicense("DLS2eyJvcmdhbml6YXRpb25JRCI6IjIwMDAwMSJ9", { executeNow: true }); +LicenseManager.initLicense("DLS2eyJvcmdhbml6YXRpb25JRCI6IjIwMDAwMSJ9"); /** * You can visit https://www.dynamsoft.com/customer/license/trialLicense?utm_source=samples&product=dbr&package=js to get your own trial license good for 30 days. * Note that if you downloaded this sample from Dynamsoft while logged in, the above license key may already be your own 30-day trial license. - * For more information, see https://www.dynamsoft.com/barcode-reader/docs/web/programming/javascript/user-guide/index.html?ver=11.2.4000&cVer=true#specify-the-license&utm_source=samples or contact support@dynamsoft.com. + * For more information, see https://www.dynamsoft.com/barcode-reader/docs/web/programming/javascript/user-guide/index.html?ver=11.4.2000&cVer=true#specify-the-license&utm_source=samples or contact support@dynamsoft.com. * LICENSE ALERT - THE END */ diff --git a/frameworks/next/scan-using-foundational-api/next.config.mjs b/frameworks/next/next.config.mjs similarity index 100% rename from frameworks/next/scan-using-foundational-api/next.config.mjs rename to frameworks/next/next.config.mjs diff --git a/frameworks/next/scan-using-foundational-api/package.json b/frameworks/next/package.json similarity index 85% rename from frameworks/next/scan-using-foundational-api/package.json rename to frameworks/next/package.json index 1c0daba4..c79cf265 100644 --- a/frameworks/next/scan-using-foundational-api/package.json +++ b/frameworks/next/package.json @@ -11,8 +11,8 @@ "dependencies": { "react": "^18", "react-dom": "^18", - "next": "14.2.35", - "dynamsoft-barcode-reader-bundle": "11.2.4000" + "next": "16.1.7", + "dynamsoft-barcode-reader-bundle": "11.4.2000" }, "devDependencies": { "typescript": "^5", @@ -22,4 +22,4 @@ "eslint": "^8", "eslint-config-next": "14.2.3" } -} +} \ No newline at end of file diff --git a/frameworks/next/scan-using-foundational-api/public/next.svg b/frameworks/next/public/next.svg similarity index 100% rename from frameworks/next/scan-using-foundational-api/public/next.svg rename to frameworks/next/public/next.svg diff --git a/frameworks/next/scan-using-foundational-api/public/vercel.svg b/frameworks/next/public/vercel.svg similarity index 100% rename from frameworks/next/scan-using-foundational-api/public/vercel.svg rename to frameworks/next/public/vercel.svg diff --git a/frameworks/next/scan-using-foundational-api/README.md b/frameworks/next/scan-using-foundational-api/README.md deleted file mode 100644 index 3e9cad23..00000000 --- a/frameworks/next/scan-using-foundational-api/README.md +++ /dev/null @@ -1,434 +0,0 @@ -# Hello World Sample for Next.js - -[Next.js](https://nextjs.org/) is a react framework that enables functionalities such as server-side rendering and generating static websites for react-based web applications. Follow this guide to learn how to implement [Dynamsoft Barcode Reader JavaScript SDK](https://www.dynamsoft.com/barcode-reader/sdk-javascript/) (hereafter called "the library") into a Next.js application. Note that in this sample, `TypeScript` is used. - -In this guide, we will be using [`dynamsoft-barcode-reader-bundle 11.2.4000`](https://www.npmjs.com/package/dynamsoft-barcode-reader-bundle/v/11.2.4000). - -> Note: -> -> If you’re looking to integrate DBR-JS into a framework that we don't yet have a sample, don't worry! We have a [comprehensive guide](https://www.dynamsoft.com/barcode-reader/docs/web/programming/javascript/user-guide/use-in-framework.html) that provides detailed instruction and best practices for a seamless integration into any frameworks! -> -> Additionally, we're here to help! Please don't hesitate to [contact us](#Support) for any support or questions you might have. - -## Official Sample - -* Hello World in Next.js - Source Code - -## Preparation - -Make sure you have [node](https://nodejs.org/) installed. `node 18.17.1` and `next 14.2.3` are used in the example below. - -## Quick Start - -```cmd -npm install -npm run dev -``` -Then open http://localhost:3000/ to view the sample app. - -## Creating the sample project - -In this section, we will be creating a Next.js application utilizing the Dynamsoft Barcode Reader bundle sdk. - -We'll be exploring how you could create a page that not only enables barcode scanning via a webcam or a built-in camera, but also decode barcodes from local images. - -By the end of this guide, you'll have a good understanding of the SDK and be ready to discover more ways to use it! - -### Create a [Next.js](https://nextjs.org/) Application bootstrapped with [create-next-app](https://github.com/vercel/next.js/tree/canary/packages/create-next-app) with TypeScript. - -```cmd -npx create-next-app@latest -``` - -On installation, you will be prompted to configure your project.\ -You can customize these options according to your preferences.\ -Below is the configuration used for this sample. - -``` -√ What is your project named? ... my-app -√ Would you like to use TypeScript? ... Yes -√ Would you like to use ESLint? ... Yes -√ Would you like to use Tailwind CSS? ... No -√ Would you like to use `src/` directory? ... No -√ Would you like to use App Router? (recommended) ... Yes -√ Would you like to customize the default import alias (@/*)? ... Yes -√ What import alias would you like configured? ... @/* -``` - -### **CD** to the root directory of the application and install necessary libraries - -```cmd -cd my-app -npm install dynamsoft-barcode-reader-bundle@11.2.4000 -E -``` - -## Start to implement - -### Add file "dynamsoft.config.ts" at the root of the app to configure libraries - -```typescript -/* /dynamsoft.config.ts */ -import { CoreModule } from "dynamsoft-core"; -import { LicenseManager } from "dynamsoft-license"; -import "dynamsoft-barcode-reader"; - -// Configures the paths where the .wasm files and other necessary resources for modules are located. -CoreModule.engineResourcePaths.rootDirectory = "https://cdn.jsdelivr.net/npm/"; - -/** LICENSE ALERT - README - * To use the library, you need to first specify a license key using the API "initLicense()" as shown below. - */ - -LicenseManager.initLicense("DLS2eyJvcmdhbml6YXRpb25JRCI6IjIwMDAwMSJ9", { - executeNow: true, -}); - -/** - * You can visit https://www.dynamsoft.com/customer/license/trialLicense?utm_source=samples&product=dbr&package=js to get your own trial license good for 30 days. - * Note that if you downloaded this sample from Dynamsoft while logged in, the above license key may already be your own 30-day trial license. - * For more information, see https://www.dynamsoft.com/barcode-reader/docs/web/programming/javascript/user-guide/index.html?ver=11.2.4000&cVer=true#specify-the-license&utm_source=samples or contact support@dynamsoft.com. - * LICENSE ALERT - THE END - */ - -// Optional. Preload .wasm file for reading barcodes. It will save time on the initial decoding by skipping the resource loading. -CoreModule.loadWasm(); -``` - -> Note: -> -> * `initLicense()` specify a license key to use the library. You can visit https://www.dynamsoft.com/customer/license/trialLicense?utm_source=sample&product=dbr&package=js to get your own trial license good for 30 days. -> * `engineResourcePaths` tells the library where to get the necessary resources at runtime. - -### Build directory structure - -* Create a directory `components` on the root directory, and then create another two directories, `VideoCapture` and `ImageCapture` under `/components/`. - -### Create and edit the `VideoCapture` component - -* Create `VideoCapture.tsx` under `/components/VideoCapture/`. The `VideoCapture` component helps decode barcodes via camera. - -* In `VideoCapture.tsx`, add code for initializing and destroying some instances. For our stylesheet (CSS) specification, please refer to our [source code](#Official-Sample). - -```tsx -/* /components/VideoCapture/VideoCapture.tsx */ -import React, { useEffect, useRef, useState } from "react"; -import "../../dynamsoft.config"; // import side effects. The license, engineResourcePath, so on. -import { CameraEnhancer, CameraView } from "dynamsoft-camera-enhancer"; -import { CaptureVisionRouter } from "dynamsoft-capture-vision-router"; -import { MultiFrameResultCrossFilter } from "dynamsoft-utility"; -import "./VideoCapture.css"; - -const componentDestroyedErrorMsg = "VideoCapture Component Destroyed"; - -function VideoCapture() { - const cameraViewContainer = useRef(null); - const [resultsText, setResultText] = useState(""); - - useEffect((): any => { - let resolveInit: () => void; - const pInit: Promise = new Promise((r) => { - resolveInit = r; - }); - let isDestroyed = false; - - let cvRouter: CaptureVisionRouter; - let cameraEnhancer: CameraEnhancer; - - (async () => { - try { - // Create a `CameraEnhancer` instance for camera control and a `CameraView` instance for UI control. - const cameraView = await CameraView.createInstance(); - if (isDestroyed) { - throw Error(componentDestroyedErrorMsg); - } // Check if component is destroyed after every async - cameraEnhancer = await CameraEnhancer.createInstance(cameraView); - if (isDestroyed) { - throw Error(componentDestroyedErrorMsg); - } - - // Get default UI and append it to DOM. - cameraViewContainer.current!.append(cameraView.getUIElement()); - - // Create a `CaptureVisionRouter` instance and set `CameraEnhancer` instance as its image source. - cvRouter = await CaptureVisionRouter.createInstance(); - if (isDestroyed) { - throw Error(componentDestroyedErrorMsg); - } - cvRouter.setInput(cameraEnhancer); - - // Define a callback for results. - cvRouter.addResultReceiver({ - onDecodedBarcodesReceived: (result) => { - if (!result.barcodeResultItems.length) return; - - let _resultText = ""; - console.log(result); - for (let item of result.barcodeResultItems) { - _resultText += `${item.formatString}: ${item.text}\n\n`; - } - setResultText(_resultText); - }, - }); - - // Filter out unchecked and duplicate results. - const filter = new MultiFrameResultCrossFilter(); - // Filter out unchecked barcodes. - filter.enableResultCrossVerification("barcode", true); - // Filter out duplicate barcodes within 3 seconds. - filter.enableResultDeduplication("barcode", true); - await cvRouter.addResultFilter(filter); - if (isDestroyed) { - throw Error(componentDestroyedErrorMsg); - } - - // Open camera and start scanning single barcode. - await cameraEnhancer.open(); - cameraView.setScanLaserVisible(true); - if (isDestroyed) { - throw Error(componentDestroyedErrorMsg); - } - await cvRouter.startCapturing("ReadSingleBarcode"); - if (isDestroyed) { - throw Error(componentDestroyedErrorMsg); - } - } catch (ex: any) { - if ((ex as Error)?.message === componentDestroyedErrorMsg) { - console.log(componentDestroyedErrorMsg); - } else { - let errMsg = ex.message || ex; - console.error(ex); - alert(errMsg); - } - } - })(); - - // Resolve pInit promise once initialization is complete. - resolveInit!(); - - // componentWillUnmount. dispose cvRouter when it's no longer needed - return async () => { - isDestroyed = true; - try { - // Wait for the pInit to complete before disposing resources. - await pInit; - cvRouter?.dispose(); - cameraEnhancer?.dispose(); - } catch (_) {} - }; - }, []); - - return ( -
-
-
- Results: -
{resultsText}
-
- ); -} - -export default VideoCapture; -``` - -> Note: -> -> * The component should never update so that events bound to the UI stay valid. In this component, the useEffect() hook is used to handle the component’s mount and unmount lifecycle events, and there are no state updates that would cause a re-render. -> * If you're looking to customize the UI, the UI customization feature are provided by the auxiliary SDK "Dynamsoft Camera Enhancer". For more details, refer to our [User Guide](https://www.dynamsoft.com/barcode-reader/docs/web/programming/javascript/user-guide/index.html#customizing-the-ui) - -### Create and edit the `ImageCapture` component - -* Create `ImageCapture.tsx` under `/components/ImageCapture/`. The `ImageCapture` component helps decode barcodes in an image. - -* In `ImageCapture.tsx`, add code for initializing and destroying the `CaptureVisionRouter` instance. For our stylesheet (CSS) specification, please refer to our [source code](#Official-Sample). - -```tsx -/* /components/ImageCapture/ImageCapture.tsx */ -import React, { useRef, useEffect, MutableRefObject, useState } from "react"; -import "../../dynamsoft.config"; // import side effects. The license, engineResourcePath, so on. -import { EnumCapturedResultItemType } from "dynamsoft-core"; -import { BarcodeResultItem } from "dynamsoft-barcode-reader"; -import { CaptureVisionRouter } from "dynamsoft-capture-vision-router"; -import "./ImageCapture.css"; - -function ImageCapture() { - const [resultText, setResultText] = useState(""); - - let pCvRouter: MutableRefObject | null> = useRef(null); - let isDestroyed = useRef(false); - - const captureImage = async (e: React.ChangeEvent) => { - let files = [...(e.target.files as any as File[])]; - e.target.value = ""; // reset input - let _resultText = ""; - - try { - // ensure cvRouter is created only once - const cvRouter = await (pCvRouter.current = pCvRouter.current || CaptureVisionRouter.createInstance()); - if (isDestroyed.current) return; - - for (let file of files) { - // Decode selected image with 'ReadBarcodes_ReadRateFirst' template. - const result = await cvRouter.capture(file, "ReadBarcodes_ReadRateFirst"); - console.log(result); - if (isDestroyed.current) return; - - let _resultText = ""; - // Print file name if there's multiple files - if (files.length > 1) { - _resultText += `\n${file.name}:\n`; - } - for (let _item of result.items) { - if (_item.type !== EnumCapturedResultItemType.CRIT_BARCODE) { - continue; // check if captured result item is a barcode - } - let item = _item as BarcodeResultItem; - _resultText += item.text + "\n"; // output the decoded barcode text - } - // If no items are found, display that no barcode was detected - if (!result.items.length) _resultText = "No barcode found"; - setResultText(_resultText); - } - } catch (ex: any) { - let errMsg = ex.message || ex; - console.error(ex); - alert(errMsg); - } - }; - - useEffect((): any => { - // In 'development', React runs setup and cleanup one extra time before the actual setup in Strict Mode. - isDestroyed.current = false; - - // componentWillUnmount. dispose cvRouter when it's no longer needed - return () => { - isDestroyed.current = true; - if (pCvRouter.current) { - pCvRouter.current.then((cvRouter) => { - cvRouter.dispose(); - }).catch((_) => { }) - } - }; - }, []); - - return ( -
-
- -
-
{resultText}
-
- ); -} - -export default ImageCapture; -``` - -### Add the `VideoCapture` and `ImageCapture` component to `page.tsx` - -* On `/app/page.tsx`, we will edit the component so that it offers buttons to switch components between `VideoCapture` and `ImageCapture`. - -* Add following code to `page.tsx`. For our stylesheet (CSS) specification, please refer to our [source code](#Official-Sample). - -```tsx -/* /app/page.tsx */ -"use client"; - -import dynamic from "next/dynamic"; -import { useState } from "react"; -import "./page.css"; - -const VideoCapture = dynamic(() => import("../components/VideoCapture/VideoCapture"), { - ssr: false, -}); -const ImageCapture = dynamic(() => import("../components/ImageCapture/ImageCapture"), { - ssr: false, -}); - -enum Modes { - VIDEO_CAPTURE = "video", - IMAGE_CAPTURE = "image", -} - -export default function Home() { - const [mode, setMode] = useState(Modes.VIDEO_CAPTURE); - - const showVideoCapture = () => setMode(Modes.VIDEO_CAPTURE); - const showImageCapture = () => setMode(Modes.IMAGE_CAPTURE); - - return ( -
-
-

Hello World for Next.js

-
-
- - -
-
{mode === Modes.VIDEO_CAPTURE ? : }
-
- ); -} -``` -> Note: -> -> With Next.js' dynamic `import()`, we can significantly improve the initial load speed and performance when we dynamically import Dynamsoft's Barcode Scanning component on-demand. -> -> Additionally, we need to set `{ ssr: false }` since the component is client-side only and could not be rendered server-side. -> -> Read more: [https://nextjs.org/learn-pages-router/seo/improve/dynamic-import-components](https://nextjs.org/learn-pages-router/seo/improve/dynamic-import-components) - -* Try running the project. - -```cmd -npm run dev -``` - -If you followed all the steps correctly, you will have a working page that turns one of the cameras hooked to or built in your computer or mobile device into a barcode scanner. Also, if you want to decode a local image, just click the `Image Decode` button and select the image you want to decode. Once barcodes are found, the results will show in a dialog. - -## Development server - -Runs the app in the development mode.\ -Open [http://localhost:3000](http://localhost:3000) to view it in the browser. - -The page will reload if you make edits.\ -You will also see any lint errors in the console. - -## Learn More - -To learn more about Next.js, take a look at the following resources: - -- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. -- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. - -You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome! - -## Deploy on Vercel - -The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. - -Check out [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details. - -## Support - -If you have any questions, feel free to [contact Dynamsoft Support](https://www.dynamsoft.com/company/contact?utm_source=sampleReadme). diff --git a/frameworks/next/scan-using-foundational-api/tsconfig.json b/frameworks/next/tsconfig.json similarity index 53% rename from frameworks/next/scan-using-foundational-api/tsconfig.json rename to frameworks/next/tsconfig.json index e7ff90fd..9e9bbf7b 100644 --- a/frameworks/next/scan-using-foundational-api/tsconfig.json +++ b/frameworks/next/tsconfig.json @@ -1,6 +1,10 @@ { "compilerOptions": { - "lib": ["dom", "dom.iterable", "esnext"], + "lib": [ + "dom", + "dom.iterable", + "esnext" + ], "allowJs": true, "skipLibCheck": true, "strict": true, @@ -10,7 +14,7 @@ "moduleResolution": "bundler", "resolveJsonModule": true, "isolatedModules": true, - "jsx": "preserve", + "jsx": "react-jsx", "incremental": true, "plugins": [ { @@ -18,9 +22,20 @@ } ], "paths": { - "@/*": ["./*"] - } + "@/*": [ + "./*" + ] + }, + "target": "ES2017" }, - "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], - "exclude": ["node_modules"] + "include": [ + "next-env.d.ts", + "**/*.ts", + "**/*.tsx", + ".next/types/**/*.ts", + ".next/dev/types/**/*.ts" + ], + "exclude": [ + "node_modules" + ] } diff --git a/frameworks/nuxt/scan-using-foundational-api/.gitignore b/frameworks/nuxt/.gitignore similarity index 100% rename from frameworks/nuxt/scan-using-foundational-api/.gitignore rename to frameworks/nuxt/.gitignore diff --git a/frameworks/nuxt/README.md b/frameworks/nuxt/README.md index 86c6af3d..bd71ee2b 100644 --- a/frameworks/nuxt/README.md +++ b/frameworks/nuxt/README.md @@ -1,23 +1,383 @@ -# Nuxt samples +# Hello World Sample for NuxtJS -This directory contains Nuxt examples demonstrating use of the Dynamsoft Barcode Reader in Nuxt projects. +[Nuxt](https://nuxtjs.org/) is a higher-level framework that builds on top of [Vue](https://vuejs.org/). Check out the following guide on how to implement [Dynamsoft Barcode Reader JavaScript SDK](https://www.dynamsoft.com/barcode-reader/sdk-javascript/) (hereafter called "the library") into a Nuxt application. Note that in this sample `TypeScript` is used. -**Included examples** +In this guide, we will be using [`dynamsoft-barcode-reader-bundle 11.4.2000`](https://www.npmjs.com/package/dynamsoft-barcode-reader-bundle/v/11.4.2000). -- `scan-using-foundational-api/` — Nuxt example using the foundational API. -- `scan-using-rtu-api/` — Nuxt example using the RTU API. (**Recommended for most users**) +> Note: +> +> If you're looking to integrate DBR-JS into a framework that we don't yet have a sample, don't worry! We have a [comprehensive guide](https://www.dynamsoft.com/barcode-reader/docs/web/programming/javascript/user-guide/use-in-framework.html) that provides detailed instruction and best practices for a seamless integration into any frameworks! +> +> Additionally, we're here to help! Please don't hesitate to [contact us](#Support) for any support or questions you might have. -## Quick start +## Official Sample -1. Change to the example directory, e.g.: +* Hello World in Nuxt - Source Code - ```bash - cd scan-using-foundational-api - ``` +## Preparation -2. Follow the subexample README for exact steps (typically: npm install && npm run dev). +Make sure you have [node](https://nodejs.org/) installed. `node 16.20.1` and `nuxt 3.2.3` are used in this article. -## Notes +## Quick Start -- Use the Nuxt dev server for best results; opening static files directly is not recommended. -- See the repository root README.md for general usage and license information. \ No newline at end of file +```cmd +npm install +npm run dev +``` + +Then open `https://localhost:3000/` to view the sample app. + +## Creating the sample project + +In this section, we will be creating a NuxtJS application utilizing the Dynamsoft Barcode Reader bundle sdk. + +We'll be exploring how you could create a page that not only enables barcode scanning via a webcam or a built-in camera, but also decode barcodes from local images. + +By the end of this guide, you'll have a good understanding of the SDK and be ready to discover more ways to use it! + +### Create a Bootstrapped Nuxt Application + +```cmd +npx nuxi@latest init my-app +``` + +You will be asked to configure quite a few things for the application during the creation. In our example, we chose the default one in every step. + +### **CD** to the root directory of the application and install the dependencies + +```cmd +cd my-app +npm install dynamsoft-barcode-reader-bundle@11.4.2000 -E +``` + +## Start to implement + +### Add file "dynamsoft.config.ts" at the root of the app to configure libraries + +```typescript +/* /dynamsoft.config.ts */ +import { CoreModule } from "dynamsoft-core"; +import { LicenseManager } from "dynamsoft-license"; +import "dynamsoft-barcode-reader"; + +// Configures the paths where the .wasm files and other necessary resources for modules are located. +CoreModule.engineResourcePaths.rootDirectory = "https://cdn.jsdelivr.net/npm/"; + +/** LICENSE ALERT - README + * To use the library, you need to first specify a license key using the API "initLicense()" as shown below. + */ + +LicenseManager.initLicense("DLS2eyJvcmdhbml6YXRpb25JRCI6IjIwMDAwMSJ9", { + executeNow: true, +}); + +/** + * You can visit https://www.dynamsoft.com/customer/license/trialLicense?utm_source=samples&product=dbr&package=js to get your own trial license good for 30 days. + * Note that if you downloaded this sample from Dynamsoft while logged in, the above license key may already be your own 30-day trial license. + * For more information, see https://www.dynamsoft.com/barcode-reader/docs/web/programming/javascript/user-guide/index.html?ver=11.4.2000&cVer=true#specify-the-license&utm_source=samples or contact support@dynamsoft.com. + * LICENSE ALERT - THE END + */ + +// Optional. Preload .wasm file for reading barcodes. It will save time on the initial decoding by skipping the resource loading. +CoreModule.loadWasm(); +``` + +> Note: +> +> * `initLicense()` specify a license key to use the library. You can visit https://www.dynamsoft.com/customer/license/trialLicense?utm_source=sample&product=dbr&package=js to get your own trial license good for 30 days. +> * `engineResourcePaths` tells the library where to get the necessary resources at runtime. + +### Create a directory "components" and create the following files inside it to represent two components + +* `VideoCapture.client.vue` +* `ImageCapture.client.vue` + +`.client` suffix means the component is rendered only client-side. + +### Edit the `VideoCapture` component + +* In `VideoCapture.client.vue`, add code for initializing and destroying some instances. The `VideoCapture` component helps decode barcodes via camera. For our stylesheet (CSS) specification, please refer to our [source code](#Official-Sample). + +```vue + + + + + + +``` +> Note: +> +> If you're looking to customize the UI, the UI customization feature are provided by the auxiliary SDK "Dynamsoft Camera Enhancer". For more details, refer to our [User Guide](https://www.dynamsoft.com/barcode-reader/docs/web/programming/javascript/user-guide/index.html#customizing-the-ui) + +### Edit the `ImageCapture` component + +* In `ImageCapture.client.vue`, add code for initializing and destroying the `CaptureVisionRouter` instance. The `ImageCapture` helps decode barcodes in an image. For our stylesheet (CSS) specification, please refer to our [source code](#Official-Sample). + +```vue + + + + + + +``` + +### Add `VideoCapture` and `ImageCapture` components in `app.vue` + +* On `/app.vue`, we will edit the component so that it offers buttons to switch components between `VideoCapture` and `ImageCapture`. + +* Add following code to `app.vue`. For our stylesheet (CSS) specification, please refer to our [source code](#Official-Sample). + +```vue + + + + +``` +> Note: +> +> Since `VideoCapture` and `ImageCapture` components are only rendered on the client side, we want to make sure that these components are not causing sie effects during the server rendering phase. We can solve this using the `client-only` component. + +* Try running the project. + +```cmd +npm run dev +``` + +If you followed all the steps correctly, you will have a working page that turns one of the cameras hooked to or built in your computer or mobile device into a barcode scanner. Also, if you want to decode a local image, just click the `Decode Image` button and select the image you want to decode. Once barcodes are found, the results will show in a dialog. + +## Project Setup + +```sh +npm install +``` + +### Compile and Hot-Reload for Development + +```sh +npm run dev +``` + +### Type-Check, Compile and Minify for Production + +```sh +npm run build +``` + +## Support + +If you have any questions, feel free to [contact Dynamsoft support](https://www.dynamsoft.com/company/contact?utm_source=sampleReadme). \ No newline at end of file diff --git a/frameworks/nuxt/scan-using-foundational-api/app.vue b/frameworks/nuxt/app.vue similarity index 80% rename from frameworks/nuxt/scan-using-foundational-api/app.vue rename to frameworks/nuxt/app.vue index 5430ef36..6c98850c 100644 --- a/frameworks/nuxt/scan-using-foundational-api/app.vue +++ b/frameworks/nuxt/app.vue @@ -5,10 +5,8 @@
- - + +
@@ -18,8 +16,6 @@ diff --git a/frameworks/nuxt/scan-using-foundational-api/components/VideoCapture.client.vue b/frameworks/nuxt/components/VideoCapture.client.vue similarity index 96% rename from frameworks/nuxt/scan-using-foundational-api/components/VideoCapture.client.vue rename to frameworks/nuxt/components/VideoCapture.client.vue index e86a3223..9242fa10 100644 --- a/frameworks/nuxt/scan-using-foundational-api/components/VideoCapture.client.vue +++ b/frameworks/nuxt/components/VideoCapture.client.vue @@ -37,7 +37,7 @@ onMounted(async () => { cvRouter.setInput(cameraEnhancer); // Define a callback for results. - cvRouter.addResultReceiver({ + await cvRouter.addResultReceiver({ onDecodedBarcodesReceived: (result) => { if (!result.barcodeResultItems.length) return; @@ -95,7 +95,7 @@ onBeforeUnmount(async () => {

- Results: +
Results:
{{ resultText }}
@@ -106,5 +106,6 @@ onBeforeUnmount(async () => { height: 10vh; overflow: auto; white-space: pre-wrap; + text-align: center; } diff --git a/frameworks/next/scan-using-foundational-api/dynamsoft.config.ts b/frameworks/nuxt/dynamsoft.config.ts similarity index 94% rename from frameworks/next/scan-using-foundational-api/dynamsoft.config.ts rename to frameworks/nuxt/dynamsoft.config.ts index b25d65cb..e54a421d 100644 --- a/frameworks/next/scan-using-foundational-api/dynamsoft.config.ts +++ b/frameworks/nuxt/dynamsoft.config.ts @@ -12,7 +12,7 @@ LicenseManager.initLicense("DLS2eyJvcmdhbml6YXRpb25JRCI6IjIwMDAwMSJ9", { execute /** * You can visit https://www.dynamsoft.com/customer/license/trialLicense?utm_source=samples&product=dbr&package=js to get your own trial license good for 30 days. * Note that if you downloaded this sample from Dynamsoft while logged in, the above license key may already be your own 30-day trial license. - * For more information, see https://www.dynamsoft.com/barcode-reader/docs/web/programming/javascript/user-guide/index.html?ver=11.2.4000&cVer=true#specify-the-license&utm_source=samples or contact support@dynamsoft.com. + * For more information, see https://www.dynamsoft.com/barcode-reader/docs/web/programming/javascript/user-guide/index.html?ver=11.4.2000&cVer=true#specify-the-license&utm_source=samples or contact support@dynamsoft.com. * LICENSE ALERT - THE END */ diff --git a/frameworks/nuxt/scan-using-foundational-api/nuxt.config.ts b/frameworks/nuxt/nuxt.config.ts similarity index 82% rename from frameworks/nuxt/scan-using-foundational-api/nuxt.config.ts rename to frameworks/nuxt/nuxt.config.ts index 8d361178..4bbb3a1b 100644 --- a/frameworks/nuxt/scan-using-foundational-api/nuxt.config.ts +++ b/frameworks/nuxt/nuxt.config.ts @@ -1,4 +1,4 @@ // https://nuxt.com/docs/api/configuration/nuxt-config export default defineNuxtConfig({ - + telemetry: false }) diff --git a/frameworks/nuxt/scan-using-foundational-api/package.json b/frameworks/nuxt/package.json similarity index 85% rename from frameworks/nuxt/scan-using-foundational-api/package.json rename to frameworks/nuxt/package.json index 000d468c..b12a47ce 100644 --- a/frameworks/nuxt/scan-using-foundational-api/package.json +++ b/frameworks/nuxt/package.json @@ -13,6 +13,6 @@ "nuxt": "3.2.3" }, "dependencies": { - "dynamsoft-barcode-reader-bundle": "11.2.4000" + "dynamsoft-barcode-reader-bundle": "11.4.2000" } } \ No newline at end of file diff --git a/frameworks/nuxt/scan-using-foundational-api/public/favicon.ico b/frameworks/nuxt/public/favicon.ico similarity index 100% rename from frameworks/nuxt/scan-using-foundational-api/public/favicon.ico rename to frameworks/nuxt/public/favicon.ico diff --git a/frameworks/nuxt/scan-using-foundational-api/README.md b/frameworks/nuxt/scan-using-foundational-api/README.md deleted file mode 100644 index 003c4582..00000000 --- a/frameworks/nuxt/scan-using-foundational-api/README.md +++ /dev/null @@ -1,383 +0,0 @@ -# Hello World Sample for NuxtJS - -[Nuxt](https://nuxtjs.org/) is a higher-level framework that builds on top of [Vue](https://vuejs.org/). Check out the following guide on how to implement [Dynamsoft Barcode Reader JavaScript SDK](https://www.dynamsoft.com/barcode-reader/sdk-javascript/) (hereafter called "the library") into a Nuxt application. Note that in this sample `TypeScript` is used. - -In this guide, we will be using [`dynamsoft-barcode-reader-bundle 11.2.4000`](https://www.npmjs.com/package/dynamsoft-barcode-reader-bundle/v/11.2.4000). - -> Note: -> -> If you’re looking to integrate DBR-JS into a framework that we don't yet have a sample, don't worry! We have a [comprehensive guide](https://www.dynamsoft.com/barcode-reader/docs/web/programming/javascript/user-guide/use-in-framework.html) that provides detailed instruction and best practices for a seamless integration into any frameworks! -> -> Additionally, we're here to help! Please don't hesitate to [contact us](#Support) for any support or questions you might have. - -## Official Sample - -* Hello World in Nuxt - Source Code - -## Preparation - -Make sure you have [node](https://nodejs.org/) installed. `node 16.20.1` and `nuxt 3.2.3` are used in this article. - -## Quick Start - -```cmd -npm install -npm run dev -``` - -Then open `https://localhost:3000/` to view the sample app. - -## Creating the sample project - -In this section, we will be creating a NuxtJS application utilizing the Dynamsoft Barcode Reader bundle sdk. - -We'll be exploring how you could create a page that not only enables barcode scanning via a webcam or a built-in camera, but also decode barcodes from local images. - -By the end of this guide, you'll have a good understanding of the SDK and be ready to discover more ways to use it! - -### Create a Bootstrapped Nuxt Application - -```cmd -npx nuxi@latest init my-app -``` - -You will be asked to configure quite a few things for the application during the creation. In our example, we chose the default one in every step. - -### **CD** to the root directory of the application and install the dependencies - -```cmd -cd my-app -npm install dynamsoft-barcode-reader-bundle@11.2.4000 -E -``` - -## Start to implement - -### Add file "dynamsoft.config.ts" at the root of the app to configure libraries - -```typescript -/* /dynamsoft.config.ts */ -import { CoreModule } from "dynamsoft-core"; -import { LicenseManager } from "dynamsoft-license"; -import "dynamsoft-barcode-reader"; - -// Configures the paths where the .wasm files and other necessary resources for modules are located. -CoreModule.engineResourcePaths.rootDirectory = "https://cdn.jsdelivr.net/npm/"; - -/** LICENSE ALERT - README - * To use the library, you need to first specify a license key using the API "initLicense()" as shown below. - */ - -LicenseManager.initLicense("DLS2eyJvcmdhbml6YXRpb25JRCI6IjIwMDAwMSJ9", { - executeNow: true, -}); - -/** - * You can visit https://www.dynamsoft.com/customer/license/trialLicense?utm_source=samples&product=dbr&package=js to get your own trial license good for 30 days. - * Note that if you downloaded this sample from Dynamsoft while logged in, the above license key may already be your own 30-day trial license. - * For more information, see https://www.dynamsoft.com/barcode-reader/docs/web/programming/javascript/user-guide/index.html?ver=11.2.4000&cVer=true#specify-the-license&utm_source=samples or contact support@dynamsoft.com. - * LICENSE ALERT - THE END - */ - -// Optional. Preload .wasm file for reading barcodes. It will save time on the initial decoding by skipping the resource loading. -CoreModule.loadWasm(); -``` - -> Note: -> -> * `initLicense()` specify a license key to use the library. You can visit https://www.dynamsoft.com/customer/license/trialLicense?utm_source=sample&product=dbr&package=js to get your own trial license good for 30 days. -> * `engineResourcePaths` tells the library where to get the necessary resources at runtime. - -### Create a directory "components" and create the following files inside it to represent two components - -* `VideoCapture.client.vue` -* `ImageCapture.client.vue` - -`.client` suffix means the component is rendered only client-side. - -### Edit the `VideoCapture` component - -* In `VideoCapture.client.vue`, add code for initializing and destroying some instances. The `VideoCapture` component helps decode barcodes via camera. For our stylesheet (CSS) specification, please refer to our [source code](#Official-Sample). - -```vue - - - - - - -``` -> Note: -> -> If you're looking to customize the UI, the UI customization feature are provided by the auxiliary SDK "Dynamsoft Camera Enhancer". For more details, refer to our [User Guide](https://www.dynamsoft.com/barcode-reader/docs/web/programming/javascript/user-guide/index.html#customizing-the-ui) - -### Edit the `ImageCapture` component - -* In `ImageCapture.client.vue`, add code for initializing and destroying the `CaptureVisionRouter` instance. The `ImageCapture` helps decode barcodes in an image. For our stylesheet (CSS) specification, please refer to our [source code](#Official-Sample). - -```vue - - - - - - -``` - -### Add `VideoCapture` and `ImageCapture` components in `app.vue` - -* On `/app.vue`, we will edit the component so that it offers buttons to switch components between `VideoCapture` and `ImageCapture`. - -* Add following code to `app.vue`. For our stylesheet (CSS) specification, please refer to our [source code](#Official-Sample). - -```vue - - - - -``` -> Note: -> -> Since `VideoCapture` and `ImageCapture` components are only rendered on the client side, we want to make sure that these components are not causing sie effects during the server rendering phase. We can solve this using the `client-only` component. - -* Try running the project. - -```cmd -npm run dev -``` - -If you followed all the steps correctly, you will have a working page that turns one of the cameras hooked to or built in your computer or mobile device into a barcode scanner. Also, if you want to decode a local image, just click the `Decode Image` button and select the image you want to decode. Once barcodes are found, the results will show in a dialog. - -## Project Setup - -```sh -npm install -``` - -### Compile and Hot-Reload for Development - -```sh -npm run dev -``` - -### Type-Check, Compile and Minify for Production - -```sh -npm run build -``` - -## Support - -If you have any questions, feel free to [contact Dynamsoft support](https://www.dynamsoft.com/company/contact?utm_source=sampleReadme). \ No newline at end of file diff --git a/frameworks/nuxt/scan-using-foundational-api/assets/main.css b/frameworks/nuxt/scan-using-foundational-api/assets/main.css deleted file mode 100644 index b458c93e..00000000 --- a/frameworks/nuxt/scan-using-foundational-api/assets/main.css +++ /dev/null @@ -1,7 +0,0 @@ -* { - margin: 0; - padding: 0; - box-sizing: border-box; - text-align: center; - } - \ No newline at end of file diff --git a/frameworks/nuxt/scan-using-foundational-api/tsconfig.json b/frameworks/nuxt/tsconfig.json similarity index 100% rename from frameworks/nuxt/scan-using-foundational-api/tsconfig.json rename to frameworks/nuxt/tsconfig.json diff --git a/frameworks/pwa/README.md b/frameworks/pwa/README.md index 46ff2b72..dbc6d279 100644 --- a/frameworks/pwa/README.md +++ b/frameworks/pwa/README.md @@ -1,23 +1,307 @@ -# PWA samples +# Hello World Sample for PWA -This directory contains Progressive Web App examples demonstrating how to use Dynamsoft Barcode Reader in PWA contexts. +[PWA](https://web.dev/progressive-web-apps/) is short for Progressive Web Apps, which are web applications designed to mimic the functionality and user experience of platform-specific (native) applications. Follow this guide to learn how to implement [Dynamsoft Barcode Reader JavaScript SDK](https://www.dynamsoft.com/barcode-reader/sdk-javascript/) (hereafter called "the library") into a PWA application. -**Included examples** +In this guide, we will be using [`dynamsoft-barcode-reader-bundle 11.4.2000](https://www.npmjs.com/package/dynamsoft-barcode-reader-bundle/v/11.4.2000). -- scan-using-foundational-api/ (helloworld-pwa.html) — PWA sample pages and service worker. -- scan-using-rtu-api/ — RTU API PWA example. +> Note: +> +> If you're looking to integrate DBR-JS into a framework that we don't yet have a sample, don't worry! We have a [comprehensive guide](https://www.dynamsoft.com/barcode-reader/docs/web/programming/javascript/user-guide/use-in-framework.html) that provides detailed instruction and best practices for a seamless integration into any frameworks! +> +> Additionally, we're here to help! Please don't hesitate to [contact us](#Support) for any support or questions you might have. -## Quick start +## Official Sample -1. Change to the example directory, e.g.: +* Hello World in PWA - Source Code - ```bash - cd scan-using-foundational-api - ``` +## Preparation -2. Serve the files over HTTPS or a local dev server and open the provided HTML (service worker requires secure context). +We will try to turn our basic "Hello World" sample into a PWA. Follow these steps: -## Notes +* Create new file named `helloworld-pwa.html` and add the following code: -- PWAs require HTTPS (or localhost) for service worker and camera features. -- See the repository root README.md for general usage and license information. \ No newline at end of file +```html + + + + + + + Dynamsoft Barcode Reader PWA Sample - Hello World + + + +

Hello World for PWA

+
+
+ Results: +
+ + + + + +``` + +* Next, set up a secure environment (HTTPS) to run the page `helloworld-pwa.html`. This is required as PWAs only run in secure environments. +> Note: +> +> In this sample, we're using IIS to set up a secure site at https://localhost. The page will be located at the root of the site so that it can be accessed at https://localhost/helloworld-pwa.html. + +## Make the app progressive + +### Register a service worker for offline support + +Service Workers form the foundation of PWAs, acting as the virtual proxy between the browser and the network. They enable offline content delivery, manage notifications, and perform heavy calculations on a separate thread + +* To use a service worker, we first need to register it. In the `helloworld-pwa.html` file, add the following code at the end of the script: + +```javascript +/* /helloworld-pwa.html */ +if ('serviceWorker' in navigator) { + navigator.serviceWorker.register('./service-worker.js'); +}; +``` + +* Next, create the `service-worker.js` file with the following content: + +```javascript +/* /service-worker.js */ +// Files to cache +const cacheName = 'helloworld-pwa'; +const appShellFiles = [ + './helloworld-pwa.html', +]; + +// Installing Service Worker +self.addEventListener("install", (e) => { + console.log("[Service Worker] Install"); + e.waitUntil( + (async () => { + const cache = await caches.open(cacheName); + console.log("[Service Worker] Caching all: app shell and content"); + await cache.addAll(appShellFiles); + })() + ); +}); + +self.addEventListener("fetch", (e) => { + e.respondWith( + (async () => { + // Fetch cached response if exists + const cachedResponse = await caches.match(e.request); + console.log(`[Service Worker] Fetching resource: ${e.request.url}`); + if (cachedResponse) { + return cachedResponse; + } + + // Otherwise, fetch from network + const response = await fetch(e.request); + const cache = await caches.open(cacheName); + console.log(`[Service Worker] Caching new resource: ${e.request.url}`); + if (e.request.method !== "POST") { + cache.put(e.request, response.clone()); + } + return response; + })() + ); +}); +``` + +With the above code, the application can now work offline because the service worker will cache the `helloworld-pwa.html` page and its related resources. + +For more information, refer to [Making PWAs work offline with Service workers](https://developer.mozilla.org/en-US/docs/Web/Progressive_web_apps/Offline_Service_workers). + +> Note: +> +> Since the files are cached, changes we make in later steps may not be reflected immediately. To ensure updates are applied, clear the cache after changes are made. You can do this by running the following code in the browser console: +> +> ```javascript +> const cacheName = 'helloworld-pwa'; +> const cache = await caches.delete(cacheName); +> ``` + +### Use a web manifest file to make the application installable + +A web manifest file contains a list of information about a website in JSON format. This information is used to enable the web app to be installed on a device. + +* Create a file named `helloworld-pwa.json` with the following content: + +```json +/* /helloworld-pwa.json */ +{ + "name": "Dynamsoft Barcode Reader Progressive Web App", + "short_name": "DBR-PWA", + "description": "Progressive Web App that reads barcodes from a video input with Dynamsoft Barcode Reader.", + "start_url": "./helloworld-pwa.html", + "scope": ".", + "display": "standalone", + "theme_color": "#B12A34", + "background_color": "#B12A34", + "icons": [ + { + "src": "./dynamsoft-512x512.png", + "sizes": "512x512", + "type": "image/png" + }, + { + "src": "./dynamsoft-192x192.png", + "sizes": "192x192", + "type": "image/png" + } + ] +} +``` + +> Note: The icon files can be found in the github repository. + +* Then we include the file in the `` block of the `helloworld-pwa.html` file as such: + +```html + + +``` + +* For compatibility on safari, we need add some `meta` in ``. + +```html + + + + + + + + + +``` + +Now, if you open the application again in your browser, you will notice an install icon appear on the right side of the address bar. When you click on it, a pop-up will appear asking if you want to install the app. + +Once installed, you can use it just like any native app. + +To enable offline functionality for Dynamsoft Barcode Reader, you'll need to cache more files. + +### Enabling offline functionality for Dynamsoft Barcode Reader + +These directories below are the resources required for Dynamsoft Barcode Reader functionality. Once added, these files are cached on installation of the service worker (i.e. `install` event), wensuring the PWA remains fully functional without any internet. + +Add this code below to the `service-worker.js` +```javascript +/* /service-worker.js */ +const engineResourcePaths = { + dbrBundle: "https://cdn.jsdelivr.net/npm/dynamsoft-barcode-reader-bundle@11.4.2000/dist/", +}; + +// Files to cache +const cacheName = "helloworld-pwa"; +const appShellFiles = [ + "./helloworld-pwa.html", + "./dynamsoft-192x192.png", + "./dynamsoft-512x512.png", + "./helloworld-pwa.json", + `${engineResourcePaths.dbrBundle}dbr.bundle.worker.js`, + `${engineResourcePaths.dbrBundle}dynamsoft-capture-vision-bundle.js` + `${engineResourcePaths.dbrBundle}dynamsoft-capture-vision-bundle.wasm`, + `${engineResourcePaths.dbrBundle}models/OneDDeblur.data`, + `${engineResourcePaths.dbrBundle}parser-resources/AADHAAR_Map.txt`, + `${engineResourcePaths.dbrBundle}parser-resources/AADHAAR.dcpres`, + `${engineResourcePaths.dbrBundle}parser-resources/AAMVA_DL_ID_WITH_MAG_STRIPE.dcpres`, + `${engineResourcePaths.dbrBundle}parser-resources/AAMVA_DL_ID.dcpres`, + `${engineResourcePaths.dbrBundle}parser-resources/AAMVA_Map.txt`, + `${engineResourcePaths.dbrBundle}parser-resources/GS1_AI_Map.txt`, + `${engineResourcePaths.dbrBundle}parser-resources/GS1_AI.txt`, + `${engineResourcePaths.dbrBundle}parser-resources/MRTD_Map.txt`, + `${engineResourcePaths.dbrBundle}parser-resources/MRTD_TD1_ID.dcpres`, + `${engineResourcePaths.dbrBundle}parser-resources/MRTD_TD2_FRENCH_ID.dcpres`, + `${engineResourcePaths.dbrBundle}parser-resources/MRTD_TD2_ID.dcpres`, + `${engineResourcePaths.dbrBundle}parser-resources/MRTD_TD2_VISA.dcpres`, + `${engineResourcePaths.dbrBundle}parser-resources/MRTD_TD3_PASSPORT.dcpres`, + `${engineResourcePaths.dbrBundle}parser-resources/MRTD_TD3_VISA.dcpres`, + `${engineResourcePaths.dbrBundle}parser-resources/SOUTH_AFRICA_DL_Map.txt`, + `${engineResourcePaths.dbrBundle}parser-resources/SOUTH_AFRICA_DL.dcpres`, + `${engineResourcePaths.dbrBundle}parser-resources/VIN_Map.txt`, + `${engineResourcePaths.dbrBundle}parser-resources/VIN.dcpres`, + `${engineResourcePaths.dbrBundle}templates/DBR-PresetTemplates.json`, + `${engineResourcePaths.dbrBundle}ui/barcode-scanner.ui.xml`, + `${engineResourcePaths.dbrBundle}ui/dce.ui.xml`, + `${engineResourcePaths.dbrBundle}ui/dls.license.dialog.html`, +]; +``` + +## Summary + +In this article we took a look at how you can turn a simple barcode reading page into a PWA that is installable, re-engageable and capable of working offline. To learn more about Progressive web apps, you can click [here](https://developer.mozilla.org/en-US/docs/Web/Progressive_web_apps). + +## Support + +If you have any questions, feel free to [contact Dynamsoft support](https://www.dynamsoft.com/company/contact?utm_source=sampleReadme). \ No newline at end of file diff --git a/frameworks/pwa/scan-using-foundational-api/dynamsoft-192x192.png b/frameworks/pwa/dynamsoft-192x192.png similarity index 100% rename from frameworks/pwa/scan-using-foundational-api/dynamsoft-192x192.png rename to frameworks/pwa/dynamsoft-192x192.png diff --git a/frameworks/pwa/scan-using-foundational-api/dynamsoft-512x512.png b/frameworks/pwa/dynamsoft-512x512.png similarity index 100% rename from frameworks/pwa/scan-using-foundational-api/dynamsoft-512x512.png rename to frameworks/pwa/dynamsoft-512x512.png diff --git a/frameworks/pwa/scan-using-foundational-api/helloworld-pwa.html b/frameworks/pwa/helloworld-pwa.html similarity index 92% rename from frameworks/pwa/scan-using-foundational-api/helloworld-pwa.html rename to frameworks/pwa/helloworld-pwa.html index 5d156f50..82ccaacc 100644 --- a/frameworks/pwa/scan-using-foundational-api/helloworld-pwa.html +++ b/frameworks/pwa/helloworld-pwa.html @@ -7,7 +7,6 @@ Dynamsoft Barcode Reader PWA Sample - Hello World (Decode via Camera) - @@ -16,6 +15,8 @@ + + @@ -24,18 +25,18 @@

Hello World for PWA


Results:
- + - - - - -``` - -* Next, set up a secure environment (HTTPS) to run the page `helloworld-pwa.html`. This is required as PWAs only run in secure environments. -> Note: -> -> In this sample, we're using IIS to set up a secure site at https://localhost. The page will be located at the root of the site so that it can be accessed at https://localhost/helloworld-pwa.html. - -## Make the app progressive - -### Register a service worker for offline support - -Service Workers form the foundation of PWAs, acting as the virtual proxy between the browser and the network. They enable offline content delivery, manage notifications, and perform heavy calculations on a separate thread - -* To use a service worker, we first need to register it. In the `helloworld-pwa.html` file, add the following code at the end of the script: - -```javascript -/* /helloworld-pwa.html */ -if ('serviceWorker' in navigator) { - navigator.serviceWorker.register('./service-worker.js'); -}; -``` - -* Next, create the `service-worker.js` file with the following content: - -```javascript -/* /service-worker.js */ -// Files to cache -const cacheName = 'helloworld-pwa'; -const appShellFiles = [ - './helloworld-pwa.html', -]; - -// Installing Service Worker -self.addEventListener("install", (e) => { - console.log("[Service Worker] Install"); - e.waitUntil( - (async () => { - const cache = await caches.open(cacheName); - console.log("[Service Worker] Caching all: app shell and content"); - await cache.addAll(appShellFiles); - })() - ); -}); - -self.addEventListener("fetch", (e) => { - e.respondWith( - (async () => { - // Fetch cached response if exists - const cachedResponse = await caches.match(e.request); - console.log(`[Service Worker] Fetching resource: ${e.request.url}`); - if (cachedResponse) { - return cachedResponse; - } - - // Otherwise, fetch from network - const response = await fetch(e.request); - const cache = await caches.open(cacheName); - console.log(`[Service Worker] Caching new resource: ${e.request.url}`); - if (e.request.method !== "POST") { - cache.put(e.request, response.clone()); - } - return response; - })() - ); -}); -``` - -With the above code, the application can now work offline because the service worker will cache the `helloworld-pwa.html` page and its related resources. - -For more information, refer to [Making PWAs work offline with Service workers](https://developer.mozilla.org/en-US/docs/Web/Progressive_web_apps/Offline_Service_workers). - -> Note: -> -> Since the files are cached, changes we make in later steps may not be reflected immediately. To ensure updates are applied, clear the cache after changes are made. You can do this by running the following code in the browser console: -> -> ```javascript -> const cacheName = 'helloworld-pwa'; -> const cache = await caches.delete(cacheName); -> ``` - -### Use a web manifest file to make the application installable - -A web manifest file contains a list of information about a website in JSON format. This information is used to enable the web app to be installed on a device. - -* Create a file named `helloworld-pwa.json` with the following content: - -```json -/* /helloworld-pwa.json */ -{ - "name": "Dynamsoft Barcode Reader Progressive Web App", - "short_name": "DBR-PWA", - "description": "Progressive Web App that reads barcodes from a video input with Dynamsoft Barcode Reader.", - "start_url": "./helloworld-pwa.html", - "scope": ".", - "display": "standalone", - "theme_color": "#B12A34", - "background_color": "#B12A34", - "icons": [ - { - "src": "./dynamsoft-512x512.png", - "sizes": "512x512", - "type": "image/png" - }, - { - "src": "./dynamsoft-192x192.png", - "sizes": "192x192", - "type": "image/png" - } - ] -} -``` - -> Note: The icon files can be found in the github repository. - -* Then we include the file in the `` block of the `helloworld-pwa.html` file as such: - -```html - - -``` - -* For compatibility on safari, we need add some `meta` in ``. - -```html - - - - - - - - - -``` - -Now, if you open the application again in your browser, you will notice an install icon appear on the right side of the address bar. When you click on it, a pop-up will appear asking if you want to install the app. - -Once installed, you can use it just like any native app. - -To enable offline functionality for Dynamsoft Barcode Reader, you'll need to cache more files. - -### Enabling offline functionality for Dynamsoft Barcode Reader - -These directories below are the resources required for Dynamsoft Barcode Reader functionality. Once added, these files are cached on installation of the service worker (i.e. `install` event), wensuring the PWA remains fully functional without any internet. - -Add this code below to the `service-worker.js` -```javascript -/* /service-worker.js */ -const engineResourcePaths = { - dbrBundle: "https://cdn.jsdelivr.net/npm/dynamsoft-barcode-reader-bundle@11.2.4000/dist/", -}; - -// Files to cache -const cacheName = "helloworld-pwa"; -const appShellFiles = [ - "./helloworld-pwa.html", - "./dynamsoft-192x192.png", - "./dynamsoft-512x512.png", - "./helloworld-pwa.json", - `${engineResourcePaths.dbrBundle}dbr.bundle.worker.js`, - `${engineResourcePaths.dbrBundle}dynamsoft-capture-vision-bundle.js` - `${engineResourcePaths.dbrBundle}dynamsoft-capture-vision-bundle.wasm`, - `${engineResourcePaths.dbrBundle}models/OneDDeblur.data`, - `${engineResourcePaths.dbrBundle}parser-resources/AADHAAR_Map.txt`, - `${engineResourcePaths.dbrBundle}parser-resources/AADHAAR.dcpres`, - `${engineResourcePaths.dbrBundle}parser-resources/AAMVA_DL_ID_WITH_MAG_STRIPE.dcpres`, - `${engineResourcePaths.dbrBundle}parser-resources/AAMVA_DL_ID.dcpres`, - `${engineResourcePaths.dbrBundle}parser-resources/AAMVA_Map.txt`, - `${engineResourcePaths.dbrBundle}parser-resources/GS1_AI_Map.txt`, - `${engineResourcePaths.dbrBundle}parser-resources/GS1_AI.txt`, - `${engineResourcePaths.dbrBundle}parser-resources/MRTD_Map.txt`, - `${engineResourcePaths.dbrBundle}parser-resources/MRTD_TD1_ID.dcpres`, - `${engineResourcePaths.dbrBundle}parser-resources/MRTD_TD2_FRENCH_ID.dcpres`, - `${engineResourcePaths.dbrBundle}parser-resources/MRTD_TD2_ID.dcpres`, - `${engineResourcePaths.dbrBundle}parser-resources/MRTD_TD2_VISA.dcpres`, - `${engineResourcePaths.dbrBundle}parser-resources/MRTD_TD3_PASSPORT.dcpres`, - `${engineResourcePaths.dbrBundle}parser-resources/MRTD_TD3_VISA.dcpres`, - `${engineResourcePaths.dbrBundle}parser-resources/SOUTH_AFRICA_DL_Map.txt`, - `${engineResourcePaths.dbrBundle}parser-resources/SOUTH_AFRICA_DL.dcpres`, - `${engineResourcePaths.dbrBundle}parser-resources/VIN_Map.txt`, - `${engineResourcePaths.dbrBundle}parser-resources/VIN.dcpres`, - `${engineResourcePaths.dbrBundle}templates/DBR-PresetTemplates.json`, - `${engineResourcePaths.dbrBundle}ui/barcode-scanner.ui.xml`, - `${engineResourcePaths.dbrBundle}ui/dce.ui.xml`, - `${engineResourcePaths.dbrBundle}ui/dls.license.dialog.html`, -]; -``` - -## Summary - -In this article we took a look at how you can turn a simple barcode reading page into a PWA that is installable, re-engageable and capable of working offline. To learn more about Progressive web apps, you can click [here](https://developer.mozilla.org/en-US/docs/Web/Progressive_web_apps). - -## Support - -If you have any questions, feel free to [contact Dynamsoft support](https://www.dynamsoft.com/company/contact?utm_source=sampleReadme). \ No newline at end of file diff --git a/frameworks/pwa/scan-using-foundational-api/service-worker.js b/frameworks/pwa/scan-using-foundational-api/service-worker.js deleted file mode 100644 index 0fb7589b..00000000 --- a/frameworks/pwa/scan-using-foundational-api/service-worker.js +++ /dev/null @@ -1,92 +0,0 @@ -const engineResourcePaths = { - dbrBundle: "https://cdn.jsdelivr.net/npm/dynamsoft-barcode-reader-bundle@11.2.4000/dist/", -}; - -// Files to cache -const cacheName = "helloworld-pwa"; -// Here we choose some files into appShellFiles to cache. -// To keep it simple, you can put all the files -// in "node_modules/dynamsoft-barcode-reader-bundle/dist" into the list. -const appShellFiles = [ - "./helloworld-pwa.html", - "./dynamsoft-192x192.png", - "./dynamsoft-512x512.png", - "./helloworld-pwa.json", - `${engineResourcePaths.dbrBundle}dbr.bundle.worker.js`, - `${engineResourcePaths.dbrBundle}dynamsoft-barcode-reader-bundle.js`, - `${engineResourcePaths.dbrBundle}dynamsoft-barcode-reader-bundle.wasm`, - `${engineResourcePaths.dbrBundle}dynamsoft-barcode-reader-bundle-ml-simd.js`, - `${engineResourcePaths.dbrBundle}dynamsoft-barcode-reader-bundle-ml-simd.wasm`, - `${engineResourcePaths.dbrBundle}dynamsoft-barcode-reader-bundle-ml-simd-pthread.js`, - `${engineResourcePaths.dbrBundle}dynamsoft-barcode-reader-bundle-ml-simd-pthread.worker.js`, - `${engineResourcePaths.dbrBundle}dynamsoft-barcode-reader-bundle-ml-simd-pthread.wasm`, - `${engineResourcePaths.dbrBundle}models/OneDDeblur.data`, - `${engineResourcePaths.dbrBundle}models/OneDLocalization.data`, - `${engineResourcePaths.dbrBundle}models/DataMatrixQRCodeLocalization.data`, - `${engineResourcePaths.dbrBundle}models/Code128Decoder.data`, - `${engineResourcePaths.dbrBundle}models/EAN13Decoder.data`, - `${engineResourcePaths.dbrBundle}parser-resources/AADHAAR_Map.txt`, - `${engineResourcePaths.dbrBundle}parser-resources/AADHAAR.dcpres`, - `${engineResourcePaths.dbrBundle}parser-resources/AAMVA_DL_ID_WITH_MAG_STRIPE.dcpres`, - `${engineResourcePaths.dbrBundle}parser-resources/AAMVA_DL_ID.dcpres`, - `${engineResourcePaths.dbrBundle}parser-resources/AAMVA_Map.txt`, - `${engineResourcePaths.dbrBundle}parser-resources/GS1_AI_Map.txt`, - `${engineResourcePaths.dbrBundle}parser-resources/GS1_AI.txt`, - `${engineResourcePaths.dbrBundle}parser-resources/MRTD_Map.txt`, - `${engineResourcePaths.dbrBundle}parser-resources/MRTD_TD1_ID.dcpres`, - `${engineResourcePaths.dbrBundle}parser-resources/MRTD_TD2_FRENCH_ID.dcpres`, - `${engineResourcePaths.dbrBundle}parser-resources/MRTD_TD2_ID.dcpres`, - `${engineResourcePaths.dbrBundle}parser-resources/MRTD_TD2_VISA.dcpres`, - `${engineResourcePaths.dbrBundle}parser-resources/MRTD_TD3_PASSPORT.dcpres`, - `${engineResourcePaths.dbrBundle}parser-resources/MRTD_TD3_VISA.dcpres`, - `${engineResourcePaths.dbrBundle}parser-resources/SOUTH_AFRICA_DL_Map.txt`, - `${engineResourcePaths.dbrBundle}parser-resources/SOUTH_AFRICA_DL.dcpres`, - `${engineResourcePaths.dbrBundle}parser-resources/VIN_Map.txt`, - `${engineResourcePaths.dbrBundle}parser-resources/VIN.dcpres`, - `${engineResourcePaths.dbrBundle}templates/DBR-PresetTemplates.json`, - `${engineResourcePaths.dbrBundle}ui/barcode-scanner.ui.xml`, - `${engineResourcePaths.dbrBundle}ui/dce.ui.xml`, - `${engineResourcePaths.dbrBundle}ui/dls.license.dialog.html`, -]; - -// Installing Service Worker -self.addEventListener("install", (e) => { - console.log("[Service Worker] Install"); - e.waitUntil( - (async () => { - const cache = await caches.open(cacheName); - console.log(cache); - console.log("[Service Worker] Caching all: app shell and content"); - await cache.addAll(appShellFiles); - })() - ); -}); - -self.addEventListener("fetch", (e) => { - e.respondWith( - (async () => { - // Fetch cached response if exists - const cachedResponse = await caches.match(e.request); - console.log(`[Service Worker] Fetching resource: ${e.request.url}`); - if (cachedResponse) { - return cachedResponse; - } - - // Otherwise, fetch from network - const response = await fetch(e.request); - - if ( - e.request.method !== "POST" && - // Authorization requests should not be cached - !/https:\/\/.*?\.dynamsoft.com\/auth/.test(e.request.url) - // You can add other filter conditions - ) { - const cache = await caches.open(cacheName); - console.log(`[Service Worker] Caching new resource: ${e.request.url}`); - cache.put(e.request, response.clone()); - } - - return response; - })() - ); -}); diff --git a/frameworks/pwa/scan-using-rtu-api/README.md b/frameworks/pwa/scan-using-rtu-api/README.md deleted file mode 100644 index 7a9a2965..00000000 --- a/frameworks/pwa/scan-using-rtu-api/README.md +++ /dev/null @@ -1,17 +0,0 @@ -# 📦 Scan Single Barcode - PWA - -This sample shows how to integrate the `BarcodeScanner` API from the [Dynamsoft Barcode Reader JavaScript SDK](https://www.dynamsoft.com/barcode-reader/sdk-javascript/) into a **PWA** application to scan a single barcode from video. - -## ✨ Features - -- Easy integration with pre-built UI -- BarcodeScanner instance created in a component -- Scans one barcode at a time from video - -## 📌 Customization - -Please check the official [documentation](https://dynamsoft.com/barcode-reader/docs/web/programming/javascript/user-guide/barcode-scanner-customization.html). - -## 📄 Support - -If you have any questions, feel free to [contact Dynamsoft Support](https://www.dynamsoft.com/company/contact?utm_source=sampleReadme). diff --git a/frameworks/pwa/scan-using-rtu-api/dynamsoft-192x192.png b/frameworks/pwa/scan-using-rtu-api/dynamsoft-192x192.png deleted file mode 100644 index e02348bebe310ace87fe77d58e4e76dc581da970..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6638 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 diff --git a/frameworks/pwa/scan-using-rtu-api/dynamsoft-512x512.png b/frameworks/pwa/scan-using-rtu-api/dynamsoft-512x512.png deleted file mode 100644 index 1e0ec7dc683f5f9d9208e4e2faf5ab12a46bba67..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9938 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 diff --git a/frameworks/pwa/scan-using-rtu-api/helloworld-pwa.html b/frameworks/pwa/scan-using-rtu-api/helloworld-pwa.html deleted file mode 100644 index 7afb3ae0..00000000 --- a/frameworks/pwa/scan-using-rtu-api/helloworld-pwa.html +++ /dev/null @@ -1,109 +0,0 @@ - - - - - - - - - Dynamsoft Barcode Reader PWA Sample - Hello World (Decode via Camera) - - - - - - - - - - - - -

- Hello World (Scan One Single Barcode via Camera) -

- -
- - - - - - - - - - - - - \ No newline at end of file diff --git a/frameworks/pwa/scan-using-rtu-api/helloworld-pwa.json b/frameworks/pwa/scan-using-rtu-api/helloworld-pwa.json deleted file mode 100644 index 1c6c8e42..00000000 --- a/frameworks/pwa/scan-using-rtu-api/helloworld-pwa.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "name": "Dynamsoft Barcode Reader Progressive Web App", - "short_name": "DBR-PWA", - "description": "Progressive Web App that reads barcodes from a video input with Dynamsoft Barcode Reader.", - "start_url": "./helloworld-pwa.html", - "scope": ".", - "display": "standalone", - "theme_color": "#B12A34", - "background_color": "#B12A34", - "icons": [ - { - "src": "./dynamsoft-512x512.png", - "sizes": "512x512", - "type": "image/png" - }, - { - "src": "./dynamsoft-192x192.png", - "sizes": "192x192", - "type": "image/png" - } - ] -} \ No newline at end of file diff --git a/frameworks/pwa/scan-using-rtu-api/service-worker.js b/frameworks/pwa/scan-using-rtu-api/service-worker.js deleted file mode 100644 index 0fb7589b..00000000 --- a/frameworks/pwa/scan-using-rtu-api/service-worker.js +++ /dev/null @@ -1,92 +0,0 @@ -const engineResourcePaths = { - dbrBundle: "https://cdn.jsdelivr.net/npm/dynamsoft-barcode-reader-bundle@11.2.4000/dist/", -}; - -// Files to cache -const cacheName = "helloworld-pwa"; -// Here we choose some files into appShellFiles to cache. -// To keep it simple, you can put all the files -// in "node_modules/dynamsoft-barcode-reader-bundle/dist" into the list. -const appShellFiles = [ - "./helloworld-pwa.html", - "./dynamsoft-192x192.png", - "./dynamsoft-512x512.png", - "./helloworld-pwa.json", - `${engineResourcePaths.dbrBundle}dbr.bundle.worker.js`, - `${engineResourcePaths.dbrBundle}dynamsoft-barcode-reader-bundle.js`, - `${engineResourcePaths.dbrBundle}dynamsoft-barcode-reader-bundle.wasm`, - `${engineResourcePaths.dbrBundle}dynamsoft-barcode-reader-bundle-ml-simd.js`, - `${engineResourcePaths.dbrBundle}dynamsoft-barcode-reader-bundle-ml-simd.wasm`, - `${engineResourcePaths.dbrBundle}dynamsoft-barcode-reader-bundle-ml-simd-pthread.js`, - `${engineResourcePaths.dbrBundle}dynamsoft-barcode-reader-bundle-ml-simd-pthread.worker.js`, - `${engineResourcePaths.dbrBundle}dynamsoft-barcode-reader-bundle-ml-simd-pthread.wasm`, - `${engineResourcePaths.dbrBundle}models/OneDDeblur.data`, - `${engineResourcePaths.dbrBundle}models/OneDLocalization.data`, - `${engineResourcePaths.dbrBundle}models/DataMatrixQRCodeLocalization.data`, - `${engineResourcePaths.dbrBundle}models/Code128Decoder.data`, - `${engineResourcePaths.dbrBundle}models/EAN13Decoder.data`, - `${engineResourcePaths.dbrBundle}parser-resources/AADHAAR_Map.txt`, - `${engineResourcePaths.dbrBundle}parser-resources/AADHAAR.dcpres`, - `${engineResourcePaths.dbrBundle}parser-resources/AAMVA_DL_ID_WITH_MAG_STRIPE.dcpres`, - `${engineResourcePaths.dbrBundle}parser-resources/AAMVA_DL_ID.dcpres`, - `${engineResourcePaths.dbrBundle}parser-resources/AAMVA_Map.txt`, - `${engineResourcePaths.dbrBundle}parser-resources/GS1_AI_Map.txt`, - `${engineResourcePaths.dbrBundle}parser-resources/GS1_AI.txt`, - `${engineResourcePaths.dbrBundle}parser-resources/MRTD_Map.txt`, - `${engineResourcePaths.dbrBundle}parser-resources/MRTD_TD1_ID.dcpres`, - `${engineResourcePaths.dbrBundle}parser-resources/MRTD_TD2_FRENCH_ID.dcpres`, - `${engineResourcePaths.dbrBundle}parser-resources/MRTD_TD2_ID.dcpres`, - `${engineResourcePaths.dbrBundle}parser-resources/MRTD_TD2_VISA.dcpres`, - `${engineResourcePaths.dbrBundle}parser-resources/MRTD_TD3_PASSPORT.dcpres`, - `${engineResourcePaths.dbrBundle}parser-resources/MRTD_TD3_VISA.dcpres`, - `${engineResourcePaths.dbrBundle}parser-resources/SOUTH_AFRICA_DL_Map.txt`, - `${engineResourcePaths.dbrBundle}parser-resources/SOUTH_AFRICA_DL.dcpres`, - `${engineResourcePaths.dbrBundle}parser-resources/VIN_Map.txt`, - `${engineResourcePaths.dbrBundle}parser-resources/VIN.dcpres`, - `${engineResourcePaths.dbrBundle}templates/DBR-PresetTemplates.json`, - `${engineResourcePaths.dbrBundle}ui/barcode-scanner.ui.xml`, - `${engineResourcePaths.dbrBundle}ui/dce.ui.xml`, - `${engineResourcePaths.dbrBundle}ui/dls.license.dialog.html`, -]; - -// Installing Service Worker -self.addEventListener("install", (e) => { - console.log("[Service Worker] Install"); - e.waitUntil( - (async () => { - const cache = await caches.open(cacheName); - console.log(cache); - console.log("[Service Worker] Caching all: app shell and content"); - await cache.addAll(appShellFiles); - })() - ); -}); - -self.addEventListener("fetch", (e) => { - e.respondWith( - (async () => { - // Fetch cached response if exists - const cachedResponse = await caches.match(e.request); - console.log(`[Service Worker] Fetching resource: ${e.request.url}`); - if (cachedResponse) { - return cachedResponse; - } - - // Otherwise, fetch from network - const response = await fetch(e.request); - - if ( - e.request.method !== "POST" && - // Authorization requests should not be cached - !/https:\/\/.*?\.dynamsoft.com\/auth/.test(e.request.url) - // You can add other filter conditions - ) { - const cache = await caches.open(cacheName); - console.log(`[Service Worker] Caching new resource: ${e.request.url}`); - cache.put(e.request, response.clone()); - } - - return response; - })() - ); -}); diff --git a/frameworks/pwa/service-worker.js b/frameworks/pwa/service-worker.js new file mode 100644 index 00000000..e0539995 --- /dev/null +++ b/frameworks/pwa/service-worker.js @@ -0,0 +1,95 @@ +const engineResourcePaths = { + dbrBundle: "https://npm.scannerproxy.com:802/cdn/@dynamsoft/dynamsoft-barcode-reader-bundle@11.4.2000-dev-20260410144128/dist/", +}; + +// Files to cache +const cacheName = "helloworld-pwa"; +// Here we choose some files into appShellFiles to cache. +// To keep it simple, you can put all the files +// in "node_modules/dynamsoft-barcode-reader-bundle/dist" into the list. +const appShellFiles = [ + "./helloworld-pwa.html", + "./dynamsoft-192x192.png", + "./dynamsoft-512x512.png", + "./helloworld-pwa.json", + `${engineResourcePaths.dbrBundle}dbr.bundle.worker.js`, + `${engineResourcePaths.dbrBundle}dynamsoft-barcode-reader-bundle-ml-simd.js`, + `${engineResourcePaths.dbrBundle}dynamsoft-barcode-reader-bundle-ml-simd.wasm`, + `${engineResourcePaths.dbrBundle}models/Code128Decoder.data`, + `${engineResourcePaths.dbrBundle}models/EAN13Decoder.data`, + `${engineResourcePaths.dbrBundle}models/Code39ITFDecoder.data`, + `${engineResourcePaths.dbrBundle}templates/DBR-PresetTemplates.json`, + `${engineResourcePaths.dbrBundle}ui/dce.ui.xml`, + `${engineResourcePaths.dbrBundle}ui/dls.license.dialog.html`, + + // `${engineResourcePaths.dbrBundle}dynamsoft-barcode-reader-bundle.js`, + // `${engineResourcePaths.dbrBundle}dynamsoft-barcode-reader-bundle.wasm`, + // `${engineResourcePaths.dbrBundle}dynamsoft-barcode-reader-bundle-ml-simd-pthread.js`, + // `${engineResourcePaths.dbrBundle}dynamsoft-barcode-reader-bundle-ml-simd-pthread.worker.js`, + // `${engineResourcePaths.dbrBundle}dynamsoft-barcode-reader-bundle-ml-simd-pthread.wasm`, + // `${engineResourcePaths.dbrBundle}models/OneDDeblur.data`, + // `${engineResourcePaths.dbrBundle}models/OneDLocalization.data`, + // `${engineResourcePaths.dbrBundle}models/DataMatrixQRCodeLocalization.data`, + // `${engineResourcePaths.dbrBundle}models/DataMatrixQRCodeDeblur.data`, + // `${engineResourcePaths.dbrBundle}models/PDF417Deblur.data`, + // `${engineResourcePaths.dbrBundle}models/PDF417Localization.data`, + // `${engineResourcePaths.dbrBundle}parser-resources/AADHAAR.data`, + // `${engineResourcePaths.dbrBundle}parser-resources/AAMVA_DL_ID.data`, + // `${engineResourcePaths.dbrBundle}parser-resources/GS1_AI.data`, + // `${engineResourcePaths.dbrBundle}parser-resources/MRTD.data`, + // `${engineResourcePaths.dbrBundle}parser-resources/SOUTH_AFRICA_DL.data`, + // `${engineResourcePaths.dbrBundle}parser-resources/VIN.data`, +]; + +// Installing Service Worker +self.addEventListener("install", (e) => { + console.log("[Service Worker] Install"); + e.waitUntil( + (async () => { + const cache = await caches.open(cacheName); + console.log(cache); + console.log("[Service Worker] Caching all: app shell and content"); + // Avoid failing the whole install if one resource is temporarily unreachable. + await Promise.allSettled(appShellFiles.map((file) => cache.add(file))); + })() + ); +}); + +self.addEventListener("fetch", (e) => { + e.respondWith( + (async () => { + try { + // Fetch cached response if exists + const cachedResponse = await caches.match(e.request); + console.log(`[Service Worker] Fetching resource: ${e.request.url}`); + if (cachedResponse) { + return cachedResponse; + } + + // Otherwise, fetch from network + const response = await fetch(e.request); + + if ( + e.request.method === "GET" && + response.ok && + // Authorization requests should not be cached + !/https:\/\/.*?\.dynamsoft.com\/auth/.test(e.request.url) + // You can add other filter conditions + ) { + const cache = await caches.open(cacheName); + console.log(`[Service Worker] Caching new resource: ${e.request.url}`); + cache.put(e.request, response.clone()); + } + + return response; + } catch (error) { + // Network fallback: try cache one more time before failing. + const fallbackResponse = await caches.match(e.request); + if (fallbackResponse) { + return fallbackResponse; + } + throw error; + } + })() + ); +}); diff --git a/frameworks/react/scan-using-foundational-api/.gitignore b/frameworks/react/.gitignore similarity index 100% rename from frameworks/react/scan-using-foundational-api/.gitignore rename to frameworks/react/.gitignore diff --git a/frameworks/react/README.md b/frameworks/react/README.md index 88def624..e3e7245f 100644 --- a/frameworks/react/README.md +++ b/frameworks/react/README.md @@ -1,23 +1,396 @@ -# React samples +# Hello World Sample for React with Hooks -This directory contains React-based examples demonstrating how to use the Dynamsoft Barcode Reader (JavaScript edition) in React projects. +[React](https://reactjs.org/) is a JavaScript library meant explicitly for creating interactive UIs. Follow this guide to learn how to implement [Dynamsoft Barcode Reader JavaScript SDK](https://www.dynamsoft.com/barcode-reader/sdk-javascript/) (hereafter called "the library") into a React application. Note that in this sample we will use `TypeScript` and [Hooks](https://reactjs.org/docs/hooks-intro.html). Also, there is another sample `react` defining components as classes in React. -**Included examples** +In this guide, we will be using [`dynamsoft-barcode-reader-bundle 11.4.2000](https://www.npmjs.com/package/dynamsoft-barcode-reader-bundle/v/11.4.2000). -- `scan-using-foundational-api/` — React + TypeScript example using the foundational API. -- `scan-using-rtu-api/` — React example using the RTU API. +> Note: +> +> If you're looking to integrate DBR-JS into a framework that we don't yet have a sample, don't worry! We have a [comprehensive guide](https://www.dynamsoft.com/barcode-reader/docs/web/programming/javascript/user-guide/use-in-framework.html) that provides detailed instruction and best practices for a seamless integration into any frameworks! +> +> Additionally, we're here to help! Please don't hesitate to [contact us](#Support) for any support or questions you might have. -## Quick start +## Official Sample -1. Change to a subexample directory, e.g.: +* Hello World in React with Hooks - Source Code - ```bash - cd scan-using-foundational-api - ``` +## Preparation -2. Follow the subexample README for exact steps (typically: `npm install` && `npm run dev` or `npm run start`). +Make sure you have [node](https://nodejs.org/) installed. `node 16.20.1` and `react 18.2.0` are used in the example below. -## Notes +## Quick Start -- Run examples via the framework dev server. Opening files directly may break module loading or camera access. -- See the repository root `README.md` for general usage and license information. \ No newline at end of file +```cmd +npm install +npm start +``` +Then open http://localhost:3000/ to view the sample app. + +## Create the sample project + +In this section, we will be creating a React application utilizing the Dynamsoft Barcode Reader bundle sdk. + +We'll be exploring how you could create a page that not only enables barcode scanning via a webcam or a built-in camera, but also decode barcodes from local images. + +By the end of this guide, you'll have a good understanding of the SDK and be ready to discover more ways to use it! + +### Create a Bootstrapped Raw React Application with TypeScript + +```cmd +npx create-react-app my-app --template typescript +``` + +### **CD** to the root directory of the application and install necessary libraries + +```cmd +cd my-app +npm install dynamsoft-barcode-reader-bundle@11.4.2000 -E +``` + +## Start to implement + +### Add file "dynamsoft.config.ts" under "/src/" to configure libraries + +```typescript +/* /src/dynamsoft.config.ts */ +import { CoreModule } from "dynamsoft-core"; +import { LicenseManager } from "dynamsoft-license"; +import "dynamsoft-barcode-reader"; + +// Configures the paths where the .wasm files and other necessary resources for modules are located. +CoreModule.engineResourcePaths.rootDirectory = "https://cdn.jsdelivr.net/npm/"; + +/** LICENSE ALERT - README + * To use the library, you need to first specify a license key using the API "initLicense()" as shown below. + */ + +LicenseManager.initLicense("DLS2eyJvcmdhbml6YXRpb25JRCI6IjIwMDAwMSJ9", { + executeNow: true, +}); + +/** + * You can visit https://www.dynamsoft.com/customer/license/trialLicense?utm_source=samples&product=dbr&package=js to get your own trial license good for 30 days. + * Note that if you downloaded this sample from Dynamsoft while logged in, the above license key may already be your own 30-day trial license. + * For more information, see https://www.dynamsoft.com/barcode-reader/docs/web/programming/javascript/user-guide/index.html?ver=11.4.2000&cVer=true#specify-the-license&utm_source=samples or contact support@dynamsoft.com. + * LICENSE ALERT - THE END + */ + +// Optional. Preload .wasm file for reading barcodes. It will save time on the initial decoding by skipping the resource loading. +CoreModule.loadWasm(); +``` + +> Note: +> +> * `initLicense()` specify a license key to use the library. You can visit https://www.dynamsoft.com/customer/license/trialLicense?utm_source=sample&product=dbr&package=js to get your own trial license good for 30 days. +> * `engineResourcePaths` tells the library where to get the necessary resources at runtime. + +### Build directory structure + +* Create a directory `components` under `/src/`, and then create two other directories, `VideoCapture` and `ImageCapture` under `/components/`. + +### Create and edit the `VideoCapture` component + +* Create `VideoCapture.tsx` under `/src/components/VideoCapture/`. The `VideoCapture` component helps decode barcodes via camera. + +* In `VideoCapture.tsx`, add code for initializing and destroying some instances. For our stylesheet (CSS) specification, please refer to our [source code](#Official-Sample). + +```tsx +/* /src/components/VideoCapture/VideoCapture.tsx */ +import { useEffect, useRef, useState } from "react"; +import "../../dynamsoft.config"; // import side effects. The license, engineResourcePath, so on. +import { CameraEnhancer, CameraView } from "dynamsoft-camera-enhancer"; +import { CaptureVisionRouter } from "dynamsoft-capture-vision-router"; +import { MultiFrameResultCrossFilter } from "dynamsoft-utility"; +import "./VideoCapture.css"; + +const componentDestroyedErrorMsg = "VideoCapture Component Destroyed"; + +function VideoCapture() { + const [resultText, setResultText] = useState(""); + const cameraViewContainer = useRef(null); + + useEffect((): any => { + let resolveInit: () => void; + const pInit: Promise = new Promise((r) => { + resolveInit = r; + }); + let isDestroyed = false; + + let cvRouter: CaptureVisionRouter; + let cameraEnhancer: CameraEnhancer; + + (async () => { + try { + // Create a `CameraEnhancer` instance for camera control and a `CameraView` instance for UI control. + const cameraView = await CameraView.createInstance(); + if (isDestroyed) { + throw Error(componentDestroyedErrorMsg); + } // Check if component is destroyed after every async + cameraEnhancer = await CameraEnhancer.createInstance(cameraView); + if (isDestroyed) { + throw Error(componentDestroyedErrorMsg); + } + + // Get default UI and append it to DOM. + cameraViewContainer.current!.append(cameraView.getUIElement()); + + // Create a `CaptureVisionRouter` instance and set `CameraEnhancer` instance as its image source. + cvRouter = await CaptureVisionRouter.createInstance(); + if (isDestroyed) { + throw Error(componentDestroyedErrorMsg); + } + cvRouter.setInput(cameraEnhancer); + + // Define a callback for results. + cvRouter.addResultReceiver({ + onDecodedBarcodesReceived: (result) => { + if (!result.barcodeResultItems.length) return; + + let _resultText = ""; + setResultText(_resultText); + console.log(result); + for (let item of result.barcodeResultItems) { + _resultText += `${item.formatString}: ${item.text}\n\n`; + } + setResultText(_resultText); + }, + }); + + // Filter out unchecked and duplicate results. + const filter = new MultiFrameResultCrossFilter(); + // Filter out unchecked barcodes. + filter.enableResultCrossVerification("barcode", true); + // Filter out duplicate barcodes within 3 seconds. + filter.enableResultDeduplication("barcode", true); + await cvRouter.addResultFilter(filter); + if (isDestroyed) { + throw Error(componentDestroyedErrorMsg); + } + + // Open camera and start scanning single barcode. + await cameraEnhancer.open(); + cameraView.setScanLaserVisible(true); + if (isDestroyed) { + throw Error(componentDestroyedErrorMsg); + } + await cvRouter.startCapturing("ReadSingleBarcode"); + if (isDestroyed) { + throw Error(componentDestroyedErrorMsg); + } + } catch (ex: any) { + if ((ex as Error)?.message === componentDestroyedErrorMsg) { + console.log(componentDestroyedErrorMsg); + } else { + let errMsg = ex.message || ex; + console.error(ex); + alert(errMsg); + } + } + // Resolve pInit promise once initialization is complete. + resolveInit!(); + })(); + + // componentWillUnmount. dispose cvRouter when it's no longer needed + return () => { + isDestroyed = true; + // Wait for the pInit to complete before disposing resources. + pInit.then(() => { + cvRouter?.dispose(); + cameraEnhancer?.dispose(); + }).catch((_) => { }) + }; + }, []); + + return ( +
+
+
+ Results: +
{resultText}
+
+ ); +} + +export default VideoCapture; +``` + +> Note: +> +> * The component should never update so that events bound to the UI stay valid. In this copmonent, the useEffect() hook is used to handle the component's mount and unmount lifecycle events, and there are no state updates that would cause a re-render. +> * If you're looking to customize the UI, the UI customization feature are provided by the auxiliary SDK "Dynamsoft Camera Enhancer". For more details, refer to our [User Guide](https://www.dynamsoft.com/barcode-reader/docs/web/programming/javascript/user-guide/index.html#customizing-the-ui) + +### Create and edit the `ImageCapture` component + +* Create `ImageCapture.tsx` under `/src/components/ImageCapture/`. The `ImageCapture` component helps decode barcodes in an image. + +* In `ImageCapture.tsx`, add code for initializing and destroying the `CaptureVisionRouter` instance. For our stylesheet (CSS) specification, please refer to our [source code](#Official-Sample). + +```tsx +/* /src/components/ImageCapture/ImageCapture.tsx */ +import React, { useRef, useEffect, MutableRefObject, useState } from "react"; +import "../../dynamsoft.config"; // import side effects. The license, engineResourcePath, so on. +import { EnumCapturedResultItemType } from "dynamsoft-core"; +import { BarcodeResultItem } from "dynamsoft-barcode-reader"; +import { CaptureVisionRouter } from "dynamsoft-capture-vision-router"; +import "./ImageCapture.css"; + +function ImageCapture() { + const [resultText, setResultText] = useState(""); + + let pCvRouter: MutableRefObject | null> = useRef(null); + let isDestroyed = useRef(false); + + const captureImage = async (e: React.ChangeEvent) => { + let files = [...(e.target.files as any as File[])]; + e.target.value = ""; // reset input + setResultText(""); + + try { + // ensure cvRouter is created only once + const cvRouter = await (pCvRouter.current = pCvRouter.current || CaptureVisionRouter.createInstance()); + if (isDestroyed.current) return; + + let _resultText = ""; + for (let file of files) { + // Decode selected image with 'ReadBarcodes_ReadRateFirst' template. + const result = await cvRouter.capture(file, "ReadBarcodes_ReadRateFirst"); + console.log(result); + if (isDestroyed.current) return; + + // Print file name if there's multiple files + if (files.length > 1) { + _resultText += `\n${file.name}:\n`; + } + for (let _item of result.items) { + if (_item.type !== EnumCapturedResultItemType.CRIT_BARCODE) { + continue; // check if captured result item is a barcode + } + let item = _item as BarcodeResultItem; + _resultText += item.formatString + ": " + item.text + "\n" + } + setResultText(_resultText); + // If no items are found, display that no barcode was detected + if (!result.items.length) setResultText(_resultText + "No barcode found"); + } + } catch (ex: any) { + let errMsg = ex.message || ex; + console.error(ex); + alert(errMsg); + } + }; + + useEffect((): any => { + // In 'development', React runs setup and cleanup one extra time before the actual setup in Strict Mode. + isDestroyed.current = false; + + // componentWillUnmount. dispose cvRouter when it's no longer needed + return () => { + isDestroyed.current = true; + if (pCvRouter.current) { + pCvRouter.current.then((cvRouter) => { + cvRouter.dispose(); + }).catch((_) => { }) + } + }; + }, []); + + return ( +
+
+ +
+
{resultText}
+
+ ); +} + +export default ImageCapture; +``` + +### Add the `VideoCapture` and `ImageCapture` component to `App.tsx` + +* On `/src/App.tsx`, we will edit the component so that it offers buttons to switch components between `VideoCapture` and `ImageCapture`. + +* Add following code to `App.tsx`. For our stylesheet (CSS) specification, please refer to our [source code](#Official-Sample). + +```tsx +/* /src/App.tsx */ +import { useState } from "react"; +import reactLogo from "./assets/logo.svg"; +import VideoCapture from "./components/VideoCapture/VideoCapture"; +import ImageCapture from "./components/ImageCapture/ImageCapture"; +import "./App.css"; + +enum Modes { + VIDEO_CAPTURE = "video", + IMAGE_CAPTURE = "image", +} + +function App() { + const [mode, setMode] = useState(Modes.VIDEO_CAPTURE); + + const showVideoCapture = () => setMode(Modes.VIDEO_CAPTURE); + + const showImageCapture = () => setMode(Modes.IMAGE_CAPTURE); + + return ( +
+
+

Hello World for React

+ logo +
+
+ + +
+
{mode === Modes.VIDEO_CAPTURE ? : }
+
+ ); +} + +export default App; +``` + +* Try running the project. + +```cmd +npm start +``` + +If you followed all the steps correctly, you will have a working page that turns one of the cameras hooked to or built in your computer or mobile device into a barcode scanner. Also, if you want to decode a local image, just click the `Decode Image` button and select the image you want to decode. Once barcodes are found, the results will show in a dialog. + +## Development server + +Runs the app in the development mode.\ +Open [http://localhost:3000](http://localhost:3000) to view it in the browser. + +The page will reload if you make edits.\ +You will also see any lint errors in the console. + +## Build + +Builds the app for production to the `build` folder.\ +It correctly bundles React in production mode and optimizes the build for the best performance. + +The build is minified and the filenames include the hashes.\ +Your app is ready to be deployed! + +See the section about [deployment](https://create-react-app.dev/docs/deployment/) for more information. + +## Support + +If you have any questions, feel free to [contact Dynamsoft support](https://www.dynamsoft.com/company/contact?utm_source=sampleReadme). diff --git a/frameworks/react/scan-using-foundational-api/package.json b/frameworks/react/package.json similarity index 95% rename from frameworks/react/scan-using-foundational-api/package.json rename to frameworks/react/package.json index 465c9542..1f0485b2 100644 --- a/frameworks/react/scan-using-foundational-api/package.json +++ b/frameworks/react/package.json @@ -11,7 +11,7 @@ "@types/node": "^16.18.99", "@types/react": "^18.3.3", "@types/react-dom": "^18.3.0", - "dynamsoft-barcode-reader-bundle": "11.2.4000", + "dynamsoft-barcode-reader-bundle": "11.4.2000", "react": "^18.3.1", "react-dom": "^18.3.1", "react-scripts": "5.0.1", diff --git a/frameworks/react/scan-using-foundational-api/public/favicon.ico b/frameworks/react/public/favicon.ico similarity index 100% rename from frameworks/react/scan-using-foundational-api/public/favicon.ico rename to frameworks/react/public/favicon.ico diff --git a/frameworks/react/scan-using-foundational-api/public/index.html b/frameworks/react/public/index.html similarity index 93% rename from frameworks/react/scan-using-foundational-api/public/index.html rename to frameworks/react/public/index.html index a289ff17..ab650d8e 100644 --- a/frameworks/react/scan-using-foundational-api/public/index.html +++ b/frameworks/react/public/index.html @@ -10,7 +10,6 @@ content="Dynamsoft Barcode Reader in a React Application, helps read barcodes from camera or images." /> - -
- - - - - - - - - \ No newline at end of file diff --git a/frameworks/svelte/scan-using-foundational-api/.gitignore b/frameworks/svelte/.gitignore similarity index 100% rename from frameworks/svelte/scan-using-foundational-api/.gitignore rename to frameworks/svelte/.gitignore diff --git a/frameworks/svelte/README.md b/frameworks/svelte/README.md index 3cea8a4e..e769e6a3 100644 --- a/frameworks/svelte/README.md +++ b/frameworks/svelte/README.md @@ -1,23 +1,351 @@ -# Svelte samples +# Hello World for Vite + Svelte + TS - Dynamsoft Barcode Reader Sample -This directory contains Svelte examples demonstrating how to use the Dynamsoft Barcode Reader in Svelte applications. +[Svelte](https://svelte.dev/) is a JavaScript library meant explicitly for creating interactive UIs. Svelte compiles components into code that directly manipulates the DOM, unlike other frameworks such as Vue and React that relies on a virtual DOM for updates. Follow this guide to learn how to implement [Dynamsoft Barcode Reader JavaScript SDK](https://www.dynamsoft.com/barcode-reader/sdk-javascript/) (hereafter called "the library") into a Svelte application using Vite. Note that in this sample we will use TypeScript. -**Included examples** +In this guide, we will be using [`dynamsoft-barcode-reader-bundle 11.4.2000](https://www.npmjs.com/package/dynamsoft-barcode-reader-bundle/v/11.4.2000). -- scan-using-foundational-api/ — Svelte + Vite example using foundational API. -- scan-using-rtu-api/ — RTU API Svelte example. +> Note: +> +> If you're looking to integrate DBR-JS into a framework that we don't yet have a sample, don't worry! We have a [comprehensive guide](https://www.dynamsoft.com/barcode-reader/docs/web/programming/javascript/user-guide/use-in-framework.html) that provides detailed instruction and best practices for a seamless integration into any frameworks! +> +> Additionally, we're here to help! Please don't hesitate to [contact us](#Support) for any support or questions you might have. -## Quick start +## Official Sample -1. Change to a subexample directory, e.g.: +* Hello World for Vite + Svelte + TS - Source Code - ```bash - cd scan-using-foundational-api - ``` +## Preparation -2. Follow the subexample README for exact steps (typically: npm install && npm run dev). +Make sure you have [node](https://nodejs.org/) installed. `node 16.20.1` and `svelte 4.2.12` are used in the example below. -## Notes +## Quick Start -- Run via Vite or the framework dev server; opening files directly may break functionality. -- See the repository root README.md for general usage and license information. \ No newline at end of file +```cmd +npm install +npm run dev +``` +Then open http://localhost:5173/ to view the sample app. + +## Create the sample project + +If you're planning to start the project from scratch, in this section, we will be creating a Svelte application with Vite utilizing the Dynamsoft Barcode Reader bundle sdk. + +We'll be exploring how you could create a page that not only enables barcode scanning via a webcam or a built-in camera, but also decode barcodes from local images. + +By the end of this guide, you'll have a good understanding of the SDK and be ready to discover more ways to use it! + +### Create a Bootstrapped Svelte Application with Vite and TypeScript + +```cmd +npm create vite@latest my-app + + +√ Select a framework: » Svelte +√ Select a variant: » TypeScript +``` + +### **CD** to the root directory of the application and install necessary libraries + +```cmd +cd my-app +npm install dynamsoft-barcode-reader-bundle@11.4.2000 -E +``` + +## Start to implement + +### Add file "dynamsoft.config.ts" under "/src/" to configure libraries + +```typescript +/* /src/dynamsoft.config.ts */ +import { CoreModule } from "dynamsoft-core"; +import { LicenseManager } from "dynamsoft-license"; +import "dynamsoft-barcode-reader"; + +// Configures the paths where the .wasm files and other necessary resources for modules are located. +CoreModule.engineResourcePaths.rootDirectory = "https://cdn.jsdelivr.net/npm/"; + +/** LICENSE ALERT - README + * To use the library, you need to first specify a license key using the API "initLicense()" as shown below. + */ + +LicenseManager.initLicense("DLS2eyJvcmdhbml6YXRpb25JRCI6IjIwMDAwMSJ9", { + executeNow: true, +}); + +/** + * You can visit https://www.dynamsoft.com/customer/license/trialLicense?utm_source=samples&product=dbr&package=js to get your own trial license good for 30 days. + * Note that if you downloaded this sample from Dynamsoft while logged in, the above license key may already be your own 30-day trial license. + * For more information, see https://www.dynamsoft.com/barcode-reader/docs/web/programming/javascript/user-guide/index.html?ver=11.4.2000&cVer=true#specify-the-license&utm_source=samples or contact support@dynamsoft.com. + * LICENSE ALERT - THE END + */ + +// Optional. Preload .wasm file for reading barcodes. It will save time on the initial decoding by skipping the resource loading. +CoreModule.loadWasm(); +``` + +> Note: +> +> * `initLicense()` specify a license key to use the library. You can visit https://www.dynamsoft.com/customer/license/trialLicense?utm_source=sample&product=dbr&package=js to get your own trial license good for 30 days. +> * `engineResourcePaths` tells the library where to get the necessary resources at runtime. + +### Build directory structure + +* Create a directory `components` under `/src/` + +### Create and edit the `VideoCapture` component + +* Create `VideoCapture.svelte` under `/src/components/`. The `VideoCapture` component helps decode barcodes via camera. + +* In `VideoCapture.svelte`, add code for initializing and destroying some instances. For our stylesheet (CSS) specification, please refer to our [source code](#Official-Sample). + +```svelte + + + +
+
+ Results:
+
{resultText}
+
+``` + +> Note: +> +> * If you're looking to customize the UI, the UI customization feature are provided by the auxiliary SDK "Dynamsoft Camera Enhancer". For more details, refer to our [User Guide](https://www.dynamsoft.com/barcode-reader/docs/web/programming/javascript/user-guide/index.html#customizing-the-ui) + +### Create and edit the `ImageCapture` component + +* Create `ImageCapture.svelte` under `/src/components/`. The `ImageCapture` component helps decode barcodes in an image. + +* In `ImageCapture.svelte`, add code for initializing and destroying some instances. For our stylesheet (CSS) specification, please refer to our [source code](#Official-Sample). + +```svelte + + + +
+
+ +
+
{resultText}
+
+``` + +### Add the `VideoCapture` and `ImageCapture` component to `App.svelte` + +* On `/src/App.svelte`, we will edit the component so that it offers buttons to switch components between `VideoCapture` and `ImageCapture`. + +* Add following code to `App.svelte`. For our stylesheet (CSS) specification, please refer to our [source code](#Official-Sample). + +```svelte + + + +
+
+
+

Hello World for Svelte

+ +
+
+ + +
+ {#if mode === "video"} + + {:else} + + {/if} +
+
+``` + +* Try running the project. + +```cmd +npm run dev +``` + +If you followed all the steps correctly, you will have a working page that turns one of the cameras hooked to or built in your computer or mobile device into a barcode scanner. Also, if you want to decode a local image, just click the `Decode Image` button and select the image you want to decode. Once barcodes are found, the results will show in a dialog. + +## Support + +If you have any questions, feel free to [contact Dynamsoft support](https://www.dynamsoft.com/company/contact?utm_source=sampleReadme). \ No newline at end of file diff --git a/frameworks/svelte/scan-using-foundational-api/index.html b/frameworks/svelte/index.html similarity index 100% rename from frameworks/svelte/scan-using-foundational-api/index.html rename to frameworks/svelte/index.html diff --git a/frameworks/svelte/scan-using-foundational-api/logo.svg b/frameworks/svelte/logo.svg similarity index 100% rename from frameworks/svelte/scan-using-foundational-api/logo.svg rename to frameworks/svelte/logo.svg diff --git a/frameworks/svelte/scan-using-foundational-api/package.json b/frameworks/svelte/package.json similarity index 90% rename from frameworks/svelte/scan-using-foundational-api/package.json rename to frameworks/svelte/package.json index 8a0bc6c7..5da46364 100644 --- a/frameworks/svelte/scan-using-foundational-api/package.json +++ b/frameworks/svelte/package.json @@ -10,7 +10,7 @@ "check": "svelte-check --tsconfig ./tsconfig.json" }, "dependencies": { - "dynamsoft-barcode-reader-bundle": "11.2.4000" + "dynamsoft-barcode-reader-bundle": "11.4.2000" }, "devDependencies": { "@sveltejs/vite-plugin-svelte": "^3.0.2", @@ -21,4 +21,4 @@ "typescript": "^5.2.2", "vite": "^5.0.0" } -} +} \ No newline at end of file diff --git a/frameworks/svelte/scan-using-foundational-api/README.md b/frameworks/svelte/scan-using-foundational-api/README.md deleted file mode 100644 index 512d0e39..00000000 --- a/frameworks/svelte/scan-using-foundational-api/README.md +++ /dev/null @@ -1,351 +0,0 @@ -# Hello World for Vite + Svelte + TS - Dynamsoft Barcode Reader Sample - -[Svelte](https://svelte.dev/) is a JavaScript library meant explicitly for creating interactive UIs. Svelte compiles components into code that directly manipulates the DOM, unlike other frameworks such as Vue and React that relies on a virtual DOM for updates. Follow this guide to learn how to implement [Dynamsoft Barcode Reader JavaScript SDK](https://www.dynamsoft.com/barcode-reader/sdk-javascript/) (hereafter called "the library") into a Svelte application using Vite. Note that in this sample we will use TypeScript. - -In this guide, we will be using [`dynamsoft-barcode-reader-bundle 11.2.4000](https://www.npmjs.com/package/dynamsoft-barcode-reader-bundle/v/11.2.4000). - -> Note: -> -> If you’re looking to integrate DBR-JS into a framework that we don't yet have a sample, don't worry! We have a [comprehensive guide](https://www.dynamsoft.com/barcode-reader/docs/web/programming/javascript/user-guide/use-in-framework.html) that provides detailed instruction and best practices for a seamless integration into any frameworks! -> -> Additionally, we're here to help! Please don't hesitate to [contact us](#Support) for any support or questions you might have. - -## Official Sample - -* Hello World for Vite + Svelte + TS - Source Code - -## Preparation - -Make sure you have [node](https://nodejs.org/) installed. `node 16.20.1` and `svelte 4.2.12` are used in the example below. - -## Quick Start - -```cmd -npm install -npm run dev -``` -Then open http://localhost:5173/ to view the sample app. - -## Create the sample project - -If you're planning to start the project from scratch, in this section, we will be creating a Svelte application with Vite utilizing the Dynamsoft Barcode Reader bundle sdk. - -We'll be exploring how you could create a page that not only enables barcode scanning via a webcam or a built-in camera, but also decode barcodes from local images. - -By the end of this guide, you'll have a good understanding of the SDK and be ready to discover more ways to use it! - -### Create a Bootstrapped Svelte Application with Vite and TypeScript - -```cmd -npm create vite@latest my-app - - -√ Select a framework: » Svelte -√ Select a variant: » TypeScript -``` - -### **CD** to the root directory of the application and install necessary libraries - -```cmd -cd my-app -npm install dynamsoft-barcode-reader-bundle@11.2.4000 -E -``` - -## Start to implement - -### Add file "dynamsoft.config.ts" under "/src/" to configure libraries - -```typescript -/* /src/dynamsoft.config.ts */ -import { CoreModule } from "dynamsoft-core"; -import { LicenseManager } from "dynamsoft-license"; -import "dynamsoft-barcode-reader"; - -// Configures the paths where the .wasm files and other necessary resources for modules are located. -CoreModule.engineResourcePaths.rootDirectory = "https://cdn.jsdelivr.net/npm/"; - -/** LICENSE ALERT - README - * To use the library, you need to first specify a license key using the API "initLicense()" as shown below. - */ - -LicenseManager.initLicense("DLS2eyJvcmdhbml6YXRpb25JRCI6IjIwMDAwMSJ9", { - executeNow: true, -}); - -/** - * You can visit https://www.dynamsoft.com/customer/license/trialLicense?utm_source=samples&product=dbr&package=js to get your own trial license good for 30 days. - * Note that if you downloaded this sample from Dynamsoft while logged in, the above license key may already be your own 30-day trial license. - * For more information, see https://www.dynamsoft.com/barcode-reader/docs/web/programming/javascript/user-guide/index.html?ver=11.2.4000&cVer=true#specify-the-license&utm_source=samples or contact support@dynamsoft.com. - * LICENSE ALERT - THE END - */ - -// Optional. Preload .wasm file for reading barcodes. It will save time on the initial decoding by skipping the resource loading. -CoreModule.loadWasm(); -``` - -> Note: -> -> * `initLicense()` specify a license key to use the library. You can visit https://www.dynamsoft.com/customer/license/trialLicense?utm_source=sample&product=dbr&package=js to get your own trial license good for 30 days. -> * `engineResourcePaths` tells the library where to get the necessary resources at runtime. - -### Build directory structure - -* Create a directory `components` under `/src/` - -### Create and edit the `VideoCapture` component - -* Create `VideoCapture.svelte` under `/src/components/`. The `VideoCapture` component helps decode barcodes via camera. - -* In `VideoCapture.svelte`, add code for initializing and destroying some instances. For our stylesheet (CSS) specification, please refer to our [source code](#Official-Sample). - -```svelte - - - -
-
- Results:
-
{resultText}
-
-``` - -> Note: -> -> * If you're looking to customize the UI, the UI customization feature are provided by the auxiliary SDK "Dynamsoft Camera Enhancer". For more details, refer to our [User Guide](https://www.dynamsoft.com/barcode-reader/docs/web/programming/javascript/user-guide/index.html#customizing-the-ui) - -### Create and edit the `ImageCapture` component - -* Create `ImageCapture.svelte` under `/src/components/`. The `ImageCapture` component helps decode barcodes in an image. - -* In `ImageCapture.svelte`, add code for initializing and destroying some instances. For our stylesheet (CSS) specification, please refer to our [source code](#Official-Sample). - -```svelte - - - -
-
- -
-
{resultText}
-
-``` - -### Add the `VideoCapture` and `ImageCapture` component to `App.svelte` - -* On `/src/App.svelte`, we will edit the component so that it offers buttons to switch components between `VideoCapture` and `ImageCapture`. - -* Add following code to `App.svelte`. For our stylesheet (CSS) specification, please refer to our [source code](#Official-Sample). - -```svelte - - - -
-
-
-

Hello World for Svelte

- -
-
- - -
- {#if mode === "video"} - - {:else} - - {/if} -
-
-``` - -* Try running the project. - -```cmd -npm run dev -``` - -If you followed all the steps correctly, you will have a working page that turns one of the cameras hooked to or built in your computer or mobile device into a barcode scanner. Also, if you want to decode a local image, just click the `Decode Image` button and select the image you want to decode. Once barcodes are found, the results will show in a dialog. - -## Support - -If you have any questions, feel free to [contact Dynamsoft support](https://www.dynamsoft.com/company/contact?utm_source=sampleReadme). \ No newline at end of file diff --git a/frameworks/svelte/scan-using-rtu-api/.gitignore b/frameworks/svelte/scan-using-rtu-api/.gitignore deleted file mode 100644 index b398d222..00000000 --- a/frameworks/svelte/scan-using-rtu-api/.gitignore +++ /dev/null @@ -1,26 +0,0 @@ -# Logs -logs -*.log -npm-debug.log* -yarn-debug.log* -yarn-error.log* -pnpm-debug.log* -lerna-debug.log* - -node_modules -dist -dist-ssr -*.local - -# Editor directories and files -.vscode/* -!.vscode/extensions.json -.idea -.DS_Store -*.suo -*.ntvs* -*.njsproj -*.sln -*.sw? - -package-lock.json diff --git a/frameworks/svelte/scan-using-rtu-api/README.md b/frameworks/svelte/scan-using-rtu-api/README.md deleted file mode 100644 index 567cc40a..00000000 --- a/frameworks/svelte/scan-using-rtu-api/README.md +++ /dev/null @@ -1,33 +0,0 @@ -# 📦 Scan Single Barcode - Svelte - -This sample shows how to integrate the `BarcodeScanner` API from the [Dynamsoft Barcode Reader JavaScript SDK](https://www.dynamsoft.com/barcode-reader/sdk-javascript/) into a **Svelte** application to scan a single barcode from video. - -## ✨ Features - -- Easy integration with pre-built UI -- BarcodeScanner instance created in a Svelte component -- Scans one barcode at a time from video - -## 🚀 Quick Start - -### 1. Install Dependencies - -```bash -npm install -``` - -### 2. Run the App - -```bash -npm run dev -``` - -Then open http://localhost:5173/ to view the sample app. - -## 📌 Customization - -Please check the official [documentation](https://dynamsoft.com/barcode-reader/docs/web/programming/javascript/user-guide/barcode-scanner-customization.html). - -## 📄 Support - -If you have any questions, feel free to [contact Dynamsoft Support](https://www.dynamsoft.com/company/contact?utm_source=sampleReadme). diff --git a/frameworks/svelte/scan-using-rtu-api/index.html b/frameworks/svelte/scan-using-rtu-api/index.html deleted file mode 100644 index dce29517..00000000 --- a/frameworks/svelte/scan-using-rtu-api/index.html +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - Dynamsoft Barcode Reader Sample - Hello World (Decode via Camera) - - -
- - - diff --git a/frameworks/svelte/scan-using-rtu-api/package.json b/frameworks/svelte/scan-using-rtu-api/package.json deleted file mode 100644 index 8c35efa4..00000000 --- a/frameworks/svelte/scan-using-rtu-api/package.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "name": "dbrjs-svelte-rtu", - "private": true, - "version": "0.0.0", - "type": "module", - "scripts": { - "dev": "vite", - "build": "vite build", - "preview": "vite preview", - "check": "svelte-check --tsconfig ./tsconfig.json" - }, - "dependencies": { - "dynamsoft-barcode-reader-bundle": "11.2.4000" - }, - "devDependencies": { - "@sveltejs/vite-plugin-svelte": "^3.0.2", - "@tsconfig/svelte": "^5.0.2", - "svelte": "^4.2.12", - "svelte-check": "^3.6.6", - "tslib": "^2.6.2", - "typescript": "^5.2.2", - "vite": "^5.0.0" - } -} diff --git a/frameworks/svelte/scan-using-rtu-api/src/App.svelte b/frameworks/svelte/scan-using-rtu-api/src/App.svelte deleted file mode 100644 index f966ed5b..00000000 --- a/frameworks/svelte/scan-using-rtu-api/src/App.svelte +++ /dev/null @@ -1,67 +0,0 @@ - - -
-

Barcode Scanner for Svelte

-
-
diff --git a/frameworks/svelte/scan-using-rtu-api/src/main.ts b/frameworks/svelte/scan-using-rtu-api/src/main.ts deleted file mode 100644 index 8c4eaed9..00000000 --- a/frameworks/svelte/scan-using-rtu-api/src/main.ts +++ /dev/null @@ -1,7 +0,0 @@ -import App from "./App.svelte"; - -const app = new App({ - target: document.getElementById("app")!, -}); - -export default app; diff --git a/frameworks/svelte/scan-using-rtu-api/src/vite-env.d.ts b/frameworks/svelte/scan-using-rtu-api/src/vite-env.d.ts deleted file mode 100644 index 4078e747..00000000 --- a/frameworks/svelte/scan-using-rtu-api/src/vite-env.d.ts +++ /dev/null @@ -1,2 +0,0 @@ -/// -/// diff --git a/frameworks/svelte/scan-using-rtu-api/svelte.config.js b/frameworks/svelte/scan-using-rtu-api/svelte.config.js deleted file mode 100644 index b0683fd2..00000000 --- a/frameworks/svelte/scan-using-rtu-api/svelte.config.js +++ /dev/null @@ -1,7 +0,0 @@ -import { vitePreprocess } from '@sveltejs/vite-plugin-svelte' - -export default { - // Consult https://svelte.dev/docs#compile-time-svelte-preprocess - // for more information about preprocessors - preprocess: vitePreprocess(), -} diff --git a/frameworks/svelte/scan-using-rtu-api/tsconfig.json b/frameworks/svelte/scan-using-rtu-api/tsconfig.json deleted file mode 100644 index 5fb548f2..00000000 --- a/frameworks/svelte/scan-using-rtu-api/tsconfig.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "extends": "@tsconfig/svelte/tsconfig.json", - "compilerOptions": { - "target": "ESNext", - "useDefineForClassFields": true, - "module": "ESNext", - "resolveJsonModule": true, - /** - * Typecheck JS in `.svelte` and `.js` files by default. - * Disable checkJs if you'd like to use dynamic types in JS. - * Note that setting allowJs false does not prevent the use - * of JS in `.svelte` files. - */ - "allowJs": true, - "checkJs": true, - "isolatedModules": true - }, - "include": ["src/**/*.ts", "src/**/*.js", "src/**/*.svelte"], - "references": [{ "path": "./tsconfig.node.json" }] -} diff --git a/frameworks/svelte/scan-using-rtu-api/tsconfig.node.json b/frameworks/svelte/scan-using-rtu-api/tsconfig.node.json deleted file mode 100644 index d02c37df..00000000 --- a/frameworks/svelte/scan-using-rtu-api/tsconfig.node.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "compilerOptions": { - "composite": true, - "skipLibCheck": true, - "module": "ESNext", - "moduleResolution": "bundler", - "strict": true - }, - "include": ["vite.config.ts"] -} diff --git a/frameworks/svelte/scan-using-rtu-api/vite.config.ts b/frameworks/svelte/scan-using-rtu-api/vite.config.ts deleted file mode 100644 index 2aeffabd..00000000 --- a/frameworks/svelte/scan-using-rtu-api/vite.config.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { defineConfig } from 'vite' -import { svelte } from '@sveltejs/vite-plugin-svelte' - -// https://vitejs.dev/config/ -export default defineConfig({ - plugins: [svelte()], - base: "./" -}) diff --git a/frameworks/svelte/scan-using-foundational-api/src/App.svelte b/frameworks/svelte/src/App.svelte similarity index 100% rename from frameworks/svelte/scan-using-foundational-api/src/App.svelte rename to frameworks/svelte/src/App.svelte diff --git a/frameworks/svelte/scan-using-foundational-api/src/components/ImageCapture.svelte b/frameworks/svelte/src/components/ImageCapture.svelte similarity index 100% rename from frameworks/svelte/scan-using-foundational-api/src/components/ImageCapture.svelte rename to frameworks/svelte/src/components/ImageCapture.svelte diff --git a/frameworks/svelte/scan-using-foundational-api/src/components/VideoCapture.svelte b/frameworks/svelte/src/components/VideoCapture.svelte similarity index 98% rename from frameworks/svelte/scan-using-foundational-api/src/components/VideoCapture.svelte rename to frameworks/svelte/src/components/VideoCapture.svelte index 48ccb59d..435c85c6 100644 --- a/frameworks/svelte/scan-using-foundational-api/src/components/VideoCapture.svelte +++ b/frameworks/svelte/src/components/VideoCapture.svelte @@ -50,7 +50,7 @@ cvRouter.setInput(cameraEnhancer); // Define a callback for results. - cvRouter.addResultReceiver({ + await cvRouter.addResultReceiver({ onDecodedBarcodesReceived: (result) => { if (!result.barcodeResultItems.length) return; diff --git a/frameworks/svelte/scan-using-foundational-api/src/dynamsoft.config.ts b/frameworks/svelte/src/dynamsoft.config.ts similarity index 94% rename from frameworks/svelte/scan-using-foundational-api/src/dynamsoft.config.ts rename to frameworks/svelte/src/dynamsoft.config.ts index f3e49db1..f6b6c6eb 100644 --- a/frameworks/svelte/scan-using-foundational-api/src/dynamsoft.config.ts +++ b/frameworks/svelte/src/dynamsoft.config.ts @@ -13,7 +13,7 @@ LicenseManager.initLicense("DLS2eyJvcmdhbml6YXRpb25JRCI6IjIwMDAwMSJ9", { execute /** * You can visit https://www.dynamsoft.com/customer/license/trialLicense?utm_source=samples&product=dbr&package=js to get your own trial license good for 30 days. * Note that if you downloaded this sample from Dynamsoft while logged in, the above license key may already be your own 30-day trial license. - * For more information, see https://www.dynamsoft.com/barcode-reader/docs/web/programming/javascript/user-guide/index.html?ver=11.2.4000&cVer=true#specify-the-license&utm_source=samples or contact support@dynamsoft.com. + * For more information, see https://www.dynamsoft.com/barcode-reader/docs/web/programming/javascript/user-guide/index.html?ver=11.4.2000&cVer=true#specify-the-license&utm_source=samples or contact support@dynamsoft.com. * LICENSE ALERT - THE END */ diff --git a/frameworks/svelte/scan-using-foundational-api/src/main.ts b/frameworks/svelte/src/main.ts similarity index 100% rename from frameworks/svelte/scan-using-foundational-api/src/main.ts rename to frameworks/svelte/src/main.ts diff --git a/frameworks/svelte/scan-using-foundational-api/src/vite-env.d.ts b/frameworks/svelte/src/vite-env.d.ts similarity index 100% rename from frameworks/svelte/scan-using-foundational-api/src/vite-env.d.ts rename to frameworks/svelte/src/vite-env.d.ts diff --git a/frameworks/svelte/scan-using-foundational-api/svelte.config.js b/frameworks/svelte/svelte.config.js similarity index 100% rename from frameworks/svelte/scan-using-foundational-api/svelte.config.js rename to frameworks/svelte/svelte.config.js diff --git a/frameworks/svelte/scan-using-foundational-api/tsconfig.json b/frameworks/svelte/tsconfig.json similarity index 100% rename from frameworks/svelte/scan-using-foundational-api/tsconfig.json rename to frameworks/svelte/tsconfig.json diff --git a/frameworks/svelte/scan-using-foundational-api/tsconfig.node.json b/frameworks/svelte/tsconfig.node.json similarity index 100% rename from frameworks/svelte/scan-using-foundational-api/tsconfig.node.json rename to frameworks/svelte/tsconfig.node.json diff --git a/frameworks/svelte/scan-using-foundational-api/vite.config.ts b/frameworks/svelte/vite.config.ts similarity index 100% rename from frameworks/svelte/scan-using-foundational-api/vite.config.ts rename to frameworks/svelte/vite.config.ts diff --git a/frameworks/vue/scan-using-foundational-api/.gitignore b/frameworks/vue/.gitignore similarity index 100% rename from frameworks/vue/scan-using-foundational-api/.gitignore rename to frameworks/vue/.gitignore diff --git a/frameworks/vue/README.md b/frameworks/vue/README.md index 05808ade..a7abe7b2 100644 --- a/frameworks/vue/README.md +++ b/frameworks/vue/README.md @@ -1,30 +1,379 @@ -# Vue samples +# Hello World Sample for Vue3 -This directory contains Vue-based examples demonstrating how to use the Dynamsoft Barcode Reader (JavaScript edition) in Vue projects. +[Vue 3](https://v3.vuejs.org/) is version 3 of Vue which is a progressive framework for building user interfaces. Check out the following guide on how to implement [Dynamsoft Barcode Reader JavaScript SDK](https://www.dynamsoft.com/barcode-reader/sdk-javascript/) (hereafter called "the library") into a Vue 3 application. Note that in this sample, `TypeScript` is used. -**Included examples** +In this guide, we will be using [`dynamsoft-barcode-reader-bundle 11.4.2000](https://www.npmjs.com/package/dynamsoft-barcode-reader-bundle/v/11.4.2000). -- `scan-using-foundational-api/` — Full example using the foundational API. -- `scan-using-rtu-api/` — Demo showing usage of the RTU API. +> Note: +> +> If you're looking to integrate DBR-JS into a framework that we don't yet have a sample, don't worry! We have a [comprehensive guide](https://www.dynamsoft.com/barcode-reader/docs/web/programming/javascript/user-guide/use-in-framework.html) that provides detailed instruction and best practices for a seamless integration into any frameworks! +> +> Additionally, we're here to help! Please don't hesitate to [contact us](#Support) for any support or questions you might have. -## Quick start +## Official Sample -1. Change to a subexample directory, for example: +* Hello World in Vue 3 - Source Code - ```bash - cd scan-using-foundational-api - ``` +## Preparation -2. Install dependencies and start the dev server: +Make sure you have [node](https://nodejs.org/) installed. `node 16.20.1` and `vue 3.3.4` are used in the example below. - ```bash - npm install - npm run dev - ``` +## Quick Start -3. Open the local address shown in the terminal (commonly `http://localhost:3000` when using Vite). +```cmd +npm install +npm run dev +``` +Then open http://localhost:5173/ to view the sample app. -## Notes +## Creating the sample project -- Run the example via a development server. Opening static HTML files directly may break module loading or camera access. -- For general usage and license info, see the repository root `README.md`. \ No newline at end of file +In this section, we will be creating a Vue application utilizing the Dynamsoft Barcode Reader bundle sdk. + +We'll be exploring how you could create a page that not only enables barcode scanning via a webcam or a built-in camera, but also decode barcodes from local images. + +By the end of this guide, you'll have a good understanding of the SDK and be ready to discover more ways to use it! + +### Create a Bootstrapped Raw Vue Application + +```cmd +npm create vue@3 +``` + +On installation, you will be prompted to configure your project.\ +You can customize these options according to your preferences.\ +Below is the configuration used for this sample. + +``` +√ Project name: ... vue-project +√ Add TypeScript? ... Yes +√ Add JSX Support? ... No +√ Add Vue Router for Single Page Application development? ... No +√ Add Pinia for state management? ... No +√ Add Vitest for Unit Testing? ... No +√ Add an End-to-End Testing Solution? » No +√ Add ESLint for code quality? ... No +√ Add Vue DevTools 7 extension for debugging? (experimental) ... No +``` + +### **CD** to the root directory of the application and install necessary libraries + +```cmd +cd vue-project +npm install dynamsoft-barcode-reader-bundle@11.4.2000 -E +``` + +## Start to implement + +### Add file "dynamsoft.config.ts" under "/src/" to configure libraries + +```typescript +/* /src/dynamsoft.config.ts */ +import { CoreModule } from "dynamsoft-core"; +import { LicenseManager } from "dynamsoft-license"; +import "dynamsoft-barcode-reader"; + +// Configures the paths where the .wasm files and other necessary resources for modules are located. +CoreModule.engineResourcePaths.rootDirectory = "https://cdn.jsdelivr.net/npm/"; + +/** LICENSE ALERT - README + * To use the library, you need to first specify a license key using the API "initLicense()" as shown below. + */ + +LicenseManager.initLicense("DLS2eyJvcmdhbml6YXRpb25JRCI6IjIwMDAwMSJ9", { + executeNow: true, +}); + +/** + * You can visit https://www.dynamsoft.com/customer/license/trialLicense?utm_source=samples&product=dbr&package=js to get your own trial license good for 30 days. + * Note that if you downloaded this sample from Dynamsoft while logged in, the above license key may already be your own 30-day trial license. + * For more information, see https://www.dynamsoft.com/barcode-reader/docs/web/programming/javascript/user-guide/index.html?ver=11.4.2000&cVer=true#specify-the-license&utm_source=samples or contact support@dynamsoft.com. + * LICENSE ALERT - THE END + */ + +// Optional. Preload .wasm file for reading barcodes. It will save time on the initial decoding by skipping the resource loading. +CoreModule.loadWasm(); +``` + +> Note: +> +> * `initLicense()` specify a license key to use the library. You can visit https://www.dynamsoft.com/customer/license/trialLicense?utm_source=sample&product=dbr&package=js to get your own trial license good for 30 days. +> * `engineResourcePaths` tells the library where to get the necessary resources at runtime. + +### Create and edit the `VideoCapture` component + +* Create `VideoCapture.vue` under `/components/`. The VideoCapture component helps decode barcodes via camera. + +* In `VideoCapture.vue`, add the following code for initializing and destroying some instances. For our stylesheet (CSS) specification, please refer to our [source code](#Official-Sample). + +```vue + + + + +``` +> Note: +> +> If you're looking to customize the UI, the UI customization feature are provided by the auxiliary SDK "Dynamsoft Camera Enhancer". For more details, refer to our [User Guide](https://www.dynamsoft.com/barcode-reader/docs/web/programming/javascript/user-guide/index.html#customizing-the-ui) + +### Create and edit the `ImageCapture` component + +* Create `ImageCapture.vue` under `/components/`. The `ImageCapture` component helps decode barcodes in an image. + +* In `ImageCapture.vue`, add code for initializing and destroying `CaptureVisionRouter` instance. For our stylesheet (CSS) specification, please refer to our [source code](#Official-Sample). + +```vue + + + + +``` + +### Add the `VideoCapture` and `ImageCapture` component to `App.vue` + +* On `/src/App.vue`, we will edit the component so that it offers buttons to switch components between `VideoCapture` and `ImageCapture`. + +* Add following code to `App.vue`. For our stylesheet (CSS) specification, please refer to our [source code](#Official-Sample). + +```vue + + + + +``` +> Note: +> +> With Vue's `defineAsyncComponent` we can improve the initial load speed and performance of the application. +> +> `defineAsyncComponent` allows us to load components such as `VideoCapture` and `ImageCapture` asynchronously, which means that the component's code is only loaded when it's needed. This will result in a faster initial load times. +> +> However, if you're implementing server-side rendering with Vue, using `defineAsyncComponent` might cause issues while loading `VideoCapture` and `ImageCapture` as we use the window/document object. Make sure to load these components on the client-side! +> +> Read more: https://vuejs.org/guide/components/async.html + +* Try running the project. + +```cmd +npm run dev +``` +If you followed all the steps correctly, you will have a working page that turns one of the cameras hooked to or built in your computer or mobile device into a barcode scanner. Also, if you want to decode a local image, just click the `Decode Image` button and select the image you want to decode. Once barcodes are found, the results will show in a dialog. + +### Comment out the following code in `assets/main.css`. (optional) + +```css +@media (min-width: 1024px) { + /* body { + display: flex; + place-items: center; + } + + #app { + display: grid; + grid-template-columns: 1fr 1fr; + padding: 0 2rem; + } */ +} +``` + +## Project Setup + +```sh +npm install +``` + +### Compile and Hot-Reload for Development + +```sh +npm run dev +``` + +### Type-Check, Compile and Minify for Production + +```sh +npm run build +``` + +## Support + +If you have any questions, feel free to [contact Dynamsoft support](https://www.dynamsoft.com/company/contact?utm_source=sampleReadme). diff --git a/frameworks/vue/scan-using-foundational-api/env.d.ts b/frameworks/vue/env.d.ts similarity index 100% rename from frameworks/vue/scan-using-foundational-api/env.d.ts rename to frameworks/vue/env.d.ts diff --git a/frameworks/vue/scan-using-foundational-api/index.html b/frameworks/vue/index.html similarity index 83% rename from frameworks/vue/scan-using-foundational-api/index.html rename to frameworks/vue/index.html index 5c2edf90..b9a150ab 100644 --- a/frameworks/vue/scan-using-foundational-api/index.html +++ b/frameworks/vue/index.html @@ -9,7 +9,6 @@ content="Dynamsoft Barcode Reader in a Vue 3 Application, helps read barcodes from camera or images." /> - Hello World for Vue 3 - Dynamsoft Barcode Reader Sample diff --git a/frameworks/vue/scan-using-foundational-api/package.json b/frameworks/vue/package.json similarity index 91% rename from frameworks/vue/scan-using-foundational-api/package.json rename to frameworks/vue/package.json index 22f56bbb..65b59454 100644 --- a/frameworks/vue/scan-using-foundational-api/package.json +++ b/frameworks/vue/package.json @@ -11,7 +11,7 @@ "type-check": "vue-tsc --noEmit" }, "dependencies": { - "dynamsoft-barcode-reader-bundle": "11.2.4000", + "dynamsoft-barcode-reader-bundle": "11.4.2000", "vue": "^3.2.45" }, "devDependencies": { @@ -23,4 +23,4 @@ "vite": "^4.0.0", "vue-tsc": "^1.0.12" } -} +} \ No newline at end of file diff --git a/frameworks/vue/scan-using-foundational-api/public/favicon.ico b/frameworks/vue/public/favicon.ico similarity index 100% rename from frameworks/vue/scan-using-foundational-api/public/favicon.ico rename to frameworks/vue/public/favicon.ico diff --git a/frameworks/vue/scan-using-foundational-api/README.md b/frameworks/vue/scan-using-foundational-api/README.md deleted file mode 100644 index 367862ba..00000000 --- a/frameworks/vue/scan-using-foundational-api/README.md +++ /dev/null @@ -1,379 +0,0 @@ -# Hello World Sample for Vue3 - -[Vue 3](https://v3.vuejs.org/) is version 3 of Vue which is a progressive framework for building user interfaces. Check out the following guide on how to implement [Dynamsoft Barcode Reader JavaScript SDK](https://www.dynamsoft.com/barcode-reader/sdk-javascript/) (hereafter called "the library") into a Vue 3 application. Note that in this sample, `TypeScript` is used. - -In this guide, we will be using [`dynamsoft-barcode-reader-bundle 11.2.4000](https://www.npmjs.com/package/dynamsoft-barcode-reader-bundle/v/11.2.4000). - -> Note: -> -> If you’re looking to integrate DBR-JS into a framework that we don't yet have a sample, don't worry! We have a [comprehensive guide](https://www.dynamsoft.com/barcode-reader/docs/web/programming/javascript/user-guide/use-in-framework.html) that provides detailed instruction and best practices for a seamless integration into any frameworks! -> -> Additionally, we're here to help! Please don't hesitate to [contact us](#Support) for any support or questions you might have. - -## Official Sample - -* Hello World in Vue 3 - Source Code - -## Preparation - -Make sure you have [node](https://nodejs.org/) installed. `node 16.20.1` and `vue 3.3.4` are used in the example below. - -## Quick Start - -```cmd -npm install -npm run dev -``` -Then open http://localhost:5173/ to view the sample app. - -## Creating the sample project - -In this section, we will be creating a Vue application utilizing the Dynamsoft Barcode Reader bundle sdk. - -We'll be exploring how you could create a page that not only enables barcode scanning via a webcam or a built-in camera, but also decode barcodes from local images. - -By the end of this guide, you'll have a good understanding of the SDK and be ready to discover more ways to use it! - -### Create a Bootstrapped Raw Vue Application - -```cmd -npm create vue@3 -``` - -On installation, you will be prompted to configure your project.\ -You can customize these options according to your preferences.\ -Below is the configuration used for this sample. - -``` -√ Project name: ... vue-project -√ Add TypeScript? ... Yes -√ Add JSX Support? ... No -√ Add Vue Router for Single Page Application development? ... No -√ Add Pinia for state management? ... No -√ Add Vitest for Unit Testing? ... No -√ Add an End-to-End Testing Solution? » No -√ Add ESLint for code quality? ... No -√ Add Vue DevTools 7 extension for debugging? (experimental) ... No -``` - -### **CD** to the root directory of the application and install necessary libraries - -```cmd -cd vue-project -npm install dynamsoft-barcode-reader-bundle@11.2.4000 -E -``` - -## Start to implement - -### Add file "dynamsoft.config.ts" under "/src/" to configure libraries - -```typescript -/* /src/dynamsoft.config.ts */ -import { CoreModule } from "dynamsoft-core"; -import { LicenseManager } from "dynamsoft-license"; -import "dynamsoft-barcode-reader"; - -// Configures the paths where the .wasm files and other necessary resources for modules are located. -CoreModule.engineResourcePaths.rootDirectory = "https://cdn.jsdelivr.net/npm/"; - -/** LICENSE ALERT - README - * To use the library, you need to first specify a license key using the API "initLicense()" as shown below. - */ - -LicenseManager.initLicense("DLS2eyJvcmdhbml6YXRpb25JRCI6IjIwMDAwMSJ9", { - executeNow: true, -}); - -/** - * You can visit https://www.dynamsoft.com/customer/license/trialLicense?utm_source=samples&product=dbr&package=js to get your own trial license good for 30 days. - * Note that if you downloaded this sample from Dynamsoft while logged in, the above license key may already be your own 30-day trial license. - * For more information, see https://www.dynamsoft.com/barcode-reader/docs/web/programming/javascript/user-guide/index.html?ver=11.2.4000&cVer=true#specify-the-license&utm_source=samples or contact support@dynamsoft.com. - * LICENSE ALERT - THE END - */ - -// Optional. Preload .wasm file for reading barcodes. It will save time on the initial decoding by skipping the resource loading. -CoreModule.loadWasm(); -``` - -> Note: -> -> * `initLicense()` specify a license key to use the library. You can visit https://www.dynamsoft.com/customer/license/trialLicense?utm_source=sample&product=dbr&package=js to get your own trial license good for 30 days. -> * `engineResourcePaths` tells the library where to get the necessary resources at runtime. - -### Create and edit the `VideoCapture` component - -* Create `VideoCapture.vue` under `/components/`. The VideoCapture component helps decode barcodes via camera. - -* In `VideoCapture.vue`, add the following code for initializing and destroying some instances. For our stylesheet (CSS) specification, please refer to our [source code](#Official-Sample). - -```vue - - - - -``` -> Note: -> -> If you're looking to customize the UI, the UI customization feature are provided by the auxiliary SDK "Dynamsoft Camera Enhancer". For more details, refer to our [User Guide](https://www.dynamsoft.com/barcode-reader/docs/web/programming/javascript/user-guide/index.html#customizing-the-ui) - -### Create and edit the `ImageCapture` component - -* Create `ImageCapture.vue` under `/components/`. The `ImageCapture` component helps decode barcodes in an image. - -* In `ImageCapture.vue`, add code for initializing and destroying `CaptureVisionRouter` instance. For our stylesheet (CSS) specification, please refer to our [source code](#Official-Sample). - -```vue - - - - -``` - -### Add the `VideoCapture` and `ImageCapture` component to `App.vue` - -* On `/src/App.vue`, we will edit the component so that it offers buttons to switch components between `VideoCapture` and `ImageCapture`. - -* Add following code to `App.vue`. For our stylesheet (CSS) specification, please refer to our [source code](#Official-Sample). - -```vue - - - - -``` -> Note: -> -> With Vue's `defineAsyncComponent` we can improve the initial load speed and performance of the application. -> -> `defineAsyncComponent` allows us to load components such as `VideoCapture` and `ImageCapture` asynchronously, which means that the component's code is only loaded when it's needed. This will result in a faster initial load times. -> -> However, if you're implementing server-side rendering with Vue, using `defineAsyncComponent` might cause issues while loading `VideoCapture` and `ImageCapture` as we use the window/document object. Make sure to load these components on the client-side! -> -> Read more: https://vuejs.org/guide/components/async.html - -* Try running the project. - -```cmd -npm run dev -``` -If you followed all the steps correctly, you will have a working page that turns one of the cameras hooked to or built in your computer or mobile device into a barcode scanner. Also, if you want to decode a local image, just click the `Decode Image` button and select the image you want to decode. Once barcodes are found, the results will show in a dialog. - -### Comment out the following code in `assets/main.css`. (optional) - -```css -@media (min-width: 1024px) { - /* body { - display: flex; - place-items: center; - } - - #app { - display: grid; - grid-template-columns: 1fr 1fr; - padding: 0 2rem; - } */ -} -``` - -## Project Setup - -```sh -npm install -``` - -### Compile and Hot-Reload for Development - -```sh -npm run dev -``` - -### Type-Check, Compile and Minify for Production - -```sh -npm run build -``` - -## Support - -If you have any questions, feel free to [contact Dynamsoft support](https://www.dynamsoft.com/company/contact?utm_source=sampleReadme). diff --git a/frameworks/vue/scan-using-rtu-api/.gitignore b/frameworks/vue/scan-using-rtu-api/.gitignore deleted file mode 100644 index b398d222..00000000 --- a/frameworks/vue/scan-using-rtu-api/.gitignore +++ /dev/null @@ -1,26 +0,0 @@ -# Logs -logs -*.log -npm-debug.log* -yarn-debug.log* -yarn-error.log* -pnpm-debug.log* -lerna-debug.log* - -node_modules -dist -dist-ssr -*.local - -# Editor directories and files -.vscode/* -!.vscode/extensions.json -.idea -.DS_Store -*.suo -*.ntvs* -*.njsproj -*.sln -*.sw? - -package-lock.json diff --git a/frameworks/vue/scan-using-rtu-api/README.md b/frameworks/vue/scan-using-rtu-api/README.md deleted file mode 100644 index 9a06afd5..00000000 --- a/frameworks/vue/scan-using-rtu-api/README.md +++ /dev/null @@ -1,33 +0,0 @@ -# 📦 Scan Single Barcode - Vue - -This sample shows how to integrate the `BarcodeScanner` API from the [Dynamsoft Barcode Reader JavaScript SDK](https://www.dynamsoft.com/barcode-reader/sdk-javascript/) into a **Vue 3** application to scan a single barcode from video. - -## ✨ Features - -- Easy integration with pre-built UI -- BarcodeScanner instance created in a Vue component -- Scans one barcode at a time from video - -## 🚀 Quick Start - -### 1. Install Dependencies - -```bash -npm install -``` - -### 2. Run the App - -```bash -npm run dev -``` - -Then open http://localhost:5173/ to view the sample app. - -## 📌 Customization - -Please check the official [documentation](https://dynamsoft.com/barcode-reader/docs/web/programming/javascript/user-guide/barcode-scanner-customization.html). - -## 📄 Support - -If you have any questions, feel free to [contact Dynamsoft Support](https://www.dynamsoft.com/company/contact?utm_source=sampleReadme). diff --git a/frameworks/vue/scan-using-rtu-api/index.html b/frameworks/vue/scan-using-rtu-api/index.html deleted file mode 100644 index 6f337734..00000000 --- a/frameworks/vue/scan-using-rtu-api/index.html +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - Dynamsoft Barcode Reader Sample - Hello World (Decode via Camera) - - -
- - - diff --git a/frameworks/vue/scan-using-rtu-api/package.json b/frameworks/vue/scan-using-rtu-api/package.json deleted file mode 100644 index 3c209647..00000000 --- a/frameworks/vue/scan-using-rtu-api/package.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "name": "dbr-vue", - "private": true, - "version": "0.0.0", - "type": "module", - "scripts": { - "dev": "vite", - "build": "vue-tsc -b && vite build", - "preview": "vite preview" - }, - "dependencies": { - "dynamsoft-barcode-reader-bundle": "11.2.4000", - "vue": "^3.5.18" - }, - "devDependencies": { - "@vitejs/plugin-vue": "^6.0.1", - "@vue/tsconfig": "^0.7.0", - "typescript": "~5.8.3", - "vite": "^7.1.2", - "vue-tsc": "^3.0.5" - } -} diff --git a/frameworks/vue/scan-using-rtu-api/src/App.vue b/frameworks/vue/scan-using-rtu-api/src/App.vue deleted file mode 100644 index 4842b0fd..00000000 --- a/frameworks/vue/scan-using-rtu-api/src/App.vue +++ /dev/null @@ -1,61 +0,0 @@ - - - diff --git a/frameworks/vue/scan-using-rtu-api/src/main.ts b/frameworks/vue/scan-using-rtu-api/src/main.ts deleted file mode 100644 index 01433bca..00000000 --- a/frameworks/vue/scan-using-rtu-api/src/main.ts +++ /dev/null @@ -1,4 +0,0 @@ -import { createApp } from 'vue' -import App from './App.vue' - -createApp(App).mount('#app') diff --git a/frameworks/vue/scan-using-rtu-api/src/vite-env.d.ts b/frameworks/vue/scan-using-rtu-api/src/vite-env.d.ts deleted file mode 100644 index 11f02fe2..00000000 --- a/frameworks/vue/scan-using-rtu-api/src/vite-env.d.ts +++ /dev/null @@ -1 +0,0 @@ -/// diff --git a/frameworks/vue/scan-using-rtu-api/tsconfig.app.json b/frameworks/vue/scan-using-rtu-api/tsconfig.app.json deleted file mode 100644 index 3dbbc453..00000000 --- a/frameworks/vue/scan-using-rtu-api/tsconfig.app.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "extends": "@vue/tsconfig/tsconfig.dom.json", - "compilerOptions": { - "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", - - /* Linting */ - "strict": true, - "noUnusedLocals": true, - "noUnusedParameters": true, - "erasableSyntaxOnly": true, - "noFallthroughCasesInSwitch": true, - "noUncheckedSideEffectImports": true - }, - "include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.vue"] -} diff --git a/frameworks/vue/scan-using-rtu-api/tsconfig.json b/frameworks/vue/scan-using-rtu-api/tsconfig.json deleted file mode 100644 index 1ffef600..00000000 --- a/frameworks/vue/scan-using-rtu-api/tsconfig.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "files": [], - "references": [ - { "path": "./tsconfig.app.json" }, - { "path": "./tsconfig.node.json" } - ] -} diff --git a/frameworks/vue/scan-using-rtu-api/tsconfig.node.json b/frameworks/vue/scan-using-rtu-api/tsconfig.node.json deleted file mode 100644 index f85a3990..00000000 --- a/frameworks/vue/scan-using-rtu-api/tsconfig.node.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "compilerOptions": { - "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", - "target": "ES2023", - "lib": ["ES2023"], - "module": "ESNext", - "skipLibCheck": true, - - /* Bundler mode */ - "moduleResolution": "bundler", - "allowImportingTsExtensions": true, - "verbatimModuleSyntax": true, - "moduleDetection": "force", - "noEmit": true, - - /* Linting */ - "strict": true, - "noUnusedLocals": true, - "noUnusedParameters": true, - "erasableSyntaxOnly": true, - "noFallthroughCasesInSwitch": true, - "noUncheckedSideEffectImports": true - }, - "include": ["vite.config.ts"] -} diff --git a/frameworks/vue/scan-using-rtu-api/vite.config.ts b/frameworks/vue/scan-using-rtu-api/vite.config.ts deleted file mode 100644 index bbcf80cc..00000000 --- a/frameworks/vue/scan-using-rtu-api/vite.config.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { defineConfig } from 'vite' -import vue from '@vitejs/plugin-vue' - -// https://vite.dev/config/ -export default defineConfig({ - plugins: [vue()], -}) diff --git a/frameworks/vue/scan-using-foundational-api/src/App.vue b/frameworks/vue/src/App.vue similarity index 98% rename from frameworks/vue/scan-using-foundational-api/src/App.vue rename to frameworks/vue/src/App.vue index d51c0d57..752b1e44 100644 --- a/frameworks/vue/scan-using-foundational-api/src/App.vue +++ b/frameworks/vue/src/App.vue @@ -42,6 +42,7 @@ const mode: Ref = ref("video"); .buttons-container { width: 30%; margin: 20px auto; + text-align: center; } .buttons-container button { diff --git a/frameworks/vue/scan-using-foundational-api/src/assets/logo.svg b/frameworks/vue/src/assets/logo.svg similarity index 100% rename from frameworks/vue/scan-using-foundational-api/src/assets/logo.svg rename to frameworks/vue/src/assets/logo.svg diff --git a/frameworks/vue/scan-using-foundational-api/src/assets/main.css b/frameworks/vue/src/assets/main.css similarity index 72% rename from frameworks/vue/scan-using-foundational-api/src/assets/main.css rename to frameworks/vue/src/assets/main.css index 77f7db1b..cca57b36 100644 --- a/frameworks/vue/scan-using-foundational-api/src/assets/main.css +++ b/frameworks/vue/src/assets/main.css @@ -2,5 +2,4 @@ margin: 0; padding: 0; box-sizing: border-box; - text-align: center; } diff --git a/frameworks/vue/scan-using-foundational-api/src/components/ImageCapture.vue b/frameworks/vue/src/components/ImageCapture.vue similarity index 99% rename from frameworks/vue/scan-using-foundational-api/src/components/ImageCapture.vue rename to frameworks/vue/src/components/ImageCapture.vue index f0b9fe23..e01c672e 100644 --- a/frameworks/vue/scan-using-foundational-api/src/components/ImageCapture.vue +++ b/frameworks/vue/src/components/ImageCapture.vue @@ -83,5 +83,6 @@ onBeforeUnmount(async () => { margin-top: 20px; height: 100%; white-space: pre-wrap; + text-align: center; } \ No newline at end of file diff --git a/frameworks/vue/scan-using-foundational-api/src/components/VideoCapture.vue b/frameworks/vue/src/components/VideoCapture.vue similarity index 96% rename from frameworks/vue/scan-using-foundational-api/src/components/VideoCapture.vue rename to frameworks/vue/src/components/VideoCapture.vue index cab91598..c0804d0f 100644 --- a/frameworks/vue/scan-using-foundational-api/src/components/VideoCapture.vue +++ b/frameworks/vue/src/components/VideoCapture.vue @@ -37,7 +37,7 @@ onMounted(async () => { cvRouter.setInput(cameraEnhancer); // Define a callback for results. - cvRouter.addResultReceiver({ + await cvRouter.addResultReceiver({ onDecodedBarcodesReceived: (result) => { if (!result.barcodeResultItems.length) return; @@ -95,7 +95,7 @@ onBeforeUnmount(async () => {

- Results: +
Results:
{{ resultText }}
@@ -106,5 +106,6 @@ onBeforeUnmount(async () => { height: 10vh; overflow: auto; white-space: pre-wrap; + text-align: center; } \ No newline at end of file diff --git a/frameworks/vue/scan-using-foundational-api/src/dynamsoft.config.ts b/frameworks/vue/src/dynamsoft.config.ts similarity index 94% rename from frameworks/vue/scan-using-foundational-api/src/dynamsoft.config.ts rename to frameworks/vue/src/dynamsoft.config.ts index b25d65cb..e54a421d 100644 --- a/frameworks/vue/scan-using-foundational-api/src/dynamsoft.config.ts +++ b/frameworks/vue/src/dynamsoft.config.ts @@ -12,7 +12,7 @@ LicenseManager.initLicense("DLS2eyJvcmdhbml6YXRpb25JRCI6IjIwMDAwMSJ9", { execute /** * You can visit https://www.dynamsoft.com/customer/license/trialLicense?utm_source=samples&product=dbr&package=js to get your own trial license good for 30 days. * Note that if you downloaded this sample from Dynamsoft while logged in, the above license key may already be your own 30-day trial license. - * For more information, see https://www.dynamsoft.com/barcode-reader/docs/web/programming/javascript/user-guide/index.html?ver=11.2.4000&cVer=true#specify-the-license&utm_source=samples or contact support@dynamsoft.com. + * For more information, see https://www.dynamsoft.com/barcode-reader/docs/web/programming/javascript/user-guide/index.html?ver=11.4.2000&cVer=true#specify-the-license&utm_source=samples or contact support@dynamsoft.com. * LICENSE ALERT - THE END */ diff --git a/frameworks/vue/scan-using-foundational-api/src/main.ts b/frameworks/vue/src/main.ts similarity index 100% rename from frameworks/vue/scan-using-foundational-api/src/main.ts rename to frameworks/vue/src/main.ts diff --git a/frameworks/vue/scan-using-foundational-api/tsconfig.config.json b/frameworks/vue/tsconfig.config.json similarity index 100% rename from frameworks/vue/scan-using-foundational-api/tsconfig.config.json rename to frameworks/vue/tsconfig.config.json diff --git a/frameworks/vue/scan-using-foundational-api/tsconfig.json b/frameworks/vue/tsconfig.json similarity index 100% rename from frameworks/vue/scan-using-foundational-api/tsconfig.json rename to frameworks/vue/tsconfig.json diff --git a/frameworks/vue/scan-using-foundational-api/vite.config.ts b/frameworks/vue/vite.config.ts similarity index 100% rename from frameworks/vue/scan-using-foundational-api/vite.config.ts rename to frameworks/vue/vite.config.ts diff --git a/frameworks/webview/README.md b/frameworks/webview/README.md deleted file mode 100644 index 5a761c48..00000000 --- a/frameworks/webview/README.md +++ /dev/null @@ -1,23 +0,0 @@ -# WebView samples - -This directory contains WebView examples demonstrating how to use the Dynamsoft Barcode Reader inside native WebView-based apps (Android/iOS). - -**Included examples** - -- scan-using-foundational-api/ — WebView project with native wrappers and HTML demo. -- scan-using-rtu-api/ — WebView RTU example. - -## Quick start - -1. Change to a subexample directory, e.g.: - - ```bash - cd scan-using-foundational-api - ``` - -2. Follow the subexample README for platform-specific setup (open Android Studio/Xcode or run provided scripts). - -## Notes - -- Native build environments are required for mobile platform testing. See subexample README for details. -- See the repository root README.md for general usage and license \ No newline at end of file diff --git a/frameworks/webview/scan-using-foundational-api/android/.gitignore b/frameworks/webview/android/.gitignore similarity index 100% rename from frameworks/webview/scan-using-foundational-api/android/.gitignore rename to frameworks/webview/android/.gitignore diff --git a/frameworks/webview/scan-using-foundational-api/android/README.md b/frameworks/webview/android/README.md similarity index 100% rename from frameworks/webview/scan-using-foundational-api/android/README.md rename to frameworks/webview/android/README.md diff --git a/frameworks/webview/scan-using-foundational-api/android/app/.gitignore b/frameworks/webview/android/app/.gitignore similarity index 100% rename from frameworks/webview/scan-using-foundational-api/android/app/.gitignore rename to frameworks/webview/android/app/.gitignore diff --git a/frameworks/webview/scan-using-foundational-api/android/app/build.gradle b/frameworks/webview/android/app/build.gradle similarity index 100% rename from frameworks/webview/scan-using-foundational-api/android/app/build.gradle rename to frameworks/webview/android/app/build.gradle diff --git a/frameworks/webview/scan-using-foundational-api/android/app/proguard-rules.pro b/frameworks/webview/android/app/proguard-rules.pro similarity index 100% rename from frameworks/webview/scan-using-foundational-api/android/app/proguard-rules.pro rename to frameworks/webview/android/app/proguard-rules.pro diff --git a/frameworks/webview/scan-using-foundational-api/android/app/src/main/AndroidManifest.xml b/frameworks/webview/android/app/src/main/AndroidManifest.xml similarity index 100% rename from frameworks/webview/scan-using-foundational-api/android/app/src/main/AndroidManifest.xml rename to frameworks/webview/android/app/src/main/AndroidManifest.xml diff --git a/frameworks/webview/scan-using-foundational-api/android/app/src/main/assets/decodeBarcodeInVideo.html b/frameworks/webview/android/app/src/main/assets/decodeBarcodeInVideo.html similarity index 91% rename from frameworks/webview/scan-using-foundational-api/android/app/src/main/assets/decodeBarcodeInVideo.html rename to frameworks/webview/android/app/src/main/assets/decodeBarcodeInVideo.html index b5bb53d7..a0a527bc 100644 --- a/frameworks/webview/scan-using-foundational-api/android/app/src/main/assets/decodeBarcodeInVideo.html +++ b/frameworks/webview/android/app/src/main/assets/decodeBarcodeInVideo.html @@ -5,7 +5,6 @@ - Dynamsoft Barcode Reader Sample - Hello World (Decoding via Camera) @@ -14,7 +13,7 @@

Hello World (Decode via Camera)

Results:
- + + - - - - - - - - - - \ No newline at end of file diff --git a/frameworks/webview/scan-using-rtu-api/android/app/src/main/java/com/dynamsoft/dbrjswebview/MainActivity.kt b/frameworks/webview/scan-using-rtu-api/android/app/src/main/java/com/dynamsoft/dbrjswebview/MainActivity.kt deleted file mode 100644 index 8ecaf703..00000000 --- a/frameworks/webview/scan-using-rtu-api/android/app/src/main/java/com/dynamsoft/dbrjswebview/MainActivity.kt +++ /dev/null @@ -1,105 +0,0 @@ -package com.dynamsoft.dbrjswebview - -import android.Manifest -import android.annotation.SuppressLint -import android.content.pm.PackageManager -import android.net.Uri -import androidx.appcompat.app.AppCompatActivity -import android.os.Bundle -import android.webkit.* -import androidx.activity.result.contract.ActivityResultContracts -import androidx.annotation.RequiresApi -import androidx.core.content.ContextCompat -import androidx.webkit.WebViewAssetLoader -import androidx.webkit.WebViewClientCompat - -class MainActivity : AppCompatActivity() { - @SuppressLint("SetJavaScriptEnabled") - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - setContentView(R.layout.activity_main) - - val myWebView: WebView = findViewById(R.id.webview) - myWebView.settings.javaScriptEnabled = true - myWebView.settings.mediaPlaybackRequiresUserGesture = false - myWebView.settings.domStorageEnabled = true - - myWebView.webViewClient = MyWebViewClient() - myWebView.webChromeClient = MyWebChromeClient() - - myWebView.loadUrl("https://appassets.androidplatform.net/assets/decodeBarcodeInVideo.html") - } - - // Warning: If you use online url, you don't need `LocalContentWebViewClient` - // Refer: https://developer.android.com/develop/ui/views/layout/webapps/load-local-content?hl=en - private inner class MyWebViewClient : WebViewClientCompat() { - - private val assetLoader = WebViewAssetLoader.Builder() - .addPathHandler("/assets/", WebViewAssetLoader.AssetsPathHandler(this@MainActivity)) - .build() - - @RequiresApi(21) - override fun shouldInterceptRequest( - view: WebView, - request: WebResourceRequest - ): WebResourceResponse? { - return assetLoader.shouldInterceptRequest(request.url) - } - - // to support API < 21 - @Deprecated("Deprecated in Java") - override fun shouldInterceptRequest( - view: WebView, - url: String - ): WebResourceResponse? { - return assetLoader.shouldInterceptRequest(Uri.parse(url)) - } - } - - var cameraPermissionReq: PermissionRequest? = null - private inner class MyWebChromeClient : WebChromeClient() { - @RequiresApi(21) - override fun onPermissionRequest(request: PermissionRequest) { - if(request.resources.contains(PermissionRequest.RESOURCE_VIDEO_CAPTURE)){ - // Refer: https://developer.android.com/training/permissions/requesting - if(ContextCompat.checkSelfPermission( - this@MainActivity, - Manifest.permission.CAMERA - ) == PackageManager.PERMISSION_GRANTED){ - // You can use the API that requires the permission. - request.grant(arrayOf(PermissionRequest.RESOURCE_VIDEO_CAPTURE)) - }else{ - // You can directly ask for the permission. - // The registered ActivityResultCallback gets the result of this request. - this@MainActivity.cameraPermissionReq = request - requestCameraPermissionLauncher.launch(Manifest.permission.CAMERA) - } - }else{ - request.deny() - } - } - } - - // Refer: https://developer.android.com/training/permissions/requesting - @RequiresApi(21) - val requestCameraPermissionLauncher = registerForActivityResult( - ActivityResultContracts.RequestPermission() - ) { isGranted: Boolean -> - // Refer: https://www.dynamsoft.com/codepool/use-barcode-scanner-in-android-webview.html#set-up-webview - this@MainActivity.runOnUiThread { - if (isGranted) { - // Permission is granted. Continue the action or workflow in your - // app. - cameraPermissionReq?.grant(arrayOf(PermissionRequest.RESOURCE_VIDEO_CAPTURE)) - } else { - // Explain to the user that the feature is unavailable because the - // feature requires a permission that the user has denied. At the - // same time, respect the user's decision. Don't link to system - // settings in an effort to convince the user to change their - // decision. - cameraPermissionReq?.deny() - } - cameraPermissionReq = null - } - } -} \ No newline at end of file diff --git a/frameworks/webview/scan-using-rtu-api/android/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/frameworks/webview/scan-using-rtu-api/android/app/src/main/res/drawable-v24/ic_launcher_foreground.xml deleted file mode 100644 index 2b068d11..00000000 --- a/frameworks/webview/scan-using-rtu-api/android/app/src/main/res/drawable-v24/ic_launcher_foreground.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/frameworks/webview/scan-using-rtu-api/android/app/src/main/res/drawable/ic_launcher_background.xml b/frameworks/webview/scan-using-rtu-api/android/app/src/main/res/drawable/ic_launcher_background.xml deleted file mode 100644 index 07d5da9c..00000000 --- a/frameworks/webview/scan-using-rtu-api/android/app/src/main/res/drawable/ic_launcher_background.xml +++ /dev/null @@ -1,170 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/frameworks/webview/scan-using-rtu-api/android/app/src/main/res/layout/activity_main.xml b/frameworks/webview/scan-using-rtu-api/android/app/src/main/res/layout/activity_main.xml deleted file mode 100644 index 7b58479b..00000000 --- a/frameworks/webview/scan-using-rtu-api/android/app/src/main/res/layout/activity_main.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/frameworks/webview/scan-using-rtu-api/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/frameworks/webview/scan-using-rtu-api/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml deleted file mode 100644 index eca70cfe..00000000 --- a/frameworks/webview/scan-using-rtu-api/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/frameworks/webview/scan-using-rtu-api/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/frameworks/webview/scan-using-rtu-api/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml deleted file mode 100644 index eca70cfe..00000000 --- a/frameworks/webview/scan-using-rtu-api/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/frameworks/webview/scan-using-rtu-api/android/app/src/main/res/mipmap-anydpi-v33/ic_launcher.xml b/frameworks/webview/scan-using-rtu-api/android/app/src/main/res/mipmap-anydpi-v33/ic_launcher.xml deleted file mode 100644 index 6f3b755b..00000000 --- a/frameworks/webview/scan-using-rtu-api/android/app/src/main/res/mipmap-anydpi-v33/ic_launcher.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/frameworks/webview/scan-using-rtu-api/android/app/src/main/res/mipmap-hdpi/ic_launcher.webp b/frameworks/webview/scan-using-rtu-api/android/app/src/main/res/mipmap-hdpi/ic_launcher.webp deleted file mode 100644 index c209e78ecd372343283f4157dcfd918ec5165bb3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1404 zcmV-?1%vuhNk&F=1pok7MM6+kP&il$0000G0000-002h-06|PpNX!5L00Dqw+t%{r zzW2vH!KF=w&cMnnN@{whkTw+#mAh0SV?YL=)3MimFYCWp#fpdtz~8$hD5VPuQgtcN zXl<@<#Cme5f5yr2h%@8TWh?)bSK`O z^Z@d={gn7J{iyxL_y_%J|L>ep{dUxUP8a{byupH&!UNR*OutO~0{*T4q5R6@ApLF! z5{w?Z150gC7#>(VHFJZ-^6O@PYp{t!jH(_Z*nzTK4 zkc{fLE4Q3|mA2`CWQ3{8;gxGizgM!zccbdQoOLZc8hThi-IhN90RFT|zlxh3Ty&VG z?Fe{#9RrRnxzsu|Lg2ddugg7k%>0JeD+{XZ7>Z~{=|M+sh1MF7~ zz>To~`~LVQe1nNoR-gEzkpe{Ak^7{{ZBk2i_<+`Bq<^GB!RYG+z)h;Y3+<{zlMUYd zrd*W4w&jZ0%kBuDZ1EW&KLpyR7r2=}fF2%0VwHM4pUs}ZI2egi#DRMYZPek*^H9YK zay4Iy3WXFG(F14xYsoDA|KXgGc5%2DhmQ1gFCkrgHBm!lXG8I5h*uf{rn48Z!_@ z4Bk6TJAB2CKYqPjiX&mWoW>OPFGd$wqroa($ne7EUK;#3VYkXaew%Kh^3OrMhtjYN?XEoY`tRPQsAkH-DSL^QqyN0>^ zmC>{#F14jz4GeW{pJoRpLFa_*GI{?T93^rX7SPQgT@LbLqpNA}<@2wH;q493)G=1Y z#-sCiRNX~qf3KgiFzB3I>4Z%AfS(3$`-aMIBU+6?gbgDb!)L~A)je+;fR0jWLL-Fu z4)P{c7{B4Hp91&%??2$v9iRSFnuckHUm}or9seH6 z>%NbT+5*@L5(I9j@06@(!{ZI?U0=pKn8uwIg&L{JV14+8s2hnvbRrU|hZCd}IJu7*;;ECgO%8_*W Kmw_-CKmY()leWbG diff --git a/frameworks/webview/scan-using-rtu-api/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp b/frameworks/webview/scan-using-rtu-api/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp deleted file mode 100644 index b2dfe3d1ba5cf3ee31b3ecc1ced89044a1f3b7a9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2898 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 diff --git a/frameworks/webview/scan-using-rtu-api/android/app/src/main/res/mipmap-mdpi/ic_launcher.webp b/frameworks/webview/scan-using-rtu-api/android/app/src/main/res/mipmap-mdpi/ic_launcher.webp deleted file mode 100644 index 4f0f1d64e58ba64d180ce43ee13bf9a17835fbca..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 982 zcmV;{11bDcNk&G_0{{S5MM6+kP&il$0000G0000l001ul06|PpNU8t;00Dqo+t#w^ z^1csucXz7-Qrhzl9HuHB%l>&>1tG2^vb*E&k^T3$FG1eQZ51g$uv4V+kI`0<^1Z@N zk?Jjh$olyC%l>)Xq;7!>{iBj&BjJ`P&$fsCfpve_epJOBkTF?nu-B7D!hO=2ZR}

C%4 zc_9eOXvPbC4kzU8YowIA8cW~Uv|eB&yYwAObSwL2vY~UYI7NXPvf3b+c^?wcs~_t{ ze_m66-0)^{JdOMKPwjpQ@Sna!*?$wTZ~su*tNv7o!gXT!GRgivP}ec?5>l1!7<(rT zds|8x(qGc673zrvYIz;J23FG{9nHMnAuP}NpAED^laz3mAN1sy+NXK)!6v1FxQ;lh zOBLA>$~P3r4b*NcqR;y6pwyhZ3_PiDb|%n1gGjl3ZU}ujInlP{eks-#oA6>rh&g+!f`hv#_%JrgYPu z(U^&XLW^QX7F9Z*SRPpQl{B%x)_AMp^}_v~?j7 zapvHMKxSf*Mtyx8I}-<*UGn3)oHd(nn=)BZ`d$lDBwq_GL($_TPaS{UeevT(AJ`p0 z9%+hQb6z)U9qjbuXjg|dExCLjpS8$VKQ55VsIC%@{N5t{NsW)=hNGI`J=x97_kbz@ E0Of=7!TQj4N+cqN`nQhxvX7dAV-`K|Ub$-q+H-5I?Tx0g9jWxd@A|?POE8`3b8fO$T))xP* z(X?&brZw({`)WU&rdAs1iTa0x6F@PIxJ&&L|dpySV!ID|iUhjCcKz(@mE z!x@~W#3H<)4Ae(4eQJRk`Iz3<1)6^m)0b_4_TRZ+cz#eD3f8V;2r-1fE!F}W zEi0MEkTTx}8i1{`l_6vo0(Vuh0HD$I4SjZ=?^?k82R51bC)2D_{y8mi_?X^=U?2|F{Vr7s!k(AZC$O#ZMyavHhlQ7 zUR~QXuH~#o#>(b$u4?s~HLF*3IcF7023AlwAYudn0FV~|odGH^05AYPEfR)8p`i{n zwg3zPVp{+wOsxKc>)(pMupKF!Y2HoUqQ3|Yu|8lwR=?5zZuhG6J?H`bSNk_wPoM{u zSL{c@pY7+c2kck>`^q1^^gR0QB7Y?KUD{vz-uVX~;V-rW)PDcI)$_UjgVV?S?=oLR zf4}zz{#*R_{LkiJ#0RdQLNC^2Vp%JPEUvG9ra2BVZ92(p9h7Ka@!yf9(lj#}>+|u* z;^_?KWdzkM`6gqPo9;;r6&JEa)}R3X{(CWv?NvgLeOTq$cZXqf7|sPImi-7cS8DCN zGf;DVt3Am`>hH3{4-WzH43Ftx)SofNe^-#|0HdCo<+8Qs!}TZP{HH8~z5n`ExcHuT zDL1m&|DVpIy=xsLO>8k92HcmfSKhflQ0H~9=^-{#!I1g(;+44xw~=* zxvNz35vfsQE)@)Zsp*6_GjYD};Squ83<_?^SbALb{a`j<0Gn%6JY!zhp=Fg}Ga2|8 z52e1WU%^L1}15Ex0fF$e@eCT(()_P zvV?CA%#Sy08_U6VPt4EtmVQraWJX` zh=N|WQ>LgrvF~R&qOfB$!%D3cGv?;Xh_z$z7k&s4N)$WYf*k=|*jCEkO19{h_(%W4 zPuOqbCw`SeAX*R}UUsbVsgtuG?xs(#Ikx9`JZoQFz0n*7ZG@Fv@kZk`gzO$HoA9kN z8U5{-yY zvV{`&WKU2$mZeoBmiJrEdzUZAv1sRxpePdg1)F*X^Y)zp^Y*R;;z~vOv-z&)&G)JQ{m!C9cmziu1^nHA z`#`0c>@PnQ9CJKgC5NjJD8HM3|KC(g5nnCq$n0Gsu_DXk36@ql%npEye|?%RmG)

FJ$wK}0tWNB{uH;AM~i diff --git a/frameworks/webview/scan-using-rtu-api/android/app/src/main/res/mipmap-xhdpi/ic_launcher.webp b/frameworks/webview/scan-using-rtu-api/android/app/src/main/res/mipmap-xhdpi/ic_launcher.webp deleted file mode 100644 index 948a3070fe34c611c42c0d3ad3013a0dce358be0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1900 zcmV-y2b1_xNk&Fw2LJ$9MM6+kP&il$0000G0001A003VA06|PpNH75a00DqwTbm-~ zullQTcXxO9ki!OCRx^i?oR|n!<8G0=kI^!JSjFi-LL*`V;ET0H2IXfU0*i>o6o6Gy zRq6Ap5(_{XLdXcL-MzlN`ugSdZY_`jXhcENAu)N_0?GhF))9R;E`!bo9p?g?SRgw_ zEXHhFG$0{qYOqhdX<(wE4N@es3VIo$%il%6xP9gjiBri+2pI6aY4 zJbgh-Ud|V%3O!IcHKQx1FQH(_*TK;1>FQWbt^$K1zNn^cczkBs=QHCYZ8b&l!UV{K z{L0$KCf_&KR^}&2Fe|L&?1I7~pBENnCtCuH3sjcx6$c zwqkNkru);ie``q+_QI;IYLD9OV0ZxkuyBz|5<$1BH|vtey$> z5oto4=l-R-Aaq`Dk0}o9N0VrkqW_#;!u{!bJLDq%0092{Ghe=F;(kn} z+sQ@1=UlX30+2nWjkL$B^b!H2^QYO@iFc0{(-~yXj2TWz?VG{v`Jg zg}WyYnwGgn>{HFaG7E~pt=)sOO}*yd(UU-D(E&x{xKEl6OcU?pl)K%#U$dn1mDF19 zSw@l8G!GNFB3c3VVK0?uyqN&utT-D5%NM4g-3@Sii9tSXKtwce~uF zS&Jn746EW^wV~8zdQ1XC28~kXu8+Yo9p!<8h&(Q({J*4DBglPdpe4M_mD8AguZFn~ ztiuO~{6Bx?SfO~_ZV(GIboeR9~hAym{{fV|VM=77MxDrbW6`ujX z<3HF(>Zr;#*uCvC*bpoSr~C$h?_%nXps@A)=l_;({Fo#6Y1+Zv`!T5HB+)#^-Ud_; zBwftPN=d8Vx)*O1Mj+0oO=mZ+NVH*ptNDC-&zZ7Hwho6UQ#l-yNvc0Cm+2$$6YUk2D2t#vdZX-u3>-Be1u9gtTBiMB^xwWQ_rgvGpZ6(C@e23c!^K=>ai-Rqu zhqT`ZQof;9Bu!AD(i^PCbYV%yha9zuoKMp`U^z;3!+&d@Hud&_iy!O-$b9ZLcSRh? z)R|826w}TU!J#X6P%@Zh=La$I6zXa#h!B;{qfug}O%z@K{EZECu6zl)7CiNi%xti0 zB{OKfAj83~iJvmpTU|&q1^?^cIMn2RQ?jeSB95l}{DrEPTW{_gmU_pqTc)h@4T>~& zluq3)GM=xa(#^VU5}@FNqpc$?#SbVsX!~RH*5p0p@w z;~v{QMX0^bFT1!cXGM8K9FP+=9~-d~#TK#ZE{4umGT=;dfvWi?rYj;^l_Zxywze`W z^Cr{55U@*BalS}K%Czii_80e0#0#Zkhlij4-~I@}`-JFJ7$5{>LnoJSs??J8kWVl6|8A}RCGAu9^rAsfCE=2}tHwl93t0C?#+jMpvr7O3`2=tr{Hg$=HlnjVG^ewm|Js0J*kfPa6*GhtB>`fN!m#9J(sU!?(OSfzY*zS(FJ<-Vb zfAIg+`U)YaXv#sY(c--|X zEB+TVyZ%Ie4L$gi#Fc++`h6%vzsS$pjz9aLt+ZL(g;n$Dzy5=m=_TV(3H8^C{r0xd zp#a%}ht55dOq?yhwYPrtp-m1xXp;4X;)NhxxUpgP%XTLmO zcjaFva^}dP3$&sfFTIR_jC=2pHh9kpI@2(6V*GQo7Ws)`j)hd+tr@P~gR*2gO@+1? zG<`_tB+LJuF|SZ9tIec;h%}}6WClT`L>HSW?E{Hp1h^+mlbf_$9zA>!ug>NALJsO{ mU%z=YwVD?}XMya)Bp;vlyE5&E_6!fzx9pwrdz474!~g(M6R?N? diff --git a/frameworks/webview/scan-using-rtu-api/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp b/frameworks/webview/scan-using-rtu-api/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp deleted file mode 100644 index 1b9a6956b3acdc11f40ce2bb3f6efbd845cc243f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3918 zcmV-U53%r4Nk&FS4*&pHMM6+kP&il$0000G0001A003VA06|PpNSy@$00HoY|G(*G z+qV7x14$dSO^Re!iqt-AAIE9iwr$(CZQJL$blA4B`>;C3fBY6Q8_YSjb2%a=fc}4E zrSzssacq<^nmW|Rs93PJni30R<8w<(bK_$LO4L?!_OxLl$}K$MUEllnMK|rg=f3;y z*?;3j|Nh>)p0JQ3A~rf(MibH2r+)3cyV1qF&;8m{w-S*y+0mM){KTK^M5}ksc`qX3 zy>rf^b>~l>SSHds8(I@hz3&PD@LmEs4&prkT=BjsBCXTMhN$_)+kvnl0bLKW5rEsj z*d#KXGDB4P&>etx0X+`R19yC=LS)j!mgs5M0L~+o-T~Jl!p!AJxnGAhV%~rhYUL4hlWhgES3Kb5oA&X z{}?3OBSS-{!v$nCIGj->(-TAG)8LR{htr41^gxsT8yqt2@DEG6Yl`Uma3Nd4;YUoW zTbkYl3CMU5ypMF3EIkYmWL|*BknM`0+Kq6CpvO(y$#j94e+q{vI{Zp8cV_6RK!`&C zob$*5Q|$IZ09dW=L!V zw@#2wviu|<#3lgGE8GEhcx+zBt`} zOwP8j9X%^f7i_bth4PiJ$LYtFJSCN$3xwDN;8mr*B;CJwBP2G0TMq0uNt7S^DO_wE zepk!Wrn#Z#03j{`c*Rf~y3o7?J}w?tEELRUR2cgxB*Y{LzA#pxHgf}q?u5idu>077 zd^=p)`nA}6e`|@`p?u}YU66PP_MA}Zqqe!c{nK&z%Jwq1N4e_q<#4g^xaz=ao;u|6 zwpRcW2Lax=ZGbx=Q*HhlJ`Ns#Y*r0*%!T?P*TTiX;rb)$CGLz=rSUum$)3Qyv{BL2 zO*=OI2|%(Yz~`pNEOnLp>+?T@glq-DujlIp?hdJeZ7ctP4_OKx|5@EOps3rr(pWzg zK4d3&oN-X2qN(d_MkfwB4I)_)!I_6nj2iA9u^pQ{;GckGLxBGrJUM2Wdda!k)Y>lq zmjws>dVQ*vW9lvEMkiN3wE-__6OWD0txS&Qn0n22cyj4Q*8(nG4!G{6OOwNvsrPIL zCl-$W9UwkEUVuLwyD%|inbOF*xMODZ4VMEVAq_zUxZ+K#Gdqf!DW$5f)?7UNOFMz! zrB~tuu=6X2FE(p^iqgxr+?ZK;=yz`e;C$#_@D9Lj-+TDVOrva>(#*PVbaHO>A)mhl z07OJWCqYC60518$!&c`eNBcBW%GnfaQ*$eazV^2_AW?j)h;J1nUjN(I9=0+!RVx~% z3@Tf!P0TE+98jA?WceK-}A1% zW!K)lyKcGqy#M~})315-A#2NXQ`?6NR#Apo=S!oF=JfpX>iR*49ec{7AN$xxpK{D$ z2d%Fz&rdfSqourN$~Y^NFIMV1CZ?J*bMx~H3k&meGtH@q9ra2vZxmA$S(#jaaj-g4 ztJmxG+DLV<*q<|sDXPp$X>E)#S}Vm&sRaO5P&goh2><}FEdZSXDqsL$06sAkh(e+v zAsBhKSRexgwg6tIy~GFJzaTxXD(}|+0eOwFDA%rn`X;MVwDHT9=4=g%OaJ9s%3b9>9EUTnnp0t;2Zpa{*>mk~hZqItE_!dQ zOtC>8`$l|mV43Jbudf0N6&&X;{=z}Zi}d1`2qmJ}i|0*GsulD3>GgQXHN)pkR6sf1 z?5ZU%&xtL}oH;YiAA)d*^Ndw2T$+Mjuzyzz@-SM`9df7LqTxLuIwC~S0092~+=qYv z@*ja;?Wt!T!{U?c*Z0YtGe)XbI&y-?B&G2$`JDM)(dIV9G`Sc#6?sI60de6kv+)Qb zUW~2|WjvJq3TA8`0+sWA3zRhY9a~ow)O~&StBkG2{*{TGiY~S8ep{V&Vo2l<6LWsu z^#p0-v*t2?3&aA1)ozu|%efSR=XnpX$lvTeRdKlvM!@|pM5p2w3u-6 zU>}t2xiYLS+{|%C65AzX+23Mtlq?BS&YdYcYsVjoiE&rT>;Necn6l^K)T^lmE`5u{ zm1i+-a-gc;Z&v-{;8r)z6NYfBUv+=_L}ef}qa9FX01)+Aaf+;xj(mL6|JUzGJR1|fnanb%?BPPIp>SCjP|8qE5qJ{=n5ZGw?81z3(k;pzH%1CtlX50{E7h)$h{qGKfzC`e2o`*IqA#tjA z`Fz&^%$b9F*N`)U-#6>a)Z`55`$Dd0cfcs0$d13^ONrdCu9xcv_=n#WQo8stcz3jP9|2EvdI-RhJM3%Q%oM&!OlShM|0 z?gz?wHZSnm45njLtsz8PVT1S&jAlbKg5kVam$p16=EK@Sj4EP0OtH zmJDmdc^v)x>56Qg_wmYHz6h)>kl_h$>0@J!ypv%APmjZTAQVLy6Fu50RGY&JAVNhx zrF_qG6`x9MkT;1SFWo$)l{M$;3qUDn9JwE}z zRl#E_bDRJFii61kPgBybIgp8dNW!Cc1b*^YYk-#oWLJvtM_v^hQx~9?8LD4VFFxBF z3MlrsSC%f9Oupn*ctPL0U1fwfX?`tRhPD{PSLFPQOmIt$mDy0SgpNVvHS+f#Do>h1Gn?LZU9(KaN>Q_=Y*_T zvtD7%_u^^+{g`0VGzg(VZrpVQ6Ub5M=tI_p7T93R8@3Zulu3|#{iNcu!oiHxZ4Rf*( zfmiN$$ru(*_Zqn=`Gq#OuHRTSwp7uH_SokR&|)RuW5yo=Z|_4?qU-JU+tpt>!B&Is z@N(=SG;bpVc;AO@zbmMM zScqq1)b-ZQIrs={oD}|?6y{$HNB1U0^LsBh8JI&3!GBZxOXI<}&5-$lgkAaYqhOTb z?2vEnZ$-kk;*M_17(upJF3%+iH*s0-r{vttXVB2OUwI1s^+G(Ft(U8gYFXC}#P&E^ z>T@C^tS`Z7{6HT4_nF~n>JlZtk5&qDBl6r|^kzQYe`wq!C)n@$c>WOPA61NDFj<<6 zGW71NMMhwAl!U-yqrq2xrSFqRCI8acw7?}3j;ynxo*-b7Co;g5r%^j=H@9({PXXBf z@r>U>>N;E)81wx`B4f%{PB~MHka_);%kBCb(d|Jy5!MqJ%2p`t&@L)4$T2j&-WHvG zv3(uyA_gwqNu(k?jQTtv3dgPKRZoH8prxe7>pQBW5L&dpumS&5Ld2?(sCpJjvc4L5 zEnh&?91WVm)ZdTj=fjJ$pPDdgAttLXuke+?KdKxu*;kTC(r!tQk6;gxj4h%FdHAt(^M3YvYj(!tOeN)+Hvj6+< zzyJRG?^lZfWuR#t!tUKP&(?%3v&Zd$R2YN>lB(Lq`OInY48%4%yTv2 zYe1{G`3)(PDEio5Y@-I5tUf`c%%OCJMtSW56g3iEg%3`$7XSJJHyA z<|7&N)5Xrlgv~%BO24eFd;Hd;uiK%D`EdK|quUeRZDqbh9l)%j%J#0lfrZumvA<_w zu&=AVvdChf6}eqh(bUz`(`Ue*p01{fBAcTgKyDYLs_I+YyJEk+rM@avU~>fB$n)HS zM7pfJydu`i%gfS<{PF94kZDv$t>06sAkheDzu40NJ$5CMW%n^Lls?8^p^QGWURbKu3ZduZQZ((s2? zzE`}<{;Zt7<$C|9R8A~DJ~@%x>TfP zF>TX8)@v|t)q4GjRt<}5s6hLHwRel7>V@&r-O|Av(yh;Q1A{E>Ir>p+%dHD|=l+lT zpr(Dg&>#Nu=!)6bCLr-ZS%|;h)Ij$+e@r8_{qO19QvDe=&1tmpY*0lcA^Cc-#{9fQ z<~$*<&P$Q<_jy#<$40PMofM7aQ}C=jphI`4kLg}Z7CIN#26D{-4v-_CA-LiE@(%{y!BzsU%gG`Q?sjLUf%qFSl0y)2#ae*+EI>s|i`d^V$Dn)qmzqRq6VJRY|{4ujsIU%#bnqU6MR&-1I_43=|5(6Jr;Jvert) zE?S|Tmn}Tv<-??sxV5@9t}3D=>YZ0JrQe$CO~|EY=Lj9RM&4svQHPQL6%pV5fPFiH zfXDx;l@~et{*{U*#c#Dvzu)|znDO7$#CRx)Z&yp-}SrD{&|(MQtfUz~n35@RLfUy=aqrhCX0M}J_r5QsK~NmRCR|Nm&L z41UdsLjWxSUlL41r^0K&nCCK>fdR-!MYjFg(z9_mF^C|#ZQw?`)f6uVzF^`bRnVY& zo}@M06J&_+>w9@jpaO4snmU;0t-(zYW1qVBHtuD!d?%?AtN7Plp><-1Y8Rqb20ZaP zTCgn*-Sri4Q8Xn>=gNaWQ57%!D35UkA@ksOlPB*Dvw}t02ENAqw|kFhn%ZyyW%+t{ zNdM!uqEM^;2}f+tECHbwLmH*!nZVrb$-az%t50Y2pg(HqhvY-^-lb}>^6l{$jOI6} zo_kBzj%8aX|6H5M0Y<)7pzz_wLkIpRm!;PzY)9+24wk2&TT{w--phDGDCOz{cN_ca zpnm7`$oDy=HX%0i-`769*0M6(e5j-?(?24%)<)&46y0e&6@HCDZAm9W6Ib#Y#BF6- z=30crHGg+RRTe%VBC>T00OV6F+gQDAK38Ne3N9bm|62tPccBJi)5{B z4zc^Db72XiBd}v$CF|yU{Z=M|DZ%-(XarYNclODlb1Kz1_EKLy(NSLCN`eUl(rBCL zT*jx@wNvze0|TSqgE(QArOZU)_?qH(sj#TwzElLs9q)(0u!_P|R%Cy_0JFQxgGV>1 zz4?_uq<8_gM0`c*Hh|;UMz~vrg1gQXp{ufg`hM_qU;U>+zmvc5blCLSq@PrEBSGR# z&8=2Z4uXN`F3p73ueD1l{s{k$WipAvSh5W7ABe?4)t;r@V?y`bNB5FvBuE|0VRTb< zM1Hn^?DSsJY+sX@T5xW=#>T9VEV|?<(=6|ge$X6Sb05!LFdjDcoq*gM(Zq=t;_)Le&jyt(&9jzR73noru`a# zN*<`KwGa^gZU3-)MSLF0aFag#f0<>E(bYTeHmtdbns#|I)-$)mJ`q9ctQ8g0=ET?| zdO}eZ*b_p>ygRTtR^5Ggdam=Zb5wmd{}np+Jn1d_=M`~P=M67jj})fH4ztb5yQqQW z^C|C&^LHAK-u+ooIK)yM)QM?t;|<{P;;{`p=BclzAN#JzL4jCwXkQB1Dy{=^KR`=~ zTrr)y7eiYBzSNs_DvO=4A6#EgGS-zY%Vi)N*Yb`U;6o}KR}dq{r9pT5wqZ@3NOE8- z9-(}D|Nc5732CSYQbL)!gPQ#RbD8BhK3dl{sUuPvei0tkvnJBxDEAYTesU8H$)g(Plra{VH(v3u^CO1~(+ zU0O7#)jaS4{NcwA+LuSm&VBcX2#Im3xg)W}ySNw%->orn1taZ&+d)}8gJTqA!u|5P z{yv?zol_3|(1(%M(EVU=cp?L`{Pi|ixk{U)*guFML3P!OSlz;zGA#T+E@8@cgQ_mv1o7RSU=Zo_82F?&&2r;WE z@wk}JHYEZ9nYUc(Vv~iTCa3u8e4q(yq<29VoNbKk|`mq%I6u)My=gPIDuUb&lzf4`MEA9^g8u z)vp8|$$HE9m_BTV?lOosIGa4jud=jIbw)O2eCMfyw2*S8?hjWw^nqws$O*M$3I1)x zR0PWFb3$ySOcGTe1dz%N0l;RPc`x%05FtT^f^j{YCP}*Q=lvp4$ZXrTZQHhO+w%wJn3c8j%+5C3UAFD&%8dBl_qi9D5g8fry}6Ev z2_Q~)5^N$!IU`BPh1O|=BxQ#*C5*}`lluC515$lxc-vNC)IgW=K|=z7o%cWFpndn= zX}f{`!VK02_kU+Q5a3m37J;c} zTzbxteE{GNf?yLt5X=Bzc-mio^Up0nunMCgp*ZJ;%MJvPM3QK)BryP(_v@ei4UvHr z6+sbCifQaOkL6-;5fL8$W($zZ_;CZp305C;~$hhRquZr-r)jjd1z z31%ZK{-(`P#|Um_Sivn@p$-vz46uqT>QG0B1w9znfS9A8PB2LaHdzA|_)yjXVR*l{ zkcu3@vEf7bxH0nkh`q?8FmoO_Ucui*>_a~P?qQrlZ9@+D7%MTpSnztpylXrt5!-k8_QPB?YL8Kx_On8WD zgT+111d(Op$^$&KLAN5+@?>f7F4~wFi(8TL8+szgVmcMDTp5l&k6~=rA{Dt}!gb^r zSWY<)M7D|Z2P0cEodj6E42PV>&>DFmQpgt)E-|#sSUU@uKed+F680H@<;-x{p|nuH4!_mn85rx>wz;0mPi2ZkL#k6;sznu?cXh!T0S>{w6 zL^gvR05NY64l*<+_L>On$rjx9!US;l;LX6@z}yi#2XHh)F@Oo+l)h%fq$v}DNmF2> zfs^_t0)3N-W<9-N?uedVv{)-J0W5mh#29QM5R5h&KuiRM=0Zvnf#lF=K#WlCgc#9c zS;qvh(P$!_a8JwyhI^ZJV2k+B6Z^64?w|1?5gyo6y{}923CRZfYVe1#?F% z7h2SUiNO3;T#JUOyovSs@@C1GtwipycA=*x5{BpIZ_#GCMuV8XK=x;qCNy{d7?wA~ zC+=vjls;ci&zW=6$H~4^K%v{p}Ab?U%C6Z4p%eC<3ExqU$XR<}LLF67A$Sr20DR_pJ3yeBa~ z^sw{V0FI5;UpwXsScYuhbqGQ`YQ25;6p6W^+tgL&;Ml;>S3CGpSZ>VrTn0m1$y$HU z&65)I!c?oREz};c=nLCliriqQX->4uivHTgd${GqeAlf*!P^B|jkU|*IdNP(&6C>4 zqOW$)Nw9nvjy^&`?E|gotDV{JmJ9Q~vuhy<`^C4XIUDt|j4o6rK^e8_(=YqC zuaR6TRVf@tUFHB079o4MBIh{M~4>WwnGgesQH*3?w(RA%hCZ*7)b!aNV=yOQ%o_Y=Lt0Sl*(9^jfRnC210Om$=y>*o|3z} zAR&vAdrB#mWoaB0fJSw9xw|Am$fzK>rx-~R#7IFSAwdu_EI|SRfB*yl0w8oX09H^q zAjl2?0I)v*odGJ40FVGaF&2qJq9Gv`>V>2r0|c`GX8h>CX8eHcOy>S0@<;M3<_6UM z7yCEpug5NZL!H_0>Hg_HasQGxR`rY&Z{geOy?N92Z z{lER^um|$*?*G63*njwc(R?NT)Bei*3jVzR>FWUDb^gKhtL4A=kE_1p-%Fo2`!8M} z(0AjuCiS;G{?*^1tB-uY%=)SRx&D)pK4u@>f6@KPe3}2j_har$>HqzH;UCR^ssFD0 z7h+VLO4o@_Yt>>AeaZKUxqyvxWCAjKB>qjQ30UA)#w z&=RmdwlT`7a8J8Yae=7*c8XL|{@%wA8uvCqfsNX^?UZsS>wX}QD{K}ad4y~iO*p%4 z_cS{u7Ek%?WV6em2(U9#d8(&JDirb^u~7wK4+xP$iiI6IlD|a&S)6o=kG;59N|>K1 zn(0mUqbG3YIY7dQd+*4~)`!S9m7H6HP6YcKHhBc#b%1L}VIisp%;TckEkcu0>lo@u995$<*Em;XNodjTiCdC%R+TX|_ZR#|1`RR|`^@Teh zl#w@8fI1FTx2Dy+{blUT{`^kY*V-AZUd?ZZqCS4gW(kY5?retkLbF=>p=59Nl|=sf zo1Pc|{{N4>5nt#627ylGF`3n>X%`w%bw-Y~zWM_{Si$dc82|=YhISal{N7OY?O`C4 zD|qb}6nLWJ`hUyL+E>-;ricg9J@ZNYP(x(Sct&OI$Y!QWr*=^VN;G3#i>^1n4e#Je zOVhbFbLpXVu*16enDM+ic;97@R~u&kh__kgP#!R`*rQEnA+_dLkNP~L`0alC|J;c; zeiK=s8;BsLE)KbG3BD&Br@(Ha@SBT&$?xX`=$;eeel=|R_dIr6-Ro?=HEjnsJ_b`1 zK6Yg^-6;^2aW!xeTK)A~3Rm|L^FCHB_I>jIju7ZGo&N_1*QHkxH2!!%@o4iZ?vntS;&zJdPe1dH#04YD93A44o-MpfD zP{rn_aq>U%RDvC2+bp;xPlsOzauIi3*Lf42`jVKKZCRuKdYhi>FDuL2l=v{$BCN#Q6796s%r-AG$Q^t(3c@ zD?w0UhYr11@feiyl9kY_@H8~|xlmO<8PfQmj1!$@WieW@VxR@Psxfe-v9WCi1+f>F4VL?0O~K7T?m4-u|pSkBpUJZZe*16_wAp zSYZ@;k`3;W3UHKUWc8QeI}0jH5Ly=cGWQPw(Kr2fm=-5L(d`lcXofy8tJY3@Tuadz zYWXR{mW7XT!RF#RVCe%}=tM*O6!AD3^(!8un~opNI%Uko7$5t@<8+?; zTxDys(MyyGsUjtSu9$+|_-t!U3fVb1dkK?l`17<+jfl=hrBHnDSV>^R1=TnQeyqbW z>ov#l%!1|S!1>8UUxIdhQq`_klcHVx0{?#>K3#$4GlXncwldt!g17TcvKq-jo_996 z>oA=tH9CqRl6Yw?Uc`am!V?lHJbizOJaVaScf1UP5e7Dbgabq=b!B~T&_F6?ooU>w%x0A zH~&MHJ=q`fCH{U<7MDXE4SD32cDZA)WJeWkllJ`UspWaS#eDe^kg^oU_A14UE9zG-a^g{xaXf$})Wik>gT zl#dkzGr(;h0JZDuFn(+k8wNq?PZ5grQ<+sM?wBGt@JnH6v0#or-5wBQWKU~(S_> zkE!tc*ZJ1Y&*p(xX84POb3cClRMd!^qJ#CAZfIepEj-<`VURS_yCz0(?*Ixcj4 z-!zV1_QZhpm=0<;*(nm+F>T=)o?ep@CK5I%g^VAA+RB25ab?7)A~z~egru=I1S|@v zH7tXV!0wmGS^qj#e+MY;C5eUjEAp$Y?LDkS^QPZ}8WN85?r$u<-Epi;yZ1|J2J`se z$D6DpH~2F=eI0B&=UFAUnJvZAmClJlK)sutJ?M>xpZiWV&0=G4MZP+x+p>EX=HbCz zxls%Mw?*u^;LbHWIWCyq+yi)`GmFn9J112CZda_u@YIP%i;srFg_paU02Ifij*7}l z&CF-(3|>*a|+vbNR`^RP=9G?ymEJ0Z~)d&c*UE$UMepZ zcITr{0WqhxkjUnM15js_gW=e3Uh|y6ZReaXHIz-=p`x5VvB&rH9y>Amv@^WmXFEw) zQXYrk3feir=a{jMQ+wDIkkFnZ$k{sJakHn*?u za%4b!00ev8NVLM1TY=cl?KB&55BY_MU-sg?c>=Dbz_W{(Z~c?HJi*XpYL)C6Bd8WH zt+v-#0&o~@t4qESi*)+eW%@VD0|o^yF)n0hME$UtXF$*Lvh}7sso{`|pn*JDIy5^Fm3s$5*zEE=?u5<=l8FJc3r%+H} zdfoNl2J0^~!-*mOL5o-x32|e0Im*E!yY7F7E5N)W3>+v_LBydlEx?4$RL5f2oYRD# zaR0wv(-p~wO0eLDl3K=%`{5+0Gd$ktO=W)gWlGZJ0`K z$_RNA=ckrfa;H0KA~dR^p�(p-{x$&=IACIfoAR!za)F-^da-t3#0Dycnp zwO~NVXwXCl;jE<}>%@xz|=8fIJAB?>+E{7)|4l${4ngA3G|=r z2Dyv;VVWSgZx9Wj>qUjleGl3Ei9K4>h!(lPS%8VOG>Xu0%6VDz^O=bjJmuP7>DeUv zrbI}MlHB^^d?{zv6d=@_ZD2lg1&G7UjnVN{1}9WkaM3H~btX0GtSzB+tZ^qRgWo4m z!GmimlG$=wgXCnr6j@m<1gAL46#T~5Bnm=2{^@>|t&`9mkEPddj zAvG~@Tv~TAm2i%VW}R-g(Z0)z-Y|szHr@rk>4MAyG*Ma*7Yh#H7(!-5>DZ@8r;_dx z{prSe<>~099F8vsYd2xff7uAS%7{S)f(|@me3t2$iy&NEc7OUEchp@9A|X;;IA>8!oX+y(BKJ$EzV* znR$z;!L$s7uy@{OT~nG#B!NRraT8(X##Ho!0r_o@gg0CA-9H^;-uE&?$2$nHv_00o z%cbuUc-tCx$Uh&EZ4Nf4Zgqv)Y6>usG3>GeQnxx_Z6+PcbX-+ysbt1hQ`K1LDpOE? zrAhIZhSN9yVIAOa22gn577tbc&i3|3V8NWy&!tw##`}9*x}gtI^h1DzZRA>UuaJG) zaZ7j)dq!O}{?#8Y7~7i6fHh4{`pL?>-18|p!S75Y#^DM>-S3)vuZG+Q7l@ek zQP~#cBpWgg#mApc_sPYjpw8odQuRokmTkzcNl`^CcKB7e&;zViV;{Y{o^Y$%7i0m# z62%#1Lq!RC?}lK>%mp}T!3Xv;L*0v*>USLm``N%>w>@fwC+#T&Tx2bN4w(20JB}oU zuSa6v^kXi0xPs?pbaOHnyiqq6By1EZY9OZ^^QA>{q-Hsd&m`pbQ%8121aWG-F5xf zlZ%;B{;C>X19|`^_?dVyCq>n+41w7|!tUS!{9rHlbhX=SZO5CQ^;!Du_E7*`GiR^Q w)2!4MKjfSAeNo!9>IaV6aUZ*?W>} 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

UmY2RIYtNPVDpE$%vda+HD#3m z&VuXJ{BK&Qe+rBa7eq}Q(bq|tn(RrJAk|ztj2(i{d>nmQnM?;HF2k&9sA6up5tmjl z7lySlzMbifH17-m-Lwa_F&e7nOH?ESi3#ckR3tsM+jsck3`oG!uMS}|eAwVXv>}qxwq?QY%QJ0}r@^;fhuUA9W z*BVl>TGo&N004@xSiwDUXUvp51sVmqO3m)=B55aPwf@0=e}cN+$-BdKxY`YrT_4)0 z_d10#i44Q*rFr8MC>*)v$EJvz``(pb{e&*6k+b zsMz%($|1+8hn8c2?P(l@;Rb&CsZeYoCI3?2!LqjbwPXW3z4G$Qfj=cT5Yb%vY0(AX oeb?AaKtwrnc|$|zzw9vfvn^aJJ!zd)XFXqqy0000001=f@-~a#s diff --git a/frameworks/webview/scan-using-rtu-api/android/app/src/main/res/values-night/themes.xml b/frameworks/webview/scan-using-rtu-api/android/app/src/main/res/values-night/themes.xml deleted file mode 100644 index 77300351..00000000 --- a/frameworks/webview/scan-using-rtu-api/android/app/src/main/res/values-night/themes.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - \ No newline at end of file diff --git a/frameworks/webview/scan-using-rtu-api/android/app/src/main/res/values/colors.xml b/frameworks/webview/scan-using-rtu-api/android/app/src/main/res/values/colors.xml deleted file mode 100644 index f8c6127d..00000000 --- a/frameworks/webview/scan-using-rtu-api/android/app/src/main/res/values/colors.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - #FFBB86FC - #FF6200EE - #FF3700B3 - #FF03DAC5 - #FF018786 - #FF000000 - #FFFFFFFF - \ No newline at end of file diff --git a/frameworks/webview/scan-using-rtu-api/android/app/src/main/res/values/strings.xml b/frameworks/webview/scan-using-rtu-api/android/app/src/main/res/values/strings.xml deleted file mode 100644 index 5d77158e..00000000 --- a/frameworks/webview/scan-using-rtu-api/android/app/src/main/res/values/strings.xml +++ /dev/null @@ -1,3 +0,0 @@ - - Dynamsoft Barcode - \ No newline at end of file diff --git a/frameworks/webview/scan-using-rtu-api/android/app/src/main/res/values/themes.xml b/frameworks/webview/scan-using-rtu-api/android/app/src/main/res/values/themes.xml deleted file mode 100644 index e2ed77aa..00000000 --- a/frameworks/webview/scan-using-rtu-api/android/app/src/main/res/values/themes.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - \ No newline at end of file diff --git a/frameworks/webview/scan-using-rtu-api/android/app/src/main/res/xml/backup_rules.xml b/frameworks/webview/scan-using-rtu-api/android/app/src/main/res/xml/backup_rules.xml deleted file mode 100644 index fa0f996d..00000000 --- a/frameworks/webview/scan-using-rtu-api/android/app/src/main/res/xml/backup_rules.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - \ No newline at end of file diff --git a/frameworks/webview/scan-using-rtu-api/android/app/src/main/res/xml/data_extraction_rules.xml b/frameworks/webview/scan-using-rtu-api/android/app/src/main/res/xml/data_extraction_rules.xml deleted file mode 100644 index 9ee9997b..00000000 --- a/frameworks/webview/scan-using-rtu-api/android/app/src/main/res/xml/data_extraction_rules.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/frameworks/webview/scan-using-rtu-api/android/build.gradle b/frameworks/webview/scan-using-rtu-api/android/build.gradle deleted file mode 100644 index ab2b874f..00000000 --- a/frameworks/webview/scan-using-rtu-api/android/build.gradle +++ /dev/null @@ -1,6 +0,0 @@ -// Top-level build file where you can add configuration options common to all sub-projects/modules. -plugins { - id 'com.android.application' version '7.4.2' apply false - id 'com.android.library' version '7.4.2' apply false - id 'org.jetbrains.kotlin.android' version '1.8.0' apply false -} \ No newline at end of file diff --git a/frameworks/webview/scan-using-rtu-api/android/gradle.properties b/frameworks/webview/scan-using-rtu-api/android/gradle.properties deleted file mode 100644 index 3c5031eb..00000000 --- a/frameworks/webview/scan-using-rtu-api/android/gradle.properties +++ /dev/null @@ -1,23 +0,0 @@ -# Project-wide Gradle settings. -# IDE (e.g. Android Studio) users: -# Gradle settings configured through the IDE *will override* -# any settings specified in this file. -# For more details on how to configure your build environment visit -# http://www.gradle.org/docs/current/userguide/build_environment.html -# Specifies the JVM arguments used for the daemon process. -# The setting is particularly useful for tweaking memory settings. -org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8 -# When configured, Gradle will run in incubating parallel mode. -# This option should only be used with decoupled projects. More details, visit -# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects -# org.gradle.parallel=true -# AndroidX package structure to make it clearer which packages are bundled with the -# Android operating system, and which are packaged with your app's APK -# https://developer.android.com/topic/libraries/support-library/androidx-rn -android.useAndroidX=true -# Kotlin code style for this project: "official" or "obsolete": -kotlin.code.style=official -# Enables namespacing of each library's R class so that its R class includes only the -# resources declared in the library itself and none from the library's dependencies, -# thereby reducing the size of the R class for that library -android.nonTransitiveRClass=true \ No newline at end of file diff --git a/frameworks/webview/scan-using-rtu-api/android/gradle/wrapper/gradle-wrapper.jar b/frameworks/webview/scan-using-rtu-api/android/gradle/wrapper/gradle-wrapper.jar deleted file mode 100644 index e708b1c023ec8b20f512888fe07c5bd3ff77bb8f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 59203 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

K7UpUK$>l@ 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 E2O(~oYXATM diff --git a/frameworks/webview/scan-using-rtu-api/android/gradle/wrapper/gradle-wrapper.properties b/frameworks/webview/scan-using-rtu-api/android/gradle/wrapper/gradle-wrapper.properties deleted file mode 100644 index dea1f353..00000000 --- a/frameworks/webview/scan-using-rtu-api/android/gradle/wrapper/gradle-wrapper.properties +++ /dev/null @@ -1,6 +0,0 @@ -#Thu Apr 13 17:46:19 CST 2023 -distributionBase=GRADLE_USER_HOME -distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-bin.zip -distributionPath=wrapper/dists -zipStorePath=wrapper/dists -zipStoreBase=GRADLE_USER_HOME diff --git a/frameworks/webview/scan-using-rtu-api/android/gradlew b/frameworks/webview/scan-using-rtu-api/android/gradlew deleted file mode 100644 index 4f906e0c..00000000 --- a/frameworks/webview/scan-using-rtu-api/android/gradlew +++ /dev/null @@ -1,185 +0,0 @@ -#!/usr/bin/env sh - -# -# Copyright 2015 the original author or authors. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -############################################################################## -## -## Gradle start up script for UN*X -## -############################################################################## - -# Attempt to set APP_HOME -# Resolve links: $0 may be a link -PRG="$0" -# Need this for relative symlinks. -while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi -done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >/dev/null -APP_HOME="`pwd -P`" -cd "$SAVED" >/dev/null - -APP_NAME="Gradle" -APP_BASE_NAME=`basename "$0"` - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' - -# Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" - -warn () { - echo "$*" -} - -die () { - echo - echo "$*" - echo - exit 1 -} - -# OS specific support (must be 'true' or 'false'). -cygwin=false -msys=false -darwin=false -nonstop=false -case "`uname`" in - CYGWIN* ) - cygwin=true - ;; - Darwin* ) - darwin=true - ;; - MINGW* ) - msys=true - ;; - NONSTOP* ) - nonstop=true - ;; -esac - -CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar - - -# Determine the Java command to use to start the JVM. -if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" - else - JAVACMD="$JAVA_HOME/bin/java" - fi - if [ ! -x "$JAVACMD" ] ; then - die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." - fi -else - JAVACMD="java" - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." -fi - -# Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then - MAX_FD_LIMIT=`ulimit -H -n` - if [ $? -eq 0 ] ; then - if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then - MAX_FD="$MAX_FD_LIMIT" - fi - ulimit -n $MAX_FD - if [ $? -ne 0 ] ; then - warn "Could not set maximum file descriptor limit: $MAX_FD" - fi - else - warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" - fi -fi - -# For Darwin, add options to specify how the application appears in the dock -if $darwin; then - GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" -fi - -# For Cygwin or MSYS, switch paths to Windows format before running java -if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then - APP_HOME=`cygpath --path --mixed "$APP_HOME"` - CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - - JAVACMD=`cygpath --unix "$JAVACMD"` - - # We build the pattern for arguments to be converted via cygpath - ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` - SEP="" - for dir in $ROOTDIRSRAW ; do - ROOTDIRS="$ROOTDIRS$SEP$dir" - SEP="|" - done - OURCYGPATTERN="(^($ROOTDIRS))" - # Add a user-defined pattern to the cygpath arguments - if [ "$GRADLE_CYGPATTERN" != "" ] ; then - OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" - fi - # Now convert the arguments - kludge to limit ourselves to /bin/sh - i=0 - for arg in "$@" ; do - CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` - CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option - - if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition - eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` - else - eval `echo args$i`="\"$arg\"" - fi - i=`expr $i + 1` - done - case $i in - 0) set -- ;; - 1) set -- "$args0" ;; - 2) set -- "$args0" "$args1" ;; - 3) set -- "$args0" "$args1" "$args2" ;; - 4) set -- "$args0" "$args1" "$args2" "$args3" ;; - 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; - esac -fi - -# Escape application args -save () { - for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done - echo " " -} -APP_ARGS=`save "$@"` - -# Collect all arguments for the java command, following the shell quoting and substitution rules -eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" - -exec "$JAVACMD" "$@" diff --git a/frameworks/webview/scan-using-rtu-api/android/gradlew.bat b/frameworks/webview/scan-using-rtu-api/android/gradlew.bat deleted file mode 100644 index 107acd32..00000000 --- a/frameworks/webview/scan-using-rtu-api/android/gradlew.bat +++ /dev/null @@ -1,89 +0,0 @@ -@rem -@rem Copyright 2015 the original author or authors. -@rem -@rem Licensed under the Apache License, Version 2.0 (the "License"); -@rem you may not use this file except in compliance with the License. -@rem You may obtain a copy of the License at -@rem -@rem https://www.apache.org/licenses/LICENSE-2.0 -@rem -@rem Unless required by applicable law or agreed to in writing, software -@rem distributed under the License is distributed on an "AS IS" BASIS, -@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -@rem See the License for the specific language governing permissions and -@rem limitations under the License. -@rem - -@if "%DEBUG%" == "" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Resolve any "." and ".." in APP_HOME to make it shorter. -for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto execute - -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto execute - -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:execute -@rem Setup the command line - -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar - - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* - -:end -@rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega diff --git a/frameworks/webview/scan-using-rtu-api/android/settings.gradle b/frameworks/webview/scan-using-rtu-api/android/settings.gradle deleted file mode 100644 index e5f9d85d..00000000 --- a/frameworks/webview/scan-using-rtu-api/android/settings.gradle +++ /dev/null @@ -1,16 +0,0 @@ -pluginManagement { - repositories { - google() - mavenCentral() - gradlePluginPortal() - } -} -dependencyResolutionManagement { - repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) - repositories { - google() - mavenCentral() - } -} -rootProject.name = "Dynamsoft Barcode" -include ':app' diff --git a/frameworks/webview/scan-using-rtu-api/ios/.gitignore b/frameworks/webview/scan-using-rtu-api/ios/.gitignore deleted file mode 100644 index ba1ff083..00000000 --- a/frameworks/webview/scan-using-rtu-api/ios/.gitignore +++ /dev/null @@ -1,90 +0,0 @@ -# Xcode -# -# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore - -## User settings -xcuserdata/ - -## compatibility with Xcode 8 and earlier (ignoring not required starting Xcode 9) -*.xcscmblueprint -*.xccheckout - -## compatibility with Xcode 3 and earlier (ignoring not required starting Xcode 4) -build/ -DerivedData/ -*.moved-aside -*.pbxuser -!default.pbxuser -*.mode1v3 -!default.mode1v3 -*.mode2v3 -!default.mode2v3 -*.perspectivev3 -!default.perspectivev3 - -## Obj-C/Swift specific -*.hmap - -## App packaging -*.ipa -*.dSYM.zip -*.dSYM - -## Playgrounds -timeline.xctimeline -playground.xcworkspace - -# Swift Package Manager -# -# Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. -# Packages/ -# Package.pins -# Package.resolved -# *.xcodeproj -# -# Xcode automatically generates this directory with a .xcworkspacedata file and xcuserdata -# hence it is not needed unless you have added a package configuration file to your project -# .swiftpm - -.build/ - -# CocoaPods -# -# We recommend against adding the Pods directory to your .gitignore. However -# you should judge for yourself, the pros and cons are mentioned at: -# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control -# -# Pods/ -# -# Add this line if you want to avoid checking in source code from the Xcode workspace -# *.xcworkspace - -# Carthage -# -# Add this line if you want to avoid checking in source code from Carthage dependencies. -# Carthage/Checkouts - -Carthage/Build/ - -# Accio dependency management -Dependencies/ -.accio/ - -# fastlane -# -# It is recommended to not store the screenshots in the git repo. -# Instead, use fastlane to re-generate the screenshots whenever they are needed. -# For more information about the recommended setup visit: -# https://docs.fastlane.tools/best-practices/source-control/#source-control - -fastlane/report.xml -fastlane/Preview.html -fastlane/screenshots/**/*.png -fastlane/test_output - -# Code Injection -# -# After new code Injection tools there's a generated folder /iOSInjectionProject -# https://github.com/johnno1962/injectionforxcode - -iOSInjectionProject/ \ No newline at end of file diff --git a/frameworks/webview/scan-using-rtu-api/ios/README.md b/frameworks/webview/scan-using-rtu-api/ios/README.md deleted file mode 100644 index 392f84cb..00000000 --- a/frameworks/webview/scan-using-rtu-api/ios/README.md +++ /dev/null @@ -1,141 +0,0 @@ -# iOS WKWebView - Scan Using RTU API (BarcodeScanner) - -This sample demonstrates how to integrate **Dynamsoft Barcode Reader JavaScript SDK** into an iOS WKWebView application using the **RTU (Ready-To-Use) API** for rapid, one-line integration. - -## Overview - -The RTU API (`BarcodeScanner`) provides the fastest way to add barcode scanning to your app: -- ✅ **One-line integration** - Launch a full scanner with a single API call -- ✅ **Built-in UI** - Pre-designed camera view with scan region highlighting -- ✅ **Simple configuration** - Customize behavior through intuitive config objects -- ✅ **Production-ready** - Optimized for common scanning scenarios - -This sample uses: -- **WKWebView** for rendering the JavaScript-based barcode scanner -- **Dynamsoft Barcode Reader v11.2.4000** RTU API (BarcodeScanner) -- Native iOS permissions handling for camera access -- Swift for iOS implementation - -## Key Features - -### 1. Camera Permission Handling - -Camera permission is declared in `Info.plist`: - -```xml -NSCameraUsageDescription -Decoding barcodes from video needs to access your camera. -``` - -### 2. One-Line RTU API Integration - -The HTML file (`decodeBarcodeInVideo.html`) demonstrates the simplest integration possible: - -```javascript -// Configure the scanner -const config = { - license: "YOUR-LICENSE-KEY", - container: document.querySelector(".barcode-scanner-view"), - // Optional: Add custom configuration - // showUploadImageButton: true, - // scannerViewConfig: { showFlashButton: true } -}; - -// Create and launch the scanner in one call -const barcodeScanner = new Dynamsoft.BarcodeScanner(config); -barcodeScanner.launch().then((result) => { - // Handle the scanned barcode - alert(result.barcodeResults[0].text); -}); -``` - -That's it! The SDK handles: -- Camera initialization and permissions -- UI rendering with scan region overlay -- Barcode detection and decoding -- Result presentation - -## How to Run - -1. **Open the Project** - ```bash - cd ios - open dbrjswebview.xcodeproj - ``` - -2. **Configure Signing** - - Select your project in Xcode - - Go to **Signing & Capabilities** - - Select your development team - -3. **Build and Run** - - Connect an iOS device (camera doesn't work in simulator for WebView) - - Select your device as the run destination - - Click **Run** (⌘R) - - Grant camera permission when prompted - -4. **Test the Scanner** - - Point the camera at a barcode - - The scanner will automatically detect and decode it - - Result will be displayed in an alert - -## API Reference - -- [BarcodeScanner API Reference](https://www.dynamsoft.com/barcode-reader/docs/web/programming/javascript/api-reference/barcode-scanner.html) -- [BarcodeScanner User Guide](https://www.dynamsoft.com/barcode-reader/docs/web/programming/javascript/user-guide/index.html) - -## When to Use RTU vs Foundational API - -**Use RTU API (BarcodeScanner) when:** -- ✅ You need a quick, working solution -- ✅ Default UI and behavior meet your needs -- ✅ You're building a standard scanning application - -**Use [Foundational API](../../scan-using-foundational-api/ios/) when:** -- 🔧 You're building complex, custom workflows -- 🔧 You need to integrate with custom camera systems - -## License - -This sample uses a Dynamsoft trial license. To use in production: -1. Visit the [Customer Portal](https://www.dynamsoft.com/customer/license/trialLicense?product=dbr&utm_source=sampleReadme) to obtain a license -2. Replace the license key in `decodeBarcodeInVideo.html`: - ```javascript - const config = { - license: "YOUR-LICENSE-KEY", // Replace here - // ... - }; - ``` - -## Troubleshooting - -**Camera not opening:** -- Ensure camera permission is granted in device settings -- Check iOS version (14.5+ required for camera in WKWebView) -- Verify you're testing on a physical device (not simulator) - -**WKWebView blank screen:** -- Enable JavaScript in WKWebView configuration -- Check Safari Developer Console for JavaScript errors -- Enable Web Inspector: Settings → Safari → Advanced → Web Inspector - -**Permission denied:** -- Verify `NSCameraUsageDescription` is set in `Info.plist` -- Reset app permissions: Settings → Privacy → Camera - -**Scanner not responding:** -- Verify license key is valid and not expired -- Check network connectivity (for license validation) - -## Support - -Need help? Contact Dynamsoft support: -- 📧 Email: [support@dynamsoft.com](mailto:support@dynamsoft.com) -- 💬 Online: [Contact Form](https://www.dynamsoft.com/company/contact?utm_source=sampleReadme) -- 📚 Documentation: [Dynamsoft Barcode Reader Docs](https://www.dynamsoft.com/barcode-reader/docs/web/) - -## Related Samples - -- [Android WebView (RTU API)](../android/) - Android version of this sample -- [iOS WKWebView (Foundational API)](../../scan-using-foundational-api/ios/) - Full control version -- [Capacitor Sample](../../../capacitor/) - Cross-platform hybrid framework approach diff --git a/frameworks/webview/scan-using-rtu-api/ios/dbrjswebview.xcodeproj/project.pbxproj b/frameworks/webview/scan-using-rtu-api/ios/dbrjswebview.xcodeproj/project.pbxproj deleted file mode 100644 index 7f7ce301..00000000 --- a/frameworks/webview/scan-using-rtu-api/ios/dbrjswebview.xcodeproj/project.pbxproj +++ /dev/null @@ -1,373 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 56; - objects = { - -/* Begin PBXBuildFile section */ - 68309E9F29F28D950016A358 /* html in Resources */ = {isa = PBXBuildFile; fileRef = 68309E9E29F28D950016A358 /* html */; }; - 68A0A94529EE855E00DC7D57 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 68A0A94429EE855E00DC7D57 /* AppDelegate.swift */; }; - 68A0A94729EE855E00DC7D57 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 68A0A94629EE855E00DC7D57 /* SceneDelegate.swift */; }; - 68A0A94929EE855E00DC7D57 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 68A0A94829EE855E00DC7D57 /* ViewController.swift */; }; - 68A0A94C29EE855E00DC7D57 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 68A0A94A29EE855E00DC7D57 /* Main.storyboard */; }; - 68A0A94E29EE856100DC7D57 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 68A0A94D29EE856100DC7D57 /* Assets.xcassets */; }; - 68A0A95129EE856100DC7D57 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 68A0A94F29EE856100DC7D57 /* LaunchScreen.storyboard */; }; -/* End PBXBuildFile section */ - -/* Begin PBXFileReference section */ - 68309E9E29F28D950016A358 /* html */ = {isa = PBXFileReference; lastKnownFileType = folder; path = html; sourceTree = ""; }; - 68A0A94129EE855E00DC7D57 /* dbrjswebview.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = dbrjswebview.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 68A0A94429EE855E00DC7D57 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; - 68A0A94629EE855E00DC7D57 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; - 68A0A94829EE855E00DC7D57 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; - 68A0A94B29EE855E00DC7D57 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; - 68A0A94D29EE856100DC7D57 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; - 68A0A95029EE856100DC7D57 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; - 68A0A95229EE856100DC7D57 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 68A0A93E29EE855E00DC7D57 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 68A0A93829EE855E00DC7D57 = { - isa = PBXGroup; - children = ( - 68A0A94329EE855E00DC7D57 /* dbrjswebview */, - 68A0A94229EE855E00DC7D57 /* Products */, - ); - sourceTree = ""; - }; - 68A0A94229EE855E00DC7D57 /* Products */ = { - isa = PBXGroup; - children = ( - 68A0A94129EE855E00DC7D57 /* dbrjswebview.app */, - ); - name = Products; - sourceTree = ""; - }; - 68A0A94329EE855E00DC7D57 /* dbrjswebview */ = { - isa = PBXGroup; - children = ( - 68309E9E29F28D950016A358 /* html */, - 68A0A94429EE855E00DC7D57 /* AppDelegate.swift */, - 68A0A94629EE855E00DC7D57 /* SceneDelegate.swift */, - 68A0A94829EE855E00DC7D57 /* ViewController.swift */, - 68A0A94A29EE855E00DC7D57 /* Main.storyboard */, - 68A0A94D29EE856100DC7D57 /* Assets.xcassets */, - 68A0A94F29EE856100DC7D57 /* LaunchScreen.storyboard */, - 68A0A95229EE856100DC7D57 /* Info.plist */, - ); - path = dbrjswebview; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 68A0A94029EE855E00DC7D57 /* dbrjswebview */ = { - isa = PBXNativeTarget; - buildConfigurationList = 68A0A95529EE856100DC7D57 /* Build configuration list for PBXNativeTarget "dbrjswebview" */; - buildPhases = ( - 68A0A93D29EE855E00DC7D57 /* Sources */, - 68A0A93E29EE855E00DC7D57 /* Frameworks */, - 68A0A93F29EE855E00DC7D57 /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = dbrjswebview; - productName = dbrjswebview; - productReference = 68A0A94129EE855E00DC7D57 /* dbrjswebview.app */; - productType = "com.apple.product-type.application"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 68A0A93929EE855E00DC7D57 /* Project object */ = { - isa = PBXProject; - attributes = { - BuildIndependentTargetsInParallel = 1; - LastSwiftUpdateCheck = 1400; - LastUpgradeCheck = 1400; - TargetAttributes = { - 68A0A94029EE855E00DC7D57 = { - CreatedOnToolsVersion = 14.0.1; - }; - }; - }; - buildConfigurationList = 68A0A93C29EE855E00DC7D57 /* Build configuration list for PBXProject "dbrjswebview" */; - compatibilityVersion = "Xcode 14.0"; - developmentRegion = en; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = 68A0A93829EE855E00DC7D57; - productRefGroup = 68A0A94229EE855E00DC7D57 /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 68A0A94029EE855E00DC7D57 /* dbrjswebview */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 68A0A93F29EE855E00DC7D57 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 68A0A95129EE856100DC7D57 /* LaunchScreen.storyboard in Resources */, - 68309E9F29F28D950016A358 /* html in Resources */, - 68A0A94E29EE856100DC7D57 /* Assets.xcassets in Resources */, - 68A0A94C29EE855E00DC7D57 /* Main.storyboard in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 68A0A93D29EE855E00DC7D57 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 68A0A94929EE855E00DC7D57 /* ViewController.swift in Sources */, - 68A0A94529EE855E00DC7D57 /* AppDelegate.swift in Sources */, - 68A0A94729EE855E00DC7D57 /* SceneDelegate.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXVariantGroup section */ - 68A0A94A29EE855E00DC7D57 /* Main.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 68A0A94B29EE855E00DC7D57 /* Base */, - ); - name = Main.storyboard; - sourceTree = ""; - }; - 68A0A94F29EE856100DC7D57 /* LaunchScreen.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 68A0A95029EE856100DC7D57 /* Base */, - ); - name = LaunchScreen.storyboard; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - -/* Begin XCBuildConfiguration section */ - 68A0A95329EE856100DC7D57 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_ENABLE_OBJC_WEAK = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = dwarf; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 16.0; - MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; - MTL_FAST_MATH = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = iphoneos; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - }; - name = Debug; - }; - 68A0A95429EE856100DC7D57 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_ENABLE_OBJC_WEAK = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 16.0; - MTL_ENABLE_DEBUG_INFO = NO; - MTL_FAST_MATH = YES; - SDKROOT = iphoneos; - SWIFT_COMPILATION_MODE = wholemodule; - SWIFT_OPTIMIZATION_LEVEL = "-O"; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - 68A0A95629EE856100DC7D57 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; - CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; - DEVELOPMENT_TEAM = KK22Q4GV82; - GENERATE_INFOPLIST_FILE = YES; - INFOPLIST_FILE = dbrjswebview/Info.plist; - INFOPLIST_KEY_CFBundleDisplayName = DyBarcode; - INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; - INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen; - INFOPLIST_KEY_UIMainStoryboardFile = Main; - INFOPLIST_KEY_UIStatusBarStyle = ""; - INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; - INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; - IPHONEOS_DEPLOYMENT_TARGET = 14.3; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - ); - MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = com.dynamsoft.dbrjswebview; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_EMIT_LOC_STRINGS = YES; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; - 68A0A95729EE856100DC7D57 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; - CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; - DEVELOPMENT_TEAM = KK22Q4GV82; - GENERATE_INFOPLIST_FILE = YES; - INFOPLIST_FILE = dbrjswebview/Info.plist; - INFOPLIST_KEY_CFBundleDisplayName = DyBarcode; - INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; - INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen; - INFOPLIST_KEY_UIMainStoryboardFile = Main; - INFOPLIST_KEY_UIStatusBarStyle = ""; - INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; - INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; - IPHONEOS_DEPLOYMENT_TARGET = 14.3; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - ); - MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = com.dynamsoft.dbrjswebview; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_EMIT_LOC_STRINGS = YES; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 68A0A93C29EE855E00DC7D57 /* Build configuration list for PBXProject "dbrjswebview" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 68A0A95329EE856100DC7D57 /* Debug */, - 68A0A95429EE856100DC7D57 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 68A0A95529EE856100DC7D57 /* Build configuration list for PBXNativeTarget "dbrjswebview" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 68A0A95629EE856100DC7D57 /* Debug */, - 68A0A95729EE856100DC7D57 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 68A0A93929EE855E00DC7D57 /* Project object */; -} diff --git a/frameworks/webview/scan-using-rtu-api/ios/dbrjswebview.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/frameworks/webview/scan-using-rtu-api/ios/dbrjswebview.xcodeproj/project.xcworkspace/contents.xcworkspacedata deleted file mode 100644 index 919434a6..00000000 --- a/frameworks/webview/scan-using-rtu-api/ios/dbrjswebview.xcodeproj/project.xcworkspace/contents.xcworkspacedata +++ /dev/null @@ -1,7 +0,0 @@ - - - - - diff --git a/frameworks/webview/scan-using-rtu-api/ios/dbrjswebview.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/frameworks/webview/scan-using-rtu-api/ios/dbrjswebview.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist deleted file mode 100644 index 18d98100..00000000 --- a/frameworks/webview/scan-using-rtu-api/ios/dbrjswebview.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +++ /dev/null @@ -1,8 +0,0 @@ - - - - - IDEDidComputeMac32BitWarning - - - diff --git a/frameworks/webview/scan-using-rtu-api/ios/dbrjswebview/AppDelegate.swift b/frameworks/webview/scan-using-rtu-api/ios/dbrjswebview/AppDelegate.swift deleted file mode 100644 index ad05d455..00000000 --- a/frameworks/webview/scan-using-rtu-api/ios/dbrjswebview/AppDelegate.swift +++ /dev/null @@ -1,36 +0,0 @@ -// -// AppDelegate.swift -// dbrjswebview -// -// Created by Dynamsoft on 2023/4/18. -// - -import UIKit - -@main -class AppDelegate: UIResponder, UIApplicationDelegate { - - - - func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { - // Override point for customization after application launch. - return true - } - - // MARK: UISceneSession Lifecycle - - func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration { - // Called when a new scene session is being created. - // Use this method to select a configuration to create the new scene with. - return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role) - } - - func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set) { - // Called when the user discards a scene session. - // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions. - // Use this method to release any resources that were specific to the discarded scenes, as they will not return. - } - - -} - diff --git a/frameworks/webview/scan-using-rtu-api/ios/dbrjswebview/Assets.xcassets/AccentColor.colorset/Contents.json b/frameworks/webview/scan-using-rtu-api/ios/dbrjswebview/Assets.xcassets/AccentColor.colorset/Contents.json deleted file mode 100644 index eb878970..00000000 --- a/frameworks/webview/scan-using-rtu-api/ios/dbrjswebview/Assets.xcassets/AccentColor.colorset/Contents.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "colors" : [ - { - "idiom" : "universal" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/frameworks/webview/scan-using-rtu-api/ios/dbrjswebview/Assets.xcassets/AppIcon.appiconset/Contents.json b/frameworks/webview/scan-using-rtu-api/ios/dbrjswebview/Assets.xcassets/AppIcon.appiconset/Contents.json deleted file mode 100644 index 13613e3e..00000000 --- a/frameworks/webview/scan-using-rtu-api/ios/dbrjswebview/Assets.xcassets/AppIcon.appiconset/Contents.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "platform" : "ios", - "size" : "1024x1024" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/frameworks/webview/scan-using-rtu-api/ios/dbrjswebview/Assets.xcassets/Contents.json b/frameworks/webview/scan-using-rtu-api/ios/dbrjswebview/Assets.xcassets/Contents.json deleted file mode 100644 index 73c00596..00000000 --- a/frameworks/webview/scan-using-rtu-api/ios/dbrjswebview/Assets.xcassets/Contents.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/frameworks/webview/scan-using-rtu-api/ios/dbrjswebview/Base.lproj/LaunchScreen.storyboard b/frameworks/webview/scan-using-rtu-api/ios/dbrjswebview/Base.lproj/LaunchScreen.storyboard deleted file mode 100644 index 865e9329..00000000 --- a/frameworks/webview/scan-using-rtu-api/ios/dbrjswebview/Base.lproj/LaunchScreen.storyboard +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/frameworks/webview/scan-using-rtu-api/ios/dbrjswebview/Base.lproj/Main.storyboard b/frameworks/webview/scan-using-rtu-api/ios/dbrjswebview/Base.lproj/Main.storyboard deleted file mode 100644 index 85dc8abf..00000000 --- a/frameworks/webview/scan-using-rtu-api/ios/dbrjswebview/Base.lproj/Main.storyboard +++ /dev/null @@ -1,33 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/frameworks/webview/scan-using-rtu-api/ios/dbrjswebview/Info.plist b/frameworks/webview/scan-using-rtu-api/ios/dbrjswebview/Info.plist deleted file mode 100644 index 93bb4788..00000000 --- a/frameworks/webview/scan-using-rtu-api/ios/dbrjswebview/Info.plist +++ /dev/null @@ -1,27 +0,0 @@ - - - - - NSCameraUsageDescription - Decoding barcodes from video needs to access your camera. - UIApplicationSceneManifest - - UIApplicationSupportsMultipleScenes - - UISceneConfigurations - - UIWindowSceneSessionRoleApplication - - - UISceneConfigurationName - Default Configuration - UISceneDelegateClassName - $(PRODUCT_MODULE_NAME).SceneDelegate - UISceneStoryboardFile - Main - - - - - - diff --git a/frameworks/webview/scan-using-rtu-api/ios/dbrjswebview/SceneDelegate.swift b/frameworks/webview/scan-using-rtu-api/ios/dbrjswebview/SceneDelegate.swift deleted file mode 100644 index 0860c7e6..00000000 --- a/frameworks/webview/scan-using-rtu-api/ios/dbrjswebview/SceneDelegate.swift +++ /dev/null @@ -1,52 +0,0 @@ -// -// SceneDelegate.swift -// dbrjswebview -// -// Created by Dynamsoft on 2023/4/18. -// - -import UIKit - -class SceneDelegate: UIResponder, UIWindowSceneDelegate { - - var window: UIWindow? - - - func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { - // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`. - // If using a storyboard, the `window` property will automatically be initialized and attached to the scene. - // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead). - guard let _ = (scene as? UIWindowScene) else { return } - } - - func sceneDidDisconnect(_ scene: UIScene) { - // Called as the scene is being released by the system. - // This occurs shortly after the scene enters the background, or when its session is discarded. - // Release any resources associated with this scene that can be re-created the next time the scene connects. - // The scene may re-connect later, as its session was not necessarily discarded (see `application:didDiscardSceneSessions` instead). - } - - func sceneDidBecomeActive(_ scene: UIScene) { - // Called when the scene has moved from an inactive state to an active state. - // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive. - } - - func sceneWillResignActive(_ scene: UIScene) { - // Called when the scene will move from an active state to an inactive state. - // This may occur due to temporary interruptions (ex. an incoming phone call). - } - - func sceneWillEnterForeground(_ scene: UIScene) { - // Called as the scene transitions from the background to the foreground. - // Use this method to undo the changes made on entering the background. - } - - func sceneDidEnterBackground(_ scene: UIScene) { - // Called as the scene transitions from the foreground to the background. - // Use this method to save data, release shared resources, and store enough scene-specific state information - // to restore the scene back to its current state. - } - - -} - diff --git a/frameworks/webview/scan-using-rtu-api/ios/dbrjswebview/ViewController.swift b/frameworks/webview/scan-using-rtu-api/ios/dbrjswebview/ViewController.swift deleted file mode 100644 index 4e787292..00000000 --- a/frameworks/webview/scan-using-rtu-api/ios/dbrjswebview/ViewController.swift +++ /dev/null @@ -1,116 +0,0 @@ -// -// ViewController.swift -// dbrjswebview -// -// Created by Dynamsoft on 2023/4/18. -// - -import UIKit -import WebKit - -// Refer: https://developer.apple.com/documentation/webkit/viewing_desktop_or_mobile_web_content_using_a_web_view -class ViewController: UIViewController, WKUIDelegate { - - let webView: WKWebView - - required init?(coder: NSCoder) { - print("entered init") - let configuration = WKWebViewConfiguration() - configuration.allowsInlineMediaPlayback = true - configuration.mediaTypesRequiringUserActionForPlayback = [] - // Refer: https://stackoverflow.com/a/51736967 - configuration.websiteDataStore = WKWebsiteDataStore.default() - webView = WKWebView(frame: .init(), configuration: configuration) - - super.init(coder: coder) - } - - // Refer: https://www.hackingwithswift.com/articles/112/the-ultimate-guide-to-wkwebview - override func loadView() { - self.view = webView - } - - override func viewDidLoad() { - super.viewDidLoad() - print("entered viewDidLoad") - // Do any additional setup after loading the view. - - // Refer: https://stackoverflow.com/a/40316507 - webView.uiDelegate = self - - //let url = URL(string: "https://your.online.website/target/page.html")! - //webView.load(URLRequest(url: url)) - - // load local html - let fileUrl = Bundle.main.url(forResource: "html/decodeFileInVideo", withExtension: "html")! - webView.loadFileURL(fileUrl, allowingReadAccessTo: fileUrl) - print("finish viewDidLoad") - } - - // Refer: https://stackoverflow.com/a/40316507 - - func webView(_ webView: WKWebView, runJavaScriptAlertPanelWithMessage message: String, initiatedByFrame frame: WKFrameInfo, - completionHandler: @escaping () -> Void) { - - let alertController = UIAlertController(title: nil, message: message, preferredStyle: .actionSheet) - alertController.addAction(UIAlertAction(title: "OK", style: .default, handler: { (action) in - completionHandler() - })) - - present(alertController, animated: true, completion: nil) - } - - - func webView(_ webView: WKWebView, runJavaScriptConfirmPanelWithMessage message: String, initiatedByFrame frame: WKFrameInfo, - completionHandler: @escaping (Bool) -> Void) { - - let alertController = UIAlertController(title: nil, message: message, preferredStyle: .actionSheet) - - alertController.addAction(UIAlertAction(title: "OK", style: .default, handler: { (action) in - completionHandler(true) - })) - - alertController.addAction(UIAlertAction(title: "Cancel", style: .default, handler: { (action) in - completionHandler(false) - })) - - present(alertController, animated: true, completion: nil) - } - - - func webView(_ webView: WKWebView, runJavaScriptTextInputPanelWithPrompt prompt: String, defaultText: String?, initiatedByFrame frame: WKFrameInfo, - completionHandler: @escaping (String?) -> Void) { - - let alertController = UIAlertController(title: nil, message: prompt, preferredStyle: .actionSheet) - - alertController.addTextField { (textField) in - textField.text = defaultText - } - - alertController.addAction(UIAlertAction(title: "OK", style: .default, handler: { (action) in - if let text = alertController.textFields?.first?.text { - completionHandler(text) - } else { - completionHandler(defaultText) - } - })) - - alertController.addAction(UIAlertAction(title: "Cancel", style: .default, handler: { (action) in - completionHandler(nil) - })) - - present(alertController, animated: true, completion: nil) - } - - // Auto grant camera access - // Refer: https://stackoverflow.com/a/72729381/6414094 - func webView(_ webView: WKWebView, - requestMediaCapturePermissionFor - origin: WKSecurityOrigin,initiatedByFrame - frame: WKFrameInfo,type: WKMediaCaptureType, - decisionHandler: @escaping (WKPermissionDecision) -> Void){ - decisionHandler(.grant) - } - -} - diff --git a/frameworks/webview/scan-using-rtu-api/ios/dbrjswebview/html/decodeFileInVideo.html b/frameworks/webview/scan-using-rtu-api/ios/dbrjswebview/html/decodeFileInVideo.html deleted file mode 100644 index a7b6b8f2..00000000 --- a/frameworks/webview/scan-using-rtu-api/ios/dbrjswebview/html/decodeFileInVideo.html +++ /dev/null @@ -1,85 +0,0 @@ - - - - - - - - Dynamsoft Barcode Scanner Sample - Hello World (Decode via Camera) - - - - -

- Hello World (Scan One Single Barcode via Camera) -

- -
- - - - - - - - - - - - - \ No newline at end of file diff --git a/hello-world.html b/hello-world.html index 6a14633e..b78fb99b 100644 --- a/hello-world.html +++ b/hello-world.html @@ -4,9 +4,12 @@ - - Dynamsoft Barcode Scanner Sample - Hello World (Decode via Camera) - + Dynamsoft Barcode Scanner Sample - Hello World (Decode via Camera) + + + + + @@ -14,57 +17,45 @@

Hello World (Scan Barcode via Camera)

-
- - - - - - +
+
@@ -1071,7 +1071,7 @@

Workflow Examples
- Read and Parse GS1-AI Dynamsoft Barcode Reader Sample - Hello World (Read an Image) + + + +

Hello World (Read an Image)

- +
Results:
- - - - + +

Hello World (Scan One Single Barcode via Camera)

- +
+ - - + cvRouter.setInput(cameraEnhancer); - - + -
+
+
+
+
+ Loading... +
+
+
+
+ +
+
@@ -45,43 +59,87 @@
  • @@ -150,6 +208,27 @@ } backBtn.addEventListener("click", launchBarcodeScanner); + + clearBtn.addEventListener("click", () => { + currentSessionResult = []; + renderCurrentSessionScanResult(); + }); + + doneBtn.addEventListener("click", async () => { + const { cameraEnhancer, cvRouter } = await pInit; + await cameraEnhancer.close(); + await cvRouter.stopCapturing(); + barcodeScannerView.style.display = "none"; + summaryView.style.display = "flex"; + totalUniqueBarcodesCount += currentSessionResult.length; + document.querySelector(".total-unique-barcodes-count .count").innerText = totalUniqueBarcodesCount; + document.querySelector(".total-count-in-this-session .count").innerText = currentSessionResult.length; + document.querySelector(".time").innerText = getDurationTime(startTime); + readerResultList(); + currentSessionResult = []; + renderCurrentSessionScanResult(); + console.log("Current Scan Session Result: ", currentSessionResult); + }); diff --git a/scenarios/cart-builder/README.md b/scenarios/cart-builder/README.md index ebd5c5be..a2c8f539 100644 --- a/scenarios/cart-builder/README.md +++ b/scenarios/cart-builder/README.md @@ -4,7 +4,8 @@ A lightweight demo that simulates a shopping experience: scan a barcode and add ## Included files -- `cart-builder.html` — single‑file sample. +- `index.html` — the demo page (simple UI and prototype flows). +- `index.css` — styles for the demo. ## ✨ Features @@ -24,7 +25,7 @@ A lightweight demo that simulates a shopping experience: scan a barcode and add ## Quick start -Opening HTML files directly may not work as expected. Instead, run a local development server. Here’s a quick method using [Visual Studio Code](https://code.visualstudio.com/): +Opening HTML files directly may not work as expected. Instead, run a local development server. Here's a quick method using [Visual Studio Code](https://code.visualstudio.com/): 1. Install the [Five Server extension](https://marketplace.visualstudio.com/items?itemName=yandeu.five-server) from the VS Code Marketplace. diff --git a/scenarios/cart-builder/index.css b/scenarios/cart-builder/index.css new file mode 100644 index 00000000..847e1fb2 --- /dev/null +++ b/scenarios/cart-builder/index.css @@ -0,0 +1,85 @@ +body { + font-family: Arial, sans-serif; + margin: 0; + padding: 20px; + background: #f0f0f0; +} + +header { + text-align: center; + margin-bottom: 30px; +} + +.scan-btn { + display: flex; + align-items: center; + justify-content: center; + padding: 8px 16px; + margin: 0 auto 20px; + font-size: 14px; + background: #4caf50; + color: #fff; + border: none; + border-radius: 4px; + cursor: pointer; +} + +.scan-btn:hover { + background: #45a049; +} + +.barcode-icon { + height: 12px; + margin-left: 8px; +} + +.cart { + max-width: 600px; + margin: 0 auto; + background: #fff; + padding: 20px; + border-radius: 5px; + box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1); +} + +.cart-item { + display: flex; + justify-content: space-between; + padding: 10px 0; + border-bottom: 1px solid #ddd; +} + +.cart-item:last-child { + border-bottom: none; +} + +.floatingDiv { + position: fixed; + top: 40%; + left: 10%; + width: 50%; + height: 25%; + max-width: 400px; + max-height: 200px; + min-width: 150px; + min-height: 150px; + background: #f9f9f9; + border: 2px solid #ccc; + border-radius: 8px; + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); + cursor: move; + z-index: 999; + padding: 3px; + box-sizing: border-box; + touch-action: none; +} + +.floatingDiv .btn-close { + position: absolute; + top: 10px; + right: 10px; + width: 20px; + height: 20px; + z-index: 1; + cursor: pointer; +} \ No newline at end of file diff --git a/scenarios/cart-builder/cart-builder.html b/scenarios/cart-builder/index.html similarity index 57% rename from scenarios/cart-builder/cart-builder.html rename to scenarios/cart-builder/index.html index ee1f46c5..4c80f8ea 100644 --- a/scenarios/cart-builder/cart-builder.html +++ b/scenarios/cart-builder/index.html @@ -5,89 +5,12 @@ List-Builder - Scan to Cart Simulation + - + - - - @@ -96,7 +19,7 @@

    🛒 Scan Barcode to Add Items to Cart

  • - - +

    Simulated Shopping Cart

    -
    +

    No items in cart. Start scanning!

    - + + + @@ -306,19 +82,16 @@
    - - - diff --git a/scenarios/pick-one-to-fill/README.md b/scenarios/pick-one-to-fill/README.md index b280b595..42733240 100644 --- a/scenarios/pick-one-to-fill/README.md +++ b/scenarios/pick-one-to-fill/README.md @@ -19,11 +19,11 @@ A compact demo that helps pick the correct item from several candidates by scann 1. Click the "Open Camera" button to activate the camera. 2. Aim at the sample image shown below. 3. Click the "Decode" button to start barcode recognition. -4. If only one barcode is detected, its value will be automatically filled into the corresponding field. If multiple barcodes are detected, the video stream will freeze, and you’ll need to manually select one from the decoded results to fill in. +4. If only one barcode is detected, its value will be automatically filled into the corresponding field. If multiple barcodes are detected, the video stream will freeze, and you'll need to manually select one from the decoded results to fill in. ## Quick start -Opening HTML files directly may not work as expected. Instead, run a local development server. Here’s a quick method using [Visual Studio Code](https://code.visualstudio.com/): +Opening HTML files directly may not work as expected. Instead, run a local development server. Here's a quick method using [Visual Studio Code](https://code.visualstudio.com/): 1. Install the [Five Server extension](https://marketplace.visualstudio.com/items?itemName=yandeu.five-server) from the VS Code Marketplace. diff --git a/scenarios/pick-one-to-fill/index.html b/scenarios/pick-one-to-fill/index.html index 6bc36616..f9117d74 100644 --- a/scenarios/pick-one-to-fill/index.html +++ b/scenarios/pick-one-to-fill/index.html @@ -7,7 +7,7 @@ Pick One To Fill with BarcodeScanner - + @@ -57,57 +57,62 @@ const barcodeScannerView = document.querySelector(".barcode-scanner-view"); const scanBtns = document.querySelectorAll(".open-btn"); const decodeBtns = document.querySelectorAll(".decode-btn"); - let barcodeScanner = null; - let cvRouter = null; + + Dynamsoft.License.LicenseManager.initLicense("DLS2eyJvcmdhbml6YXRpb25JRCI6IjIwMDAwMSJ9"); + const pInit = (async () => { + const cameraView = await Dynamsoft.DCE.CameraView.createInstance(); + const cameraEnhancer = await Dynamsoft.DCE.CameraEnhancer.createInstance(cameraView); + const cvRouter = await Dynamsoft.CVR.CaptureVisionRouter.createInstance(); + + cvRouter.setInput(cameraEnhancer); + barcodeScannerView.append(cameraView.getUIElement()); + + return { + cameraView, + cameraEnhancer, + cvRouter + } + })(); for (let i = 0; i < scanBtns.length; i++) { const scanBtn = scanBtns[i]; const decodeBtn = decodeBtns[i]; - scanBtn.addEventListener("click", (e) => { - if (barcodeScanner) return; - // Configuration object for initializing the BarcodeScanner instance. Refer to https://www.dynamsoft.com/barcode-reader/docs/web/programming/javascript/api-reference/barcode-scanner.html#barcodescannerconfig - let config = { - license: "DLS2eyJvcmdhbml6YXRpb25JRCI6IjIwMDAwMSJ9", // Replace with your Dynamsoft license key - container: barcodeScannerView, // Specify where to render the scanner UI - autoStartCapturing: false, - onInitReady: (components) => { - components.cameraView.setVideoFit("contain"); - cvRouter = components.cvRouter; - }, - // The watermark can be removed via showPoweredByDynamsoft configuration option. - // showPoweredByDynamsoft: false, - }; + scanBtn.addEventListener("click", async (e) => { + const { cameraView, cameraEnhancer, cvRouter } = await pInit; + if (cameraEnhancer.isOpen()) return; + await cameraEnhancer.open(); + + const target = e.target.classList[1].split("-")[1]; + const targetInput = document.querySelector(`.${target} input`); - // Create a new instance of the Dynamsoft Barcode Scanner - barcodeScanner = new Dynamsoft.BarcodeScanner(config); + const resultReceiver = new Dynamsoft.CVR.CapturedResultReceiver(); + resultReceiver.onDecodedBarcodesReceived = (result) => { + if (result.barcodeResultItems.length > 0) { + // Display the first detected barcode's text in an alert + targetInput.value = result.barcodeResultItems[0].text; + guideView.style.display = "flex"; + barcodeScannerView.style.display = "none"; + scanBtn.style.display = "inline-block"; + decodeBtn.style.display = "none"; + decodeBtn.innerText = "Decode to Auto-Fill"; + cameraEnhancer.close(); + cvRouter.stopCapturing(); + cvRouter.removeResultReceiver(resultReceiver); + } + } + await cvRouter.addResultReceiver(resultReceiver); guideView.style.display = "none"; barcodeScannerView.style.display = "block"; scanBtn.style.display = "none"; decodeBtn.style.display = "inline-block"; - - const target = e.target.classList[1].split("-")[1]; - const targetInput = document.querySelector(`.${target} input`) - - // Launch the scanner and handle the scanned result - barcodeScanner.launch().then((result) => { - // Display the first detected barcode's text in an alert - if (result.barcodeResults.length) { - targetInput.value = result.barcodeResults[0].text; - } - guideView.style.display = "flex"; - barcodeScannerView.style.display = "none"; - scanBtn.style.display = "inline-block"; - decodeBtn.style.display = "none"; - decodeBtn.innerText = "Decode to Auto-Fill"; - barcodeScanner = null; - }); }) - decodeBtn.addEventListener("click", () => { + decodeBtn.addEventListener("click", async () => { decodeBtn.innerText = "Scanning..."; - cvRouter.startCapturing("ReadBarcodes_SpeedFirst"); + const { cameraView, cameraEnhancer, cvRouter } = await pInit; + await cvRouter.startCapturing("ReadSingleBarcode"); }) } diff --git a/scenarios/read-a-drivers-license/README.md b/scenarios/read-a-drivers-license/README.md index d571efa5..50600724 100644 --- a/scenarios/read-a-drivers-license/README.md +++ b/scenarios/read-a-drivers-license/README.md @@ -21,7 +21,7 @@ A focused demo that decodes and parses barcode data from driver's license images ## Quick start -Opening HTML files directly may not work as expected. Instead, run a local development server. Here’s a quick method using [Visual Studio Code](https://code.visualstudio.com/): +Opening HTML files directly may not work as expected. Instead, run a local development server. Here's a quick method using [Visual Studio Code](https://code.visualstudio.com/): 1. Install the [Five Server extension](https://marketplace.visualstudio.com/items?itemName=yandeu.five-server) from the VS Code Marketplace. diff --git a/scenarios/read-a-drivers-license/index.html b/scenarios/read-a-drivers-license/index.html index 99f97c95..fff14556 100644 --- a/scenarios/read-a-drivers-license/index.html +++ b/scenarios/read-a-drivers-license/index.html @@ -21,14 +21,15 @@

    Read a Driver's License

    logo-dynamsoft
    +
      Back to Scan
      - No PDF417 detected. Please try again.
      - - + + + diff --git a/scenarios/read-a-drivers-license/style.css b/scenarios/read-a-drivers-license/style.css index 61855c1e..a6a21546 100644 --- a/scenarios/read-a-drivers-license/style.css +++ b/scenarios/read-a-drivers-license/style.css @@ -81,6 +81,11 @@ body { height: 32px; } +.barcode-scanner-view { + width: 100%; + height: 100%; +} + .parsed-result-view { position: absolute; width: 100%; diff --git a/scenarios/read-and-parse-GS1-AI/README.md b/scenarios/read-and-parse-GS1-AI/README.md index 1c699c4e..82ced8a1 100644 --- a/scenarios/read-and-parse-GS1-AI/README.md +++ b/scenarios/read-and-parse-GS1-AI/README.md @@ -9,13 +9,6 @@ A focused demo that decodes GS1-formatted barcodes and parses Application Identi - `index.css` — styles used by the foundational demo. - `read_and_parse_gs1.json` — GS1 template file used by this implementation. -- scan-using-rtu-api/ — RTU implementation: - - `rtu.html` — RTU demo page. - - `rtu_gs1.json` — GS1 template file used by this implementation. - - `convert-GS1AI-title.js` — helper to convert or format AI titles for display. - - `style.css` — RTU demo styles. - - `info.svg`, `logo-dynamsoft-blackBg-190x47-DZ66W3xz.png` — visual assets used by the RTU demo. - ## ✨ Features - Decode GS1 barcodes (GS1-128 / EAN / GS1 Databar variants) from live camera or static image inputs. @@ -23,14 +16,12 @@ A focused demo that decodes GS1-formatted barcodes and parses Application Identi ## 🔧 How it works -- Both demos initialize the barcode scanner to decode GS1 payloads from camera frames or image files. +- The demos initialize the barcode scanner to decode GS1 payloads from camera frames or image files. - Decoded GS1 strings are parsed according to the provided JSON template (mapping AIs to labels and formats). -- The foundational demo is a compact single-page example that loads `read_and_parse_gs1.json` and renders parsed fields alongside the raw payload. -- The RTU demo demonstrates a more integrated UI flow (uses `rtu_gs1.json`, helper script `convert-GS1AI-title.js`, and additional assets/styles) suitable for embedding into larger apps. ## Quick start -Opening HTML files directly may not work as expected. Instead, run a local development server. Here’s a quick method using [Visual Studio Code](https://code.visualstudio.com/): +Opening HTML files directly may not work as expected. Instead, run a local development server. Here's a quick method using [Visual Studio Code](https://code.visualstudio.com/): 1. Install the [Five Server extension](https://marketplace.visualstudio.com/items?itemName=yandeu.five-server) from the VS Code Marketplace. @@ -40,7 +31,6 @@ Opening HTML files directly may not work as expected. Instead, run a local devel - Use high-resolution images or increase camera resolution for small or dense GS1 fields. - Validate AI date/number formats (some AIs imply decimal places or YY/MM/YY formats). -- Use the RTU implementation as a reference if you need a richer runtime UI integration. ## 📌 Notes diff --git a/scenarios/read-and-parse-GS1-AI/scan-using-foundational-api/index.css b/scenarios/read-and-parse-GS1-AI/index.css similarity index 100% rename from scenarios/read-and-parse-GS1-AI/scan-using-foundational-api/index.css rename to scenarios/read-and-parse-GS1-AI/index.css diff --git a/scenarios/read-and-parse-GS1-AI/scan-using-foundational-api/index.html b/scenarios/read-and-parse-GS1-AI/index.html similarity index 97% rename from scenarios/read-and-parse-GS1-AI/scan-using-foundational-api/index.html rename to scenarios/read-and-parse-GS1-AI/index.html index 65d418fe..e93e3f7b 100644 --- a/scenarios/read-and-parse-GS1-AI/scan-using-foundational-api/index.html +++ b/scenarios/read-and-parse-GS1-AI/index.html @@ -50,19 +50,19 @@

      Read a GS1-AI

      - + - + - - - - - \ No newline at end of file diff --git a/scenarios/read-and-parse-GS1-AI/scan-using-rtu-api/info.svg b/scenarios/read-and-parse-GS1-AI/scan-using-rtu-api/info.svg deleted file mode 100644 index f0dab9d4..00000000 --- a/scenarios/read-and-parse-GS1-AI/scan-using-rtu-api/info.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/scenarios/read-and-parse-GS1-AI/scan-using-rtu-api/logo-dynamsoft-blackBg-190x47-DZ66W3xz.png b/scenarios/read-and-parse-GS1-AI/scan-using-rtu-api/logo-dynamsoft-blackBg-190x47-DZ66W3xz.png deleted file mode 100644 index 7967e8edbde77fcdf84333b58ac1046f821c9e0b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5449 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 LnIX#&&Jq6u=Qz1) diff --git a/scenarios/read-and-parse-GS1-AI/scan-using-rtu-api/rtu_gs1.json b/scenarios/read-and-parse-GS1-AI/scan-using-rtu-api/rtu_gs1.json deleted file mode 100644 index 67497355..00000000 --- a/scenarios/read-and-parse-GS1-AI/scan-using-rtu-api/rtu_gs1.json +++ /dev/null @@ -1,163 +0,0 @@ -{ - "BarcodeReaderTaskSettingOptions": [ - { - "Name": "task_gs1_ai_barcode", - "ExpectedBarcodesCount": 1, - "BarcodeFormatIds": [ - "BF_GS1_DATABAR", - "BF_CODE_128", - "BF_GS1_COMPOSITE", - "BF_DATAMATRIX", - "BF_QR_CODE" - ], - "BarcodeFormatSpecificationNameArray": [ - "bfs_gs1_ai" - ], - "SectionArray": [ - { - "Section": "ST_REGION_PREDETECTION", - "ImageParameterName": "ip_localize_barcode", - "StageArray": [ - { - "Stage": "SST_PREDETECT_REGIONS" - } - ] - }, - { - "Section": "ST_BARCODE_LOCALIZATION", - "ImageParameterName": "ip_localize_barcode", - "StageArray": [ - { - "LocalizationModes": [ - { - "Mode": "LM_SCAN_DIRECTLY", - "ScanDirection": 2 - }, - { - "Mode": "LM_CONNECTED_BLOCKS", - "ModelNameArray": [] - }, - { - "Mode": "LM_CONNECTED_BLOCKS", - "ModelNameArray": [ - "OneDLocalization" - ] - } - ], - "Stage": "SST_LOCALIZE_CANDIDATE_BARCODES" - }, - { - "Stage": "SST_LOCALIZE_BARCODES" - } - ] - }, - { - "Section": "ST_BARCODE_DECODING", - "ImageParameterName": "ip_localize_barcode", - "StageArray": [ - { - "Stage": "SST_RESIST_DEFORMATION" - }, - { - "Stage": "SST_COMPLEMENT_BARCODE" - }, - { - "Stage": "SST_SCALE_BARCODE_IMAGE" - }, - { - "DeblurModes": [ - { - "Mode": "DM_BASED_ON_LOC_BIN" - }, - { - "Mode": "DM_THRESHOLD_BINARIZATION" - }, - { - "Mode": "DM_DIRECT_BINARIZATION" - }, - { - "Mode": "DM_NEURAL_NETWORK", - "ModelNameArray": [ - "Code128Decoder" - ] - }, - { - "Mode": "DM_DEEP_ANALYSIS" - } - ], - "Stage": "SST_DECODE_BARCODES" - } - ] - } - ] - } - ], - "BarcodeFormatSpecificationOptions": [ - { - "Name": "bfs_gs1_ai", - "BarcodeFormatIds": [ - "BF_GS1_DATABAR", - "BF_CODE_128", - "BF_GS1_COMPOSITE", - "BF_DATAMATRIX", - "BF_QR_CODE" - ], - "IncludeTrailingCheckDigit": 0, - "IncludeImpliedAI01": 1 - } - ], - "CaptureVisionTemplates": [ - { - "Name": "ReadBarcodes_SpeedFirst", - "ImageROIProcessingNameArray": [ - "roi_gs1_ai_barcode" - ] - }, - { - "Name": "ReadBarcodes_ReadRateFirst", - "ImageROIProcessingNameArray": [ - "roi_gs1_ai_barcode" - ] - } - ], - "ImageParameterOptions": [ - { - "Name": "ip_localize_barcode", - "ApplicableStages": [ - { - "Stage": "SST_BINARIZE_IMAGE", - "BinarizationModes": [ - { - "Mode": "BM_LOCAL_BLOCK" - } - ] - }, - { - "Stage": "SST_BINARIZE_TEXTURE_REMOVED_GRAYSCALE" - }, - { - "Stage": "SST_TRANSFORM_GRAYSCALE", - "GrayscaleTransformationModes": [ - { - "Mode": "GTM_ORIGINAL" - }, - { - "Mode": "GTM_INVERTED" - } - ] - } - ] - } - ], - "TargetROIDefOptions": [ - { - "Name": "roi_gs1_ai_barcode", - "TaskSettingNameArray": [ - "task_gs1_ai_barcode" - ] - } - ], - "GlobalParameter": { - "IntraOpNumThreads": 1 - } -} diff --git a/scenarios/read-and-parse-GS1-AI/scan-using-rtu-api/style.css b/scenarios/read-and-parse-GS1-AI/scan-using-rtu-api/style.css deleted file mode 100644 index 0cd02c7c..00000000 --- a/scenarios/read-and-parse-GS1-AI/scan-using-rtu-api/style.css +++ /dev/null @@ -1,200 +0,0 @@ - -* { - box-sizing: border-box; -} -html, -body { - margin: 0; - padding: 0; - height: 100%; - font-family: Arial, Helvetica, sans-serif; - font-size: 20px; -} -html { - width: 100%; - background: rgb(50, 50, 50); -} -body { - max-width: 720px; - margin: 0 auto; -} - -.barcode-scanner-view{ - width:100%; - height:100%; -} - -.landing-page { - width: 100%; - height: 100%; - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - position: relative; -} - -.landing-title { - color: white; - font-size: 28px; - text-align: center; - padding: 0 24px; - position: absolute; - width: 100%; - bottom: max(60%, calc(50% + 70px)); -} - -.play-button { - width: 80px; - height: 80px; - background: white; - border-radius: 50%; - display: flex; - align-items: center; - justify-content: center; - cursor: pointer; - box-shadow: 0 8px 16px rgba(0, 0, 0, 0.2); - transition: transform 0.2s, box-shadow 0.2s, opacity 0.2s; - position: relative; -} -.play-button:hover { - transform: scale(1.1); - box-shadow: 0 12px 24px rgba(0, 0, 0, 0.3); -} -.play-button:active { - transform: scale(0.95); -} -.play-button.disabled { - opacity: 0.8; - cursor: not-allowed; - pointer-events: none; -} -.play-button.disabled .play-icon { - display: none; -} -.play-button.disabled::before { - content: ""; - position: absolute; - width: 70px; - height: 70px; - border: 3px solid rgba(254, 142, 20, 0.3); - border-top-color: #fe8e14; - border-radius: 50%; - animation: spin 1s linear infinite; -} -.play-button.disabled::after { - content: "Loading"; - position: absolute; - color: #fe8e14; - font-size: 12px; - font-weight: bold; - letter-spacing: 0.5px; -} -@keyframes spin { - 0% { - transform: rotate(0deg); - } - 100% { - transform: rotate(360deg); - } -} -.play-icon { - width: 0; - height: 0; - border-left: 24px solid #fe8e14; - border-top: 16px solid transparent; - border-bottom: 16px solid transparent; - margin-left: 6px; -} - -.landing-page .logo { - position: absolute; - bottom: 8%; - left: 50%; - transform: translateX(-50%); -} -.landing-page .logo img { - width: 95px; - height: 23.5px; -} - -.result-page { - background: rgb(222, 223, 225); - width: 100%; - min-height: 100%; - padding: 1px; - position: relative; -} - -.barcode-text { - background: rgb(245, 245, 245); - font-size: 18px; - line-height: 32px; - margin: 1px 0 10px; - padding: 14px 30px; - word-break: break-all; - color: rgb(50, 50, 50); - font-weight: bold; -} - -.gs1AI-info > div { - background: rgb(245, 245, 245); - font-size: 18px; - line-height: 32px; - margin: 1px 0; - padding: 14px 30px; - color: rgb(102, 102, 102); -} -.gs1AI-info > div > span:first-child{ - color: rgb(50, 50, 50); -} -.has-info::after{ - content: url("info.svg"); - margin-left: 2px; - position: relative; - top: 1px; - cursor: pointer; -} - -.goods-name { - font-weight: bolder; -} - -.back-to-scan { - width: calc(100% - 52px); - margin: 26px; - padding: 14px; - font-family: Arial, Helvetica, sans-serif; - font-size: 24px; - line-height: 32px; - background: #fe8e14; - text-align: center; - color: white; - border-radius: 6px; - display: block; - border: 0; - cursor: pointer; -} -.back-to-scan:hover{ - transform: scale(1.05); -} -.back-to-scan:active { - transform: scale(0.95); -} - -.result-page .powered-by-dynamsoft{ - height:74px; -} -.result-page .powered-by-dynamsoft:after{ - content: "Powered by Dynamsoft"; - position: absolute; - bottom: 0; - height: 74px; - font-size: 16px; - line-height: 74px; - color: rgb(119, 119, 119); - width: 100%; - text-align: center; -} - -.dm-camera-mn-toast{position:absolute;font-size:max(1.25vmin,16px);line-height:max(3vmin,32px);padding:0 max(0.5vmin,4px);left:50%;bottom:max(12.5vmin,100px);transform:translateX(-50%);color:#fff;border-radius:max(0.5vmin,4px);background:rgba(100,100,100,0.5);} diff --git a/scenarios/read-vin/README.md b/scenarios/read-vin/README.md index 8d5e220f..5368c4b2 100644 --- a/scenarios/read-vin/README.md +++ b/scenarios/read-vin/README.md @@ -21,7 +21,7 @@ This focused demo decodes and parses VIN barcodes from vehicle images or live ca ## Quick start -Opening HTML files directly may not work as expected. Instead, run a local development server. Here’s a quick method using [Visual Studio Code](https://code.visualstudio.com/): +Opening HTML files directly may not work as expected. Instead, run a local development server. Here's a quick method using [Visual Studio Code](https://code.visualstudio.com/): 1. Install the [Five Server extension](https://marketplace.visualstudio.com/items?itemName=yandeu.five-server) from the VS Code Marketplace. diff --git a/scenarios/read-vin/index.html b/scenarios/read-vin/index.html index 4e508611..b66fbb6e 100644 --- a/scenarios/read-vin/index.html +++ b/scenarios/read-vin/index.html @@ -9,7 +9,7 @@ Dynamsoft Barcode Reader Sample - Read a VIN - + @@ -21,13 +21,12 @@

      Read VIN

      logo-dynamsoft +
        Back to Scan
        - No VIN Barcode detected. Please try again.
        - diff --git a/scenarios/read-vin/style.css b/scenarios/read-vin/style.css index 2326cc25..cf0eb2a4 100644 --- a/scenarios/read-vin/style.css +++ b/scenarios/read-vin/style.css @@ -81,6 +81,11 @@ body { height: 32px; } +.barcode-scanner-view { + width: 100%; + height: 100%; +} + .parsed-result-view { position: absolute; width: 100%; @@ -100,7 +105,7 @@ body { background-color: #fff; margin-bottom: 10px; color: #323234; - padding: 10px 27px; + padding: 0 27px; font-weight: 600; overflow: auto; word-break: break-all; diff --git a/scenarios/scan-1D-Industrial/README.md b/scenarios/scan-1D-Industrial/README.md index 46471497..337c4604 100644 --- a/scenarios/scan-1D-Industrial/README.md +++ b/scenarios/scan-1D-Industrial/README.md @@ -21,7 +21,7 @@ A focused demo for decoding industrial-strength 1D barcodes (high-density, damag ## Quick start -Opening HTML files directly may not work as expected. Instead, run a local development server. Here’s a quick method using [Visual Studio Code](https://code.visualstudio.com/): +Opening HTML files directly may not work as expected. Instead, run a local development server. Here's a quick method using [Visual Studio Code](https://code.visualstudio.com/): 1. Install the [Five Server extension](https://marketplace.visualstudio.com/items?itemName=yandeu.five-server) from the VS Code Marketplace. diff --git a/scenarios/scan-1D-Industrial/ReadOneDIndustrial.json b/scenarios/scan-1D-Industrial/ReadOneDIndustrial.json index c414b31a..9d954ecd 100644 --- a/scenarios/scan-1D-Industrial/ReadOneDIndustrial.json +++ b/scenarios/scan-1D-Industrial/ReadOneDIndustrial.json @@ -72,7 +72,7 @@ }, { "Mode": "DM_NEURAL_NETWORK", - "ModelNameArray": ["Code128Decoder", "OneDDeblur"] + "ModelNameArray": ["Code128Decoder", "Code39ITFDecoder"] }, { "Mode": "DM_DEEP_ANALYSIS" diff --git a/scenarios/scan-1D-Industrial/index.html b/scenarios/scan-1D-Industrial/index.html index a86e089d..1197e38a 100644 --- a/scenarios/scan-1D-Industrial/index.html +++ b/scenarios/scan-1D-Industrial/index.html @@ -4,69 +4,12 @@ - - Dynamsoft Barcode Scanner Sample - Scan oneD Industrial codes - - - - -

        - Scan oneD Industrial codes -

        - -
        - + Dynamsoft Barcode Scanner Sample - Scan oneD Industrial codes - + - - +
        +
        + + \ No newline at end of file diff --git a/scenarios/scan-1D-Retail/README.md b/scenarios/scan-1D-Retail/README.md index 277b2778..dc4e054c 100644 --- a/scenarios/scan-1D-Retail/README.md +++ b/scenarios/scan-1D-Retail/README.md @@ -20,7 +20,7 @@ A demo tuned for retail 1D barcodes (UPC/EAN etc.) demonstrating speed and accur ## Quick start -Opening HTML files directly may not work as expected. Instead, run a local development server. Here’s a quick method using [Visual Studio Code](https://code.visualstudio.com/): +Opening HTML files directly may not work as expected. Instead, run a local development server. Here's a quick method using [Visual Studio Code](https://code.visualstudio.com/): 1. Install the [Five Server extension](https://marketplace.visualstudio.com/items?itemName=yandeu.five-server) from the VS Code Marketplace. diff --git a/scenarios/scan-1D-Retail/ReadOneDRetail.json b/scenarios/scan-1D-Retail/ReadOneDRetail.json index bde1f746..9a363333 100644 --- a/scenarios/scan-1D-Retail/ReadOneDRetail.json +++ b/scenarios/scan-1D-Retail/ReadOneDRetail.json @@ -72,7 +72,7 @@ }, { "Mode": "DM_NEURAL_NETWORK", - "ModelNameArray": ["EAN13Decoder", "OneDDeblur"] + "ModelNameArray": ["EAN13Decoder"] }, { "Mode": "DM_DEEP_ANALYSIS" diff --git a/scenarios/scan-1D-Retail/index.html b/scenarios/scan-1D-Retail/index.html index 486345a5..a9114576 100644 --- a/scenarios/scan-1D-Retail/index.html +++ b/scenarios/scan-1D-Retail/index.html @@ -4,69 +4,12 @@ - - Dynamsoft Barcode Scanner Sample - Scan oneD Retail codes - - - - -

        - Scan oneD Retail codes -

        - -
        - + Dynamsoft Barcode Scanner Sample - Scan oneD Retail codes - + - - +
        +
        + + \ No newline at end of file diff --git a/scenarios/scan-and-search/README.md b/scenarios/scan-and-search/README.md index e4908b8a..3d93a2bb 100644 --- a/scenarios/scan-and-search/README.md +++ b/scenarios/scan-and-search/README.md @@ -4,7 +4,7 @@ A demo that scans a barcode and performs a lookup/search operation (product or i ## Included files -- `scan-and-search.html` — single‑file demo (scan UI + search/lookup flow). +- `index.html` — single‑file demo (scan UI + search/lookup flow). ## ✨ Features @@ -22,7 +22,7 @@ A demo that scans a barcode and performs a lookup/search operation (product or i ## Quick start -Opening HTML files directly may not work as expected. Instead, run a local development server. Here’s a quick method using [Visual Studio Code](https://code.visualstudio.com/): +Opening HTML files directly may not work as expected. Instead, run a local development server. Here's a quick method using [Visual Studio Code](https://code.visualstudio.com/): 1. Install the [Five Server extension](https://marketplace.visualstudio.com/items?itemName=yandeu.five-server) from the VS Code Marketplace. diff --git a/scenarios/scan-and-search/index.css b/scenarios/scan-and-search/index.css new file mode 100644 index 00000000..cbbce166 --- /dev/null +++ b/scenarios/scan-and-search/index.css @@ -0,0 +1,194 @@ +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +body { + font-family: Arial, sans-serif; + background: #fff; + display: flex; + justify-content: center; + align-items: center; + flex-direction: column; + min-height: 100vh; + padding: 10px; + margin: 0; +} + +#container { + display: flex; + align-items: center; + width: 100%; + max-width: 400px; +} + +#scan-btn { + width: 48px; + height: 48px; + background-color: #ff5000; + border: none; + border-radius: 6px 0 0 6px; + display: flex; + align-items: center; + justify-content: center; + cursor: pointer; + transition: background-color 0.3s ease; +} + +#scan-btn:hover { + background-color: #e54c00; +} + +#text-input { + flex: 1; + height: 48px; + padding: 0 12px; + font-size: 16px; + border: 1px solid #ccc; + border-left: none; + border-right: none; + box-sizing: border-box; +} + +#search-btn { + width: 48px; + height: 48px; + background-color: #ff5000; + border: none; + border-radius: 0 6px 6px 0; + display: flex; + align-items: center; + justify-content: center; + cursor: pointer; + transition: background-color 0.3s ease; +} + +#search-btn:hover { + background-color: #e54c00; +} + +.search-icon { + position: relative; + width: 20px; + height: 20px; + border: 3px solid white; + border-radius: 50%; + box-sizing: border-box; +} + +.search-icon::after { + content: ""; + position: absolute; + width: 10px; + height: 3px; + background: white; + transform: rotate(45deg); + right: -6px; + bottom: -3px; + transform-origin: center; +} + +.scan-icon { + position: relative; + width: 20px; + height: 20px; +} + +.scan-icon::before { + content: ""; + position: absolute; + left: 0; + right: 0; + top: 50%; + height: 2px; + background-color: white; + transform: translateY(-50%); +} + +.corner { + position: absolute; + width: 5px; + height: 5px; + border: 2px solid white; +} + +.tl { + top: 0; + left: 0; + border-right: none; + border-bottom: none; +} + +.tr { + top: 0; + right: 0; + border-left: none; + border-bottom: none; +} + +.bl { + bottom: 0; + left: 0; + border-right: none; + border-top: none; +} + +.br { + bottom: 0; + right: 0; + border-left: none; + border-top: none; +} + +h2 { + margin: 20px 0; +} + +#barcode-scanner-view { + position: fixed; + left: 0; + top: 0; + width: 100%; + height: 100vh; + display: none; + background-color: rgba(0, 0, 0, 0.8); + z-index: 9999; +} + +textarea { + width: 100%; + max-width: 380px; + height: 300px; + margin-top: 20px; + padding: 10px; + font-size: 1em; + border: 1px solid #ccc; + border-radius: 5px; + resize: vertical; + transition: border-color 0.3s; +} + +textarea:focus { + border-color: #007bff; + outline: none; +} + +@media (max-width: 480px) { + + #scan-btn, + #search-btn { + width: 40px; + height: 40px; + } + + #text-input { + height: 40px; + font-size: 14px; + } + + textarea { + height: 200px; + font-size: 14px; + } +} \ No newline at end of file diff --git a/scenarios/scan-and-search/index.html b/scenarios/scan-and-search/index.html new file mode 100644 index 00000000..7e99ac3f --- /dev/null +++ b/scenarios/scan-and-search/index.html @@ -0,0 +1,91 @@ + + + + + + + Scan & Search with BarcodeScanner + + + + + + + + +

        📦 Instant Product Information Lookup

        +

        Enter a UPC, EAN, or ISBN number to retrieve accurate product data from a specific database

        +
        + + + +
        + + +
        + + + + + \ No newline at end of file diff --git a/scenarios/scan-and-search/scan-and-search.html b/scenarios/scan-and-search/scan-and-search.html deleted file mode 100644 index f19ec448..00000000 --- a/scenarios/scan-and-search/scan-and-search.html +++ /dev/null @@ -1,268 +0,0 @@ - - - - - - - Scan & Search with BarcodeScanner - - - - - - - - -

        📦 Instant Product Information Lookup

        -

        Enter a UPC, EAN, or ISBN number to retrieve accurate product data from a specific database

        -

        -
        - - - -
        - - -
        - - - - - - \ No newline at end of file diff --git a/scenarios/scan-common-1D-and-2D/README.md b/scenarios/scan-common-1D-and-2D/README.md index f344f7e6..98e43031 100644 --- a/scenarios/scan-common-1D-and-2D/README.md +++ b/scenarios/scan-common-1D-and-2D/README.md @@ -14,7 +14,7 @@ A demo configured to detect a wide range of barcode formats (1D and 2D). Useful ## Quick start -Opening HTML files directly may not work as expected. Instead, run a local development server. Here’s a quick method using [Visual Studio Code](https://code.visualstudio.com/): +Opening HTML files directly may not work as expected. Instead, run a local development server. Here's a quick method using [Visual Studio Code](https://code.visualstudio.com/): 1. Install the [Five Server extension](https://marketplace.visualstudio.com/items?itemName=yandeu.five-server) from the VS Code Marketplace. diff --git a/scenarios/scan-common-1D-and-2D/index.html b/scenarios/scan-common-1D-and-2D/index.html index d45b483f..2aec0d30 100644 --- a/scenarios/scan-common-1D-and-2D/index.html +++ b/scenarios/scan-common-1D-and-2D/index.html @@ -4,69 +4,12 @@ - - Dynamsoft Barcode Scanner Sample - Scan Common 1D And 2D - - - - -

        - Scan Common 1D And 2D -

        - -
        - + Dynamsoft Barcode Scanner Sample - Scan Common 1D And 2D - + - - +
        +
        + + \ No newline at end of file diff --git a/scenarios/scan-common-2D-codes/README.md b/scenarios/scan-common-2D-codes/README.md index 0aa7c011..f5c8ad2a 100644 --- a/scenarios/scan-common-2D-codes/README.md +++ b/scenarios/scan-common-2D-codes/README.md @@ -20,7 +20,7 @@ A demo focused on decoding common 2D barcode formats (QR, DataMatrix, PDF417, et ## Quick start -Opening HTML files directly may not work as expected. Instead, run a local development server. Here’s a quick method using [Visual Studio Code](https://code.visualstudio.com/): +Opening HTML files directly may not work as expected. Instead, run a local development server. Here's a quick method using [Visual Studio Code](https://code.visualstudio.com/): 1. Install the [Five Server extension](https://marketplace.visualstudio.com/items?itemName=yandeu.five-server) from the VS Code Marketplace. diff --git a/scenarios/scan-common-2D-codes/index.html b/scenarios/scan-common-2D-codes/index.html index 5b4bb7c1..1a2a8b02 100644 --- a/scenarios/scan-common-2D-codes/index.html +++ b/scenarios/scan-common-2D-codes/index.html @@ -4,69 +4,12 @@ - - Dynamsoft Barcode Scanner Sample - Scan Common 2D codes - - - - -

        - Scan Common 2D codes -

        - -
        - + Dynamsoft Barcode Scanner Sample - Scan Common 2D codes - + - - +
        +
        + + \ No newline at end of file diff --git a/scenarios/scan-datamatrix-code/README.md b/scenarios/scan-datamatrix-code/README.md index 75092622..df346ccf 100644 --- a/scenarios/scan-datamatrix-code/README.md +++ b/scenarios/scan-datamatrix-code/README.md @@ -9,7 +9,7 @@ This sample demonstrates decoding DataMatrix barcodes from camera or image input ## Quick start -Opening HTML files directly may not work as expected. Instead, run a local development server. Here’s a quick method using [Visual Studio Code](https://code.visualstudio.com/): +Opening HTML files directly may not work as expected. Instead, run a local development server. Here's a quick method using [Visual Studio Code](https://code.visualstudio.com/): 1. Install the [Five Server extension](https://marketplace.visualstudio.com/items?itemName=yandeu.five-server) from the VS Code Marketplace. diff --git a/scenarios/scan-datamatrix-code/index.html b/scenarios/scan-datamatrix-code/index.html index 8ce924c7..44b9e5d3 100644 --- a/scenarios/scan-datamatrix-code/index.html +++ b/scenarios/scan-datamatrix-code/index.html @@ -4,69 +4,12 @@ - - Dynamsoft Barcode Scanner Sample - Scan DataMatrix codes - - - - -

        - Scan DataMatrix codes -

        - -
        - + Dynamsoft Barcode Scanner Sample - Scan DataMatrix codes - + - - +
        +
        + + \ No newline at end of file diff --git a/scenarios/scan-dpm-codes/index.html b/scenarios/scan-dpm-codes/index.html index 1cbdead2..16be754d 100644 --- a/scenarios/scan-dpm-codes/index.html +++ b/scenarios/scan-dpm-codes/index.html @@ -4,69 +4,12 @@ - - Dynamsoft Barcode Scanner Sample - Scan DPM codes - - - - -

        - Scan DPM codes -

        - -
        - + Dynamsoft Barcode Scanner Sample - Scan DPM codes - + - - +
        +
        + + \ No newline at end of file diff --git a/scenarios/scan-from-distance/README.md b/scenarios/scan-from-distance/README.md index 02b79095..f6af1d77 100644 --- a/scenarios/scan-from-distance/README.md +++ b/scenarios/scan-from-distance/README.md @@ -19,7 +19,7 @@ A demo that demonstrates techniques for scanning barcodes from a distance (ROI, ## Quick start -Opening HTML files directly may not work as expected. Instead, run a local development server. Here’s a quick method using [Visual Studio Code](https://code.visualstudio.com/): +Opening HTML files directly may not work as expected. Instead, run a local development server. Here's a quick method using [Visual Studio Code](https://code.visualstudio.com/): 1. Install the [Five Server extension](https://marketplace.visualstudio.com/items?itemName=yandeu.five-server) from the VS Code Marketplace. diff --git a/scenarios/scan-from-distance/index.html b/scenarios/scan-from-distance/index.html index fd9734b9..548fbd4f 100644 --- a/scenarios/scan-from-distance/index.html +++ b/scenarios/scan-from-distance/index.html @@ -4,69 +4,12 @@ - - Dynamsoft Barcode Scanner Sample - Scan From Distance - - - - -

        - Scan From Distance -

        - -
        - + Dynamsoft Barcode Scanner Sample - Scan From Distance - + - - +
        +
        + + \ No newline at end of file diff --git a/scenarios/scan-qr-code/README.md b/scenarios/scan-qr-code/README.md index 2b52cd4b..1ae770fe 100644 --- a/scenarios/scan-qr-code/README.md +++ b/scenarios/scan-qr-code/README.md @@ -20,7 +20,7 @@ A focused demo for scanning QR codes from camera video or static images using th ## Quick start -Opening HTML files directly may not work as expected. Instead, run a local development server. Here’s a quick method using [Visual Studio Code](https://code.visualstudio.com/): +Opening HTML files directly may not work as expected. Instead, run a local development server. Here's a quick method using [Visual Studio Code](https://code.visualstudio.com/): 1. Install the [Five Server extension](https://marketplace.visualstudio.com/items?itemName=yandeu.five-server) from the VS Code Marketplace. diff --git a/scenarios/scan-qr-code/index.html b/scenarios/scan-qr-code/index.html index dd845a47..07d27803 100644 --- a/scenarios/scan-qr-code/index.html +++ b/scenarios/scan-qr-code/index.html @@ -4,69 +4,12 @@ - - Dynamsoft Barcode Scanner Sample - Scan QR codes - - - - -

        - Scan QR codes -

        - -
        - + Dynamsoft Barcode Scanner Sample - Scan QR codes - + - - +
        +
        + + \ No newline at end of file diff --git a/scenarios/show-result-texts-on-the-video/README.md b/scenarios/show-result-texts-on-the-video/README.md index a72116e8..a4be5d80 100644 --- a/scenarios/show-result-texts-on-the-video/README.md +++ b/scenarios/show-result-texts-on-the-video/README.md @@ -4,7 +4,7 @@ A demo that overlays decoded barcode text directly onto the live camera video. U ## Included files -- `show-result-texts-on-the-video.html` — demo page that overlays decoded text on video. +- `index.html` — demo page that overlays decoded text on video. ## ✨ Features @@ -20,7 +20,7 @@ A demo that overlays decoded barcode text directly onto the live camera video. U ## Quick start -Opening HTML files directly may not work as expected. Instead, run a local development server. Here’s a quick method using [Visual Studio Code](https://code.visualstudio.com/): +Opening HTML files directly may not work as expected. Instead, run a local development server. Here's a quick method using [Visual Studio Code](https://code.visualstudio.com/): 1. Install the [Five Server extension](https://marketplace.visualstudio.com/items?itemName=yandeu.five-server) from the VS Code Marketplace. diff --git a/scenarios/show-result-texts-on-the-video/show-result-texts-on-the-video.html b/scenarios/show-result-texts-on-the-video/index.html similarity index 90% rename from scenarios/show-result-texts-on-the-video/show-result-texts-on-the-video.html rename to scenarios/show-result-texts-on-the-video/index.html index 6ed221a3..ab1e5358 100644 --- a/scenarios/show-result-texts-on-the-video/show-result-texts-on-the-video.html +++ b/scenarios/show-result-texts-on-the-video/index.html @@ -6,9 +6,35 @@ - + Dynamsoft Barcode Reader Sample - Display Barcode Results as Video Overlays + + + + +