From 8933d89b56df9c9974ffdda9e8a6780a1f34178c Mon Sep 17 00:00:00 2001 From: Alex Hart Date: Tue, 17 Sep 2024 09:23:27 -0300 Subject: [PATCH] Filter call link events we don't have root keys for and disambiguate return / join. --- .../securesms/calls/log/CallLogAdapter.kt | 24 ++++++++++++------- .../securesms/calls/log/CallLogFragment.kt | 1 + .../securesms/calls/log/CallLogPeekHelper.kt | 20 ++++++++++++++++ .../securesms/calls/log/CallLogRepository.kt | 1 + .../securesms/calls/log/CallLogRow.kt | 8 +++---- .../securesms/database/CallTable.kt | 7 +++++- 6 files changed, 47 insertions(+), 14 deletions(-) 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 4c50cddc6c..e1a923dbdc 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 @@ -15,6 +15,7 @@ import org.thoughtcrime.securesms.databinding.CallLogAdapterItemBinding import org.thoughtcrime.securesms.databinding.CallLogCreateCallLinkItemBinding import org.thoughtcrime.securesms.databinding.ConversationListItemClearFilterBinding import org.thoughtcrime.securesms.recipients.Recipient +import org.thoughtcrime.securesms.recipients.RecipientId import org.thoughtcrime.securesms.util.DateUtils import org.thoughtcrime.securesms.util.SearchUtil import org.thoughtcrime.securesms.util.adapter.mapping.BindingFactory @@ -84,14 +85,15 @@ class CallLogAdapter( fun submitCallRows( rows: List, selectionState: CallLogSelectionState, + localCallRecipientId: RecipientId, onCommit: () -> Unit ): Int { val filteredRows = rows .filterNotNull() .map { when (it) { - is CallLogRow.Call -> CallModel(it, selectionState, itemCount) - is CallLogRow.CallLink -> CallLinkModel(it, selectionState, itemCount) + is CallLogRow.Call -> CallModel(it, selectionState, itemCount, it.peer.id == localCallRecipientId) + is CallLogRow.CallLink -> CallLinkModel(it, selectionState, itemCount, it.recipient.id == localCallRecipientId) is CallLogRow.ClearFilter -> ClearFilterModel() is CallLogRow.CreateCallLink -> CreateCallLinkModel() } @@ -105,14 +107,16 @@ class CallLogAdapter( private class CallModel( val call: CallLogRow.Call, val selectionState: CallLogSelectionState, - val itemCount: Int + val itemCount: Int, + val isLocalDeviceInCall: Boolean ) : MappingModel { override fun areItemsTheSame(newItem: CallModel): Boolean = call.id == newItem.call.id override fun areContentsTheSame(newItem: CallModel): Boolean { return call == newItem.call && isSelectionStateTheSame(newItem) && - isItemCountTheSame(newItem) + isItemCountTheSame(newItem) && + isLocalDeviceInCall == newItem.isLocalDeviceInCall } override fun getChangePayload(newItem: CallModel): Any? { @@ -136,7 +140,8 @@ class CallLogAdapter( private class CallLinkModel( val callLink: CallLogRow.CallLink, val selectionState: CallLogSelectionState, - val itemCount: Int + val itemCount: Int, + val isLocalDeviceInCall: Boolean ) : MappingModel { override fun areItemsTheSame(newItem: CallLinkModel): Boolean { @@ -146,7 +151,8 @@ class CallLogAdapter( override fun areContentsTheSame(newItem: CallLinkModel): Boolean { return callLink == newItem.callLink && isSelectionStateTheSame(newItem) && - isItemCountTheSame(newItem) + isItemCountTheSame(newItem) && + isLocalDeviceInCall == newItem.isLocalDeviceInCall } override fun getChangePayload(newItem: CallLinkModel): Any? { @@ -230,7 +236,7 @@ class CallLogAdapter( if (model.callLink.callLinkPeekInfo?.isActive == true) { binding.groupCallButton.setText( - if (model.callLink.callLinkPeekInfo.isJoined) { + if (model.callLink.callLinkPeekInfo.isJoined && model.isLocalDeviceInCall) { R.string.CallLogAdapter__return } else { R.string.CallLogAdapter__join @@ -364,7 +370,7 @@ class CallLogAdapter( binding.groupCallButton.visible = true binding.groupCallButton.setText( - if (model.call.callLinkPeekInfo.isJoined) { + if (model.call.callLinkPeekInfo.isJoined && model.isLocalDeviceInCall) { R.string.CallLogAdapter__return } else { R.string.CallLogAdapter__join @@ -393,7 +399,7 @@ class CallLogAdapter( binding.groupCallButton.visible = true binding.groupCallButton.setText( - if (model.call.groupCallState == CallLogRow.GroupCallState.LOCAL_USER_JOINED) { + if (model.call.groupCallState == CallLogRow.GroupCallState.LOCAL_USER_JOINED && model.isLocalDeviceInCall) { R.string.CallLogAdapter__return } else { R.string.CallLogAdapter__join diff --git a/app/src/main/java/org/thoughtcrime/securesms/calls/log/CallLogFragment.kt b/app/src/main/java/org/thoughtcrime/securesms/calls/log/CallLogFragment.kt index 9589422351..aaaa90b57a 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/calls/log/CallLogFragment.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/calls/log/CallLogFragment.kt @@ -152,6 +152,7 @@ class CallLogFragment : Fragment(R.layout.call_log_fragment), CallLogAdapter.Cal val filteredCount = callLogAdapter.submitCallRows( data, selected, + viewModel.callLogPeekHelper.localDeviceCallRecipientId, scrollToPositionDelegate::notifyListCommitted ) binding.emptyState.visible = filteredCount == 0 diff --git a/app/src/main/java/org/thoughtcrime/securesms/calls/log/CallLogPeekHelper.kt b/app/src/main/java/org/thoughtcrime/securesms/calls/log/CallLogPeekHelper.kt index a132f2164a..957d0b9628 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/calls/log/CallLogPeekHelper.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/calls/log/CallLogPeekHelper.kt @@ -5,12 +5,15 @@ package org.thoughtcrime.securesms.calls.log +import android.os.Bundle +import android.os.ResultReceiver import androidx.lifecycle.DefaultLifecycleObserver import androidx.lifecycle.LifecycleOwner import org.signal.core.util.concurrent.SignalExecutors import org.signal.core.util.logging.Log import org.thoughtcrime.securesms.dependencies.AppDependencies import org.thoughtcrime.securesms.recipients.RecipientId +import org.thoughtcrime.securesms.service.webrtc.ActiveCallData import org.thoughtcrime.securesms.service.webrtc.links.CallLinkRoomId import org.thoughtcrime.securesms.util.ThrottledDebouncer import org.thoughtcrime.securesms.util.concurrent.SerialExecutor @@ -37,6 +40,10 @@ class CallLogPeekHelper : DefaultLifecycleObserver { private var isFirstLoad = true private var isPaused = false + @Volatile + var localDeviceCallRecipientId: RecipientId = RecipientId.UNKNOWN + private set + override fun onResume(owner: LifecycleOwner) { executor.execute { isPaused = false @@ -147,6 +154,19 @@ class CallLogPeekHelper : DefaultLifecycleObserver { return@execute } + Log.d(TAG, "Checking if user is in a call locally.") + + AppDependencies.signalCallManager.isCallActive(object : ResultReceiver(null) { + override fun onReceiveResult(resultCode: Int, resultData: Bundle?) { + if (resultCode == 1 && resultData != null) { + val activeCallData = ActiveCallData.fromBundle(resultData) + localDeviceCallRecipientId = activeCallData.recipientId + } else { + localDeviceCallRecipientId = RecipientId.UNKNOWN + } + } + }) + Log.d(TAG, "Peeks in queue. Taking first $PEEK_SIZE.") val items = peekQueue.take(PEEK_SIZE) diff --git a/app/src/main/java/org/thoughtcrime/securesms/calls/log/CallLogRepository.kt b/app/src/main/java/org/thoughtcrime/securesms/calls/log/CallLogRepository.kt index e0f147e047..5a6003d76b 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/calls/log/CallLogRepository.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/calls/log/CallLogRepository.kt @@ -19,6 +19,7 @@ class CallLogRepository( private val updateCallLinkRepository: UpdateCallLinkRepository = UpdateCallLinkRepository(), private val callLogPeekHelper: CallLogPeekHelper ) : CallLogPagedDataSource.CallRepository { + override fun getCallsCount(query: String?, filter: CallLogFilter): Int { return SignalDatabase.calls.getCallsCount(query, filter) } diff --git a/app/src/main/java/org/thoughtcrime/securesms/calls/log/CallLogRow.kt b/app/src/main/java/org/thoughtcrime/securesms/calls/log/CallLogRow.kt index f97808e49b..e57acbeac4 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/calls/log/CallLogRow.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/calls/log/CallLogRow.kt @@ -48,19 +48,19 @@ sealed class CallLogRow { /** * A row which can be used to clear the current filter. */ - object ClearFilter : CallLogRow() { + data object ClearFilter : CallLogRow() { override val id: Id = Id.ClearFilter } - object CreateCallLink : CallLogRow() { + data object CreateCallLink : CallLogRow() { override val id: Id = Id.CreateCallLink } sealed class Id { data class Call(val children: Set) : Id() data class CallLink(val roomId: CallLinkRoomId) : Id() - object ClearFilter : Id() - object CreateCallLink : Id() + data object ClearFilter : Id() + data object CreateCallLink : Id() } enum class GroupCallState { 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 4f162ed324..1d8f1bc5b5 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/CallTable.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/database/CallTable.kt @@ -1365,7 +1365,12 @@ class CallTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTabl INNER JOIN ${RecipientTable.TABLE_NAME} ON ${RecipientTable.TABLE_NAME}.${RecipientTable.ID} = $PEER LEFT JOIN ${MessageTable.TABLE_NAME} ON ${MessageTable.TABLE_NAME}.${MessageTable.ID} = $MESSAGE_ID LEFT JOIN ${GroupTable.TABLE_NAME} ON ${GroupTable.TABLE_NAME}.${GroupTable.RECIPIENT_ID} = ${RecipientTable.TABLE_NAME}.${RecipientTable.ID} - WHERE true_parent = p.$ID ${if (queryClause.where.isNotEmpty()) "AND ${queryClause.where}" else ""} + WHERE true_parent = p.$ID + AND CASE + WHEN p.$TYPE = ${Type.serialize(Type.AD_HOC_CALL)} THEN EXISTS (SELECT * FROM ${CallLinkTable.TABLE_NAME} WHERE ${CallLinkTable.RECIPIENT_ID} = $PEER AND ${CallLinkTable.ROOT_KEY} NOT NULL) + ELSE 1 + END + ${if (queryClause.where.isNotEmpty()) "AND ${queryClause.where}" else ""} GROUP BY CASE WHEN p.type = 4 THEN p.peer ELSE p._id END ORDER BY p.$TIMESTAMP DESC $offsetLimit