Voice Mode improvements

This commit is contained in:
JHubi1 2024-06-25 21:08:59 +02:00
parent 4d90f8611b
commit d768294458
No known key found for this signature in database
GPG Key ID: 7BF82570CBBBD050
3 changed files with 185 additions and 123 deletions

View File

@ -433,11 +433,22 @@
"description": "Text displayed while loading voice permissions", "description": "Text displayed while loading voice permissions",
"context": "Visible in the settings view" "context": "Visible in the settings view"
}, },
"settingsVoiceTtsNotSupported": "Text-to-speech not supported",
"@settingsVoiceTtsNotSupported": {
"description": "Text displayed when text-to-speech is not supported",
"context": "Visible in the settings view"
},
"settingsVoiceTtsNotSupportedDescription": "Text-to-speech services are not supported for the selected language. Select a different language in the language drawer to reenable them.\nOther services like voice recognition and AI thinking will still work as usual, but interaction might not be as fluent.",
"settingsVoicePermissionNot": "Permissions not granted", "settingsVoicePermissionNot": "Permissions not granted",
"@settingsVoicePermissionNot": { "@settingsVoicePermissionNot": {
"description": "Text displayed when voice permissions are not granted", "description": "Text displayed when voice permissions are not granted",
"context": "Visible in the settings view" "context": "Visible in the settings view"
}, },
"settingsVoiceNotEnabled": "Voice mode not enabled",
"@settingsVoiceNotEnabled": {
"description": "Text displayed when voice mode is not enabled",
"context": "Visible in the settings view"
},
"settingsVoiceNotSupported": "Voice mode not supported", "settingsVoiceNotSupported": "Voice mode not supported",
"@settingsVoiceNotSupported": { "@settingsVoiceNotSupported": {
"description": "Text displayed when voice mode is not supported", "description": "Text displayed when voice mode is not supported",

View File

@ -85,7 +85,7 @@ class _ScreenVoiceState extends State<ScreenVoice> {
text = ""; text = "";
speech.listen( speech.listen(
localeId: (prefs!.getString("voiceLanguage") ?? ""), localeId: (prefs!.getString("voiceLanguage") ?? "en-US"),
listenOptions: listenOptions:
stt.SpeechListenOptions(listenMode: stt.ListenMode.dictation), stt.SpeechListenOptions(listenMode: stt.ListenMode.dictation),
onResult: (result) { onResult: (result) {
@ -172,91 +172,93 @@ class _ScreenVoiceState extends State<ScreenVoice> {
lightHaptic(); lightHaptic();
}); });
if (done && // var volume = await VolumeController().getVolume();
(await voice.getLanguages as List).contains( // var voicesTmp1 = await voice.getLanguages;
(prefs!.getString("voiceLanguage") ?? "en_US") // var voices = jsonEncode(voicesTmp1);
.replaceAll("_", "-"))) { // var isVoiceAvailable = (await voice.isLanguageAvailable(
// (prefs!.getString("voiceLanguage") ?? "en_US")
// .replaceAll("_", "-")))
// .toString();
// var voices2Tmp1 = await speech.locales();
// var voices2Tmp2 = [];
// for (var voice in voices2Tmp1) {
// voices2Tmp2.add(voice.localeId.replaceAll("_", "-"));
// }
// var voices2 = jsonEncode(voices2Tmp2);
// await showDialog(
// // ignore: use_build_context_synchronously
// context: context,
// builder: (context) {
// return Dialog.fullscreen(
// child: ListView(children: [
// const Row(
// crossAxisAlignment: CrossAxisAlignment.center,
// mainAxisSize: MainAxisSize.max,
// children: [
// Expanded(child: Divider(color: Colors.red)),
// SizedBox(width: 8),
// Text("START", style: TextStyle(color: Colors.red)),
// SizedBox(width: 8),
// Expanded(child: Divider(color: Colors.red))
// ]),
// Text((prefs!.getString("voiceLanguage") ?? "en_US")
// .replaceAll("_", "-")),
// const Divider(),
// Text(volume.toString()),
// const Divider(),
// Text(voices),
// const Divider(),
// Text(voicesTmp1
// .contains((prefs!.getString("voiceLanguage") ?? "en_US")
// .replaceAll("_", "-"))
// .toString()),
// const Divider(),
// Text(isVoiceAvailable),
// const Divider(),
// Text(voices2),
// const Divider(),
// Text(voices2Tmp2
// .contains((prefs!.getString("voiceLanguage") ?? "en_US")
// .replaceAll("_", "-"))
// .toString()),
// const Divider(),
// Text(speech.isAvailable.toString()),
// const Row(
// crossAxisAlignment: CrossAxisAlignment.center,
// mainAxisSize: MainAxisSize.max,
// children: [
// Expanded(child: Divider(color: Colors.red)),
// SizedBox(width: 8),
// Text("END", style: TextStyle(color: Colors.red)),
// SizedBox(width: 8),
// Expanded(child: Divider(color: Colors.red))
// ])
// ]));
// });
if (done) {
aiThinking = false; aiThinking = false;
heavyHaptic(); heavyHaptic();
voice.setLanguage((prefs!.getString("voiceLanguage") ?? "en_US")
.replaceAll("_", "-"));
voice.setSpeechRate(0.6);
voice.setCompletionHandler(() async {
speaking = false;
try {
setState(() {});
} catch (_) {}
process();
});
var tmp = aiText;
tmp.replaceAll("-", ".");
tmp.replaceAll("*", ".");
// var volume = await VolumeController().getVolume(); if ((await voice.getLanguages as List).contains(
// var voicesTmp1 = await voice.getLanguages; (prefs!.getString("voiceLanguage") ?? "en_US")
// var voices = jsonEncode(voicesTmp1); .replaceAll("_", "-"))) {
// var isVoiceAvailable = (await voice.isLanguageAvailable( voice.setLanguage((prefs!.getString("voiceLanguage") ?? "en_US")
// (prefs!.getString("voiceLanguage") ?? "en_US") .replaceAll("_", "-"));
// .replaceAll("_", "-"))) voice.setSpeechRate(0.6);
// .toString(); voice.setCompletionHandler(() async {
// var voices2Tmp1 = await speech.locales(); speaking = false;
// var voices2Tmp2 = []; try {
// for (var voice in voices2Tmp1) { setState(() {});
// voices2Tmp2.add(voice.localeId.replaceAll("_", "-")); } catch (_) {}
// } process();
// var voices2 = jsonEncode(voices2Tmp2); });
// await showDialog( var tmp = aiText;
// // ignore: use_build_context_synchronously tmp.replaceAll("-", ".");
// context: context, tmp.replaceAll("*", ".");
// builder: (context) {
// return Dialog.fullscreen(
// child: ListView(children: [
// const Row(
// crossAxisAlignment: CrossAxisAlignment.center,
// mainAxisSize: MainAxisSize.max,
// children: [
// Expanded(child: Divider(color: Colors.red)),
// SizedBox(width: 8),
// Text("START", style: TextStyle(color: Colors.red)),
// SizedBox(width: 8),
// Expanded(child: Divider(color: Colors.red))
// ]),
// Text((prefs!.getString("voiceLanguage") ?? "en_US")
// .replaceAll("_", "-")),
// const Divider(),
// Text(volume.toString()),
// const Divider(),
// Text(voices),
// const Divider(),
// Text(voicesTmp1
// .contains((prefs!.getString("voiceLanguage") ?? "en_US")
// .replaceAll("_", "-"))
// .toString()),
// const Divider(),
// Text(isVoiceAvailable),
// const Divider(),
// Text(voices2),
// const Divider(),
// Text(voices2Tmp2
// .contains((prefs!.getString("voiceLanguage") ?? "en_US")
// .replaceAll("_", "-"))
// .toString()),
// const Divider(),
// Text(speech.isAvailable.toString()),
// const Row(
// crossAxisAlignment: CrossAxisAlignment.center,
// mainAxisSize: MainAxisSize.max,
// children: [
// Expanded(child: Divider(color: Colors.red)),
// SizedBox(width: 8),
// Text("END", style: TextStyle(color: Colors.red)),
// SizedBox(width: 8),
// Expanded(child: Divider(color: Colors.red))
// ])
// ]));
// });
voice.speak(tmp); voice.speak(tmp);
}
} }
}, },
addToSystem: (prefs!.getBool("voiceLimitLanguage") ?? true) addToSystem: (prefs!.getBool("voiceLimitLanguage") ?? true)

View File

@ -27,20 +27,35 @@ class _ScreenSettingsVoiceState extends State<ScreenSettingsVoice> {
Iterable<String> languageOptionIds = []; Iterable<String> languageOptionIds = [];
Iterable<String> languageOptions = []; Iterable<String> languageOptions = [];
List voiceLanguageOptionsAvailable = [];
List voiceLanguageOptions = [];
bool dialogMustLoad = true;
void load() async {
var tmp = await speech.locales();
languageOptionIds = tmp.map((e) => e.localeId);
languageOptions = tmp.map((e) => e.name);
permissionRecord = await Permission.microphone.isGranted;
permissionBluetooth = await Permission.bluetoothConnect.isGranted;
permissionLoading = false;
voiceLanguageOptions = await voice.getLanguages as List;
for (int i = 0; i < languageOptionIds.length; i++) {
if (voiceLanguageOptions
.contains(languageOptionIds.elementAt(i).replaceAll("_", "-"))) {
voiceLanguageOptionsAvailable.add(languageOptionIds.elementAt(i));
}
}
setState(() {});
}
@override @override
void initState() { void initState() {
super.initState(); super.initState();
void load() async {
var tmp = await speech.locales();
languageOptionIds = tmp.map((e) => e.localeId);
languageOptions = tmp.map((e) => e.name);
permissionRecord = await Permission.microphone.isGranted;
permissionBluetooth = await Permission.bluetoothConnect.isGranted;
permissionLoading = false;
setState(() {});
}
load(); load();
} }
@ -56,25 +71,48 @@ class _ScreenSettingsVoiceState extends State<ScreenSettingsVoice> {
child: Column(children: [ child: Column(children: [
Expanded( Expanded(
child: ListView(children: [ child: ListView(children: [
// const SizedBox(height: 8), (permissionLoading ||
((prefs!.getBool("voiceModeEnabled") ?? false) ||
permissionLoading ||
(permissionBluetooth && (permissionBluetooth &&
permissionRecord && permissionRecord &&
voiceSupported)) voiceSupported &&
voiceLanguageOptionsAvailable.contains(
(prefs!.getString("voiceLanguage") ??
"en_US"))))
? const SizedBox.shrink() ? const SizedBox.shrink()
: button( : button(
permissionLoading permissionLoading
? AppLocalizations.of(context)! ? AppLocalizations.of(context)!
.settingsVoicePermissionLoading .settingsVoicePermissionLoading
: (permissionBluetooth && permissionRecord) : (!voiceLanguageOptionsAvailable.contains(
(prefs!.getString(
"voiceLanguage") ??
"en_US")) &&
(prefs!.getBool("voiceModeEnabled") ??
false))
? AppLocalizations.of(context)! ? AppLocalizations.of(context)!
.settingsVoiceNotSupported .settingsVoiceTtsNotSupported
: AppLocalizations.of(context)! : !(permissionBluetooth && permissionRecord)
.settingsVoicePermissionNot, ? AppLocalizations.of(context)!
.settingsVoicePermissionNot
: !(prefs!.getBool(
"voiceModeEnabled") ??
false)
? AppLocalizations.of(context)!
.settingsVoiceNotEnabled
: AppLocalizations.of(context)!
.settingsVoiceNotSupported,
Icons.info_rounded, () { Icons.info_rounded, () {
if (permissionLoading) return; if (permissionLoading) return;
if (!(permissionBluetooth && permissionRecord)) { if (!voiceLanguageOptions.contains(
(prefs!.getString("voiceLanguage") ??
"en_US"))) {
selectionHaptic();
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text(AppLocalizations.of(context)!
.settingsVoiceTtsNotSupportedDescription),
showCloseIcon: true));
} else if (!(permissionBluetooth &&
permissionRecord)) {
void load() async { void load() async {
try { try {
if (await Permission if (await Permission
@ -135,33 +173,42 @@ class _ScreenSettingsVoiceState extends State<ScreenSettingsVoice> {
Icons.language_rounded, () { Icons.language_rounded, () {
int usedIndex = -1; int usedIndex = -1;
Function? setModalState; Function? setModalState;
void load() async {
var tmp = await speech.locales();
languageOptionIds = tmp.map((e) => e.localeId);
languageOptions = tmp.map((e) => e.name);
if ((prefs!.getString("voiceLanguage") ?? "") != "") {
for (int i = 0; i < languageOptionIds.length; i++) {
if (languageOptionIds.elementAt(i) ==
(prefs!.getString("voiceLanguage") ?? "")) {
usedIndex = i;
setModalState!(() {});
break;
}
}
}
}
selectionHaptic(); selectionHaptic();
load();
showModalBottomSheet( showModalBottomSheet(
context: context, context: context,
builder: builder:
(context) => StatefulBuilder( (context) => StatefulBuilder(
builder: (context, setLocalState) { builder: (context, setLocalState) {
setModalState = setLocalState; setModalState = setLocalState;
void loadSelected() async {
if ((prefs!.getString("voiceLanguage") ??
"") !=
"") {
for (int i = 0;
i < languageOptionIds.length;
i++) {
if (languageOptionIds.elementAt(i) ==
(prefs!.getString(
"voiceLanguage") ??
"")) {
setModalState!(() {
usedIndex = i;
});
break;
}
}
}
}
if (dialogMustLoad) {
load();
loadSelected();
dialogMustLoad = false;
}
return PopScope( return PopScope(
onPopInvoked: (didPop) { onPopInvoked: (didPop) {
if (usedIndex == -1) return; if (usedIndex == -1) return;
@ -169,7 +216,9 @@ class _ScreenSettingsVoiceState extends State<ScreenSettingsVoice> {
"voiceLanguage", "voiceLanguage",
languageOptionIds languageOptionIds
.elementAt(usedIndex)); .elementAt(usedIndex));
setState(() {}); setState(() {
dialogMustLoad = true;
});
}, },
child: Container( child: Container(
width: double.infinity, width: double.infinity,
@ -226,8 +275,8 @@ class _ScreenSettingsVoiceState extends State<ScreenSettingsVoice> {
avatar: (usedIndex == avatar: (usedIndex ==
index) index)
? null ? null
: (languageOptionIds.elementAt(index).startsWith(AppLocalizations.of(context)!.localeName)) : (voiceLanguageOptionsAvailable.contains(languageOptionIds.elementAt(index)))
? const Icon(Icons.star_rounded) ? const Icon(Icons.spatial_tracking_rounded)
: null, : null,
checkmarkColor: (usedIndex == checkmarkColor: (usedIndex ==
index) index)