Add the join / return button to call log items.
This commit is contained in:
parent
9d575650d1
commit
c254b08e33
7 changed files with 138 additions and 18 deletions
|
@ -153,13 +153,12 @@ class CallLogAdapter(
|
|||
|
||||
val event = model.call.call.event
|
||||
val direction = model.call.call.direction
|
||||
val type = model.call.call.type
|
||||
|
||||
binding.callRecipientAvatar.setAvatar(GlideApp.with(binding.callRecipientAvatar), model.call.peer, true)
|
||||
binding.callRecipientBadge.setBadgeFromRecipient(model.call.peer)
|
||||
binding.callRecipientName.text = model.call.peer.getDisplayName(context)
|
||||
presentCallInfo(event, direction, model.call.date)
|
||||
presentCallType(type, model.call.peer)
|
||||
presentCallType(model)
|
||||
}
|
||||
|
||||
private fun presentCallInfo(event: CallTable.Event, direction: CallTable.Direction, date: Long) {
|
||||
|
@ -190,24 +189,47 @@ class CallLogAdapter(
|
|||
binding.callInfo.setTextColor(color)
|
||||
}
|
||||
|
||||
private fun presentCallType(callType: CallTable.Type, peer: Recipient) {
|
||||
when (callType) {
|
||||
private fun presentCallType(model: CallModel) {
|
||||
when (model.call.call.type) {
|
||||
CallTable.Type.AUDIO_CALL -> {
|
||||
binding.callType.setImageResource(R.drawable.symbol_phone_24)
|
||||
binding.callType.setOnClickListener { onStartAudioCallClicked(peer) }
|
||||
binding.callType.setOnClickListener { onStartAudioCallClicked(model.call.peer) }
|
||||
binding.callType.visible = true
|
||||
binding.groupCallButton.visible = false
|
||||
}
|
||||
|
||||
CallTable.Type.VIDEO_CALL -> {
|
||||
binding.callType.setImageResource(R.drawable.symbol_video_24)
|
||||
binding.callType.setOnClickListener { onStartVideoCallClicked(peer) }
|
||||
binding.callType.setOnClickListener { onStartVideoCallClicked(model.call.peer) }
|
||||
binding.callType.visible = true
|
||||
binding.groupCallButton.visible = false
|
||||
}
|
||||
|
||||
CallTable.Type.GROUP_CALL, CallTable.Type.AD_HOC_CALL -> {
|
||||
// TODO [alex] -- Group call button
|
||||
binding.callType.setImageResource(R.drawable.symbol_video_24)
|
||||
binding.callType.setOnClickListener { onStartVideoCallClicked(model.call.peer) }
|
||||
binding.groupCallButton.setOnClickListener { onStartVideoCallClicked(model.call.peer) }
|
||||
|
||||
when (model.call.groupCallState) {
|
||||
CallLogRow.GroupCallState.NONE, CallLogRow.GroupCallState.FULL -> {
|
||||
binding.callType.visible = true
|
||||
binding.groupCallButton.visible = false
|
||||
}
|
||||
CallLogRow.GroupCallState.ACTIVE, CallLogRow.GroupCallState.LOCAL_USER_JOINED -> {
|
||||
binding.callType.visible = false
|
||||
binding.groupCallButton.visible = true
|
||||
|
||||
binding.groupCallButton.setText(
|
||||
if (model.call.groupCallState == CallLogRow.GroupCallState.LOCAL_USER_JOINED) {
|
||||
R.string.CallLogAdapter__return
|
||||
} else {
|
||||
R.string.CallLogAdapter__join
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
binding.callType.visible = true
|
||||
}
|
||||
|
||||
@DrawableRes
|
||||
|
|
|
@ -26,16 +26,11 @@ class CallLogRepository : CallLogPagedDataSource.CallRepository {
|
|||
refresh()
|
||||
}
|
||||
|
||||
val messageObserver = DatabaseObserver.MessageObserver {
|
||||
refresh()
|
||||
}
|
||||
|
||||
ApplicationDependencies.getDatabaseObserver().registerConversationListObserver(databaseObserver)
|
||||
ApplicationDependencies.getDatabaseObserver().registerMessageUpdateObserver(messageObserver)
|
||||
ApplicationDependencies.getDatabaseObserver().registerCallUpdateObserver(databaseObserver)
|
||||
|
||||
emitter.setCancellable {
|
||||
ApplicationDependencies.getDatabaseObserver().unregisterObserver(databaseObserver)
|
||||
ApplicationDependencies.getDatabaseObserver().unregisterObserver(messageObserver)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package org.thoughtcrime.securesms.calls.log
|
||||
|
||||
import org.thoughtcrime.securesms.database.CallTable
|
||||
import org.thoughtcrime.securesms.database.model.databaseprotos.GroupCallUpdateDetails
|
||||
import org.thoughtcrime.securesms.recipients.Recipient
|
||||
|
||||
/**
|
||||
|
@ -17,6 +18,7 @@ sealed class CallLogRow {
|
|||
val call: CallTable.Call,
|
||||
val peer: Recipient,
|
||||
val date: Long,
|
||||
val groupCallState: GroupCallState,
|
||||
override val id: Id = Id.Call(call.callId)
|
||||
) : CallLogRow()
|
||||
|
||||
|
@ -36,4 +38,48 @@ sealed class CallLogRow {
|
|||
object ClearFilter : Id()
|
||||
object CreateCallLink : Id()
|
||||
}
|
||||
|
||||
enum class GroupCallState {
|
||||
/**
|
||||
* No group call available.
|
||||
*/
|
||||
NONE,
|
||||
|
||||
/**
|
||||
* Active, but the local user is not in the call.
|
||||
*/
|
||||
ACTIVE,
|
||||
|
||||
/**
|
||||
* Active and the local user is in the call
|
||||
*/
|
||||
LOCAL_USER_JOINED,
|
||||
|
||||
/**
|
||||
* Active but the call is full.
|
||||
*/
|
||||
FULL;
|
||||
|
||||
companion object {
|
||||
fun fromDetails(groupCallUpdateDetails: GroupCallUpdateDetails?): GroupCallState {
|
||||
if (groupCallUpdateDetails == null) {
|
||||
return NONE
|
||||
}
|
||||
|
||||
if (groupCallUpdateDetails.isCallFull) {
|
||||
return FULL
|
||||
}
|
||||
|
||||
if (groupCallUpdateDetails.inCallUuidsList.contains(Recipient.self().requireServiceId().uuid().toString())) {
|
||||
return LOCAL_USER_JOINED
|
||||
}
|
||||
|
||||
return if (groupCallUpdateDetails.inCallUuidsCount > 0) {
|
||||
ACTIVE
|
||||
} else {
|
||||
NONE
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@ import org.signal.core.util.readToSingleLong
|
|||
import org.signal.core.util.readToSingleObject
|
||||
import org.signal.core.util.requireLong
|
||||
import org.signal.core.util.requireObject
|
||||
import org.signal.core.util.requireString
|
||||
import org.signal.core.util.select
|
||||
import org.signal.core.util.update
|
||||
import org.signal.core.util.withinTransaction
|
||||
|
@ -22,6 +23,7 @@ import org.signal.ringrtc.CallId
|
|||
import org.signal.ringrtc.CallManager.RingUpdate
|
||||
import org.thoughtcrime.securesms.calls.log.CallLogFilter
|
||||
import org.thoughtcrime.securesms.calls.log.CallLogRow
|
||||
import org.thoughtcrime.securesms.database.model.GroupCallUpdateDetailsUtil
|
||||
import org.thoughtcrime.securesms.database.model.MessageId
|
||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies
|
||||
import org.thoughtcrime.securesms.jobs.CallSyncEventJob
|
||||
|
@ -93,6 +95,7 @@ class CallTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTabl
|
|||
}
|
||||
|
||||
ApplicationDependencies.getMessageNotifier().updateNotification(context)
|
||||
ApplicationDependencies.getDatabaseObserver().notifyCallUpdateObservers()
|
||||
|
||||
Log.i(TAG, "Inserted call: $callId type: $type direction: $direction event:$event")
|
||||
}
|
||||
|
@ -117,6 +120,7 @@ class CallTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTabl
|
|||
|
||||
SignalDatabase.messages.updateCallLog(call.messageId!!, call.messageType)
|
||||
ApplicationDependencies.getMessageNotifier().updateNotification(context)
|
||||
ApplicationDependencies.getDatabaseObserver().notifyCallUpdateObservers()
|
||||
}
|
||||
|
||||
call
|
||||
|
@ -205,6 +209,7 @@ class CallTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTabl
|
|||
|
||||
CallSyncEventJob.enqueueDeleteSyncEvents(toSync)
|
||||
ApplicationDependencies.getDeletedCallEventManager().scheduleIfNecessary()
|
||||
ApplicationDependencies.getDatabaseObserver().notifyCallUpdateObservers()
|
||||
}
|
||||
|
||||
// region Group / Ad-Hoc Calling
|
||||
|
@ -228,6 +233,7 @@ class CallTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTabl
|
|||
}
|
||||
|
||||
ApplicationDependencies.getMessageNotifier().updateNotification(context)
|
||||
ApplicationDependencies.getDatabaseObserver().notifyCallUpdateObservers()
|
||||
Log.d(TAG, "Marked group call event for deletion: ${call.callId}")
|
||||
}
|
||||
|
||||
|
@ -275,6 +281,7 @@ class CallTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTabl
|
|||
.run()
|
||||
|
||||
ApplicationDependencies.getMessageNotifier().updateNotification(context)
|
||||
ApplicationDependencies.getDatabaseObserver().notifyCallUpdateObservers()
|
||||
Log.d(TAG, "Transitioned group call ${call.callId} from ${call.event} to $newEvent")
|
||||
}
|
||||
|
||||
|
@ -316,6 +323,8 @@ class CallTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTabl
|
|||
)
|
||||
.run()
|
||||
}
|
||||
|
||||
ApplicationDependencies.getDatabaseObserver().notifyCallUpdateObservers()
|
||||
}
|
||||
|
||||
fun insertOrUpdateGroupCallFromExternalEvent(
|
||||
|
@ -434,6 +443,8 @@ class CallTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTabl
|
|||
} else {
|
||||
Log.d(TAG, "Skipping call event processing for null era id.")
|
||||
}
|
||||
|
||||
ApplicationDependencies.getDatabaseObserver().notifyCallUpdateObservers()
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -445,7 +456,9 @@ class CallTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTabl
|
|||
peekJoinedUuids: Collection<UUID>,
|
||||
isCallFull: Boolean
|
||||
): Boolean {
|
||||
return SignalDatabase.messages.updatePreviousGroupCall(threadId, peekGroupCallEraId, peekJoinedUuids, isCallFull)
|
||||
val sameEraId = SignalDatabase.messages.updatePreviousGroupCall(threadId, peekGroupCallEraId, peekJoinedUuids, isCallFull)
|
||||
ApplicationDependencies.getDatabaseObserver().notifyCallUpdateObservers()
|
||||
return sameEraId
|
||||
}
|
||||
|
||||
fun insertOrUpdateGroupCallFromRingState(
|
||||
|
@ -545,6 +558,8 @@ class CallTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTabl
|
|||
|
||||
createEventFromRingState(ringId, groupRecipientId, ringerRecipient, event, dateReceived)
|
||||
}
|
||||
|
||||
ApplicationDependencies.getDatabaseObserver().notifyCallUpdateObservers()
|
||||
}
|
||||
|
||||
private fun updateEventFromRingState(
|
||||
|
@ -634,6 +649,8 @@ class CallTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTabl
|
|||
SignalDatabase.messages.updateCallTimestamps(call.messageId, timestamp)
|
||||
}
|
||||
}
|
||||
|
||||
ApplicationDependencies.getDatabaseObserver().notifyCallUpdateObservers()
|
||||
}
|
||||
|
||||
private fun setMessageId(callId: Long, messageId: MessageId) {
|
||||
|
@ -723,7 +740,7 @@ class CallTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTabl
|
|||
//language=sql
|
||||
val statement = """
|
||||
SELECT
|
||||
${if (isCount) "COUNT(*)," else "$TABLE_NAME.*, ${MessageTable.DATE_RECEIVED},"}
|
||||
${if (isCount) "COUNT(*)," else "$TABLE_NAME.*, ${MessageTable.DATE_RECEIVED}, ${MessageTable.BODY},"}
|
||||
LOWER(
|
||||
COALESCE(
|
||||
NULLIF(${RecipientTable.TABLE_NAME}.${RecipientTable.SYSTEM_JOINED_NAME}, ''),
|
||||
|
@ -756,10 +773,13 @@ class CallTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTabl
|
|||
val call = Call.deserialize(it)
|
||||
val recipient = Recipient.resolved(call.peer)
|
||||
val date = it.requireLong(MessageTable.DATE_RECEIVED)
|
||||
val groupCallDetails = GroupCallUpdateDetailsUtil.parse(it.requireString(MessageTable.BODY))
|
||||
|
||||
CallLogRow.Call(
|
||||
call = call,
|
||||
peer = recipient,
|
||||
date = date
|
||||
date = date,
|
||||
groupCallState = CallLogRow.GroupCallState.fromDetails(groupCallDetails)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -45,6 +45,8 @@ public class DatabaseObserver {
|
|||
private static final String KEY_SCHEDULED_MESSAGES = "ScheduledMessages";
|
||||
private static final String KEY_CONVERSATION_DELETES = "ConversationDeletes";
|
||||
|
||||
private static final String KEY_CALL_UPDATES = "CallUpdates";
|
||||
|
||||
private final Application application;
|
||||
private final Executor executor;
|
||||
|
||||
|
@ -64,6 +66,8 @@ public class DatabaseObserver {
|
|||
private final Set<Observer> notificationProfileObservers;
|
||||
private final Map<RecipientId, Set<Observer>> storyObservers;
|
||||
|
||||
private final Set<Observer> callUpdateObservers;
|
||||
|
||||
public DatabaseObserver(Application application) {
|
||||
this.application = application;
|
||||
this.executor = new SerialExecutor(SignalExecutors.BOUNDED);
|
||||
|
@ -82,6 +86,7 @@ public class DatabaseObserver {
|
|||
this.notificationProfileObservers = new HashSet<>();
|
||||
this.storyObservers = new HashMap<>();
|
||||
this.scheduledMessageObservers = new HashMap<>();
|
||||
this.callUpdateObservers = new HashSet<>();
|
||||
}
|
||||
|
||||
public void registerConversationListObserver(@NonNull Observer listener) {
|
||||
|
@ -177,6 +182,10 @@ public class DatabaseObserver {
|
|||
});
|
||||
}
|
||||
|
||||
public void registerCallUpdateObserver(@NonNull Observer observer) {
|
||||
executor.execute(() -> callUpdateObservers.add(observer));
|
||||
}
|
||||
|
||||
public void unregisterObserver(@NonNull Observer listener) {
|
||||
executor.execute(() -> {
|
||||
conversationListObservers.remove(listener);
|
||||
|
@ -191,6 +200,7 @@ public class DatabaseObserver {
|
|||
unregisterMapped(storyObservers, listener);
|
||||
unregisterMapped(scheduledMessageObservers, listener);
|
||||
unregisterMapped(conversationDeleteObservers, listener);
|
||||
callUpdateObservers.remove(listener);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -328,6 +338,10 @@ public class DatabaseObserver {
|
|||
});
|
||||
}
|
||||
|
||||
public void notifyCallUpdateObservers() {
|
||||
runPostSuccessfulTransaction(KEY_CALL_UPDATES, () -> notifySet(callUpdateObservers));
|
||||
}
|
||||
|
||||
private void runPostSuccessfulTransaction(@NonNull String dedupeKey, @NonNull Runnable runnable) {
|
||||
SignalDatabase.runPostSuccessfulTransaction(dedupeKey, () -> {
|
||||
executor.execute(runnable);
|
||||
|
|
|
@ -126,4 +126,23 @@
|
|||
app:tint="@color/signal_colorOnSurface"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/group_call_button"
|
||||
style="@style/Signal.Widget.Button.Small.Primary"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:backgroundTint="@color/signal_colorPrimary"
|
||||
android:textColor="@color/signal_colorOnPrimary"
|
||||
android:visibility="gone"
|
||||
app:icon="@drawable/symbol_video_fill_24"
|
||||
app:iconPadding="4dp"
|
||||
app:iconSize="20dp"
|
||||
app:iconTint="@color/signal_colorOnPrimary"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:strokeWidth="0dp"
|
||||
tools:text="Return"
|
||||
tools:visibility="visible" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -5775,6 +5775,10 @@
|
|||
<string name="CallLogAdapter__outgoing">Outgoing</string>
|
||||
<!-- Displayed for missed calls -->
|
||||
<string name="CallLogAdapter__missed">Missed</string>
|
||||
<!-- Displayed on Group Call button if user is not in the call -->
|
||||
<string name="CallLogAdapter__join">Join</string>
|
||||
<!-- Displayed on Group Call button if user is in the call -->
|
||||
<string name="CallLogAdapter__return">Return</string>
|
||||
|
||||
<!-- Call Log context menu -->
|
||||
<!-- Displayed as a context menu item to start a video call -->
|
||||
|
|
Loading…
Add table
Reference in a new issue