Update app icon & implement recovery phrase screen

This commit is contained in:
Niels Andriesse
2020-01-09 11:35:43 +11:00
parent df61cbb30d
commit 8a5307000b
34 changed files with 400 additions and 48 deletions

View File

@@ -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));
}

View File

@@ -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));
}

View File

@@ -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...");

View File

@@ -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)

View File

@@ -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
}

View File

@@ -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")
}

View File

@@ -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()
}

View File

@@ -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();