Merge branch 'develop' into fix_draft_sharesheet
This commit is contained in:
commit
bbbaa60ddd
@ -8,14 +8,15 @@ Improvements 🙌:
|
|||||||
- Open an existing DM instead of creating a new one (#2319)
|
- Open an existing DM instead of creating a new one (#2319)
|
||||||
|
|
||||||
Bugfix 🐛:
|
Bugfix 🐛:
|
||||||
- Fix issue when updating the avatar of a room
|
|
||||||
- Fix issue when restoring draft after sharing (#2287)
|
- Fix issue when restoring draft after sharing (#2287)
|
||||||
|
- Fix issue when updating the avatar of a room (new avatar vanishing)
|
||||||
|
- Discard change dialog displayed by mistake when avatar has been updated
|
||||||
|
|
||||||
Translations 🗣:
|
Translations 🗣:
|
||||||
-
|
-
|
||||||
|
|
||||||
SDK API changes ⚠️:
|
SDK API changes ⚠️:
|
||||||
-
|
- AccountService now exposes suspendable function instead of using MatrixCallback (#2354). Note: We will incrementally migrate all the SDK API in a near future.
|
||||||
|
|
||||||
Build 🧱:
|
Build 🧱:
|
||||||
-
|
-
|
||||||
|
@ -43,8 +43,8 @@ class ChangePasswordTest : InstrumentedTest {
|
|||||||
val session = commonTestHelper.createAccount(TestConstants.USER_ALICE, SessionTestParams(withInitialSync = false))
|
val session = commonTestHelper.createAccount(TestConstants.USER_ALICE, SessionTestParams(withInitialSync = false))
|
||||||
|
|
||||||
// Change password
|
// Change password
|
||||||
commonTestHelper.doSync<Unit> {
|
commonTestHelper.runBlockingTest {
|
||||||
session.changePassword(TestConstants.PASSWORD, NEW_PASSWORD, it)
|
session.changePassword(TestConstants.PASSWORD, NEW_PASSWORD)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try to login with the previous password, it will fail
|
// Try to login with the previous password, it will fail
|
||||||
|
@ -43,8 +43,8 @@ class DeactivateAccountTest : InstrumentedTest {
|
|||||||
val session = commonTestHelper.createAccount(TestConstants.USER_ALICE, SessionTestParams(withInitialSync = false))
|
val session = commonTestHelper.createAccount(TestConstants.USER_ALICE, SessionTestParams(withInitialSync = false))
|
||||||
|
|
||||||
// Deactivate the account
|
// Deactivate the account
|
||||||
commonTestHelper.doSync<Unit> {
|
commonTestHelper.runBlockingTest {
|
||||||
session.deactivateAccount(TestConstants.PASSWORD, false, it)
|
session.deactivateAccount(TestConstants.PASSWORD, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try to login on the previous account, it will fail (M_USER_DEACTIVATED)
|
// Try to login on the previous account, it will fail (M_USER_DEACTIVATED)
|
||||||
|
@ -40,6 +40,7 @@ import kotlinx.coroutines.GlobalScope
|
|||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
|
import kotlinx.coroutines.withTimeout
|
||||||
import org.junit.Assert.assertEquals
|
import org.junit.Assert.assertEquals
|
||||||
import org.junit.Assert.assertNotNull
|
import org.junit.Assert.assertNotNull
|
||||||
import org.junit.Assert.assertTrue
|
import org.junit.Assert.assertTrue
|
||||||
@ -343,6 +344,14 @@ class CommonTestHelper(context: Context) {
|
|||||||
await(latch, timeout)
|
await(latch, timeout)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun <T> runBlockingTest(timeout: Long = TestConstants.timeOutMillis, block: suspend () -> T): T {
|
||||||
|
return runBlocking {
|
||||||
|
withTimeout(timeout) {
|
||||||
|
block()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Transform a method with a MatrixCallback to a synchronous method
|
// Transform a method with a MatrixCallback to a synchronous method
|
||||||
inline fun <reified T> doSync(timeout: Long? = TestConstants.timeOutMillis, block: (MatrixCallback<T>) -> Unit): T {
|
inline fun <reified T> doSync(timeout: Long? = TestConstants.timeOutMillis, block: (MatrixCallback<T>) -> Unit): T {
|
||||||
val lock = CountDownLatch(1)
|
val lock = CountDownLatch(1)
|
||||||
|
@ -16,9 +16,6 @@
|
|||||||
|
|
||||||
package org.matrix.android.sdk.api.session.account
|
package org.matrix.android.sdk.api.session.account
|
||||||
|
|
||||||
import org.matrix.android.sdk.api.MatrixCallback
|
|
||||||
import org.matrix.android.sdk.api.util.Cancelable
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This interface defines methods to manage the account. It's implemented at the session level.
|
* This interface defines methods to manage the account. It's implemented at the session level.
|
||||||
*/
|
*/
|
||||||
@ -28,7 +25,7 @@ interface AccountService {
|
|||||||
* @param password Current password.
|
* @param password Current password.
|
||||||
* @param newPassword New password
|
* @param newPassword New password
|
||||||
*/
|
*/
|
||||||
fun changePassword(password: String, newPassword: String, callback: MatrixCallback<Unit>): Cancelable
|
suspend fun changePassword(password: String, newPassword: String)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deactivate the account.
|
* Deactivate the account.
|
||||||
@ -46,5 +43,5 @@ interface AccountService {
|
|||||||
* @param eraseAllData set to true to forget all messages that have been sent. Warning: this will cause future users to see
|
* @param eraseAllData set to true to forget all messages that have been sent. Warning: this will cause future users to see
|
||||||
* an incomplete view of conversations
|
* an incomplete view of conversations
|
||||||
*/
|
*/
|
||||||
fun deactivateAccount(password: String, eraseAllData: Boolean, callback: MatrixCallback<Unit>): Cancelable
|
suspend fun deactivateAccount(password: String, eraseAllData: Boolean)
|
||||||
}
|
}
|
||||||
|
@ -16,30 +16,17 @@
|
|||||||
|
|
||||||
package org.matrix.android.sdk.internal.session.account
|
package org.matrix.android.sdk.internal.session.account
|
||||||
|
|
||||||
import org.matrix.android.sdk.api.MatrixCallback
|
|
||||||
import org.matrix.android.sdk.api.session.account.AccountService
|
import org.matrix.android.sdk.api.session.account.AccountService
|
||||||
import org.matrix.android.sdk.api.util.Cancelable
|
|
||||||
import org.matrix.android.sdk.internal.task.TaskExecutor
|
|
||||||
import org.matrix.android.sdk.internal.task.configureWith
|
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
internal class DefaultAccountService @Inject constructor(private val changePasswordTask: ChangePasswordTask,
|
internal class DefaultAccountService @Inject constructor(private val changePasswordTask: ChangePasswordTask,
|
||||||
private val deactivateAccountTask: DeactivateAccountTask,
|
private val deactivateAccountTask: DeactivateAccountTask) : AccountService {
|
||||||
private val taskExecutor: TaskExecutor) : AccountService {
|
|
||||||
|
|
||||||
override fun changePassword(password: String, newPassword: String, callback: MatrixCallback<Unit>): Cancelable {
|
override suspend fun changePassword(password: String, newPassword: String) {
|
||||||
return changePasswordTask
|
changePasswordTask.execute(ChangePasswordTask.Params(password, newPassword))
|
||||||
.configureWith(ChangePasswordTask.Params(password, newPassword)) {
|
|
||||||
this.callback = callback
|
|
||||||
}
|
|
||||||
.executeBy(taskExecutor)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun deactivateAccount(password: String, eraseAllData: Boolean, callback: MatrixCallback<Unit>): Cancelable {
|
override suspend fun deactivateAccount(password: String, eraseAllData: Boolean) {
|
||||||
return deactivateAccountTask
|
deactivateAccountTask.execute(DeactivateAccountTask.Params(password, eraseAllData))
|
||||||
.configureWith(DeactivateAccountTask.Params(password, eraseAllData)) {
|
|
||||||
this.callback = callback
|
|
||||||
}
|
|
||||||
.executeBy(taskExecutor)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -35,6 +35,7 @@ import org.matrix.android.sdk.internal.task.TaskExecutor
|
|||||||
import org.matrix.android.sdk.internal.task.configureWith
|
import org.matrix.android.sdk.internal.task.configureWith
|
||||||
import org.matrix.android.sdk.internal.task.launchToCallback
|
import org.matrix.android.sdk.internal.task.launchToCallback
|
||||||
import org.matrix.android.sdk.internal.util.MatrixCoroutineDispatchers
|
import org.matrix.android.sdk.internal.util.MatrixCoroutineDispatchers
|
||||||
|
import org.matrix.android.sdk.internal.util.awaitCallback
|
||||||
|
|
||||||
internal class DefaultStateService @AssistedInject constructor(@Assisted private val roomId: String,
|
internal class DefaultStateService @AssistedInject constructor(@Assisted private val roomId: String,
|
||||||
private val stateEventDataSource: StateEventDataSource,
|
private val stateEventDataSource: StateEventDataSource,
|
||||||
@ -132,23 +133,23 @@ internal class DefaultStateService @AssistedInject constructor(@Assisted private
|
|||||||
override fun updateAvatar(avatarUri: Uri, fileName: String, callback: MatrixCallback<Unit>): Cancelable {
|
override fun updateAvatar(avatarUri: Uri, fileName: String, callback: MatrixCallback<Unit>): Cancelable {
|
||||||
return taskExecutor.executorScope.launchToCallback(coroutineDispatchers.main, callback) {
|
return taskExecutor.executorScope.launchToCallback(coroutineDispatchers.main, callback) {
|
||||||
val response = fileUploader.uploadFromUri(avatarUri, fileName, "image/jpeg")
|
val response = fileUploader.uploadFromUri(avatarUri, fileName, "image/jpeg")
|
||||||
|
awaitCallback<Unit> {
|
||||||
sendStateEvent(
|
sendStateEvent(
|
||||||
eventType = EventType.STATE_ROOM_AVATAR,
|
eventType = EventType.STATE_ROOM_AVATAR,
|
||||||
body = mapOf("url" to response.contentUri),
|
body = mapOf("url" to response.contentUri),
|
||||||
callback = callback,
|
callback = it,
|
||||||
stateKey = null
|
stateKey = null
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun deleteAvatar(callback: MatrixCallback<Unit>): Cancelable {
|
override fun deleteAvatar(callback: MatrixCallback<Unit>): Cancelable {
|
||||||
return taskExecutor.executorScope.launchToCallback(coroutineDispatchers.main, callback) {
|
return sendStateEvent(
|
||||||
sendStateEvent(
|
|
||||||
eventType = EventType.STATE_ROOM_AVATAR,
|
eventType = EventType.STATE_ROOM_AVATAR,
|
||||||
body = emptyMap(),
|
body = emptyMap(),
|
||||||
callback = callback,
|
callback = callback,
|
||||||
stateKey = null
|
stateKey = null
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -211,7 +211,10 @@ class RoomSettingsViewModel @AssistedInject constructor(@Assisted initialState:
|
|||||||
postLoading(false)
|
postLoading(false)
|
||||||
setState {
|
setState {
|
||||||
deletePendingAvatar(this)
|
deletePendingAvatar(this)
|
||||||
copy(newHistoryVisibility = null)
|
copy(
|
||||||
|
avatarAction = RoomSettingsViewState.AvatarAction.None,
|
||||||
|
newHistoryVisibility = null
|
||||||
|
)
|
||||||
}
|
}
|
||||||
_viewEvents.post(RoomSettingsViewEvents.Success)
|
_viewEvents.post(RoomSettingsViewEvents.Success)
|
||||||
},
|
},
|
||||||
|
@ -27,6 +27,7 @@ import android.widget.ImageView
|
|||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.appcompat.app.AlertDialog
|
import androidx.appcompat.app.AlertDialog
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
|
import androidx.lifecycle.lifecycleScope
|
||||||
import androidx.preference.EditTextPreference
|
import androidx.preference.EditTextPreference
|
||||||
import androidx.preference.Preference
|
import androidx.preference.Preference
|
||||||
import androidx.preference.PreferenceCategory
|
import androidx.preference.PreferenceCategory
|
||||||
@ -451,30 +452,27 @@ class VectorSettingsGeneralFragment @Inject constructor(
|
|||||||
val newPwd = newPasswordText.text.toString()
|
val newPwd = newPasswordText.text.toString()
|
||||||
|
|
||||||
showPasswordLoadingView(true)
|
showPasswordLoadingView(true)
|
||||||
session.changePassword(oldPwd, newPwd, object : MatrixCallback<Unit> {
|
lifecycleScope.launch {
|
||||||
override fun onSuccess(data: Unit) {
|
val result = runCatching {
|
||||||
|
session.changePassword(oldPwd, newPwd)
|
||||||
|
}
|
||||||
if (!isAdded) {
|
if (!isAdded) {
|
||||||
return
|
return@launch
|
||||||
}
|
}
|
||||||
showPasswordLoadingView(false)
|
showPasswordLoadingView(false)
|
||||||
|
result.fold({
|
||||||
dialog.dismiss()
|
dialog.dismiss()
|
||||||
activity.toast(R.string.settings_password_updated)
|
activity.toast(R.string.settings_password_updated)
|
||||||
}
|
}, { failure ->
|
||||||
|
|
||||||
override fun onFailure(failure: Throwable) {
|
|
||||||
if (!isAdded) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
showPasswordLoadingView(false)
|
|
||||||
if (failure.isInvalidPassword()) {
|
if (failure.isInvalidPassword()) {
|
||||||
oldPasswordTil.error = getString(R.string.settings_fail_to_update_password_invalid_current_password)
|
oldPasswordTil.error = getString(R.string.settings_fail_to_update_password_invalid_current_password)
|
||||||
} else {
|
} else {
|
||||||
oldPasswordTil.error = getString(R.string.settings_fail_to_update_password)
|
oldPasswordTil.error = getString(R.string.settings_fail_to_update_password)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
dialog.show()
|
dialog.show()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package im.vector.app.features.settings.account.deactivation
|
package im.vector.app.features.settings.account.deactivation
|
||||||
|
|
||||||
|
import androidx.lifecycle.viewModelScope
|
||||||
import com.airbnb.mvrx.FragmentViewModelContext
|
import com.airbnb.mvrx.FragmentViewModelContext
|
||||||
import com.airbnb.mvrx.MvRxState
|
import com.airbnb.mvrx.MvRxState
|
||||||
import com.airbnb.mvrx.MvRxViewModelFactory
|
import com.airbnb.mvrx.MvRxViewModelFactory
|
||||||
@ -24,9 +25,10 @@ import com.squareup.inject.assisted.AssistedInject
|
|||||||
import im.vector.app.core.extensions.exhaustive
|
import im.vector.app.core.extensions.exhaustive
|
||||||
import im.vector.app.core.platform.VectorViewModel
|
import im.vector.app.core.platform.VectorViewModel
|
||||||
import im.vector.app.core.platform.VectorViewModelAction
|
import im.vector.app.core.platform.VectorViewModelAction
|
||||||
import org.matrix.android.sdk.api.MatrixCallback
|
import kotlinx.coroutines.launch
|
||||||
import org.matrix.android.sdk.api.failure.isInvalidPassword
|
import org.matrix.android.sdk.api.failure.isInvalidPassword
|
||||||
import org.matrix.android.sdk.api.session.Session
|
import org.matrix.android.sdk.api.session.Session
|
||||||
|
import java.lang.Exception
|
||||||
|
|
||||||
data class DeactivateAccountViewState(
|
data class DeactivateAccountViewState(
|
||||||
val passwordShown: Boolean = false
|
val passwordShown: Boolean = false
|
||||||
@ -67,20 +69,21 @@ class DeactivateAccountViewModel @AssistedInject constructor(@Assisted private v
|
|||||||
|
|
||||||
_viewEvents.post(DeactivateAccountViewEvents.Loading())
|
_viewEvents.post(DeactivateAccountViewEvents.Loading())
|
||||||
|
|
||||||
session.deactivateAccount(action.password, action.eraseAllData, object : MatrixCallback<Unit> {
|
viewModelScope.launch {
|
||||||
override fun onSuccess(data: Unit) {
|
val event = try {
|
||||||
_viewEvents.post(DeactivateAccountViewEvents.Done)
|
session.deactivateAccount(action.password, action.eraseAllData)
|
||||||
|
DeactivateAccountViewEvents.Done
|
||||||
|
} catch (failure: Exception) {
|
||||||
|
if (failure.isInvalidPassword()) {
|
||||||
|
DeactivateAccountViewEvents.InvalidPassword
|
||||||
|
} else {
|
||||||
|
DeactivateAccountViewEvents.OtherFailure(failure)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onFailure(failure: Throwable) {
|
_viewEvents.post(event)
|
||||||
if (failure.isInvalidPassword()) {
|
|
||||||
_viewEvents.post(DeactivateAccountViewEvents.InvalidPassword)
|
|
||||||
} else {
|
|
||||||
_viewEvents.post(DeactivateAccountViewEvents.OtherFailure(failure))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object : MvRxViewModelFactory<DeactivateAccountViewModel, DeactivateAccountViewState> {
|
companion object : MvRxViewModelFactory<DeactivateAccountViewModel, DeactivateAccountViewState> {
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user