feat(voice): integrate one-shot voice capture into Quick Capture bar
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+30
-1
@@ -29,6 +29,8 @@ import 'screens/settings/settings_screen.dart';
|
||||
import 'screens/setup/setup_screen.dart';
|
||||
import 'screens/splash/splash_screen.dart';
|
||||
import 'screens/tasks/task_edit_screen.dart';
|
||||
import 'providers/voice_provider.dart';
|
||||
import 'widgets/voice_mic_button.dart';
|
||||
|
||||
// ChangeNotifier that fires when auth or server URL changes,
|
||||
// used as GoRouter.refreshListenable so the router re-evaluates redirects
|
||||
@@ -399,6 +401,7 @@ class _QuickCaptureBarState extends ConsumerState<_QuickCaptureBar> {
|
||||
@override
|
||||
void dispose() {
|
||||
_controller.dispose();
|
||||
ref.read(voiceProvider.notifier).exitVoiceMode();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@@ -440,6 +443,25 @@ class _QuickCaptureBarState extends ConsumerState<_QuickCaptureBar> {
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _toggleCaptureMic() async {
|
||||
final voice = ref.read(voiceProvider);
|
||||
if (voice.voiceModeActive) {
|
||||
ref.read(voiceProvider.notifier).exitVoiceMode();
|
||||
return;
|
||||
}
|
||||
await ref.read(voiceProvider.notifier).enterVoiceMode(
|
||||
onTranscript: (transcript) async {
|
||||
ref.read(captureWorkQueueProvider.notifier).enqueue(transcript);
|
||||
},
|
||||
enableTts: false,
|
||||
onError: (msg) {
|
||||
if (!mounted) return;
|
||||
ScaffoldMessenger.of(context)
|
||||
.showSnackBar(SnackBar(content: Text(msg)));
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
String _hintForLocation(String location) {
|
||||
if (location.startsWith(Routes.knowledge)) return 'Capture a note…';
|
||||
if (location.startsWith(Routes.projects)) return 'Capture a note…';
|
||||
@@ -482,7 +504,9 @@ class _QuickCaptureBarState extends ConsumerState<_QuickCaptureBar> {
|
||||
onSubmitted: (_) => _submit(),
|
||||
onChanged: (_) => setState(() {}),
|
||||
decoration: InputDecoration(
|
||||
hintText: _hintForLocation(location),
|
||||
hintText: ref.watch(voiceProvider).voiceModeActive
|
||||
? 'Listening…'
|
||||
: _hintForLocation(location),
|
||||
isDense: true,
|
||||
contentPadding: const EdgeInsets.symmetric(
|
||||
horizontal: 14, vertical: 10),
|
||||
@@ -512,6 +536,11 @@ class _QuickCaptureBarState extends ConsumerState<_QuickCaptureBar> {
|
||||
),
|
||||
),
|
||||
),
|
||||
VoiceMicButton(
|
||||
mode: ref.watch(voiceProvider).mode,
|
||||
voiceModeActive: ref.watch(voiceProvider).voiceModeActive,
|
||||
onTap: _toggleCaptureMic,
|
||||
),
|
||||
IconButton(
|
||||
icon: const Icon(Icons.settings_outlined),
|
||||
tooltip: 'Settings',
|
||||
|
||||
Reference in New Issue
Block a user