mirror of
https://github.com/SchildiChat/SchildiChat-android.git
synced 2024-12-18 07:11:58 +03:00
Start sending message : introduce WorkManager. WIP - have to clean
This commit is contained in:
parent
b2bb89ac94
commit
f050574728
19 changed files with 207 additions and 11 deletions
Binary file not shown.
|
@ -50,6 +50,13 @@ class RoomDetailFragment : RiotFragment() {
|
|||
room.loadRoomMembersIfNeeded()
|
||||
room.liveTimeline().observe(this, Observer { renderEvents(it) })
|
||||
room.roomSummary.observe(this, Observer { renderRoomSummary(it) })
|
||||
sendButton.setOnClickListener {
|
||||
val textMessage = composerEditText.text.toString()
|
||||
if (textMessage.isNotBlank()) {
|
||||
composerEditText.text = null
|
||||
room.sendTextMessage(textMessage)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupToolbar() {
|
||||
|
|
BIN
app/src/main/res/drawable-hdpi/ic_send_white.png
Normal file
BIN
app/src/main/res/drawable-hdpi/ic_send_white.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 335 B |
BIN
app/src/main/res/drawable-mdpi/ic_send_white.png
Normal file
BIN
app/src/main/res/drawable-mdpi/ic_send_white.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 257 B |
BIN
app/src/main/res/drawable-xhdpi/ic_send_white.png
Normal file
BIN
app/src/main/res/drawable-xhdpi/ic_send_white.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 423 B |
BIN
app/src/main/res/drawable-xxhdpi/ic_send_white.png
Normal file
BIN
app/src/main/res/drawable-xxhdpi/ic_send_white.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 550 B |
BIN
app/src/main/res/drawable-xxxhdpi/ic_send_white.png
Normal file
BIN
app/src/main/res/drawable-xxxhdpi/ic_send_white.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 728 B |
|
@ -73,9 +73,53 @@
|
|||
android:id="@+id/recyclerView"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintBottom_toTopOf="@+id/composerDivider"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/toolbar" />
|
||||
|
||||
<View
|
||||
android:id="@+id/composerDivider"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:background="@color/pale_grey"
|
||||
app:layout_constraintBottom_toTopOf="@+id/composerLayout" />
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/composerLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent">
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/sendButton"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:background="?android:attr/selectableItemBackground"
|
||||
android:src="@drawable/ic_send_white"
|
||||
android:tint="?attr/colorAccent"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_centerVertical="true" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/composerEditText"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_toLeftOf="@id/sendButton"
|
||||
android:background="@android:color/transparent"
|
||||
android:gravity="center_vertical"
|
||||
android:hint="Send a message"
|
||||
android:minHeight="48dp"
|
||||
android:nextFocusLeft="@id/composerEditText"
|
||||
android:nextFocusUp="@id/composerEditText"
|
||||
android:padding="16dp"
|
||||
android:textSize="14sp" />
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
</android.support.constraint.ConstraintLayout>
|
|
@ -75,6 +75,9 @@ dependencies {
|
|||
// Paging
|
||||
implementation "android.arch.paging:runtime:1.0.1"
|
||||
|
||||
// Work
|
||||
implementation "android.arch.work:work-runtime-ktx:1.0.0-alpha10"
|
||||
|
||||
// FP
|
||||
implementation "io.arrow-kt:arrow-core:$arrow_version"
|
||||
implementation "io.arrow-kt:arrow-instances-core:$arrow_version"
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
}
|
|
@ -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)
|
||||
}
|
||||
|
||||
}
|
|
@ -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>
|
||||
|
||||
|
||||
}
|
|
@ -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()
|
||||
|
|
|
@ -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)
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -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 })
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -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
|
||||
)
|
|
@ -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)
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in a new issue