mirror of
https://github.com/oxen-io/session-android.git
synced 2024-11-30 21:45:20 +00:00
Somewhat simplify device linking UI
This commit is contained in:
parent
a44c3fcd57
commit
ac9c9f534e
@ -2,22 +2,16 @@ package org.thoughtcrime.securesms.loki
|
|||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.support.v7.app.AlertDialog
|
import android.support.v7.app.AlertDialog
|
||||||
import org.thoughtcrime.securesms.crypto.IdentityKeyUtil
|
|
||||||
import org.thoughtcrime.securesms.database.DatabaseFactory
|
import org.thoughtcrime.securesms.database.DatabaseFactory
|
||||||
import org.thoughtcrime.securesms.logging.Log
|
|
||||||
import org.thoughtcrime.securesms.util.Util
|
import org.thoughtcrime.securesms.util.Util
|
||||||
import org.whispersystems.signalservice.loki.api.DeviceLinkingSession
|
import org.whispersystems.signalservice.loki.api.DeviceLinkingSession
|
||||||
import org.whispersystems.signalservice.loki.api.DeviceLinkingSessionListener
|
import org.whispersystems.signalservice.loki.api.DeviceLinkingSessionListener
|
||||||
import org.whispersystems.signalservice.loki.api.LokiStorageAPI
|
|
||||||
import org.whispersystems.signalservice.loki.api.PairingAuthorisation
|
import org.whispersystems.signalservice.loki.api.PairingAuthorisation
|
||||||
import org.whispersystems.signalservice.loki.utilities.retryIfNeeded
|
|
||||||
|
|
||||||
class DeviceLinkingDialog private constructor(private val context: Context, private val mode: DeviceLinkingView.Mode, private val delegate: DeviceLinkingDialogDelegate?) : DeviceLinkingViewDelegate, DeviceLinkingSessionListener {
|
class DeviceLinkingDialog private constructor(private val context: Context, private val mode: DeviceLinkingView.Mode, private val delegate: DeviceLinkingDialogDelegate?) : DeviceLinkingViewDelegate, DeviceLinkingSessionListener {
|
||||||
private lateinit var view: DeviceLinkingView
|
private lateinit var view: DeviceLinkingView
|
||||||
private lateinit var dialog: AlertDialog
|
private lateinit var dialog: AlertDialog
|
||||||
|
|
||||||
private val userPrivateKey = IdentityKeyUtil.getIdentityKeyPair(context).privateKey.serialize()
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
fun show(context: Context, mode: DeviceLinkingView.Mode, delegate: DeviceLinkingDialogDelegate?): DeviceLinkingDialog {
|
fun show(context: Context, mode: DeviceLinkingView.Mode, delegate: DeviceLinkingDialogDelegate?): DeviceLinkingDialog {
|
||||||
@ -31,42 +25,18 @@ class DeviceLinkingDialog private constructor(private val context: Context, priv
|
|||||||
view = DeviceLinkingView(context, mode, this)
|
view = DeviceLinkingView(context, mode, this)
|
||||||
dialog = AlertDialog.Builder(context).setView(view).show()
|
dialog = AlertDialog.Builder(context).setView(view).show()
|
||||||
view.dismiss = { dismiss() }
|
view.dismiss = { dismiss() }
|
||||||
startListening()
|
|
||||||
}
|
|
||||||
|
|
||||||
public fun dismiss() {
|
|
||||||
stopListening()
|
|
||||||
dialog.dismiss()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun startListening() {
|
|
||||||
DeviceLinkingSession.shared.startListeningForLinkingRequests()
|
DeviceLinkingSession.shared.startListeningForLinkingRequests()
|
||||||
DeviceLinkingSession.shared.addListener(this)
|
DeviceLinkingSession.shared.addListener(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun stopListening() {
|
private fun dismiss() {
|
||||||
DeviceLinkingSession.shared.stopListeningForLinkingRequests()
|
DeviceLinkingSession.shared.stopListeningForLinkingRequests()
|
||||||
DeviceLinkingSession.shared.removeListener(this)
|
DeviceLinkingSession.shared.removeListener(this)
|
||||||
|
dialog.dismiss()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun sendPairingAuthorizedMessage(pairing: PairingAuthorisation): Boolean {
|
override fun handleDeviceLinkAuthorized(pairingAuthorisation: PairingAuthorisation) {
|
||||||
val signedAuthorisation = pairing.sign(PairingAuthorisation.Type.GRANT, userPrivateKey)
|
delegate?.handleDeviceLinkAuthorized(pairingAuthorisation)
|
||||||
if (signedAuthorisation == null || signedAuthorisation.type != PairingAuthorisation.Type.GRANT) {
|
|
||||||
Log.d("Loki", "Failed to sign pairing authorization.")
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
retryIfNeeded(8) {
|
|
||||||
sendPairingAuthorisationMessage(context, pairing.secondaryDevicePublicKey, signedAuthorisation).get()
|
|
||||||
}.fail {
|
|
||||||
Log.d("Loki", "Failed to send pairing authorization message to ${pairing.secondaryDevicePublicKey}.")
|
|
||||||
}
|
|
||||||
DatabaseFactory.getLokiAPIDatabase(context).insertOrUpdatePairingAuthorisation(signedAuthorisation)
|
|
||||||
LokiStorageAPI.shared.updateUserDeviceMappings()
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun handleDeviceLinkAuthorized(pairing: PairingAuthorisation) {
|
|
||||||
delegate?.handleDeviceLinkAuthorized(pairing)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun handleDeviceLinkingDialogDismissed() {
|
override fun handleDeviceLinkingDialogDismissed() {
|
||||||
@ -77,6 +47,10 @@ class DeviceLinkingDialog private constructor(private val context: Context, priv
|
|||||||
delegate?.handleDeviceLinkingDialogDismissed()
|
delegate?.handleDeviceLinkingDialogDismissed()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun sendPairingAuthorizedMessage(pairingAuthorisation: PairingAuthorisation) {
|
||||||
|
delegate?.sendPairingAuthorizedMessage(pairingAuthorisation)
|
||||||
|
}
|
||||||
|
|
||||||
override fun requestUserAuthorization(authorisation: PairingAuthorisation) {
|
override fun requestUserAuthorization(authorisation: PairingAuthorisation) {
|
||||||
Util.runOnMain {
|
Util.runOnMain {
|
||||||
view.requestUserAuthorization(authorisation)
|
view.requestUserAuthorization(authorisation)
|
||||||
|
@ -4,6 +4,7 @@ import org.whispersystems.signalservice.loki.api.PairingAuthorisation
|
|||||||
|
|
||||||
interface DeviceLinkingDialogDelegate {
|
interface DeviceLinkingDialogDelegate {
|
||||||
|
|
||||||
fun handleDeviceLinkAuthorized(pairing: PairingAuthorisation) { }
|
fun handleDeviceLinkAuthorized(pairingAuthorisation: PairingAuthorisation) { }
|
||||||
fun handleDeviceLinkingDialogDismissed() { }
|
fun handleDeviceLinkingDialogDismissed() { }
|
||||||
|
fun sendPairingAuthorizedMessage(pairingAuthorisation: PairingAuthorisation) { }
|
||||||
}
|
}
|
@ -82,11 +82,9 @@ class DeviceLinkingView private constructor(context: Context, attrs: AttributeSe
|
|||||||
// endregion
|
// endregion
|
||||||
|
|
||||||
// region Device Linking
|
// region Device Linking
|
||||||
fun requestUserAuthorization(authorisation: PairingAuthorisation) {
|
fun requestUserAuthorization(pairingAuthorisation: PairingAuthorisation) {
|
||||||
if (mode != Mode.Master) { throw IllegalStateException() }
|
if (mode != Mode.Master || pairingAuthorisation.type != PairingAuthorisation.Type.REQUEST || this.pairingAuthorisation != null) { return }
|
||||||
if (authorisation.type != PairingAuthorisation.Type.REQUEST) { throw IllegalStateException() }
|
this.pairingAuthorisation = pairingAuthorisation
|
||||||
if (pairingAuthorisation != null) { return }
|
|
||||||
pairingAuthorisation = authorisation
|
|
||||||
spinner.visibility = View.GONE
|
spinner.visibility = View.GONE
|
||||||
val titleTextViewLayoutParams = titleTextView.layoutParams as LayoutParams
|
val titleTextViewLayoutParams = titleTextView.layoutParams as LayoutParams
|
||||||
titleTextViewLayoutParams.topMargin = toPx(16, resources)
|
titleTextViewLayoutParams.topMargin = toPx(16, resources)
|
||||||
@ -94,14 +92,14 @@ class DeviceLinkingView private constructor(context: Context, attrs: AttributeSe
|
|||||||
titleTextView.text = resources.getString(R.string.view_device_linking_title_3)
|
titleTextView.text = resources.getString(R.string.view_device_linking_title_3)
|
||||||
explanationTextView.text = resources.getString(R.string.view_device_linking_explanation_2)
|
explanationTextView.text = resources.getString(R.string.view_device_linking_explanation_2)
|
||||||
mnemonicTextView.visibility = View.VISIBLE
|
mnemonicTextView.visibility = View.VISIBLE
|
||||||
val hexEncodedPublicKey = authorisation.secondaryDevicePublicKey.removing05PrefixIfNeeded()
|
val hexEncodedPublicKey = pairingAuthorisation.secondaryDevicePublicKey.removing05PrefixIfNeeded()
|
||||||
mnemonicTextView.text = MnemonicCodec(languageFileDirectory).encode(hexEncodedPublicKey).split(" ").slice(0 until 3).joinToString(" ")
|
mnemonicTextView.text = MnemonicCodec(languageFileDirectory).encode(hexEncodedPublicKey).split(" ").slice(0 until 3).joinToString(" ")
|
||||||
authorizeButton.visibility = View.VISIBLE
|
authorizeButton.visibility = View.VISIBLE
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onDeviceLinkAuthorized(authorisation: PairingAuthorisation) {
|
fun onDeviceLinkAuthorized(pairingAuthorisation: PairingAuthorisation) {
|
||||||
if (mode != Mode.Slave || pairingAuthorisation != null) { return }
|
if (mode != Mode.Slave || pairingAuthorisation.type != PairingAuthorisation.Type.GRANT || this.pairingAuthorisation != null) { return }
|
||||||
pairingAuthorisation = authorisation
|
this.pairingAuthorisation = pairingAuthorisation
|
||||||
spinner.visibility = View.GONE
|
spinner.visibility = View.GONE
|
||||||
val titleTextViewLayoutParams = titleTextView.layoutParams as LayoutParams
|
val titleTextViewLayoutParams = titleTextView.layoutParams as LayoutParams
|
||||||
titleTextViewLayoutParams.topMargin = toPx(8, resources)
|
titleTextViewLayoutParams.topMargin = toPx(8, resources)
|
||||||
@ -116,7 +114,7 @@ class DeviceLinkingView private constructor(context: Context, attrs: AttributeSe
|
|||||||
buttonContainer.visibility = View.GONE
|
buttonContainer.visibility = View.GONE
|
||||||
cancelButton.visibility = View.GONE
|
cancelButton.visibility = View.GONE
|
||||||
Handler().postDelayed({
|
Handler().postDelayed({
|
||||||
delegate.handleDeviceLinkAuthorized(authorisation)
|
delegate.handleDeviceLinkAuthorized(pairingAuthorisation)
|
||||||
dismiss?.invoke()
|
dismiss?.invoke()
|
||||||
}, 4000)
|
}, 4000)
|
||||||
}
|
}
|
||||||
@ -124,12 +122,12 @@ class DeviceLinkingView private constructor(context: Context, attrs: AttributeSe
|
|||||||
|
|
||||||
// region Interaction
|
// region Interaction
|
||||||
private fun authorizePairing() {
|
private fun authorizePairing() {
|
||||||
if (pairingAuthorisation == null || mode != Mode.Master ) { return; }
|
val pairingAuthorisation = this.pairingAuthorisation
|
||||||
if (delegate.sendPairingAuthorizedMessage(pairingAuthorisation!!)) {
|
if (mode != Mode.Master || pairingAuthorisation == null) { return; }
|
||||||
delegate.handleDeviceLinkAuthorized(pairingAuthorisation!!)
|
delegate.sendPairingAuthorizedMessage(pairingAuthorisation)
|
||||||
|
delegate.handleDeviceLinkAuthorized(pairingAuthorisation)
|
||||||
dismiss?.invoke()
|
dismiss?.invoke()
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private fun cancel() {
|
private fun cancel() {
|
||||||
delegate.handleDeviceLinkingDialogDismissed()
|
delegate.handleDeviceLinkingDialogDismissed()
|
||||||
|
@ -4,7 +4,7 @@ import org.whispersystems.signalservice.loki.api.PairingAuthorisation
|
|||||||
|
|
||||||
interface DeviceLinkingViewDelegate {
|
interface DeviceLinkingViewDelegate {
|
||||||
|
|
||||||
fun handleDeviceLinkAuthorized(pairing: PairingAuthorisation) { }
|
fun handleDeviceLinkAuthorized(pairingAuthorisation: PairingAuthorisation) { }
|
||||||
fun handleDeviceLinkingDialogDismissed() { }
|
fun handleDeviceLinkingDialogDismissed() { }
|
||||||
fun sendPairingAuthorizedMessage(pairing: PairingAuthorisation): Boolean { return false }
|
fun sendPairingAuthorizedMessage(pairingAuthorisation: PairingAuthorisation) { }
|
||||||
}
|
}
|
@ -57,7 +57,6 @@ fun shouldAutomaticallyBecomeFriendsWithDevice(publicKey: String, context: Conte
|
|||||||
}
|
}
|
||||||
deferred.resolve(lokiThreadDatabase.getFriendRequestStatus(threadID) == LokiThreadFriendRequestStatus.FRIENDS)
|
deferred.resolve(lokiThreadDatabase.getFriendRequestStatus(threadID) == LokiThreadFriendRequestStatus.FRIENDS)
|
||||||
}
|
}
|
||||||
|
|
||||||
return deferred.promise
|
return deferred.promise
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,6 +25,7 @@ import org.thoughtcrime.securesms.util.Hex
|
|||||||
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
||||||
import org.whispersystems.curve25519.Curve25519
|
import org.whispersystems.curve25519.Curve25519
|
||||||
import org.whispersystems.libsignal.util.KeyHelper
|
import org.whispersystems.libsignal.util.KeyHelper
|
||||||
|
import org.whispersystems.signalservice.loki.api.LokiStorageAPI
|
||||||
import org.whispersystems.signalservice.loki.api.PairingAuthorisation
|
import org.whispersystems.signalservice.loki.api.PairingAuthorisation
|
||||||
import org.whispersystems.signalservice.loki.crypto.MnemonicCodec
|
import org.whispersystems.signalservice.loki.crypto.MnemonicCodec
|
||||||
import org.whispersystems.signalservice.loki.utilities.Analytics
|
import org.whispersystems.signalservice.loki.utilities.Analytics
|
||||||
@ -217,10 +218,10 @@ class SeedActivity : BaseActionBarActivity(), DeviceLinkingDialogDelegate {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun handleDeviceLinkAuthorized(pairing: PairingAuthorisation) {
|
override fun handleDeviceLinkAuthorized(pairingAuthorisation: PairingAuthorisation) {
|
||||||
Analytics.shared.track("Device Linked Successfully")
|
Analytics.shared.track("Device Linked Successfully")
|
||||||
if (pairing.secondaryDevicePublicKey == TextSecurePreferences.getLocalNumber(this)) {
|
if (pairingAuthorisation.secondaryDevicePublicKey == TextSecurePreferences.getLocalNumber(this)) {
|
||||||
TextSecurePreferences.setMasterHexEncodedPublicKey(this, pairing.primaryDevicePublicKey)
|
TextSecurePreferences.setMasterHexEncodedPublicKey(this, pairingAuthorisation.primaryDevicePublicKey)
|
||||||
}
|
}
|
||||||
startActivity(Intent(this, ConversationListActivity::class.java))
|
startActivity(Intent(this, ConversationListActivity::class.java))
|
||||||
finish()
|
finish()
|
||||||
@ -230,6 +231,22 @@ class SeedActivity : BaseActionBarActivity(), DeviceLinkingDialogDelegate {
|
|||||||
resetForRegistration()
|
resetForRegistration()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun sendPairingAuthorizedMessage(pairingAuthorisation: PairingAuthorisation) {
|
||||||
|
val userPrivateKey = IdentityKeyUtil.getIdentityKeyPair(this).privateKey.serialize()
|
||||||
|
val signedPairingAuthorisation = pairingAuthorisation.sign(PairingAuthorisation.Type.GRANT, userPrivateKey)
|
||||||
|
if (signedPairingAuthorisation == null || signedPairingAuthorisation.type != PairingAuthorisation.Type.GRANT) {
|
||||||
|
Log.d("Loki", "Failed to sign pairing authorization.")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
retryIfNeeded(8) {
|
||||||
|
sendPairingAuthorisationMessage(this, pairingAuthorisation.secondaryDevicePublicKey, signedPairingAuthorisation).get()
|
||||||
|
}.fail {
|
||||||
|
Log.d("Loki", "Failed to send pairing authorization message to ${pairingAuthorisation.secondaryDevicePublicKey}.")
|
||||||
|
}
|
||||||
|
DatabaseFactory.getLokiAPIDatabase(this).insertOrUpdatePairingAuthorisation(signedPairingAuthorisation)
|
||||||
|
LokiStorageAPI.shared.updateUserDeviceMappings()
|
||||||
|
}
|
||||||
|
|
||||||
private fun resetForRegistration() {
|
private fun resetForRegistration() {
|
||||||
IdentityKeyUtil.delete(this, IdentityKeyUtil.lokiSeedKey)
|
IdentityKeyUtil.delete(this, IdentityKeyUtil.lokiSeedKey)
|
||||||
TextSecurePreferences.removeLocalRegistrationId(this)
|
TextSecurePreferences.removeLocalRegistrationId(this)
|
||||||
|
Loading…
Reference in New Issue
Block a user