diff --git a/android/gradle.properties b/android/gradle.properties
index 2597170..2234d2d 100644
--- a/android/gradle.properties
+++ b/android/gradle.properties
@@ -1,3 +1,4 @@
org.gradle.jvmargs=-Xmx4G -XX:MaxMetaspaceSize=2G -XX:+HeapDumpOnOutOfMemoryError
android.useAndroidX=true
android.enableJetifier=true
+dev.steenbakker.mobile_scanner.useUnbundled=true
\ No newline at end of file
diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist
index 304dcb9..2c865eb 100644
--- a/ios/Runner/Info.plist
+++ b/ios/Runner/Info.plist
@@ -45,5 +45,9 @@
UIApplicationSupportsIndirectInputEvents
+ io.flutter.embedded_views_preview
+
+ NSCameraUsageDescription
+ This app needs camera access to scan QR codes
diff --git a/lib/app/route.dart b/lib/app/route.dart
index f97d12c..fdcca4a 100644
--- a/lib/app/route.dart
+++ b/lib/app/route.dart
@@ -1,4 +1,5 @@
import 'package:flutter/material.dart';
+import '../screen/home/rekam_screen.dart';
import '../screen/home/home_screen.dart';
import '../screen/login/login_screen.dart';
@@ -7,8 +8,7 @@ import '../screen/splash/splash_screen.dart';
const splashRoute = "/splashRoute";
const loginRoute = "/loginRoute";
const homeRoute = "/homeRoute";
-const scanRoute = "/scanRoute";
-const editScanRoute = "/editScanRoute";
+const rekamRoute = "/rekamRoute";
class AppRoute {
static Route generateRoute(RouteSettings settings) {
@@ -45,6 +45,17 @@ class AppRoute {
});
}
+ // rekam screen
+ if (settings.name == rekamRoute) {
+ return MaterialPageRoute(builder: (context) {
+ return MediaQuery(
+ data: MediaQuery.of(context).copyWith(
+ textScaler: TextScaler.linear(1.0), padding: EdgeInsets.all(0)),
+ child: RekamScreen(),
+ );
+ });
+ }
+
return MaterialPageRoute(builder: (context) {
return MediaQuery(
data: MediaQuery.of(context).copyWith(
diff --git a/lib/provider/voice_to_text_provider.dart b/lib/provider/voice_to_text_provider.dart
index 3b2a34b..101300a 100644
--- a/lib/provider/voice_to_text_provider.dart
+++ b/lib/provider/voice_to_text_provider.dart
@@ -1,4 +1,5 @@
import 'package:flutter_riverpod/flutter_riverpod.dart';
+import 'package:mobile_scanner/mobile_scanner.dart';
import '../../model/edit_voice_to_text_model.dart';
import '../../model/voice_to_text_model.dart';
@@ -19,4 +20,9 @@ final selectedEdit = StateProvider(
Voice2text_Updated: "",
Voice2text_User_ID: "",
),
+);
+
+//
+final barcodeX = StateProvider(
+ (ref) => Barcode(),
);
\ No newline at end of file
diff --git a/lib/screen/home/home_screen.dart b/lib/screen/home/home_screen.dart
index 8d93372..a5bb747 100644
--- a/lib/screen/home/home_screen.dart
+++ b/lib/screen/home/home_screen.dart
@@ -134,7 +134,7 @@ class HomeScreen extends HookConsumerWidget {
),
child: ElevatedButton(
onPressed: () {
- // Navigator.of(context).pushNamed(scanRoute);
+ Navigator.of(context).pushNamed(rekamRoute);
},
style: ElevatedButton.styleFrom(
backgroundColor: Constant.bgButton,
diff --git a/lib/screen/home/rekam_screen.dart b/lib/screen/home/rekam_screen.dart
new file mode 100644
index 0000000..b08f7e7
--- /dev/null
+++ b/lib/screen/home/rekam_screen.dart
@@ -0,0 +1,198 @@
+import 'package:flutter/material.dart';
+import 'package:flutter/services.dart';
+import 'package:flutter_hooks/flutter_hooks.dart';
+import 'package:fluttervoice2text/provider/voice_to_text_provider.dart';
+import 'package:hooks_riverpod/hooks_riverpod.dart';
+import 'package:mobile_scanner/mobile_scanner.dart';
+
+import '../../app/constant.dart';
+
+class RekamScreen extends HookConsumerWidget {
+ const RekamScreen({super.key});
+
+ @override
+ Widget build(BuildContext context, WidgetRef ref) {
+ SystemChrome.setEnabledSystemUIMode(
+ SystemUiMode.manual,
+ overlays: [SystemUiOverlay.bottom],
+ );
+
+ final isRekam = useState(false);
+ final judulTombol = useState("MULAI REKAM");
+ final qrCodeStr = useState("");
+ final isSelesaiRekam = useState(false);
+
+ void handleBarcode(BarcodeCapture barcodes) {
+ if (barcodes.barcodes.isNotEmpty) {
+ final scannedBarcode =
+ barcodes.barcodes.firstOrNull?.displayValue ?? "";
+ if (scannedBarcode.isNotEmpty) {
+ ref.read(barcodeX.notifier).state = barcodes.barcodes.first;
+ qrCodeStr.value = scannedBarcode;
+ }
+ }
+ }
+
+ Widget buildBarcode(Barcode? value) {
+ final qrCode = value?.displayValue ?? "";
+
+ if (qrCode.isEmpty) {
+ return const Text(
+ 'Scan untuk mendapatkan QR Code',
+ overflow: TextOverflow.fade,
+ style: TextStyle(color: Colors.white),
+ );
+ }
+
+ return Text(
+ "Info: $qrCode",
+ overflow: TextOverflow.fade,
+ style: const TextStyle(color: Colors.white),
+ );
+ }
+
+ useEffect(() {
+ handleBarcode;
+ return () {};
+ }, []);
+
+ return GestureDetector(
+ onTap: () {
+ FocusManager.instance.primaryFocus!.unfocus();
+ },
+ child: Scaffold(
+ resizeToAvoidBottomInset: true,
+ backgroundColor: Constant.bgGrey,
+ bottomNavigationBar: BottomAppBar(
+ color: Colors.blueGrey.shade100,
+ height: Constant.getActualYPhone(
+ context: context,
+ y: 100,
+ ),
+ shape: const CircularNotchedRectangle(),
+ child: Row(
+ children: [
+ ElevatedButton.icon(
+ onPressed: () {
+ ref.read(barcodeX.notifier).state = Barcode();
+ isRekam.value = false;
+ judulTombol.value = "MULAI REKAM";
+ qrCodeStr.value = "";
+ isSelesaiRekam.value = false;
+ Navigator.of(context).pop();
+ },
+ icon: Icon(
+ Icons.arrow_back,
+ size: 17,
+ color: Constant.textWhite,
+ ),
+ label: Text(
+ 'Kembali',
+ style: Constant.cardText(context: context).copyWith(
+ color: Constant.textWhite,
+ ),
+ ),
+ style: ElevatedButton.styleFrom(
+ backgroundColor: Colors.green.shade400,
+ shape: RoundedRectangleBorder(
+ borderRadius: BorderRadius.circular(8),
+ ),
+ elevation: 8,
+ shadowColor: Constant.bgButton.withOpacity(0.24),
+ ),
+ ),
+ const Spacer(),
+ // button
+ ElevatedButton(
+ onPressed: (qrCodeStr.value.isEmpty || isSelesaiRekam.value)
+ ? null
+ : () {
+ judulTombol.value = "SELESAI";
+ isSelesaiRekam.value = true;
+ },
+ style: ElevatedButton.styleFrom(
+ backgroundColor: (qrCodeStr.value.isEmpty || isSelesaiRekam.value)
+ ? Constant.bgGrey
+ : Constant.bgButton,
+ shape: RoundedRectangleBorder(
+ borderRadius: BorderRadius.circular(8),
+ ),
+ elevation: 8,
+ shadowColor: Constant.bgButton.withOpacity(0.24),
+ ),
+ child: Row(
+ mainAxisAlignment: MainAxisAlignment.center,
+ children: [
+ Icon(
+ Icons.mic,
+ size: Constant.getActualXPhone(
+ context: context,
+ x: 20,
+ ),
+ color: Constant.textWhite,
+ ),
+ SizedBox(
+ width: Constant.getActualXPhone(
+ context: context,
+ x: 10,
+ ),
+ ),
+ Text(
+ judulTombol.value,
+ style: Constant.titleButton500(context: context).copyWith(
+ color: Constant.textWhite,
+ ),
+ ),
+ ],
+ ),
+ ),
+ ],
+ ),
+ ),
+ appBar: AppBar(
+ title: Text(
+ 'Rekam Audio',
+ style: Constant.titlePosisiHP(context: context),
+ ),
+ automaticallyImplyLeading: false,
+ ),
+ body: Padding(
+ padding: EdgeInsets.symmetric(
+ horizontal: Constant.getActualXPhone(context: context, x: 20),
+ ),
+ child: Column(
+ children: [
+ // scanner
+ if (isRekam.value == false) ...[
+ SizedBox(
+ width: double.infinity,
+ height: Constant.getActualYPhone(
+ context: context,
+ y: 450,
+ ),
+ child: MobileScanner(
+ onDetect: handleBarcode,
+ ),
+ ),
+ SizedBox(
+ height: Constant.getActualYPhone(
+ context: context,
+ y: 15,
+ ),
+ ),
+ ],
+
+ // text
+ Container(
+ alignment: Alignment.center,
+ padding: const EdgeInsets.symmetric(vertical: 10),
+ color: Constant.inputanGrey,
+ child: buildBarcode(ref.watch(barcodeX)),
+ ),
+ ],
+ ),
+ ),
+ ),
+ );
+ }
+}
diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift
index 5ea4a51..b6a1bab 100644
--- a/macos/Flutter/GeneratedPluginRegistrant.swift
+++ b/macos/Flutter/GeneratedPluginRegistrant.swift
@@ -6,12 +6,14 @@ import FlutterMacOS
import Foundation
import audioplayers_darwin
+import mobile_scanner
import path_provider_foundation
import record_darwin
import shared_preferences_foundation
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
AudioplayersDarwinPlugin.register(with: registry.registrar(forPlugin: "AudioplayersDarwinPlugin"))
+ MobileScannerPlugin.register(with: registry.registrar(forPlugin: "MobileScannerPlugin"))
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
RecordPlugin.register(with: registry.registrar(forPlugin: "RecordPlugin"))
SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))
diff --git a/pubspec.lock b/pubspec.lock
index d081ec0..b76436d 100644
--- a/pubspec.lock
+++ b/pubspec.lock
@@ -320,6 +320,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.15.0"
+ mobile_scanner:
+ dependency: "direct main"
+ description:
+ name: mobile_scanner
+ sha256: "91d28b825784e15572fdc39165c5733099ce0e69c6f6f0964ebdbf98a62130fd"
+ url: "https://pub.dev"
+ source: hosted
+ version: "6.0.6"
path:
dependency: transitive
description:
diff --git a/pubspec.yaml b/pubspec.yaml
index 3d18441..7c58398 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -49,6 +49,7 @@ dependencies:
audioplayers: ^6.2.0
toastification: ^2.3.0
record: ^5.2.1
+ mobile_scanner: ^6.0.6
dev_dependencies:
flutter_test: