basic call

This commit is contained in:
adbenitez
2025-06-20 18:56:45 +02:00
parent 100bb06e20
commit 365f1dbbe6
5 changed files with 148 additions and 22 deletions
File diff suppressed because one or more lines are too long
@@ -51,6 +51,7 @@ import org.thoughtcrime.securesms.util.Prefs;
import org.thoughtcrime.securesms.util.RelayUtil;
import org.thoughtcrime.securesms.util.Util;
import org.thoughtcrime.securesms.util.ViewUtil;
import org.thoughtcrime.securesms.videochat.VideochatUtil;
import java.util.Timer;
import java.util.TimerTask;
@@ -81,6 +82,7 @@ public class ConversationListFragment extends BaseConversationListFragment
eventCenter.addMultiAccountObserver(DcContext.DC_EVENT_INCOMING_MSG, this);
eventCenter.addMultiAccountObserver(DcContext.DC_EVENT_MSGS_NOTICED, this);
eventCenter.addMultiAccountObserver(DcContext.DC_EVENT_CHAT_DELETED, this);
eventCenter.addMultiAccountObserver(DcContext.DC_EVENT_INCOMING_CALL, this);
eventCenter.addObserver(DcContext.DC_EVENT_CHAT_MODIFIED, this);
eventCenter.addObserver(DcContext.DC_EVENT_CONTACTS_CHANGED, this);
eventCenter.addObserver(DcContext.DC_EVENT_MSGS_CHANGED, this);
@@ -343,6 +345,9 @@ public class ConversationListFragment extends BaseConversationListFragment
((ConversationListActivity) activity).refreshAvatar();
}
} else if (event.getId() == DcContext.DC_EVENT_INCOMING_CALL) {
// TODO: show notification
VideochatUtil.joinCall(getActivity(), event.getData1Int(), event.getData2Str());
} else {
loadChatlistAsync();
}
@@ -1,57 +1,71 @@
package org.thoughtcrime.securesms.videochat;
import android.annotation.SuppressLint;
import android.os.Bundle;
import android.view.Menu;
import android.webkit.JavascriptInterface;
import android.webkit.PermissionRequest;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import androidx.annotation.NonNull;
import com.b44t.messenger.DcChat;
import com.b44t.messenger.DcContext;
import com.b44t.messenger.DcEvent;
import org.thoughtcrime.securesms.WebViewActivity;
import org.thoughtcrime.securesms.connect.DcEventCenter;
import org.thoughtcrime.securesms.connect.DcHelper;
import org.thoughtcrime.securesms.util.Util;
public class VideochatActivity extends WebViewActivity {
private static final String TAG = VideochatActivity.class.getSimpleName();
import java.util.Objects;
public class VideochatActivity extends WebViewActivity implements DcEventCenter.DcEventDelegate {
public static final String EXTRA_CHAT_ID = "chat_id";
public static final String EXTRA_CALL_ID = "call_id";
public static final String EXTRA_HASH = "hash";
private DcContext dcContext;
private String url = "file:///android_asset/call.html";
private int chatId;
private int callId;
@SuppressLint("SetJavaScriptEnabled")
@Override
protected void onCreate(Bundle state, boolean ready) {
super.onCreate(state, ready);
this.dcContext = DcHelper.getContext(getApplicationContext());
Bundle b = getIntent().getExtras();
String hash = b.getString(EXTRA_HASH, "");
int chatId = b.getInt(EXTRA_CHAT_ID, 0);
Bundle bundle = getIntent().getExtras();
assert bundle != null;
String hash = bundle.getString(EXTRA_HASH, "");
chatId = bundle.getInt(EXTRA_CHAT_ID, 0);
callId = bundle.getInt(EXTRA_CALL_ID, 0);
WebSettings webSettings = webView.getSettings();
webSettings.setJavaScriptEnabled(true);
webSettings.setMediaPlaybackRequiresUserGesture(false);
webView.addJavascriptInterface(new InternalJSApi(), "calls");
webView.setWebChromeClient(new WebChromeClient() {
@Override
public void onPermissionRequest(PermissionRequest request) {
Util.runOnMain(() -> {
request.grant(request.getResources());
});
Util.runOnMain(() -> request.grant(request.getResources()));
}
});
DcEventCenter eventCenter = DcHelper.getEventCenter(getApplicationContext());
eventCenter.addObserver(DcContext.DC_EVENT_OUTGOING_CALL_ACCEPTED, this);
eventCenter.addObserver(DcContext.DC_EVENT_CALL_ENDED, this);
Util.runOnAnyBackgroundThread(() -> {
final DcChat chat = dcContext.getChat(chatId);
Util.runOnMain(() -> {
getSupportActionBar().setTitle(chat.getName());
});
Util.runOnMain(() -> Objects.requireNonNull(getSupportActionBar()).setTitle(chat.getName()));
});
webView.loadUrl(url+hash);
String url = "file:///android_asset/call.html";
webView.loadUrl(url + hash);
}
@Override
@@ -65,4 +79,39 @@ public class VideochatActivity extends WebViewActivity {
finish();
return true;
}
@Override
public void handleEvent(@NonNull DcEvent event) {
switch (event.getId()) {
case DcContext.DC_EVENT_OUTGOING_CALL_ACCEPTED:
if (event.getData1Int() == callId) {
String hash = "#answer=" + event.getData2Str();
webView.evaluateJavascript("window.location.hash = `"+hash+"`", null);
}
break;
case DcContext.DC_EVENT_CALL_ENDED:
if (event.getData1Int() == callId) {
finish();
}
break;
}
}
class InternalJSApi {
@JavascriptInterface
public void startCall(String payload) {
callId = dcContext.placeOutgoingCall(chatId, payload);
}
@JavascriptInterface
public void acceptCall(String payload) {
dcContext.acceptIncomingCall(callId, payload);
}
@JavascriptInterface
public void endCall() {
dcContext.endCall(callId);
}
}
}
@@ -15,10 +15,6 @@ import org.thoughtcrime.securesms.connect.DcHelper;
import org.thoughtcrime.securesms.permissions.Permissions;
import org.thoughtcrime.securesms.util.IntentUtils;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
public class VideochatUtil {
public static void startMeeting(Activity activity, int chatId) {
@@ -53,16 +49,19 @@ public class VideochatUtil {
.setTitle(activity.getString(R.string.videochat_invite_user_to_videochat, dcChat.getName()))
.setNegativeButton(R.string.cancel, null)
.setPositiveButton(R.string.ok, (dialog, which) -> {
joinCall(activity, chatId, "#call");
openCall(activity, chatId, 0, "#call");
})
.show();
}
public static void joinCall(Activity activity, int chatId) {
joinCall(activity, chatId, "");
public static void joinCall(Activity activity, int callId, String payload) {
DcContext dcContext = DcHelper.getContext(activity);
DcMsg dcMsg = dcContext.getMsg(callId);
String hash = "#offer=" + payload;
openCall(activity, dcMsg.getChatId(), callId, hash);
}
private static void joinCall(Activity activity, int chatId, String hash) {
private static void openCall(Activity activity, int chatId, int callId, String hash) {
Permissions.with(activity)
.request(Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO)
.ifNecessary()
@@ -71,6 +70,7 @@ public class VideochatUtil {
Intent intent = new Intent(activity, VideochatActivity.class);
intent.setAction(Intent.ACTION_VIEW);
intent.putExtra(VideochatActivity.EXTRA_CHAT_ID, chatId);
intent.putExtra(VideochatActivity.EXTRA_CALL_ID, callId);
intent.putExtra(VideochatActivity.EXTRA_HASH, hash);
activity.startActivity(intent);
})