Implement linked devices screen redesign

This commit is contained in:
Niels Andriesse 2020-01-09 15:52:40 +11:00
parent 38f3c3cff6
commit 7424684c75
9 changed files with 295 additions and 3 deletions

View File

@ -160,6 +160,8 @@
android:name="org.thoughtcrime.securesms.loki.redesign.activities.NotificationSettingsActivity" /> android:name="org.thoughtcrime.securesms.loki.redesign.activities.NotificationSettingsActivity" />
<activity <activity
android:name="org.thoughtcrime.securesms.loki.redesign.activities.ChatSettingsActivity" /> android:name="org.thoughtcrime.securesms.loki.redesign.activities.ChatSettingsActivity" />
<activity
android:name="org.thoughtcrime.securesms.loki.redesign.activities.LinkedDevicesActivity" />
<!-- Session --> <!-- Session -->
<activity android:name="org.thoughtcrime.securesms.loki.LinkedDevicesActivity" /> <activity android:name="org.thoughtcrime.securesms.loki.LinkedDevicesActivity" />
<activity <activity

View File

@ -4,6 +4,6 @@
android:viewportWidth="24" android:viewportWidth="24"
android:viewportHeight="24"> android:viewportHeight="24">
<path <path
android:fillColor="#FF000000" android:fillColor="#FFFFFF"
android:pathData="M22,11.2l-9.2,0l0,-9.2l-1.6,0l0,9.2l-9.2,0l0,1.6l9.2,0l0,9.2l1.6,0l0,-9.2l9.2,0z"/> android:pathData="M22,11.2l-9.2,0l0,-9.2l-1.6,0l0,9.2l-9.2,0l0,1.6l9.2,0l0,9.2l1.6,0l0,-9.2l9.2,0z"/>
</vector> </vector>

View File

@ -3,9 +3,9 @@
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle"> android:shape="rectangle">
<solid android:color="@color/unimportant_dialog_button_background" /> <solid android:color="@color/accent" />
<corners android:radius="@dimen/dialog_button_corner_radius" /> <corners android:radius="@dimen/dialog_button_corner_radius" />
<stroke android:width="@dimen/border_thickness" android:color="@color/unimportant_dialog_button_background" /> <stroke android:width="@dimen/border_thickness" android:color="@color/accent" />
</shape> </shape>

View File

@ -0,0 +1,37 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/default_session_background">
<android.support.v7.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:orientation="vertical"
android:layout_centerInParent="true">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="@dimen/medium_font_size"
android:textColor="@color/text"
android:text="You don't have any linked devices yet" />
<Button
style="@style/MediumProminentOutlineButton"
android:id="@+id/linkDeviceButton"
android:layout_width="196dp"
android:layout_height="@dimen/medium_button_height"
android:layout_marginTop="@dimen/medium_spacing"
android:text="Link a Device" />
</LinearLayout>
</RelativeLayout>

View File

@ -0,0 +1,85 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/default_dialog_background_inset"
android:gravity="center_horizontal"
android:orientation="vertical"
android:paddingLeft="32dp"
android:paddingTop="@dimen/medium_spacing"
android:paddingRight="32dp"
android:paddingBottom="@dimen/medium_spacing">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/small_spacing"
android:gravity="center">
<ImageView
android:id="@+id/qrCodeImageView"
android:layout_width="128dp"
android:layout_height="128dp" />
</RelativeLayout>
<TextView
android:id="@+id/titleTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/large_spacing"
android:text="Waiting for Device"
android:textColor="@color/text"
android:textStyle="bold"
android:textSize="@dimen/medium_font_size" />
<TextView
android:id="@+id/explanationTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/large_spacing"
android:text="Create a new account on your other device and click &quot;Link to an existing account&quot; to start the linking process"
android:textColor="@color/text"
android:alpha="0.6"
android:textSize="@dimen/small_font_size"
android:textAlignment="center" />
<TextView
android:id="@+id/mnemonicTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:text="puffin circle idled"
android:textColor="@color/text"
android:textSize="@dimen/small_font_size"
android:textAlignment="center"
android:visibility="gone" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/large_spacing"
android:orientation="horizontal">
<Button
style="@style/UnimportantDialogButton"
android:id="@+id/cancelButton"
android:layout_width="0dp"
android:layout_height="@dimen/small_button_height"
android:layout_weight="1"
android:text="Cancel" />
<Button
style="@style/ProminentDialogButton"
android:id="@+id/authorizeButton"
android:layout_width="0dp"
android:layout_height="@dimen/small_button_height"
android:layout_weight="1"
android:layout_marginLeft="@dimen/medium_spacing"
android:text="Authorize"
android:visibility="gone" />
</LinearLayout>
</LinearLayout>

View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<menu
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/linkDeviceButton"
android:title="Link Device"
android:icon="@drawable/ic_plus_24"
app:showAsAction="always" />
</menu>

View File

@ -0,0 +1,63 @@
package org.thoughtcrime.securesms.loki.redesign.activities
import android.os.AsyncTask
import android.os.Bundle
import android.support.v7.widget.LinearLayoutManager
import android.view.Menu
import android.view.MenuItem
import kotlinx.android.synthetic.main.activity_linked_devices.*
import network.loki.messenger.R
import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity
import org.thoughtcrime.securesms.loki.redesign.dialogs.LinkDeviceMasterModeDialog
import org.thoughtcrime.securesms.loki.redesign.dialogs.LinkDeviceMasterModeDialogDelegate
import org.thoughtcrime.securesms.loki.signAndSendPairingAuthorisationMessage
import org.thoughtcrime.securesms.util.Util
import org.whispersystems.signalservice.loki.api.PairingAuthorisation
class LinkedDevicesActivity : PassphraseRequiredActionBarActivity, LinkDeviceMasterModeDialogDelegate {
constructor() : super()
override fun onCreate(savedInstanceState: Bundle?, isReady: Boolean) {
super.onCreate(savedInstanceState, isReady)
setContentView(R.layout.activity_linked_devices)
supportActionBar!!.title = "Linked Devices"
// val homeAdapter = LinkedDevicesAdapter(this, cursor)
// recyclerView.adapter = homeAdapter
recyclerView.layoutManager = LinearLayoutManager(this)
linkDeviceButton.setOnClickListener { linkDevice() }
}
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
menuInflater.inflate(R.menu.menu_linked_devices, menu)
return true
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
val id = item.itemId
when (id) {
R.id.linkDeviceButton -> linkDevice()
else -> { /* Do nothing */ }
}
return super.onOptionsItemSelected(item)
}
private fun linkDevice() {
val linkDeviceDialog = LinkDeviceMasterModeDialog()
linkDeviceDialog.delegate = this
linkDeviceDialog.show(supportFragmentManager, "Link Device Dialog")
}
override fun onDeviceLinkRequestAuthorized(authorization: PairingAuthorisation) {
AsyncTask.execute {
signAndSendPairingAuthorisationMessage(this, authorization)
Util.runOnMain {
}
}
}
override fun onDeviceLinkCanceled() {
// Do nothing
}
}

View File

@ -90,6 +90,7 @@ class SettingsActivity : PassphraseRequiredActionBarActivity() {
privacyButton.setOnClickListener { showPrivacySettings() } privacyButton.setOnClickListener { showPrivacySettings() }
notificationsButton.setOnClickListener { showNotificationSettings() } notificationsButton.setOnClickListener { showNotificationSettings() }
chatsButton.setOnClickListener { showChatSettings() } chatsButton.setOnClickListener { showChatSettings() }
linkedDevicesButton.setOnClickListener { showLinkedDevices() }
seedButton.setOnClickListener { showSeed() } seedButton.setOnClickListener { showSeed() }
clearAllDataButton.setOnClickListener { clearAllData() } clearAllDataButton.setOnClickListener { clearAllData() }
} }
@ -265,6 +266,11 @@ class SettingsActivity : PassphraseRequiredActionBarActivity() {
push(intent) push(intent)
} }
private fun showLinkedDevices() {
val intent = Intent(this, LinkedDevicesActivity::class.java)
push(intent)
}
private fun showSeed() { private fun showSeed() {
SeedDialog().show(supportFragmentManager, "Recovery Phrase Dialog") SeedDialog().show(supportFragmentManager, "Recovery Phrase Dialog")
} }

View File

@ -0,0 +1,87 @@
package org.thoughtcrime.securesms.loki.redesign.dialogs
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
import org.thoughtcrime.securesms.database.DatabaseFactory
import org.thoughtcrime.securesms.loki.MnemonicUtilities
import org.thoughtcrime.securesms.loki.redesign.utilities.QRCodeUtilities
import org.thoughtcrime.securesms.loki.toPx
import org.thoughtcrime.securesms.util.TextSecurePreferences
import org.thoughtcrime.securesms.util.Util
import org.whispersystems.signalservice.loki.api.DeviceLinkingSession
import org.whispersystems.signalservice.loki.api.DeviceLinkingSessionListener
import org.whispersystems.signalservice.loki.api.PairingAuthorisation
import org.whispersystems.signalservice.loki.crypto.MnemonicCodec
class LinkDeviceMasterModeDialog : DialogFragment(), DeviceLinkingSessionListener {
private val languageFileDirectory by lazy { MnemonicUtilities.getLanguageFileDirectory(context!!) }
private lateinit var contentView: View
private var authorization: PairingAuthorisation? = null
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!!)
val qrCode = QRCodeUtilities.encode(hexEncodedPublicKey, size)
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
}
override fun requestUserAuthorization(authorization: PairingAuthorisation) {
if (authorization.type != PairingAuthorisation.Type.REQUEST || authorization.primaryDevicePublicKey != TextSecurePreferences.getLocalNumber(context!!) || this.authorization != null) { return }
Util.runOnMain {
this.authorization = authorization
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
contentView.mnemonicTextView.text = MnemonicUtilities.getFirst3Words(MnemonicCodec(languageFileDirectory), authorization.secondaryDevicePublicKey)
contentView.authorizeButton.visibility = View.VISIBLE
}
}
private fun authorizeDeviceLink() {
val authorization = this.authorization ?: return
delegate?.onDeviceLinkRequestAuthorized(authorization)
DeviceLinkingSession.shared.stopListeningForLinkingRequests()
DeviceLinkingSession.shared.removeListener(this)
dismiss()
}
private fun onDeviceLinkCanceled() {
DeviceLinkingSession.shared.stopListeningForLinkingRequests()
DeviceLinkingSession.shared.removeListener(this)
if (authorization != null) {
DatabaseFactory.getLokiPreKeyBundleDatabase(context).removePreKeyBundle(authorization!!.secondaryDevicePublicKey)
}
dismiss()
delegate?.onDeviceLinkCanceled()
}
}
interface LinkDeviceMasterModeDialogDelegate {
fun onDeviceLinkRequestAuthorized(authorization: PairingAuthorisation)
fun onDeviceLinkCanceled()
}