Skip to content

Commit

Permalink
Merge pull request #1005 from navaronbracke/5_0_0-beta-3
Browse files Browse the repository at this point in the history
feat: 5.0.0-beta 3
  • Loading branch information
navaronbracke authored Apr 16, 2024
2 parents 269bc95 + 5c1e8ce commit 72b0335
Show file tree
Hide file tree
Showing 22 changed files with 296 additions and 351 deletions.
14 changes: 12 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,18 @@
## 5.0.0-beta.2
## 5.0.0-beta.3

**BREAKING CHANGES:**

* Flutter 3.16.0 is now required.
* Flutter 3.19.0 is now required.
* [iOS] iOS 12.0 is now the minimum supported iOS version.
* [iOS] Adds a Privacy Manifest.

Bugs fixed:
* Fixed an issue where the camera preview and barcode scanner did not work the second time on web.

Improvements:
* [web] Migrates to extension types. (thanks @koji-1009 !)

## 5.0.0-beta.2

Bugs fixed:
* Fixed an issue where the scan window was not updated when its size was changed. (thanks @navaronbracke !)
Expand Down
4 changes: 0 additions & 4 deletions example/android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,3 @@ android {
flutter {
source '../..'
}

dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
}
13 changes: 0 additions & 13 deletions example/android/build.gradle
Original file line number Diff line number Diff line change
@@ -1,16 +1,3 @@
buildscript {
ext.kotlin_version = '1.9.22'
repositories {
google()
mavenCentral()
}

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

allprojects {
repositories {
google()
Expand Down
19 changes: 14 additions & 5 deletions example/android/settings.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,21 @@ pluginManagement {
def flutterSdkPath = properties.getProperty("flutter.sdk")
assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
return flutterSdkPath
}
settings.ext.flutterSdkPath = flutterSdkPath()
}()

includeBuild("$flutterSdkPath/packages/flutter_tools/gradle")

includeBuild("${settings.ext.flutterSdkPath}/packages/flutter_tools/gradle")
repositories {
google()
mavenCentral()
gradlePluginPortal()
}
}

include ":app"
plugins {
id "dev.flutter.flutter-plugin-loader" version "1.0.0"
id "com.android.application" version "8.2.2" apply false
id "org.jetbrains.kotlin.android" version "1.9.22" apply false
}

apply from: "${settings.ext.flutterSdkPath}/packages/flutter_tools/gradle/app_plugin_loader.gradle"
include ":app"
2 changes: 1 addition & 1 deletion example/ios/Flutter/AppFrameworkInfo.plist
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,6 @@
<key>CFBundleVersion</key>
<string>1.0</string>
<key>MinimumOSVersion</key>
<string>11.0</string>
<string>12.0</string>
</dict>
</plist>
4 changes: 2 additions & 2 deletions example/ios/Podfile
Original file line number Diff line number Diff line change
@@ -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'
Expand Down Expand Up @@ -41,7 +41,7 @@ post_install do |installer|
installer.pods_project.targets.each do |target|
flutter_additional_ios_build_settings(target)
target.build_configurations.each do |config|
config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '11.0'
config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '12.0'
end
end
end
6 changes: 3 additions & 3 deletions example/ios/Runner.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -452,7 +452,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;
Expand Down Expand Up @@ -583,7 +583,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;
Expand Down Expand Up @@ -632,7 +632,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;
Expand Down
4 changes: 2 additions & 2 deletions example/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev
version: 0.0.1

environment:
sdk: ">=3.2.0 <4.0.0"
flutter: ">=3.16.0"
sdk: ">=3.3.0 <4.0.0"
flutter: ">=3.19.0"

# Dependencies specify other packages that your package needs in order to work.
# To automatically upgrade your package dependencies to the latest versions
Expand Down
14 changes: 14 additions & 0 deletions ios/Resources/PrivacyInfo.xcprivacy
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>NSPrivacyAccessedAPITypes</key>
<array/>
<key>NSPrivacyCollectedDataTypes</key>
<array/>
<key>NSPrivacyTrackingDomains</key>
<array/>
<key>NSPrivacyTracking</key>
<false/>
</dict>
</plist>
11 changes: 6 additions & 5 deletions ios/mobile_scanner.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,22 @@
#
Pod::Spec.new do |s|
s.name = 'mobile_scanner'
s.version = '3.5.6'
s.version = '5.0.0'
s.summary = 'An universal scanner for Flutter based on MLKit.'
s.description = <<-DESC
An universal scanner for Flutter based on MLKit.
DESC
s.homepage = 'http://example.com'
s.homepage = 'https://github.com/juliansteenbakker/mobile_scanner'
s.license = { :file => '../LICENSE' }
s.author = { 'Your Company' => 'email@example.com' }
s.author = { 'Julian Steenbakker' => 'juliansteenbakker@outlook.com' }
s.source = { :path => '.' }
s.source_files = 'Classes/**/*'
s.dependency 'Flutter'
s.dependency 'GoogleMLKit/BarcodeScanning', '~> 4.0.0'
s.platform = :ios, '11.0'
s.dependency 'GoogleMLKit/BarcodeScanning', '~> 5.0.0'
s.platform = :ios, '12.0'
s.static_framework = true
# Flutter.framework does not contain a i386 slice.
s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'i386' }
s.swift_version = '5.0'
s.resource_bundles = { 'mobile_scanner_privacy' => ['Resources/PrivacyInfo.xcprivacy'] }
end
54 changes: 20 additions & 34 deletions lib/src/method_channel/mobile_scanner_method_channel.dart
Original file line number Diff line number Diff line change
Expand Up @@ -94,12 +94,29 @@ class MethodChannelMobileScanner extends MobileScannerPlatform {
///
/// Throws a [MobileScannerException] if the permission is not granted.
Future<void> _requestCameraPermission() async {
final MobileScannerAuthorizationState authorizationState;

try {
authorizationState = MobileScannerAuthorizationState.fromRawValue(
final MobileScannerAuthorizationState authorizationState =
MobileScannerAuthorizationState.fromRawValue(
await methodChannel.invokeMethod<int>('state') ?? 0,
);

switch (authorizationState) {
// Authorization was already granted, no need to request it again.
case MobileScannerAuthorizationState.authorized:
return;
// Android does not have an undetermined authorization state.
// So if the permission was denied, request it again.
case MobileScannerAuthorizationState.denied:
case MobileScannerAuthorizationState.undetermined:
final bool permissionGranted =
await methodChannel.invokeMethod<bool>('request') ?? false;

if (!permissionGranted) {
throw const MobileScannerException(
errorCode: MobileScannerErrorCode.permissionDenied,
);
}
}
} on PlatformException catch (error) {
// If the permission state is invalid, that is an error.
throw MobileScannerException(
Expand All @@ -111,37 +128,6 @@ class MethodChannelMobileScanner extends MobileScannerPlatform {
),
);
}

switch (authorizationState) {
case MobileScannerAuthorizationState.authorized:
return; // Already authorized.
// Android does not have an undetermined authorization state.
// So if the permission was denied, request it again.
case MobileScannerAuthorizationState.denied:
case MobileScannerAuthorizationState.undetermined:
try {
final bool granted =
await methodChannel.invokeMethod<bool>('request') ?? false;

if (granted) {
return; // Authorization was granted.
}

throw const MobileScannerException(
errorCode: MobileScannerErrorCode.permissionDenied,
);
} on PlatformException catch (error) {
// If the permission state is invalid, that is an error.
throw MobileScannerException(
errorCode: MobileScannerErrorCode.genericError,
errorDetails: MobileScannerErrorDetails(
code: error.code,
details: error.details as Object?,
message: error.message,
),
);
}
}
}

@override
Expand Down
11 changes: 10 additions & 1 deletion lib/src/mobile_scanner_controller.dart
Original file line number Diff line number Diff line change
Expand Up @@ -223,12 +223,14 @@ class MobileScannerController extends ValueNotifier<MobileScannerState> {
}

/// Start scanning for barcodes.
/// Upon calling this method, the necessary camera permission will be requested.
///
/// The [cameraDirection] can be used to specify the camera direction.
/// If this is null, this defaults to the [facing] value.
///
/// Does nothing if the camera is already running.
/// Upon calling this method, the necessary camera permission will be requested.
///
/// If the permission is denied on iOS, MacOS or Web, there is no way to request it again.
Future<void> start({CameraFacing? cameraDirection}) async {
if (_isDisposed) {
throw const MobileScannerException(
Expand All @@ -240,6 +242,13 @@ class MobileScannerController extends ValueNotifier<MobileScannerState> {
);
}

// Permission was denied, do nothing.
// When the controller is stopped,
// the error is reset so the permission can be requested again if possible.
if (value.error?.errorCode == MobileScannerErrorCode.permissionDenied) {
return;
}

// Do nothing if the camera is already running.
if (value.isRunning) {
return;
Expand Down
27 changes: 13 additions & 14 deletions lib/src/web/barcode_reader.dart
Original file line number Diff line number Diff line change
Expand Up @@ -62,20 +62,19 @@ abstract class BarcodeReader {

final Completer<void> completer = Completer();

final HTMLScriptElement script =
(document.createElement('script') as HTMLScriptElement)
..id = scriptId
..async = true
..defer = false
..type = 'application/javascript'
..lang = 'javascript'
..crossOrigin = 'anonymous'
..src = alternateScriptUrl ?? scriptUrl
..onload = (JSAny _) {
if (!completer.isCompleted) {
completer.complete();
}
}.toJS;
final HTMLScriptElement script = HTMLScriptElement()
..id = scriptId
..async = true
..defer = false
..type = 'application/javascript'
..lang = 'javascript'
..crossOrigin = 'anonymous'
..src = alternateScriptUrl ?? scriptUrl
..onload = (JSAny _) {
if (!completer.isCompleted) {
completer.complete();
}
}.toJS;

script.onerror = (JSAny _) {
if (!completer.isCompleted) {
Expand Down
6 changes: 2 additions & 4 deletions lib/src/web/javascript_map.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,10 @@ import 'dart:js_interop';
///
/// Object literals can be made using [jsify].
@JS('Map')
@staticInterop
class JSMap<K extends JSAny, V extends JSAny> {
extension type JSMap<K extends JSAny, V extends JSAny>._(JSObject _)
implements JSObject {
external factory JSMap();
}

extension JSMapExtension<K extends JSAny, V extends JSAny> on JSMap<K, V> {
external V? get(K key);
external JSVoid set(K key, V? value);
}
17 changes: 10 additions & 7 deletions lib/src/web/media_track_constraints_delegate.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,25 +9,28 @@ final class MediaTrackConstraintsDelegate {

/// Get the settings for the given [mediaStream].
MediaTrackSettings? getSettings(MediaStream? mediaStream) {
final List<JSAny?>? tracks = mediaStream?.getVideoTracks().toDart;
final List<MediaStreamTrack>? tracks = mediaStream?.getVideoTracks().toDart;

if (tracks == null || tracks.isEmpty) {
return null;
}

final MediaStreamTrack? track = tracks.first as MediaStreamTrack?;

if (track == null) {
return null;
}
final MediaStreamTrack track = tracks.first;

final MediaTrackCapabilities capabilities = track.getCapabilities();
final MediaTrackSettings settings = track.getSettings();

if (capabilities.facingMode.toDart.isEmpty) {
return MediaTrackSettings(
width: settings.width,
height: settings.height,
);
}

return MediaTrackSettings(
width: settings.width,
height: settings.height,
facingMode: settings.facingMode,
aspectRatio: settings.aspectRatio,
);
}
}
Loading

0 comments on commit 72b0335

Please sign in to comment.