diff --git a/app/src/main/java/eu/faircode/email/AdapterMessage.java b/app/src/main/java/eu/faircode/email/AdapterMessage.java index 50a9e84703..96400923bf 100644 --- a/app/src/main/java/eu/faircode/email/AdapterMessage.java +++ b/app/src/main/java/eu/faircode/email/AdapterMessage.java @@ -485,6 +485,7 @@ public class AdapterMessage extends RecyclerView.Adapter 0 || tos > 0) ? View.VISIBLE : View.GONE); ibTranslate.setVisibility(tools && !outbox && button_translate && DeepL.isAvailable(context) && message.content ? View.VISIBLE : View.GONE); + ibTts.setVisibility(tools && !outbox && button_tts && message.content ? View.VISIBLE : View.GONE); ibSummarize.setVisibility(tools && !outbox && button_summarize && AI.isAvailable(context) && message.content ? View.VISIBLE : View.GONE); ibFullScreen.setVisibility(tools && full && button_full_screen && message.content ? View.VISIBLE : View.GONE); ibForceLight.setVisibility(tools && (full || experiments) && dark && button_force_light && message.content ? View.VISIBLE : View.GONE); @@ -4650,6 +4658,8 @@ public class AdapterMessage extends RecyclerView.Adapter() { + @Override + protected String onExecute(Context context, Bundle args) throws Throwable { + long id = args.getLong("id"); + + DB db = DB.getInstance(context); + EntityMessage message = db.message().getMessage(id); + if (message == null) + return null; + + String body = Helper.readText(message.getFile(context)); + String text = HtmlHelper.getFullText(context, body); + + // Avoid: Not enough namespace quota ... for ... + text = HtmlHelper.truncate(text, ServiceTTS.getMaxTextSize() / 3); + + return text; + } + + @Override + protected void onExecuted(Bundle args, String text) { + if (text == null) + return; + + Intent intent = new Intent(context, ServiceTTS.class) + .setAction("tts:" + message.id) + .putExtra(ServiceTTS.EXTRA_FLUSH, true) + .putExtra(ServiceTTS.EXTRA_TEXT, text) + .putExtra(ServiceTTS.EXTRA_LANGUAGE, message.language) + .putExtra(ServiceTTS.EXTRA_UTTERANCE_ID, "tts:" + message.id); + context.startService(intent); + } + + @Override + protected void onException(Bundle args, Throwable ex) { + Log.unexpectedError(parentFragment.getParentFragmentManager(), ex); + } + }.execute(context, owner, args, "tts"); + } + private void onActionSummarize(TupleMessageEx message, View anchor) { FragmentDialogSummarize.summarize(message, parentFragment.getParentFragmentManager(), anchor, owner); } diff --git a/app/src/main/java/eu/faircode/email/FragmentDialogButtons.java b/app/src/main/java/eu/faircode/email/FragmentDialogButtons.java index 7d284c18a4..fc5b4165dc 100644 --- a/app/src/main/java/eu/faircode/email/FragmentDialogButtons.java +++ b/app/src/main/java/eu/faircode/email/FragmentDialogButtons.java @@ -57,6 +57,7 @@ public class FragmentDialogButtons extends FragmentDialogBase { final CheckBox cbSearch = dview.findViewById(R.id.cbSearch); final CheckBox cbSearchText = dview.findViewById(R.id.cbSearchText); final CheckBox cbTranslate = dview.findViewById(R.id.cbTranslate); + final CheckBox cbTts = dview.findViewById(R.id.cbTts); final CheckBox cbSummarize = dview.findViewById(R.id.cbSummarize); final CheckBox cbFullScreen = dview.findViewById(R.id.cbFullScreen); final CheckBox cbForceLight = dview.findViewById(R.id.cbForceLight); @@ -89,6 +90,7 @@ public class FragmentDialogButtons extends FragmentDialogBase { cbSearch.setChecked(prefs.getBoolean("button_search", false)); cbSearchText.setChecked(prefs.getBoolean("button_search_text", false)); cbTranslate.setChecked(prefs.getBoolean("button_translate", true)); + cbTts.setChecked(prefs.getBoolean("button_tts", false)); cbSummarize.setChecked(prefs.getBoolean("button_summarize", false)); cbFullScreen.setChecked(prefs.getBoolean("button_full_screen", false)); cbForceLight.setChecked(prefs.getBoolean("button_force_light", true)); @@ -129,6 +131,7 @@ public class FragmentDialogButtons extends FragmentDialogBase { editor.putBoolean("button_search", cbSearch.isChecked()); editor.putBoolean("button_search_text", cbSearchText.isChecked()); editor.putBoolean("button_translate", cbTranslate.isChecked()); + editor.putBoolean("button_tts", cbTts.isChecked()); editor.putBoolean("button_summarize", cbSummarize.isChecked()); editor.putBoolean("button_full_screen", cbFullScreen.isChecked()); editor.putBoolean("button_force_light", cbForceLight.isChecked()); diff --git a/app/src/main/res/layout/dialog_buttons.xml b/app/src/main/res/layout/dialog_buttons.xml index 0bc2a9ce80..1d09eb748e 100644 --- a/app/src/main/res/layout/dialog_buttons.xml +++ b/app/src/main/res/layout/dialog_buttons.xml @@ -187,6 +187,19 @@ app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/cbImportance" /> + + + app:layout_constraintTop_toBottomOf="@id/cbTts" /> + +