diff --git a/src/main/AndroidManifest.xml b/src/main/AndroidManifest.xml index 76144ac40..2473b9b9c 100644 --- a/src/main/AndroidManifest.xml +++ b/src/main/AndroidManifest.xml @@ -499,5 +499,8 @@ + + + diff --git a/src/main/java/org/thoughtcrime/securesms/WebxdcActivity.java b/src/main/java/org/thoughtcrime/securesms/WebxdcActivity.java index cbcc12a19..ae70b54eb 100644 --- a/src/main/java/org/thoughtcrime/securesms/WebxdcActivity.java +++ b/src/main/java/org/thoughtcrime/securesms/WebxdcActivity.java @@ -9,6 +9,7 @@ import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.net.Uri; import android.os.Bundle; +import android.speech.tts.TextToSpeech; import android.text.TextUtils; import android.util.Base64; import android.util.Log; @@ -58,6 +59,7 @@ import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.util.Arrays; import java.util.HashMap; +import java.util.Locale; import java.util.Map; public class WebxdcActivity extends WebViewActivity implements DcEventCenter.DcEventDelegate { @@ -81,6 +83,8 @@ public class WebxdcActivity extends WebViewActivity implements DcEventCenter.DcE private boolean internetAccess = false; private boolean hideActionBar = false; + private TextToSpeech tts; + public static void openMaps(Context context, int chatId) { DcContext dcContext = DcHelper.getContext(context); int msgId = dcContext.initWebxdcIntegration(chatId); @@ -149,6 +153,7 @@ public class WebxdcActivity extends WebViewActivity implements DcEventCenter.DcE protected void onCreate(Bundle state, boolean ready) { super.onCreate(state, ready); rpc = DcHelper.getRpc(this); + initTTS(); Bundle b = getIntent().getExtras(); hideActionBar = b.getBoolean(EXTRA_HIDE_ACTION_BAR, false); @@ -270,6 +275,7 @@ public class WebxdcActivity extends WebViewActivity implements DcEventCenter.DcE lastOpenTime = System.currentTimeMillis(); DcHelper.getEventCenter(this.getApplicationContext()).removeObservers(this); leaveRealtimeChannel(); + tts.shutdown(); super.onDestroy(); } @@ -307,6 +313,14 @@ public class WebxdcActivity extends WebViewActivity implements DcEventCenter.DcE setScreenMode(newConfig); } + private void initTTS() { + tts = new TextToSpeech(this, new TextToSpeech.OnInitListener() { + @Override + public void onInit(int status) { + Log.i(TAG, "TTS Init Status: " + status); + } + }); + } private void setScreenMode(Configuration config) { // enter/exit fullscreen mode depending on orientation (landscape/portrait), // on tablets there is enough height so fullscreen mode is never enabled there @@ -613,5 +627,12 @@ public class WebxdcActivity extends WebViewActivity implements DcEventCenter.DcE e.printStackTrace(); } } + + @JavascriptInterface + public void ttsSpeak(String text, String lang) { + tts.setLanguage(Locale.forLanguageTag(lang)); + tts.speak(text, TextToSpeech.QUEUE_FLUSH, null, null); + } + } } diff --git a/src/main/res/raw/webxdc.js b/src/main/res/raw/webxdc.js index a68bdda8e..2e9df2267 100644 --- a/src/main/res/raw/webxdc.js +++ b/src/main/res/raw/webxdc.js @@ -1,4 +1,23 @@ window.webxdc = (() => { + // TTS + window.speechSynthesis = { + speak: (utterance) => { + InternalJSApi.ttsSpeak(utterance.text, utterance.lang); + }, + getVoices: () => { + return []; + }, + }; + window.SpeechSynthesisUtterance = function (text) { + return { + text: text, + lang: "", + volume: 1, + rate: 1, + pitch: 1, + }; + }; + let setUpdateListenerPromise = null; let update_listener = () => {}; let last_serial = 0;