From a21f3a1663d762c0950650d7d490dd8b5f69e2fe Mon Sep 17 00:00:00 2001 From: Adam Brown Date: Sat, 5 Nov 2022 11:12:12 +0000 Subject: [PATCH] lifting directory local echo merging to its own class --- .../DirectoryMergeWithLocalEchosUseCase.kt | 53 +++++++++++++++++++ .../app/dapk/st/engine/DirectoryUseCase.kt | 44 ++------------- .../kotlin/app/dapk/st/engine/MatrixEngine.kt | 6 +-- .../st/engine/MergeWithLocalEchosUseCase.kt | 6 +-- .../app/dapk/st/engine/TimelineUseCase.kt | 4 +- .../engine/MergeWithLocalEchosUseCaseTest.kt | 2 +- .../app/dapk/st/engine/TimelineUseCaseTest.kt | 2 +- 7 files changed, 66 insertions(+), 51 deletions(-) create mode 100644 matrix-chat-engine/src/main/kotlin/app/dapk/st/engine/DirectoryMergeWithLocalEchosUseCase.kt diff --git a/matrix-chat-engine/src/main/kotlin/app/dapk/st/engine/DirectoryMergeWithLocalEchosUseCase.kt b/matrix-chat-engine/src/main/kotlin/app/dapk/st/engine/DirectoryMergeWithLocalEchosUseCase.kt new file mode 100644 index 0000000..2f0d602 --- /dev/null +++ b/matrix-chat-engine/src/main/kotlin/app/dapk/st/engine/DirectoryMergeWithLocalEchosUseCase.kt @@ -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>) -> OverviewState + +internal class DirectoryMergeWithLocalEchosUseCaseImpl( + private val roomService: RoomService, +) : DirectoryMergeWithLocalEchosUseCase { + + override suspend fun invoke(overview: OverviewState, selfId: UserId, echos: Map>): 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): 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 + } + } + +} \ No newline at end of file diff --git a/matrix-chat-engine/src/main/kotlin/app/dapk/st/engine/DirectoryUseCase.kt b/matrix-chat-engine/src/main/kotlin/app/dapk/st/engine/DirectoryUseCase.kt index 2543fbc..f6282d3 100644 --- a/matrix-chat-engine/src/main/kotlin/app/dapk/st/engine/DirectoryUseCase.kt +++ b/matrix-chat-engine/src/main/kotlin/app/dapk/st/engine/DirectoryUseCase.kt @@ -1,7 +1,7 @@ package app.dapk.st.engine 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.room.RoomService import app.dapk.st.matrix.sync.RoomStore @@ -15,9 +15,9 @@ import kotlinx.coroutines.flow.map internal class DirectoryUseCase( private val syncService: SyncService, private val messageService: MessageService, - private val roomService: RoomService, private val credentialsStore: CredentialsStore, private val roomStore: RoomStore, + private val mergeLocalEchosUseCase: DirectoryMergeWithLocalEchosUseCaseImpl ) { fun state(): Flow { @@ -30,7 +30,7 @@ internal class DirectoryUseCase( syncService.events(), roomStore.observeMuted(), ) { _, overviewState, localEchos, unread, events, muted -> - overviewState.mergeWithLocalEchos(localEchos, userId).map { roomOverview -> + mergeLocalEchosUseCase.invoke(overviewState, userId, localEchos).map { roomOverview -> DirectoryItem( overview = roomOverview, unreadCount = UnreadCount(unread[roomOverview.roomId] ?: 0), @@ -41,42 +41,4 @@ internal class DirectoryUseCase( } } } - - private suspend fun OverviewState.mergeWithLocalEchos(localEchos: Map>, 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): 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 - } - } - } diff --git a/matrix-chat-engine/src/main/kotlin/app/dapk/st/engine/MatrixEngine.kt b/matrix-chat-engine/src/main/kotlin/app/dapk/st/engine/MatrixEngine.kt index 4d6977d..93003d1 100644 --- a/matrix-chat-engine/src/main/kotlin/app/dapk/st/engine/MatrixEngine.kt +++ b/matrix-chat-engine/src/main/kotlin/app/dapk/st/engine/MatrixEngine.kt @@ -173,14 +173,14 @@ class MatrixEngine internal constructor( DirectoryUseCase( matrix.syncService(), matrix.messageService(), - matrix.roomService(), credentialsStore, - roomStore + roomStore, + DirectoryMergeWithLocalEchosUseCaseImpl(matrix.roomService()), ) } val timelineUseCase = unsafeLazy { val matrix = lazyMatrix.value - val mergeWithLocalEchosUseCase = MergeWithLocalEchosUseCaseImpl(LocalEchoMapper(MetaMapper())) + val mergeWithLocalEchosUseCase = TimelineMergeWithLocalEchosUseCaseImpl(LocalEchoMapper(MetaMapper())) val timeline = TimelineUseCaseImpl(matrix.syncService(), matrix.messageService(), matrix.roomService(), mergeWithLocalEchosUseCase) ReadMarkingTimeline(roomStore, credentialsStore, timeline, matrix.roomService()) } diff --git a/matrix-chat-engine/src/main/kotlin/app/dapk/st/engine/MergeWithLocalEchosUseCase.kt b/matrix-chat-engine/src/main/kotlin/app/dapk/st/engine/MergeWithLocalEchosUseCase.kt index 8f91848..2b9c19c 100644 --- a/matrix-chat-engine/src/main/kotlin/app/dapk/st/engine/MergeWithLocalEchosUseCase.kt +++ b/matrix-chat-engine/src/main/kotlin/app/dapk/st/engine/MergeWithLocalEchosUseCase.kt @@ -4,11 +4,11 @@ import app.dapk.st.matrix.common.EventId import app.dapk.st.matrix.common.RoomMember import app.dapk.st.matrix.message.MessageService -internal typealias MergeWithLocalEchosUseCase = (RoomState, RoomMember, List) -> RoomState +internal typealias TimelineMergeWithLocalEchosUseCase = (RoomState, RoomMember, List) -> RoomState -internal class MergeWithLocalEchosUseCaseImpl( +internal class TimelineMergeWithLocalEchosUseCaseImpl( private val localEventMapper: LocalEchoMapper, -) : MergeWithLocalEchosUseCase { +) : TimelineMergeWithLocalEchosUseCase { override fun invoke(roomState: RoomState, member: RoomMember, echos: List): RoomState { val echosByEventId = echos.associateBy { it.eventId } diff --git a/matrix-chat-engine/src/main/kotlin/app/dapk/st/engine/TimelineUseCase.kt b/matrix-chat-engine/src/main/kotlin/app/dapk/st/engine/TimelineUseCase.kt index 1f7f930..219a93f 100644 --- a/matrix-chat-engine/src/main/kotlin/app/dapk/st/engine/TimelineUseCase.kt +++ b/matrix-chat-engine/src/main/kotlin/app/dapk/st/engine/TimelineUseCase.kt @@ -16,7 +16,7 @@ internal class TimelineUseCaseImpl( private val syncService: SyncService, private val messageService: MessageService, private val roomService: RoomService, - private val mergeWithLocalEchosUseCase: MergeWithLocalEchosUseCase + private val timelineMergeWithLocalEchosUseCase: TimelineMergeWithLocalEchosUseCase, ) : ObserveTimelineUseCase { override fun invoke(roomId: RoomId, userId: UserId): Flow { @@ -30,7 +30,7 @@ internal class TimelineUseCaseImpl( roomState = when { localEchos.isEmpty() -> roomState else -> { - mergeWithLocalEchosUseCase.invoke( + timelineMergeWithLocalEchosUseCase.invoke( roomState, roomService.findMember(roomId, userId) ?: userId.toFallbackMember(), localEchos, diff --git a/matrix-chat-engine/src/test/kotlin/app/dapk/st/engine/MergeWithLocalEchosUseCaseTest.kt b/matrix-chat-engine/src/test/kotlin/app/dapk/st/engine/MergeWithLocalEchosUseCaseTest.kt index 4868445..637b761 100644 --- a/matrix-chat-engine/src/test/kotlin/app/dapk/st/engine/MergeWithLocalEchosUseCaseTest.kt +++ b/matrix-chat-engine/src/test/kotlin/app/dapk/st/engine/MergeWithLocalEchosUseCaseTest.kt @@ -17,7 +17,7 @@ private val ANOTHER_ROOM_MESSAGE_EVENT = A_ROOM_MESSAGE_EVENT.copy(eventId = anE class MergeWithLocalEchosUseCaseTest { private val fakeLocalEchoMapper = fake.FakeLocalEventMapper() - private val mergeWithLocalEchosUseCase = MergeWithLocalEchosUseCaseImpl(fakeLocalEchoMapper.instance) + private val mergeWithLocalEchosUseCase = TimelineMergeWithLocalEchosUseCaseImpl(fakeLocalEchoMapper.instance) @Test fun `given no local echos, when merging text message, then returns original state`() { diff --git a/matrix-chat-engine/src/test/kotlin/app/dapk/st/engine/TimelineUseCaseTest.kt b/matrix-chat-engine/src/test/kotlin/app/dapk/st/engine/TimelineUseCaseTest.kt index 2c553fe..1936e9a 100644 --- a/matrix-chat-engine/src/test/kotlin/app/dapk/st/engine/TimelineUseCaseTest.kt +++ b/matrix-chat-engine/src/test/kotlin/app/dapk/st/engine/TimelineUseCaseTest.kt @@ -113,7 +113,7 @@ suspend fun Flow.test(scope: CoroutineScope) = FlowTestObserver(scope, th this.collect() } -class FakeMergeWithLocalEchosUseCase : MergeWithLocalEchosUseCase by mockk() { +class FakeMergeWithLocalEchosUseCase : TimelineMergeWithLocalEchosUseCase by mockk() { fun givenMerging(roomState: RoomState, roomMember: RoomMember, echos: List) = every { this@FakeMergeWithLocalEchosUseCase.invoke(roomState.engine(), roomMember, echos) }.delegateReturn()