Browse Source

feat: update android sdk 35

bugfix/20250501
tranleanhquoc 2 months ago
parent
commit
3f441255f9
54 changed files with 2815 additions and 132 deletions
  1. +0
    -1
      .fvm/flutter_sdk
  2. +0
    -4
      .fvm/fvm_config.json
  3. +7
    -0
      .fvmrc
  4. +3
    -0
      .gitignore
  5. +2
    -2
      .vscode/settings.json
  6. +15
    -5
      android/app/build.gradle
  7. BIN
      android/app/key.jks
  8. +2
    -3
      android/build.gradle
  9. +1
    -0
      android/gradle.properties
  10. +1
    -1
      android/gradle/wrapper/gradle-wrapper.properties
  11. +1
    -1
      android/key.properties
  12. +1
    -1
      ios/Podfile
  13. +72
    -62
      ios/Podfile.lock
  14. +41
    -45
      ios/Runner.xcodeproj/project.pbxproj
  15. +1
    -1
      ios/Runner/AppDelegate.swift
  16. +38
    -0
      lib/custom_model/product_unit.dart
  17. +16
    -0
      lib/data/repository/repository.dart
  18. +7
    -0
      packages/qr_code_scanner-1.0.1/.gitignore
  19. +168
    -0
      packages/qr_code_scanner-1.0.1/CHANGELOG.md
  20. +9
    -0
      packages/qr_code_scanner-1.0.1/LICENSE
  21. +209
    -0
      packages/qr_code_scanner-1.0.1/README.md
  22. +1
    -0
      packages/qr_code_scanner-1.0.1/analysis_options.yaml
  23. +57
    -0
      packages/qr_code_scanner-1.0.1/android/build.gradle
  24. +3
    -0
      packages/qr_code_scanner-1.0.1/android/gradle.properties
  25. +1
    -0
      packages/qr_code_scanner-1.0.1/android/settings.gradle
  26. +4
    -0
      packages/qr_code_scanner-1.0.1/android/src/main/AndroidManifest.xml
  27. +45
    -0
      packages/qr_code_scanner-1.0.1/android/src/main/kotlin/net/touchcapture/qr/flutterqr/CustomFramingRectBarcodeView.kt
  28. +47
    -0
      packages/qr_code_scanner-1.0.1/android/src/main/kotlin/net/touchcapture/qr/flutterqr/FlutterQrPlugin.kt
  29. +379
    -0
      packages/qr_code_scanner-1.0.1/android/src/main/kotlin/net/touchcapture/qr/flutterqr/QRView.kt
  30. +30
    -0
      packages/qr_code_scanner-1.0.1/android/src/main/kotlin/net/touchcapture/qr/flutterqr/QRViewFactory.kt
  31. +41
    -0
      packages/qr_code_scanner-1.0.1/android/src/main/kotlin/net/touchcapture/qr/flutterqr/QrActivityLifecycleCallbacks.kt
  32. +15
    -0
      packages/qr_code_scanner-1.0.1/android/src/main/kotlin/net/touchcapture/qr/flutterqr/QrShared.kt
  33. +4
    -0
      packages/qr_code_scanner-1.0.1/ios/Classes/FlutterQrPlugin.h
  34. +13
    -0
      packages/qr_code_scanner-1.0.1/ios/Classes/FlutterQrPlugin.m
  35. +304
    -0
      packages/qr_code_scanner-1.0.1/ios/Classes/QRView.swift
  36. +27
    -0
      packages/qr_code_scanner-1.0.1/ios/Classes/QRViewFactory.swift
  37. +22
    -0
      packages/qr_code_scanner-1.0.1/ios/Classes/SwiftFlutterQrPlugin.swift
  38. +23
    -0
      packages/qr_code_scanner-1.0.1/ios/qr_code_scanner.podspec
  39. +7
    -0
      packages/qr_code_scanner-1.0.1/lib/qr_code_scanner.dart
  40. +22
    -0
      packages/qr_code_scanner-1.0.1/lib/src/lifecycle_event_handler.dart
  41. +373
    -0
      packages/qr_code_scanner-1.0.1/lib/src/qr_code_scanner.dart
  42. +183
    -0
      packages/qr_code_scanner-1.0.1/lib/src/qr_scanner_overlay_shape.dart
  43. +16
    -0
      packages/qr_code_scanner-1.0.1/lib/src/types/barcode.dart
  44. +148
    -0
      packages/qr_code_scanner-1.0.1/lib/src/types/barcode_format.dart
  45. +10
    -0
      packages/qr_code_scanner-1.0.1/lib/src/types/camera.dart
  46. +14
    -0
      packages/qr_code_scanner-1.0.1/lib/src/types/camera_exception.dart
  47. +13
    -0
      packages/qr_code_scanner-1.0.1/lib/src/types/features.dart
  48. +6
    -0
      packages/qr_code_scanner-1.0.1/lib/src/web/flutter_qr_stub.dart
  49. +328
    -0
      packages/qr_code_scanner-1.0.1/lib/src/web/flutter_qr_web.dart
  50. +12
    -0
      packages/qr_code_scanner-1.0.1/lib/src/web/jsqr.dart
  51. +36
    -0
      packages/qr_code_scanner-1.0.1/lib/src/web/media.dart
  52. +31
    -0
      packages/qr_code_scanner-1.0.1/pubspec.yaml
  53. +3
    -4
      pubspec.lock
  54. +3
    -2
      pubspec.yaml

+ 0
- 1
.fvm/flutter_sdk View File

@@ -1 +0,0 @@
/Users/daivph/fvm/versions/3.13.9

+ 0
- 4
.fvm/fvm_config.json View File

@@ -1,4 +0,0 @@
{
"flutterSdkVersion": "3.13.9",
"flavors": {}
}

+ 7
- 0
.fvmrc View File

@@ -0,0 +1,7 @@
{
"flutter": "3.13.9",
"flavors": {},
"runPubGetOnSdkChanges": true,
"updateVscodeSettings": true,
"updateGitIgnore": true
}

+ 3
- 0
.gitignore View File

@@ -41,3 +41,6 @@ app.*.map.json

# Exceptions to above rules.
!/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages

# FVM Version Cache
.fvm/

+ 2
- 2
.vscode/settings.json View File

@@ -1,4 +1,4 @@
{
"dart.flutterSdkPath": "~/fvm/versions/3.13.9",
"java.configuration.updateBuildConfiguration": "interactive"
"dart.flutterSdkPath": ".fvm/versions/3.13.9",
"java.configuration.updateBuildConfiguration": "interactive"
}

+ 15
- 5
android/app/build.gradle View File

@@ -32,8 +32,9 @@ if (keystorePropertiesFile.exists()) {
}

android {
compileSdkVersion 34
ndkVersion "21.1.6352462"
namespace 'vn.azteam.farmdemo'
compileSdkVersion 35
ndkVersion "26.1.10909125"

sourceSets {
main.java.srcDirs += 'src/main/kotlin'
@@ -43,11 +44,20 @@ android {
disable 'InvalidPackage'
}

compileOptions {
sourceCompatibility JavaVersion.VERSION_17
targetCompatibility JavaVersion.VERSION_17
}

kotlinOptions {
jvmTarget = "17"
}

defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId "vn.azteam.farmdemo"
minSdkVersion 24
targetSdkVersion 34
targetSdkVersion 35
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
}
@@ -74,6 +84,6 @@ flutter {

dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation 'com.google.firebase:firebase-messaging:20.1.0'
implementation 'com.google.firebase:firebase-messaging:23.4.1'
}
apply plugin: 'com.google.gms.google-services'
apply plugin: 'com.google.gms.google-services'

BIN
android/app/key.jks View File


+ 2
- 3
android/build.gradle View File

@@ -6,7 +6,7 @@ buildscript {
}

dependencies {
classpath 'com.android.tools.build:gradle:7.3.1'
classpath 'com.android.tools.build:gradle:8.4.0'
classpath 'com.google.gms:google-services:4.3.3'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
@@ -22,9 +22,8 @@ allprojects {
rootProject.buildDir = '../build'
subprojects {
project.buildDir = "${rootProject.buildDir}/${project.name}"
}
subprojects {
project.evaluationDependsOn(':app')

project.configurations.all {
resolutionStrategy.eachDependency { details ->
if (details.requested.group == 'com.android.support'

+ 1
- 0
android/gradle.properties View File

@@ -2,3 +2,4 @@ org.gradle.jvmargs=-Xmx1536M
android.enableR8=true
android.useAndroidX=true
android.enableJetifier=true
android.suppressUnsupportedCompileSdk=34,35

+ 1
- 1
android/gradle/wrapper/gradle-wrapper.properties View File

@@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-all.zip

+ 1
- 1
android/key.properties View File

@@ -1,4 +1,4 @@
storePassword=123456
keyPassword=123456
keyAlias=key
storeFile=/Users/daivph/key.jks
storeFile=key.jks

+ 1
- 1
ios/Podfile View File

@@ -1,5 +1,5 @@
# Uncomment this line to define a global platform for your project
# platform :ios, '11.0'
# platform :ios, '12.0'

# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
ENV['COCOAPODS_DISABLE_STATS'] = 'true'

+ 72
- 62
ios/Podfile.lock View File

@@ -1,35 +1,35 @@
PODS:
- camera_avfoundation (0.0.1):
- Flutter
- DKImagePickerController/Core (4.3.4):
- DKImagePickerController/Core (4.3.9):
- DKImagePickerController/ImageDataManager
- DKImagePickerController/Resource
- DKImagePickerController/ImageDataManager (4.3.4)
- DKImagePickerController/PhotoGallery (4.3.4):
- DKImagePickerController/ImageDataManager (4.3.9)
- DKImagePickerController/PhotoGallery (4.3.9):
- DKImagePickerController/Core
- DKPhotoGallery
- DKImagePickerController/Resource (4.3.4)
- DKPhotoGallery (0.0.17):
- DKPhotoGallery/Core (= 0.0.17)
- DKPhotoGallery/Model (= 0.0.17)
- DKPhotoGallery/Preview (= 0.0.17)
- DKPhotoGallery/Resource (= 0.0.17)
- DKImagePickerController/Resource (4.3.9)
- DKPhotoGallery (0.0.19):
- DKPhotoGallery/Core (= 0.0.19)
- DKPhotoGallery/Model (= 0.0.19)
- DKPhotoGallery/Preview (= 0.0.19)
- DKPhotoGallery/Resource (= 0.0.19)
- SDWebImage
- SwiftyGif
- DKPhotoGallery/Core (0.0.17):
- DKPhotoGallery/Core (0.0.19):
- DKPhotoGallery/Model
- DKPhotoGallery/Preview
- SDWebImage
- SwiftyGif
- DKPhotoGallery/Model (0.0.17):
- DKPhotoGallery/Model (0.0.19):
- SDWebImage
- SwiftyGif
- DKPhotoGallery/Preview (0.0.17):
- DKPhotoGallery/Preview (0.0.19):
- DKPhotoGallery/Model
- DKPhotoGallery/Resource
- SDWebImage
- SwiftyGif
- DKPhotoGallery/Resource (0.0.17):
- DKPhotoGallery/Resource (0.0.19):
- SDWebImage
- SwiftyGif
- file_picker (0.0.1):
@@ -51,9 +51,9 @@ PODS:
- FirebaseCoreInternal (~> 10.0)
- GoogleUtilities/Environment (~> 7.8)
- GoogleUtilities/Logger (~> 7.8)
- FirebaseCoreInternal (10.16.0):
- FirebaseCoreInternal (10.29.0):
- "GoogleUtilities/NSData+zlib (~> 7.8)"
- FirebaseInstallations (10.16.0):
- FirebaseInstallations (10.29.0):
- FirebaseCore (~> 10.0)
- GoogleUtilities/Environment (~> 7.8)
- GoogleUtilities/UserDefaults (~> 7.8)
@@ -75,53 +75,63 @@ PODS:
- SDWebImageWebPCoder
- flutter_local_notifications (0.0.1):
- Flutter
- FMDB (2.7.5):
- FMDB/standard (= 2.7.5)
- FMDB/standard (2.7.5)
- GoogleDataTransport (9.2.5):
- FMDB (2.7.12):
- FMDB/standard (= 2.7.12)
- FMDB/Core (2.7.12)
- FMDB/standard (2.7.12):
- FMDB/Core
- GoogleDataTransport (9.4.1):
- GoogleUtilities/Environment (~> 7.7)
- nanopb (< 2.30910.0, >= 2.30908.0)
- nanopb (< 2.30911.0, >= 2.30908.0)
- PromisesObjC (< 3.0, >= 1.2)
- GoogleUtilities/AppDelegateSwizzler (7.11.5):
- GoogleUtilities/AppDelegateSwizzler (7.13.3):
- GoogleUtilities/Environment
- GoogleUtilities/Logger
- GoogleUtilities/Network
- GoogleUtilities/Environment (7.11.5):
- GoogleUtilities/Privacy
- GoogleUtilities/Environment (7.13.3):
- GoogleUtilities/Privacy
- PromisesObjC (< 3.0, >= 1.2)
- GoogleUtilities/Logger (7.11.5):
- GoogleUtilities/Logger (7.13.3):
- GoogleUtilities/Environment
- GoogleUtilities/Network (7.11.5):
- GoogleUtilities/Privacy
- GoogleUtilities/Network (7.13.3):
- GoogleUtilities/Logger
- "GoogleUtilities/NSData+zlib"
- GoogleUtilities/Privacy
- GoogleUtilities/Reachability
- "GoogleUtilities/NSData+zlib (7.11.5)"
- GoogleUtilities/Reachability (7.11.5):
- "GoogleUtilities/NSData+zlib (7.13.3)":
- GoogleUtilities/Privacy
- GoogleUtilities/Privacy (7.13.3)
- GoogleUtilities/Reachability (7.13.3):
- GoogleUtilities/Logger
- GoogleUtilities/UserDefaults (7.11.5):
- GoogleUtilities/Privacy
- GoogleUtilities/UserDefaults (7.13.3):
- GoogleUtilities/Logger
- GoogleUtilities/Privacy
- image_picker_ios (0.0.1):
- Flutter
- libwebp (1.3.2):
- libwebp/demux (= 1.3.2)
- libwebp/mux (= 1.3.2)
- libwebp/sharpyuv (= 1.3.2)
- libwebp/webp (= 1.3.2)
- libwebp/demux (1.3.2):
- libwebp (1.5.0):
- libwebp/demux (= 1.5.0)
- libwebp/mux (= 1.5.0)
- libwebp/sharpyuv (= 1.5.0)
- libwebp/webp (= 1.5.0)
- libwebp/demux (1.5.0):
- libwebp/webp
- libwebp/mux (1.3.2):
- libwebp/mux (1.5.0):
- libwebp/demux
- libwebp/sharpyuv (1.3.2)
- libwebp/webp (1.3.2):
- libwebp/sharpyuv (1.5.0)
- libwebp/webp (1.5.0):
- libwebp/sharpyuv
- Mantle (2.2.0):
- Mantle/extobjc (= 2.2.0)
- Mantle/extobjc (2.2.0)
- MTBBarcodeScanner (5.0.11)
- nanopb (2.30909.0):
- nanopb/decode (= 2.30909.0)
- nanopb/encode (= 2.30909.0)
- nanopb/decode (2.30909.0)
- nanopb/encode (2.30909.0)
- nanopb (2.30909.1):
- nanopb/decode (= 2.30909.1)
- nanopb/encode (= 2.30909.1)
- nanopb/decode (2.30909.1)
- nanopb/encode (2.30909.1)
- open_filex (0.0.2):
- Flutter
- package_info_plus (0.4.5):
@@ -129,14 +139,14 @@ PODS:
- path_provider_foundation (0.0.1):
- Flutter
- FlutterMacOS
- PromisesObjC (2.3.1)
- PromisesObjC (2.4.0)
- qr_code_scanner (0.2.0):
- Flutter
- MTBBarcodeScanner
- SDWebImage (5.18.3):
- SDWebImage/Core (= 5.18.3)
- SDWebImage/Core (5.18.3)
- SDWebImageWebPCoder (0.14.0):
- SDWebImage (5.21.1):
- SDWebImage/Core (= 5.21.1)
- SDWebImage/Core (5.21.1)
- SDWebImageWebPCoder (0.14.6):
- libwebp (~> 1.0)
- SDWebImage/Core (~> 5.17)
- shared_preferences_foundation (0.0.1):
@@ -145,7 +155,7 @@ PODS:
- sqflite (0.0.3):
- Flutter
- FMDB (>= 2.7.5)
- SwiftyGif (5.4.4)
- SwiftyGif (5.4.5)

DEPENDENCIES:
- camera_avfoundation (from `.symlinks/plugins/camera_avfoundation/ios`)
@@ -216,38 +226,38 @@ EXTERNAL SOURCES:

SPEC CHECKSUMS:
camera_avfoundation: 3125e8cd1a4387f6f31c6c63abb8a55892a9eeeb
DKImagePickerController: b512c28220a2b8ac7419f21c491fc8534b7601ac
DKPhotoGallery: fdfad5125a9fdda9cc57df834d49df790dbb4179
DKImagePickerController: 946cec48c7873164274ecc4624d19e3da4c1ef3c
DKPhotoGallery: b3834fecb755ee09a593d7c9e389d8b5d6deed60
file_picker: ce3938a0df3cc1ef404671531facef740d03f920
Firebase: 66043bd4579e5b73811f96829c694c7af8d67435
firebase_core: 49fd2395e3fbbf63f453888c8e9f42f541f4c11c
firebase_messaging: f29609230a6f0759b72218d66ada60ed51c14a51
FirebaseCore: 2cec518b43635f96afe7ac3a9c513e47558abd2e
FirebaseCoreInternal: 26233f705cc4531236818a07ac84d20c333e505a
FirebaseInstallations: b822f91a61f7d1ba763e5ccc9d4f2e6f2ed3b3ee
FirebaseCoreInternal: df84dd300b561c27d5571684f389bf60b0a5c934
FirebaseInstallations: 913cf60d0400ebd5d6b63a28b290372ab44590dd
FirebaseMessaging: 0c0ae1eb722ef0c07f7801e5ded8dccd1357d6d4
Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854
flutter_image_compress_common: ec1d45c362c9d30a3f6a0426c297f47c52007e3e
flutter_local_notifications: 4cde75091f6327eb8517fa068a0a5950212d2086
FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a
GoogleDataTransport: 54dee9d48d14580407f8f5fbf2f496e92437a2f2
GoogleUtilities: 13e2c67ede716b8741c7989e26893d151b2b2084
FMDB: 728731dd336af3936ce00f91d9d8495f5718a0e6
GoogleDataTransport: 6c09b596d841063d76d4288cc2d2f42cc36e1e2a
GoogleUtilities: ea963c370a38a8069cc5f7ba4ca849a60b6d7d15
image_picker_ios: 4a8aadfbb6dc30ad5141a2ce3832af9214a705b5
libwebp: 1786c9f4ff8a279e4dac1e8f385004d5fc253009
libwebp: 02b23773aedb6ff1fd38cec7a77b81414c6842a8
Mantle: c5aa8794a29a022dfbbfc9799af95f477a69b62d
MTBBarcodeScanner: f453b33c4b7dfe545d8c6484ed744d55671788cb
nanopb: b552cce312b6c8484180ef47159bc0f65a1f0431
nanopb: d4d75c12cd1316f4a64e3c6963f879ecd4b5e0d5
open_filex: 6e26e659846ec990262224a12ef1c528bb4edbe4
package_info_plus: 115f4ad11e0698c8c1c5d8a689390df880f47e85
path_provider_foundation: 29f094ae23ebbca9d3d0cec13889cd9060c0e943
PromisesObjC: c50d2056b5253dadbd6c2bea79b0674bd5a52fa4
PromisesObjC: f5707f49cb48b9636751c5b2e7d227e43fba9f47
qr_code_scanner: bb67d64904c3b9658ada8c402e8b4d406d5d796e
SDWebImage: 96e0c18ef14010b7485210e92fac888587ebb958
SDWebImageWebPCoder: 3027af94522d94df79c21c070894c8a2128927ff
SDWebImage: f29024626962457f3470184232766516dee8dfea
SDWebImageWebPCoder: e38c0a70396191361d60c092933e22c20d5b1380
shared_preferences_foundation: 5b919d13b803cadd15ed2dc053125c68730e5126
sqflite: 31f7eba61e3074736dff8807a9b41581e4f7f15a
SwiftyGif: 93a1cc87bf3a51916001cf8f3d63835fb64c819f
SwiftyGif: 706c60cf65fa2bc5ee0313beece843c8eb8194d4

PODFILE CHECKSUM: f08360d062df7ffa8ee251115991830e526d3068
PODFILE CHECKSUM: 6481fb016013975cde9a140d4cb676ca667f392d

COCOAPODS: 1.15.2
COCOAPODS: 1.14.3

+ 41
- 45
ios/Runner.xcodeproj/project.pbxproj View File

@@ -8,7 +8,6 @@

/* Begin PBXBuildFile section */
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
28BA40FE80B56A14B0D9CD11 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B548275770BC6D3B4CF786E0 /* Pods_Runner.framework */; };
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
57039D382BEF24AA002F4393 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 57039D372BEF24AA002F4393 /* GoogleService-Info.plist */; };
57EDCFFA2BBC55CE005E5B0A /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 57EDCFF92BBC55CE005E5B0A /* PrivacyInfo.xcprivacy */; };
@@ -16,6 +15,7 @@
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
A5C6DCB906831570B6082DF3 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3E269CC216B5257E93C9FA4E /* Pods_Runner.framework */; };
/* End PBXBuildFile section */

/* Begin PBXCopyFilesBuildPhase section */
@@ -35,14 +35,15 @@
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; };
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
4A9923954A102F75F089DEB2 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = "<group>"; };
3E269CC216B5257E93C9FA4E /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
56F965331AB025C195DECEF3 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = "<group>"; };
57039D372BEF24AA002F4393 /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = "<group>"; };
57CB5602257E19450029CFCB /* Runner.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Runner.entitlements; sourceTree = "<group>"; };
57EDCFF92BBC55CE005E5B0A /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = PrivacyInfo.xcprivacy; sourceTree = "<group>"; };
59505A69743F2F8D63E32074 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = "<group>"; };
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; };
74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; };
84283C2EDDE2AA27CFC254EF /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; };
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = "<group>"; };
9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = "<group>"; };
97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -50,8 +51,7 @@
97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
A721EE1634DF0272D5F66D0A /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; };
B548275770BC6D3B4CF786E0 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
9F73701B7B185BF31661C730 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
@@ -59,17 +59,17 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
28BA40FE80B56A14B0D9CD11 /* Pods_Runner.framework in Frameworks */,
A5C6DCB906831570B6082DF3 /* Pods_Runner.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */

/* Begin PBXGroup section */
27A241DF7FF8DCCE69323071 /* Frameworks */ = {
2D7EF3AE8F19BCD8F01B2BAA /* Frameworks */ = {
isa = PBXGroup;
children = (
B548275770BC6D3B4CF786E0 /* Pods_Runner.framework */,
3E269CC216B5257E93C9FA4E /* Pods_Runner.framework */,
);
name = Frameworks;
sourceTree = "<group>";
@@ -93,7 +93,7 @@
97C146F01CF9000F007C117D /* Runner */,
97C146EF1CF9000F007C117D /* Products */,
DB97C68FAB84AB5AA161781D /* Pods */,
27A241DF7FF8DCCE69323071 /* Frameworks */,
2D7EF3AE8F19BCD8F01B2BAA /* Frameworks */,
);
sourceTree = "<group>";
};
@@ -125,9 +125,9 @@
DB97C68FAB84AB5AA161781D /* Pods */ = {
isa = PBXGroup;
children = (
59505A69743F2F8D63E32074 /* Pods-Runner.debug.xcconfig */,
A721EE1634DF0272D5F66D0A /* Pods-Runner.release.xcconfig */,
4A9923954A102F75F089DEB2 /* Pods-Runner.profile.xcconfig */,
56F965331AB025C195DECEF3 /* Pods-Runner.debug.xcconfig */,
84283C2EDDE2AA27CFC254EF /* Pods-Runner.release.xcconfig */,
9F73701B7B185BF31661C730 /* Pods-Runner.profile.xcconfig */,
);
path = Pods;
sourceTree = "<group>";
@@ -139,14 +139,14 @@
isa = PBXNativeTarget;
buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
buildPhases = (
B0E181500D99EDAA32A810B2 /* [CP] Check Pods Manifest.lock */,
1403A7B7F5A6414AD23F1306 /* [CP] Check Pods Manifest.lock */,
9740EEB61CF901F6004384FC /* Run Script */,
97C146EA1CF9000F007C117D /* Sources */,
97C146EB1CF9000F007C117D /* Frameworks */,
97C146EC1CF9000F007C117D /* Resources */,
9705A1C41CF9048500538489 /* Embed Frameworks */,
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
218F0E56B9A2D546B7825C6F /* [CP] Embed Pods Frameworks */,
8A0A8E6370899AD9035DD16C /* [CP] Embed Pods Frameworks */,
);
buildRules = (
);
@@ -207,25 +207,26 @@
/* End PBXResourcesBuildPhase section */

/* Begin PBXShellScriptBuildPhase section */
218F0E56B9A2D546B7825C6F /* [CP] Embed Pods Frameworks */ = {
1403A7B7F5A6414AD23F1306 /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist",
);
inputPaths = (
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
"${PODS_ROOT}/Manifest.lock",
);
name = "[CP] Embed Pods Frameworks";
name = "[CP] Check Pods Manifest.lock";
outputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist",
);
outputPaths = (
"$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0;
};
3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
@@ -244,42 +245,37 @@
shellPath = /bin/sh;
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin";
};
9740EEB61CF901F6004384FC /* Run Script */ = {
8A0A8E6370899AD9035DD16C /* [CP] Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
alwaysOutOfDate = 1;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
inputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist",
);
name = "Run Script";
outputPaths = (
name = "[CP] Embed Pods Frameworks";
outputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
B0E181500D99EDAA32A810B2 /* [CP] Check Pods Manifest.lock */ = {
9740EEB61CF901F6004384FC /* Run Script */ = {
isa = PBXShellScriptBuildPhase;
alwaysOutOfDate = 1;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
"${PODS_ROOT}/Manifest.lock",
);
name = "[CP] Check Pods Manifest.lock";
outputFileListPaths = (
);
name = "Run Script";
outputPaths = (
"$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0;
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
};
/* End PBXShellScriptBuildPhase section */

@@ -357,7 +353,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos;
@@ -376,7 +372,7 @@
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 37;
CURRENT_PROJECT_VERSION = 40;
DEVELOPMENT_TEAM = C3DTD2JH94;
ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
@@ -393,7 +389,7 @@
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
MARKETING_VERSION = 1.1.17;
MARKETING_VERSION = 1.1.20;
PRODUCT_BUNDLE_IDENTIFIER = vn.azteam.farmdemo;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
@@ -451,7 +447,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
@@ -501,7 +497,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos;
@@ -522,7 +518,7 @@
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 37;
CURRENT_PROJECT_VERSION = 40;
DEVELOPMENT_TEAM = C3DTD2JH94;
ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
@@ -539,7 +535,7 @@
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
MARKETING_VERSION = 1.1.17;
MARKETING_VERSION = 1.1.20;
PRODUCT_BUNDLE_IDENTIFIER = vn.azteam.farmdemo;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
@@ -560,7 +556,7 @@
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 37;
CURRENT_PROJECT_VERSION = 40;
DEVELOPMENT_TEAM = C3DTD2JH94;
ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
@@ -577,7 +573,7 @@
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
MARKETING_VERSION = 1.1.17;
MARKETING_VERSION = 1.1.20;
PRODUCT_BUNDLE_IDENTIFIER = vn.azteam.farmdemo;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";

+ 1
- 1
ios/Runner/AppDelegate.swift View File

@@ -2,7 +2,7 @@ import UIKit
import Flutter
import Firebase

@UIApplicationMain
@main
@objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,

+ 38
- 0
lib/custom_model/product_unit.dart View File

@@ -0,0 +1,38 @@
import 'package:equatable/equatable.dart';

class ProductUnit extends Equatable {
ProductUnit({
this.id,
this.key,
this.name,
});

final int? id;
final String? key;
final String? name;

ProductUnit copyWith({
int? id,
String? key,
String? name,
}) {
return ProductUnit(
id: id ?? this.id,
key: key ?? this.key,
name: name ?? this.name,
);
}

factory ProductUnit.fromJson(Map<String, dynamic> json) {
return ProductUnit(
id: json["id"],
key: json["key"],
name: json["name"],
);
}

Map<String, dynamic> toJson() => {"id": id, "key": key, "name": name};

@override
List<Object?> get props => [id, key, name];
}

+ 16
- 0
lib/data/repository/repository.dart View File

@@ -33,6 +33,7 @@ import 'package:farm_tpf/utils/const_common.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';

import '../../custom_model/product_unit.dart';
import '../../presentation/screens/codes/models/stamp_type.dart';
import '../../presentation/screens/login/models/request_user.dart';
import '../../presentation/screens/login/models/response_user.dart';
@@ -140,6 +141,21 @@ class Repository {
}
}

Future<List<ProductUnit>> getProductUnits() async {
var op = buildConfigurableCacheOptions(forceRefresh: true, maxAge: Duration(days: ConstCommon.kMaxAgeCache));
try {
final result = await dio.get("${ConstCommon.baseUrl}/api/tb-product-units", options: op);
final data = result.data;
if (data is List) {
return data.map((i) => ProductUnit.fromJson(i as Map<String, dynamic>)).toList();
} else {
return [];
}
} catch (_) {
return [];
}
}

Future<List<Device>> getDeviceForActivity() async {
final client = RestClient(dio);
var op = buildConfigurableCacheOptions(forceRefresh: true, maxAge: Duration(days: ConstCommon.kMaxAgeCache));

+ 7
- 0
packages/qr_code_scanner-1.0.1/.gitignore View File

@@ -0,0 +1,7 @@
gradle-wrapper.jar
/.gradle
/captures/
/gradlew
/gradlew.bat
/local.properties
GeneratedPluginRegistrant.java

+ 168
- 0
packages/qr_code_scanner-1.0.1/CHANGELOG.md View File

@@ -0,0 +1,168 @@
## 1.0.1
* [Android] fixed null pointer on engine detached. [#567](https://github.com/juliuscanute/qr_code_scanner/issues/567)

## 1.0.0
Breaking changes:
Minimum Flutter version is now Flutter 3.0.0 (Dart 2.17.0).

#### Features
* Inverted is now mixed with normal scanning.
* onPermissionSet now works on web aswell.
* [Android] zxing core is updated to 3.5.0.
* [Android] Several code improvements.
* [Android] Several dependencies updated.

## 0.7.0
#### Features
* Add inverted feature for Android. See https://github.com/juliuscanute/qr_code_scanner/issues/403

#### Bugfixes
* Fixed permission error on devices running Android 7 or lower.
* Fixed error being thrown when user declines permission on iOS.
* Updated dependencies

## 0.6.1
* Fix bug which caused build to fail for iOS. (#452)

## 0.6.0
#### Features
* Add support for raw bytes on iOS. (#421)
* Add custom cutout width and height next to cutout size. (#432)

#### Bugfixes
* Fix for calling permission multiple times. (#381)
* Fix for QRView Overlay cutoutbottomoffset. (#383)
* Multiple minor improvements

## 0.5.2
#### Bugfixes
* Increased delay to fix QRView opening zoomed in on some devices by adding small delay to updateDimensions(). (#250)
* Updated ZXING from 3.3.0 to 3.4.1 (#369)
* Fixed permission not being called correctly on Android (#351)

## 0.5.1
Removed web from library export.

## 0.5.0
* Added initial web-support. This function is still under development and not fully tested.
* Fixed permissions on iOS.
* Updated dependencies.

## 0.4.0
Stable null-safety support. (#278)

## 0.3.5
#### Bug fixes
* Fixed QRView opening zoomed in on some devices by adding small delay to updateDimensions(). (#250)
* Changed upc-A to EAN13 on iOS. (#262)
* Fixed null-pointer on BarcodeFormat array on iOS. (#262)
* Added LifecycleEventHandler to dispose(). (#265)

## 0.3.4
#### Bug fixes
* Fixed No barcode view found on Android when calling controller.dispose() (#257)
* Fixed Hot reload not working on Android.

## 0.3.3
#### Bug fixes
* Fixed updateDimensions not being called causing zoom on iOS. (#250)
* Fixed Android permission callback not working. (#251) (#252)
* Fixed null-pointers after declining permission on Android.

## 0.3.2
#### Bug fixes
* Fixed null-pointer when no overlay provided on iOS. (#245)
* Fixed camera not stopping (green dot on iOS 14) when navigating to other page. (#240)

## 0.3.1
#### Bug fixes
* Fixed permission callback on iOS & Android.
* Fixed camera facing not working on Android.
* Fixed scanArea not being honored on Android.
* Updated ShapeBorder to QrScannerOverlayShape.

## 0.3.0
#### Breaking change
Its not necessary anymore to wrap the QRView in a SizeChangedLayoutNotifier because this is handled inside the plugin.
#### New Features
* Added possibility to set allowed barcodes. (#135)
* Added possibility to check what features are supported by device. (hasFlash, hasBackCamera, hasFrontCamera) (#135)
* Added possibility to check if flash is on. (#135)
* Added possibility to check which camera is active. (#135)
* All functions are now async so you can await them. (#135)

See the updated example on how to implement these features.
#### Bug fixes
* Fixed permission handling in Android.
* Native functions now returns results so exceptions can be thrown when an error occurs.

## 0.2.1
* Fixed critical bug where scanner wouldn't open when no scan overlay was configured.

## 0.2.0
#### Breaking change
* The plugin now returns Barcode object instead of QR String. This object includes the type of code, the code itself and on Android devices the raw bytes. (#63)
#### New Features
* Added possibility to provide scanArea on iOS. (#165)
#### Bug fixes
* Fixed preview going black after hot reload. (#76)
* Fixed nullpointer when plugin binding order isn't correct. (#181)
* Fixed permission being asked on startup (#185)

## 0.1.0
* Changed Android minSDKversion from 24 to 21 (#170)
* Fix preview size after iPad rotation (#125)
* Implemented Android Embedding V2 (#132)
* Added cutout bottom offset (#115)
* Fix Android ActivityLifecycleCallbacks (#166)
* Fix some other small bugs

## 0.0.14
* Fix disposing camera on iOS 14 (#113)

## 0.0.13
* Fix misalignment when QRView doesn't start from the top left (#45)
* Fix crash on iOS when scanning returns nil (#69, #72)
* Fix ArithmeticException on Android (#43)

## 0.0.12
* Add optional parameter to use a camera overlay.
* Simplify controller, expose scanDataStream.
* Fix for Android flash toggle.
* Add ability to pause/resume the camera.
* Thanks! to Luis Thein for all the above contributions.

## 0.0.11
* android build break fix

## 0.0.10
* update README.md

## 0.0.9
* update README.md

## 0.0.8
* migrated Android project to androidx (by Felipe César)
* migrated iOS to Swift 5 (by Felipe César)

## 0.0.7
* flash light support added

## 0.0.6
* camera flip added

## 0.0.5
* preview stretching after change screen orientation fix

## 0.0.4
* fix black screen orientation/unlock/focus

## 0.0.3
* iOS library reference fix
* Android pause/resume fix

## 0.0.2
* Added documentation to cover how to use the plugin.

## 0.0.1
* QR Code scanner embedded inside flutter.

+ 9
- 0
packages/qr_code_scanner-1.0.1/LICENSE View File

@@ -0,0 +1,9 @@
Copyright 2018 Julius Canute

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+ 209
- 0
packages/qr_code_scanner-1.0.1/README.md View File

@@ -0,0 +1,209 @@
# Project in Maintenance Mode Only

Since the underlying frameworks of this package, [zxing for android](https://github.com/zxing/zxing) and [MTBBarcodescanner for iOS](https://github.com/mikebuss/MTBBarcodeScanner) are both not longer maintaned, this plugin is no longer up to date and in maintenance mode only. Only bug fixes and minor enhancements will be considered.

I am developing a new plugin [mobile_scanner](https://pub.dev/packages/mobile_scanner) that uses the latest version of MLKit for detecting barcodes and QR codes. On Android it also uses the latest version of CameraX, and on iOS the native AVFoundation for best camera performance.

# QR Code Scanner

[![pub package](https://img.shields.io/pub/v/qr_code_scanner?include_prereleases)](https://pub.dartlang.org/packages/qr_code_scanner)
[![Join the chat](https://img.shields.io/discord/829004904600961054)](https://discord.gg/aZujk84f6V)
[![GH Actions](https://github.com/juliuscanute/qr_code_scanner/workflows/dart/badge.svg)](https://github.com/juliuscanute/qr_code_scanner/actions)

A QR code scanner that works on both iOS and Android by natively embedding the platform view within Flutter. The integration with Flutter is seamless, much better than jumping into a native Activity or a ViewController to perform the scan.

## Screenshots
<table>
<tr>
<th colspan="2">
Android
</th>
</tr>

<tr>
<td>
<p align="center">
<img src="https://raw.githubusercontent.com/juliuscanute/qr_code_scanner/master/.resources/android-app-screen-one.jpg" width="30%" height="30%">
</p>
</td>
<td>
<p align="center">
<img src="https://raw.githubusercontent.com/juliuscanute/qr_code_scanner/master/.resources/android-app-screen-two.jpg" width="30%" height="30%">
</p>
</td>
</tr>

<tr>
<th colspan="2">
iOS
</th>
</tr>

<tr>
<td>
<p align="center">
<img src="https://raw.githubusercontent.com/juliuscanute/qr_code_scanner/master/.resources/ios-app-screen-one.png" width="30%" height="30%">
</p>
</td>
<td>
<p align="center">
<img src="https://raw.githubusercontent.com/juliuscanute/qr_code_scanner/master/.resources/ios-app-screen-two.png" width="30%" height="30%">
</p>
</td>
</tr>

</table>

## Get Scanned QR Code

When a QR code is recognized, the text identified will be set in 'result' of type `Barcode`, which contains the output text as property 'code' of type `String` and scanned code type as property 'format' which is an enum `BarcodeFormat`, defined in the library.

```dart
class _QRViewExampleState extends State<QRViewExample> {
final GlobalKey qrKey = GlobalKey(debugLabel: 'QR');
Barcode? result;
QRViewController? controller;

// In order to get hot reload to work we need to pause the camera if the platform
// is android, or resume the camera if the platform is iOS.
@override
void reassemble() {
super.reassemble();
if (Platform.isAndroid) {
controller!.pauseCamera();
} else if (Platform.isIOS) {
controller!.resumeCamera();
}
}

@override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: <Widget>[
Expanded(
flex: 5,
child: QRView(
key: qrKey,
onQRViewCreated: _onQRViewCreated,
),
),
Expanded(
flex: 1,
child: Center(
child: (result != null)
? Text(
'Barcode Type: ${describeEnum(result!.format)} Data: ${result!.code}')
: Text('Scan a code'),
),
)
],
),
);
}

void _onQRViewCreated(QRViewController controller) {
this.controller = controller;
controller.scannedDataStream.listen((scanData) {
setState(() {
result = scanData;
});
});
}

@override
void dispose() {
controller?.dispose();
super.dispose();
}
}

```

## Android Integration
In order to use this plugin, please update the Gradle, Kotlin and Kotlin Gradle Plugin:

In ```android/build.gradle``` change ```ext.kotlin_version = '1.3.50'``` to ```ext.kotlin_version = '1.5.10'```

In ```android/build.gradle``` change ```classpath 'com.android.tools.build:gradle:3.5.0'``` to ```classpath 'com.android.tools.build:gradle:4.2.0'```

In ```android/gradle/wrapper/gradle-wrapper.properties``` change ```distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.2-all.zip``` to ```distributionUrl=https\://services.gradle.org/distributions/gradle-6.9-all.zip```

In ```android/app/build.gradle``` change
```defaultConfig{```
```...```
```minSdkVersion 16```
```}``` to
```defaultConfig{```
```...```
```minSdkVersion 20```
```}```

### *Warning*
If you are using Flutter Beta or Dev channel (1.25 or 1.26) you can get the following error:

`java.lang.AbstractMethodError: abstract method "void io.flutter.plugin.platform.PlatformView.onFlutterViewAttached(android.view.View)"`

This is a bug in Flutter which is being tracked here: https://github.com/flutter/flutter/issues/72185

There is a workaround by adding `android.enableDexingArtifactTransform=false` to your `gradle.properties` file.

## iOS Integration
In order to use this plugin, add the following to your Info.plist file:
```
<key>io.flutter.embedded_views_preview</key>
<true/>
<key>NSCameraUsageDescription</key>
<string>This app needs camera access to scan QR codes</string>
```

## Web Integration

Add this to `web/index.html`:

```html
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/jsQR.min.js"></script>
```

Please note: on web, only QR codes are supported. Other barcodes and 2D codes cannot be scanned.

Web support is in very early stage. Features such as flash, pause or resume are not implemented. Moreover, the camera
preview does not respect the surrounding constraints. This is not at last due to Flutter's early state of platform views
on web.

## Flip Camera (Back/Front)
The default camera is the back camera.
```dart
await controller.flipCamera();
```

## Flash (Off/On)
By default, flash is OFF.
```dart
await controller.toggleFlash();
```

## Resume/Pause
Pause camera stream and scanner.
```dart
await controller.pauseCamera();
```
Resume camera stream and scanner.
```dart
await controller.resumeCamera();
```


# SDK
Requires at least SDK 20.
Requires at least iOS 8.

# TODOs
* iOS Native embedding is written to match what is supported in the framework as of the date of publication of this package. It needs to be improved as the framework support improves.
* In future, options will be provided for default states.
* Finally, I welcome PR's to make it better :), thanks

# Credits
* Android: https://github.com/zxing/zxing
* iOS: https://github.com/mikebuss/MTBBarcodeScanner
* Special Thanks To: LeonDevLifeLog for his contributions towards improving this package.

+ 1
- 0
packages/qr_code_scanner-1.0.1/analysis_options.yaml View File

@@ -0,0 +1 @@
include: package:flutter_lints/flutter.yaml

+ 57
- 0
packages/qr_code_scanner-1.0.1/android/build.gradle View File

@@ -0,0 +1,57 @@
group 'net.touchcapture.qr.flutterqr'
version '1.0-SNAPSHOT'

buildscript {
ext.kotlin_version = '1.7.10'
repositories {
google()
mavenCentral()
}

dependencies {
classpath 'com.android.tools.build:gradle:7.2.2'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}

rootProject.allprojects {
repositories {
google()
mavenCentral()
}
}

apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'

android {
namespace 'net.touchcapture.qr.flutterqr'
compileSdkVersion 32

sourceSets {
main.java.srcDirs += 'src/main/kotlin'
}
defaultConfig {
// minSdkVersion is determined by Native View.
minSdkVersion 20
targetSdkVersion 32
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
multiDexEnabled true
}

compileOptions {
// Flag to enable support for the new language APIs
// coreLibraryDesugaringEnabled true
// Sets Java compatibility to Java 8
sourceCompatibility JavaVersion.VERSION_17
targetCompatibility JavaVersion.VERSION_17
}
}

dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation('com.journeyapps:zxing-android-embedded:4.3.0') { transitive = false }
implementation 'androidx.appcompat:appcompat:1.4.2'
implementation 'com.google.zxing:core:3.5.0'
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.2.0'
}

+ 3
- 0
packages/qr_code_scanner-1.0.1/android/gradle.properties View File

@@ -0,0 +1,3 @@
org.gradle.jvmargs=-Xmx1536M
android.enableJetifier=true
android.useAndroidX=true

+ 1
- 0
packages/qr_code_scanner-1.0.1/android/settings.gradle View File

@@ -0,0 +1 @@
rootProject.name = 'flutter_qr'

+ 4
- 0
packages/qr_code_scanner-1.0.1/android/src/main/AndroidManifest.xml View File

@@ -0,0 +1,4 @@
<manifest package="net.touchcapture.qr.flutterqr"
xmlns:tools="http://schemas.android.com/tools">
<uses-sdk tools:overrideLibrary="com.google.zxing.client.android" />
</manifest>

+ 45
- 0
packages/qr_code_scanner-1.0.1/android/src/main/kotlin/net/touchcapture/qr/flutterqr/CustomFramingRectBarcodeView.kt View File

@@ -0,0 +1,45 @@
package net.touchcapture.qr.flutterqr

import android.content.Context
import android.graphics.Rect
import android.util.AttributeSet
import com.journeyapps.barcodescanner.BarcodeView
import com.journeyapps.barcodescanner.Size

class CustomFramingRectBarcodeView : BarcodeView {
private var bottomOffset = BOTTOM_OFFSET_NOT_SET_VALUE

constructor(context: Context?) : super(context)
constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs)
constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(
context,
attrs,
defStyleAttr
)

override fun calculateFramingRect(container: Rect, surface: Rect): Rect {
val containerArea = Rect(container)
val intersects =
containerArea.intersect(surface) //adjusts the containerArea (code from super.calculateFramingRect)
val scanAreaRect = super.calculateFramingRect(container, surface)
if (bottomOffset != BOTTOM_OFFSET_NOT_SET_VALUE) { //if the setFramingRect function was called, then we shift the scan area by Y
val scanAreaRectWithOffset = Rect(scanAreaRect)
scanAreaRectWithOffset.bottom -= bottomOffset
scanAreaRectWithOffset.top -= bottomOffset
val belongsToContainer = scanAreaRectWithOffset.intersect(containerArea)
if (belongsToContainer) {
return scanAreaRectWithOffset
}
}
return scanAreaRect
}

fun setFramingRect(rectWidth: Int, rectHeight: Int, bottomOffset: Int) {
this.bottomOffset = bottomOffset
framingRectSize = Size(rectWidth, rectHeight)
}

companion object {
private const val BOTTOM_OFFSET_NOT_SET_VALUE = -1
}
}

+ 47
- 0
packages/qr_code_scanner-1.0.1/android/src/main/kotlin/net/touchcapture/qr/flutterqr/FlutterQrPlugin.kt View File

@@ -0,0 +1,47 @@
package net.touchcapture.qr.flutterqr

import androidx.annotation.NonNull
import io.flutter.embedding.engine.plugins.FlutterPlugin
import io.flutter.embedding.engine.plugins.activity.ActivityAware
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding

class FlutterQrPlugin : FlutterPlugin, ActivityAware {

/** Plugin registration embedding v2 */
override fun onAttachedToEngine(@NonNull flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
flutterPluginBinding.platformViewRegistry
.registerViewFactory(
VIEW_TYPE_ID,
QRViewFactory(flutterPluginBinding.binaryMessenger)
)
}

override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) {
// Leave empty
// Nullifying QrShared.activity and QrShared.binding here will cause errors if plugin is detached by another plugin
}

override fun onAttachedToActivity(activityPluginBinding: ActivityPluginBinding) {
QrShared.activity = activityPluginBinding.activity
QrShared.binding = activityPluginBinding
}

override fun onDetachedFromActivityForConfigChanges() {
QrShared.activity = null
QrShared.binding = null
}

override fun onReattachedToActivityForConfigChanges(activityPluginBinding: ActivityPluginBinding) {
QrShared.activity = activityPluginBinding.activity
QrShared.binding = activityPluginBinding
}

override fun onDetachedFromActivity() {
QrShared.activity = null
QrShared.binding = null
}

companion object {
private const val VIEW_TYPE_ID = "net.touchcapture.qr.flutterqr/qrview"
}
}

+ 379
- 0
packages/qr_code_scanner-1.0.1/android/src/main/kotlin/net/touchcapture/qr/flutterqr/QRView.kt View File

@@ -0,0 +1,379 @@
package net.touchcapture.qr.flutterqr

import android.Manifest
import android.annotation.SuppressLint
import android.content.Context
import android.content.pm.PackageManager
import android.hardware.Camera.CameraInfo
import android.os.Build
import android.view.View
import androidx.core.content.ContextCompat
import com.google.zxing.BarcodeFormat
import com.google.zxing.ResultPoint
import com.journeyapps.barcodescanner.BarcodeCallback
import com.journeyapps.barcodescanner.BarcodeResult
import com.journeyapps.barcodescanner.DefaultDecoderFactory
import io.flutter.plugin.common.BinaryMessenger
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
import io.flutter.plugin.common.PluginRegistry
import io.flutter.plugin.platform.PlatformView


class QRView(
private val context: Context,
messenger: BinaryMessenger,
private val id: Int,
private val params: HashMap<String, Any>
) : PlatformView, MethodChannel.MethodCallHandler, PluginRegistry.RequestPermissionsResultListener {

private var isTorchOn = false

private var isPaused = false

private var barcodeView: CustomFramingRectBarcodeView? = null

private val channel: MethodChannel = MethodChannel(
messenger, "net.touchcapture.qr.flutterqr/qrview_$id"
)

private var unRegisterLifecycleCallback: UnRegisterLifecycleCallback? = null

private val cameraRequestCode = QrShared.CAMERA_REQUEST_ID + this.id

init {
QrShared.binding?.addRequestPermissionsResultListener(this)

channel.setMethodCallHandler(this)

unRegisterLifecycleCallback = QrShared.activity?.registerLifecycleCallbacks(
onPause = {
if (!isPaused && hasCameraPermission) barcodeView?.pause()

},
onResume = {
if (!hasCameraPermission) checkAndRequestPermission()
else if (!isPaused && hasCameraPermission) barcodeView?.resume()
}
)
}

override fun dispose() {
unRegisterLifecycleCallback?.invoke()

QrShared.binding?.removeRequestPermissionsResultListener(this)

barcodeView?.pause()
barcodeView = null
}

override fun getView(): View = initBarCodeView()

override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) {
@Suppress("UNCHECKED_CAST")
when (call.method) {
"startScan" -> startScan(call.arguments as? List<Int>, result)

"stopScan" -> stopScan()

"flipCamera" -> flipCamera(result)

"toggleFlash" -> toggleFlash(result)

"pauseCamera" -> pauseCamera(result)

// Stopping camera is the same as pausing camera
"stopCamera" -> pauseCamera(result)

"resumeCamera" -> resumeCamera(result)

"requestPermissions" -> checkAndRequestPermission()

"getCameraInfo" -> getCameraInfo(result)

"getFlashInfo" -> getFlashInfo(result)

"getSystemFeatures" -> getSystemFeatures(result)

"changeScanArea" -> changeScanArea(
dpScanAreaWidth = requireNotNull(call.argument<Double>("scanAreaWidth")),
dpScanAreaHeight = requireNotNull(call.argument<Double>("scanAreaHeight")),
cutOutBottomOffset = requireNotNull(call.argument<Double>("cutOutBottomOffset")),
result = result,
)

"invertScan" -> setInvertScan(
isInvert = call.argument<Boolean>("isInvertScan") ?: false,
)

else -> result.notImplemented()
}
}

private fun initBarCodeView(): CustomFramingRectBarcodeView {
var barcodeView = barcodeView

if (barcodeView == null) {
barcodeView = CustomFramingRectBarcodeView(QrShared.activity).also {
this.barcodeView = it
}

barcodeView.decoderFactory = DefaultDecoderFactory(null, null, null, 2)

if (params[PARAMS_CAMERA_FACING] as Int == 1) {
barcodeView.cameraSettings?.requestedCameraId = CameraInfo.CAMERA_FACING_FRONT
}
} else if (!isPaused) {
barcodeView.resume()
}

return barcodeView
}

// region Camera Info

private fun getCameraInfo(result: MethodChannel.Result) {
val barcodeView = barcodeView ?: return barCodeViewNotSet(result)

result.success(barcodeView.cameraSettings.requestedCameraId)
}

private fun getFlashInfo(result: MethodChannel.Result) {
if (barcodeView == null) return barCodeViewNotSet(result)

result.success(isTorchOn)
}

private fun hasFlash(): Boolean {
return hasSystemFeature(PackageManager.FEATURE_CAMERA_FLASH)
}

@SuppressLint("UnsupportedChromeOsCameraSystemFeature")
private fun hasBackCamera(): Boolean {
return hasSystemFeature(PackageManager.FEATURE_CAMERA)
}

private fun hasFrontCamera(): Boolean {
return hasSystemFeature(PackageManager.FEATURE_CAMERA_FRONT)
}

private fun hasSystemFeature(feature: String): Boolean =
context.packageManager.hasSystemFeature(feature)

private fun getSystemFeatures(result: MethodChannel.Result) {
try {
result.success(
mapOf(
"hasFrontCamera" to hasFrontCamera(),
"hasBackCamera" to hasBackCamera(),
"hasFlash" to hasFlash(),
"activeCamera" to barcodeView?.cameraSettings?.requestedCameraId
)
)
} catch (e: Exception) {
result.error("", e.message, null)
}
}

// endregion

// region Camera Controls

private fun flipCamera(result: MethodChannel.Result) {
val barcodeView = barcodeView ?: return barCodeViewNotSet(result)

barcodeView.pause()

val settings = barcodeView.cameraSettings
if (settings.requestedCameraId == CameraInfo.CAMERA_FACING_FRONT) {
settings.requestedCameraId = CameraInfo.CAMERA_FACING_BACK
} else settings.requestedCameraId = CameraInfo.CAMERA_FACING_FRONT

barcodeView.resume()

result.success(settings.requestedCameraId)
}

private fun toggleFlash(result: MethodChannel.Result) {
val barcodeView = barcodeView ?: return barCodeViewNotSet(result)

if (hasFlash()) {
barcodeView.setTorch(!isTorchOn)
isTorchOn = !isTorchOn
result.success(isTorchOn)
} else {
result.error(ERROR_CODE_NOT_SET, ERROR_MESSAGE_FLASH_NOT_FOUND, null)
}
}

private fun pauseCamera(result: MethodChannel.Result) {
val barcodeView = barcodeView ?: return barCodeViewNotSet(result)

if (barcodeView.isPreviewActive) {
isPaused = true
barcodeView.pause()
}

result.success(true)
}

private fun resumeCamera(result: MethodChannel.Result) {
val barcodeView = barcodeView ?: return barCodeViewNotSet(result)

if (!barcodeView.isPreviewActive) {
isPaused = false
barcodeView.resume()
}

result.success(true)
}

private fun startScan(arguments: List<Int>?, result: MethodChannel.Result) {
checkAndRequestPermission()

val allowedBarcodeTypes = getAllowedBarcodeTypes(arguments, result)

barcodeView?.decodeContinuous(
object : BarcodeCallback {
override fun barcodeResult(result: BarcodeResult) {
if (allowedBarcodeTypes.isEmpty() || allowedBarcodeTypes.contains(result.barcodeFormat)) {
val code = mapOf(
"code" to result.text,
"type" to result.barcodeFormat.name,
"rawBytes" to result.rawBytes
)

channel.invokeMethod(CHANNEL_METHOD_ON_RECOGNIZE_QR, code)
}
}

override fun possibleResultPoints(resultPoints: List<ResultPoint>) = Unit
}
)
}

private fun stopScan() {
barcodeView?.stopDecoding()
}

private fun setInvertScan(isInvert: Boolean) {
val barcodeView = barcodeView ?: return
with(barcodeView) {
pause()
cameraSettings.isScanInverted = isInvert
resume()
}
}

private fun changeScanArea(
dpScanAreaWidth: Double,
dpScanAreaHeight: Double,
cutOutBottomOffset: Double,
result: MethodChannel.Result
) {
setScanAreaSize(dpScanAreaWidth, dpScanAreaHeight, cutOutBottomOffset)

result.success(true)
}

private fun setScanAreaSize(
dpScanAreaWidth: Double,
dpScanAreaHeight: Double,
dpCutOutBottomOffset: Double
) {
barcodeView?.setFramingRect(
dpScanAreaWidth.convertDpToPixels(),
dpScanAreaHeight.convertDpToPixels(),
dpCutOutBottomOffset.convertDpToPixels(),
)
}

// endregion

// region permissions

private val hasCameraPermission: Boolean
get() = Build.VERSION.SDK_INT < Build.VERSION_CODES.M ||
ContextCompat.checkSelfPermission(
context,
Manifest.permission.CAMERA
) == PackageManager.PERMISSION_GRANTED

override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<out String>,
grantResults: IntArray
): Boolean {
if (requestCode != cameraRequestCode) return false

val permissionGranted =
grantResults.firstOrNull() == PackageManager.PERMISSION_GRANTED

channel.invokeMethod(CHANNEL_METHOD_ON_PERMISSION_SET, permissionGranted)

return permissionGranted
}

private fun checkAndRequestPermission() {
if (hasCameraPermission) {
channel.invokeMethod(CHANNEL_METHOD_ON_PERMISSION_SET, true)
return
}

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
QrShared.activity?.requestPermissions(
arrayOf(Manifest.permission.CAMERA),
cameraRequestCode
)
}
}

// endregion

// region barcode common

private fun getAllowedBarcodeTypes(
arguments: List<Int>?,
result: MethodChannel.Result
): List<BarcodeFormat> {
return try {
arguments?.map {
BarcodeFormat.values()[it]
}.orEmpty()
} catch (e: Exception) {
result.error("", e.message, null)

emptyList()
}
}

private fun barCodeViewNotSet(result: MethodChannel.Result) {
result.error(
ERROR_CODE_NOT_SET,
ERROR_MESSAGE_NOT_SET,
null
)
}

// endregion

// region helpers

private fun Double.convertDpToPixels() =
(this * context.resources.displayMetrics.density).toInt()

// endregion

companion object {
private const val CHANNEL_METHOD_ON_PERMISSION_SET = "onPermissionSet"
private const val CHANNEL_METHOD_ON_RECOGNIZE_QR = "onRecognizeQR"

private const val PARAMS_CAMERA_FACING = "cameraFacing"

private const val ERROR_CODE_NOT_SET = "404"

private const val ERROR_MESSAGE_NOT_SET = "No barcode view found"
private const val ERROR_MESSAGE_FLASH_NOT_FOUND = "This device doesn't support flash"
}
}


+ 30
- 0
packages/qr_code_scanner-1.0.1/android/src/main/kotlin/net/touchcapture/qr/flutterqr/QRViewFactory.kt View File

@@ -0,0 +1,30 @@
package net.touchcapture.qr.flutterqr

import android.content.Context
import io.flutter.plugin.common.BinaryMessenger
import io.flutter.plugin.common.StandardMessageCodec
import io.flutter.plugin.platform.PlatformView
import io.flutter.plugin.platform.PlatformViewFactory


class QRViewFactory(
private val messenger: BinaryMessenger
) : PlatformViewFactory(StandardMessageCodec.INSTANCE) {

override fun create(
context: Context?,
viewId: Int,
args: Any?
): PlatformView {

@Suppress("UNCHECKED_CAST")
val params = args as HashMap<String, Any>

return QRView(
context = requireNotNull(context),
id = viewId,
messenger = messenger,
params = params
)
}
}

+ 41
- 0
packages/qr_code_scanner-1.0.1/android/src/main/kotlin/net/touchcapture/qr/flutterqr/QrActivityLifecycleCallbacks.kt View File

@@ -0,0 +1,41 @@
package net.touchcapture.qr.flutterqr

import android.app.Activity
import android.app.Application
import android.os.Bundle

class UnRegisterLifecycleCallback(
private val application: Application,
private val callback: Application.ActivityLifecycleCallbacks,
) {
operator fun invoke() = application.unregisterActivityLifecycleCallbacks(callback)
}

fun Activity.registerLifecycleCallbacks(
onPause: (() -> Unit)? = null,
onResume: (() -> Unit)? = null,
): UnRegisterLifecycleCallback {
val callback = object : Application.ActivityLifecycleCallbacks {
override fun onActivityPaused(p0: Activity) {
if (p0 == this@registerLifecycleCallbacks) onPause?.invoke()
}

override fun onActivityResumed(p0: Activity) {
if (p0 == this@registerLifecycleCallbacks) onResume?.invoke()
}

override fun onActivityStarted(p0: Activity) = Unit

override fun onActivityDestroyed(p0: Activity) = Unit

override fun onActivitySaveInstanceState(p0: Activity, p1: Bundle) = Unit

override fun onActivityStopped(p0: Activity) = Unit

override fun onActivityCreated(p0: Activity, p1: Bundle?) = Unit
}

application.registerActivityLifecycleCallbacks(callback)

return UnRegisterLifecycleCallback(application, callback)
}

+ 15
- 0
packages/qr_code_scanner-1.0.1/android/src/main/kotlin/net/touchcapture/qr/flutterqr/QrShared.kt View File

@@ -0,0 +1,15 @@
package net.touchcapture.qr.flutterqr

import android.annotation.SuppressLint
import android.app.Activity
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding

@SuppressLint("StaticFieldLeak")
object QrShared {
const val CAMERA_REQUEST_ID = 513469796

var activity: Activity? = null

var binding: ActivityPluginBinding? = null

}

+ 4
- 0
packages/qr_code_scanner-1.0.1/ios/Classes/FlutterQrPlugin.h View File

@@ -0,0 +1,4 @@
#import <Flutter/Flutter.h>

@interface FlutterQrPlugin : NSObject<FlutterPlugin>
@end

+ 13
- 0
packages/qr_code_scanner-1.0.1/ios/Classes/FlutterQrPlugin.m View File

@@ -0,0 +1,13 @@
#import "FlutterQrPlugin.h"

#if __has_include(<qr_code_scanner/qr_code_scanner-Swift.h>)
#import <qr_code_scanner/qr_code_scanner-Swift.h>
#else
#import "qr_code_scanner-Swift.h"
#endif

@implementation FlutterQrPlugin
+ (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar>*)registrar {
[SwiftFlutterQrPlugin registerWithRegistrar:registrar];
}
@end

+ 304
- 0
packages/qr_code_scanner-1.0.1/ios/Classes/QRView.swift View File

@@ -0,0 +1,304 @@
//
// QRView.swift
// flutter_qr
//
// Created by Julius Canute on 21/12/18.
//

import Foundation
import MTBBarcodeScanner

public class QRView:NSObject,FlutterPlatformView {
@IBOutlet var previewView: UIView!
var scanner: MTBBarcodeScanner?
var registrar: FlutterPluginRegistrar
var channel: FlutterMethodChannel
var cameraFacing: MTBCamera
// Codabar, maxicode, rss14 & rssexpanded not supported. Replaced with qr.
// UPCa uses ean13 object.
var QRCodeTypes = [
0: AVMetadataObject.ObjectType.aztec,
1: AVMetadataObject.ObjectType.qr,
2: AVMetadataObject.ObjectType.code39,
3: AVMetadataObject.ObjectType.code93,
4: AVMetadataObject.ObjectType.code128,
5: AVMetadataObject.ObjectType.dataMatrix,
6: AVMetadataObject.ObjectType.ean8,
7: AVMetadataObject.ObjectType.ean13,
8: AVMetadataObject.ObjectType.interleaved2of5,
9: AVMetadataObject.ObjectType.qr,
10: AVMetadataObject.ObjectType.pdf417,
11: AVMetadataObject.ObjectType.qr,
12: AVMetadataObject.ObjectType.qr,
13: AVMetadataObject.ObjectType.qr,
14: AVMetadataObject.ObjectType.ean13,
15: AVMetadataObject.ObjectType.upce
]
public init(withFrame frame: CGRect, withRegistrar registrar: FlutterPluginRegistrar, withId id: Int64, params: Dictionary<String, Any>){
self.registrar = registrar
previewView = UIView(frame: frame)
cameraFacing = MTBCamera.init(rawValue: UInt(Int(params["cameraFacing"] as! Double))) ?? MTBCamera.back
channel = FlutterMethodChannel(name: "net.touchcapture.qr.flutterqr/qrview_\(id)", binaryMessenger: registrar.messenger())
}
deinit {
scanner?.stopScanning()
}
public func view() -> UIView {
channel.setMethodCallHandler({
[weak self] (call: FlutterMethodCall, result: @escaping FlutterResult) -> Void in
switch(call.method){
case "setDimensions":
let arguments = call.arguments as! Dictionary<String, Double>
self?.setDimensions(result,
width: arguments["width"] ?? 0,
height: arguments["height"] ?? 0,
scanAreaWidth: arguments["scanAreaWidth"] ?? 0,
scanAreaHeight: arguments["scanAreaHeight"] ?? 0,
scanAreaOffset: arguments["scanAreaOffset"] ?? 0)
case "startScan":
self?.startScan(call.arguments as! Array<Int>, result)
case "flipCamera":
self?.flipCamera(result)
case "toggleFlash":
self?.toggleFlash(result)
case "pauseCamera":
self?.pauseCamera(result)
case "stopCamera":
self?.stopCamera(result)
case "resumeCamera":
self?.resumeCamera(result)
case "getCameraInfo":
self?.getCameraInfo(result)
case "getFlashInfo":
self?.getFlashInfo(result)
case "getSystemFeatures":
self?.getSystemFeatures(result)
default:
result(FlutterMethodNotImplemented)
return
}
})
return previewView
}
func setDimensions(_ result: @escaping FlutterResult, width: Double, height: Double, scanAreaWidth: Double, scanAreaHeight: Double, scanAreaOffset: Double) {
// Then set the size of the preview area.
previewView.frame = CGRect(x: 0, y: 0, width: width, height: height)
// Then set the size of the scan area.
let midX = self.view().bounds.midX
let midY = self.view().bounds.midY
if let sc: MTBBarcodeScanner = scanner {
// Set the size of the preview if preview is already created.
if let previewLayer = sc.previewLayer {
previewLayer.frame = self.previewView.bounds
}
} else {
// Create new preview.
scanner = MTBBarcodeScanner(previewView: previewView)
}

// Set scanArea if provided.
if (scanAreaWidth != 0 && scanAreaHeight != 0) {
scanner?.didStartScanningBlock = {
self.scanner?.scanRect = CGRect(x: Double(midX) - (scanAreaWidth / 2), y: Double(midY) - (scanAreaHeight / 2), width: scanAreaWidth, height: scanAreaHeight)

// Set offset if provided.
if (scanAreaOffset != 0) {
let reversedOffset = -scanAreaOffset
self.scanner?.scanRect = (self.scanner?.scanRect.offsetBy(dx: 0, dy: CGFloat(reversedOffset)))!

}
}
}
return result(width)
}
func startScan(_ arguments: Array<Int>, _ result: @escaping FlutterResult) {
// Check for allowed barcodes
var allowedBarcodeTypes: Array<AVMetadataObject.ObjectType> = []
arguments.forEach { arg in
allowedBarcodeTypes.append( QRCodeTypes[arg]!)
}
MTBBarcodeScanner.requestCameraPermission(success: { [weak self] permissionGranted in
guard let self = self else { return }

self.channel.invokeMethod("onPermissionSet", arguments: permissionGranted)

if permissionGranted {
do {
try self.scanner?.startScanning(with: self.cameraFacing, resultBlock: { [weak self] codes in
if let codes = codes {
for code in codes {
var typeString: String;
switch(code.type) {
case AVMetadataObject.ObjectType.aztec:
typeString = "AZTEC"
case AVMetadataObject.ObjectType.code39:
typeString = "CODE_39"
case AVMetadataObject.ObjectType.code93:
typeString = "CODE_93"
case AVMetadataObject.ObjectType.code128:
typeString = "CODE_128"
case AVMetadataObject.ObjectType.dataMatrix:
typeString = "DATA_MATRIX"
case AVMetadataObject.ObjectType.ean8:
typeString = "EAN_8"
case AVMetadataObject.ObjectType.ean13:
typeString = "EAN_13"
case AVMetadataObject.ObjectType.itf14,
AVMetadataObject.ObjectType.interleaved2of5:
typeString = "ITF"
case AVMetadataObject.ObjectType.pdf417:
typeString = "PDF_417"
case AVMetadataObject.ObjectType.qr:
typeString = "QR_CODE"
case AVMetadataObject.ObjectType.upce:
typeString = "UPC_E"
default:
return
}
let bytes = { () -> Data? in
if #available(iOS 11.0, *) {
switch (code.descriptor) {
case let qrDescriptor as CIQRCodeDescriptor:
return qrDescriptor.errorCorrectedPayload
case let aztecDescriptor as CIAztecCodeDescriptor:
return aztecDescriptor.errorCorrectedPayload
case let pdf417Descriptor as CIPDF417CodeDescriptor:
return pdf417Descriptor.errorCorrectedPayload
case let dataMatrixDescriptor as CIDataMatrixCodeDescriptor:
return dataMatrixDescriptor.errorCorrectedPayload
default:
return nil
}
} else {
return nil
}
}()
let result = { () -> [String : Any]? in
guard let stringValue = code.stringValue else {
guard let safeBytes = bytes else {
return nil
}
return ["type": typeString, "rawBytes": safeBytes]
}
guard let safeBytes = bytes else {
return ["code": stringValue, "type": typeString]
}
return ["code": stringValue, "type": typeString, "rawBytes": safeBytes]
}()
guard result != nil else { continue }
if allowedBarcodeTypes.count == 0 || allowedBarcodeTypes.contains(code.type) {
self?.channel.invokeMethod("onRecognizeQR", arguments: result)
}
}
}

})
} catch {
let scanError = FlutterError(code: "unknown-error", message: "Unable to start scanning", details: error)
result(scanError)
}
}
})
}
func stopCamera(_ result: @escaping FlutterResult) {
if let sc: MTBBarcodeScanner = self.scanner {
if sc.isScanning() {
sc.stopScanning()
}
}
}
func getCameraInfo(_ result: @escaping FlutterResult) {
result(self.cameraFacing.rawValue)
}
func flipCamera(_ result: @escaping FlutterResult) {
if let sc: MTBBarcodeScanner = self.scanner {
if sc.hasOppositeCamera() {
sc.flipCamera()
self.cameraFacing = sc.camera
}
return result(sc.camera.rawValue)
}
return result(FlutterError(code: "404", message: "No barcode scanner found", details: nil))
}
func getFlashInfo(_ result: @escaping FlutterResult) {
if let sc: MTBBarcodeScanner = self.scanner {
result(sc.torchMode.rawValue != 0)
} else {
let error = FlutterError(code: "cameraInformationError", message: "Could not get flash information", details: nil)
result(error)
}
}
func toggleFlash(_ result: @escaping FlutterResult){
if let sc: MTBBarcodeScanner = self.scanner {
if sc.hasTorch() {
sc.toggleTorch()
return result(sc.torchMode == MTBTorchMode(rawValue: 1))
}
return result(FlutterError(code: "404", message: "This device doesn\'t support flash", details: nil))
}
return result(FlutterError(code: "404", message: "No barcode scanner found", details: nil))
}
func pauseCamera(_ result: @escaping FlutterResult) {
if let sc: MTBBarcodeScanner = self.scanner {
if sc.isScanning() {
sc.freezeCapture()
}
return result(true)
}
return result(FlutterError(code: "404", message: "No barcode scanner found", details: nil))
}
func resumeCamera(_ result: @escaping FlutterResult) {
if let sc: MTBBarcodeScanner = self.scanner {
if !sc.isScanning() {
sc.unfreezeCapture()
}
return result(true)
}
return result(FlutterError(code: "404", message: "No barcode scanner found", details: nil))
}

func getSystemFeatures(_ result: @escaping FlutterResult) {
if let sc: MTBBarcodeScanner = scanner {
var hasBackCameraVar = false
var hasFrontCameraVar = false
let camera = sc.camera

if(camera == MTBCamera(rawValue: 0)){
hasBackCameraVar = true
if sc.hasOppositeCamera() {
hasFrontCameraVar = true
}
}else{
hasFrontCameraVar = true
if sc.hasOppositeCamera() {
hasBackCameraVar = true
}
}
return result([
"hasFrontCamera": hasFrontCameraVar,
"hasBackCamera": hasBackCameraVar,
"hasFlash": sc.hasTorch(),
"activeCamera": camera.rawValue
])
}
return result(FlutterError(code: "404", message: nil, details: nil))
}

}

+ 27
- 0
packages/qr_code_scanner-1.0.1/ios/Classes/QRViewFactory.swift View File

@@ -0,0 +1,27 @@
//
// QRViewFactory.swift
// flutter_qr
//
// Created by Julius Canute on 21/12/18.
//

import Foundation

public class QRViewFactory: NSObject, FlutterPlatformViewFactory {
var registrar: FlutterPluginRegistrar?
public init(withRegistrar registrar: FlutterPluginRegistrar){
super.init()
self.registrar = registrar
}
public func create(withFrame frame: CGRect, viewIdentifier viewId: Int64, arguments args: Any?) -> FlutterPlatformView {
let params = args as! Dictionary<String, Double>
return QRView(withFrame: frame, withRegistrar: registrar!,withId: viewId, params: params)
}
public func createArgsCodec() -> FlutterMessageCodec & NSObjectProtocol {
return FlutterStandardMessageCodec(readerWriter: FlutterStandardReaderWriter())
}
}

+ 22
- 0
packages/qr_code_scanner-1.0.1/ios/Classes/SwiftFlutterQrPlugin.swift View File

@@ -0,0 +1,22 @@
import Flutter
import UIKit

public class SwiftFlutterQrPlugin: NSObject, FlutterPlugin {

var factory: QRViewFactory
public init(with registrar: FlutterPluginRegistrar) {
self.factory = QRViewFactory(withRegistrar: registrar)
registrar.register(factory, withId: "net.touchcapture.qr.flutterqr/qrview")
}
public static func register(with registrar: FlutterPluginRegistrar) {
registrar.addApplicationDelegate(SwiftFlutterQrPlugin(with: registrar))
}
public func applicationDidEnterBackground(_ application: UIApplication) {
}

public func applicationWillTerminate(_ application: UIApplication) {
}

}

+ 23
- 0
packages/qr_code_scanner-1.0.1/ios/qr_code_scanner.podspec View File

@@ -0,0 +1,23 @@
#
# To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html
#

Pod::Spec.new do |s|
s.name = 'qr_code_scanner'
s.version = '0.2.0'
s.summary = 'QR Code Scanner for flutter.'
s.description = <<-DESC
A new Flutter project.
DESC
s.homepage = 'https://github.com/juliuscanute/qr_code_scanner'
s.license = { :file => '../LICENSE' }
s.author = { 'Your Company' => 'juliuscanute[*]touchcapture.net' }
s.source = { :path => '.' }
s.source_files = 'Classes/**/*'
s.public_header_files = 'Classes/**/*.h'
s.dependency 'Flutter'
s.dependency 'MTBBarcodeScanner'
s.ios.deployment_target = '8.0'
s.swift_version = '4.0'
end


+ 7
- 0
packages/qr_code_scanner-1.0.1/lib/qr_code_scanner.dart View File

@@ -0,0 +1,7 @@
export 'src/qr_code_scanner.dart';
export 'src/qr_scanner_overlay_shape.dart';
export 'src/types/barcode.dart';
export 'src/types/barcode_format.dart';
export 'src/types/camera.dart';
export 'src/types/camera_exception.dart';
export 'src/types/features.dart';

+ 22
- 0
packages/qr_code_scanner-1.0.1/lib/src/lifecycle_event_handler.dart View File

@@ -0,0 +1,22 @@
import 'package:flutter/material.dart';
import 'package:flutter/foundation.dart';

class LifecycleEventHandler extends WidgetsBindingObserver {
LifecycleEventHandler({
required this.resumeCallBack,
});

late final AsyncCallback resumeCallBack;

@override
Future<void> didChangeAppLifecycleState(AppLifecycleState state) async {
switch (state) {
case AppLifecycleState.resumed:
await resumeCallBack();
break;
case AppLifecycleState.inactive:
case AppLifecycleState.paused:
case AppLifecycleState.detached:
}
}
}

+ 373
- 0
packages/qr_code_scanner-1.0.1/lib/src/qr_code_scanner.dart View File

@@ -0,0 +1,373 @@
import 'dart:async';

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

import 'lifecycle_event_handler.dart';
import 'qr_scanner_overlay_shape.dart';
import 'types/barcode.dart';
import 'types/barcode_format.dart';
import 'types/camera.dart';
import 'types/camera_exception.dart';
import 'types/features.dart';
import 'web/flutter_qr_stub.dart'
// ignore: uri_does_not_exist
if (dart.library.html) 'web/flutter_qr_web.dart';

typedef QRViewCreatedCallback = void Function(QRViewController);
typedef PermissionSetCallback = void Function(QRViewController, bool);

/// The [QRView] is the view where the camera
/// and the barcode scanner gets displayed.
class QRView extends StatefulWidget {
const QRView({
required Key key,
required this.onQRViewCreated,
this.overlay,
this.overlayMargin = EdgeInsets.zero,
this.cameraFacing = CameraFacing.back,
this.onPermissionSet,
this.formatsAllowed = const <BarcodeFormat>[],
}) : super(key: key);

/// [onQRViewCreated] gets called when the view is created
final QRViewCreatedCallback onQRViewCreated;

/// Use [overlay] to provide an overlay for the view.
/// This can be used to create a certain scan area.
final QrScannerOverlayShape? overlay;

/// Use [overlayMargin] to provide a margin to [overlay]
final EdgeInsetsGeometry overlayMargin;

/// Set which camera to use on startup.
///
/// [cameraFacing] can either be CameraFacing.front or CameraFacing.back.
/// Defaults to CameraFacing.back
final CameraFacing cameraFacing;

/// Calls the provided [onPermissionSet] callback when the permission is set.
final PermissionSetCallback? onPermissionSet;

/// Use [formatsAllowed] to specify which formats needs to be scanned.
final List<BarcodeFormat> formatsAllowed;

@override
State<StatefulWidget> createState() => _QRViewState();
}

class _QRViewState extends State<QRView> {
late MethodChannel _channel;
late LifecycleEventHandler _observer;

@override
void initState() {
super.initState();
_observer = LifecycleEventHandler(resumeCallBack: updateDimensions);
WidgetsBinding.instance.addObserver(_observer);
}

@override
Widget build(BuildContext context) {
return NotificationListener(
onNotification: onNotification,
child: SizeChangedLayoutNotifier(
child: (widget.overlay != null)
? _getPlatformQrViewWithOverlay()
: _getPlatformQrView(),
),
);
}

@override
void dispose() {
super.dispose();
WidgetsBinding.instance.removeObserver(_observer);
}

Future<void> updateDimensions() async {
await QRViewController.updateDimensions(
widget.key as GlobalKey<State<StatefulWidget>>, _channel,
overlay: widget.overlay);
}

bool onNotification(notification) {
updateDimensions();
return false;
}

Widget _getPlatformQrViewWithOverlay() {
return Stack(
children: [
_getPlatformQrView(),
Padding(
padding: widget.overlayMargin,
child: Container(
decoration: ShapeDecoration(
shape: widget.overlay!,
),
),
)
],
);
}

Widget _getPlatformQrView() {
Widget _platformQrView;
if (kIsWeb) {
_platformQrView = createWebQrView(
onPlatformViewCreated: widget.onQRViewCreated,
onPermissionSet: widget.onPermissionSet,
cameraFacing: widget.cameraFacing,
);
} else {
switch (defaultTargetPlatform) {
case TargetPlatform.android:
_platformQrView = AndroidView(
viewType: 'net.touchcapture.qr.flutterqr/qrview',
onPlatformViewCreated: _onPlatformViewCreated,
creationParams:
_QrCameraSettings(cameraFacing: widget.cameraFacing).toMap(),
creationParamsCodec: const StandardMessageCodec(),
);
break;
case TargetPlatform.iOS:
_platformQrView = UiKitView(
viewType: 'net.touchcapture.qr.flutterqr/qrview',
onPlatformViewCreated: _onPlatformViewCreated,
creationParams:
_QrCameraSettings(cameraFacing: widget.cameraFacing).toMap(),
creationParamsCodec: const StandardMessageCodec(),
);
break;
default:
throw UnsupportedError(
"Trying to use the default qrview implementation for $defaultTargetPlatform but there isn't a default one");
}
}
return _platformQrView;
}

void _onPlatformViewCreated(int id) {
_channel = MethodChannel('net.touchcapture.qr.flutterqr/qrview_$id');

// Start scan after creation of the view
final controller = QRViewController._(
_channel,
widget.key as GlobalKey<State<StatefulWidget>>?,
widget.onPermissionSet,
widget.cameraFacing)
.._startScan(widget.key as GlobalKey<State<StatefulWidget>>,
widget.overlay, widget.formatsAllowed);

// Initialize the controller for controlling the QRView
widget.onQRViewCreated(controller);
}
}

class _QrCameraSettings {
_QrCameraSettings({
this.cameraFacing = CameraFacing.unknown,
});

final CameraFacing cameraFacing;

Map<String, dynamic> toMap() {
return <String, dynamic>{
'cameraFacing': cameraFacing.index,
};
}
}

class QRViewController {
QRViewController._(MethodChannel channel, GlobalKey? qrKey,
PermissionSetCallback? onPermissionSet, CameraFacing cameraFacing)
: _channel = channel,
_cameraFacing = cameraFacing {
_channel.setMethodCallHandler((call) async {
switch (call.method) {
case 'onRecognizeQR':
if (call.arguments != null) {
final args = call.arguments as Map;
final code = args['code'] as String?;
final rawType = args['type'] as String;
// Raw bytes are only supported by Android.
final rawBytes = args['rawBytes'] as List<int>?;
final format = BarcodeTypesExtension.fromString(rawType);
if (format != BarcodeFormat.unknown) {
final barcode = Barcode(code, format, rawBytes);
_scanUpdateController.sink.add(barcode);
} else {
throw Exception('Unexpected barcode type $rawType');
}
}
break;
case 'onPermissionSet':
if (call.arguments != null && call.arguments is bool) {
_hasPermissions = call.arguments;
if (onPermissionSet != null) {
onPermissionSet(this, _hasPermissions);
}
}
break;
}
});
}

final MethodChannel _channel;
final CameraFacing _cameraFacing;
final StreamController<Barcode> _scanUpdateController =
StreamController<Barcode>();

Stream<Barcode> get scannedDataStream => _scanUpdateController.stream;

bool _hasPermissions = false;
bool get hasPermissions => _hasPermissions;

/// Starts the barcode scanner
Future<void> _startScan(GlobalKey key, QrScannerOverlayShape? overlay,
List<BarcodeFormat>? barcodeFormats) async {
// We need to update the dimension before the scan is started.
try {
await QRViewController.updateDimensions(key, _channel, overlay: overlay);
return await _channel.invokeMethod(
'startScan', barcodeFormats?.map((e) => e.asInt()).toList() ?? []);
} on PlatformException catch (e) {
throw CameraException(e.code, e.message);
}
}

/// Gets information about which camera is active.
Future<CameraFacing> getCameraInfo() async {
try {
var cameraFacing = await _channel.invokeMethod('getCameraInfo') as int;
if (cameraFacing == -1) return _cameraFacing;
return CameraFacing
.values[await _channel.invokeMethod('getCameraInfo') as int];
} on PlatformException catch (e) {
throw CameraException(e.code, e.message);
}
}

/// Flips the camera between available modes
Future<CameraFacing> flipCamera() async {
try {
return CameraFacing
.values[await _channel.invokeMethod('flipCamera') as int];
} on PlatformException catch (e) {
throw CameraException(e.code, e.message);
}
}

/// Get flashlight status
Future<bool?> getFlashStatus() async {
try {
return await _channel.invokeMethod('getFlashInfo');
} on PlatformException catch (e) {
throw CameraException(e.code, e.message);
}
}

/// Toggles the flashlight between available modes
Future<void> toggleFlash() async {
try {
await _channel.invokeMethod('toggleFlash') as bool?;
} on PlatformException catch (e) {
throw CameraException(e.code, e.message);
}
}

/// Pauses the camera and barcode scanning
Future<void> pauseCamera() async {
try {
await _channel.invokeMethod('pauseCamera');
} on PlatformException catch (e) {
throw CameraException(e.code, e.message);
}
}

/// Stops barcode scanning and the camera
Future<void> stopCamera() async {
try {
await _channel.invokeMethod('stopCamera');
} on PlatformException catch (e) {
throw CameraException(e.code, e.message);
}
}

/// Resumes barcode scanning
Future<void> resumeCamera() async {
try {
await _channel.invokeMethod('resumeCamera');
} on PlatformException catch (e) {
throw CameraException(e.code, e.message);
}
}

/// Returns which features are available on device.
Future<SystemFeatures> getSystemFeatures() async {
try {
var features =
await _channel.invokeMapMethod<String, dynamic>('getSystemFeatures');
if (features != null) {
return SystemFeatures.fromJson(features);
}
throw CameraException('Error', 'Could not get system features');
} on PlatformException catch (e) {
throw CameraException(e.code, e.message);
}
}

/// Stops the camera and disposes the barcode stream.
void dispose() {
if (defaultTargetPlatform == TargetPlatform.iOS) stopCamera();
_scanUpdateController.close();
}

/// Updates the view dimensions for iOS.
static Future<bool> updateDimensions(GlobalKey key, MethodChannel channel,
{QrScannerOverlayShape? overlay}) async {
if (defaultTargetPlatform == TargetPlatform.iOS) {
// Add small delay to ensure the render box is loaded
await Future.delayed(const Duration(milliseconds: 300));
if (key.currentContext == null) return false;
final renderBox = key.currentContext!.findRenderObject() as RenderBox;
try {
await channel.invokeMethod('setDimensions', {
'width': renderBox.size.width,
'height': renderBox.size.height,
'scanAreaWidth': overlay?.cutOutWidth ?? 0,
'scanAreaHeight': overlay?.cutOutHeight ?? 0,
'scanAreaOffset': overlay?.cutOutBottomOffset ?? 0
});
return true;
} on PlatformException catch (e) {
throw CameraException(e.code, e.message);
}
} else if (defaultTargetPlatform == TargetPlatform.android) {
if (overlay == null) {
return false;
}
await channel.invokeMethod('changeScanArea', {
'scanAreaWidth': overlay.cutOutWidth,
'scanAreaHeight': overlay.cutOutHeight,
'cutOutBottomOffset': overlay.cutOutBottomOffset
});
return true;
}
return false;
}

//Starts/Stops invert scanning.
Future<void> scanInvert(bool isScanInvert) async {
if (defaultTargetPlatform == TargetPlatform.android) {
try {
await _channel
.invokeMethod('invertScan', {"isInvertScan": isScanInvert});
} on PlatformException catch (e) {
throw CameraException(e.code, e.message);
}
}
}
}

+ 183
- 0
packages/qr_code_scanner-1.0.1/lib/src/qr_scanner_overlay_shape.dart View File

@@ -0,0 +1,183 @@
import 'dart:math';

import 'package:flutter/material.dart';

class QrScannerOverlayShape extends ShapeBorder {
QrScannerOverlayShape({
this.borderColor = Colors.red,
this.borderWidth = 3.0,
this.overlayColor = const Color.fromRGBO(0, 0, 0, 80),
this.borderRadius = 0,
this.borderLength = 40,
double? cutOutSize,
double? cutOutWidth,
double? cutOutHeight,
this.cutOutBottomOffset = 0,
}) : cutOutWidth = cutOutWidth ?? cutOutSize ?? 250,
cutOutHeight = cutOutHeight ?? cutOutSize ?? 250 {
assert(
borderLength <=
min(this.cutOutWidth, this.cutOutHeight) / 2 + borderWidth * 2,
"Border can't be larger than ${min(this.cutOutWidth, this.cutOutHeight) / 2 + borderWidth * 2}",
);
assert(
(cutOutWidth == null && cutOutHeight == null) ||
(cutOutSize == null && cutOutWidth != null && cutOutHeight != null),
'Use only cutOutWidth and cutOutHeight or only cutOutSize');
}

final Color borderColor;
final double borderWidth;
final Color overlayColor;
final double borderRadius;
final double borderLength;
final double cutOutWidth;
final double cutOutHeight;
final double cutOutBottomOffset;

@override
EdgeInsetsGeometry get dimensions => const EdgeInsets.all(10);

@override
Path getInnerPath(Rect rect, {TextDirection? textDirection}) {
return Path()
..fillType = PathFillType.evenOdd
..addPath(getOuterPath(rect), Offset.zero);
}

@override
Path getOuterPath(Rect rect, {TextDirection? textDirection}) {
Path _getLeftTopPath(Rect rect) {
return Path()
..moveTo(rect.left, rect.bottom)
..lineTo(rect.left, rect.top)
..lineTo(rect.right, rect.top);
}

return _getLeftTopPath(rect)
..lineTo(
rect.right,
rect.bottom,
)
..lineTo(
rect.left,
rect.bottom,
)
..lineTo(
rect.left,
rect.top,
);
}

@override
void paint(Canvas canvas, Rect rect, {TextDirection? textDirection}) {
final width = rect.width;
final borderWidthSize = width / 2;
final height = rect.height;
final borderOffset = borderWidth / 2;
final _borderLength =
borderLength > min(cutOutHeight, cutOutHeight) / 2 + borderWidth * 2
? borderWidthSize / 2
: borderLength;
final _cutOutWidth =
cutOutWidth < width ? cutOutWidth : width - borderOffset;
final _cutOutHeight =
cutOutHeight < height ? cutOutHeight : height - borderOffset;

final backgroundPaint = Paint()
..color = overlayColor
..style = PaintingStyle.fill;

final borderPaint = Paint()
..color = borderColor
..style = PaintingStyle.stroke
..strokeWidth = borderWidth;

final boxPaint = Paint()
..color = borderColor
..style = PaintingStyle.fill
..blendMode = BlendMode.dstOut;

final cutOutRect = Rect.fromLTWH(
rect.left + width / 2 - _cutOutWidth / 2 + borderOffset,
-cutOutBottomOffset +
rect.top +
height / 2 -
_cutOutHeight / 2 +
borderOffset,
_cutOutWidth - borderOffset * 2,
_cutOutHeight - borderOffset * 2,
);

canvas
..saveLayer(
rect,
backgroundPaint,
)
..drawRect(
rect,
backgroundPaint,
)
// Draw top right corner
..drawRRect(
RRect.fromLTRBAndCorners(
cutOutRect.right - _borderLength,
cutOutRect.top,
cutOutRect.right,
cutOutRect.top + _borderLength,
topRight: Radius.circular(borderRadius),
),
borderPaint,
)
// Draw top left corner
..drawRRect(
RRect.fromLTRBAndCorners(
cutOutRect.left,
cutOutRect.top,
cutOutRect.left + _borderLength,
cutOutRect.top + _borderLength,
topLeft: Radius.circular(borderRadius),
),
borderPaint,
)
// Draw bottom right corner
..drawRRect(
RRect.fromLTRBAndCorners(
cutOutRect.right - _borderLength,
cutOutRect.bottom - _borderLength,
cutOutRect.right,
cutOutRect.bottom,
bottomRight: Radius.circular(borderRadius),
),
borderPaint,
)
// Draw bottom left corner
..drawRRect(
RRect.fromLTRBAndCorners(
cutOutRect.left,
cutOutRect.bottom - _borderLength,
cutOutRect.left + _borderLength,
cutOutRect.bottom,
bottomLeft: Radius.circular(borderRadius),
),
borderPaint,
)
..drawRRect(
RRect.fromRectAndRadius(
cutOutRect,
Radius.circular(borderRadius),
),
boxPaint,
)
..restore();
}

@override
ShapeBorder scale(double t) {
return QrScannerOverlayShape(
borderColor: borderColor,
borderWidth: borderWidth,
overlayColor: overlayColor,
);
}
}

+ 16
- 0
packages/qr_code_scanner-1.0.1/lib/src/types/barcode.dart View File

@@ -0,0 +1,16 @@
import 'barcode_format.dart';

/// The [Barcode] object holds information about the barcode or qr code.
///
/// [code] is the string-content of the barcode.
/// [format] displays which type the code is.
/// Only for Android and iOS, [rawBytes] gives a list of bytes of the result.
class Barcode {
Barcode(this.code, this.format, this.rawBytes);

final String? code;
final BarcodeFormat format;

/// Raw bytes are only supported by Android and iOS.
final List<int>? rawBytes;
}

+ 148
- 0
packages/qr_code_scanner-1.0.1/lib/src/types/barcode_format.dart View File

@@ -0,0 +1,148 @@
enum BarcodeFormat {
/// Aztec 2D barcode format.
aztec,

/// CODABAR 1D format.
/// Not supported in iOS
codabar,

/// Code 39 1D format.
code39,

/// Code 93 1D format.
code93,

/// Code 128 1D format.
code128,

/// Data Matrix 2D barcode format.
dataMatrix,

/// EAN-8 1D format.
ean8,

/// EAN-13 1D format.
ean13,

/// ITF (Interleaved Two of Five) 1D format.
itf,

/// MaxiCode 2D barcode format.
/// Not supported in iOS.
maxicode,

/// PDF417 format.
pdf417,

/// QR Code 2D barcode format.
qrcode,

/// RSS 14
/// Not supported in iOS.
rss14,

/// RSS EXPANDED
/// Not supported in iOS.
rssExpanded,

/// UPC-A 1D format.
/// Same as ean-13 on iOS.
upcA,

/// UPC-E 1D format.
upcE,

/// UPC/EAN extension format. Not a stand-alone format.
upcEanExtension,

/// Unknown
unknown
}

extension BarcodeTypesExtension on BarcodeFormat {
int asInt() {
return index;
}

static BarcodeFormat fromString(String format) {
switch (format) {
case 'AZTEC':
return BarcodeFormat.aztec;
case 'CODABAR':
return BarcodeFormat.codabar;
case 'CODE_39':
return BarcodeFormat.code39;
case 'CODE_93':
return BarcodeFormat.code93;
case 'CODE_128':
return BarcodeFormat.code128;
case 'DATA_MATRIX':
return BarcodeFormat.dataMatrix;
case 'EAN_8':
return BarcodeFormat.ean8;
case 'EAN_13':
return BarcodeFormat.ean13;
case 'ITF':
return BarcodeFormat.itf;
case 'MAXICODE':
return BarcodeFormat.maxicode;
case 'PDF_417':
return BarcodeFormat.pdf417;
case 'QR_CODE':
return BarcodeFormat.qrcode;
case 'RSS14':
return BarcodeFormat.rss14;
case 'RSS_EXPANDED':
return BarcodeFormat.rssExpanded;
case 'UPC_A':
return BarcodeFormat.upcA;
case 'UPC_E':
return BarcodeFormat.upcE;
case 'UPC_EAN_EXTENSION':
return BarcodeFormat.upcEanExtension;
default:
return BarcodeFormat.unknown;
}
}

String get formatName {
switch (this) {
case BarcodeFormat.aztec:
return 'AZTEC';
case BarcodeFormat.codabar:
return 'CODABAR';
case BarcodeFormat.code39:
return 'CODE_39';
case BarcodeFormat.code93:
return 'CODE_93';
case BarcodeFormat.code128:
return 'CODE_128';
case BarcodeFormat.dataMatrix:
return 'DATA_MATRIX';
case BarcodeFormat.ean8:
return 'EAN_8';
case BarcodeFormat.ean13:
return 'EAN_13';
case BarcodeFormat.itf:
return 'ITF';
case BarcodeFormat.maxicode:
return 'MAXICODE';
case BarcodeFormat.pdf417:
return 'PDF_417';
case BarcodeFormat.qrcode:
return 'QR_CODE';
case BarcodeFormat.rss14:
return 'RSS14';
case BarcodeFormat.rssExpanded:
return 'RSS_EXPANDED';
case BarcodeFormat.upcA:
return 'UPC_A';
case BarcodeFormat.upcE:
return 'UPC_E';
case BarcodeFormat.upcEanExtension:
return 'UPC_EAN_EXTENSION';
default:
return 'UNKNOWN';
}
}
}

+ 10
- 0
packages/qr_code_scanner-1.0.1/lib/src/types/camera.dart View File

@@ -0,0 +1,10 @@
enum CameraFacing {
/// Shows back facing camera.
back,

/// Shows front facing camera.
front,

/// Unknown camera
unknown
}

+ 14
- 0
packages/qr_code_scanner-1.0.1/lib/src/types/camera_exception.dart View File

@@ -0,0 +1,14 @@
/// This is thrown when the plugin reports an error.
class CameraException implements Exception {
/// Creates a new camera exception with the given error code and description.
CameraException(this.code, this.description);

/// Error code.
String code;

/// Textual description of the error.
String? description;

@override
String toString() => 'CameraException($code, $description)';
}

+ 13
- 0
packages/qr_code_scanner-1.0.1/lib/src/types/features.dart View File

@@ -0,0 +1,13 @@
class SystemFeatures {
SystemFeatures(this.hasFlash, this.hasBackCamera, this.hasFrontCamera);

factory SystemFeatures.fromJson(Map<String, dynamic> features) =>
SystemFeatures(
features['hasFlash'] ?? false,
features['hasBackCamera'] ?? false,
features['hasFrontCamera'] ?? false);

final bool hasFlash;
final bool hasFrontCamera;
final bool hasBackCamera;
}

+ 6
- 0
packages/qr_code_scanner-1.0.1/lib/src/web/flutter_qr_stub.dart View File

@@ -0,0 +1,6 @@
import 'package:flutter/material.dart';
import 'package:qr_code_scanner/src/types/camera.dart';

Widget createWebQrView(
{onPlatformViewCreated, onPermissionSet, CameraFacing? cameraFacing}) =>
const SizedBox();

+ 328
- 0
packages/qr_code_scanner-1.0.1/lib/src/web/flutter_qr_web.dart View File

@@ -0,0 +1,328 @@
// ignore_for_file: avoid_web_libraries_in_flutter

import 'dart:async';
import 'dart:core';
import 'dart:html' as html;
import 'dart:js_util';
import 'dart:ui' as ui;

import 'package:flutter/material.dart';

import '../../qr_code_scanner.dart';
import 'jsqr.dart';
import 'media.dart';

/// Even though it has been highly modified, the origial implementation has been
/// adopted from https://github.com:treeder/jsqr_flutter
///
/// Copyright 2020 @treeder
/// Copyright 2021 The one with the braid

class WebQrView extends StatefulWidget {
final QRViewCreatedCallback onPlatformViewCreated;
final PermissionSetCallback? onPermissionSet;
final CameraFacing? cameraFacing;

const WebQrView(
{Key? key,
required this.onPlatformViewCreated,
this.onPermissionSet,
this.cameraFacing = CameraFacing.front})
: super(key: key);

@override
_WebQrViewState createState() => _WebQrViewState();

static html.DivElement vidDiv =
html.DivElement(); // need a global for the registerViewFactory

static Future<bool> cameraAvailable() async {
final sources =
await html.window.navigator.mediaDevices!.enumerateDevices();
// List<String> vidIds = [];
var hasCam = false;
for (final e in sources) {
if (e.kind == 'videoinput') {
// vidIds.add(e['deviceId']);
hasCam = true;
}
}
return hasCam;
}
}

class _WebQrViewState extends State<WebQrView> {
html.MediaStream? _localStream;
// html.CanvasElement canvas;
// html.CanvasRenderingContext2D ctx;
bool _currentlyProcessing = false;

QRViewControllerWeb? _controller;

late Size _size = const Size(0, 0);
Timer? timer;
String? code;
String? _errorMsg;
html.VideoElement video = html.VideoElement();
String viewID = 'QRVIEW-' + DateTime.now().millisecondsSinceEpoch.toString();

final StreamController<Barcode> _scanUpdateController =
StreamController<Barcode>();
late CameraFacing facing;

Timer? _frameIntervall;

@override
void initState() {
super.initState();

facing = widget.cameraFacing ?? CameraFacing.front;

// video = html.VideoElement();
WebQrView.vidDiv.children = [video];
// ignore: UNDEFINED_PREFIXED_NAME
ui.platformViewRegistry
.registerViewFactory(viewID, (int id) => WebQrView.vidDiv);
// giving JavaScipt some time to process the DOM changes
Timer(const Duration(milliseconds: 500), () {
start();
});
}

Future start() async {
await _makeCall();
_frameIntervall?.cancel();
_frameIntervall =
Timer.periodic(const Duration(milliseconds: 200), (timer) {
_captureFrame2();
});
}

void cancel() {
if (timer != null) {
timer!.cancel();
timer = null;
}
if (_currentlyProcessing) {
_stopStream();
}
}

@override
void dispose() {
cancel();
super.dispose();
}

// Platform messages are asynchronous, so we initialize in an async method.
Future<void> _makeCall() async {
if (_localStream != null) {
return;
}

try {
var constraints = UserMediaOptions(
video: VideoOptions(
facingMode: (facing == CameraFacing.front ? 'user' : 'environment'),
));
// dart style, not working properly:
// var stream =
// await html.window.navigator.mediaDevices.getUserMedia(constraints);
// straight JS:
if (_controller == null) {
_controller = QRViewControllerWeb(this);
widget.onPlatformViewCreated(_controller!);
}
var stream = await promiseToFuture(getUserMedia(constraints));
widget.onPermissionSet?.call(_controller!, true);
_localStream = stream;
video.srcObject = _localStream;
video.setAttribute('playsinline',
'true'); // required to tell iOS safari we don't want fullscreen
await video.play();
} catch (e) {
cancel();
if (e.toString().contains("NotAllowedError")) {
widget.onPermissionSet?.call(_controller!, false);
}
setState(() {
_errorMsg = e.toString();
});
return;
}
if (!mounted) return;

setState(() {
_currentlyProcessing = true;
});
}

Future<void> _stopStream() async {
try {
// await _localStream.dispose();
_localStream!.getTracks().forEach((track) {
if (track.readyState == 'live') {
track.stop();
}
});
// video.stop();
video.srcObject = null;
_localStream = null;
// _localRenderer.srcObject = null;
// ignore: empty_catches
} catch (e) {}
}

Future<dynamic> _captureFrame2() async {
if (_localStream == null) {
return null;
}
final canvas =
html.CanvasElement(width: video.videoWidth, height: video.videoHeight);
final ctx = canvas.context2D;
// canvas.width = video.videoWidth;
// canvas.height = video.videoHeight;
ctx.drawImage(video, 0, 0);
final imgData = ctx.getImageData(0, 0, canvas.width!, canvas.height!);

final size =
Size(canvas.width?.toDouble() ?? 0, canvas.height?.toDouble() ?? 0);
if (size != _size) {
setState(() {
_setCanvasSize(size);
});
}

final code = jsQR(imgData.data, canvas.width, canvas.height);
// ignore: unnecessary_null_comparison
if (code != null) {
_scanUpdateController
.add(Barcode(code.data, BarcodeFormat.qrcode, code.data.codeUnits));
}
}

@override
Widget build(BuildContext context) {
if (_errorMsg != null) {
return Center(child: Text(_errorMsg!));
}
if (_localStream == null) {
return const Center(child: CircularProgressIndicator());
}
return LayoutBuilder(
builder: (context, constraints) {
var zoom = 1.0;

if (_size.height != 0) zoom = constraints.maxHeight / _size.height;

if (_size.width != 0) {
final horizontalZoom = constraints.maxWidth / _size.width;
if (horizontalZoom > zoom) {
zoom = horizontalZoom;
}
}

return SizedBox(
width: constraints.maxWidth,
height: constraints.maxHeight,
child: Center(
child: SizedBox.fromSize(
size: _size,
child: Transform.scale(
alignment: Alignment.center,
scale: zoom,
child: HtmlElementView(viewType: viewID),
),
),
),
);
},
);
}

void _setCanvasSize(ui.Size size) {
setState(() {
_size = size;
});
}
}

class QRViewControllerWeb implements QRViewController {
final _WebQrViewState _state;

QRViewControllerWeb(this._state);
@override
void dispose() => _state.cancel();

@override
Future<CameraFacing> flipCamera() async {
// TODO: improve error handling
_state.facing = _state.facing == CameraFacing.front
? CameraFacing.back
: CameraFacing.front;
await _state.start();
return _state.facing;
}

@override
Future<CameraFacing> getCameraInfo() async {
return _state.facing;
}

@override
Future<bool?> getFlashStatus() async {
// TODO: flash is simply not supported by JavaScipt. To avoid issuing applications, we always return it to be off.
return false;
}

@override
Future<SystemFeatures> getSystemFeatures() {
// TODO: implement getSystemFeatures
throw UnimplementedError();
}

@override
// TODO: implement hasPermissions. Blocking: WebQrView.cameraAvailable() returns a Future<bool> whereas a bool is required
bool get hasPermissions => throw UnimplementedError();

@override
Future<void> pauseCamera() {
// TODO: implement pauseCamera
throw UnimplementedError();
}

@override
Future<void> resumeCamera() {
// TODO: implement resumeCamera
throw UnimplementedError();
}

@override
Stream<Barcode> get scannedDataStream => _state._scanUpdateController.stream;

@override
Future<void> stopCamera() {
// TODO: implement stopCamera
throw UnimplementedError();
}

@override
Future<void> toggleFlash() async {
// TODO: flash is simply not supported by JavaScipt
return;
}

@override
Future<void> scanInvert(bool isScanInvert) {
// TODO: implement scanInvert
throw UnimplementedError();
}
}

Widget createWebQrView(
{onPlatformViewCreated, onPermissionSet, CameraFacing? cameraFacing}) =>
WebQrView(
onPlatformViewCreated: onPlatformViewCreated,
onPermissionSet: onPermissionSet,
cameraFacing: cameraFacing,
);

+ 12
- 0
packages/qr_code_scanner-1.0.1/lib/src/web/jsqr.dart View File

@@ -0,0 +1,12 @@
@JS()
library jsqr;

import 'package:js/js.dart';

@JS('jsQR')
external Code jsQR(var data, int? width, int? height);

@JS()
class Code {
external String get data;
}

+ 36
- 0
packages/qr_code_scanner-1.0.1/lib/src/web/media.dart View File

@@ -0,0 +1,36 @@
// This is here because dart doesn't seem to support this properly
// https://stackoverflow.com/questions/61161135/adding-support-for-navigator-mediadevices-getusermedia-to-dart

@JS('navigator.mediaDevices')
library media_devices;

import 'package:js/js.dart';

@JS('getUserMedia')
external Future<dynamic> getUserMedia(UserMediaOptions constraints);

@JS()
@anonymous
class UserMediaOptions {
external VideoOptions get video;

external factory UserMediaOptions({VideoOptions? video});
}

@JS()
@anonymous
class VideoOptions {
external String get facingMode;
// external DeviceIdOptions get deviceId;

external factory VideoOptions(
{String? facingMode, DeviceIdOptions? deviceId});
}

@JS()
@anonymous
class DeviceIdOptions {
external String get exact;

external factory DeviceIdOptions({String? exact});
}

+ 31
- 0
packages/qr_code_scanner-1.0.1/pubspec.yaml View File

@@ -0,0 +1,31 @@
name: qr_code_scanner
description: QR code scanner that can be embedded inside flutter. It uses zxing in Android and MTBBarcode scanner in iOS.
version: 1.0.1
homepage: https://juliuscanute.com
repository: https://github.com/juliuscanute/qr_code_scanner

environment:
sdk: '>=2.17.0 <3.0.0'
flutter: ">=1.12.0"

dependencies:
js: ^0.6.3
flutter:
sdk: flutter
flutter_web_plugins:
sdk: flutter

dev_dependencies:
flutter_lints: ^1.0.4

flutter:
plugin:
platforms:
android:
package: net.touchcapture.qr.flutterqr
pluginClass: FlutterQrPlugin
ios:
pluginClass: FlutterQrPlugin
# web:
# pluginClass: FlutterQrPlugin
# fileName: flutter_qr_web.dart

+ 3
- 4
pubspec.lock View File

@@ -963,10 +963,9 @@ packages:
qr_code_scanner:
dependency: "direct main"
description:
name: qr_code_scanner
sha256: f23b68d893505a424f0bd2e324ebea71ed88465d572d26bb8d2e78a4749591fd
url: "https://pub.dev"
source: hosted
path: "packages/qr_code_scanner-1.0.1"
relative: true
source: path
version: "1.0.1"
quiver:
dependency: transitive

+ 3
- 2
pubspec.yaml View File

@@ -2,7 +2,7 @@ name: farm_tpf
description: A new Flutter project.

publish_to: 'none'
version: 1.1.18+38
version: 1.1.20+40

environment:
sdk: ">=3.0.0 <4.0.0"
@@ -58,7 +58,8 @@ dependencies:
flutter_svg: ^2.0.10+1
# google_fonts: ^6.1.0
# ffi: ^1.0.0
qr_code_scanner: ^1.0.1
qr_code_scanner:
path: ./packages/qr_code_scanner-1.0.1
loading_indicator: ^3.0.1
hive: ^2.1.0
flutter_screenutil: ^5.9.3

Loading…
Cancel
Save