toggle method
Toggle voice mode on or off.
Runs pre-flight checks (auth, feature flag, recording availability, mic permission) when enabling. Returns a VoiceToggleResult describing the outcome.
Implementation
Future<VoiceToggleResult> toggle() async {
// Gate: feature + auth
if (!isVoiceModeEnabled) {
if (!hasAuth) {
return const VoiceToggleError(
'Voice mode requires authentication. Please sign in first.',
);
}
return const VoiceToggleError('Voice mode is not available.');
}
final currentlyEnabled = config.readVoiceEnabled();
// Toggle OFF — no pre-flight needed.
if (currentlyEnabled) {
final ok = await config.saveVoiceEnabled(false);
if (!ok) {
return const VoiceToggleError(
'Failed to update settings. Check your settings file for errors.',
);
}
state = VoiceState.idle;
return const VoiceToggleSuccess(
enabled: false,
message: 'Voice mode disabled.',
);
}
// Toggle ON — pre-flight checks.
final recordingIssue = await config.checkRecordingAvailability();
if (recordingIssue != null) {
return VoiceToggleError(recordingIssue);
}
final micGranted = await config.requestMicrophonePermission();
if (!micGranted) {
return const VoiceToggleError(
'Microphone access is denied. Please grant microphone permission in '
'your device settings, then try again.',
);
}
// All checks passed.
final ok = await config.saveVoiceEnabled(true);
if (!ok) {
return const VoiceToggleError(
'Failed to update settings. Check your settings file for errors.',
);
}
final stt = normalizeLanguageForSTT(config.readLanguagePreference());
String langNote = '';
if (stt.fellBackFrom != null) {
langNote =
' Note: "${stt.fellBackFrom}" is not a supported dictation '
'language; using English. Change it in settings.';
} else if (stt.code != _defaultSttLanguage) {
langNote = ' Dictation language: ${stt.code}.';
}
return VoiceToggleSuccess(
enabled: true,
message: 'Voice mode enabled.$langNote',
sttLanguage: stt,
);
}