mirror of
https://github.com/SchildiChat/SchildiChat-android.git
synced 2024-11-26 03:16:02 +03:00
Keys share request handling
This commit is contained in:
parent
a7c0e87f40
commit
480d197ffa
9 changed files with 316 additions and 6 deletions
|
@ -28,6 +28,7 @@ import im.vector.matrix.android.internal.crypto.MXEventDecryptionResult
|
||||||
import im.vector.matrix.android.internal.crypto.model.ImportRoomKeysResult
|
import im.vector.matrix.android.internal.crypto.model.ImportRoomKeysResult
|
||||||
import im.vector.matrix.android.internal.crypto.model.MXDeviceInfo
|
import im.vector.matrix.android.internal.crypto.model.MXDeviceInfo
|
||||||
import im.vector.matrix.android.internal.crypto.model.MXEncryptEventContentResult
|
import im.vector.matrix.android.internal.crypto.model.MXEncryptEventContentResult
|
||||||
|
import im.vector.matrix.android.internal.crypto.model.MXUsersDevicesMap
|
||||||
import im.vector.matrix.android.internal.crypto.model.rest.DevicesListResponse
|
import im.vector.matrix.android.internal.crypto.model.rest.DevicesListResponse
|
||||||
import im.vector.matrix.android.internal.crypto.model.rest.RoomKeyRequestBody
|
import im.vector.matrix.android.internal.crypto.model.rest.RoomKeyRequestBody
|
||||||
|
|
||||||
|
@ -99,4 +100,7 @@ interface CryptoService {
|
||||||
fun getEncryptionAlgorithm(roomId: String): String?
|
fun getEncryptionAlgorithm(roomId: String): String?
|
||||||
|
|
||||||
fun shouldEncryptForInvitedMembers(roomId: String): Boolean
|
fun shouldEncryptForInvitedMembers(roomId: String): Boolean
|
||||||
|
|
||||||
|
fun downloadKeys(userIds: List<String>, forceDownload: Boolean, callback: MatrixCallback<MXUsersDevicesMap<MXDeviceInfo>>)
|
||||||
|
|
||||||
}
|
}
|
|
@ -1050,12 +1050,22 @@ internal class CryptoManager(
|
||||||
return unknownDevices
|
return unknownDevices
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ==========================================================================================
|
override fun downloadKeys(userIds: List<String>, forceDownload: Boolean, callback: MatrixCallback<MXUsersDevicesMap<MXDeviceInfo>>) {
|
||||||
* DEBUG INFO
|
CoroutineScope(coroutineDispatchers.crypto).launch {
|
||||||
* ========================================================================================== */
|
deviceListManager
|
||||||
|
.downloadKeys(userIds, forceDownload)
|
||||||
|
.fold(
|
||||||
|
{ callback.onFailure(it) },
|
||||||
|
{ callback.onSuccess(it) }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ==========================================================================================
|
||||||
|
* DEBUG INFO
|
||||||
|
* ========================================================================================== */
|
||||||
|
|
||||||
override fun toString(): String {
|
override fun toString(): String {
|
||||||
return "CryptoManager of " + credentials.userId + " (" + credentials.deviceId + ")"
|
return "CryptoManager of " + credentials.userId + " (" + credentials.deviceId + ")"
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,7 @@ import com.squareup.moshi.JsonClass
|
||||||
*/
|
*/
|
||||||
@JsonClass(generateAdapter = true)
|
@JsonClass(generateAdapter = true)
|
||||||
data class RoomKeyRequestBody(
|
data class RoomKeyRequestBody(
|
||||||
|
@Json(name = "algorithm")
|
||||||
var algorithm: String? = null,
|
var algorithm: String? = null,
|
||||||
|
|
||||||
@Json(name = "room_id")
|
@Json(name = "room_id")
|
||||||
|
|
|
@ -56,6 +56,7 @@ import im.vector.matrix.android.internal.crypto.MXEventDecryptionResult
|
||||||
import im.vector.matrix.android.internal.crypto.model.ImportRoomKeysResult
|
import im.vector.matrix.android.internal.crypto.model.ImportRoomKeysResult
|
||||||
import im.vector.matrix.android.internal.crypto.model.MXDeviceInfo
|
import im.vector.matrix.android.internal.crypto.model.MXDeviceInfo
|
||||||
import im.vector.matrix.android.internal.crypto.model.MXEncryptEventContentResult
|
import im.vector.matrix.android.internal.crypto.model.MXEncryptEventContentResult
|
||||||
|
import im.vector.matrix.android.internal.crypto.model.MXUsersDevicesMap
|
||||||
import im.vector.matrix.android.internal.crypto.model.rest.DevicesListResponse
|
import im.vector.matrix.android.internal.crypto.model.rest.DevicesListResponse
|
||||||
import im.vector.matrix.android.internal.crypto.model.rest.RoomKeyRequestBody
|
import im.vector.matrix.android.internal.crypto.model.rest.RoomKeyRequestBody
|
||||||
import im.vector.matrix.android.internal.database.LiveEntityObserver
|
import im.vector.matrix.android.internal.database.LiveEntityObserver
|
||||||
|
@ -390,6 +391,10 @@ internal class DefaultSession(override val sessionParams: SessionParams) : Sessi
|
||||||
return cryptoService.shouldEncryptForInvitedMembers(roomId)
|
return cryptoService.shouldEncryptForInvitedMembers(roomId)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun downloadKeys(userIds: List<String>, forceDownload: Boolean, callback: MatrixCallback<MXUsersDevicesMap<MXDeviceInfo>>) {
|
||||||
|
cryptoService.downloadKeys(userIds, forceDownload, callback)
|
||||||
|
}
|
||||||
|
|
||||||
// Private methods *****************************************************************************
|
// Private methods *****************************************************************************
|
||||||
|
|
||||||
private fun assertMainThread() {
|
private fun assertMainThread() {
|
||||||
|
|
|
@ -25,6 +25,7 @@ import im.vector.riotredesign.core.resources.LocaleProvider
|
||||||
import im.vector.riotredesign.core.resources.StringArrayProvider
|
import im.vector.riotredesign.core.resources.StringArrayProvider
|
||||||
import im.vector.riotredesign.core.resources.StringProvider
|
import im.vector.riotredesign.core.resources.StringProvider
|
||||||
import im.vector.riotredesign.features.configuration.VectorConfiguration
|
import im.vector.riotredesign.features.configuration.VectorConfiguration
|
||||||
|
import im.vector.riotredesign.features.crypto.keysrequest.KeyRequestHandler
|
||||||
import im.vector.riotredesign.features.crypto.verification.IncomingVerificationRequestHandler
|
import im.vector.riotredesign.features.crypto.verification.IncomingVerificationRequestHandler
|
||||||
import im.vector.riotredesign.features.home.HomeRoomListObservableStore
|
import im.vector.riotredesign.features.home.HomeRoomListObservableStore
|
||||||
import im.vector.riotredesign.features.home.group.SelectedGroupStore
|
import im.vector.riotredesign.features.home.group.SelectedGroupStore
|
||||||
|
@ -87,6 +88,10 @@ class AppModule(private val context: Context) {
|
||||||
Matrix.getInstance().currentSession!!
|
Matrix.getInstance().currentSession!!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
single {
|
||||||
|
KeyRequestHandler(context, get())
|
||||||
|
}
|
||||||
|
|
||||||
single {
|
single {
|
||||||
IncomingVerificationRequestHandler(context, get())
|
IncomingVerificationRequestHandler(context, get())
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,279 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2016 OpenMarket Ltd
|
||||||
|
* Copyright 2017 Vector Creations Ltd
|
||||||
|
* Copyright 2018 New Vector Ltd
|
||||||
|
* 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.riotredesign.features.crypto.keysrequest
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.text.TextUtils
|
||||||
|
import im.vector.matrix.android.api.MatrixCallback
|
||||||
|
import im.vector.matrix.android.api.session.Session
|
||||||
|
import im.vector.matrix.android.api.session.crypto.keyshare.RoomKeysRequestListener
|
||||||
|
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.internal.crypto.IncomingRoomKeyRequest
|
||||||
|
import im.vector.matrix.android.internal.crypto.IncomingRoomKeyRequestCancellation
|
||||||
|
import im.vector.matrix.android.internal.crypto.model.MXDeviceInfo
|
||||||
|
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.DevicesListResponse
|
||||||
|
import im.vector.riotredesign.R
|
||||||
|
import im.vector.riotredesign.features.crypto.verification.SASVerificationActivity
|
||||||
|
import im.vector.riotredesign.features.popup.PopupAlertManager
|
||||||
|
import timber.log.Timber
|
||||||
|
import java.text.DateFormat
|
||||||
|
import java.text.SimpleDateFormat
|
||||||
|
import java.util.*
|
||||||
|
import kotlin.collections.ArrayList
|
||||||
|
import kotlin.collections.HashMap
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Manage the key share events.
|
||||||
|
* Listens for incoming key request and display an alert to the user asking him to ignore / verify
|
||||||
|
* calling device / or accept without verifying.
|
||||||
|
* If several requests come from same user/device, a single alert is displayed (this alert will accept/reject all request
|
||||||
|
* depending on user action)
|
||||||
|
*/
|
||||||
|
class KeyRequestHandler(val context: Context,
|
||||||
|
val session: Session)
|
||||||
|
: RoomKeysRequestListener,
|
||||||
|
SasVerificationService.SasVerificationListener {
|
||||||
|
|
||||||
|
private val alertsToRequests = HashMap<String, ArrayList<IncomingRoomKeyRequest>>()
|
||||||
|
|
||||||
|
init {
|
||||||
|
session.getSasVerificationService().addListener(this)
|
||||||
|
|
||||||
|
session.addRoomKeysRequestListener(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ensureStarted() = Unit
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle incoming key request.
|
||||||
|
*
|
||||||
|
* @param request the key request.
|
||||||
|
*/
|
||||||
|
override fun onRoomKeyRequest(request: IncomingRoomKeyRequest) {
|
||||||
|
val userId = request.userId
|
||||||
|
val deviceId = request.deviceId
|
||||||
|
val requestId = request.requestId
|
||||||
|
|
||||||
|
if (userId.isNullOrBlank() || deviceId.isNullOrBlank() || requestId.isNullOrBlank()) {
|
||||||
|
Timber.e("## handleKeyRequest() : invalid parameters")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
//Do we already have alerts for this user/device
|
||||||
|
val mappingKey = keyForMap(deviceId, userId)
|
||||||
|
if (alertsToRequests.containsKey(mappingKey)) {
|
||||||
|
//just add the request, there is already an alert for this
|
||||||
|
alertsToRequests[mappingKey]?.add(request)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
alertsToRequests[mappingKey] = ArrayList<IncomingRoomKeyRequest>().apply { this.add(request) }
|
||||||
|
|
||||||
|
//Add a notification for every incoming request
|
||||||
|
session.downloadKeys(Arrays.asList(userId), false, object : MatrixCallback<MXUsersDevicesMap<MXDeviceInfo>> {
|
||||||
|
override fun onSuccess(data: MXUsersDevicesMap<MXDeviceInfo>) {
|
||||||
|
val deviceInfo = data.getObject(deviceId, userId)
|
||||||
|
|
||||||
|
if (null == deviceInfo) {
|
||||||
|
Timber.e("## displayKeyShareDialog() : No details found for device $userId:$deviceId")
|
||||||
|
//ignore
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (deviceInfo.isUnknown) {
|
||||||
|
session.setDeviceVerification(MXDeviceInfo.DEVICE_VERIFICATION_UNVERIFIED, deviceId, userId)
|
||||||
|
|
||||||
|
deviceInfo.verified = MXDeviceInfo.DEVICE_VERIFICATION_UNVERIFIED
|
||||||
|
|
||||||
|
//can we get more info on this device?
|
||||||
|
session.getDevicesList(object : MatrixCallback<DevicesListResponse> {
|
||||||
|
override fun onSuccess(data: DevicesListResponse) {
|
||||||
|
data.devices?.find { it.deviceId == deviceId }?.let {
|
||||||
|
postAlert(context, userId, deviceId, true, deviceInfo, it)
|
||||||
|
} ?: run {
|
||||||
|
postAlert(context, userId, deviceId, true, deviceInfo)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onFailure(failure: Throwable) {
|
||||||
|
postAlert(context, userId, deviceId, true, deviceInfo)
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
postAlert(context, userId, deviceId, false, deviceInfo)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onFailure(failure: Throwable) {
|
||||||
|
//ignore
|
||||||
|
Timber.e(failure, "## displayKeyShareDialog : downloadKeys")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun postAlert(context: Context,
|
||||||
|
userId: String,
|
||||||
|
deviceId: String,
|
||||||
|
wasNewDevice: Boolean,
|
||||||
|
deviceInfo: MXDeviceInfo?,
|
||||||
|
moreInfo: DeviceInfo? = null) {
|
||||||
|
val deviceName = if (TextUtils.isEmpty(deviceInfo!!.displayName())) deviceInfo.deviceId else deviceInfo.displayName()
|
||||||
|
val dialogText: String?
|
||||||
|
|
||||||
|
if (moreInfo != null) {
|
||||||
|
val lastSeenIp = if (moreInfo.lastSeenIp.isNullOrBlank()) {
|
||||||
|
context.getString(R.string.encryption_information_unknown_ip)
|
||||||
|
} else {
|
||||||
|
moreInfo.lastSeenIp
|
||||||
|
}
|
||||||
|
|
||||||
|
val lastSeenTime = moreInfo.lastSeenTs?.let { ts ->
|
||||||
|
val dateFormatTime = SimpleDateFormat("HH:mm:ss", Locale.getDefault())
|
||||||
|
val date = Date(ts)
|
||||||
|
|
||||||
|
val time = dateFormatTime.format(date)
|
||||||
|
val dateFormat = DateFormat.getDateInstance(DateFormat.SHORT, Locale.getDefault())
|
||||||
|
|
||||||
|
dateFormat.format(date) + ", " + time
|
||||||
|
} ?: "-"
|
||||||
|
|
||||||
|
val lastSeenInfo = context.getString(R.string.devices_details_last_seen_format, lastSeenIp, lastSeenTime)
|
||||||
|
dialogText = if (wasNewDevice) {
|
||||||
|
context.getString(R.string.you_added_a_new_device_with_info, deviceName, lastSeenInfo)
|
||||||
|
} else {
|
||||||
|
context.getString(R.string.your_unverified_device_requesting_with_info, deviceName, lastSeenInfo)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
dialogText = if (wasNewDevice) {
|
||||||
|
context.getString(R.string.you_added_a_new_device, deviceName)
|
||||||
|
} else {
|
||||||
|
context.getString(R.string.your_unverified_device_requesting, deviceName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
val alert = PopupAlertManager.VectorAlert(
|
||||||
|
alertManagerId(deviceId, userId),
|
||||||
|
context.getString(R.string.key_share_request),
|
||||||
|
dialogText,
|
||||||
|
R.drawable.key_small
|
||||||
|
)
|
||||||
|
|
||||||
|
alert.colorRes = R.color.key_share_req_accent_color
|
||||||
|
|
||||||
|
val mappingKey = keyForMap(deviceId, userId)
|
||||||
|
alert.dismissedAction = Runnable {
|
||||||
|
denyAllRequests(mappingKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
alert.addButton(
|
||||||
|
context.getString(R.string.start_verification_short_label),
|
||||||
|
Runnable {
|
||||||
|
alert.weakCurrentActivity?.get()?.let {
|
||||||
|
val intent = SASVerificationActivity.outgoingIntent(it,
|
||||||
|
session.sessionParams.credentials.userId,
|
||||||
|
userId, deviceId)
|
||||||
|
it.startActivity(intent)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
false
|
||||||
|
)
|
||||||
|
|
||||||
|
alert.addButton(context.getString(R.string.share_without_verifying_short_label), Runnable {
|
||||||
|
shareAllSessions(mappingKey)
|
||||||
|
})
|
||||||
|
|
||||||
|
alert.addButton(context.getString(R.string.ignore_request_short_label), Runnable {
|
||||||
|
denyAllRequests(mappingKey)
|
||||||
|
})
|
||||||
|
|
||||||
|
PopupAlertManager.postVectorAlert(alert)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun denyAllRequests(mappingKey: String) {
|
||||||
|
alertsToRequests[mappingKey]?.forEach {
|
||||||
|
it.ignore?.run()
|
||||||
|
}
|
||||||
|
alertsToRequests.remove(mappingKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun shareAllSessions(mappingKey: String) {
|
||||||
|
alertsToRequests[mappingKey]?.forEach {
|
||||||
|
it.share?.run()
|
||||||
|
}
|
||||||
|
alertsToRequests.remove(mappingKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Manage a cancellation request.
|
||||||
|
*
|
||||||
|
* @param request the cancellation request.
|
||||||
|
*/
|
||||||
|
override fun onRoomKeyRequestCancellation(request: IncomingRoomKeyRequestCancellation) {
|
||||||
|
// see if we can find the request in the queue
|
||||||
|
val userId = request.userId
|
||||||
|
val deviceId = request.deviceId
|
||||||
|
val requestId = request.requestId
|
||||||
|
|
||||||
|
if (TextUtils.isEmpty(userId) || TextUtils.isEmpty(deviceId) || TextUtils.isEmpty(requestId)) {
|
||||||
|
Timber.e("## handleKeyRequestCancellation() : invalid parameters")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val alertMgrUniqueKey = alertManagerId(deviceId!!, userId!!)
|
||||||
|
alertsToRequests[alertMgrUniqueKey]?.removeAll {
|
||||||
|
it.deviceId == request.deviceId
|
||||||
|
&& it.userId == request.userId
|
||||||
|
&& it.requestId == request.requestId
|
||||||
|
}
|
||||||
|
if (alertsToRequests[alertMgrUniqueKey]?.isEmpty() == true) {
|
||||||
|
PopupAlertManager.cancelAlert(alertMgrUniqueKey)
|
||||||
|
alertsToRequests.remove(keyForMap(deviceId, userId))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun transactionCreated(tx: SasVerificationTransaction) {
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun transactionUpdated(tx: SasVerificationTransaction) {
|
||||||
|
val state = tx.state
|
||||||
|
if (state == SasVerificationTxState.Verified) {
|
||||||
|
//ok it's verified, see if we have key request for that
|
||||||
|
shareAllSessions("${tx.otherDeviceId}${tx.otherUserId}")
|
||||||
|
PopupAlertManager.cancelAlert("ikr_${tx.otherDeviceId}${tx.otherUserId}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun markedAsManuallyVerified(userId: String, deviceId: String) {
|
||||||
|
//accept related requests
|
||||||
|
shareAllSessions(keyForMap(deviceId, userId))
|
||||||
|
PopupAlertManager.cancelAlert(alertManagerId(deviceId, userId))
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun keyForMap(deviceId: String, userId: String) = "$deviceId$userId"
|
||||||
|
|
||||||
|
private fun alertManagerId(deviceId: String, userId: String) = "ikr_$deviceId$userId"
|
||||||
|
}
|
|
@ -30,10 +30,12 @@ import im.vector.riotredesign.features.popup.PopupAlertManager
|
||||||
class IncomingVerificationRequestHandler(val context: Context,
|
class IncomingVerificationRequestHandler(val context: Context,
|
||||||
private val session: Session) : SasVerificationService.SasVerificationListener {
|
private val session: Session) : SasVerificationService.SasVerificationListener {
|
||||||
|
|
||||||
fun ensureStarted() {
|
init {
|
||||||
session.getSasVerificationService().addListener(this)
|
session.getSasVerificationService().addListener(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun ensureStarted() = Unit
|
||||||
|
|
||||||
override fun transactionCreated(tx: SasVerificationTransaction) {}
|
override fun transactionCreated(tx: SasVerificationTransaction) {}
|
||||||
|
|
||||||
override fun transactionUpdated(tx: SasVerificationTransaction) {
|
override fun transactionUpdated(tx: SasVerificationTransaction) {
|
||||||
|
|
|
@ -37,6 +37,7 @@ import im.vector.riotredesign.core.extensions.replaceFragment
|
||||||
import im.vector.riotredesign.core.platform.OnBackPressed
|
import im.vector.riotredesign.core.platform.OnBackPressed
|
||||||
import im.vector.riotredesign.core.platform.ToolbarConfigurable
|
import im.vector.riotredesign.core.platform.ToolbarConfigurable
|
||||||
import im.vector.riotredesign.core.platform.VectorBaseActivity
|
import im.vector.riotredesign.core.platform.VectorBaseActivity
|
||||||
|
import im.vector.riotredesign.features.crypto.keysrequest.KeyRequestHandler
|
||||||
import im.vector.riotredesign.features.crypto.verification.IncomingVerificationRequestHandler
|
import im.vector.riotredesign.features.crypto.verification.IncomingVerificationRequestHandler
|
||||||
import im.vector.riotredesign.features.rageshake.BugReporter
|
import im.vector.riotredesign.features.rageshake.BugReporter
|
||||||
import im.vector.riotredesign.features.rageshake.VectorUncaughtExceptionHandler
|
import im.vector.riotredesign.features.rageshake.VectorUncaughtExceptionHandler
|
||||||
|
@ -60,6 +61,8 @@ class HomeActivity : VectorBaseActivity(), ToolbarConfigurable {
|
||||||
|
|
||||||
// TODO Move this elsewhere
|
// TODO Move this elsewhere
|
||||||
private val incomingVerificationRequestHandler by inject<IncomingVerificationRequestHandler>()
|
private val incomingVerificationRequestHandler by inject<IncomingVerificationRequestHandler>()
|
||||||
|
// TODO Move this elsewhere
|
||||||
|
private val keyRequestHandler by inject<KeyRequestHandler>()
|
||||||
|
|
||||||
private var progress: ProgressDialog? = null
|
private var progress: ProgressDialog? = null
|
||||||
|
|
||||||
|
@ -105,6 +108,7 @@ class HomeActivity : VectorBaseActivity(), ToolbarConfigurable {
|
||||||
}
|
}
|
||||||
|
|
||||||
incomingVerificationRequestHandler.ensureStarted()
|
incomingVerificationRequestHandler.ensureStarted()
|
||||||
|
keyRequestHandler.ensureStarted()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDestroy() {
|
override fun onDestroy() {
|
||||||
|
|
|
@ -131,6 +131,6 @@
|
||||||
|
|
||||||
<!-- Notification (do not depends on theme -->
|
<!-- Notification (do not depends on theme -->
|
||||||
<color name="notification_accent_color">#368BD6</color>
|
<color name="notification_accent_color">#368BD6</color>
|
||||||
|
<color name="key_share_req_accent_color">#ff812d</color>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|
Loading…
Reference in a new issue