forked from GitHub-Mirror/riotX-android
Send media: first working implementation. Then, need to fix local echo and handle other types than image.
This commit is contained in:
parent
18591d0287
commit
c47eeb9cec
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright 2019 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package im.vector.matrix.android.api.session.content
|
||||
|
||||
import android.os.Parcelable
|
||||
import kotlinx.android.parcel.Parcelize
|
||||
|
||||
@Parcelize
|
||||
data class ContentAttachmentData(
|
||||
val size: Long = 0,
|
||||
val duration: Long = 0,
|
||||
val date: Long = 0,
|
||||
val height: Long = 0,
|
||||
val width: Long = 0,
|
||||
val name: String? = null,
|
||||
val path: String? = null,
|
||||
val mimeType: String? = null
|
||||
) : Parcelable
|
@ -19,7 +19,7 @@ package im.vector.matrix.android.api.session.room.send
|
||||
import im.vector.matrix.android.api.MatrixCallback
|
||||
import im.vector.matrix.android.api.session.events.model.Event
|
||||
import im.vector.matrix.android.api.util.Cancelable
|
||||
import im.vector.matrix.android.internal.session.room.media.MediaAttachment
|
||||
import im.vector.matrix.android.api.session.content.ContentAttachmentData
|
||||
|
||||
/**
|
||||
* This interface defines methods to send events in a room. It's implemented at the room level.
|
||||
@ -34,6 +34,6 @@ interface SendService {
|
||||
*/
|
||||
fun sendTextMessage(text: String, callback: MatrixCallback<Event>): Cancelable
|
||||
|
||||
fun sendMedia(attachment: MediaAttachment, callback: MatrixCallback<Event>): Cancelable
|
||||
fun sendMedia(attachment: ContentAttachmentData, callback: MatrixCallback<Event>): Cancelable
|
||||
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright 2019 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package im.vector.matrix.android.internal.session.content
|
||||
|
||||
import com.squareup.moshi.Json
|
||||
import com.squareup.moshi.JsonClass
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class ContentUploadResponse(
|
||||
@Json(name = "content_uri") val contentUri: String
|
||||
)
|
@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright 2019 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package im.vector.matrix.android.internal.session.content
|
||||
|
||||
import arrow.core.Try
|
||||
import arrow.core.Try.Companion.raise
|
||||
import im.vector.matrix.android.api.auth.data.SessionParams
|
||||
import im.vector.matrix.android.api.session.content.ContentAttachmentData
|
||||
import im.vector.matrix.android.internal.di.MoshiProvider
|
||||
import okhttp3.HttpUrl
|
||||
import okhttp3.MediaType
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.Request
|
||||
import okhttp3.RequestBody
|
||||
import java.io.File
|
||||
import java.io.IOException
|
||||
|
||||
|
||||
internal class ContentUploader(private val okHttpClient: OkHttpClient,
|
||||
private val sessionParams: SessionParams) {
|
||||
|
||||
private val moshi = MoshiProvider.providesMoshi()
|
||||
private val responseAdapter = moshi.adapter(ContentUploadResponse::class.java)
|
||||
|
||||
fun uploadFile(attachment: ContentAttachmentData): Try<ContentUploadResponse> {
|
||||
if (attachment.path == null || attachment.mimeType == null) {
|
||||
return raise(RuntimeException())
|
||||
}
|
||||
val file = File(attachment.path)
|
||||
val urlString = sessionParams.homeServerConnectionConfig.homeServerUri.toString() + URI_PREFIX_CONTENT_API + "upload"
|
||||
|
||||
val urlBuilder = HttpUrl.parse(urlString)?.newBuilder()
|
||||
?: return raise(RuntimeException())
|
||||
|
||||
val httpUrl = urlBuilder
|
||||
.addQueryParameter(
|
||||
"filename", attachment.name
|
||||
).build()
|
||||
|
||||
val requestBody = RequestBody.create(
|
||||
MediaType.parse(attachment.mimeType),
|
||||
file
|
||||
)
|
||||
val request = Request.Builder()
|
||||
.url(httpUrl)
|
||||
.post(requestBody)
|
||||
.build()
|
||||
|
||||
return Try {
|
||||
okHttpClient.newCall(request).execute().use { response ->
|
||||
if (!response.isSuccessful) {
|
||||
throw IOException()
|
||||
} else {
|
||||
response.body()?.source()?.let {
|
||||
responseAdapter.fromJson(it)
|
||||
}
|
||||
?: throw IOException()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright 2019 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package im.vector.matrix.android.internal.session.content
|
||||
|
||||
import android.content.Context
|
||||
import androidx.work.Worker
|
||||
import androidx.work.WorkerParameters
|
||||
import com.squareup.moshi.JsonClass
|
||||
import im.vector.matrix.android.api.session.content.ContentAttachmentData
|
||||
import im.vector.matrix.android.api.session.events.model.Event
|
||||
import im.vector.matrix.android.api.session.events.model.toContent
|
||||
import im.vector.matrix.android.api.session.events.model.toModel
|
||||
import im.vector.matrix.android.api.session.room.model.message.MessageContent
|
||||
import im.vector.matrix.android.api.session.room.model.message.MessageImageContent
|
||||
import im.vector.matrix.android.internal.di.MatrixKoinComponent
|
||||
import im.vector.matrix.android.internal.session.room.send.SendEventWorker
|
||||
import im.vector.matrix.android.internal.util.WorkerParamsFactory
|
||||
import org.koin.standalone.inject
|
||||
|
||||
internal class UploadContentWorker(context: Context, params: WorkerParameters)
|
||||
: Worker(context, params), MatrixKoinComponent {
|
||||
|
||||
private val mediaUploader by inject<ContentUploader>()
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
internal data class Params(
|
||||
val roomId: String,
|
||||
val event: Event,
|
||||
val attachment: ContentAttachmentData
|
||||
)
|
||||
|
||||
override fun doWork(): Result {
|
||||
val params = WorkerParamsFactory.fromData<Params>(inputData)
|
||||
?: return Result.failure()
|
||||
|
||||
return mediaUploader
|
||||
.uploadFile(params.attachment)
|
||||
.fold({ handleFailure() }, { handleSuccess(params, it) })
|
||||
}
|
||||
|
||||
private fun handleFailure(): Result {
|
||||
return Result.retry()
|
||||
}
|
||||
|
||||
private fun handleSuccess(params: Params, contentUploadResponse: ContentUploadResponse): Result {
|
||||
val event = updateEvent(params.event, contentUploadResponse.contentUri)
|
||||
val sendParams = SendEventWorker.Params(params.roomId, event)
|
||||
return Result.success(WorkerParamsFactory.toData(sendParams))
|
||||
}
|
||||
|
||||
private fun updateEvent(event: Event, url: String): Event {
|
||||
val messageContent: MessageContent = event.content.toModel() ?: return event
|
||||
val updatedContent = when (messageContent) {
|
||||
is MessageImageContent -> messageContent.update(url)
|
||||
else -> messageContent
|
||||
}
|
||||
return event.copy(content = updatedContent.toContent())
|
||||
}
|
||||
|
||||
private fun MessageImageContent.update(url: String): MessageImageContent {
|
||||
return copy(url = url)
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -23,7 +23,6 @@ import androidx.work.OneTimeWorkRequestBuilder
|
||||
import androidx.work.WorkManager
|
||||
import com.zhuinden.monarchy.Monarchy
|
||||
import im.vector.matrix.android.internal.database.RealmLiveEntityObserver
|
||||
import im.vector.matrix.android.internal.database.model.EventEntity
|
||||
import im.vector.matrix.android.internal.database.model.GroupEntity
|
||||
import im.vector.matrix.android.internal.database.query.where
|
||||
import im.vector.matrix.android.internal.util.WorkerParamsFactory
|
||||
|
@ -23,7 +23,7 @@ import im.vector.matrix.android.internal.session.room.members.RoomMemberExtracto
|
||||
import im.vector.matrix.android.internal.session.room.read.DefaultReadService
|
||||
import im.vector.matrix.android.internal.session.room.read.SetReadMarkersTask
|
||||
import im.vector.matrix.android.internal.session.room.send.DefaultSendService
|
||||
import im.vector.matrix.android.internal.session.room.send.EventFactory
|
||||
import im.vector.matrix.android.internal.session.room.send.LocalEchoEventFactory
|
||||
import im.vector.matrix.android.internal.session.room.timeline.DefaultTimelineService
|
||||
import im.vector.matrix.android.internal.session.room.timeline.GetContextOfEventTask
|
||||
import im.vector.matrix.android.internal.session.room.timeline.PaginationTask
|
||||
@ -35,7 +35,7 @@ internal class RoomFactory(private val loadRoomMembersTask: LoadRoomMembersTask,
|
||||
private val paginationTask: PaginationTask,
|
||||
private val contextOfEventTask: GetContextOfEventTask,
|
||||
private val setReadMarkersTask: SetReadMarkersTask,
|
||||
private val eventFactory: EventFactory,
|
||||
private val eventFactory: LocalEchoEventFactory,
|
||||
private val taskExecutor: TaskExecutor) {
|
||||
|
||||
fun instantiate(roomId: String): Room {
|
||||
|
@ -17,12 +17,12 @@
|
||||
package im.vector.matrix.android.internal.session.room
|
||||
|
||||
import im.vector.matrix.android.internal.session.DefaultSession
|
||||
import im.vector.matrix.android.internal.session.room.media.MediaUploader
|
||||
import im.vector.matrix.android.internal.session.content.ContentUploader
|
||||
import im.vector.matrix.android.internal.session.room.members.DefaultLoadRoomMembersTask
|
||||
import im.vector.matrix.android.internal.session.room.members.LoadRoomMembersTask
|
||||
import im.vector.matrix.android.internal.session.room.read.DefaultSetReadMarkersTask
|
||||
import im.vector.matrix.android.internal.session.room.read.SetReadMarkersTask
|
||||
import im.vector.matrix.android.internal.session.room.send.EventFactory
|
||||
import im.vector.matrix.android.internal.session.room.send.LocalEchoEventFactory
|
||||
import im.vector.matrix.android.internal.session.room.timeline.*
|
||||
import org.koin.dsl.module.module
|
||||
import retrofit2.Retrofit
|
||||
@ -58,11 +58,11 @@ class RoomModule {
|
||||
}
|
||||
|
||||
scope(DefaultSession.SCOPE) {
|
||||
EventFactory(get())
|
||||
LocalEchoEventFactory(get())
|
||||
}
|
||||
|
||||
scope(DefaultSession.SCOPE) {
|
||||
MediaUploader(get(), get())
|
||||
ContentUploader(get(), get())
|
||||
}
|
||||
|
||||
scope(DefaultSession.SCOPE) {
|
||||
|
@ -18,7 +18,6 @@
|
||||
|
||||
package im.vector.matrix.android.internal.session.room.media
|
||||
|
||||
import android.net.Uri
|
||||
import android.os.Parcelable
|
||||
import kotlinx.android.parcel.Parcelize
|
||||
|
||||
@ -30,7 +29,6 @@ data class MediaAttachment(
|
||||
val height: Long = 0,
|
||||
val width: Long = 0,
|
||||
val name: String? = null,
|
||||
val thumbnail: Uri? = null,
|
||||
val path: String? = null,
|
||||
val mimeType: String? = null
|
||||
) : Parcelable
|
@ -20,11 +20,13 @@ package im.vector.matrix.android.internal.session.room.media
|
||||
|
||||
import arrow.core.Try
|
||||
import im.vector.matrix.android.api.auth.data.SessionParams
|
||||
import im.vector.matrix.android.api.session.content.ContentAttachmentData
|
||||
import im.vector.matrix.android.internal.session.content.URI_PREFIX_CONTENT_API
|
||||
import okhttp3.HttpUrl
|
||||
import okhttp3.MediaType
|
||||
import okhttp3.MultipartBody
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.Request
|
||||
import okhttp3.RequestBody
|
||||
import java.io.File
|
||||
import java.io.IOException
|
||||
|
||||
@ -32,21 +34,28 @@ import java.io.IOException
|
||||
internal class MediaUploader(private val okHttpClient: OkHttpClient,
|
||||
private val sessionParams: SessionParams) {
|
||||
|
||||
fun uploadFile(attachment: MediaAttachment): Try<String> {
|
||||
fun uploadFile(attachment: ContentAttachmentData): Try<String> {
|
||||
if (attachment.path == null || attachment.mimeType == null) {
|
||||
return Try.raise(RuntimeException())
|
||||
}
|
||||
val urlString = sessionParams.homeServerConnectionConfig.homeServerUri.toString() + URI_PREFIX_CONTENT_API + "upload"
|
||||
val file = File(attachment.path)
|
||||
val urlString = sessionParams.homeServerConnectionConfig.homeServerUri.toString() + URI_PREFIX_CONTENT_API + "upload"
|
||||
|
||||
// create RequestBody instance from file
|
||||
val requestFile = RequestBody.create(
|
||||
val urlBuilder = HttpUrl.parse(urlString)?.newBuilder()
|
||||
?: return Try.raise(RuntimeException())
|
||||
|
||||
val httpUrl = urlBuilder
|
||||
.addQueryParameter(
|
||||
"filename", attachment.name
|
||||
).build()
|
||||
|
||||
val requestBody = MultipartBody.create(
|
||||
MediaType.parse(attachment.mimeType),
|
||||
file
|
||||
)
|
||||
val request = Request.Builder()
|
||||
.url(urlString)
|
||||
.post(requestFile)
|
||||
.url(httpUrl)
|
||||
.post(requestBody)
|
||||
.build()
|
||||
|
||||
return okHttpClient.newCall(request).execute().use { response ->
|
||||
|
@ -23,17 +23,19 @@ import androidx.work.Worker
|
||||
import androidx.work.WorkerParameters
|
||||
import com.squareup.moshi.JsonClass
|
||||
import im.vector.matrix.android.internal.di.MatrixKoinComponent
|
||||
import im.vector.matrix.android.api.session.content.ContentAttachmentData
|
||||
import im.vector.matrix.android.internal.session.content.ContentUploader
|
||||
import im.vector.matrix.android.internal.util.WorkerParamsFactory
|
||||
import org.koin.standalone.inject
|
||||
|
||||
internal class UploadMediaWorker(context: Context, params: WorkerParameters)
|
||||
: Worker(context, params), MatrixKoinComponent {
|
||||
|
||||
private val mediaUploader by inject<MediaUploader>()
|
||||
private val mediaUploader by inject<ContentUploader>()
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
internal data class Params(
|
||||
val attachment: MediaAttachment
|
||||
val attachment: ContentAttachmentData
|
||||
)
|
||||
|
||||
override fun doWork(): Result {
|
||||
|
@ -35,7 +35,9 @@ internal class EventsPruner(monarchy: Monarchy) :
|
||||
override val query = Monarchy.Query<EventEntity> { EventEntity.where(it, type = EventType.REDACTION) }
|
||||
|
||||
override fun processChanges(inserted: List<EventEntity>, updated: List<EventEntity>, deleted: List<EventEntity>) {
|
||||
val redactionEvents = inserted.map { it.asDomain() }
|
||||
val redactionEvents = inserted
|
||||
.mapNotNull { it.asDomain().redacts }
|
||||
|
||||
val pruneEventWorkerParams = PruneEventWorker.Params(redactionEvents)
|
||||
val workData = WorkerParamsFactory.toData(pruneEventWorkerParams)
|
||||
|
||||
|
@ -21,7 +21,6 @@ import androidx.work.Worker
|
||||
import androidx.work.WorkerParameters
|
||||
import com.squareup.moshi.JsonClass
|
||||
import com.zhuinden.monarchy.Monarchy
|
||||
import im.vector.matrix.android.api.session.events.model.Event
|
||||
import im.vector.matrix.android.api.session.events.model.EventType
|
||||
import im.vector.matrix.android.internal.database.mapper.ContentMapper
|
||||
import im.vector.matrix.android.internal.database.model.EventEntity
|
||||
@ -37,8 +36,8 @@ internal class PruneEventWorker(context: Context,
|
||||
) : Worker(context, workerParameters), MatrixKoinComponent {
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
internal data class Params(
|
||||
val redactionEvents: List<Event>
|
||||
internal class Params(
|
||||
val eventIdsToRedact: List<String>
|
||||
)
|
||||
|
||||
private val monarchy by inject<Monarchy>()
|
||||
@ -48,18 +47,19 @@ internal class PruneEventWorker(context: Context,
|
||||
?: return Result.failure()
|
||||
|
||||
val result = monarchy.tryTransactionSync { realm ->
|
||||
params.redactionEvents.forEach { event ->
|
||||
pruneEvent(realm, event)
|
||||
params.eventIdsToRedact.forEach { eventId ->
|
||||
pruneEvent(realm, eventId)
|
||||
}
|
||||
}
|
||||
return result.fold({ Result.retry() }, { Result.success() })
|
||||
}
|
||||
|
||||
private fun pruneEvent(realm: Realm, redactionEvent: Event?) {
|
||||
if (redactionEvent == null || redactionEvent.redacts.isNullOrEmpty()) {
|
||||
private fun pruneEvent(realm: Realm, eventIdToRedact: String) {
|
||||
if (eventIdToRedact.isEmpty()) {
|
||||
return
|
||||
}
|
||||
val eventToPrune = EventEntity.where(realm, eventId = redactionEvent.redacts).findFirst()
|
||||
|
||||
val eventToPrune = EventEntity.where(realm, eventId = eventIdToRedact).findFirst()
|
||||
?: return
|
||||
|
||||
val allowedKeys = computeAllowedKeys(eventToPrune.type)
|
||||
@ -87,7 +87,7 @@ internal class PruneEventWorker(context: Context,
|
||||
EventType.STATE_ROOM_ALIASES -> listOf("aliases")
|
||||
EventType.STATE_CANONICAL_ALIAS -> listOf("alias")
|
||||
EventType.FEEDBACK -> listOf("type", "target_event_id")
|
||||
else -> emptyList()
|
||||
else -> emptyList()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -16,17 +16,23 @@
|
||||
|
||||
package im.vector.matrix.android.internal.session.room.send
|
||||
|
||||
import androidx.work.*
|
||||
import androidx.work.BackoffPolicy
|
||||
import androidx.work.Constraints
|
||||
import androidx.work.ExistingWorkPolicy
|
||||
import androidx.work.NetworkType
|
||||
import androidx.work.OneTimeWorkRequest
|
||||
import androidx.work.OneTimeWorkRequestBuilder
|
||||
import androidx.work.WorkManager
|
||||
import com.zhuinden.monarchy.Monarchy
|
||||
import im.vector.matrix.android.api.MatrixCallback
|
||||
import im.vector.matrix.android.api.session.content.ContentAttachmentData
|
||||
import im.vector.matrix.android.api.session.events.model.Event
|
||||
import im.vector.matrix.android.api.session.room.send.SendService
|
||||
import im.vector.matrix.android.api.util.Cancelable
|
||||
import im.vector.matrix.android.internal.database.helper.add
|
||||
import im.vector.matrix.android.internal.database.model.ChunkEntity
|
||||
import im.vector.matrix.android.internal.database.query.findLastLiveChunkFromRoom
|
||||
import im.vector.matrix.android.internal.session.room.media.MediaAttachment
|
||||
import im.vector.matrix.android.internal.session.room.media.UploadMediaWorker
|
||||
import im.vector.matrix.android.internal.session.content.UploadContentWorker
|
||||
import im.vector.matrix.android.internal.session.room.timeline.PaginationDirection
|
||||
import im.vector.matrix.android.internal.util.CancelableWork
|
||||
import im.vector.matrix.android.internal.util.WorkerParamsFactory
|
||||
@ -35,18 +41,19 @@ import java.util.concurrent.TimeUnit
|
||||
|
||||
private const val SEND_WORK = "SEND_WORK"
|
||||
private const val BACKOFF_DELAY = 10_000L
|
||||
|
||||
private val WORK_CONSTRAINTS = Constraints.Builder()
|
||||
.setRequiredNetworkType(NetworkType.CONNECTED)
|
||||
.build()
|
||||
|
||||
internal class DefaultSendService(private val roomId: String,
|
||||
private val eventFactory: EventFactory,
|
||||
private val eventFactory: LocalEchoEventFactory,
|
||||
private val monarchy: Monarchy) : SendService {
|
||||
|
||||
|
||||
override fun sendTextMessage(text: String, callback: MatrixCallback<Event>): Cancelable {
|
||||
val event = eventFactory.createTextEvent(roomId, text)
|
||||
saveLiveEvent(event)
|
||||
saveLocalEcho(event)
|
||||
val sendWork = createSendEventWork(event)
|
||||
WorkManager.getInstance()
|
||||
.beginUniqueWork(SEND_WORK, ExistingWorkPolicy.APPEND, sendWork)
|
||||
@ -55,12 +62,12 @@ internal class DefaultSendService(private val roomId: String,
|
||||
return CancelableWork(sendWork.id)
|
||||
}
|
||||
|
||||
override fun sendMedia(attachment: MediaAttachment, callback: MatrixCallback<Event>): Cancelable {
|
||||
override fun sendMedia(attachment: ContentAttachmentData, callback: MatrixCallback<Event>): Cancelable {
|
||||
// Create an event with the media file path
|
||||
val event = eventFactory.createImageEvent(roomId, attachment)
|
||||
saveLiveEvent(event)
|
||||
|
||||
val uploadWork = createUploadMediaWork(attachment)
|
||||
val event = eventFactory.createMediaEvent(roomId, attachment).also {
|
||||
saveLocalEcho(it)
|
||||
}
|
||||
val uploadWork = createUploadMediaWork(event, attachment)
|
||||
val sendWork = createSendEventWork(event)
|
||||
|
||||
WorkManager.getInstance()
|
||||
@ -70,10 +77,10 @@ internal class DefaultSendService(private val roomId: String,
|
||||
return CancelableWork(sendWork.id)
|
||||
}
|
||||
|
||||
private fun saveLiveEvent(event: Event) {
|
||||
private fun saveLocalEcho(event: Event) {
|
||||
monarchy.tryTransactionAsync { realm ->
|
||||
val chunkEntity = ChunkEntity.findLastLiveChunkFromRoom(realm, roomId)
|
||||
?: return@tryTransactionAsync
|
||||
?: return@tryTransactionAsync
|
||||
chunkEntity.add(roomId, event, PaginationDirection.FORWARDS)
|
||||
}
|
||||
}
|
||||
@ -89,11 +96,11 @@ internal class DefaultSendService(private val roomId: String,
|
||||
.build()
|
||||
}
|
||||
|
||||
private fun createUploadMediaWork(attachment: MediaAttachment): OneTimeWorkRequest {
|
||||
val uploadMediaWorkerParams = UploadMediaWorker.Params(attachment)
|
||||
private fun createUploadMediaWork(event: Event, attachment: ContentAttachmentData): OneTimeWorkRequest {
|
||||
val uploadMediaWorkerParams = UploadContentWorker.Params(roomId, event, attachment)
|
||||
val uploadWorkData = WorkerParamsFactory.toData(uploadMediaWorkerParams)
|
||||
|
||||
return OneTimeWorkRequestBuilder<UploadMediaWorker>()
|
||||
return OneTimeWorkRequestBuilder<UploadContentWorker>()
|
||||
.setConstraints(WORK_CONSTRAINTS)
|
||||
.setInputData(uploadWorkData)
|
||||
.setBackoffCriteria(BackoffPolicy.LINEAR, BACKOFF_DELAY, TimeUnit.MILLISECONDS)
|
||||
|
@ -17,38 +17,38 @@
|
||||
package im.vector.matrix.android.internal.session.room.send
|
||||
|
||||
import im.vector.matrix.android.api.auth.data.Credentials
|
||||
import im.vector.matrix.android.api.session.content.ContentAttachmentData
|
||||
import im.vector.matrix.android.api.session.events.model.Event
|
||||
import im.vector.matrix.android.api.session.events.model.EventType
|
||||
import im.vector.matrix.android.api.session.events.model.toContent
|
||||
import im.vector.matrix.android.api.session.events.model.toModel
|
||||
import im.vector.matrix.android.api.session.room.model.message.ImageInfo
|
||||
import im.vector.matrix.android.api.session.room.model.message.MessageImageContent
|
||||
import im.vector.matrix.android.api.session.room.model.message.MessageTextContent
|
||||
import im.vector.matrix.android.api.session.room.model.message.MessageType
|
||||
import im.vector.matrix.android.internal.session.room.media.MediaAttachment
|
||||
|
||||
internal class EventFactory(private val credentials: Credentials) {
|
||||
internal class LocalEchoEventFactory(private val credentials: Credentials) {
|
||||
|
||||
fun createTextEvent(roomId: String, text: String): Event {
|
||||
val content = MessageTextContent(type = MessageType.MSGTYPE_TEXT, body = text)
|
||||
return createEvent(roomId, content)
|
||||
}
|
||||
|
||||
fun createImageEvent(roomId: String, attachment: MediaAttachment): Event {
|
||||
fun createMediaEvent(roomId: String, attachment: ContentAttachmentData): Event {
|
||||
val content = MessageImageContent(
|
||||
type = MessageType.MSGTYPE_IMAGE,
|
||||
body = attachment.name ?: "image",
|
||||
info = ImageInfo(
|
||||
mimeType = attachment.mimeType ?: "image/png",
|
||||
width = attachment.width.toInt(),
|
||||
height = attachment.height.toInt(),
|
||||
size = attachment.size.toInt()
|
||||
),
|
||||
url = attachment.path
|
||||
)
|
||||
return createEvent(roomId, content)
|
||||
}
|
||||
|
||||
fun updateImageEvent(event: Event, url: String): Event {
|
||||
val imageContent = event.content.toModel<MessageImageContent>() ?: return event
|
||||
val updatedContent = imageContent.copy(url = url)
|
||||
return event.copy(content = updatedContent.toContent())
|
||||
}
|
||||
|
||||
fun createEvent(roomId: String, content: Any? = null): Event {
|
||||
private fun createEvent(roomId: String, content: Any? = null): Event {
|
||||
return Event(
|
||||
roomId = roomId,
|
||||
originServerTs = dummyOriginServerTs(),
|
@ -49,16 +49,17 @@ internal class SendEventWorker(context: Context, params: WorkerParameters)
|
||||
val params = WorkerParamsFactory.fromData<Params>(inputData)
|
||||
?: return Result.failure()
|
||||
|
||||
if (params.event.eventId == null) {
|
||||
val event = params.event
|
||||
if (event.eventId == null) {
|
||||
return Result.failure()
|
||||
}
|
||||
|
||||
val result = executeRequest<SendResponse> {
|
||||
apiCall = roomAPI.send(
|
||||
params.event.eventId,
|
||||
event.eventId,
|
||||
params.roomId,
|
||||
params.event.type,
|
||||
params.event.content
|
||||
event.type,
|
||||
event.content
|
||||
)
|
||||
}
|
||||
result.flatMap { sendResponse ->
|
||||
@ -69,6 +70,4 @@ internal class SendEventWorker(context: Context, params: WorkerParameters)
|
||||
}
|
||||
return result.fold({ Result.retry() }, { Result.success() })
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -22,7 +22,7 @@ import com.jakewharton.rxrelay2.BehaviorRelay
|
||||
import im.vector.matrix.android.api.MatrixCallback
|
||||
import im.vector.matrix.android.api.session.Session
|
||||
import im.vector.matrix.android.api.session.events.model.Event
|
||||
import im.vector.matrix.android.internal.session.room.media.MediaAttachment
|
||||
import im.vector.matrix.android.api.session.content.ContentAttachmentData
|
||||
import im.vector.matrix.rx.rx
|
||||
import im.vector.riotredesign.core.platform.RiotViewModel
|
||||
import im.vector.riotredesign.features.home.room.VisibleRoomStore
|
||||
@ -81,14 +81,13 @@ class RoomDetailViewModel(initialState: RoomDetailViewState,
|
||||
private fun handleSendMedia(action: RoomDetailActions.SendMedia) {
|
||||
val attachment = action.mediaFiles.firstOrNull()
|
||||
?.let {
|
||||
MediaAttachment(
|
||||
ContentAttachmentData(
|
||||
it.size,
|
||||
it.duration,
|
||||
it.date,
|
||||
it.height,
|
||||
it.width,
|
||||
it.name,
|
||||
it.thumbnail,
|
||||
it.path,
|
||||
it.mimeType
|
||||
)
|
||||
|
Loading…
Reference in New Issue
Block a user