lifting directory local echo merging to its own class
This commit is contained in:
parent
9048f9fb0c
commit
a21f3a1663
|
@ -0,0 +1,53 @@
|
||||||
|
package app.dapk.st.engine
|
||||||
|
|
||||||
|
import app.dapk.st.matrix.common.RoomId
|
||||||
|
import app.dapk.st.matrix.common.RoomMember
|
||||||
|
import app.dapk.st.matrix.common.UserId
|
||||||
|
import app.dapk.st.matrix.common.asString
|
||||||
|
import app.dapk.st.matrix.message.MessageService
|
||||||
|
import app.dapk.st.matrix.room.RoomService
|
||||||
|
|
||||||
|
internal typealias DirectoryMergeWithLocalEchosUseCase = suspend (OverviewState, UserId, Map<RoomId, List<MessageService.LocalEcho>>) -> OverviewState
|
||||||
|
|
||||||
|
internal class DirectoryMergeWithLocalEchosUseCaseImpl(
|
||||||
|
private val roomService: RoomService,
|
||||||
|
) : DirectoryMergeWithLocalEchosUseCase {
|
||||||
|
|
||||||
|
override suspend fun invoke(overview: OverviewState, selfId: UserId, echos: Map<RoomId, List<MessageService.LocalEcho>>): OverviewState {
|
||||||
|
return when {
|
||||||
|
echos.isEmpty() -> overview
|
||||||
|
else -> overview.map {
|
||||||
|
when (val roomEchos = echos[it.roomId]) {
|
||||||
|
null -> it
|
||||||
|
else -> it.mergeWithLocalEchos(
|
||||||
|
member = roomService.findMember(it.roomId, selfId) ?: RoomMember(
|
||||||
|
selfId,
|
||||||
|
null,
|
||||||
|
avatarUrl = null,
|
||||||
|
),
|
||||||
|
echos = roomEchos,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun RoomOverview.mergeWithLocalEchos(member: RoomMember, echos: List<MessageService.LocalEcho>): RoomOverview {
|
||||||
|
val latestEcho = echos.maxByOrNull { it.timestampUtc }
|
||||||
|
return if (latestEcho != null && latestEcho.timestampUtc > (this.lastMessage?.utcTimestamp ?: 0)) {
|
||||||
|
this.copy(
|
||||||
|
lastMessage = RoomOverview.LastMessage(
|
||||||
|
content = when (val message = latestEcho.message) {
|
||||||
|
is MessageService.Message.TextMessage -> message.content.body.asString()
|
||||||
|
is MessageService.Message.ImageMessage -> "\uD83D\uDCF7"
|
||||||
|
},
|
||||||
|
utcTimestamp = latestEcho.timestampUtc,
|
||||||
|
author = member,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
this
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,7 +1,7 @@
|
||||||
package app.dapk.st.engine
|
package app.dapk.st.engine
|
||||||
|
|
||||||
import app.dapk.st.core.extensions.combine
|
import app.dapk.st.core.extensions.combine
|
||||||
import app.dapk.st.matrix.common.*
|
import app.dapk.st.matrix.common.CredentialsStore
|
||||||
import app.dapk.st.matrix.message.MessageService
|
import app.dapk.st.matrix.message.MessageService
|
||||||
import app.dapk.st.matrix.room.RoomService
|
import app.dapk.st.matrix.room.RoomService
|
||||||
import app.dapk.st.matrix.sync.RoomStore
|
import app.dapk.st.matrix.sync.RoomStore
|
||||||
|
@ -15,9 +15,9 @@ import kotlinx.coroutines.flow.map
|
||||||
internal class DirectoryUseCase(
|
internal class DirectoryUseCase(
|
||||||
private val syncService: SyncService,
|
private val syncService: SyncService,
|
||||||
private val messageService: MessageService,
|
private val messageService: MessageService,
|
||||||
private val roomService: RoomService,
|
|
||||||
private val credentialsStore: CredentialsStore,
|
private val credentialsStore: CredentialsStore,
|
||||||
private val roomStore: RoomStore,
|
private val roomStore: RoomStore,
|
||||||
|
private val mergeLocalEchosUseCase: DirectoryMergeWithLocalEchosUseCaseImpl
|
||||||
) {
|
) {
|
||||||
|
|
||||||
fun state(): Flow<DirectoryState> {
|
fun state(): Flow<DirectoryState> {
|
||||||
|
@ -30,7 +30,7 @@ internal class DirectoryUseCase(
|
||||||
syncService.events(),
|
syncService.events(),
|
||||||
roomStore.observeMuted(),
|
roomStore.observeMuted(),
|
||||||
) { _, overviewState, localEchos, unread, events, muted ->
|
) { _, overviewState, localEchos, unread, events, muted ->
|
||||||
overviewState.mergeWithLocalEchos(localEchos, userId).map { roomOverview ->
|
mergeLocalEchosUseCase.invoke(overviewState, userId, localEchos).map { roomOverview ->
|
||||||
DirectoryItem(
|
DirectoryItem(
|
||||||
overview = roomOverview,
|
overview = roomOverview,
|
||||||
unreadCount = UnreadCount(unread[roomOverview.roomId] ?: 0),
|
unreadCount = UnreadCount(unread[roomOverview.roomId] ?: 0),
|
||||||
|
@ -41,42 +41,4 @@ internal class DirectoryUseCase(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun OverviewState.mergeWithLocalEchos(localEchos: Map<RoomId, List<MessageService.LocalEcho>>, userId: UserId): OverviewState {
|
|
||||||
return when {
|
|
||||||
localEchos.isEmpty() -> this
|
|
||||||
else -> this.map {
|
|
||||||
when (val roomEchos = localEchos[it.roomId]) {
|
|
||||||
null -> it
|
|
||||||
else -> it.mergeWithLocalEchos(
|
|
||||||
member = roomService.findMember(it.roomId, userId) ?: RoomMember(
|
|
||||||
userId,
|
|
||||||
null,
|
|
||||||
avatarUrl = null,
|
|
||||||
),
|
|
||||||
echos = roomEchos,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun RoomOverview.mergeWithLocalEchos(member: RoomMember, echos: List<MessageService.LocalEcho>): RoomOverview {
|
|
||||||
val latestEcho = echos.maxByOrNull { it.timestampUtc }
|
|
||||||
return if (latestEcho != null && latestEcho.timestampUtc > (this.lastMessage?.utcTimestamp ?: 0)) {
|
|
||||||
this.copy(
|
|
||||||
lastMessage = RoomOverview.LastMessage(
|
|
||||||
content = when (val message = latestEcho.message) {
|
|
||||||
is MessageService.Message.TextMessage -> message.content.body.asString()
|
|
||||||
is MessageService.Message.ImageMessage -> "\uD83D\uDCF7"
|
|
||||||
},
|
|
||||||
utcTimestamp = latestEcho.timestampUtc,
|
|
||||||
author = member,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
this
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -173,14 +173,14 @@ class MatrixEngine internal constructor(
|
||||||
DirectoryUseCase(
|
DirectoryUseCase(
|
||||||
matrix.syncService(),
|
matrix.syncService(),
|
||||||
matrix.messageService(),
|
matrix.messageService(),
|
||||||
matrix.roomService(),
|
|
||||||
credentialsStore,
|
credentialsStore,
|
||||||
roomStore
|
roomStore,
|
||||||
|
DirectoryMergeWithLocalEchosUseCaseImpl(matrix.roomService()),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
val timelineUseCase = unsafeLazy {
|
val timelineUseCase = unsafeLazy {
|
||||||
val matrix = lazyMatrix.value
|
val matrix = lazyMatrix.value
|
||||||
val mergeWithLocalEchosUseCase = MergeWithLocalEchosUseCaseImpl(LocalEchoMapper(MetaMapper()))
|
val mergeWithLocalEchosUseCase = TimelineMergeWithLocalEchosUseCaseImpl(LocalEchoMapper(MetaMapper()))
|
||||||
val timeline = TimelineUseCaseImpl(matrix.syncService(), matrix.messageService(), matrix.roomService(), mergeWithLocalEchosUseCase)
|
val timeline = TimelineUseCaseImpl(matrix.syncService(), matrix.messageService(), matrix.roomService(), mergeWithLocalEchosUseCase)
|
||||||
ReadMarkingTimeline(roomStore, credentialsStore, timeline, matrix.roomService())
|
ReadMarkingTimeline(roomStore, credentialsStore, timeline, matrix.roomService())
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,11 +4,11 @@ import app.dapk.st.matrix.common.EventId
|
||||||
import app.dapk.st.matrix.common.RoomMember
|
import app.dapk.st.matrix.common.RoomMember
|
||||||
import app.dapk.st.matrix.message.MessageService
|
import app.dapk.st.matrix.message.MessageService
|
||||||
|
|
||||||
internal typealias MergeWithLocalEchosUseCase = (RoomState, RoomMember, List<MessageService.LocalEcho>) -> RoomState
|
internal typealias TimelineMergeWithLocalEchosUseCase = (RoomState, RoomMember, List<MessageService.LocalEcho>) -> RoomState
|
||||||
|
|
||||||
internal class MergeWithLocalEchosUseCaseImpl(
|
internal class TimelineMergeWithLocalEchosUseCaseImpl(
|
||||||
private val localEventMapper: LocalEchoMapper,
|
private val localEventMapper: LocalEchoMapper,
|
||||||
) : MergeWithLocalEchosUseCase {
|
) : TimelineMergeWithLocalEchosUseCase {
|
||||||
|
|
||||||
override fun invoke(roomState: RoomState, member: RoomMember, echos: List<MessageService.LocalEcho>): RoomState {
|
override fun invoke(roomState: RoomState, member: RoomMember, echos: List<MessageService.LocalEcho>): RoomState {
|
||||||
val echosByEventId = echos.associateBy { it.eventId }
|
val echosByEventId = echos.associateBy { it.eventId }
|
||||||
|
|
|
@ -16,7 +16,7 @@ internal class TimelineUseCaseImpl(
|
||||||
private val syncService: SyncService,
|
private val syncService: SyncService,
|
||||||
private val messageService: MessageService,
|
private val messageService: MessageService,
|
||||||
private val roomService: RoomService,
|
private val roomService: RoomService,
|
||||||
private val mergeWithLocalEchosUseCase: MergeWithLocalEchosUseCase
|
private val timelineMergeWithLocalEchosUseCase: TimelineMergeWithLocalEchosUseCase,
|
||||||
) : ObserveTimelineUseCase {
|
) : ObserveTimelineUseCase {
|
||||||
|
|
||||||
override fun invoke(roomId: RoomId, userId: UserId): Flow<MessengerPageState> {
|
override fun invoke(roomId: RoomId, userId: UserId): Flow<MessengerPageState> {
|
||||||
|
@ -30,7 +30,7 @@ internal class TimelineUseCaseImpl(
|
||||||
roomState = when {
|
roomState = when {
|
||||||
localEchos.isEmpty() -> roomState
|
localEchos.isEmpty() -> roomState
|
||||||
else -> {
|
else -> {
|
||||||
mergeWithLocalEchosUseCase.invoke(
|
timelineMergeWithLocalEchosUseCase.invoke(
|
||||||
roomState,
|
roomState,
|
||||||
roomService.findMember(roomId, userId) ?: userId.toFallbackMember(),
|
roomService.findMember(roomId, userId) ?: userId.toFallbackMember(),
|
||||||
localEchos,
|
localEchos,
|
||||||
|
|
|
@ -17,7 +17,7 @@ private val ANOTHER_ROOM_MESSAGE_EVENT = A_ROOM_MESSAGE_EVENT.copy(eventId = anE
|
||||||
class MergeWithLocalEchosUseCaseTest {
|
class MergeWithLocalEchosUseCaseTest {
|
||||||
|
|
||||||
private val fakeLocalEchoMapper = fake.FakeLocalEventMapper()
|
private val fakeLocalEchoMapper = fake.FakeLocalEventMapper()
|
||||||
private val mergeWithLocalEchosUseCase = MergeWithLocalEchosUseCaseImpl(fakeLocalEchoMapper.instance)
|
private val mergeWithLocalEchosUseCase = TimelineMergeWithLocalEchosUseCaseImpl(fakeLocalEchoMapper.instance)
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `given no local echos, when merging text message, then returns original state`() {
|
fun `given no local echos, when merging text message, then returns original state`() {
|
||||||
|
|
|
@ -113,7 +113,7 @@ suspend fun <T> Flow<T>.test(scope: CoroutineScope) = FlowTestObserver(scope, th
|
||||||
this.collect()
|
this.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
class FakeMergeWithLocalEchosUseCase : MergeWithLocalEchosUseCase by mockk() {
|
class FakeMergeWithLocalEchosUseCase : TimelineMergeWithLocalEchosUseCase by mockk() {
|
||||||
fun givenMerging(roomState: RoomState, roomMember: RoomMember, echos: List<MessageService.LocalEcho>) = every {
|
fun givenMerging(roomState: RoomState, roomMember: RoomMember, echos: List<MessageService.LocalEcho>) = every {
|
||||||
this@FakeMergeWithLocalEchosUseCase.invoke(roomState.engine(), roomMember, echos)
|
this@FakeMergeWithLocalEchosUseCase.invoke(roomState.engine(), roomMember, echos)
|
||||||
}.delegateReturn()
|
}.delegateReturn()
|
||||||
|
|
Loading…
Reference in New Issue