From 5c57fbbd84a10d3c19ff3e94b9b99e9e911b9737 Mon Sep 17 00:00:00 2001 From: adbenitez Date: Wed, 29 May 2024 15:10:22 +0200 Subject: [PATCH 1/8] update res/raw/webxdc.js with new RealtimeChannel API --- src/main/res/raw/webxdc.js | 41 +++++++++++++++++++++++++++++++++++--- 1 file changed, 38 insertions(+), 3 deletions(-) diff --git a/src/main/res/raw/webxdc.js b/src/main/res/raw/webxdc.js index 2b99c2760..2634de6c8 100644 --- a/src/main/res/raw/webxdc.js +++ b/src/main/res/raw/webxdc.js @@ -1,7 +1,8 @@ window.webxdc = (() => { - let setUpdateListenerPromise = null - var update_listener = () => {}; - var last_serial = 0; + let setUpdateListenerPromise = null; + let update_listener = () => {}; + let last_serial = 0; + let realtimeChannel = null; window.__webxdcUpdate = () => { var updates = JSON.parse(InternalJSApi.getStatusUpdates(last_serial)); @@ -15,11 +16,45 @@ window.webxdc = (() => { } }; + window.__webxdcRealtimeData = () => { + const base64Data = null; // TODO: get base64Data somehow + if (realtimeChannel) { + const data = Uint8Array.from(atob(base64Data), (m) => m.codePointAt(0)); + realtimeChannel.__receive(data); + } + }; + + const createRealtimeChannel = () => { + let listener = null; + const decoder = new TextDecoder('utf8'); + return { + setListener: (li) => listener = li, + leave: () => InternalJSApi.leaveRealtimeChannel(), + send: (data) => { + if ((!data) instanceof Uint8Array) { + throw new Error('realtime listener data must be a Uint8Array') + } + InternalJSApi.sendRealtimeData(btoa(decoder.decode(data))); + }, + __receive: (data) => { + if (listener) { + listener(data); + } + }, + }; + } + return { selfAddr: InternalJSApi.selfAddr(), selfName: InternalJSApi.selfName(), + joinRealtimeChannel: () => { + realtimeChannel = createRealtimeChannel(); + InternalJSApi.sendRealtimeAdvertisement(); + return realtimeChannel; + }, + setUpdateListener: (cb, serial) => { last_serial = typeof serial === "undefined" ? 0 : parseInt(serial); update_listener = cb From 07d895594efe4b1319c3c9e5884c43f9cfb4744f Mon Sep 17 00:00:00 2001 From: adbenitez Date: Wed, 29 May 2024 19:06:01 +0200 Subject: [PATCH 2/8] add API to JavaScriptInterface and Rpc, listent to realtime data event --- src/main/java/com/b44t/messenger/rpc/Rpc.java | 12 ++++ .../securesms/WebxdcActivity.java | 67 +++++++++++++++++-- src/main/res/raw/webxdc.js | 3 +- 3 files changed, 74 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/b44t/messenger/rpc/Rpc.java b/src/main/java/com/b44t/messenger/rpc/Rpc.java index 88a65fbd4..e7ae1b9e3 100644 --- a/src/main/java/com/b44t/messenger/rpc/Rpc.java +++ b/src/main/java/com/b44t/messenger/rpc/Rpc.java @@ -126,6 +126,18 @@ public class Rpc { return getResult("draft_self_report", accountId).getAsInt(); } + public void sendWebxdcRealtimeData(Integer accountId, Integer instanceMsgId, List data) throws RpcException { + getResult("send_webxdc_realtime_data", accountId, instanceMsgId, data); + } + + public void sendWebxdcRealtimeAdvertisement(Integer accountId, Integer instanceMsgId) throws RpcException { + getResult("send_webxdc_realtime_advertisement", accountId, instanceMsgId); + } + + public void leaveWebxdcRealtime(Integer accountId, Integer instanceMessageId) throws RpcException { + getResult("leave_webxdc_realtime", accountId, instanceMessageId); + } + private static class Request { private final String jsonrpc = "2.0"; public final String method; diff --git a/src/main/java/org/thoughtcrime/securesms/WebxdcActivity.java b/src/main/java/org/thoughtcrime/securesms/WebxdcActivity.java index d2756618e..17e314191 100644 --- a/src/main/java/org/thoughtcrime/securesms/WebxdcActivity.java +++ b/src/main/java/org/thoughtcrime/securesms/WebxdcActivity.java @@ -37,6 +37,8 @@ import com.b44t.messenger.DcChat; import com.b44t.messenger.DcContext; import com.b44t.messenger.DcEvent; import com.b44t.messenger.DcMsg; +import com.b44t.messenger.rpc.Rpc; +import com.b44t.messenger.rpc.RpcException; import org.json.JSONObject; import org.thoughtcrime.securesms.connect.AccountManager; @@ -54,6 +56,7 @@ import java.io.InputStream; import java.util.HashMap; import java.util.Map; +import java.util.ArrayList; public class WebxdcActivity extends WebViewActivity implements DcEventCenter.DcEventDelegate { private static final String TAG = WebxdcActivity.class.getSimpleName(); @@ -64,6 +67,7 @@ public class WebxdcActivity extends WebViewActivity implements DcEventCenter.DcE private ValueCallback filePathCallback; private DcContext dcContext; + private Rpc rpc; private DcMsg dcAppMsg; private String baseURL; private String sourceCodeUrl = ""; @@ -136,6 +140,7 @@ public class WebxdcActivity extends WebViewActivity implements DcEventCenter.DcE @Override protected void onCreate(Bundle state, boolean ready) { super.onCreate(state, ready); + rpc = DcHelper.getRpc(this); Bundle b = getIntent().getExtras(); hideActionBar = b.getBoolean(EXTRA_HIDE_ACTION_BAR, false); @@ -164,6 +169,7 @@ public class WebxdcActivity extends WebViewActivity implements DcEventCenter.DcE DcEventCenter eventCenter = DcHelper.getEventCenter(WebxdcActivity.this.getApplicationContext()); eventCenter.addObserver(DcContext.DC_EVENT_WEBXDC_STATUS_UPDATE, this); eventCenter.addObserver(DcContext.DC_EVENT_MSGS_CHANGED, this); + eventCenter.addObserver(DcContext.DC_EVENT_WEBXDC_REALTIME_DATA, this); int appMessageId = b.getInt(EXTRA_APP_MSG_ID); int accountId = b.getInt(EXTRA_ACCOUNT_ID); @@ -341,16 +347,24 @@ public class WebxdcActivity extends WebViewActivity implements DcEventCenter.DcE return res; } + private void callJavaScriptFunction(String func) { + if (internetAccess) { + webView.evaluateJavascript("window." + func + ";", null); + } else { + webView.evaluateJavascript("document.getElementById('frame').contentWindow." + func + ";", null); + } + } + @Override public void handleEvent(@NonNull DcEvent event) { int eventId = event.getId(); if ((eventId == DcContext.DC_EVENT_WEBXDC_STATUS_UPDATE && event.getData1Int() == dcAppMsg.getId())) { - Log.i(TAG, "handleEvent"); - if (internetAccess) { - webView.loadUrl("javascript:window.__webxdcUpdate();"); - } else { - webView.loadUrl("javascript:document.getElementById('frame').contentWindow.__webxdcUpdate();"); - } + Log.i(TAG, "handling status update event"); + callJavaScriptFunction("__webxdcUpdate()"); + } else if ((eventId == DcContext.DC_EVENT_WEBXDC_REALTIME_DATA && event.getData1Int() == dcAppMsg.getId())) { + Log.i(TAG, "handling realtime data event"); + String base64 = Base64.encodeToString(event.getData2Blob(), Base64.NO_WRAP | Base64.NO_PADDING); + callJavaScriptFunction("__webxdcRealtimeData(\"" + base64 + "\")"); } else if ((eventId == DcContext.DC_EVENT_MSGS_CHANGED && event.getData2Int() == dcAppMsg.getId())) { this.dcAppMsg = this.dcContext.getMsg(event.getData2Int()); // msg changed, reload data from db Util.runOnAnyBackgroundThread(() -> { @@ -496,5 +510,46 @@ public class WebxdcActivity extends WebViewActivity implements DcEventCenter.DcE return e.toString(); } } + + /** @noinspection unused*/ + @JavascriptInterface + public void sendRealtimeAdvertisement() { + int accountId = WebxdcActivity.this.dcContext.getAccountId(); + int msgId = WebxdcActivity.this.dcAppMsg.getId(); + try { + rpc.sendWebxdcRealtimeAdvertisement(accountId, msgId); + } catch (RpcException e) { + e.printStackTrace(); + } + } + + /** @noinspection unused*/ + @JavascriptInterface + public void leaveRealtimeChannel() { + int accountId = WebxdcActivity.this.dcContext.getAccountId(); + int msgId = WebxdcActivity.this.dcAppMsg.getId(); + try { + rpc.leaveWebxdcRealtime(accountId, msgId); + } catch (RpcException e) { + e.printStackTrace(); + } + } + + /** @noinspection unused*/ + @JavascriptInterface + public void sendRealtimeData(String base64Data) { + int accountId = WebxdcActivity.this.dcContext.getAccountId(); + int msgId = WebxdcActivity.this.dcAppMsg.getId(); + byte[] bytes = Base64.decode(base64Data, Base64.NO_WRAP | Base64.NO_PADDING); + ArrayList data = new ArrayList<>(); + for (byte b : bytes) { + data.add(Integer.valueOf(b)); + } + try { + rpc.sendWebxdcRealtimeData(accountId, msgId, data); + } catch (RpcException e) { + e.printStackTrace(); + } + } } } diff --git a/src/main/res/raw/webxdc.js b/src/main/res/raw/webxdc.js index 2634de6c8..baefc094c 100644 --- a/src/main/res/raw/webxdc.js +++ b/src/main/res/raw/webxdc.js @@ -16,8 +16,7 @@ window.webxdc = (() => { } }; - window.__webxdcRealtimeData = () => { - const base64Data = null; // TODO: get base64Data somehow + window.__webxdcRealtimeData = (base64Data) => { if (realtimeChannel) { const data = Uint8Array.from(atob(base64Data), (m) => m.codePointAt(0)); realtimeChannel.__receive(data); From 50f6675d99134474d2bcd89a94d7119609609fb4 Mon Sep 17 00:00:00 2001 From: adbenitez Date: Wed, 29 May 2024 20:58:57 +0200 Subject: [PATCH 3/8] leave channel when webxdc is closed --- .../securesms/WebxdcActivity.java | 23 +++++++++++-------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/src/main/java/org/thoughtcrime/securesms/WebxdcActivity.java b/src/main/java/org/thoughtcrime/securesms/WebxdcActivity.java index 17e314191..151417927 100644 --- a/src/main/java/org/thoughtcrime/securesms/WebxdcActivity.java +++ b/src/main/java/org/thoughtcrime/securesms/WebxdcActivity.java @@ -223,6 +223,7 @@ public class WebxdcActivity extends WebViewActivity implements DcEventCenter.DcE @Override protected void onDestroy() { DcHelper.getEventCenter(this.getApplicationContext()).removeObservers(this); + leaveRealtimeChannel(); super.onDestroy(); } @@ -442,6 +443,16 @@ public class WebxdcActivity extends WebViewActivity implements DcEventCenter.DcE super.onActivityResult(reqCode, resultCode, data); } + private void leaveRealtimeChannel() { + int accountId = dcContext.getAccountId(); + int msgId = dcAppMsg.getId(); + try { + rpc.leaveWebxdcRealtime(accountId, msgId); + } catch (RpcException e) { + e.printStackTrace(); + } + } + class InternalJSApi { @JavascriptInterface public String selfAddr() { @@ -517,7 +528,7 @@ public class WebxdcActivity extends WebViewActivity implements DcEventCenter.DcE int accountId = WebxdcActivity.this.dcContext.getAccountId(); int msgId = WebxdcActivity.this.dcAppMsg.getId(); try { - rpc.sendWebxdcRealtimeAdvertisement(accountId, msgId); + WebxdcActivity.this.rpc.sendWebxdcRealtimeAdvertisement(accountId, msgId); } catch (RpcException e) { e.printStackTrace(); } @@ -526,13 +537,7 @@ public class WebxdcActivity extends WebViewActivity implements DcEventCenter.DcE /** @noinspection unused*/ @JavascriptInterface public void leaveRealtimeChannel() { - int accountId = WebxdcActivity.this.dcContext.getAccountId(); - int msgId = WebxdcActivity.this.dcAppMsg.getId(); - try { - rpc.leaveWebxdcRealtime(accountId, msgId); - } catch (RpcException e) { - e.printStackTrace(); - } + WebxdcActivity.this.leaveRealtimeChannel(); } /** @noinspection unused*/ @@ -546,7 +551,7 @@ public class WebxdcActivity extends WebViewActivity implements DcEventCenter.DcE data.add(Integer.valueOf(b)); } try { - rpc.sendWebxdcRealtimeData(accountId, msgId, data); + WebxdcActivity.this.rpc.sendWebxdcRealtimeData(accountId, msgId, data); } catch (RpcException e) { e.printStackTrace(); } From 06b36fe35ccb1341e2b644babe1d2ce88083924c Mon Sep 17 00:00:00 2001 From: adbenitez Date: Wed, 29 May 2024 21:03:12 +0200 Subject: [PATCH 4/8] fix linter warning --- .../org/thoughtcrime/securesms/WebxdcActivity.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/thoughtcrime/securesms/WebxdcActivity.java b/src/main/java/org/thoughtcrime/securesms/WebxdcActivity.java index 151417927..777e74695 100644 --- a/src/main/java/org/thoughtcrime/securesms/WebxdcActivity.java +++ b/src/main/java/org/thoughtcrime/securesms/WebxdcActivity.java @@ -349,10 +349,12 @@ public class WebxdcActivity extends WebViewActivity implements DcEventCenter.DcE } private void callJavaScriptFunction(String func) { - if (internetAccess) { - webView.evaluateJavascript("window." + func + ";", null); - } else { - webView.evaluateJavascript("document.getElementById('frame').contentWindow." + func + ";", null); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + if (internetAccess) { + webView.evaluateJavascript("window." + func + ";", null); + } else { + webView.evaluateJavascript("document.getElementById('frame').contentWindow." + func + ";", null); + } } } From 29e563f89bab7747c44bc213c582372162a7167d Mon Sep 17 00:00:00 2001 From: adbenitez Date: Mon, 10 Jun 2024 20:50:34 +0200 Subject: [PATCH 5/8] add config option for realtime channels --- .../org/thoughtcrime/securesms/connect/DcHelper.java | 1 + .../preferences/AdvancedPreferenceFragment.java | 10 ++++++++++ src/main/res/values/strings.xml | 1 + src/main/res/xml/preferences_advanced.xml | 5 +++++ 4 files changed, 17 insertions(+) diff --git a/src/main/java/org/thoughtcrime/securesms/connect/DcHelper.java b/src/main/java/org/thoughtcrime/securesms/connect/DcHelper.java index 09a0ae27d..3e01cbe35 100644 --- a/src/main/java/org/thoughtcrime/securesms/connect/DcHelper.java +++ b/src/main/java/org/thoughtcrime/securesms/connect/DcHelper.java @@ -78,6 +78,7 @@ public class DcHelper { public static final String CONFIG_SOCKS5_USER = "socks5_user"; public static final String CONFIG_SOCKS5_PASSWORD = "socks5_password"; public static final String CONFIG_VERIFIED_ONE_ON_ONE_CHATS = "verified_one_on_one_chats"; + public static final String CONFIG_WEBXDC_REALTIME_ENABLED = "webxdc_realtime_enabled"; public static DcContext getContext(@NonNull Context context) { return ApplicationContext.getInstance(context).dcContext; diff --git a/src/main/java/org/thoughtcrime/securesms/preferences/AdvancedPreferenceFragment.java b/src/main/java/org/thoughtcrime/securesms/preferences/AdvancedPreferenceFragment.java index db4360650..ed633a70a 100644 --- a/src/main/java/org/thoughtcrime/securesms/preferences/AdvancedPreferenceFragment.java +++ b/src/main/java/org/thoughtcrime/securesms/preferences/AdvancedPreferenceFragment.java @@ -8,6 +8,7 @@ import static org.thoughtcrime.securesms.connect.DcHelper.CONFIG_MVBOX_MOVE; import static org.thoughtcrime.securesms.connect.DcHelper.CONFIG_ONLY_FETCH_MVBOX; import static org.thoughtcrime.securesms.connect.DcHelper.CONFIG_SENTBOX_WATCH; import static org.thoughtcrime.securesms.connect.DcHelper.CONFIG_SHOW_EMAILS; +import static org.thoughtcrime.securesms.connect.DcHelper.CONFIG_WEBXDC_REALTIME_ENABLED; import static org.thoughtcrime.securesms.connect.DcHelper.getRpc; import android.Manifest; @@ -67,6 +68,7 @@ public class AdvancedPreferenceFragment extends ListSummaryPreferenceFragment CheckBoxPreference bccSelfCheckbox; CheckBoxPreference mvboxMoveCheckbox; CheckBoxPreference onlyFetchMvboxCheckbox; + CheckBoxPreference webxdcRealtimeCheckbox; CheckBoxPreference showSystemContacts; @Override @@ -126,6 +128,13 @@ public class AdvancedPreferenceFragment extends ListSummaryPreferenceFragment } })); + webxdcRealtimeCheckbox = (CheckBoxPreference) this.findPreference("pref_webxdc_realtime_enabled"); + webxdcRealtimeCheckbox.setOnPreferenceChangeListener((preference, newValue) -> { + boolean enabled = (Boolean) newValue; + dcContext.setConfigInt(CONFIG_WEBXDC_REALTIME_ENABLED, enabled? 1 : 0); + return true; + }); + showSystemContacts = (CheckBoxPreference) this.findPreference("pref_show_system_contacts"); showSystemContacts.setOnPreferenceChangeListener((preference, newValue) -> { boolean enabled = (Boolean) newValue; @@ -237,6 +246,7 @@ public class AdvancedPreferenceFragment extends ListSummaryPreferenceFragment bccSelfCheckbox.setChecked(0!=dcContext.getConfigInt(CONFIG_BCC_SELF)); mvboxMoveCheckbox.setChecked(0!=dcContext.getConfigInt(CONFIG_MVBOX_MOVE)); onlyFetchMvboxCheckbox.setChecked(0!=dcContext.getConfigInt(CONFIG_ONLY_FETCH_MVBOX)); + webxdcRealtimeCheckbox.setChecked(0!=dcContext.getConfigInt(CONFIG_WEBXDC_REALTIME_ENABLED)); showSystemContacts.setChecked(0!=dcContext.getConfigInt("ui.android.show_system_contacts")); } diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml index 7f21a7c13..4447680c8 100644 --- a/src/main/res/values/strings.xml +++ b/src/main/res/values/strings.xml @@ -743,6 +743,7 @@ All Experimental Features On-demand Location Streaming + Realtime Channels Developer Mode Activates debugging options and can make the app less stable. For developers only. Default image diff --git a/src/main/res/xml/preferences_advanced.xml b/src/main/res/xml/preferences_advanced.xml index d826188fd..2be13ac69 100644 --- a/src/main/res/xml/preferences_advanced.xml +++ b/src/main/res/xml/preferences_advanced.xml @@ -30,6 +30,11 @@ android:key="pref_location_streaming_enabled" android:title="@string/pref_on_demand_location_streaming"/> + + Date: Wed, 12 Jun 2024 23:02:49 +0200 Subject: [PATCH 6/8] pass JSON array to InternalJSApi.sendRealtimeData() --- .../thoughtcrime/securesms/WebxdcActivity.java | 15 +++++---------- src/main/res/raw/webxdc.js | 3 +-- 2 files changed, 6 insertions(+), 12 deletions(-) diff --git a/src/main/java/org/thoughtcrime/securesms/WebxdcActivity.java b/src/main/java/org/thoughtcrime/securesms/WebxdcActivity.java index 777e74695..4012378d7 100644 --- a/src/main/java/org/thoughtcrime/securesms/WebxdcActivity.java +++ b/src/main/java/org/thoughtcrime/securesms/WebxdcActivity.java @@ -53,10 +53,9 @@ import java.io.ByteArrayInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; - +import java.util.Arrays; import java.util.HashMap; import java.util.Map; -import java.util.ArrayList; public class WebxdcActivity extends WebViewActivity implements DcEventCenter.DcEventDelegate { private static final String TAG = WebxdcActivity.class.getSimpleName(); @@ -544,17 +543,13 @@ public class WebxdcActivity extends WebViewActivity implements DcEventCenter.DcE /** @noinspection unused*/ @JavascriptInterface - public void sendRealtimeData(String base64Data) { + public void sendRealtimeData(String jsonData) { int accountId = WebxdcActivity.this.dcContext.getAccountId(); int msgId = WebxdcActivity.this.dcAppMsg.getId(); - byte[] bytes = Base64.decode(base64Data, Base64.NO_WRAP | Base64.NO_PADDING); - ArrayList data = new ArrayList<>(); - for (byte b : bytes) { - data.add(Integer.valueOf(b)); - } try { - WebxdcActivity.this.rpc.sendWebxdcRealtimeData(accountId, msgId, data); - } catch (RpcException e) { + Integer[] data = JsonUtils.fromJson(jsonData, Integer[].class); + WebxdcActivity.this.rpc.sendWebxdcRealtimeData(accountId, msgId, Arrays.asList(data)); + } catch (IOException | RpcException e) { e.printStackTrace(); } } diff --git a/src/main/res/raw/webxdc.js b/src/main/res/raw/webxdc.js index baefc094c..bc34960e9 100644 --- a/src/main/res/raw/webxdc.js +++ b/src/main/res/raw/webxdc.js @@ -25,7 +25,6 @@ window.webxdc = (() => { const createRealtimeChannel = () => { let listener = null; - const decoder = new TextDecoder('utf8'); return { setListener: (li) => listener = li, leave: () => InternalJSApi.leaveRealtimeChannel(), @@ -33,7 +32,7 @@ window.webxdc = (() => { if ((!data) instanceof Uint8Array) { throw new Error('realtime listener data must be a Uint8Array') } - InternalJSApi.sendRealtimeData(btoa(decoder.decode(data))); + InternalJSApi.sendRealtimeData(JSON.stringify(Array.from(data))); }, __receive: (data) => { if (listener) { From cd0350cc6d7289ef4af1e0986a2a769ac548b35e Mon Sep 17 00:00:00 2001 From: adbenitez Date: Thu, 13 Jun 2024 16:26:47 +0200 Subject: [PATCH 7/8] send realtime data events as int array instead of base64 --- .../java/org/thoughtcrime/securesms/WebxdcActivity.java | 7 +++++-- src/main/res/raw/webxdc.js | 5 ++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/main/java/org/thoughtcrime/securesms/WebxdcActivity.java b/src/main/java/org/thoughtcrime/securesms/WebxdcActivity.java index 4012378d7..b126d0c10 100644 --- a/src/main/java/org/thoughtcrime/securesms/WebxdcActivity.java +++ b/src/main/java/org/thoughtcrime/securesms/WebxdcActivity.java @@ -365,8 +365,11 @@ public class WebxdcActivity extends WebViewActivity implements DcEventCenter.DcE callJavaScriptFunction("__webxdcUpdate()"); } else if ((eventId == DcContext.DC_EVENT_WEBXDC_REALTIME_DATA && event.getData1Int() == dcAppMsg.getId())) { Log.i(TAG, "handling realtime data event"); - String base64 = Base64.encodeToString(event.getData2Blob(), Base64.NO_WRAP | Base64.NO_PADDING); - callJavaScriptFunction("__webxdcRealtimeData(\"" + base64 + "\")"); + StringBuilder data = new StringBuilder(); + for (byte b : event.getData2Blob()) { + data.append(((int) b) + ","); + } + callJavaScriptFunction("__webxdcRealtimeData([" + data + "])"); } else if ((eventId == DcContext.DC_EVENT_MSGS_CHANGED && event.getData2Int() == dcAppMsg.getId())) { this.dcAppMsg = this.dcContext.getMsg(event.getData2Int()); // msg changed, reload data from db Util.runOnAnyBackgroundThread(() -> { diff --git a/src/main/res/raw/webxdc.js b/src/main/res/raw/webxdc.js index bc34960e9..9d23bdbf5 100644 --- a/src/main/res/raw/webxdc.js +++ b/src/main/res/raw/webxdc.js @@ -16,10 +16,9 @@ window.webxdc = (() => { } }; - window.__webxdcRealtimeData = (base64Data) => { + window.__webxdcRealtimeData = (intArray) => { if (realtimeChannel) { - const data = Uint8Array.from(atob(base64Data), (m) => m.codePointAt(0)); - realtimeChannel.__receive(data); + realtimeChannel.__receive(Uint8Array.from(intArray)); } }; From 3cd1f3b8cc73b323c3817a0e6757ea1455474ad7 Mon Sep 17 00:00:00 2001 From: adbenitez Date: Thu, 13 Jun 2024 19:42:11 +0200 Subject: [PATCH 8/8] update realtime preference name title and set summary --- src/main/res/values/strings.xml | 1 - src/main/res/xml/preferences_advanced.xml | 3 ++- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml index 4447680c8..7f21a7c13 100644 --- a/src/main/res/values/strings.xml +++ b/src/main/res/values/strings.xml @@ -743,7 +743,6 @@ All Experimental Features On-demand Location Streaming - Realtime Channels Developer Mode Activates debugging options and can make the app less stable. For developers only. Default image diff --git a/src/main/res/xml/preferences_advanced.xml b/src/main/res/xml/preferences_advanced.xml index 2be13ac69..9098d943d 100644 --- a/src/main/res/xml/preferences_advanced.xml +++ b/src/main/res/xml/preferences_advanced.xml @@ -33,7 +33,8 @@ + android:summary="@string/enable_realtime_explain" + android:title="@string/enable_realtime"/>