porting the messenger module to chat-engine
This commit is contained in:
parent
baf7cfc17a
commit
e61dea7ba7
|
@ -178,11 +178,8 @@ internal class FeatureModules internal constructor(
|
||||||
val messengerModule by unsafeLazy {
|
val messengerModule by unsafeLazy {
|
||||||
MessengerModule(
|
MessengerModule(
|
||||||
matrixModules.engine,
|
matrixModules.engine,
|
||||||
matrixModules.message,
|
|
||||||
clock,
|
|
||||||
context,
|
context,
|
||||||
base64,
|
base64,
|
||||||
imageContentReader,
|
|
||||||
storeModule.value.messageStore(),
|
storeModule.value.messageStore(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,4 +20,5 @@ interface ChatEngine {
|
||||||
|
|
||||||
suspend fun InputStream.importRoomKeys(password: String): Flow<ImportResult>
|
suspend fun InputStream.importRoomKeys(password: String): Flow<ImportResult>
|
||||||
|
|
||||||
|
suspend fun send(message: SendMessage, room: RoomOverview)
|
||||||
}
|
}
|
||||||
|
|
|
@ -197,4 +197,25 @@ sealed class MessageMeta {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sealed interface SendMessage {
|
||||||
|
|
||||||
|
data class TextMessage(
|
||||||
|
val content: String,
|
||||||
|
val reply: Reply? = null,
|
||||||
|
) : SendMessage {
|
||||||
|
|
||||||
|
data class Reply(
|
||||||
|
val author: RoomMember,
|
||||||
|
val originalMessage: String,
|
||||||
|
val eventId: EventId,
|
||||||
|
val timestampUtc: Long,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
data class ImageMessage(
|
||||||
|
val uri: String,
|
||||||
|
) : SendMessage
|
||||||
|
|
||||||
}
|
}
|
|
@ -3,10 +3,6 @@ apply plugin: 'kotlin-parcelize'
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation project(":chat-engine")
|
implementation project(":chat-engine")
|
||||||
implementation project(":matrix:services:sync")
|
|
||||||
implementation project(":matrix:services:message")
|
|
||||||
implementation project(":matrix:services:crypto")
|
|
||||||
implementation project(":matrix:services:room")
|
|
||||||
implementation project(":domains:android:compose-core")
|
implementation project(":domains:android:compose-core")
|
||||||
implementation project(":domains:android:viewmodel")
|
implementation project(":domains:android:viewmodel")
|
||||||
implementation project(":domains:store")
|
implementation project(":domains:store")
|
||||||
|
|
|
@ -5,33 +5,19 @@ import app.dapk.st.core.Base64
|
||||||
import app.dapk.st.core.ProvidableModule
|
import app.dapk.st.core.ProvidableModule
|
||||||
import app.dapk.st.domain.application.message.MessageOptionsStore
|
import app.dapk.st.domain.application.message.MessageOptionsStore
|
||||||
import app.dapk.st.engine.ChatEngine
|
import app.dapk.st.engine.ChatEngine
|
||||||
import app.dapk.st.matrix.common.CredentialsStore
|
|
||||||
import app.dapk.st.matrix.common.RoomId
|
import app.dapk.st.matrix.common.RoomId
|
||||||
import app.dapk.st.matrix.message.MessageService
|
|
||||||
import app.dapk.st.matrix.message.internal.ImageContentReader
|
|
||||||
import app.dapk.st.matrix.room.RoomService
|
|
||||||
import app.dapk.st.matrix.sync.RoomStore
|
|
||||||
import app.dapk.st.matrix.sync.SyncService
|
|
||||||
import java.time.Clock
|
|
||||||
|
|
||||||
class MessengerModule(
|
class MessengerModule(
|
||||||
private val chatEngine: ChatEngine,
|
private val chatEngine: ChatEngine,
|
||||||
private val messageService: MessageService,
|
|
||||||
private val clock: Clock,
|
|
||||||
private val context: Context,
|
private val context: Context,
|
||||||
private val base64: Base64,
|
private val base64: Base64,
|
||||||
private val imageMetaReader: ImageContentReader,
|
|
||||||
private val messageOptionsStore: MessageOptionsStore,
|
private val messageOptionsStore: MessageOptionsStore,
|
||||||
) : ProvidableModule {
|
) : ProvidableModule {
|
||||||
|
|
||||||
internal fun messengerViewModel(): MessengerViewModel {
|
internal fun messengerViewModel(): MessengerViewModel {
|
||||||
return MessengerViewModel(
|
return MessengerViewModel(
|
||||||
chatEngine,
|
chatEngine,
|
||||||
messageService,
|
|
||||||
LocalIdFactory(),
|
|
||||||
imageMetaReader,
|
|
||||||
messageOptionsStore,
|
messageOptionsStore,
|
||||||
clock
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,9 +6,8 @@ import app.dapk.st.core.extensions.takeIfContent
|
||||||
import app.dapk.st.domain.application.message.MessageOptionsStore
|
import app.dapk.st.domain.application.message.MessageOptionsStore
|
||||||
import app.dapk.st.engine.ChatEngine
|
import app.dapk.st.engine.ChatEngine
|
||||||
import app.dapk.st.engine.RoomEvent
|
import app.dapk.st.engine.RoomEvent
|
||||||
|
import app.dapk.st.engine.SendMessage
|
||||||
import app.dapk.st.matrix.common.RoomId
|
import app.dapk.st.matrix.common.RoomId
|
||||||
import app.dapk.st.matrix.message.MessageService
|
|
||||||
import app.dapk.st.matrix.message.internal.ImageContentReader
|
|
||||||
import app.dapk.st.navigator.MessageAttachment
|
import app.dapk.st.navigator.MessageAttachment
|
||||||
import app.dapk.st.viewmodel.DapkViewModel
|
import app.dapk.st.viewmodel.DapkViewModel
|
||||||
import app.dapk.st.viewmodel.MutableStateFactory
|
import app.dapk.st.viewmodel.MutableStateFactory
|
||||||
|
@ -17,15 +16,10 @@ import kotlinx.coroutines.Job
|
||||||
import kotlinx.coroutines.flow.launchIn
|
import kotlinx.coroutines.flow.launchIn
|
||||||
import kotlinx.coroutines.flow.onEach
|
import kotlinx.coroutines.flow.onEach
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import java.time.Clock
|
|
||||||
|
|
||||||
internal class MessengerViewModel(
|
internal class MessengerViewModel(
|
||||||
private val chatEngine: ChatEngine,
|
private val chatEngine: ChatEngine,
|
||||||
private val messageService: MessageService,
|
|
||||||
private val localIdFactory: LocalIdFactory,
|
|
||||||
private val imageContentReader: ImageContentReader,
|
|
||||||
private val messageOptionsStore: MessageOptionsStore,
|
private val messageOptionsStore: MessageOptionsStore,
|
||||||
private val clock: Clock,
|
|
||||||
factory: MutableStateFactory<MessengerScreenState> = defaultStateFactory(),
|
factory: MutableStateFactory<MessengerScreenState> = defaultStateFactory(),
|
||||||
) : DapkViewModel<MessengerScreenState, MessengerEvent>(
|
) : DapkViewModel<MessengerScreenState, MessengerEvent>(
|
||||||
initialState = MessengerScreenState(
|
initialState = MessengerScreenState(
|
||||||
|
@ -83,6 +77,7 @@ internal class MessengerViewModel(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private fun sendMessage() {
|
private fun sendMessage() {
|
||||||
when (val composerState = state.composerState) {
|
when (val composerState = state.composerState) {
|
||||||
is ComposerState.Text -> {
|
is ComposerState.Text -> {
|
||||||
|
@ -92,27 +87,23 @@ internal class MessengerViewModel(
|
||||||
state.roomState.takeIfContent()?.let { content ->
|
state.roomState.takeIfContent()?.let { content ->
|
||||||
val roomState = content.roomState
|
val roomState = content.roomState
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
messageService.scheduleMessage(
|
chatEngine.send(
|
||||||
MessageService.Message.TextMessage(
|
message = SendMessage.TextMessage(
|
||||||
MessageService.Message.Content.TextContent(body = copy.value),
|
content = copy.value,
|
||||||
roomId = roomState.roomOverview.roomId,
|
|
||||||
sendEncrypted = roomState.roomOverview.isEncrypted,
|
|
||||||
localId = localIdFactory.create(),
|
|
||||||
timestampUtc = clock.millis(),
|
|
||||||
reply = copy.reply?.let {
|
reply = copy.reply?.let {
|
||||||
MessageService.Message.TextMessage.Reply(
|
SendMessage.TextMessage.Reply(
|
||||||
author = it.author,
|
author = it.author,
|
||||||
originalMessage = when (it) {
|
originalMessage = when (it) {
|
||||||
is RoomEvent.Image -> TODO()
|
is RoomEvent.Image -> TODO()
|
||||||
is RoomEvent.Reply -> TODO()
|
is RoomEvent.Reply -> TODO()
|
||||||
is RoomEvent.Message -> it.content
|
is RoomEvent.Message -> it.content
|
||||||
},
|
},
|
||||||
replyContent = copy.value,
|
|
||||||
eventId = it.eventId,
|
eventId = it.eventId,
|
||||||
timestampUtc = it.utcTimestamp,
|
timestampUtc = it.utcTimestamp,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
)
|
),
|
||||||
|
room = roomState.roomOverview,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -125,26 +116,7 @@ internal class MessengerViewModel(
|
||||||
state.roomState.takeIfContent()?.let { content ->
|
state.roomState.takeIfContent()?.let { content ->
|
||||||
val roomState = content.roomState
|
val roomState = content.roomState
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
val imageUri = copy.values.first().uri.value
|
chatEngine.send(SendMessage.ImageMessage(uri = copy.values.first().uri.value), roomState.roomOverview)
|
||||||
val meta = imageContentReader.meta(imageUri)
|
|
||||||
|
|
||||||
messageService.scheduleMessage(
|
|
||||||
MessageService.Message.ImageMessage(
|
|
||||||
MessageService.Message.Content.ImageContent(
|
|
||||||
uri = imageUri, MessageService.Message.Content.ImageContent.Meta(
|
|
||||||
height = meta.height,
|
|
||||||
width = meta.width,
|
|
||||||
size = meta.size,
|
|
||||||
fileName = meta.fileName,
|
|
||||||
mimeType = meta.mimeType,
|
|
||||||
)
|
|
||||||
),
|
|
||||||
roomId = roomState.roomOverview.roomId,
|
|
||||||
sendEncrypted = roomState.roomOverview.isEncrypted,
|
|
||||||
localId = localIdFactory.create(),
|
|
||||||
timestampUtc = clock.millis(),
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -37,6 +37,7 @@ class MatrixEngine internal constructor(
|
||||||
private val directoryUseCase: Lazy<DirectoryUseCase>,
|
private val directoryUseCase: Lazy<DirectoryUseCase>,
|
||||||
private val matrix: Lazy<MatrixClient>,
|
private val matrix: Lazy<MatrixClient>,
|
||||||
private val timelineUseCase: Lazy<ReadMarkingTimeline>,
|
private val timelineUseCase: Lazy<ReadMarkingTimeline>,
|
||||||
|
private val sendMessageUseCase: Lazy<SendMessageUseCase>,
|
||||||
) : ChatEngine {
|
) : ChatEngine {
|
||||||
|
|
||||||
override fun directory() = directoryUseCase.value.state()
|
override fun directory() = directoryUseCase.value.state()
|
||||||
|
@ -67,6 +68,10 @@ class MatrixEngine internal constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override suspend fun send(message: SendMessage, room: RoomOverview) {
|
||||||
|
sendMessageUseCase.value.send(message, room)
|
||||||
|
}
|
||||||
|
|
||||||
class Factory {
|
class Factory {
|
||||||
|
|
||||||
fun create(
|
fun create(
|
||||||
|
@ -128,7 +133,12 @@ class MatrixEngine internal constructor(
|
||||||
ReadMarkingTimeline(roomStore, credentialsStore, timeline, matrix.roomService())
|
ReadMarkingTimeline(roomStore, credentialsStore, timeline, matrix.roomService())
|
||||||
}
|
}
|
||||||
|
|
||||||
return MatrixEngine(directoryUseCase, lazyMatrix, timelineUseCase)
|
val sendMessageUseCase = unsafeLazy {
|
||||||
|
val matrix = lazyMatrix.value
|
||||||
|
SendMessageUseCase(matrix.messageService(), LocalIdFactory(), imageContentReader, Clock.systemUTC())
|
||||||
|
}
|
||||||
|
|
||||||
|
return MatrixEngine(directoryUseCase, lazyMatrix, timelineUseCase, sendMessageUseCase)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,60 @@
|
||||||
|
package app.dapk.st.engine
|
||||||
|
|
||||||
|
import app.dapk.st.matrix.message.MessageService
|
||||||
|
import app.dapk.st.matrix.message.internal.ImageContentReader
|
||||||
|
import java.time.Clock
|
||||||
|
|
||||||
|
internal class SendMessageUseCase(
|
||||||
|
private val messageService: MessageService,
|
||||||
|
private val localIdFactory: LocalIdFactory,
|
||||||
|
private val imageContentReader: ImageContentReader,
|
||||||
|
private val clock: Clock,
|
||||||
|
) {
|
||||||
|
|
||||||
|
suspend fun send(message: SendMessage, room: RoomOverview) {
|
||||||
|
when (message) {
|
||||||
|
is SendMessage.ImageMessage -> createImageMessage(message, room)
|
||||||
|
is SendMessage.TextMessage -> messageService.scheduleMessage(createTextMessage(message, room))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private suspend fun createImageMessage(message: SendMessage.ImageMessage, room: RoomOverview) {
|
||||||
|
val meta = imageContentReader.meta(message.uri)
|
||||||
|
messageService.scheduleMessage(
|
||||||
|
MessageService.Message.ImageMessage(
|
||||||
|
MessageService.Message.Content.ImageContent(
|
||||||
|
uri = message.uri,
|
||||||
|
MessageService.Message.Content.ImageContent.Meta(
|
||||||
|
height = meta.height,
|
||||||
|
width = meta.width,
|
||||||
|
size = meta.size,
|
||||||
|
fileName = meta.fileName,
|
||||||
|
mimeType = meta.mimeType,
|
||||||
|
)
|
||||||
|
),
|
||||||
|
roomId = room.roomId,
|
||||||
|
sendEncrypted = room.isEncrypted,
|
||||||
|
localId = localIdFactory.create(),
|
||||||
|
timestampUtc = clock.millis(),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createTextMessage(message: SendMessage.TextMessage, room: RoomOverview) = MessageService.Message.TextMessage(
|
||||||
|
content = MessageService.Message.Content.TextContent(message.content),
|
||||||
|
roomId = room.roomId,
|
||||||
|
sendEncrypted = room.isEncrypted,
|
||||||
|
localId = localIdFactory.create(),
|
||||||
|
timestampUtc = clock.millis(),
|
||||||
|
reply = message.reply?.let {
|
||||||
|
MessageService.Message.TextMessage.Reply(
|
||||||
|
author = it.author,
|
||||||
|
originalMessage = it.originalMessage,
|
||||||
|
replyContent = message.content,
|
||||||
|
eventId = it.eventId,
|
||||||
|
timestampUtc = it.timestampUtc,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue