Update Self Verification BottomSheet for quads
This commit is contained in:
parent
cb73955946
commit
3dc89c8d87
|
@ -53,6 +53,8 @@ interface CrossSigningService {
|
||||||
fun trustUser(otherUserId: String,
|
fun trustUser(otherUserId: String,
|
||||||
callback: MatrixCallback<Unit>)
|
callback: MatrixCallback<Unit>)
|
||||||
|
|
||||||
|
fun markMyMasterKeyAsTrusted()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sign one of your devices and upload the signature
|
* Sign one of your devices and upload the signature
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -374,7 +374,9 @@ internal class DefaultCrossSigningService @Inject constructor(
|
||||||
?.fromBase64NoPadding()
|
?.fromBase64NoPadding()
|
||||||
|
|
||||||
var isMaterKeyTrusted = false
|
var isMaterKeyTrusted = false
|
||||||
if (masterPrivateKey != null) {
|
if (myMasterKey.trustLevel?.locallyVerified == true) {
|
||||||
|
isMaterKeyTrusted = true
|
||||||
|
} else if (masterPrivateKey != null) {
|
||||||
// Check if private match public
|
// Check if private match public
|
||||||
var olmPkSigning: OlmPkSigning? = null
|
var olmPkSigning: OlmPkSigning? = null
|
||||||
try {
|
try {
|
||||||
|
@ -507,6 +509,11 @@ internal class DefaultCrossSigningService @Inject constructor(
|
||||||
}.executeBy(taskExecutor)
|
}.executeBy(taskExecutor)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun markMyMasterKeyAsTrusted() {
|
||||||
|
cryptoStore.markMyMasterKeyAsLocallyTrusted(true)
|
||||||
|
checkSelfTrust()
|
||||||
|
}
|
||||||
|
|
||||||
override fun signDevice(deviceId: String, callback: MatrixCallback<Unit>) {
|
override fun signDevice(deviceId: String, callback: MatrixCallback<Unit>) {
|
||||||
// This device should be yours
|
// This device should be yours
|
||||||
val device = cryptoStore.getUserDevice(userId, deviceId)
|
val device = cryptoStore.getUserDevice(userId, deviceId)
|
||||||
|
|
|
@ -413,6 +413,8 @@ internal interface IMXCryptoStore {
|
||||||
fun getLiveCrossSigningInfo(userId: String) : LiveData<Optional<MXCrossSigningInfo>>
|
fun getLiveCrossSigningInfo(userId: String) : LiveData<Optional<MXCrossSigningInfo>>
|
||||||
fun setCrossSigningInfo(userId: String, info: MXCrossSigningInfo?)
|
fun setCrossSigningInfo(userId: String, info: MXCrossSigningInfo?)
|
||||||
|
|
||||||
|
fun markMyMasterKeyAsLocallyTrusted(trusted: Boolean)
|
||||||
|
|
||||||
fun storePrivateKeysInfo(msk: String?, usk: String?, ssk: String?)
|
fun storePrivateKeysInfo(msk: String?, usk: String?, ssk: String?)
|
||||||
fun getCrossSigningPrivateKeys() : PrivateKeysInfo?
|
fun getCrossSigningPrivateKeys() : PrivateKeysInfo?
|
||||||
|
|
||||||
|
|
|
@ -1094,6 +1094,24 @@ internal class RealmCryptoStore @Inject constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun markMyMasterKeyAsLocallyTrusted(trusted: Boolean) {
|
||||||
|
doRealmTransaction(realmConfiguration) { realm ->
|
||||||
|
realm.where<CryptoMetadataEntity>().findFirst()?.userId?.let { myUserId ->
|
||||||
|
CrossSigningInfoEntity.get(realm, myUserId)?.getMasterKey()?.let { xInfoEntity ->
|
||||||
|
val level = xInfoEntity.trustLevelEntity
|
||||||
|
if (level == null) {
|
||||||
|
val newLevel = realm.createObject(TrustLevelEntity::class.java)
|
||||||
|
newLevel.locallyVerified = trusted
|
||||||
|
xInfoEntity.trustLevelEntity = newLevel
|
||||||
|
} else {
|
||||||
|
level.locallyVerified = trusted
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun addOrUpdateCrossSigningInfo(realm: Realm, userId: String, info: MXCrossSigningInfo?): CrossSigningInfoEntity? {
|
private fun addOrUpdateCrossSigningInfo(realm: Realm, userId: String, info: MXCrossSigningInfo?): CrossSigningInfoEntity? {
|
||||||
var existing = CrossSigningInfoEntity.get(realm, userId)
|
var existing = CrossSigningInfoEntity.get(realm, userId)
|
||||||
if (info == null) {
|
if (info == null) {
|
||||||
|
|
|
@ -222,14 +222,19 @@ internal class DefaultQrCodeVerificationTransaction(
|
||||||
|
|
||||||
private fun trust(canTrustOtherUserMasterKey: Boolean, toVerifyDeviceIds: List<String>) {
|
private fun trust(canTrustOtherUserMasterKey: Boolean, toVerifyDeviceIds: List<String>) {
|
||||||
// If not me sign his MSK and upload the signature
|
// If not me sign his MSK and upload the signature
|
||||||
if (otherUserId != userId && canTrustOtherUserMasterKey) {
|
if (canTrustOtherUserMasterKey) {
|
||||||
// we should trust this master key
|
if (otherUserId != userId ) {
|
||||||
// And check verification MSK -> SSK?
|
// we should trust this master key
|
||||||
crossSigningService.trustUser(otherUserId, object : MatrixCallback<Unit> {
|
// And check verification MSK -> SSK?
|
||||||
override fun onFailure(failure: Throwable) {
|
crossSigningService.trustUser(otherUserId, object : MatrixCallback<Unit> {
|
||||||
Timber.e(failure, "## QR Verification: Failed to trust User $otherUserId")
|
override fun onFailure(failure: Throwable) {
|
||||||
}
|
Timber.e(failure, "## QR Verification: Failed to trust User $otherUserId")
|
||||||
})
|
}
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
//Mark my keys as trusted locally
|
||||||
|
crossSigningService.markMyMasterKeyAsTrusted()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (otherUserId == userId) {
|
if (otherUserId == userId) {
|
||||||
|
|
|
@ -28,4 +28,5 @@ sealed class VerificationAction : VectorViewModelAction {
|
||||||
data class SASMatchAction(val otherUserId: String, val sasTransactionId: String) : VerificationAction()
|
data class SASMatchAction(val otherUserId: String, val sasTransactionId: String) : VerificationAction()
|
||||||
data class SASDoNotMatchAction(val otherUserId: String, val sasTransactionId: String) : VerificationAction()
|
data class SASDoNotMatchAction(val otherUserId: String, val sasTransactionId: String) : VerificationAction()
|
||||||
object GotItConclusion : VerificationAction()
|
object GotItConclusion : VerificationAction()
|
||||||
|
object SkipVerification : VerificationAction()
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,7 @@ import butterknife.BindView
|
||||||
import com.airbnb.mvrx.MvRx
|
import com.airbnb.mvrx.MvRx
|
||||||
import com.airbnb.mvrx.fragmentViewModel
|
import com.airbnb.mvrx.fragmentViewModel
|
||||||
import com.airbnb.mvrx.withState
|
import com.airbnb.mvrx.withState
|
||||||
|
import im.vector.matrix.android.api.session.Session
|
||||||
import im.vector.matrix.android.api.session.crypto.sas.VerificationTxState
|
import im.vector.matrix.android.api.session.crypto.sas.VerificationTxState
|
||||||
import im.vector.riotx.R
|
import im.vector.riotx.R
|
||||||
import im.vector.riotx.core.di.ScreenComponent
|
import im.vector.riotx.core.di.ScreenComponent
|
||||||
|
@ -54,8 +55,8 @@ class VerificationBottomSheet : VectorBaseBottomSheetDialogFragment() {
|
||||||
val otherUserId: String,
|
val otherUserId: String,
|
||||||
val verificationId: String? = null,
|
val verificationId: String? = null,
|
||||||
val roomId: String? = null,
|
val roomId: String? = null,
|
||||||
// Special mode where UX should show loading wheel until other user sends a request/tx
|
// Special mode where UX should show loading wheel until other session sends a request/tx
|
||||||
val waitForIncomingRequest: Boolean = false
|
val selfVerificationMode: Boolean = false
|
||||||
) : Parcelable
|
) : Parcelable
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
|
@ -183,7 +184,7 @@ class VerificationBottomSheet : VectorBaseBottomSheetDialogFragment() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// If it's an outgoing
|
// If it's an outgoing
|
||||||
if (state.pendingRequest.invoke() == null || state.pendingRequest.invoke()?.isIncoming == false || state.waitForOtherUserMode) {
|
if (state.pendingRequest.invoke() == null || state.pendingRequest.invoke()?.isIncoming == false || state.selfVerificationMode) {
|
||||||
Timber.v("## SAS show bottom sheet for outgoing request")
|
Timber.v("## SAS show bottom sheet for outgoing request")
|
||||||
if (state.pendingRequest.invoke()?.isReady == true) {
|
if (state.pendingRequest.invoke()?.isReady == true) {
|
||||||
Timber.v("## SAS show bottom sheet for outgoing and ready request")
|
Timber.v("## SAS show bottom sheet for outgoing and ready request")
|
||||||
|
@ -230,14 +231,25 @@ class VerificationBottomSheet : VectorBaseBottomSheetDialogFragment() {
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun withArgs(roomId: String?, otherUserId: String, transactionId: String? = null, waitForIncomingRequest: Boolean = false): VerificationBottomSheet {
|
fun withArgs(roomId: String?, otherUserId: String, transactionId: String? = null): VerificationBottomSheet {
|
||||||
return VerificationBottomSheet().apply {
|
return VerificationBottomSheet().apply {
|
||||||
arguments = Bundle().apply {
|
arguments = Bundle().apply {
|
||||||
putParcelable(MvRx.KEY_ARG, VerificationArgs(
|
putParcelable(MvRx.KEY_ARG, VerificationArgs(
|
||||||
otherUserId = otherUserId,
|
otherUserId = otherUserId,
|
||||||
roomId = roomId,
|
roomId = roomId,
|
||||||
verificationId = transactionId,
|
verificationId = transactionId,
|
||||||
waitForIncomingRequest = waitForIncomingRequest
|
selfVerificationMode = false
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun forSelfVerification(session: Session) : VerificationBottomSheet{
|
||||||
|
return VerificationBottomSheet().apply {
|
||||||
|
arguments = Bundle().apply {
|
||||||
|
putParcelable(MvRx.KEY_ARG, VerificationArgs(
|
||||||
|
otherUserId = session.myUserId,
|
||||||
|
selfVerificationMode = true
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,7 +52,7 @@ data class VerificationBottomSheetViewState(
|
||||||
val qrTransactionState: VerificationTxState? = null,
|
val qrTransactionState: VerificationTxState? = null,
|
||||||
val transactionId: String? = null,
|
val transactionId: String? = null,
|
||||||
// true when we display the loading and we wait for the other (incoming request)
|
// true when we display the loading and we wait for the other (incoming request)
|
||||||
val waitForOtherUserMode: Boolean = false,
|
val selfVerificationMode: Boolean = false,
|
||||||
val isMe: Boolean = false
|
val isMe: Boolean = false
|
||||||
) : MvRxState
|
) : MvRxState
|
||||||
|
|
||||||
|
@ -67,10 +67,10 @@ class VerificationBottomSheetViewModel @AssistedInject constructor(@Assisted ini
|
||||||
|
|
||||||
val userItem = session.getUser(args.otherUserId)
|
val userItem = session.getUser(args.otherUserId)
|
||||||
|
|
||||||
val isWaitingForOtherMode = args.waitForIncomingRequest
|
val selfVerificationMode = args.selfVerificationMode
|
||||||
|
|
||||||
var autoReady = false
|
var autoReady = false
|
||||||
val pr = if (isWaitingForOtherMode) {
|
val pr = if (selfVerificationMode) {
|
||||||
// See if active tx for this user and take it
|
// See if active tx for this user and take it
|
||||||
|
|
||||||
session.cryptoService().verificationService().getExistingVerificationRequest(args.otherUserId)
|
session.cryptoService().verificationService().getExistingVerificationRequest(args.otherUserId)
|
||||||
|
@ -100,7 +100,7 @@ class VerificationBottomSheetViewModel @AssistedInject constructor(@Assisted ini
|
||||||
qrTransactionState = qrTx?.state,
|
qrTransactionState = qrTx?.state,
|
||||||
transactionId = pr?.transactionId ?: args.verificationId,
|
transactionId = pr?.transactionId ?: args.verificationId,
|
||||||
pendingRequest = if (pr != null) Success(pr) else Uninitialized,
|
pendingRequest = if (pr != null) Success(pr) else Uninitialized,
|
||||||
waitForOtherUserMode = isWaitingForOtherMode,
|
selfVerificationMode = selfVerificationMode,
|
||||||
roomId = args.roomId,
|
roomId = args.roomId,
|
||||||
isMe = args.otherUserId == session.myUserId
|
isMe = args.otherUserId == session.myUserId
|
||||||
)
|
)
|
||||||
|
@ -250,6 +250,9 @@ class VerificationBottomSheetViewModel @AssistedInject constructor(@Assisted ini
|
||||||
is VerificationAction.GotItConclusion -> {
|
is VerificationAction.GotItConclusion -> {
|
||||||
_viewEvents.post(VerificationBottomSheetViewEvents.Dismiss)
|
_viewEvents.post(VerificationBottomSheetViewEvents.Dismiss)
|
||||||
}
|
}
|
||||||
|
is VerificationAction.SkipVerification -> {
|
||||||
|
_viewEvents.post(VerificationBottomSheetViewEvents.Dismiss)
|
||||||
|
}
|
||||||
}.exhaustive
|
}.exhaustive
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -258,7 +261,7 @@ class VerificationBottomSheetViewModel @AssistedInject constructor(@Assisted ini
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun transactionUpdated(tx: VerificationTransaction) = withState { state ->
|
override fun transactionUpdated(tx: VerificationTransaction) = withState { state ->
|
||||||
if (state.waitForOtherUserMode && state.transactionId == null) {
|
if (state.selfVerificationMode && state.transactionId == null) {
|
||||||
// is this an incoming with that user
|
// is this an incoming with that user
|
||||||
if (tx.isIncoming && tx.otherUserId == state.otherUserMxItem?.id) {
|
if (tx.isIncoming && tx.otherUserId == state.otherUserMxItem?.id) {
|
||||||
// Also auto accept incoming if needed!
|
// Also auto accept incoming if needed!
|
||||||
|
@ -308,7 +311,7 @@ class VerificationBottomSheetViewModel @AssistedInject constructor(@Assisted ini
|
||||||
|
|
||||||
override fun verificationRequestUpdated(pr: PendingVerificationRequest) = withState { state ->
|
override fun verificationRequestUpdated(pr: PendingVerificationRequest) = withState { state ->
|
||||||
|
|
||||||
if (state.waitForOtherUserMode && state.pendingRequest.invoke() == null && state.transactionId == null) {
|
if (state.selfVerificationMode && state.pendingRequest.invoke() == null && state.transactionId == null) {
|
||||||
// is this an incoming with that user
|
// is this an incoming with that user
|
||||||
if (pr.isIncoming && pr.otherUserId == state.otherUserMxItem?.id) {
|
if (pr.isIncoming && pr.otherUserId == state.otherUserMxItem?.id) {
|
||||||
if (!pr.isReady) {
|
if (!pr.isReady) {
|
||||||
|
|
|
@ -50,7 +50,7 @@ class VerificationRequestController @Inject constructor(
|
||||||
val state = viewState ?: return
|
val state = viewState ?: return
|
||||||
val matrixItem = viewState?.otherUserMxItem ?: return
|
val matrixItem = viewState?.otherUserMxItem ?: return
|
||||||
|
|
||||||
if (state.waitForOtherUserMode) {
|
if (state.selfVerificationMode) {
|
||||||
bottomSheetVerificationNoticeItem {
|
bottomSheetVerificationNoticeItem {
|
||||||
id("notice")
|
id("notice")
|
||||||
notice(stringProvider.getString(R.string.verification_open_other_to_verify))
|
notice(stringProvider.getString(R.string.verification_open_other_to_verify))
|
||||||
|
@ -62,8 +62,28 @@ class VerificationRequestController @Inject constructor(
|
||||||
|
|
||||||
bottomSheetVerificationWaitingItem {
|
bottomSheetVerificationWaitingItem {
|
||||||
id("waiting")
|
id("waiting")
|
||||||
title(stringProvider.getString(R.string.verification_request_waiting_for, matrixItem.getBestName()))
|
title(stringProvider.getString(R.string.verification_request_waiting, matrixItem.getBestName()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bottomSheetVerificationActionItem {
|
||||||
|
id("passphrase")
|
||||||
|
title(stringProvider.getString(R.string.verification_cannot_access_other_session))
|
||||||
|
titleColor(colorProvider.getColorFromAttribute(R.attr.riotx_text_primary))
|
||||||
|
subTitle(stringProvider.getString(R.string.verification_use_passphrase))
|
||||||
|
iconRes(R.drawable.ic_arrow_right)
|
||||||
|
iconColor(colorProvider.getColorFromAttribute(R.attr.riotx_text_primary))
|
||||||
|
listener { listener?.onClickRecoverFromPassphrase() }
|
||||||
|
}
|
||||||
|
bottomSheetVerificationActionItem {
|
||||||
|
id("skip")
|
||||||
|
title(stringProvider.getString(R.string.skip))
|
||||||
|
titleColor(colorProvider.getColor(R.color.riotx_destructive_accent))
|
||||||
|
// subTitle(stringProvider.getString(R.string.verification_use_passphrase))
|
||||||
|
iconRes(R.drawable.ic_arrow_right)
|
||||||
|
iconColor(colorProvider.getColor(R.color.riotx_destructive_accent))
|
||||||
|
listener { listener?.onClickDismiss() }
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
val styledText = matrixItem.let {
|
val styledText = matrixItem.let {
|
||||||
stringProvider.getString(R.string.verification_request_notice, it.id)
|
stringProvider.getString(R.string.verification_request_notice, it.id)
|
||||||
|
@ -112,5 +132,7 @@ class VerificationRequestController @Inject constructor(
|
||||||
|
|
||||||
interface Listener {
|
interface Listener {
|
||||||
fun onClickOnVerificationStart()
|
fun onClickOnVerificationStart()
|
||||||
|
fun onClickRecoverFromPassphrase()
|
||||||
|
fun onClickDismiss()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,4 +61,11 @@ class VerificationRequestFragment @Inject constructor(
|
||||||
viewModel.handle(VerificationAction.RequestVerificationByDM(otherUserId, state.roomId))
|
viewModel.handle(VerificationAction.RequestVerificationByDM(otherUserId, state.roomId))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onClickRecoverFromPassphrase() {
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onClickDismiss() {
|
||||||
|
viewModel.handle(VerificationAction.SkipVerification)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -145,41 +145,12 @@ class HomeActivity : VectorBaseActivity(), ToolbarConfigurable {
|
||||||
val crossSigningEnabledOnAccount = myCrossSigningKeys != null
|
val crossSigningEnabledOnAccount = myCrossSigningKeys != null
|
||||||
|
|
||||||
if (crossSigningEnabledOnAccount && myCrossSigningKeys?.isTrusted() == false) {
|
if (crossSigningEnabledOnAccount && myCrossSigningKeys?.isTrusted() == false) {
|
||||||
|
|
||||||
// We need to ask
|
// We need to ask
|
||||||
sharedActionViewModel.hasDisplayedCompleteSecurityPrompt = true
|
sharedActionViewModel.hasDisplayedCompleteSecurityPrompt = true
|
||||||
PopupAlertManager.postVectorAlert(
|
navigator.waitSessionVerification(this)
|
||||||
PopupAlertManager.VectorAlert(
|
} else {
|
||||||
uid = "completeSecurity",
|
// TODO upgrade security -> bootstrap cross signing
|
||||||
title = getString(R.string.crosssigning_verify_this_session),
|
|
||||||
description = getString(R.string.crosssigning_other_user_not_trust),
|
|
||||||
iconId = R.drawable.ic_shield_warning
|
|
||||||
).apply {
|
|
||||||
colorInt = ContextCompat.getColor(this@HomeActivity, R.color.riotx_positive_accent)
|
|
||||||
contentAction = Runnable {
|
|
||||||
Runnable {
|
|
||||||
(weakCurrentActivity?.get() as? VectorBaseActivity)?.let {
|
|
||||||
it.navigator.waitSessionVerification(it)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
dismissedAction = Runnable {
|
|
||||||
// tx.cancel()
|
|
||||||
}
|
|
||||||
addButton(
|
|
||||||
getString(R.string.later),
|
|
||||||
Runnable {
|
|
||||||
}
|
|
||||||
)
|
|
||||||
addButton(
|
|
||||||
getString(R.string.verification_profile_verify),
|
|
||||||
Runnable {
|
|
||||||
(weakCurrentActivity?.get() as? VectorBaseActivity)?.let {
|
|
||||||
it.navigator.waitSessionVerification(it)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -95,12 +95,8 @@ class DefaultNavigator @Inject constructor(
|
||||||
override fun waitSessionVerification(context: Context) {
|
override fun waitSessionVerification(context: Context) {
|
||||||
val session = sessionHolder.getSafeActiveSession() ?: return
|
val session = sessionHolder.getSafeActiveSession() ?: return
|
||||||
if (context is VectorBaseActivity) {
|
if (context is VectorBaseActivity) {
|
||||||
VerificationBottomSheet.withArgs(
|
VerificationBottomSheet.forSelfVerification(session)
|
||||||
roomId = null,
|
.show(context.supportFragmentManager, VerificationBottomSheet.WAITING_SELF_VERIF_TAG)
|
||||||
otherUserId = session.myUserId,
|
|
||||||
waitForIncomingRequest = true
|
|
||||||
|
|
||||||
).show(context.supportFragmentManager, VerificationBottomSheet.WAITING_SELF_VERIF_TAG)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -60,7 +60,7 @@
|
||||||
android:id="@+id/bottomSheetFragmentContainer"
|
android:id="@+id/bottomSheetFragmentContainer"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="16dp"
|
android:layout_marginTop="8dp"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@+id/verificationRequestAvatar" />
|
app:layout_constraintTop_toBottomOf="@+id/verificationRequestAvatar" />
|
||||||
|
|
|
@ -2140,7 +2140,6 @@ Abisua: Fitxategi hau ezabatu daiteke aplikazioa desinstalatzen bada.</string>
|
||||||
<item quantity="other">%d saio aktibo</item>
|
<item quantity="other">%d saio aktibo</item>
|
||||||
</plurals>
|
</plurals>
|
||||||
|
|
||||||
<string name="crosssigning_verify_this_session">Egiaztatu saio hau</string>
|
|
||||||
<string name="crosssigning_other_user_not_trust">Beste erabiltzaile batzuk ez fidagarritzat jo lezakete</string>
|
<string name="crosssigning_other_user_not_trust">Beste erabiltzaile batzuk ez fidagarritzat jo lezakete</string>
|
||||||
<string name="complete_security">Bete segurtasuna</string>
|
<string name="complete_security">Bete segurtasuna</string>
|
||||||
|
|
||||||
|
|
|
@ -2148,7 +2148,6 @@ Si vous n’avez pas configuré de nouvelle méthode de récupération, un attaq
|
||||||
<item quantity="other">%d sessions actives</item>
|
<item quantity="other">%d sessions actives</item>
|
||||||
</plurals>
|
</plurals>
|
||||||
|
|
||||||
<string name="crosssigning_verify_this_session">Vérifier cette session</string>
|
|
||||||
<string name="crosssigning_other_user_not_trust">Les autres utilisateurs ne lui font peut-être pas confiance</string>
|
<string name="crosssigning_other_user_not_trust">Les autres utilisateurs ne lui font peut-être pas confiance</string>
|
||||||
<string name="complete_security">Compléter la sécurité</string>
|
<string name="complete_security">Compléter la sécurité</string>
|
||||||
|
|
||||||
|
|
|
@ -2143,7 +2143,6 @@ Ha nem te állítottad be a visszaállítási metódust, akkor egy támadó pró
|
||||||
<item quantity="other">%d munkamenet használatban</item>
|
<item quantity="other">%d munkamenet használatban</item>
|
||||||
</plurals>
|
</plurals>
|
||||||
|
|
||||||
<string name="crosssigning_verify_this_session">Munkamenet ellenőrzése</string>
|
|
||||||
<string name="crosssigning_other_user_not_trust">Más felhasználók lehet, hogy nem bíznak benne</string>
|
<string name="crosssigning_other_user_not_trust">Más felhasználók lehet, hogy nem bíznak benne</string>
|
||||||
<string name="complete_security">Biztonság beállítása</string>
|
<string name="complete_security">Biztonság beállítása</string>
|
||||||
|
|
||||||
|
|
|
@ -2193,7 +2193,6 @@
|
||||||
<item quantity="other">%d sessioni attive</item>
|
<item quantity="other">%d sessioni attive</item>
|
||||||
</plurals>
|
</plurals>
|
||||||
|
|
||||||
<string name="crosssigning_verify_this_session">Verifica questa sessione</string>
|
|
||||||
<string name="crosssigning_other_user_not_trust">Gli altri utenti potrebbero non fidarsi</string>
|
<string name="crosssigning_other_user_not_trust">Gli altri utenti potrebbero non fidarsi</string>
|
||||||
<string name="complete_security">Completa la sicurezza</string>
|
<string name="complete_security">Completa la sicurezza</string>
|
||||||
|
|
||||||
|
|
|
@ -2062,7 +2062,6 @@ Që të garantoni se s’ju shpëton gjë, thjesht mbajeni të aktivizuar mekani
|
||||||
<item quantity="other">%d sesione aktive</item>
|
<item quantity="other">%d sesione aktive</item>
|
||||||
</plurals>
|
</plurals>
|
||||||
|
|
||||||
<string name="crosssigning_verify_this_session">Verifikoni këtë sesion</string>
|
|
||||||
<string name="crosssigning_other_user_not_trust">Përdorues të tjerë mund të mos e besojnë</string>
|
<string name="crosssigning_other_user_not_trust">Përdorues të tjerë mund të mos e besojnë</string>
|
||||||
<string name="complete_security">Siguri e Plotë</string>
|
<string name="complete_security">Siguri e Plotë</string>
|
||||||
|
|
||||||
|
|
|
@ -2093,7 +2093,6 @@ Matrix 中的消息可見度類似于電子郵件。我們忘記您的郵件意
|
||||||
<item quantity="other">%d 活躍的工作階段</item>
|
<item quantity="other">%d 活躍的工作階段</item>
|
||||||
</plurals>
|
</plurals>
|
||||||
|
|
||||||
<string name="crosssigning_verify_this_session">驗證此工作階段</string>
|
|
||||||
<string name="crosssigning_other_user_not_trust">其他使用者可能不會信任它</string>
|
<string name="crosssigning_other_user_not_trust">其他使用者可能不會信任它</string>
|
||||||
<string name="complete_security">全面的安全性</string>
|
<string name="complete_security">全面的安全性</string>
|
||||||
|
|
||||||
|
|
|
@ -2121,11 +2121,10 @@ Not all features in Riot are implemented in RiotX yet. Main missing (and coming
|
||||||
<item quantity="other">%d active sessions</item>
|
<item quantity="other">%d active sessions</item>
|
||||||
</plurals>
|
</plurals>
|
||||||
|
|
||||||
<string name="crosssigning_verify_this_session">Verify this session</string>
|
|
||||||
<string name="crosssigning_other_user_not_trust">Other users may not trust it</string>
|
<string name="crosssigning_other_user_not_trust">Other users may not trust it</string>
|
||||||
<string name="complete_security">Complete Security</string>
|
<string name="complete_security">Complete Security</string>
|
||||||
|
|
||||||
<string name="verification_open_other_to_verify">Open an existing session & use it to verify this one, granting it access to encrypted messages. If you can’t access one, use your recovery key or passphrase.</string>
|
<string name="verification_open_other_to_verify">Open an existing session & use it to verify this one, granting it access to encrypted messages.</string>
|
||||||
|
|
||||||
|
|
||||||
<string name="verification_profile_verify">Verify</string>
|
<string name="verification_profile_verify">Verify</string>
|
||||||
|
|
|
@ -18,6 +18,9 @@
|
||||||
</plurals>
|
</plurals>
|
||||||
<string name="poll_item_selected_aria">Selected Option</string>
|
<string name="poll_item_selected_aria">Selected Option</string>
|
||||||
<string name="command_description_poll">Creates a simple poll</string>
|
<string name="command_description_poll">Creates a simple poll</string>
|
||||||
|
|
||||||
|
<string name="verification_cannot_access_other_session">Can‘t access an existing session?</string>
|
||||||
|
<string name="verification_use_passphrase">Use your recovery key or passphrase</string>
|
||||||
<!-- END Strings added by Valere -->
|
<!-- END Strings added by Valere -->
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue