diff --git a/apps/mobile/apps/client/android/app/src/main/java/io/flutter/plugins/GeneratedPluginRegistrant.java b/apps/mobile/apps/client/android/app/src/main/java/io/flutter/plugins/GeneratedPluginRegistrant.java index f3808646..e6d40294 100644 --- a/apps/mobile/apps/client/android/app/src/main/java/io/flutter/plugins/GeneratedPluginRegistrant.java +++ b/apps/mobile/apps/client/android/app/src/main/java/io/flutter/plugins/GeneratedPluginRegistrant.java @@ -50,6 +50,11 @@ public final class GeneratedPluginRegistrant { } catch (Exception e) { Log.e(TAG, "Error registering plugin path_provider_android, io.flutter.plugins.pathprovider.PathProviderPlugin", e); } + try { + flutterEngine.getPlugins().add(new com.llfbandit.record.RecordPlugin()); + } catch (Exception e) { + Log.e(TAG, "Error registering plugin record_android, com.llfbandit.record.RecordPlugin", e); + } try { flutterEngine.getPlugins().add(new io.flutter.plugins.sharedpreferences.SharedPreferencesPlugin()); } catch (Exception e) { diff --git a/apps/mobile/apps/client/linux/flutter/generated_plugin_registrant.cc b/apps/mobile/apps/client/linux/flutter/generated_plugin_registrant.cc index 7299b5cf..adc5a9fe 100644 --- a/apps/mobile/apps/client/linux/flutter/generated_plugin_registrant.cc +++ b/apps/mobile/apps/client/linux/flutter/generated_plugin_registrant.cc @@ -7,12 +7,16 @@ #include "generated_plugin_registrant.h" #include +#include #include void fl_register_plugins(FlPluginRegistry* registry) { g_autoptr(FlPluginRegistrar) file_selector_linux_registrar = fl_plugin_registry_get_registrar_for_plugin(registry, "FileSelectorPlugin"); file_selector_plugin_register_with_registrar(file_selector_linux_registrar); + g_autoptr(FlPluginRegistrar) record_linux_registrar = + fl_plugin_registry_get_registrar_for_plugin(registry, "RecordLinuxPlugin"); + record_linux_plugin_register_with_registrar(record_linux_registrar); g_autoptr(FlPluginRegistrar) url_launcher_linux_registrar = fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin"); url_launcher_plugin_register_with_registrar(url_launcher_linux_registrar); diff --git a/apps/mobile/apps/client/linux/flutter/generated_plugins.cmake b/apps/mobile/apps/client/linux/flutter/generated_plugins.cmake index 786ff5c2..1262bd6f 100644 --- a/apps/mobile/apps/client/linux/flutter/generated_plugins.cmake +++ b/apps/mobile/apps/client/linux/flutter/generated_plugins.cmake @@ -4,6 +4,7 @@ list(APPEND FLUTTER_PLUGIN_LIST file_selector_linux + record_linux url_launcher_linux ) diff --git a/apps/mobile/apps/client/windows/flutter/generated_plugin_registrant.cc b/apps/mobile/apps/client/windows/flutter/generated_plugin_registrant.cc index 3a3369d4..3c9a7f78 100644 --- a/apps/mobile/apps/client/windows/flutter/generated_plugin_registrant.cc +++ b/apps/mobile/apps/client/windows/flutter/generated_plugin_registrant.cc @@ -9,6 +9,7 @@ #include #include #include +#include #include void RegisterPlugins(flutter::PluginRegistry* registry) { @@ -18,6 +19,8 @@ void RegisterPlugins(flutter::PluginRegistry* registry) { registry->GetRegistrarForPlugin("FirebaseAuthPluginCApi")); FirebaseCorePluginCApiRegisterWithRegistrar( registry->GetRegistrarForPlugin("FirebaseCorePluginCApi")); + RecordWindowsPluginCApiRegisterWithRegistrar( + registry->GetRegistrarForPlugin("RecordWindowsPluginCApi")); UrlLauncherWindowsRegisterWithRegistrar( registry->GetRegistrarForPlugin("UrlLauncherWindows")); } diff --git a/apps/mobile/apps/client/windows/flutter/generated_plugins.cmake b/apps/mobile/apps/client/windows/flutter/generated_plugins.cmake index b9b24c8b..f2ab3101 100644 --- a/apps/mobile/apps/client/windows/flutter/generated_plugins.cmake +++ b/apps/mobile/apps/client/windows/flutter/generated_plugins.cmake @@ -6,6 +6,7 @@ list(APPEND FLUTTER_PLUGIN_LIST file_selector_windows firebase_auth firebase_core + record_windows url_launcher_windows ) diff --git a/apps/mobile/apps/staff/android/app/src/main/java/io/flutter/plugins/GeneratedPluginRegistrant.java b/apps/mobile/apps/staff/android/app/src/main/java/io/flutter/plugins/GeneratedPluginRegistrant.java index fbdc8215..14bcfe40 100644 --- a/apps/mobile/apps/staff/android/app/src/main/java/io/flutter/plugins/GeneratedPluginRegistrant.java +++ b/apps/mobile/apps/staff/android/app/src/main/java/io/flutter/plugins/GeneratedPluginRegistrant.java @@ -65,6 +65,11 @@ public final class GeneratedPluginRegistrant { } catch (Exception e) { Log.e(TAG, "Error registering plugin permission_handler_android, com.baseflow.permissionhandler.PermissionHandlerPlugin", e); } + try { + flutterEngine.getPlugins().add(new com.llfbandit.record.RecordPlugin()); + } catch (Exception e) { + Log.e(TAG, "Error registering plugin record_android, com.llfbandit.record.RecordPlugin", e); + } try { flutterEngine.getPlugins().add(new io.flutter.plugins.sharedpreferences.SharedPreferencesPlugin()); } catch (Exception e) { diff --git a/apps/mobile/apps/staff/linux/flutter/generated_plugin_registrant.cc b/apps/mobile/apps/staff/linux/flutter/generated_plugin_registrant.cc index 7299b5cf..adc5a9fe 100644 --- a/apps/mobile/apps/staff/linux/flutter/generated_plugin_registrant.cc +++ b/apps/mobile/apps/staff/linux/flutter/generated_plugin_registrant.cc @@ -7,12 +7,16 @@ #include "generated_plugin_registrant.h" #include +#include #include void fl_register_plugins(FlPluginRegistry* registry) { g_autoptr(FlPluginRegistrar) file_selector_linux_registrar = fl_plugin_registry_get_registrar_for_plugin(registry, "FileSelectorPlugin"); file_selector_plugin_register_with_registrar(file_selector_linux_registrar); + g_autoptr(FlPluginRegistrar) record_linux_registrar = + fl_plugin_registry_get_registrar_for_plugin(registry, "RecordLinuxPlugin"); + record_linux_plugin_register_with_registrar(record_linux_registrar); g_autoptr(FlPluginRegistrar) url_launcher_linux_registrar = fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin"); url_launcher_plugin_register_with_registrar(url_launcher_linux_registrar); diff --git a/apps/mobile/apps/staff/linux/flutter/generated_plugins.cmake b/apps/mobile/apps/staff/linux/flutter/generated_plugins.cmake index 786ff5c2..1262bd6f 100644 --- a/apps/mobile/apps/staff/linux/flutter/generated_plugins.cmake +++ b/apps/mobile/apps/staff/linux/flutter/generated_plugins.cmake @@ -4,6 +4,7 @@ list(APPEND FLUTTER_PLUGIN_LIST file_selector_linux + record_linux url_launcher_linux ) diff --git a/apps/mobile/apps/staff/windows/flutter/generated_plugin_registrant.cc b/apps/mobile/apps/staff/windows/flutter/generated_plugin_registrant.cc index f06cf63c..b6746a97 100644 --- a/apps/mobile/apps/staff/windows/flutter/generated_plugin_registrant.cc +++ b/apps/mobile/apps/staff/windows/flutter/generated_plugin_registrant.cc @@ -11,6 +11,7 @@ #include #include #include +#include #include void RegisterPlugins(flutter::PluginRegistry* registry) { @@ -24,6 +25,8 @@ void RegisterPlugins(flutter::PluginRegistry* registry) { registry->GetRegistrarForPlugin("GeolocatorWindows")); PermissionHandlerWindowsPluginRegisterWithRegistrar( registry->GetRegistrarForPlugin("PermissionHandlerWindowsPlugin")); + RecordWindowsPluginCApiRegisterWithRegistrar( + registry->GetRegistrarForPlugin("RecordWindowsPluginCApi")); UrlLauncherWindowsRegisterWithRegistrar( registry->GetRegistrarForPlugin("UrlLauncherWindows")); } diff --git a/apps/mobile/apps/staff/windows/flutter/generated_plugins.cmake b/apps/mobile/apps/staff/windows/flutter/generated_plugins.cmake index e3928570..589f702c 100644 --- a/apps/mobile/apps/staff/windows/flutter/generated_plugins.cmake +++ b/apps/mobile/apps/staff/windows/flutter/generated_plugins.cmake @@ -8,6 +8,7 @@ list(APPEND FLUTTER_PLUGIN_LIST firebase_core geolocator_windows permission_handler_windows + record_windows url_launcher_windows ) diff --git a/apps/mobile/packages/core/lib/core.dart b/apps/mobile/packages/core/lib/core.dart index e5dff061..d76a363f 100644 --- a/apps/mobile/packages/core/lib/core.dart +++ b/apps/mobile/packages/core/lib/core.dart @@ -23,9 +23,12 @@ export 'src/services/api_service/core_api_services/llm/llm_service.dart'; export 'src/services/api_service/core_api_services/llm/llm_response.dart'; export 'src/services/api_service/core_api_services/verification/verification_service.dart'; export 'src/services/api_service/core_api_services/verification/verification_response.dart'; +export 'src/services/api_service/core_api_services/rapid_order/rapid_order_service.dart'; +export 'src/services/api_service/core_api_services/rapid_order/rapid_order_response.dart'; // Device Services export 'src/services/device/camera/camera_service.dart'; export 'src/services/device/gallery/gallery_service.dart'; export 'src/services/device/file/file_picker_service.dart'; export 'src/services/device/file_upload/device_file_upload_service.dart'; +export 'src/services/device/audio/audio_recorder_service.dart'; diff --git a/apps/mobile/packages/core/lib/src/core_module.dart b/apps/mobile/packages/core/lib/src/core_module.dart index bd782a8a..3f1c9f0c 100644 --- a/apps/mobile/packages/core/lib/src/core_module.dart +++ b/apps/mobile/packages/core/lib/src/core_module.dart @@ -29,6 +29,9 @@ class CoreModule extends Module { () => VerificationService(i.get()), ); i.addSingleton(() => LlmService(i.get())); + i.addSingleton( + () => RapidOrderService(i.get()), + ); // 4. Register Device dependency i.addSingleton(() => ImagePicker()); @@ -37,6 +40,7 @@ class CoreModule extends Module { i.addSingleton(() => CameraService(i.get())); i.addSingleton(() => GalleryService(i.get())); i.addSingleton(FilePickerService.new); + i.addSingleton(AudioRecorderService.new); i.addSingleton( () => DeviceFileUploadService( cameraService: i.get(), diff --git a/apps/mobile/packages/core/lib/src/services/api_service/core_api_services/core_api_endpoints.dart b/apps/mobile/packages/core/lib/src/services/api_service/core_api_services/core_api_endpoints.dart index 1c2a80cd..89dd46d9 100644 --- a/apps/mobile/packages/core/lib/src/services/api_service/core_api_services/core_api_endpoints.dart +++ b/apps/mobile/packages/core/lib/src/services/api_service/core_api_services/core_api_endpoints.dart @@ -30,4 +30,11 @@ class CoreApiEndpoints { /// Retry a verification job. static String verificationRetry(String id) => '$baseUrl/core/verifications/$id/retry'; + + /// Transcribe audio to text for rapid orders. + static const String transcribeRapidOrder = + '$baseUrl/core/rapid-orders/transcribe'; + + /// Parse text to structured rapid order. + static const String parseRapidOrder = '$baseUrl/core/rapid-orders/parse'; } diff --git a/apps/mobile/packages/core/lib/src/services/api_service/core_api_services/rapid_order/rapid_order_response.dart b/apps/mobile/packages/core/lib/src/services/api_service/core_api_services/rapid_order/rapid_order_response.dart new file mode 100644 index 00000000..eeefb7fc --- /dev/null +++ b/apps/mobile/packages/core/lib/src/services/api_service/core_api_services/rapid_order/rapid_order_response.dart @@ -0,0 +1,239 @@ +/// Response model for RAPID order transcription. +class RapidOrderTranscriptionResponse { + /// Creates a [RapidOrderTranscriptionResponse]. + const RapidOrderTranscriptionResponse({ + required this.transcript, + required this.confidence, + required this.language, + required this.warnings, + required this.model, + }); + + /// Factory to create [RapidOrderTranscriptionResponse] from JSON. + factory RapidOrderTranscriptionResponse.fromJson(Map json) { + return RapidOrderTranscriptionResponse( + transcript: json['transcript'] as String, + confidence: (json['confidence'] as num).toDouble(), + language: json['language'] as String, + warnings: List.from(json['warnings'] as Iterable), + model: json['model'] as String, + ); + } + + /// The transcribed text. + final String transcript; + + /// Confidence score (0.0 to 1.0). + final double confidence; + + /// Language code. + final String language; + + /// Any warnings from the transcription process. + final List warnings; + + /// The model name used for transcription. + final String model; + + /// Converts the response to a JSON map. + Map toJson() { + return { + 'transcript': transcript, + 'confidence': confidence, + 'language': language, + 'warnings': warnings, + 'model': model, + }; + } +} + +/// Response model for RAPID order parsing. +class RapidOrderParseResponse { + /// Creates a [RapidOrderParseResponse]. + const RapidOrderParseResponse({ + required this.parsed, + required this.missingFields, + required this.warnings, + required this.confidence, + required this.model, + }); + + /// Factory to create [RapidOrderParseResponse] from JSON. + factory RapidOrderParseResponse.fromJson(Map json) { + return RapidOrderParseResponse( + parsed: RapidOrderParsedData.fromJson( + json['parsed'] as Map, + ), + missingFields: List.from( + json['missingFields'] as Iterable, + ), + warnings: List.from(json['warnings'] as Iterable), + confidence: RapidOrderParseConfidence.fromJson( + json['confidence'] as Map, + ), + model: json['model'] as String, + ); + } + + /// The parsed order data. + final RapidOrderParsedData parsed; + + /// Fields that were identified as missing from the input. + final List missingFields; + + /// Any warnings from the parsing process. + final List warnings; + + /// Confidence scores. + final RapidOrderParseConfidence confidence; + + /// The model name used for parsing. + final String model; + + /// Converts the response to a JSON map. + Map toJson() { + return { + 'parsed': parsed.toJson(), + 'missingFields': missingFields, + 'warnings': warnings, + 'confidence': confidence.toJson(), + 'model': model, + }; + } +} + +/// Parsed data for a rapid order. +class RapidOrderParsedData { + /// Creates a [RapidOrderParsedData]. + const RapidOrderParsedData({ + required this.orderType, + required this.isRapid, + required this.positions, + required this.sourceText, + this.startAt, + this.endAt, + this.durationMinutes, + this.locationHint, + this.notes, + }); + + /// Factory to create [RapidOrderParsedData] from JSON. + factory RapidOrderParsedData.fromJson(Map json) { + return RapidOrderParsedData( + orderType: json['orderType'] as String, + isRapid: json['isRapid'] as bool, + positions: (json['positions'] as List) + .map( + (dynamic e) => + RapidOrderPosition.fromJson(e as Map), + ) + .toList(), + sourceText: json['sourceText'] as String, + startAt: json['startAt'] as String?, + endAt: json['endAt'] as String?, + durationMinutes: json['durationMinutes'] as int?, + locationHint: json['locationHint'] as String?, + notes: json['notes'] as String?, + ); + } + + /// The type of order (typically ONE_TIME). + final String orderType; + + /// Whether this is a rapid order. + final bool isRapid; + + /// The requested positions. + final List positions; + + /// The source text that was parsed. + final String sourceText; + + /// ISO datetime string for the start of the order. + final String? startAt; + + /// ISO datetime string for the end of the order. + final String? endAt; + + /// Duration in minutes. + final int? durationMinutes; + + /// Hint about the location. + final String? locationHint; + + /// Any notes captured from the input. + final String? notes; + + /// Converts to a JSON map. + Map toJson() { + return { + 'orderType': orderType, + 'isRapid': isRapid, + 'positions': positions.map((RapidOrderPosition e) => e.toJson()).toList(), + 'sourceText': sourceText, + if (startAt != null) 'startAt': startAt, + if (endAt != null) 'endAt': endAt, + if (durationMinutes != null) 'durationMinutes': durationMinutes, + if (locationHint != null) 'locationHint': locationHint, + if (notes != null) 'notes': notes, + }; + } +} + +/// A position within a rapid order. +class RapidOrderPosition { + /// Creates a [RapidOrderPosition]. + const RapidOrderPosition({required this.role, required this.count}); + + /// Factory to create [RapidOrderPosition] from JSON. + factory RapidOrderPosition.fromJson(Map json) { + return RapidOrderPosition( + role: json['role'] as String, + count: json['count'] as int, + ); + } + + /// The role name. + final String role; + + /// Number of people needed for this role. + final int count; + + /// Converts to a JSON map. + Map toJson() { + return {'role': role, 'count': count}; + } +} + +/// Confidence scores for a rapid order parse. +class RapidOrderParseConfidence { + /// Creates a [RapidOrderParseConfidence]. + const RapidOrderParseConfidence({ + required this.overall, + required this.fields, + }); + + /// Factory to create [RapidOrderParseConfidence] from JSON. + factory RapidOrderParseConfidence.fromJson(Map json) { + return RapidOrderParseConfidence( + overall: (json['overall'] as num).toDouble(), + fields: Map.from( + (json['fields'] as Map).map( + (String k, dynamic v) => + MapEntry(k, (v as num).toDouble()), + ), + ), + ); + } + + /// Overall confidence score (0.0 to 1.0). + final double overall; + + /// Confidence scores for specific fields. + final Map fields; + + /// Converts to a JSON map. + Map toJson() { + return {'overall': overall, 'fields': fields}; + } +} diff --git a/apps/mobile/packages/core/lib/src/services/api_service/core_api_services/rapid_order/rapid_order_service.dart b/apps/mobile/packages/core/lib/src/services/api_service/core_api_services/rapid_order/rapid_order_service.dart new file mode 100644 index 00000000..5715d9ec --- /dev/null +++ b/apps/mobile/packages/core/lib/src/services/api_service/core_api_services/rapid_order/rapid_order_service.dart @@ -0,0 +1,70 @@ +import 'package:krow_domain/krow_domain.dart'; +import '../core_api_endpoints.dart'; +import 'rapid_order_response.dart'; + +/// Service for handling RAPID order operations (Transcription and Parsing). +class RapidOrderService extends BaseCoreService { + /// Creates a [RapidOrderService]. + RapidOrderService(super.api); + + /// Transcribes audio from a file to text for a RAPID order. + /// + /// [audioFileUri] is the URI of the audio file to transcribe. + /// [locale] is the optional locale hint (default: 'en-US'). + /// [promptHints] are optional domain hints to improve transcription quality. + Future transcribeAudio({ + required String audioFileUri, + String locale = 'en-US', + List? promptHints, + }) async { + final ApiResponse res = await action(() async { + return api.post( + CoreApiEndpoints.transcribeRapidOrder, + data: { + 'audioFileUri': audioFileUri, + 'locale': locale, + if (promptHints != null) 'promptHints': promptHints, + }, + ); + }); + + if (res.code.startsWith('2')) { + return RapidOrderTranscriptionResponse.fromJson( + res.data as Map, + ); + } + + throw Exception(res.message); + } + + /// Parses text into a structured RAPID order draft JSON. + /// + /// [text] is the input text to parse. + /// [locale] is the optional locale hint (default: 'en-US'). + /// [timezone] is the optional IANA timezone hint. + /// [now] is an optional current ISO datetime for reference. + Future parseText({ + required String text, + String locale = 'en-US', + String? timezone, + String? now, + }) async { + final ApiResponse res = await action(() async { + return api.post( + CoreApiEndpoints.parseRapidOrder, + data: { + 'text': text, + 'locale': locale, + if (timezone != null) 'timezone': timezone, + if (now != null) 'now': now, + }, + ); + }); + + if (res.code.startsWith('2')) { + return RapidOrderParseResponse.fromJson(res.data as Map); + } + + throw Exception(res.message); + } +} diff --git a/apps/mobile/packages/core/lib/src/services/device/audio/audio_recorder_service.dart b/apps/mobile/packages/core/lib/src/services/device/audio/audio_recorder_service.dart new file mode 100644 index 00000000..dd31512a --- /dev/null +++ b/apps/mobile/packages/core/lib/src/services/device/audio/audio_recorder_service.dart @@ -0,0 +1,55 @@ +import 'dart:io'; +import 'package:path_provider/path_provider.dart'; +import 'package:record/record.dart'; +import 'package:krow_domain/krow_domain.dart'; + +/// Service for recording audio using the device microphone. +class AudioRecorderService extends BaseDeviceService { + /// Creates an [AudioRecorderService]. + AudioRecorderService() : _recorder = AudioRecorder(); + + final AudioRecorder _recorder; + + /// Starts recording audio to a temporary file. + /// + /// Returns the path where the audio is being recorded. + Future startRecording() async { + return action(() async { + if (await _recorder.hasPermission()) { + final Directory tempDir = await getTemporaryDirectory(); + final String path = + '${tempDir.path}/rapid_order_audio_${DateTime.now().millisecondsSinceEpoch}.m4a'; + + // Configure the recording + const RecordConfig config = RecordConfig( + encoder: AudioEncoder.aacLc, // Good balance of quality and size + bitRate: 128000, + sampleRate: 44100, + ); + + await _recorder.start(config, path: path); + } else { + throw Exception('Microphone permission not granted'); + } + }); + } + + /// Stops the current recording. + /// + /// Returns the path to the recorded audio file, or null if no recording was active. + Future stopRecording() async { + return action(() async { + return await _recorder.stop(); + }); + } + + /// Checks if the recorder is currently recording. + Future isRecording() async { + return await _recorder.isRecording(); + } + + /// Disposes the recorder resources. + void dispose() { + _recorder.dispose(); + } +} diff --git a/apps/mobile/packages/design_system/lib/src/ui_icons.dart b/apps/mobile/packages/design_system/lib/src/ui_icons.dart index 24801c39..f9d97f3e 100644 --- a/apps/mobile/packages/design_system/lib/src/ui_icons.dart +++ b/apps/mobile/packages/design_system/lib/src/ui_icons.dart @@ -285,4 +285,7 @@ class UiIcons { /// Circle dollar icon static const IconData circleDollar = _IconLib.circleDollarSign; + + /// Microphone icon + static const IconData microphone = _IconLib.mic; } diff --git a/apps/mobile/packages/features/client/orders/create_order/lib/src/domain/usecases/transcribe_rapid_order_usecase.dart b/apps/mobile/packages/features/client/orders/create_order/lib/src/domain/usecases/transcribe_rapid_order_usecase.dart new file mode 100644 index 00000000..b805ff53 --- /dev/null +++ b/apps/mobile/packages/features/client/orders/create_order/lib/src/domain/usecases/transcribe_rapid_order_usecase.dart @@ -0,0 +1,16 @@ +import '../repositories/client_create_order_repository_interface.dart'; + +/// Use case for transcribing audio for a rapid order. +class TranscribeRapidOrderUseCase { + /// Creates a [TranscribeRapidOrderUseCase]. + TranscribeRapidOrderUseCase(this._repository); + + final ClientCreateOrderRepositoryInterface _repository; + + /// Executes the use case. + /// + /// [audioPath] is the local path to the audio file. + Future call(String audioPath) async { + return _repository.transcribeRapidOrder(audioPath); + } +} diff --git a/apps/mobile/packages/features/client/orders/create_order/lib/src/presentation/widgets/rapid_order/rapid_order_view.dart b/apps/mobile/packages/features/client/orders/create_order/lib/src/presentation/widgets/rapid_order/rapid_order_view.dart index f15757c2..f306e312 100644 --- a/apps/mobile/packages/features/client/orders/create_order/lib/src/presentation/widgets/rapid_order/rapid_order_view.dart +++ b/apps/mobile/packages/features/client/orders/create_order/lib/src/presentation/widgets/rapid_order/rapid_order_view.dart @@ -29,7 +29,7 @@ class RapidOrderView extends StatelessWidget { title: labels.success_title, message: labels.success_message, buttonLabel: labels.back_to_orders, - onDone: () => Modular.to.navigate(ClientPaths.orders), + onDone: () => Modular.to.toClientOrders(), ); } @@ -280,7 +280,7 @@ class _RapidOrderActions extends StatelessWidget { Expanded( child: UiButton.secondary( text: isListening ? labels.listening : labels.speak, - leadingIcon: UiIcons.bell, // Placeholder for mic + leadingIcon: UiIcons.microphone, onPressed: () => BlocProvider.of( context, ).add(const RapidOrderVoiceToggled()), diff --git a/apps/mobile/packages/features/client/orders/orders_common/linux/flutter/generated_plugin_registrant.cc b/apps/mobile/packages/features/client/orders/orders_common/linux/flutter/generated_plugin_registrant.cc index 64a0ecea..a81c4d4a 100644 --- a/apps/mobile/packages/features/client/orders/orders_common/linux/flutter/generated_plugin_registrant.cc +++ b/apps/mobile/packages/features/client/orders/orders_common/linux/flutter/generated_plugin_registrant.cc @@ -7,9 +7,13 @@ #include "generated_plugin_registrant.h" #include +#include void fl_register_plugins(FlPluginRegistry* registry) { g_autoptr(FlPluginRegistrar) file_selector_linux_registrar = fl_plugin_registry_get_registrar_for_plugin(registry, "FileSelectorPlugin"); file_selector_plugin_register_with_registrar(file_selector_linux_registrar); + g_autoptr(FlPluginRegistrar) record_linux_registrar = + fl_plugin_registry_get_registrar_for_plugin(registry, "RecordLinuxPlugin"); + record_linux_plugin_register_with_registrar(record_linux_registrar); } diff --git a/apps/mobile/packages/features/client/orders/orders_common/linux/flutter/generated_plugins.cmake b/apps/mobile/packages/features/client/orders/orders_common/linux/flutter/generated_plugins.cmake index 2db3c22a..9609b4d7 100644 --- a/apps/mobile/packages/features/client/orders/orders_common/linux/flutter/generated_plugins.cmake +++ b/apps/mobile/packages/features/client/orders/orders_common/linux/flutter/generated_plugins.cmake @@ -4,6 +4,7 @@ list(APPEND FLUTTER_PLUGIN_LIST file_selector_linux + record_linux ) list(APPEND FLUTTER_FFI_PLUGIN_LIST diff --git a/apps/mobile/packages/features/client/orders/orders_common/windows/flutter/generated_plugin_registrant.cc b/apps/mobile/packages/features/client/orders/orders_common/windows/flutter/generated_plugin_registrant.cc index 5861e0f0..ec331e03 100644 --- a/apps/mobile/packages/features/client/orders/orders_common/windows/flutter/generated_plugin_registrant.cc +++ b/apps/mobile/packages/features/client/orders/orders_common/windows/flutter/generated_plugin_registrant.cc @@ -9,6 +9,7 @@ #include #include #include +#include void RegisterPlugins(flutter::PluginRegistry* registry) { FileSelectorWindowsRegisterWithRegistrar( @@ -17,4 +18,6 @@ void RegisterPlugins(flutter::PluginRegistry* registry) { registry->GetRegistrarForPlugin("FirebaseAuthPluginCApi")); FirebaseCorePluginCApiRegisterWithRegistrar( registry->GetRegistrarForPlugin("FirebaseCorePluginCApi")); + RecordWindowsPluginCApiRegisterWithRegistrar( + registry->GetRegistrarForPlugin("RecordWindowsPluginCApi")); } diff --git a/apps/mobile/packages/features/client/orders/orders_common/windows/flutter/generated_plugins.cmake b/apps/mobile/packages/features/client/orders/orders_common/windows/flutter/generated_plugins.cmake index ce851e9d..0125068a 100644 --- a/apps/mobile/packages/features/client/orders/orders_common/windows/flutter/generated_plugins.cmake +++ b/apps/mobile/packages/features/client/orders/orders_common/windows/flutter/generated_plugins.cmake @@ -6,6 +6,7 @@ list(APPEND FLUTTER_PLUGIN_LIST file_selector_windows firebase_auth firebase_core + record_windows ) list(APPEND FLUTTER_FFI_PLUGIN_LIST