mirror of
https://github.com/element-hq/element-android
synced 2024-11-28 13:38:49 +03:00
Basic Incoming request toast + cleaning
This commit is contained in:
parent
8400ab6efe
commit
8749e49e80
25 changed files with 189 additions and 1355 deletions
|
@ -44,6 +44,7 @@ interface SasVerificationService {
|
||||||
|
|
||||||
fun getExistingVerificationRequest(otherUser: String, tid: String?): PendingVerificationRequest?
|
fun getExistingVerificationRequest(otherUser: String, tid: String?): PendingVerificationRequest?
|
||||||
|
|
||||||
|
fun getExistingVerificationRequestInRoom(roomId: String, tid: String?): PendingVerificationRequest?
|
||||||
/**
|
/**
|
||||||
* Shortcut for KeyVerificationStart.VERIF_METHOD_SAS
|
* Shortcut for KeyVerificationStart.VERIF_METHOD_SAS
|
||||||
* @see beginKeyVerification
|
* @see beginKeyVerification
|
||||||
|
|
|
@ -104,6 +104,7 @@ internal class DefaultRoomVerificationUpdateTask @Inject constructor(
|
||||||
// The verification is started from another device
|
// The verification is started from another device
|
||||||
Timber.v("## SAS Verification live observer: Transaction started by other device tid:${it.transactionID} ")
|
Timber.v("## SAS Verification live observer: Transaction started by other device tid:${it.transactionID} ")
|
||||||
it.transactionID?.let { txId -> transactionsHandledByOtherDevice.add(txId) }
|
it.transactionID?.let { txId -> transactionsHandledByOtherDevice.add(txId) }
|
||||||
|
params.sasVerificationService.onRoomRequestHandledByOtherDevice(event)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (EventType.KEY_VERIFICATION_READY == event.type) {
|
} else if (EventType.KEY_VERIFICATION_READY == event.type) {
|
||||||
|
@ -112,11 +113,13 @@ internal class DefaultRoomVerificationUpdateTask @Inject constructor(
|
||||||
// The verification is started from another device
|
// The verification is started from another device
|
||||||
Timber.v("## SAS Verification live observer: Transaction started by other device tid:${it.transactionID} ")
|
Timber.v("## SAS Verification live observer: Transaction started by other device tid:${it.transactionID} ")
|
||||||
it.transactionID?.let { txId -> transactionsHandledByOtherDevice.add(txId) }
|
it.transactionID?.let { txId -> transactionsHandledByOtherDevice.add(txId) }
|
||||||
|
params.sasVerificationService.onRoomRequestHandledByOtherDevice(event)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (EventType.KEY_VERIFICATION_CANCEL == event.type || EventType.KEY_VERIFICATION_DONE == event.type) {
|
} else if (EventType.KEY_VERIFICATION_CANCEL == event.type || EventType.KEY_VERIFICATION_DONE == event.type) {
|
||||||
event.getClearContent().toModel<MessageRelationContent>()?.relatesTo?.eventId?.let {
|
event.getClearContent().toModel<MessageRelationContent>()?.relatesTo?.eventId?.let {
|
||||||
transactionsHandledByOtherDevice.remove(it)
|
transactionsHandledByOtherDevice.remove(it)
|
||||||
|
params.sasVerificationService.onRoomRequestHandledByOtherDevice(event)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -216,7 +216,20 @@ internal class DefaultSasVerificationService @Inject constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onRoomRequestReceived(event: Event) {
|
fun onRoomRequestHandledByOtherDevice(event: Event) {
|
||||||
|
val requestInfo = event.getClearContent().toModel<MessageRelationContent>()
|
||||||
|
?: return
|
||||||
|
val requestId = requestInfo.relatesTo?.eventId ?: return
|
||||||
|
getExistingVerificationRequestInRoom(event.roomId ?: "", requestId)?.let {
|
||||||
|
updatePendingRequest(
|
||||||
|
it.copy(
|
||||||
|
handledByOtherSession = true
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun onRoomRequestReceived(event: Event) {
|
||||||
Timber.v("## SAS Verification request from ${event.senderId} in room ${event.roomId}")
|
Timber.v("## SAS Verification request from ${event.senderId} in room ${event.roomId}")
|
||||||
val requestInfo = event.getClearContent().toModel<MessageVerificationRequestContent>()
|
val requestInfo = event.getClearContent().toModel<MessageVerificationRequestContent>()
|
||||||
?: return
|
?: return
|
||||||
|
@ -245,6 +258,7 @@ internal class DefaultSasVerificationService @Inject constructor(
|
||||||
ageLocalTs = event.ageLocalTs ?: System.currentTimeMillis(),
|
ageLocalTs = event.ageLocalTs ?: System.currentTimeMillis(),
|
||||||
isIncoming = true,
|
isIncoming = true,
|
||||||
otherUserId = senderId, // requestInfo.toUserId,
|
otherUserId = senderId, // requestInfo.toUserId,
|
||||||
|
roomId = event.roomId,
|
||||||
transactionId = event.eventId,
|
transactionId = event.eventId,
|
||||||
requestInfo = requestInfo
|
requestInfo = requestInfo
|
||||||
)
|
)
|
||||||
|
@ -647,6 +661,16 @@ internal class DefaultSasVerificationService @Inject constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun getExistingVerificationRequestInRoom(roomId: String, tid: String?): PendingVerificationRequest? {
|
||||||
|
synchronized(lock = pendingRequests) {
|
||||||
|
return tid?.let { tid ->
|
||||||
|
pendingRequests.flatMap { entry ->
|
||||||
|
entry.value.filter { it.roomId == roomId && it.transactionId == tid }
|
||||||
|
}.firstOrNull()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun getExistingTransactionsForUser(otherUser: String): Collection<VerificationTransaction>? {
|
private fun getExistingTransactionsForUser(otherUser: String): Collection<VerificationTransaction>? {
|
||||||
synchronized(txMap) {
|
synchronized(txMap) {
|
||||||
return txMap[otherUser]?.values
|
return txMap[otherUser]?.values
|
||||||
|
@ -723,6 +747,7 @@ internal class DefaultSasVerificationService @Inject constructor(
|
||||||
val verificationRequest = PendingVerificationRequest(
|
val verificationRequest = PendingVerificationRequest(
|
||||||
ageLocalTs = System.currentTimeMillis(),
|
ageLocalTs = System.currentTimeMillis(),
|
||||||
isIncoming = false,
|
isIncoming = false,
|
||||||
|
roomId = roomId,
|
||||||
localID = localID,
|
localID = localID,
|
||||||
otherUserId = userId
|
otherUserId = userId
|
||||||
)
|
)
|
||||||
|
|
|
@ -27,11 +27,13 @@ data class PendingVerificationRequest(
|
||||||
val isIncoming: Boolean = false,
|
val isIncoming: Boolean = false,
|
||||||
val localID: String = UUID.randomUUID().toString(),
|
val localID: String = UUID.randomUUID().toString(),
|
||||||
val otherUserId: String,
|
val otherUserId: String,
|
||||||
|
val roomId: String?,
|
||||||
val transactionId: String? = null,
|
val transactionId: String? = null,
|
||||||
val requestInfo: MessageVerificationRequestContent? = null,
|
val requestInfo: MessageVerificationRequestContent? = null,
|
||||||
val readyInfo: VerificationInfoReady? = null,
|
val readyInfo: VerificationInfoReady? = null,
|
||||||
val cancelConclusion: CancelCode? = null,
|
val cancelConclusion: CancelCode? = null,
|
||||||
val isSuccessful : Boolean = false
|
val isSuccessful : Boolean = false,
|
||||||
|
val handledByOtherSession : Boolean = false
|
||||||
|
|
||||||
) {
|
) {
|
||||||
|
|
||||||
|
|
|
@ -47,9 +47,6 @@
|
||||||
android:label="@string/title_activity_settings"
|
android:label="@string/title_activity_settings"
|
||||||
android:windowSoftInputMode="adjustResize" />
|
android:windowSoftInputMode="adjustResize" />
|
||||||
<activity android:name=".features.media.VideoMediaViewerActivity" />
|
<activity android:name=".features.media.VideoMediaViewerActivity" />
|
||||||
<activity
|
|
||||||
android:name=".features.crypto.verification.SASVerificationActivity"
|
|
||||||
android:label="@string/title_activity_verify_device" />
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".features.crypto.keysbackup.restore.KeysBackupRestoreActivity"
|
android:name=".features.crypto.keysbackup.restore.KeysBackupRestoreActivity"
|
||||||
android:label="@string/title_activity_keys_backup_setup" />
|
android:label="@string/title_activity_keys_backup_setup" />
|
||||||
|
|
|
@ -234,31 +234,6 @@ interface FragmentModule {
|
||||||
@FragmentKey(VectorSettingsIgnoredUsersFragment::class)
|
@FragmentKey(VectorSettingsIgnoredUsersFragment::class)
|
||||||
fun bindVectorSettingsIgnoredUsersFragment(fragment: VectorSettingsIgnoredUsersFragment): Fragment
|
fun bindVectorSettingsIgnoredUsersFragment(fragment: VectorSettingsIgnoredUsersFragment): Fragment
|
||||||
|
|
||||||
@Binds
|
|
||||||
@IntoMap
|
|
||||||
@FragmentKey(VectorSettingsDevicesFragment::class)
|
|
||||||
fun bindVectorSettingsDevicesFragment(fragment: VectorSettingsDevicesFragment): Fragment
|
|
||||||
|
|
||||||
@Binds
|
|
||||||
@IntoMap
|
|
||||||
@FragmentKey(SASVerificationIncomingFragment::class)
|
|
||||||
fun bindSASVerificationIncomingFragment(fragment: SASVerificationIncomingFragment): Fragment
|
|
||||||
|
|
||||||
@Binds
|
|
||||||
@IntoMap
|
|
||||||
@FragmentKey(SASVerificationShortCodeFragment::class)
|
|
||||||
fun bindSASVerificationShortCodeFragment(fragment: SASVerificationShortCodeFragment): Fragment
|
|
||||||
|
|
||||||
@Binds
|
|
||||||
@IntoMap
|
|
||||||
@FragmentKey(SASVerificationVerifiedFragment::class)
|
|
||||||
fun bindSASVerificationVerifiedFragment(fragment: SASVerificationVerifiedFragment): Fragment
|
|
||||||
|
|
||||||
@Binds
|
|
||||||
@IntoMap
|
|
||||||
@FragmentKey(SASVerificationStartFragment::class)
|
|
||||||
fun bindSASVerificationStartFragment(fragment: SASVerificationStartFragment): Fragment
|
|
||||||
|
|
||||||
@Binds
|
@Binds
|
||||||
@IntoMap
|
@IntoMap
|
||||||
@FragmentKey(PublicRoomsFragment::class)
|
@FragmentKey(PublicRoomsFragment::class)
|
||||||
|
|
|
@ -27,7 +27,6 @@ import im.vector.riotx.features.crypto.keysbackup.restore.KeysBackupRestoreFromK
|
||||||
import im.vector.riotx.features.crypto.keysbackup.restore.KeysBackupRestoreFromPassphraseViewModel
|
import im.vector.riotx.features.crypto.keysbackup.restore.KeysBackupRestoreFromPassphraseViewModel
|
||||||
import im.vector.riotx.features.crypto.keysbackup.restore.KeysBackupRestoreSharedViewModel
|
import im.vector.riotx.features.crypto.keysbackup.restore.KeysBackupRestoreSharedViewModel
|
||||||
import im.vector.riotx.features.crypto.keysbackup.setup.KeysBackupSetupSharedViewModel
|
import im.vector.riotx.features.crypto.keysbackup.setup.KeysBackupSetupSharedViewModel
|
||||||
import im.vector.riotx.features.crypto.verification.SasVerificationViewModel
|
|
||||||
import im.vector.riotx.features.home.HomeSharedActionViewModel
|
import im.vector.riotx.features.home.HomeSharedActionViewModel
|
||||||
import im.vector.riotx.features.home.room.detail.RoomDetailSharedActionViewModel
|
import im.vector.riotx.features.home.room.detail.RoomDetailSharedActionViewModel
|
||||||
import im.vector.riotx.features.home.room.detail.timeline.action.MessageSharedActionViewModel
|
import im.vector.riotx.features.home.room.detail.timeline.action.MessageSharedActionViewModel
|
||||||
|
@ -61,11 +60,6 @@ interface ViewModelModule {
|
||||||
@ViewModelKey(EmojiChooserViewModel::class)
|
@ViewModelKey(EmojiChooserViewModel::class)
|
||||||
fun bindEmojiChooserViewModel(viewModel: EmojiChooserViewModel): ViewModel
|
fun bindEmojiChooserViewModel(viewModel: EmojiChooserViewModel): ViewModel
|
||||||
|
|
||||||
@Binds
|
|
||||||
@IntoMap
|
|
||||||
@ViewModelKey(SasVerificationViewModel::class)
|
|
||||||
fun bindSasVerificationViewModel(viewModel: SasVerificationViewModel): ViewModel
|
|
||||||
|
|
||||||
@Binds
|
@Binds
|
||||||
@IntoMap
|
@IntoMap
|
||||||
@ViewModelKey(KeysBackupRestoreFromKeyViewModel::class)
|
@ViewModelKey(KeysBackupRestoreFromKeyViewModel::class)
|
||||||
|
|
|
@ -101,10 +101,12 @@ abstract class VectorBaseActivity : AppCompatActivity(), HasScreenInjector {
|
||||||
private lateinit var configurationViewModel: ConfigurationViewModel
|
private lateinit var configurationViewModel: ConfigurationViewModel
|
||||||
private lateinit var sessionListener: SessionListener
|
private lateinit var sessionListener: SessionListener
|
||||||
protected lateinit var bugReporter: BugReporter
|
protected lateinit var bugReporter: BugReporter
|
||||||
lateinit var rageShake: RageShake
|
private lateinit var rageShake: RageShake
|
||||||
|
|
||||||
|
lateinit var navigator: Navigator
|
||||||
private set
|
private set
|
||||||
protected lateinit var navigator: Navigator
|
|
||||||
private lateinit var fragmentFactory: FragmentFactory
|
private lateinit var fragmentFactory: FragmentFactory
|
||||||
|
|
||||||
private lateinit var activeSessionHolder: ActiveSessionHolder
|
private lateinit var activeSessionHolder: ActiveSessionHolder
|
||||||
private lateinit var vectorPreferences: VectorPreferences
|
private lateinit var vectorPreferences: VectorPreferences
|
||||||
|
|
||||||
|
@ -210,8 +212,8 @@ abstract class VectorBaseActivity : AppCompatActivity(), HasScreenInjector {
|
||||||
handleInvalidToken(globalError)
|
handleInvalidToken(globalError)
|
||||||
is GlobalError.ConsentNotGivenError ->
|
is GlobalError.ConsentNotGivenError ->
|
||||||
consentNotGivenHelper.displayDialog(globalError.consentUri,
|
consentNotGivenHelper.displayDialog(globalError.consentUri,
|
||||||
activeSessionHolder.getActiveSession().sessionParams.homeServerConnectionConfig.homeServerUri.host
|
activeSessionHolder.getActiveSession().sessionParams.homeServerConnectionConfig.homeServerUri.host
|
||||||
?: "")
|
?: "")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -33,13 +33,11 @@ import im.vector.matrix.android.internal.crypto.model.MXUsersDevicesMap
|
||||||
import im.vector.matrix.android.internal.crypto.model.rest.DeviceInfo
|
import im.vector.matrix.android.internal.crypto.model.rest.DeviceInfo
|
||||||
import im.vector.matrix.android.internal.crypto.model.rest.DevicesListResponse
|
import im.vector.matrix.android.internal.crypto.model.rest.DevicesListResponse
|
||||||
import im.vector.riotx.R
|
import im.vector.riotx.R
|
||||||
import im.vector.riotx.features.crypto.verification.SASVerificationActivity
|
|
||||||
import im.vector.riotx.features.popup.PopupAlertManager
|
import im.vector.riotx.features.popup.PopupAlertManager
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import java.text.DateFormat
|
import java.text.DateFormat
|
||||||
import java.text.SimpleDateFormat
|
import java.text.SimpleDateFormat
|
||||||
import java.util.Locale
|
import java.util.*
|
||||||
import java.util.Date
|
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
import kotlin.collections.ArrayList
|
import kotlin.collections.ArrayList
|
||||||
|
@ -195,18 +193,19 @@ class KeyRequestHandler @Inject constructor(private val context: Context)
|
||||||
denyAllRequests(mappingKey)
|
denyAllRequests(mappingKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
alert.addButton(
|
// TODO send to the new profile page
|
||||||
context.getString(R.string.start_verification_short_label),
|
// alert.addButton(
|
||||||
Runnable {
|
// context.getString(R.string.start_verification_short_label),
|
||||||
alert.weakCurrentActivity?.get()?.let {
|
// Runnable {
|
||||||
val intent = SASVerificationActivity.outgoingIntent(it,
|
// alert.weakCurrentActivity?.get()?.let {
|
||||||
session?.myUserId ?: "",
|
// val intent = SASVerificationActivity.outgoingIntent(it,
|
||||||
userId, deviceId)
|
// session?.myUserId ?: "",
|
||||||
it.startActivity(intent)
|
// userId, deviceId)
|
||||||
}
|
// it.startActivity(intent)
|
||||||
},
|
// }
|
||||||
false
|
// },
|
||||||
)
|
// false
|
||||||
|
// )
|
||||||
|
|
||||||
alert.addButton(context.getString(R.string.share_without_verifying_short_label), Runnable {
|
alert.addButton(context.getString(R.string.share_without_verifying_short_label), Runnable {
|
||||||
shareAllSessions(mappingKey)
|
shareAllSessions(mappingKey)
|
||||||
|
|
|
@ -20,8 +20,13 @@ import im.vector.matrix.android.api.session.Session
|
||||||
import im.vector.matrix.android.api.session.crypto.sas.SasVerificationService
|
import im.vector.matrix.android.api.session.crypto.sas.SasVerificationService
|
||||||
import im.vector.matrix.android.api.session.crypto.sas.SasVerificationTransaction
|
import im.vector.matrix.android.api.session.crypto.sas.SasVerificationTransaction
|
||||||
import im.vector.matrix.android.api.session.crypto.sas.SasVerificationTxState
|
import im.vector.matrix.android.api.session.crypto.sas.SasVerificationTxState
|
||||||
|
import im.vector.matrix.android.internal.crypto.verification.PendingVerificationRequest
|
||||||
import im.vector.riotx.R
|
import im.vector.riotx.R
|
||||||
|
import im.vector.riotx.core.platform.VectorBaseActivity
|
||||||
|
import im.vector.riotx.features.home.room.detail.RoomDetailActivity
|
||||||
|
import im.vector.riotx.features.home.room.detail.RoomDetailArgs
|
||||||
import im.vector.riotx.features.popup.PopupAlertManager
|
import im.vector.riotx.features.popup.PopupAlertManager
|
||||||
|
import im.vector.riotx.features.themes.ThemeUtils
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
|
|
||||||
|
@ -48,46 +53,46 @@ class IncomingVerificationRequestHandler @Inject constructor(private val context
|
||||||
override fun transactionUpdated(tx: SasVerificationTransaction) {
|
override fun transactionUpdated(tx: SasVerificationTransaction) {
|
||||||
when (tx.state) {
|
when (tx.state) {
|
||||||
SasVerificationTxState.OnStarted -> {
|
SasVerificationTxState.OnStarted -> {
|
||||||
// Add a notification for every incoming request
|
// // Add a notification for every incoming request
|
||||||
val name = session?.getUser(tx.otherUserId)?.displayName
|
// val name = session?.getUser(tx.otherUserId)?.displayName
|
||||||
?: tx.otherUserId
|
// ?: tx.otherUserId
|
||||||
|
//
|
||||||
val alert = PopupAlertManager.VectorAlert(
|
// val alert = PopupAlertManager.VectorAlert(
|
||||||
"kvr_${tx.transactionId}",
|
// "kvr_${tx.transactionId}",
|
||||||
context.getString(R.string.sas_incoming_request_notif_title),
|
// context.getString(R.string.sas_incoming_request_notif_title),
|
||||||
context.getString(R.string.sas_incoming_request_notif_content, name),
|
// context.getString(R.string.sas_incoming_request_notif_content, name),
|
||||||
R.drawable.shield)
|
// R.drawable.shield)
|
||||||
.apply {
|
// .apply {
|
||||||
contentAction = Runnable {
|
// contentAction = Runnable {
|
||||||
val intent = SASVerificationActivity.incomingIntent(context,
|
// val intent = SASVerificationActivity.incomingIntent(context,
|
||||||
session?.myUserId ?: "",
|
// session?.myUserId ?: "",
|
||||||
tx.otherUserId,
|
// tx.otherUserId,
|
||||||
tx.transactionId)
|
// tx.transactionId)
|
||||||
weakCurrentActivity?.get()?.startActivity(intent)
|
// weakCurrentActivity?.get()?.startActivity(intent)
|
||||||
}
|
// }
|
||||||
dismissedAction = Runnable {
|
// dismissedAction = Runnable {
|
||||||
tx.cancel()
|
// tx.cancel()
|
||||||
}
|
// }
|
||||||
addButton(
|
// addButton(
|
||||||
context.getString(R.string.ignore),
|
// context.getString(R.string.ignore),
|
||||||
Runnable {
|
// Runnable {
|
||||||
tx.cancel()
|
// tx.cancel()
|
||||||
}
|
// }
|
||||||
)
|
// )
|
||||||
addButton(
|
// addButton(
|
||||||
context.getString(R.string.action_open),
|
// context.getString(R.string.action_open),
|
||||||
Runnable {
|
// Runnable {
|
||||||
val intent = SASVerificationActivity.incomingIntent(context,
|
// val intent = SASVerificationActivity.incomingIntent(context,
|
||||||
session?.myUserId ?: "",
|
// session?.myUserId ?: "",
|
||||||
tx.otherUserId,
|
// tx.otherUserId,
|
||||||
tx.transactionId)
|
// tx.transactionId)
|
||||||
weakCurrentActivity?.get()?.startActivity(intent)
|
// weakCurrentActivity?.get()?.startActivity(intent)
|
||||||
}
|
// }
|
||||||
)
|
// )
|
||||||
// 10mn expiration
|
// // 10mn expiration
|
||||||
expirationTimestamp = System.currentTimeMillis() + (10 * 60 * 1000L)
|
// expirationTimestamp = System.currentTimeMillis() + (10 * 60 * 1000L)
|
||||||
}
|
// }
|
||||||
PopupAlertManager.postVectorAlert(alert)
|
// PopupAlertManager.postVectorAlert(alert)
|
||||||
}
|
}
|
||||||
SasVerificationTxState.Cancelled,
|
SasVerificationTxState.Cancelled,
|
||||||
SasVerificationTxState.OnCancelled,
|
SasVerificationTxState.OnCancelled,
|
||||||
|
@ -101,4 +106,54 @@ class IncomingVerificationRequestHandler @Inject constructor(private val context
|
||||||
|
|
||||||
override fun markedAsManuallyVerified(userId: String, deviceId: String) {
|
override fun markedAsManuallyVerified(userId: String, deviceId: String) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun verificationRequestCreated(pr: PendingVerificationRequest) {
|
||||||
|
// For incoming request we should prompt (if not in activity where this request apply)
|
||||||
|
if (pr.isIncoming) {
|
||||||
|
val name = session?.getUser(pr.otherUserId)?.displayName
|
||||||
|
?: pr.otherUserId
|
||||||
|
|
||||||
|
val alert = PopupAlertManager.VectorAlert(
|
||||||
|
uniqueIdForVerificationRequest(pr),
|
||||||
|
context.getString(R.string.sas_incoming_request_notif_title),
|
||||||
|
"$name(${pr.otherUserId})",
|
||||||
|
R.drawable.ic_shield_black,
|
||||||
|
shouldBeDisplayedIn = { activity ->
|
||||||
|
if (activity is RoomDetailActivity) {
|
||||||
|
activity.intent?.extras?.getParcelable<RoomDetailArgs>(RoomDetailActivity.EXTRA_ROOM_DETAIL_ARGS)?.let {
|
||||||
|
it.roomId != pr.roomId
|
||||||
|
} ?: true
|
||||||
|
} else true
|
||||||
|
})
|
||||||
|
.apply {
|
||||||
|
contentAction = Runnable {
|
||||||
|
(weakCurrentActivity?.get() as? VectorBaseActivity)?.let {
|
||||||
|
it.navigator.openRoom(it, pr.roomId ?: "", pr.transactionId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dismissedAction = Runnable {
|
||||||
|
session?.getSasVerificationService()?.declineVerificationRequestInDMs(pr.otherUserId,
|
||||||
|
pr.requestInfo?.fromDevice ?: "",
|
||||||
|
pr.transactionId ?: "",
|
||||||
|
pr.roomId ?: ""
|
||||||
|
)
|
||||||
|
}
|
||||||
|
colorInt = ThemeUtils.getColor(context, R.attr.vctr_notice_secondary)
|
||||||
|
// 5mn expiration
|
||||||
|
expirationTimestamp = System.currentTimeMillis() + (5 * 60 * 1000L)
|
||||||
|
}
|
||||||
|
PopupAlertManager.postVectorAlert(alert)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun verificationRequestUpdated(pr: PendingVerificationRequest) {
|
||||||
|
// If an incoming request is readied (by another device?) we should discard the alert
|
||||||
|
if (pr.isIncoming && (pr.isReady || pr.handledByOtherSession)) {
|
||||||
|
PopupAlertManager.cancelAlert(uniqueIdForVerificationRequest(pr))
|
||||||
|
}
|
||||||
|
super.verificationRequestUpdated(pr)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun uniqueIdForVerificationRequest(pr: PendingVerificationRequest) =
|
||||||
|
"verificationRequest_${pr.transactionId}"
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,245 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2019 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.riotx.features.crypto.verification
|
|
||||||
|
|
||||||
import android.app.Activity
|
|
||||||
import android.content.Context
|
|
||||||
import android.content.Intent
|
|
||||||
import android.view.MenuItem
|
|
||||||
import androidx.appcompat.app.AlertDialog
|
|
||||||
import androidx.lifecycle.Observer
|
|
||||||
import im.vector.matrix.android.api.session.crypto.sas.CancelCode
|
|
||||||
import im.vector.matrix.android.api.session.crypto.sas.IncomingSasVerificationTransaction
|
|
||||||
import im.vector.matrix.android.api.session.crypto.sas.OutgoingSasVerificationRequest
|
|
||||||
import im.vector.matrix.android.api.session.crypto.sas.SasVerificationTxState
|
|
||||||
import im.vector.riotx.R
|
|
||||||
import im.vector.riotx.core.extensions.commitTransaction
|
|
||||||
import im.vector.riotx.core.extensions.observeEvent
|
|
||||||
import im.vector.riotx.core.platform.SimpleFragmentActivity
|
|
||||||
import im.vector.riotx.core.platform.WaitingViewData
|
|
||||||
|
|
||||||
// TODO Deprecated("replaced by bottomsheet UX")
|
|
||||||
class SASVerificationActivity : SimpleFragmentActivity() {
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
|
|
||||||
private const val EXTRA_MATRIX_ID = "EXTRA_MATRIX_ID"
|
|
||||||
private const val EXTRA_TRANSACTION_ID = "EXTRA_TRANSACTION_ID"
|
|
||||||
private const val EXTRA_OTHER_USER_ID = "EXTRA_OTHER_USER_ID"
|
|
||||||
private const val EXTRA_OTHER_DEVICE_ID = "EXTRA_OTHER_DEVICE_ID"
|
|
||||||
private const val EXTRA_IS_INCOMING = "EXTRA_IS_INCOMING"
|
|
||||||
|
|
||||||
/* ==========================================================================================
|
|
||||||
* INPUT
|
|
||||||
* ========================================================================================== */
|
|
||||||
|
|
||||||
fun incomingIntent(context: Context, matrixID: String, otherUserId: String, transactionID: String): Intent {
|
|
||||||
val intent = Intent(context, SASVerificationActivity::class.java)
|
|
||||||
intent.putExtra(EXTRA_MATRIX_ID, matrixID)
|
|
||||||
intent.putExtra(EXTRA_TRANSACTION_ID, transactionID)
|
|
||||||
intent.putExtra(EXTRA_OTHER_USER_ID, otherUserId)
|
|
||||||
intent.putExtra(EXTRA_IS_INCOMING, true)
|
|
||||||
return intent
|
|
||||||
}
|
|
||||||
|
|
||||||
fun outgoingIntent(context: Context, matrixID: String, otherUserId: String, otherDeviceId: String): Intent {
|
|
||||||
val intent = Intent(context, SASVerificationActivity::class.java)
|
|
||||||
intent.putExtra(EXTRA_MATRIX_ID, matrixID)
|
|
||||||
intent.putExtra(EXTRA_OTHER_DEVICE_ID, otherDeviceId)
|
|
||||||
intent.putExtra(EXTRA_OTHER_USER_ID, otherUserId)
|
|
||||||
intent.putExtra(EXTRA_IS_INCOMING, false)
|
|
||||||
return intent
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ==========================================================================================
|
|
||||||
* OUTPUT
|
|
||||||
* ========================================================================================== */
|
|
||||||
|
|
||||||
fun getOtherUserId(intent: Intent?): String? {
|
|
||||||
return intent?.getStringExtra(EXTRA_OTHER_USER_ID)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getOtherDeviceId(intent: Intent?): String? {
|
|
||||||
return intent?.getStringExtra(EXTRA_OTHER_DEVICE_ID)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getTitleRes() = R.string.title_activity_verify_device
|
|
||||||
|
|
||||||
private lateinit var viewModel: SasVerificationViewModel
|
|
||||||
|
|
||||||
override fun initUiAndData() {
|
|
||||||
super.initUiAndData()
|
|
||||||
viewModel = viewModelProvider.get(SasVerificationViewModel::class.java)
|
|
||||||
val transactionID: String? = intent.getStringExtra(EXTRA_TRANSACTION_ID)
|
|
||||||
|
|
||||||
if (isFirstCreation()) {
|
|
||||||
val isIncoming = intent.getBooleanExtra(EXTRA_IS_INCOMING, false)
|
|
||||||
if (isIncoming) {
|
|
||||||
// incoming always have a transaction id
|
|
||||||
viewModel.initIncoming(session, intent.getStringExtra(EXTRA_OTHER_USER_ID), transactionID)
|
|
||||||
} else {
|
|
||||||
viewModel.initOutgoing(session, intent.getStringExtra(EXTRA_OTHER_USER_ID), intent.getStringExtra(EXTRA_OTHER_DEVICE_ID))
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isIncoming) {
|
|
||||||
val incoming = viewModel.transaction as? IncomingSasVerificationTransaction
|
|
||||||
when (incoming?.uxState) {
|
|
||||||
null,
|
|
||||||
IncomingSasVerificationTransaction.UxState.UNKNOWN,
|
|
||||||
IncomingSasVerificationTransaction.UxState.SHOW_ACCEPT,
|
|
||||||
IncomingSasVerificationTransaction.UxState.WAIT_FOR_KEY_AGREEMENT -> {
|
|
||||||
supportActionBar?.setTitle(R.string.sas_incoming_request_title)
|
|
||||||
supportFragmentManager.commitTransaction {
|
|
||||||
setCustomAnimations(R.anim.no_anim, R.anim.exit_fade_out)
|
|
||||||
replace(R.id.container, SASVerificationIncomingFragment::class.java, null)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
IncomingSasVerificationTransaction.UxState.WAIT_FOR_VERIFICATION,
|
|
||||||
IncomingSasVerificationTransaction.UxState.SHOW_SAS -> {
|
|
||||||
supportFragmentManager.commitTransaction {
|
|
||||||
setCustomAnimations(R.anim.no_anim, R.anim.exit_fade_out)
|
|
||||||
replace(R.id.container, SASVerificationShortCodeFragment::class.java, null)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
IncomingSasVerificationTransaction.UxState.VERIFIED -> {
|
|
||||||
supportFragmentManager.commitTransaction {
|
|
||||||
setCustomAnimations(R.anim.no_anim, R.anim.exit_fade_out)
|
|
||||||
replace(R.id.container, SASVerificationVerifiedFragment::class.java, null)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
IncomingSasVerificationTransaction.UxState.CANCELLED_BY_ME,
|
|
||||||
IncomingSasVerificationTransaction.UxState.CANCELLED_BY_OTHER -> {
|
|
||||||
viewModel.navigateCancel()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
val outgoing = viewModel.transaction as? OutgoingSasVerificationRequest
|
|
||||||
// transaction can be null, as not yet created
|
|
||||||
when (outgoing?.uxState) {
|
|
||||||
null,
|
|
||||||
OutgoingSasVerificationRequest.UxState.UNKNOWN,
|
|
||||||
OutgoingSasVerificationRequest.UxState.WAIT_FOR_START,
|
|
||||||
OutgoingSasVerificationRequest.UxState.WAIT_FOR_KEY_AGREEMENT -> {
|
|
||||||
supportFragmentManager.commitTransaction {
|
|
||||||
setCustomAnimations(R.anim.no_anim, R.anim.exit_fade_out)
|
|
||||||
replace(R.id.container, SASVerificationStartFragment::class.java, null)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
OutgoingSasVerificationRequest.UxState.SHOW_SAS,
|
|
||||||
OutgoingSasVerificationRequest.UxState.WAIT_FOR_VERIFICATION -> {
|
|
||||||
supportFragmentManager.commitTransaction {
|
|
||||||
setCustomAnimations(R.anim.no_anim, R.anim.exit_fade_out)
|
|
||||||
replace(R.id.container, SASVerificationShortCodeFragment::class.java, null)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
OutgoingSasVerificationRequest.UxState.VERIFIED -> {
|
|
||||||
supportFragmentManager.commitTransaction {
|
|
||||||
setCustomAnimations(R.anim.no_anim, R.anim.exit_fade_out)
|
|
||||||
replace(R.id.container, SASVerificationVerifiedFragment::class.java, null)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
OutgoingSasVerificationRequest.UxState.CANCELLED_BY_ME,
|
|
||||||
OutgoingSasVerificationRequest.UxState.CANCELLED_BY_OTHER -> {
|
|
||||||
viewModel.navigateCancel()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
viewModel.navigateEvent.observeEvent(this) { uxStateEvent ->
|
|
||||||
when (uxStateEvent) {
|
|
||||||
SasVerificationViewModel.NAVIGATE_FINISH -> {
|
|
||||||
finish()
|
|
||||||
}
|
|
||||||
SasVerificationViewModel.NAVIGATE_FINISH_SUCCESS -> {
|
|
||||||
val dataResult = Intent()
|
|
||||||
dataResult.putExtra(EXTRA_OTHER_DEVICE_ID, viewModel.otherDeviceId)
|
|
||||||
dataResult.putExtra(EXTRA_OTHER_USER_ID, viewModel.otherUserId)
|
|
||||||
setResult(Activity.RESULT_OK, dataResult)
|
|
||||||
finish()
|
|
||||||
}
|
|
||||||
SasVerificationViewModel.NAVIGATE_SAS_DISPLAY -> {
|
|
||||||
supportFragmentManager.commitTransaction {
|
|
||||||
setCustomAnimations(R.anim.enter_from_right, R.anim.exit_fade_out)
|
|
||||||
replace(R.id.container, SASVerificationShortCodeFragment::class.java, null)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
SasVerificationViewModel.NAVIGATE_SUCCESS -> {
|
|
||||||
supportFragmentManager.commitTransaction {
|
|
||||||
setCustomAnimations(R.anim.enter_from_right, R.anim.exit_fade_out)
|
|
||||||
replace(R.id.container, SASVerificationVerifiedFragment::class.java, null)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
SasVerificationViewModel.NAVIGATE_CANCELLED -> {
|
|
||||||
val isCancelledByMe = viewModel.transaction?.state == SasVerificationTxState.Cancelled
|
|
||||||
val humanReadableReason = when (viewModel.transaction?.cancelledReason) {
|
|
||||||
CancelCode.User -> getString(R.string.sas_error_m_user)
|
|
||||||
CancelCode.Timeout -> getString(R.string.sas_error_m_timeout)
|
|
||||||
CancelCode.UnknownTransaction -> getString(R.string.sas_error_m_unknown_transaction)
|
|
||||||
CancelCode.UnknownMethod -> getString(R.string.sas_error_m_unknown_method)
|
|
||||||
CancelCode.MismatchedCommitment -> getString(R.string.sas_error_m_mismatched_commitment)
|
|
||||||
CancelCode.MismatchedSas -> getString(R.string.sas_error_m_mismatched_sas)
|
|
||||||
CancelCode.UnexpectedMessage -> getString(R.string.sas_error_m_unexpected_message)
|
|
||||||
CancelCode.InvalidMessage -> getString(R.string.sas_error_m_invalid_message)
|
|
||||||
CancelCode.MismatchedKeys -> getString(R.string.sas_error_m_key_mismatch)
|
|
||||||
// Use user error
|
|
||||||
CancelCode.UserMismatchError -> getString(R.string.sas_error_m_user_error)
|
|
||||||
null -> getString(R.string.sas_error_unknown)
|
|
||||||
}
|
|
||||||
val message =
|
|
||||||
if (isCancelledByMe) getString(R.string.sas_cancelled_by_me, humanReadableReason)
|
|
||||||
else getString(R.string.sas_cancelled_by_other, humanReadableReason)
|
|
||||||
// Show a dialog
|
|
||||||
if (!this.isFinishing) {
|
|
||||||
AlertDialog.Builder(this)
|
|
||||||
.setTitle(R.string.sas_cancelled_dialog_title)
|
|
||||||
.setMessage(message)
|
|
||||||
.setCancelable(false)
|
|
||||||
.setPositiveButton(R.string.ok) { _, _ ->
|
|
||||||
// nop
|
|
||||||
finish()
|
|
||||||
}
|
|
||||||
.show()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
viewModel.loadingLiveEvent.observe(this, Observer {
|
|
||||||
if (it == null) {
|
|
||||||
hideWaitingView()
|
|
||||||
} else {
|
|
||||||
val status = if (it == -1) "" else getString(it)
|
|
||||||
updateWaitingView(WaitingViewData(status, isIndeterminate = true))
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
|
||||||
if (item.itemId == android.R.id.home) {
|
|
||||||
// we want to cancel the transaction
|
|
||||||
viewModel.cancelTransaction()
|
|
||||||
}
|
|
||||||
|
|
||||||
return super.onOptionsItemSelected(item)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onBackPressed() {
|
|
||||||
// we want to cancel the transaction
|
|
||||||
viewModel.cancelTransaction()
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,100 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2019 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.riotx.features.crypto.verification
|
|
||||||
|
|
||||||
import android.os.Bundle
|
|
||||||
import android.widget.ImageView
|
|
||||||
import android.widget.TextView
|
|
||||||
import androidx.lifecycle.Observer
|
|
||||||
import butterknife.BindView
|
|
||||||
import butterknife.OnClick
|
|
||||||
import im.vector.matrix.android.api.session.crypto.sas.IncomingSasVerificationTransaction
|
|
||||||
import im.vector.matrix.android.api.util.MatrixItem
|
|
||||||
import im.vector.matrix.android.api.util.toMatrixItem
|
|
||||||
import im.vector.riotx.R
|
|
||||||
import im.vector.riotx.core.platform.VectorBaseFragment
|
|
||||||
import im.vector.riotx.features.home.AvatarRenderer
|
|
||||||
import javax.inject.Inject
|
|
||||||
|
|
||||||
// TODO Deprecated("replaced by bottomsheet UX")
|
|
||||||
class SASVerificationIncomingFragment @Inject constructor(
|
|
||||||
private var avatarRenderer: AvatarRenderer
|
|
||||||
) : VectorBaseFragment() {
|
|
||||||
|
|
||||||
@BindView(R.id.sas_incoming_request_user_display_name)
|
|
||||||
lateinit var otherUserDisplayNameTextView: TextView
|
|
||||||
|
|
||||||
@BindView(R.id.sas_incoming_request_user_id)
|
|
||||||
lateinit var otherUserIdTextView: TextView
|
|
||||||
|
|
||||||
@BindView(R.id.sas_incoming_request_user_device)
|
|
||||||
lateinit var otherDeviceTextView: TextView
|
|
||||||
|
|
||||||
@BindView(R.id.sas_incoming_request_user_avatar)
|
|
||||||
lateinit var avatarImageView: ImageView
|
|
||||||
|
|
||||||
override fun getLayoutResId() = R.layout.fragment_sas_verification_incoming_request
|
|
||||||
|
|
||||||
private lateinit var viewModel: SasVerificationViewModel
|
|
||||||
|
|
||||||
override fun onActivityCreated(savedInstanceState: Bundle?) {
|
|
||||||
super.onActivityCreated(savedInstanceState)
|
|
||||||
|
|
||||||
viewModel = activityViewModelProvider.get(SasVerificationViewModel::class.java)
|
|
||||||
|
|
||||||
otherUserDisplayNameTextView.text = viewModel.otherUser?.displayName ?: viewModel.otherUserId
|
|
||||||
otherUserIdTextView.text = viewModel.otherUserId
|
|
||||||
otherDeviceTextView.text = viewModel.otherDeviceId
|
|
||||||
|
|
||||||
viewModel.otherUser?.let {
|
|
||||||
avatarRenderer.render(it.toMatrixItem(), avatarImageView)
|
|
||||||
} ?: run {
|
|
||||||
// Fallback to what we know
|
|
||||||
avatarRenderer.render(MatrixItem.UserItem(viewModel.otherUserId ?: "", viewModel.otherUserId), avatarImageView)
|
|
||||||
}
|
|
||||||
|
|
||||||
viewModel.transactionState.observe(viewLifecycleOwner, Observer {
|
|
||||||
val uxState = (viewModel.transaction as? IncomingSasVerificationTransaction)?.uxState
|
|
||||||
when (uxState) {
|
|
||||||
IncomingSasVerificationTransaction.UxState.SHOW_ACCEPT -> {
|
|
||||||
viewModel.loadingLiveEvent.value = null
|
|
||||||
}
|
|
||||||
IncomingSasVerificationTransaction.UxState.WAIT_FOR_KEY_AGREEMENT -> {
|
|
||||||
viewModel.loadingLiveEvent.value = R.string.sas_waiting_for_partner
|
|
||||||
}
|
|
||||||
IncomingSasVerificationTransaction.UxState.SHOW_SAS -> {
|
|
||||||
viewModel.shortCodeReady()
|
|
||||||
}
|
|
||||||
IncomingSasVerificationTransaction.UxState.CANCELLED_BY_ME,
|
|
||||||
IncomingSasVerificationTransaction.UxState.CANCELLED_BY_OTHER -> {
|
|
||||||
viewModel.loadingLiveEvent.value = null
|
|
||||||
viewModel.navigateCancel()
|
|
||||||
}
|
|
||||||
else -> Unit
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
@OnClick(R.id.sas_request_continue_button)
|
|
||||||
fun didAccept() {
|
|
||||||
viewModel.acceptTransaction()
|
|
||||||
}
|
|
||||||
|
|
||||||
@OnClick(R.id.sas_request_cancel_button)
|
|
||||||
fun didCancel() {
|
|
||||||
viewModel.cancelTransaction()
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,170 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2019 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.riotx.features.crypto.verification
|
|
||||||
|
|
||||||
import android.os.Bundle
|
|
||||||
import android.view.ViewGroup
|
|
||||||
import android.widget.TextView
|
|
||||||
import androidx.core.view.isInvisible
|
|
||||||
import androidx.core.view.isVisible
|
|
||||||
import androidx.lifecycle.Observer
|
|
||||||
import butterknife.BindView
|
|
||||||
import butterknife.OnClick
|
|
||||||
import im.vector.matrix.android.api.session.crypto.sas.IncomingSasVerificationTransaction
|
|
||||||
import im.vector.matrix.android.api.session.crypto.sas.OutgoingSasVerificationRequest
|
|
||||||
import im.vector.riotx.R
|
|
||||||
import im.vector.riotx.core.platform.VectorBaseFragment
|
|
||||||
import javax.inject.Inject
|
|
||||||
|
|
||||||
// TODO Deprecated("replaced by bottomsheet UX")
|
|
||||||
class SASVerificationShortCodeFragment @Inject constructor(): VectorBaseFragment() {
|
|
||||||
|
|
||||||
private lateinit var viewModel: SasVerificationViewModel
|
|
||||||
|
|
||||||
@BindView(R.id.sas_decimal_code)
|
|
||||||
lateinit var decimalTextView: TextView
|
|
||||||
|
|
||||||
@BindView(R.id.sas_emoji_description)
|
|
||||||
lateinit var descriptionTextView: TextView
|
|
||||||
|
|
||||||
@BindView(R.id.sas_emoji_grid)
|
|
||||||
lateinit var emojiGrid: ViewGroup
|
|
||||||
|
|
||||||
@BindView(R.id.emoji0)
|
|
||||||
lateinit var emoji0View: ViewGroup
|
|
||||||
@BindView(R.id.emoji1)
|
|
||||||
lateinit var emoji1View: ViewGroup
|
|
||||||
@BindView(R.id.emoji2)
|
|
||||||
lateinit var emoji2View: ViewGroup
|
|
||||||
@BindView(R.id.emoji3)
|
|
||||||
lateinit var emoji3View: ViewGroup
|
|
||||||
@BindView(R.id.emoji4)
|
|
||||||
lateinit var emoji4View: ViewGroup
|
|
||||||
@BindView(R.id.emoji5)
|
|
||||||
lateinit var emoji5View: ViewGroup
|
|
||||||
@BindView(R.id.emoji6)
|
|
||||||
lateinit var emoji6View: ViewGroup
|
|
||||||
|
|
||||||
override fun getLayoutResId() = R.layout.fragment_sas_verification_display_code
|
|
||||||
|
|
||||||
override fun onActivityCreated(savedInstanceState: Bundle?) {
|
|
||||||
super.onActivityCreated(savedInstanceState)
|
|
||||||
viewModel = activityViewModelProvider.get(SasVerificationViewModel::class.java)
|
|
||||||
|
|
||||||
viewModel.transaction?.let {
|
|
||||||
if (it.supportsEmoji()) {
|
|
||||||
val emojicodes = it.getEmojiCodeRepresentation()
|
|
||||||
emojicodes.forEachIndexed { index, emojiRepresentation ->
|
|
||||||
when (index) {
|
|
||||||
0 -> {
|
|
||||||
emoji0View.findViewById<TextView>(R.id.item_emoji_tv).text = emojiRepresentation.emoji
|
|
||||||
emoji0View.findViewById<TextView>(R.id.item_emoji_name_tv).setText(emojiRepresentation.nameResId)
|
|
||||||
}
|
|
||||||
1 -> {
|
|
||||||
emoji1View.findViewById<TextView>(R.id.item_emoji_tv).text = emojiRepresentation.emoji
|
|
||||||
emoji1View.findViewById<TextView>(R.id.item_emoji_name_tv).setText(emojiRepresentation.nameResId)
|
|
||||||
}
|
|
||||||
2 -> {
|
|
||||||
emoji2View.findViewById<TextView>(R.id.item_emoji_tv).text = emojiRepresentation.emoji
|
|
||||||
emoji2View.findViewById<TextView>(R.id.item_emoji_name_tv).setText(emojiRepresentation.nameResId)
|
|
||||||
}
|
|
||||||
3 -> {
|
|
||||||
emoji3View.findViewById<TextView>(R.id.item_emoji_tv).text = emojiRepresentation.emoji
|
|
||||||
emoji3View.findViewById<TextView>(R.id.item_emoji_name_tv)?.setText(emojiRepresentation.nameResId)
|
|
||||||
}
|
|
||||||
4 -> {
|
|
||||||
emoji4View.findViewById<TextView>(R.id.item_emoji_tv).text = emojiRepresentation.emoji
|
|
||||||
emoji4View.findViewById<TextView>(R.id.item_emoji_name_tv).setText(emojiRepresentation.nameResId)
|
|
||||||
}
|
|
||||||
5 -> {
|
|
||||||
emoji5View.findViewById<TextView>(R.id.item_emoji_tv).text = emojiRepresentation.emoji
|
|
||||||
emoji5View.findViewById<TextView>(R.id.item_emoji_name_tv).setText(emojiRepresentation.nameResId)
|
|
||||||
}
|
|
||||||
6 -> {
|
|
||||||
emoji6View.findViewById<TextView>(R.id.item_emoji_tv).text = emojiRepresentation.emoji
|
|
||||||
emoji6View.findViewById<TextView>(R.id.item_emoji_name_tv).setText(emojiRepresentation.nameResId)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// decimal is at least supported
|
|
||||||
decimalTextView.text = it.getDecimalCodeRepresentation()
|
|
||||||
|
|
||||||
if (it.supportsEmoji()) {
|
|
||||||
descriptionTextView.text = getString(R.string.sas_emoji_description)
|
|
||||||
decimalTextView.isVisible = false
|
|
||||||
emojiGrid.isVisible = true
|
|
||||||
} else {
|
|
||||||
descriptionTextView.text = getString(R.string.sas_decimal_description)
|
|
||||||
decimalTextView.isVisible = true
|
|
||||||
emojiGrid.isInvisible = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
viewModel.transactionState.observe(viewLifecycleOwner, Observer {
|
|
||||||
if (viewModel.transaction is IncomingSasVerificationTransaction) {
|
|
||||||
val uxState = (viewModel.transaction as IncomingSasVerificationTransaction).uxState
|
|
||||||
when (uxState) {
|
|
||||||
IncomingSasVerificationTransaction.UxState.SHOW_SAS -> {
|
|
||||||
viewModel.loadingLiveEvent.value = null
|
|
||||||
}
|
|
||||||
IncomingSasVerificationTransaction.UxState.VERIFIED -> {
|
|
||||||
viewModel.loadingLiveEvent.value = null
|
|
||||||
viewModel.deviceIsVerified()
|
|
||||||
}
|
|
||||||
IncomingSasVerificationTransaction.UxState.CANCELLED_BY_ME,
|
|
||||||
IncomingSasVerificationTransaction.UxState.CANCELLED_BY_OTHER -> {
|
|
||||||
viewModel.loadingLiveEvent.value = null
|
|
||||||
viewModel.navigateCancel()
|
|
||||||
}
|
|
||||||
else -> {
|
|
||||||
viewModel.loadingLiveEvent.value = R.string.sas_waiting_for_partner
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (viewModel.transaction is OutgoingSasVerificationRequest) {
|
|
||||||
val uxState = (viewModel.transaction as OutgoingSasVerificationRequest).uxState
|
|
||||||
when (uxState) {
|
|
||||||
OutgoingSasVerificationRequest.UxState.SHOW_SAS -> {
|
|
||||||
viewModel.loadingLiveEvent.value = null
|
|
||||||
}
|
|
||||||
OutgoingSasVerificationRequest.UxState.VERIFIED -> {
|
|
||||||
viewModel.loadingLiveEvent.value = null
|
|
||||||
viewModel.deviceIsVerified()
|
|
||||||
}
|
|
||||||
OutgoingSasVerificationRequest.UxState.CANCELLED_BY_ME,
|
|
||||||
OutgoingSasVerificationRequest.UxState.CANCELLED_BY_OTHER -> {
|
|
||||||
viewModel.loadingLiveEvent.value = null
|
|
||||||
viewModel.navigateCancel()
|
|
||||||
}
|
|
||||||
else -> {
|
|
||||||
viewModel.loadingLiveEvent.value = R.string.sas_waiting_for_partner
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
@OnClick(R.id.sas_request_continue_button)
|
|
||||||
fun didAccept() {
|
|
||||||
viewModel.confirmEmojiSame()
|
|
||||||
}
|
|
||||||
|
|
||||||
@OnClick(R.id.sas_request_cancel_button)
|
|
||||||
fun didCancel() {
|
|
||||||
viewModel.cancelTransaction()
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,120 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2019 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.riotx.features.crypto.verification
|
|
||||||
|
|
||||||
import android.os.Bundle
|
|
||||||
import android.view.ViewGroup
|
|
||||||
import android.widget.Button
|
|
||||||
import android.widget.ProgressBar
|
|
||||||
import android.widget.TextView
|
|
||||||
import androidx.core.view.isInvisible
|
|
||||||
import androidx.core.view.isVisible
|
|
||||||
import androidx.lifecycle.Observer
|
|
||||||
import androidx.transition.TransitionManager
|
|
||||||
import butterknife.BindView
|
|
||||||
import butterknife.OnClick
|
|
||||||
import im.vector.matrix.android.api.session.crypto.sas.OutgoingSasVerificationRequest
|
|
||||||
import im.vector.riotx.R
|
|
||||||
import im.vector.riotx.core.platform.VectorBaseActivity
|
|
||||||
import im.vector.riotx.core.platform.VectorBaseFragment
|
|
||||||
import javax.inject.Inject
|
|
||||||
|
|
||||||
// TODO Deprecated("replaced by bottomsheet UX")
|
|
||||||
class SASVerificationStartFragment @Inject constructor(): VectorBaseFragment() {
|
|
||||||
|
|
||||||
override fun getLayoutResId() = R.layout.fragment_sas_verification_start
|
|
||||||
|
|
||||||
private lateinit var viewModel: SasVerificationViewModel
|
|
||||||
|
|
||||||
@BindView(R.id.rootLayout)
|
|
||||||
lateinit var rootLayout: ViewGroup
|
|
||||||
|
|
||||||
@BindView(R.id.sas_start_button)
|
|
||||||
lateinit var startButton: Button
|
|
||||||
|
|
||||||
@BindView(R.id.sas_start_button_loading)
|
|
||||||
lateinit var startButtonLoading: ProgressBar
|
|
||||||
|
|
||||||
@BindView(R.id.sas_verifying_keys)
|
|
||||||
lateinit var loadingText: TextView
|
|
||||||
|
|
||||||
override fun onActivityCreated(savedInstanceState: Bundle?) {
|
|
||||||
super.onActivityCreated(savedInstanceState)
|
|
||||||
viewModel = activityViewModelProvider.get(SasVerificationViewModel::class.java)
|
|
||||||
viewModel.transactionState.observe(viewLifecycleOwner, Observer {
|
|
||||||
val uxState = (viewModel.transaction as? OutgoingSasVerificationRequest)?.uxState
|
|
||||||
when (uxState) {
|
|
||||||
OutgoingSasVerificationRequest.UxState.WAIT_FOR_KEY_AGREEMENT -> {
|
|
||||||
// display loading
|
|
||||||
TransitionManager.beginDelayedTransition(this.rootLayout)
|
|
||||||
this.loadingText.isVisible = true
|
|
||||||
this.startButton.isInvisible = true
|
|
||||||
this.startButtonLoading.isVisible = true
|
|
||||||
this.startButtonLoading.animate()
|
|
||||||
}
|
|
||||||
OutgoingSasVerificationRequest.UxState.SHOW_SAS -> {
|
|
||||||
viewModel.shortCodeReady()
|
|
||||||
}
|
|
||||||
OutgoingSasVerificationRequest.UxState.CANCELLED_BY_ME,
|
|
||||||
OutgoingSasVerificationRequest.UxState.CANCELLED_BY_OTHER -> {
|
|
||||||
viewModel.navigateCancel()
|
|
||||||
}
|
|
||||||
else -> {
|
|
||||||
TransitionManager.beginDelayedTransition(this.rootLayout)
|
|
||||||
this.loadingText.isVisible = false
|
|
||||||
this.startButton.isVisible = true
|
|
||||||
this.startButtonLoading.isVisible = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
@OnClick(R.id.sas_start_button)
|
|
||||||
fun doStart() {
|
|
||||||
viewModel.beginSasKeyVerification()
|
|
||||||
}
|
|
||||||
|
|
||||||
@OnClick(R.id.sas_legacy_verification)
|
|
||||||
fun doLegacy() {
|
|
||||||
(requireActivity() as VectorBaseActivity).notImplemented()
|
|
||||||
|
|
||||||
/*
|
|
||||||
viewModel.session.crypto?.getDeviceInfo(viewModel.otherUserMxItem ?: "", viewModel.otherDeviceId
|
|
||||||
?: "", object : SimpleApiCallback<MXDeviceInfo>() {
|
|
||||||
override fun onSuccess(info: MXDeviceInfo?) {
|
|
||||||
info?.let {
|
|
||||||
|
|
||||||
CommonActivityUtils.displayDeviceVerificationDialogLegacy(it, it.userId, viewModel.session, activity, object : YesNoListener {
|
|
||||||
override fun yes() {
|
|
||||||
viewModel.manuallyVerified()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun no() {
|
|
||||||
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
|
||||||
@OnClick(R.id.sas_cancel_button)
|
|
||||||
fun doCancel() {
|
|
||||||
// Transaction may be started, or not
|
|
||||||
viewModel.cancelTransaction()
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,41 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2019 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.riotx.features.crypto.verification
|
|
||||||
|
|
||||||
import android.os.Bundle
|
|
||||||
import butterknife.OnClick
|
|
||||||
import im.vector.riotx.R
|
|
||||||
import im.vector.riotx.core.platform.VectorBaseFragment
|
|
||||||
import javax.inject.Inject
|
|
||||||
|
|
||||||
// TODO Deprecated("replaced by bottomsheet UX")
|
|
||||||
class SASVerificationVerifiedFragment @Inject constructor() : VectorBaseFragment() {
|
|
||||||
|
|
||||||
override fun getLayoutResId() = R.layout.fragment_sas_verification_verified
|
|
||||||
|
|
||||||
private lateinit var viewModel: SasVerificationViewModel
|
|
||||||
|
|
||||||
override fun onActivityCreated(savedInstanceState: Bundle?) {
|
|
||||||
super.onActivityCreated(savedInstanceState)
|
|
||||||
|
|
||||||
viewModel = activityViewModelProvider.get(SasVerificationViewModel::class.java)
|
|
||||||
}
|
|
||||||
|
|
||||||
@OnClick(R.id.sas_verification_verified_done_button)
|
|
||||||
fun onDone() {
|
|
||||||
viewModel.finishSuccess()
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,153 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2019 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.riotx.features.crypto.verification
|
|
||||||
|
|
||||||
import androidx.lifecycle.LiveData
|
|
||||||
import androidx.lifecycle.MutableLiveData
|
|
||||||
import androidx.lifecycle.ViewModel
|
|
||||||
import im.vector.matrix.android.api.session.Session
|
|
||||||
import im.vector.matrix.android.api.session.crypto.sas.IncomingSasVerificationTransaction
|
|
||||||
import im.vector.matrix.android.api.session.crypto.sas.SasVerificationService
|
|
||||||
import im.vector.matrix.android.api.session.crypto.sas.SasVerificationTransaction
|
|
||||||
import im.vector.matrix.android.api.session.crypto.sas.SasVerificationTxState
|
|
||||||
import im.vector.matrix.android.api.session.user.model.User
|
|
||||||
import im.vector.riotx.core.utils.LiveEvent
|
|
||||||
import javax.inject.Inject
|
|
||||||
|
|
||||||
// TODO Deprecated("replaced by bottomsheet UX")
|
|
||||||
class SasVerificationViewModel @Inject constructor() : ViewModel(),
|
|
||||||
SasVerificationService.SasVerificationListener {
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
const val NAVIGATE_FINISH = "NAVIGATE_FINISH"
|
|
||||||
const val NAVIGATE_FINISH_SUCCESS = "NAVIGATE_FINISH_SUCCESS"
|
|
||||||
const val NAVIGATE_SAS_DISPLAY = "NAVIGATE_SAS_DISPLAY"
|
|
||||||
const val NAVIGATE_SUCCESS = "NAVIGATE_SUCCESS"
|
|
||||||
const val NAVIGATE_CANCELLED = "NAVIGATE_CANCELLED"
|
|
||||||
}
|
|
||||||
|
|
||||||
private lateinit var sasVerificationService: SasVerificationService
|
|
||||||
|
|
||||||
var otherUserId: String? = null
|
|
||||||
var otherDeviceId: String? = null
|
|
||||||
var otherUser: User? = null
|
|
||||||
var transaction: SasVerificationTransaction? = null
|
|
||||||
|
|
||||||
var transactionState: MutableLiveData<SasVerificationTxState> = MutableLiveData()
|
|
||||||
|
|
||||||
init {
|
|
||||||
// Force a first observe
|
|
||||||
transactionState.value = null
|
|
||||||
}
|
|
||||||
|
|
||||||
private var _navigateEvent: MutableLiveData<LiveEvent<String>> = MutableLiveData()
|
|
||||||
val navigateEvent: LiveData<LiveEvent<String>>
|
|
||||||
get() = _navigateEvent
|
|
||||||
|
|
||||||
var loadingLiveEvent: MutableLiveData<Int> = MutableLiveData()
|
|
||||||
|
|
||||||
var transactionID: String? = null
|
|
||||||
set(value) {
|
|
||||||
if (value != null) {
|
|
||||||
transaction = sasVerificationService.getExistingTransaction(otherUserId!!, value)
|
|
||||||
transactionState.value = transaction?.state
|
|
||||||
otherDeviceId = transaction?.otherDeviceId
|
|
||||||
}
|
|
||||||
field = value
|
|
||||||
}
|
|
||||||
|
|
||||||
fun initIncoming(session: Session, otherUserId: String, transactionID: String?) {
|
|
||||||
this.sasVerificationService = session.getSasVerificationService()
|
|
||||||
this.otherUserId = otherUserId
|
|
||||||
this.transactionID = transactionID
|
|
||||||
this.sasVerificationService.addListener(this)
|
|
||||||
this.otherUser = session.getUser(otherUserId)
|
|
||||||
if (transactionID == null || transaction == null) {
|
|
||||||
// sanity, this transaction is not known anymore
|
|
||||||
_navigateEvent.value = LiveEvent(NAVIGATE_FINISH)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun initOutgoing(session: Session, otherUserId: String, otherDeviceId: String) {
|
|
||||||
this.sasVerificationService = session.getSasVerificationService()
|
|
||||||
this.otherUserId = otherUserId
|
|
||||||
this.otherDeviceId = otherDeviceId
|
|
||||||
this.sasVerificationService.addListener(this)
|
|
||||||
this.otherUser = session.getUser(otherUserId)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun beginSasKeyVerification() {
|
|
||||||
val verificationSAS = sasVerificationService.beginKeyVerificationSAS(otherUserId!!, otherDeviceId!!)
|
|
||||||
this.transactionID = verificationSAS
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun transactionCreated(tx: SasVerificationTransaction) {
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun transactionUpdated(tx: SasVerificationTransaction) {
|
|
||||||
if (transactionID == tx.transactionId) {
|
|
||||||
transactionState.value = tx.state
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun markedAsManuallyVerified(userId: String, deviceId: String) {
|
|
||||||
}
|
|
||||||
|
|
||||||
fun cancelTransaction() {
|
|
||||||
transaction?.cancel()
|
|
||||||
_navigateEvent.value = LiveEvent(NAVIGATE_FINISH)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun finishSuccess() {
|
|
||||||
_navigateEvent.value = LiveEvent(NAVIGATE_FINISH_SUCCESS)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun manuallyVerified() {
|
|
||||||
if (otherUserId != null && otherDeviceId != null) {
|
|
||||||
sasVerificationService.markedLocallyAsManuallyVerified(otherUserId!!, otherDeviceId!!)
|
|
||||||
}
|
|
||||||
_navigateEvent.value = LiveEvent(NAVIGATE_FINISH_SUCCESS)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun acceptTransaction() {
|
|
||||||
(transaction as? IncomingSasVerificationTransaction)?.performAccept()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun confirmEmojiSame() {
|
|
||||||
transaction?.userHasVerifiedShortCode()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun shortCodeReady() {
|
|
||||||
loadingLiveEvent.value = null
|
|
||||||
_navigateEvent.value = LiveEvent(NAVIGATE_SAS_DISPLAY)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun deviceIsVerified() {
|
|
||||||
loadingLiveEvent.value = null
|
|
||||||
_navigateEvent.value = LiveEvent(NAVIGATE_SUCCESS)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun navigateCancel() {
|
|
||||||
_navigateEvent.value = LiveEvent(NAVIGATE_CANCELLED)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onCleared() {
|
|
||||||
super.onCleared()
|
|
||||||
if (::sasVerificationService.isInitialized) {
|
|
||||||
sasVerificationService.removeListener(this)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -67,6 +67,6 @@ sealed class RoomDetailAction : VectorViewModelAction {
|
||||||
|
|
||||||
data class AcceptVerificationRequest(val transactionId: String, val otherUserId: String, val otherdDeviceId: String) : RoomDetailAction()
|
data class AcceptVerificationRequest(val transactionId: String, val otherUserId: String, val otherdDeviceId: String) : RoomDetailAction()
|
||||||
data class DeclineVerificationRequest(val transactionId: String, val otherUserId: String, val otherdDeviceId: String) : RoomDetailAction()
|
data class DeclineVerificationRequest(val transactionId: String, val otherUserId: String, val otherdDeviceId: String) : RoomDetailAction()
|
||||||
|
|
||||||
data class RequestVerification(val userId: String) : RoomDetailAction()
|
data class RequestVerification(val userId: String) : RoomDetailAction()
|
||||||
|
data class ResumeVerification(val transactionId: String, val otherUserId: String? = null, val otherdDeviceId: String? = null) : RoomDetailAction()
|
||||||
}
|
}
|
||||||
|
|
|
@ -109,7 +109,7 @@ class RoomDetailActivity : VectorBaseActivity(), ToolbarConfigurable {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
private const val EXTRA_ROOM_DETAIL_ARGS = "EXTRA_ROOM_DETAIL_ARGS"
|
const val EXTRA_ROOM_DETAIL_ARGS = "EXTRA_ROOM_DETAIL_ARGS"
|
||||||
|
|
||||||
fun newIntent(context: Context, roomDetailArgs: RoomDetailArgs): Intent {
|
fun newIntent(context: Context, roomDetailArgs: RoomDetailArgs): Intent {
|
||||||
return Intent(context, RoomDetailActivity::class.java).apply {
|
return Intent(context, RoomDetailActivity::class.java).apply {
|
||||||
|
|
|
@ -849,6 +849,15 @@ class RoomDetailFragment @Inject constructor(
|
||||||
data.transactionId
|
data.transactionId
|
||||||
).show(parentFragmentManager, "REQ")
|
).show(parentFragmentManager, "REQ")
|
||||||
}
|
}
|
||||||
|
is RoomDetailAction.ResumeVerification -> {
|
||||||
|
val otherUserId = data.otherUserId ?: return
|
||||||
|
VerificationBottomSheet().apply {
|
||||||
|
arguments = Bundle().apply {
|
||||||
|
putParcelable(MvRx.KEY_ARG, VerificationBottomSheet.VerificationArgs(
|
||||||
|
otherUserId, data.transactionId, roomId = roomDetailArgs.roomId))
|
||||||
|
}
|
||||||
|
}.show(parentFragmentManager, "REQ")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -998,6 +1007,9 @@ class RoomDetailFragment @Inject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onEventCellClicked(informationData: MessageInformationData, messageContent: MessageContent?, view: View) {
|
override fun onEventCellClicked(informationData: MessageInformationData, messageContent: MessageContent?, view: View) {
|
||||||
|
if (messageContent is MessageVerificationRequestContent) {
|
||||||
|
roomDetailViewModel.handle(RoomDetailAction.ResumeVerification(informationData.eventId))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onEventLongClicked(informationData: MessageInformationData, messageContent: MessageContent?, view: View): Boolean {
|
override fun onEventLongClicked(informationData: MessageInformationData, messageContent: MessageContent?, view: View): Boolean {
|
||||||
|
|
|
@ -187,6 +187,7 @@ class RoomDetailViewModel @AssistedInject constructor(@Assisted initialState: Ro
|
||||||
is RoomDetailAction.AcceptVerificationRequest -> handleAcceptVerification(action)
|
is RoomDetailAction.AcceptVerificationRequest -> handleAcceptVerification(action)
|
||||||
is RoomDetailAction.DeclineVerificationRequest -> handleDeclineVerification(action)
|
is RoomDetailAction.DeclineVerificationRequest -> handleDeclineVerification(action)
|
||||||
is RoomDetailAction.RequestVerification -> handleRequestVerification(action)
|
is RoomDetailAction.RequestVerification -> handleRequestVerification(action)
|
||||||
|
is RoomDetailAction.ResumeVerification -> handleResumeRequestVerification(action)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -824,6 +825,18 @@ class RoomDetailViewModel @AssistedInject constructor(@Assisted initialState: Ro
|
||||||
_requestLiveData.postValue(LiveEvent(Success(action)))
|
_requestLiveData.postValue(LiveEvent(Success(action)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun handleResumeRequestVerification(action: RoomDetailAction.ResumeVerification) {
|
||||||
|
// Check if this request is still active and handled by me
|
||||||
|
session.getSasVerificationService().getExistingVerificationRequestInRoom(room.roomId, action.transactionId)?.let {
|
||||||
|
if (it.handledByOtherSession) return
|
||||||
|
if (!it.isFinished) {
|
||||||
|
_requestLiveData.postValue(LiveEvent(Success(action.copy(
|
||||||
|
otherUserId = it.otherUserId
|
||||||
|
))))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun observeSyncState() {
|
private fun observeSyncState() {
|
||||||
session.rx()
|
session.rx()
|
||||||
.liveSyncState()
|
.liveSyncState()
|
||||||
|
|
|
@ -20,12 +20,12 @@ import android.os.Build
|
||||||
import android.os.Handler
|
import android.os.Handler
|
||||||
import android.os.Looper
|
import android.os.Looper
|
||||||
import android.view.View
|
import android.view.View
|
||||||
|
import androidx.annotation.ColorInt
|
||||||
import androidx.annotation.ColorRes
|
import androidx.annotation.ColorRes
|
||||||
import androidx.annotation.DrawableRes
|
import androidx.annotation.DrawableRes
|
||||||
import com.tapadoo.alerter.Alerter
|
import com.tapadoo.alerter.Alerter
|
||||||
import com.tapadoo.alerter.OnHideAlertListener
|
import com.tapadoo.alerter.OnHideAlertListener
|
||||||
import im.vector.riotx.R
|
import im.vector.riotx.R
|
||||||
import im.vector.riotx.features.crypto.verification.SASVerificationActivity
|
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import java.lang.ref.WeakReference
|
import java.lang.ref.WeakReference
|
||||||
|
|
||||||
|
@ -78,8 +78,7 @@ object PopupAlertManager {
|
||||||
setLightStatusBar()
|
setLightStatusBar()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (currentAlerter?.shouldBeDisplayedIn?.invoke(activity) == false) {
|
||||||
if (shouldIgnoreActivity(activity)) {
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -108,8 +107,6 @@ object PopupAlertManager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun shouldIgnoreActivity(activity: Activity) = activity is SASVerificationActivity
|
|
||||||
|
|
||||||
private fun displayNextIfPossible() {
|
private fun displayNextIfPossible() {
|
||||||
val currentActivity = weakCurrentActivity?.get()
|
val currentActivity = weakCurrentActivity?.get()
|
||||||
if (Alerter.isShowing || currentActivity == null) {
|
if (Alerter.isShowing || currentActivity == null) {
|
||||||
|
@ -209,7 +206,13 @@ object PopupAlertManager {
|
||||||
})
|
})
|
||||||
.enableSwipeToDismiss()
|
.enableSwipeToDismiss()
|
||||||
.enableInfiniteDuration(true)
|
.enableInfiniteDuration(true)
|
||||||
.setBackgroundColorRes(alert.colorRes ?: R.color.notification_accent_color)
|
.apply {
|
||||||
|
if (alert.colorInt != null) {
|
||||||
|
setBackgroundColorInt(alert.colorInt!!)
|
||||||
|
} else {
|
||||||
|
setBackgroundColorRes(alert.colorRes ?: R.color.notification_accent_color)
|
||||||
|
}
|
||||||
|
}
|
||||||
.show()
|
.show()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -229,7 +232,8 @@ object PopupAlertManager {
|
||||||
data class VectorAlert(val uid: String,
|
data class VectorAlert(val uid: String,
|
||||||
val title: String,
|
val title: String,
|
||||||
val description: String,
|
val description: String,
|
||||||
@DrawableRes val iconId: Int?) {
|
@DrawableRes val iconId: Int?,
|
||||||
|
val shouldBeDisplayedIn: ((Activity) -> Boolean)? = null) {
|
||||||
|
|
||||||
data class Button(val title: String, val action: Runnable, val autoClose: Boolean)
|
data class Button(val title: String, val action: Runnable, val autoClose: Boolean)
|
||||||
|
|
||||||
|
@ -250,5 +254,8 @@ object PopupAlertManager {
|
||||||
|
|
||||||
@ColorRes
|
@ColorRes
|
||||||
var colorRes: Int? = null
|
var colorRes: Int? = null
|
||||||
|
|
||||||
|
@ColorInt
|
||||||
|
var colorInt: Int? = null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,132 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:background="?android:colorBackground">
|
|
||||||
|
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/sas_emoji_description"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_margin="@dimen/layout_horizontal_margin"
|
|
||||||
android:layout_marginTop="@dimen/layout_vertical_margin"
|
|
||||||
android:gravity="center"
|
|
||||||
android:textColor="?riotx_text_primary"
|
|
||||||
android:textSize="16sp"
|
|
||||||
android:textStyle="bold"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
|
||||||
tools:text="@string/sas_emoji_description" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/sas_emoji_description_2"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_margin="@dimen/layout_vertical_margin"
|
|
||||||
android:gravity="center"
|
|
||||||
android:text="@string/sas_security_advise"
|
|
||||||
android:textColor="?riotx_text_secondary"
|
|
||||||
android:textSize="15sp"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toBottomOf="@id/sas_emoji_description" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/sas_decimal_code"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="center"
|
|
||||||
android:textColor="?riotx_text_primary"
|
|
||||||
android:textSize="28sp"
|
|
||||||
android:textStyle="bold"
|
|
||||||
android:visibility="invisible"
|
|
||||||
app:layout_constraintBottom_toBottomOf="@+id/sas_emoji_grid"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="@+id/sas_emoji_grid"
|
|
||||||
tools:text="1234-4320-3905"
|
|
||||||
tools:visibility="visible" />
|
|
||||||
|
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout
|
|
||||||
android:id="@+id/sas_emoji_grid"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_margin="@dimen/layout_vertical_margin"
|
|
||||||
android:visibility="invisible"
|
|
||||||
app:layout_constrainedWidth="true"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toBottomOf="@+id/sas_emoji_description_2"
|
|
||||||
tools:visibility="visible">
|
|
||||||
|
|
||||||
<include
|
|
||||||
android:id="@+id/emoji0"
|
|
||||||
layout="@layout/item_emoji_verif" />
|
|
||||||
|
|
||||||
<include
|
|
||||||
android:id="@+id/emoji1"
|
|
||||||
layout="@layout/item_emoji_verif" />
|
|
||||||
|
|
||||||
<include
|
|
||||||
android:id="@+id/emoji2"
|
|
||||||
layout="@layout/item_emoji_verif" />
|
|
||||||
|
|
||||||
<include
|
|
||||||
android:id="@+id/emoji3"
|
|
||||||
layout="@layout/item_emoji_verif" />
|
|
||||||
|
|
||||||
<include
|
|
||||||
android:id="@+id/emoji4"
|
|
||||||
layout="@layout/item_emoji_verif" />
|
|
||||||
|
|
||||||
<include
|
|
||||||
android:id="@+id/emoji5"
|
|
||||||
layout="@layout/item_emoji_verif" />
|
|
||||||
|
|
||||||
<include
|
|
||||||
android:id="@+id/emoji6"
|
|
||||||
layout="@layout/item_emoji_verif" />
|
|
||||||
|
|
||||||
<androidx.constraintlayout.helper.widget.Flow
|
|
||||||
android:id="@+id/sas_emoji_grid_flow"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
app:constraint_referenced_ids="emoji0,emoji1,emoji2,emoji3,emoji4,emoji5,emoji6"
|
|
||||||
app:flow_horizontalBias="0.5"
|
|
||||||
app:flow_horizontalGap="16dp"
|
|
||||||
app:flow_horizontalStyle="packed"
|
|
||||||
app:flow_verticalBias="0"
|
|
||||||
app:flow_verticalGap="8dp"
|
|
||||||
app:flow_wrapMode="chain"
|
|
||||||
tools:ignore="MissingConstraints" />
|
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
|
||||||
android:id="@+id/sas_request_continue_button"
|
|
||||||
style="@style/VectorButtonStyle"
|
|
||||||
android:layout_margin="@dimen/layout_vertical_margin"
|
|
||||||
android:minWidth="160dp"
|
|
||||||
android:text="@string/_continue"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintTop_toBottomOf="@+id/sas_emoji_grid" />
|
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
|
||||||
android:id="@+id/sas_request_cancel_button"
|
|
||||||
style="@style/VectorButtonStyleText"
|
|
||||||
android:layout_margin="@dimen/layout_vertical_margin"
|
|
||||||
android:text="@string/cancel"
|
|
||||||
app:layout_constraintEnd_toStartOf="@+id/sas_request_continue_button"
|
|
||||||
app:layout_constraintTop_toBottomOf="@+id/sas_emoji_grid" />
|
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
||||||
|
|
||||||
</ScrollView>
|
|
|
@ -1,132 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent">
|
|
||||||
|
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/sas_incoming_request_title"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginStart="20dp"
|
|
||||||
android:layout_marginLeft="20dp"
|
|
||||||
android:layout_marginTop="30dp"
|
|
||||||
android:layout_marginEnd="20dp"
|
|
||||||
android:layout_marginRight="20dp"
|
|
||||||
android:layout_marginBottom="16dp"
|
|
||||||
android:gravity="center"
|
|
||||||
android:text="@string/sas_incoming_request_title"
|
|
||||||
android:textAlignment="center"
|
|
||||||
android:textColor="?riotx_text_primary"
|
|
||||||
android:textSize="17sp"
|
|
||||||
android:textStyle="bold"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/sas_incoming_request_user_avatar"
|
|
||||||
android:layout_width="120dp"
|
|
||||||
android:layout_height="120dp"
|
|
||||||
android:layout_marginTop="@dimen/layout_vertical_margin"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toBottomOf="@+id/sas_incoming_request_title"
|
|
||||||
tools:src="@tools:sample/avatars" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/sas_incoming_request_user_display_name"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="8dp"
|
|
||||||
android:textAlignment="center"
|
|
||||||
android:textColor="?riotx_text_primary"
|
|
||||||
android:textSize="18sp"
|
|
||||||
android:textStyle="bold"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toBottomOf="@id/sas_incoming_request_user_avatar"
|
|
||||||
tools:text="User name" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/sas_incoming_request_user_id"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:textAlignment="center"
|
|
||||||
android:textColor="?riotx_text_secondary"
|
|
||||||
android:textSize="13sp"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toBottomOf="@id/sas_incoming_request_user_display_name"
|
|
||||||
tools:text="\@foo:matrix.org" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/sas_incoming_request_user_device"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="8dp"
|
|
||||||
android:textAlignment="center"
|
|
||||||
android:textColor="?riotx_text_secondary"
|
|
||||||
android:textSize="15sp"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toBottomOf="@id/sas_incoming_request_user_id"
|
|
||||||
tools:text="Device: Mobile" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/sas_incoming_request_description"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_margin="@dimen/layout_vertical_margin"
|
|
||||||
android:text="@string/sas_incoming_request_description"
|
|
||||||
android:textAlignment="center"
|
|
||||||
android:textColor="?riotx_text_secondary"
|
|
||||||
android:textSize="15sp"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toBottomOf="@id/sas_incoming_request_user_device" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/sas_incoming_request_description_2"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_margin="@dimen/layout_vertical_margin"
|
|
||||||
android:text="@string/sas_incoming_request_description_2"
|
|
||||||
android:textAlignment="center"
|
|
||||||
android:textColor="?riotx_text_secondary"
|
|
||||||
android:textSize="15sp"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toBottomOf="@id/sas_incoming_request_description" />
|
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
|
||||||
android:id="@+id/sas_request_continue_button"
|
|
||||||
style="@style/VectorButtonStyle"
|
|
||||||
android:layout_marginTop="@dimen/layout_vertical_margin_big"
|
|
||||||
android:layout_marginEnd="@dimen/layout_vertical_margin"
|
|
||||||
android:layout_marginRight="@dimen/layout_vertical_margin"
|
|
||||||
android:layout_marginBottom="@dimen/layout_vertical_margin"
|
|
||||||
android:minWidth="160dp"
|
|
||||||
android:text="@string/_continue"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintTop_toBottomOf="@+id/sas_incoming_request_description_2" />
|
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
|
||||||
android:id="@+id/sas_request_cancel_button"
|
|
||||||
style="@style/VectorButtonStyleText"
|
|
||||||
android:layout_gravity="end"
|
|
||||||
android:layout_marginEnd="@dimen/layout_vertical_margin"
|
|
||||||
android:layout_marginRight="@dimen/layout_vertical_margin"
|
|
||||||
android:text="@string/cancel"
|
|
||||||
app:layout_constraintEnd_toStartOf="@+id/sas_request_continue_button"
|
|
||||||
app:layout_constraintTop_toTopOf="@+id/sas_request_continue_button" />
|
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
||||||
|
|
||||||
</ScrollView>
|
|
|
@ -1,89 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent">
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:id="@+id/rootLayout"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:orientation="vertical">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/sas_verification_title"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_margin="16dp"
|
|
||||||
android:text="@string/sas_verify_title"
|
|
||||||
android:textColor="?riotx_text_primary"
|
|
||||||
android:textSize="16sp"
|
|
||||||
android:textStyle="bold" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/sas_verification_description"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_margin="16dp"
|
|
||||||
android:text="@string/sas_security_advise"
|
|
||||||
android:textColor="?riotx_text_secondary" />
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="end"
|
|
||||||
android:orientation="horizontal">
|
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
|
||||||
android:id="@+id/sas_cancel_button"
|
|
||||||
style="@style/VectorButtonStyleText"
|
|
||||||
android:layout_marginEnd="8dp"
|
|
||||||
android:layout_marginRight="8dp"
|
|
||||||
android:text="@string/cancel" />
|
|
||||||
|
|
||||||
<FrameLayout
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginEnd="@dimen/layout_horizontal_margin"
|
|
||||||
android:layout_marginRight="@dimen/layout_horizontal_margin">
|
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
|
||||||
android:id="@+id/sas_start_button"
|
|
||||||
style="@style/VectorButtonStyle"
|
|
||||||
android:minWidth="160dp"
|
|
||||||
android:text="@string/sas_verify_start_button_title" />
|
|
||||||
|
|
||||||
<ProgressBar
|
|
||||||
android:id="@+id/sas_start_button_loading"
|
|
||||||
android:layout_width="19dp"
|
|
||||||
android:layout_height="20dp"
|
|
||||||
android:layout_gravity="center"
|
|
||||||
android:indeterminate="true"
|
|
||||||
android:visibility="gone"
|
|
||||||
tools:visibility="visible" />
|
|
||||||
|
|
||||||
</FrameLayout>
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
|
||||||
android:id="@+id/sas_legacy_verification"
|
|
||||||
style="@style/VectorButtonStyleText"
|
|
||||||
android:layout_gravity="end"
|
|
||||||
android:layout_margin="@dimen/layout_horizontal_margin"
|
|
||||||
android:text="@string/sas_legacy_verification_button_title"
|
|
||||||
android:visibility="visible" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/sas_verifying_keys"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_margin="16dp"
|
|
||||||
android:text="@string/sas_verifying_keys"
|
|
||||||
android:textColor="?riotx_text_secondary"
|
|
||||||
android:visibility="gone"
|
|
||||||
tools:visibility="visible" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
</ScrollView>
|
|
|
@ -1,69 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:background="?android:colorBackground">
|
|
||||||
|
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/sas_verification_verified_title"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginStart="20dp"
|
|
||||||
android:layout_marginTop="30dp"
|
|
||||||
android:layout_marginEnd="20dp"
|
|
||||||
android:layout_marginBottom="16dp"
|
|
||||||
android:text="@string/sas_verified"
|
|
||||||
android:textColor="?riotx_text_primary"
|
|
||||||
android:textSize="18sp"
|
|
||||||
android:textStyle="bold"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/sas_verification_verified_description"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_margin="@dimen/layout_vertical_margin"
|
|
||||||
android:gravity="center"
|
|
||||||
android:text="@string/sas_verified_successful"
|
|
||||||
android:textColor="?riotx_text_secondary"
|
|
||||||
android:textSize="15sp"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toBottomOf="@id/sas_verification_verified_title" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/sas_verification_verified_description_2"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_margin="@dimen/layout_vertical_margin"
|
|
||||||
android:gravity="center"
|
|
||||||
android:text="@string/sas_verified_successful_description"
|
|
||||||
android:textColor="?riotx_text_secondary"
|
|
||||||
android:textSize="15sp"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toBottomOf="@id/sas_verification_verified_description" />
|
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
|
||||||
android:id="@+id/sas_verification_verified_done_button"
|
|
||||||
style="@style/VectorButtonStyle"
|
|
||||||
android:layout_marginTop="@dimen/layout_vertical_margin_big"
|
|
||||||
android:layout_marginEnd="@dimen/layout_vertical_margin"
|
|
||||||
android:layout_marginRight="@dimen/layout_vertical_margin"
|
|
||||||
android:layout_marginBottom="@dimen/layout_vertical_margin"
|
|
||||||
android:minWidth="160dp"
|
|
||||||
android:text="@string/sas_got_it"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintTop_toBottomOf="@+id/sas_verification_verified_description_2" />
|
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
||||||
|
|
||||||
</ScrollView>
|
|
Loading…
Reference in a new issue