Initial raise hand support.

This commit is contained in:
Nicholas Tinsley
2023-12-08 21:07:00 -05:00
committed by Cody Henthorne
parent f2a7824168
commit c2f5a6390e
28 changed files with 577 additions and 23 deletions

View File

@@ -50,6 +50,7 @@ public class BeginCallActionProcessorDelegate extends WebRtcActionProcessor {
true,
true,
false,
currentState.getCallInfoState().getRaisedHands().contains(remotePeer.getRecipient()),
0,
true,
0,
@@ -108,6 +109,7 @@ public class BeginCallActionProcessorDelegate extends WebRtcActionProcessor {
true,
true,
false,
currentState.getCallInfoState().getRaisedHands().contains(remotePeer.getRecipient()),
0,
true,
0,

View File

@@ -116,6 +116,7 @@ public class GroupActionProcessor extends DeviceAwareActionProcessor {
device.getForwardingVideo() == null || device.getForwardingVideo(),
Boolean.FALSE.equals(device.getAudioMuted()),
Boolean.FALSE.equals(device.getVideoMuted()),
currentState.getCallInfoState().getRaisedHands().contains(recipient),
device.getSpeakerTime(),
device.getMediaKeysReceived(),
device.getAddedTime(),

View File

@@ -14,6 +14,7 @@ import org.signal.ringrtc.GroupCall;
import org.signal.ringrtc.PeekInfo;
import org.thoughtcrime.securesms.events.CallParticipant;
import org.thoughtcrime.securesms.events.CallParticipantId;
import org.thoughtcrime.securesms.events.GroupCallRaiseHandEvent;
import org.thoughtcrime.securesms.events.GroupCallReactionEvent;
import org.thoughtcrime.securesms.events.WebRtcViewModel;
import org.thoughtcrime.securesms.keyvalue.SignalStore;
@@ -26,10 +27,15 @@ import org.thoughtcrime.securesms.service.webrtc.state.WebRtcServiceState;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;
import ezvcard.util.StringUtils;
/**
* Process actions for when the call has at least once been connected and joined.
@@ -202,6 +208,21 @@ public class GroupConnectedActionProcessor extends GroupActionProcessor {
return terminateGroupCall(currentState);
}
@Override
protected @NonNull WebRtcServiceState handleSelfRaiseHand(@NonNull WebRtcServiceState currentState, boolean raised) {
Log.i(tag, "handleSelfRaiseHand():");
try {
final CallInfoState callInfoState = currentState.getCallInfoState();
callInfoState.requireGroupCall().raiseHand(raised);
return currentState;
} catch (CallException e) {
Log.w(TAG, "Unable to " + (raised ? "raise" : "lower") + " hand in group call", e);
}
return currentState;
}
@Override
protected @NonNull WebRtcEphemeralState handleSendGroupReact(@NonNull WebRtcServiceState currentState, @NonNull WebRtcEphemeralState ephemeralState, @NonNull String reaction) {
try {
@@ -242,4 +263,37 @@ public class GroupConnectedActionProcessor extends GroupActionProcessor {
return new GroupCallReactionEvent(participant.getRecipient(), reaction.value, System.currentTimeMillis());
}
@Override
protected @NonNull WebRtcServiceState handleGroupCallRaisedHand(@NonNull WebRtcServiceState currentState, List<Long> raisedHands) {
Log.i(tag, "handleGroupCallRaisedHand():");
List<GroupCallRaiseHandEvent> existingHands = currentState.getCallInfoState().getRaisedHands();
List<CallParticipant> participants = currentState.getCallInfoState().getRemoteCallParticipants();
List<GroupCallRaiseHandEvent> currentRaisedHands = raisedHands
.stream().map(demuxId -> {
if (Objects.equals(demuxId, currentState.getCallInfoState().requireGroupCall().getLocalDeviceState().getDemuxId())) {
return Recipient.self();
}
CallParticipant participant = participants.stream().filter(it -> it.getCallParticipantId().getDemuxId() == demuxId).findFirst().orElse(null);
if (participant == null) {
Log.v(TAG, "Could not find CallParticipantId in list of call participants based on demuxId for raise hand.");
return null;
}
return participant.getRecipient();
})
.filter(Objects::nonNull)
.map(recipient -> {
final Optional<GroupCallRaiseHandEvent> matchingEvent = existingHands.stream().filter(existingEvent -> existingEvent.getSender().equals(recipient)).findFirst();
if (matchingEvent.isPresent()) {
return matchingEvent.get();
} else {
return new GroupCallRaiseHandEvent(recipient, System.currentTimeMillis());
}
})
.collect(Collectors.toList());
return currentState.builder().changeCallInfoState().setRaisedHand(currentRaisedHands).build();
}
}

View File

@@ -137,6 +137,7 @@ public class GroupPreJoinActionProcessor extends GroupActionProcessor {
true,
true,
true,
currentState.getCallInfoState().getRaisedHands().contains(recipient),
0,
false,
0,

View File

@@ -167,6 +167,7 @@ public final class IncomingGroupCallActionProcessor extends DeviceAwareActionPro
true,
true,
false,
currentState.getCallInfoState().getRaisedHands().contains(remotePeerGroup.getRecipient()),
0,
true,
0,

View File

@@ -295,6 +295,10 @@ public final class SignalCallManager implements CallManager.Observer, GroupCall.
process((s, p) -> p.handleScreenOffChange(s));
}
public void raiseHand(boolean raised) {
process((s, p) -> p.handleSelfRaiseHand(s, raised));
}
public void react(@NonNull String reaction) {
processStateless(s -> serviceState.getActionProcessor().handleSendGroupReact(serviceState, s, reaction));
}
@@ -909,7 +913,9 @@ public final class SignalCallManager implements CallManager.Observer, GroupCall.
@Override
public void onRaisedHands(@NonNull GroupCall groupCall, List<Long> raisedHands) {
// TODO: Implement handling of raise hand.
if (FeatureFlags.groupCallRaiseHand()) {
process((s, p) -> p.handleGroupCallRaisedHand(s, raisedHands));
}
}
@Override

View File

@@ -546,6 +546,12 @@ public abstract class WebRtcActionProcessor {
return currentState;
}
protected @NonNull WebRtcServiceState handleSelfRaiseHand(@NonNull WebRtcServiceState currentState, boolean raised) {
Log.i(tag, "raiseHand not processed");
return currentState;
}
protected @NonNull WebRtcEphemeralState handleSendGroupReact(@NonNull WebRtcServiceState currentState, @NonNull WebRtcEphemeralState ephemeralState, @NonNull String reaction) {
Log.i(tag, "react not processed");
return ephemeralState;
@@ -739,6 +745,11 @@ public abstract class WebRtcActionProcessor {
return ephemeralState;
}
protected @NonNull WebRtcServiceState handleGroupCallRaisedHand(@NonNull WebRtcServiceState currentState, List<Long> raisedHands) {
Log.i(tag, "handleGroupCallRaisedHand not processed");
return currentState;
}
protected @NonNull WebRtcServiceState handleGroupRequestMembershipProof(@NonNull WebRtcServiceState currentState, int groupCallHashCode) {
Log.i(tag, "handleGroupRequestMembershipProof not processed");
return currentState;

View File

@@ -5,6 +5,7 @@ import org.signal.ringrtc.CallId
import org.signal.ringrtc.GroupCall
import org.thoughtcrime.securesms.events.CallParticipant
import org.thoughtcrime.securesms.events.CallParticipantId
import org.thoughtcrime.securesms.events.GroupCallRaiseHandEvent
import org.thoughtcrime.securesms.events.WebRtcViewModel
import org.thoughtcrime.securesms.recipients.Recipient
import org.thoughtcrime.securesms.recipients.RecipientId
@@ -30,7 +31,8 @@ data class CallInfoState(
var remoteDevicesCount: OptionalLong = OptionalLong.empty(),
var participantLimit: Long? = null,
var pendingParticipants: PendingParticipantCollection = PendingParticipantCollection(),
var callLinkDisconnectReason: CallLinkDisconnectReason? = null
var callLinkDisconnectReason: CallLinkDisconnectReason? = null,
var raisedHands: List<GroupCallRaiseHandEvent> = emptyList()
) {
val remoteCallParticipants: List<CallParticipant>

View File

@@ -12,6 +12,7 @@ import org.thoughtcrime.securesms.components.webrtc.BroadcastVideoSink;
import org.thoughtcrime.securesms.components.webrtc.EglBaseWrapper;
import org.thoughtcrime.securesms.events.CallParticipant;
import org.thoughtcrime.securesms.events.CallParticipantId;
import org.thoughtcrime.securesms.events.GroupCallRaiseHandEvent;
import org.thoughtcrime.securesms.events.WebRtcViewModel;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.recipients.RecipientId;
@@ -364,5 +365,10 @@ public class WebRtcServiceStateBuilder {
toBuild.setCallLinkDisconnectReason(callLinkDisconnectReason);
return this;
}
public @NonNull CallInfoStateBuilder setRaisedHand(@NonNull List<GroupCallRaiseHandEvent> raisedHands) {
toBuild.setRaisedHands(raisedHands);
return this;
}
}
}