Start sending message : introduce WorkManager. WIP - have to clean

This commit is contained in:
ganfra
2018-11-08 19:08:14 +01:00
parent b2bb89ac94
commit f050574728
19 changed files with 207 additions and 11 deletions

View File

@ -6,12 +6,14 @@ import com.squareup.moshi.JsonClass
import im.vector.matrix.android.internal.di.MoshiProvider
import im.vector.matrix.android.internal.legacy.util.JsonUtils
typealias Content = Map<String, Any>
@JsonClass(generateAdapter = true)
data class Event(
@Json(name = "type") val type: String,
@Json(name = "event_id") val eventId: String?,
@Json(name = "content") val content: Map<String, Any>? = null,
@Json(name = "prev_content") val prevContent: Map<String, Any>? = null,
@Json(name = "content") val content: Content? = null,
@Json(name = "prev_content") val prevContent: Content? = null,
@Json(name = "origin_server_ts") val originServerTs: Long? = null,
@Json(name = "sender") val sender: String? = null,
@Json(name = "state_key") val stateKey: String? = null,
@ -39,7 +41,7 @@ data class Event(
return toModel(prevContent)
}
inline fun <reified T> toModel(data: Map<String, Any>?): T? {
inline fun <reified T> toModel(data: Content?): T? {
val moshi = MoshiProvider.providesMoshi()
val moshiAdapter = moshi.adapter(T::class.java)
return moshiAdapter.fromJsonValue(data)

View File

@ -5,7 +5,7 @@ import im.vector.matrix.android.api.session.room.model.MyMembership
import im.vector.matrix.android.api.session.room.model.RoomSummary
import im.vector.matrix.android.api.util.Cancelable
interface Room : TimelineHolder {
interface Room : TimelineHolder, SendService {
val roomId: String

View File

@ -0,0 +1,10 @@
package im.vector.matrix.android.api.session.room
import im.vector.matrix.android.api.util.Cancelable
interface SendService {
fun sendTextMessage(text: String): Cancelable
}

View File

@ -7,6 +7,7 @@ import com.zhuinden.monarchy.Monarchy
import im.vector.matrix.android.api.MatrixCallback
import im.vector.matrix.android.api.session.events.model.EnrichedEvent
import im.vector.matrix.android.api.session.room.Room
import im.vector.matrix.android.api.session.room.SendService
import im.vector.matrix.android.api.session.room.TimelineHolder
import im.vector.matrix.android.api.session.room.model.Membership
import im.vector.matrix.android.api.session.room.model.MyMembership
@ -28,11 +29,11 @@ internal data class DefaultRoom(
override val myMembership: MyMembership
) : Room, KoinComponent {
private val loadRoomMembersRequest by inject<LoadRoomMembersRequest>()
private val syncTokenStore by inject<SyncTokenStore>()
private val monarchy by inject<Monarchy>()
private val timelineHolder by inject<TimelineHolder>(parameters = { parametersOf(roomId) })
private val sendService by inject<SendService>(parameters = { parametersOf(roomId) })
override val roomSummary: LiveData<RoomSummary> by lazy {
val liveData = monarchy
@ -66,4 +67,8 @@ internal data class DefaultRoom(
}
override fun sendTextMessage(text: String): Cancelable {
return sendService.sendTextMessage(text)
}
}

View File

@ -1,12 +1,14 @@
package im.vector.matrix.android.internal.session.room
import im.vector.matrix.android.api.session.room.model.MessageContent
import im.vector.matrix.android.internal.network.NetworkConstants
import im.vector.matrix.android.internal.session.room.members.RoomMembersResponse
import im.vector.matrix.android.internal.session.room.send.SendResponse
import im.vector.matrix.android.internal.session.room.timeline.TokenChunkEvent
import kotlinx.coroutines.Deferred
import retrofit2.Call
import retrofit2.Response
import retrofit2.http.Body
import retrofit2.http.GET
import retrofit2.http.PUT
import retrofit2.http.Path
import retrofit2.http.Query
@ -46,4 +48,20 @@ internal interface RoomAPI {
): Call<RoomMembersResponse>
/**
* Send an event to a room.
*
* @param txId the transaction Id
* @param roomId the room id
* @param eventType the event type
* @param content the event content
*/
@PUT(NetworkConstants.URI_API_PREFIX_PATH_R0 + "rooms/{roomId}/send/{eventType}/{txId}")
fun send(@Path("txId") txId: String,
@Path("roomId") roomId: String,
@Path("eventType") eventType: String,
@Body content: MessageContent
): Call<SendResponse>
}

View File

@ -1,12 +1,13 @@
package im.vector.matrix.android.internal.session.room
import im.vector.matrix.android.api.session.room.SendService
import im.vector.matrix.android.api.session.room.TimelineHolder
import im.vector.matrix.android.internal.session.DefaultSession
import im.vector.matrix.android.internal.session.room.members.LoadRoomMembersRequest
import im.vector.matrix.android.internal.session.room.send.DefaultSendService
import im.vector.matrix.android.internal.session.room.timeline.DefaultTimelineHolder
import im.vector.matrix.android.internal.session.room.timeline.PaginationRequest
import im.vector.matrix.android.internal.session.room.timeline.TimelineBoundaryCallback
import org.koin.core.parameter.parametersOf
import org.koin.dsl.context.ModuleDefinition
import org.koin.dsl.module.Module
import org.koin.dsl.module.module
@ -31,14 +32,16 @@ class RoomModule : Module {
PaginationRequest(get(), get(), get(), get())
}
factory {
val roomId: String = it[0]
TimelineBoundaryCallback(roomId, get(), get(), Executors.newSingleThreadExecutor())
val timelineBoundaryCallback = TimelineBoundaryCallback(roomId, get(), get(), Executors.newSingleThreadExecutor())
DefaultTimelineHolder(roomId, get(), timelineBoundaryCallback) as TimelineHolder
}
factory {
val roomId: String = it[0]
DefaultTimelineHolder(roomId, get(), get(parameters = { parametersOf(roomId) })) as TimelineHolder
DefaultSendService(roomId) as SendService
}
}.invoke()

View File

@ -0,0 +1,45 @@
package im.vector.matrix.android.internal.session.room.send
import androidx.work.BackoffPolicy
import androidx.work.Constraints
import androidx.work.Data
import androidx.work.ExistingWorkPolicy
import androidx.work.NetworkType
import androidx.work.OneTimeWorkRequestBuilder
import androidx.work.WorkManager
import im.vector.matrix.android.api.session.room.SendService
import im.vector.matrix.android.api.util.Cancelable
import im.vector.matrix.android.internal.util.CancelableWork
import java.util.concurrent.TimeUnit
private const val SEND_WORK_NAME = "SEND_WORK_NAME"
internal class DefaultSendService(private val roomId: String) : SendService {
private val sendConstraints = Constraints.Builder()
.setRequiredNetworkType(NetworkType.CONNECTED)
.build()
override fun sendTextMessage(text: String): Cancelable {
val data = mapOf(
"roomId" to roomId,
"text" to text
)
val workData = Data.Builder().putAll(data).build()
val sendWork = OneTimeWorkRequestBuilder<SendContentWorker>()
.setConstraints(sendConstraints)
.setInputData(workData)
.setBackoffCriteria(BackoffPolicy.LINEAR, 10_000, TimeUnit.MILLISECONDS)
.build()
val work = WorkManager.getInstance()
.beginUniqueWork(SEND_WORK_NAME, ExistingWorkPolicy.APPEND, sendWork)
.enqueue()
return CancelableWork(work)
}
}

View File

@ -0,0 +1,37 @@
package im.vector.matrix.android.internal.session.room.send
import android.content.Context
import androidx.work.Worker
import androidx.work.WorkerParameters
import im.vector.matrix.android.api.session.events.model.EventType
import im.vector.matrix.android.api.session.room.model.MessageContent
import im.vector.matrix.android.api.session.room.model.MessageType
import im.vector.matrix.android.internal.network.executeRequest
import im.vector.matrix.android.internal.session.room.RoomAPI
import org.koin.standalone.KoinComponent
import org.koin.standalone.inject
internal class SendContentWorker(context: Context, params: WorkerParameters)
: Worker(context, params), KoinComponent {
private val roomAPI by inject<RoomAPI>()
override fun doWork(): Result {
val roomId = inputData.getString("roomId")
val text = inputData.getString("text")
val fakeId = roomId + "-" + System.currentTimeMillis()
if (roomId == null || text == null) {
return Result.FAILURE
}
val result = executeRequest<SendResponse> {
apiCall = roomAPI.send(fakeId, roomId, EventType.MESSAGE, MessageContent(MessageType.MSGTYPE_TEXT, text))
}
return result.fold({ Result.RETRY }, { Result.SUCCESS })
}
}

View File

@ -0,0 +1,9 @@
package im.vector.matrix.android.internal.session.room.send
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
@JsonClass(generateAdapter = true)
internal data class SendResponse(
@Json(name = "event_id") val eventId: String
)

View File

@ -0,0 +1,13 @@
package im.vector.matrix.android.internal.util
import com.google.common.util.concurrent.ListenableFuture
import im.vector.matrix.android.api.util.Cancelable
import kotlinx.coroutines.Job
internal class CancelableWork(private val work: ListenableFuture<Void>) : Cancelable {
override fun cancel() {
work.cancel(true)
}
}