2020-05-11 16:19:26 +10:00
|
|
|
package org.thoughtcrime.securesms.loki.dialogs
|
2020-01-09 15:52:40 +11:00
|
|
|
|
|
|
|
import android.app.Dialog
|
|
|
|
import android.graphics.Color
|
|
|
|
import android.graphics.drawable.ColorDrawable
|
|
|
|
import android.os.Bundle
|
|
|
|
import android.support.v4.app.DialogFragment
|
|
|
|
import android.support.v7.app.AlertDialog
|
|
|
|
import android.view.LayoutInflater
|
|
|
|
import android.view.View
|
|
|
|
import android.widget.LinearLayout
|
|
|
|
import kotlinx.android.synthetic.main.dialog_link_device_master_mode.view.*
|
|
|
|
import network.loki.messenger.R
|
2020-05-20 15:44:21 +10:00
|
|
|
import nl.komponents.kovenant.functional.bind
|
|
|
|
import nl.komponents.kovenant.ui.failUi
|
|
|
|
import nl.komponents.kovenant.ui.successUi
|
2020-01-09 15:52:40 +11:00
|
|
|
import org.thoughtcrime.securesms.database.DatabaseFactory
|
2020-05-20 15:44:21 +10:00
|
|
|
import org.thoughtcrime.securesms.loki.protocol.MultiDeviceProtocol
|
2020-05-11 16:19:26 +10:00
|
|
|
import org.thoughtcrime.securesms.loki.utilities.MnemonicUtilities
|
|
|
|
import org.thoughtcrime.securesms.loki.utilities.QRCodeUtilities
|
2020-05-20 15:44:21 +10:00
|
|
|
import org.thoughtcrime.securesms.loki.utilities.toPx
|
2020-01-09 15:52:40 +11:00
|
|
|
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
|
|
|
import org.thoughtcrime.securesms.util.Util
|
2020-05-20 15:44:21 +10:00
|
|
|
import org.whispersystems.signalservice.loki.api.LokiAPI
|
|
|
|
import org.whispersystems.signalservice.loki.api.fileserver.LokiFileServerAPI
|
2020-05-11 16:19:26 +10:00
|
|
|
import org.whispersystems.signalservice.loki.crypto.MnemonicCodec
|
2020-05-07 17:59:41 +10:00
|
|
|
import org.whispersystems.signalservice.loki.protocol.multidevice.DeviceLink
|
|
|
|
import org.whispersystems.signalservice.loki.protocol.multidevice.DeviceLinkingSession
|
|
|
|
import org.whispersystems.signalservice.loki.protocol.multidevice.DeviceLinkingSessionListener
|
2020-01-09 15:52:40 +11:00
|
|
|
|
|
|
|
class LinkDeviceMasterModeDialog : DialogFragment(), DeviceLinkingSessionListener {
|
|
|
|
private val languageFileDirectory by lazy { MnemonicUtilities.getLanguageFileDirectory(context!!) }
|
|
|
|
private lateinit var contentView: View
|
2020-02-12 16:42:33 +11:00
|
|
|
private var deviceLink: DeviceLink? = null
|
2020-01-09 15:52:40 +11:00
|
|
|
var delegate: LinkDeviceMasterModeDialogDelegate? = null
|
|
|
|
|
|
|
|
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
|
|
|
val builder = AlertDialog.Builder(context!!)
|
|
|
|
contentView = LayoutInflater.from(context!!).inflate(R.layout.dialog_link_device_master_mode, null)
|
|
|
|
val size = toPx(128, resources)
|
|
|
|
val hexEncodedPublicKey = TextSecurePreferences.getLocalNumber(context!!)
|
2020-01-17 14:24:33 +11:00
|
|
|
val qrCode = QRCodeUtilities.encode(hexEncodedPublicKey, size, false, false)
|
2020-01-09 15:52:40 +11:00
|
|
|
contentView.qrCodeImageView.setImageBitmap(qrCode)
|
|
|
|
contentView.cancelButton.setOnClickListener { onDeviceLinkCanceled() }
|
|
|
|
contentView.authorizeButton.setOnClickListener { authorizeDeviceLink() }
|
|
|
|
builder.setView(contentView)
|
|
|
|
DeviceLinkingSession.shared.startListeningForLinkingRequests() // FIXME: This flag is named poorly as it's actually also used for authorizations
|
|
|
|
DeviceLinkingSession.shared.addListener(this)
|
|
|
|
val result = builder.create()
|
|
|
|
result.window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
|
|
|
|
return result
|
|
|
|
}
|
|
|
|
|
2020-02-12 16:42:33 +11:00
|
|
|
override fun requestUserAuthorization(deviceLink: DeviceLink) {
|
|
|
|
if (deviceLink.type != DeviceLink.Type.REQUEST || deviceLink.masterHexEncodedPublicKey != TextSecurePreferences.getLocalNumber(context!!) || this.deviceLink != null) { return }
|
2020-01-09 15:52:40 +11:00
|
|
|
Util.runOnMain {
|
2020-02-12 16:42:33 +11:00
|
|
|
this.deviceLink = deviceLink
|
2020-01-09 15:52:40 +11:00
|
|
|
contentView.qrCodeImageView.visibility = View.GONE
|
|
|
|
val titleTextViewLayoutParams = contentView.titleTextView.layoutParams as LinearLayout.LayoutParams
|
|
|
|
titleTextViewLayoutParams.topMargin = toPx(8, resources)
|
|
|
|
contentView.titleTextView.layoutParams = titleTextViewLayoutParams
|
|
|
|
contentView.titleTextView.text = "Linking Request Received"
|
|
|
|
contentView.explanationTextView.text = "Please check that the words below match those shown on your other device"
|
|
|
|
contentView.mnemonicTextView.visibility = View.VISIBLE
|
2020-02-12 16:42:33 +11:00
|
|
|
contentView.mnemonicTextView.text = MnemonicUtilities.getFirst3Words(MnemonicCodec(languageFileDirectory), deviceLink.slaveHexEncodedPublicKey)
|
2020-01-09 15:52:40 +11:00
|
|
|
contentView.authorizeButton.visibility = View.VISIBLE
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private fun authorizeDeviceLink() {
|
2020-05-20 15:44:21 +10:00
|
|
|
val deviceLink = this.deviceLink ?: return
|
2020-01-09 15:52:40 +11:00
|
|
|
DeviceLinkingSession.shared.stopListeningForLinkingRequests()
|
|
|
|
DeviceLinkingSession.shared.removeListener(this)
|
2020-05-20 15:44:21 +10:00
|
|
|
Util.runOnMain {
|
|
|
|
contentView.qrCodeImageViewContainer.visibility = View.GONE
|
|
|
|
contentView.spinner.visibility = View.VISIBLE
|
|
|
|
val titleTextViewLayoutParams = contentView.titleTextView.layoutParams as LinearLayout.LayoutParams
|
|
|
|
titleTextViewLayoutParams.topMargin = toPx(24, resources)
|
|
|
|
contentView.titleTextView.layoutParams = titleTextViewLayoutParams
|
|
|
|
contentView.titleTextView.text = "Authorizing Device Link"
|
|
|
|
contentView.explanationTextView.text = "Please wait while the device link is created. This can take up to a minute."
|
|
|
|
contentView.mnemonicTextView.visibility = View.GONE
|
|
|
|
contentView.buttonContainer.visibility = View.GONE
|
|
|
|
contentView.cancelButton.visibility = View.GONE
|
|
|
|
contentView.authorizeButton.visibility = View.GONE
|
|
|
|
}
|
|
|
|
LokiFileServerAPI.shared.addDeviceLink(deviceLink).bind(LokiAPI.sharedContext) {
|
|
|
|
MultiDeviceProtocol.signAndSendDeviceLinkMessage(context!!, deviceLink)
|
|
|
|
}.success {
|
|
|
|
TextSecurePreferences.setMultiDevice(context!!, true)
|
|
|
|
}.successUi {
|
|
|
|
delegate?.onDeviceLinkRequestAuthorized()
|
|
|
|
dismiss()
|
|
|
|
}.fail {
|
|
|
|
LokiFileServerAPI.shared.removeDeviceLink(deviceLink) // If this fails we have a problem
|
|
|
|
DatabaseFactory.getLokiPreKeyBundleDatabase(context!!).removePreKeyBundle(deviceLink.slaveHexEncodedPublicKey)
|
|
|
|
}.failUi {
|
|
|
|
delegate?.onDeviceLinkAuthorizationFailed()
|
|
|
|
dismiss()
|
|
|
|
}
|
2020-01-09 15:52:40 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
private fun onDeviceLinkCanceled() {
|
|
|
|
DeviceLinkingSession.shared.stopListeningForLinkingRequests()
|
|
|
|
DeviceLinkingSession.shared.removeListener(this)
|
2020-02-12 16:42:33 +11:00
|
|
|
if (deviceLink != null) {
|
|
|
|
DatabaseFactory.getLokiPreKeyBundleDatabase(context).removePreKeyBundle(deviceLink!!.slaveHexEncodedPublicKey)
|
2020-01-09 15:52:40 +11:00
|
|
|
}
|
|
|
|
dismiss()
|
|
|
|
delegate?.onDeviceLinkCanceled()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
interface LinkDeviceMasterModeDialogDelegate {
|
|
|
|
|
2020-05-20 15:44:21 +10:00
|
|
|
fun onDeviceLinkRequestAuthorized()
|
|
|
|
fun onDeviceLinkAuthorizationFailed()
|
2020-01-09 15:52:40 +11:00
|
|
|
fun onDeviceLinkCanceled()
|
|
|
|
}
|