Add proper call tab return state.

This commit is contained in:
Alex Hart
2024-09-06 13:25:28 -03:00
committed by Cody Henthorne
parent 514f7cc767
commit 1f09f48e6b
13 changed files with 171 additions and 99 deletions

View File

@@ -8,6 +8,7 @@ package org.thoughtcrime.securesms.calls.links
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.layout.Arrangement.spacedBy
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
@@ -33,20 +34,21 @@ import androidx.compose.ui.platform.LocalInspectionMode
import androidx.compose.ui.res.dimensionResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.res.vectorResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import org.signal.core.ui.Buttons
import org.signal.core.ui.theme.SignalTheme
import org.signal.core.ui.Previews
import org.signal.core.ui.SignalPreview
import org.thoughtcrime.securesms.R
import org.thoughtcrime.securesms.conversation.colors.AvatarColorPair
import org.thoughtcrime.securesms.database.CallLinkTable
import org.thoughtcrime.securesms.recipients.RecipientId
import org.thoughtcrime.securesms.service.webrtc.CallLinkPeekInfo
import org.thoughtcrime.securesms.service.webrtc.links.CallLinkCredentials
import org.thoughtcrime.securesms.service.webrtc.links.CallLinkRoomId
import org.thoughtcrime.securesms.service.webrtc.links.SignalCallLinkState
import java.time.Instant
@Preview
@SignalPreview
@Composable
private fun SignalCallRowPreview() {
val callLink = remember {
@@ -63,17 +65,29 @@ private fun SignalCallRowPreview() {
)
)
}
SignalTheme(false) {
SignalCallRow(
callLink = callLink,
onJoinClicked = {}
)
Previews.Preview {
Column(
verticalArrangement = spacedBy(8.dp)
) {
SignalCallRow(
callLink = callLink,
callLinkPeekInfo = null,
onJoinClicked = {}
)
SignalCallRow(
callLink = callLink,
callLinkPeekInfo = CallLinkPeekInfo(null, true, true),
onJoinClicked = {}
)
}
}
}
@Composable
fun SignalCallRow(
callLink: CallLinkTable.CallLink,
callLinkPeekInfo: CallLinkPeekInfo?,
onJoinClicked: (() -> Unit)?,
modifier: Modifier = Modifier
) {
@@ -140,7 +154,13 @@ fun SignalCallRow(
),
modifier = Modifier.align(CenterVertically)
) {
Text(text = stringResource(id = R.string.CreateCallLinkBottomSheetDialogFragment__join))
val textId = if (callLinkPeekInfo?.isJoined == true) {
R.string.CallLogAdapter__return
} else {
R.string.CreateCallLinkBottomSheetDialogFragment__join
}
Text(text = stringResource(id = textId))
}
}
}

View File

@@ -100,6 +100,7 @@ class CreateCallLinkBottomSheetDialogFragment : ComposeBottomSheetDialogFragment
SignalCallRow(
callLink = callLink,
callLinkPeekInfo = null,
onJoinClicked = this@CreateCallLinkBottomSheetDialogFragment::onJoinClicked
)

View File

@@ -41,7 +41,6 @@ import org.thoughtcrime.securesms.calls.links.CallLinks
import org.thoughtcrime.securesms.calls.links.EditCallLinkNameDialogFragment
import org.thoughtcrime.securesms.calls.links.SignalCallRow
import org.thoughtcrime.securesms.compose.ComposeFragment
import org.thoughtcrime.securesms.conversation.colors.AvatarColor
import org.thoughtcrime.securesms.database.CallLinkTable
import org.thoughtcrime.securesms.recipients.RecipientId
import org.thoughtcrime.securesms.service.webrtc.links.CallLinkCredentials
@@ -200,12 +199,11 @@ private interface CallLinkDetailsCallback {
@Preview
@Composable
private fun CallLinkDetailsPreview() {
val avatarColor = remember {
AvatarColor.random()
}
val callLink = remember {
val credentials = CallLinkCredentials.generate()
val credentials = CallLinkCredentials(
byteArrayOf(1, 2, 3, 4),
byteArrayOf(3, 4, 5, 6)
)
CallLinkTable.CallLink(
recipientId = RecipientId.UNKNOWN,
roomId = credentials.roomId,
@@ -258,6 +256,7 @@ private fun CallLinkDetails(
Column(modifier = Modifier.padding(paddingValues)) {
SignalCallRow(
callLink = state.callLink,
callLinkPeekInfo = state.peekInfo,
onJoinClicked = callback::onJoinClicked,
modifier = Modifier.padding(top = 16.dp, bottom = 12.dp)
)

View File

@@ -7,9 +7,11 @@ package org.thoughtcrime.securesms.calls.links.details
import androidx.compose.runtime.Immutable
import org.thoughtcrime.securesms.database.CallLinkTable
import org.thoughtcrime.securesms.service.webrtc.CallLinkPeekInfo
@Immutable
data class CallLinkDetailsState(
val displayRevocationDialog: Boolean = false,
val callLink: CallLinkTable.CallLink? = null
val callLink: CallLinkTable.CallLink? = null,
val peekInfo: CallLinkPeekInfo? = null
)

View File

@@ -10,14 +10,17 @@ import androidx.compose.runtime.State
import androidx.compose.runtime.mutableStateOf
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
import io.reactivex.rxjava3.core.Single
import io.reactivex.rxjava3.disposables.CompositeDisposable
import io.reactivex.rxjava3.kotlin.plusAssign
import io.reactivex.rxjava3.kotlin.subscribeBy
import io.reactivex.rxjava3.schedulers.Schedulers
import io.reactivex.rxjava3.subjects.BehaviorSubject
import org.signal.ringrtc.CallLinkState
import org.thoughtcrime.securesms.calls.links.CallLinks
import org.thoughtcrime.securesms.calls.links.UpdateCallLinkRepository
import org.thoughtcrime.securesms.dependencies.AppDependencies
import org.thoughtcrime.securesms.recipients.Recipient
import org.thoughtcrime.securesms.service.webrtc.links.CallLinkRoomId
import org.thoughtcrime.securesms.service.webrtc.links.UpdateCallLinkResult
@@ -43,13 +46,33 @@ class CallLinkDetailsViewModel(
init {
disposables += repository.refreshCallLinkState(callLinkRoomId)
disposables += CallLinks.watchCallLink(callLinkRoomId).subscribeBy {
_state.value = _state.value.copy(callLink = it)
}
disposables += CallLinks.watchCallLink(callLinkRoomId)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribeBy {
_state.value = _state.value.copy(callLink = it)
}
disposables += repository
.watchCallLinkRecipient(callLinkRoomId)
.subscribeBy(onNext = recipientSubject::onNext)
disposables += recipientSubject
.map { it.id }
.distinctUntilChanged()
.flatMap { recipientId ->
AppDependencies.signalCallManager.peekInfoCache
.distinctUntilChanged()
.filter { it.containsKey(recipientId) }
.map { it[recipientId]!! }
.distinctUntilChanged()
.toObservable()
}
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribeBy { callLinkPeekInfo ->
_state.value = _state.value.copy(peekInfo = callLinkPeekInfo)
}
}
override fun onCleared() {

View File

@@ -228,13 +228,28 @@ class CallLogAdapter(
)
)
binding.callType.setImageResource(R.drawable.symbol_video_24)
binding.callType.contentDescription = context.getString(R.string.CallLogAdapter__start_a_video_call)
binding.callType.setOnClickListener {
onStartVideoCallClicked(model.callLink.recipient, true)
if (model.callLink.callLinkPeekInfo?.isActive == true) {
binding.groupCallButton.setText(
if (model.callLink.callLinkPeekInfo.isJoined) {
R.string.CallLogAdapter__return
} else {
R.string.CallLogAdapter__join
}
)
binding.groupCallButton.setOnClickListener {
onStartVideoCallClicked(model.callLink.recipient, true)
}
binding.callType.visible = false
binding.groupCallButton.visible = true
} else {
binding.callType.setImageResource(R.drawable.symbol_video_24)
binding.callType.contentDescription = context.getString(R.string.CallLogAdapter__start_a_video_call)
binding.callType.setOnClickListener {
onStartVideoCallClicked(model.callLink.recipient, true)
}
binding.callType.visible = true
binding.groupCallButton.visible = false
}
binding.callType.visible = true
binding.groupCallButton.visible = false
}
}
@@ -338,7 +353,30 @@ class CallLogAdapter(
binding.groupCallButton.visible = false
}
CallTable.Type.GROUP_CALL, CallTable.Type.AD_HOC_CALL -> {
CallTable.Type.AD_HOC_CALL -> {
binding.callType.setImageResource(R.drawable.symbol_video_24)
binding.callType.contentDescription = context.getString(R.string.CallLogAdapter__start_a_video_call)
binding.callType.setOnClickListener { onStartVideoCallClicked(model.call.peer, model.call.canUserBeginCall) }
binding.groupCallButton.setOnClickListener { onStartVideoCallClicked(model.call.peer, model.call.canUserBeginCall) }
if (model.call.callLinkPeekInfo?.isActive == true) {
binding.callType.visible = false
binding.groupCallButton.visible = true
binding.groupCallButton.setText(
if (model.call.callLinkPeekInfo.isJoined) {
R.string.CallLogAdapter__return
} else {
R.string.CallLogAdapter__join
}
)
} else {
binding.callType.visible = true
binding.groupCallButton.visible = false
}
}
CallTable.Type.GROUP_CALL -> {
binding.callType.setImageResource(R.drawable.symbol_video_24)
binding.callType.contentDescription = context.getString(R.string.CallLogAdapter__start_a_video_call)
binding.callType.setOnClickListener { onStartVideoCallClicked(model.call.peer, model.call.canUserBeginCall) }
@@ -401,6 +439,7 @@ class CallLogAdapter(
call.direction == CallTable.Direction.OUTGOING -> R.string.CallLogAdapter__outgoing
else -> throw AssertionError()
}
else -> if (call.isDisplayedAsMissedCallInUi) R.string.CallLogAdapter__missed else R.string.CallLogAdapter__incoming
}
}

View File

@@ -11,7 +11,6 @@ import org.thoughtcrime.securesms.database.CallLinkTable
import org.thoughtcrime.securesms.database.DatabaseObserver
import org.thoughtcrime.securesms.database.SignalDatabase
import org.thoughtcrime.securesms.dependencies.AppDependencies
import org.thoughtcrime.securesms.jobs.CallLinkPeekJob
import org.thoughtcrime.securesms.jobs.CallLogEventSendJob
import org.thoughtcrime.securesms.service.webrtc.links.CallLinkRoomId
import org.thoughtcrime.securesms.service.webrtc.links.UpdateCallLinkResult
@@ -158,29 +157,4 @@ class CallLogRepository(
SignalDatabase.calls.updateAdHocCallEventDeletionTimestamps()
}
}
fun peekCallLinks(): Completable {
return Completable.fromAction {
val callLinks: List<CallLogRow.CallLink> = SignalDatabase.callLinks.getCallLinks(
query = null,
offset = 0,
limit = 10
)
val callEvents: List<CallLogRow.Call> = SignalDatabase.calls.getCalls(
offset = 0,
limit = 10,
searchTerm = null,
filter = CallLogFilter.AD_HOC
)
val recipients = (callLinks.map { it.recipient } + callEvents.map { it.peer }).toSet()
val jobs = recipients.take(10).map {
CallLinkPeekJob(it.id)
}
AppDependencies.jobManager.addAll(jobs)
}.subscribeOn(Schedulers.io())
}
}

View File

@@ -6,7 +6,6 @@ import androidx.lifecycle.ViewModel
import io.reactivex.rxjava3.core.BackpressureStrategy
import io.reactivex.rxjava3.core.Flowable
import io.reactivex.rxjava3.core.Maybe
import io.reactivex.rxjava3.core.Observable
import io.reactivex.rxjava3.disposables.CompositeDisposable
import io.reactivex.rxjava3.kotlin.plusAssign
import io.reactivex.rxjava3.processors.BehaviorProcessor
@@ -16,9 +15,7 @@ import org.signal.paging.PagedData
import org.signal.paging.PagingConfig
import org.signal.paging.ProxyPagingController
import org.thoughtcrime.securesms.dependencies.AppDependencies
import org.thoughtcrime.securesms.util.RemoteConfig
import org.thoughtcrime.securesms.util.rx.RxStore
import java.util.concurrent.TimeUnit
/**
* ViewModel for call log management.
@@ -82,22 +79,15 @@ class CallLogViewModel(
controller.onDataInvalidated()
}
if (RemoteConfig.adHocCalling) {
disposables += Observable
.interval(30, TimeUnit.SECONDS, Schedulers.computation())
.flatMapCompletable { callLogRepository.peekCallLinks() }
.subscribe()
disposables += AppDependencies
.signalCallManager
.peekInfoCache
.observeOn(Schedulers.computation())
.distinctUntilChanged()
.subscribe {
callLogPeekHelper.onDataSetInvalidated()
controller.onDataInvalidated()
}
}
disposables += AppDependencies
.signalCallManager
.peekInfoCache
.observeOn(Schedulers.computation())
.distinctUntilChanged()
.subscribe {
callLogPeekHelper.onDataSetInvalidated()
controller.onDataInvalidated()
}
}
override fun onCleared() {