computing the image size before sending to allow it to be used in local echos

- fixes local echo images changing size
This commit is contained in:
Adam Brown 2022-10-01 12:22:19 +01:00
parent 2bb2091234
commit 2110667d90
8 changed files with 46 additions and 11 deletions

View File

@ -93,7 +93,9 @@ internal class AppModule(context: Application, logger: MatrixLogger) {
private val workModule = WorkModule(context) private val workModule = WorkModule(context)
private val imageLoaderModule = ImageLoaderModule(context) private val imageLoaderModule = ImageLoaderModule(context)
private val matrixModules = MatrixModules(storeModule, trackingModule, workModule, logger, coroutineDispatchers, context.contentResolver, base64, buildMeta) private val imageContentReader by unsafeLazy { AndroidImageContentReader(context.contentResolver) }
private val matrixModules = MatrixModules(storeModule, trackingModule, workModule, logger, coroutineDispatchers, imageContentReader, base64, buildMeta)
val domainModules = DomainModules(matrixModules, trackingModule.errorTracker, workModule, storeModule, context, coroutineDispatchers) val domainModules = DomainModules(matrixModules, trackingModule.errorTracker, workModule, storeModule, context, coroutineDispatchers)
val coreAndroidModule = CoreAndroidModule( val coreAndroidModule = CoreAndroidModule(
@ -133,6 +135,7 @@ internal class AppModule(context: Application, logger: MatrixLogger) {
trackingModule, trackingModule,
coreAndroidModule, coreAndroidModule,
imageLoaderModule, imageLoaderModule,
imageContentReader,
context, context,
buildMeta, buildMeta,
deviceMeta, deviceMeta,
@ -149,6 +152,7 @@ internal class FeatureModules internal constructor(
private val trackingModule: TrackingModule, private val trackingModule: TrackingModule,
private val coreAndroidModule: CoreAndroidModule, private val coreAndroidModule: CoreAndroidModule,
imageLoaderModule: ImageLoaderModule, imageLoaderModule: ImageLoaderModule,
imageContentReader: ImageContentReader,
context: Context, context: Context,
buildMeta: BuildMeta, buildMeta: BuildMeta,
deviceMeta: DeviceMeta, deviceMeta: DeviceMeta,
@ -185,6 +189,7 @@ internal class FeatureModules internal constructor(
clock, clock,
context, context,
base64, base64,
imageContentReader,
) )
} }
val homeModule by unsafeLazy { HomeModule(storeModule.value, matrixModules.profile, matrixModules.sync, buildMeta) } val homeModule by unsafeLazy { HomeModule(storeModule.value, matrixModules.profile, matrixModules.sync, buildMeta) }
@ -238,7 +243,7 @@ internal class MatrixModules(
private val workModule: WorkModule, private val workModule: WorkModule,
private val logger: MatrixLogger, private val logger: MatrixLogger,
private val coroutineDispatchers: CoroutineDispatchers, private val coroutineDispatchers: CoroutineDispatchers,
private val contentResolver: ContentResolver, private val imageContentReader: ImageContentReader,
private val base64: Base64, private val base64: Base64,
private val buildMeta: BuildMeta, private val buildMeta: BuildMeta,
) { ) {
@ -280,7 +285,6 @@ internal class MatrixModules(
base64 = base64, base64 = base64,
coroutineDispatchers = coroutineDispatchers, coroutineDispatchers = coroutineDispatchers,
) )
val imageContentReader = AndroidImageContentReader(contentResolver)
installMessageService( installMessageService(
store.localEchoStore, store.localEchoStore,
BackgroundWorkAdapter(workModule.workScheduler()), BackgroundWorkAdapter(workModule.workScheduler()),

View File

@ -39,7 +39,7 @@ internal class LocalEchoMapper(private val metaMapper: MetaMapper) {
author = member, author = member,
utcTimestamp = message.timestampUtc, utcTimestamp = message.timestampUtc,
meta = metaMapper.toMeta(this), meta = metaMapper.toMeta(this),
imageMeta = RoomEvent.Image.ImageMeta(100, 100, message.content.uri, null), imageMeta = RoomEvent.Image.ImageMeta(message.content.meta.width, message.content.meta.height, message.content.uri, null),
) )
} }
} }

View File

@ -6,6 +6,7 @@ import app.dapk.st.core.ProvidableModule
import app.dapk.st.matrix.common.CredentialsStore 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.MessageService
import app.dapk.st.matrix.message.internal.ImageContentReader
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
import app.dapk.st.matrix.sync.SyncService import app.dapk.st.matrix.sync.SyncService
@ -20,10 +21,11 @@ class MessengerModule(
private val clock: Clock, private val clock: Clock,
private val context: Context, private val context: Context,
private val base64: Base64, private val base64: Base64,
private val imageMetaReader: ImageContentReader,
) : ProvidableModule { ) : ProvidableModule {
internal fun messengerViewModel(): MessengerViewModel { internal fun messengerViewModel(): MessengerViewModel {
return MessengerViewModel(messageService, roomService, roomStore, credentialsStore, timelineUseCase(), LocalIdFactory(), clock) return MessengerViewModel(messageService, roomService, roomStore, credentialsStore, timelineUseCase(), LocalIdFactory(), imageMetaReader, clock)
} }
private fun timelineUseCase(): TimelineUseCaseImpl { private fun timelineUseCase(): TimelineUseCaseImpl {

View File

@ -8,6 +8,7 @@ import app.dapk.st.matrix.common.EventId
import app.dapk.st.matrix.common.RoomId import app.dapk.st.matrix.common.RoomId
import app.dapk.st.matrix.common.UserId import app.dapk.st.matrix.common.UserId
import app.dapk.st.matrix.message.MessageService 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.room.RoomService
import app.dapk.st.matrix.sync.RoomEvent import app.dapk.st.matrix.sync.RoomEvent
import app.dapk.st.matrix.sync.RoomStore import app.dapk.st.matrix.sync.RoomStore
@ -28,6 +29,7 @@ internal class MessengerViewModel(
private val credentialsStore: CredentialsStore, private val credentialsStore: CredentialsStore,
private val observeTimeline: ObserveTimelineUseCase, private val observeTimeline: ObserveTimelineUseCase,
private val localIdFactory: LocalIdFactory, private val localIdFactory: LocalIdFactory,
private val imageContentReader: ImageContentReader,
private val clock: Clock, private val clock: Clock,
factory: MutableStateFactory<MessengerScreenState> = defaultStateFactory(), factory: MutableStateFactory<MessengerScreenState> = defaultStateFactory(),
) : DapkViewModel<MessengerScreenState, MessengerEvent>( ) : DapkViewModel<MessengerScreenState, MessengerEvent>(
@ -147,9 +149,20 @@ 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
val meta = imageContentReader.meta(imageUri)
messageService.scheduleMessage( messageService.scheduleMessage(
MessageService.Message.ImageMessage( MessageService.Message.ImageMessage(
MessageService.Message.Content.ApiImageContent(uri = copy.values.first().uri.value), 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, roomId = roomState.roomOverview.roomId,
sendEncrypted = roomState.roomOverview.isEncrypted, sendEncrypted = roomState.roomOverview.isEncrypted,
localId = localIdFactory.create(), localId = localIdFactory.create(),

View File

@ -6,6 +6,7 @@ import app.dapk.st.matrix.common.EventId
import app.dapk.st.matrix.common.RoomId import app.dapk.st.matrix.common.RoomId
import app.dapk.st.matrix.common.UserId import app.dapk.st.matrix.common.UserId
import app.dapk.st.matrix.message.MessageService 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.room.RoomService
import app.dapk.st.matrix.sync.RoomState import app.dapk.st.matrix.sync.RoomState
import app.dapk.st.matrix.sync.SyncService import app.dapk.st.matrix.sync.SyncService
@ -47,6 +48,7 @@ class MessengerViewModelTest {
fakeCredentialsStore, fakeCredentialsStore,
fakeObserveTimelineUseCase, fakeObserveTimelineUseCase,
localIdFactory = FakeLocalIdFactory().also { it.givenCreate().returns(A_LOCAL_ID) }.instance, localIdFactory = FakeLocalIdFactory().also { it.givenCreate().returns(A_LOCAL_ID) }.instance,
imageContentReader = FakeImageContentReader(),
clock = fixedClock(A_CURRENT_TIMESTAMP), clock = fixedClock(A_CURRENT_TIMESTAMP),
factory = runViewModelTest.testMutableStateFactory(), factory = runViewModelTest.testMutableStateFactory(),
) )
@ -150,3 +152,5 @@ class FakeRoomService : RoomService by mockk() {
} }
fun fixedClock(timestamp: Long = 0) = Clock.fixed(Instant.ofEpochMilli(timestamp), ZoneOffset.UTC) fun fixedClock(timestamp: Long = 0) = Clock.fixed(Instant.ofEpochMilli(timestamp), ZoneOffset.UTC)
class FakeImageContentReader: ImageContentReader by mockk()

View File

@ -54,7 +54,7 @@ interface MessageService : MatrixService {
@Serializable @Serializable
@SerialName("image_message") @SerialName("image_message")
data class ImageMessage( data class ImageMessage(
@SerialName("content") val content: Content.ApiImageContent, @SerialName("content") val content: Content.ImageContent,
@SerialName("send_encrypted") val sendEncrypted: Boolean, @SerialName("send_encrypted") val sendEncrypted: Boolean,
@SerialName("room_id") val roomId: RoomId, @SerialName("room_id") val roomId: RoomId,
@SerialName("local_id") val localId: String, @SerialName("local_id") val localId: String,
@ -70,9 +70,21 @@ interface MessageService : MatrixService {
) : Content() ) : Content()
@Serializable @Serializable
data class ApiImageContent( data class ImageContent(
@SerialName("uri") val uri: String, @SerialName("uri") val uri: String,
) : Content() @SerialName("meta") val meta: Meta,
) : Content() {
@Serializable
data class Meta(
val height: Int,
val width: Int,
val size: Long,
val fileName: String,
val mimeType: String,
)
}
} }
} }

View File

@ -59,7 +59,7 @@ internal class SendMessageUseCase(
} }
private suspend fun imageMessageRequest(message: Message.ImageMessage): HttpRequest<ApiSendResponse> { private suspend fun imageMessageRequest(message: Message.ImageMessage): HttpRequest<ApiSendResponse> {
val imageMeta = imageContentReader.meta(message.content.uri) val imageMeta = message.content.meta
return when (message.sendEncrypted) { return when (message.sendEncrypted) {
true -> { true -> {

View File

@ -183,7 +183,7 @@ class MatrixTestScope(private val testScope: TestScope) {
println("sending ${file.name}") println("sending ${file.name}")
this.client.messageService().scheduleMessage( this.client.messageService().scheduleMessage(
MessageService.Message.ImageMessage( MessageService.Message.ImageMessage(
content = MessageService.Message.Content.ApiImageContent( content = MessageService.Message.Content.ImageContent(
uri = file.absolutePath, uri = file.absolutePath,
), ),
roomId = roomId, roomId = roomId,