mirror of
https://github.com/oxen-io/session-android.git
synced 2025-12-03 10:22:20 +00:00
Update app icon & implement recovery phrase screen
This commit is contained in:
@@ -46,7 +46,7 @@ public abstract class BaseActionBarActivity extends AppCompatActivity {
|
||||
DynamicLanguageActivityHelper.recreateIfNotInCorrectLanguage(this, TextSecurePreferences.getLanguage(this));
|
||||
String name = getResources().getString(R.string.app_name);
|
||||
Bitmap icon = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher_foreground);
|
||||
int color = getResources().getColor(R.color.loki_darkest_gray);
|
||||
int color = getResources().getColor(R.color.app_icon_background);
|
||||
setTaskDescription(new ActivityManager.TaskDescription(name, icon, color));
|
||||
}
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ public abstract class BaseActivity extends FragmentActivity {
|
||||
DynamicLanguageActivityHelper.recreateIfNotInCorrectLanguage(this, TextSecurePreferences.getLanguage(this));
|
||||
String name = getResources().getString(R.string.app_name);
|
||||
Bitmap icon = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher_foreground);
|
||||
int color = getResources().getColor(R.color.loki_darkest_gray);
|
||||
int color = getResources().getColor(R.color.app_icon_background);
|
||||
setTaskDescription(new ActivityManager.TaskDescription(name, icon, color));
|
||||
}
|
||||
|
||||
|
||||
@@ -43,13 +43,12 @@ import android.view.animation.Animation;
|
||||
import android.view.animation.BounceInterpolator;
|
||||
import android.view.animation.TranslateAnimation;
|
||||
import android.view.inputmethod.EditorInfo;
|
||||
import android.widget.Button;
|
||||
import android.widget.EditText;
|
||||
import android.widget.ImageButton;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.dd.CircularProgressButton;
|
||||
|
||||
import org.thoughtcrime.securesms.animation.AnimationCompleteListener;
|
||||
import org.thoughtcrime.securesms.components.AnimatingToggle;
|
||||
import org.thoughtcrime.securesms.crypto.InvalidPassphraseException;
|
||||
@@ -76,7 +75,7 @@ public class PassphrasePromptActivity extends PassphraseActivity {
|
||||
|
||||
private View passphraseAuthContainer;
|
||||
private ImageView fingerprintPrompt;
|
||||
private CircularProgressButton lockScreenButton;
|
||||
private Button lockScreenButton;
|
||||
|
||||
private EditText passphraseText;
|
||||
private ImageButton showButton;
|
||||
@@ -278,7 +277,7 @@ public class PassphrasePromptActivity extends PassphraseActivity {
|
||||
fingerprintManager.authenticate(null, 0, fingerprintCancellationSignal, fingerprintListener, null);
|
||||
} else if (Build.VERSION.SDK_INT >= 21){
|
||||
Log.i(TAG, "firing intent...");
|
||||
Intent intent = keyguardManager.createConfirmDeviceCredentialIntent("Unlock Loki Messenger", "");
|
||||
Intent intent = keyguardManager.createConfirmDeviceCredentialIntent("Unlock Session", "");
|
||||
startActivityForResult(intent, 1);
|
||||
} else {
|
||||
Log.w(TAG, "Not compatible...");
|
||||
|
||||
@@ -16,6 +16,10 @@ import android.support.v4.content.Loader
|
||||
import android.support.v7.widget.LinearLayoutManager
|
||||
import android.support.v7.widget.RecyclerView
|
||||
import android.support.v7.widget.helper.ItemTouchHelper
|
||||
import android.text.Spannable
|
||||
import android.text.SpannableString
|
||||
import android.text.style.ForegroundColorSpan
|
||||
import android.view.View
|
||||
import kotlinx.android.synthetic.main.activity_home.*
|
||||
import network.loki.messenger.R
|
||||
import org.thoughtcrime.securesms.ApplicationContext
|
||||
@@ -28,13 +32,14 @@ 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.loki.redesign.views.SeedReminderViewDelegate
|
||||
import org.thoughtcrime.securesms.mms.GlideApp
|
||||
import org.thoughtcrime.securesms.mms.GlideRequests
|
||||
import org.thoughtcrime.securesms.notifications.MessageNotifier
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
||||
import kotlin.math.abs
|
||||
|
||||
class HomeActivity : PassphraseRequiredActionBarActivity, ConversationClickListener {
|
||||
class HomeActivity : PassphraseRequiredActionBarActivity, ConversationClickListener, SeedReminderViewDelegate {
|
||||
private lateinit var glide: GlideRequests
|
||||
|
||||
private val hexEncodedPublicKey: String
|
||||
@@ -79,6 +84,19 @@ class HomeActivity : PassphraseRequiredActionBarActivity, ConversationClickListe
|
||||
profileButton.update()
|
||||
profileButton.setOnClickListener { openSettings() }
|
||||
joinPublicChatButton.setOnClickListener { joinPublicChat() }
|
||||
// Set up seed reminder view
|
||||
val isMasterDevice = (TextSecurePreferences.getMasterHexEncodedPublicKey(this) == null)
|
||||
val hasViewedSeed = TextSecurePreferences.getHasViewedSeed(this)
|
||||
if (!hasViewedSeed && isMasterDevice) {
|
||||
val seedReminderViewTitle = SpannableString("You're almost finished! 80%")
|
||||
seedReminderViewTitle.setSpan(ForegroundColorSpan(resources.getColorWithID(R.color.accent, theme)), 24, 27, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
|
||||
seedReminderView.title = seedReminderViewTitle
|
||||
seedReminderView.subtitle = "Secure your account by saving your recovery phrase"
|
||||
seedReminderView.setProgress(80, false)
|
||||
seedReminderView.delegate = this
|
||||
} else {
|
||||
seedReminderView.visibility = View.GONE
|
||||
}
|
||||
// Set up recycler view
|
||||
val cursor = DatabaseFactory.getThreadDatabase(this).conversationList
|
||||
val homeAdapter = HomeAdapter(this, cursor)
|
||||
@@ -119,6 +137,21 @@ class HomeActivity : PassphraseRequiredActionBarActivity, ConversationClickListe
|
||||
}
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
val isMasterDevice = (TextSecurePreferences.getMasterHexEncodedPublicKey(this) == null)
|
||||
val hasViewedSeed = TextSecurePreferences.getHasViewedSeed(this)
|
||||
if (hasViewedSeed || !isMasterDevice) {
|
||||
seedReminderView.visibility = View.GONE
|
||||
}
|
||||
}
|
||||
// endregion
|
||||
|
||||
override fun handleSeedReminderViewContinueButtonTapped() {
|
||||
val intent = Intent(this, SeedActivity::class.java)
|
||||
show(intent)
|
||||
}
|
||||
|
||||
override fun onConversationClick(view: ConversationView) {
|
||||
val thread = view.thread ?: return
|
||||
openConversation(thread)
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
package org.thoughtcrime.securesms.loki.redesign.activities
|
||||
|
||||
import android.content.ClipData
|
||||
import android.content.ClipboardManager
|
||||
import android.content.Context
|
||||
import android.os.Bundle
|
||||
import android.text.Spannable
|
||||
import android.text.SpannableString
|
||||
import android.text.style.ForegroundColorSpan
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.Toast
|
||||
import kotlinx.android.synthetic.main.activity_seed_v2.*
|
||||
import network.loki.messenger.R
|
||||
import org.thoughtcrime.securesms.BaseActionBarActivity
|
||||
import org.thoughtcrime.securesms.crypto.IdentityKeyUtil
|
||||
import org.thoughtcrime.securesms.loki.getColorWithID
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
||||
import org.whispersystems.signalservice.loki.crypto.MnemonicCodec
|
||||
import org.whispersystems.signalservice.loki.utilities.hexEncodedPrivateKey
|
||||
import java.io.File
|
||||
|
||||
class SeedActivity : BaseActionBarActivity() {
|
||||
|
||||
private val seed by lazy {
|
||||
val languageFileDirectory = File(applicationInfo.dataDir)
|
||||
var hexEncodedSeed = IdentityKeyUtil.retrieve(this, IdentityKeyUtil.lokiSeedKey)
|
||||
if (hexEncodedSeed == null) {
|
||||
hexEncodedSeed = IdentityKeyUtil.getIdentityKeyPair(this).hexEncodedPrivateKey // Legacy account
|
||||
}
|
||||
MnemonicCodec(languageFileDirectory).encode(hexEncodedSeed!!, MnemonicCodec.Language.Configuration.english)
|
||||
}
|
||||
|
||||
// region Lifecycle
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_seed_v2)
|
||||
supportActionBar!!.title = "Your Recovery Phrase"
|
||||
val seedReminderViewTitle = SpannableString("You're almost finished! 90%")
|
||||
seedReminderViewTitle.setSpan(ForegroundColorSpan(resources.getColorWithID(R.color.accent, theme)), 24, 27, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
|
||||
seedReminderView.title = seedReminderViewTitle
|
||||
seedReminderView.subtitle = "Press the redacted words to view your recovery phrase and secure your account"
|
||||
seedReminderView.setProgress(90, false)
|
||||
seedReminderView.hideContinueButton()
|
||||
var redactedSeed = seed
|
||||
var index = 0
|
||||
for (character in seed) {
|
||||
if (character.isLetter()) {
|
||||
redactedSeed = redactedSeed.replaceRange(index, index + 1, "▆")
|
||||
}
|
||||
index += 1
|
||||
}
|
||||
seedTextView.setTextColor(resources.getColorWithID(R.color.accent, theme))
|
||||
seedTextView.text = redactedSeed
|
||||
seedTextView.setOnLongClickListener { revealSeed(); true }
|
||||
revealButton.setOnLongClickListener { revealSeed(); true }
|
||||
copyButton.setOnClickListener { copySeed() }
|
||||
}
|
||||
// endregion
|
||||
|
||||
// region Updating
|
||||
private fun revealSeed() {
|
||||
val seedReminderViewTitle = SpannableString("Account secured! 100%")
|
||||
seedReminderViewTitle.setSpan(ForegroundColorSpan(resources.getColorWithID(R.color.accent, theme)), 17, 21, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
|
||||
seedReminderView.title = seedReminderViewTitle
|
||||
seedReminderView.subtitle = "Make sure to store your recovery phrase in a safe place"
|
||||
seedReminderView.setProgress(100, true)
|
||||
val seedTextViewLayoutParams = seedTextView.layoutParams as LinearLayout.LayoutParams
|
||||
seedTextViewLayoutParams.height = seedTextView.height
|
||||
seedTextView.layoutParams = seedTextViewLayoutParams
|
||||
seedTextView.setTextColor(resources.getColorWithID(R.color.text, theme))
|
||||
seedTextView.text = seed
|
||||
TextSecurePreferences.setHasViewedSeed(this, true)
|
||||
}
|
||||
// endregion
|
||||
|
||||
// region Interaction
|
||||
private fun copySeed() {
|
||||
revealSeed()
|
||||
val clipboard = getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
|
||||
val clip = ClipData.newPlainText("Seed", seed)
|
||||
clipboard.primaryClip = clip
|
||||
Toast.makeText(this, R.string.activity_register_public_key_copied_message, Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
// endregion
|
||||
}
|
||||
@@ -23,6 +23,7 @@ import nl.komponents.kovenant.all
|
||||
import nl.komponents.kovenant.deferred
|
||||
import nl.komponents.kovenant.ui.alwaysUi
|
||||
import org.thoughtcrime.securesms.ApplicationContext
|
||||
import org.thoughtcrime.securesms.ApplicationPreferencesActivity
|
||||
import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity
|
||||
import org.thoughtcrime.securesms.avatar.AvatarSelection
|
||||
import org.thoughtcrime.securesms.crypto.ProfileKeyUtil
|
||||
@@ -87,6 +88,7 @@ class SettingsActivity : PassphraseRequiredActionBarActivity() {
|
||||
seedButtonTopSeparator.visibility = View.GONE
|
||||
seedButton.visibility = View.GONE
|
||||
}
|
||||
privacyButton.setOnClickListener { showPrivacySettings() }
|
||||
seedButton.setOnClickListener { showSeed() }
|
||||
clearAllDataButton.setOnClickListener { clearAllData() }
|
||||
}
|
||||
@@ -247,6 +249,11 @@ class SettingsActivity : PassphraseRequiredActionBarActivity() {
|
||||
startActivity(intent)
|
||||
}
|
||||
|
||||
private fun showPrivacySettings() {
|
||||
val intent = Intent(this, ApplicationPreferencesActivity::class.java)
|
||||
push(intent)
|
||||
}
|
||||
|
||||
private fun showSeed() {
|
||||
SeedDialog().show(supportFragmentManager, "Recovery Phrase Dialog")
|
||||
}
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
package org.thoughtcrime.securesms.loki.redesign.views
|
||||
|
||||
import android.content.Context
|
||||
import android.os.Build
|
||||
import android.util.AttributeSet
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.widget.FrameLayout
|
||||
import kotlinx.android.synthetic.main.view_seed_reminder.view.*
|
||||
import network.loki.messenger.R
|
||||
|
||||
class SeedReminderView : FrameLayout {
|
||||
var title: CharSequence
|
||||
get() = titleTextView.text
|
||||
set(value) { titleTextView.text = value }
|
||||
var subtitle: CharSequence
|
||||
get() = subtitleTextView.text
|
||||
set(value) { subtitleTextView.text = value }
|
||||
var delegate: SeedReminderViewDelegate? = null
|
||||
|
||||
constructor(context: Context) : super(context) {
|
||||
setUpViewHierarchy()
|
||||
}
|
||||
|
||||
constructor(context: Context, attrs: AttributeSet) : super(context, attrs) {
|
||||
setUpViewHierarchy()
|
||||
}
|
||||
|
||||
constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(context, attrs, defStyleAttr) {
|
||||
setUpViewHierarchy()
|
||||
}
|
||||
|
||||
constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int, defStyleRes: Int) : super(context, attrs, defStyleAttr, defStyleRes) {
|
||||
setUpViewHierarchy()
|
||||
}
|
||||
|
||||
private fun setUpViewHierarchy() {
|
||||
val inflater = context.applicationContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
|
||||
val contentView = inflater.inflate(R.layout.view_seed_reminder, null)
|
||||
addView(contentView)
|
||||
button.setOnClickListener { delegate?.handleSeedReminderViewContinueButtonTapped() }
|
||||
}
|
||||
|
||||
fun setProgress(progress: Int, isAnimated: Boolean) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
progressBar.setProgress(progress, isAnimated)
|
||||
} else {
|
||||
progressBar.progress = progress
|
||||
}
|
||||
}
|
||||
|
||||
fun hideContinueButton() {
|
||||
button.visibility = View.GONE
|
||||
}
|
||||
}
|
||||
|
||||
interface SeedReminderViewDelegate {
|
||||
|
||||
fun handleSeedReminderViewContinueButtonTapped()
|
||||
}
|
||||
@@ -1195,6 +1195,14 @@ public class TextSecurePreferences {
|
||||
setStringPreference(context, "master_hex_encoded_public_key", masterHexEncodedPublicKey.toLowerCase());
|
||||
}
|
||||
|
||||
public static Boolean getHasViewedSeed(Context context) {
|
||||
return getBooleanPreference(context, "has_viewed_seed", false);
|
||||
}
|
||||
|
||||
public static void setHasViewedSeed(Context context, Boolean hasViewedSeed) {
|
||||
setBooleanPreference(context, "has_viewed_seed", hasViewedSeed);
|
||||
}
|
||||
|
||||
public static void setResetDatabase(Context context, boolean resetDatabase) {
|
||||
// We do it this way so that it gets persisted in storage straight away
|
||||
PreferenceManager.getDefaultSharedPreferences(context).edit().putBoolean("database_reset", resetDatabase).commit();
|
||||
|
||||
Reference in New Issue
Block a user