mirror of
https://github.com/oxen-io/session-android.git
synced 2025-04-20 22:31:30 +00:00
Implement multi device UI
This commit is contained in:
parent
2a741049cc
commit
1f8b9bfe58
@ -23,20 +23,15 @@ class LandingActivity : BaseActionBarActivity() {
|
|||||||
setContentView(R.layout.activity_landing)
|
setContentView(R.layout.activity_landing)
|
||||||
setUpActionBarSessionLogo(true)
|
setUpActionBarSessionLogo(true)
|
||||||
findViewById<FakeChatView>(R.id.fakeChatView).startAnimating()
|
findViewById<FakeChatView>(R.id.fakeChatView).startAnimating()
|
||||||
|
|
||||||
findViewById<View>(R.id.registerButton).setOnClickListener { register() }
|
findViewById<View>(R.id.registerButton).setOnClickListener { register() }
|
||||||
findViewById<View>(R.id.restoreButton).setOnClickListener { restoreFromRecoveryPhrase() }
|
findViewById<View>(R.id.restoreButton).setOnClickListener { restore() }
|
||||||
findViewById<View>(R.id.restoreBackupButton).setOnClickListener { restoreFromBackup() }
|
findViewById<View>(R.id.linkButton).setOnClickListener { link() }
|
||||||
|
|
||||||
// Setup essentials for a new user.
|
|
||||||
IdentityKeyUtil.generateIdentityKeyPair(this)
|
IdentityKeyUtil.generateIdentityKeyPair(this)
|
||||||
|
|
||||||
TextSecurePreferences.setLastExperienceVersionCode(this, Util.getCanonicalVersionCode())
|
TextSecurePreferences.setLastExperienceVersionCode(this, Util.getCanonicalVersionCode())
|
||||||
TextSecurePreferences.setPasswordDisabled(this, true)
|
TextSecurePreferences.setPasswordDisabled(this, true)
|
||||||
TextSecurePreferences.setReadReceiptsEnabled(this, true)
|
TextSecurePreferences.setReadReceiptsEnabled(this, true)
|
||||||
TextSecurePreferences.setTypingIndicatorsEnabled(this, true)
|
TextSecurePreferences.setTypingIndicatorsEnabled(this, true)
|
||||||
|
// AC: This is a temporary workaround to trick the old code that the screen is unlocked.
|
||||||
//AC: This is a temporary workaround to trick the old code that the screen is unlocked.
|
|
||||||
KeyCachingService.setMasterSecret(applicationContext, Object())
|
KeyCachingService.setMasterSecret(applicationContext, Object())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -45,21 +40,13 @@ class LandingActivity : BaseActionBarActivity() {
|
|||||||
push(intent)
|
push(intent)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun restoreFromRecoveryPhrase() {
|
private fun restore() {
|
||||||
val intent = Intent(this, RecoveryPhraseRestoreActivity::class.java)
|
val intent = Intent(this, RecoveryPhraseRestoreActivity::class.java)
|
||||||
push(intent)
|
push(intent)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun restoreFromBackup() {
|
private fun link() {
|
||||||
val intent = Intent(this, BackupRestoreActivity::class.java)
|
val intent = Intent(this, LinkDeviceActivity::class.java)
|
||||||
push(intent)
|
push(intent)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun reset() {
|
|
||||||
IdentityKeyUtil.delete(this, IdentityKeyUtil.LOKI_SEED)
|
|
||||||
TextSecurePreferences.removeLocalNumber(this)
|
|
||||||
TextSecurePreferences.setHasSeenWelcomeScreen(this, false)
|
|
||||||
val application = ApplicationContext.getInstance(this)
|
|
||||||
application.stopPolling()
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -0,0 +1,125 @@
|
|||||||
|
package org.thoughtcrime.securesms.loki.activities
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.os.Bundle
|
||||||
|
import androidx.fragment.app.Fragment
|
||||||
|
import androidx.fragment.app.FragmentPagerAdapter
|
||||||
|
import android.text.InputType
|
||||||
|
import android.view.*
|
||||||
|
import android.view.inputmethod.EditorInfo
|
||||||
|
import android.view.inputmethod.InputMethodManager
|
||||||
|
import android.widget.Toast
|
||||||
|
import kotlinx.android.synthetic.main.activity_create_private_chat.*
|
||||||
|
import kotlinx.android.synthetic.main.fragment_recovery_phrase.*
|
||||||
|
import network.loki.messenger.R
|
||||||
|
import org.session.libsignal.service.loki.crypto.MnemonicCodec
|
||||||
|
import org.session.libsignal.utilities.Hex
|
||||||
|
import org.thoughtcrime.securesms.BaseActionBarActivity
|
||||||
|
import org.thoughtcrime.securesms.loki.fragments.ScanQRCodeWrapperFragment
|
||||||
|
import org.thoughtcrime.securesms.loki.fragments.ScanQRCodeWrapperFragmentDelegate
|
||||||
|
import org.thoughtcrime.securesms.loki.utilities.MnemonicUtilities
|
||||||
|
import org.thoughtcrime.securesms.loki.utilities.setUpActionBarSessionLogo
|
||||||
|
|
||||||
|
class LinkDeviceActivity : BaseActionBarActivity(), ScanQRCodeWrapperFragmentDelegate {
|
||||||
|
private val adapter = LinkDeviceActivityAdapter(this)
|
||||||
|
|
||||||
|
// region Lifecycle
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
setUpActionBarSessionLogo()
|
||||||
|
setContentView(R.layout.activity_link_device)
|
||||||
|
viewPager.adapter = adapter
|
||||||
|
tabLayout.setupWithViewPager(viewPager)
|
||||||
|
}
|
||||||
|
// endregion
|
||||||
|
|
||||||
|
// region Interaction
|
||||||
|
override fun handleQRCodeScanned(mnemonic: String) {
|
||||||
|
continueWithMnemonic(mnemonic)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun continueWithMnemonic(mnemonic: String) {
|
||||||
|
val loadFileContents: (String) -> String = { fileName ->
|
||||||
|
MnemonicUtilities.loadFileContents(this, fileName)
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
val hexEncodedSeed = MnemonicCodec(loadFileContents).decode(mnemonic)
|
||||||
|
val seed = Hex.fromStringCondensed(hexEncodedSeed)
|
||||||
|
continueWithSeed(seed)
|
||||||
|
} catch (error: Exception) {
|
||||||
|
val message = if (error is MnemonicCodec.DecodingError) {
|
||||||
|
error.description
|
||||||
|
} else {
|
||||||
|
"An error occurred."
|
||||||
|
}
|
||||||
|
Toast.makeText(this, message, Toast.LENGTH_LONG).show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun continueWithSeed(seed: ByteArray) {
|
||||||
|
// TODO: Implement
|
||||||
|
}
|
||||||
|
// endregion
|
||||||
|
}
|
||||||
|
|
||||||
|
// region Adapter
|
||||||
|
private class LinkDeviceActivityAdapter(private val activity: LinkDeviceActivity) : FragmentPagerAdapter(activity.supportFragmentManager) {
|
||||||
|
val recoveryPhraseFragment = RecoveryPhraseFragment()
|
||||||
|
|
||||||
|
override fun getCount(): Int {
|
||||||
|
return 2
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getItem(index: Int): Fragment {
|
||||||
|
return when (index) {
|
||||||
|
0 -> recoveryPhraseFragment
|
||||||
|
1 -> {
|
||||||
|
val result = ScanQRCodeWrapperFragment()
|
||||||
|
result.delegate = activity
|
||||||
|
result.message = "Navigate to Settings → Recovery Phrase on your other device to show your QR code."
|
||||||
|
result
|
||||||
|
}
|
||||||
|
else -> throw IllegalStateException()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getPageTitle(index: Int): CharSequence? {
|
||||||
|
return when (index) {
|
||||||
|
0 -> "Recovery Phrase"
|
||||||
|
1 -> "Scan QR Code"
|
||||||
|
else -> throw IllegalStateException()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// endregion
|
||||||
|
|
||||||
|
// region Recovery Phrase Fragment
|
||||||
|
class RecoveryPhraseFragment : Fragment() {
|
||||||
|
|
||||||
|
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
|
||||||
|
return inflater.inflate(R.layout.fragment_recovery_phrase, container, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
mnemonicEditText.imeOptions = EditorInfo.IME_ACTION_DONE or 16777216 // Always use incognito keyboard
|
||||||
|
mnemonicEditText.setRawInputType(InputType.TYPE_CLASS_TEXT)
|
||||||
|
mnemonicEditText.setOnEditorActionListener { v, actionID, _ ->
|
||||||
|
if (actionID == EditorInfo.IME_ACTION_DONE) {
|
||||||
|
val imm = v.context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
|
||||||
|
imm.hideSoftInputFromWindow(v.windowToken, 0)
|
||||||
|
handleContinueButtonTapped()
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
continueButton.setOnClickListener { handleContinueButtonTapped() }
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun handleContinueButtonTapped() {
|
||||||
|
val mnemonic = mnemonicEditText.text?.trim().toString()
|
||||||
|
(requireActivity() as LinkDeviceActivity).continueWithMnemonic(mnemonic)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// endregion
|
@ -49,27 +49,16 @@
|
|||||||
android:layout_marginRight="@dimen/massive_spacing"
|
android:layout_marginRight="@dimen/massive_spacing"
|
||||||
android:text="@string/activity_landing_restore_button_title" />
|
android:text="@string/activity_landing_restore_button_title" />
|
||||||
|
|
||||||
<Button
|
|
||||||
style="@style/Widget.Session.Button.Common.ProminentOutline"
|
|
||||||
android:id="@+id/restoreBackupButton"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="@dimen/medium_button_height"
|
|
||||||
android:layout_marginLeft="@dimen/massive_spacing"
|
|
||||||
android:layout_marginTop="@dimen/medium_spacing"
|
|
||||||
android:layout_marginRight="@dimen/massive_spacing"
|
|
||||||
android:text="@string/activity_landing_restore_backup_button_title" />
|
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/linkButton"
|
android:id="@+id/linkButton"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="@dimen/onboarding_button_bottom_offset"
|
android:layout_height="@dimen/onboarding_button_bottom_offset"
|
||||||
android:layout_marginLeft="@dimen/massive_spacing"
|
android:layout_marginLeft="@dimen/massive_spacing"
|
||||||
android:layout_marginRight="@dimen/massive_spacing"
|
android:layout_marginRight="@dimen/massive_spacing"
|
||||||
android:visibility="invisible"
|
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:background="@color/transparent"
|
android:background="@color/transparent"
|
||||||
android:textAllCaps="false"
|
android:textAllCaps="false"
|
||||||
android:textSize="@dimen/medium_font_size"
|
android:textSize="@dimen/medium_font_size"
|
||||||
android:text="@string/activity_landing_link_button_title" />
|
android:text="Link a Device" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
63
app/src/main/res/layout-sw400dp/fragment_recovery_phrase.xml
Normal file
63
app/src/main/res/layout-sw400dp/fragment_recovery_phrase.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"
|
||||||
|
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/very_large_spacing"
|
||||||
|
android:layout_marginRight="@dimen/very_large_spacing"
|
||||||
|
android:textSize="@dimen/very_large_font_size"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:textColor="@color/text"
|
||||||
|
android:text="Recovery Phrase" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginLeft="@dimen/very_large_spacing"
|
||||||
|
android:layout_marginTop="7dp"
|
||||||
|
android:layout_marginRight="@dimen/very_large_spacing"
|
||||||
|
android:textSize="@dimen/medium_font_size"
|
||||||
|
android:textColor="@color/text"
|
||||||
|
android:text="To link your device, enter the recovery phrase that was given to you when you signed up." />
|
||||||
|
|
||||||
|
<EditText
|
||||||
|
style="@style/SessionEditText"
|
||||||
|
android:id="@+id/mnemonicEditText"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="80dp"
|
||||||
|
android:layout_marginLeft="@dimen/very_large_spacing"
|
||||||
|
android:layout_marginTop="12dp"
|
||||||
|
android:layout_marginRight="@dimen/very_large_spacing"
|
||||||
|
android:paddingTop="0dp"
|
||||||
|
android:paddingBottom="0dp"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:inputType="textMultiLine"
|
||||||
|
android:maxLines="2"
|
||||||
|
android:hint="@string/activity_restore_seed_edit_text_hint" />
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:layout_weight="1"/>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
style="@style/Widget.Session.Button.Common.ProminentFilled"
|
||||||
|
android:id="@+id/continueButton"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="@dimen/medium_button_height"
|
||||||
|
android:layout_marginLeft="@dimen/massive_spacing"
|
||||||
|
android:layout_marginRight="@dimen/massive_spacing"
|
||||||
|
android:layout_marginBottom="@dimen/medium_spacing"
|
||||||
|
android:text="@string/continue_2" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
@ -49,27 +49,16 @@
|
|||||||
android:layout_marginRight="@dimen/massive_spacing"
|
android:layout_marginRight="@dimen/massive_spacing"
|
||||||
android:text="@string/activity_landing_restore_button_title" />
|
android:text="@string/activity_landing_restore_button_title" />
|
||||||
|
|
||||||
<Button
|
|
||||||
style="@style/Widget.Session.Button.Common.ProminentOutline"
|
|
||||||
android:id="@+id/restoreBackupButton"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="@dimen/medium_button_height"
|
|
||||||
android:layout_marginLeft="@dimen/massive_spacing"
|
|
||||||
android:layout_marginTop="@dimen/small_spacing"
|
|
||||||
android:layout_marginRight="@dimen/massive_spacing"
|
|
||||||
android:text="@string/activity_landing_restore_backup_button_title" />
|
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/linkButton"
|
android:id="@+id/linkButton"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="@dimen/onboarding_button_bottom_offset"
|
android:layout_height="@dimen/onboarding_button_bottom_offset"
|
||||||
android:layout_marginLeft="@dimen/massive_spacing"
|
android:layout_marginLeft="@dimen/massive_spacing"
|
||||||
android:layout_marginRight="@dimen/massive_spacing"
|
android:layout_marginRight="@dimen/massive_spacing"
|
||||||
android:visibility="invisible"
|
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:background="@color/transparent"
|
android:background="@color/transparent"
|
||||||
android:textAllCaps="false"
|
android:textAllCaps="false"
|
||||||
android:textSize="@dimen/medium_font_size"
|
android:textSize="@dimen/medium_font_size"
|
||||||
android:text="@string/activity_landing_link_button_title" />
|
android:text="Link a Device" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
14
app/src/main/res/layout/activity_link_device.xml
Normal file
14
app/src/main/res/layout/activity_link_device.xml
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.viewpager.widget.ViewPager
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:id="@+id/viewPager"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent" >
|
||||||
|
|
||||||
|
<com.google.android.material.tabs.TabLayout
|
||||||
|
style="@style/Widget.Session.TabLayout"
|
||||||
|
android:id="@+id/tabLayout"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="@dimen/tab_bar_height" />
|
||||||
|
|
||||||
|
</androidx.viewpager.widget.ViewPager>
|
63
app/src/main/res/layout/fragment_recovery_phrase.xml
Normal file
63
app/src/main/res/layout/fragment_recovery_phrase.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"
|
||||||
|
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/very_large_spacing"
|
||||||
|
android:layout_marginRight="@dimen/very_large_spacing"
|
||||||
|
android:textSize="@dimen/large_font_size"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:textColor="@color/text"
|
||||||
|
android:text="Recovery Phrase" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginLeft="@dimen/very_large_spacing"
|
||||||
|
android:layout_marginTop="4dp"
|
||||||
|
android:layout_marginRight="@dimen/very_large_spacing"
|
||||||
|
android:textSize="@dimen/small_font_size"
|
||||||
|
android:textColor="@color/text"
|
||||||
|
android:text="@string/activity_restore_explanation" />
|
||||||
|
|
||||||
|
<EditText
|
||||||
|
style="@style/SmallSessionEditText"
|
||||||
|
android:id="@+id/mnemonicEditText"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="80dp"
|
||||||
|
android:layout_marginLeft="@dimen/very_large_spacing"
|
||||||
|
android:layout_marginTop="10dp"
|
||||||
|
android:layout_marginRight="@dimen/very_large_spacing"
|
||||||
|
android:paddingTop="0dp"
|
||||||
|
android:paddingBottom="0dp"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:inputType="textMultiLine"
|
||||||
|
android:maxLines="2"
|
||||||
|
android:hint="@string/activity_restore_seed_edit_text_hint" />
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:layout_weight="1"/>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
style="@style/Widget.Session.Button.Common.ProminentFilled"
|
||||||
|
android:id="@+id/continueButton"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="@dimen/medium_button_height"
|
||||||
|
android:layout_marginLeft="@dimen/massive_spacing"
|
||||||
|
android:layout_marginRight="@dimen/massive_spacing"
|
||||||
|
android:layout_marginBottom="@dimen/medium_spacing"
|
||||||
|
android:text="@string/continue_2" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
@ -88,7 +88,7 @@
|
|||||||
|
|
||||||
</PreferenceCategory>
|
</PreferenceCategory>
|
||||||
|
|
||||||
<PreferenceCategory android:layout="@layout/preference_divider" />
|
<!-- <PreferenceCategory android:layout="@layout/preference_divider" />
|
||||||
|
|
||||||
<PreferenceCategory android:key="backup_category" android:title="@string/preferences_chats__backups">
|
<PreferenceCategory android:key="backup_category" android:title="@string/preferences_chats__backups">
|
||||||
|
|
||||||
@ -105,6 +105,6 @@
|
|||||||
android:dependency="pref_backup_enabled_v3"
|
android:dependency="pref_backup_enabled_v3"
|
||||||
tools:summary="Last backup: 3 days ago" />
|
tools:summary="Last backup: 3 days ago" />
|
||||||
|
|
||||||
</PreferenceCategory>
|
</PreferenceCategory> -->
|
||||||
|
|
||||||
</PreferenceScreen>
|
</PreferenceScreen>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user