Merge branch 'develop' into feature/fix_regression_verif_dm

This commit is contained in:
Benoit Marty 2020-09-21 09:52:58 +02:00 committed by GitHub
commit 69a4312613
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 127 additions and 25 deletions

View File

@ -5,10 +5,11 @@ Features ✨:
- -
Improvements 🙌: Improvements 🙌:
- - Add "show password" in import Megolm keys dialog
Bugfix 🐛: Bugfix 🐛:
- User Verification in DM not working - User Verification in DM not working
- Manual import of Megolm keys does back up the imported keys
Translations 🗣: Translations 🗣:
- -
@ -20,7 +21,7 @@ Build 🧱:
- -
Other changes: Other changes:
- - Add an advanced action to reset an account data entry
Changes in Element 1.0.7 (2020-09-17) Changes in Element 1.0.7 (2020-09-17)
=================================================== ===================================================

View File

@ -27,6 +27,12 @@ import androidx.lifecycle.LiveData
import com.squareup.moshi.Types import com.squareup.moshi.Types
import com.zhuinden.monarchy.Monarchy import com.zhuinden.monarchy.Monarchy
import dagger.Lazy import dagger.Lazy
import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.cancelChildren
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.withContext
import org.matrix.android.sdk.api.MatrixCallback import org.matrix.android.sdk.api.MatrixCallback
import org.matrix.android.sdk.api.NoOpMatrixCallback import org.matrix.android.sdk.api.NoOpMatrixCallback
import org.matrix.android.sdk.api.crypto.MXCryptoConfig import org.matrix.android.sdk.api.crypto.MXCryptoConfig
@ -102,12 +108,6 @@ import org.matrix.android.sdk.internal.task.launchToCallback
import org.matrix.android.sdk.internal.util.JsonCanonicalizer import org.matrix.android.sdk.internal.util.JsonCanonicalizer
import org.matrix.android.sdk.internal.util.MatrixCoroutineDispatchers import org.matrix.android.sdk.internal.util.MatrixCoroutineDispatchers
import org.matrix.android.sdk.internal.util.fetchCopied import org.matrix.android.sdk.internal.util.fetchCopied
import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.cancelChildren
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.withContext
import org.matrix.olm.OlmManager import org.matrix.olm.OlmManager
import timber.log.Timber import timber.log.Timber
import java.util.concurrent.atomic.AtomicBoolean import java.util.concurrent.atomic.AtomicBoolean
@ -1072,7 +1072,11 @@ internal class DefaultCryptoService @Inject constructor(
throw Exception("Error") throw Exception("Error")
} }
megolmSessionDataImporter.handle(importedSessions, true, progressListener) megolmSessionDataImporter.handle(
megolmSessionsData = importedSessions,
fromBackup = false,
progressListener = progressListener
)
} }
}.foldToCallback(callback) }.foldToCallback(callback)
} }

View File

@ -39,7 +39,7 @@ internal class MegolmSessionDataImporter @Inject constructor(private val olmDevi
* Must be call on the crypto coroutine thread * Must be call on the crypto coroutine thread
* *
* @param megolmSessionsData megolm sessions. * @param megolmSessionsData megolm sessions.
* @param backUpKeys true to back up them to the homeserver. * @param fromBackup true if the imported keys are already backed up on the server.
* @param progressListener the progress listener * @param progressListener the progress listener
* @return import room keys result * @return import room keys result
*/ */

View File

@ -56,6 +56,9 @@ abstract class GenericItemWithValue : VectorEpoxyModel<GenericItemWithValue.Hold
@EpoxyAttribute @EpoxyAttribute
var itemClickAction: View.OnClickListener? = null var itemClickAction: View.OnClickListener? = null
@EpoxyAttribute
var itemLongClickAction: View.OnLongClickListener? = null
override fun bind(holder: Holder) { override fun bind(holder: Holder) {
super.bind(holder) super.bind(holder)
holder.titleText.setTextOrHide(title) holder.titleText.setTextOrHide(title)
@ -76,6 +79,7 @@ abstract class GenericItemWithValue : VectorEpoxyModel<GenericItemWithValue.Hold
} }
holder.view.setOnClickListener(itemClickAction?.let { DebouncedClickListener(it) }) holder.view.setOnClickListener(itemClickAction?.let { DebouncedClickListener(it) })
holder.view.setOnLongClickListener(itemLongClickAction)
} }
class Holder : VectorEpoxyHolder() { class Holder : VectorEpoxyHolder() {

View File

@ -24,6 +24,7 @@ import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.Button import android.widget.Button
import android.widget.ImageView
import android.widget.TextView import android.widget.TextView
import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AlertDialog
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
@ -38,6 +39,7 @@ import im.vector.app.R
import im.vector.app.core.di.ActiveSessionHolder import im.vector.app.core.di.ActiveSessionHolder
import im.vector.app.core.dialogs.ExportKeysDialog import im.vector.app.core.dialogs.ExportKeysDialog
import im.vector.app.core.extensions.queryExportKeys import im.vector.app.core.extensions.queryExportKeys
import im.vector.app.core.extensions.showPassword
import im.vector.app.core.intent.ExternalIntentData import im.vector.app.core.intent.ExternalIntentData
import im.vector.app.core.intent.analyseIntent import im.vector.app.core.intent.analyseIntent
import im.vector.app.core.intent.getFilenameFromUri import im.vector.app.core.intent.getFilenameFromUri
@ -458,6 +460,15 @@ class VectorSettingsSecurityPrivacyFragment @Inject constructor(
val passPhraseEditText = dialogLayout.findViewById<TextInputEditText>(R.id.dialog_e2e_keys_passphrase_edit_text) val passPhraseEditText = dialogLayout.findViewById<TextInputEditText>(R.id.dialog_e2e_keys_passphrase_edit_text)
val importButton = dialogLayout.findViewById<Button>(R.id.dialog_e2e_keys_import_button) val importButton = dialogLayout.findViewById<Button>(R.id.dialog_e2e_keys_import_button)
val showPassword = dialogLayout.findViewById<ImageView>(R.id.importDialogShowPassword)
var passwordVisible = false
showPassword.setOnClickListener {
passwordVisible = !passwordVisible
passPhraseEditText.showPassword(passwordVisible)
showPassword.setImageResource(if (passwordVisible) R.drawable.ic_eye_closed else R.drawable.ic_eye)
}
passPhraseEditText.addTextChangedListener(object : SimpleTextWatcher() { passPhraseEditText.addTextChangedListener(object : SimpleTextWatcher() {
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) { override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {
importButton.isEnabled = !passPhraseEditText.text.isNullOrEmpty() importButton.isEnabled = !passPhraseEditText.text.isNullOrEmpty()

View File

@ -0,0 +1,23 @@
/*
* 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.app.features.settings.devtools
import im.vector.app.core.platform.VectorViewModelAction
sealed class AccountDataAction : VectorViewModelAction {
data class DeleteAccountData(val type: String) : AccountDataAction()
}

View File

@ -21,13 +21,13 @@ import com.airbnb.epoxy.TypedEpoxyController
import com.airbnb.mvrx.Fail import com.airbnb.mvrx.Fail
import com.airbnb.mvrx.Loading import com.airbnb.mvrx.Loading
import com.airbnb.mvrx.Success import com.airbnb.mvrx.Success
import org.matrix.android.sdk.api.session.accountdata.UserAccountDataEvent
import im.vector.app.R import im.vector.app.R
import im.vector.app.core.epoxy.loadingItem import im.vector.app.core.epoxy.loadingItem
import im.vector.app.core.resources.StringProvider import im.vector.app.core.resources.StringProvider
import im.vector.app.core.ui.list.genericFooterItem import im.vector.app.core.ui.list.genericFooterItem
import im.vector.app.core.ui.list.genericItemWithValue import im.vector.app.core.ui.list.genericItemWithValue
import im.vector.app.core.utils.DebouncedClickListener import im.vector.app.core.utils.DebouncedClickListener
import org.matrix.android.sdk.api.session.accountdata.UserAccountDataEvent
import javax.inject.Inject import javax.inject.Inject
class AccountDataEpoxyController @Inject constructor( class AccountDataEpoxyController @Inject constructor(
@ -36,6 +36,7 @@ class AccountDataEpoxyController @Inject constructor(
interface InteractionListener { interface InteractionListener {
fun didTap(data: UserAccountDataEvent) fun didTap(data: UserAccountDataEvent)
fun didLongTap(data: UserAccountDataEvent)
} }
var interactionListener: InteractionListener? = null var interactionListener: InteractionListener? = null
@ -70,6 +71,10 @@ class AccountDataEpoxyController @Inject constructor(
itemClickAction(DebouncedClickListener(View.OnClickListener { itemClickAction(DebouncedClickListener(View.OnClickListener {
interactionListener?.didTap(accountData) interactionListener?.didTap(accountData)
})) }))
itemLongClickAction(View.OnLongClickListener {
interactionListener?.didLongTap(accountData)
true
})
} }
} }
} }

View File

@ -16,13 +16,14 @@
package im.vector.app.features.settings.devtools package im.vector.app.features.settings.devtools
import android.content.DialogInterface
import android.os.Bundle import android.os.Bundle
import android.view.View import android.view.View
import androidx.appcompat.app.AlertDialog
import com.airbnb.mvrx.fragmentViewModel import com.airbnb.mvrx.fragmentViewModel
import com.airbnb.mvrx.withState import com.airbnb.mvrx.withState
import org.matrix.android.sdk.internal.di.MoshiProvider
import org.matrix.android.sdk.api.session.accountdata.UserAccountDataEvent
import im.vector.app.R import im.vector.app.R
import im.vector.app.core.dialogs.withColoredButton
import im.vector.app.core.extensions.cleanup import im.vector.app.core.extensions.cleanup
import im.vector.app.core.extensions.configureWith import im.vector.app.core.extensions.configureWith
import im.vector.app.core.platform.VectorBaseActivity import im.vector.app.core.platform.VectorBaseActivity
@ -31,6 +32,8 @@ import im.vector.app.core.resources.ColorProvider
import im.vector.app.core.utils.createJSonViewerStyleProvider import im.vector.app.core.utils.createJSonViewerStyleProvider
import kotlinx.android.synthetic.main.fragment_generic_recycler.* import kotlinx.android.synthetic.main.fragment_generic_recycler.*
import org.billcarsonfr.jsonviewer.JSonViewerDialog import org.billcarsonfr.jsonviewer.JSonViewerDialog
import org.matrix.android.sdk.api.session.accountdata.UserAccountDataEvent
import org.matrix.android.sdk.internal.di.MoshiProvider
import javax.inject.Inject import javax.inject.Inject
class AccountDataFragment @Inject constructor( class AccountDataFragment @Inject constructor(
@ -74,4 +77,16 @@ class AccountDataFragment @Inject constructor(
createJSonViewerStyleProvider(colorProvider) createJSonViewerStyleProvider(colorProvider)
).show(childFragmentManager, "JSON_VIEWER") ).show(childFragmentManager, "JSON_VIEWER")
} }
override fun didLongTap(data: UserAccountDataEvent) {
AlertDialog.Builder(requireActivity())
.setTitle(R.string.delete)
.setMessage(getString(R.string.delete_account_data_warning, data.type))
.setNegativeButton(R.string.cancel, null)
.setPositiveButton(R.string.delete) { _, _ ->
viewModel.handle(AccountDataAction.DeleteAccountData(data.type))
}
.show()
.withColoredButton(DialogInterface.BUTTON_POSITIVE)
}
} }

View File

@ -16,6 +16,7 @@
package im.vector.app.features.settings.devtools package im.vector.app.features.settings.devtools
import androidx.lifecycle.viewModelScope
import com.airbnb.mvrx.Async import com.airbnb.mvrx.Async
import com.airbnb.mvrx.FragmentViewModelContext import com.airbnb.mvrx.FragmentViewModelContext
import com.airbnb.mvrx.MvRxState import com.airbnb.mvrx.MvRxState
@ -24,11 +25,13 @@ import com.airbnb.mvrx.Uninitialized
import com.airbnb.mvrx.ViewModelContext import com.airbnb.mvrx.ViewModelContext
import com.squareup.inject.assisted.Assisted import com.squareup.inject.assisted.Assisted
import com.squareup.inject.assisted.AssistedInject import com.squareup.inject.assisted.AssistedInject
import org.matrix.android.sdk.api.session.Session import im.vector.app.core.extensions.exhaustive
import org.matrix.android.sdk.api.session.accountdata.UserAccountDataEvent
import im.vector.app.core.platform.EmptyAction
import im.vector.app.core.platform.EmptyViewEvents import im.vector.app.core.platform.EmptyViewEvents
import im.vector.app.core.platform.VectorViewModel import im.vector.app.core.platform.VectorViewModel
import kotlinx.coroutines.launch
import org.matrix.android.sdk.api.session.Session
import org.matrix.android.sdk.api.session.accountdata.UserAccountDataEvent
import org.matrix.android.sdk.internal.util.awaitCallback
import org.matrix.android.sdk.rx.rx import org.matrix.android.sdk.rx.rx
data class AccountDataViewState( data class AccountDataViewState(
@ -37,7 +40,7 @@ data class AccountDataViewState(
class AccountDataViewModel @AssistedInject constructor(@Assisted initialState: AccountDataViewState, class AccountDataViewModel @AssistedInject constructor(@Assisted initialState: AccountDataViewState,
private val session: Session) private val session: Session)
: VectorViewModel<AccountDataViewState, EmptyAction, EmptyViewEvents>(initialState) { : VectorViewModel<AccountDataViewState, AccountDataAction, EmptyViewEvents>(initialState) {
init { init {
session.rx().liveAccountData(emptySet()) session.rx().liveAccountData(emptySet())
@ -46,7 +49,19 @@ class AccountDataViewModel @AssistedInject constructor(@Assisted initialState: A
} }
} }
override fun handle(action: EmptyAction) {} override fun handle(action: AccountDataAction) {
when (action) {
is AccountDataAction.DeleteAccountData -> handleDeleteAccountData(action)
}.exhaustive
}
private fun handleDeleteAccountData(action: AccountDataAction.DeleteAccountData) {
viewModelScope.launch {
awaitCallback {
session.updateAccountData(action.type, emptyMap(), it)
}
}
}
@AssistedInject.Factory @AssistedInject.Factory
interface Factory { interface Factory {

View File

@ -1,10 +1,10 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/layout_root" android:id="@+id/layout_root"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:orientation="vertical"
android:paddingStart="?dialogPreferredPadding" android:paddingStart="?dialogPreferredPadding"
android:paddingTop="12dp" android:paddingTop="12dp"
android:paddingEnd="?dialogPreferredPadding" android:paddingEnd="?dialogPreferredPadding"
@ -19,14 +19,20 @@
android:textColor="?riotx_text_primary" android:textColor="?riotx_text_primary"
android:textSize="16sp" android:textSize="16sp"
android:visibility="gone" android:visibility="gone"
tools:text="filename.txt" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="@string/import_e2e_keys_from_file"
tools:visibility="visible" /> tools:visibility="visible" />
<com.google.android.material.textfield.TextInputLayout <com.google.android.material.textfield.TextInputLayout
android:id="@+id/importDialogTil"
style="@style/VectorTextInputLayout" style="@style/VectorTextInputLayout"
android:layout_width="match_parent" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:textColorHint="?attr/vctr_default_text_hint_color"> android:textColorHint="?attr/vctr_default_text_hint_color"
app:layout_constraintEnd_toStartOf="@+id/importDialogShowPassword"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/dialog_e2e_keys_passphrase_filename">
<com.google.android.material.textfield.TextInputEditText <com.google.android.material.textfield.TextInputEditText
android:id="@+id/dialog_e2e_keys_passphrase_edit_text" android:id="@+id/dialog_e2e_keys_passphrase_edit_text"
@ -38,6 +44,19 @@
</com.google.android.material.textfield.TextInputLayout> </com.google.android.material.textfield.TextInputLayout>
<ImageView
android:id="@+id/importDialogShowPassword"
android:layout_width="@dimen/layout_touch_size"
android:layout_height="@dimen/layout_touch_size"
android:layout_marginTop="8dp"
android:background="?attr/selectableItemBackground"
android:scaleType="center"
android:src="@drawable/ic_eye"
android:tint="?attr/colorAccent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/importDialogTil"
app:layout_constraintTop_toTopOf="@id/importDialogTil" />
<com.google.android.material.button.MaterialButton <com.google.android.material.button.MaterialButton
android:id="@+id/dialog_e2e_keys_import_button" android:id="@+id/dialog_e2e_keys_import_button"
style="@style/VectorButtonStyle" style="@style/VectorButtonStyle"
@ -46,5 +65,8 @@
android:layout_gravity="end" android:layout_gravity="end"
android:layout_marginTop="10dp" android:layout_marginTop="10dp"
android:enabled="false" android:enabled="false"
android:text="@string/encryption_import_import" /> android:text="@string/encryption_import_import"
</LinearLayout> app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@+id/importDialogTil" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -2226,6 +2226,8 @@
<string name="settings_dev_tools">Dev Tools</string> <string name="settings_dev_tools">Dev Tools</string>
<string name="settings_account_data">Account Data</string> <string name="settings_account_data">Account Data</string>
<string name="delete_account_data_warning">Delete the account data of type %1$s?\n\nUse with caution, it may lead to unexpected behavior.</string>
<plurals name="poll_info"> <plurals name="poll_info">
<item quantity="zero">%d vote</item> <item quantity="zero">%d vote</item>
<item quantity="other">%d votes</item> <item quantity="other">%d votes</item>