Merge remote-tracking branch 'upstream/main'

This commit is contained in:
adbenitez
2024-06-13 20:45:33 +02:00
7 changed files with 128 additions and 7 deletions
@@ -126,6 +126,18 @@ public class Rpc {
return getResult("draft_self_report", accountId).getAsInt();
}
public void sendWebxdcRealtimeData(Integer accountId, Integer instanceMsgId, List<Integer> 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;
@@ -38,6 +38,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;
@@ -52,7 +54,7 @@ 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;
@@ -65,6 +67,7 @@ public class WebxdcActivity extends WebViewActivity implements DcEventCenter.DcE
private ValueCallback<Uri[]> filePathCallback;
private DcContext dcContext;
private Rpc rpc;
private DcMsg dcAppMsg;
private String baseURL;
private String sourceCodeUrl = "";
@@ -137,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);
@@ -161,6 +165,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);
@@ -221,6 +226,7 @@ public class WebxdcActivity extends WebViewActivity implements DcEventCenter.DcE
@Override
protected void onDestroy() {
DcHelper.getEventCenter(this.getApplicationContext()).removeObservers(this);
leaveRealtimeChannel();
super.onDestroy();
}
@@ -346,12 +352,25 @@ public class WebxdcActivity extends WebViewActivity implements DcEventCenter.DcE
return res;
}
private void callJavaScriptFunction(String func) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
webView.evaluateJavascript("window." + 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");
webView.loadUrl("javascript:window.__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");
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(() -> {
@@ -429,6 +448,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 deltalab() {
@@ -526,5 +555,36 @@ 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 {
WebxdcActivity.this.rpc.sendWebxdcRealtimeAdvertisement(accountId, msgId);
} catch (RpcException e) {
e.printStackTrace();
}
}
/** @noinspection unused*/
@JavascriptInterface
public void leaveRealtimeChannel() {
WebxdcActivity.this.leaveRealtimeChannel();
}
/** @noinspection unused*/
@JavascriptInterface
public void sendRealtimeData(String jsonData) {
int accountId = WebxdcActivity.this.dcContext.getAccountId();
int msgId = WebxdcActivity.this.dcAppMsg.getId();
try {
Integer[] data = JsonUtils.fromJson(jsonData, Integer[].class);
WebxdcActivity.this.rpc.sendWebxdcRealtimeData(accountId, msgId, Arrays.asList(data));
} catch (IOException | RpcException e) {
e.printStackTrace();
}
}
}
}
@@ -81,6 +81,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;
@@ -7,6 +7,7 @@ import static org.thoughtcrime.securesms.connect.DcHelper.CONFIG_E2EE_ENABLED;
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_SHOW_EMAILS;
import static org.thoughtcrime.securesms.connect.DcHelper.CONFIG_WEBXDC_REALTIME_ENABLED;
import static org.thoughtcrime.securesms.connect.DcHelper.getRpc;
import android.Manifest;
@@ -63,6 +64,7 @@ public class AdvancedPreferenceFragment extends ListSummaryPreferenceFragment
CheckBoxPreference bccSelfCheckbox;
CheckBoxPreference mvboxMoveCheckbox;
CheckBoxPreference onlyFetchMvboxCheckbox;
CheckBoxPreference webxdcRealtimeCheckbox;
@Override
public void onCreate(Bundle paramBundle) {
@@ -114,6 +116,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;
});
Preference manageKeys = this.findPreference("pref_manage_keys");
manageKeys.setOnPreferenceClickListener(new ManageKeysListener());
@@ -183,6 +192,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));
}
@Override
+35 -3
View File
@@ -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,6 +16,31 @@ window.webxdc = (() => {
}
};
window.__webxdcRealtimeData = (intArray) => {
if (realtimeChannel) {
realtimeChannel.__receive(Uint8Array.from(intArray));
}
};
const createRealtimeChannel = () => {
let listener = null;
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(JSON.stringify(Array.from(data)));
},
__receive: (data) => {
if (listener) {
listener(data);
}
},
};
}
return {
deltalab: InternalJSApi.deltalab(),
@@ -24,6 +50,12 @@ window.webxdc = (() => {
selfName: InternalJSApi.selfName(),
joinRealtimeChannel: () => {
realtimeChannel = createRealtimeChannel();
InternalJSApi.sendRealtimeAdvertisement();
return realtimeChannel;
},
setUpdateListener: (cb, serial) => {
last_serial = typeof serial === "undefined" ? 0 : parseInt(serial);
update_listener = cb
@@ -20,6 +20,12 @@
android:title="@string/videochat_instance"
android:summary="@string/none"/>
<org.thoughtcrime.securesms.components.SwitchPreferenceCompat
android:defaultValue="true"
android:key="pref_webxdc_realtime_enabled"
android:summary="@string/enable_realtime_explain"
android:title="@string/enable_realtime"/>
<org.thoughtcrime.securesms.components.SwitchPreferenceCompat
android:defaultValue="false"
android:key="pref_developer_mode_enabled"