From 0db8e7da430e6b9899be55ab466278a094e82d22 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 5 Aug 2019 14:19:14 +0200 Subject: [PATCH 01/20] Format --- vector/src/main/res/values-v21/theme_dark.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/vector/src/main/res/values-v21/theme_dark.xml b/vector/src/main/res/values-v21/theme_dark.xml index 54e2f589..285a3a2d 100644 --- a/vector/src/main/res/values-v21/theme_dark.xml +++ b/vector/src/main/res/values-v21/theme_dark.xml @@ -8,7 +8,6 @@ true - @transition/image_preview_transition @transition/image_preview_transition From 394b89e76bbc52f430ae59e3f353476a4c93afa3 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 5 Aug 2019 14:30:42 +0200 Subject: [PATCH 02/20] Avoid duplicated code --- .../features/media/ImageContentRenderer.kt | 70 +++++++------------ 1 file changed, 26 insertions(+), 44 deletions(-) diff --git a/vector/src/main/java/im/vector/riotx/features/media/ImageContentRenderer.kt b/vector/src/main/java/im/vector/riotx/features/media/ImageContentRenderer.kt index 4ae9f473..7a7c880c 100644 --- a/vector/src/main/java/im/vector/riotx/features/media/ImageContentRenderer.kt +++ b/vector/src/main/java/im/vector/riotx/features/media/ImageContentRenderer.kt @@ -31,6 +31,7 @@ import im.vector.matrix.android.api.session.content.ContentUrlResolver import im.vector.matrix.android.internal.crypto.attachments.ElementToDecrypt import im.vector.riotx.core.di.ActiveSessionHolder import im.vector.riotx.core.glide.GlideApp +import im.vector.riotx.core.glide.GlideRequest import im.vector.riotx.core.utils.DimensionUtils.dpToPx import kotlinx.android.parcel.Parcelize import timber.log.Timber @@ -67,27 +68,7 @@ class ImageContentRenderer @Inject constructor(private val activeSessionHolder: imageView.layoutParams.height = height imageView.layoutParams.width = width - val glideRequest = if (data.elementToDecrypt != null) { - // Encrypted image - GlideApp - .with(imageView) - .load(data) - } else { - // Clear image - val contentUrlResolver = activeSessionHolder.getActiveSession().contentUrlResolver() - val resolvedUrl = when (mode) { - Mode.FULL_SIZE -> contentUrlResolver.resolveFullSize(data.url) - Mode.THUMBNAIL -> contentUrlResolver.resolveThumbnail(data.url, width, height, ContentUrlResolver.ThumbnailMethod.SCALE) - } - //Fallback to base url - ?: data.url - - GlideApp - .with(imageView) - .load(resolvedUrl) - } - - glideRequest + createGlideRequest(data, mode, imageView, width, height) .dontAnimate() .transform(RoundedCorners(dpToPx(8, imageView.context))) .thumbnail(0.3f) @@ -95,31 +76,11 @@ class ImageContentRenderer @Inject constructor(private val activeSessionHolder: } - fun renderFitTarget(data: Data, mode: Mode, imageView: ImageView, callback :((Boolean) -> Unit)? = null) { + fun renderFitTarget(data: Data, mode: Mode, imageView: ImageView, callback: ((Boolean) -> Unit)? = null) { val (width, height) = processSize(data, mode) - val glideRequest = if (data.elementToDecrypt != null) { - // Encrypted image - GlideApp - .with(imageView) - .load(data) - } else { - // Clear image - val contentUrlResolver = activeSessionHolder.getActiveSession().contentUrlResolver() - val resolvedUrl = when (mode) { - Mode.FULL_SIZE -> contentUrlResolver.resolveFullSize(data.url) - Mode.THUMBNAIL -> contentUrlResolver.resolveThumbnail(data.url, width, height, ContentUrlResolver.ThumbnailMethod.SCALE) - } - //Fallback to base url - ?: data.url - - GlideApp - .with(imageView) - .load(resolvedUrl) - } - - glideRequest - .listener(object: RequestListener { + createGlideRequest(data, mode, imageView, width, height) + .listener(object : RequestListener { override fun onLoadFailed(e: GlideException?, model: Any?, target: Target?, @@ -140,7 +101,28 @@ class ImageContentRenderer @Inject constructor(private val activeSessionHolder: }) .fitCenter() .into(imageView) + } + private fun createGlideRequest(data: Data, mode: Mode, imageView: ImageView, width: Int, height: Int): GlideRequest { + return if (data.elementToDecrypt != null) { + // Encrypted image + GlideApp + .with(imageView) + .load(data) + } else { + // Clear image + val contentUrlResolver = activeSessionHolder.getActiveSession().contentUrlResolver() + val resolvedUrl = when (mode) { + Mode.FULL_SIZE -> contentUrlResolver.resolveFullSize(data.url) + Mode.THUMBNAIL -> contentUrlResolver.resolveThumbnail(data.url, width, height, ContentUrlResolver.ThumbnailMethod.SCALE) + } + //Fallback to base url + ?: data.url + + GlideApp + .with(imageView) + .load(resolvedUrl) + } } fun render(data: Data, imageView: BigImageView) { From dafdc1d3adcfcb449693a18e11137dcb67aafb0b Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 5 Aug 2019 14:47:16 +0200 Subject: [PATCH 03/20] Cleaner API --- .../vector/matrix/android/internal/auth/SessionParamsStore.kt | 2 +- .../matrix/android/internal/auth/db/RealmSessionParamsStore.kt | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/SessionParamsStore.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/SessionParamsStore.kt index e7729d37..9067e818 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/SessionParamsStore.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/SessionParamsStore.kt @@ -27,7 +27,7 @@ internal interface SessionParamsStore { fun getAll(): List - fun save(sessionParams: SessionParams): Try + fun save(sessionParams: SessionParams): Try fun delete(userId: String): Try diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/db/RealmSessionParamsStore.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/db/RealmSessionParamsStore.kt index 1bb27d20..38771c91 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/db/RealmSessionParamsStore.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/db/RealmSessionParamsStore.kt @@ -62,7 +62,7 @@ internal class RealmSessionParamsStore @Inject constructor(private val mapper: S return sessionParams } - override fun save(sessionParams: SessionParams): Try { + override fun save(sessionParams: SessionParams): Try { return Try { val entity = mapper.map(sessionParams) if (entity != null) { @@ -72,7 +72,6 @@ internal class RealmSessionParamsStore @Inject constructor(private val mapper: S } realm.close() } - sessionParams } } From 1462fa0484cfed4fa28af217e119c3b5526c2403 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 5 Aug 2019 15:09:06 +0200 Subject: [PATCH 04/20] Simple code --- .../im/vector/matrix/android/internal/extensions/Try.kt | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/extensions/Try.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/extensions/Try.kt index 18ab0e47..78529404 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/extensions/Try.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/extensions/Try.kt @@ -31,3 +31,11 @@ inline fun TryOf.onError(f: (Throwable) -> Unit): Try = fix() fun Try.foldToCallback(callback: MatrixCallback): Unit = fold( { callback.onFailure(it) }, { callback.onSuccess(it) }) + +/** + * Same as doOnNext for Observables + */ +inline fun Try.alsoDo(f: (A) -> Unit) = map { + f(it) + it +} \ No newline at end of file From c0b94f41115c9cb2b3989f274571d8c361f34019 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 5 Aug 2019 15:33:23 +0200 Subject: [PATCH 05/20] Typo --- .../internal/session/user/accountdata/AccountDataModule.kt | 2 +- .../session/user/accountdata/UpdateUserAccountDataTask.kt | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/user/accountdata/AccountDataModule.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/user/accountdata/AccountDataModule.kt index e4b76ca1..850312d8 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/user/accountdata/AccountDataModule.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/user/accountdata/AccountDataModule.kt @@ -36,6 +36,6 @@ internal abstract class AccountDataModule { } @Binds - abstract fun bindUpdateUserAccountDataTask(updateUserAccountDataTask: DefaultUpdateUserAcountDataTask): UpdateUserAccountDataTask + abstract fun bindUpdateUserAccountDataTask(updateUserAccountDataTask: DefaultUpdateUserAccountDataTask): UpdateUserAccountDataTask } \ No newline at end of file diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/user/accountdata/UpdateUserAccountDataTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/user/accountdata/UpdateUserAccountDataTask.kt index ddbdb973..80fc4cc3 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/user/accountdata/UpdateUserAccountDataTask.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/user/accountdata/UpdateUserAccountDataTask.kt @@ -41,8 +41,8 @@ internal interface UpdateUserAccountDataTask : Task Date: Mon, 5 Aug 2019 16:05:57 +0200 Subject: [PATCH 06/20] More code cleanup/review --- .../java/im/vector/riotx/core/extensions/EditText.kt | 11 ++++------- .../riotx/core/platform/ConfigurationViewModel.kt | 3 ++- .../vector/riotx/core/platform/SimpleTextWatcher.kt | 1 + .../home/createdirect/CreateDirectRoomActivity.kt | 9 ++------- .../home/createdirect/CreateDirectRoomViewModel.kt | 7 +++---- .../features/home/room/detail/RoomDetailFragment.kt | 5 +++-- .../features/home/room/list/RoomListViewModel.kt | 2 +- 7 files changed, 16 insertions(+), 22 deletions(-) diff --git a/vector/src/main/java/im/vector/riotx/core/extensions/EditText.kt b/vector/src/main/java/im/vector/riotx/core/extensions/EditText.kt index ace13754..cf64c9b3 100644 --- a/vector/src/main/java/im/vector/riotx/core/extensions/EditText.kt +++ b/vector/src/main/java/im/vector/riotx/core/extensions/EditText.kt @@ -18,25 +18,22 @@ package im.vector.riotx.core.extensions import android.text.Editable import android.text.InputType -import android.text.TextWatcher import android.view.MotionEvent import android.view.View import android.view.inputmethod.EditorInfo import android.widget.EditText import androidx.annotation.DrawableRes import im.vector.riotx.R +import im.vector.riotx.core.platform.SimpleTextWatcher fun EditText.setupAsSearch(@DrawableRes searchIconRes: Int = R.drawable.ic_filter, @DrawableRes clearIconRes: Int = R.drawable.ic_x_green) { - addTextChangedListener(object : TextWatcher { - override fun afterTextChanged(editable: Editable?) { - val clearIcon = if (editable?.isNotEmpty() == true) clearIconRes else 0 + addTextChangedListener(object : SimpleTextWatcher() { + override fun afterTextChanged(s: Editable) { + val clearIcon = if (s.isNotEmpty()) clearIconRes else 0 setCompoundDrawablesWithIntrinsicBounds(searchIconRes, 0, clearIcon, 0) } - - override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) = Unit - override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) = Unit }) maxLines = 1 diff --git a/vector/src/main/java/im/vector/riotx/core/platform/ConfigurationViewModel.kt b/vector/src/main/java/im/vector/riotx/core/platform/ConfigurationViewModel.kt index bb2db5cb..dae8145f 100644 --- a/vector/src/main/java/im/vector/riotx/core/platform/ConfigurationViewModel.kt +++ b/vector/src/main/java/im/vector/riotx/core/platform/ConfigurationViewModel.kt @@ -19,6 +19,7 @@ package im.vector.riotx.core.platform import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel +import im.vector.riotx.core.extensions.postLiveEvent import im.vector.riotx.core.utils.LiveEvent import im.vector.riotx.features.configuration.VectorConfiguration import timber.log.Timber @@ -46,7 +47,7 @@ class ConfigurationViewModel @Inject constructor( if (newHash != currentConfigurationValue) { Timber.v("Configuration: recreate the Activity") currentConfigurationValue = newHash - _activityRestarter.postValue(LiveEvent(Unit)) + _activityRestarter.postLiveEvent(Unit) } } } diff --git a/vector/src/main/java/im/vector/riotx/core/platform/SimpleTextWatcher.kt b/vector/src/main/java/im/vector/riotx/core/platform/SimpleTextWatcher.kt index e54a6d29..94680556 100644 --- a/vector/src/main/java/im/vector/riotx/core/platform/SimpleTextWatcher.kt +++ b/vector/src/main/java/im/vector/riotx/core/platform/SimpleTextWatcher.kt @@ -19,6 +19,7 @@ package im.vector.riotx.core.platform import android.text.Editable import android.text.TextWatcher + /** * TextWatcher with default no op implementation */ diff --git a/vector/src/main/java/im/vector/riotx/features/home/createdirect/CreateDirectRoomActivity.kt b/vector/src/main/java/im/vector/riotx/features/home/createdirect/CreateDirectRoomActivity.kt index 8c40e569..b18892ac 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/createdirect/CreateDirectRoomActivity.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/createdirect/CreateDirectRoomActivity.kt @@ -24,11 +24,7 @@ import android.os.Bundle import android.view.View import androidx.appcompat.app.AlertDialog import androidx.lifecycle.ViewModelProviders -import com.airbnb.mvrx.Async -import com.airbnb.mvrx.Fail -import com.airbnb.mvrx.Loading -import com.airbnb.mvrx.Success -import com.airbnb.mvrx.viewModel +import com.airbnb.mvrx.* import im.vector.matrix.android.api.session.room.failure.CreateRoomFailure import im.vector.riotx.R import im.vector.riotx.core.di.ScreenComponent @@ -39,7 +35,6 @@ import im.vector.riotx.core.extensions.observeEvent import im.vector.riotx.core.platform.SimpleFragmentActivity import im.vector.riotx.core.platform.WaitingViewData import kotlinx.android.synthetic.main.activity.* -import timber.log.Timber import javax.inject.Inject class CreateDirectRoomActivity : SimpleFragmentActivity() { @@ -98,7 +93,7 @@ class CreateDirectRoomActivity : SimpleFragmentActivity() { } else AlertDialog.Builder(this) .setMessage(errorFormatter.toHumanReadable(error)) - .setPositiveButton(R.string.ok) { dialog, id -> dialog.cancel() } + .setPositiveButton(R.string.ok, null) .show() } diff --git a/vector/src/main/java/im/vector/riotx/features/home/createdirect/CreateDirectRoomViewModel.kt b/vector/src/main/java/im/vector/riotx/features/home/createdirect/CreateDirectRoomViewModel.kt index b0fed9b8..a0d47dc0 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/createdirect/CreateDirectRoomViewModel.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/createdirect/CreateDirectRoomViewModel.kt @@ -21,7 +21,9 @@ package im.vector.riotx.features.home.createdirect import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import arrow.core.Option -import com.airbnb.mvrx.* +import com.airbnb.mvrx.ActivityViewModelContext +import com.airbnb.mvrx.MvRxViewModelFactory +import com.airbnb.mvrx.ViewModelContext import com.jakewharton.rxrelay2.BehaviorRelay import com.squareup.inject.assisted.Assisted import com.squareup.inject.assisted.AssistedInject @@ -33,10 +35,8 @@ import im.vector.matrix.rx.rx import im.vector.riotx.core.extensions.postLiveEvent import im.vector.riotx.core.platform.VectorViewModel import im.vector.riotx.core.utils.LiveEvent -import io.reactivex.Observable import io.reactivex.Single import io.reactivex.android.schedulers.AndroidSchedulers -import io.reactivex.functions.BiFunction import java.util.concurrent.TimeUnit private typealias KnowUsersFilter = String @@ -103,7 +103,6 @@ class CreateDirectRoomViewModel @AssistedInject constructor(@Assisted .execute { copy(createAndInviteState = it) } - .disposeOnClear() } private fun handleRemoveSelectedUser(action: CreateDirectRoomActions.RemoveSelectedUser) = withState { state -> diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailFragment.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailFragment.kt index 5d10ab2c..5df4eef2 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailFragment.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailFragment.kt @@ -300,8 +300,9 @@ class RoomDetailFragment : composerLayout.collapse() } - private fun enterSpecialMode(event: TimelineEvent, @DrawableRes - iconRes: Int, useText: Boolean) { + private fun enterSpecialMode(event: TimelineEvent, + @DrawableRes iconRes: Int, + useText: Boolean) { commandAutocompletePolicy.enabled = false //switch to expanded bar composerLayout.composerRelatedMessageTitle.apply { diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/list/RoomListViewModel.kt b/vector/src/main/java/im/vector/riotx/features/home/room/list/RoomListViewModel.kt index 01675852..0fed679e 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/list/RoomListViewModel.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/list/RoomListViewModel.kt @@ -84,7 +84,7 @@ class RoomListViewModel @AssistedInject constructor(@Assisted initialState: Room // PRIVATE METHODS ***************************************************************************** private fun handleSelectRoom(action: RoomListActions.SelectRoom) { - _openRoomLiveData.postValue(LiveEvent(action.roomSummary.roomId)) + _openRoomLiveData.postLiveEvent(action.roomSummary.roomId) } private fun handleToggleCategory(action: RoomListActions.ToggleCategory) = setState { From 652ac81fa19d545765aeba91f63e02e2d77943cb Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 5 Aug 2019 16:17:38 +0200 Subject: [PATCH 07/20] simple code --- .../android/api/session/events/model/Event.kt | 32 ++++++------------- 1 file changed, 10 insertions(+), 22 deletions(-) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/events/model/Event.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/events/model/Event.kt index 7dd0c6e2..a0a037f0 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/events/model/Event.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/events/model/Event.kt @@ -302,31 +302,19 @@ data class Event( fun Event.isTextMessage(): Boolean { - if (this.getClearType() == EventType.MESSAGE) { - return getClearContent()?.toModel()?.let { - when (it.type) { - MessageType.MSGTYPE_TEXT, - MessageType.MSGTYPE_EMOTE, - MessageType.MSGTYPE_NOTICE -> { - true - } - else -> false - } - } ?: false + return getClearType() == EventType.MESSAGE + && when (getClearContent()?.toModel()?.type) { + MessageType.MSGTYPE_TEXT, + MessageType.MSGTYPE_EMOTE, + MessageType.MSGTYPE_NOTICE -> true + else -> false } - return false } fun Event.isImageMessage(): Boolean { - if (this.getClearType() == EventType.MESSAGE) { - return getClearContent()?.toModel()?.let { - when (it.type) { - MessageType.MSGTYPE_IMAGE -> { - true - } - else -> false - } - } ?: false + return getClearType() == EventType.MESSAGE + && when (getClearContent()?.toModel()?.type) { + MessageType.MSGTYPE_IMAGE -> true + else -> false } - return false } \ No newline at end of file From f910cd6f978a299233ac45c8529667098fe9713d Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 5 Aug 2019 16:23:43 +0200 Subject: [PATCH 08/20] More robust SDK: retry only when on failure --- .../session/room/send/DefaultSendService.kt | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/DefaultSendService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/DefaultSendService.kt index 2d585ad6..3f9d000d 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/DefaultSendService.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/DefaultSendService.kt @@ -22,10 +22,7 @@ import com.zhuinden.monarchy.Monarchy 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.crypto.CryptoService -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.isTextMessage -import im.vector.matrix.android.api.session.events.model.toModel +import im.vector.matrix.android.api.session.events.model.* import im.vector.matrix.android.api.session.room.model.message.MessageContent import im.vector.matrix.android.api.session.room.model.message.MessageType import im.vector.matrix.android.api.session.room.send.SendService @@ -106,7 +103,7 @@ internal class DefaultSendService @Inject constructor(private val context: Conte } override fun resendTextMessage(localEcho: TimelineEvent): Cancelable? { - if (localEcho.root.isTextMessage()) { + if (localEcho.root.isTextMessage() && localEcho.root.sendState.hasFailed()) { return sendEvent(localEcho.root) } return null @@ -114,7 +111,8 @@ internal class DefaultSendService @Inject constructor(private val context: Conte } override fun resendMediaMessage(localEcho: TimelineEvent): Cancelable? { - //TODO this need a refactoring of attachement sending + if (localEcho.root.isImageMessage() && localEcho.root.sendState.hasFailed()) { + //TODO this need a refactoring of attachement sending // val clearContent = localEcho.root.getClearContent() // val messageContent = clearContent?.toModel() ?: return null // when (messageContent.type) { @@ -143,8 +141,9 @@ internal class DefaultSendService @Inject constructor(private val context: Conte // } // } // } + return null + } return null - } override fun deleteFailedEcho(localEcho: TimelineEvent) { From 4deb7eb86598d3a74c11cd618dddb9e0c1929990 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 5 Aug 2019 16:40:18 +0200 Subject: [PATCH 09/20] Javadoc for NoMerger --- .../android/internal/session/room/send/DefaultSendService.kt | 4 ++-- .../matrix/android/internal/session/room/send/NoMerger.kt | 5 ++++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/DefaultSendService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/DefaultSendService.kt index 3f9d000d..b1b2d7a3 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/DefaultSendService.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/DefaultSendService.kt @@ -278,7 +278,7 @@ internal class DefaultSendService @Inject constructor(private val context: Conte return "${roomId}_$identifier" } - private fun createEncryptEventWork(event: Event, startChain: Boolean = false): OneTimeWorkRequest { + private fun createEncryptEventWork(event: Event, startChain: Boolean): OneTimeWorkRequest { // Same parameter val params = EncryptEventWorker.Params(credentials.userId, roomId, event) val sendWorkData = WorkerParamsFactory.toData(params) @@ -314,7 +314,7 @@ internal class DefaultSendService @Inject constructor(private val context: Conte private fun createUploadMediaWork(event: Event, attachment: ContentAttachmentData, isRoomEncrypted: Boolean, - startChain: Boolean = false): OneTimeWorkRequest { + startChain: Boolean): OneTimeWorkRequest { val uploadMediaWorkerParams = UploadContentWorker.Params(credentials.userId, roomId, event, attachment, isRoomEncrypted) val uploadWorkData = WorkerParamsFactory.toData(uploadMediaWorkerParams) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/NoMerger.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/NoMerger.kt index 6938bc22..77198857 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/NoMerger.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/NoMerger.kt @@ -18,7 +18,10 @@ package im.vector.matrix.android.internal.session.room.send import androidx.work.Data import androidx.work.InputMerger -class NoMerger : InputMerger() { +/** + * InputMerger which takes only the first input, to ensure an appended work with only have the specified parameters + */ +internal class NoMerger : InputMerger() { override fun merge(inputs: MutableList): Data { return inputs.first() } From acae0fad3ec8dee042b7a600b4b5b38491d13c5b Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 5 Aug 2019 16:50:25 +0200 Subject: [PATCH 10/20] Better private method name --- .../session/room/send/DefaultSendService.kt | 15 ++++++++------- .../room/timeline/TimelineSendEventWorkCommon.kt | 8 ++++---- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/DefaultSendService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/DefaultSendService.kt index b1b2d7a3..1d8eaf3f 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/DefaultSendService.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/DefaultSendService.kt @@ -161,15 +161,16 @@ internal class DefaultSendService @Inject constructor(private val context: Conte override fun clearSendingQueue() { TimelineSendEventWorkCommon.cancelAllWorks(context, roomId) - WorkManager.getInstance(context).cancelUniqueWork(buildWorkIdentifier(UPLOAD_WORK)) + WorkManager.getInstance(context).cancelUniqueWork(buildWorkName(UPLOAD_WORK)) + // TODO Valere: what is the aim of this code ? Cancellation above is not enough? matrixOneTimeWorkRequestBuilder() .build().let { TimelineSendEventWorkCommon.postWork(context, roomId, it, ExistingWorkPolicy.REPLACE) //need to clear also image sending queue WorkManager.getInstance(context) - .beginUniqueWork(buildWorkIdentifier(UPLOAD_WORK), ExistingWorkPolicy.REPLACE, it) + .beginUniqueWork(buildWorkName(UPLOAD_WORK), ExistingWorkPolicy.REPLACE, it) .enqueue() } @@ -249,20 +250,20 @@ internal class DefaultSendService @Inject constructor(private val context: Conte val encryptWork = createEncryptEventWork(localEcho, false /*not start of chain, take input error*/) val op: Operation = WorkManager.getInstance(context) - .beginUniqueWork(buildWorkIdentifier(UPLOAD_WORK), ExistingWorkPolicy.APPEND, uploadWork) + .beginUniqueWork(buildWorkName(UPLOAD_WORK), ExistingWorkPolicy.APPEND, uploadWork) .then(encryptWork) .then(sendWork) .enqueue() op.result.addListener(Runnable { if (op.result.isCancelled) { - Timber.e("CHAINE WAS CANCELLED") + Timber.e("CHAIN WAS CANCELLED") } else if (op.state.value is Operation.State.FAILURE) { - Timber.e("CHAINE DID FAIL") + Timber.e("CHAIN DID FAIL") } }, workerFutureListenerExecutor) } else { WorkManager.getInstance(context) - .beginUniqueWork(buildWorkIdentifier(UPLOAD_WORK), ExistingWorkPolicy.APPEND, uploadWork) + .beginUniqueWork(buildWorkName(UPLOAD_WORK), ExistingWorkPolicy.APPEND, uploadWork) .then(sendWork) .enqueue() } @@ -274,7 +275,7 @@ internal class DefaultSendService @Inject constructor(private val context: Conte localEchoEventFactory.saveLocalEcho(monarchy, event) } - private fun buildWorkIdentifier(identifier: String): String { + private fun buildWorkName(identifier: String): String { return "${roomId}_$identifier" } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/TimelineSendEventWorkCommon.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/TimelineSendEventWorkCommon.kt index e75bb91b..2a72d3ff 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/TimelineSendEventWorkCommon.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/TimelineSendEventWorkCommon.kt @@ -41,7 +41,7 @@ internal object TimelineSendEventWorkCommon { else -> { val firstWork = workRequests.first() var continuation = WorkManager.getInstance(context) - .beginUniqueWork(buildWorkIdentifier(roomId), ExistingWorkPolicy.APPEND, firstWork) + .beginUniqueWork(buildWorkName(roomId), ExistingWorkPolicy.APPEND, firstWork) for (i in 1 until workRequests.size) { val workRequest = workRequests[i] continuation = continuation.then(workRequest) @@ -53,7 +53,7 @@ internal object TimelineSendEventWorkCommon { fun postWork(context: Context, roomId: String, workRequest: OneTimeWorkRequest, policy: ExistingWorkPolicy = ExistingWorkPolicy.APPEND) { WorkManager.getInstance(context) - .beginUniqueWork(buildWorkIdentifier(roomId), policy, workRequest) + .beginUniqueWork(buildWorkName(roomId), policy, workRequest) .enqueue() } @@ -65,11 +65,11 @@ internal object TimelineSendEventWorkCommon { .build() } - private fun buildWorkIdentifier(roomId: String): String { + private fun buildWorkName(roomId: String): String { return "${roomId}_$SEND_WORK" } fun cancelAllWorks(context: Context, roomId: String) { - WorkManager.getInstance(context).cancelUniqueWork(buildWorkIdentifier(roomId)) + WorkManager.getInstance(context).cancelUniqueWork(buildWorkName(roomId)) } } \ No newline at end of file From 097e9714ff8633e7e4b3d47591a085483e1a7918 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 5 Aug 2019 17:03:19 +0200 Subject: [PATCH 11/20] Cleaner code --- .../timeline/action/MessageMenuViewModel.kt | 27 +++++++------------ 1 file changed, 10 insertions(+), 17 deletions(-) diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/action/MessageMenuViewModel.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/action/MessageMenuViewModel.kt index 15e08831..fcf00173 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/action/MessageMenuViewModel.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/action/MessageMenuViewModel.kt @@ -99,39 +99,32 @@ class MessageMenuViewModel @AssistedInject constructor(@Assisted initialState: M private fun observeEvent() { RxRoom(room) .liveTimelineEvent(eventId) - ?.map { + .map { actionsForEvent(it) } - ?.execute { + .execute { copy(actions = it) } } private fun actionsForEvent(event: TimelineEvent): List { - val messageContent: MessageContent? = event.annotations?.editSummary?.aggregatedContent.toModel() ?: event.root.getClearContent().toModel() val type = messageContent?.type - return if (event.root.sendState.hasFailed()) { - arrayListOf().apply { + return arrayListOf().apply { + if (event.root.sendState.hasFailed()) { if (canRetry(event)) { - this.add(SimpleAction(ACTION_RESEND, R.string.global_retry, R.drawable.ic_refresh_cw, eventId)) + add(SimpleAction(ACTION_RESEND, R.string.global_retry, R.drawable.ic_refresh_cw, eventId)) } - this.add(SimpleAction(ACTION_REMOVE, R.string.remove, R.drawable.ic_trash, eventId)) - } - } else if (event.root.sendState.isSending()) { - //TODO is uploading attachment? - arrayListOf().apply { + add(SimpleAction(ACTION_REMOVE, R.string.remove, R.drawable.ic_trash, eventId)) + } else if (event.root.sendState.isSending()) { + //TODO is uploading attachment? if (canCancel(event)) { - this.add(SimpleAction(ACTION_CANCEL, R.string.cancel, R.drawable.ic_close_round, eventId)) + add(SimpleAction(ACTION_CANCEL, R.string.cancel, R.drawable.ic_close_round, eventId)) } - } - } else { - arrayListOf().apply { - + } else { if (!event.root.isRedacted()) { - if (canReply(event, messageContent)) { add(SimpleAction(ACTION_REPLY, R.string.reply, R.drawable.ic_reply, eventId)) } From f2a3bdb68ee5aa711446120f341a4a0d3e27a4e0 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 5 Aug 2019 17:35:26 +0200 Subject: [PATCH 12/20] Kotlin style --- .../home/room/detail/RoomDetailFragment.kt | 129 +++++++++--------- .../detail/timeline/action/ActionsHandler.kt | 12 +- .../action/MessageActionsBottomSheet.kt | 4 +- .../timeline/action/MessageMenuViewModel.kt | 73 +++++----- 4 files changed, 103 insertions(+), 115 deletions(-) diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailFragment.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailFragment.kt index 5df4eef2..a277f9a5 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailFragment.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailFragment.kt @@ -821,106 +821,101 @@ class RoomDetailFragment : textComposerViewModel.process(TextComposerActions.QueryUsers(query)) } - private fun handleActions(actionData: ActionsHandler.ActionData) { - when (actionData.actionId) { - MessageMenuViewModel.ACTION_ADD_REACTION -> { - val eventId = actionData.data?.toString() ?: return - startActivityForResult(EmojiReactionPickerActivity.intent(requireContext(), eventId), REACTION_SELECT_REQUEST_CODE) + private fun handleActions(action: SimpleAction) { + when (action) { + is SimpleAction.AddReaction -> { + startActivityForResult(EmojiReactionPickerActivity.intent(requireContext(), action.eventId), REACTION_SELECT_REQUEST_CODE) } - MessageMenuViewModel.ACTION_VIEW_REACTIONS -> { - val messageInformationData = actionData.data as? MessageInformationData - ?: return - ViewReactionBottomSheet.newInstance(roomDetailArgs.roomId, messageInformationData) + is SimpleAction.ViewReactions -> { + ViewReactionBottomSheet.newInstance(roomDetailArgs.roomId, action.messageInformationData) .show(requireActivity().supportFragmentManager, "DISPLAY_REACTIONS") } - MessageMenuViewModel.ACTION_COPY -> { + is SimpleAction.Copy -> { //I need info about the current selected message :/ - copyToClipboard(requireContext(), actionData.data?.toString() ?: "", false) + copyToClipboard(requireContext(), action.content, false) val msg = requireContext().getString(R.string.copied_to_clipboard) showSnackWithMessage(msg, Snackbar.LENGTH_SHORT) } - MessageMenuViewModel.ACTION_DELETE -> { - val eventId = actionData.data?.toString() ?: return - roomDetailViewModel.process(RoomDetailActions.RedactAction(eventId, context?.getString(R.string.event_redacted_by_user_reason))) + is SimpleAction.Delete -> { + roomDetailViewModel.process(RoomDetailActions.RedactAction(action.eventId, context?.getString(R.string.event_redacted_by_user_reason))) } - MessageMenuViewModel.ACTION_SHARE -> { + is SimpleAction.Share -> { //TODO current data communication is too limited //Need to now the media type - actionData.data?.toString()?.let { - //TODO bad, just POC - BigImageViewer.imageLoader().loadImage( - actionData.hashCode(), - Uri.parse(it), - object : ImageLoader.Callback { - override fun onFinish() {} - - override fun onSuccess(image: File?) { - if (image != null) - shareMedia(requireContext(), image, "image/*") - } - - override fun onFail(error: Exception?) {} - - override fun onCacheHit(imageType: Int, image: File?) {} - - override fun onCacheMiss(imageType: Int, image: File?) {} - - override fun onProgress(progress: Int) {} - - override fun onStart() {} + //TODO bad, just POC + BigImageViewer.imageLoader().loadImage( + action.hashCode(), + Uri.parse(action.imageUrl), + object : ImageLoader.Callback { + override fun onFinish() {} + override fun onSuccess(image: File?) { + if (image != null) + shareMedia(requireContext(), image, "image/*") } - ) - } + override fun onFail(error: Exception?) {} + + override fun onCacheHit(imageType: Int, image: File?) {} + + override fun onCacheMiss(imageType: Int, image: File?) {} + + override fun onProgress(progress: Int) {} + + override fun onStart() {} + + } + ) } - MessageMenuViewModel.VIEW_SOURCE, - MessageMenuViewModel.VIEW_DECRYPTED_SOURCE -> { + is SimpleAction.ViewSource -> { val view = LayoutInflater.from(requireContext()).inflate(R.layout.dialog_event_content, null) view.findViewById(R.id.event_content_text_view)?.let { - it.text = actionData.data?.toString() ?: "" + it.text = action.content } AlertDialog.Builder(requireActivity()) .setView(view) - .setPositiveButton(R.string.ok) { dialog, id -> dialog.cancel() } + .setPositiveButton(R.string.ok, null) .show() } - MessageMenuViewModel.ACTION_QUICK_REACT -> { - //eventId,ClickedOn,Add - (actionData.data as? Triple)?.let { (eventId, clickedOn, add) -> - roomDetailViewModel.process(RoomDetailActions.UpdateQuickReactAction(eventId, clickedOn, add)) + is SimpleAction.ViewDecryptedSource -> { + val view = LayoutInflater.from(requireContext()).inflate(R.layout.dialog_event_content, null) + view.findViewById(R.id.event_content_text_view)?.let { + it.text = action.content } + + AlertDialog.Builder(requireActivity()) + .setView(view) + .setPositiveButton(R.string.ok, null) + .show() } - MessageMenuViewModel.ACTION_EDIT -> { - val eventId = actionData.data.toString() - roomDetailViewModel.process(RoomDetailActions.EnterEditMode(eventId)) + is SimpleAction.QuickReact -> { + //eventId,ClickedOn,Add + roomDetailViewModel.process(RoomDetailActions.UpdateQuickReactAction(action.eventId, action.clickedOn, action.add)) } - MessageMenuViewModel.ACTION_QUOTE -> { - val eventId = actionData.data.toString() - roomDetailViewModel.process(RoomDetailActions.EnterQuoteMode(eventId)) + is SimpleAction.Edit -> { + roomDetailViewModel.process(RoomDetailActions.EnterEditMode(action.eventId)) } - MessageMenuViewModel.ACTION_REPLY -> { - val eventId = actionData.data.toString() - roomDetailViewModel.process(RoomDetailActions.EnterReplyMode(eventId)) + is SimpleAction.Quote -> { + roomDetailViewModel.process(RoomDetailActions.EnterQuoteMode(action.eventId)) } - MessageMenuViewModel.ACTION_COPY_PERMALINK -> { - val eventId = actionData.data.toString() - val permalink = PermalinkFactory.createPermalink(roomDetailArgs.roomId, eventId) + is SimpleAction.Reply -> { + roomDetailViewModel.process(RoomDetailActions.EnterReplyMode(action.eventId)) + } + is SimpleAction.CopyPermalink -> { + val permalink = PermalinkFactory.createPermalink(roomDetailArgs.roomId, action.eventId) copyToClipboard(requireContext(), permalink, false) showSnackWithMessage(requireContext().getString(R.string.copied_to_clipboard), Snackbar.LENGTH_SHORT) } - MessageMenuViewModel.ACTION_RESEND -> { - val eventId = actionData.data.toString() - roomDetailViewModel.process(RoomDetailActions.ResendMessage(eventId)) + is SimpleAction.Resend -> { + roomDetailViewModel.process(RoomDetailActions.ResendMessage(action.eventId)) } - MessageMenuViewModel.ACTION_REMOVE -> { - val eventId = actionData.data.toString() - roomDetailViewModel.process(RoomDetailActions.RemoveFailedEcho(eventId)) + is SimpleAction.Remove -> { + roomDetailViewModel.process(RoomDetailActions.RemoveFailedEcho(action.eventId)) } - else -> { - Toast.makeText(context, "Action ${actionData.actionId} not implemented", Toast.LENGTH_LONG).show() + else -> { + Toast.makeText(context, "Action $action is not implemented yet", Toast.LENGTH_LONG).show() } } } diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/action/ActionsHandler.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/action/ActionsHandler.kt index 6ad47bfe..ddc8a543 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/action/ActionsHandler.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/action/ActionsHandler.kt @@ -17,6 +17,7 @@ package im.vector.riotx.features.home.room.detail.timeline.action import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel +import im.vector.riotx.core.extensions.postLiveEvent import im.vector.riotx.core.utils.LiveEvent import javax.inject.Inject @@ -25,15 +26,10 @@ import javax.inject.Inject */ class ActionsHandler @Inject constructor() : ViewModel() { - data class ActionData( - val actionId: String, - val data: Any? - ) + val actionCommandEvent = MutableLiveData>() - val actionCommandEvent = MutableLiveData>() - - fun fireAction(actionId: String, data: Any? = null) { - actionCommandEvent.value = LiveEvent(ActionData(actionId,data)) + fun fireAction(action: SimpleAction) { + actionCommandEvent.postLiveEvent(action) } } \ No newline at end of file diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/action/MessageActionsBottomSheet.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/action/MessageActionsBottomSheet.kt index f3bec83a..a80a3454 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/action/MessageActionsBottomSheet.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/action/MessageActionsBottomSheet.kt @@ -89,7 +89,7 @@ class MessageActionsBottomSheet : VectorBaseBottomSheetDialogFragment() { } menuActionFragment.interactionListener = object : MessageMenuFragment.InteractionListener { override fun didSelectMenuAction(simpleAction: SimpleAction) { - actionHandlerModel.fireAction(simpleAction.uid, simpleAction.data) + actionHandlerModel.fireAction(simpleAction) dismiss() } } @@ -105,7 +105,7 @@ class MessageActionsBottomSheet : VectorBaseBottomSheetDialogFragment() { quickReactionFragment.interactionListener = object : QuickReactionFragment.InteractionListener { override fun didQuickReactWith(clickedOn: String, add: Boolean, eventId: String) { - actionHandlerModel.fireAction(MessageMenuViewModel.ACTION_QUICK_REACT, Triple(eventId, clickedOn, add)) + actionHandlerModel.fireAction(SimpleAction.QuickReact(eventId, clickedOn, add)) dismiss() } } diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/action/MessageMenuViewModel.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/action/MessageMenuViewModel.kt index fcf00173..4a8661d8 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/action/MessageMenuViewModel.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/action/MessageMenuViewModel.kt @@ -15,6 +15,8 @@ */ package im.vector.riotx.features.home.room.detail.timeline.action +import androidx.annotation.DrawableRes +import androidx.annotation.StringRes import com.airbnb.mvrx.* import com.squareup.inject.assisted.Assisted import com.squareup.inject.assisted.AssistedInject @@ -36,7 +38,24 @@ import im.vector.riotx.core.utils.isSingleEmoji import im.vector.riotx.features.home.room.detail.timeline.item.MessageInformationData -data class SimpleAction(val uid: String, val titleRes: Int, val iconResId: Int?, val data: Any? = null) +sealed class SimpleAction(@StringRes val titleRes: Int, @DrawableRes val iconResId: Int) { + data class AddReaction(val eventId: String) : SimpleAction(R.string.message_add_reaction, R.drawable.ic_add_reaction) + data class Copy(val content: String) : SimpleAction(R.string.copy, R.drawable.ic_copy) + data class Edit(val eventId: String) : SimpleAction(R.string.edit, R.drawable.ic_edit) + data class Quote(val eventId: String) : SimpleAction(R.string.quote, R.drawable.ic_quote) + data class Reply(val eventId: String) : SimpleAction(R.string.reply, R.drawable.ic_reply) + data class Share(val imageUrl: String?) : SimpleAction(R.string.share, R.drawable.ic_share) + data class Resend(val eventId: String) : SimpleAction(R.string.global_retry, R.drawable.ic_refresh_cw) + data class Remove(val eventId: String) : SimpleAction(R.string.remove, R.drawable.ic_trash) + data class Delete(val eventId: String) : SimpleAction(R.string.delete, R.drawable.ic_delete) + data class Cancel(val eventId: String) : SimpleAction(R.string.cancel, R.drawable.ic_close_round) + data class ViewSource(val content: String) : SimpleAction(R.string.view_source, R.drawable.ic_view_source) + data class ViewDecryptedSource(val content: String) : SimpleAction(R.string.view_decrypted_source, R.drawable.ic_view_source) + data class CopyPermalink(val eventId: String) : SimpleAction(R.string.permalink, R.drawable.ic_permalink) + data class Flag(val eventId: String) : SimpleAction(R.string.report_content, R.drawable.ic_flag) + data class QuickReact(val eventId: String, val clickedOn: String, val add: Boolean) : SimpleAction(0, 0) + data class ViewReactions(val messageInformationData: MessageInformationData) : SimpleAction(R.string.message_view_reaction, R.drawable.ic_view_reactions) +} data class MessageMenuState( val roomId: String, @@ -68,24 +87,6 @@ class MessageMenuViewModel @AssistedInject constructor(@Assisted initialState: M private val informationData: MessageInformationData = initialState.informationData companion object : MvRxViewModelFactory { - - const val ACTION_ADD_REACTION = "add_reaction" - const val ACTION_COPY = "copy" - const val ACTION_EDIT = "edit" - const val ACTION_QUOTE = "quote" - const val ACTION_REPLY = "reply" - const val ACTION_SHARE = "share" - const val ACTION_RESEND = "resend" - const val ACTION_REMOVE = "remove" - const val ACTION_DELETE = "delete" - const val ACTION_CANCEL = "cancel" - const val VIEW_SOURCE = "VIEW_SOURCE" - const val VIEW_DECRYPTED_SOURCE = "VIEW_DECRYPTED_SOURCE" - const val ACTION_COPY_PERMALINK = "ACTION_COPY_PERMALINK" - const val ACTION_FLAG = "ACTION_FLAG" - const val ACTION_QUICK_REACT = "ACTION_QUICK_REACT" - const val ACTION_VIEW_REACTIONS = "ACTION_VIEW_REACTIONS" - override fun create(viewModelContext: ViewModelContext, state: MessageMenuState): MessageMenuViewModel? { val fragment: MessageMenuFragment = (viewModelContext as FragmentViewModelContext).fragment() return fragment.messageMenuViewModelFactory.create(state) @@ -115,52 +116,48 @@ class MessageMenuViewModel @AssistedInject constructor(@Assisted initialState: M return arrayListOf().apply { if (event.root.sendState.hasFailed()) { if (canRetry(event)) { - add(SimpleAction(ACTION_RESEND, R.string.global_retry, R.drawable.ic_refresh_cw, eventId)) + add(SimpleAction.Resend(eventId)) } - add(SimpleAction(ACTION_REMOVE, R.string.remove, R.drawable.ic_trash, eventId)) + add(SimpleAction.Remove(eventId)) } else if (event.root.sendState.isSending()) { //TODO is uploading attachment? if (canCancel(event)) { - add(SimpleAction(ACTION_CANCEL, R.string.cancel, R.drawable.ic_close_round, eventId)) + add(SimpleAction.Cancel(eventId)) } } else { if (!event.root.isRedacted()) { if (canReply(event, messageContent)) { - add(SimpleAction(ACTION_REPLY, R.string.reply, R.drawable.ic_reply, eventId)) + add(SimpleAction.Reply(eventId)) } if (canEdit(event, session.myUserId)) { - add(SimpleAction(ACTION_EDIT, R.string.edit, R.drawable.ic_edit, eventId)) + add(SimpleAction.Edit(eventId)) } if (canRedact(event, session.myUserId)) { - add(SimpleAction(ACTION_DELETE, R.string.delete, R.drawable.ic_delete, eventId)) + add(SimpleAction.Delete(eventId)) } if (canCopy(type)) { //TODO copy images? html? see ClipBoard - add(SimpleAction(ACTION_COPY, R.string.copy, R.drawable.ic_copy, messageContent!!.body)) + add(SimpleAction.Copy(messageContent!!.body)) } if (event.canReact()) { - add(SimpleAction(ACTION_ADD_REACTION, R.string.message_add_reaction, R.drawable.ic_add_reaction, eventId)) + add(SimpleAction.AddReaction(eventId)) } if (canQuote(event, messageContent)) { - add(SimpleAction(ACTION_QUOTE, R.string.quote, R.drawable.ic_quote, eventId)) + add(SimpleAction.Quote(eventId)) } if (canViewReactions(event)) { - add(SimpleAction(ACTION_VIEW_REACTIONS, R.string.message_view_reaction, R.drawable.ic_view_reactions, informationData)) + add(SimpleAction.ViewReactions(informationData)) } if (canShare(type)) { if (messageContent is MessageImageContent) { - add( - SimpleAction(ACTION_SHARE, - R.string.share, R.drawable.ic_share, - session.contentUrlResolver().resolveFullSize(messageContent.url)) - ) + add(SimpleAction.Share(session.contentUrlResolver().resolveFullSize(messageContent.url))) } //TODO } @@ -174,17 +171,17 @@ class MessageMenuViewModel @AssistedInject constructor(@Assisted initialState: M } } - add(SimpleAction(VIEW_SOURCE, R.string.view_source, R.drawable.ic_view_source, event.root.toContentStringWithIndent())) + add(SimpleAction.ViewSource(event.root.toContentStringWithIndent())) if (event.isEncrypted()) { val decryptedContent = event.root.toClearContentStringWithIndent() ?: stringProvider.getString(R.string.encryption_information_decryption_error) - add(SimpleAction(VIEW_DECRYPTED_SOURCE, R.string.view_decrypted_source, R.drawable.ic_view_source, decryptedContent)) + add(SimpleAction.ViewDecryptedSource(decryptedContent)) } - add(SimpleAction(ACTION_COPY_PERMALINK, R.string.permalink, R.drawable.ic_permalink, event.root.eventId)) + add(SimpleAction.CopyPermalink(eventId)) if (session.myUserId != event.root.senderId && event.root.getClearType() == EventType.MESSAGE) { //not sent by me - add(SimpleAction(ACTION_FLAG, R.string.report_content, R.drawable.ic_flag, event.root.eventId)) + add(SimpleAction.Flag(eventId)) } } } From 2f94fbd7eb14d5bcf82376bbfcd3a317544f6654 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 5 Aug 2019 17:37:52 +0200 Subject: [PATCH 13/20] Use existing method --- .../room/detail/timeline/action/MessageMenuViewModel.kt | 8 ++------ .../home/room/detail/timeline/item/AbsMessageItem.kt | 6 +----- 2 files changed, 3 insertions(+), 11 deletions(-) diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/action/MessageMenuViewModel.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/action/MessageMenuViewModel.kt index 4a8661d8..0cc95af7 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/action/MessageMenuViewModel.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/action/MessageMenuViewModel.kt @@ -259,9 +259,7 @@ class MessageMenuViewModel @AssistedInject constructor(@Assisted initialState: M MessageType.MSGTYPE_NOTICE, MessageType.MSGTYPE_EMOTE, MessageType.FORMAT_MATRIX_HTML, - MessageType.MSGTYPE_LOCATION -> { - true - } + MessageType.MSGTYPE_LOCATION -> true else -> false } } @@ -271,9 +269,7 @@ class MessageMenuViewModel @AssistedInject constructor(@Assisted initialState: M return when (type) { MessageType.MSGTYPE_IMAGE, MessageType.MSGTYPE_AUDIO, - MessageType.MSGTYPE_VIDEO -> { - true - } + MessageType.MSGTYPE_VIDEO -> true else -> false } } diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/item/AbsMessageItem.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/item/AbsMessageItem.kt index fad25870..670cf471 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/item/AbsMessageItem.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/item/AbsMessageItem.kt @@ -166,11 +166,7 @@ abstract class AbsMessageItem : BaseEventItem() { root.isClickable = informationData.sendState.isSent() val state = if (informationData.hasPendingEdits) SendState.UNSENT else informationData.sendState textView?.setTextColor(colorProvider.getMessageTextColor(state)) - failureIndicator?.isVisible = when (informationData.sendState) { - SendState.UNDELIVERED, - SendState.FAILED_UNKNOWN_DEVICES -> true - else -> false - } + failureIndicator?.isVisible = informationData.sendState.hasFailed() } abstract class Holder(@IdRes stubId: Int) : BaseHolder(stubId) { From bb04af1e2c1d918409ede6662b1b641dc63268db Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 5 Aug 2019 17:43:49 +0200 Subject: [PATCH 14/20] Remove useless code --- .../home/room/detail/timeline/item/MessageImageVideoItem.kt | 4 ---- 1 file changed, 4 deletions(-) diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/item/MessageImageVideoItem.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/item/MessageImageVideoItem.kt index 9ed9103c..6f713b17 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/item/MessageImageVideoItem.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/item/MessageImageVideoItem.kt @@ -53,10 +53,6 @@ abstract class MessageImageVideoItem : AbsMessageItem Date: Mon, 5 Aug 2019 17:59:33 +0200 Subject: [PATCH 15/20] Search firstIndexOf, because server url can contains port (This is what JS does, but Riot Android is also bugged) --- .../main/java/im/vector/matrix/android/api/MatrixPatterns.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/MatrixPatterns.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/MatrixPatterns.kt index 48e50eca..93540829 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/MatrixPatterns.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/MatrixPatterns.kt @@ -149,7 +149,7 @@ object MatrixPatterns { return null } - val index = matrixId.lastIndexOf(":") + val index = matrixId.indexOf(":") return if (index == -1) { null From 7b5dff3dcf0cfadf55df5e7e73d5045ff9256639 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 5 Aug 2019 18:30:31 +0200 Subject: [PATCH 16/20] Mutualize :? part --- .../main/java/im/vector/riotx/core/error/ErrorFormatter.kt | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/vector/src/main/java/im/vector/riotx/core/error/ErrorFormatter.kt b/vector/src/main/java/im/vector/riotx/core/error/ErrorFormatter.kt index 9d478f34..d42bce64 100644 --- a/vector/src/main/java/im/vector/riotx/core/error/ErrorFormatter.kt +++ b/vector/src/main/java/im/vector/riotx/core/error/ErrorFormatter.kt @@ -31,15 +31,14 @@ class ErrorFormatter @Inject constructor(val stringProvider: StringProvider) { fun toHumanReadable(throwable: Throwable?): String { return when (throwable) { - null -> "" + null -> null is Failure.NetworkConnection -> stringProvider.getString(R.string.error_no_network) is Failure.ServerError -> { throwable.error.message.takeIf { it.isNotEmpty() } - ?: throwable.error.code.takeIf { it.isNotEmpty() } - ?: stringProvider.getString(R.string.unknown_error) + ?: throwable.error.code.takeIf { it.isNotEmpty() } } else -> throwable.localizedMessage - ?: stringProvider.getString(R.string.unknown_error) } + ?: stringProvider.getString(R.string.unknown_error) } } \ No newline at end of file From 15c4b03340102c572c9e228bddde0cbd4f226154 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 5 Aug 2019 19:00:50 +0200 Subject: [PATCH 17/20] Event: do not display sendState in View Source and cleanup the class --- .../android/api/session/events/model/Event.kt | 119 ++---------------- 1 file changed, 8 insertions(+), 111 deletions(-) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/events/model/Event.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/events/model/Event.kt index a0a037f0..902515a2 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/events/model/Event.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/events/model/Event.kt @@ -82,8 +82,13 @@ data class Event( ) { + @Transient var mxDecryptionResult: OlmDecryptionResult? = null + + @Transient var mCryptoError: MXCryptoError.ErrorType? = null + + @Transient var sendState: SendState = SendState.UNKNOWN @@ -99,42 +104,6 @@ data class Event( // Crypto //============================================================================================================== -// /** -// * For encrypted events, the plaintext payload for the event. -// * This is a small MXEvent instance with typically value for `type` and 'content' fields. -// */ -// @Transient -// var mClearEvent: Event? = null -// private set -// -// /** -// * Curve25519 key which we believe belongs to the sender of the event. -// * See `senderKey` property. -// */ -// @Transient -// private var mSenderCurve25519Key: String? = null -// -// /** -// * Ed25519 key which the sender of this event (for olm) or the creator of the megolm session (for megolm) claims to own. -// * See `claimedEd25519Key` property. -// */ -// @Transient -// private var mClaimedEd25519Key: String? = null -// -// /** -// * Curve25519 keys of devices involved in telling us about the senderCurve25519Key and claimedEd25519Key. -// * See `forwardingCurve25519KeyChain` property. -// */ -// @Transient -// private var mForwardingCurve25519KeyChain: List = ArrayList() -// -// /** -// * Decryption error -// */ -// @Transient -// var mCryptoError: MXCryptoError? = null -// private set - /** * @return true if this event is encrypted. */ @@ -142,51 +111,11 @@ data class Event( return TextUtils.equals(type, EventType.ENCRYPTED) } - /** - * Update the clear data on this event. - * This is used after decrypting an event; it should not be used by applications. - * - * @param decryptionResult the decryption result, including the plaintext and some key info. - */ -// internal fun setClearData(decryptionResult: MXEventDecryptionResult?) { -// mClearEvent = null -// if (decryptionResult != null) { -// if (decryptionResult.clearEvent != null) { -// val adapter = MoshiProvider.providesMoshi().adapter(Event::class.java) -// mClearEvent = adapter.fromJsonValue(decryptionResult.clearEvent) -// -// if (mClearEvent != null) { -// mSenderCurve25519Key = decryptionResult.senderCurve25519Key -// mClaimedEd25519Key = decryptionResult.claimedEd25519Key -// mForwardingCurve25519KeyChain = decryptionResult.forwardingCurve25519KeyChain -// -// // For encrypted events with relation, the m.relates_to is kept in clear, so we need to put it back -// // in the clear event -// try { -// content?.get("m.relates_to")?.let { clearRelates -> -// mClearEvent = mClearEvent?.copy( -// content = HashMap(mClearEvent!!.content).apply { -// this["m.relates_to"] = clearRelates -// } -// ) -// } -// } catch (e: Exception) { -// Timber.e(e, "Unable to restore 'm.relates_to' the clear event") -// } -// } -// -// -// } -// } -// mCryptoError = null -// } - /** * @return The curve25519 key that sent this event. */ fun getSenderKey(): String? { return mxDecryptionResult?.senderKey - // return mClearEvent?.mSenderCurve25519Key ?: mSenderCurve25519Key } /** @@ -194,23 +123,13 @@ data class Event( */ fun getKeysClaimed(): Map { return mxDecryptionResult?.keysClaimed ?: HashMap() -// val res = HashMap() -// -// val claimedEd25519Key = if (null != mClearEvent) mClearEvent!!.mClaimedEd25519Key else mClaimedEd25519Key -// -// if (null != claimedEd25519Key) { -// res["ed25519"] = claimedEd25519Key -// } -// -// return res } -// + /** * @return the event type */ fun getClearType(): String { - return mxDecryptionResult?.payload?.get("type")?.toString() - ?: type//get("type")?.toString() ?: type + return mxDecryptionResult?.payload?.get("type")?.toString() ?: type } /** @@ -220,30 +139,8 @@ data class Event( return mxDecryptionResult?.payload?.get("content") as? Content ?: content } -// /** -// * @return the linked crypto error -// */ -// fun getCryptoError(): MXCryptoError? { -// return mCryptoError -// } -// -// /** -// * Update the linked crypto error -// * -// * @param error the new crypto error. -// */ -// fun setCryptoError(error: MXCryptoError?) { -// mCryptoError = error -// if (null != error) { -// mClearEvent = null -// } -// } - - fun toContentStringWithIndent(): String { - val contentMap = this.toContent()?.toMutableMap() ?: HashMap() - contentMap.remove("mxDecryptionResult") - contentMap.remove("mCryptoError") + val contentMap = toContent()?.toMutableMap() ?: HashMap() return JSONObject(contentMap).toString(4) } From 4009f2c1762f927078c43ea7a4def2a102520e62 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 6 Aug 2019 15:03:15 +0200 Subject: [PATCH 18/20] Add comment to explain why we use a AlwaysSuccessfulWorker --- .../android/internal/session/room/send/DefaultSendService.kt | 5 +++-- .../FakeSendWorker.kt => worker/AlwaysSuccessfulWorker.kt} | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) rename matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/{session/room/send/FakeSendWorker.kt => worker/AlwaysSuccessfulWorker.kt} (85%) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/DefaultSendService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/DefaultSendService.kt index 1d8eaf3f..b4759c41 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/DefaultSendService.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/DefaultSendService.kt @@ -38,6 +38,7 @@ import im.vector.matrix.android.internal.database.query.where import im.vector.matrix.android.internal.session.content.UploadContentWorker import im.vector.matrix.android.internal.session.room.timeline.TimelineSendEventWorkCommon import im.vector.matrix.android.internal.util.CancelableWork +import im.vector.matrix.android.internal.worker.AlwaysSuccessfulWorker import im.vector.matrix.android.internal.worker.WorkManagerUtil import im.vector.matrix.android.internal.worker.WorkManagerUtil.matrixOneTimeWorkRequestBuilder import im.vector.matrix.android.internal.worker.WorkerParamsFactory @@ -163,8 +164,8 @@ internal class DefaultSendService @Inject constructor(private val context: Conte TimelineSendEventWorkCommon.cancelAllWorks(context, roomId) WorkManager.getInstance(context).cancelUniqueWork(buildWorkName(UPLOAD_WORK)) - // TODO Valere: what is the aim of this code ? Cancellation above is not enough? - matrixOneTimeWorkRequestBuilder() + // Replace the worker chains with a AlwaysSuccessfulWorker, to ensure the queues are well emptied + matrixOneTimeWorkRequestBuilder() .build().let { TimelineSendEventWorkCommon.postWork(context, roomId, it, ExistingWorkPolicy.REPLACE) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/FakeSendWorker.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/worker/AlwaysSuccessfulWorker.kt similarity index 85% rename from matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/FakeSendWorker.kt rename to matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/worker/AlwaysSuccessfulWorker.kt index f62c42d0..c0cae10d 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/FakeSendWorker.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/worker/AlwaysSuccessfulWorker.kt @@ -13,13 +13,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package im.vector.matrix.android.internal.session.room.send +package im.vector.matrix.android.internal.worker import android.content.Context import androidx.work.Worker import androidx.work.WorkerParameters -internal class FakeSendWorker(context: Context, params: WorkerParameters) +internal class AlwaysSuccessfulWorker(context: Context, params: WorkerParameters) : Worker(context, params) { override fun doWork(): Result { From d82fd10f3b3e29f2f6184bf4ea9ffd25814bf7c0 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 6 Aug 2019 15:15:40 +0200 Subject: [PATCH 19/20] Start chain: add missing cases --- .../room/relation/DefaultRelationService.kt | 7 +++---- .../session/room/send/DefaultSendService.kt | 12 ++++++------ .../timeline/TimelineSendEventWorkCommon.kt | 8 +++++++- .../android/internal/worker/Extensions.kt | 18 ++++++++++++++++++ 4 files changed, 34 insertions(+), 11 deletions(-) create mode 100644 matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/worker/Extensions.kt diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/relation/DefaultRelationService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/relation/DefaultRelationService.kt index b5a0e50e..cd31c978 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/relation/DefaultRelationService.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/relation/DefaultRelationService.kt @@ -115,7 +115,7 @@ internal class DefaultRelationService @Inject constructor(private val context: C eventId, reason) val redactWorkData = WorkerParamsFactory.toData(sendContentWorkerParams) - return TimelineSendEventWorkCommon.createWork(redactWorkData) + return TimelineSendEventWorkCommon.createWork(redactWorkData, true) } override fun editTextMessage(targetEventId: String, @@ -199,14 +199,13 @@ internal class DefaultRelationService @Inject constructor(private val context: C // Same parameter val params = EncryptEventWorker.Params(credentials.userId, roomId, event, keepKeys) val sendWorkData = WorkerParamsFactory.toData(params) - return TimelineSendEventWorkCommon.createWork(sendWorkData) + return TimelineSendEventWorkCommon.createWork(sendWorkData, true) } private fun createSendEventWork(event: Event): OneTimeWorkRequest { val sendContentWorkerParams = SendEventWorker.Params(credentials.userId, roomId, event) val sendWorkData = WorkerParamsFactory.toData(sendContentWorkerParams) - val workRequest = TimelineSendEventWorkCommon.createWork(sendWorkData) - return workRequest + return TimelineSendEventWorkCommon.createWork(sendWorkData, true) } override fun getEventSummaryLive(eventId: String): LiveData { diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/DefaultSendService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/DefaultSendService.kt index b4759c41..34260cb2 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/DefaultSendService.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/DefaultSendService.kt @@ -80,11 +80,11 @@ internal class DefaultSendService @Inject constructor(private val context: Conte return if (cryptoService.isRoomEncrypted(roomId)) { Timber.v("Send event in encrypted room") val encryptWork = createEncryptEventWork(event, true) - val sendWork = createSendEventWork(event) + val sendWork = createSendEventWork(event, false) TimelineSendEventWorkCommon.postSequentialWorks(context, roomId, encryptWork, sendWork) CancelableWork(context, encryptWork.id) } else { - val sendWork = createSendEventWork(event) + val sendWork = createSendEventWork(event, true) TimelineSendEventWorkCommon.postWork(context, roomId, sendWork) CancelableWork(context, sendWork.id) } @@ -245,7 +245,7 @@ internal class DefaultSendService @Inject constructor(private val context: Conte val isRoomEncrypted = cryptoService.isRoomEncrypted(roomId) val uploadWork = createUploadMediaWork(localEcho, attachment, isRoomEncrypted, startChain = true) - val sendWork = createSendEventWork(localEcho) + val sendWork = createSendEventWork(localEcho, false) if (isRoomEncrypted) { val encryptWork = createEncryptEventWork(localEcho, false /*not start of chain, take input error*/) @@ -297,11 +297,11 @@ internal class DefaultSendService @Inject constructor(private val context: Conte .build() } - private fun createSendEventWork(event: Event): OneTimeWorkRequest { + private fun createSendEventWork(event: Event, startChain: Boolean): OneTimeWorkRequest { val sendContentWorkerParams = SendEventWorker.Params(credentials.userId, roomId, event) val sendWorkData = WorkerParamsFactory.toData(sendContentWorkerParams) - return TimelineSendEventWorkCommon.createWork(sendWorkData) + return TimelineSendEventWorkCommon.createWork(sendWorkData, startChain) } private fun createRedactEventWork(event: Event, reason: String?): OneTimeWorkRequest { @@ -310,7 +310,7 @@ internal class DefaultSendService @Inject constructor(private val context: Conte } val sendContentWorkerParams = RedactEventWorker.Params(credentials.userId, redactEvent.eventId!!, roomId, event.eventId, reason) val redactWorkData = WorkerParamsFactory.toData(sendContentWorkerParams) - return TimelineSendEventWorkCommon.createWork(redactWorkData) + return TimelineSendEventWorkCommon.createWork(redactWorkData, true) } private fun createUploadMediaWork(event: Event, diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/TimelineSendEventWorkCommon.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/TimelineSendEventWorkCommon.kt index 2a72d3ff..71d6f5d4 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/TimelineSendEventWorkCommon.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/TimelineSendEventWorkCommon.kt @@ -17,6 +17,7 @@ package im.vector.matrix.android.internal.session.room.timeline import android.content.Context import androidx.work.* +import im.vector.matrix.android.internal.session.room.send.NoMerger import im.vector.matrix.android.internal.worker.WorkManagerUtil import im.vector.matrix.android.internal.worker.WorkManagerUtil.matrixOneTimeWorkRequestBuilder import java.util.concurrent.TimeUnit @@ -57,9 +58,14 @@ internal object TimelineSendEventWorkCommon { .enqueue() } - inline fun createWork(data: Data): OneTimeWorkRequest { + inline fun createWork(data: Data, startChain: Boolean): OneTimeWorkRequest { return matrixOneTimeWorkRequestBuilder() .setConstraints(WorkManagerUtil.workConstraints) + .apply { + if (startChain) { + setInputMerger(NoMerger::class.java) + } + } .setInputData(data) .setBackoffCriteria(BackoffPolicy.LINEAR, BACKOFF_DELAY, TimeUnit.MILLISECONDS) .build() diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/worker/Extensions.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/worker/Extensions.kt new file mode 100644 index 00000000..28630395 --- /dev/null +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/worker/Extensions.kt @@ -0,0 +1,18 @@ +/* + * 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.worker + From 7a6fc4936b645bcc72cf1aec4bbba4192c29a2ec Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 6 Aug 2019 15:23:13 +0200 Subject: [PATCH 20/20] Start chain: create extension --- .../session/room/send/DefaultSendService.kt | 13 +++---------- .../android/internal/session/room/send/NoMerger.kt | 2 +- .../room/timeline/TimelineSendEventWorkCommon.kt | 8 ++------ .../matrix/android/internal/worker/Extensions.kt | 12 ++++++++++++ 4 files changed, 18 insertions(+), 17 deletions(-) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/DefaultSendService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/DefaultSendService.kt index 34260cb2..8b65be24 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/DefaultSendService.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/DefaultSendService.kt @@ -42,6 +42,7 @@ import im.vector.matrix.android.internal.worker.AlwaysSuccessfulWorker import im.vector.matrix.android.internal.worker.WorkManagerUtil import im.vector.matrix.android.internal.worker.WorkManagerUtil.matrixOneTimeWorkRequestBuilder import im.vector.matrix.android.internal.worker.WorkerParamsFactory +import im.vector.matrix.android.internal.worker.startChain import timber.log.Timber import java.util.concurrent.Executors import java.util.concurrent.TimeUnit @@ -288,11 +289,7 @@ internal class DefaultSendService @Inject constructor(private val context: Conte return matrixOneTimeWorkRequestBuilder() .setConstraints(WorkManagerUtil.workConstraints) .setInputData(sendWorkData) - .apply { - if (startChain) { - setInputMerger(NoMerger::class.java) - } - } + .startChain(startChain) .setBackoffCriteria(BackoffPolicy.LINEAR, BACKOFF_DELAY, TimeUnit.MILLISECONDS) .build() } @@ -322,11 +319,7 @@ internal class DefaultSendService @Inject constructor(private val context: Conte return matrixOneTimeWorkRequestBuilder() .setConstraints(WorkManagerUtil.workConstraints) - .apply { - if (startChain) { - setInputMerger(NoMerger::class.java) - } - } + .startChain(startChain) .setInputData(uploadWorkData) .setBackoffCriteria(BackoffPolicy.LINEAR, BACKOFF_DELAY, TimeUnit.MILLISECONDS) .build() diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/NoMerger.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/NoMerger.kt index 77198857..c41c4bc0 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/NoMerger.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/NoMerger.kt @@ -19,7 +19,7 @@ import androidx.work.Data import androidx.work.InputMerger /** - * InputMerger which takes only the first input, to ensure an appended work with only have the specified parameters + * InputMerger which takes only the first input, to ensure an appended work will only have the specified parameters */ internal class NoMerger : InputMerger() { override fun merge(inputs: MutableList): Data { diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/TimelineSendEventWorkCommon.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/TimelineSendEventWorkCommon.kt index 71d6f5d4..575c0662 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/TimelineSendEventWorkCommon.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/TimelineSendEventWorkCommon.kt @@ -17,9 +17,9 @@ package im.vector.matrix.android.internal.session.room.timeline import android.content.Context import androidx.work.* -import im.vector.matrix.android.internal.session.room.send.NoMerger import im.vector.matrix.android.internal.worker.WorkManagerUtil import im.vector.matrix.android.internal.worker.WorkManagerUtil.matrixOneTimeWorkRequestBuilder +import im.vector.matrix.android.internal.worker.startChain import java.util.concurrent.TimeUnit @@ -61,11 +61,7 @@ internal object TimelineSendEventWorkCommon { inline fun createWork(data: Data, startChain: Boolean): OneTimeWorkRequest { return matrixOneTimeWorkRequestBuilder() .setConstraints(WorkManagerUtil.workConstraints) - .apply { - if (startChain) { - setInputMerger(NoMerger::class.java) - } - } + .startChain(startChain) .setInputData(data) .setBackoffCriteria(BackoffPolicy.LINEAR, BACKOFF_DELAY, TimeUnit.MILLISECONDS) .build() diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/worker/Extensions.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/worker/Extensions.kt index 28630395..dab71625 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/worker/Extensions.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/worker/Extensions.kt @@ -16,3 +16,15 @@ package im.vector.matrix.android.internal.worker +import androidx.work.OneTimeWorkRequest +import im.vector.matrix.android.internal.session.room.send.NoMerger + +/** + * If startChain parameter is true, the builder will have a inputMerger set to [NoMerger] + */ +internal fun OneTimeWorkRequest.Builder.startChain(startChain: Boolean): OneTimeWorkRequest.Builder { + if (startChain) { + setInputMerger(NoMerger::class.java) + } + return this +}