diff --git a/app/src/main/java/org/thoughtcrime/securesms/backup/v2/database/CallTableBackupExtensions.kt b/app/src/main/java/org/thoughtcrime/securesms/backup/v2/database/CallTableBackupExtensions.kt index 04bb76f661..0f48979fa3 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/backup/v2/database/CallTableBackupExtensions.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/backup/v2/database/CallTableBackupExtensions.kt @@ -109,7 +109,8 @@ class CallLogIterator(private val cursor: Cursor) : Iterator, Close CallTable.Event.DECLINED -> Call.Event.DECLINED CallTable.Event.GENERIC_GROUP_CALL -> Call.Event.GENERIC_GROUP_CALL CallTable.Event.JOINED -> Call.Event.JOINED - CallTable.Event.MISSED -> Call.Event.MISSED + CallTable.Event.MISSED, + CallTable.Event.MISSED_NOTIFICATION_PROFILE -> Call.Event.MISSED CallTable.Event.DELETE -> Call.Event.DELETE CallTable.Event.RINGING -> Call.Event.UNKNOWN_EVENT CallTable.Event.NOT_ACCEPTED -> Call.Event.NOT_ACCEPTED diff --git a/app/src/main/java/org/thoughtcrime/securesms/calls/log/CallLogAdapter.kt b/app/src/main/java/org/thoughtcrime/securesms/calls/log/CallLogAdapter.kt index d5ffc9e24d..9125e44670 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/calls/log/CallLogAdapter.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/calls/log/CallLogAdapter.kt @@ -305,7 +305,7 @@ class CallLogAdapter( val color = ContextCompat.getColor( context, - if (call.record.event == CallTable.Event.MISSED) { + if (call.record.event.isMissedCall()) { R.color.signal_colorError } else { R.color.signal_colorOnSurfaceVariant @@ -375,7 +375,7 @@ class CallLogAdapter( MessageTypes.OUTGOING_AUDIO_CALL_TYPE, MessageTypes.OUTGOING_VIDEO_CALL_TYPE -> R.drawable.symbol_arrow_upright_compact_16 MessageTypes.GROUP_CALL_TYPE -> when { call.type == CallTable.Type.AD_HOC_CALL -> R.drawable.symbol_link_compact_16 - call.event == CallTable.Event.MISSED -> R.drawable.symbol_missed_incoming_compact_16 + call.event.isMissedCall() -> R.drawable.symbol_missed_incoming_compact_16 call.event == CallTable.Event.GENERIC_GROUP_CALL || call.event == CallTable.Event.JOINED -> R.drawable.symbol_group_compact_16 call.direction == CallTable.Direction.INCOMING -> R.drawable.symbol_arrow_downleft_compact_16 call.direction == CallTable.Direction.OUTGOING -> R.drawable.symbol_arrow_upright_compact_16 @@ -389,8 +389,8 @@ class CallLogAdapter( @StringRes private fun getCallStateStringRes(call: CallTable.Call): Int { return when (call.messageType) { - MessageTypes.MISSED_VIDEO_CALL_TYPE -> R.string.CallLogAdapter__missed - MessageTypes.MISSED_AUDIO_CALL_TYPE -> R.string.CallLogAdapter__missed + MessageTypes.MISSED_VIDEO_CALL_TYPE, + MessageTypes.MISSED_AUDIO_CALL_TYPE -> if (call.event == CallTable.Event.MISSED) R.string.CallLogAdapter__missed else R.string.CallLogAdapter__missed_notification_profile MessageTypes.INCOMING_AUDIO_CALL_TYPE -> R.string.CallLogAdapter__incoming MessageTypes.INCOMING_VIDEO_CALL_TYPE -> R.string.CallLogAdapter__incoming MessageTypes.OUTGOING_AUDIO_CALL_TYPE -> R.string.CallLogAdapter__outgoing @@ -398,6 +398,7 @@ class CallLogAdapter( MessageTypes.GROUP_CALL_TYPE -> when { call.type == CallTable.Type.AD_HOC_CALL -> R.string.CallLogAdapter__call_link call.event == CallTable.Event.MISSED -> R.string.CallLogAdapter__missed + call.event == CallTable.Event.MISSED_NOTIFICATION_PROFILE -> R.string.CallLogAdapter__missed_notification_profile call.event == CallTable.Event.GENERIC_GROUP_CALL || call.event == CallTable.Event.JOINED -> R.string.CallPreference__group_call call.direction == CallTable.Direction.INCOMING -> R.string.CallLogAdapter__incoming call.direction == CallTable.Direction.OUTGOING -> R.string.CallLogAdapter__outgoing diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/settings/conversation/preferences/CallPreference.kt b/app/src/main/java/org/thoughtcrime/securesms/components/settings/conversation/preferences/CallPreference.kt index aece9c00fb..6ac7dabbfd 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/settings/conversation/preferences/CallPreference.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/components/settings/conversation/preferences/CallPreference.kt @@ -49,7 +49,7 @@ object CallPreference { MessageTypes.INCOMING_AUDIO_CALL_TYPE, MessageTypes.INCOMING_VIDEO_CALL_TYPE -> R.drawable.symbol_arrow_downleft_24 MessageTypes.OUTGOING_AUDIO_CALL_TYPE, MessageTypes.OUTGOING_VIDEO_CALL_TYPE -> R.drawable.symbol_arrow_upright_24 MessageTypes.GROUP_CALL_TYPE -> when { - call.event == CallTable.Event.MISSED -> R.drawable.symbol_missed_incoming_24 + call.event.isMissedCall() -> R.drawable.symbol_missed_incoming_24 call.event == CallTable.Event.GENERIC_GROUP_CALL || call.event == CallTable.Event.JOINED -> R.drawable.symbol_group_24 call.direction == CallTable.Direction.INCOMING -> R.drawable.symbol_arrow_downleft_24 call.direction == CallTable.Direction.OUTGOING -> R.drawable.symbol_arrow_upright_24 @@ -61,14 +61,15 @@ object CallPreference { private fun getCallType(call: CallTable.Call): String { val id = when (call.messageType) { - MessageTypes.MISSED_VIDEO_CALL_TYPE -> R.string.MessageRecord_missed_voice_call - MessageTypes.MISSED_AUDIO_CALL_TYPE -> R.string.MessageRecord_missed_video_call + MessageTypes.MISSED_VIDEO_CALL_TYPE -> if (call.event == CallTable.Event.MISSED) R.string.MessageRecord_missed_voice_call else R.string.MessageRecord_missed_voice_call_notification_profile + MessageTypes.MISSED_AUDIO_CALL_TYPE -> if (call.event == CallTable.Event.MISSED) R.string.MessageRecord_missed_video_call else R.string.MessageRecord_missed_video_call_notification_profile MessageTypes.INCOMING_AUDIO_CALL_TYPE -> R.string.MessageRecord_incoming_voice_call MessageTypes.INCOMING_VIDEO_CALL_TYPE -> R.string.MessageRecord_incoming_video_call MessageTypes.OUTGOING_AUDIO_CALL_TYPE -> R.string.MessageRecord_outgoing_voice_call MessageTypes.OUTGOING_VIDEO_CALL_TYPE -> R.string.MessageRecord_outgoing_video_call MessageTypes.GROUP_CALL_TYPE -> when { call.event == CallTable.Event.MISSED -> R.string.CallPreference__missed_group_call + call.event == CallTable.Event.MISSED_NOTIFICATION_PROFILE -> R.string.CallPreference__missed_group_call_notification_profile call.event == CallTable.Event.GENERIC_GROUP_CALL || call.event == CallTable.Event.JOINED -> R.string.CallPreference__group_call call.direction == CallTable.Direction.INCOMING -> R.string.CallPreference__incoming_group_call call.direction == CallTable.Direction.OUTGOING -> R.string.CallPreference__outgoing_group_call diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/CallTable.kt b/app/src/main/java/org/thoughtcrime/securesms/database/CallTable.kt index 195e925121..e3f384e2e5 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/CallTable.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/database/CallTable.kt @@ -348,7 +348,7 @@ class CallTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTabl checkIsGroupOrAdHocCall(call) val newEvent = when (call.event) { - Event.RINGING, Event.MISSED, Event.DECLINED -> Event.ACCEPTED + Event.RINGING, Event.MISSED, Event.MISSED_NOTIFICATION_PROFILE, Event.DECLINED -> Event.ACCEPTED Event.GENERIC_GROUP_CALL -> Event.JOINED else -> { Log.d(TAG, "[acceptIncomingGroupCall] Call in state ${call.event} cannot be transitioned by ACCEPTED") @@ -371,7 +371,7 @@ class CallTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTabl val newEvent = when (call.event) { Event.GENERIC_GROUP_CALL, Event.JOINED -> Event.OUTGOING_RING - Event.RINGING, Event.MISSED, Event.DECLINED, Event.ACCEPTED -> { + Event.RINGING, Event.MISSED, Event.MISSED_NOTIFICATION_PROFILE, Event.DECLINED, Event.ACCEPTED -> { Log.w(TAG, "[acceptOutgoingGroupCall] This shouldn't have been an outgoing ring because the call already existed!") Event.ACCEPTED } @@ -396,7 +396,7 @@ class CallTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTabl check(call.direction == Direction.INCOMING) val newEvent = when (call.event) { - Event.GENERIC_GROUP_CALL, Event.RINGING, Event.MISSED -> Event.DECLINED + Event.GENERIC_GROUP_CALL, Event.RINGING, Event.MISSED, Event.MISSED_NOTIFICATION_PROFILE -> Event.DECLINED Event.JOINED -> Event.ACCEPTED else -> { Log.d(TAG, "Call in state ${call.event} cannot be transitioned by DECLINED") @@ -689,15 +689,17 @@ class CallTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTabl handleGroupRingState(ringId, groupRecipientId, ringerRecipient, dateReceived, ringState) } + @JvmOverloads fun insertOrUpdateGroupCallFromRingState( ringId: Long, groupRecipientId: RecipientId, ringerAci: ACI, dateReceived: Long, - ringState: RingUpdate + ringState: RingUpdate, + dueToNotificationProfile: Boolean = false ) { val ringerRecipient = Recipient.externalPush(ringerAci) - handleGroupRingState(ringId, groupRecipientId, ringerRecipient.id, dateReceived, ringState) + handleGroupRingState(ringId, groupRecipientId, ringerRecipient.id, dateReceived, ringState, dueToNotificationProfile) } fun isRingCancelled(ringId: Long, groupRecipientId: RecipientId): Boolean { @@ -710,7 +712,8 @@ class CallTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTabl groupRecipientId: RecipientId, ringerRecipient: RecipientId, dateReceived: Long, - ringState: RingUpdate + ringState: RingUpdate, + dueToNotificationProfile: Boolean = false ) { writableDatabase.withinTransaction { Log.d(TAG, "Processing group ring state update for $ringId in state $ringState") @@ -733,7 +736,7 @@ class CallTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTabl RingUpdate.EXPIRED_REQUEST, RingUpdate.CANCELLED_BY_RINGER -> { when (call.event) { - Event.GENERIC_GROUP_CALL, Event.RINGING -> updateEventFromRingState(ringId, Event.MISSED, ringerRecipient) + Event.GENERIC_GROUP_CALL, Event.RINGING -> updateEventFromRingState(ringId, if (dueToNotificationProfile) Event.MISSED_NOTIFICATION_PROFILE else Event.MISSED, ringerRecipient) Event.JOINED -> updateEventFromRingState(ringId, Event.ACCEPTED, ringerRecipient) Event.OUTGOING_RING -> Log.w(TAG, "Received an expiration or cancellation while in OUTGOING_RING state. Ignoring.") else -> Unit @@ -765,7 +768,7 @@ class CallTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTabl RingUpdate.DECLINED_ON_ANOTHER_DEVICE -> { when (call.event) { - Event.RINGING, Event.MISSED, Event.GENERIC_GROUP_CALL -> updateEventFromRingState(ringId, Event.DECLINED) + Event.RINGING, Event.MISSED, Event.MISSED_NOTIFICATION_PROFILE, Event.GENERIC_GROUP_CALL -> updateEventFromRingState(ringId, Event.DECLINED) Event.JOINED -> updateEventFromRingState(ringId, Event.ACCEPTED) Event.OUTGOING_RING -> Log.w(TAG, "Received DECLINED_ON_ANOTHER_DEVICE while in OUTGOING_RING state.") else -> Unit @@ -775,7 +778,7 @@ class CallTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTabl } else { val event: Event = when (ringState) { RingUpdate.REQUESTED -> Event.RINGING - RingUpdate.EXPIRED_REQUEST -> Event.MISSED + RingUpdate.EXPIRED_REQUEST -> if (dueToNotificationProfile) Event.MISSED_NOTIFICATION_PROFILE else Event.MISSED RingUpdate.ACCEPTED_ON_ANOTHER_DEVICE -> { Log.w(TAG, "Missed original ring request for $ringId") Event.ACCEPTED @@ -939,7 +942,7 @@ class CallTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTabl fun deleteAllNonAdHocCallEventsExcept(callRowIds: Set, missedOnly: Boolean) { val callFilter = if (missedOnly) { - "$EVENT = ${Event.serialize(Event.MISSED)} AND $DELETION_TIMESTAMP = 0" + "($EVENT = ${Event.serialize(Event.MISSED)} OR $EVENT = ${Event.serialize(Event.MISSED_NOTIFICATION_PROFILE)}) AND $DELETION_TIMESTAMP = 0" } else { "$DELETION_TIMESTAMP = 0" } @@ -1040,7 +1043,7 @@ class CallTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTabl private fun getCallsCursor(isCount: Boolean, offset: Int, limit: Int, searchTerm: String?, filter: CallLogFilter): Cursor { val filterClause: SqlUtil.Query = when (filter) { CallLogFilter.ALL -> SqlUtil.buildQuery("$DELETION_TIMESTAMP = 0") - CallLogFilter.MISSED -> SqlUtil.buildQuery("$EVENT = ${Event.serialize(Event.MISSED)} AND $DELETION_TIMESTAMP = 0") + CallLogFilter.MISSED -> SqlUtil.buildQuery("($EVENT = ${Event.serialize(Event.MISSED)} OR $EVENT = ${Event.serialize(Event.MISSED_NOTIFICATION_PROFILE)}) AND $DELETION_TIMESTAMP = 0") CallLogFilter.AD_HOC -> SqlUtil.buildQuery("$TYPE = ${Type.serialize(Type.AD_HOC_CALL)} AND $DELETION_TIMESTAMP = 0") } @@ -1079,6 +1082,16 @@ class CallTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTabl "p.$ID, p.$TIMESTAMP, $EVENT, $DIRECTION, $PEER, p.$TYPE, $CALL_ID, $MESSAGE_ID, $RINGER, children, in_period, ${MessageTable.BODY}," } + val eventTypeSubQuery = """ + ($TABLE_NAME.$EVENT = c.$EVENT AND ($TABLE_NAME.$EVENT = ${Event.serialize(Event.MISSED)} OR $TABLE_NAME.$EVENT = ${Event.serialize(Event.MISSED_NOTIFICATION_PROFILE)})) OR + ( + $TABLE_NAME.$EVENT != ${Event.serialize(Event.MISSED)} AND + c.$EVENT != ${Event.serialize(Event.MISSED)} AND + $TABLE_NAME.$EVENT != ${Event.serialize(Event.MISSED_NOTIFICATION_PROFILE)} AND + c.$EVENT != ${Event.serialize(Event.MISSED_NOTIFICATION_PROFILE)} + ) + """ + //language=sql val statement = """ SELECT $projection @@ -1106,10 +1119,7 @@ class CallTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTabl AND $TABLE_NAME.$PEER = c.$PEER AND $TABLE_NAME.$TIMESTAMP - $TIME_WINDOW <= c.$TIMESTAMP AND $TABLE_NAME.$TIMESTAMP >= c.$TIMESTAMP - AND ( - ($TABLE_NAME.$EVENT = c.$EVENT AND $TABLE_NAME.$EVENT = ${Event.serialize(Event.MISSED)}) OR - ($TABLE_NAME.$EVENT != ${Event.serialize(Event.MISSED)} AND c.$EVENT != ${Event.serialize(Event.MISSED)}) - ) + AND ($eventTypeSubQuery) AND ${filterClause.where} ORDER BY $TIMESTAMP DESC @@ -1124,10 +1134,7 @@ class CallTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTabl AND $TABLE_NAME.$PEER = c.$PEER AND c.$TIMESTAMP - $TIME_WINDOW <= $TABLE_NAME.$TIMESTAMP AND c.$TIMESTAMP >= $TABLE_NAME.$TIMESTAMP - AND ( - ($TABLE_NAME.$EVENT = c.$EVENT AND $TABLE_NAME.$EVENT = ${Event.serialize(Event.MISSED)}) OR - ($TABLE_NAME.$EVENT != ${Event.serialize(Event.MISSED)} AND c.$EVENT != ${Event.serialize(Event.MISSED)}) - ) + AND ($eventTypeSubQuery) AND ${filterClause.where} ) as children, ( @@ -1255,7 +1262,7 @@ class CallTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTabl return MessageTypes.GROUP_CALL_TYPE } - return if (direction == Direction.INCOMING && event == Event.MISSED) { + return if (direction == Direction.INCOMING && event.isMissedCall()) { if (type == Type.VIDEO_CALL) MessageTypes.MISSED_VIDEO_CALL_TYPE else MessageTypes.MISSED_AUDIO_CALL_TYPE } else if (direction == Direction.INCOMING) { if (type == Type.VIDEO_CALL) MessageTypes.INCOMING_VIDEO_CALL_TYPE else MessageTypes.INCOMING_AUDIO_CALL_TYPE @@ -1372,6 +1379,13 @@ class CallTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTabl */ MISSED(3), + /** + * 1:1 and Group/Ad-Hoc Calls. + * + * Call was auto-declined due to a notification profile. + */ + MISSED_NOTIFICATION_PROFILE(10), + /** * 1:1 and Group/Ad-Hoc Calls. */ @@ -1402,7 +1416,11 @@ class CallTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTabl /** * Group Calls: If you are ringing a group. */ - OUTGOING_RING(9); + OUTGOING_RING(9); // Next is 11 + + fun isMissedCall(): Boolean { + return this == MISSED || this == MISSED_NOTIFICATION_PROFILE + } companion object Serializer : IntSerializer { override fun serialize(data: Event): Int = data.code diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/ThreadBodyUtil.java b/app/src/main/java/org/thoughtcrime/securesms/database/ThreadBodyUtil.java index 1f00b92cdb..382f81bcc7 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/ThreadBodyUtil.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/ThreadBodyUtil.java @@ -135,12 +135,16 @@ public final class ThreadBodyUtil { } } else { boolean isVideoCall = call.getType() == CallTable.Type.VIDEO_CALL; - boolean isMissed = call.getEvent() == CallTable.Event.MISSED; + boolean isMissed = call.getEvent().isMissedCall(); if (accepted) { return context.getString(isVideoCall ? R.string.MessageRecord_incoming_video_call : R.string.MessageRecord_incoming_voice_call); } else if (isMissed) { - return isVideoCall ? context.getString(R.string.MessageRecord_missed_video_call) : context.getString(R.string.MessageRecord_missed_voice_call); + if (call.getEvent() == CallTable.Event.MISSED_NOTIFICATION_PROFILE) { + return isVideoCall ? context.getString(R.string.MessageRecord_missed_video_call_notification_profile) : context.getString(R.string.MessageRecord_missed_voice_call_notification_profile); + } else { + return isVideoCall ? context.getString(R.string.MessageRecord_missed_video_call) : context.getString(R.string.MessageRecord_missed_voice_call); + } } else { return isVideoCall ? context.getString(R.string.MessageRecord_you_declined_a_video_call) : context.getString(R.string.MessageRecord_you_declined_a_voice_call); } diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/model/MmsMessageRecord.java b/app/src/main/java/org/thoughtcrime/securesms/database/model/MmsMessageRecord.java index 5091055e20..4d044a5da9 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/model/MmsMessageRecord.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/model/MmsMessageRecord.java @@ -225,8 +225,8 @@ public class MmsMessageRecord extends MessageRecord { @Override public @Nullable UpdateDescription getUpdateDisplayBody(@NonNull Context context, @Nullable Consumer recipientClickHandler) { if (isCallLog() && call != null && !(call.getType() == CallTable.Type.GROUP_CALL)) { - boolean accepted = call.getEvent() == CallTable.Event.ACCEPTED; - String callDateString = getCallDateString(context); + boolean accepted = call.getEvent() == CallTable.Event.ACCEPTED; + String callDateString = getCallDateString(context); if (call.getDirection() == CallTable.Direction.OUTGOING) { if (call.getType() == CallTable.Type.AUDIO_CALL) { @@ -238,15 +238,27 @@ public class MmsMessageRecord extends MessageRecord { } } else { boolean isVideoCall = call.getType() == CallTable.Type.VIDEO_CALL; - boolean isMissed = call.getEvent() == CallTable.Event.MISSED; + boolean isMissed = call.getEvent().isMissedCall(); if (accepted) { int updateString = isVideoCall ? R.string.MessageRecord_incoming_video_call : R.string.MessageRecord_incoming_voice_call; int icon = isVideoCall ? R.drawable.ic_update_video_call_incoming_16 : R.drawable.ic_update_audio_call_incoming_16; return staticUpdateDescription(context.getString(R.string.MessageRecord_call_message_with_date, context.getString(updateString), callDateString), icon); } else if (isMissed) { - return isVideoCall ? staticUpdateDescription(context.getString(R.string.MessageRecord_call_message_with_date, context.getString(R.string.MessageRecord_missed_video_call), callDateString), R.drawable.ic_update_video_call_missed_16, ContextCompat.getColor(context, R.color.core_red_shade), ContextCompat.getColor(context, R.color.core_red)) - : staticUpdateDescription(context.getString(R.string.MessageRecord_call_message_with_date, context.getString(R.string.MessageRecord_missed_voice_call), callDateString), R.drawable.ic_update_audio_call_missed_16, ContextCompat.getColor(context, R.color.core_red_shade), ContextCompat.getColor(context, R.color.core_red)); + int icon = isVideoCall ? R.drawable.ic_update_video_call_missed_16 : R.drawable.ic_update_audio_call_missed_16; + int message; + if (call.getEvent() == CallTable.Event.MISSED_NOTIFICATION_PROFILE) { + message = isVideoCall ? R.string.MessageRecord_missed_video_call_notification_profile : R.string.MessageRecord_missed_voice_call_notification_profile; + } else { + message = isVideoCall ? R.string.MessageRecord_missed_video_call : R.string.MessageRecord_missed_voice_call; + } + + return staticUpdateDescription(context.getString(R.string.MessageRecord_call_message_with_date, + context.getString(message), + callDateString), + icon, + ContextCompat.getColor(context, R.color.core_red_shade), + ContextCompat.getColor(context, R.color.core_red)); } else { return isVideoCall ? staticUpdateDescription(context.getString(R.string.MessageRecord_call_message_with_date, context.getString(R.string.MessageRecord_you_declined_a_video_call), callDateString), R.drawable.ic_update_video_call_incoming_16) : staticUpdateDescription(context.getString(R.string.MessageRecord_call_message_with_date, context.getString(R.string.MessageRecord_you_declined_a_voice_call), callDateString), R.drawable.ic_update_audio_call_incoming_16); diff --git a/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/IdleActionProcessor.java b/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/IdleActionProcessor.java index a46d3da071..692471738f 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/IdleActionProcessor.java +++ b/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/IdleActionProcessor.java @@ -124,7 +124,7 @@ public class IdleActionProcessor extends WebRtcActionProcessor { if (activeProfile != null && !(activeProfile.isRecipientAllowed(remotePeerGroup.getId()) || activeProfile.getAllowAllCalls())) { try { Log.i(TAG, "Incoming ring request for profile restricted recipient"); - SignalDatabase.calls().insertOrUpdateGroupCallFromRingState(ringId, remotePeerGroup.getId(), sender, System.currentTimeMillis(), CallManager.RingUpdate.EXPIRED_REQUEST); + SignalDatabase.calls().insertOrUpdateGroupCallFromRingState(ringId, remotePeerGroup.getId(), sender, System.currentTimeMillis(), CallManager.RingUpdate.EXPIRED_REQUEST, true); webRtcInteractor.getCallManager().cancelGroupRing(groupId.getDecodedId(), ringId, CallManager.RingCancelReason.DeclinedByUser); } catch (CallException e) { Log.w(TAG, "Error while trying to cancel ring: " + ringId, e); diff --git a/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/SignalCallManager.java b/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/SignalCallManager.java index c10dd3ca2d..a64adee61a 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/SignalCallManager.java +++ b/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/SignalCallManager.java @@ -963,15 +963,15 @@ public final class SignalCallManager implements CallManager.Observer, GroupCall. }); } - public void insertMissedCall(@NonNull RemotePeer remotePeer, long timestamp, boolean isVideoOffer) { + public void insertMissedCall(@NonNull RemotePeer remotePeer, long timestamp, boolean isVideoOffer, @NonNull CallTable.Event missedEvent) { CallTable.Call call = SignalDatabase.calls() - .updateOneToOneCall(remotePeer.getCallId().longValue(), CallTable.Event.MISSED); + .updateOneToOneCall(remotePeer.getCallId().longValue(), missedEvent); if (call == null) { CallTable.Type type = isVideoOffer ? CallTable.Type.VIDEO_CALL : CallTable.Type.AUDIO_CALL; SignalDatabase.calls() - .insertOneToOneCall(remotePeer.getCallId().longValue(), timestamp, remotePeer.getId(), type, CallTable.Direction.INCOMING, CallTable.Event.MISSED); + .insertOneToOneCall(remotePeer.getCallId().longValue(), timestamp, remotePeer.getId(), type, CallTable.Direction.INCOMING, missedEvent); } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/WebRtcActionProcessor.java b/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/WebRtcActionProcessor.java index 8916507314..e0091015a9 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/WebRtcActionProcessor.java +++ b/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/WebRtcActionProcessor.java @@ -22,6 +22,7 @@ import org.thoughtcrime.securesms.components.sensors.Orientation; import org.thoughtcrime.securesms.components.webrtc.BroadcastVideoSink; import org.thoughtcrime.securesms.components.webrtc.EglBaseWrapper; import org.thoughtcrime.securesms.components.webrtc.GroupCallSafetyNumberChangeNotificationUtil; +import org.thoughtcrime.securesms.database.CallTable; import org.thoughtcrime.securesms.database.SignalDatabase; import org.thoughtcrime.securesms.dependencies.ApplicationDependencies; import org.thoughtcrime.securesms.events.CallParticipant; @@ -197,7 +198,8 @@ public abstract class WebRtcActionProcessor { NotificationProfile activeProfile = NotificationProfiles.getActiveProfile(SignalDatabase.notificationProfiles().getProfiles()); if (activeProfile != null && !(activeProfile.isRecipientAllowed(callMetadata.getRemotePeer().getId()) || activeProfile.getAllowAllCalls())) { Log.w(tag, "Caller is excluded by notification profile."); - webRtcInteractor.insertMissedCall(callMetadata.getRemotePeer(), receivedOfferMetadata.getServerReceivedTimestamp(), offerMetadata.getOfferType() == OfferMessage.Type.VIDEO_CALL); + currentState = currentState.getActionProcessor().handleSendHangup(currentState, callMetadata, WebRtcData.HangupMetadata.fromType(HangupMessage.Type.BUSY), true); + webRtcInteractor.insertMissedCall(callMetadata.getRemotePeer(), receivedOfferMetadata.getServerReceivedTimestamp(), offerMetadata.getOfferType() == OfferMessage.Type.VIDEO_CALL, CallTable.Event.MISSED_NOTIFICATION_PROFILE); return currentState; } diff --git a/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/WebRtcInteractor.java b/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/WebRtcInteractor.java index c113b1d3d3..37c5e7e31d 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/WebRtcInteractor.java +++ b/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/WebRtcInteractor.java @@ -9,6 +9,7 @@ import androidx.annotation.Nullable; import org.signal.ringrtc.CallId; import org.signal.ringrtc.CallManager; import org.signal.ringrtc.GroupCall; +import org.thoughtcrime.securesms.database.CallTable; import org.thoughtcrime.securesms.groups.GroupId; import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.recipients.RecipientId; @@ -20,6 +21,7 @@ import org.thoughtcrime.securesms.webrtc.audio.AudioManagerCommand; import org.thoughtcrime.securesms.webrtc.audio.SignalAudioManager; import org.thoughtcrime.securesms.webrtc.locks.LockManager; import org.whispersystems.signalservice.api.messages.calls.SignalServiceCallMessage; +import org.whispersystems.signalservice.internal.push.SyncMessage; import java.util.Collection; import java.util.UUID; @@ -110,7 +112,11 @@ public class WebRtcInteractor { } void insertMissedCall(@NonNull RemotePeer remotePeer, long timestamp, boolean isVideoOffer) { - signalCallManager.insertMissedCall(remotePeer, timestamp, isVideoOffer); + insertMissedCall(remotePeer, timestamp, isVideoOffer, CallTable.Event.MISSED); + } + + void insertMissedCall(@NonNull RemotePeer remotePeer, long timestamp, boolean isVideoOffer, @NonNull CallTable.Event missedEvent) { + signalCallManager.insertMissedCall(remotePeer, timestamp, isVideoOffer, missedEvent); } void insertReceivedCall(@NonNull RemotePeer remotePeer, boolean isVideoOffer) { diff --git a/app/src/main/res/layout/call_log_adapter_item.xml b/app/src/main/res/layout/call_log_adapter_item.xml index b793748300..c6de6ffb0d 100644 --- a/app/src/main/res/layout/call_log_adapter_item.xml +++ b/app/src/main/res/layout/call_log_adapter_item.xml @@ -74,7 +74,7 @@ android:drawablePadding="6dp" android:ellipsize="end" android:gravity="start|center_vertical" - android:maxLines="1" + android:maxLines="2" android:textAlignment="viewStart" android:textAppearance="@style/Signal.Text.BodyMedium" android:textColor="@color/signal_colorOnSurfaceVariant" diff --git a/app/src/main/res/layout/conversation_settings_call_preference_item.xml b/app/src/main/res/layout/conversation_settings_call_preference_item.xml index 39c92bb8e1..0f603d47a2 100644 --- a/app/src/main/res/layout/conversation_settings_call_preference_item.xml +++ b/app/src/main/res/layout/conversation_settings_call_preference_item.xml @@ -21,11 +21,12 @@ Missed voice call Missed video call + + Missed voice call while notification profile on + + Missed video call while notification profile on You declined a voice call @@ -6255,6 +6259,8 @@ Outgoing Missed + + Missed while notification profile on Join @@ -6362,6 +6368,8 @@ Group call Missed group call + + Missed group call while notification profile on Incoming group call