Fix local dev config and ALOTTTT OFF FLUTTER, im tired boss..
This commit is contained in:
@@ -4,6 +4,9 @@ import 'package:flutter/material.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
|
||||
import '../../app/injection_container.dart';
|
||||
import '../../core/errors/friendly_error.dart';
|
||||
import '../../core/network/api_client.dart';
|
||||
import '../../core/services/hardware_shortcut_listener.dart';
|
||||
import '../../core/services/stt_service.dart';
|
||||
import '../../core/services/tts_service.dart';
|
||||
import '../../core/services/voice_command_handler.dart';
|
||||
@@ -20,6 +23,8 @@ class _UserShellState extends State<UserShell> {
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_loadVoiceCommands();
|
||||
_startHardwareShortcuts();
|
||||
sl<SttService>().startListening();
|
||||
sl<VoiceCommandHandler>().onCommand = (key) {
|
||||
if (!mounted) return;
|
||||
@@ -58,6 +63,70 @@ class _UserShellState extends State<UserShell> {
|
||||
};
|
||||
}
|
||||
|
||||
Future<void> _loadVoiceCommands() async {
|
||||
await runFriendlyAction(
|
||||
() async {
|
||||
final res = await sl<ApiClient>()
|
||||
.dio
|
||||
.get('/user/voice-commands')
|
||||
.timeout(const Duration(seconds: 8));
|
||||
final body = res.data;
|
||||
final data = body is Map ? body['data'] : body;
|
||||
if (data is! List) return;
|
||||
final commands = data
|
||||
.whereType<Map>()
|
||||
.map((item) => _voiceCommandFromJson(Map<String, dynamic>.from(item)))
|
||||
.whereType<VoiceCommand>()
|
||||
.toList();
|
||||
if (commands.isNotEmpty) {
|
||||
sl<VoiceCommandHandler>().loadCommands(commands);
|
||||
}
|
||||
},
|
||||
onError: (_) {},
|
||||
fallback: 'Voice command belum bisa dimuat.',
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> _startHardwareShortcuts() async {
|
||||
await runFriendlyAction(
|
||||
() => sl<HardwareShortcutListener>().startListening(
|
||||
onAction: (action) {
|
||||
if (!mounted) return;
|
||||
switch (action) {
|
||||
case HardwareShortcutAction.callGuardian:
|
||||
context.go('/user/call');
|
||||
sl<TtsService>().speak('Memanggil guardian');
|
||||
break;
|
||||
case HardwareShortcutAction.startWalkguide:
|
||||
context.go('/user/walkguide');
|
||||
sl<TtsService>().speak('WalkGuide dibuka');
|
||||
break;
|
||||
case HardwareShortcutAction.stopWalkguide:
|
||||
context.go('/user/walkguide');
|
||||
sl<TtsService>().speak('WalkGuide dibuka untuk dihentikan');
|
||||
break;
|
||||
case HardwareShortcutAction.sendSos:
|
||||
context.go('/user/sos');
|
||||
sl<TtsService>().speak('SOS dibuka');
|
||||
break;
|
||||
case HardwareShortcutAction.openNotification:
|
||||
context.go('/user/notifications');
|
||||
sl<TtsService>().speak('Notifikasi dibuka');
|
||||
break;
|
||||
}
|
||||
},
|
||||
),
|
||||
onError: (_) {},
|
||||
fallback: 'Hardware shortcut belum bisa dimuat.',
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
sl<HardwareShortcutListener>().stopListening();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final location = GoRouterState.of(context).matchedLocation;
|
||||
@@ -169,3 +238,49 @@ String _spokenRouteName(VoiceCommandKey key) {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
VoiceCommand? _voiceCommandFromJson(Map<String, dynamic> item) {
|
||||
final key = _commandKeyFromBackend(item['commandKey']?.toString());
|
||||
final phrase = item['triggerPhrase']?.toString().trim();
|
||||
if (key == null || phrase == null || phrase.isEmpty) return null;
|
||||
return VoiceCommand(
|
||||
key: key,
|
||||
phrase: phrase,
|
||||
enabled: item['enabled'] != false,
|
||||
);
|
||||
}
|
||||
|
||||
VoiceCommandKey? _commandKeyFromBackend(String? key) {
|
||||
switch (key) {
|
||||
case 'OPEN_WALKGUIDE':
|
||||
return VoiceCommandKey.openWalkguide;
|
||||
case 'START_WALKGUIDE':
|
||||
return VoiceCommandKey.startWalkguide;
|
||||
case 'STOP_WALKGUIDE':
|
||||
return VoiceCommandKey.stopWalkguide;
|
||||
case 'CALL_GUARDIAN':
|
||||
return VoiceCommandKey.callGuardian;
|
||||
case 'OPEN_NOTIFICATION':
|
||||
return VoiceCommandKey.openNotification;
|
||||
case 'READ_ALL_NOTIF':
|
||||
return VoiceCommandKey.readAllNotif;
|
||||
case 'OPEN_SOS':
|
||||
return VoiceCommandKey.openSos;
|
||||
case 'SEND_SOS':
|
||||
return VoiceCommandKey.sendSos;
|
||||
case 'WHERE_AM_I':
|
||||
return VoiceCommandKey.whereAmI;
|
||||
case 'OPEN_ACTIVITY':
|
||||
return VoiceCommandKey.openActivity;
|
||||
case 'OPEN_NAVIGATION':
|
||||
return VoiceCommandKey.openNavigation;
|
||||
case 'OPEN_SETTINGS':
|
||||
return VoiceCommandKey.openSettings;
|
||||
case 'REPEAT_LAST':
|
||||
return VoiceCommandKey.repeatLast;
|
||||
case 'STOP_TTS':
|
||||
return VoiceCommandKey.stopTts;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user