mirror of
https://github.com/element-hq/element-android
synced 2024-11-24 10:25:35 +03:00
Merge branch 'develop' into feature/fix_sending_too_long
This commit is contained in:
commit
4d7b0e3e68
14 changed files with 176 additions and 39 deletions
10
.github/ISSUE_TEMPLATE/matrix-sdk.md
vendored
Normal file
10
.github/ISSUE_TEMPLATE/matrix-sdk.md
vendored
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
---
|
||||||
|
name: Matrix SDK
|
||||||
|
about: Report issue or ask for a feature regarding the Android Matrix SDK
|
||||||
|
title: "[SDK] "
|
||||||
|
labels: matrix-sdk
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<!-- This issue template should be used by third party application maintainers, to report a bug or to request a feature on the SDK module of the application Element Android-->
|
|
@ -5,10 +5,12 @@ Features ✨:
|
||||||
-
|
-
|
||||||
|
|
||||||
Improvements 🙌:
|
Improvements 🙌:
|
||||||
-
|
- Add "show password" in import Megolm keys dialog
|
||||||
|
|
||||||
Bugfix 🐛:
|
Bugfix 🐛:
|
||||||
- Long message cannot be sent/takes infinite time & blocks other messages #1397
|
- Long message cannot be sent/takes infinite time & blocks other messages #1397
|
||||||
|
- User Verification in DM not working
|
||||||
|
- Manual import of Megolm keys does back up the imported keys
|
||||||
|
|
||||||
Translations 🗣:
|
Translations 🗣:
|
||||||
-
|
-
|
||||||
|
@ -20,7 +22,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)
|
||||||
===================================================
|
===================================================
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -24,6 +24,7 @@ import com.squareup.moshi.JsonClass
|
||||||
import org.matrix.android.sdk.api.failure.shouldBeRetried
|
import org.matrix.android.sdk.api.failure.shouldBeRetried
|
||||||
import org.matrix.android.sdk.api.session.crypto.CryptoService
|
import org.matrix.android.sdk.api.session.crypto.CryptoService
|
||||||
import org.matrix.android.sdk.internal.crypto.tasks.SendVerificationMessageTask
|
import org.matrix.android.sdk.internal.crypto.tasks.SendVerificationMessageTask
|
||||||
|
import org.matrix.android.sdk.internal.session.room.send.CancelSendTracker
|
||||||
import org.matrix.android.sdk.internal.session.room.send.LocalEchoRepository
|
import org.matrix.android.sdk.internal.session.room.send.LocalEchoRepository
|
||||||
import org.matrix.android.sdk.internal.worker.SessionWorkerParams
|
import org.matrix.android.sdk.internal.worker.SessionWorkerParams
|
||||||
import org.matrix.android.sdk.internal.worker.WorkerParamsFactory
|
import org.matrix.android.sdk.internal.worker.WorkerParamsFactory
|
||||||
|
@ -55,6 +56,8 @@ internal class SendVerificationMessageWorker(context: Context,
|
||||||
@Inject
|
@Inject
|
||||||
lateinit var cryptoService: CryptoService
|
lateinit var cryptoService: CryptoService
|
||||||
|
|
||||||
|
@Inject lateinit var cancelSendTracker: CancelSendTracker
|
||||||
|
|
||||||
override suspend fun doWork(): Result {
|
override suspend fun doWork(): Result {
|
||||||
val errorOutputData = Data.Builder().putBoolean(OUTPUT_KEY_FAILED, true).build()
|
val errorOutputData = Data.Builder().putBoolean(OUTPUT_KEY_FAILED, true).build()
|
||||||
val params = WorkerParamsFactory.fromData<Params>(inputData)
|
val params = WorkerParamsFactory.fromData<Params>(inputData)
|
||||||
|
@ -68,16 +71,26 @@ internal class SendVerificationMessageWorker(context: Context,
|
||||||
sessionComponent.inject(this)
|
sessionComponent.inject(this)
|
||||||
|
|
||||||
val localEvent = localEchoRepository.getUpToDateEcho(params.eventId) ?: return Result.success(errorOutputData)
|
val localEvent = localEchoRepository.getUpToDateEcho(params.eventId) ?: return Result.success(errorOutputData)
|
||||||
|
val localEventId = localEvent.eventId ?: ""
|
||||||
|
val roomId = localEvent.roomId ?: ""
|
||||||
|
|
||||||
|
if (cancelSendTracker.isCancelRequestedFor(localEventId, roomId)) {
|
||||||
|
return Result.success()
|
||||||
|
.also {
|
||||||
|
cancelSendTracker.markCancelled(localEventId, roomId)
|
||||||
|
Timber.e("## SendEvent: Event sending has been cancelled $localEventId")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return try {
|
return try {
|
||||||
val eventId = sendVerificationMessageTask.execute(
|
val resultEventId = sendVerificationMessageTask.execute(
|
||||||
SendVerificationMessageTask.Params(
|
SendVerificationMessageTask.Params(
|
||||||
event = localEvent,
|
event = localEvent,
|
||||||
cryptoService = cryptoService
|
cryptoService = cryptoService
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
Result.success(Data.Builder().putString(params.eventId, eventId).build())
|
Result.success(Data.Builder().putString(localEventId, resultEventId).build())
|
||||||
} catch (exception: Throwable) {
|
} catch (exception: Throwable) {
|
||||||
if (exception.shouldBeRetried()) {
|
if (exception.shouldBeRetried()) {
|
||||||
Result.retry()
|
Result.retry()
|
||||||
|
|
|
@ -115,20 +115,31 @@ internal class VerificationTransportRoomMessage(
|
||||||
val observer = object : Observer<List<WorkInfo>> {
|
val observer = object : Observer<List<WorkInfo>> {
|
||||||
override fun onChanged(workInfoList: List<WorkInfo>?) {
|
override fun onChanged(workInfoList: List<WorkInfo>?) {
|
||||||
workInfoList
|
workInfoList
|
||||||
?.filter { it.state == WorkInfo.State.SUCCEEDED }
|
|
||||||
?.firstOrNull { it.id == enqueueInfo.second }
|
?.firstOrNull { it.id == enqueueInfo.second }
|
||||||
?.let { wInfo ->
|
?.let { wInfo ->
|
||||||
if (SendVerificationMessageWorker.hasFailed(wInfo.outputData)) {
|
|
||||||
Timber.e("## SAS verification [${tx?.transactionId}] failed to send verification message in state : ${tx?.state}")
|
when (wInfo.state) {
|
||||||
tx?.cancel(onErrorReason)
|
WorkInfo.State.FAILED -> {
|
||||||
} else {
|
tx?.cancel(onErrorReason)
|
||||||
if (onDone != null) {
|
workLiveData.removeObserver(this)
|
||||||
onDone()
|
}
|
||||||
} else {
|
WorkInfo.State.SUCCEEDED -> {
|
||||||
tx?.state = nextState
|
if (SendVerificationMessageWorker.hasFailed(wInfo.outputData)) {
|
||||||
|
Timber.e("## SAS verification [${tx?.transactionId}] failed to send verification message in state : ${tx?.state}")
|
||||||
|
tx?.cancel(onErrorReason)
|
||||||
|
} else {
|
||||||
|
if (onDone != null) {
|
||||||
|
onDone()
|
||||||
|
} else {
|
||||||
|
tx?.state = nextState
|
||||||
|
}
|
||||||
|
}
|
||||||
|
workLiveData.removeObserver(this)
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
// nop
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
workLiveData.removeObserver(this)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -184,7 +195,7 @@ internal class VerificationTransportRoomMessage(
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
workManagerProvider.workManager
|
workManagerProvider.workManager
|
||||||
.beginUniqueWork("${roomId}_VerificationWork", ExistingWorkPolicy.APPEND, workRequest)
|
.beginUniqueWork("${roomId}_VerificationWork", ExistingWorkPolicy.APPEND_OR_REPLACE, workRequest)
|
||||||
.enqueue()
|
.enqueue()
|
||||||
|
|
||||||
// I cannot just listen to the given work request, because when used in a uniqueWork,
|
// I cannot just listen to the given work request, because when used in a uniqueWork,
|
||||||
|
@ -280,7 +291,7 @@ internal class VerificationTransportRoomMessage(
|
||||||
.setBackoffCriteria(BackoffPolicy.LINEAR, 2_000L, TimeUnit.MILLISECONDS)
|
.setBackoffCriteria(BackoffPolicy.LINEAR, 2_000L, TimeUnit.MILLISECONDS)
|
||||||
.build()
|
.build()
|
||||||
return workManagerProvider.workManager
|
return workManagerProvider.workManager
|
||||||
.beginUniqueWork(uniqueQueueName(), ExistingWorkPolicy.APPEND, workRequest)
|
.beginUniqueWork(uniqueQueueName(), ExistingWorkPolicy.APPEND_OR_REPLACE, workRequest)
|
||||||
.enqueue() to workRequest.id
|
.enqueue() to workRequest.id
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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()
|
||||||
|
}
|
|
@ -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
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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>
|
|
@ -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>
|
||||||
|
|
Loading…
Reference in a new issue