From a69049645aec95c41c0ab1cf8ac2840e89dd9604 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 26 Feb 2020 11:11:10 +0100 Subject: [PATCH 01/91] FTUE: do not display a different color when encrypting message when not in developer mode. --- CHANGES.md | 1 + .../detail/timeline/MessageColorProvider.kt | 58 +++++++++++++++++++ .../timeline/factory/MessageItemFactory.kt | 2 +- .../factory/VerificationItemFactory.kt | 8 +-- .../helper/ContentUploadStateTrackerBinder.kt | 17 +++--- .../helper/MessageItemAttributesFactory.kt | 6 +- .../timeline/item/AbsBaseMessageItem.kt | 7 +-- .../detail/timeline/item/AbsMessageItem.kt | 4 +- .../item/VerificationRequestConclusionItem.kt | 4 +- .../timeline/item/VerificationRequestItem.kt | 4 +- .../riotx/features/ui/ColorProviderExt.kt | 37 ------------ 11 files changed, 84 insertions(+), 64 deletions(-) create mode 100644 vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/MessageColorProvider.kt delete mode 100644 vector/src/main/java/im/vector/riotx/features/ui/ColorProviderExt.kt diff --git a/CHANGES.md b/CHANGES.md index 37b6c63393..abf318ef50 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -11,6 +11,7 @@ Features ✨: Improvements 🙌: - Migrate to binary QR code verification (#994) - Share action is added to room profile and room member profile (#858) + - FTUE: do not display a different color when encrypting message when not in developer mode. Bugfix 🐛: - Account creation: wrongly hints that an email can be used to create an account (#941) diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/MessageColorProvider.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/MessageColorProvider.kt new file mode 100644 index 0000000000..c6ab5b024f --- /dev/null +++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/MessageColorProvider.kt @@ -0,0 +1,58 @@ +/* + * 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.riotx.features.home.room.detail.timeline + +import androidx.annotation.ColorInt +import im.vector.matrix.android.api.session.room.send.SendState +import im.vector.riotx.R +import im.vector.riotx.core.resources.ColorProvider +import im.vector.riotx.features.settings.VectorPreferences +import javax.inject.Inject + +class MessageColorProvider @Inject constructor( + private val colorProvider: ColorProvider, + private val vectorPreferences: VectorPreferences) { + + @ColorInt + fun getMessageTextColor(sendState: SendState): Int { + return if (vectorPreferences.developerMode()) { + when (sendState) { + // SendStates, in the classical order they will occur + SendState.UNKNOWN, + SendState.UNSENT -> colorProvider.getColorFromAttribute(R.attr.vctr_sending_message_text_color) + SendState.ENCRYPTING -> colorProvider.getColorFromAttribute(R.attr.vctr_encrypting_message_text_color) + SendState.SENDING -> colorProvider.getColorFromAttribute(R.attr.vctr_sending_message_text_color) + SendState.SENT, + SendState.SYNCED -> colorProvider.getColorFromAttribute(R.attr.vctr_message_text_color) + SendState.UNDELIVERED, + SendState.FAILED_UNKNOWN_DEVICES -> colorProvider.getColorFromAttribute(R.attr.vctr_unsent_message_text_color) + } + } else { + // When not in developer mode, we do not use special color for the encrypting state + when (sendState) { + SendState.UNKNOWN, + SendState.UNSENT, + SendState.ENCRYPTING, + SendState.SENDING -> colorProvider.getColorFromAttribute(R.attr.vctr_sending_message_text_color) + SendState.SENT, + SendState.SYNCED -> colorProvider.getColorFromAttribute(R.attr.vctr_message_text_color) + SendState.UNDELIVERED, + SendState.FAILED_UNKNOWN_DEVICES -> colorProvider.getColorFromAttribute(R.attr.vctr_unsent_message_text_color) + } + } + } +} diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/factory/MessageItemFactory.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/factory/MessageItemFactory.kt index 83f0c63147..2b221b9fef 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/factory/MessageItemFactory.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/factory/MessageItemFactory.kt @@ -222,7 +222,7 @@ class MessageItemFactory @Inject constructor( referenceId = informationData.eventId, informationData = informationData, avatarRenderer = attributes.avatarRenderer, - colorProvider = attributes.colorProvider, + messageColorProvider = attributes.messageColorProvider, itemLongClickListener = attributes.itemLongClickListener, itemClickListener = attributes.itemClickListener, reactionPillCallback = attributes.reactionPillCallback, diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/factory/VerificationItemFactory.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/factory/VerificationItemFactory.kt index dc5bd740dd..12bc10ebdb 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/factory/VerificationItemFactory.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/factory/VerificationItemFactory.kt @@ -27,8 +27,8 @@ import im.vector.matrix.android.api.session.room.model.message.MessageVerificati import im.vector.matrix.android.api.session.room.timeline.TimelineEvent import im.vector.matrix.android.internal.session.room.VerificationState import im.vector.riotx.core.epoxy.VectorEpoxyModel -import im.vector.riotx.core.resources.ColorProvider import im.vector.riotx.core.resources.UserPreferencesProvider +import im.vector.riotx.features.home.room.detail.timeline.MessageColorProvider import im.vector.riotx.features.home.room.detail.timeline.TimelineEventController import im.vector.riotx.features.home.room.detail.timeline.helper.AvatarSizeProvider import im.vector.riotx.features.home.room.detail.timeline.helper.MessageInformationDataFactory @@ -43,7 +43,7 @@ import javax.inject.Inject * several checks are made to see if this conclusion is attached to a known request */ class VerificationItemFactory @Inject constructor( - private val colorProvider: ColorProvider, + private val messageColorProvider: MessageColorProvider, private val messageInformationDataFactory: MessageInformationDataFactory, private val messageItemAttributesFactory: MessageItemAttributesFactory, private val avatarSizeProvider: AvatarSizeProvider, @@ -97,7 +97,7 @@ class VerificationItemFactory @Inject constructor( isPositive = false, informationData = informationData, avatarRenderer = attributes.avatarRenderer, - colorProvider = colorProvider, + messageColorProvider = messageColorProvider, emojiTypeFace = attributes.emojiTypeFace, itemClickListener = attributes.itemClickListener, itemLongClickListener = attributes.itemLongClickListener, @@ -130,7 +130,7 @@ class VerificationItemFactory @Inject constructor( isPositive = true, informationData = informationData, avatarRenderer = attributes.avatarRenderer, - colorProvider = colorProvider, + messageColorProvider = messageColorProvider, emojiTypeFace = attributes.emojiTypeFace, itemClickListener = attributes.itemClickListener, itemLongClickListener = attributes.itemLongClickListener, diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/helper/ContentUploadStateTrackerBinder.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/helper/ContentUploadStateTrackerBinder.kt index d80c625e8f..4cf14fa83b 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/helper/ContentUploadStateTrackerBinder.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/helper/ContentUploadStateTrackerBinder.kt @@ -27,14 +27,13 @@ import im.vector.riotx.R import im.vector.riotx.core.di.ActiveSessionHolder import im.vector.riotx.core.di.ScreenScope import im.vector.riotx.core.error.ErrorFormatter -import im.vector.riotx.core.resources.ColorProvider import im.vector.riotx.core.utils.TextUtils -import im.vector.riotx.features.ui.getMessageTextColor +import im.vector.riotx.features.home.room.detail.timeline.MessageColorProvider import javax.inject.Inject @ScreenScope class ContentUploadStateTrackerBinder @Inject constructor(private val activeSessionHolder: ActiveSessionHolder, - private val colorProvider: ColorProvider, + private val messageColorProvider: MessageColorProvider, private val errorFormatter: ErrorFormatter) { private val updateListeners = mutableMapOf() @@ -44,7 +43,7 @@ class ContentUploadStateTrackerBinder @Inject constructor(private val activeSess progressLayout: ViewGroup) { activeSessionHolder.getSafeActiveSession()?.also { session -> val uploadStateTracker = session.contentUploadProgressTracker() - val updateListener = ContentMediaProgressUpdater(progressLayout, isLocalFile, colorProvider, errorFormatter) + val updateListener = ContentMediaProgressUpdater(progressLayout, isLocalFile, messageColorProvider, errorFormatter) updateListeners[eventId] = updateListener uploadStateTracker.track(eventId, updateListener) } @@ -68,7 +67,7 @@ class ContentUploadStateTrackerBinder @Inject constructor(private val activeSess private class ContentMediaProgressUpdater(private val progressLayout: ViewGroup, private val isLocalFile: Boolean, - private val colorProvider: ColorProvider, + private val messageColorProvider: MessageColorProvider, private val errorFormatter: ErrorFormatter) : ContentUploadStateTracker.UpdateListener { override fun onUpdate(state: ContentUploadStateTracker.State) { @@ -92,7 +91,7 @@ private class ContentMediaProgressUpdater(private val progressLayout: ViewGroup, progressBar?.isIndeterminate = true progressBar?.progress = 0 progressTextView?.text = progressLayout.context.getString(R.string.send_file_step_idle) - progressTextView?.setTextColor(colorProvider.getMessageTextColor(SendState.UNSENT)) + progressTextView?.setTextColor(messageColorProvider.getMessageTextColor(SendState.UNSENT)) } else { progressLayout.isVisible = false } @@ -120,7 +119,7 @@ private class ContentMediaProgressUpdater(private val progressLayout: ViewGroup, val progressTextView = progressLayout.findViewById(R.id.mediaProgressTextView) progressBar?.isIndeterminate = true progressTextView?.text = progressLayout.context.getString(resId) - progressTextView?.setTextColor(colorProvider.getMessageTextColor(SendState.ENCRYPTING)) + progressTextView?.setTextColor(messageColorProvider.getMessageTextColor(SendState.ENCRYPTING)) } private fun doHandleProgress(resId: Int, current: Long, total: Long) { @@ -134,7 +133,7 @@ private class ContentMediaProgressUpdater(private val progressLayout: ViewGroup, progressTextView?.text = progressLayout.context.getString(resId, TextUtils.formatFileSize(progressLayout.context, current, true), TextUtils.formatFileSize(progressLayout.context, total, true)) - progressTextView?.setTextColor(colorProvider.getMessageTextColor(SendState.SENDING)) + progressTextView?.setTextColor(messageColorProvider.getMessageTextColor(SendState.SENDING)) } private fun handleFailure(state: ContentUploadStateTracker.State.Failure) { @@ -143,7 +142,7 @@ private class ContentMediaProgressUpdater(private val progressLayout: ViewGroup, val progressTextView = progressLayout.findViewById(R.id.mediaProgressTextView) progressBar?.isVisible = false progressTextView?.text = errorFormatter.toHumanReadable(state.throwable) - progressTextView?.setTextColor(colorProvider.getMessageTextColor(SendState.UNDELIVERED)) + progressTextView?.setTextColor(messageColorProvider.getMessageTextColor(SendState.UNDELIVERED)) } private fun handleSuccess() { diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/helper/MessageItemAttributesFactory.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/helper/MessageItemAttributesFactory.kt index 0e1229eeca..7433b03408 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/helper/MessageItemAttributesFactory.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/helper/MessageItemAttributesFactory.kt @@ -20,9 +20,9 @@ package im.vector.riotx.features.home.room.detail.timeline.helper import android.view.View import im.vector.matrix.android.api.session.room.model.message.MessageContent import im.vector.riotx.EmojiCompatFontProvider -import im.vector.riotx.core.resources.ColorProvider import im.vector.riotx.core.utils.DebouncedClickListener import im.vector.riotx.features.home.AvatarRenderer +import im.vector.riotx.features.home.room.detail.timeline.MessageColorProvider import im.vector.riotx.features.home.room.detail.timeline.TimelineEventController import im.vector.riotx.features.home.room.detail.timeline.item.AbsMessageItem import im.vector.riotx.features.home.room.detail.timeline.item.MessageInformationData @@ -30,7 +30,7 @@ import javax.inject.Inject class MessageItemAttributesFactory @Inject constructor( private val avatarRenderer: AvatarRenderer, - private val colorProvider: ColorProvider, + private val messageColorProvider: MessageColorProvider, private val avatarSizeProvider: AvatarSizeProvider, private val emojiCompatFontProvider: EmojiCompatFontProvider) { @@ -41,7 +41,7 @@ class MessageItemAttributesFactory @Inject constructor( avatarSize = avatarSizeProvider.avatarSize, informationData = informationData, avatarRenderer = avatarRenderer, - colorProvider = colorProvider, + messageColorProvider = messageColorProvider, itemLongClickListener = View.OnLongClickListener { view -> callback?.onEventLongClicked(informationData, messageContent, view) ?: false }, diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/item/AbsBaseMessageItem.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/item/AbsBaseMessageItem.kt index 6d99bb2650..149b5e74ad 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/item/AbsBaseMessageItem.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/item/AbsBaseMessageItem.kt @@ -24,12 +24,11 @@ import androidx.annotation.IdRes import androidx.core.view.isVisible import im.vector.matrix.android.api.session.room.send.SendState import im.vector.riotx.R -import im.vector.riotx.core.resources.ColorProvider import im.vector.riotx.core.utils.DebouncedClickListener import im.vector.riotx.features.home.AvatarRenderer +import im.vector.riotx.features.home.room.detail.timeline.MessageColorProvider import im.vector.riotx.features.home.room.detail.timeline.TimelineEventController import im.vector.riotx.features.reactions.widget.ReactionButton -import im.vector.riotx.features.ui.getMessageTextColor /** * Base timeline item with reactions and read receipts. @@ -105,7 +104,7 @@ abstract class AbsBaseMessageItem : BaseEventItem protected open fun renderSendState(root: View, textView: TextView?, failureIndicator: ImageView? = null) { root.isClickable = baseAttributes.informationData.sendState.isSent() val state = if (baseAttributes.informationData.hasPendingEdits) SendState.UNSENT else baseAttributes.informationData.sendState - textView?.setTextColor(baseAttributes.colorProvider.getMessageTextColor(state)) + textView?.setTextColor(baseAttributes.messageColorProvider.getMessageTextColor(state)) failureIndicator?.isVisible = baseAttributes.informationData.sendState.hasFailed() } @@ -120,7 +119,7 @@ abstract class AbsBaseMessageItem : BaseEventItem // val avatarSize: Int, val informationData: MessageInformationData val avatarRenderer: AvatarRenderer - val colorProvider: ColorProvider + val messageColorProvider: MessageColorProvider val itemLongClickListener: View.OnLongClickListener? val itemClickListener: View.OnClickListener? // val memberClickListener: View.OnClickListener? 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 ae69164951..2b01e915df 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 @@ -23,9 +23,9 @@ import android.widget.TextView import androidx.annotation.IdRes import com.airbnb.epoxy.EpoxyAttribute import im.vector.riotx.R -import im.vector.riotx.core.resources.ColorProvider import im.vector.riotx.core.utils.DebouncedClickListener import im.vector.riotx.features.home.AvatarRenderer +import im.vector.riotx.features.home.room.detail.timeline.MessageColorProvider import im.vector.riotx.features.home.room.detail.timeline.TimelineEventController /** @@ -88,7 +88,7 @@ abstract class AbsMessageItem : AbsBaseMessageItem val avatarSize: Int, override val informationData: MessageInformationData, override val avatarRenderer: AvatarRenderer, - override val colorProvider: ColorProvider, + override val messageColorProvider: MessageColorProvider, override val itemLongClickListener: View.OnLongClickListener? = null, override val itemClickListener: View.OnClickListener? = null, val memberClickListener: View.OnClickListener? = null, diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/item/VerificationRequestConclusionItem.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/item/VerificationRequestConclusionItem.kt index 036bf2b036..2b28e15cab 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/item/VerificationRequestConclusionItem.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/item/VerificationRequestConclusionItem.kt @@ -26,8 +26,8 @@ import androidx.core.view.updateLayoutParams import com.airbnb.epoxy.EpoxyAttribute import com.airbnb.epoxy.EpoxyModelClass import im.vector.riotx.R -import im.vector.riotx.core.resources.ColorProvider import im.vector.riotx.features.home.AvatarRenderer +import im.vector.riotx.features.home.room.detail.timeline.MessageColorProvider import im.vector.riotx.features.home.room.detail.timeline.TimelineEventController @EpoxyModelClass(layout = R.layout.item_timeline_event_base_state) @@ -80,7 +80,7 @@ abstract class VerificationRequestConclusionItem : AbsBaseMessageItem getColorFromAttribute(R.attr.vctr_sending_message_text_color) - SendState.ENCRYPTING -> getColorFromAttribute(R.attr.vctr_encrypting_message_text_color) - SendState.SENDING -> getColorFromAttribute(R.attr.vctr_sending_message_text_color) - SendState.SENT, - SendState.SYNCED -> getColorFromAttribute(R.attr.vctr_message_text_color) - SendState.UNDELIVERED, - SendState.FAILED_UNKNOWN_DEVICES -> getColorFromAttribute(R.attr.vctr_unsent_message_text_color) - } -} From 9bb4c7ed256d876c6c21cd83e0d9711ab4bcdeee Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 27 Feb 2020 12:34:33 +0100 Subject: [PATCH 02/91] Version++ --- CHANGES.md | 24 ++++++++++++++++++++++++ vector/build.gradle | 2 +- 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index 95f35e3e1d..65f6e96f69 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,3 +1,27 @@ +Changes in RiotX 0.18.0 (2020-XX-XX) +=================================================== + +Features ✨: + - + +Improvements 🙌: + - + +Bugfix 🐛: + - + +Translations 🗣: + - + +SDK API changes ⚠️: + - + +Build 🧱: + - + +Other changes: + - + Changes in RiotX 0.17.0 (2020-02-27) =================================================== diff --git a/vector/build.gradle b/vector/build.gradle index 483cd53831..988712d87e 100644 --- a/vector/build.gradle +++ b/vector/build.gradle @@ -15,7 +15,7 @@ androidExtensions { } ext.versionMajor = 0 -ext.versionMinor = 17 +ext.versionMinor = 18 ext.versionPatch = 0 static def getGitTimestamp() { From bc9493d5b947bed8694c785843f9dd0c929e1f36 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 27 Feb 2020 12:47:11 +0100 Subject: [PATCH 03/91] Upgrade ktlint to version 0.36.0 --- .buildkite/pipeline.yml | 2 +- CHANGES.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.buildkite/pipeline.yml b/.buildkite/pipeline.yml index a410ea0af9..31d2d1f457 100644 --- a/.buildkite/pipeline.yml +++ b/.buildkite/pipeline.yml @@ -81,7 +81,7 @@ steps: - label: "ktlint" command: - - "curl -sSLO https://github.com/pinterest/ktlint/releases/download/0.34.2/ktlint && chmod a+x ktlint" + - "curl -sSLO https://github.com/pinterest/ktlint/releases/download/0.36.0/ktlint && chmod a+x ktlint" - "./ktlint --android --experimental -v" plugins: - docker#v3.1.0: diff --git a/CHANGES.md b/CHANGES.md index 65f6e96f69..ea6aee07c4 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -17,7 +17,7 @@ SDK API changes ⚠️: - Build 🧱: - - + - Upgrade ktlint to version 0.36.0 Other changes: - From a1466e299bd994d33ca6e59eb33ee999cae9d7bf Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 27 Feb 2020 14:30:49 +0100 Subject: [PATCH 04/91] Fix missing recycle call and ensure this mistake will not happen again --- vector/lint.xml | 1 + .../vector/riotx/core/platform/BadgeFloatingActionButton.kt | 2 +- .../home/room/detail/timeline/item/PollResultLineView.kt | 4 ++-- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/vector/lint.xml b/vector/lint.xml index 6a9b0634a7..c39f1dcd8d 100644 --- a/vector/lint.xml +++ b/vector/lint.xml @@ -30,6 +30,7 @@ + diff --git a/vector/src/main/java/im/vector/riotx/core/platform/BadgeFloatingActionButton.kt b/vector/src/main/java/im/vector/riotx/core/platform/BadgeFloatingActionButton.kt index ebf04e7097..49931e2b54 100644 --- a/vector/src/main/java/im/vector/riotx/core/platform/BadgeFloatingActionButton.kt +++ b/vector/src/main/java/im/vector/riotx/core/platform/BadgeFloatingActionButton.kt @@ -129,7 +129,7 @@ class BadgeFloatingActionButton @JvmOverloads constructor( attrs?.let { initAttrs(attrs) } } - @SuppressWarnings("ResourceType", "Recycle") + @SuppressWarnings("Recycle") private fun initAttrs(attrs: AttributeSet) { context.obtainStyledAttributes(attrs, R.styleable.BadgeFloatingActionButton).use { counterBackgroundColor = it.getColor(R.styleable.BadgeFloatingActionButton_badgeBackgroundColor, 0) diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/item/PollResultLineView.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/item/PollResultLineView.kt index f1e1753b17..a0ad3466f7 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/item/PollResultLineView.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/item/PollResultLineView.kt @@ -73,11 +73,11 @@ class PollResultLineView @JvmOverloads constructor( orientation = HORIZONTAL ButterKnife.bind(this) - val typedArray = context.obtainStyledAttributes(attrs, - R.styleable.PollResultLineView, 0, 0) + val typedArray = context.obtainStyledAttributes(attrs, R.styleable.PollResultLineView, 0, 0) label = typedArray.getString(R.styleable.PollResultLineView_optionName) ?: "" percent = typedArray.getString(R.styleable.PollResultLineView_optionCount) ?: "" optionSelected = typedArray.getBoolean(R.styleable.PollResultLineView_optionSelected, false) isWinner = typedArray.getBoolean(R.styleable.PollResultLineView_optionIsWinner, false) + typedArray.recycle() } } From c0d6b9d13034d13745e7b684c929c4120657c26c Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 27 Feb 2020 14:35:57 +0100 Subject: [PATCH 05/91] Lint fix IconXmlAndPng error --- vector/lint.xml | 1 + .../res/drawable-xxhdpi/ic_material_share.png | Bin 1052 -> 0 bytes 2 files changed, 1 insertion(+) delete mode 100755 vector/src/main/res/drawable-xxhdpi/ic_material_share.png diff --git a/vector/lint.xml b/vector/lint.xml index c39f1dcd8d..21ff01a99b 100644 --- a/vector/lint.xml +++ b/vector/lint.xml @@ -6,6 +6,7 @@ + diff --git a/vector/src/main/res/drawable-xxhdpi/ic_material_share.png b/vector/src/main/res/drawable-xxhdpi/ic_material_share.png deleted file mode 100755 index 0fe15fc056771d76cc8b830697d18ab4f6ce804e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1052 zcmV+%1mpXOP)004R> z004l5008;`004mK004C`008P>0026e000+ooVrmw00002VoOIv0RM-N%)bBt010qN zS#tmY3ljhU3ljkVnw%H_00WdsL_t(|+U=W5NK{c6$A1|Tgykd1%rsy0phcV9)G8^G z7Ue=}Q7VB(i$b!(RDyKVLqcrRCKIF7P{cALQv_#`n_2~xmV}{JhL)-MYUZ{`%g3BM zbB5@CH}3yi&RzU}!#V$RzHjb;BS(%LIr@(jM36m=Z>AU*Ll_tg;o>5j>|;KOMm!jc z%0mMQcCdep?@P?j)i{~b?H4G`&sDx;`&mBi8yFmsYCnN-zW~PAC=;OGFZ%`twKBhd zkKX`p;^YAo`EB38;JiG5HZ6b_c>n`i0DbZRrnLa38t$RJOS`7p|v(X>B9w3L49IG;7m8yHl|u)mAv0hl-V!aD2CM^hb;c>@n=R-0cz z5n~E_AAMZu+?=r5ei}Ura}yM^k~D^u_J=uWt@*7yQJSm&-KIoQ;U$-*xk;pz=0hn{ z#^nokFM2wPTprNFC?mX~kyF-g+#s?UR4$8?ESEiL*vT{Hmb}3l+2+@CN4e@d*e=21 zGLyJ0U{raVJZ!D)L@vwYLIrDOAmsW$@F>USU&$j_ z0zx_?rnAcsE;FV0{1vGZ5Td#5C6Q*hMbzvQNi-=Tn@ExYk;g;cG0p_NG;?~%k3Olq zR$eo%$ck5$f;ppHZUbb>iB~g4QlZ@Tog`xmCDWy3=y)qPA%1xlS8}=2(x%?p7(0&K020s?vinan8)i?RuM*>60(5^>GAqOIh6lZ z-Ned|SM%y3Tz)?8o6y}1l>OEza&(0 z=NwCy5BnRWH~--#EoF`DZ~u?>(!Qu)^Ux-D>v~rVS(H*m6{Td#%za0W9653%Pd@>k W_~uS4Xs)3E0000 Date: Thu, 27 Feb 2020 14:43:07 +0100 Subject: [PATCH 06/91] Lint: fix IconDipSize and IconDuplicatesConfig error (by removing unused resource) --- vector/lint.xml | 2 ++ .../res/drawable-mdpi/ic_material_camera.png | Bin 539 -> 0 bytes .../res/drawable-mdpi/ic_material_file.png | Bin 545 -> 0 bytes .../drawable-mdpi/ic_material_videocam.png | Bin 3120 -> 0 bytes .../res/drawable-mdpi/ic_send_sticker.png | Bin 7243 -> 0 bytes .../vector_cancel_upload_download.png | Bin 309 -> 0 bytes .../res/drawable-mdpi/vector_micro_green.png | Bin 399 -> 0 bytes .../res/drawable-mdpi/video_call_black.png | Bin 224 -> 0 bytes .../res/drawable-mdpi/video_call_green.png | Bin 298 -> 0 bytes .../res/drawable-mdpi/voice_call_black.png | Bin 574 -> 0 bytes .../drawable-mdpi/voice_call_end_fushia.png | Bin 331 -> 0 bytes .../res/drawable-mdpi/voice_call_green.png | Bin 432 -> 0 bytes .../drawable-mdpi/voice_call_start_green.png | Bin 684 -> 0 bytes .../res/drawable-xhdpi/ic_send_sticker.png | Bin 4586 -> 0 bytes .../drawable-xxhdpi/ic_material_camera.png | Bin 539 -> 0 bytes .../res/drawable-xxhdpi/ic_material_file.png | Bin 545 -> 0 bytes .../drawable-xxhdpi/ic_material_videocam.png | Bin 3120 -> 0 bytes .../res/drawable-xxhdpi/ic_send_sticker.png | Bin 7243 -> 0 bytes .../vector_cancel_upload_download.png | Bin 309 -> 0 bytes .../drawable-xxhdpi/vector_micro_green.png | Bin 399 -> 0 bytes .../res/drawable-xxhdpi/video_call_black.png | Bin 224 -> 0 bytes .../res/drawable-xxhdpi/video_call_green.png | Bin 298 -> 0 bytes .../res/drawable-xxhdpi/voice_call_black.png | Bin 574 -> 0 bytes .../drawable-xxhdpi/voice_call_end_fushia.png | Bin 331 -> 0 bytes .../res/drawable-xxhdpi/voice_call_green.png | Bin 432 -> 0 bytes .../voice_call_start_green.png | Bin 684 -> 0 bytes vector/src/main/res/menu/vector_searches.xml | 18 ------------------ 27 files changed, 2 insertions(+), 18 deletions(-) delete mode 100755 vector/src/main/res/drawable-mdpi/ic_material_camera.png delete mode 100755 vector/src/main/res/drawable-mdpi/ic_material_file.png delete mode 100755 vector/src/main/res/drawable-mdpi/ic_material_videocam.png delete mode 100644 vector/src/main/res/drawable-mdpi/ic_send_sticker.png delete mode 100755 vector/src/main/res/drawable-mdpi/vector_cancel_upload_download.png delete mode 100755 vector/src/main/res/drawable-mdpi/vector_micro_green.png delete mode 100755 vector/src/main/res/drawable-mdpi/video_call_black.png delete mode 100755 vector/src/main/res/drawable-mdpi/video_call_green.png delete mode 100755 vector/src/main/res/drawable-mdpi/voice_call_black.png delete mode 100755 vector/src/main/res/drawable-mdpi/voice_call_end_fushia.png delete mode 100755 vector/src/main/res/drawable-mdpi/voice_call_green.png delete mode 100755 vector/src/main/res/drawable-mdpi/voice_call_start_green.png delete mode 100644 vector/src/main/res/drawable-xhdpi/ic_send_sticker.png delete mode 100755 vector/src/main/res/drawable-xxhdpi/ic_material_camera.png delete mode 100755 vector/src/main/res/drawable-xxhdpi/ic_material_file.png delete mode 100755 vector/src/main/res/drawable-xxhdpi/ic_material_videocam.png delete mode 100644 vector/src/main/res/drawable-xxhdpi/ic_send_sticker.png delete mode 100755 vector/src/main/res/drawable-xxhdpi/vector_cancel_upload_download.png delete mode 100755 vector/src/main/res/drawable-xxhdpi/vector_micro_green.png delete mode 100755 vector/src/main/res/drawable-xxhdpi/video_call_black.png delete mode 100755 vector/src/main/res/drawable-xxhdpi/video_call_green.png delete mode 100755 vector/src/main/res/drawable-xxhdpi/voice_call_black.png delete mode 100755 vector/src/main/res/drawable-xxhdpi/voice_call_end_fushia.png delete mode 100755 vector/src/main/res/drawable-xxhdpi/voice_call_green.png delete mode 100755 vector/src/main/res/drawable-xxhdpi/voice_call_start_green.png delete mode 100755 vector/src/main/res/menu/vector_searches.xml diff --git a/vector/lint.xml b/vector/lint.xml index 21ff01a99b..6d4c4125ef 100644 --- a/vector/lint.xml +++ b/vector/lint.xml @@ -7,6 +7,8 @@ + + diff --git a/vector/src/main/res/drawable-mdpi/ic_material_camera.png b/vector/src/main/res/drawable-mdpi/ic_material_camera.png deleted file mode 100755 index 78e5bb23ffb7086c06c271d3775167fbb46799af..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 539 zcmeAS@N?(olHy`uVBq!ia0vp^2_VeD1|%QND7OGoY)RhkE)4%caKYZ?lYt_f1s;*b z3=G`DAk4@xYmNj^kiEpy*OmPNlMoLt&wHnBAq)(RD?D8sLn>~)opV<5kb(efteupX zwWf;ek_lTTPkMB+oBb^R2L7^Vc}@9cflWWE7=eZ`IGFfk8l2uItNU)V-)6-Fnl+}J zVum%UoMNUmqMTxuHLRRswl(>jZa?-3^?ayRy^+EAP3;25z3>*ned}9Xd>(NduG*g` zeu43v0s|ul1B(KKKm$X8LjRUE?+Y1cx^w^gUHVGtQ^vvXYD)c5HTp_HEgz!qFZO2C zZ4R6?p_=Ren=ggWs$QGSK2-8#pL~JZn%&7OD&GbrPl)T#{at3mxuSh*!|I0ktASd3 z>V@{&^H0ip>Ru@_QDpW0ts&?2JSMJ+-?%xbXGoCD4FiUjR4*>(su$bNjQE&ErRJ^13X}?rO)&E=9>#OR2@>Lkg zYM%R9BwL`mVv_xtpvrtB_N`ORUOM|Z>hABnfVmx6`ZP3E{1xSaH4 zY5&4De|M!wBZC726Epzc9kPEO)>3~?b}93VCabIUo(xK-*!V$V4F!c2%um^0rEq0C Q%7R2ZUHx3vIVCg!0B-!qZvX%Q diff --git a/vector/src/main/res/drawable-mdpi/ic_material_file.png b/vector/src/main/res/drawable-mdpi/ic_material_file.png deleted file mode 100755 index 64561dd4a46c142420570672762bddfe6787f914..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 545 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 B>+Jvl diff --git a/vector/src/main/res/drawable-mdpi/ic_send_sticker.png b/vector/src/main/res/drawable-mdpi/ic_send_sticker.png deleted file mode 100644 index a369cbee494db6f376916acfa2e9a41125454a71..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7243 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 Z{~v}UpUcfOD|G+>002ovPDHLkV1hrJ(nJ6N diff --git a/vector/src/main/res/drawable-mdpi/vector_cancel_upload_download.png b/vector/src/main/res/drawable-mdpi/vector_cancel_upload_download.png deleted file mode 100755 index 51b4401ca053ca8cad6e9903646709a2f44444df..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 309 zcmeAS@N?(olHy`uVBq!ia0vp^9w5xY0wn)GsXhaw{&>1LhEy=VysgJ$~x+g}6OvsxLimbaeN-!xQItoH=3nd`|H@dF!kYp_dChV`b9AudQLRn7yg2 zv~UiON9*MGOYAy6D=_*g@;c3(5`S(Hi^X;wk8Ms*3SMP^!WTf z-E_DAd$kLMWY`Z`);MuKF9=d$?_mzLoFj7Xp~|_3ODg!(3;AT&wLoS^O+0tsvcZJ& zD(m_$dNm(!9@n+CTyDa$w$*a^-$!>qK3P{4end8+qbAwoFEAV!JYD@<);T3K0RXh> Be)#|Z diff --git a/vector/src/main/res/drawable-mdpi/vector_micro_green.png b/vector/src/main/res/drawable-mdpi/vector_micro_green.png deleted file mode 100755 index 15114b7e71ac34437adbe2a98e55aff5231a17a2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 399 zcmeAS@N?(olHy`uVBq!ia0vp^9w5xY1|&n@ZgvM!Y)RhkE)4%caKYZ?lYt_f1s;*b z3=G`DAk4@xYmNj^kiEpy*OmPN6Azb)h28H)5e5cE8BZ6-kcwMxZ(kHWq#)pOF{h9B zW?ySWOY4n3)l62;kQtHF_WU$snr_ZiHcVT5@5pZA-Y+zvGP=F8$3=r0W$l}bM6|Y+qUyFoX zl-B|ZK4W}Um_O@Lj@@IPxU0`z%{x1dt6;nO-_EyZGu}69X`5YHTH7+QcCU;_psw;( z-T0$Zp1zOZIdt=8+|?&J+INg^-75UP`tZciZ~OV2zV0nsQ2&lMx>@RBY}QS#$91#9 z)=taxE?||hoWSh)cTVbU$?t7NZ(se?K9u3`Zf{8C0^21yGNFVdQ&MBb@0KGVuZ2$lO diff --git a/vector/src/main/res/drawable-mdpi/video_call_black.png b/vector/src/main/res/drawable-mdpi/video_call_black.png deleted file mode 100755 index 0039e804eb1684ea4ebc31799709a087f572e5f5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 224 zcmeAS@N?(olHy`uVBq!ia0vp^9w5xY0wn)GsXhawmV3H5hEy=Vy|MA+VFv-1hn?^8 z4~ug1g)FcZ2tQ~w=Lplx+X;0Q`O-fM6yDE!@w@{FUidGcwkmVlvbJqjp=XW1?wu~T z^_Jsx-sfxGL;v3?&|*&U<2W%#V1lKfLa~y=Gna-loeVRD8I9DLAQAzLOe`D%^2a{x z=bL%t*T#(tHXb^qa&Ey|=ZV3$mi+%IV|?53_`T+<7p`3W@mfYIs|#!;^C!uxN8C@h R>H?k2;OXk;vd$@?2>^U;U)TTu diff --git a/vector/src/main/res/drawable-mdpi/video_call_green.png b/vector/src/main/res/drawable-mdpi/video_call_green.png deleted file mode 100755 index 028ec1e3e302dde605f2d1a8862de2217926fd24..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 298 zcmeAS@N?(olHy`uVBq!ia0vp^9w5xY1|&n@ZgvM!Y)RhkE)4%caKYZ?lYt_f1s;*b z3=G`DAk4@xYmNj^kiEpy*OmPt2L~Uwq9gZHGoa9RPZ!6Kid%1QUgT{u5NQkCA-%J& z*`lR+N1yUbuGYAuH}&U?4IeV!y1gS8sG5Oc@wbWHa__G{m(P1vx%>Uy{gEs4kG*i# zFJze&rROEnxXf&pkh;xS->P)!2PJ-H@rHV$L$%!{Psm^&nbmf4NDs!00GCXBW5P9(i&9mcltT_n9>4aSD3%Ow3uICgQ2 zjr=FWc(D&`CQobQ>*Xz@9Ht9Lp&X-lu|@Xg_43>xNU@I>XQUCw| diff --git a/vector/src/main/res/drawable-mdpi/voice_call_end_fushia.png b/vector/src/main/res/drawable-mdpi/voice_call_end_fushia.png deleted file mode 100755 index 814aa0017ec07a455055bb0eb22c95204a72cbb7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 331 zcmeAS@N?(olHy`uVBq!ia0vp^9w5xY1|&n@ZgvM!Y)RhkE)4%caKYZ?lYt_f1s;*b z3=G`DAk4@xYmNj^kiEpy*OmPN2Pd15<(4UiKoN!;o-U3d6}R5rI4#(0z~kW9z3|Eu z*Y!_kIk(kp=;Hls6HD+YPol zAC+BvrAO4b#Zp)+t^0HKk_^dZ*Z9*<8@oPpjM}q2Wq$G8hlRh)KI{%S{ie|F?7og- znM~1VKPE;WvEkyHSs5(cxv~HO3k;4oxOt7FTe3vU+l70 z`ip>ia-T)@$9spa%u_uVv*WvkY1+@<%{Mg)&z<{pUH$sSM|TRvzz$_t@se|+bC%Ul RZ`TlzfTydU%Q~loCIBCygU0{> diff --git a/vector/src/main/res/drawable-mdpi/voice_call_green.png b/vector/src/main/res/drawable-mdpi/voice_call_green.png deleted file mode 100755 index 7afa5cd1188503686266a4b66f6d4e10cd070e9f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 432 zcmeAS@N?(olHy`uVBq!ia0vp^9w5xY1|&n@ZgvM!Y)RhkE)4%caKYZ?lYt_f1s;*b z3=G`DAk4@xYmNj^kiEpy*OmPt2L~Sy-_qHBD;O9UZ9QEaLn>~)opqb{kO7aYr+Jbr zTOtQrqO4m}eM`&b8y{ca$yc#ne!YK7j2?$#i+~fy-wPA|y!cnOFTBZS-S&y17d9%N z(0cHx!HC;|fk~i&fn~v-#d7S791aXw%o@py#TZZ3NH0IaaD^k_SkPRrilryh-X^o3 zD`cBe%jBnSADkw7t(p0`hPB6|MPA*i)f3nkoVkB6grRiT?3q&|M8$ctIo^I-kT+pQ z(lx$S@07MKS?%;_?iW4wvkWJmEP42JQmDuM!Zi!{&j(pmubAss%3AVFAgb0!>iQb- zGjcAIHk3`CeuU@qp*Qy*?p0gxa>n(hCp+bGq_?MgpA+hP!kBm0eUWb0I@^xbZo(ex zPF78i*&%fL#WDlVsvVklM7r6uYC2Ojc7L#4aCMOcZ-}OY*oIR~mzb{oe18@k5*dN= Y{8H1JWj_jB0ER7tr>mdKI;Vst0QrxrMgRZ+ diff --git a/vector/src/main/res/drawable-mdpi/voice_call_start_green.png b/vector/src/main/res/drawable-mdpi/voice_call_start_green.png deleted file mode 100755 index b11532ef5a34edaf915afa9f64be727aa763d796..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 684 zcmeAS@N?(olHy`uVBq!ia0vp^6F``Q4M;wBd$a>cu_bxCyDx`7I;J! zGca%qgD@k*tT_@uLG}_)Usv`A9L$_1f@*Sm+Zh;`EInNuLn>~)y>l?|u!DfB<4MVh ze2oGujT873Z@TME(G*{N_pkL`#sCi6^B$W%76J`{f|w(s)GsQw<=ByArcQTKst0xI`x+`cV*&Wu+R z!s^&UOV@1V7g|38p00i_>zopr0B$`3wEzGB diff --git a/vector/src/main/res/drawable-xhdpi/ic_send_sticker.png b/vector/src/main/res/drawable-xhdpi/ic_send_sticker.png deleted file mode 100644 index c17d04e498f80249f128587a9e76e3501504ee64..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4586 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 diff --git a/vector/src/main/res/drawable-xxhdpi/ic_material_camera.png b/vector/src/main/res/drawable-xxhdpi/ic_material_camera.png deleted file mode 100755 index 78e5bb23ffb7086c06c271d3775167fbb46799af..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 539 zcmeAS@N?(olHy`uVBq!ia0vp^2_VeD1|%QND7OGoY)RhkE)4%caKYZ?lYt_f1s;*b z3=G`DAk4@xYmNj^kiEpy*OmPNlMoLt&wHnBAq)(RD?D8sLn>~)opV<5kb(efteupX zwWf;ek_lTTPkMB+oBb^R2L7^Vc}@9cflWWE7=eZ`IGFfk8l2uItNU)V-)6-Fnl+}J zVum%UoMNUmqMTxuHLRRswl(>jZa?-3^?ayRy^+EAP3;25z3>*ned}9Xd>(NduG*g` zeu43v0s|ul1B(KKKm$X8LjRUE?+Y1cx^w^gUHVGtQ^vvXYD)c5HTp_HEgz!qFZO2C zZ4R6?p_=Ren=ggWs$QGSK2-8#pL~JZn%&7OD&GbrPl)T#{at3mxuSh*!|I0ktASd3 z>V@{&^H0ip>Ru@_QDpW0ts&?2JSMJ+-?%xbXGoCD4FiUjR4*>(su$bNjQE&ErRJ^13X}?rO)&E=9>#OR2@>Lkg zYM%R9BwL`mVv_xtpvrtB_N`ORUOM|Z>hABnfVmx6`ZP3E{1xSaH4 zY5&4De|M!wBZC726Epzc9kPEO)>3~?b}93VCabIUo(xK-*!V$V4F!c2%um^0rEq0C Q%7R2ZUHx3vIVCg!0B-!qZvX%Q diff --git a/vector/src/main/res/drawable-xxhdpi/ic_material_file.png b/vector/src/main/res/drawable-xxhdpi/ic_material_file.png deleted file mode 100755 index 64561dd4a46c142420570672762bddfe6787f914..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 545 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 B>+Jvl diff --git a/vector/src/main/res/drawable-xxhdpi/ic_send_sticker.png b/vector/src/main/res/drawable-xxhdpi/ic_send_sticker.png deleted file mode 100644 index a369cbee494db6f376916acfa2e9a41125454a71..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7243 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 Z{~v}UpUcfOD|G+>002ovPDHLkV1hrJ(nJ6N diff --git a/vector/src/main/res/drawable-xxhdpi/vector_cancel_upload_download.png b/vector/src/main/res/drawable-xxhdpi/vector_cancel_upload_download.png deleted file mode 100755 index 51b4401ca053ca8cad6e9903646709a2f44444df..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 309 zcmeAS@N?(olHy`uVBq!ia0vp^9w5xY0wn)GsXhaw{&>1LhEy=VysgJ$~x+g}6OvsxLimbaeN-!xQItoH=3nd`|H@dF!kYp_dChV`b9AudQLRn7yg2 zv~UiON9*MGOYAy6D=_*g@;c3(5`S(Hi^X;wk8Ms*3SMP^!WTf z-E_DAd$kLMWY`Z`);MuKF9=d$?_mzLoFj7Xp~|_3ODg!(3;AT&wLoS^O+0tsvcZJ& zD(m_$dNm(!9@n+CTyDa$w$*a^-$!>qK3P{4end8+qbAwoFEAV!JYD@<);T3K0RXh> Be)#|Z diff --git a/vector/src/main/res/drawable-xxhdpi/vector_micro_green.png b/vector/src/main/res/drawable-xxhdpi/vector_micro_green.png deleted file mode 100755 index 15114b7e71ac34437adbe2a98e55aff5231a17a2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 399 zcmeAS@N?(olHy`uVBq!ia0vp^9w5xY1|&n@ZgvM!Y)RhkE)4%caKYZ?lYt_f1s;*b z3=G`DAk4@xYmNj^kiEpy*OmPN6Azb)h28H)5e5cE8BZ6-kcwMxZ(kHWq#)pOF{h9B zW?ySWOY4n3)l62;kQtHF_WU$snr_ZiHcVT5@5pZA-Y+zvGP=F8$3=r0W$l}bM6|Y+qUyFoX zl-B|ZK4W}Um_O@Lj@@IPxU0`z%{x1dt6;nO-_EyZGu}69X`5YHTH7+QcCU;_psw;( z-T0$Zp1zOZIdt=8+|?&J+INg^-75UP`tZciZ~OV2zV0nsQ2&lMx>@RBY}QS#$91#9 z)=taxE?||hoWSh)cTVbU$?t7NZ(se?K9u3`Zf{8C0^21yGNFVdQ&MBb@0KGVuZ2$lO diff --git a/vector/src/main/res/drawable-xxhdpi/video_call_black.png b/vector/src/main/res/drawable-xxhdpi/video_call_black.png deleted file mode 100755 index 0039e804eb1684ea4ebc31799709a087f572e5f5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 224 zcmeAS@N?(olHy`uVBq!ia0vp^9w5xY0wn)GsXhawmV3H5hEy=Vy|MA+VFv-1hn?^8 z4~ug1g)FcZ2tQ~w=Lplx+X;0Q`O-fM6yDE!@w@{FUidGcwkmVlvbJqjp=XW1?wu~T z^_Jsx-sfxGL;v3?&|*&U<2W%#V1lKfLa~y=Gna-loeVRD8I9DLAQAzLOe`D%^2a{x z=bL%t*T#(tHXb^qa&Ey|=ZV3$mi+%IV|?53_`T+<7p`3W@mfYIs|#!;^C!uxN8C@h R>H?k2;OXk;vd$@?2>^U;U)TTu diff --git a/vector/src/main/res/drawable-xxhdpi/video_call_green.png b/vector/src/main/res/drawable-xxhdpi/video_call_green.png deleted file mode 100755 index 028ec1e3e302dde605f2d1a8862de2217926fd24..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 298 zcmeAS@N?(olHy`uVBq!ia0vp^9w5xY1|&n@ZgvM!Y)RhkE)4%caKYZ?lYt_f1s;*b z3=G`DAk4@xYmNj^kiEpy*OmPt2L~Uwq9gZHGoa9RPZ!6Kid%1QUgT{u5NQkCA-%J& z*`lR+N1yUbuGYAuH}&U?4IeV!y1gS8sG5Oc@wbWHa__G{m(P1vx%>Uy{gEs4kG*i# zFJze&rROEnxXf&pkh;xS->P)!2PJ-H@rHV$L$%!{Psm^&nbmf4NDs!00GCXBW5P9(i&9mcltT_n9>4aSD3%Ow3uICgQ2 zjr=FWc(D&`CQobQ>*Xz@9Ht9Lp&X-lu|@Xg_43>xNU@I>XQUCw| diff --git a/vector/src/main/res/drawable-xxhdpi/voice_call_end_fushia.png b/vector/src/main/res/drawable-xxhdpi/voice_call_end_fushia.png deleted file mode 100755 index 814aa0017ec07a455055bb0eb22c95204a72cbb7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 331 zcmeAS@N?(olHy`uVBq!ia0vp^9w5xY1|&n@ZgvM!Y)RhkE)4%caKYZ?lYt_f1s;*b z3=G`DAk4@xYmNj^kiEpy*OmPN2Pd15<(4UiKoN!;o-U3d6}R5rI4#(0z~kW9z3|Eu z*Y!_kIk(kp=;Hls6HD+YPol zAC+BvrAO4b#Zp)+t^0HKk_^dZ*Z9*<8@oPpjM}q2Wq$G8hlRh)KI{%S{ie|F?7og- znM~1VKPE;WvEkyHSs5(cxv~HO3k;4oxOt7FTe3vU+l70 z`ip>ia-T)@$9spa%u_uVv*WvkY1+@<%{Mg)&z<{pUH$sSM|TRvzz$_t@se|+bC%Ul RZ`TlzfTydU%Q~loCIBCygU0{> diff --git a/vector/src/main/res/drawable-xxhdpi/voice_call_green.png b/vector/src/main/res/drawable-xxhdpi/voice_call_green.png deleted file mode 100755 index 7afa5cd1188503686266a4b66f6d4e10cd070e9f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 432 zcmeAS@N?(olHy`uVBq!ia0vp^9w5xY1|&n@ZgvM!Y)RhkE)4%caKYZ?lYt_f1s;*b z3=G`DAk4@xYmNj^kiEpy*OmPt2L~Sy-_qHBD;O9UZ9QEaLn>~)opqb{kO7aYr+Jbr zTOtQrqO4m}eM`&b8y{ca$yc#ne!YK7j2?$#i+~fy-wPA|y!cnOFTBZS-S&y17d9%N z(0cHx!HC;|fk~i&fn~v-#d7S791aXw%o@py#TZZ3NH0IaaD^k_SkPRrilryh-X^o3 zD`cBe%jBnSADkw7t(p0`hPB6|MPA*i)f3nkoVkB6grRiT?3q&|M8$ctIo^I-kT+pQ z(lx$S@07MKS?%;_?iW4wvkWJmEP42JQmDuM!Zi!{&j(pmubAss%3AVFAgb0!>iQb- zGjcAIHk3`CeuU@qp*Qy*?p0gxa>n(hCp+bGq_?MgpA+hP!kBm0eUWb0I@^xbZo(ex zPF78i*&%fL#WDlVsvVklM7r6uYC2Ojc7L#4aCMOcZ-}OY*oIR~mzb{oe18@k5*dN= Y{8H1JWj_jB0ER7tr>mdKI;Vst0QrxrMgRZ+ diff --git a/vector/src/main/res/drawable-xxhdpi/voice_call_start_green.png b/vector/src/main/res/drawable-xxhdpi/voice_call_start_green.png deleted file mode 100755 index b11532ef5a34edaf915afa9f64be727aa763d796..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 684 zcmeAS@N?(olHy`uVBq!ia0vp^6F``Q4M;wBd$a>cu_bxCyDx`7I;J! zGca%qgD@k*tT_@uLG}_)Usv`A9L$_1f@*Sm+Zh;`EInNuLn>~)y>l?|u!DfB<4MVh ze2oGujT873Z@TME(G*{N_pkL`#sCi6^B$W%76J`{f|w(s)GsQw<=ByArcQTKst0xI`x+`cV*&Wu+R z!s^&UOV@1V7g|38p00i_>zopr0B$`3wEzGB diff --git a/vector/src/main/res/menu/vector_searches.xml b/vector/src/main/res/menu/vector_searches.xml deleted file mode 100755 index 542c433272..0000000000 --- a/vector/src/main/res/menu/vector_searches.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - From d85776297d18a6e5e832f77cf854d76f321ae09f Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 27 Feb 2020 14:56:18 +0100 Subject: [PATCH 07/91] Lint: fix IconDuplicates by remove unused resources --- vector/lint.xml | 1 + .../drawable-hdpi/ic_person_black_24dp.png | Bin 269 -> 0 bytes .../drawable-mdpi/ic_person_black_24dp.png | Bin 189 -> 0 bytes .../drawable-xhdpi/ic_person_black_24dp.png | Bin 307 -> 0 bytes .../res/drawable-xxhdpi/ic_devices_info.png | Bin 240 -> 0 bytes .../ic_material_message_black.png | Bin 318 -> 0 bytes .../ic_material_message_grey.png | Bin 712 -> 0 bytes .../ic_perm_device_information_black.png | Bin 240 -> 0 bytes .../res/drawable-xxhdpi/ic_person_black.png | Bin 428 -> 0 bytes .../drawable-xxhdpi/ic_person_black_24dp.png | Bin 428 -> 0 bytes .../drawable-xxhdpi/vector_close_widget.png | Bin 309 -> 0 bytes .../vector_create_direct_room.png | Bin 1787 -> 0 bytes .../vector_creation_remove_user.png | Bin 309 -> 0 bytes .../vector_leave_room_black.png | Bin 309 -> 0 bytes .../drawable-xxxhdpi/ic_person_black_24dp.png | Bin 565 -> 0 bytes .../res/menu/vector_home_group_settings.xml | 7 --- vector/src/main/res/menu/vector_room.xml | 43 ------------------ 17 files changed, 1 insertion(+), 50 deletions(-) delete mode 100644 vector/src/main/res/drawable-hdpi/ic_person_black_24dp.png delete mode 100644 vector/src/main/res/drawable-mdpi/ic_person_black_24dp.png delete mode 100644 vector/src/main/res/drawable-xhdpi/ic_person_black_24dp.png delete mode 100755 vector/src/main/res/drawable-xxhdpi/ic_devices_info.png delete mode 100644 vector/src/main/res/drawable-xxhdpi/ic_material_message_black.png delete mode 100644 vector/src/main/res/drawable-xxhdpi/ic_material_message_grey.png delete mode 100755 vector/src/main/res/drawable-xxhdpi/ic_perm_device_information_black.png delete mode 100755 vector/src/main/res/drawable-xxhdpi/ic_person_black.png delete mode 100644 vector/src/main/res/drawable-xxhdpi/ic_person_black_24dp.png delete mode 100755 vector/src/main/res/drawable-xxhdpi/vector_close_widget.png delete mode 100755 vector/src/main/res/drawable-xxhdpi/vector_create_direct_room.png delete mode 100755 vector/src/main/res/drawable-xxhdpi/vector_creation_remove_user.png delete mode 100755 vector/src/main/res/drawable-xxhdpi/vector_leave_room_black.png delete mode 100644 vector/src/main/res/drawable-xxxhdpi/ic_person_black_24dp.png delete mode 100755 vector/src/main/res/menu/vector_home_group_settings.xml delete mode 100755 vector/src/main/res/menu/vector_room.xml diff --git a/vector/lint.xml b/vector/lint.xml index 6d4c4125ef..2a7197e534 100644 --- a/vector/lint.xml +++ b/vector/lint.xml @@ -9,6 +9,7 @@ + diff --git a/vector/src/main/res/drawable-hdpi/ic_person_black_24dp.png b/vector/src/main/res/drawable-hdpi/ic_person_black_24dp.png deleted file mode 100644 index 6fbcc6d4258cf676f816ee8970ad77e06bf74f9f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 269 zcmV+o0rLKdP)I`H9;{R%N3%Udmjd26I6u~}~xB@LCArhk-&_cUGBxnlZYAM5q%#4W5 zoTq=`!qxhvT+hJN%*c^kLu)4DTN5i9$W274u}p0}k!VkC1Ci)TZBvn`_{X92X_sp2 zibT6=%iW4nHx@LoYFzrFWesHxTzmCq=uoEhCpxyA=(|_=_^NQH@7Sh}iZVMc%!G9B z&TY&5XkOQ|sL+#rbEIt;i5d;9OIY$KYW84}vNO@3Q_5aMg9^%`S?y4TDruBU-cV>nBw2MvWwby8c0^P&l>FVdQ&MBb@07o52e*gdg diff --git a/vector/src/main/res/drawable-xhdpi/ic_person_black_24dp.png b/vector/src/main/res/drawable-xhdpi/ic_person_black_24dp.png deleted file mode 100644 index 360a32f27cd837c6e2036bf8087f3fbd440d26af..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 307 zcmV-30nGl1P)8`r`AL0Dh?&)4uZS5=#i{jTauwS5FB-rB8cb#+9sDUC`vn+$E-^GHOc!q zDBthD=Sjj#5Cjdxq~xrsG7=)Z+F^peRg%*4_xO9Xrm3%q3EEJC2Qk`MNrYL79E~x{ zk)t_gE97YT2L>|aXogvW91SsxC>>|ohu=KZ5nl9|qBY&o1z!^><&U2;qKj7%W9BTY zW(?^Q{40B$bIC0W3O=g}7Thr4j9rXk2IR<5#s!D8(BYJ4RI?{e=+M9ckEme}>{HV* zZ>UAD9MyaK57e^vI$v>(3|+BRfegK{m5enX2m?V7d;xL&3kk*tXR!bP002ovPDHLk FV1itgfiM67 diff --git a/vector/src/main/res/drawable-xxhdpi/ic_devices_info.png b/vector/src/main/res/drawable-xxhdpi/ic_devices_info.png deleted file mode 100755 index 0ac10c8f3317acfb8ba5102d361f1133465a72aa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 240 zcmeAS@N?(olHy`uVBq!ia0vp^9w5xY0wn)GsXhawwtKobhEy=Vy?M~9-9g0d<7TP* zj`IsQTn}kp7WY*C(xP2!wX=%z1&YpX7yYTr=6YmZ#Ny3`%5^t?Pv2X6OZ$9Ii4?0Y z&!UXxnJK-FB6$})u690JyX02KBiSXp1dm#KihdRTa+!tm*X!RLLMj@iy$X&^HGG^x zPj>rE05VxPg;YEy+)o8EPWb}`?pOcJ-+%Ib=cBhvb}4sV_cZQtU6xC`h722WQ%mvv4FO#pytV%Gow diff --git a/vector/src/main/res/drawable-xxhdpi/ic_material_message_black.png b/vector/src/main/res/drawable-xxhdpi/ic_material_message_black.png deleted file mode 100644 index 0d989b2bcd7dc84e35e5da655d154f9b4fd4c857..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 318 zcmeAS@N?(olHy`uVBq!ia0vp^2_VeD0wg^q?%&M7z{u+9;uuoF`1Z;{-@^_PtPgii zj0<2g8&Z+DtJXuTQd&Fq#Y z{c>skHqQgI)Eyca7_-$MtYrW(n7CrJ91dv8P59iw$|0bT(8{vsGWVPYCUu3+g4_ZM z51bnsL>XEAfGYpXUSQ$)@$6X10Y%vjr`b%l-E6Q`VV1Kv&1&-P^t0d(k8L(2bAOO- z&^{$@H~-7eCFj*^?OuNNobUgu=F;=Ys6v-&jEy(@|2I0eLH&|)8!%iLJYD@<);T3K F0RYTwgvtN_ diff --git a/vector/src/main/res/drawable-xxhdpi/ic_material_message_grey.png b/vector/src/main/res/drawable-xxhdpi/ic_material_message_grey.png deleted file mode 100644 index 92a1da89f601ed2fb474d9ac5c4d78a796a3a054..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 712 zcmeAS@N?(olHy`uVBq!ia0vp^6F``Q4M;wBd$farfvMlq#WAGf*4sOVe$tL24T@xciGJSKPuY*00ZLEDZ)s+`Li7+C}y zV8n$D44OX^wSat;hASEis-4+56qd54te#gR&5uw8W(D{<{6{fvK_X+&r^6vY<2@Kw z20C!#*Xxb!45o~ThADpxM1gJ-a>x?7aB2c0&=9Z>fC3=%UW%DA*h-Y#dd9HQ-?-t* za!rS>ZE@EH9lFY7DxHKB*6!A43Wg^31;2o7punsD_PjO> z2N#358azOOLnJZ+B?N4^n48@9GI&D#!7_mblxCPbK)z|6#~`q1;l+YYn{P7!fv2mV J%Q~loCIGMN`2PR^ diff --git a/vector/src/main/res/drawable-xxhdpi/ic_perm_device_information_black.png b/vector/src/main/res/drawable-xxhdpi/ic_perm_device_information_black.png deleted file mode 100755 index 0ac10c8f3317acfb8ba5102d361f1133465a72aa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 240 zcmeAS@N?(olHy`uVBq!ia0vp^9w5xY0wn)GsXhawwtKobhEy=Vy?M~9-9g0d<7TP* zj`IsQTn}kp7WY*C(xP2!wX=%z1&YpX7yYTr=6YmZ#Ny3`%5^t?Pv2X6OZ$9Ii4?0Y z&!UXxnJK-FB6$})u690JyX02KBiSXp1dm#KihdRTa+!tm*X!RLLMj@iy$X&^HGG^x zPj>rE05VxPg;YEy+)o8EPWb}`?pOcJ-+%Ib=cBhvb}4sV_cZQtU6xC`h722WQ%mvv4FO#pytV%Gow diff --git a/vector/src/main/res/drawable-xxhdpi/ic_person_black.png b/vector/src/main/res/drawable-xxhdpi/ic_person_black.png deleted file mode 100755 index f1e148490b9b0ab76648553a96da8ee27ba0b8be..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 428 zcmV;d0aN~oP)IS7U|zrX^K8 zYaj=Djz=}bpbDN8SRn=_1bER!3~S>-krXj3CB(TVVo?Lhed z{|IQ4B71FVagCD+X)s{Mde@9Tbpn)9|D_zac+4w$Oo&O??n;Q6(B&mnZj!^3dqfOL z48GPO5qELu4sZB^SQhh|5*fR|BR(KUH0B{WGV*{=NCr*0&(W^%4#}{$T;>QRVkF}} zbDO_(gKvm~zH%LVTw;ni>LVAi_7rj06ReF9hrP$z55!^Lu_kWQK{`kW{Uel8N~vG5 Wub7svB(2u~0000IS7U|zrX^K8 zYaj=Djz=}bpbDN8SRn=_1bER!3~S>-krXj3CB(TVVo?Lhed z{|IQ4B71FVagCD+X)s{Mde@9Tbpn)9|D_zac+4w$Oo&O??n;Q6(B&mnZj!^3dqfOL z48GPO5qELu4sZB^SQhh|5*fR|BR(KUH0B{WGV*{=NCr*0&(W^%4#}{$T;>QRVkF}} zbDO_(gKvm~zH%LVTw;ni>LVAi_7rj06ReF9hrP$z55!^Lu_kWQK{`kW{Uel8N~vG5 Wub7svB(2u~00001LhEy=VysgJ$~x+g}6OvsxLimbaeN-!xQItoH=3nd`|H@dF!kYp_dChV`b9AudQLRn7yg2 zv~UiON9*MGOYAy6D=_*g@;c3(5`S(Hi^X;wk8Ms*3SMP^!WTf z-E_DAd$kLMWY`Z`);MuKF9=d$?_mzLoFj7Xp~|_3ODg!(3;AT&wLoS^O+0tsvcZJ& zD(m_$dNm(!9@n+CTyDa$w$*a^-$!>qK3P{4end8+qbAwoFEAV!JYD@<);T3K0RXh> Be)#|Z diff --git a/vector/src/main/res/drawable-xxhdpi/vector_create_direct_room.png b/vector/src/main/res/drawable-xxhdpi/vector_create_direct_room.png deleted file mode 100755 index a5b2b57497d496ad8e3807e35dfb29992eabb93f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1787 zcmV469L4=^lShC28c;S zK~#9!?VMX|6jd0<|KIHF(%J%YjT%~#-4;q35(NdC5VOGSY&PK%*&r?uH2Q=ZQ)i4{z^1o1(5X}~lj^03*R>Cz}|HKsu&)wGr|6fp*92vBs{**V7tD(QvUPCM;% zZ{OQ)&iVG7-+q_#ojG%Wq7=oB&~y(V6bj8S3}ZGC&ElNT1^^g4C7Tn5Vms8 zeUqfN7eF&(>~u>@%da^H$nW=yZnrxE;2i+ZPw{{7BN2U`N~O-Uwzj6T8j#=b7d;-& z>zwoV0eBsa6+~A6989HBrzR8Bqyds7DM&;|2II@=uVGj{)_jZnX>C&mNS5XI0DPRorIqCK`35vi>zH&vk|gZ_a4g3x#|+YMnx>KD-n@CHZ9wUC`jaeJ9Z!W+CzHvK zY`K^uNq!RwQJX$ zf^=Ee^%Z6Xu4vY4-n@CcIp>bRsi~EKFpPDkfCis<7B-;~41^IrxC}*EmdS!@ihNM> zSU`TiznpXaRFMy!sjI6i9aXHBmX2&&@%jL4AxUa7d_4W0L zL?S3FE3@2h$&w`~FCXsV0|Nu->FKeo_^;4&UAF>gvMYy?dv_5Sgy)Wv#8P$zd)wc#h_JaT$bb|HFA)knS$>8O~s2 zEmrV=h^RYLEq1Zc0WrodW&+d#fEO?y?smH`m;#E&<2N|xJp~M?D;ka7GzBzhMP~{a z&{@-!^bkN_6{wpr!!S;d2`C1S0|LN_=rgBA*WBC;UDqFd)^#1t&CO1_*QaK2*R(J_ zaNvN@*4EYrV2u-loW=uG?TVtT9XB8VkY#x#=llmu@I-zNNSbrLLRHnvW(_j#D8}RQ zP5>wKxb8Zh3C@^+06-MQdH|hy2&bdJzyIB_+KmY)8jU_M3}ZWhJ9)&XpE34IXJ@Bw z8xQ~_5{WASb^|c-A?^U!t*UCDmByBXucm3;Uaz;8h_)hk&rLHT+NCJUIjbGUm7O$A zyX^D%bO0N26wn8XqMR5{hjFKGP1C;f`Ft9HjX9M5bpWp^igJ9s9VawFP1Anydc9pl zv=Q0=*5Lr>Jff=V*AvQic7A#N`t^%lF4tKAtFjc%_nhSO=_002ovPDHLkV1i;qL;C;# diff --git a/vector/src/main/res/drawable-xxhdpi/vector_creation_remove_user.png b/vector/src/main/res/drawable-xxhdpi/vector_creation_remove_user.png deleted file mode 100755 index 51b4401ca053ca8cad6e9903646709a2f44444df..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 309 zcmeAS@N?(olHy`uVBq!ia0vp^9w5xY0wn)GsXhaw{&>1LhEy=VysgJ$~x+g}6OvsxLimbaeN-!xQItoH=3nd`|H@dF!kYp_dChV`b9AudQLRn7yg2 zv~UiON9*MGOYAy6D=_*g@;c3(5`S(Hi^X;wk8Ms*3SMP^!WTf z-E_DAd$kLMWY`Z`);MuKF9=d$?_mzLoFj7Xp~|_3ODg!(3;AT&wLoS^O+0tsvcZJ& zD(m_$dNm(!9@n+CTyDa$w$*a^-$!>qK3P{4end8+qbAwoFEAV!JYD@<);T3K0RXh> Be)#|Z diff --git a/vector/src/main/res/drawable-xxhdpi/vector_leave_room_black.png b/vector/src/main/res/drawable-xxhdpi/vector_leave_room_black.png deleted file mode 100755 index 51b4401ca053ca8cad6e9903646709a2f44444df..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 309 zcmeAS@N?(olHy`uVBq!ia0vp^9w5xY0wn)GsXhaw{&>1LhEy=VysgJ$~x+g}6OvsxLimbaeN-!xQItoH=3nd`|H@dF!kYp_dChV`b9AudQLRn7yg2 zv~UiON9*MGOYAy6D=_*g@;c3(5`S(Hi^X;wk8Ms*3SMP^!WTf z-E_DAd$kLMWY`Z`);MuKF9=d$?_mzLoFj7Xp~|_3ODg!(3;AT&wLoS^O+0tsvcZJ& zD(m_$dNm(!9@n+CTyDa$w$*a^-$!>qK3P{4end8+qbAwoFEAV!JYD@<);T3K0RXh> Be)#|Z diff --git a/vector/src/main/res/drawable-xxxhdpi/ic_person_black_24dp.png b/vector/src/main/res/drawable-xxxhdpi/ic_person_black_24dp.png deleted file mode 100644 index 1ebc37be1701e3932b1d8c4de99edb246c7ae1c5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 565 zcmV-50?Pe~P)}mEdFOO0kk66l|j-6?~9x1EYin+HvWh zjh(a$!K9k0^!NfrGjnHhZ{U2sFEBs2bI6raN-3q3Qc9IsCm`g6goI;40&0{Q3ybV> zid;~ix6I?TD>OJm{!zjUJRG&a0Ww4#d>ph)7a6jcDvnv8i=-&V$01iaKvLGh!x;@E zLmN0^kuxMi2|iBPMKTuPfNPv08S7EPx^={$HLME|gPK?uA_ldv?gTL?#<~PCXrKd( z9b0}v`V+qy_cK~U3|hsy5`83NKbgS+f!PDHZ=NLM37y3e8%Tzp;tY=tlCn0_IK(GL zQuLjhIHt-`iqBudL38X6`FLh=l*ez zvdRofDW#OtrdXoJW8SgHAu)aaApEAwC-!*H6Yf)G3g=v>&Nd%OkReKFvqPN<)=hAi z1`(36h)q_wgcZxYBt|grh%N3gLX*@9k(~R$112fl1P}R!6x3H9ahU?G5FrH@agRcH z>~M~Zq-{KMRv|=2Septts_+>ZabLJWPRbl27K$j7i&u!H0x)-rbHq~T+{V}@VzDiZ z?IRY8F!lqn*e{HU<#d1!&;dH2h;)EbN-3q3QcC>=IV&s}(aLsG00000NkvXXu0mjf D>pAVy diff --git a/vector/src/main/res/menu/vector_home_group_settings.xml b/vector/src/main/res/menu/vector_home_group_settings.xml deleted file mode 100755 index e40c4b487f..0000000000 --- a/vector/src/main/res/menu/vector_home_group_settings.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - \ No newline at end of file diff --git a/vector/src/main/res/menu/vector_room.xml b/vector/src/main/res/menu/vector_room.xml deleted file mode 100755 index bb84a3ff29..0000000000 --- a/vector/src/main/res/menu/vector_room.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - - - - - - - - - - - From 12861aacdae6f93f5870fa3ab45412aa43e48618 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 27 Feb 2020 15:11:43 +0100 Subject: [PATCH 08/91] lint: check negative margin --- vector/lint.xml | 2 ++ .../src/main/res/layout/vector_message_merge_avatar_list.xml | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/vector/lint.xml b/vector/lint.xml index 2a7197e534..c74fcef250 100644 --- a/vector/lint.xml +++ b/vector/lint.xml @@ -10,6 +10,7 @@ + @@ -23,6 +24,7 @@ + diff --git a/vector/src/main/res/layout/vector_message_merge_avatar_list.xml b/vector/src/main/res/layout/vector_message_merge_avatar_list.xml index 853dfc80d7..58f38ada0e 100644 --- a/vector/src/main/res/layout/vector_message_merge_avatar_list.xml +++ b/vector/src/main/res/layout/vector_message_merge_avatar_list.xml @@ -21,6 +21,7 @@ android:layout_marginLeft="-5dp" android:adjustViewBounds="true" android:scaleType="centerCrop" + tools:ignore="NegativeMargin" tools:src="@tools:sample/avatars" /> \ No newline at end of file From 36a848471f84db9482a09a707f308b9471fbe9d4 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 27 Feb 2020 15:27:46 +0100 Subject: [PATCH 09/91] Enable other lint check (no change necessary in source) --- vector/lint.xml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/vector/lint.xml b/vector/lint.xml index c74fcef250..c5fe018fd9 100644 --- a/vector/lint.xml +++ b/vector/lint.xml @@ -37,9 +37,10 @@ + - + From 9f28738fd6095c4592f7419db4e1afd57d1fd4cf Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 27 Feb 2020 15:41:35 +0100 Subject: [PATCH 10/91] Restore availability to Chromebooks (#932) --- CHANGES.md | 2 +- vector/lint.xml | 3 +++ vector/src/main/AndroidManifest.xml | 9 +++++++++ 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index ea6aee07c4..da27d0a0e1 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -20,7 +20,7 @@ Build 🧱: - Upgrade ktlint to version 0.36.0 Other changes: - - + - Restore availability to Chromebooks (#932) Changes in RiotX 0.17.0 (2020-02-27) =================================================== diff --git a/vector/lint.xml b/vector/lint.xml index c5fe018fd9..3d3bb1856f 100644 --- a/vector/lint.xml +++ b/vector/lint.xml @@ -43,4 +43,7 @@ + + + diff --git a/vector/src/main/AndroidManifest.xml b/vector/src/main/AndroidManifest.xml index 488f357c4b..2e56e20ce7 100644 --- a/vector/src/main/AndroidManifest.xml +++ b/vector/src/main/AndroidManifest.xml @@ -9,6 +9,15 @@ + + + + + Date: Thu, 27 Feb 2020 17:03:48 +0100 Subject: [PATCH 11/91] Verification with QrCode: ensure there is a Camera to scan QrCodes. --- .../riotx/core/hardware/HardwareInfo.kt | 46 ++++++++++++++++++ .../features/crypto/verification/Config.kt | 29 ------------ .../SupportedVerificationMethodsProvider.kt | 47 +++++++++++++++++++ .../VerificationBottomSheetViewModel.kt | 24 ++++++---- .../home/room/detail/RoomDetailViewModel.kt | 22 +++++---- .../features/navigation/DefaultNavigator.kt | 10 ++-- .../settings/devices/DevicesViewModel.kt | 12 +++-- 7 files changed, 134 insertions(+), 56 deletions(-) create mode 100644 vector/src/main/java/im/vector/riotx/core/hardware/HardwareInfo.kt delete mode 100644 vector/src/main/java/im/vector/riotx/features/crypto/verification/Config.kt create mode 100644 vector/src/main/java/im/vector/riotx/features/crypto/verification/SupportedVerificationMethodsProvider.kt diff --git a/vector/src/main/java/im/vector/riotx/core/hardware/HardwareInfo.kt b/vector/src/main/java/im/vector/riotx/core/hardware/HardwareInfo.kt new file mode 100644 index 0000000000..1ce0dda025 --- /dev/null +++ b/vector/src/main/java/im/vector/riotx/core/hardware/HardwareInfo.kt @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2020 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. + */ + +@file:Suppress("DEPRECATION") + +package im.vector.riotx.core.hardware + +import android.content.Context +import android.hardware.Camera +import android.hardware.camera2.CameraCharacteristics +import android.hardware.camera2.CameraManager +import android.os.Build +import javax.inject.Inject + +class HardwareInfo @Inject constructor( + private val context: Context +) { + /** + * Tell if the device has a back (or external) camera + */ + fun hasBackCamera(): Boolean { + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { + return Camera.getNumberOfCameras() > 0 + } + + val manager = context.getSystemService(Context.CAMERA_SERVICE) as CameraManager? ?: return Camera.getNumberOfCameras() > 0 + + return manager.cameraIdList.any { + val lensFacing = manager.getCameraCharacteristics(it).get(CameraCharacteristics.LENS_FACING) + lensFacing == CameraCharacteristics.LENS_FACING_BACK || lensFacing == CameraCharacteristics.LENS_FACING_EXTERNAL + } + } +} diff --git a/vector/src/main/java/im/vector/riotx/features/crypto/verification/Config.kt b/vector/src/main/java/im/vector/riotx/features/crypto/verification/Config.kt deleted file mode 100644 index 80f2b1153a..0000000000 --- a/vector/src/main/java/im/vector/riotx/features/crypto/verification/Config.kt +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright 2020 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.riotx.features.crypto.verification - -import im.vector.matrix.android.api.session.crypto.verification.VerificationMethod - -val supportedVerificationMethods = - listOf( - // RiotX supports SAS verification - VerificationMethod.SAS, - // RiotX is able to show QR codes - VerificationMethod.QR_CODE_SHOW, - // RiotX is able to scan QR codes - VerificationMethod.QR_CODE_SCAN - ) diff --git a/vector/src/main/java/im/vector/riotx/features/crypto/verification/SupportedVerificationMethodsProvider.kt b/vector/src/main/java/im/vector/riotx/features/crypto/verification/SupportedVerificationMethodsProvider.kt new file mode 100644 index 0000000000..e7ed123de6 --- /dev/null +++ b/vector/src/main/java/im/vector/riotx/features/crypto/verification/SupportedVerificationMethodsProvider.kt @@ -0,0 +1,47 @@ +/* + * Copyright 2020 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.riotx.features.crypto.verification + +import im.vector.matrix.android.api.session.crypto.verification.VerificationMethod +import im.vector.riotx.core.hardware.HardwareInfo +import timber.log.Timber +import javax.inject.Inject + +class SupportedVerificationMethodsProvider @Inject constructor( + private val hardwareInfo: HardwareInfo +) { + /** + * Provide the list of supported method by RiotX, with or without the QR_CODE_SCAN, depending if a back camera + * is available + */ + fun provide(): List { + return mutableListOf( + // RiotX supports SAS verification + VerificationMethod.SAS, + // RiotX is able to show QR codes + VerificationMethod.QR_CODE_SHOW) + .apply { + if (hardwareInfo.hasBackCamera()) { + // RiotX is able to scan QR codes, and a Camera is available + add(VerificationMethod.QR_CODE_SCAN) + } else { + // This quite uncommon + Timber.w("No back Camera detected") + } + } + } +} diff --git a/vector/src/main/java/im/vector/riotx/features/crypto/verification/VerificationBottomSheetViewModel.kt b/vector/src/main/java/im/vector/riotx/features/crypto/verification/VerificationBottomSheetViewModel.kt index c5fd167f39..29caea9683 100644 --- a/vector/src/main/java/im/vector/riotx/features/crypto/verification/VerificationBottomSheetViewModel.kt +++ b/vector/src/main/java/im/vector/riotx/features/crypto/verification/VerificationBottomSheetViewModel.kt @@ -63,9 +63,11 @@ data class VerificationBottomSheetViewState( val isMe: Boolean = false ) : MvRxState -class VerificationBottomSheetViewModel @AssistedInject constructor(@Assisted initialState: VerificationBottomSheetViewState, - @Assisted args: VerificationBottomSheet.VerificationArgs, - private val session: Session) +class VerificationBottomSheetViewModel @AssistedInject constructor( + @Assisted initialState: VerificationBottomSheetViewState, + @Assisted args: VerificationBottomSheet.VerificationArgs, + private val session: Session, + private val supportedVerificationMethodsProvider: SupportedVerificationMethodsProvider) : VectorViewModel(initialState), VerificationService.Listener { @@ -116,9 +118,11 @@ class VerificationBottomSheetViewModel @AssistedInject constructor(@Assisted ini if (autoReady) { // TODO, can I be here in DM mode? in this case should test if roomID is null? session.cryptoService().verificationService() - .readyPendingVerification(supportedVerificationMethods, + .readyPendingVerification( + supportedVerificationMethodsProvider.provide(), pr!!.otherUserId, - pr.transactionId ?: "") + pr.transactionId ?: "" + ) } } @@ -173,7 +177,7 @@ class VerificationBottomSheetViewModel @AssistedInject constructor(@Assisted ini session .cryptoService() .verificationService() - .requestKeyVerificationInDMs(supportedVerificationMethods, otherUserId, data, pendingLocalId) + .requestKeyVerificationInDMs(supportedVerificationMethodsProvider.provide(), otherUserId, data, pendingLocalId) ) ) } @@ -191,7 +195,7 @@ class VerificationBottomSheetViewModel @AssistedInject constructor(@Assisted ini pendingRequest = Success(session .cryptoService() .verificationService() - .requestKeyVerificationInDMs(supportedVerificationMethods, otherUserId, roomId) + .requestKeyVerificationInDMs(supportedVerificationMethodsProvider.provide(), otherUserId, roomId) ) ) } @@ -362,9 +366,11 @@ class VerificationBottomSheetViewModel @AssistedInject constructor(@Assisted ini // auto ready in this case, as we are waiting // TODO, can I be here in DM mode? in this case should test if roomID is null? session.cryptoService().verificationService() - .readyPendingVerification(supportedVerificationMethods, + .readyPendingVerification( + supportedVerificationMethodsProvider.provide(), pr.otherUserId, - pr.transactionId ?: "") + pr.transactionId ?: "" + ) } // Use this one! diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailViewModel.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailViewModel.kt index 8a231fb25d..f98dd1ae5c 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailViewModel.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailViewModel.kt @@ -65,7 +65,7 @@ import im.vector.riotx.core.resources.UserPreferencesProvider import im.vector.riotx.core.utils.subscribeLogError import im.vector.riotx.features.command.CommandParser import im.vector.riotx.features.command.ParsedCommand -import im.vector.riotx.features.crypto.verification.supportedVerificationMethods +import im.vector.riotx.features.crypto.verification.SupportedVerificationMethodsProvider import im.vector.riotx.features.home.room.detail.composer.rainbow.RainbowGenerator import im.vector.riotx.features.home.room.detail.timeline.helper.TimelineDisplayableEvents import im.vector.riotx.features.home.room.typing.TypingHelper @@ -81,13 +81,15 @@ import java.io.File import java.util.concurrent.TimeUnit import java.util.concurrent.atomic.AtomicBoolean -class RoomDetailViewModel @AssistedInject constructor(@Assisted initialState: RoomDetailViewState, - userPreferencesProvider: UserPreferencesProvider, - private val vectorPreferences: VectorPreferences, - private val stringProvider: StringProvider, - private val typingHelper: TypingHelper, - private val rainbowGenerator: RainbowGenerator, - private val session: Session +class RoomDetailViewModel @AssistedInject constructor( + @Assisted initialState: RoomDetailViewState, + userPreferencesProvider: UserPreferencesProvider, + private val vectorPreferences: VectorPreferences, + private val stringProvider: StringProvider, + private val typingHelper: TypingHelper, + private val rainbowGenerator: RainbowGenerator, + private val session: Session, + private val supportedVerificationMethodsProvider: SupportedVerificationMethodsProvider ) : VectorViewModel(initialState), Timeline.Listener { private val room = session.getRoom(initialState.roomId)!! @@ -421,7 +423,7 @@ class RoomDetailViewModel @AssistedInject constructor(@Assisted initialState: Ro session .cryptoService() .verificationService() - .requestKeyVerificationInDMs(supportedVerificationMethods, slashCommandResult.userId, room.roomId) + .requestKeyVerificationInDMs(supportedVerificationMethodsProvider.provide(), slashCommandResult.userId, room.roomId) _viewEvents.post(RoomDetailViewEvents.SlashCommandHandled()) popDraft() } @@ -828,7 +830,7 @@ class RoomDetailViewModel @AssistedInject constructor(@Assisted initialState: Ro private fun handleAcceptVerification(action: RoomDetailAction.AcceptVerificationRequest) { Timber.v("## SAS handleAcceptVerification ${action.otherUserId}, roomId:${room.roomId}, txId:${action.transactionId}") if (session.cryptoService().verificationService().readyPendingVerificationInDMs( - supportedVerificationMethods, + supportedVerificationMethodsProvider.provide(), action.otherUserId, room.roomId, action.transactionId)) { diff --git a/vector/src/main/java/im/vector/riotx/features/navigation/DefaultNavigator.kt b/vector/src/main/java/im/vector/riotx/features/navigation/DefaultNavigator.kt index 63fab290be..a080cabf1b 100644 --- a/vector/src/main/java/im/vector/riotx/features/navigation/DefaultNavigator.kt +++ b/vector/src/main/java/im/vector/riotx/features/navigation/DefaultNavigator.kt @@ -24,7 +24,6 @@ import androidx.core.app.ActivityOptionsCompat import androidx.core.app.TaskStackBuilder import androidx.core.view.ViewCompat import im.vector.matrix.android.api.session.crypto.verification.IncomingSasVerificationTransaction -import im.vector.matrix.android.api.session.crypto.verification.VerificationMethod import im.vector.matrix.android.api.session.room.model.roomdirectory.PublicRoom import im.vector.matrix.android.api.util.MatrixItem import im.vector.riotx.R @@ -35,6 +34,7 @@ import im.vector.riotx.core.utils.toast import im.vector.riotx.features.createdirect.CreateDirectRoomActivity import im.vector.riotx.features.crypto.keysbackup.settings.KeysBackupManageActivity import im.vector.riotx.features.crypto.keysbackup.setup.KeysBackupSetupActivity +import im.vector.riotx.features.crypto.verification.SupportedVerificationMethodsProvider import im.vector.riotx.features.crypto.verification.VerificationBottomSheet import im.vector.riotx.features.debug.DebugMenuActivity import im.vector.riotx.features.home.room.detail.RoomDetailActivity @@ -56,7 +56,8 @@ import javax.inject.Singleton @Singleton class DefaultNavigator @Inject constructor( private val sessionHolder: ActiveSessionHolder, - private val vectorPreferences: VectorPreferences + private val vectorPreferences: VectorPreferences, + private val supportedVerificationMethodsProvider: SupportedVerificationMethodsProvider ) : Navigator { override fun openRoom(context: Context, roomId: String, eventId: String?, buildTask: Boolean) { @@ -85,9 +86,10 @@ class DefaultNavigator @Inject constructor( override fun requestSessionVerification(context: Context) { val session = sessionHolder.getSafeActiveSession() ?: return val pr = session.cryptoService().verificationService().requestKeyVerification( - listOf(VerificationMethod.SAS, VerificationMethod.QR_CODE_SCAN, VerificationMethod.QR_CODE_SHOW), + supportedVerificationMethodsProvider.provide(), session.myUserId, - session.cryptoService().getUserDevices(session.myUserId).map { it.deviceId }) + session.cryptoService().getUserDevices(session.myUserId).map { it.deviceId } + ) if (context is VectorBaseActivity) { VerificationBottomSheet.withArgs( roomId = null, diff --git a/vector/src/main/java/im/vector/riotx/features/settings/devices/DevicesViewModel.kt b/vector/src/main/java/im/vector/riotx/features/settings/devices/DevicesViewModel.kt index ce6e388af6..79a5fe84aa 100644 --- a/vector/src/main/java/im/vector/riotx/features/settings/devices/DevicesViewModel.kt +++ b/vector/src/main/java/im/vector/riotx/features/settings/devices/DevicesViewModel.kt @@ -40,7 +40,7 @@ import im.vector.matrix.android.internal.crypto.model.rest.DeviceInfo import im.vector.matrix.android.internal.crypto.model.rest.DevicesListResponse import im.vector.matrix.rx.rx import im.vector.riotx.core.platform.VectorViewModel -import im.vector.riotx.features.crypto.verification.supportedVerificationMethods +import im.vector.riotx.features.crypto.verification.SupportedVerificationMethodsProvider data class DevicesViewState( val myDeviceId: String = "", @@ -50,8 +50,10 @@ data class DevicesViewState( val request: Async = Uninitialized ) : MvRxState -class DevicesViewModel @AssistedInject constructor(@Assisted initialState: DevicesViewState, - private val session: Session) +class DevicesViewModel @AssistedInject constructor( + @Assisted initialState: DevicesViewState, + private val session: Session, + private val supportedVerificationMethodsProvider: SupportedVerificationMethodsProvider) : VectorViewModel(initialState), VerificationService.Listener { @AssistedInject.Factory @@ -172,7 +174,9 @@ class DevicesViewModel @AssistedInject constructor(@Assisted initialState: Devic } private fun handleVerify(action: DevicesAction.VerifyMyDevice) { - val txID = session.cryptoService().verificationService().requestKeyVerification(supportedVerificationMethods, session.myUserId, listOf(action.deviceId)) + val txID = session.cryptoService() + .verificationService() + .requestKeyVerification(supportedVerificationMethodsProvider.provide(), session.myUserId, listOf(action.deviceId)) _viewEvents.post(DevicesViewEvents.ShowVerifyDevice( session.myUserId, txID.transactionId From 77dd911054ad100c6975074fb1dbd607a6c27140 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 27 Feb 2020 17:42:25 +0100 Subject: [PATCH 12/91] Code quality --- .../verification/VerificationBottomSheetViewModel.kt | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/vector/src/main/java/im/vector/riotx/features/crypto/verification/VerificationBottomSheetViewModel.kt b/vector/src/main/java/im/vector/riotx/features/crypto/verification/VerificationBottomSheetViewModel.kt index 29caea9683..bda483d6ef 100644 --- a/vector/src/main/java/im/vector/riotx/features/crypto/verification/VerificationBottomSheetViewModel.kt +++ b/vector/src/main/java/im/vector/riotx/features/crypto/verification/VerificationBottomSheetViewModel.kt @@ -177,7 +177,12 @@ class VerificationBottomSheetViewModel @AssistedInject constructor( session .cryptoService() .verificationService() - .requestKeyVerificationInDMs(supportedVerificationMethodsProvider.provide(), otherUserId, data, pendingLocalId) + .requestKeyVerificationInDMs( + supportedVerificationMethodsProvider.provide(), + otherUserId, + data, + pendingLocalId + ) ) ) } @@ -298,8 +303,6 @@ class VerificationBottomSheetViewModel @AssistedInject constructor( } catch (failure: Throwable) { _viewEvents.post(VerificationBottomSheetViewEvents.ModalError(failure.localizedMessage)) } - - Unit } }.exhaustive } From ceab0903cfcfd3ad20b39624c1e427e904de253e Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 27 Feb 2020 18:09:37 +0100 Subject: [PATCH 13/91] Improve code - TU passed --- .../internal/crypto/verification/qrcode/Extensions.kt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/verification/qrcode/Extensions.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/verification/qrcode/Extensions.kt index da926a0e10..d94e4c5c69 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/verification/qrcode/Extensions.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/verification/qrcode/Extensions.kt @@ -94,11 +94,11 @@ fun String.toQrCodeData(): QrCodeData? { val mode = byteArray[cursor].toInt() cursor++ - // Get transaction length - val bigEndian1 = byteArray[cursor].toUnsignedInt() - val bigEndian2 = byteArray[cursor + 1].toUnsignedInt() + // Get transaction length, Big Endian format + val msb = byteArray[cursor].toUnsignedInt() + val lsb = byteArray[cursor + 1].toUnsignedInt() - val transactionLength = bigEndian1 * 0x0100 + bigEndian2 + val transactionLength = msb.shl(8) + lsb cursor++ cursor++ From 8299487f6dead3f4010c014a5c58c0fa86c4e9ba Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 27 Feb 2020 18:13:42 +0100 Subject: [PATCH 14/91] Avoid using encoder flag to decode Base64 string... --- .../matrix/android/internal/crypto/crosssigning/Extensions.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/crosssigning/Extensions.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/crosssigning/Extensions.kt index 6ffc341881..7d55ebb1ad 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/crosssigning/Extensions.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/crosssigning/Extensions.kt @@ -33,5 +33,5 @@ fun ByteArray.toBase64NoPadding(): String { } fun String.fromBase64NoPadding(): ByteArray { - return Base64.decode(this, Base64.NO_PADDING or Base64.NO_WRAP) + return Base64.decode(this, Base64.DEFAULT) } From 1ead2778c2f5c22600d648c32b91a445bcd4301e Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 27 Feb 2020 18:15:39 +0100 Subject: [PATCH 15/91] ... and rename the method fromBase64NoPadding() to fromBase64() --- .../crosssigning/DefaultCrossSigningService.kt | 14 +++++++------- .../internal/crypto/crosssigning/Extensions.kt | 2 +- .../secrets/DefaultSharedSecretStorageService.kt | 10 +++++----- .../crypto/verification/qrcode/Extensions.kt | 8 ++++---- .../VerificationBottomSheetViewModel.kt | 4 ++-- 5 files changed, 19 insertions(+), 19 deletions(-) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/crosssigning/DefaultCrossSigningService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/crosssigning/DefaultCrossSigningService.kt index a29f27ddd6..acc9f4134d 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/crosssigning/DefaultCrossSigningService.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/crosssigning/DefaultCrossSigningService.kt @@ -80,7 +80,7 @@ internal class DefaultCrossSigningService @Inject constructor( cryptoStore.getCrossSigningPrivateKeys()?.let { privateKeysInfo -> privateKeysInfo.master - ?.fromBase64NoPadding() + ?.fromBase64() ?.let { privateKeySeed -> val pkSigning = OlmPkSigning() if (pkSigning.initWithSeed(privateKeySeed) == mxCrossSigningInfo.masterKey()?.unpaddedBase64PublicKey) { @@ -93,7 +93,7 @@ internal class DefaultCrossSigningService @Inject constructor( } } privateKeysInfo.user - ?.fromBase64NoPadding() + ?.fromBase64() ?.let { privateKeySeed -> val pkSigning = OlmPkSigning() if (pkSigning.initWithSeed(privateKeySeed) == mxCrossSigningInfo.userKey()?.unpaddedBase64PublicKey) { @@ -106,7 +106,7 @@ internal class DefaultCrossSigningService @Inject constructor( } } privateKeysInfo.selfSigned - ?.fromBase64NoPadding() + ?.fromBase64() ?.let { privateKeySeed -> val pkSigning = OlmPkSigning() if (pkSigning.initWithSeed(privateKeySeed) == mxCrossSigningInfo.selfSigningKey()?.unpaddedBase64PublicKey) { @@ -307,7 +307,7 @@ internal class DefaultCrossSigningService @Inject constructor( var userKeyIsTrusted = false var selfSignedKeyIsTrusted = false - masterKeyPrivateKey?.fromBase64NoPadding() + masterKeyPrivateKey?.fromBase64() ?.let { privateKeySeed -> val pkSigning = OlmPkSigning() try { @@ -324,7 +324,7 @@ internal class DefaultCrossSigningService @Inject constructor( } } - uskKeyPrivateKey?.fromBase64NoPadding() + uskKeyPrivateKey?.fromBase64() ?.let { privateKeySeed -> val pkSigning = OlmPkSigning() try { @@ -341,7 +341,7 @@ internal class DefaultCrossSigningService @Inject constructor( } } - sskPrivateKey?.fromBase64NoPadding() + sskPrivateKey?.fromBase64() ?.let { privateKeySeed -> val pkSigning = OlmPkSigning() try { @@ -450,7 +450,7 @@ internal class DefaultCrossSigningService @Inject constructor( // 1) check if I know the private key val masterPrivateKey = cryptoStore.getCrossSigningPrivateKeys() ?.master - ?.fromBase64NoPadding() + ?.fromBase64() var isMaterKeyTrusted = false if (myMasterKey.trustLevel?.locallyVerified == true) { diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/crosssigning/Extensions.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/crosssigning/Extensions.kt index 7d55ebb1ad..9125a99e70 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/crosssigning/Extensions.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/crosssigning/Extensions.kt @@ -32,6 +32,6 @@ fun ByteArray.toBase64NoPadding(): String { return Base64.encodeToString(this, Base64.NO_PADDING or Base64.NO_WRAP) } -fun String.fromBase64NoPadding(): ByteArray { +fun String.fromBase64(): ByteArray { return Base64.decode(this, Base64.DEFAULT) } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/secrets/DefaultSharedSecretStorageService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/secrets/DefaultSharedSecretStorageService.kt index 9627492dc7..b76b66b830 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/secrets/DefaultSharedSecretStorageService.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/secrets/DefaultSharedSecretStorageService.kt @@ -35,7 +35,7 @@ import im.vector.matrix.android.api.session.securestorage.SsssKeySpec import im.vector.matrix.android.api.session.securestorage.SsssPassphrase import im.vector.matrix.android.internal.crypto.SSSS_ALGORITHM_AES_HMAC_SHA2 import im.vector.matrix.android.internal.crypto.SSSS_ALGORITHM_CURVE25519_AES_SHA2 -import im.vector.matrix.android.internal.crypto.crosssigning.fromBase64NoPadding +import im.vector.matrix.android.internal.crypto.crosssigning.fromBase64 import im.vector.matrix.android.internal.crypto.crosssigning.toBase64NoPadding import im.vector.matrix.android.internal.crypto.keysbackup.generatePrivateKeyWithPassword import im.vector.matrix.android.internal.crypto.keysbackup.util.computeRecoveryKey @@ -268,7 +268,7 @@ internal class DefaultSharedSecretStorageService @Inject constructor( val ivParameterSpec = IvParameterSpec(iv) cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec) // secret are not that big, just do Final - val cipherBytes = cipher.doFinal(clearDataBase64.fromBase64NoPadding()) + val cipherBytes = cipher.doFinal(clearDataBase64.fromBase64()) require(cipherBytes.isNotEmpty()) val macKeySpec = SecretKeySpec(macKey, "HmacSHA256") @@ -295,9 +295,9 @@ internal class DefaultSharedSecretStorageService @Inject constructor( val aesKey = pseudoRandomKey.copyOfRange(0, 32) val macKey = pseudoRandomKey.copyOfRange(32, 64) - val iv = cipherContent.initializationVector?.fromBase64NoPadding() ?: ByteArray(16) + val iv = cipherContent.initializationVector?.fromBase64() ?: ByteArray(16) - val cipherRawBytes = cipherContent.ciphertext!!.fromBase64NoPadding() + val cipherRawBytes = cipherContent.ciphertext!!.fromBase64() val cipher = Cipher.getInstance("AES/CTR/NoPadding") @@ -314,7 +314,7 @@ internal class DefaultSharedSecretStorageService @Inject constructor( val mac = Mac.getInstance("HmacSHA256").apply { init(macKeySpec) } val digest = mac.doFinal(cipherRawBytes) - if (!cipherContent.mac?.fromBase64NoPadding()?.contentEquals(digest).orFalse()) { + if (!cipherContent.mac?.fromBase64()?.contentEquals(digest).orFalse()) { throw SharedSecretStorageError.BadMac } else { // we are good diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/verification/qrcode/Extensions.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/verification/qrcode/Extensions.kt index d94e4c5c69..567fcdbf74 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/verification/qrcode/Extensions.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/verification/qrcode/Extensions.kt @@ -16,7 +16,7 @@ package im.vector.matrix.android.internal.crypto.verification.qrcode -import im.vector.matrix.android.internal.crypto.crosssigning.fromBase64NoPadding +import im.vector.matrix.android.internal.crypto.crosssigning.fromBase64 import im.vector.matrix.android.internal.crypto.crosssigning.toBase64NoPadding import im.vector.matrix.android.internal.extensions.toUnsignedInt @@ -52,15 +52,15 @@ fun QrCodeData.toEncodedString(): String { } // Keys - firstKey.fromBase64NoPadding().forEach { + firstKey.fromBase64().forEach { result += it } - secondKey.fromBase64NoPadding().forEach { + secondKey.fromBase64().forEach { result += it } // Secret - sharedSecret.fromBase64NoPadding().forEach { + sharedSecret.fromBase64().forEach { result += it } diff --git a/vector/src/main/java/im/vector/riotx/features/crypto/verification/VerificationBottomSheetViewModel.kt b/vector/src/main/java/im/vector/riotx/features/crypto/verification/VerificationBottomSheetViewModel.kt index c5fd167f39..f4670b90e1 100644 --- a/vector/src/main/java/im/vector/riotx/features/crypto/verification/VerificationBottomSheetViewModel.kt +++ b/vector/src/main/java/im/vector/riotx/features/crypto/verification/VerificationBottomSheetViewModel.kt @@ -42,7 +42,7 @@ import im.vector.matrix.android.api.session.events.model.LocalEcho import im.vector.matrix.android.api.session.room.model.create.CreateRoomParams import im.vector.matrix.android.api.util.MatrixItem import im.vector.matrix.android.api.util.toMatrixItem -import im.vector.matrix.android.internal.crypto.crosssigning.fromBase64NoPadding +import im.vector.matrix.android.internal.crypto.crosssigning.fromBase64 import im.vector.matrix.android.internal.crypto.crosssigning.isVerified import im.vector.matrix.android.internal.crypto.verification.PendingVerificationRequest import im.vector.riotx.core.extensions.exhaustive @@ -265,7 +265,7 @@ class VerificationBottomSheetViewModel @AssistedInject constructor(@Assisted ini } is VerificationAction.GotResultFromSsss -> { try { - action.cypherData.fromBase64NoPadding().inputStream().use { ins -> + action.cypherData.fromBase64().inputStream().use { ins -> val res = session.loadSecureSecret>(ins, action.alias) val trustResult = session.cryptoService().crossSigningService().checkTrustFromPrivateKeys( res?.get(MASTER_KEY_SSSS_NAME), From 0a9008a73d2a702527e44ec94a98395a133f5f6f Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 27 Feb 2020 18:35:05 +0100 Subject: [PATCH 16/91] Be robust if other client sends padded base64 in the reciprocate --- .../crypto/crosssigning/ExtensionsKtTest.kt | 32 +++++++++++++++++++ .../DefaultQrCodeVerificationTransaction.kt | 3 +- 2 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 matrix-sdk-android/src/androidTest/java/im/vector/matrix/android/internal/crypto/crosssigning/ExtensionsKtTest.kt diff --git a/matrix-sdk-android/src/androidTest/java/im/vector/matrix/android/internal/crypto/crosssigning/ExtensionsKtTest.kt b/matrix-sdk-android/src/androidTest/java/im/vector/matrix/android/internal/crypto/crosssigning/ExtensionsKtTest.kt new file mode 100644 index 0000000000..ca83af2f42 --- /dev/null +++ b/matrix-sdk-android/src/androidTest/java/im/vector/matrix/android/internal/crypto/crosssigning/ExtensionsKtTest.kt @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2020 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.crypto.crosssigning + +import org.amshove.kluent.shouldBeTrue +import org.junit.Test + +@Suppress("SpellCheckingInspection") +class ExtensionsKtTest { + + @Test + fun testComparingBase64StringWithOrWithoutPadding() { + // Without padding + "NMJyumnhMic".fromBase64().contentEquals("NMJyumnhMic".fromBase64()).shouldBeTrue() + // With padding + "NMJyumnhMic".fromBase64().contentEquals("NMJyumnhMic=".fromBase64()).shouldBeTrue() + } +} diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/verification/qrcode/DefaultQrCodeVerificationTransaction.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/verification/qrcode/DefaultQrCodeVerificationTransaction.kt index 9c2a40a4e8..95438bf88d 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/verification/qrcode/DefaultQrCodeVerificationTransaction.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/verification/qrcode/DefaultQrCodeVerificationTransaction.kt @@ -24,6 +24,7 @@ import im.vector.matrix.android.api.session.crypto.verification.VerificationTxSt import im.vector.matrix.android.api.session.events.model.EventType import im.vector.matrix.android.internal.crypto.actions.SetDeviceVerificationAction import im.vector.matrix.android.internal.crypto.crosssigning.DeviceTrustLevel +import im.vector.matrix.android.internal.crypto.crosssigning.fromBase64 import im.vector.matrix.android.internal.crypto.store.IMXCryptoStore import im.vector.matrix.android.internal.crypto.verification.DefaultVerificationTransaction import im.vector.matrix.android.internal.crypto.verification.VerificationInfo @@ -199,7 +200,7 @@ internal class DefaultQrCodeVerificationTransaction( return } - if (startReq.sharedSecret == qrCodeData.sharedSecret) { + if ((startReq.sharedSecret?.fromBase64()?.contentEquals(qrCodeData.sharedSecret.fromBase64()) == true)) { // Ok, we can trust the other user // We can only trust the master key in this case // But first, ask the user for a confirmation From b1b8513da4842e7439c57633af326876933b4213 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 27 Feb 2020 19:17:14 +0100 Subject: [PATCH 17/91] Create fromBase64Safe() to parse data received from external source --- .../crypto/crosssigning/ExtensionsKtTest.kt | 6 ++++++ .../securestorage/SharedSecretStorageError.kt | 2 ++ .../internal/crypto/crosssigning/Extensions.kt | 13 +++++++++++++ .../secrets/DefaultSharedSecretStorageService.kt | 2 +- .../qrcode/DefaultQrCodeVerificationTransaction.kt | 3 ++- .../crypto/verification/qrcode/Extensions.kt | 2 +- 6 files changed, 25 insertions(+), 3 deletions(-) diff --git a/matrix-sdk-android/src/androidTest/java/im/vector/matrix/android/internal/crypto/crosssigning/ExtensionsKtTest.kt b/matrix-sdk-android/src/androidTest/java/im/vector/matrix/android/internal/crypto/crosssigning/ExtensionsKtTest.kt index ca83af2f42..84da654c4c 100644 --- a/matrix-sdk-android/src/androidTest/java/im/vector/matrix/android/internal/crypto/crosssigning/ExtensionsKtTest.kt +++ b/matrix-sdk-android/src/androidTest/java/im/vector/matrix/android/internal/crypto/crosssigning/ExtensionsKtTest.kt @@ -16,6 +16,7 @@ package im.vector.matrix.android.internal.crypto.crosssigning +import org.amshove.kluent.shouldBeNull import org.amshove.kluent.shouldBeTrue import org.junit.Test @@ -29,4 +30,9 @@ class ExtensionsKtTest { // With padding "NMJyumnhMic".fromBase64().contentEquals("NMJyumnhMic=".fromBase64()).shouldBeTrue() } + + @Test + fun testBadBase64() { + "===".fromBase64Safe().shouldBeNull() + } } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/securestorage/SharedSecretStorageError.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/securestorage/SharedSecretStorageError.kt index abd12789a5..a6bf75f2c0 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/securestorage/SharedSecretStorageError.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/securestorage/SharedSecretStorageError.kt @@ -28,5 +28,7 @@ sealed class SharedSecretStorageError(message: String?) : Throwable(message) { object BadKeyFormat : SharedSecretStorageError("Bad Key Format") object ParsingError : SharedSecretStorageError("parsing Error") object BadMac : SharedSecretStorageError("Bad mac") + object BadCipherText : SharedSecretStorageError("Bad cipher text") + data class OtherError(val reason: Throwable) : SharedSecretStorageError(reason.localizedMessage) } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/crosssigning/Extensions.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/crosssigning/Extensions.kt index 9125a99e70..fadfb567b3 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/crosssigning/Extensions.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/crosssigning/Extensions.kt @@ -19,6 +19,7 @@ import android.util.Base64 import im.vector.matrix.android.internal.crypto.model.CryptoCrossSigningKey import im.vector.matrix.android.internal.crypto.model.CryptoDeviceInfo import im.vector.matrix.android.internal.util.JsonCanonicalizer +import timber.log.Timber fun CryptoDeviceInfo.canonicalSignable(): String { return JsonCanonicalizer.getCanonicalJson(Map::class.java, signalableJSONDictionary()) @@ -35,3 +36,15 @@ fun ByteArray.toBase64NoPadding(): String { fun String.fromBase64(): ByteArray { return Base64.decode(this, Base64.DEFAULT) } + +/** + * Decode the base 64. Return null in case of bad format. Should be used when parsing received data from external source + */ +fun String.fromBase64Safe(): ByteArray? { + return try { + Base64.decode(this, Base64.DEFAULT) + } catch (throwable: Throwable) { + Timber.e(throwable, "Unable to decode base64 string") + null + } +} diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/secrets/DefaultSharedSecretStorageService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/secrets/DefaultSharedSecretStorageService.kt index b76b66b830..649f60887d 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/secrets/DefaultSharedSecretStorageService.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/secrets/DefaultSharedSecretStorageService.kt @@ -297,7 +297,7 @@ internal class DefaultSharedSecretStorageService @Inject constructor( val iv = cipherContent.initializationVector?.fromBase64() ?: ByteArray(16) - val cipherRawBytes = cipherContent.ciphertext!!.fromBase64() + val cipherRawBytes = cipherContent.ciphertext?.fromBase64() ?: throw SharedSecretStorageError.BadCipherText val cipher = Cipher.getInstance("AES/CTR/NoPadding") diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/verification/qrcode/DefaultQrCodeVerificationTransaction.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/verification/qrcode/DefaultQrCodeVerificationTransaction.kt index 95438bf88d..241c741757 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/verification/qrcode/DefaultQrCodeVerificationTransaction.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/verification/qrcode/DefaultQrCodeVerificationTransaction.kt @@ -25,6 +25,7 @@ import im.vector.matrix.android.api.session.events.model.EventType import im.vector.matrix.android.internal.crypto.actions.SetDeviceVerificationAction import im.vector.matrix.android.internal.crypto.crosssigning.DeviceTrustLevel import im.vector.matrix.android.internal.crypto.crosssigning.fromBase64 +import im.vector.matrix.android.internal.crypto.crosssigning.fromBase64Safe import im.vector.matrix.android.internal.crypto.store.IMXCryptoStore import im.vector.matrix.android.internal.crypto.verification.DefaultVerificationTransaction import im.vector.matrix.android.internal.crypto.verification.VerificationInfo @@ -200,7 +201,7 @@ internal class DefaultQrCodeVerificationTransaction( return } - if ((startReq.sharedSecret?.fromBase64()?.contentEquals(qrCodeData.sharedSecret.fromBase64()) == true)) { + if (startReq.sharedSecret?.fromBase64Safe()?.contentEquals(qrCodeData.sharedSecret.fromBase64()) == true) { // Ok, we can trust the other user // We can only trust the master key in this case // But first, ask the user for a confirmation diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/verification/qrcode/Extensions.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/verification/qrcode/Extensions.kt index 567fcdbf74..a4c4e649cc 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/verification/qrcode/Extensions.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/verification/qrcode/Extensions.kt @@ -98,7 +98,7 @@ fun String.toQrCodeData(): QrCodeData? { val msb = byteArray[cursor].toUnsignedInt() val lsb = byteArray[cursor + 1].toUnsignedInt() - val transactionLength = msb.shl(8) + lsb + val transactionLength = msb.shl(8) + lsb cursor++ cursor++ From 151fec5ce0c021c07bff5ec6cc915c4703e3559f Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 28 Feb 2020 11:38:30 +0100 Subject: [PATCH 18/91] Fix crash on attachment preview screen (#1088) --- CHANGES.md | 2 +- .../features/attachments/preview/AttachmentsPreviewFragment.kt | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 65f6e96f69..4f8838deb6 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -8,7 +8,7 @@ Improvements 🙌: - Bugfix 🐛: - - + - Fix crash on attachment preview screen (#1088) Translations 🗣: - diff --git a/vector/src/main/java/im/vector/riotx/features/attachments/preview/AttachmentsPreviewFragment.kt b/vector/src/main/java/im/vector/riotx/features/attachments/preview/AttachmentsPreviewFragment.kt index 1d525dddf7..e52b497df4 100644 --- a/vector/src/main/java/im/vector/riotx/features/attachments/preview/AttachmentsPreviewFragment.kt +++ b/vector/src/main/java/im/vector/riotx/features/attachments/preview/AttachmentsPreviewFragment.kt @@ -39,6 +39,7 @@ import com.airbnb.mvrx.fragmentViewModel import com.airbnb.mvrx.withState import com.yalantis.ucrop.UCrop import com.yalantis.ucrop.UCropActivity +import im.vector.matrix.android.api.extensions.orFalse import im.vector.matrix.android.api.session.content.ContentAttachmentData import im.vector.riotx.R import im.vector.riotx.core.extensions.cleanup @@ -115,7 +116,7 @@ class AttachmentsPreviewFragment @Inject constructor( override fun onPrepareOptionsMenu(menu: Menu) { withState(viewModel) { state -> val editMenuItem = menu.findItem(R.id.attachmentsPreviewEditAction) - val showEditMenuItem = state.attachments[state.currentAttachmentIndex].isEditable() + val showEditMenuItem = state.attachments.getOrNull(state.currentAttachmentIndex)?.isEditable().orFalse() editMenuItem.setVisible(showEditMenuItem) } From 779026b0afdff168bceb963ba1e59ededdb9320f Mon Sep 17 00:00:00 2001 From: Valere Date: Fri, 28 Feb 2020 11:46:32 +0100 Subject: [PATCH 19/91] Fix / mark master key as trusted after self verif --- .../SASDefaultVerificationTransaction.kt | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/verification/SASDefaultVerificationTransaction.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/verification/SASDefaultVerificationTransaction.kt index 7856e571eb..f56e414a26 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/verification/SASDefaultVerificationTransaction.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/verification/SASDefaultVerificationTransaction.kt @@ -299,14 +299,21 @@ internal abstract class SASDefaultVerificationTransaction( } // If not me sign his MSK and upload the signature - if (otherMasterKeyIsVerified && otherUserId != userId) { + if (otherMasterKeyIsVerified) { // we should trust this master key // And check verification MSK -> SSK? - crossSigningService.trustUser(otherUserId, object : MatrixCallback { - override fun onFailure(failure: Throwable) { - Timber.e(failure, "## SAS Verification: Failed to trust User $otherUserId") + if (otherUserId != userId) { + crossSigningService.trustUser(otherUserId, object : MatrixCallback { + override fun onFailure(failure: Throwable) { + Timber.e(failure, "## SAS Verification: Failed to trust User $otherUserId") + } + }) + } else { + // Notice other master key is mine because other is me + if (otherMasterKey?.trustLevel?.isVerified() == false) { + crossSigningService.markMyMasterKeyAsTrusted() } - }) + } } if (otherUserId == userId) { From 039924436f3fbf67217102fb5ea3a4a605f164e5 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 28 Feb 2020 14:14:06 +0100 Subject: [PATCH 20/91] Json parsing --- .../api/pushrules/rest/GetPushRulesResponse.kt | 5 +++-- .../android/api/pushrules/rest/PushCondition.kt | 9 ++++++++- .../matrix/android/api/pushrules/rest/PushRule.kt | 11 ++++++++++- .../api/pushrules/rest/{Ruleset.kt => RuleSet.kt} | 11 ++++++++++- 4 files changed, 31 insertions(+), 5 deletions(-) rename matrix-sdk-android/src/main/java/im/vector/matrix/android/api/pushrules/rest/{Ruleset.kt => RuleSet.kt} (74%) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/pushrules/rest/GetPushRulesResponse.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/pushrules/rest/GetPushRulesResponse.kt index c5f03aed41..2ce6c8364a 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/pushrules/rest/GetPushRulesResponse.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/pushrules/rest/GetPushRulesResponse.kt @@ -20,6 +20,7 @@ import com.squareup.moshi.JsonClass /** * All push rulesets for a user. + * Ref: https://matrix.org/docs/spec/client_server/latest#get-matrix-client-r0-pushrules */ @JsonClass(generateAdapter = true) internal data class GetPushRulesResponse( @@ -27,11 +28,11 @@ internal data class GetPushRulesResponse( * Global rules, account level applying to all devices */ @Json(name = "global") - val global: Ruleset, + val global: RuleSet, /** * Device specific rules, apply only to current device */ @Json(name = "device") - val device: Ruleset? = null + val device: RuleSet? = null ) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/pushrules/rest/PushCondition.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/pushrules/rest/PushCondition.kt index cc19e6a7d1..edfb56e019 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/pushrules/rest/PushCondition.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/pushrules/rest/PushCondition.kt @@ -24,21 +24,27 @@ import im.vector.matrix.android.api.pushrules.RoomMemberCountCondition import im.vector.matrix.android.api.pushrules.SenderNotificationPermissionCondition import timber.log.Timber +/** + * Ref: https://matrix.org/docs/spec/client_server/latest#get-matrix-client-r0-pushrules + */ @JsonClass(generateAdapter = true) data class PushCondition( /** * Required. The kind of condition to apply. */ + @Json(name = "kind") val kind: String, /** * Required for event_match conditions. The dot- separated field of the event to match. */ + @Json(name = "key") val key: String? = null, /** * Required for event_match conditions. */ + @Json(name = "pattern") val pattern: String? = null, /** @@ -47,7 +53,8 @@ data class PushCondition( * A prefix of < matches rooms where the member count is strictly less than the given number and so forth. * If no prefix is present, this parameter defaults to ==. */ - @Json(name = "is") val iz: String? = null + @Json(name = "is") + val iz: String? = null ) { fun asExecutableCondition(): Condition? { diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/pushrules/rest/PushRule.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/pushrules/rest/PushRule.kt index e9423d7c40..d746aed5d8 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/pushrules/rest/PushRule.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/pushrules/rest/PushRule.kt @@ -19,30 +19,39 @@ package im.vector.matrix.android.api.pushrules.rest import com.squareup.moshi.Json import com.squareup.moshi.JsonClass +/** + * Ref: https://matrix.org/docs/spec/client_server/latest#get-matrix-client-r0-pushrules + */ @JsonClass(generateAdapter = true) data class PushRule( /** * Required. The actions to perform when this rule is matched. */ + @Json(name = "actions") val actions: List, /** * Required. Whether this is a default rule, or has been set explicitly. */ + @Json(name = "default") val default: Boolean? = false, /** * Required. Whether the push rule is enabled or not. */ + @Json(name = "enabled") val enabled: Boolean, /** * Required. The ID of this rule. */ - @Json(name = "rule_id") val ruleId: String, + @Json(name = "rule_id") + val ruleId: String, /** * The conditions that must hold true for an event in order for a rule to be applied to an event */ + @Json(name = "conditions") val conditions: List? = null, /** * The glob-style pattern to match against. Only applicable to content rules. */ + @Json(name = "pattern") val pattern: String? = null ) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/pushrules/rest/Ruleset.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/pushrules/rest/RuleSet.kt similarity index 74% rename from matrix-sdk-android/src/main/java/im/vector/matrix/android/api/pushrules/rest/Ruleset.kt rename to matrix-sdk-android/src/main/java/im/vector/matrix/android/api/pushrules/rest/RuleSet.kt index a7093731b5..82aa5da716 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/pushrules/rest/Ruleset.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/pushrules/rest/RuleSet.kt @@ -15,13 +15,22 @@ */ package im.vector.matrix.android.api.pushrules.rest +import com.squareup.moshi.Json import com.squareup.moshi.JsonClass +/** + * Ref: https://matrix.org/docs/spec/client_server/latest#get-matrix-client-r0-pushrules + */ @JsonClass(generateAdapter = true) -internal data class Ruleset( +internal data class RuleSet( + @Json(name = "content") val content: List? = null, + @Json(name = "override") val override: List? = null, + @Json(name = "room") val room: List? = null, + @Json(name = "sender") val sender: List? = null, + @Json(name = "underride") val underride: List? = null ) From 1c35d07acc67ec79a7b1fcee321157953e116dcd Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 28 Feb 2020 14:46:42 +0100 Subject: [PATCH 21/91] PushRuleService.getPushRules() now returns a RuleSet. Use getAllRules() on this object to get all the rules. --- CHANGES.md | 2 +- .../matrix/android/api/pushrules/PushRuleService.kt | 4 ++-- .../matrix/android/api/pushrules/rest/RuleSet.kt | 9 +++++++-- .../session/notification/DefaultPushRuleService.kt | 12 +++++++++--- .../internal/session/sync/SyncResponseHandler.kt | 2 +- .../VectorSettingsNotificationPreferenceFragment.kt | 4 ++-- .../features/settings/push/PushRulesViewModel.kt | 2 +- .../settings/troubleshoot/TestAccountSettings.kt | 2 +- .../settings/troubleshoot/TestBingRulesSettings.kt | 2 +- 9 files changed, 25 insertions(+), 14 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 4f8838deb6..20c2e5b266 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -14,7 +14,7 @@ Translations 🗣: - SDK API changes ⚠️: - - + - PushRuleService.getPushRules() now returns a RuleSet. Use getAllRules() on this object to get all the rules. Build 🧱: - diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/pushrules/PushRuleService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/pushrules/PushRuleService.kt index 0ef70eb99b..94c2121695 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/pushrules/PushRuleService.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/pushrules/PushRuleService.kt @@ -17,6 +17,7 @@ package im.vector.matrix.android.api.pushrules import im.vector.matrix.android.api.MatrixCallback import im.vector.matrix.android.api.pushrules.rest.PushRule +import im.vector.matrix.android.api.pushrules.rest.RuleSet import im.vector.matrix.android.api.session.events.model.Event import im.vector.matrix.android.api.util.Cancelable @@ -27,8 +28,7 @@ interface PushRuleService { */ fun fetchPushRules(scope: String = RuleScope.GLOBAL) - // TODO get push rule set - fun getPushRules(scope: String = RuleScope.GLOBAL): List + fun getPushRules(scope: String = RuleScope.GLOBAL): RuleSet // TODO update rule diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/pushrules/rest/RuleSet.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/pushrules/rest/RuleSet.kt index 82aa5da716..43b2599b52 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/pushrules/rest/RuleSet.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/pushrules/rest/RuleSet.kt @@ -22,7 +22,7 @@ import com.squareup.moshi.JsonClass * Ref: https://matrix.org/docs/spec/client_server/latest#get-matrix-client-r0-pushrules */ @JsonClass(generateAdapter = true) -internal data class RuleSet( +data class RuleSet( @Json(name = "content") val content: List? = null, @Json(name = "override") @@ -33,4 +33,9 @@ internal data class RuleSet( val sender: List? = null, @Json(name = "underride") val underride: List? = null -) +) { + fun getAllRules(): List { + // Ref. for the order: https://matrix.org/docs/spec/client_server/latest#push-rules + return override.orEmpty() + content.orEmpty() + room.orEmpty() + sender.orEmpty() + underride.orEmpty() + } +} diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/notification/DefaultPushRuleService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/notification/DefaultPushRuleService.kt index 7e8dc1eb30..e6e45735e9 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/notification/DefaultPushRuleService.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/notification/DefaultPushRuleService.kt @@ -22,6 +22,7 @@ import im.vector.matrix.android.api.pushrules.RuleKind import im.vector.matrix.android.api.pushrules.RuleSetKey import im.vector.matrix.android.api.pushrules.getActions import im.vector.matrix.android.api.pushrules.rest.PushRule +import im.vector.matrix.android.api.pushrules.rest.RuleSet import im.vector.matrix.android.api.session.events.model.Event import im.vector.matrix.android.api.util.Cancelable import im.vector.matrix.android.internal.database.mapper.PushRulesMapper @@ -55,7 +56,7 @@ internal class DefaultPushRuleService @Inject constructor( .executeBy(taskExecutor) } - override fun getPushRules(scope: String): List { + override fun getPushRules(scope: String): RuleSet { var contentRules: List = emptyList() var overrideRules: List = emptyList() var roomRules: List = emptyList() @@ -90,8 +91,13 @@ internal class DefaultPushRuleService @Inject constructor( } } - // Ref. for the order: https://matrix.org/docs/spec/client_server/latest#push-rules - return overrideRules + contentRules + roomRules + senderRules + underrideRules + return RuleSet( + content = contentRules, + override = overrideRules, + room = roomRules, + sender = senderRules, + underride = underrideRules + ) } override fun updatePushRuleEnableStatus(kind: RuleKind, pushRule: PushRule, enabled: Boolean, callback: MatrixCallback): Cancelable { diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/SyncResponseHandler.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/SyncResponseHandler.kt index 1454fdae7d..4ae42b273d 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/SyncResponseHandler.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/SyncResponseHandler.kt @@ -120,7 +120,7 @@ internal class SyncResponseHandler @Inject constructor(private val monarchy: Mon return } // nothing on initial sync - val rules = pushRuleService.getPushRules(RuleScope.GLOBAL) + val rules = pushRuleService.getPushRules(RuleScope.GLOBAL).getAllRules() processEventForPushTask.execute(ProcessEventForPushTask.Params(roomsSyncResponse, rules)) Timber.v("[PushRules] <-- Push task scheduled") } diff --git a/vector/src/main/java/im/vector/riotx/features/settings/VectorSettingsNotificationPreferenceFragment.kt b/vector/src/main/java/im/vector/riotx/features/settings/VectorSettingsNotificationPreferenceFragment.kt index 5e7bc9d95b..65f68bb3b7 100644 --- a/vector/src/main/java/im/vector/riotx/features/settings/VectorSettingsNotificationPreferenceFragment.kt +++ b/vector/src/main/java/im/vector/riotx/features/settings/VectorSettingsNotificationPreferenceFragment.kt @@ -42,7 +42,7 @@ class VectorSettingsNotificationPreferenceFragment @Inject constructor( override fun bindPref() { findPreference(VectorPreferences.SETTINGS_ENABLE_ALL_NOTIF_PREFERENCE_KEY)!!.let { pref -> val pushRuleService = session - val mRuleMaster = pushRuleService.getPushRules() + val mRuleMaster = pushRuleService.getPushRules().getAllRules() .find { it.ruleId == RuleIds.RULE_ID_DISABLE_ALL } if (mRuleMaster == null) { @@ -105,7 +105,7 @@ class VectorSettingsNotificationPreferenceFragment @Inject constructor( private fun updateEnabledForAccount(preference: Preference?) { val pushRuleService = session val switchPref = preference as SwitchPreference - pushRuleService.getPushRules() + pushRuleService.getPushRules().getAllRules() .find { it.ruleId == RuleIds.RULE_ID_DISABLE_ALL } ?.let { // Trick, we must enable this room to disable notifications diff --git a/vector/src/main/java/im/vector/riotx/features/settings/push/PushRulesViewModel.kt b/vector/src/main/java/im/vector/riotx/features/settings/push/PushRulesViewModel.kt index 3c71238b33..43854af666 100644 --- a/vector/src/main/java/im/vector/riotx/features/settings/push/PushRulesViewModel.kt +++ b/vector/src/main/java/im/vector/riotx/features/settings/push/PushRulesViewModel.kt @@ -35,7 +35,7 @@ class PushRulesViewModel(initialState: PushRulesViewState) override fun initialState(viewModelContext: ViewModelContext): PushRulesViewState? { val session = (viewModelContext.activity as HasScreenInjector).injector().activeSessionHolder().getActiveSession() - val rules = session.getPushRules() + val rules = session.getPushRules().getAllRules() return PushRulesViewState(rules) } } diff --git a/vector/src/main/java/im/vector/riotx/features/settings/troubleshoot/TestAccountSettings.kt b/vector/src/main/java/im/vector/riotx/features/settings/troubleshoot/TestAccountSettings.kt index feea3e40d0..d89bd15e14 100644 --- a/vector/src/main/java/im/vector/riotx/features/settings/troubleshoot/TestAccountSettings.kt +++ b/vector/src/main/java/im/vector/riotx/features/settings/troubleshoot/TestAccountSettings.kt @@ -32,7 +32,7 @@ class TestAccountSettings @Inject constructor(private val stringProvider: String override fun perform() { val session = activeSessionHolder.getSafeActiveSession() ?: return - val defaultRule = session.getPushRules() + val defaultRule = session.getPushRules().getAllRules() .find { it.ruleId == RuleIds.RULE_ID_DISABLE_ALL } if (defaultRule != null) { diff --git a/vector/src/main/java/im/vector/riotx/features/settings/troubleshoot/TestBingRulesSettings.kt b/vector/src/main/java/im/vector/riotx/features/settings/troubleshoot/TestBingRulesSettings.kt index 4847587d56..52c1ceb07c 100644 --- a/vector/src/main/java/im/vector/riotx/features/settings/troubleshoot/TestBingRulesSettings.kt +++ b/vector/src/main/java/im/vector/riotx/features/settings/troubleshoot/TestBingRulesSettings.kt @@ -40,7 +40,7 @@ class TestBingRulesSettings @Inject constructor(private val activeSessionHolder: override fun perform() { val session = activeSessionHolder.getSafeActiveSession() ?: return - val pushRules = session.getPushRules() + val pushRules = session.getPushRules().getAllRules() var oneOrMoreRuleIsOff = false var oneOrMoreRuleAreSilent = false testedRules.forEach { ruleId -> From 3013e311a46988418643dfab327d340c8201818c Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 28 Feb 2020 16:45:46 +0100 Subject: [PATCH 22/91] Restore push rule settings - WIP --- .../android/api/pushrules/rest/PushRule.kt | 115 ++++++++++++- .../android/api/pushrules/rest/RuleSet.kt | 40 +++++ .../core/preference/BingRulePreference.kt | 160 +++++++----------- ...sAdvancedNotificationPreferenceFragment.kt | 27 +-- vector/src/main/res/values/strings_riotX.xml | 2 +- ...ings_notification_advanced_preferences.xml | 49 +++--- .../res/xml/vector_settings_notifications.xml | 4 +- 7 files changed, 262 insertions(+), 135 deletions(-) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/pushrules/rest/PushRule.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/pushrules/rest/PushRule.kt index d746aed5d8..d60fe2e9c4 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/pushrules/rest/PushRule.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/pushrules/rest/PushRule.kt @@ -18,6 +18,9 @@ package im.vector.matrix.android.api.pushrules.rest import com.squareup.moshi.Json import com.squareup.moshi.JsonClass +import im.vector.matrix.android.api.pushrules.Action +import im.vector.matrix.android.api.pushrules.getActions +import im.vector.matrix.android.api.pushrules.toJson /** * Ref: https://matrix.org/docs/spec/client_server/latest#get-matrix-client-r0-pushrules @@ -54,4 +57,114 @@ data class PushRule( */ @Json(name = "pattern") val pattern: String? = null -) +) { + /** + * Add the default notification sound. + */ + fun setNotificationSound(): PushRule { + return setNotificationSound(ACTION_VALUE_DEFAULT) + } + + fun getNotificationSound(): String? { + return (getActions().firstOrNull { it is Action.Sound } as? Action.Sound)?.sound + } + + /** + * Set the notification sound + * + * @param sound notification sound + */ + fun setNotificationSound(sound: String): PushRule { + return copy( + actions = (getActions().filter { it !is Action.Sound } + Action.Sound(sound)).toJson() + ) + } + + /** + * Remove the notification sound + */ + fun removeNotificationSound(): PushRule { + return copy( + actions = (getActions().filter { it !is Action.Sound }).toJson() + ) + } + + /** + * Set the highlight status. + * + * @param highlight the highlight status + */ + fun setHighlight(highlight: Boolean): PushRule { + return copy( + actions = (getActions().filter { it !is Action.Highlight } + Action.Highlight(highlight)).toJson() + ) + } + + /** + * Set the notification status. + * + * @param notify true to notify + */ + fun setNotify(notify: Boolean): PushRule { + val mutableActions = actions.toMutableList() + + mutableActions.remove(ACTION_DONT_NOTIFY) + mutableActions.remove(ACTION_NOTIFY) + + if (notify) { + mutableActions.add(ACTION_NOTIFY) + } else { + mutableActions.add(ACTION_DONT_NOTIFY) + } + + return copy(actions = mutableActions) + } + + /** + * Return true if the rule should highlight the event. + * + * @return true if the rule should play sound + */ + fun shouldNotify() = actions.contains(ACTION_NOTIFY) + + /** + * Return true if the rule should not highlight the event. + * + * @return true if the rule should not play sound + */ + fun shouldNotNotify() = actions.contains(ACTION_DONT_NOTIFY) + + companion object { + /* ========================================================================================== + * Rule id + * ========================================================================================== */ + + const val RULE_ID_DISABLE_ALL = ".m.rule.master" + const val RULE_ID_CONTAIN_USER_NAME = ".m.rule.contains_user_name" + const val RULE_ID_CONTAIN_DISPLAY_NAME = ".m.rule.contains_display_name" + const val RULE_ID_ONE_TO_ONE_ROOM = ".m.rule.room_one_to_one" + const val RULE_ID_INVITE_ME = ".m.rule.invite_for_me" + const val RULE_ID_PEOPLE_JOIN_LEAVE = ".m.rule.member_event" + const val RULE_ID_CALL = ".m.rule.call" + const val RULE_ID_SUPPRESS_BOTS_NOTIFICATIONS = ".m.rule.suppress_notices" + const val RULE_ID_ALL_OTHER_MESSAGES_ROOMS = ".m.rule.message" + const val RULE_ID_FALLBACK = ".m.rule.fallback" + + /* ========================================================================================== + * Actions + * ========================================================================================== */ + + const val ACTION_NOTIFY = "notify" + const val ACTION_DONT_NOTIFY = "dont_notify" + const val ACTION_COALESCE = "coalesce" + + const val ACTION_SET_TWEAK_SOUND_VALUE = "sound" + const val ACTION_SET_TWEAK_HIGHLIGHT_VALUE = "highlight" + + const val ACTION_PARAMETER_SET_TWEAK = "set_tweak" + const val ACTION_PARAMETER_VALUE = "value" + + const val ACTION_VALUE_DEFAULT = "default" + const val ACTION_VALUE_RING = "ring" + } +} diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/pushrules/rest/RuleSet.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/pushrules/rest/RuleSet.kt index 43b2599b52..28f680b12b 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/pushrules/rest/RuleSet.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/pushrules/rest/RuleSet.kt @@ -17,6 +17,7 @@ package im.vector.matrix.android.api.pushrules.rest import com.squareup.moshi.Json import com.squareup.moshi.JsonClass +import im.vector.matrix.android.api.pushrules.RuleSetKey /** * Ref: https://matrix.org/docs/spec/client_server/latest#get-matrix-client-r0-pushrules @@ -38,4 +39,43 @@ data class RuleSet( // Ref. for the order: https://matrix.org/docs/spec/client_server/latest#push-rules return override.orEmpty() + content.orEmpty() + room.orEmpty() + sender.orEmpty() + underride.orEmpty() } + + /** + * Find a rule from its ruleID. + * + * @param ruleId a RULE_ID_XX value + * @return the matched bing rule or null it doesn't exist. + */ + fun findDefaultRule(ruleId: String?): PushRuleAndKind? { + var result: PushRuleAndKind? = null + // sanity check + if (null != ruleId) { + if (PushRule.RULE_ID_CONTAIN_USER_NAME == ruleId) { + result = findRule(content, ruleId)?.let { PushRuleAndKind(it, RuleSetKey.CONTENT) } + } else { + // assume that the ruleId is unique. + result = findRule(override, ruleId)?.let { PushRuleAndKind(it, RuleSetKey.OVERRIDE) } + if (null == result) { + result = findRule(underride, ruleId)?.let { PushRuleAndKind(it, RuleSetKey.UNDERRIDE) } + } + } + } + return result + } + + /** + * Find a rule from its rule Id. + * + * @param rules the rules list. + * @param ruleId the rule Id. + * @return the bing rule if it exists, else null. + */ + private fun findRule(rules: List?, ruleId: String): PushRule? { + return rules?.firstOrNull { it.ruleId == ruleId } + } } + +data class PushRuleAndKind( + val pushRule: PushRule, + val kind: RuleSetKey +) diff --git a/vector/src/main/java/im/vector/riotx/core/preference/BingRulePreference.kt b/vector/src/main/java/im/vector/riotx/core/preference/BingRulePreference.kt index 76df61dd33..2cb363621f 100755 --- a/vector/src/main/java/im/vector/riotx/core/preference/BingRulePreference.kt +++ b/vector/src/main/java/im/vector/riotx/core/preference/BingRulePreference.kt @@ -22,49 +22,17 @@ import android.view.View import android.widget.RadioGroup import android.widget.TextView import androidx.preference.PreferenceViewHolder +import im.vector.matrix.android.api.pushrules.RuleSetKey +import im.vector.matrix.android.api.pushrules.rest.PushRule +import im.vector.matrix.android.api.pushrules.rest.PushRuleAndKind import im.vector.riotx.R -// TODO Replace by real Bingrule class, then delete -@Suppress("UNUSED_PARAMETER") -class BingRule(rule: BingRule) { - fun shouldNotNotify() = false - fun shouldNotify() = false - fun setNotify(b: Boolean) { - } - - fun setHighlight(b: Boolean) { - } - - fun removeNotificationSound() { - } - - val ruleId: CharSequence? = null - var isEnabled = false - var notificationSound: String? = null - val kind: CharSequence? = null - - companion object { - const val RULE_ID_SUPPRESS_BOTS_NOTIFICATIONS = "TODO" - const val ACTION_VALUE_DEFAULT = "TODO" - const val KIND_UNDERRIDE = "TODO" - const val RULE_ID_INVITE_ME = "TODO" - const val RULE_ID_CALL = "TODO" - const val ACTION_VALUE_RING = "TODO" - const val RULE_ID_DISABLE_ALL = "TODO" - const val ACTION_DONT_NOTIFY = "TODO" - const val RULE_ID_CONTAIN_DISPLAY_NAME = "TODO" - const val RULE_ID_CONTAIN_USER_NAME = "TODO" - const val RULE_ID_ONE_TO_ONE_ROOM = "TODO" - const val RULE_ID_ALL_OTHER_MESSAGES_ROOMS = "TODO" - } -} - class BingRulePreference : VectorPreference { /** - * @return the selected bing rule + * @return the selected push rule and its kind */ - var rule: BingRule? = null + var ruleAndKind: PushRuleAndKind? = null private set constructor(context: Context) : super(context) @@ -80,29 +48,29 @@ class BingRulePreference : VectorPreference { /** * @return the bing rule status index */ - val ruleStatusIndex: Int + private val ruleStatusIndex: Int get() { - if (null != rule) { - if (rule!!.ruleId == BingRule.RULE_ID_SUPPRESS_BOTS_NOTIFICATIONS) { - if (rule!!.shouldNotNotify()) { - return if (rule!!.isEnabled) { - NOTIFICATION_OFF_INDEX - } else { - NOTIFICATION_SILENT_INDEX - } - } else if (rule!!.shouldNotify()) { - return NOTIFICATION_NOISY_INDEX - } - } + val safeRule = ruleAndKind?.pushRule ?: return NOTIFICATION_OFF_INDEX - if (rule!!.isEnabled) { - return if (rule!!.shouldNotNotify()) { + if (safeRule.ruleId == PushRule.RULE_ID_SUPPRESS_BOTS_NOTIFICATIONS) { + if (safeRule.shouldNotNotify()) { + return if (safeRule.enabled) { NOTIFICATION_OFF_INDEX - } else if (null != rule!!.notificationSound) { - NOTIFICATION_NOISY_INDEX } else { NOTIFICATION_SILENT_INDEX } + } else if (safeRule.shouldNotify()) { + return NOTIFICATION_NOISY_INDEX + } + } + + if (safeRule.enabled) { + return if (safeRule.shouldNotNotify()) { + NOTIFICATION_OFF_INDEX + } else if (null != safeRule.getNotificationSound()) { + NOTIFICATION_NOISY_INDEX + } else { + NOTIFICATION_SILENT_INDEX } } @@ -110,12 +78,12 @@ class BingRulePreference : VectorPreference { } /** - * Update the bing rule. + * Update the push rule. * - * @param aBingRule + * @param pushRule */ - fun setBingRule(aBingRule: BingRule) { - rule = aBingRule + fun setPushRule(pushRuleAndKind: PushRuleAndKind?) { + ruleAndKind = pushRuleAndKind refreshSummary() } @@ -131,63 +99,63 @@ class BingRulePreference : VectorPreference { } /** - * Create a bing rule with the updated required at index. + * Create a push rule with the updated required at index. * * @param index index - * @return a bing rule with the updated flags / null if there is no update + * @return a push rule with the updated flags / null if there is no update */ - fun createRule(index: Int): BingRule? { - var rule: BingRule? = null + fun createRule(index: Int): PushRule? { + val safeRule = ruleAndKind?.pushRule ?: return null + val safeKind = ruleAndKind?.kind ?: return null - if (null != this.rule && index != ruleStatusIndex) { - rule = BingRule(this.rule!!) - - if (rule.ruleId == BingRule.RULE_ID_SUPPRESS_BOTS_NOTIFICATIONS) { + return if (index != ruleStatusIndex) { + if (safeRule.ruleId == PushRule.RULE_ID_SUPPRESS_BOTS_NOTIFICATIONS) { when (index) { NOTIFICATION_OFF_INDEX -> { - rule.isEnabled = true - rule.setNotify(false) + safeRule.copy(enabled = true) + .setNotify(false) } NOTIFICATION_SILENT_INDEX -> { - rule.isEnabled = false - rule.setNotify(false) + safeRule.copy(enabled = false) + .setNotify(false) } NOTIFICATION_NOISY_INDEX -> { - rule.isEnabled = true - rule.setNotify(true) - rule.notificationSound = BingRule.ACTION_VALUE_DEFAULT + safeRule.copy(enabled = true) + .setNotify(true) + .setNotificationSound() } - } - - return rule - } - - if (NOTIFICATION_OFF_INDEX == index) { - if (this.rule!!.kind == BingRule.KIND_UNDERRIDE - || rule.ruleId == BingRule.RULE_ID_SUPPRESS_BOTS_NOTIFICATIONS) { - rule.setNotify(false) - } else { - rule.isEnabled = false + else -> safeRule } } else { - rule.isEnabled = true - rule.setNotify(true) - rule.setHighlight(this.rule!!.kind != BingRule.KIND_UNDERRIDE - && rule.ruleId != BingRule.RULE_ID_INVITE_ME - && NOTIFICATION_NOISY_INDEX == index) - if (NOTIFICATION_NOISY_INDEX == index) { - rule.notificationSound = if (rule.ruleId == BingRule.RULE_ID_CALL) { - BingRule.ACTION_VALUE_RING + if (NOTIFICATION_OFF_INDEX == index) { + if (safeKind == RuleSetKey.UNDERRIDE || safeRule.ruleId == PushRule.RULE_ID_SUPPRESS_BOTS_NOTIFICATIONS) { + safeRule.setNotify(false) } else { - BingRule.ACTION_VALUE_DEFAULT + safeRule.copy(enabled = false) } } else { - rule.removeNotificationSound() + val newRule = safeRule.copy(enabled = true) + .setNotify(true) + .setHighlight(safeKind != RuleSetKey.UNDERRIDE + && safeRule.ruleId != PushRule.RULE_ID_INVITE_ME + && NOTIFICATION_NOISY_INDEX == index) + + if (NOTIFICATION_NOISY_INDEX == index) { + newRule.setNotificationSound( + if (safeRule.ruleId == PushRule.RULE_ID_CALL) { + PushRule.ACTION_VALUE_RING + } else { + PushRule.ACTION_VALUE_DEFAULT + } + ) + } else { + newRule.removeNotificationSound() + } } } + } else { + safeRule } - - return rule } override fun onBindViewHolder(holder: PreferenceViewHolder) { diff --git a/vector/src/main/java/im/vector/riotx/features/settings/VectorSettingsAdvancedNotificationPreferenceFragment.kt b/vector/src/main/java/im/vector/riotx/features/settings/VectorSettingsAdvancedNotificationPreferenceFragment.kt index a8328fae52..3ecd08953c 100644 --- a/vector/src/main/java/im/vector/riotx/features/settings/VectorSettingsAdvancedNotificationPreferenceFragment.kt +++ b/vector/src/main/java/im/vector/riotx/features/settings/VectorSettingsAdvancedNotificationPreferenceFragment.kt @@ -23,8 +23,9 @@ import android.os.Parcelable import androidx.core.content.edit import androidx.preference.Preference import androidx.preference.PreferenceManager +import im.vector.matrix.android.api.pushrules.rest.PushRule +import im.vector.matrix.android.api.pushrules.rest.PushRuleAndKind import im.vector.riotx.R -import im.vector.riotx.core.preference.BingRule import im.vector.riotx.core.preference.BingRulePreference import im.vector.riotx.core.preference.VectorPreference import im.vector.riotx.features.notifications.NotificationUtils @@ -102,14 +103,14 @@ class VectorSettingsAdvancedNotificationPreferenceFragment @Inject constructor( val preference = findPreference(preferenceKey) if (preference is BingRulePreference) { // preference.isEnabled = null != rules && isConnected && pushManager.areDeviceNotificationsAllowed() - val rule: BingRule? = null // TODO session.dataHandler.pushRules()?.findDefaultRule(mPrefKeyToBingRuleId[preferenceKey]) + val ruleAndKind: PushRuleAndKind? = session.getPushRules().findDefaultRule(mPrefKeyToBingRuleId[preferenceKey]) - if (rule == null) { + if (ruleAndKind == null) { // The rule is not defined, hide the preference preference.isVisible = false } else { preference.isVisible = true - preference.setBingRule(rule) + preference.setPushRule(ruleAndKind) preference.onPreferenceChangeListener = Preference.OnPreferenceChangeListener { _, newValue -> val rule2 = preference.createRule(newValue as Int) if (null != rule2) { @@ -181,7 +182,7 @@ class VectorSettingsAdvancedNotificationPreferenceFragment @Inject constructor( val rule = it.findDefaultRule(ruleId) var isEnabled = null != rule && rule.isEnabled - if (TextUtils.equals(ruleId, BingRule.RULE_ID_DISABLE_ALL) || TextUtils.equals(ruleId, BingRule.RULE_ID_SUPPRESS_BOTS_NOTIFICATIONS)) { + if (TextUtils.equals(ruleId, PushRule.RULE_ID_DISABLE_ALL) || TextUtils.equals(ruleId, PushRule.RULE_ID_SUPPRESS_BOTS_NOTIFICATIONS)) { isEnabled = !isEnabled } else if (isEnabled) { val domainActions = rule!!.domainActions @@ -191,7 +192,7 @@ class VectorSettingsAdvancedNotificationPreferenceFragment @Inject constructor( isEnabled = false } else if (1 == domainActions.size) { try { - isEnabled = !TextUtils.equals(domainActions[0] as String, BingRule.ACTION_DONT_NOTIFY) + isEnabled = !TextUtils.equals(domainActions[0] as String, PushRule.ACTION_DONT_NOTIFY) } catch (e: Exception) { Timber.e(e, "## refreshPreferences failed") } @@ -216,13 +217,13 @@ class VectorSettingsAdvancedNotificationPreferenceFragment @Inject constructor( // preference name <-> rule Id private var mPrefKeyToBingRuleId = mapOf( - VectorPreferences.SETTINGS_CONTAINING_MY_DISPLAY_NAME_PREFERENCE_KEY to BingRule.RULE_ID_CONTAIN_DISPLAY_NAME, - VectorPreferences.SETTINGS_CONTAINING_MY_USER_NAME_PREFERENCE_KEY to BingRule.RULE_ID_CONTAIN_USER_NAME, - VectorPreferences.SETTINGS_MESSAGES_IN_ONE_TO_ONE_PREFERENCE_KEY to BingRule.RULE_ID_ONE_TO_ONE_ROOM, - VectorPreferences.SETTINGS_MESSAGES_IN_GROUP_CHAT_PREFERENCE_KEY to BingRule.RULE_ID_ALL_OTHER_MESSAGES_ROOMS, - VectorPreferences.SETTINGS_INVITED_TO_ROOM_PREFERENCE_KEY to BingRule.RULE_ID_INVITE_ME, - VectorPreferences.SETTINGS_CALL_INVITATIONS_PREFERENCE_KEY to BingRule.RULE_ID_CALL, - VectorPreferences.SETTINGS_MESSAGES_SENT_BY_BOT_PREFERENCE_KEY to BingRule.RULE_ID_SUPPRESS_BOTS_NOTIFICATIONS + VectorPreferences.SETTINGS_CONTAINING_MY_DISPLAY_NAME_PREFERENCE_KEY to PushRule.RULE_ID_CONTAIN_DISPLAY_NAME, + VectorPreferences.SETTINGS_CONTAINING_MY_USER_NAME_PREFERENCE_KEY to PushRule.RULE_ID_CONTAIN_USER_NAME, + VectorPreferences.SETTINGS_MESSAGES_IN_ONE_TO_ONE_PREFERENCE_KEY to PushRule.RULE_ID_ONE_TO_ONE_ROOM, + VectorPreferences.SETTINGS_MESSAGES_IN_GROUP_CHAT_PREFERENCE_KEY to PushRule.RULE_ID_ALL_OTHER_MESSAGES_ROOMS, + VectorPreferences.SETTINGS_INVITED_TO_ROOM_PREFERENCE_KEY to PushRule.RULE_ID_INVITE_ME, + VectorPreferences.SETTINGS_CALL_INVITATIONS_PREFERENCE_KEY to PushRule.RULE_ID_CALL, + VectorPreferences.SETTINGS_MESSAGES_SENT_BY_BOT_PREFERENCE_KEY to PushRule.RULE_ID_SUPPRESS_BOTS_NOTIFICATIONS ) } } diff --git a/vector/src/main/res/values/strings_riotX.xml b/vector/src/main/res/values/strings_riotX.xml index 00bf65e121..2d1ed60505 100644 --- a/vector/src/main/res/values/strings_riotX.xml +++ b/vector/src/main/res/values/strings_riotX.xml @@ -11,7 +11,7 @@ - + Notifications configuration diff --git a/vector/src/main/res/xml/vector_settings_notification_advanced_preferences.xml b/vector/src/main/res/xml/vector_settings_notification_advanced_preferences.xml index b5f01d98f6..8882a434eb 100644 --- a/vector/src/main/res/xml/vector_settings_notification_advanced_preferences.xml +++ b/vector/src/main/res/xml/vector_settings_notification_advanced_preferences.xml @@ -36,29 +36,36 @@ - - - - - + android:title="@string/settings_notification_configuration"> - + + - + + + + + + + + diff --git a/vector/src/main/res/xml/vector_settings_notifications.xml b/vector/src/main/res/xml/vector_settings_notifications.xml index 2114dba373..82c9cde759 100644 --- a/vector/src/main/res/xml/vector_settings_notifications.xml +++ b/vector/src/main/res/xml/vector_settings_notifications.xml @@ -24,13 +24,11 @@ + app:fragment="im.vector.riotx.features.settings.VectorSettingsAdvancedNotificationPreferenceFragment" /> Date: Fri, 28 Feb 2020 18:35:51 +0100 Subject: [PATCH 23/91] Restore push rule settings - fix issues --- .../android/api/pushrules/PushRuleService.kt | 5 +- .../notification/DefaultPushRuleService.kt | 10 ++++ .../internal/session/pushers/PushRulesApi.kt | 1 + .../internal/session/pushers/PushersModule.kt | 3 + .../pushers/UpdatePushRuleActionsTask.kt | 55 +++++++++++++++++++ .../core/preference/BingRulePreference.kt | 5 +- ...sAdvancedNotificationPreferenceFragment.kt | 42 +++++++------- .../settings/VectorSettingsBaseFragment.kt | 3 + ...rSettingsNotificationPreferenceFragment.kt | 2 +- 9 files changed, 99 insertions(+), 27 deletions(-) create mode 100644 matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/pushers/UpdatePushRuleActionsTask.kt diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/pushrules/PushRuleService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/pushrules/PushRuleService.kt index 94c2121695..1c1c2f266c 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/pushrules/PushRuleService.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/pushrules/PushRuleService.kt @@ -22,7 +22,6 @@ import im.vector.matrix.android.api.session.events.model.Event import im.vector.matrix.android.api.util.Cancelable interface PushRuleService { - /** * Fetch the push rules from the server */ @@ -30,12 +29,12 @@ interface PushRuleService { fun getPushRules(scope: String = RuleScope.GLOBAL): RuleSet - // TODO update rule - fun updatePushRuleEnableStatus(kind: RuleKind, pushRule: PushRule, enabled: Boolean, callback: MatrixCallback): Cancelable fun addPushRule(kind: RuleKind, pushRule: PushRule, callback: MatrixCallback): Cancelable + fun updatePushRuleActions(kind: RuleKind, oldPushRule: PushRule, newPushRule: PushRule, callback: MatrixCallback): Cancelable + fun removePushRule(kind: RuleKind, pushRule: PushRule, callback: MatrixCallback): Cancelable fun addPushRuleListener(listener: PushRuleListener) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/notification/DefaultPushRuleService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/notification/DefaultPushRuleService.kt index e6e45735e9..f01b86fbdd 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/notification/DefaultPushRuleService.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/notification/DefaultPushRuleService.kt @@ -32,6 +32,7 @@ import im.vector.matrix.android.internal.session.SessionScope import im.vector.matrix.android.internal.session.pushers.AddPushRuleTask import im.vector.matrix.android.internal.session.pushers.GetPushRulesTask import im.vector.matrix.android.internal.session.pushers.RemovePushRuleTask +import im.vector.matrix.android.internal.session.pushers.UpdatePushRuleActionsTask import im.vector.matrix.android.internal.session.pushers.UpdatePushRuleEnableStatusTask import im.vector.matrix.android.internal.task.TaskExecutor import im.vector.matrix.android.internal.task.configureWith @@ -43,6 +44,7 @@ internal class DefaultPushRuleService @Inject constructor( private val getPushRulesTask: GetPushRulesTask, private val updatePushRuleEnableStatusTask: UpdatePushRuleEnableStatusTask, private val addPushRuleTask: AddPushRuleTask, + private val updatePushRuleActionsTask: UpdatePushRuleActionsTask, private val removePushRuleTask: RemovePushRuleTask, private val taskExecutor: TaskExecutor, private val monarchy: Monarchy @@ -117,6 +119,14 @@ internal class DefaultPushRuleService @Inject constructor( .executeBy(taskExecutor) } + override fun updatePushRuleActions(kind: RuleKind, oldPushRule: PushRule, newPushRule: PushRule, callback: MatrixCallback): Cancelable { + return updatePushRuleActionsTask + .configureWith(UpdatePushRuleActionsTask.Params(kind, oldPushRule, newPushRule)) { + this.callback = callback + } + .executeBy(taskExecutor) + } + override fun removePushRule(kind: RuleKind, pushRule: PushRule, callback: MatrixCallback): Cancelable { return removePushRuleTask .configureWith(RemovePushRuleTask.Params(kind, pushRule)) { diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/pushers/PushRulesApi.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/pushers/PushRulesApi.kt index db7d2a15ed..6dc7c1cd5a 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/pushers/PushRulesApi.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/pushers/PushRulesApi.kt @@ -47,6 +47,7 @@ internal interface PushRulesApi { /** * Update the ruleID action + * Ref: https://matrix.org/docs/spec/client_server/latest#put-matrix-client-r0-pushrules-scope-kind-ruleid-actions * * @param kind the notification kind (sender, room...) * @param ruleId the ruleId diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/pushers/PushersModule.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/pushers/PushersModule.kt index 35ee90bf42..e80fca09e7 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/pushers/PushersModule.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/pushers/PushersModule.kt @@ -72,6 +72,9 @@ internal abstract class PushersModule { @Binds abstract fun bindAddPushRuleTask(task: DefaultAddPushRuleTask): AddPushRuleTask + @Binds + abstract fun bindUpdatePushRuleActionTask(task: DefaultUpdatePushRuleActionsTask): UpdatePushRuleActionsTask + @Binds abstract fun bindRemovePushRuleTask(task: DefaultRemovePushRuleTask): RemovePushRuleTask diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/pushers/UpdatePushRuleActionsTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/pushers/UpdatePushRuleActionsTask.kt new file mode 100644 index 0000000000..d8025be14d --- /dev/null +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/pushers/UpdatePushRuleActionsTask.kt @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2020 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package im.vector.matrix.android.internal.session.pushers + +import im.vector.matrix.android.api.pushrules.RuleKind +import im.vector.matrix.android.api.pushrules.rest.PushRule +import im.vector.matrix.android.internal.network.executeRequest +import im.vector.matrix.android.internal.task.Task +import org.greenrobot.eventbus.EventBus +import javax.inject.Inject + +internal interface UpdatePushRuleActionsTask : Task { + data class Params( + val kind: RuleKind, + val oldPushRule: PushRule, + val newPushRule: PushRule + ) +} + +internal class DefaultUpdatePushRuleActionsTask @Inject constructor( + private val pushRulesApi: PushRulesApi, + private val eventBus: EventBus +) : UpdatePushRuleActionsTask { + + override suspend fun execute(params: UpdatePushRuleActionsTask.Params) { + if (params.oldPushRule.enabled != params.newPushRule.enabled) { + // First change enabled state + executeRequest(eventBus) { + apiCall = pushRulesApi.updateEnableRuleStatus(params.kind.value, params.newPushRule.ruleId, params.newPushRule.enabled) + } + } + + if (params.newPushRule.enabled) { + // Also ensure the actions are up to date + val body = mapOf("actions" to params.newPushRule.actions) + + executeRequest(eventBus) { + apiCall = pushRulesApi.updateRuleActions(params.kind.value, params.newPushRule.ruleId, body) + } + } + } +} diff --git a/vector/src/main/java/im/vector/riotx/core/preference/BingRulePreference.kt b/vector/src/main/java/im/vector/riotx/core/preference/BingRulePreference.kt index 2cb363621f..1f074261a4 100755 --- a/vector/src/main/java/im/vector/riotx/core/preference/BingRulePreference.kt +++ b/vector/src/main/java/im/vector/riotx/core/preference/BingRulePreference.kt @@ -67,7 +67,7 @@ class BingRulePreference : VectorPreference { if (safeRule.enabled) { return if (safeRule.shouldNotNotify()) { NOTIFICATION_OFF_INDEX - } else if (null != safeRule.getNotificationSound()) { + } else if (safeRule.getNotificationSound() != null) { NOTIFICATION_NOISY_INDEX } else { NOTIFICATION_SILENT_INDEX @@ -104,7 +104,7 @@ class BingRulePreference : VectorPreference { * @param index index * @return a push rule with the updated flags / null if there is no update */ - fun createRule(index: Int): PushRule? { + fun createNewRule(index: Int): PushRule? { val safeRule = ruleAndKind?.pushRule ?: return null val safeKind = ruleAndKind?.kind ?: return null @@ -114,6 +114,7 @@ class BingRulePreference : VectorPreference { NOTIFICATION_OFF_INDEX -> { safeRule.copy(enabled = true) .setNotify(false) + .removeNotificationSound() } NOTIFICATION_SILENT_INDEX -> { safeRule.copy(enabled = false) diff --git a/vector/src/main/java/im/vector/riotx/features/settings/VectorSettingsAdvancedNotificationPreferenceFragment.kt b/vector/src/main/java/im/vector/riotx/features/settings/VectorSettingsAdvancedNotificationPreferenceFragment.kt index 3ecd08953c..483539036e 100644 --- a/vector/src/main/java/im/vector/riotx/features/settings/VectorSettingsAdvancedNotificationPreferenceFragment.kt +++ b/vector/src/main/java/im/vector/riotx/features/settings/VectorSettingsAdvancedNotificationPreferenceFragment.kt @@ -23,11 +23,13 @@ import android.os.Parcelable import androidx.core.content.edit import androidx.preference.Preference import androidx.preference.PreferenceManager +import im.vector.matrix.android.api.MatrixCallback import im.vector.matrix.android.api.pushrules.rest.PushRule import im.vector.matrix.android.api.pushrules.rest.PushRuleAndKind import im.vector.riotx.R import im.vector.riotx.core.preference.BingRulePreference import im.vector.riotx.core.preference.VectorPreference +import im.vector.riotx.core.utils.toast import im.vector.riotx.features.notifications.NotificationUtils import javax.inject.Inject @@ -112,29 +114,27 @@ class VectorSettingsAdvancedNotificationPreferenceFragment @Inject constructor( preference.isVisible = true preference.setPushRule(ruleAndKind) preference.onPreferenceChangeListener = Preference.OnPreferenceChangeListener { _, newValue -> - val rule2 = preference.createRule(newValue as Int) - if (null != rule2) { - /* - TODO - displayLoadingView() - session.dataHandler.bingRulesManager.updateRule(preference.rule, - rule, - object : BingRulesManager.onBingRuleUpdateListener { - private fun onDone() { - refreshDisplay() - hideLoadingView() - } + val newRule = preference.createNewRule(newValue as Int) + if (newRule != null) { + displayLoadingView() - override fun onBingRuleUpdateSuccess() { - onDone() - } + session.updatePushRuleActions(ruleAndKind.kind, preference.ruleAndKind?.pushRule ?: ruleAndKind.pushRule, newRule, object : MatrixCallback { + override fun onSuccess(data: Unit) { + if (!isAdded) { + return + } + preference.setPushRule(ruleAndKind.copy(pushRule = newRule)) + hideLoadingView() + } - override fun onBingRuleUpdateFailure(errorMessage: String) { - activity?.toast(errorMessage) - onDone() - } - }) - */ + override fun onFailure(failure: Throwable) { + if (!isAdded) { + return + } + hideLoadingView() + activity?.toast(errorFormatter.toHumanReadable(failure)) + } + }) } false } diff --git a/vector/src/main/java/im/vector/riotx/features/settings/VectorSettingsBaseFragment.kt b/vector/src/main/java/im/vector/riotx/features/settings/VectorSettingsBaseFragment.kt index e32cc98123..85d32251b6 100644 --- a/vector/src/main/java/im/vector/riotx/features/settings/VectorSettingsBaseFragment.kt +++ b/vector/src/main/java/im/vector/riotx/features/settings/VectorSettingsBaseFragment.kt @@ -26,6 +26,7 @@ import im.vector.riotx.R import im.vector.riotx.core.di.DaggerScreenComponent import im.vector.riotx.core.di.HasScreenInjector import im.vector.riotx.core.di.ScreenComponent +import im.vector.riotx.core.error.ErrorFormatter import im.vector.riotx.core.platform.VectorBaseActivity import im.vector.riotx.core.utils.toast import timber.log.Timber @@ -40,6 +41,7 @@ abstract class VectorSettingsBaseFragment : PreferenceFragmentCompat(), HasScree // members protected lateinit var session: Session + protected lateinit var errorFormatter: ErrorFormatter private lateinit var screenComponent: ScreenComponent abstract val preferenceXmlRes: Int @@ -54,6 +56,7 @@ abstract class VectorSettingsBaseFragment : PreferenceFragmentCompat(), HasScree screenComponent = DaggerScreenComponent.factory().create(vectorActivity.getVectorComponent(), vectorActivity) super.onAttach(context) session = screenComponent.activeSessionHolder().getActiveSession() + errorFormatter = screenComponent.errorFormatter() injectWith(injector()) } diff --git a/vector/src/main/java/im/vector/riotx/features/settings/VectorSettingsNotificationPreferenceFragment.kt b/vector/src/main/java/im/vector/riotx/features/settings/VectorSettingsNotificationPreferenceFragment.kt index 65f68bb3b7..4e4e9ddb7a 100644 --- a/vector/src/main/java/im/vector/riotx/features/settings/VectorSettingsNotificationPreferenceFragment.kt +++ b/vector/src/main/java/im/vector/riotx/features/settings/VectorSettingsNotificationPreferenceFragment.kt @@ -114,7 +114,7 @@ class VectorSettingsNotificationPreferenceFragment @Inject constructor( !switchPref.isChecked, object : MatrixCallback { override fun onSuccess(data: Unit) { - // Push rules will be updated form the sync + // Push rules will be updated from the sync } override fun onFailure(failure: Throwable) { From 551604cdcb9d31482c3b40c323238b5da2bc538a Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 28 Feb 2020 19:02:13 +0100 Subject: [PATCH 24/91] Add missing push rules --- .../android/api/pushrules/rest/PushRule.kt | 5 +++ .../features/settings/VectorPreferences.kt | 4 ++ ...sAdvancedNotificationPreferenceFragment.kt | 44 +++++++++++-------- vector/src/main/res/values/strings_riotX.xml | 4 ++ ...ings_notification_advanced_preferences.xml | 18 ++++++++ 5 files changed, 57 insertions(+), 18 deletions(-) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/pushrules/rest/PushRule.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/pushrules/rest/PushRule.kt index d60fe2e9c4..699ce29032 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/pushrules/rest/PushRule.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/pushrules/rest/PushRule.kt @@ -148,6 +148,11 @@ data class PushRule( const val RULE_ID_CALL = ".m.rule.call" const val RULE_ID_SUPPRESS_BOTS_NOTIFICATIONS = ".m.rule.suppress_notices" const val RULE_ID_ALL_OTHER_MESSAGES_ROOMS = ".m.rule.message" + const val RULE_ID_AT_ROOMS = ".m.rule.roomnotif" + const val RULE_ID_TOMBSTONE = ".m.rule.tombstone" + const val RULE_ID_E2E_ONE_TO_ONE_ROOM = ".m.rule.encrypted_room_one_to_one" + const val RULE_ID_E2E_GROUP = ".m.rule.encrypted" + const val RULE_ID_REACTION = ".m.rule.reaction" const val RULE_ID_FALLBACK = ".m.rule.fallback" /* ========================================================================================== diff --git a/vector/src/main/java/im/vector/riotx/features/settings/VectorPreferences.kt b/vector/src/main/java/im/vector/riotx/features/settings/VectorPreferences.kt index 816b5b3fee..2132911fff 100755 --- a/vector/src/main/java/im/vector/riotx/features/settings/VectorPreferences.kt +++ b/vector/src/main/java/im/vector/riotx/features/settings/VectorPreferences.kt @@ -121,6 +121,10 @@ class VectorPreferences @Inject constructor(private val context: Context) { const val SETTINGS_MESSAGES_IN_GROUP_CHAT_PREFERENCE_KEY = "SETTINGS_MESSAGES_IN_GROUP_CHAT_PREFERENCE_KEY_2" const val SETTINGS_INVITED_TO_ROOM_PREFERENCE_KEY = "SETTINGS_INVITED_TO_ROOM_PREFERENCE_KEY_2" const val SETTINGS_CALL_INVITATIONS_PREFERENCE_KEY = "SETTINGS_CALL_INVITATIONS_PREFERENCE_KEY_2" + const val SETTINGS_MESSAGES_CONTAINING_AT_ROOM_PREFERENCE_KEY = "SETTINGS_MESSAGES_CONTAINING_AT_ROOM_PREFERENCE_KEY" + const val SETTINGS_MESSAGES_IN_E2E_ONE_ONE_CHAT_PREFERENCE_KEY = "SETTINGS_MESSAGES_IN_E2E_ONE_ONE_CHAT_PREFERENCE_KEY" + const val SETTINGS_MESSAGES_IN_E2E_GROUP_CHAT_PREFERENCE_KEY = "SETTINGS_MESSAGES_IN_E2E_GROUP_CHAT_PREFERENCE_KEY" + const val SETTINGS_ROOMS_UPGRADED_KEY = "SETTINGS_ROOMS_UPGRADED_KEY" // media private const val SETTINGS_DEFAULT_MEDIA_COMPRESSION_KEY = "SETTINGS_DEFAULT_MEDIA_COMPRESSION_KEY" diff --git a/vector/src/main/java/im/vector/riotx/features/settings/VectorSettingsAdvancedNotificationPreferenceFragment.kt b/vector/src/main/java/im/vector/riotx/features/settings/VectorSettingsAdvancedNotificationPreferenceFragment.kt index 483539036e..134eaaa5c1 100644 --- a/vector/src/main/java/im/vector/riotx/features/settings/VectorSettingsAdvancedNotificationPreferenceFragment.kt +++ b/vector/src/main/java/im/vector/riotx/features/settings/VectorSettingsAdvancedNotificationPreferenceFragment.kt @@ -118,23 +118,27 @@ class VectorSettingsAdvancedNotificationPreferenceFragment @Inject constructor( if (newRule != null) { displayLoadingView() - session.updatePushRuleActions(ruleAndKind.kind, preference.ruleAndKind?.pushRule ?: ruleAndKind.pushRule, newRule, object : MatrixCallback { - override fun onSuccess(data: Unit) { - if (!isAdded) { - return - } - preference.setPushRule(ruleAndKind.copy(pushRule = newRule)) - hideLoadingView() - } + session.updatePushRuleActions( + ruleAndKind.kind, + preference.ruleAndKind?.pushRule ?: ruleAndKind.pushRule, + newRule, + object : MatrixCallback { + override fun onSuccess(data: Unit) { + if (!isAdded) { + return + } + preference.setPushRule(ruleAndKind.copy(pushRule = newRule)) + hideLoadingView() + } - override fun onFailure(failure: Throwable) { - if (!isAdded) { - return - } - hideLoadingView() - activity?.toast(errorFormatter.toHumanReadable(failure)) - } - }) + override fun onFailure(failure: Throwable) { + if (!isAdded) { + return + } + hideLoadingView() + activity?.toast(errorFormatter.toHumanReadable(failure)) + } + }) } false } @@ -216,14 +220,18 @@ class VectorSettingsAdvancedNotificationPreferenceFragment @Inject constructor( private const val REQUEST_NOTIFICATION_RINGTONE = 888 // preference name <-> rule Id - private var mPrefKeyToBingRuleId = mapOf( + private val mPrefKeyToBingRuleId = mapOf( VectorPreferences.SETTINGS_CONTAINING_MY_DISPLAY_NAME_PREFERENCE_KEY to PushRule.RULE_ID_CONTAIN_DISPLAY_NAME, VectorPreferences.SETTINGS_CONTAINING_MY_USER_NAME_PREFERENCE_KEY to PushRule.RULE_ID_CONTAIN_USER_NAME, VectorPreferences.SETTINGS_MESSAGES_IN_ONE_TO_ONE_PREFERENCE_KEY to PushRule.RULE_ID_ONE_TO_ONE_ROOM, VectorPreferences.SETTINGS_MESSAGES_IN_GROUP_CHAT_PREFERENCE_KEY to PushRule.RULE_ID_ALL_OTHER_MESSAGES_ROOMS, VectorPreferences.SETTINGS_INVITED_TO_ROOM_PREFERENCE_KEY to PushRule.RULE_ID_INVITE_ME, VectorPreferences.SETTINGS_CALL_INVITATIONS_PREFERENCE_KEY to PushRule.RULE_ID_CALL, - VectorPreferences.SETTINGS_MESSAGES_SENT_BY_BOT_PREFERENCE_KEY to PushRule.RULE_ID_SUPPRESS_BOTS_NOTIFICATIONS + VectorPreferences.SETTINGS_MESSAGES_SENT_BY_BOT_PREFERENCE_KEY to PushRule.RULE_ID_SUPPRESS_BOTS_NOTIFICATIONS, + VectorPreferences.SETTINGS_MESSAGES_CONTAINING_AT_ROOM_PREFERENCE_KEY to PushRule.RULE_ID_AT_ROOMS, + VectorPreferences.SETTINGS_MESSAGES_IN_E2E_ONE_ONE_CHAT_PREFERENCE_KEY to PushRule.RULE_ID_E2E_ONE_TO_ONE_ROOM, + VectorPreferences.SETTINGS_MESSAGES_IN_E2E_GROUP_CHAT_PREFERENCE_KEY to PushRule.RULE_ID_E2E_GROUP, + VectorPreferences.SETTINGS_ROOMS_UPGRADED_KEY to PushRule.RULE_ID_TOMBSTONE ) } } diff --git a/vector/src/main/res/values/strings_riotX.xml b/vector/src/main/res/values/strings_riotX.xml index 2d1ed60505..c20698d767 100644 --- a/vector/src/main/res/values/strings_riotX.xml +++ b/vector/src/main/res/values/strings_riotX.xml @@ -12,6 +12,10 @@ Notifications configuration + Messages containing @room + Encrypted messages in one-to-one chats + Encrypted messages in group chats + When rooms are upgraded diff --git a/vector/src/main/res/xml/vector_settings_notification_advanced_preferences.xml b/vector/src/main/res/xml/vector_settings_notification_advanced_preferences.xml index 8882a434eb..33f8fe1d81 100644 --- a/vector/src/main/res/xml/vector_settings_notification_advanced_preferences.xml +++ b/vector/src/main/res/xml/vector_settings_notification_advanced_preferences.xml @@ -14,14 +14,28 @@ android:key="SETTINGS_CONTAINING_MY_USER_NAME_PREFERENCE_KEY_2" android:title="@string/settings_containing_my_user_name" /> + + + + + + + + @@ -34,6 +48,10 @@ android:key="SETTINGS_MESSAGES_SENT_BY_BOT_PREFERENCE_KEY_2" android:title="@string/settings_messages_sent_by_bot" /> + + Date: Fri, 28 Feb 2020 19:04:30 +0100 Subject: [PATCH 25/91] Cleanup --- .../features/settings/VectorPreferences.kt | 15 +++++------ ...ings_notification_advanced_preferences.xml | 27 +++++++++++++------ 2 files changed, 26 insertions(+), 16 deletions(-) diff --git a/vector/src/main/java/im/vector/riotx/features/settings/VectorPreferences.kt b/vector/src/main/java/im/vector/riotx/features/settings/VectorPreferences.kt index 2132911fff..c92c394cfb 100755 --- a/vector/src/main/java/im/vector/riotx/features/settings/VectorPreferences.kt +++ b/vector/src/main/java/im/vector/riotx/features/settings/VectorPreferences.kt @@ -35,7 +35,7 @@ import javax.inject.Inject class VectorPreferences @Inject constructor(private val context: Context) { companion object { - const val SETTINGS_MESSAGES_SENT_BY_BOT_PREFERENCE_KEY = "SETTINGS_MESSAGES_SENT_BY_BOT_PREFERENCE_KEY_2" + const val SETTINGS_MESSAGES_SENT_BY_BOT_PREFERENCE_KEY = "SETTINGS_MESSAGES_SENT_BY_BOT_PREFERENCE_KEY" const val SETTINGS_CHANGE_PASSWORD_PREFERENCE_KEY = "SETTINGS_CHANGE_PASSWORD_PREFERENCE_KEY" const val SETTINGS_VERSION_PREFERENCE_KEY = "SETTINGS_VERSION_PREFERENCE_KEY" const val SETTINGS_SDK_VERSION_PREFERENCE_KEY = "SETTINGS_SDK_VERSION_PREFERENCE_KEY" @@ -106,7 +106,6 @@ class VectorPreferences @Inject constructor(private val context: Context) { const val SETTINGS_GROUPS_FLAIR_KEY = "SETTINGS_GROUPS_FLAIR_KEY" // notifications - const val SETTINGS_NOTIFICATIONS_KEY = "SETTINGS_NOTIFICATIONS_KEY" const val SETTINGS_ENABLE_ALL_NOTIF_PREFERENCE_KEY = "SETTINGS_ENABLE_ALL_NOTIF_PREFERENCE_KEY" const val SETTINGS_ENABLE_THIS_DEVICE_PREFERENCE_KEY = "SETTINGS_ENABLE_THIS_DEVICE_PREFERENCE_KEY" // public static final String SETTINGS_TURN_SCREEN_ON_PREFERENCE_KEY = "SETTINGS_TURN_SCREEN_ON_PREFERENCE_KEY"; @@ -115,12 +114,12 @@ class VectorPreferences @Inject constructor(private val context: Context) { const val SETTINGS_SYSTEM_SILENT_NOTIFICATION_PREFERENCE_KEY = "SETTINGS_SYSTEM_SILENT_NOTIFICATION_PREFERENCE_KEY" const val SETTINGS_NOTIFICATION_RINGTONE_PREFERENCE_KEY = "SETTINGS_NOTIFICATION_RINGTONE_PREFERENCE_KEY" const val SETTINGS_NOTIFICATION_RINGTONE_SELECTION_PREFERENCE_KEY = "SETTINGS_NOTIFICATION_RINGTONE_SELECTION_PREFERENCE_KEY" - const val SETTINGS_CONTAINING_MY_DISPLAY_NAME_PREFERENCE_KEY = "SETTINGS_CONTAINING_MY_DISPLAY_NAME_PREFERENCE_KEY_2" - const val SETTINGS_CONTAINING_MY_USER_NAME_PREFERENCE_KEY = "SETTINGS_CONTAINING_MY_USER_NAME_PREFERENCE_KEY_2" - const val SETTINGS_MESSAGES_IN_ONE_TO_ONE_PREFERENCE_KEY = "SETTINGS_MESSAGES_IN_ONE_TO_ONE_PREFERENCE_KEY_2" - const val SETTINGS_MESSAGES_IN_GROUP_CHAT_PREFERENCE_KEY = "SETTINGS_MESSAGES_IN_GROUP_CHAT_PREFERENCE_KEY_2" - const val SETTINGS_INVITED_TO_ROOM_PREFERENCE_KEY = "SETTINGS_INVITED_TO_ROOM_PREFERENCE_KEY_2" - const val SETTINGS_CALL_INVITATIONS_PREFERENCE_KEY = "SETTINGS_CALL_INVITATIONS_PREFERENCE_KEY_2" + const val SETTINGS_CONTAINING_MY_DISPLAY_NAME_PREFERENCE_KEY = "SETTINGS_CONTAINING_MY_DISPLAY_NAME_PREFERENCE_KEY" + const val SETTINGS_CONTAINING_MY_USER_NAME_PREFERENCE_KEY = "SETTINGS_CONTAINING_MY_USER_NAME_PREFERENCE_KEY" + const val SETTINGS_MESSAGES_IN_ONE_TO_ONE_PREFERENCE_KEY = "SETTINGS_MESSAGES_IN_ONE_TO_ONE_PREFERENCE_KEY" + const val SETTINGS_MESSAGES_IN_GROUP_CHAT_PREFERENCE_KEY = "SETTINGS_MESSAGES_IN_GROUP_CHAT_PREFERENCE_KEY" + const val SETTINGS_INVITED_TO_ROOM_PREFERENCE_KEY = "SETTINGS_INVITED_TO_ROOM_PREFERENCE_KEY" + const val SETTINGS_CALL_INVITATIONS_PREFERENCE_KEY = "SETTINGS_CALL_INVITATIONS_PREFERENCE_KEY" const val SETTINGS_MESSAGES_CONTAINING_AT_ROOM_PREFERENCE_KEY = "SETTINGS_MESSAGES_CONTAINING_AT_ROOM_PREFERENCE_KEY" const val SETTINGS_MESSAGES_IN_E2E_ONE_ONE_CHAT_PREFERENCE_KEY = "SETTINGS_MESSAGES_IN_E2E_ONE_ONE_CHAT_PREFERENCE_KEY" const val SETTINGS_MESSAGES_IN_E2E_GROUP_CHAT_PREFERENCE_KEY = "SETTINGS_MESSAGES_IN_E2E_GROUP_CHAT_PREFERENCE_KEY" diff --git a/vector/src/main/res/xml/vector_settings_notification_advanced_preferences.xml b/vector/src/main/res/xml/vector_settings_notification_advanced_preferences.xml index 33f8fe1d81..3ef86d1198 100644 --- a/vector/src/main/res/xml/vector_settings_notification_advanced_preferences.xml +++ b/vector/src/main/res/xml/vector_settings_notification_advanced_preferences.xml @@ -3,53 +3,63 @@ @@ -63,6 +73,7 @@ From 957b9eee23bffd3e9ae7e0e675fe116b6710436f Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 28 Feb 2020 19:06:26 +0100 Subject: [PATCH 26/91] Cleanup --- ...sAdvancedNotificationPreferenceFragment.kt | 61 ++----------------- 1 file changed, 5 insertions(+), 56 deletions(-) diff --git a/vector/src/main/java/im/vector/riotx/features/settings/VectorSettingsAdvancedNotificationPreferenceFragment.kt b/vector/src/main/java/im/vector/riotx/features/settings/VectorSettingsAdvancedNotificationPreferenceFragment.kt index 134eaaa5c1..90f28e5d15 100644 --- a/vector/src/main/java/im/vector/riotx/features/settings/VectorSettingsAdvancedNotificationPreferenceFragment.kt +++ b/vector/src/main/java/im/vector/riotx/features/settings/VectorSettingsAdvancedNotificationPreferenceFragment.kt @@ -20,9 +20,7 @@ import android.content.Intent import android.media.RingtoneManager import android.net.Uri import android.os.Parcelable -import androidx.core.content.edit import androidx.preference.Preference -import androidx.preference.PreferenceManager import im.vector.matrix.android.api.MatrixCallback import im.vector.matrix.android.api.pushrules.rest.PushRule import im.vector.matrix.android.api.pushrules.rest.PushRuleAndKind @@ -37,15 +35,6 @@ class VectorSettingsAdvancedNotificationPreferenceFragment @Inject constructor( private val vectorPreferences: VectorPreferences ) : VectorSettingsBaseFragment() { - // events listener - /* TODO - private val mEventsListener = object : MXEventListener() { - override fun onBingRulesUpdate() { - refreshPreferences() - refreshDisplay() - } - } */ - override var titleRes: Int = R.string.settings_notification_advanced override val preferenceXmlRes = R.xml.vector_settings_notification_advanced_preferences @@ -101,11 +90,11 @@ class VectorSettingsAdvancedNotificationPreferenceFragment @Inject constructor( } } - for (preferenceKey in mPrefKeyToBingRuleId.keys) { + for (preferenceKey in prefKeyToPushRuleId.keys) { val preference = findPreference(preferenceKey) if (preference is BingRulePreference) { // preference.isEnabled = null != rules && isConnected && pushManager.areDeviceNotificationsAllowed() - val ruleAndKind: PushRuleAndKind? = session.getPushRules().findDefaultRule(mPrefKeyToBingRuleId[preferenceKey]) + val ruleAndKind: PushRuleAndKind? = session.getPushRules().findDefaultRule(prefKeyToPushRuleId[preferenceKey]) if (ruleAndKind == null) { // The rule is not defined, hide the preference @@ -136,6 +125,8 @@ class VectorSettingsAdvancedNotificationPreferenceFragment @Inject constructor( return } hideLoadingView() + // Restore the previous value + refreshDisplay() activity?.toast(errorFormatter.toHumanReadable(failure)) } }) @@ -170,48 +161,6 @@ class VectorSettingsAdvancedNotificationPreferenceFragment @Inject constructor( } } - /** - * Refresh the known information about the account - */ - private fun refreshPreferences() { - PreferenceManager.getDefaultSharedPreferences(activity).edit { - /* TODO - session.dataHandler.pushRules()?.let { - for (prefKey in mPrefKeyToBingRuleId.keys) { - val preference = findPreference(prefKey) - - if (null != preference && preference is SwitchPreference) { - val ruleId = mPrefKeyToBingRuleId[prefKey] - - val rule = it.findDefaultRule(ruleId) - var isEnabled = null != rule && rule.isEnabled - - if (TextUtils.equals(ruleId, PushRule.RULE_ID_DISABLE_ALL) || TextUtils.equals(ruleId, PushRule.RULE_ID_SUPPRESS_BOTS_NOTIFICATIONS)) { - isEnabled = !isEnabled - } else if (isEnabled) { - val domainActions = rule!!.domainActions - - // no action -> noting will be done - if (null == domainActions || domainActions.isEmpty()) { - isEnabled = false - } else if (1 == domainActions.size) { - try { - isEnabled = !TextUtils.equals(domainActions[0] as String, PushRule.ACTION_DONT_NOTIFY) - } catch (e: Exception) { - Timber.e(e, "## refreshPreferences failed") - } - - } - }// check if the rule is only defined by don't notify - - putBoolean(prefKey, isEnabled) - } - } - } - */ - } - } - /* ========================================================================================== * Companion * ========================================================================================== */ @@ -220,7 +169,7 @@ class VectorSettingsAdvancedNotificationPreferenceFragment @Inject constructor( private const val REQUEST_NOTIFICATION_RINGTONE = 888 // preference name <-> rule Id - private val mPrefKeyToBingRuleId = mapOf( + private val prefKeyToPushRuleId = mapOf( VectorPreferences.SETTINGS_CONTAINING_MY_DISPLAY_NAME_PREFERENCE_KEY to PushRule.RULE_ID_CONTAIN_DISPLAY_NAME, VectorPreferences.SETTINGS_CONTAINING_MY_USER_NAME_PREFERENCE_KEY to PushRule.RULE_ID_CONTAIN_USER_NAME, VectorPreferences.SETTINGS_MESSAGES_IN_ONE_TO_ONE_PREFERENCE_KEY to PushRule.RULE_ID_ONE_TO_ONE_ROOM, From c20de4feb02586ac45c831fa98dfa3619964f71b Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 28 Feb 2020 19:13:22 +0100 Subject: [PATCH 27/91] Cleanup --- .../features/settings/VectorPreferences.kt | 11 ---------- ...sAdvancedNotificationPreferenceFragment.kt | 22 +++++++++---------- ...ings_notification_advanced_preferences.xml | 22 +++++++++---------- 3 files changed, 22 insertions(+), 33 deletions(-) diff --git a/vector/src/main/java/im/vector/riotx/features/settings/VectorPreferences.kt b/vector/src/main/java/im/vector/riotx/features/settings/VectorPreferences.kt index c92c394cfb..cd647de891 100755 --- a/vector/src/main/java/im/vector/riotx/features/settings/VectorPreferences.kt +++ b/vector/src/main/java/im/vector/riotx/features/settings/VectorPreferences.kt @@ -35,7 +35,6 @@ import javax.inject.Inject class VectorPreferences @Inject constructor(private val context: Context) { companion object { - const val SETTINGS_MESSAGES_SENT_BY_BOT_PREFERENCE_KEY = "SETTINGS_MESSAGES_SENT_BY_BOT_PREFERENCE_KEY" const val SETTINGS_CHANGE_PASSWORD_PREFERENCE_KEY = "SETTINGS_CHANGE_PASSWORD_PREFERENCE_KEY" const val SETTINGS_VERSION_PREFERENCE_KEY = "SETTINGS_VERSION_PREFERENCE_KEY" const val SETTINGS_SDK_VERSION_PREFERENCE_KEY = "SETTINGS_SDK_VERSION_PREFERENCE_KEY" @@ -114,16 +113,6 @@ class VectorPreferences @Inject constructor(private val context: Context) { const val SETTINGS_SYSTEM_SILENT_NOTIFICATION_PREFERENCE_KEY = "SETTINGS_SYSTEM_SILENT_NOTIFICATION_PREFERENCE_KEY" const val SETTINGS_NOTIFICATION_RINGTONE_PREFERENCE_KEY = "SETTINGS_NOTIFICATION_RINGTONE_PREFERENCE_KEY" const val SETTINGS_NOTIFICATION_RINGTONE_SELECTION_PREFERENCE_KEY = "SETTINGS_NOTIFICATION_RINGTONE_SELECTION_PREFERENCE_KEY" - const val SETTINGS_CONTAINING_MY_DISPLAY_NAME_PREFERENCE_KEY = "SETTINGS_CONTAINING_MY_DISPLAY_NAME_PREFERENCE_KEY" - const val SETTINGS_CONTAINING_MY_USER_NAME_PREFERENCE_KEY = "SETTINGS_CONTAINING_MY_USER_NAME_PREFERENCE_KEY" - const val SETTINGS_MESSAGES_IN_ONE_TO_ONE_PREFERENCE_KEY = "SETTINGS_MESSAGES_IN_ONE_TO_ONE_PREFERENCE_KEY" - const val SETTINGS_MESSAGES_IN_GROUP_CHAT_PREFERENCE_KEY = "SETTINGS_MESSAGES_IN_GROUP_CHAT_PREFERENCE_KEY" - const val SETTINGS_INVITED_TO_ROOM_PREFERENCE_KEY = "SETTINGS_INVITED_TO_ROOM_PREFERENCE_KEY" - const val SETTINGS_CALL_INVITATIONS_PREFERENCE_KEY = "SETTINGS_CALL_INVITATIONS_PREFERENCE_KEY" - const val SETTINGS_MESSAGES_CONTAINING_AT_ROOM_PREFERENCE_KEY = "SETTINGS_MESSAGES_CONTAINING_AT_ROOM_PREFERENCE_KEY" - const val SETTINGS_MESSAGES_IN_E2E_ONE_ONE_CHAT_PREFERENCE_KEY = "SETTINGS_MESSAGES_IN_E2E_ONE_ONE_CHAT_PREFERENCE_KEY" - const val SETTINGS_MESSAGES_IN_E2E_GROUP_CHAT_PREFERENCE_KEY = "SETTINGS_MESSAGES_IN_E2E_GROUP_CHAT_PREFERENCE_KEY" - const val SETTINGS_ROOMS_UPGRADED_KEY = "SETTINGS_ROOMS_UPGRADED_KEY" // media private const val SETTINGS_DEFAULT_MEDIA_COMPRESSION_KEY = "SETTINGS_DEFAULT_MEDIA_COMPRESSION_KEY" diff --git a/vector/src/main/java/im/vector/riotx/features/settings/VectorSettingsAdvancedNotificationPreferenceFragment.kt b/vector/src/main/java/im/vector/riotx/features/settings/VectorSettingsAdvancedNotificationPreferenceFragment.kt index 90f28e5d15..772e9df3d3 100644 --- a/vector/src/main/java/im/vector/riotx/features/settings/VectorSettingsAdvancedNotificationPreferenceFragment.kt +++ b/vector/src/main/java/im/vector/riotx/features/settings/VectorSettingsAdvancedNotificationPreferenceFragment.kt @@ -170,17 +170,17 @@ class VectorSettingsAdvancedNotificationPreferenceFragment @Inject constructor( // preference name <-> rule Id private val prefKeyToPushRuleId = mapOf( - VectorPreferences.SETTINGS_CONTAINING_MY_DISPLAY_NAME_PREFERENCE_KEY to PushRule.RULE_ID_CONTAIN_DISPLAY_NAME, - VectorPreferences.SETTINGS_CONTAINING_MY_USER_NAME_PREFERENCE_KEY to PushRule.RULE_ID_CONTAIN_USER_NAME, - VectorPreferences.SETTINGS_MESSAGES_IN_ONE_TO_ONE_PREFERENCE_KEY to PushRule.RULE_ID_ONE_TO_ONE_ROOM, - VectorPreferences.SETTINGS_MESSAGES_IN_GROUP_CHAT_PREFERENCE_KEY to PushRule.RULE_ID_ALL_OTHER_MESSAGES_ROOMS, - VectorPreferences.SETTINGS_INVITED_TO_ROOM_PREFERENCE_KEY to PushRule.RULE_ID_INVITE_ME, - VectorPreferences.SETTINGS_CALL_INVITATIONS_PREFERENCE_KEY to PushRule.RULE_ID_CALL, - VectorPreferences.SETTINGS_MESSAGES_SENT_BY_BOT_PREFERENCE_KEY to PushRule.RULE_ID_SUPPRESS_BOTS_NOTIFICATIONS, - VectorPreferences.SETTINGS_MESSAGES_CONTAINING_AT_ROOM_PREFERENCE_KEY to PushRule.RULE_ID_AT_ROOMS, - VectorPreferences.SETTINGS_MESSAGES_IN_E2E_ONE_ONE_CHAT_PREFERENCE_KEY to PushRule.RULE_ID_E2E_ONE_TO_ONE_ROOM, - VectorPreferences.SETTINGS_MESSAGES_IN_E2E_GROUP_CHAT_PREFERENCE_KEY to PushRule.RULE_ID_E2E_GROUP, - VectorPreferences.SETTINGS_ROOMS_UPGRADED_KEY to PushRule.RULE_ID_TOMBSTONE + "SETTINGS_PUSH_RULE_CONTAINING_MY_DISPLAY_NAME_PREFERENCE_KEY" to PushRule.RULE_ID_CONTAIN_DISPLAY_NAME, + "SETTINGS_PUSH_RULE_CONTAINING_MY_USER_NAME_PREFERENCE_KEY" to PushRule.RULE_ID_CONTAIN_USER_NAME, + "SETTINGS_PUSH_RULE_MESSAGES_IN_ONE_TO_ONE_PREFERENCE_KEY" to PushRule.RULE_ID_ONE_TO_ONE_ROOM, + "SETTINGS_PUSH_RULE_MESSAGES_IN_GROUP_CHAT_PREFERENCE_KEY" to PushRule.RULE_ID_ALL_OTHER_MESSAGES_ROOMS, + "SETTINGS_PUSH_RULE_INVITED_TO_ROOM_PREFERENCE_KEY" to PushRule.RULE_ID_INVITE_ME, + "SETTINGS_PUSH_RULE_CALL_INVITATIONS_PREFERENCE_KEY" to PushRule.RULE_ID_CALL, + "SETTINGS_PUSH_RULE_MESSAGES_SENT_BY_BOT_PREFERENCE_KEY" to PushRule.RULE_ID_SUPPRESS_BOTS_NOTIFICATIONS, + "SETTINGS_PUSH_RULE_MESSAGES_CONTAINING_AT_ROOM_PREFERENCE_KEY" to PushRule.RULE_ID_AT_ROOMS, + "SETTINGS_PUSH_RULE_MESSAGES_IN_E2E_ONE_ONE_CHAT_PREFERENCE_KEY" to PushRule.RULE_ID_E2E_ONE_TO_ONE_ROOM, + "SETTINGS_PUSH_RULE_MESSAGES_IN_E2E_GROUP_CHAT_PREFERENCE_KEY" to PushRule.RULE_ID_E2E_GROUP, + "SETTINGS_PUSH_RULE_ROOMS_UPGRADED_KEY" to PushRule.RULE_ID_TOMBSTONE ) } } diff --git a/vector/src/main/res/xml/vector_settings_notification_advanced_preferences.xml b/vector/src/main/res/xml/vector_settings_notification_advanced_preferences.xml index 3ef86d1198..d5768235f1 100644 --- a/vector/src/main/res/xml/vector_settings_notification_advanced_preferences.xml +++ b/vector/src/main/res/xml/vector_settings_notification_advanced_preferences.xml @@ -6,59 +6,59 @@ android:title="@string/settings_notification_by_event"> From 1228fcda0d4913d6d306da45fb2432b478240c2a Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 28 Feb 2020 19:14:15 +0100 Subject: [PATCH 28/91] Rename class --- ...ificationTroubleshootTestManagerFactory.kt | 6 ++--- ...ulePreference.kt => PushRulePreference.kt} | 4 ++-- ...sAdvancedNotificationPreferenceFragment.kt | 4 ++-- ...esSettings.kt => TestPushRulesSettings.kt} | 2 +- ...le.xml => vector_preference_push_rule.xml} | 0 ...ings_notification_advanced_preferences.xml | 22 +++++++++---------- 6 files changed, 19 insertions(+), 19 deletions(-) rename vector/src/main/java/im/vector/riotx/core/preference/{BingRulePreference.kt => PushRulePreference.kt} (98%) rename vector/src/main/java/im/vector/riotx/features/settings/troubleshoot/{TestBingRulesSettings.kt => TestPushRulesSettings.kt} (98%) rename vector/src/main/res/layout/{vector_preference_bing_rule.xml => vector_preference_push_rule.xml} (100%) diff --git a/vector/src/fdroid/java/im/vector/riotx/push/fcm/NotificationTroubleshootTestManagerFactory.kt b/vector/src/fdroid/java/im/vector/riotx/push/fcm/NotificationTroubleshootTestManagerFactory.kt index 723a0b9327..b88a379450 100644 --- a/vector/src/fdroid/java/im/vector/riotx/push/fcm/NotificationTroubleshootTestManagerFactory.kt +++ b/vector/src/fdroid/java/im/vector/riotx/push/fcm/NotificationTroubleshootTestManagerFactory.kt @@ -20,7 +20,7 @@ import im.vector.riotx.fdroid.features.settings.troubleshoot.TestAutoStartBoot import im.vector.riotx.fdroid.features.settings.troubleshoot.TestBackgroundRestrictions import im.vector.riotx.features.settings.troubleshoot.NotificationTroubleshootTestManager import im.vector.riotx.features.settings.troubleshoot.TestAccountSettings -import im.vector.riotx.features.settings.troubleshoot.TestBingRulesSettings +import im.vector.riotx.features.settings.troubleshoot.TestPushRulesSettings import im.vector.riotx.features.settings.troubleshoot.TestDeviceSettings import im.vector.riotx.features.settings.troubleshoot.TestSystemSettings import javax.inject.Inject @@ -28,7 +28,7 @@ import javax.inject.Inject class NotificationTroubleshootTestManagerFactory @Inject constructor(private val testSystemSettings: TestSystemSettings, private val testAccountSettings: TestAccountSettings, private val testDeviceSettings: TestDeviceSettings, - private val testBingRulesSettings: TestBingRulesSettings, + private val testPushRulesSettings: TestPushRulesSettings, private val testAutoStartBoot: TestAutoStartBoot, private val testBackgroundRestrictions: TestBackgroundRestrictions) { @@ -37,7 +37,7 @@ class NotificationTroubleshootTestManagerFactory @Inject constructor(private val mgr.addTest(testSystemSettings) mgr.addTest(testAccountSettings) mgr.addTest(testDeviceSettings) - mgr.addTest(testBingRulesSettings) + mgr.addTest(testPushRulesSettings) mgr.addTest(testAutoStartBoot) mgr.addTest(testBackgroundRestrictions) return mgr diff --git a/vector/src/main/java/im/vector/riotx/core/preference/BingRulePreference.kt b/vector/src/main/java/im/vector/riotx/core/preference/PushRulePreference.kt similarity index 98% rename from vector/src/main/java/im/vector/riotx/core/preference/BingRulePreference.kt rename to vector/src/main/java/im/vector/riotx/core/preference/PushRulePreference.kt index 1f074261a4..16dd1bb486 100755 --- a/vector/src/main/java/im/vector/riotx/core/preference/BingRulePreference.kt +++ b/vector/src/main/java/im/vector/riotx/core/preference/PushRulePreference.kt @@ -27,7 +27,7 @@ import im.vector.matrix.android.api.pushrules.rest.PushRule import im.vector.matrix.android.api.pushrules.rest.PushRuleAndKind import im.vector.riotx.R -class BingRulePreference : VectorPreference { +class PushRulePreference : VectorPreference { /** * @return the selected push rule and its kind @@ -42,7 +42,7 @@ class BingRulePreference : VectorPreference { constructor(context: Context, attrs: AttributeSet, defStyle: Int) : super(context, attrs, defStyle) init { - layoutResource = R.layout.vector_preference_bing_rule + layoutResource = R.layout.vector_preference_push_rule } /** diff --git a/vector/src/main/java/im/vector/riotx/features/settings/VectorSettingsAdvancedNotificationPreferenceFragment.kt b/vector/src/main/java/im/vector/riotx/features/settings/VectorSettingsAdvancedNotificationPreferenceFragment.kt index 772e9df3d3..5fa822ea92 100644 --- a/vector/src/main/java/im/vector/riotx/features/settings/VectorSettingsAdvancedNotificationPreferenceFragment.kt +++ b/vector/src/main/java/im/vector/riotx/features/settings/VectorSettingsAdvancedNotificationPreferenceFragment.kt @@ -25,7 +25,7 @@ import im.vector.matrix.android.api.MatrixCallback import im.vector.matrix.android.api.pushrules.rest.PushRule import im.vector.matrix.android.api.pushrules.rest.PushRuleAndKind import im.vector.riotx.R -import im.vector.riotx.core.preference.BingRulePreference +import im.vector.riotx.core.preference.PushRulePreference import im.vector.riotx.core.preference.VectorPreference import im.vector.riotx.core.utils.toast import im.vector.riotx.features.notifications.NotificationUtils @@ -92,7 +92,7 @@ class VectorSettingsAdvancedNotificationPreferenceFragment @Inject constructor( for (preferenceKey in prefKeyToPushRuleId.keys) { val preference = findPreference(preferenceKey) - if (preference is BingRulePreference) { + if (preference is PushRulePreference) { // preference.isEnabled = null != rules && isConnected && pushManager.areDeviceNotificationsAllowed() val ruleAndKind: PushRuleAndKind? = session.getPushRules().findDefaultRule(prefKeyToPushRuleId[preferenceKey]) diff --git a/vector/src/main/java/im/vector/riotx/features/settings/troubleshoot/TestBingRulesSettings.kt b/vector/src/main/java/im/vector/riotx/features/settings/troubleshoot/TestPushRulesSettings.kt similarity index 98% rename from vector/src/main/java/im/vector/riotx/features/settings/troubleshoot/TestBingRulesSettings.kt rename to vector/src/main/java/im/vector/riotx/features/settings/troubleshoot/TestPushRulesSettings.kt index 52c1ceb07c..bbdf8fa62c 100644 --- a/vector/src/main/java/im/vector/riotx/features/settings/troubleshoot/TestBingRulesSettings.kt +++ b/vector/src/main/java/im/vector/riotx/features/settings/troubleshoot/TestPushRulesSettings.kt @@ -23,7 +23,7 @@ import im.vector.riotx.core.resources.StringProvider import im.vector.riotx.features.notifications.toNotificationAction import javax.inject.Inject -class TestBingRulesSettings @Inject constructor(private val activeSessionHolder: ActiveSessionHolder, +class TestPushRulesSettings @Inject constructor(private val activeSessionHolder: ActiveSessionHolder, private val stringProvider: StringProvider) : TroubleshootTest(R.string.settings_troubleshoot_test_bing_settings_title) { diff --git a/vector/src/main/res/layout/vector_preference_bing_rule.xml b/vector/src/main/res/layout/vector_preference_push_rule.xml similarity index 100% rename from vector/src/main/res/layout/vector_preference_bing_rule.xml rename to vector/src/main/res/layout/vector_preference_push_rule.xml diff --git a/vector/src/main/res/xml/vector_settings_notification_advanced_preferences.xml b/vector/src/main/res/xml/vector_settings_notification_advanced_preferences.xml index d5768235f1..a58a2d8f19 100644 --- a/vector/src/main/res/xml/vector_settings_notification_advanced_preferences.xml +++ b/vector/src/main/res/xml/vector_settings_notification_advanced_preferences.xml @@ -5,59 +5,59 @@ android:key="SETTINGS_NOTIFICATION_LEVEL" android:title="@string/settings_notification_by_event"> - - - - - - - - - - - From 3987a68a9ac9963aa905877693f18f94a61a8628 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 28 Feb 2020 22:10:07 +0100 Subject: [PATCH 29/91] Changelog --- CHANGES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index 20c2e5b266..bff3421110 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -5,7 +5,7 @@ Features ✨: - Improvements 🙌: - - + - Restore the push rules configuration in the settings Bugfix 🐛: - Fix crash on attachment preview screen (#1088) From 06e0af9a5b2b34c4d2e39e4e17ec9cfe4bec39ec Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 26 Feb 2020 08:49:17 +0100 Subject: [PATCH 30/91] small mistake --- .../im/vector/riotx/features/notifications/NotificationUtils.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vector/src/main/java/im/vector/riotx/features/notifications/NotificationUtils.kt b/vector/src/main/java/im/vector/riotx/features/notifications/NotificationUtils.kt index ff0947598f..50fb5b70de 100755 --- a/vector/src/main/java/im/vector/riotx/features/notifications/NotificationUtils.kt +++ b/vector/src/main/java/im/vector/riotx/features/notifications/NotificationUtils.kt @@ -423,9 +423,9 @@ class NotificationUtils @Inject constructor(private val context: Context, // 'importance' which is set in the NotificationChannel. The integers representing // 'priority' are different from 'importance', so make sure you don't mix them. .apply { - priority = NotificationCompat.PRIORITY_DEFAULT if (roomInfo.shouldBing) { // Compat + priority = NotificationCompat.PRIORITY_DEFAULT vectorPreferences.getNotificationRingTone()?.let { setSound(it) } From 6009026e2fe55fc460bfeba5c203df726a549951 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Sat, 29 Feb 2020 09:35:26 +0100 Subject: [PATCH 31/91] Notification settings: create a category for troubleshhot --- vector/src/main/res/values/strings_riotX.xml | 1 + .../src/main/res/xml/vector_settings_notifications.xml | 9 +++++---- vector/src/main/res/xml/vector_settings_root.xml | 1 - 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/vector/src/main/res/values/strings_riotX.xml b/vector/src/main/res/values/strings_riotX.xml index c20698d767..d627ac0dd7 100644 --- a/vector/src/main/res/values/strings_riotX.xml +++ b/vector/src/main/res/values/strings_riotX.xml @@ -16,6 +16,7 @@ Encrypted messages in one-to-one chats Encrypted messages in group chats When rooms are upgraded + Troubleshoot diff --git a/vector/src/main/res/xml/vector_settings_notifications.xml b/vector/src/main/res/xml/vector_settings_notifications.xml index 82c9cde759..fb660ba8b9 100644 --- a/vector/src/main/res/xml/vector_settings_notifications.xml +++ b/vector/src/main/res/xml/vector_settings_notifications.xml @@ -2,9 +2,7 @@ - + + + + + - diff --git a/vector/src/main/res/xml/vector_settings_notification_advanced_preferences.xml b/vector/src/main/res/xml/vector_settings_notification_advanced_preferences.xml index a58a2d8f19..6e0fb71671 100644 --- a/vector/src/main/res/xml/vector_settings_notification_advanced_preferences.xml +++ b/vector/src/main/res/xml/vector_settings_notification_advanced_preferences.xml @@ -64,37 +64,4 @@ - - - - - - - - - - - - - - diff --git a/vector/src/main/res/xml/vector_settings_notifications.xml b/vector/src/main/res/xml/vector_settings_notifications.xml index fb660ba8b9..5ecf693b44 100644 --- a/vector/src/main/res/xml/vector_settings_notifications.xml +++ b/vector/src/main/res/xml/vector_settings_notifications.xml @@ -24,12 +24,44 @@ android:dependency="SETTINGS_ENABLE_THIS_DEVICE_PREFERENCE_KEY" android:key="SETTINGS_NOTIFICATION_ADVANCED_PREFERENCE_KEY" android:persistent="false" - android:summary="@string/settings_notification_advanced_summary" + android:summary="@string/settings_notification_advanced_summary_riotx" android:title="@string/settings_notification_advanced" app:fragment="im.vector.riotx.features.settings.VectorSettingsAdvancedNotificationPreferenceFragment" /> + + + + + + + + + + + + + + Date: Sat, 29 Feb 2020 10:05:00 +0100 Subject: [PATCH 34/91] Code cleanup --- .../android/api/pushrules/rest/PushRule.kt | 2 +- .../features/settings/VectorPreferences.kt | 1 - .../settings/VectorSettingsActivity.kt | 23 +++++++------------ ...sAdvancedNotificationPreferenceFragment.kt | 5 ++-- ...rSettingsNotificationPreferenceFragment.kt | 1 - 5 files changed, 11 insertions(+), 21 deletions(-) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/pushrules/rest/PushRule.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/pushrules/rest/PushRule.kt index 699ce29032..8611f124e8 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/pushrules/rest/PushRule.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/pushrules/rest/PushRule.kt @@ -85,7 +85,7 @@ data class PushRule( */ fun removeNotificationSound(): PushRule { return copy( - actions = (getActions().filter { it !is Action.Sound }).toJson() + actions = getActions().filter { it !is Action.Sound }.toJson() ) } diff --git a/vector/src/main/java/im/vector/riotx/features/settings/VectorPreferences.kt b/vector/src/main/java/im/vector/riotx/features/settings/VectorPreferences.kt index cd647de891..acc3c72253 100755 --- a/vector/src/main/java/im/vector/riotx/features/settings/VectorPreferences.kt +++ b/vector/src/main/java/im/vector/riotx/features/settings/VectorPreferences.kt @@ -45,7 +45,6 @@ class VectorPreferences @Inject constructor(private val context: Context) { const val SETTINGS_APP_TERM_CONDITIONS_PREFERENCE_KEY = "SETTINGS_APP_TERM_CONDITIONS_PREFERENCE_KEY" const val SETTINGS_PRIVACY_POLICY_PREFERENCE_KEY = "SETTINGS_PRIVACY_POLICY_PREFERENCE_KEY" - const val SETTINGS_NOTIFICATION_TROUBLESHOOT_PREFERENCE_KEY = "SETTINGS_NOTIFICATION_TROUBLESHOOT_PREFERENCE_KEY" const val SETTINGS_NOTIFICATION_ADVANCED_PREFERENCE_KEY = "SETTINGS_NOTIFICATION_ADVANCED_PREFERENCE_KEY" const val SETTINGS_THIRD_PARTY_NOTICES_PREFERENCE_KEY = "SETTINGS_THIRD_PARTY_NOTICES_PREFERENCE_KEY" const val SETTINGS_OTHER_THIRD_PARTY_NOTICES_PREFERENCE_KEY = "SETTINGS_OTHER_THIRD_PARTY_NOTICES_PREFERENCE_KEY" diff --git a/vector/src/main/java/im/vector/riotx/features/settings/VectorSettingsActivity.kt b/vector/src/main/java/im/vector/riotx/features/settings/VectorSettingsActivity.kt index 490805ea3c..909d40a74c 100755 --- a/vector/src/main/java/im/vector/riotx/features/settings/VectorSettingsActivity.kt +++ b/vector/src/main/java/im/vector/riotx/features/settings/VectorSettingsActivity.kt @@ -77,21 +77,14 @@ class VectorSettingsActivity : VectorBaseActivity(), } override fun onPreferenceStartFragment(caller: PreferenceFragmentCompat, pref: Preference): Boolean { - val oFragment = when { - VectorPreferences.SETTINGS_NOTIFICATION_TROUBLESHOOT_PREFERENCE_KEY == pref.key -> - supportFragmentManager.fragmentFactory.instantiate(classLoader, VectorSettingsNotificationsTroubleshootFragment::class.java.name) - VectorPreferences.SETTINGS_NOTIFICATION_ADVANCED_PREFERENCE_KEY == pref.key -> - supportFragmentManager.fragmentFactory.instantiate(classLoader, VectorSettingsAdvancedNotificationPreferenceFragment::class.java.name) - else -> - try { - pref.fragment?.let { - supportFragmentManager.fragmentFactory.instantiate(classLoader, it) - } - } catch (e: Throwable) { - showSnackbar(getString(R.string.not_implemented)) - Timber.e(e) - null - } + val oFragment = try { + pref.fragment?.let { + supportFragmentManager.fragmentFactory.instantiate(classLoader, it) + } + } catch (e: Throwable) { + showSnackbar(getString(R.string.not_implemented)) + Timber.e(e) + null } if (oFragment != null) { diff --git a/vector/src/main/java/im/vector/riotx/features/settings/VectorSettingsAdvancedNotificationPreferenceFragment.kt b/vector/src/main/java/im/vector/riotx/features/settings/VectorSettingsAdvancedNotificationPreferenceFragment.kt index b7c1a0490b..95901de471 100644 --- a/vector/src/main/java/im/vector/riotx/features/settings/VectorSettingsAdvancedNotificationPreferenceFragment.kt +++ b/vector/src/main/java/im/vector/riotx/features/settings/VectorSettingsAdvancedNotificationPreferenceFragment.kt @@ -25,9 +25,8 @@ import im.vector.riotx.core.preference.VectorPreference import im.vector.riotx.core.utils.toast import javax.inject.Inject -class VectorSettingsAdvancedNotificationPreferenceFragment @Inject constructor( - private val vectorPreferences: VectorPreferences -) : VectorSettingsBaseFragment() { +class VectorSettingsAdvancedNotificationPreferenceFragment @Inject constructor() + : VectorSettingsBaseFragment() { override var titleRes: Int = R.string.settings_notification_advanced diff --git a/vector/src/main/java/im/vector/riotx/features/settings/VectorSettingsNotificationPreferenceFragment.kt b/vector/src/main/java/im/vector/riotx/features/settings/VectorSettingsNotificationPreferenceFragment.kt index 0ee42b7653..a1e67e6cd0 100644 --- a/vector/src/main/java/im/vector/riotx/features/settings/VectorSettingsNotificationPreferenceFragment.kt +++ b/vector/src/main/java/im/vector/riotx/features/settings/VectorSettingsNotificationPreferenceFragment.kt @@ -136,7 +136,6 @@ class VectorSettingsNotificationPreferenceFragment @Inject constructor( } } - override fun onResume() { super.onResume() activeSessionHolder.getSafeActiveSession()?.refreshPushers() From b7ff546f6608390f1d1fd5fe88615afa1c029a08 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Sun, 1 Mar 2020 09:59:00 +0100 Subject: [PATCH 35/91] Add support for `/plain` command (#12) --- CHANGES.md | 2 +- .../java/im/vector/riotx/features/command/Command.kt | 1 + .../im/vector/riotx/features/command/CommandParser.kt | 9 +++++++++ .../im/vector/riotx/features/command/ParsedCommand.kt | 1 + .../features/home/room/detail/RoomDetailViewModel.kt | 6 ++++++ vector/src/main/res/values/strings_riotX.xml | 2 +- 6 files changed, 19 insertions(+), 2 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 4f8838deb6..b2ad0766c4 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -5,7 +5,7 @@ Features ✨: - Improvements 🙌: - - + - Add support for `/plain` command (#12) Bugfix 🐛: - Fix crash on attachment preview screen (#1088) diff --git a/vector/src/main/java/im/vector/riotx/features/command/Command.kt b/vector/src/main/java/im/vector/riotx/features/command/Command.kt index f39f1cb7cd..72f686c2c8 100644 --- a/vector/src/main/java/im/vector/riotx/features/command/Command.kt +++ b/vector/src/main/java/im/vector/riotx/features/command/Command.kt @@ -43,6 +43,7 @@ enum class Command(val command: String, val parameters: String, @StringRes val d SPOILER("/spoiler", "", R.string.command_description_spoiler), POLL("/poll", "Question | Option 1 | Option 2 ...", R.string.command_description_poll), SHRUG("/shrug", "", R.string.command_description_shrug), + PLAIN("/plain", "", R.string.command_description_plain), // TODO temporary command VERIFY_USER("/verify", "", R.string.command_description_verify); diff --git a/vector/src/main/java/im/vector/riotx/features/command/CommandParser.kt b/vector/src/main/java/im/vector/riotx/features/command/CommandParser.kt index abc047e273..875fe92610 100644 --- a/vector/src/main/java/im/vector/riotx/features/command/CommandParser.kt +++ b/vector/src/main/java/im/vector/riotx/features/command/CommandParser.kt @@ -57,6 +57,15 @@ object CommandParser { } return when (val slashCommand = messageParts.first()) { + Command.PLAIN.command -> { + val text = textMessage.substring(Command.PLAIN.command.length).trim() + + if (text.isNotEmpty()) { + ParsedCommand.SendPlainText(text) + } else { + ParsedCommand.ErrorSyntax(Command.PLAIN) + } + } Command.CHANGE_DISPLAY_NAME.command -> { val newDisplayName = textMessage.substring(Command.CHANGE_DISPLAY_NAME.command.length).trim() diff --git a/vector/src/main/java/im/vector/riotx/features/command/ParsedCommand.kt b/vector/src/main/java/im/vector/riotx/features/command/ParsedCommand.kt index d823429ac9..e4fee27ee6 100644 --- a/vector/src/main/java/im/vector/riotx/features/command/ParsedCommand.kt +++ b/vector/src/main/java/im/vector/riotx/features/command/ParsedCommand.kt @@ -33,6 +33,7 @@ sealed class ParsedCommand { // Valid commands: + class SendPlainText(val message: CharSequence) : ParsedCommand() class SendEmote(val message: CharSequence) : ParsedCommand() class SendRainbow(val message: CharSequence) : ParsedCommand() class SendRainbowEmote(val message: CharSequence) : ParsedCommand() diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailViewModel.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailViewModel.kt index 8a231fb25d..1fcae90e95 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailViewModel.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailViewModel.kt @@ -340,6 +340,12 @@ class RoomDetailViewModel @AssistedInject constructor(@Assisted initialState: Ro is ParsedCommand.ErrorUnknownSlashCommand -> { _viewEvents.post(RoomDetailViewEvents.SlashCommandUnknown(slashCommandResult.slashCommand)) } + is ParsedCommand.SendPlainText -> { + // Send the text message to the room, without markdown + room.sendTextMessage(slashCommandResult.message, autoMarkdown = false) + _viewEvents.post(RoomDetailViewEvents.MessageSent) + popDraft() + } is ParsedCommand.Invite -> { handleInviteSlashCommand(slashCommandResult) popDraft() diff --git a/vector/src/main/res/values/strings_riotX.xml b/vector/src/main/res/values/strings_riotX.xml index 00bf65e121..69d821c0ca 100644 --- a/vector/src/main/res/values/strings_riotX.xml +++ b/vector/src/main/res/values/strings_riotX.xml @@ -26,7 +26,7 @@ - + Sends a message as plain text, without interpreting it as markdown From 5f14516dec3b67286e26c5f9fec0e3df207c2215 Mon Sep 17 00:00:00 2001 From: onurays Date: Tue, 3 Mar 2020 10:39:24 +0100 Subject: [PATCH 36/91] Share images from clear and encrypted rooms. --- .../android/api/session/file/FileService.kt | 6 +- .../internal/session/DefaultFileService.kt | 73 ++++++++----------- .../session/content/UploadContentWorker.kt | 5 +- .../session/room/send/DefaultSendService.kt | 2 +- .../features/attachments/AttachmentsHelper.kt | 9 ++- .../home/room/detail/RoomDetailFragment.kt | 38 ++++------ .../timeline/action/EventSharedAction.kt | 3 +- .../action/MessageActionsViewModel.kt | 6 +- .../features/share/IncomingShareFragment.kt | 3 +- .../src/main/res/xml/riotx_provider_paths.xml | 4 + 10 files changed, 69 insertions(+), 80 deletions(-) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/file/FileService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/file/FileService.kt index 4d9cff3e92..32fb1a6ab0 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/file/FileService.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/file/FileService.kt @@ -34,7 +34,11 @@ interface FileService { /** * Download file in cache */ - FOR_INTERNAL_USE + FOR_INTERNAL_USE, + /** + * Download file in file provider path + */ + FOR_EXTERNAL_SHARE } /** diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/DefaultFileService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/DefaultFileService.kt index cf7e1b1d83..41a246397b 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/DefaultFileService.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/DefaultFileService.kt @@ -25,10 +25,10 @@ import im.vector.matrix.android.api.util.Cancelable import im.vector.matrix.android.internal.crypto.attachments.ElementToDecrypt import im.vector.matrix.android.internal.crypto.attachments.MXEncryptedAttachments import im.vector.matrix.android.internal.di.SessionCacheDirectory +import im.vector.matrix.android.internal.di.SessionFilesDirectory import im.vector.matrix.android.internal.di.Unauthenticated import im.vector.matrix.android.internal.extensions.foldToCallback import im.vector.matrix.android.internal.util.MatrixCoroutineDispatchers -import im.vector.matrix.android.internal.util.md5 import im.vector.matrix.android.internal.util.toCancelable import im.vector.matrix.android.internal.util.writeToFile import kotlinx.coroutines.GlobalScope @@ -44,6 +44,8 @@ import javax.inject.Inject internal class DefaultFileService @Inject constructor( @SessionCacheDirectory private val cacheDirectory: File, + @SessionFilesDirectory + private val filesDirectory: File, private val contentUrlResolver: ContentUrlResolver, @Unauthenticated private val okHttpClient: OkHttpClient, @@ -62,60 +64,47 @@ internal class DefaultFileService @Inject constructor( return GlobalScope.launch(coroutineDispatchers.main) { withContext(coroutineDispatchers.io) { Try { - val folder = getFolder(downloadMode, id) - + val folder = File(cacheDirectory, "MF") + if (!folder.exists()) { + folder.mkdirs() + } File(folder, fileName) }.flatMap { destFile -> - if (!destFile.exists() || downloadMode == FileService.DownloadMode.TO_EXPORT) { - Try { - val resolvedUrl = contentUrlResolver.resolveFullSize(url) ?: throw IllegalArgumentException("url is null") + if (!destFile.exists()) { + val resolvedUrl = contentUrlResolver.resolveFullSize(url) ?: throw IllegalArgumentException("url is null") - val request = Request.Builder() - .url(resolvedUrl) - .build() + val request = Request.Builder() + .url(resolvedUrl) + .build() - val response = okHttpClient.newCall(request).execute() - var inputStream = response.body?.byteStream() - Timber.v("Response size ${response.body?.contentLength()} - Stream available: ${inputStream?.available()}") - if (!response.isSuccessful - || inputStream == null) { - throw IOException() - } - - if (elementToDecrypt != null) { - Timber.v("## decrypt file") - inputStream = MXEncryptedAttachments.decryptAttachment(inputStream, elementToDecrypt) - ?: throw IllegalStateException("Decryption error") - } - - writeToFile(inputStream, destFile) - destFile + val response = okHttpClient.newCall(request).execute() + var inputStream = response.body?.byteStream() + Timber.v("Response size ${response.body?.contentLength()} - Stream available: ${inputStream?.available()}") + if (!response.isSuccessful || inputStream == null) { + return@flatMap Try.Failure(IOException()) } - } else { - Try.just(destFile) + + if (elementToDecrypt != null) { + Timber.v("## decrypt file") + inputStream = MXEncryptedAttachments.decryptAttachment(inputStream, elementToDecrypt) + ?: throw IllegalStateException("Decryption error") + } + + writeToFile(inputStream, destFile) } + + Try.just(copyFile(destFile, downloadMode)) } } .foldToCallback(callback) }.toCancelable() } - private fun getFolder(downloadMode: FileService.DownloadMode, id: String): File { + private fun copyFile(file: File, downloadMode: FileService.DownloadMode): File { return when (downloadMode) { - FileService.DownloadMode.FOR_INTERNAL_USE -> { - // Create dir tree (MF stands for Matrix File): - // //MF// - val tmpFolderSession = File(cacheDirectory, "MF") - File(tmpFolderSession, id.md5()) - } - FileService.DownloadMode.TO_EXPORT -> { - Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) - } + FileService.DownloadMode.TO_EXPORT -> file.copyTo(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), true) + FileService.DownloadMode.FOR_INTERNAL_USE -> file.copyTo(File(filesDirectory, "ext_share"), true) + FileService.DownloadMode.FOR_EXTERNAL_SHARE -> file } - .also { folder -> - if (!folder.exists()) { - folder.mkdirs() - } - } } } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/content/UploadContentWorker.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/content/UploadContentWorker.kt index 94bdb11edb..5e1a524be6 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/content/UploadContentWorker.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/content/UploadContentWorker.kt @@ -205,7 +205,10 @@ internal class UploadContentWorker(val context: Context, params: WorkerParameter return Result.success( WorkerParamsFactory.toData( - params.copy( + MultipleEventSendingDispatcherWorker.Params( + sessionId = params.sessionId, + events = params.events, + isEncrypted = params.isRoomEncrypted, lastFailureMessage = failure.localizedMessage ) ) 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 a99337695a..58f4d4fc5e 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 @@ -233,7 +233,7 @@ internal class DefaultSendService @AssistedInject constructor( val dispatcherWork = createMultipleEventDispatcherWork(isRoomEncrypted) workManagerProvider.workManager - .beginUniqueWork(buildWorkName(UPLOAD_WORK), ExistingWorkPolicy.APPEND, uploadWork) + .beginWith(uploadWork) .then(dispatcherWork) .enqueue() .also { operation -> diff --git a/vector/src/main/java/im/vector/riotx/features/attachments/AttachmentsHelper.kt b/vector/src/main/java/im/vector/riotx/features/attachments/AttachmentsHelper.kt index c9ee1cb6e5..ba1197b787 100644 --- a/vector/src/main/java/im/vector/riotx/features/attachments/AttachmentsHelper.kt +++ b/vector/src/main/java/im/vector/riotx/features/attachments/AttachmentsHelper.kt @@ -27,6 +27,7 @@ import com.kbeanie.multipicker.api.Picker.PICK_IMAGE_CAMERA import com.kbeanie.multipicker.api.Picker.PICK_IMAGE_DEVICE import com.kbeanie.multipicker.core.ImagePickerImpl import com.kbeanie.multipicker.core.PickerManager +import com.kbeanie.multipicker.utils.IntentUtils import im.vector.matrix.android.BuildConfig import im.vector.matrix.android.api.session.content.ContentAttachmentData import im.vector.riotx.core.platform.Restorable @@ -176,13 +177,13 @@ class AttachmentsHelper private constructor(private val context: Context, fun handleShareIntent(intent: Intent): Boolean { val type = intent.resolveType(context) ?: return false if (type.startsWith("image")) { - imagePicker.submit(intent) + imagePicker.submit(IntentUtils.getPickerIntentForSharing(intent)) } else if (type.startsWith("video")) { - videoPicker.submit(intent) + videoPicker.submit(IntentUtils.getPickerIntentForSharing(intent)) } else if (type.startsWith("audio")) { - videoPicker.submit(intent) + videoPicker.submit(IntentUtils.getPickerIntentForSharing(intent)) } else if (type.startsWith("application") || type.startsWith("file") || type.startsWith("*")) { - filePicker.submit(intent) + filePicker.submit(IntentUtils.getPickerIntentForSharing(intent)) } else { return false } 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 c2eb61b3ca..80548cbe71 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 @@ -57,17 +57,17 @@ import com.airbnb.mvrx.Success import com.airbnb.mvrx.args import com.airbnb.mvrx.fragmentViewModel import com.airbnb.mvrx.withState -import com.github.piasy.biv.BigImageViewer -import com.github.piasy.biv.loader.ImageLoader import com.google.android.material.checkbox.MaterialCheckBox import com.google.android.material.snackbar.Snackbar import com.google.android.material.textfield.TextInputEditText import com.google.android.material.textfield.TextInputLayout import com.jakewharton.rxbinding3.widget.textChanges +import im.vector.matrix.android.api.MatrixCallback import im.vector.matrix.android.api.permalinks.PermalinkFactory import im.vector.matrix.android.api.session.Session 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.file.FileService import im.vector.matrix.android.api.session.room.model.Membership import im.vector.matrix.android.api.session.room.model.message.MessageAudioContent import im.vector.matrix.android.api.session.room.model.message.MessageContent @@ -77,12 +77,14 @@ import im.vector.matrix.android.api.session.room.model.message.MessageImageInfoC import im.vector.matrix.android.api.session.room.model.message.MessageTextContent import im.vector.matrix.android.api.session.room.model.message.MessageVerificationRequestContent import im.vector.matrix.android.api.session.room.model.message.MessageVideoContent +import im.vector.matrix.android.api.session.room.model.message.getFileUrl import im.vector.matrix.android.api.session.room.send.SendState import im.vector.matrix.android.api.session.room.timeline.Timeline import im.vector.matrix.android.api.session.room.timeline.TimelineEvent import im.vector.matrix.android.api.session.room.timeline.getLastMessageContent import im.vector.matrix.android.api.util.MatrixItem import im.vector.matrix.android.api.util.toMatrixItem +import im.vector.matrix.android.internal.crypto.attachments.toElementToDecrypt import im.vector.riotx.R import im.vector.riotx.core.dialogs.withColoredButton import im.vector.riotx.core.epoxy.LayoutManagerStateRestorer @@ -1145,30 +1147,18 @@ class RoomDetailFragment @Inject constructor( promptConfirmationToRedactEvent(action) } is EventSharedAction.Share -> { - // TODO current data communication is too limited - // Need to now the media type - // 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/*") + session.downloadFile( + FileService.DownloadMode.FOR_EXTERNAL_SHARE, + action.eventId, + action.messageContent.body, + action.messageContent.getFileUrl(), + action.messageContent.encryptedFileInfo?.toElementToDecrypt(), + object : MatrixCallback { + override fun onSuccess(data: File) { + if (isAdded) { + shareMedia(requireContext(), data, "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() {} } ) } diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/action/EventSharedAction.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/action/EventSharedAction.kt index cba89d8481..ec1f43feb0 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/action/EventSharedAction.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/action/EventSharedAction.kt @@ -18,6 +18,7 @@ package im.vector.riotx.features.home.room.detail.timeline.action import androidx.annotation.DrawableRes import androidx.annotation.StringRes +import im.vector.matrix.android.api.session.room.model.message.MessageImageContent import im.vector.riotx.R import im.vector.riotx.core.platform.VectorSharedAction import im.vector.riotx.features.home.room.detail.timeline.item.MessageInformationData @@ -46,7 +47,7 @@ sealed class EventSharedAction(@StringRes val titleRes: Int, data class Reply(val eventId: String) : EventSharedAction(R.string.reply, R.drawable.ic_reply) - data class Share(val imageUrl: String) : + data class Share(val eventId: String, val messageContent: MessageImageContent) : EventSharedAction(R.string.share, R.drawable.ic_share) data class Resend(val eventId: String) : diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/action/MessageActionsViewModel.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/action/MessageActionsViewModel.kt index fa9bdbc29c..1e14f5292b 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/action/MessageActionsViewModel.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/action/MessageActionsViewModel.kt @@ -262,11 +262,9 @@ class MessageActionsViewModel @AssistedInject constructor(@Assisted if (canShare(msgType)) { if (messageContent is MessageImageContent) { - session.contentUrlResolver().resolveFullSize(messageContent.url)?.let { url -> - add(EventSharedAction.Share(url)) - } + add(EventSharedAction.Share(timelineEvent.eventId, messageContent)) } - // TODO + // TODO Support other media types } if (timelineEvent.root.sendState == SendState.SENT) { diff --git a/vector/src/main/java/im/vector/riotx/features/share/IncomingShareFragment.kt b/vector/src/main/java/im/vector/riotx/features/share/IncomingShareFragment.kt index eb0f5128ba..74821ab2fe 100644 --- a/vector/src/main/java/im/vector/riotx/features/share/IncomingShareFragment.kt +++ b/vector/src/main/java/im/vector/riotx/features/share/IncomingShareFragment.kt @@ -28,7 +28,6 @@ import androidx.appcompat.widget.SearchView import androidx.core.view.isVisible import com.airbnb.mvrx.fragmentViewModel import com.airbnb.mvrx.withState -import com.kbeanie.multipicker.utils.IntentUtils import im.vector.matrix.android.api.session.content.ContentAttachmentData import im.vector.matrix.android.api.session.room.model.RoomSummary import im.vector.riotx.R @@ -78,7 +77,7 @@ class IncomingShareFragment @Inject constructor( val intent = vectorBaseActivity.intent val isShareManaged = when (intent?.action) { Intent.ACTION_SEND -> { - var isShareManaged = attachmentsHelper.handleShareIntent(IntentUtils.getPickerIntentForSharing(intent)) + var isShareManaged = attachmentsHelper.handleShareIntent(intent) if (!isShareManaged) { isShareManaged = handleTextShare(intent) } diff --git a/vector/src/main/res/xml/riotx_provider_paths.xml b/vector/src/main/res/xml/riotx_provider_paths.xml index 7d3fcb2203..2069cf3191 100644 --- a/vector/src/main/res/xml/riotx_provider_paths.xml +++ b/vector/src/main/res/xml/riotx_provider_paths.xml @@ -3,4 +3,8 @@ + + \ No newline at end of file From c4f2eeeab7637b341a1381d284676f78ea73bb06 Mon Sep 17 00:00:00 2001 From: onurays Date: Tue, 3 Mar 2020 10:40:58 +0100 Subject: [PATCH 37/91] Changelog added. --- CHANGES.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGES.md b/CHANGES.md index 4f8838deb6..28fa27932f 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -9,6 +9,7 @@ Improvements 🙌: Bugfix 🐛: - Fix crash on attachment preview screen (#1088) + - "Share" option is not appearing in encrypted rooms for images (#1031) Translations 🗣: - From 319667096f1d3dbd6843b3161c29275a751e42f6 Mon Sep 17 00:00:00 2001 From: onurays Date: Tue, 3 Mar 2020 13:41:40 +0100 Subject: [PATCH 38/91] Return Try.Failure instead of throwing exception. --- .../matrix/android/internal/session/DefaultFileService.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/DefaultFileService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/DefaultFileService.kt index 41a246397b..ba6f9543e7 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/DefaultFileService.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/DefaultFileService.kt @@ -87,7 +87,7 @@ internal class DefaultFileService @Inject constructor( if (elementToDecrypt != null) { Timber.v("## decrypt file") inputStream = MXEncryptedAttachments.decryptAttachment(inputStream, elementToDecrypt) - ?: throw IllegalStateException("Decryption error") + ?: return@flatMap Try.Failure(IllegalStateException("Decryption error")) } writeToFile(inputStream, destFile) From d09ac8fbce1068afe43aea729e618a6287875e0c Mon Sep 17 00:00:00 2001 From: onurays Date: Tue, 3 Mar 2020 14:54:05 +0100 Subject: [PATCH 39/91] Try to show full image as the fallback of the thumbnail. --- .../features/media/ImageContentRenderer.kt | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) 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 e497d9ce04..3f0daebdbe 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 @@ -127,6 +127,23 @@ class ImageContentRenderer @Inject constructor(private val activeSessionHolder: GlideApp .with(imageView) .load(resolvedUrl) + .listener(object : RequestListener { + override fun onResourceReady(resource: Drawable?, model: Any?, target: Target?, dataSource: DataSource?, isFirstResource: Boolean): Boolean { + return false + } + + override fun onLoadFailed(e: GlideException?, model: Any?, target: Target?, isFirstResource: Boolean): Boolean { + data.url + ?.takeIf { it != resolvedUrl } + ?.let { + GlideApp + .with(imageView) + .load(it) + return false + } + return true + } + }) } } From 34c5537436555c8c3579a393aef1f0a5857060ea Mon Sep 17 00:00:00 2001 From: onurays Date: Tue, 3 Mar 2020 16:42:33 +0100 Subject: [PATCH 40/91] Fix fallback to full image. --- .../features/media/ImageContentRenderer.kt | 29 ++++++++----------- 1 file changed, 12 insertions(+), 17 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 3f0daebdbe..6f34001124 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 @@ -127,23 +127,18 @@ class ImageContentRenderer @Inject constructor(private val activeSessionHolder: GlideApp .with(imageView) .load(resolvedUrl) - .listener(object : RequestListener { - override fun onResourceReady(resource: Drawable?, model: Any?, target: Target?, dataSource: DataSource?, isFirstResource: Boolean): Boolean { - return false - } - - override fun onLoadFailed(e: GlideException?, model: Any?, target: Target?, isFirstResource: Boolean): Boolean { - data.url - ?.takeIf { it != resolvedUrl } - ?.let { - GlideApp - .with(imageView) - .load(it) - return false - } - return true - } - }) + .apply { + contentUrlResolver + .resolveFullSize(data.url) + ?.takeIf { it != resolvedUrl } + ?.let { fullSizeUrl -> + error( + GlideApp + .with(imageView) + .load(fullSizeUrl) + ) + } + } } } From 7158554ee2aef1543b276d93303fc1948022af5c Mon Sep 17 00:00:00 2001 From: onurays Date: Tue, 3 Mar 2020 16:56:22 +0100 Subject: [PATCH 41/91] Add fallback logic only if the mode is thumbnail. --- .../features/media/ImageContentRenderer.kt | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 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 6f34001124..737549d5b8 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 @@ -128,16 +128,13 @@ class ImageContentRenderer @Inject constructor(private val activeSessionHolder: .with(imageView) .load(resolvedUrl) .apply { - contentUrlResolver - .resolveFullSize(data.url) - ?.takeIf { it != resolvedUrl } - ?.let { fullSizeUrl -> - error( - GlideApp - .with(imageView) - .load(fullSizeUrl) - ) - } + if (mode == Mode.THUMBNAIL) { + error( + GlideApp + .with(imageView) + .load(contentUrlResolver.resolveFullSize(data.url)) + ) + } } } } From 30e46445ca1c3f24324ce039febbdf32a5df5077 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 4 Mar 2020 09:35:09 +0100 Subject: [PATCH 42/91] Add documentation to install environment and run integration tests (#1098) Add documentation to install environment and run integration tests --- CONTRIBUTING.md | 2 + docs/integration_tests.md | 97 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 99 insertions(+) create mode 100644 docs/integration_tests.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 8e08a921fb..176a6ee9c1 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -82,6 +82,8 @@ Make sure the following commands execute without any error: RiotX is currently supported on Android KitKat (API 19+): please test your change on an Android device (or Android emulator) running with API 19. Many issues can happen (including crashes) on older devices. Also, if possible, please test your change on a real device. Testing on Android emulator may not be sufficient. +You should consider adding Unit tests with your PR, and also integration tests (AndroidTest). Please refer to [this document](./docs/integration_tests.md) to install and run the integration test environment. + ### Internationalisation When adding new string resources, please only add new entries in file `value/strings.xml`. Translations will be added later by the community of translators with a specific tool named [Weblate](https://translate.riot.im/projects/riot-android/). diff --git a/docs/integration_tests.md b/docs/integration_tests.md new file mode 100644 index 0000000000..f7557a87a2 --- /dev/null +++ b/docs/integration_tests.md @@ -0,0 +1,97 @@ +# Integration tests + +Integration tests are useful to ensure that the code works well for any use cases. + +They can also be used as sample on how to use the Matrix SDK. + +In a ideal world, every API of the SDK should be covered by integration tests. For the moment, we have test mainly for the Crypto part, which is the tricky part. But it covers quite a lot of features: accounts creation, login to existing account, send encrypted messages, keys backup, verification, etc. + +The Matrix SDK is able to open multiple sessions, for the same user, of for different users. This way we can test communication between several sessions on a single device. + +## Pre requirements + +Integration tests need a homeserver running on localhost. + +The documentation describes what we do to have one, using [Synapse](https://github.com/matrix-org/synapse/), which is the Matrix reference homeserver. + +## Install and run Synapse + +Steps: + +- Install virtualenv + +```bash +python3 -m pip install virtualenv +``` + +- Clone Synapse repository + +```bash +git clone -b develop https://github.com/matrix-org/synapse.git +``` +or +```bash +git clone -b develop git@github.com:matrix-org/synapse.git +``` + +You should have the develop branch cloned by default. + +- Run synapse, from the Synapse folder you just cloned + +```bash +virtualenv -p python3 env +source env/bin/activate +pip install -e . +demo/start.sh --no-rate-limit +``` + +Alternatively, to install the latest Synapse release package (and not a cloned branch) you can run the following instead of `pip install -e .`: + +```bash +pip install matrix-synapse +``` + +You should now have 3 running federated Synapse instances 🎉, at http://127.0.0.1:8080/, http://127.0.0.1:8081/ and http://127.0.0.1:8082/, which should display a "It Works! Synapse is running" message. + +## Run the test + +It's recommended to run tests using an Android Emulator and not a real device. First reason for that is that the tests will use http://10.0.2.2:8080 to connect to Synapse, which run locally on your machine. + +You can run all the tests in the `androidTest` folders. + +## Stop Synapse + +To stop Synapse, you can run the following commands: + +```bash +./demo/stop.sh +``` + +And you can deactivate the virtualenv: + +```bash +deactivate +``` + +## Troubleshoot + +You'll need python3 to be able to run synapse + +### Android Emulator does cannot reach the homeserver + +Try on the Emulator browser to open "http://10.0.2.2:8080". You should see the "Synapse is running" message. + +### virtualenv command fails + +You can try using +```bash +python3 -m venv env +``` +or +```bash +python3 -m virtualenv env +``` +instead of +```bash +virtualenv -p python3 env +``` From 0121eee5b83e36af7b2c97899198ec5f4ad834c5 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 4 Mar 2020 09:37:32 +0100 Subject: [PATCH 43/91] changelog --- CHANGES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index b2ad0766c4..37ff98758b 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -20,7 +20,7 @@ Build 🧱: - Other changes: - - + - Add a [documentation](./docs/integration_tests.md) to run integration tests Changes in RiotX 0.17.0 (2020-02-27) =================================================== From d6df0e451c585de1179ff8558ead6cead0636ad7 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 4 Mar 2020 10:37:31 +0100 Subject: [PATCH 44/91] Detect spaces in password if user fail to login (#1038) --- CHANGES.md | 1 + .../vector/riotx/features/login/LoginFragment.kt | 14 +++++++++++++- vector/src/main/res/values/strings_riotX.xml | 1 + 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index 37ff98758b..0184981252 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -6,6 +6,7 @@ Features ✨: Improvements 🙌: - Add support for `/plain` command (#12) + - Detect spaces in password if user fail to login (#1038) Bugfix 🐛: - Fix crash on attachment preview screen (#1088) diff --git a/vector/src/main/java/im/vector/riotx/features/login/LoginFragment.kt b/vector/src/main/java/im/vector/riotx/features/login/LoginFragment.kt index 3e45eeb406..01cc19fa5b 100644 --- a/vector/src/main/java/im/vector/riotx/features/login/LoginFragment.kt +++ b/vector/src/main/java/im/vector/riotx/features/login/LoginFragment.kt @@ -209,7 +209,14 @@ class LoginFragment @Inject constructor() : AbstractLoginFragment() { } else { // Trick to display the error without text. loginFieldTil.error = " " - passwordFieldTil.error = errorFormatter.toHumanReadable(state.asyncLoginAction.error) + if (error is Failure.ServerError + && error.error.code == MatrixError.M_FORBIDDEN + && error.error.message == "Invalid password" + && spaceInPassword()) { + passwordFieldTil.error = getString(R.string.auth_invalid_login_param_space_in_password) + } else { + passwordFieldTil.error = errorFormatter.toHumanReadable(error) + } } } // Success is handled by the LoginActivity @@ -226,4 +233,9 @@ class LoginFragment @Inject constructor() : AbstractLoginFragment() { is Success -> Unit } } + + /** + * Detect if password ends or starts with spaces + */ + private fun spaceInPassword() = passwordField.text.toString().let { it.trim() != it } } diff --git a/vector/src/main/res/values/strings_riotX.xml b/vector/src/main/res/values/strings_riotX.xml index 69d821c0ca..579fdae874 100644 --- a/vector/src/main/res/values/strings_riotX.xml +++ b/vector/src/main/res/values/strings_riotX.xml @@ -29,4 +29,5 @@ Sends a message as plain text, without interpreting it as markdown + Incorrect username and/or password. The entered password starts or ends with spaces, please check it. From 78bc2bbaa5b2cdcc4380b568809952327daeac80 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 4 Mar 2020 12:15:33 +0100 Subject: [PATCH 45/91] AndroidStudio cleanup --- .idea/codeStyles/Project.xml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml index 40ee4ee5cf..b3719669fd 100644 --- a/.idea/codeStyles/Project.xml +++ b/.idea/codeStyles/Project.xml @@ -1,9 +1,6 @@