From 6d9473b277ae7fe9e8b28af06a9cddf473a9bbe1 Mon Sep 17 00:00:00 2001 From: Jakob Nixdorf Date: Mon, 13 Nov 2017 14:48:34 +0100 Subject: [PATCH 1/7] Add an option to scroll overlong labels instead of simply truncating them --- .../flocke/andotp/Activities/MainActivity.java | 3 ++- .../shadowice/flocke/andotp/Utilities/Settings.java | 4 ++++ .../flocke/andotp/View/EntriesCardAdapter.java | 2 ++ .../flocke/andotp/View/EntryViewHolder.java | 13 +++++++++++++ app/src/main/res/values/settings.xml | 1 + app/src/main/res/values/strings_settings.xml | 3 +++ app/src/main/res/xml/preferences.xml | 6 ++++++ 7 files changed, 31 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/org/shadowice/flocke/andotp/Activities/MainActivity.java b/app/src/main/java/org/shadowice/flocke/andotp/Activities/MainActivity.java index 980465c7..8842813a 100644 --- a/app/src/main/java/org/shadowice/flocke/andotp/Activities/MainActivity.java +++ b/app/src/main/java/org/shadowice/flocke/andotp/Activities/MainActivity.java @@ -363,7 +363,8 @@ public class MainActivity extends BaseActivity public void onSharedPreferenceChanged(SharedPreferences prefs, String key) { if (key.equals(getString(R.string.settings_key_label_size)) || - key.equals(getString(R.string.settings_key_tap_to_reveal))) { + key.equals(getString(R.string.settings_key_tap_to_reveal)) || + key.equals(getString(R.string.settings_key_label_scroll))) { adapter.notifyDataSetChanged(); } else if (key.equals(getString(R.string.settings_key_theme))) { recreate(); diff --git a/app/src/main/java/org/shadowice/flocke/andotp/Utilities/Settings.java b/app/src/main/java/org/shadowice/flocke/andotp/Utilities/Settings.java index a1b9b1c9..6aaa1889 100644 --- a/app/src/main/java/org/shadowice/flocke/andotp/Utilities/Settings.java +++ b/app/src/main/java/org/shadowice/flocke/andotp/Utilities/Settings.java @@ -206,6 +206,10 @@ public class Settings { return getString(R.string.settings_key_theme, R.string.settings_default_theme); } + public boolean getScrollLabel() { + return getBoolean(R.string.settings_key_label_scroll, false); + } + public boolean getFirstTimeWarningShown() { return getBoolean(R.string.settings_key_security_backup_warning, false); } diff --git a/app/src/main/java/org/shadowice/flocke/andotp/View/EntriesCardAdapter.java b/app/src/main/java/org/shadowice/flocke/andotp/View/EntriesCardAdapter.java index 1964cfef..7e3859a3 100644 --- a/app/src/main/java/org/shadowice/flocke/andotp/View/EntriesCardAdapter.java +++ b/app/src/main/java/org/shadowice/flocke/andotp/View/EntriesCardAdapter.java @@ -135,6 +135,8 @@ public class EntriesCardAdapter extends RecyclerView.Adapter int fontSize = sharedPrefs.getInt(context.getString(R.string.settings_key_label_size), context.getResources().getInteger(R.integer.settings_default_label_size)); entryViewHolder.setLabelSize(fontSize); + + entryViewHolder.setLabelScroll(sharedPrefs.getBoolean(context.getString(R.string.settings_key_label_scroll), false)); } @Override diff --git a/app/src/main/java/org/shadowice/flocke/andotp/View/EntryViewHolder.java b/app/src/main/java/org/shadowice/flocke/andotp/View/EntryViewHolder.java index dc1df524..e7b57b93 100644 --- a/app/src/main/java/org/shadowice/flocke/andotp/View/EntryViewHolder.java +++ b/app/src/main/java/org/shadowice/flocke/andotp/View/EntryViewHolder.java @@ -26,6 +26,7 @@ import android.content.Context; import android.graphics.ColorFilter; import android.support.v7.widget.CardView; import android.support.v7.widget.RecyclerView; +import android.text.TextUtils; import android.util.TypedValue; import android.view.View; import android.widget.ImageButton; @@ -116,6 +117,18 @@ public class EntryViewHolder extends RecyclerView.ViewHolder label.setTextSize(TypedValue.COMPLEX_UNIT_PT, size); } + public void setLabelScroll(boolean active) { + if (active) { + label.setEllipsize(TextUtils.TruncateAt.MARQUEE); + label.setHorizontallyScrolling(true); + label.setSelected(true); + } else { + label.setEllipsize(TextUtils.TruncateAt.END); + label.setHorizontallyScrolling(false); + label.setSelected(false); + } + } + public void enableTapToReveal() { valueLayout.setVisibility(View.GONE); coverLayout.setVisibility(View.VISIBLE); diff --git a/app/src/main/res/values/settings.xml b/app/src/main/res/values/settings.xml index 84a98bbb..fc4146e7 100644 --- a/app/src/main/res/values/settings.xml +++ b/app/src/main/res/values/settings.xml @@ -13,6 +13,7 @@ pref_theme pref_label_size + pref_label_scroll pref_backup_ask pref_backup_directory diff --git a/app/src/main/res/values/strings_settings.xml b/app/src/main/res/values/strings_settings.xml index b34cd8eb..3202f1f7 100644 --- a/app/src/main/res/values/strings_settings.xml +++ b/app/src/main/res/values/strings_settings.xml @@ -16,6 +16,7 @@ Theme Label font size + Scroll label Ask for filename Backup directory @@ -30,6 +31,8 @@ revealed manually Decide what happens when a Panic Trigger is received + Scroll overlong labels instead of truncating them + Ask for the filename every time a backup is created or restored Directory for the backups (filenames will depend diff --git a/app/src/main/res/xml/preferences.xml b/app/src/main/res/xml/preferences.xml index d8d5047e..fdfc2aef 100644 --- a/app/src/main/res/xml/preferences.xml +++ b/app/src/main/res/xml/preferences.xml @@ -52,6 +52,12 @@ app:vnt_maxValue="@integer/settings_max_label_size" app:vnt_minValue="@integer/settings_min_label_size" /> + + Date: Mon, 13 Nov 2017 16:14:08 +0100 Subject: [PATCH 2/7] Convert secrets from JSON files to upper-case Fixes #55 --- .../main/java/org/shadowice/flocke/andotp/Database/Entry.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/org/shadowice/flocke/andotp/Database/Entry.java b/app/src/main/java/org/shadowice/flocke/andotp/Database/Entry.java index 94ab69d2..7afe5445 100644 --- a/app/src/main/java/org/shadowice/flocke/andotp/Database/Entry.java +++ b/app/src/main/java/org/shadowice/flocke/andotp/Database/Entry.java @@ -119,7 +119,7 @@ public class Entry { } public Entry (JSONObject jsonObj) throws JSONException { - this.secret = new Base32().decode(jsonObj.getString(JSON_SECRET)); + this.secret = new Base32().decode(jsonObj.getString(JSON_SECRET).toUpperCase()); this.label = jsonObj.getString(JSON_LABEL); this.period = jsonObj.getInt(JSON_PERIOD); From 6fb96e18a91cb940e4729b46f943746d45dc9fb5 Mon Sep 17 00:00:00 2001 From: Jakob Nixdorf Date: Tue, 14 Nov 2017 15:44:53 +0100 Subject: [PATCH 3/7] Add the option to append entries during restore --- .../andotp/Activities/BackupActivity.java | 32 +++++++++++++++++-- .../andotp/Utilities/DatabaseHelper.java | 15 +++------ app/src/main/res/layout/content_backup.xml | 26 +++++++++++++++ app/src/main/res/values/strings_backup.xml | 2 ++ 4 files changed, 62 insertions(+), 13 deletions(-) diff --git a/app/src/main/java/org/shadowice/flocke/andotp/Activities/BackupActivity.java b/app/src/main/java/org/shadowice/flocke/andotp/Activities/BackupActivity.java index e596f64a..627127c0 100644 --- a/app/src/main/java/org/shadowice/flocke/andotp/Activities/BackupActivity.java +++ b/app/src/main/java/org/shadowice/flocke/andotp/Activities/BackupActivity.java @@ -40,6 +40,7 @@ import android.util.Log; import android.view.View; import android.view.ViewStub; import android.widget.LinearLayout; +import android.widget.Switch; import android.widget.TextView; import android.widget.Toast; @@ -92,6 +93,8 @@ public class BackupActivity extends BaseActivity { private Uri encryptTargetFile; private Uri decryptSourceFile; + private Switch replace; + private boolean reload = false; @Override @@ -193,6 +196,8 @@ public class BackupActivity extends BaseActivity { }); } + replace = v.findViewById(R.id.backup_replace); + } // End with a result @@ -361,10 +366,18 @@ public class BackupActivity extends BaseActivity { private void doRestorePlain(Uri uri) { if (Tools.isExternalStorageReadable()) { - boolean success = DatabaseHelper.importFromJSON(this, uri); + ArrayList entries = DatabaseHelper.importFromJSON(this, uri); - if (success) { + if (entries != null) { + if (! replace.isChecked()) { + ArrayList currentEntries = DatabaseHelper.loadDatabase(this); + entries.removeAll(currentEntries); + entries.addAll(currentEntries); + } + + DatabaseHelper.saveDatabase(this, entries); reload = true; + Toast.makeText(this, R.string.backup_toast_import_success, Toast.LENGTH_LONG).show(); } else { Toast.makeText(this, R.string.backup_toast_import_failed, Toast.LENGTH_LONG).show(); @@ -427,6 +440,13 @@ public class BackupActivity extends BaseActivity { byte[] decrypted = EncryptionHelper.decrypt(key, encrypted); ArrayList entries = DatabaseHelper.stringToEntries(new String(decrypted, StandardCharsets.UTF_8)); + + if (! replace.isChecked()) { + ArrayList currentEntries = DatabaseHelper.loadDatabase(this); + entries.removeAll(currentEntries); + entries.addAll(currentEntries); + } + DatabaseHelper.saveDatabase(this, entries); } catch (Exception e) { e.printStackTrace(); @@ -491,9 +511,15 @@ public class BackupActivity extends BaseActivity { ArrayList entries = DatabaseHelper.stringToEntries(content); if (entries.size() > 0) { - DatabaseHelper.saveDatabase(this, entries); + if (! replace.isChecked()) { + ArrayList currentEntries = DatabaseHelper.loadDatabase(this); + entries.removeAll(currentEntries); + entries.addAll(currentEntries); + } + DatabaseHelper.saveDatabase(this, entries); reload = true; + Toast.makeText(this, R.string.backup_toast_import_success, Toast.LENGTH_LONG).show(); } else { Toast.makeText(this, R.string.backup_toast_import_failed, Toast.LENGTH_LONG).show(); diff --git a/app/src/main/java/org/shadowice/flocke/andotp/Utilities/DatabaseHelper.java b/app/src/main/java/org/shadowice/flocke/andotp/Utilities/DatabaseHelper.java index 68c3c3e1..477e1c93 100644 --- a/app/src/main/java/org/shadowice/flocke/andotp/Utilities/DatabaseHelper.java +++ b/app/src/main/java/org/shadowice/flocke/andotp/Utilities/DatabaseHelper.java @@ -113,19 +113,14 @@ public class DatabaseHelper { return FileHelper.writeStringToFile(context, file, entriesToString(entries)); } - public static boolean importFromJSON(Context context, Uri file) { - boolean success = false; - + public static ArrayList importFromJSON(Context context, Uri file) { String content = FileHelper.readFileToString(context, file); - if (! content.isEmpty()) { - ArrayList entries = stringToEntries(content); + ArrayList entries = null; - saveDatabase(context, entries); + if (! content.isEmpty()) + entries = stringToEntries(content); - success = true; - } - - return success; + return entries; } } \ No newline at end of file diff --git a/app/src/main/res/layout/content_backup.xml b/app/src/main/res/layout/content_backup.xml index cce0cd2e..4cc475bb 100644 --- a/app/src/main/res/layout/content_backup.xml +++ b/app/src/main/res/layout/content_backup.xml @@ -191,5 +191,31 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/strings_backup.xml b/app/src/main/res/values/strings_backup.xml index 0d8d24c4..c15347d6 100644 --- a/app/src/main/res/values/strings_backup.xml +++ b/app/src/main/res/values/strings_backup.xml @@ -31,6 +31,8 @@ before you can create encrypted backups. + Replace already existing entries + Security warning From 07fc20bc0d27a528b7cb13ca2006599c509fa56b Mon Sep 17 00:00:00 2001 From: Jakob Nixdorf Date: Wed, 15 Nov 2017 11:48:26 +0100 Subject: [PATCH 4/7] Add in-app language switcher Closes #53 --- .../andotp/Activities/MainActivity.java | 3 ++- .../andotp/Activities/SettingsActivity.java | 3 ++- .../andotp/Activities/ThemedActivity.java | 27 ++++++++++++++++++- .../flocke/andotp/Utilities/Settings.java | 10 +++++++ .../flocke/andotp/Utilities/Tools.java | 10 +++++++ app/src/main/res/values/settings.xml | 15 +++++++++++ app/src/main/res/values/strings_settings.xml | 14 ++++++++++ app/src/main/res/xml/preferences.xml | 8 ++++++ 8 files changed, 87 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/org/shadowice/flocke/andotp/Activities/MainActivity.java b/app/src/main/java/org/shadowice/flocke/andotp/Activities/MainActivity.java index 8842813a..617b349f 100644 --- a/app/src/main/java/org/shadowice/flocke/andotp/Activities/MainActivity.java +++ b/app/src/main/java/org/shadowice/flocke/andotp/Activities/MainActivity.java @@ -366,7 +366,8 @@ public class MainActivity extends BaseActivity key.equals(getString(R.string.settings_key_tap_to_reveal)) || key.equals(getString(R.string.settings_key_label_scroll))) { adapter.notifyDataSetChanged(); - } else if (key.equals(getString(R.string.settings_key_theme))) { + } else if (key.equals(getString(R.string.settings_key_theme)) || + key.equals(getString(R.string.settings_key_lang))) { recreate(); } } diff --git a/app/src/main/java/org/shadowice/flocke/andotp/Activities/SettingsActivity.java b/app/src/main/java/org/shadowice/flocke/andotp/Activities/SettingsActivity.java index 0024b0e8..6f85ccad 100644 --- a/app/src/main/java/org/shadowice/flocke/andotp/Activities/SettingsActivity.java +++ b/app/src/main/java/org/shadowice/flocke/andotp/Activities/SettingsActivity.java @@ -85,7 +85,8 @@ public class SettingsActivity extends BaseActivity } public void onSharedPreferenceChanged(SharedPreferences prefs, String key) { - if (key.equals(getString(R.string.settings_key_theme))) { + if (key.equals(getString(R.string.settings_key_theme)) || + key.equals(getString(R.string.settings_key_lang))) { recreate(); } } diff --git a/app/src/main/java/org/shadowice/flocke/andotp/Activities/ThemedActivity.java b/app/src/main/java/org/shadowice/flocke/andotp/Activities/ThemedActivity.java index 71cbe2a9..1824dbad 100644 --- a/app/src/main/java/org/shadowice/flocke/andotp/Activities/ThemedActivity.java +++ b/app/src/main/java/org/shadowice/flocke/andotp/Activities/ThemedActivity.java @@ -22,12 +22,15 @@ package org.shadowice.flocke.andotp.Activities; +import android.content.res.Configuration; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import org.shadowice.flocke.andotp.R; import org.shadowice.flocke.andotp.Utilities.Settings; +import java.util.Locale; + public abstract class ThemedActivity extends AppCompatActivity { public Settings settings; @@ -35,6 +38,20 @@ public abstract class ThemedActivity extends AppCompatActivity { protected void onCreate(Bundle savedInstanceState) { settings = new Settings(this); + setTheme(); + setLocale(); + + super.onCreate(savedInstanceState); + } + + @Override + public void onResume() { + setLocale(); + + super.onResume(); + } + + public void setTheme() { String theme = settings.getTheme(); if (theme.equals("light")) { @@ -44,7 +61,15 @@ public abstract class ThemedActivity extends AppCompatActivity { } else if (theme.equals("black")) { setTheme(R.style.AppTheme_Black_NoActionBar); } + } - super.onCreate(savedInstanceState); + public void setLocale() { + Locale locale = settings.getLang(); + Locale.setDefault(locale); + + Configuration config = new Configuration(); + config.locale = locale; + + getBaseContext().getResources().updateConfiguration(config, getBaseContext().getResources().getDisplayMetrics()); } } diff --git a/app/src/main/java/org/shadowice/flocke/andotp/Utilities/Settings.java b/app/src/main/java/org/shadowice/flocke/andotp/Utilities/Settings.java index 6aaa1889..b9a9a4e6 100644 --- a/app/src/main/java/org/shadowice/flocke/andotp/Utilities/Settings.java +++ b/app/src/main/java/org/shadowice/flocke/andotp/Utilities/Settings.java @@ -36,6 +36,7 @@ import java.io.File; import java.nio.charset.StandardCharsets; import java.security.KeyPair; import java.util.Collections; +import java.util.Locale; import java.util.Set; import static org.shadowice.flocke.andotp.Preferences.PasswordEncryptedPreference.KEY_ALIAS; @@ -202,6 +203,15 @@ public class Settings { return settings.getStringSet(getResString(R.string.settings_key_panic), Collections.emptySet()); } + public Locale getLang() { + String lang = getString(R.string.settings_key_lang, R.string.settings_default_lang); + + if (lang.equals("system")) + return Tools.getSystemLocale(); + else + return new Locale(lang); + } + public String getTheme() { return getString(R.string.settings_key_theme, R.string.settings_default_theme); } diff --git a/app/src/main/java/org/shadowice/flocke/andotp/Utilities/Tools.java b/app/src/main/java/org/shadowice/flocke/andotp/Utilities/Tools.java index ef434d77..faefd08e 100644 --- a/app/src/main/java/org/shadowice/flocke/andotp/Utilities/Tools.java +++ b/app/src/main/java/org/shadowice/flocke/andotp/Utilities/Tools.java @@ -29,9 +29,11 @@ import android.graphics.ColorFilter; import android.graphics.PorterDuff; import android.graphics.PorterDuffColorFilter; import android.net.Uri; +import android.os.Build; import android.os.Environment; import java.io.File; +import java.util.Locale; public class Tools { /* Checks if external storage is available for read and write */ @@ -70,4 +72,12 @@ public class Tools { File dir = new File(path); return dir.exists() || dir.mkdirs(); } + + public static Locale getSystemLocale() { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + return Resources.getSystem().getConfiguration().getLocales().get(0); + } else { + return Resources.getSystem().getConfiguration().locale; + } + } } diff --git a/app/src/main/res/values/settings.xml b/app/src/main/res/values/settings.xml index fc4146e7..f6146bf8 100644 --- a/app/src/main/res/values/settings.xml +++ b/app/src/main/res/values/settings.xml @@ -11,6 +11,7 @@ pref_auth_pin_hash pref_panic + pref_lang pref_theme pref_label_size pref_label_scroll @@ -30,6 +31,7 @@ none + system light 8 @@ -46,6 +48,19 @@ settings + + system + en + cs + de + es + fr + gl + nl + pl + ru + + light dark diff --git a/app/src/main/res/values/strings_settings.xml b/app/src/main/res/values/strings_settings.xml index 3202f1f7..aebf17e4 100644 --- a/app/src/main/res/values/strings_settings.xml +++ b/app/src/main/res/values/strings_settings.xml @@ -14,6 +14,7 @@ PIN Panic Trigger + Language Theme Label font size Scroll label @@ -64,6 +65,19 @@ Reset app settings + + System default + English + Czech + German + Spanish + French + Galician + Dutch + Polish + Russian + + Light theme Dark theme diff --git a/app/src/main/res/xml/preferences.xml b/app/src/main/res/xml/preferences.xml index fdfc2aef..8c32e7ea 100644 --- a/app/src/main/res/xml/preferences.xml +++ b/app/src/main/res/xml/preferences.xml @@ -37,6 +37,14 @@ + + Date: Wed, 15 Nov 2017 13:30:18 +0100 Subject: [PATCH 5/7] AboutActivity: fix layout for some translations --- app/src/main/res/layout/content_about.xml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/src/main/res/layout/content_about.xml b/app/src/main/res/layout/content_about.xml index 240601d4..35d1d7ab 100644 --- a/app/src/main/res/layout/content_about.xml +++ b/app/src/main/res/layout/content_about.xml @@ -486,7 +486,7 @@ android:id="@+id/about_layout_bugs" android:orientation="horizontal" android:layout_width="match_parent" - android:layout_height="?android:attr/listPreferredItemHeight" + android:layout_height="wrap_content" android:layout_marginTop="@dimen/activity_margin" android:paddingTop="@dimen/activity_margin_small" android:paddingBottom="@dimen/activity_margin_small" @@ -504,7 +504,7 @@ Date: Wed, 15 Nov 2017 13:38:04 +0100 Subject: [PATCH 6/7] MainActivity: fix layout for some translations --- .../main/res/layout/dialog_manual_entry.xml | 20 ++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/app/src/main/res/layout/dialog_manual_entry.xml b/app/src/main/res/layout/dialog_manual_entry.xml index c75ca8c5..0f257090 100644 --- a/app/src/main/res/layout/dialog_manual_entry.xml +++ b/app/src/main/res/layout/dialog_manual_entry.xml @@ -9,10 +9,11 @@ @@ -28,10 +29,11 @@ @@ -48,10 +50,11 @@ @@ -61,7 +64,7 @@ android:layout_weight="7" android:layout_width="0dp" android:layout_height="wrap_content" - android:lines="2" + android:lines="3" android:hint="@string/hint_secret" /> @@ -69,10 +72,11 @@ @@ -90,10 +94,11 @@ @@ -111,10 +116,11 @@ From 6a7ea85dcff80cfba19501651b53b50c86b1856c Mon Sep 17 00:00:00 2001 From: Jakob Nixdorf Date: Wed, 15 Nov 2017 13:43:23 +0100 Subject: [PATCH 7/7] Change the cover for hidden labels to "Hidden" This makes it shorter and hopefully fixes broken layouts in some translations --- app/src/main/res/layout/component_card.xml | 2 +- app/src/main/res/values/strings_main.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/res/layout/component_card.xml b/app/src/main/res/layout/component_card.xml index 568b1611..839975c5 100644 --- a/app/src/main/res/layout/component_card.xml +++ b/app/src/main/res/layout/component_card.xml @@ -66,7 +66,7 @@ android:textColor="?android:attr/textColorSecondary" android:textSize="28sp" android:textStyle="bold" - android:text="@string/label_tap_to_reveal" /> + android:text="@string/label_hidden" /> diff --git a/app/src/main/res/values/strings_main.xml b/app/src/main/res/values/strings_main.xml index d5eb4193..84f76ffa 100644 --- a/app/src/main/res/values/strings_main.xml +++ b/app/src/main/res/values/strings_main.xml @@ -17,7 +17,7 @@ OTP Token - Tap to reveal + Hidden Type Secret Period