mirror of
https://github.com/ArcaneChat/android.git
synced 2026-07-03 14:05:24 +02:00
Make it possible to answer incoming calls from messages (#4415)
This commit is contained in:
@@ -1091,7 +1091,18 @@ public class ConversationItem extends BaseConversationItem {
|
||||
if (!messageRecord.isOutgoing() && callInfo.state instanceof CallState.Alerting) {
|
||||
int callId = messageRecord.getId();
|
||||
CallCoordinator coordinator = CallCoordinator.getInstance(context);
|
||||
coordinator.showIncomingCallScreen(callId);
|
||||
|
||||
if (coordinator.hasActiveCall()) {
|
||||
coordinator.showIncomingCallScreen(callId);
|
||||
} else {
|
||||
if (callInfo.sdpOffer == null) {
|
||||
Toast.makeText(context, R.string.error, Toast.LENGTH_SHORT).show();
|
||||
return;
|
||||
}
|
||||
int accId = dcContext.getAccountId();
|
||||
coordinator.handleIncomingCallFromConversation(
|
||||
accId, callId, callInfo.sdpOffer, callInfo.hasVideo);
|
||||
}
|
||||
} else {
|
||||
if (callInfo.hasVideo) {
|
||||
CallUtil.startVideoCall(getContext(), chatId);
|
||||
|
||||
@@ -23,6 +23,7 @@ import android.os.Looper;
|
||||
import android.telecom.DisconnectCause;
|
||||
import android.util.Log;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.RequiresApi;
|
||||
import androidx.core.app.NotificationManagerCompat;
|
||||
import androidx.core.content.ContextCompat;
|
||||
@@ -32,6 +33,7 @@ import androidx.core.telecom.CallControlScope;
|
||||
import androidx.core.telecom.CallEndpointCompat;
|
||||
import androidx.core.telecom.CallException;
|
||||
import androidx.core.telecom.CallsManager;
|
||||
import androidx.core.util.Pair;
|
||||
import androidx.lifecycle.FlowLiveDataConversions;
|
||||
import androidx.lifecycle.LiveData;
|
||||
import androidx.lifecycle.MediatorLiveData;
|
||||
@@ -898,32 +900,15 @@ public class CallCoordinator implements DcEventCenter.DcEventDelegate {
|
||||
int accId, int callId, String offerSdp, boolean startsWithVideo) {
|
||||
Log.d(TAG, "onIncomingCall: accId=" + accId + ", callId=" + callId);
|
||||
|
||||
if (hasActiveCall()) {
|
||||
Log.w(TAG, "Already have an active call, ignoring incoming call");
|
||||
return;
|
||||
}
|
||||
Pair<DcChat, String> result = setupIncomingCallState(accId, callId, offerSdp, startsWithVideo);
|
||||
if (result == null) return;
|
||||
|
||||
resetLiveDataForNewCall();
|
||||
|
||||
this.activeAccId = accId;
|
||||
this.activeCallId = callId;
|
||||
this.isIncomingCall = true;
|
||||
this.startsWithVideo = startsWithVideo;
|
||||
this.pendingOfferSdp = offerSdp;
|
||||
|
||||
// Get caller info
|
||||
DcContext dcContext = ApplicationContext.getDcAccounts().getAccount(accId);
|
||||
int chatId = dcContext.getMsg(callId).getChatId();
|
||||
this.activeChatId = chatId;
|
||||
DcChat dcChat = dcContext.getChat(chatId);
|
||||
String callerName = getNameFromChat(dcChat);
|
||||
DcChat dcChat = result.first;
|
||||
String callerName = result.second;
|
||||
Icon callerIcon = getIconFromChat(this.appContext, dcChat);
|
||||
|
||||
displayName.postValue(callerName);
|
||||
displayIcon.postValue(callerIcon);
|
||||
|
||||
this.preferredStartingEndpoint = getPreferredStartingEndpoint(startsWithVideo);
|
||||
|
||||
// Add to CallsManager
|
||||
CallAttributesCompat callAttributes = createCallAttributes(callerName, callId, true);
|
||||
addCallToTelecom(callAttributes, callerName, callerIcon);
|
||||
@@ -934,6 +919,37 @@ public class CallCoordinator implements DcEventCenter.DcEventDelegate {
|
||||
startAndBindService();
|
||||
}
|
||||
|
||||
public synchronized void handleIncomingCallFromConversation(
|
||||
int accId, int callId, String offerSdp, boolean hasVideo) {
|
||||
Log.d(TAG, "handleIncomingCallFromConversation: accId=" + accId + ", callId=" + callId);
|
||||
|
||||
if (offerSdp == null || offerSdp.isEmpty()) {
|
||||
Log.e(TAG, "Cannot start incoming call: no SDP offer");
|
||||
return;
|
||||
}
|
||||
|
||||
Pair<DcChat, String> result = setupIncomingCallState(accId, callId, offerSdp, hasVideo);
|
||||
if (result == null) return;
|
||||
|
||||
DcChat dcChat = result.first;
|
||||
String callerName = result.second;
|
||||
|
||||
new Thread(
|
||||
() -> {
|
||||
Icon callerIcon = getIconFromChat(this.appContext, dcChat);
|
||||
displayIcon.postValue(callerIcon);
|
||||
})
|
||||
.start();
|
||||
|
||||
// Add to CallsManager
|
||||
CallAttributesCompat callAttributes = createCallAttributes(callerName, callId, true);
|
||||
addCallToTelecom(callAttributes, callerName, null);
|
||||
|
||||
startAndBindService();
|
||||
|
||||
launchCallActivity();
|
||||
}
|
||||
|
||||
private synchronized void onIncomingCallAccepted(int callId, boolean fromThisDevice) {
|
||||
Log.d(TAG, "onIncomingCallAccepted: callId=" + callId + ", fromThisDevice=" + fromThisDevice);
|
||||
|
||||
@@ -1304,6 +1320,35 @@ public class CallCoordinator implements DcEventCenter.DcEventDelegate {
|
||||
addCallToTelecom(callAttributes, calleeName, calleeIcon);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private Pair<DcChat, String> setupIncomingCallState(
|
||||
int accId, int callId, String offerSdp, boolean startsWithVideo) {
|
||||
if (hasActiveCall()) {
|
||||
Log.w(TAG, "Already have an active call, ignoring incoming call");
|
||||
return null;
|
||||
}
|
||||
|
||||
resetLiveDataForNewCall();
|
||||
|
||||
this.activeAccId = accId;
|
||||
this.activeCallId = callId;
|
||||
this.isIncomingCall = true;
|
||||
this.startsWithVideo = startsWithVideo;
|
||||
this.pendingOfferSdp = offerSdp;
|
||||
|
||||
DcContext dcContext = ApplicationContext.getDcAccounts().getAccount(accId);
|
||||
int chatId = dcContext.getMsg(callId).getChatId();
|
||||
this.activeChatId = chatId;
|
||||
DcChat dcChat = dcContext.getChat(chatId);
|
||||
String callerName = getNameFromChat(dcChat);
|
||||
|
||||
displayName.postValue(callerName);
|
||||
|
||||
this.preferredStartingEndpoint = getPreferredStartingEndpoint(startsWithVideo);
|
||||
|
||||
return new Pair<>(dcChat, callerName);
|
||||
}
|
||||
|
||||
public synchronized void ensureServiceStarted() {
|
||||
if (isServiceBound || !hasActiveCall()) {
|
||||
return;
|
||||
|
||||
Reference in New Issue
Block a user