mirror of
https://github.com/vector-im/element-android.git
synced 2024-11-16 01:45:05 +08:00
Merge branch 'develop' of https://github.com/vector-im/riotX-android into develop
Signed-off-by: Waylon Cude <waylon.cude@finzdani.net>
This commit is contained in:
commit
d20cf484ff
@ -2,6 +2,7 @@ Changes in RiotX 0.19.0 (2020-XX-XX)
|
|||||||
===================================================
|
===================================================
|
||||||
|
|
||||||
Features ✨:
|
Features ✨:
|
||||||
|
- Change password (#528)
|
||||||
- Cross-Signing | Support SSSS secret sharing (#944)
|
- Cross-Signing | Support SSSS secret sharing (#944)
|
||||||
- Cross-Signing | Verify new session from existing session (#1134)
|
- Cross-Signing | Verify new session from existing session (#1134)
|
||||||
- Cross-Signing | Bootstraping cross signing with 4S from mobile (#985)
|
- Cross-Signing | Bootstraping cross signing with 4S from mobile (#985)
|
||||||
@ -31,6 +32,7 @@ Bugfix 🐛:
|
|||||||
- Cross-Signing | web <-> riotX After QR code scan, gossiping fails (#1210)
|
- Cross-Signing | web <-> riotX After QR code scan, gossiping fails (#1210)
|
||||||
- Fix crash when trying to download file without internet connection (#1229)
|
- Fix crash when trying to download file without internet connection (#1229)
|
||||||
- Local echo are not updated in timeline (for failed & encrypted states)
|
- Local echo are not updated in timeline (for failed & encrypted states)
|
||||||
|
- Render image event even if thumbnail_info does not have mimetype defined (#1209)
|
||||||
- RiotX now uses as many threads as it needs to do work and send messages (#1221)
|
- RiotX now uses as many threads as it needs to do work and send messages (#1221)
|
||||||
|
|
||||||
Translations 🗣:
|
Translations 🗣:
|
||||||
@ -43,6 +45,7 @@ Build 🧱:
|
|||||||
- Compile with Android SDK 29 (Android Q)
|
- Compile with Android SDK 29 (Android Q)
|
||||||
|
|
||||||
Other changes:
|
Other changes:
|
||||||
|
- Add a setting to prevent screenshots of the application, disabled by default (#1027)
|
||||||
- Increase File Logger capacities ( + use dev log preferences)
|
- Increase File Logger capacities ( + use dev log preferences)
|
||||||
|
|
||||||
Changes in RiotX 0.18.1 (2020-03-17)
|
Changes in RiotX 0.18.1 (2020-03-17)
|
||||||
|
@ -31,3 +31,9 @@ fun Throwable.shouldBeRetried(): Boolean {
|
|||||||
return this is Failure.NetworkConnection
|
return this is Failure.NetworkConnection
|
||||||
|| (this is Failure.ServerError && error.code == MatrixError.M_LIMIT_EXCEEDED)
|
|| (this is Failure.ServerError && error.code == MatrixError.M_LIMIT_EXCEEDED)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun Throwable.isInvalidPassword(): Boolean {
|
||||||
|
return this is Failure.ServerError
|
||||||
|
&& error.code == MatrixError.M_FORBIDDEN
|
||||||
|
&& error.message == "Invalid password"
|
||||||
|
}
|
||||||
|
@ -21,6 +21,7 @@ import androidx.lifecycle.LiveData
|
|||||||
import im.vector.matrix.android.api.auth.data.SessionParams
|
import im.vector.matrix.android.api.auth.data.SessionParams
|
||||||
import im.vector.matrix.android.api.failure.GlobalError
|
import im.vector.matrix.android.api.failure.GlobalError
|
||||||
import im.vector.matrix.android.api.pushrules.PushRuleService
|
import im.vector.matrix.android.api.pushrules.PushRuleService
|
||||||
|
import im.vector.matrix.android.api.session.account.AccountService
|
||||||
import im.vector.matrix.android.api.session.accountdata.AccountDataService
|
import im.vector.matrix.android.api.session.accountdata.AccountDataService
|
||||||
import im.vector.matrix.android.api.session.cache.CacheService
|
import im.vector.matrix.android.api.session.cache.CacheService
|
||||||
import im.vector.matrix.android.api.session.content.ContentUploadStateTracker
|
import im.vector.matrix.android.api.session.content.ContentUploadStateTracker
|
||||||
@ -59,7 +60,8 @@ interface Session :
|
|||||||
InitialSyncProgressService,
|
InitialSyncProgressService,
|
||||||
HomeServerCapabilitiesService,
|
HomeServerCapabilitiesService,
|
||||||
SecureStorageService,
|
SecureStorageService,
|
||||||
AccountDataService {
|
AccountDataService,
|
||||||
|
AccountService {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The params associated to the session
|
* The params associated to the session
|
||||||
|
@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
* 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.api.session.account
|
||||||
|
|
||||||
|
import im.vector.matrix.android.api.MatrixCallback
|
||||||
|
import im.vector.matrix.android.api.util.Cancelable
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This interface defines methods to manage the account. It's implemented at the session level.
|
||||||
|
*/
|
||||||
|
interface AccountService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ask the homeserver to change the password.
|
||||||
|
* @param password Current password.
|
||||||
|
* @param newPassword New password
|
||||||
|
*/
|
||||||
|
fun changePassword(password: String, newPassword: String, callback: MatrixCallback<Unit>): Cancelable
|
||||||
|
}
|
@ -0,0 +1,42 @@
|
|||||||
|
/*
|
||||||
|
* 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.api.session.account.model
|
||||||
|
|
||||||
|
import com.squareup.moshi.Json
|
||||||
|
import com.squareup.moshi.JsonClass
|
||||||
|
import im.vector.matrix.android.internal.crypto.model.rest.UserPasswordAuth
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class to pass request parameters to update the password.
|
||||||
|
*/
|
||||||
|
@JsonClass(generateAdapter = true)
|
||||||
|
internal data class ChangePasswordParams(
|
||||||
|
@Json(name = "auth")
|
||||||
|
val auth: UserPasswordAuth? = null,
|
||||||
|
|
||||||
|
@Json(name = "new_password")
|
||||||
|
val newPassword: String? = null
|
||||||
|
) {
|
||||||
|
companion object {
|
||||||
|
fun create(userId: String, oldPassword: String, newPassword: String): ChangePasswordParams {
|
||||||
|
return ChangePasswordParams(
|
||||||
|
auth = UserPasswordAuth(user = userId, password = oldPassword),
|
||||||
|
newPassword = newPassword
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -17,6 +17,10 @@
|
|||||||
package im.vector.matrix.android.api.session.homeserver
|
package im.vector.matrix.android.api.session.homeserver
|
||||||
|
|
||||||
data class HomeServerCapabilities(
|
data class HomeServerCapabilities(
|
||||||
|
/**
|
||||||
|
* True if it is possible to change the password of the account.
|
||||||
|
*/
|
||||||
|
val canChangePassword: Boolean = true,
|
||||||
/**
|
/**
|
||||||
* Max size of file which can be uploaded to the homeserver in bytes. [MAX_UPLOAD_FILE_SIZE_UNKNOWN] if unknown or not retrieved yet
|
* Max size of file which can be uploaded to the homeserver in bytes. [MAX_UPLOAD_FILE_SIZE_UNKNOWN] if unknown or not retrieved yet
|
||||||
*/
|
*/
|
||||||
|
@ -24,7 +24,7 @@ data class AudioInfo(
|
|||||||
/**
|
/**
|
||||||
* The mimetype of the audio e.g. "audio/aac".
|
* The mimetype of the audio e.g. "audio/aac".
|
||||||
*/
|
*/
|
||||||
@Json(name = "mimetype") val mimeType: String,
|
@Json(name = "mimetype") val mimeType: String?,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The size of the audio clip in bytes.
|
* The size of the audio clip in bytes.
|
||||||
|
@ -39,5 +39,5 @@ data class ThumbnailInfo(
|
|||||||
/**
|
/**
|
||||||
* The mimetype of the image, e.g. "image/jpeg".
|
* The mimetype of the image, e.g. "image/jpeg".
|
||||||
*/
|
*/
|
||||||
@Json(name = "mimetype") val mimeType: String
|
@Json(name = "mimetype") val mimeType: String?
|
||||||
)
|
)
|
||||||
|
@ -21,7 +21,7 @@ import com.squareup.moshi.JsonClass
|
|||||||
import im.vector.matrix.android.internal.auth.data.LoginFlowTypes
|
import im.vector.matrix.android.internal.auth.data.LoginFlowTypes
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class provides the authentication data to delete a device
|
* This class provides the authentication data by using user and password
|
||||||
*/
|
*/
|
||||||
@JsonClass(generateAdapter = true)
|
@JsonClass(generateAdapter = true)
|
||||||
data class UserPasswordAuth(
|
data class UserPasswordAuth(
|
||||||
|
@ -177,7 +177,7 @@ internal class DefaultQrCodeVerificationTransaction(
|
|||||||
}.exhaustive
|
}.exhaustive
|
||||||
|
|
||||||
if (!canTrustOtherUserMasterKey && toVerifyDeviceIds.isEmpty()) {
|
if (!canTrustOtherUserMasterKey && toVerifyDeviceIds.isEmpty()) {
|
||||||
// // Nothing to verify
|
// Nothing to verify
|
||||||
cancel(CancelCode.MismatchedKeys)
|
cancel(CancelCode.MismatchedKeys)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -26,12 +26,14 @@ internal object HomeServerCapabilitiesMapper {
|
|||||||
|
|
||||||
fun map(entity: HomeServerCapabilitiesEntity): HomeServerCapabilities {
|
fun map(entity: HomeServerCapabilitiesEntity): HomeServerCapabilities {
|
||||||
return HomeServerCapabilities(
|
return HomeServerCapabilities(
|
||||||
|
canChangePassword = entity.canChangePassword,
|
||||||
maxUploadFileSize = entity.maxUploadFileSize
|
maxUploadFileSize = entity.maxUploadFileSize
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun map(domain: HomeServerCapabilities): HomeServerCapabilitiesEntity {
|
fun map(domain: HomeServerCapabilities): HomeServerCapabilitiesEntity {
|
||||||
return HomeServerCapabilitiesEntity(
|
return HomeServerCapabilitiesEntity(
|
||||||
|
canChangePassword = domain.canChangePassword,
|
||||||
maxUploadFileSize = domain.maxUploadFileSize
|
maxUploadFileSize = domain.maxUploadFileSize
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,7 @@ import im.vector.matrix.android.api.session.homeserver.HomeServerCapabilities
|
|||||||
import io.realm.RealmObject
|
import io.realm.RealmObject
|
||||||
|
|
||||||
internal open class HomeServerCapabilitiesEntity(
|
internal open class HomeServerCapabilitiesEntity(
|
||||||
|
var canChangePassword: Boolean = true,
|
||||||
var maxUploadFileSize: Long = HomeServerCapabilities.MAX_UPLOAD_FILE_SIZE_UNKNOWN,
|
var maxUploadFileSize: Long = HomeServerCapabilities.MAX_UPLOAD_FILE_SIZE_UNKNOWN,
|
||||||
var lastUpdatedTimestamp: Long = 0L
|
var lastUpdatedTimestamp: Long = 0L
|
||||||
) : RealmObject() {
|
) : RealmObject() {
|
||||||
|
@ -25,6 +25,7 @@ import im.vector.matrix.android.api.failure.GlobalError
|
|||||||
import im.vector.matrix.android.api.pushrules.PushRuleService
|
import im.vector.matrix.android.api.pushrules.PushRuleService
|
||||||
import im.vector.matrix.android.api.session.InitialSyncProgressService
|
import im.vector.matrix.android.api.session.InitialSyncProgressService
|
||||||
import im.vector.matrix.android.api.session.Session
|
import im.vector.matrix.android.api.session.Session
|
||||||
|
import im.vector.matrix.android.api.session.account.AccountService
|
||||||
import im.vector.matrix.android.api.session.accountdata.AccountDataService
|
import im.vector.matrix.android.api.session.accountdata.AccountDataService
|
||||||
import im.vector.matrix.android.api.session.cache.CacheService
|
import im.vector.matrix.android.api.session.cache.CacheService
|
||||||
import im.vector.matrix.android.api.session.content.ContentUploadStateTracker
|
import im.vector.matrix.android.api.session.content.ContentUploadStateTracker
|
||||||
@ -94,6 +95,7 @@ internal class DefaultSession @Inject constructor(
|
|||||||
private val homeServerCapabilitiesService: Lazy<HomeServerCapabilitiesService>,
|
private val homeServerCapabilitiesService: Lazy<HomeServerCapabilitiesService>,
|
||||||
private val accountDataService: Lazy<AccountDataService>,
|
private val accountDataService: Lazy<AccountDataService>,
|
||||||
private val _sharedSecretStorageService: Lazy<SharedSecretStorageService>,
|
private val _sharedSecretStorageService: Lazy<SharedSecretStorageService>,
|
||||||
|
private val accountService: Lazy<AccountService>,
|
||||||
private val timelineEventDecryptor: TimelineEventDecryptor,
|
private val timelineEventDecryptor: TimelineEventDecryptor,
|
||||||
private val shieldTrustUpdater: ShieldTrustUpdater)
|
private val shieldTrustUpdater: ShieldTrustUpdater)
|
||||||
: Session,
|
: Session,
|
||||||
@ -110,7 +112,8 @@ internal class DefaultSession @Inject constructor(
|
|||||||
SecureStorageService by secureStorageService.get(),
|
SecureStorageService by secureStorageService.get(),
|
||||||
HomeServerCapabilitiesService by homeServerCapabilitiesService.get(),
|
HomeServerCapabilitiesService by homeServerCapabilitiesService.get(),
|
||||||
ProfileService by profileService.get(),
|
ProfileService by profileService.get(),
|
||||||
AccountDataService by accountDataService.get() {
|
AccountDataService by accountDataService.get(),
|
||||||
|
AccountService by accountService.get() {
|
||||||
|
|
||||||
override val sharedSecretStorageService: SharedSecretStorageService
|
override val sharedSecretStorageService: SharedSecretStorageService
|
||||||
get() = _sharedSecretStorageService.get()
|
get() = _sharedSecretStorageService.get()
|
||||||
|
@ -28,6 +28,7 @@ import im.vector.matrix.android.internal.crypto.verification.SendVerificationMes
|
|||||||
import im.vector.matrix.android.internal.di.MatrixComponent
|
import im.vector.matrix.android.internal.di.MatrixComponent
|
||||||
import im.vector.matrix.android.internal.di.SessionAssistedInjectModule
|
import im.vector.matrix.android.internal.di.SessionAssistedInjectModule
|
||||||
import im.vector.matrix.android.internal.network.NetworkConnectivityChecker
|
import im.vector.matrix.android.internal.network.NetworkConnectivityChecker
|
||||||
|
import im.vector.matrix.android.internal.session.account.AccountModule
|
||||||
import im.vector.matrix.android.internal.session.cache.CacheModule
|
import im.vector.matrix.android.internal.session.cache.CacheModule
|
||||||
import im.vector.matrix.android.internal.session.content.ContentModule
|
import im.vector.matrix.android.internal.session.content.ContentModule
|
||||||
import im.vector.matrix.android.internal.session.content.UploadContentWorker
|
import im.vector.matrix.android.internal.session.content.UploadContentWorker
|
||||||
@ -55,24 +56,25 @@ import im.vector.matrix.android.internal.task.TaskExecutor
|
|||||||
import im.vector.matrix.android.internal.util.MatrixCoroutineDispatchers
|
import im.vector.matrix.android.internal.util.MatrixCoroutineDispatchers
|
||||||
|
|
||||||
@Component(dependencies = [MatrixComponent::class],
|
@Component(dependencies = [MatrixComponent::class],
|
||||||
modules = [
|
modules = [
|
||||||
SessionModule::class,
|
SessionModule::class,
|
||||||
RoomModule::class,
|
RoomModule::class,
|
||||||
SyncModule::class,
|
SyncModule::class,
|
||||||
HomeServerCapabilitiesModule::class,
|
HomeServerCapabilitiesModule::class,
|
||||||
SignOutModule::class,
|
SignOutModule::class,
|
||||||
GroupModule::class,
|
GroupModule::class,
|
||||||
UserModule::class,
|
UserModule::class,
|
||||||
FilterModule::class,
|
FilterModule::class,
|
||||||
GroupModule::class,
|
GroupModule::class,
|
||||||
ContentModule::class,
|
ContentModule::class,
|
||||||
CacheModule::class,
|
CacheModule::class,
|
||||||
CryptoModule::class,
|
CryptoModule::class,
|
||||||
PushersModule::class,
|
PushersModule::class,
|
||||||
AccountDataModule::class,
|
AccountDataModule::class,
|
||||||
ProfileModule::class,
|
ProfileModule::class,
|
||||||
SessionAssistedInjectModule::class
|
SessionAssistedInjectModule::class,
|
||||||
]
|
AccountModule::class
|
||||||
|
]
|
||||||
)
|
)
|
||||||
@SessionScope
|
@SessionScope
|
||||||
internal interface SessionComponent {
|
internal interface SessionComponent {
|
||||||
|
@ -0,0 +1,34 @@
|
|||||||
|
/*
|
||||||
|
* 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.account
|
||||||
|
|
||||||
|
import im.vector.matrix.android.api.session.account.model.ChangePasswordParams
|
||||||
|
import im.vector.matrix.android.internal.network.NetworkConstants
|
||||||
|
import retrofit2.Call
|
||||||
|
import retrofit2.http.Body
|
||||||
|
import retrofit2.http.Headers
|
||||||
|
import retrofit2.http.POST
|
||||||
|
|
||||||
|
internal interface AccountAPI {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ask the homeserver to change the password with the provided new password.
|
||||||
|
* @param params parameters to change password.
|
||||||
|
*/
|
||||||
|
@POST(NetworkConstants.URI_API_PREFIX_PATH_R0 + "account/password")
|
||||||
|
fun changePassword(@Body params: ChangePasswordParams): Call<Unit>
|
||||||
|
}
|
@ -0,0 +1,44 @@
|
|||||||
|
/*
|
||||||
|
* 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.account
|
||||||
|
|
||||||
|
import dagger.Binds
|
||||||
|
import dagger.Module
|
||||||
|
import dagger.Provides
|
||||||
|
import im.vector.matrix.android.api.session.account.AccountService
|
||||||
|
import im.vector.matrix.android.internal.session.SessionScope
|
||||||
|
import retrofit2.Retrofit
|
||||||
|
|
||||||
|
@Module
|
||||||
|
internal abstract class AccountModule {
|
||||||
|
|
||||||
|
@Module
|
||||||
|
companion object {
|
||||||
|
@Provides
|
||||||
|
@JvmStatic
|
||||||
|
@SessionScope
|
||||||
|
fun providesAccountAPI(retrofit: Retrofit): AccountAPI {
|
||||||
|
return retrofit.create(AccountAPI::class.java)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Binds
|
||||||
|
abstract fun bindChangePasswordTask(task: DefaultChangePasswordTask): ChangePasswordTask
|
||||||
|
|
||||||
|
@Binds
|
||||||
|
abstract fun bindAccountService(service: DefaultAccountService): AccountService
|
||||||
|
}
|
@ -0,0 +1,76 @@
|
|||||||
|
/*
|
||||||
|
* 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.account
|
||||||
|
|
||||||
|
import im.vector.matrix.android.api.failure.Failure
|
||||||
|
import im.vector.matrix.android.api.session.account.model.ChangePasswordParams
|
||||||
|
import im.vector.matrix.android.internal.auth.registration.RegistrationFlowResponse
|
||||||
|
import im.vector.matrix.android.internal.di.MoshiProvider
|
||||||
|
import im.vector.matrix.android.internal.di.UserId
|
||||||
|
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 ChangePasswordTask : Task<ChangePasswordTask.Params, Unit> {
|
||||||
|
data class Params(
|
||||||
|
val password: String,
|
||||||
|
val newPassword: String
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class DefaultChangePasswordTask @Inject constructor(
|
||||||
|
private val accountAPI: AccountAPI,
|
||||||
|
private val eventBus: EventBus,
|
||||||
|
@UserId private val userId: String
|
||||||
|
) : ChangePasswordTask {
|
||||||
|
|
||||||
|
override suspend fun execute(params: ChangePasswordTask.Params) {
|
||||||
|
val changePasswordParams = ChangePasswordParams.create(userId, params.password, params.newPassword)
|
||||||
|
try {
|
||||||
|
executeRequest<Unit>(eventBus) {
|
||||||
|
apiCall = accountAPI.changePassword(changePasswordParams)
|
||||||
|
}
|
||||||
|
} catch (throwable: Throwable) {
|
||||||
|
if (throwable is Failure.OtherServerError
|
||||||
|
&& throwable.httpCode == 401
|
||||||
|
/* Avoid infinite loop */
|
||||||
|
&& changePasswordParams.auth?.session == null) {
|
||||||
|
try {
|
||||||
|
MoshiProvider.providesMoshi()
|
||||||
|
.adapter(RegistrationFlowResponse::class.java)
|
||||||
|
.fromJson(throwable.errorBody)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
null
|
||||||
|
}?.let {
|
||||||
|
// Retry with authentication
|
||||||
|
try {
|
||||||
|
executeRequest<Unit>(eventBus) {
|
||||||
|
apiCall = accountAPI.changePassword(
|
||||||
|
changePasswordParams.copy(auth = changePasswordParams.auth?.copy(session = it.session))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
} catch (failure: Throwable) {
|
||||||
|
throw failure
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw throwable
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,36 @@
|
|||||||
|
/*
|
||||||
|
* 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.account
|
||||||
|
|
||||||
|
import im.vector.matrix.android.api.MatrixCallback
|
||||||
|
import im.vector.matrix.android.api.session.account.AccountService
|
||||||
|
import im.vector.matrix.android.api.util.Cancelable
|
||||||
|
import im.vector.matrix.android.internal.task.TaskExecutor
|
||||||
|
import im.vector.matrix.android.internal.task.configureWith
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
internal class DefaultAccountService @Inject constructor(private val changePasswordTask: ChangePasswordTask,
|
||||||
|
private val taskExecutor: TaskExecutor) : AccountService {
|
||||||
|
|
||||||
|
override fun changePassword(password: String, newPassword: String, callback: MatrixCallback<Unit>): Cancelable {
|
||||||
|
return changePasswordTask
|
||||||
|
.configureWith(ChangePasswordTask.Params(password, newPassword)) {
|
||||||
|
this.callback = callback
|
||||||
|
}
|
||||||
|
.executeBy(taskExecutor)
|
||||||
|
}
|
||||||
|
}
|
@ -22,6 +22,12 @@ import retrofit2.http.GET
|
|||||||
|
|
||||||
internal interface CapabilitiesAPI {
|
internal interface CapabilitiesAPI {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Request the homeserver capabilities
|
||||||
|
*/
|
||||||
|
@GET(NetworkConstants.URI_API_PREFIX_PATH_R0 + "capabilities")
|
||||||
|
fun getCapabilities(): Call<GetCapabilitiesResult>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Request the upload capabilities
|
* Request the upload capabilities
|
||||||
*/
|
*/
|
||||||
|
@ -51,15 +51,23 @@ internal class DefaultGetHomeServerCapabilitiesTask @Inject constructor(
|
|||||||
apiCall = capabilitiesAPI.getUploadCapabilities()
|
apiCall = capabilitiesAPI.getUploadCapabilities()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val capabilities = runCatching {
|
||||||
|
executeRequest<GetCapabilitiesResult>(eventBus) {
|
||||||
|
apiCall = capabilitiesAPI.getCapabilities()
|
||||||
|
}
|
||||||
|
}.getOrNull()
|
||||||
|
|
||||||
// TODO Add other call here (get version, etc.)
|
// TODO Add other call here (get version, etc.)
|
||||||
|
|
||||||
insertInDb(uploadCapabilities)
|
insertInDb(capabilities, uploadCapabilities)
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun insertInDb(getUploadCapabilitiesResult: GetUploadCapabilitiesResult) {
|
private suspend fun insertInDb(getCapabilitiesResult: GetCapabilitiesResult?, getUploadCapabilitiesResult: GetUploadCapabilitiesResult) {
|
||||||
monarchy.awaitTransaction { realm ->
|
monarchy.awaitTransaction { realm ->
|
||||||
val homeServerCapabilitiesEntity = HomeServerCapabilitiesEntity.getOrCreate(realm)
|
val homeServerCapabilitiesEntity = HomeServerCapabilitiesEntity.getOrCreate(realm)
|
||||||
|
|
||||||
|
homeServerCapabilitiesEntity.canChangePassword = getCapabilitiesResult.canChangePassword()
|
||||||
|
|
||||||
homeServerCapabilitiesEntity.maxUploadFileSize = getUploadCapabilitiesResult.maxUploadSize
|
homeServerCapabilitiesEntity.maxUploadFileSize = getUploadCapabilitiesResult.maxUploadSize
|
||||||
?: HomeServerCapabilities.MAX_UPLOAD_FILE_SIZE_UNKNOWN
|
?: HomeServerCapabilities.MAX_UPLOAD_FILE_SIZE_UNKNOWN
|
||||||
|
|
||||||
|
@ -0,0 +1,58 @@
|
|||||||
|
/*
|
||||||
|
* 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.homeserver
|
||||||
|
|
||||||
|
import com.squareup.moshi.Json
|
||||||
|
import com.squareup.moshi.JsonClass
|
||||||
|
import im.vector.matrix.android.api.extensions.orTrue
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ref: https://matrix.org/docs/spec/client_server/latest#get-matrix-client-r0-capabilities
|
||||||
|
*/
|
||||||
|
@JsonClass(generateAdapter = true)
|
||||||
|
internal data class GetCapabilitiesResult(
|
||||||
|
/**
|
||||||
|
* Required. The custom capabilities the server supports, using the Java package naming convention.
|
||||||
|
*/
|
||||||
|
@Json(name = "capabilities")
|
||||||
|
val capabilities: Capabilities? = null
|
||||||
|
)
|
||||||
|
|
||||||
|
@JsonClass(generateAdapter = true)
|
||||||
|
internal data class Capabilities(
|
||||||
|
/**
|
||||||
|
* Capability to indicate if the user can change their password.
|
||||||
|
*/
|
||||||
|
@Json(name = "m.change_password")
|
||||||
|
val changePassword: ChangePassword? = null
|
||||||
|
|
||||||
|
// No need for m.room_versions for the moment
|
||||||
|
)
|
||||||
|
|
||||||
|
@JsonClass(generateAdapter = true)
|
||||||
|
internal data class ChangePassword(
|
||||||
|
/**
|
||||||
|
* Required. True if the user can change their password, false otherwise.
|
||||||
|
*/
|
||||||
|
@Json(name = "enabled")
|
||||||
|
val enabled: Boolean?
|
||||||
|
)
|
||||||
|
|
||||||
|
// The spec says: If not present, the client should assume that password changes are possible via the API
|
||||||
|
internal fun GetCapabilitiesResult?.canChangePassword(): Boolean {
|
||||||
|
return this?.capabilities?.changePassword?.enabled.orTrue()
|
||||||
|
}
|
@ -20,7 +20,7 @@ import com.squareup.moshi.Json
|
|||||||
import com.squareup.moshi.JsonClass
|
import com.squareup.moshi.JsonClass
|
||||||
|
|
||||||
@JsonClass(generateAdapter = true)
|
@JsonClass(generateAdapter = true)
|
||||||
data class GetUploadCapabilitiesResult(
|
internal data class GetUploadCapabilitiesResult(
|
||||||
/**
|
/**
|
||||||
* The maximum size an upload can be in bytes. Clients SHOULD use this as a guide when uploading content.
|
* The maximum size an upload can be in bytes. Clients SHOULD use this as a guide when uploading content.
|
||||||
* If not listed or null, the size limit should be treated as unknown.
|
* If not listed or null, the size limit should be treated as unknown.
|
||||||
|
@ -314,7 +314,7 @@ internal class LocalEchoEventFactory @Inject constructor(
|
|||||||
msgType = MessageType.MSGTYPE_AUDIO,
|
msgType = MessageType.MSGTYPE_AUDIO,
|
||||||
body = attachment.name ?: "audio",
|
body = attachment.name ?: "audio",
|
||||||
audioInfo = AudioInfo(
|
audioInfo = AudioInfo(
|
||||||
mimeType = attachment.getSafeMimeType()?.takeIf { it.isNotBlank() } ?: "audio/mpeg",
|
mimeType = attachment.getSafeMimeType()?.takeIf { it.isNotBlank() },
|
||||||
size = attachment.size
|
size = attachment.size
|
||||||
),
|
),
|
||||||
url = attachment.queryUri.toString()
|
url = attachment.queryUri.toString()
|
||||||
@ -327,8 +327,7 @@ internal class LocalEchoEventFactory @Inject constructor(
|
|||||||
msgType = MessageType.MSGTYPE_FILE,
|
msgType = MessageType.MSGTYPE_FILE,
|
||||||
body = attachment.name ?: "file",
|
body = attachment.name ?: "file",
|
||||||
info = FileInfo(
|
info = FileInfo(
|
||||||
mimeType = attachment.getSafeMimeType()?.takeIf { it.isNotBlank() }
|
mimeType = attachment.getSafeMimeType()?.takeIf { it.isNotBlank() },
|
||||||
?: "application/octet-stream",
|
|
||||||
size = attachment.size
|
size = attachment.size
|
||||||
),
|
),
|
||||||
url = attachment.queryUri.toString()
|
url = attachment.queryUri.toString()
|
||||||
|
@ -18,6 +18,7 @@ package im.vector.riotx.core.error
|
|||||||
|
|
||||||
import im.vector.matrix.android.api.failure.Failure
|
import im.vector.matrix.android.api.failure.Failure
|
||||||
import im.vector.matrix.android.api.failure.MatrixError
|
import im.vector.matrix.android.api.failure.MatrixError
|
||||||
|
import im.vector.matrix.android.api.failure.isInvalidPassword
|
||||||
import im.vector.riotx.R
|
import im.vector.riotx.R
|
||||||
import im.vector.riotx.core.resources.StringProvider
|
import im.vector.riotx.core.resources.StringProvider
|
||||||
import java.net.HttpURLConnection
|
import java.net.HttpURLConnection
|
||||||
@ -54,8 +55,7 @@ class DefaultErrorFormatter @Inject constructor(
|
|||||||
// Special case for terms and conditions
|
// Special case for terms and conditions
|
||||||
stringProvider.getString(R.string.error_terms_not_accepted)
|
stringProvider.getString(R.string.error_terms_not_accepted)
|
||||||
}
|
}
|
||||||
throwable.error.code == MatrixError.M_FORBIDDEN
|
throwable.isInvalidPassword() -> {
|
||||||
&& throwable.error.message == "Invalid password" -> {
|
|
||||||
stringProvider.getString(R.string.auth_invalid_login_param)
|
stringProvider.getString(R.string.auth_invalid_login_param)
|
||||||
}
|
}
|
||||||
throwable.error.code == MatrixError.M_USER_IN_USE -> {
|
throwable.error.code == MatrixError.M_USER_IN_USE -> {
|
||||||
@ -67,7 +67,7 @@ class DefaultErrorFormatter @Inject constructor(
|
|||||||
throwable.error.code == MatrixError.M_NOT_JSON -> {
|
throwable.error.code == MatrixError.M_NOT_JSON -> {
|
||||||
stringProvider.getString(R.string.login_error_not_json)
|
stringProvider.getString(R.string.login_error_not_json)
|
||||||
}
|
}
|
||||||
throwable.error.code == MatrixError.M_THREEPID_DENIED -> {
|
throwable.error.code == MatrixError.M_THREEPID_DENIED -> {
|
||||||
stringProvider.getString(R.string.login_error_threepid_denied)
|
stringProvider.getString(R.string.login_error_threepid_denied)
|
||||||
}
|
}
|
||||||
throwable.error.code == MatrixError.M_LIMIT_EXCEEDED -> {
|
throwable.error.code == MatrixError.M_LIMIT_EXCEEDED -> {
|
||||||
|
@ -23,6 +23,7 @@ import android.os.Parcelable
|
|||||||
import android.view.Menu
|
import android.view.Menu
|
||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
import android.view.View
|
import android.view.View
|
||||||
|
import android.view.WindowManager
|
||||||
import androidx.annotation.AttrRes
|
import androidx.annotation.AttrRes
|
||||||
import androidx.annotation.LayoutRes
|
import androidx.annotation.LayoutRes
|
||||||
import androidx.annotation.MainThread
|
import androidx.annotation.MainThread
|
||||||
@ -183,6 +184,11 @@ abstract class VectorBaseActivity : AppCompatActivity(), HasScreenInjector {
|
|||||||
handleGlobalError(it)
|
handleGlobalError(it)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set flag FLAG_SECURE
|
||||||
|
if (vectorPreferences.useFlagSecure()) {
|
||||||
|
window.addFlags(WindowManager.LayoutParams.FLAG_SECURE)
|
||||||
|
}
|
||||||
|
|
||||||
doBeforeSetContentView()
|
doBeforeSetContentView()
|
||||||
|
|
||||||
if (getLayoutRes() != -1) {
|
if (getLayoutRes() != -1) {
|
||||||
|
@ -28,6 +28,7 @@ import com.airbnb.mvrx.Success
|
|||||||
import com.jakewharton.rxbinding3.widget.textChanges
|
import com.jakewharton.rxbinding3.widget.textChanges
|
||||||
import im.vector.matrix.android.api.failure.Failure
|
import im.vector.matrix.android.api.failure.Failure
|
||||||
import im.vector.matrix.android.api.failure.MatrixError
|
import im.vector.matrix.android.api.failure.MatrixError
|
||||||
|
import im.vector.matrix.android.api.failure.isInvalidPassword
|
||||||
import im.vector.riotx.R
|
import im.vector.riotx.R
|
||||||
import im.vector.riotx.core.extensions.hideKeyboard
|
import im.vector.riotx.core.extensions.hideKeyboard
|
||||||
import im.vector.riotx.core.extensions.showPassword
|
import im.vector.riotx.core.extensions.showPassword
|
||||||
@ -209,10 +210,7 @@ class LoginFragment @Inject constructor() : AbstractLoginFragment() {
|
|||||||
} else {
|
} else {
|
||||||
// Trick to display the error without text.
|
// Trick to display the error without text.
|
||||||
loginFieldTil.error = " "
|
loginFieldTil.error = " "
|
||||||
if (error is Failure.ServerError
|
if (error.isInvalidPassword() && spaceInPassword()) {
|
||||||
&& error.error.code == MatrixError.M_FORBIDDEN
|
|
||||||
&& error.error.message == "Invalid password"
|
|
||||||
&& spaceInPassword()) {
|
|
||||||
passwordFieldTil.error = getString(R.string.auth_invalid_login_param_space_in_password)
|
passwordFieldTil.error = getString(R.string.auth_invalid_login_param_space_in_password)
|
||||||
} else {
|
} else {
|
||||||
passwordFieldTil.error = errorFormatter.toHumanReadable(error)
|
passwordFieldTil.error = errorFormatter.toHumanReadable(error)
|
||||||
|
@ -150,6 +150,9 @@ class VectorPreferences @Inject constructor(private val context: Context) {
|
|||||||
const val SETTINGS_USE_RAGE_SHAKE_KEY = "SETTINGS_USE_RAGE_SHAKE_KEY"
|
const val SETTINGS_USE_RAGE_SHAKE_KEY = "SETTINGS_USE_RAGE_SHAKE_KEY"
|
||||||
const val SETTINGS_RAGE_SHAKE_DETECTION_THRESHOLD_KEY = "SETTINGS_RAGE_SHAKE_DETECTION_THRESHOLD_KEY"
|
const val SETTINGS_RAGE_SHAKE_DETECTION_THRESHOLD_KEY = "SETTINGS_RAGE_SHAKE_DETECTION_THRESHOLD_KEY"
|
||||||
|
|
||||||
|
// Security
|
||||||
|
const val SETTINGS_SECURITY_USE_FLAG_SECURE = "SETTINGS_SECURITY_USE_FLAG_SECURE"
|
||||||
|
|
||||||
// other
|
// other
|
||||||
const val SETTINGS_MEDIA_SAVING_PERIOD_KEY = "SETTINGS_MEDIA_SAVING_PERIOD_KEY"
|
const val SETTINGS_MEDIA_SAVING_PERIOD_KEY = "SETTINGS_MEDIA_SAVING_PERIOD_KEY"
|
||||||
private const val SETTINGS_MEDIA_SAVING_PERIOD_SELECTED_KEY = "SETTINGS_MEDIA_SAVING_PERIOD_SELECTED_KEY"
|
private const val SETTINGS_MEDIA_SAVING_PERIOD_SELECTED_KEY = "SETTINGS_MEDIA_SAVING_PERIOD_SELECTED_KEY"
|
||||||
@ -199,7 +202,8 @@ class VectorPreferences @Inject constructor(private val context: Context) {
|
|||||||
SETTINGS_SET_SYNC_TIMEOUT_PREFERENCE_KEY,
|
SETTINGS_SET_SYNC_TIMEOUT_PREFERENCE_KEY,
|
||||||
SETTINGS_SET_SYNC_DELAY_PREFERENCE_KEY,
|
SETTINGS_SET_SYNC_DELAY_PREFERENCE_KEY,
|
||||||
|
|
||||||
SETTINGS_USE_RAGE_SHAKE_KEY
|
SETTINGS_USE_RAGE_SHAKE_KEY,
|
||||||
|
SETTINGS_SECURITY_USE_FLAG_SECURE
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -746,4 +750,11 @@ class VectorPreferences @Inject constructor(private val context: Context) {
|
|||||||
fun displayAllEvents(): Boolean {
|
fun displayAllEvents(): Boolean {
|
||||||
return defaultPrefs.getBoolean(SETTINGS_DISPLAY_ALL_EVENTS_KEY, false)
|
return defaultPrefs.getBoolean(SETTINGS_DISPLAY_ALL_EVENTS_KEY, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The user does not allow screenshots of the application
|
||||||
|
*/
|
||||||
|
fun useFlagSecure(): Boolean {
|
||||||
|
return defaultPrefs.getBoolean(SETTINGS_SECURITY_USE_FLAG_SECURE, false)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -35,6 +35,8 @@ import com.bumptech.glide.Glide
|
|||||||
import com.bumptech.glide.load.engine.cache.DiskCache
|
import com.bumptech.glide.load.engine.cache.DiskCache
|
||||||
import com.google.android.material.textfield.TextInputEditText
|
import com.google.android.material.textfield.TextInputEditText
|
||||||
import com.google.android.material.textfield.TextInputLayout
|
import com.google.android.material.textfield.TextInputLayout
|
||||||
|
import im.vector.matrix.android.api.MatrixCallback
|
||||||
|
import im.vector.matrix.android.api.failure.isInvalidPassword
|
||||||
import im.vector.riotx.R
|
import im.vector.riotx.R
|
||||||
import im.vector.riotx.core.extensions.hideKeyboard
|
import im.vector.riotx.core.extensions.hideKeyboard
|
||||||
import im.vector.riotx.core.extensions.showPassword
|
import im.vector.riotx.core.extensions.showPassword
|
||||||
@ -108,10 +110,14 @@ class VectorSettingsGeneralFragment : VectorSettingsBaseFragment() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Password
|
// Password
|
||||||
mPasswordPreference.onPreferenceClickListener = Preference.OnPreferenceClickListener {
|
// Hide the preference if password can not be updated
|
||||||
notImplemented()
|
if (session.getHomeServerCapabilities().canChangePassword) {
|
||||||
// onPasswordUpdateClick()
|
mPasswordPreference.onPreferenceClickListener = Preference.OnPreferenceClickListener {
|
||||||
false
|
onPasswordUpdateClick()
|
||||||
|
false
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
mPasswordPreference.isVisible = false
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add Email
|
// Add Email
|
||||||
@ -684,21 +690,20 @@ class VectorSettingsGeneralFragment : VectorSettingsBaseFragment() {
|
|||||||
|
|
||||||
var passwordShown = false
|
var passwordShown = false
|
||||||
|
|
||||||
showPassword.setOnClickListener(object : View.OnClickListener {
|
showPassword.setOnClickListener {
|
||||||
override fun onClick(v: View?) {
|
passwordShown = !passwordShown
|
||||||
passwordShown = !passwordShown
|
|
||||||
|
|
||||||
oldPasswordText.showPassword(passwordShown)
|
oldPasswordText.showPassword(passwordShown)
|
||||||
newPasswordText.showPassword(passwordShown)
|
newPasswordText.showPassword(passwordShown)
|
||||||
confirmNewPasswordText.showPassword(passwordShown)
|
confirmNewPasswordText.showPassword(passwordShown)
|
||||||
|
|
||||||
showPassword.setImageResource(if (passwordShown) R.drawable.ic_eye_closed_black else R.drawable.ic_eye_black)
|
showPassword.setImageResource(if (passwordShown) R.drawable.ic_eye_closed_black else R.drawable.ic_eye_black)
|
||||||
}
|
}
|
||||||
})
|
|
||||||
|
|
||||||
val dialog = AlertDialog.Builder(activity)
|
val dialog = AlertDialog.Builder(activity)
|
||||||
.setView(view)
|
.setView(view)
|
||||||
.setPositiveButton(R.string.settings_change_password_submit, null)
|
.setCancelable(false)
|
||||||
|
.setPositiveButton(R.string.settings_change_password, null)
|
||||||
.setNegativeButton(R.string.cancel, null)
|
.setNegativeButton(R.string.cancel, null)
|
||||||
.setOnDismissListener {
|
.setOnDismissListener {
|
||||||
view.hideKeyboard()
|
view.hideKeyboard()
|
||||||
@ -707,12 +712,13 @@ class VectorSettingsGeneralFragment : VectorSettingsBaseFragment() {
|
|||||||
|
|
||||||
dialog.setOnShowListener {
|
dialog.setOnShowListener {
|
||||||
val updateButton = dialog.getButton(AlertDialog.BUTTON_POSITIVE)
|
val updateButton = dialog.getButton(AlertDialog.BUTTON_POSITIVE)
|
||||||
|
val cancelButton = dialog.getButton(AlertDialog.BUTTON_NEGATIVE)
|
||||||
updateButton.isEnabled = false
|
updateButton.isEnabled = false
|
||||||
|
|
||||||
fun updateUi() {
|
fun updateUi() {
|
||||||
val oldPwd = oldPasswordText.text.toString().trim()
|
val oldPwd = oldPasswordText.text.toString()
|
||||||
val newPwd = newPasswordText.text.toString().trim()
|
val newPwd = newPasswordText.text.toString()
|
||||||
val newConfirmPwd = confirmNewPasswordText.text.toString().trim()
|
val newConfirmPwd = confirmNewPasswordText.text.toString()
|
||||||
|
|
||||||
updateButton.isEnabled = oldPwd.isNotEmpty() && newPwd.isNotEmpty() && newPwd == newConfirmPwd
|
updateButton.isEnabled = oldPwd.isNotEmpty() && newPwd.isNotEmpty() && newPwd == newConfirmPwd
|
||||||
|
|
||||||
@ -750,6 +756,7 @@ class VectorSettingsGeneralFragment : VectorSettingsBaseFragment() {
|
|||||||
confirmNewPasswordText.isEnabled = false
|
confirmNewPasswordText.isEnabled = false
|
||||||
changePasswordLoader.isVisible = true
|
changePasswordLoader.isVisible = true
|
||||||
updateButton.isEnabled = false
|
updateButton.isEnabled = false
|
||||||
|
cancelButton.isEnabled = false
|
||||||
} else {
|
} else {
|
||||||
showPassword.isEnabled = true
|
showPassword.isEnabled = true
|
||||||
oldPasswordText.isEnabled = true
|
oldPasswordText.isEnabled = true
|
||||||
@ -757,6 +764,7 @@ class VectorSettingsGeneralFragment : VectorSettingsBaseFragment() {
|
|||||||
confirmNewPasswordText.isEnabled = true
|
confirmNewPasswordText.isEnabled = true
|
||||||
changePasswordLoader.isVisible = false
|
changePasswordLoader.isVisible = false
|
||||||
updateButton.isEnabled = true
|
updateButton.isEnabled = true
|
||||||
|
cancelButton.isEnabled = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -768,47 +776,32 @@ class VectorSettingsGeneralFragment : VectorSettingsBaseFragment() {
|
|||||||
|
|
||||||
view.hideKeyboard()
|
view.hideKeyboard()
|
||||||
|
|
||||||
val oldPwd = oldPasswordText.text.toString().trim()
|
val oldPwd = oldPasswordText.text.toString()
|
||||||
val newPwd = newPasswordText.text.toString().trim()
|
val newPwd = newPasswordText.text.toString()
|
||||||
|
|
||||||
notImplemented()
|
|
||||||
/* TODO
|
|
||||||
showPasswordLoadingView(true)
|
showPasswordLoadingView(true)
|
||||||
|
session.changePassword(oldPwd, newPwd, object : MatrixCallback<Unit> {
|
||||||
session.updatePassword(oldPwd, newPwd, object : MatrixCallback<Unit> {
|
override fun onSuccess(data: Unit) {
|
||||||
private fun onDone(@StringRes textResId: Int) {
|
if (!isAdded) {
|
||||||
|
return
|
||||||
|
}
|
||||||
showPasswordLoadingView(false)
|
showPasswordLoadingView(false)
|
||||||
|
dialog.dismiss()
|
||||||
|
activity.toast(R.string.settings_password_updated)
|
||||||
|
}
|
||||||
|
|
||||||
if (textResId == R.string.settings_fail_to_update_password_invalid_current_password) {
|
override fun onFailure(failure: Throwable) {
|
||||||
oldPasswordTil.error = getString(textResId)
|
if (!isAdded) {
|
||||||
} else {
|
return
|
||||||
dialog.dismiss()
|
|
||||||
activity.toast(textResId, Toast.LENGTH_LONG)
|
|
||||||
}
|
}
|
||||||
}
|
showPasswordLoadingView(false)
|
||||||
|
if (failure.isInvalidPassword()) {
|
||||||
override fun onSuccess(info: Void?) {
|
oldPasswordTil.error = getString(R.string.settings_fail_to_update_password_invalid_current_password)
|
||||||
onDone(R.string.settings_password_updated)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onNetworkError(e: Exception) {
|
|
||||||
onDone(R.string.settings_fail_to_update_password)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onMatrixError(e: MatrixError) {
|
|
||||||
if (e.error == "Invalid password") {
|
|
||||||
onDone(R.string.settings_fail_to_update_password_invalid_current_password)
|
|
||||||
} else {
|
} else {
|
||||||
dialog.dismiss()
|
oldPasswordTil.error = getString(R.string.settings_fail_to_update_password)
|
||||||
onDone(R.string.settings_fail_to_update_password)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onUnexpectedError(e: Exception) {
|
|
||||||
onDone(R.string.settings_fail_to_update_password)
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
dialog.show()
|
dialog.show()
|
||||||
|
@ -39,7 +39,8 @@
|
|||||||
android:id="@+id/change_password_old_pwd_til"
|
android:id="@+id/change_password_old_pwd_til"
|
||||||
style="@style/VectorTextInputLayout"
|
style="@style/VectorTextInputLayout"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content">
|
android:layout_height="wrap_content"
|
||||||
|
app:errorEnabled="true">
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputEditText
|
<com.google.android.material.textfield.TextInputEditText
|
||||||
android:id="@+id/change_password_old_pwd_text"
|
android:id="@+id/change_password_old_pwd_text"
|
||||||
@ -53,7 +54,9 @@
|
|||||||
<com.google.android.material.textfield.TextInputLayout
|
<com.google.android.material.textfield.TextInputLayout
|
||||||
style="@style/VectorTextInputLayout"
|
style="@style/VectorTextInputLayout"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content">
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
app:errorEnabled="true">
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputEditText
|
<com.google.android.material.textfield.TextInputEditText
|
||||||
android:id="@+id/change_password_new_pwd_text"
|
android:id="@+id/change_password_new_pwd_text"
|
||||||
@ -69,6 +72,7 @@
|
|||||||
style="@style/VectorTextInputLayout"
|
style="@style/VectorTextInputLayout"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
app:errorEnabled="true">
|
app:errorEnabled="true">
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputEditText
|
<com.google.android.material.textfield.TextInputEditText
|
||||||
|
@ -14,6 +14,12 @@
|
|||||||
|
|
||||||
<!-- END Strings added by Benoit -->
|
<!-- END Strings added by Benoit -->
|
||||||
|
|
||||||
|
<!-- BEGIN Strings added by Benoit2 -->
|
||||||
|
<string name="settings_security_prevent_screenshots_title">Prevent screenshots of the application</string>
|
||||||
|
<string name="settings_security_prevent_screenshots_summary">Enabling this setting adds the FLAG_SECURE to all Activities. Restart the application for the change to take effect.</string>
|
||||||
|
|
||||||
|
<!-- END Strings added by Benoit2 -->
|
||||||
|
|
||||||
|
|
||||||
<!-- BEGIN Strings added by Ganfra -->
|
<!-- BEGIN Strings added by Ganfra -->
|
||||||
|
|
||||||
@ -29,4 +35,7 @@
|
|||||||
|
|
||||||
<!-- END Strings added by Others -->
|
<!-- END Strings added by Others -->
|
||||||
|
|
||||||
|
<!-- BEGIN Strings added by Benoit -->
|
||||||
|
<string name="change_password_summary">Set a new account password…</string>
|
||||||
|
<!---->
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
|
|
||||||
<im.vector.riotx.core.preference.VectorPreference
|
<im.vector.riotx.core.preference.VectorPreference
|
||||||
android:key="SETTINGS_CHANGE_PASSWORD_PREFERENCE_KEY"
|
android:key="SETTINGS_CHANGE_PASSWORD_PREFERENCE_KEY"
|
||||||
android:summary="@string/password_hint"
|
android:summary="@string/change_password_summary"
|
||||||
android:title="@string/settings_password" />
|
android:title="@string/settings_password" />
|
||||||
|
|
||||||
<!-- Email will be added here -->
|
<!-- Email will be added here -->
|
||||||
|
@ -6,36 +6,35 @@
|
|||||||
<!-- ************ Cryptography section ************ -->
|
<!-- ************ Cryptography section ************ -->
|
||||||
<im.vector.riotx.core.preference.VectorPreferenceCategory
|
<im.vector.riotx.core.preference.VectorPreferenceCategory
|
||||||
android:key="SETTINGS_CRYPTOGRAPHY_PREFERENCE_KEY"
|
android:key="SETTINGS_CRYPTOGRAPHY_PREFERENCE_KEY"
|
||||||
tools:isPreferenceVisible="true"
|
android:title="@string/settings_cryptography"
|
||||||
app:isPreferenceVisible="false"
|
app:isPreferenceVisible="false"
|
||||||
android:title="@string/settings_cryptography">
|
tools:isPreferenceVisible="true">
|
||||||
<im.vector.riotx.core.preference.VectorPreference
|
<im.vector.riotx.core.preference.VectorPreference
|
||||||
android:key="SETTINGS_ENCRYPTION_CROSS_SIGNING_PREFERENCE_KEY"
|
android:key="SETTINGS_ENCRYPTION_CROSS_SIGNING_PREFERENCE_KEY"
|
||||||
tools:icon="@drawable/ic_shield_trusted"
|
|
||||||
android:persistent="false"
|
android:persistent="false"
|
||||||
android:title="@string/encryption_information_cross_signing_state"
|
android:title="@string/encryption_information_cross_signing_state"
|
||||||
tools:summary="@string/encryption_information_dg_xsigning_complete"
|
|
||||||
app:fragment="im.vector.riotx.features.settings.crosssigning.CrossSigningSettingsFragment"
|
app:fragment="im.vector.riotx.features.settings.crosssigning.CrossSigningSettingsFragment"
|
||||||
/>
|
tools:icon="@drawable/ic_shield_trusted"
|
||||||
|
tools:summary="@string/encryption_information_dg_xsigning_complete" />
|
||||||
|
|
||||||
|
|
||||||
<!-- <im.vector.riotx.core.preference.VectorPreference-->
|
<!-- <im.vector.riotx.core.preference.VectorPreference-->
|
||||||
<!-- android:key="SETTINGS_ENCRYPTION_INFORMATION_DEVICE_NAME_PREFERENCE_KEY"-->
|
<!-- android:key="SETTINGS_ENCRYPTION_INFORMATION_DEVICE_NAME_PREFERENCE_KEY"-->
|
||||||
<!-- android:title="@string/encryption_information_device_name" />-->
|
<!-- android:title="@string/encryption_information_device_name" />-->
|
||||||
|
|
||||||
<!-- <im.vector.riotx.core.preference.VectorPreference-->
|
<!-- <im.vector.riotx.core.preference.VectorPreference-->
|
||||||
<!-- android:key="SETTINGS_ENCRYPTION_INFORMATION_DEVICE_ID_PREFERENCE_KEY"-->
|
<!-- android:key="SETTINGS_ENCRYPTION_INFORMATION_DEVICE_ID_PREFERENCE_KEY"-->
|
||||||
<!-- android:title="@string/encryption_information_device_id" />-->
|
<!-- android:title="@string/encryption_information_device_id" />-->
|
||||||
|
|
||||||
<!-- <im.vector.riotx.core.preference.VectorPreference-->
|
<!-- <im.vector.riotx.core.preference.VectorPreference-->
|
||||||
<!-- android:key="SETTINGS_ENCRYPTION_INFORMATION_DEVICE_KEY_PREFERENCE_KEY"-->
|
<!-- android:key="SETTINGS_ENCRYPTION_INFORMATION_DEVICE_KEY_PREFERENCE_KEY"-->
|
||||||
<!-- android:title="@string/encryption_information_device_key" />-->
|
<!-- android:title="@string/encryption_information_device_key" />-->
|
||||||
|
|
||||||
<im.vector.riotx.core.preference.VectorSwitchPreference
|
<im.vector.riotx.core.preference.VectorSwitchPreference
|
||||||
|
android:enabled="false"
|
||||||
android:key="SETTINGS_ENCRYPTION_NEVER_SENT_TO_PREFERENCE_KEY"
|
android:key="SETTINGS_ENCRYPTION_NEVER_SENT_TO_PREFERENCE_KEY"
|
||||||
android:summary="@string/encryption_never_send_to_unverified_devices_summary"
|
android:summary="@string/encryption_never_send_to_unverified_devices_summary"
|
||||||
android:title="@string/encryption_never_send_to_unverified_devices_title"
|
android:title="@string/encryption_never_send_to_unverified_devices_title" />
|
||||||
android:enabled="false" />
|
|
||||||
|
|
||||||
</im.vector.riotx.core.preference.VectorPreferenceCategory>
|
</im.vector.riotx.core.preference.VectorPreferenceCategory>
|
||||||
|
|
||||||
@ -85,4 +84,15 @@
|
|||||||
|
|
||||||
</im.vector.riotx.core.preference.VectorPreferenceCategory>
|
</im.vector.riotx.core.preference.VectorPreferenceCategory>
|
||||||
|
|
||||||
|
<im.vector.riotx.core.preference.VectorPreferenceCategory
|
||||||
|
android:title="@string/settings_other">
|
||||||
|
|
||||||
|
<im.vector.riotx.core.preference.VectorSwitchPreference
|
||||||
|
android:defaultValue="false"
|
||||||
|
android:key="SETTINGS_SECURITY_USE_FLAG_SECURE"
|
||||||
|
android:summary="@string/settings_security_prevent_screenshots_summary"
|
||||||
|
android:title="@string/settings_security_prevent_screenshots_title" />
|
||||||
|
|
||||||
|
</im.vector.riotx.core.preference.VectorPreferenceCategory>
|
||||||
|
|
||||||
</androidx.preference.PreferenceScreen>
|
</androidx.preference.PreferenceScreen>
|
Loading…
Reference in New Issue
Block a user