qr scanner initial

This commit is contained in:
Fabian Freund
2026-01-13 13:10:54 +01:00
parent 435ea4d43f
commit 57bb288bcc
4 changed files with 123 additions and 4 deletions
@@ -25,6 +25,7 @@ import 'package:weblibre/features/bangs/data/models/bang_data.dart';
import 'package:weblibre/features/geckoview/features/search/domain/providers/engine_suggestions.dart';
import 'package:weblibre/features/user/domain/providers.dart';
import 'package:weblibre/presentation/widgets/auto_suggest_text_field.dart';
import 'package:weblibre/presentation/widgets/qr_scanner_button.dart';
import 'package:weblibre/presentation/widgets/speech_to_text_button.dart';
import 'package:weblibre/presentation/widgets/url_icon.dart';
@@ -122,10 +123,22 @@ class SearchField extends HookConsumerWidget {
},
icon: const Icon(Icons.clear),
)
: SpeechToTextButton(
onTextReceived: (data) {
textEditingController.text = data.toString();
},
: Row(
mainAxisSize: MainAxisSize.min,
children: [
QrScannerButton(
onScanResult: (scanResult) {
if (scanResult?.code != null) {
textEditingController.text = scanResult!.code!;
}
},
),
SpeechToTextButton(
onTextReceived: (data) {
textEditingController.text = data;
},
),
],
),
),
onTapOutside: unfocusOnTapOutside
@@ -0,0 +1,77 @@
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:qr_code_scanner_plus/qr_code_scanner_plus.dart';
import 'package:weblibre/utils/ui_helper.dart' as ui_helper;
class QrScannerDialog extends HookWidget {
@override
Widget build(BuildContext context) {
final qrKey = useMemoized(() => GlobalKey(debugLabel: 'qr_scanner'));
final qrController = useState<QRViewController?>(null);
final flashState = useState(false);
useEffect(() {
StreamSubscription<Barcode>? sub;
if (qrController.value != null) {
sub = qrController.value!.scannedDataStream.listen((event) {
if (context.mounted) {
Navigator.pop(context, event);
}
});
}
return () {
unawaited(sub?.cancel());
};
}, [qrController.value]);
return Dialog.fullscreen(
child: Scaffold(
appBar: AppBar(
title: const Text('Scan code'),
actions: [
IconButton(
isSelected: flashState.value,
onPressed: () async {
if (qrController.value != null) {
await qrController.value!.toggleFlash();
flashState.value =
await qrController.value!.getFlashStatus() ?? false;
}
},
icon: const Icon(Icons.flash_on),
selectedIcon: const Icon(Icons.flash_off),
),
IconButton(
onPressed: () async {
await qrController.value?.flipCamera();
},
icon: const Icon(Icons.cameraswitch),
),
],
),
body: SafeArea(
child: QRView(
key: qrKey,
onQRViewCreated: (controller) {
qrController.value = controller;
},
onPermissionSet: (controller, result) {
if (!result) {
ui_helper.showErrorMessage(
context,
'No Camera Permission granted',
);
}
},
),
),
),
);
}
}
@@ -0,0 +1,28 @@
import 'package:flutter/material.dart';
import 'package:flutter_material_design_icons/flutter_material_design_icons.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:qr_code_scanner_plus/qr_code_scanner_plus.dart';
import 'package:weblibre/features/qr_scanner/presentation/dialogs/qr_scanner_dialog.dart';
class QrScannerButton extends HookConsumerWidget {
final void Function(Barcode? scanResult) onScanResult;
const QrScannerButton({required this.onScanResult});
@override
Widget build(BuildContext context, WidgetRef ref) {
return IconButton(
onPressed: () async {
final result = await showDialog<Barcode>(
context: context,
builder: (context) {
return QrScannerDialog();
},
);
onScanResult(result);
},
icon: const Icon(MdiIcons.barcodeScan),
);
}
}
+1
View File
@@ -61,6 +61,7 @@ dependencies:
path_provider: ^2.1.5
permission_handler: ^12.0.1
pretty_qr_code: ^3.5.0
qr_code_scanner_plus: ^2.0.14
quick_actions: ^1.1.0
riverpod: ^3.1.0
riverpod_annotation: ^4.0.0