diff --git a/src/main/java/org/thoughtcrime/securesms/ConversationItem.java b/src/main/java/org/thoughtcrime/securesms/ConversationItem.java index 7e25ff032..bb9fc5e64 100644 --- a/src/main/java/org/thoughtcrime/securesms/ConversationItem.java +++ b/src/main/java/org/thoughtcrime/securesms/ConversationItem.java @@ -70,11 +70,14 @@ import org.thoughtcrime.securesms.util.MediaUtil; import org.thoughtcrime.securesms.util.Util; import org.thoughtcrime.securesms.util.ViewUtil; import org.thoughtcrime.securesms.util.views.Stub; +import org.thoughtcrime.securesms.videochat.VideochatUtil; import java.util.List; import java.util.Set; import chat.delta.rpc.RpcException; +import chat.delta.rpc.types.CallInfo; +import chat.delta.rpc.types.CallState; import chat.delta.rpc.types.Reactions; import chat.delta.rpc.types.VcardContact; @@ -589,7 +592,7 @@ public class ConversationItem extends BaseConversationItem } catch (RpcException e) { Log.e(TAG, "Error in Rpc.callInfo", e); } - callViewStub.get().setOnClickListener(passthroughClickListener); + callViewStub.get().setCallClickListener(new CallClickListener()); callViewStub.get().setOnLongClickListener(passthroughClickListener); callViewStub.get().setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS); @@ -983,4 +986,21 @@ public class ConversationItem extends BaseConversationItem } } } + + private class CallClickListener implements CallItemView.CallClickListener { + public void onClick(final View v, final CallInfo callInfo) { + if (shouldInterceptClicks(messageRecord) || !batchSelected.isEmpty()) { + performClick(); + } else { + int accId = dcContext.getAccountId(); + int chatId = messageRecord.getChatId(); + if (!messageRecord.isOutgoing() && callInfo.state instanceof CallState.Alerting) { + int callId = messageRecord.getId(); + VideochatUtil.openCall(getContext(), accId, chatId, callId, callInfo.sdpOffer); + } else { + VideochatUtil.startCall(getContext(), accId, chatId); + } + } + } + } } diff --git a/src/main/java/org/thoughtcrime/securesms/components/CallItemView.java b/src/main/java/org/thoughtcrime/securesms/components/CallItemView.java index cc4844eb8..4d829b2bd 100644 --- a/src/main/java/org/thoughtcrime/securesms/components/CallItemView.java +++ b/src/main/java/org/thoughtcrime/securesms/components/CallItemView.java @@ -4,6 +4,7 @@ import android.content.Context; import android.content.res.TypedArray; import android.graphics.Color; import android.util.AttributeSet; +import android.view.View; import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.TextView; @@ -21,6 +22,8 @@ public class CallItemView extends FrameLayout { private final @NonNull ImageView icon; private final @NonNull TextView title; private final @NonNull ConversationItemFooter footer; + private CallInfo callInfo; + private CallClickListener viewListener; public CallItemView(Context context) { this(context, null); @@ -38,9 +41,20 @@ public class CallItemView extends FrameLayout { this.icon = findViewById(R.id.call_icon); this.title = findViewById(R.id.title); this.footer = findViewById(R.id.footer); + + setOnClickListener(v -> { + if (viewListener != null && callInfo != null) { + viewListener.onClick(v, callInfo); + } + }); + } + + public void setCallClickListener(CallClickListener listener) { + viewListener = listener; } public void setCallItem(boolean isOutgoing, CallInfo callInfo) { + this.callInfo = callInfo; if (callInfo.state instanceof CallState.Missed) { title.setText(R.string.missed_call); } else if (callInfo.state instanceof CallState.Cancelled) { @@ -77,4 +91,8 @@ public class CallItemView extends FrameLayout { public String getDescription() { return title.getText() + "\n" + footer.getDescription(); } + + public interface CallClickListener { + void onClick(View v, CallInfo callInfo); + } } diff --git a/src/main/java/org/thoughtcrime/securesms/videochat/VideochatUtil.java b/src/main/java/org/thoughtcrime/securesms/videochat/VideochatUtil.java index 7288536d3..209e22896 100644 --- a/src/main/java/org/thoughtcrime/securesms/videochat/VideochatUtil.java +++ b/src/main/java/org/thoughtcrime/securesms/videochat/VideochatUtil.java @@ -2,13 +2,21 @@ package org.thoughtcrime.securesms.videochat; import android.Manifest; import android.app.Activity; +import android.content.Context; import android.content.Intent; +import android.util.Base64; +import android.util.Log; import org.thoughtcrime.securesms.R; import org.thoughtcrime.securesms.connect.DcHelper; import org.thoughtcrime.securesms.permissions.Permissions; +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; + public class VideochatUtil { + private static final String TAG = VideochatUtil.class.getSimpleName(); public static void startCall(Activity activity, int chatId) { Permissions.with(activity) @@ -17,14 +25,36 @@ public class VideochatUtil { .withPermanentDenialDialog(activity.getString(R.string.perm_explain_access_to_camera_denied)) .onAllGranted(() -> { int accId = DcHelper.getContext(activity).getAccountId(); - Intent intent = new Intent(activity, VideochatActivity.class); - intent.setAction(Intent.ACTION_VIEW); - intent.putExtra(VideochatActivity.EXTRA_ACCOUNT_ID, accId); - intent.putExtra(VideochatActivity.EXTRA_CHAT_ID, chatId); - intent.putExtra(VideochatActivity.EXTRA_HASH, "#startCall"); - activity.startActivity(intent); + startCall(activity, accId, chatId); }) .execute(); } + public static void startCall(Context context, int accId, int chatId) { + Intent intent = new Intent(context, VideochatActivity.class); + intent.setAction(Intent.ACTION_VIEW); + intent.putExtra(VideochatActivity.EXTRA_ACCOUNT_ID, accId); + intent.putExtra(VideochatActivity.EXTRA_CHAT_ID, chatId); + intent.putExtra(VideochatActivity.EXTRA_HASH, "#startCall"); + context.startActivity(intent); + } + + public static void openCall(Context context, int accId, int chatId, int callId, String payload) { + String base64 = Base64.encodeToString(payload.getBytes(StandardCharsets.UTF_8), Base64.NO_WRAP); + String hash = ""; + try { + hash = "#offerIncomingCall=" + URLEncoder.encode(base64, "UTF-8"); + } catch (UnsupportedEncodingException e) { + Log.e(TAG, "Error", e); + } + + Intent intent = new Intent(context, VideochatActivity.class); + intent.setAction(Intent.ACTION_VIEW); + intent.putExtra(VideochatActivity.EXTRA_ACCOUNT_ID, accId); + intent.putExtra(VideochatActivity.EXTRA_CHAT_ID, chatId); + intent.putExtra(VideochatActivity.EXTRA_CALL_ID, callId); + intent.putExtra(VideochatActivity.EXTRA_HASH, hash); + context.startActivity(intent); + } + }