Julian Steenbakker

style: flutter format

... ... @@ -27,10 +27,11 @@ class _BarcodeScannerWithControllerState
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.black,
body: Builder(builder: (context) {
return Stack(
children: [
MobileScanner(
body: Builder(
builder: (context) {
return Stack(
children: [
MobileScanner(
controller: controller,
fit: BoxFit.contain,
// allowDuplicates: true,
... ... @@ -42,120 +43,130 @@ class _BarcodeScannerWithControllerState
setState(() {
this.barcode = barcode.rawValue;
});
},),
Align(
alignment: Alignment.bottomCenter,
child: Container(
},
),
Align(
alignment: Alignment.bottomCenter,
height: 100,
color: Colors.black.withOpacity(0.4),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
IconButton(
color: Colors.white,
icon: ValueListenableBuilder(
valueListenable: controller.torchState,
builder: (context, state, child) {
if (state == null) {
return const Icon(Icons.flash_off,
color: Colors.grey,);
}
switch (state as TorchState) {
case TorchState.off:
return const Icon(Icons.flash_off,
color: Colors.grey,);
case TorchState.on:
return const Icon(Icons.flash_on,
color: Colors.yellow,);
}
},
child: Container(
alignment: Alignment.bottomCenter,
height: 100,
color: Colors.black.withOpacity(0.4),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
IconButton(
color: Colors.white,
icon: ValueListenableBuilder(
valueListenable: controller.torchState,
builder: (context, state, child) {
if (state == null) {
return const Icon(
Icons.flash_off,
color: Colors.grey,
);
}
switch (state as TorchState) {
case TorchState.off:
return const Icon(
Icons.flash_off,
color: Colors.grey,
);
case TorchState.on:
return const Icon(
Icons.flash_on,
color: Colors.yellow,
);
}
},
),
iconSize: 32.0,
onPressed: () => controller.toggleTorch(),
),
iconSize: 32.0,
onPressed: () => controller.toggleTorch(),
),
IconButton(
IconButton(
color: Colors.white,
icon: isStarted
? const Icon(Icons.stop)
: const Icon(Icons.play_arrow),
iconSize: 32.0,
onPressed: () => setState(() {
isStarted
? controller.stop()
: controller.start();
isStarted = !isStarted;
}),),
Center(
child: SizedBox(
width: MediaQuery.of(context).size.width - 200,
height: 50,
child: FittedBox(
child: Text(
barcode ?? 'Scan something!',
overflow: TextOverflow.fade,
style: Theme.of(context)
.textTheme
.headline4!
.copyWith(color: Colors.white),
isStarted ? controller.stop() : controller.start();
isStarted = !isStarted;
}),
),
Center(
child: SizedBox(
width: MediaQuery.of(context).size.width - 200,
height: 50,
child: FittedBox(
child: Text(
barcode ?? 'Scan something!',
overflow: TextOverflow.fade,
style: Theme.of(context)
.textTheme
.headline4!
.copyWith(color: Colors.white),
),
),
),
),
),
IconButton(
color: Colors.white,
icon: ValueListenableBuilder(
valueListenable: controller.cameraFacingState,
builder: (context, state, child) {
if (state == null) {
return const Icon(Icons.camera_front);
}
switch (state as CameraFacing) {
case CameraFacing.front:
IconButton(
color: Colors.white,
icon: ValueListenableBuilder(
valueListenable: controller.cameraFacingState,
builder: (context, state, child) {
if (state == null) {
return const Icon(Icons.camera_front);
case CameraFacing.back:
return const Icon(Icons.camera_rear);
}
switch (state as CameraFacing) {
case CameraFacing.front:
return const Icon(Icons.camera_front);
case CameraFacing.back:
return const Icon(Icons.camera_rear);
}
},
),
iconSize: 32.0,
onPressed: () => controller.switchCamera(),
),
IconButton(
color: Colors.white,
icon: const Icon(Icons.image),
iconSize: 32.0,
onPressed: () async {
final ImagePicker _picker = ImagePicker();
// Pick an image
final XFile? image = await _picker.pickImage(
source: ImageSource.gallery,
);
if (image != null) {
if (await controller.analyzeImage(image.path)) {
if (!mounted) return;
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('Barcode found!'),
backgroundColor: Colors.green,
),
);
} else {
if (!mounted) return;
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('No barcode found!'),
backgroundColor: Colors.red,
),
);
}
}
},
),
iconSize: 32.0,
onPressed: () => controller.switchCamera(),
),
IconButton(
color: Colors.white,
icon: const Icon(Icons.image),
iconSize: 32.0,
onPressed: () async {
final ImagePicker _picker = ImagePicker();
// Pick an image
final XFile? image = await _picker.pickImage(
source: ImageSource.gallery,);
if (image != null) {
if (await controller.analyzeImage(image.path)) {
if (!mounted) return;
ScaffoldMessenger.of(context)
.showSnackBar(const SnackBar(
content: Text('Barcode found!'),
backgroundColor: Colors.green,
),);
} else {
if (!mounted) return;
ScaffoldMessenger.of(context)
.showSnackBar(const SnackBar(
content: Text('No barcode found!'),
backgroundColor: Colors.red,
),);
}
}
},
),
],
],
),
),
),
),
],
);
},),
],
);
},
),
);
}
}
... ...
... ... @@ -18,49 +18,52 @@ class _BarcodeScannerWithoutControllerState
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.black,
body: Builder(builder: (context) {
return Stack(
children: [
MobileScanner(
body: Builder(
builder: (context) {
return Stack(
children: [
MobileScanner(
fit: BoxFit.contain,
// allowDuplicates: false,
onDetect: (barcode, args) {
setState(() {
this.barcode = barcode.rawValue;
});
},),
Align(
alignment: Alignment.bottomCenter,
child: Container(
},
),
Align(
alignment: Alignment.bottomCenter,
height: 100,
color: Colors.black.withOpacity(0.4),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Center(
child: SizedBox(
width: MediaQuery.of(context).size.width - 120,
height: 50,
child: FittedBox(
child: Text(
barcode ?? 'Scan something!',
overflow: TextOverflow.fade,
style: Theme.of(context)
.textTheme
.headline4!
.copyWith(color: Colors.white),
child: Container(
alignment: Alignment.bottomCenter,
height: 100,
color: Colors.black.withOpacity(0.4),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Center(
child: SizedBox(
width: MediaQuery.of(context).size.width - 120,
height: 50,
child: FittedBox(
child: Text(
barcode ?? 'Scan something!',
overflow: TextOverflow.fade,
style: Theme.of(context)
.textTheme
.headline4!
.copyWith(color: Colors.white),
),
),
),
),
),
],
],
),
),
),
),
],
);
},),
],
);
},
),
);
}
}
... ...
... ... @@ -19,17 +19,22 @@ class MyHome extends StatelessWidget {
children: [
ElevatedButton(
onPressed: () {
Navigator.of(context).push(MaterialPageRoute(
builder: (context) => const BarcodeScannerWithController(),
),);
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => const BarcodeScannerWithController(),
),
);
},
child: const Text('MobileScanner with Controller'),
),
ElevatedButton(
onPressed: () {
Navigator.of(context).push(MaterialPageRoute(
builder: (context) => const BarcodeScannerWithoutController(),
),);
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) =>
const BarcodeScannerWithoutController(),
),
);
},
child: const Text('MobileScanner without Controller'),
),
... ...
... ... @@ -14,13 +14,15 @@ import 'package:mobile_scanner/src/web/media.dart';
class MobileScannerWebPlugin {
static void registerWith(Registrar registrar) {
final PluginEventChannel event = PluginEventChannel(
'dev.steenbakker.mobile_scanner/scanner/event',
const StandardMethodCodec(),
registrar,);
'dev.steenbakker.mobile_scanner/scanner/event',
const StandardMethodCodec(),
registrar,
);
final MethodChannel channel = MethodChannel(
'dev.steenbakker.mobile_scanner/scanner/method',
const StandardMethodCodec(),
registrar,);
'dev.steenbakker.mobile_scanner/scanner/method',
const StandardMethodCodec(),
registrar,
);
final MobileScannerWebPlugin instance = MobileScannerWebPlugin();
WidgetsFlutterBinding.ensureInitialized();
... ... @@ -57,9 +59,10 @@ class MobileScannerWebPlugin {
return cancel();
default:
throw PlatformException(
code: 'Unimplemented',
details: "The mobile_scanner plugin for web doesn't implement "
"the method '${call.method}'",);
code: 'Unimplemented',
details: "The mobile_scanner plugin for web doesn't implement "
"the method '${call.method}'",
);
}
}
... ... @@ -87,10 +90,11 @@ class MobileScannerWebPlugin {
// See https://github.com/flutter/flutter/issues/41563
// ignore: UNDEFINED_PREFIXED_NAME, avoid_dynamic_calls
ui.platformViewRegistry.registerViewFactory(
viewID,
(int id) => vidDiv
..style.width = '100%'
..style.height = '100%',);
viewID,
(int id) => vidDiv
..style.width = '100%'
..style.height = '100%',
);
// Check if stream is running
if (_localStream != null) {
... ... @@ -108,8 +112,9 @@ class MobileScannerWebPlugin {
if (capabilities != null && capabilities['facingMode'] as bool) {
final constraints = {
'video': VideoOptions(
facingMode:
cameraFacing == CameraFacing.front ? 'user' : 'environment',)
facingMode:
cameraFacing == CameraFacing.front ? 'user' : 'environment',
)
};
_localStream =
... ...
... ... @@ -28,13 +28,13 @@ class MobileScanner extends StatefulWidget {
final bool allowDuplicates;
/// Create a [MobileScanner] with a [controller], the [controller] must has been initialized.
const MobileScanner(
{Key? key,
this.onDetect,
this.controller,
this.fit = BoxFit.cover,
this.allowDuplicates = false, })
: super(key: key);
const MobileScanner({
Key? key,
this.onDetect,
this.controller,
this.fit = BoxFit.cover,
this.allowDuplicates = false,
}) : super(key: key);
@override
State<MobileScanner> createState() => _MobileScannerState();
... ... @@ -69,8 +69,9 @@ class _MobileScannerState extends State<MobileScanner>
@override
Widget build(BuildContext context) {
return LayoutBuilder(builder: (context, BoxConstraints constraints) {
return ValueListenableBuilder(
return LayoutBuilder(
builder: (context, BoxConstraints constraints) {
return ValueListenableBuilder(
valueListenable: controller.args,
builder: (context, value, child) {
value = value as MobileScannerArguments?;
... ... @@ -104,8 +105,10 @@ class _MobileScannerState extends State<MobileScanner>
),
);
}
},);
},);
},
);
},
);
}
@override
... ...
... ... @@ -13,6 +13,10 @@ class MobileScannerArguments {
final String? webId;
/// Create a [MobileScannerArguments].
MobileScannerArguments(
{this.textureId, required this.size, required this.hasTorch, this.webId, });
MobileScannerArguments({
this.textureId,
required this.size,
required this.hasTorch,
this.webId,
});
}
... ...
... ... @@ -55,11 +55,12 @@ class MobileScannerController {
Stream<Barcode> get barcodes => barcodesController.stream;
MobileScannerController(
{this.facing = CameraFacing.back,
this.ratio,
this.torchEnabled,
this.formats, }) {
MobileScannerController({
this.facing = CameraFacing.back,
this.ratio,
this.torchEnabled,
this.formats,
}) {
// In case a new instance is created before calling dispose()
if (_controllerHashcode != null) {
stop();
... ... @@ -95,7 +96,11 @@ class MobileScannerController {
barcodesController.add(barcode);
break;
case 'barcodeMac':
barcodesController.add(Barcode(rawValue: (data as Map<String, dynamic>)['payload'] as String));
barcodesController.add(
Barcode(
rawValue: (data as Map<String, dynamic>)['payload'] as String,
),
);
break;
case 'barcodeWeb':
barcodesController.add(Barcode(rawValue: data as String));
... ... @@ -128,11 +133,12 @@ class MobileScannerController {
// Check authorization status
if (!kIsWeb) {
MobileScannerState state =
MobileScannerState.values[await methodChannel.invokeMethod('state') as int];
MobileScannerState state = MobileScannerState
.values[await methodChannel.invokeMethod('state') as int];
switch (state) {
case MobileScannerState.undetermined:
final bool result = await methodChannel.invokeMethod('request') as bool;
final bool result =
await methodChannel.invokeMethod('request') as bool;
state = result
? MobileScannerState.authorized
: MobileScannerState.denied;
... ... @@ -165,7 +171,9 @@ class MobileScannerController {
Map<String, dynamic>? startResult = {};
try {
startResult = await methodChannel.invokeMapMethod<String, dynamic>(
'start', arguments,);
'start',
arguments,
);
} on PlatformException catch (error) {
debugPrint('${error.code}: ${error.message}');
isStarting = false;
... ... @@ -182,14 +190,19 @@ class MobileScannerController {
if (kIsWeb) {
args.value = MobileScannerArguments(
webId: startResult['ViewID'] as String?,
size: Size(startResult['videoWidth'] as double, startResult['videoHeight'] as double),
hasTorch: hasTorch,);
webId: startResult['ViewID'] as String?,
size: Size(
startResult['videoWidth'] as double,
startResult['videoHeight'] as double,
),
hasTorch: hasTorch,
);
} else {
args.value = MobileScannerArguments(
textureId: startResult['textureId'] as int,
size: toSize(startResult['size'] as Map<String, double>),
hasTorch: hasTorch,);
textureId: startResult['textureId'] as int,
size: toSize(startResult['size'] as Map<String, double>),
hasTorch: hasTorch,
);
}
isStarting = false;
... ... @@ -232,7 +245,8 @@ class MobileScannerController {
await methodChannel.invokeMethod('stop');
} on PlatformException catch (error) {
debugPrint(
'${error.code}: camera is stopped! Please start before switching camera.',);
'${error.code}: camera is stopped! Please start before switching camera.',
);
return;
}
facing =
... ...
... ... @@ -63,21 +63,22 @@ class Barcode {
/// Gets parsed WiFi AP details.
final WiFi? wifi;
Barcode(
{this.corners,
this.format = BarcodeFormat.ean13,
this.rawBytes,
this.type = BarcodeType.text,
this.calendarEvent,
this.contactInfo,
this.driverLicense,
this.email,
this.geoPoint,
this.phone,
this.sms,
this.url,
this.wifi,
required this.rawValue, });
Barcode({
this.corners,
this.format = BarcodeFormat.ean13,
this.rawBytes,
this.type = BarcodeType.text,
this.calendarEvent,
this.contactInfo,
this.driverLicense,
this.email,
this.geoPoint,
this.phone,
this.sms,
this.url,
this.wifi,
required this.rawValue,
});
/// Create a [Barcode] from native data.
Barcode.fromNative(Map<String, dynamic> data)
... ... @@ -86,7 +87,8 @@ class Barcode {
rawBytes = data['rawBytes'] as Uint8List?,
rawValue = data['rawValue'] as String?,
type = BarcodeType.values[data['type'] as int],
calendarEvent = toCalendarEvent(data['calendarEvent'] as Map<String, String?>?),
calendarEvent =
toCalendarEvent(data['calendarEvent'] as Map<String, String?>?),
contactInfo = toContactInfo(data['contactInfo'] as Map?),
driverLicense = toDriverLicense(data['driverLicense'] as Map?),
email = toEmail(data['email'] as Map?),
... ... @@ -185,13 +187,16 @@ class ContactInfo {
/// Create a [ContactInfo] from native data.
ContactInfo.fromNative(Map<dynamic, dynamic> data)
: addresses = List.unmodifiable(
(data['addresses'] as List<Map>).map((e) => Address.fromNative(e)),),
emails =
List.unmodifiable((data['emails'] as List<Map>).map((e) => Email.fromNative(e))),
(data['addresses'] as List<Map>).map((e) => Address.fromNative(e)),
),
emails = List.unmodifiable(
(data['emails'] as List<Map>).map((e) => Email.fromNative(e)),
),
name = toName(data['name'] as Map?),
organization = data['organization'] as String?,
phones =
List.unmodifiable((data['phones'] as List<Map>).map((e) => Phone.fromNative(e))),
phones = List.unmodifiable(
(data['phones'] as List<Map>).map((e) => Phone.fromNative(e)),
),
title = data['title'] as String?,
urls = List.unmodifiable(data['urls'] as List);
}
... ...
import 'package:flutter/material.dart';
import 'package:mobile_scanner/mobile_scanner.dart';
Size toSize(Map<dynamic, double> data) {
final width = data['width']!;
final height = data['height']!;
... ... @@ -10,7 +9,9 @@ Size toSize(Map<dynamic, double> data) {
List<Offset>? toCorners(List<Map>? data) {
if (data != null) {
return List.unmodifiable(data.map((e) => Offset(e['x'] as double, e['y'] as double)));
return List.unmodifiable(
data.map((e) => Offset(e['x'] as double, e['y'] as double)),
);
} else {
return null;
}
... ...
... ... @@ -25,8 +25,12 @@ class VideoOptions {
external Map get width;
external Map get height;
external factory VideoOptions(
{String? facingMode, DeviceIdOptions? deviceId, Map? width, Map? height, });
external factory VideoOptions({
String? facingMode,
DeviceIdOptions? deviceId,
Map? width,
Map? height,
});
}
@JS()
... ...