Send reaction view quick react and picker

+ fix / Error when to many reactions in cells (more than placeholders -8-)
+ fix / DefaultTimeline quick map access was not shifted when items inserted at given index
This commit is contained in:
Valere
2019-05-16 16:35:54 +02:00
parent e27367e3f2
commit ef26519993
18 changed files with 266 additions and 57 deletions

View File

@ -49,4 +49,6 @@ interface SendService {
fun sendMedias(attachments: List<ContentAttachmentData>): Cancelable
fun sendReaction(reaction: String, targetEventId: String) : Cancelable
}

View File

@ -18,6 +18,7 @@ package im.vector.matrix.android.internal.session.room
import im.vector.matrix.android.api.session.events.model.Content
import im.vector.matrix.android.api.session.events.model.Event
import im.vector.matrix.android.api.session.room.model.annotation.ReactionContent
import im.vector.matrix.android.api.session.room.model.create.CreateRoomParams
import im.vector.matrix.android.api.session.room.model.create.CreateRoomResponse
import im.vector.matrix.android.internal.network.NetworkConstants
@ -156,4 +157,20 @@ internal interface RoomAPI {
@Path("state_event_type") stateEventType: String,
@Path("state_key") stateKey: String,
@Body params: Map<String, String>): Call<Unit>
/**
* Send a relation event to a room.
*
* @param txId the transaction Id
* @param roomId the room id
* @param eventType the event type
* @param content the event content
*/
@POST(NetworkConstants.URI_API_PREFIX_PATH_R0 + "rooms/{roomId}/send_relation/{parent_id}/{relation_type}/{event_type}")
fun sendRelation(@Path("roomId") roomId: String,
@Path("parentId") parent_id: String,
@Path("relation_type") relationType: String,
@Path("eventType") eventType: String,
@Body content: Content?
): Call<SendResponse>
}

View File

@ -74,6 +74,18 @@ internal class DefaultSendService(private val roomId: String,
return cancelableBag
}
override fun sendReaction(reaction: String, targetEventId: String) : Cancelable {
val event = eventFactory.createReactionEvent(roomId,targetEventId,reaction).also {
saveLocalEcho(it)
}
val sendRelationWork = createSendRelationWork(event)
WorkManager.getInstance()
.beginUniqueWork(buildWorkIdentifier(SEND_WORK), ExistingWorkPolicy.APPEND, sendRelationWork)
.enqueue()
return CancelableWork(sendRelationWork.id)
}
override fun sendMedia(attachment: ContentAttachmentData): Cancelable {
// Create an event with the media file path
val event = eventFactory.createMediaEvent(roomId, attachment).also {
@ -116,6 +128,19 @@ internal class DefaultSendService(private val roomId: String,
.build()
}
private fun createSendRelationWork(event: Event): OneTimeWorkRequest {
//TODO use the new API to send relation (for now use regular send)
val sendContentWorkerParams = SendEventWorker.Params(
roomId, event)
val sendWorkData = WorkerParamsFactory.toData(sendContentWorkerParams)
return OneTimeWorkRequestBuilder<SendEventWorker>()
.setConstraints(WORK_CONSTRAINTS)
.setInputData(sendWorkData)
.setBackoffCriteria(BackoffPolicy.LINEAR, BACKOFF_DELAY, TimeUnit.MILLISECONDS)
.build()
}
private fun createUploadMediaWork(event: Event, attachment: ContentAttachmentData): OneTimeWorkRequest {
val uploadMediaWorkerParams = UploadContentWorker.Params(roomId, event, attachment)
val uploadWorkData = WorkerParamsFactory.toData(uploadMediaWorkerParams)

View File

@ -21,18 +21,11 @@ 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.RelationType
import im.vector.matrix.android.api.session.events.model.toContent
import im.vector.matrix.android.api.session.room.model.message.AudioInfo
import im.vector.matrix.android.api.session.room.model.message.FileInfo
import im.vector.matrix.android.api.session.room.model.message.ImageInfo
import im.vector.matrix.android.api.session.room.model.message.MessageAudioContent
import im.vector.matrix.android.api.session.room.model.message.MessageFileContent
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.api.session.room.model.message.MessageVideoContent
import im.vector.matrix.android.api.session.room.model.message.ThumbnailInfo
import im.vector.matrix.android.api.session.room.model.message.VideoInfo
import im.vector.matrix.android.api.session.room.model.annotation.ReactionContent
import im.vector.matrix.android.api.session.room.model.annotation.ReactionInfo
import im.vector.matrix.android.api.session.room.model.message.*
import im.vector.matrix.android.internal.session.content.ThumbnailExtractor
internal class LocalEchoEventFactory(private val credentials: Credentials) {
@ -47,10 +40,29 @@ internal class LocalEchoEventFactory(private val credentials: Credentials) {
ContentAttachmentData.Type.IMAGE -> createImageEvent(roomId, attachment)
ContentAttachmentData.Type.VIDEO -> createVideoEvent(roomId, attachment)
ContentAttachmentData.Type.AUDIO -> createAudioEvent(roomId, attachment)
ContentAttachmentData.Type.FILE -> createFileEvent(roomId, attachment)
ContentAttachmentData.Type.FILE -> createFileEvent(roomId, attachment)
}
}
fun createReactionEvent(roomId: String, targetEventId: String, reaction: String): Event {
val content = ReactionContent(
ReactionInfo(
RelationType.ANNOTATION,
targetEventId,
reaction
)
)
return Event(
roomId = roomId,
originServerTs = dummyOriginServerTs(),
sender = credentials.userId,
eventId = dummyEventId(roomId),
type = EventType.REACTION,
content = content.toContent()
)
}
private fun createImageEvent(roomId: String, attachment: ContentAttachmentData): Event {
val content = MessageImageContent(
type = MessageType.MSGTYPE_IMAGE,

View File

@ -0,0 +1,55 @@
package im.vector.matrix.android.internal.session.room.send
import android.content.Context
import androidx.work.Worker
import androidx.work.WorkerParameters
import com.squareup.moshi.JsonClass
import im.vector.matrix.android.api.session.events.model.Event
import im.vector.matrix.android.api.session.events.model.toModel
import im.vector.matrix.android.api.session.room.model.annotation.ReactionContent
import im.vector.matrix.android.api.session.room.model.annotation.ReactionInfo
import im.vector.matrix.android.internal.di.MatrixKoinComponent
import im.vector.matrix.android.internal.network.executeRequest
import im.vector.matrix.android.internal.session.room.RoomAPI
import im.vector.matrix.android.internal.util.WorkerParamsFactory
import org.koin.standalone.inject
class SendRelationWorker(context: Context, params: WorkerParameters)
: Worker(context, params), MatrixKoinComponent {
@JsonClass(generateAdapter = true)
internal data class Params(
val roomId: String,
val event: Event,
val relationType: String? = null
)
private val roomAPI by inject<RoomAPI>()
override fun doWork(): Result {
val params = WorkerParamsFactory.fromData<SendRelationWorker.Params>(inputData)
?: return Result.failure()
val localEvent = params.event
if (localEvent.eventId == null) {
return Result.failure()
}
val relationContent = localEvent.content.toModel<ReactionContent>()
?: return Result.failure()
val relatedEventId = relationContent.relatesTo?.eventId ?: return Result.failure()
val relationType = (relationContent.relatesTo as? ReactionInfo)?.type ?: params.relationType
?: return Result.failure()
val result = executeRequest<SendResponse> {
apiCall = roomAPI.sendRelation(
roomId = params.roomId,
parent_id = relatedEventId,
relationType = relationType,
eventType = localEvent.type,
content = localEvent.content
)
}
return result.fold({ Result.retry() }, { Result.success() })
}
}

View File

@ -419,6 +419,8 @@ internal class DefaultTimeline(
val timelineEvent = timelineEventFactory.create(eventEntity)
val position = if (direction == Timeline.Direction.FORWARDS) 0 else builtEvents.size
builtEvents.add(position, timelineEvent)
//Need to shift :/
builtEventsIdMap.entries.filter { it.value >= position }.forEach { it.setValue(it.value + 1) }
builtEventsIdMap[eventEntity.eventId] = position
}
Timber.v("Built ${offsetResults.size} items from db")