mirror of
https://github.com/oxen-io/session-android.git
synced 2024-12-24 00:37:47 +00:00
Partially implement device linking redesign & fix copy
This commit is contained in:
parent
7da4f1f6ae
commit
df61cbb30d
@ -126,37 +126,32 @@
|
||||
|
||||
<!-- Session -->
|
||||
<activity
|
||||
android:name="org.thoughtcrime.securesms.loki.redesign.activities.LandingActivity"
|
||||
android:launchMode="singleTask" />
|
||||
android:name="org.thoughtcrime.securesms.loki.redesign.activities.LandingActivity" />
|
||||
<activity
|
||||
android:name="org.thoughtcrime.securesms.loki.redesign.activities.RegisterActivity"
|
||||
android:launchMode="singleTask" />
|
||||
<activity
|
||||
android:name="org.thoughtcrime.securesms.loki.redesign.activities.DisplayNameActivity"
|
||||
android:launchMode="singleTask"
|
||||
android:windowSoftInputMode="adjustResize" />
|
||||
android:name="org.thoughtcrime.securesms.loki.redesign.activities.RegisterActivity" />
|
||||
<activity
|
||||
android:name="org.thoughtcrime.securesms.loki.redesign.activities.RestoreActivity"
|
||||
android:launchMode="singleTask"
|
||||
android:windowSoftInputMode="adjustResize" />
|
||||
<activity
|
||||
android:name="org.thoughtcrime.securesms.loki.redesign.activities.LinkDeviceActivity"
|
||||
android:windowSoftInputMode="adjustResize" />
|
||||
<activity
|
||||
android:name="org.thoughtcrime.securesms.loki.redesign.activities.DisplayNameActivity"
|
||||
android:windowSoftInputMode="adjustResize" />
|
||||
<activity
|
||||
android:name="org.thoughtcrime.securesms.loki.redesign.activities.HomeActivity"
|
||||
android:launchMode="singleTask"
|
||||
android:theme="@style/Session.DarkTheme.NoActionBar" />
|
||||
<activity
|
||||
android:name="org.thoughtcrime.securesms.loki.redesign.activities.CreatePrivateChatActivity"
|
||||
android:launchMode="singleTask" />
|
||||
<activity
|
||||
android:name="org.thoughtcrime.securesms.loki.redesign.activities.JoinPublicChatActivity"
|
||||
android:launchMode="singleTask"
|
||||
android:windowSoftInputMode="adjustResize" />
|
||||
<activity
|
||||
android:name="org.thoughtcrime.securesms.loki.redesign.activities.SettingsActivity"
|
||||
android:launchMode="singleTask"
|
||||
android:theme="@style/Session.DarkTheme.NoActionBar" />
|
||||
<activity
|
||||
android:name="org.thoughtcrime.securesms.loki.redesign.activities.QRCodeActivity"
|
||||
android:launchMode="singleTask" />
|
||||
android:name="org.thoughtcrime.securesms.loki.redesign.activities.QRCodeActivity" />
|
||||
<activity
|
||||
android:name="org.thoughtcrime.securesms.loki.redesign.activities.CreatePrivateChatActivity" />
|
||||
<activity
|
||||
android:name="org.thoughtcrime.securesms.loki.redesign.activities.JoinPublicChatActivity"
|
||||
android:windowSoftInputMode="adjustResize" />
|
||||
<!-- Session -->
|
||||
<activity android:name="org.thoughtcrime.securesms.loki.LinkedDevicesActivity" />
|
||||
<activity
|
||||
|
@ -1,7 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<set xmlns:android="http://schemas.android.com/apk/res/android" >
|
||||
<set
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:interpolator="@android:anim/decelerate_interpolator">
|
||||
|
||||
<translate
|
||||
android:duration="350"
|
||||
android:fromYDelta="100%"
|
||||
android:toYDelta="0%" />
|
||||
android:duration="250"
|
||||
android:fromYDelta="100%"
|
||||
android:toYDelta="0%" />
|
||||
|
||||
</set>
|
@ -1,5 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<set
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:interpolator="@android:anim/decelerate_interpolator">
|
||||
|
14
res/layout/activity_link_device.xml
Normal file
14
res/layout/activity_link_device.xml
Normal file
@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<android.support.v4.view.ViewPager
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/viewPager"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" >
|
||||
|
||||
<android.support.design.widget.TabLayout
|
||||
style="@style/Session.DarkTabLayout"
|
||||
android:id="@+id/tabLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/tab_bar_height" />
|
||||
|
||||
</android.support.v4.view.ViewPager>
|
@ -30,7 +30,7 @@
|
||||
android:layout_marginRight="@dimen/very_large_spacing"
|
||||
android:textSize="@dimen/medium_font_size"
|
||||
android:textColor="@color/text"
|
||||
android:text="Enter the seed that was given to you when you signed up to restore your account." />
|
||||
android:text="Enter the recovery phrase that was given to you when you signed up to restore your account." />
|
||||
|
||||
<EditText
|
||||
style="@style/SessionEditText"
|
||||
@ -40,7 +40,7 @@
|
||||
android:layout_marginLeft="@dimen/very_large_spacing"
|
||||
android:layout_marginTop="20dp"
|
||||
android:layout_marginRight="@dimen/very_large_spacing"
|
||||
android:hint="Enter your seed" />
|
||||
android:hint="Enter your recovery phrase" />
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
|
@ -205,6 +205,7 @@
|
||||
android:text="Chats" />
|
||||
|
||||
<View
|
||||
android:id="@+id/linkedDevicesButtonTopSeparator"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1px"
|
||||
android:background="@color/separator" />
|
||||
@ -221,6 +222,7 @@
|
||||
android:text="Linked Devices" />
|
||||
|
||||
<View
|
||||
android:id="@+id/seedButtonTopSeparator"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1px"
|
||||
android:background="@color/separator" />
|
||||
@ -234,7 +236,7 @@
|
||||
android:textSize="@dimen/medium_font_size"
|
||||
android:textStyle="bold"
|
||||
android:gravity="center"
|
||||
android:text="Show Seed" />
|
||||
android:text="Show Recovery Phrase" />
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
|
63
res/layout/dialog_link_device_slave_mode.xml
Normal file
63
res/layout/dialog_link_device_slave_mode.xml
Normal file
@ -0,0 +1,63 @@
|
||||
<?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"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
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">
|
||||
|
||||
<com.github.ybq.android.spinkit.SpinKitView
|
||||
style="@style/SpinKitView.DoubleBounce"
|
||||
android:id="@+id/spinner"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_centerInParent="true"
|
||||
app:SpinKit_Color="@color/text" />
|
||||
|
||||
<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 Authorization"
|
||||
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="Please check that the words below match those shown on your other device."
|
||||
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="@dimen/large_spacing"
|
||||
android:text="puffin circle idled"
|
||||
android:textColor="@color/text"
|
||||
android:textSize="@dimen/small_font_size"
|
||||
android:textAlignment="center" />
|
||||
|
||||
<Button
|
||||
style="@style/UnimportantDialogButton"
|
||||
android:id="@+id/cancelButton"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/small_button_height"
|
||||
android:layout_marginTop="@dimen/large_spacing"
|
||||
android:text="Cancel" />
|
||||
|
||||
</LinearLayout>
|
@ -14,7 +14,7 @@
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Your Seed"
|
||||
android:text="Your Recovery Phrase"
|
||||
android:textColor="@color/text"
|
||||
android:textStyle="bold"
|
||||
android:textSize="@dimen/medium_font_size" />
|
||||
@ -33,7 +33,7 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/large_spacing"
|
||||
android:text="This is your personal password. It can be used to restore your account or migrate your account to a new device."
|
||||
android:text="This is your personal recovery phrase. It can be used to restore your account or migrate your account to a new device."
|
||||
android:textColor="@color/text"
|
||||
android:textSize="@dimen/small_font_size"
|
||||
android:textAlignment="center"
|
||||
|
@ -27,7 +27,7 @@
|
||||
android:textColor="@color/text"
|
||||
android:alpha="0.6"
|
||||
android:textAlignment="center"
|
||||
android:text="Enter the URL of the public chat you'd like to join" />
|
||||
android:text="Enter the URL of the channel you'd like to join" />
|
||||
|
||||
<View
|
||||
android:layout_width="0dp"
|
||||
|
59
res/layout/fragment_enter_session_id.xml
Normal file
59
res/layout/fragment_enter_session_id.xml
Normal file
@ -0,0 +1,59 @@
|
||||
<?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_session_background"
|
||||
android:orientation="vertical">
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"/>
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="@dimen/large_spacing"
|
||||
android:layout_marginRight="@dimen/large_spacing"
|
||||
android:textSize="@dimen/very_large_font_size"
|
||||
android:textStyle="bold"
|
||||
android:textColor="@color/text"
|
||||
android:text="Link your device" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="@dimen/large_spacing"
|
||||
android:layout_marginTop="@dimen/medium_spacing"
|
||||
android:layout_marginRight="@dimen/large_spacing"
|
||||
android:textSize="@dimen/medium_font_size"
|
||||
android:textColor="@color/text"
|
||||
android:text="Enter your Session ID to start the linking process." />
|
||||
|
||||
<EditText
|
||||
style="@style/SessionEditText"
|
||||
android:id="@+id/sessionIDEditText"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="@dimen/large_spacing"
|
||||
android:layout_marginTop="20dp"
|
||||
android:layout_marginRight="@dimen/large_spacing"
|
||||
android:hint="Enter your session ID" />
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"/>
|
||||
|
||||
<Button
|
||||
style="@style/MediumProminentOutlineButton"
|
||||
android:id="@+id/requestDeviceLinkButton"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/medium_button_height"
|
||||
android:layout_marginLeft="90dp"
|
||||
android:layout_marginRight="90dp"
|
||||
android:layout_marginBottom="@dimen/medium_spacing"
|
||||
android:text="Next" />
|
||||
|
||||
</LinearLayout>
|
@ -53,7 +53,7 @@
|
||||
android:textSize="@dimen/medium_font_size"
|
||||
android:textColor="@color/text"
|
||||
android:textAlignment="center"
|
||||
android:text="This is your unique public QR code. Other users may scan this in order to begin a conversation with you." />
|
||||
android:text="This is your unique public QR code. Other users can scan this to start a conversation with you." />
|
||||
|
||||
<Button
|
||||
style="@style/MediumUnimportantOutlineButton"
|
||||
|
@ -22,7 +22,7 @@
|
||||
android:layout_width="@dimen/fake_chat_view_bubble_width"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/medium_spacing"
|
||||
android:text="It's a secure, decentralized cross-platform private messaging app"
|
||||
android:text="It's a secure, decentralized private messaging app"
|
||||
android:layout_gravity="left" />
|
||||
|
||||
<TextView
|
||||
@ -31,7 +31,7 @@
|
||||
android:layout_width="@dimen/fake_chat_view_bubble_width"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/medium_spacing"
|
||||
android:text="So it doesn't collect my personal information or my conversation metadata? How's it work?"
|
||||
android:text="So it doesn't collect my personal information or my conversation metadata? How does it work?"
|
||||
android:layout_gravity="right" />
|
||||
|
||||
<TextView
|
||||
|
@ -13,6 +13,6 @@
|
||||
android:textColor="@color/text"
|
||||
android:alpha="0.6"
|
||||
android:textSize="@dimen/small_font_size"
|
||||
android:text="Your Public Key" />
|
||||
android:text="Your Session ID" />
|
||||
|
||||
</RelativeLayout>
|
@ -9,6 +9,7 @@ import org.thoughtcrime.securesms.ApplicationContext
|
||||
import org.thoughtcrime.securesms.BaseActionBarActivity
|
||||
import org.thoughtcrime.securesms.ConversationListActivity
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory
|
||||
import org.thoughtcrime.securesms.loki.redesign.utilities.show
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
||||
import org.whispersystems.signalservice.api.crypto.ProfileCipher
|
||||
import org.whispersystems.signalservice.loki.utilities.Analytics
|
||||
@ -44,7 +45,7 @@ class DisplayNameActivity : BaseActionBarActivity() {
|
||||
application.setUpP2PAPI()
|
||||
application.startLongPollingIfNeeded()
|
||||
application.setUpStorageAPIIfNeeded()
|
||||
startActivity(Intent(this, ConversationListActivity::class.java))
|
||||
show(Intent(this, ConversationListActivity::class.java))
|
||||
finish()
|
||||
val publicChatAPI = ApplicationContext.getInstance(this).lokiPublicChatAPI
|
||||
if (publicChatAPI != null) {
|
||||
|
@ -256,7 +256,7 @@ class SeedActivity : BaseActionBarActivity(), DeviceLinkingDelegate, ScanListene
|
||||
TextSecurePreferences.setHasSeenWelcomeScreen(this, false)
|
||||
TextSecurePreferences.setPromptedPushRegistration(this, false)
|
||||
}
|
||||
// endregion
|
||||
|
||||
override fun onQrDataFound(data: String?) {
|
||||
runOnUiThread {
|
||||
if (data != null && PublicKeyValidation.isValid(data.trim())) {
|
||||
|
@ -26,6 +26,7 @@ import org.thoughtcrime.securesms.database.ThreadDatabase
|
||||
import org.thoughtcrime.securesms.database.model.ThreadRecord
|
||||
import org.thoughtcrime.securesms.loki.getColorWithID
|
||||
import org.thoughtcrime.securesms.loki.redesign.utilities.push
|
||||
import org.thoughtcrime.securesms.loki.redesign.utilities.show
|
||||
import org.thoughtcrime.securesms.loki.redesign.views.ConversationView
|
||||
import org.thoughtcrime.securesms.mms.GlideApp
|
||||
import org.thoughtcrime.securesms.mms.GlideRequests
|
||||
@ -140,17 +141,17 @@ class HomeActivity : PassphraseRequiredActionBarActivity, ConversationClickListe
|
||||
|
||||
private fun openSettings() {
|
||||
val intent = Intent(this, SettingsActivity::class.java)
|
||||
startActivity(intent)
|
||||
show(intent)
|
||||
}
|
||||
|
||||
private fun createPrivateChat() {
|
||||
val intent = Intent(this, CreatePrivateChatActivity::class.java)
|
||||
startActivity(intent)
|
||||
show(intent)
|
||||
}
|
||||
|
||||
private fun joinPublicChat() {
|
||||
val intent = Intent(this, JoinPublicChatActivity::class.java)
|
||||
startActivity(intent)
|
||||
show(intent)
|
||||
}
|
||||
|
||||
private class SwipeCallback(val activity: HomeActivity) : ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT) {
|
||||
|
@ -33,7 +33,7 @@ class JoinPublicChatActivity : PassphraseRequiredActionBarActivity(), ScanQRCode
|
||||
// Set content view
|
||||
setContentView(R.layout.activity_join_public_chat)
|
||||
// Set title
|
||||
supportActionBar!!.title = "Join Public Chat"
|
||||
supportActionBar!!.title = "Join Channel"
|
||||
// Set up view pager
|
||||
viewPager.adapter = adapter
|
||||
tabLayout.setupWithViewPager(viewPager)
|
||||
@ -80,7 +80,7 @@ class JoinPublicChatActivity : PassphraseRequiredActionBarActivity(), ScanQRCode
|
||||
finish()
|
||||
}.failUi {
|
||||
hideLoader()
|
||||
Toast.makeText(this, "Couldn't Join Public Chat", Toast.LENGTH_SHORT).show()
|
||||
Toast.makeText(this, "Couldn't Join Channel", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
// endregion
|
||||
@ -99,7 +99,7 @@ private class JoinPublicChatActivityAdapter(val activity: JoinPublicChatActivity
|
||||
1 -> {
|
||||
val result = ScanQRCodeWrapperFragment()
|
||||
result.delegate = activity
|
||||
result.message = "Scan the QR code of the public chat you'd like to join"
|
||||
result.message = "Scan the QR code of the channel you'd like to join"
|
||||
result
|
||||
}
|
||||
else -> throw IllegalStateException()
|
||||
@ -108,7 +108,7 @@ private class JoinPublicChatActivityAdapter(val activity: JoinPublicChatActivity
|
||||
|
||||
override fun getPageTitle(index: Int): CharSequence? {
|
||||
return when (index) {
|
||||
0 -> "Enter Chat URL"
|
||||
0 -> "Enter Channel URL"
|
||||
1 -> "Scan QR Code"
|
||||
else -> throw IllegalStateException()
|
||||
}
|
||||
@ -116,7 +116,7 @@ private class JoinPublicChatActivityAdapter(val activity: JoinPublicChatActivity
|
||||
}
|
||||
// endregion
|
||||
|
||||
// region Enter Public Key Fragment
|
||||
// region Enter Chat URL Fragment
|
||||
class EnterChatURLFragment : Fragment() {
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
|
||||
|
@ -1,14 +1,36 @@
|
||||
package org.thoughtcrime.securesms.loki.redesign.activities
|
||||
|
||||
import android.content.Intent
|
||||
import android.os.AsyncTask
|
||||
import android.os.Bundle
|
||||
import android.widget.Toast
|
||||
import kotlinx.android.synthetic.main.activity_landing.*
|
||||
import network.loki.messenger.R
|
||||
import org.thoughtcrime.securesms.ApplicationContext
|
||||
import org.thoughtcrime.securesms.BaseActionBarActivity
|
||||
import org.thoughtcrime.securesms.crypto.IdentityKeyUtil
|
||||
import org.thoughtcrime.securesms.database.Address
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory
|
||||
import org.thoughtcrime.securesms.database.IdentityDatabase
|
||||
import org.thoughtcrime.securesms.logging.Log
|
||||
import org.thoughtcrime.securesms.loki.redesign.dialogs.LinkDeviceSlaveModeDialog
|
||||
import org.thoughtcrime.securesms.loki.redesign.dialogs.LinkDeviceSlaveModeDialogDelegate
|
||||
import org.thoughtcrime.securesms.loki.redesign.utilities.push
|
||||
import org.thoughtcrime.securesms.loki.redesign.utilities.setUpActionBarSessionLogo
|
||||
import org.thoughtcrime.securesms.loki.redesign.utilities.show
|
||||
import org.thoughtcrime.securesms.loki.sendPairingAuthorisationMessage
|
||||
import org.thoughtcrime.securesms.util.Base64
|
||||
import org.thoughtcrime.securesms.util.Hex
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
||||
import org.whispersystems.curve25519.Curve25519
|
||||
import org.whispersystems.libsignal.ecc.Curve
|
||||
import org.whispersystems.libsignal.ecc.ECKeyPair
|
||||
import org.whispersystems.libsignal.util.KeyHelper
|
||||
import org.whispersystems.signalservice.loki.api.PairingAuthorisation
|
||||
import org.whispersystems.signalservice.loki.utilities.hexEncodedPublicKey
|
||||
import org.whispersystems.signalservice.loki.utilities.retryIfNeeded
|
||||
|
||||
class LandingActivity : BaseActionBarActivity() {
|
||||
class LandingActivity : BaseActionBarActivity(), LinkDeviceSlaveModeDialogDelegate {
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
@ -17,6 +39,17 @@ class LandingActivity : BaseActionBarActivity() {
|
||||
fakeChatView.startAnimating()
|
||||
registerButton.setOnClickListener { register() }
|
||||
restoreButton.setOnClickListener { restore() }
|
||||
linkButton.setOnClickListener { linkDevice() }
|
||||
if (TextSecurePreferences.databaseResetFromUnpair(this)) {
|
||||
Toast.makeText(this, "Your device was unlinked successfully", Toast.LENGTH_LONG).show()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||
super.onActivityResult(requestCode, resultCode, intent)
|
||||
if (resultCode != RESULT_OK) { return }
|
||||
val hexEncodedPublicKey = data!!.getStringExtra("hexEncodedPublicKey")
|
||||
requestDeviceLink(hexEncodedPublicKey)
|
||||
}
|
||||
|
||||
private fun register() {
|
||||
@ -28,4 +61,72 @@ class LandingActivity : BaseActionBarActivity() {
|
||||
val intent = Intent(this, RestoreActivity::class.java)
|
||||
push(intent)
|
||||
}
|
||||
|
||||
private fun linkDevice() {
|
||||
val intent = Intent(this, LinkDeviceActivity::class.java)
|
||||
show(intent, true)
|
||||
}
|
||||
|
||||
private fun requestDeviceLink(hexEncodedPublicKey: String) {
|
||||
var seed: ByteArray? = null
|
||||
var keyPair: ECKeyPair? = null
|
||||
fun generateKeyPair() {
|
||||
val seedCandidate = Curve25519.getInstance(Curve25519.BEST).generateSeed(16)
|
||||
try {
|
||||
keyPair = Curve.generateKeyPair(seedCandidate + seedCandidate) // Validate the seed
|
||||
} catch (exception: Exception) {
|
||||
return generateKeyPair()
|
||||
}
|
||||
seed = seedCandidate
|
||||
}
|
||||
generateKeyPair()
|
||||
IdentityKeyUtil.save(this, IdentityKeyUtil.lokiSeedKey, Hex.toStringCondensed(seed))
|
||||
IdentityKeyUtil.save(this, IdentityKeyUtil.IDENTITY_PUBLIC_KEY_PREF, Base64.encodeBytes(keyPair!!.publicKey.serialize()))
|
||||
IdentityKeyUtil.save(this, IdentityKeyUtil.IDENTITY_PRIVATE_KEY_PREF, Base64.encodeBytes(keyPair!!.privateKey.serialize()))
|
||||
val userHexEncodedPublicKey = keyPair!!.hexEncodedPublicKey
|
||||
val registrationID = KeyHelper.generateRegistrationId(false)
|
||||
TextSecurePreferences.setLocalRegistrationId(this, registrationID)
|
||||
DatabaseFactory.getIdentityDatabase(this).saveIdentity(Address.fromSerialized(userHexEncodedPublicKey),
|
||||
IdentityKeyUtil.getIdentityKeyPair(this).publicKey, IdentityDatabase.VerifiedStatus.VERIFIED,
|
||||
true, System.currentTimeMillis(), true)
|
||||
TextSecurePreferences.setLocalNumber(this, userHexEncodedPublicKey)
|
||||
TextSecurePreferences.setHasSeenWelcomeScreen(this, true)
|
||||
TextSecurePreferences.setPromptedPushRegistration(this, true)
|
||||
val authorisation = PairingAuthorisation(hexEncodedPublicKey, userHexEncodedPublicKey).sign(PairingAuthorisation.Type.REQUEST, keyPair!!.privateKey.serialize())
|
||||
if (authorisation == null) {
|
||||
Log.d("Loki", "Failed to sign device link request.")
|
||||
reset()
|
||||
return Toast.makeText(application, "Couldn't link device.", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
val application = ApplicationContext.getInstance(this)
|
||||
application.startLongPollingIfNeeded()
|
||||
application.setUpP2PAPI()
|
||||
application.setUpStorageAPIIfNeeded()
|
||||
val linkDeviceDialog = LinkDeviceSlaveModeDialog()
|
||||
linkDeviceDialog.delegate = this
|
||||
linkDeviceDialog.show(supportFragmentManager, "Link Device Dialog")
|
||||
AsyncTask.execute {
|
||||
retryIfNeeded(8) {
|
||||
sendPairingAuthorisationMessage(this@LandingActivity, authorisation.primaryDevicePublicKey, authorisation)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDeviceLinkRequestAuthorized(authorization: PairingAuthorisation) {
|
||||
TextSecurePreferences.setMasterHexEncodedPublicKey(this, authorization.primaryDevicePublicKey)
|
||||
val intent = Intent(this, HomeActivity::class.java)
|
||||
show(intent)
|
||||
finish()
|
||||
}
|
||||
|
||||
override fun onDeviceLinkCanceled() {
|
||||
reset()
|
||||
}
|
||||
|
||||
private fun reset() {
|
||||
IdentityKeyUtil.delete(this, IdentityKeyUtil.lokiSeedKey)
|
||||
TextSecurePreferences.removeLocalNumber(this)
|
||||
TextSecurePreferences.setHasSeenWelcomeScreen(this, false)
|
||||
TextSecurePreferences.setPromptedPushRegistration(this, false)
|
||||
}
|
||||
}
|
@ -0,0 +1,103 @@
|
||||
package org.thoughtcrime.securesms.loki.redesign.activities
|
||||
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.support.v4.app.Fragment
|
||||
import android.support.v4.app.FragmentPagerAdapter
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.inputmethod.InputMethodManager
|
||||
import android.widget.Toast
|
||||
import kotlinx.android.synthetic.main.activity_link_device.*
|
||||
import kotlinx.android.synthetic.main.fragment_enter_session_id.*
|
||||
import network.loki.messenger.R
|
||||
import org.thoughtcrime.securesms.BaseActionBarActivity
|
||||
import org.thoughtcrime.securesms.loki.redesign.fragments.ScanQRCodeWrapperFragment
|
||||
import org.thoughtcrime.securesms.loki.redesign.fragments.ScanQRCodeWrapperFragmentDelegate
|
||||
import org.whispersystems.signalservice.loki.utilities.PublicKeyValidation
|
||||
|
||||
class LinkDeviceActivity : BaseActionBarActivity(), ScanQRCodeWrapperFragmentDelegate {
|
||||
private val adapter = LinkDeviceActivityAdapter(this)
|
||||
|
||||
// region Lifecycle
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
// Set content view
|
||||
setContentView(R.layout.activity_link_device)
|
||||
// Set title
|
||||
supportActionBar!!.title = "Link Device"
|
||||
// Set up view pager
|
||||
viewPager.adapter = adapter
|
||||
tabLayout.setupWithViewPager(viewPager)
|
||||
}
|
||||
// endregion
|
||||
|
||||
// region Interaction
|
||||
override fun handleQRCodeScanned(hexEncodedPublicKey: String) {
|
||||
requestDeviceLinkIfPossible(hexEncodedPublicKey)
|
||||
}
|
||||
|
||||
fun requestDeviceLinkIfPossible(hexEncodedPublicKey: String) {
|
||||
if (!PublicKeyValidation.isValid(hexEncodedPublicKey)) {
|
||||
Toast.makeText(this, "Invalid Session ID", Toast.LENGTH_SHORT).show()
|
||||
} else {
|
||||
val intent = Intent()
|
||||
intent.putExtra("hexEncodedPublicKey", hexEncodedPublicKey)
|
||||
setResult(RESULT_OK, intent)
|
||||
finish()
|
||||
}
|
||||
}
|
||||
// endregion
|
||||
}
|
||||
|
||||
// region Adapter
|
||||
private class LinkDeviceActivityAdapter(val activity: LinkDeviceActivity) : FragmentPagerAdapter(activity.supportFragmentManager) {
|
||||
|
||||
override fun getCount(): Int {
|
||||
return 2
|
||||
}
|
||||
|
||||
override fun getItem(index: Int): Fragment {
|
||||
return when (index) {
|
||||
0 -> EnterSessionIDFragment()
|
||||
1 -> {
|
||||
val result = ScanQRCodeWrapperFragment()
|
||||
result.delegate = activity
|
||||
result.message = "Link to your existing account by going into your in-app settings and clicking \"Linked Devices\""
|
||||
result
|
||||
}
|
||||
else -> throw IllegalStateException()
|
||||
}
|
||||
}
|
||||
|
||||
override fun getPageTitle(index: Int): CharSequence? {
|
||||
return when (index) {
|
||||
0 -> "Enter Session ID"
|
||||
1 -> "Scan QR Code"
|
||||
else -> throw IllegalStateException()
|
||||
}
|
||||
}
|
||||
}
|
||||
// endregion
|
||||
|
||||
// region Enter Session ID Fragment
|
||||
class EnterSessionIDFragment : Fragment() {
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
|
||||
return inflater.inflate(R.layout.fragment_enter_session_id, container, false)
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
requestDeviceLinkButton.setOnClickListener { requestDeviceLinkIfPossible() }
|
||||
}
|
||||
|
||||
private fun requestDeviceLinkIfPossible() {
|
||||
val inputMethodManager = context!!.getSystemService(BaseActionBarActivity.INPUT_METHOD_SERVICE) as InputMethodManager
|
||||
inputMethodManager.hideSoftInputFromWindow(sessionIDEditText.windowToken, 0)
|
||||
val hexEncodedPublicKey = sessionIDEditText.text.trim().toString().toLowerCase()
|
||||
(activity!! as LinkDeviceActivity).requestDeviceLinkIfPossible(hexEncodedPublicKey)
|
||||
}
|
||||
}
|
||||
// endregion
|
@ -124,7 +124,7 @@ class ViewMyQRCodeFragment : Fragment() {
|
||||
val size = toPx(280, resources)
|
||||
val qrCode = QRCodeUtilities.encode(hexEncodedPublicKey, size)
|
||||
qrCodeImageView.setImageBitmap(qrCode)
|
||||
val explanation = SpannableStringBuilder("This is your unique public QR code. Other users may scan this in order to begin a conversation with you.")
|
||||
val explanation = SpannableStringBuilder("This is your unique public QR code. Other users can scan this to start a conversation with you.")
|
||||
explanation.setSpan(StyleSpan(Typeface.BOLD), 8, 34, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
|
||||
explanationTextView.text = explanation
|
||||
shareButton.setOnClickListener { shareQRCode() }
|
||||
|
@ -80,6 +80,13 @@ class SettingsActivity : PassphraseRequiredActionBarActivity() {
|
||||
publicKeyTextView.text = hexEncodedPublicKey
|
||||
copyButton.setOnClickListener { copyPublicKey() }
|
||||
shareButton.setOnClickListener { sharePublicKey() }
|
||||
val isMasterDevice = (TextSecurePreferences.getMasterHexEncodedPublicKey(this) == null)
|
||||
if (!isMasterDevice) {
|
||||
linkedDevicesButtonTopSeparator.visibility = View.GONE
|
||||
linkedDevicesButton.visibility = View.GONE
|
||||
seedButtonTopSeparator.visibility = View.GONE
|
||||
seedButton.visibility = View.GONE
|
||||
}
|
||||
seedButton.setOnClickListener { showSeed() }
|
||||
clearAllDataButton.setOnClickListener { clearAllData() }
|
||||
}
|
||||
@ -241,7 +248,7 @@ class SettingsActivity : PassphraseRequiredActionBarActivity() {
|
||||
}
|
||||
|
||||
private fun showSeed() {
|
||||
SeedDialog().show(supportFragmentManager, "Seed Dialog")
|
||||
SeedDialog().show(supportFragmentManager, "Recovery Phrase Dialog")
|
||||
}
|
||||
|
||||
private fun clearAllData() {
|
||||
|
@ -0,0 +1,76 @@
|
||||
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.os.Handler
|
||||
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_slave_mode.view.*
|
||||
import network.loki.messenger.R
|
||||
import org.thoughtcrime.securesms.loki.MnemonicUtilities
|
||||
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 LinkDeviceSlaveModeDialog : DialogFragment(), DeviceLinkingSessionListener {
|
||||
private val languageFileDirectory by lazy { MnemonicUtilities.getLanguageFileDirectory(context!!) }
|
||||
private lateinit var contentView: View
|
||||
private var authorization: PairingAuthorisation? = null
|
||||
var delegate: LinkDeviceSlaveModeDialogDelegate? = null
|
||||
|
||||
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
||||
val builder = AlertDialog.Builder(context!!)
|
||||
contentView = LayoutInflater.from(context!!).inflate(R.layout.dialog_link_device_slave_mode, null)
|
||||
val hexEncodedPublicKey = TextSecurePreferences.getLocalNumber(context)
|
||||
contentView.mnemonicTextView.text = MnemonicUtilities.getFirst3Words(MnemonicCodec(languageFileDirectory), hexEncodedPublicKey)
|
||||
contentView.cancelButton.setOnClickListener { onDeviceLinkCanceled() }
|
||||
builder.setView(contentView)
|
||||
DeviceLinkingSession.shared.startListeningForLinkingRequests()
|
||||
DeviceLinkingSession.shared.addListener(this)
|
||||
val result = builder.create()
|
||||
result.window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
|
||||
return result
|
||||
}
|
||||
|
||||
override fun onDeviceLinkRequestAuthorized(authorization: PairingAuthorisation) {
|
||||
if (authorization.type != PairingAuthorisation.Type.GRANT || authorization.secondaryDevicePublicKey != TextSecurePreferences.getLocalNumber(context!!) || this.authorization != null) { return }
|
||||
Util.runOnMain {
|
||||
this.authorization = authorization
|
||||
DeviceLinkingSession.shared.stopListeningForLinkingRequests()
|
||||
DeviceLinkingSession.shared.removeListener(this)
|
||||
contentView.spinner.visibility = View.GONE
|
||||
val titleTextViewLayoutParams = contentView.titleTextView.layoutParams as LinearLayout.LayoutParams
|
||||
titleTextViewLayoutParams.topMargin = 0
|
||||
contentView.titleTextView.layoutParams = titleTextViewLayoutParams
|
||||
contentView.titleTextView.text = "Device Link Authorized"
|
||||
contentView.explanationTextView.text = "Your device has been linked successfully"
|
||||
contentView.mnemonicTextView.visibility = View.GONE
|
||||
contentView.cancelButton.visibility = View.GONE
|
||||
Handler().postDelayed({
|
||||
dismiss()
|
||||
delegate?.onDeviceLinkRequestAuthorized(authorization)
|
||||
}, 4000)
|
||||
}
|
||||
}
|
||||
|
||||
private fun onDeviceLinkCanceled() {
|
||||
DeviceLinkingSession.shared.stopListeningForLinkingRequests()
|
||||
DeviceLinkingSession.shared.removeListener(this)
|
||||
dismiss()
|
||||
delegate?.onDeviceLinkCanceled()
|
||||
}
|
||||
}
|
||||
|
||||
interface LinkDeviceSlaveModeDialogDelegate {
|
||||
|
||||
fun onDeviceLinkRequestAuthorized(authorization: PairingAuthorisation)
|
||||
fun onDeviceLinkCanceled()
|
||||
}
|
@ -21,7 +21,20 @@ fun AppCompatActivity.setUpActionBarSessionLogo() {
|
||||
supportActionBar!!.setDisplayShowCustomEnabled(true)
|
||||
}
|
||||
|
||||
fun AppCompatActivity.push(intent: Intent) {
|
||||
startActivity(intent)
|
||||
fun AppCompatActivity.push(intent: Intent, isForResult: Boolean = false) {
|
||||
if (isForResult) {
|
||||
startActivityForResult(intent, 42)
|
||||
} else {
|
||||
startActivity(intent)
|
||||
}
|
||||
overridePendingTransition(R.anim.slide_from_right, R.anim.fade_scale_out)
|
||||
}
|
||||
|
||||
fun AppCompatActivity.show(intent: Intent, isForResult: Boolean = false) {
|
||||
if (isForResult) {
|
||||
startActivityForResult(intent, 42)
|
||||
} else {
|
||||
startActivity(intent)
|
||||
}
|
||||
overridePendingTransition(R.anim.slide_from_bottom, R.anim.fade_scale_out)
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user