Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(RC): send pings as self deleting and messsage duration clenup #1877

Merged
merged 8 commits into from
Jul 13, 2023
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -77,9 +77,6 @@ import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.firstOrNull
import kotlinx.coroutines.flow.map
import kotlinx.datetime.Instant
import kotlin.time.Duration.Companion.ZERO
import kotlin.time.DurationUnit
import kotlin.time.toDuration

interface ConversationRepository {
@DelicateKaliumApi("This function does not get values from cache")
Expand Down Expand Up @@ -187,7 +184,6 @@ interface ConversationRepository {
): Either<CoreFailure, Unit>

suspend fun getConversationUnreadEventsCount(conversationId: ConversationId): Either<StorageFailure, Long>
suspend fun getUserSelfDeletionTimer(conversationId: ConversationId): Either<StorageFailure, SelfDeletionTimer?>
suspend fun updateUserSelfDeletionTimer(conversationId: ConversationId, selfDeletionTimer: SelfDeletionTimer): Either<CoreFailure, Unit>
}

Expand Down Expand Up @@ -685,22 +681,13 @@ internal class ConversationDataSource internal constructor(
override suspend fun getConversationUnreadEventsCount(conversationId: ConversationId): Either<StorageFailure, Long> =
wrapStorageRequest { messageDAO.getConversationUnreadEventsCount(conversationId.toDao()) }

override suspend fun getUserSelfDeletionTimer(conversationId: ConversationId): Either<StorageFailure, SelfDeletionTimer> =
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this fun is not used anywhere

wrapStorageRequest {
SelfDeletionTimer.Enabled(
conversationDAO.getConversationByQualifiedID(conversationId.toDao())?.messageTimer?.toDuration(
DurationUnit.MILLISECONDS
) ?: ZERO
)
}

override suspend fun updateUserSelfDeletionTimer(
conversationId: ConversationId,
selfDeletionTimer: SelfDeletionTimer
): Either<CoreFailure, Unit> = wrapStorageRequest {
conversationDAO.updateUserMessageTimer(
conversationId = conversationId.toDao(),
messageTimer = selfDeletionTimer.toDuration().inWholeMilliseconds
messageTimer = selfDeletionTimer.duration?.inWholeMilliseconds
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,9 @@ class ProtoContentMapperImpl(

is MessageContent.Knock -> {
val knock = GenericMessage.Content.Knock(Knock(hotKnock = readableContent.hotKnock))
Ephemeral.Content.Knock(knock.value)
Ephemeral.Content.Knock(
knock.value
)
}

is MessageContent.FailedDecryption,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ import com.wire.kalium.logic.feature.CurrentClientIdProvider
import com.wire.kalium.logic.feature.message.MessageSendFailureHandler
import com.wire.kalium.logic.feature.message.MessageSender
import com.wire.kalium.logic.feature.selfDeletingMessages.ObserveSelfDeletionTimerSettingsForConversationUseCase
import com.wire.kalium.logic.feature.selfDeletingMessages.SelfDeletionTimer
import com.wire.kalium.logic.functional.Either
import com.wire.kalium.logic.functional.flatMap
import com.wire.kalium.logic.functional.fold
Expand All @@ -60,7 +59,6 @@ import kotlinx.coroutines.flow.first
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import okio.Path
import kotlin.coroutines.cancellation.CancellationException
import kotlin.time.Duration

interface ScheduleNewAssetMessageUseCase {
Expand Down Expand Up @@ -128,19 +126,9 @@ internal class ScheduleNewAssetMessageUseCaseImpl(
val generatedMessageUuid = uuid4().toString()
val expectsReadConfirmation = userPropertyRepository.getReadReceiptsStatus()

val messageTimer = selfDeleteTimer(conversationId, true).first().let {
val logMap = it.toLogString(eventDescription = "Sending asset message with self-deletion timer")
if (it != SelfDeletionTimer.Disabled) kaliumLogger.d("${SelfDeletionTimer.SELF_DELETION_LOG_TAG}: $logMap")

when (it) {
SelfDeletionTimer.Disabled -> null
is SelfDeletionTimer.Enabled -> it.userDuration
is SelfDeletionTimer.Enforced.ByGroup -> it.duration
is SelfDeletionTimer.Enforced.ByTeam -> it.duration
}
}.let {
if (it == Duration.ZERO) null else it
}
val messageTimer = selfDeleteTimer(conversationId, true)
.first()
.duration

return withContext(dispatcher.io) {
// We persist the asset with temporary id and message right away so that it can be displayed on the conversation screen loading
Expand Down Expand Up @@ -172,25 +160,12 @@ internal class ScheduleNewAssetMessageUseCaseImpl(
)
}
}

launch {
uploadAssetAndUpdateMessage(currentAssetMessageContent, message, conversationId, expectsReadConfirmation)
.onSuccess {
// We delete asset added temporarily that was used to show the loading
assetDataSource.deleteAssetLocally(currentAssetMessageContent.assetId.key)
}
}.invokeOnCompletion { cause ->
if (cause is CancellationException) {
kaliumLogger.d(
"Asset upload was cancelled, " +
"for message with id ${message.id} and conversationId $conversationId"
)
} else {
kaliumLogger.d(
"Asset uploaded successfully, " +
"for message with id ${message.id} and conversationId $conversationId"
)
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,8 @@ class MessageScope internal constructor(
currentClientIdProvider,
slowSyncRepository,
messageSender,
messageSendFailureHandler
messageSendFailureHandler,
observeSelfDeletingMessages
)

val markMessagesAsNotified: MarkMessagesAsNotifiedUseCase
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,13 @@ import com.wire.kalium.logic.data.message.PersistMessageUseCase
import com.wire.kalium.logic.data.sync.SlowSyncRepository
import com.wire.kalium.logic.data.sync.SlowSyncStatus
import com.wire.kalium.logic.feature.CurrentClientIdProvider
import com.wire.kalium.logic.feature.selfDeletingMessages.ObserveSelfDeletionTimerSettingsForConversationUseCase
import com.wire.kalium.logic.functional.Either
import com.wire.kalium.logic.functional.flatMap
import com.wire.kalium.logic.functional.onFailure
import com.wire.kalium.util.DateTimeUtil
import kotlinx.coroutines.flow.first
import kotlin.time.Duration

@Suppress("LongParameterList")
/**
Expand All @@ -44,7 +46,8 @@ class SendKnockUseCase internal constructor(
private val currentClientIdProvider: CurrentClientIdProvider,
private val slowSyncRepository: SlowSyncRepository,
private val messageSender: MessageSender,
private val messageSendFailureHandler: MessageSendFailureHandler
private val messageSendFailureHandler: MessageSendFailureHandler,
private val selfDeleteTimer: ObserveSelfDeletionTimerSettingsForConversationUseCase
) {

/**
Expand All @@ -60,6 +63,9 @@ class SendKnockUseCase internal constructor(
}

val generatedMessageUuid = uuid4().toString()
val messageTimer: Duration? = selfDeleteTimer(conversationId, true)
.first()
.duration

return currentClientIdProvider().flatMap { currentClientId ->
val message = Message.Regular(
Expand All @@ -71,7 +77,8 @@ class SendKnockUseCase internal constructor(
senderClientId = currentClientId,
status = Message.Status.PENDING,
editStatus = Message.EditStatus.NotEdited,
isSelfMessage = true
isSelfMessage = true,
expirationData = messageTimer?.let { Message.ExpirationData(it) }
)
persistMessage(message)
.flatMap { messageSender.sendMessage(message) }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,9 @@ import com.wire.kalium.logic.data.sync.SlowSyncRepository
import com.wire.kalium.logic.data.sync.SlowSyncStatus
import com.wire.kalium.logic.feature.CurrentClientIdProvider
import com.wire.kalium.logic.feature.selfDeletingMessages.ObserveSelfDeletionTimerSettingsForConversationUseCase
import com.wire.kalium.logic.feature.selfDeletingMessages.SelfDeletionTimer
import com.wire.kalium.logic.feature.selfDeletingMessages.SelfDeletionTimer.Companion.SELF_DELETION_LOG_TAG
import com.wire.kalium.logic.functional.Either
import com.wire.kalium.logic.functional.flatMap
import com.wire.kalium.logic.functional.onFailure
import com.wire.kalium.logic.kaliumLogger
import com.wire.kalium.util.DateTimeUtil
import com.wire.kalium.util.KaliumDispatcher
import com.wire.kalium.util.KaliumDispatcherImpl
Expand Down Expand Up @@ -73,18 +70,9 @@ class SendTextMessageUseCase internal constructor(

val generatedMessageUuid = uuid4().toString()
val expectsReadConfirmation = userPropertyRepository.getReadReceiptsStatus()
val messageTimer: Duration? = selfDeleteTimer(conversationId, true).first().let {
val logMap = it.toLogString(eventDescription = "Sending text message with self-deletion timer")
if (it != SelfDeletionTimer.Disabled) kaliumLogger.d("$SELF_DELETION_LOG_TAG: $logMap")
when (it) {
SelfDeletionTimer.Disabled -> null
is SelfDeletionTimer.Enabled -> it.userDuration
is SelfDeletionTimer.Enforced.ByGroup -> it.duration
is SelfDeletionTimer.Enforced.ByTeam -> it.duration
}
}.let {
if (it == Duration.ZERO) null else it
}
val messageTimer: Duration? = selfDeleteTimer(conversationId, true)
.first()
.duration

provideClientId().flatMap { clientId ->
val message = Message.Regular(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ import com.wire.kalium.logic.functional.fold
import com.wire.kalium.logic.util.isPositiveNotNull
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.combine
import kotlin.time.Duration.Companion.ZERO

/**
* When invoked, this use case will start observing on a given conversation, the currently applied [SelfDeletionTimer]
Expand Down Expand Up @@ -66,12 +65,12 @@ class ObserveSelfDeletionTimerSettingsForConversationUseCaseImpl internal constr

private fun onTeamEnabled(conversation: Either<StorageFailure, Conversation>, considerSelfUserSettings: Boolean): SelfDeletionTimer =
conversation.fold({
SelfDeletionTimer.Enabled(ZERO)
SelfDeletionTimer.Enabled(null)
MohamadJaara marked this conversation as resolved.
Show resolved Hide resolved
}, {
when {
it.messageTimer.isPositiveNotNull() -> SelfDeletionTimer.Enforced.ByGroup(it.messageTimer)
considerSelfUserSettings && it.userMessageTimer.isPositiveNotNull() -> SelfDeletionTimer.Enabled(it.userMessageTimer)
else -> SelfDeletionTimer.Enabled(ZERO)
else -> SelfDeletionTimer.Enabled(null)
}
})
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,30 +22,28 @@ import com.wire.kalium.util.serialization.toJsonElement
import kotlin.time.Duration
import kotlin.time.Duration.Companion.ZERO

sealed class SelfDeletionTimer {
sealed interface SelfDeletionTimer {
val duration: Duration?
vitorhugods marked this conversation as resolved.
Show resolved Hide resolved

/**
* Represents a self deletion timer that is currently disabled
*/
object Disabled : SelfDeletionTimer()
object Disabled : SelfDeletionTimer {
override val duration: Duration? = null
}

/**
* Represents a self deletion timer that is enabled and can be changed/updated by the user
*/
data class Enabled(val userDuration: Duration) : SelfDeletionTimer()
data class Enabled(override val duration: Duration?) : SelfDeletionTimer
vitorhugods marked this conversation as resolved.
Show resolved Hide resolved

/**
* Represents a self deletion timer that is imposed by the team or conversation settings that can't be changed by the user
* @param enforcedDuration the team or conversation imposed timer
*/
sealed class Enforced(val enforcedDuration: Duration) : SelfDeletionTimer() {
data class ByTeam(val duration: Duration) : Enforced(duration)
data class ByGroup(val duration: Duration) : Enforced(duration)
}

fun toDuration(): Duration = when (this) {
is Enabled -> userDuration
is Enforced -> enforcedDuration
is Disabled -> ZERO
sealed interface Enforced : SelfDeletionTimer {
data class ByTeam(override val duration: Duration) : Enforced
data class ByGroup(override val duration: Duration) : Enforced
}

fun toLogString(eventDescription: String): String = toLogMap(eventDescription).toJsonElement().toString()
Expand All @@ -65,7 +63,7 @@ sealed class SelfDeletionTimer {
private fun toLogMap(eventDescription: String): Map<String, Any?> = mapOf(
eventKey to eventDescription,
typeKey to this::class.simpleName,
durationKey to toDuration().inWholeSeconds,
durationKey to duration?.inWholeSeconds,
isEnforcedKey to isEnforced,
isDisabledKey to isDisabled
)
Expand Down
Loading
Loading