From 04e6e368110849b5e927b4090b3bb2127392c8f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20Sch=C3=A4ttgen?= Date: Wed, 6 Jun 2018 21:26:09 +0200 Subject: [PATCH 01/14] Started working on custom profile images --- app/build.gradle | 2 + .../me/impy/aegis/ui/EditProfileActivity.java | 42 +++++++++++++++++++ .../main/res/layout/activity_edit_profile.xml | 28 +++++++++---- 3 files changed, 63 insertions(+), 9 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 5606dfbb..b9646da8 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -36,6 +36,8 @@ dependencies { implementation 'com.amulyakhare:com.amulyakhare.textdrawable:1.0.1' implementation 'me.dm7.barcodescanner:zxing:1.9' implementation 'com.android.support:cardview-v7:27.1.1' + implementation 'com.github.esafirm.android-image-picker:imagepicker:1.13.0' + compile 'com.github.avito-tech:krop:3e65e12' implementation 'com.android.support:support-v4:27.1.1' implementation 'com.mattprecious.swirl:swirl:1.0.0' implementation 'com.madgag.spongycastle:core:1.56.0.0' diff --git a/app/src/main/java/me/impy/aegis/ui/EditProfileActivity.java b/app/src/main/java/me/impy/aegis/ui/EditProfileActivity.java index 6430dde8..b522471f 100644 --- a/app/src/main/java/me/impy/aegis/ui/EditProfileActivity.java +++ b/app/src/main/java/me/impy/aegis/ui/EditProfileActivity.java @@ -1,6 +1,9 @@ package me.impy.aegis.ui; import android.content.Intent; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.Color; import android.os.Bundle; import android.support.annotation.ArrayRes; import android.support.v7.app.ActionBar; @@ -21,6 +24,10 @@ import android.widget.RelativeLayout; import android.widget.Spinner; import com.amulyakhare.textdrawable.TextDrawable; +import com.avito.android.krop.KropView; +import com.esafirm.imagepicker.features.ImagePicker; +import com.esafirm.imagepicker.features.ReturnMode; +import com.esafirm.imagepicker.model.Image; import me.impy.aegis.R; import me.impy.aegis.crypto.KeyInfo; @@ -50,6 +57,8 @@ public class EditProfileActivity extends AegisActivity { private Spinner _spinnerDigits; private SpinnerItemSelectedListener _selectedListener = new SpinnerItemSelectedListener(); + private KropView _kropView; + private RelativeLayout _advancedSettingsHeader; private RelativeLayout _advancedSettings; @@ -74,6 +83,7 @@ public class EditProfileActivity extends AegisActivity { } _iconView = findViewById(R.id.profile_drawable); + _kropView = findViewById(R.id.krop_view); _textName = findViewById(R.id.text_name); _textIssuer = findViewById(R.id.text_issuer); _textPeriod = findViewById(R.id.text_period); @@ -118,6 +128,24 @@ public class EditProfileActivity extends AegisActivity { } }); + ImagePicker imagePicker = ImagePicker.create(EditProfileActivity.this) + .returnMode(ReturnMode.ALL) // set whether pick and / or camera action should return immediate result or not. + .folderMode(true) // folder mode (false by default) + .toolbarFolderTitle("Folder") // folder selection title + .toolbarImageTitle("Tap to select") // image selection title + .toolbarArrowColor(Color.BLACK) // Toolbar 'up' arrow color + .single() // single mode + .showCamera(false) // show camera or not (true by default) + .imageDirectory("Camera"); + + // Open ImagePicker when clicking on the icon + _iconView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + imagePicker.start(); // start image picker activity with request code + } + }); + _advancedSettingsHeader.setOnClickListener(v -> { openAdvancedSettings(); }); @@ -258,6 +286,20 @@ public class EditProfileActivity extends AegisActivity { finish(); } + @Override + protected void onActivityResult(int requestCode, final int resultCode, Intent data) { + if (ImagePicker.shouldHandle(requestCode, resultCode, data)) { + // or get a single image only + Image image = ImagePicker.getFirstImageOrNull(data); + BitmapFactory.Options bmOptions = new BitmapFactory.Options(); + Bitmap bitmap = BitmapFactory.decodeFile(image.getPath(),bmOptions); + _kropView.setBitmap(bitmap); + _kropView.setVisibility(View.VISIBLE); + } + + super.onActivityResult(requestCode, resultCode, data); + } + private boolean onSave() { if (_textSecret.length() == 0) { onError("Secret is a required field."); diff --git a/app/src/main/res/layout/activity_edit_profile.xml b/app/src/main/res/layout/activity_edit_profile.xml index 55078e00..d048074a 100644 --- a/app/src/main/res/layout/activity_edit_profile.xml +++ b/app/src/main/res/layout/activity_edit_profile.xml @@ -16,18 +16,28 @@ android:layout_height="250dp" android:background="@color/colorPrimary"> - + - + android:layout_centerHorizontal="true" + android:layout_centerVertical="true" + android:scaleType="centerCrop" /> + + + + From d8bfe2e94736e9b3c40dd19a99daa29ef4f0f49a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20Sch=C3=A4ttgen?= Date: Wed, 6 Jun 2018 21:57:38 +0200 Subject: [PATCH 02/14] User is now able to crop custom images --- app/build.gradle | 1 + .../me/impy/aegis/helpers/TextDrawableHelper.java | 4 +++- .../java/me/impy/aegis/ui/EditProfileActivity.java | 13 ++++++++++++- app/src/main/res/drawable/ic_check_black_24dp.xml | 9 +++++++++ app/src/main/res/layout/activity_edit_profile.xml | 14 +++++++++++--- 5 files changed, 36 insertions(+), 5 deletions(-) create mode 100644 app/src/main/res/drawable/ic_check_black_24dp.xml diff --git a/app/build.gradle b/app/build.gradle index b9646da8..dcb307fe 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -32,6 +32,7 @@ dependencies { implementation 'com.android.support:recyclerview-v7:27.1.1' implementation 'com.android.support:appcompat-v7:27.1.1' implementation 'com.android.support:design:27.1.1' + implementation 'de.hdodenhof:circleimageview:2.2.0' implementation 'com.takisoft.fix:preference-v7:27.1.1.1' implementation 'com.amulyakhare:com.amulyakhare.textdrawable:1.0.1' implementation 'me.dm7.barcodescanner:zxing:1.9' diff --git a/app/src/main/java/me/impy/aegis/helpers/TextDrawableHelper.java b/app/src/main/java/me/impy/aegis/helpers/TextDrawableHelper.java index 7f4afeec..cdf96610 100644 --- a/app/src/main/java/me/impy/aegis/helpers/TextDrawableHelper.java +++ b/app/src/main/java/me/impy/aegis/helpers/TextDrawableHelper.java @@ -15,6 +15,8 @@ public class TextDrawableHelper { ColorGenerator generator = ColorGenerator.MATERIAL; int color = generator.getColor(s); - return TextDrawable.builder().buildRound(s.substring(0, 1).toUpperCase(), color); + return TextDrawable.builder().beginConfig() + .width(100) + .height(100).endConfig().buildRect(s.substring(0, 1).toUpperCase(), color); } } diff --git a/app/src/main/java/me/impy/aegis/ui/EditProfileActivity.java b/app/src/main/java/me/impy/aegis/ui/EditProfileActivity.java index b522471f..59724f95 100644 --- a/app/src/main/java/me/impy/aegis/ui/EditProfileActivity.java +++ b/app/src/main/java/me/impy/aegis/ui/EditProfileActivity.java @@ -29,6 +29,7 @@ import com.esafirm.imagepicker.features.ImagePicker; import com.esafirm.imagepicker.features.ReturnMode; import com.esafirm.imagepicker.model.Image; +import de.hdodenhof.circleimageview.CircleImageView; import me.impy.aegis.R; import me.impy.aegis.crypto.KeyInfo; import me.impy.aegis.crypto.KeyInfoException; @@ -45,7 +46,8 @@ public class EditProfileActivity extends AegisActivity { private boolean _edited = false; private KeyProfile _profile; - private ImageView _iconView; + private CircleImageView _iconView; + private ImageView _saveImageButton; private EditText _textName; private EditText _textIssuer; @@ -84,6 +86,7 @@ public class EditProfileActivity extends AegisActivity { _iconView = findViewById(R.id.profile_drawable); _kropView = findViewById(R.id.krop_view); + _saveImageButton = findViewById(R.id.iv_saveImage); _textName = findViewById(R.id.text_name); _textIssuer = findViewById(R.id.text_issuer); _textPeriod = findViewById(R.id.text_period); @@ -295,6 +298,14 @@ public class EditProfileActivity extends AegisActivity { Bitmap bitmap = BitmapFactory.decodeFile(image.getPath(),bmOptions); _kropView.setBitmap(bitmap); _kropView.setVisibility(View.VISIBLE); + + _saveImageButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + _iconView.setImageBitmap(_kropView.getCroppedBitmap()); + _kropView.setVisibility(View.GONE); + } + }); } super.onActivityResult(requestCode, resultCode, data); diff --git a/app/src/main/res/drawable/ic_check_black_24dp.xml b/app/src/main/res/drawable/ic_check_black_24dp.xml new file mode 100644 index 00000000..3c728c59 --- /dev/null +++ b/app/src/main/res/drawable/ic_check_black_24dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/layout/activity_edit_profile.xml b/app/src/main/res/layout/activity_edit_profile.xml index d048074a..289e7662 100644 --- a/app/src/main/res/layout/activity_edit_profile.xml +++ b/app/src/main/res/layout/activity_edit_profile.xml @@ -16,14 +16,14 @@ android:layout_height="250dp" android:background="@color/colorPrimary"> - - + /> + From 11b195aab30cddfd8047b6bda3b5a02be63cefc8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20Sch=C3=A4ttgen?= Date: Wed, 6 Jun 2018 22:22:38 +0200 Subject: [PATCH 03/14] Added (de)serialization for the custom images --- .../java/me/impy/aegis/crypto/KeyInfo.java | 19 +++++++++++ .../me/impy/aegis/ui/EditProfileActivity.java | 32 +++++++++++++++++++ 2 files changed, 51 insertions(+) diff --git a/app/src/main/java/me/impy/aegis/crypto/KeyInfo.java b/app/src/main/java/me/impy/aegis/crypto/KeyInfo.java index 5d6f9231..9103ec63 100644 --- a/app/src/main/java/me/impy/aegis/crypto/KeyInfo.java +++ b/app/src/main/java/me/impy/aegis/crypto/KeyInfo.java @@ -1,6 +1,7 @@ package me.impy.aegis.crypto; import android.net.Uri; +import android.util.Base64; import java.io.Serializable; import java.util.Arrays; @@ -17,6 +18,7 @@ public class KeyInfo implements Serializable { private String _algorithm = "SHA1"; private int _digits = 6; private int _period = 30; + private String _image; public String getURL() { Uri.Builder builder = new Uri.Builder(); @@ -27,6 +29,9 @@ public class KeyInfo implements Serializable { builder.appendQueryParameter("period", Integer.toString(_period)); builder.appendQueryParameter("algorithm", _algorithm); builder.appendQueryParameter("secret", new String(Base32.encode(_secret))); + if (_image != null && !_image.equals("")) { + builder.appendQueryParameter("image", _image); + } if (_type.equals("hotp")) { builder.appendQueryParameter("counter", Long.toString(_counter)); } @@ -103,6 +108,10 @@ public class KeyInfo implements Serializable { if (digits != null) { info.setDigits(Integer.parseInt(digits)); } + String image = url.getQueryParameter("image"); + if (image != null) { + info.setImage(Base64.decode(image, Base64.DEFAULT)); + } // 'counter' is required if the type is 'hotp' String counter = url.getQueryParameter("counter"); @@ -173,6 +182,16 @@ public class KeyInfo implements Serializable { setSecret(secret); } + public void setImage(byte[] image) + { + _image = Base64.encodeToString(image, Base64.DEFAULT); + } + + public byte[] getImage() + { + return Base64.decode(_image, Base64.DEFAULT); + } + public void setSecret(byte[] secret) { _secret = secret; } diff --git a/app/src/main/java/me/impy/aegis/ui/EditProfileActivity.java b/app/src/main/java/me/impy/aegis/ui/EditProfileActivity.java index 59724f95..fe04ea70 100644 --- a/app/src/main/java/me/impy/aegis/ui/EditProfileActivity.java +++ b/app/src/main/java/me/impy/aegis/ui/EditProfileActivity.java @@ -3,7 +3,10 @@ package me.impy.aegis.ui; import android.content.Intent; import android.graphics.Bitmap; import android.graphics.BitmapFactory; +import android.graphics.Canvas; import android.graphics.Color; +import android.graphics.drawable.BitmapDrawable; +import android.graphics.drawable.Drawable; import android.os.Bundle; import android.support.annotation.ArrayRes; import android.support.v7.app.ActionBar; @@ -29,6 +32,8 @@ import com.esafirm.imagepicker.features.ImagePicker; import com.esafirm.imagepicker.features.ReturnMode; import com.esafirm.imagepicker.model.Image; +import java.io.ByteArrayOutputStream; + import de.hdodenhof.circleimageview.CircleImageView; import me.impy.aegis.R; import me.impy.aegis.crypto.KeyInfo; @@ -349,6 +354,12 @@ public class EditProfileActivity extends AegisActivity { info.setAlgorithm(algo); info.setType(type); info.setAccountName(_textName.getText().toString()); + + ByteArrayOutputStream stream = new ByteArrayOutputStream(); + drawableToBitmap(_iconView.getDrawable()).compress(Bitmap.CompressFormat.JPEG, 100, stream); + byte[] bitmapdata = stream.toByteArray(); + + info.setImage(bitmapdata); } catch (KeyInfoException e) { onError("The entered info is incorrect: " + e.getMessage()); return false; @@ -419,4 +430,25 @@ public class EditProfileActivity extends AegisActivity { } return -1; } + + public static Bitmap drawableToBitmap(Drawable drawable) { + if (drawable instanceof BitmapDrawable) { + return ((BitmapDrawable) drawable).getBitmap(); + } + + final int width = !drawable.getBounds().isEmpty() ? drawable + .getBounds().width() : drawable.getIntrinsicWidth(); + + final int height = !drawable.getBounds().isEmpty() ? drawable + .getBounds().height() : drawable.getIntrinsicHeight(); + + final Bitmap bitmap = Bitmap.createBitmap(width <= 0 ? 1 : width, + height <= 0 ? 1 : height, Bitmap.Config.ARGB_8888); + + Canvas canvas = new Canvas(bitmap); + drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight()); + drawable.draw(canvas); + + return bitmap; + } } From 34b6cf944fec84e67de21d6ca82ebc737523d15e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20Sch=C3=A4ttgen?= Date: Wed, 6 Jun 2018 22:31:14 +0200 Subject: [PATCH 04/14] ProfileHolder now shows correct image --- .../impy/aegis/ui/views/KeyProfileHolder.java | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/me/impy/aegis/ui/views/KeyProfileHolder.java b/app/src/main/java/me/impy/aegis/ui/views/KeyProfileHolder.java index da19b193..8bd15d06 100644 --- a/app/src/main/java/me/impy/aegis/ui/views/KeyProfileHolder.java +++ b/app/src/main/java/me/impy/aegis/ui/views/KeyProfileHolder.java @@ -1,6 +1,10 @@ package me.impy.aegis.ui.views; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; import android.graphics.PorterDuff; +import android.graphics.drawable.BitmapDrawable; +import android.graphics.drawable.Drawable; import android.support.v7.widget.RecyclerView; import android.view.View; import android.widget.ImageView; @@ -61,8 +65,17 @@ public class KeyProfileHolder extends RecyclerView.ViewHolder { _profileIssuer.setText(" - " + profile.getEntry().getInfo().getIssuer()); } - TextDrawable drawable = profile.getDrawable(); - _profileDrawable.setImageDrawable(drawable); + if (profile.getEntry().getInfo().getImage() != null) + { + byte[] imageBytes = profile.getEntry().getInfo().getImage(); + Bitmap image = BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.length); + _profileDrawable.setImageBitmap(image); + } + else + { + TextDrawable drawable = profile.getDrawable(); + _profileDrawable.setImageDrawable(drawable); + } refreshCode(); } From 97eb3490d89eb4fbc27f01d19f5e78e92693fda2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20Sch=C3=A4ttgen?= Date: Wed, 6 Jun 2018 23:53:33 +0200 Subject: [PATCH 05/14] MainActivity is now using CircleImageView too --- .../me/impy/aegis/helpers/TextDrawableHelper.java | 8 +++++--- .../java/me/impy/aegis/ui/EditProfileActivity.java | 4 ++-- .../java/me/impy/aegis/ui/views/KeyProfile.java | 6 ++++-- .../me/impy/aegis/ui/views/KeyProfileHolder.java | 2 +- app/src/main/res/layout/card_keyprofile.xml | 14 ++++++++------ 5 files changed, 20 insertions(+), 14 deletions(-) diff --git a/app/src/main/java/me/impy/aegis/helpers/TextDrawableHelper.java b/app/src/main/java/me/impy/aegis/helpers/TextDrawableHelper.java index cdf96610..03b960e6 100644 --- a/app/src/main/java/me/impy/aegis/helpers/TextDrawableHelper.java +++ b/app/src/main/java/me/impy/aegis/helpers/TextDrawableHelper.java @@ -1,5 +1,7 @@ package me.impy.aegis.helpers; +import android.view.View; + import com.amulyakhare.textdrawable.TextDrawable; import com.amulyakhare.textdrawable.util.ColorGenerator; @@ -8,7 +10,7 @@ public class TextDrawableHelper { } - public static TextDrawable generate(String s) { + public static TextDrawable generate(String s, View view) { if (s == null || s.length() <= 1) { return null; } @@ -16,7 +18,7 @@ public class TextDrawableHelper { ColorGenerator generator = ColorGenerator.MATERIAL; int color = generator.getColor(s); return TextDrawable.builder().beginConfig() - .width(100) - .height(100).endConfig().buildRect(s.substring(0, 1).toUpperCase(), color); + .width(view.getWidth()) + .height(view.getHeight()).endConfig().buildRect(s.substring(0, 1).toUpperCase(), color); } } diff --git a/app/src/main/java/me/impy/aegis/ui/EditProfileActivity.java b/app/src/main/java/me/impy/aegis/ui/EditProfileActivity.java index fe04ea70..20476833 100644 --- a/app/src/main/java/me/impy/aegis/ui/EditProfileActivity.java +++ b/app/src/main/java/me/impy/aegis/ui/EditProfileActivity.java @@ -131,7 +131,7 @@ public class EditProfileActivity extends AegisActivity { @Override public void afterTextChanged(Editable s) { - TextDrawable drawable = TextDrawableHelper.generate(s.toString()); + TextDrawable drawable = TextDrawableHelper.generate(s.toString(), _iconView); _iconView.setImageDrawable(drawable); } }); @@ -166,7 +166,7 @@ public class EditProfileActivity extends AegisActivity { private void updateFields() { DatabaseEntry entry = _profile.getEntry(); - _iconView.setImageDrawable(_profile.getDrawable()); + _iconView.setImageDrawable(_profile.getDrawable(_iconView)); _textName.setText(entry.getName()); _textIssuer.setText(entry.getInfo().getIssuer()); diff --git a/app/src/main/java/me/impy/aegis/ui/views/KeyProfile.java b/app/src/main/java/me/impy/aegis/ui/views/KeyProfile.java index addc14d6..a375bad8 100644 --- a/app/src/main/java/me/impy/aegis/ui/views/KeyProfile.java +++ b/app/src/main/java/me/impy/aegis/ui/views/KeyProfile.java @@ -1,5 +1,7 @@ package me.impy.aegis.ui.views; +import android.view.View; + import com.amulyakhare.textdrawable.TextDrawable; import java.io.Serializable; @@ -38,7 +40,7 @@ public class KeyProfile implements Serializable { return _code; } - public TextDrawable getDrawable() { - return TextDrawableHelper.generate(getEntry().getName()); + public TextDrawable getDrawable(View view) { + return TextDrawableHelper.generate(getEntry().getName(), view); } } diff --git a/app/src/main/java/me/impy/aegis/ui/views/KeyProfileHolder.java b/app/src/main/java/me/impy/aegis/ui/views/KeyProfileHolder.java index 8bd15d06..e2a4f884 100644 --- a/app/src/main/java/me/impy/aegis/ui/views/KeyProfileHolder.java +++ b/app/src/main/java/me/impy/aegis/ui/views/KeyProfileHolder.java @@ -73,7 +73,7 @@ public class KeyProfileHolder extends RecyclerView.ViewHolder { } else { - TextDrawable drawable = profile.getDrawable(); + TextDrawable drawable = profile.getDrawable(_profileDrawable); _profileDrawable.setImageDrawable(drawable); } diff --git a/app/src/main/res/layout/card_keyprofile.xml b/app/src/main/res/layout/card_keyprofile.xml index 22b8c510..eb4b0681 100644 --- a/app/src/main/res/layout/card_keyprofile.xml +++ b/app/src/main/res/layout/card_keyprofile.xml @@ -23,12 +23,14 @@ android:layout_height="match_parent" android:paddingLeft="16dp"> - + Date: Thu, 7 Jun 2018 00:30:49 +0200 Subject: [PATCH 06/14] Added way to remove custom images --- .../java/me/impy/aegis/crypto/KeyInfo.java | 9 +++- .../me/impy/aegis/ui/EditProfileActivity.java | 45 ++++++++++++++++--- .../impy/aegis/ui/views/KeyProfileHolder.java | 2 +- app/src/main/res/menu/menu_edit.xml | 5 +++ app/src/main/res/values/strings.xml | 1 + 5 files changed, 52 insertions(+), 10 deletions(-) diff --git a/app/src/main/java/me/impy/aegis/crypto/KeyInfo.java b/app/src/main/java/me/impy/aegis/crypto/KeyInfo.java index 9103ec63..2307cb65 100644 --- a/app/src/main/java/me/impy/aegis/crypto/KeyInfo.java +++ b/app/src/main/java/me/impy/aegis/crypto/KeyInfo.java @@ -184,12 +184,17 @@ public class KeyInfo implements Serializable { public void setImage(byte[] image) { - _image = Base64.encodeToString(image, Base64.DEFAULT); + if(image != null && !image.equals("")) + { + _image = Base64.encodeToString(image, Base64.DEFAULT); + } else { + _image = null; + } } public byte[] getImage() { - return Base64.decode(_image, Base64.DEFAULT); + return _image != null ? Base64.decode(_image, Base64.DEFAULT) : null; } public void setSecret(byte[] secret) { diff --git a/app/src/main/java/me/impy/aegis/ui/EditProfileActivity.java b/app/src/main/java/me/impy/aegis/ui/EditProfileActivity.java index 20476833..5e33780b 100644 --- a/app/src/main/java/me/impy/aegis/ui/EditProfileActivity.java +++ b/app/src/main/java/me/impy/aegis/ui/EditProfileActivity.java @@ -49,6 +49,8 @@ import me.impy.aegis.ui.views.KeyProfile; public class EditProfileActivity extends AegisActivity { private boolean _isNew = false; private boolean _edited = false; + private boolean _hasCustomImage = false; + private KeyProfile _profile; private CircleImageView _iconView; @@ -131,8 +133,11 @@ public class EditProfileActivity extends AegisActivity { @Override public void afterTextChanged(Editable s) { - TextDrawable drawable = TextDrawableHelper.generate(s.toString(), _iconView); - _iconView.setImageDrawable(drawable); + if(!_hasCustomImage) + { + TextDrawable drawable = TextDrawableHelper.generate(s.toString(), _iconView); + _iconView.setImageDrawable(drawable); + } } }); @@ -166,7 +171,18 @@ public class EditProfileActivity extends AegisActivity { private void updateFields() { DatabaseEntry entry = _profile.getEntry(); - _iconView.setImageDrawable(_profile.getDrawable(_iconView)); + + if (_profile.getEntry().getInfo().getImage() != null) + { + byte[] imageBytes = _profile.getEntry().getInfo().getImage(); + Bitmap image = BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.length); + _iconView.setImageBitmap(image); + _hasCustomImage = true; + } + else + { + _iconView.setImageDrawable(_profile.getDrawable(_iconView)); + } _textName.setText(entry.getName()); _textIssuer.setText(entry.getInfo().getIssuer()); @@ -270,6 +286,9 @@ public class EditProfileActivity extends AegisActivity { finish(true); }); break; + case R.id.action_default_image: + _iconView.setImageDrawable(_profile.getDrawable(_iconView)); + _hasCustomImage = false; default: return super.onOptionsItemSelected(item); } @@ -283,6 +302,10 @@ public class EditProfileActivity extends AegisActivity { if (_isNew) { menu.findItem(R.id.action_delete).setVisible(false); } + if (!_hasCustomImage) { + menu.findItem(R.id.action_default_image).setVisible(false); + } + return true; } @@ -309,6 +332,7 @@ public class EditProfileActivity extends AegisActivity { public void onClick(View v) { _iconView.setImageBitmap(_kropView.getCroppedBitmap()); _kropView.setVisibility(View.GONE); + _hasCustomImage = true; } }); } @@ -355,11 +379,18 @@ public class EditProfileActivity extends AegisActivity { info.setType(type); info.setAccountName(_textName.getText().toString()); - ByteArrayOutputStream stream = new ByteArrayOutputStream(); - drawableToBitmap(_iconView.getDrawable()).compress(Bitmap.CompressFormat.JPEG, 100, stream); - byte[] bitmapdata = stream.toByteArray(); + if(_hasCustomImage) + { + ByteArrayOutputStream stream = new ByteArrayOutputStream(); + drawableToBitmap(_iconView.getDrawable()).compress(Bitmap.CompressFormat.JPEG, 100, stream); + byte[] bitmapdata = stream.toByteArray(); - info.setImage(bitmapdata); + info.setImage(bitmapdata); + } + else + { + info.setImage(null); + } } catch (KeyInfoException e) { onError("The entered info is incorrect: " + e.getMessage()); return false; diff --git a/app/src/main/java/me/impy/aegis/ui/views/KeyProfileHolder.java b/app/src/main/java/me/impy/aegis/ui/views/KeyProfileHolder.java index e2a4f884..c876a6e5 100644 --- a/app/src/main/java/me/impy/aegis/ui/views/KeyProfileHolder.java +++ b/app/src/main/java/me/impy/aegis/ui/views/KeyProfileHolder.java @@ -65,7 +65,7 @@ public class KeyProfileHolder extends RecyclerView.ViewHolder { _profileIssuer.setText(" - " + profile.getEntry().getInfo().getIssuer()); } - if (profile.getEntry().getInfo().getImage() != null) + if (profile.getEntry().getInfo().getImage() != null && !profile.getEntry().getInfo().getImage().equals("")) { byte[] imageBytes = profile.getEntry().getInfo().getImage(); Bitmap image = BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.length); diff --git a/app/src/main/res/menu/menu_edit.xml b/app/src/main/res/menu/menu_edit.xml index de645b02..ac68ddd2 100644 --- a/app/src/main/res/menu/menu_edit.xml +++ b/app/src/main/res/menu/menu_edit.xml @@ -11,4 +11,9 @@ android:id="@+id/action_delete" android:title="@string/action_delete" app:showAsAction="never"/> + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index f94f622c..352bb667 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -3,6 +3,7 @@ Settings Import Delete + Set default image Discard Save IntroActivity From 0f0c6d998c583b96e4c543dd5497ca029b916968 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20Sch=C3=A4ttgen?= Date: Thu, 7 Jun 2018 00:36:27 +0200 Subject: [PATCH 07/14] Minor bugfix --- app/src/main/java/me/impy/aegis/ui/EditProfileActivity.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/me/impy/aegis/ui/EditProfileActivity.java b/app/src/main/java/me/impy/aegis/ui/EditProfileActivity.java index 5e33780b..c3932372 100644 --- a/app/src/main/java/me/impy/aegis/ui/EditProfileActivity.java +++ b/app/src/main/java/me/impy/aegis/ui/EditProfileActivity.java @@ -181,7 +181,8 @@ public class EditProfileActivity extends AegisActivity { } else { - _iconView.setImageDrawable(_profile.getDrawable(_iconView)); + TextDrawable drawable = TextDrawableHelper.generate(entry.getInfo().getIssuer(), _iconView); + _iconView.setImageDrawable(drawable); } _textName.setText(entry.getName()); From 9c0ce4210cee3fd33b532ce568a2c74a48a94113 Mon Sep 17 00:00:00 2001 From: Alexander Bakker Date: Thu, 7 Jun 2018 12:34:20 +0200 Subject: [PATCH 08/14] Ask for storage permissions before showing the dialog on import --- .../java/me/impy/aegis/ui/PreferencesFragment.java | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/me/impy/aegis/ui/PreferencesFragment.java b/app/src/main/java/me/impy/aegis/ui/PreferencesFragment.java index f1134d80..fed1c3b4 100644 --- a/app/src/main/java/me/impy/aegis/ui/PreferencesFragment.java +++ b/app/src/main/java/me/impy/aegis/ui/PreferencesFragment.java @@ -221,6 +221,10 @@ public class PreferencesFragment extends PreferenceFragmentCompat implements Pas } private void onImport() { + if (!PermissionHelper.request(getActivity(), CODE_PERM_IMPORT, Manifest.permission.READ_EXTERNAL_STORAGE)) { + return; + } + Map> importers = DatabaseImporter.getImporters(); String[] names = importers.keySet().toArray(new String[importers.size()]); @@ -232,11 +236,9 @@ public class PreferencesFragment extends PreferenceFragmentCompat implements Pas int i = ((AlertDialog) dialog).getListView().getCheckedItemPosition(); _importerType = importers.get(names[i]); - if (PermissionHelper.request(getActivity(), CODE_PERM_IMPORT, Manifest.permission.READ_EXTERNAL_STORAGE)) { - Intent intent = new Intent(Intent.ACTION_GET_CONTENT); - intent.setType("*/*"); - startActivityForResult(intent, CODE_IMPORT); - } + Intent intent = new Intent(Intent.ACTION_GET_CONTENT); + intent.setType("*/*"); + startActivityForResult(intent, CODE_IMPORT); } }) .show(); From 8419e1f35d3f51a83b86ba348888915a4051928b Mon Sep 17 00:00:00 2001 From: Alexander Bakker Date: Thu, 7 Jun 2018 12:42:25 +0200 Subject: [PATCH 09/14] Correctly enable/disable the fingerprint option in the intro --- .../impy/aegis/ui/slides/CustomAuthenticationSlide.java | 9 +++------ .../main/res/layout/fragment_authentication_slide.xml | 2 ++ 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/me/impy/aegis/ui/slides/CustomAuthenticationSlide.java b/app/src/main/java/me/impy/aegis/ui/slides/CustomAuthenticationSlide.java index b46f7421..ef5ea468 100644 --- a/app/src/main/java/me/impy/aegis/ui/slides/CustomAuthenticationSlide.java +++ b/app/src/main/java/me/impy/aegis/ui/slides/CustomAuthenticationSlide.java @@ -8,10 +8,8 @@ import android.support.v4.app.Fragment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.widget.ArrayAdapter; import android.widget.RadioButton; import android.widget.RadioGroup; -import android.widget.Spinner; import android.widget.TextView; import com.github.paolorotolo.appintro.ISlidePolicy; @@ -25,7 +23,6 @@ public class CustomAuthenticationSlide extends Fragment implements ISlidePolicy, public static final int CRYPT_TYPE_PASS = 2; public static final int CRYPT_TYPE_FINGER = 3; - private Spinner _authenticationSpinner; private RadioGroup _buttonGroup; private int _bgColor; @@ -36,13 +33,13 @@ public class CustomAuthenticationSlide extends Fragment implements ISlidePolicy, _buttonGroup.setOnCheckedChangeListener(this); onCheckedChanged(_buttonGroup, _buttonGroup.getCheckedRadioButtonId()); - // only show the fingerprint option if the api version is new enough, permission is granted and a scanner is found + // only enable the fingerprint option if the api version is new enough, permission is granted and a scanner is found FingerprintManager manager = FingerprintHelper.getManager(getContext()); if (manager != null) { RadioButton button = view.findViewById(R.id.rb_fingerprint); TextView text = view.findViewById(R.id.text_rb_fingerprint); - button.setEnabled(false); - text.setEnabled(false); + button.setEnabled(true); + text.setEnabled(true); } view.findViewById(R.id.main).setBackgroundColor(_bgColor); diff --git a/app/src/main/res/layout/fragment_authentication_slide.xml b/app/src/main/res/layout/fragment_authentication_slide.xml index 030c0f2e..c480af0a 100644 --- a/app/src/main/res/layout/fragment_authentication_slide.xml +++ b/app/src/main/res/layout/fragment_authentication_slide.xml @@ -72,6 +72,7 @@ Date: Thu, 7 Jun 2018 14:33:33 +0200 Subject: [PATCH 10/14] Fix serialization of entry icons and some other stuff --- .../main/java/me/impy/aegis/db/DatabaseEntry.java | 15 ++++++++++----- .../me/impy/aegis/helpers/TextDrawableHelper.java | 7 ++++--- .../java/me/impy/aegis/ui/EditEntryActivity.java | 6 +++--- .../main/java/me/impy/aegis/ui/MainActivity.java | 4 +--- .../java/me/impy/aegis/ui/views/EntryAdapter.java | 5 +++++ .../java/me/impy/aegis/ui/views/EntryHolder.java | 2 +- .../me/impy/aegis/ui/views/EntryListView.java | 7 +++++++ 7 files changed, 31 insertions(+), 15 deletions(-) diff --git a/app/src/main/java/me/impy/aegis/db/DatabaseEntry.java b/app/src/main/java/me/impy/aegis/db/DatabaseEntry.java index 1027ac7c..9a5fefe6 100644 --- a/app/src/main/java/me/impy/aegis/db/DatabaseEntry.java +++ b/app/src/main/java/me/impy/aegis/db/DatabaseEntry.java @@ -37,8 +37,8 @@ public class DatabaseEntry implements Serializable { obj.put("uuid", _uuid.toString()); obj.put("name", _name); obj.put("issuer", _issuer); - obj.put("info", _info.toJson()); obj.put("icon", _icon == null ? JSONObject.NULL : Base64.encode(_icon)); + obj.put("info", _info.toJson()); } catch (JSONException e) { throw new RuntimeException(e); } @@ -55,12 +55,13 @@ public class DatabaseEntry implements Serializable { } _name = obj.getString("name"); _issuer = obj.getString("issuer"); - _info = OtpInfo.parseJson(obj.getString("type"), obj.getJSONObject("info")); - String icon = obj.optString("icon", null); - if (icon != null) { - _icon = Base64.decode(icon); + Object icon = obj.get("icon"); + if (icon != JSONObject.NULL) { + _icon = Base64.decode((String) icon); } + + _info = OtpInfo.parseJson(obj.getString("type"), obj.getJSONObject("info")); } public UUID getUUID() { @@ -98,4 +99,8 @@ public class DatabaseEntry implements Serializable { public void setIcon(byte[] icon) { _icon = icon; } + + public boolean hasIcon() { + return _icon != null; + } } diff --git a/app/src/main/java/me/impy/aegis/helpers/TextDrawableHelper.java b/app/src/main/java/me/impy/aegis/helpers/TextDrawableHelper.java index 1adea7a7..181e5fb5 100644 --- a/app/src/main/java/me/impy/aegis/helpers/TextDrawableHelper.java +++ b/app/src/main/java/me/impy/aegis/helpers/TextDrawableHelper.java @@ -18,10 +18,11 @@ public class TextDrawableHelper { text = fallback; } - ColorGenerator generator = ColorGenerator.MATERIAL; - int color = generator.getColor(text); + int color = ColorGenerator.MATERIAL.getColor(text); return TextDrawable.builder().beginConfig() .width(view.getWidth()) - .height(view.getHeight()).endConfig().buildRect(text.substring(0, 1).toUpperCase(), color); + .height(view.getHeight()) + .endConfig() + .buildRect(text.substring(0, 1).toUpperCase(), color); } } diff --git a/app/src/main/java/me/impy/aegis/ui/EditEntryActivity.java b/app/src/main/java/me/impy/aegis/ui/EditEntryActivity.java index cba5c419..cbaafdad 100644 --- a/app/src/main/java/me/impy/aegis/ui/EditEntryActivity.java +++ b/app/src/main/java/me/impy/aegis/ui/EditEntryActivity.java @@ -115,10 +115,10 @@ public class EditEntryActivity extends AegisActivity { // fill the fields with values if possible if (_entry != null) { - if (_entry.getIcon() != null) { + if (_entry.hasIcon()) { byte[] imageBytes = _entry.getIcon(); - Bitmap image = BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.length); - _iconView.setImageBitmap(image); + Bitmap bitmap = BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.length); + _iconView.setImageBitmap(bitmap); _hasCustomImage = true; } else { TextDrawable drawable = TextDrawableHelper.generate(_entry.getIssuer(), _entry.getName(), _iconView); diff --git a/app/src/main/java/me/impy/aegis/ui/MainActivity.java b/app/src/main/java/me/impy/aegis/ui/MainActivity.java index a0744bba..7bd36484 100644 --- a/app/src/main/java/me/impy/aegis/ui/MainActivity.java +++ b/app/src/main/java/me/impy/aegis/ui/MainActivity.java @@ -411,9 +411,7 @@ public class MainActivity extends AegisActivity implements EntryListView.Listene private void loadEntries() { updateLockIcon(); - for (DatabaseEntry entry : _db.getEntries()) { - _entryListView.addEntry(entry); - } + _entryListView.addEntries(_db.getEntries()); } private void updateLockIcon() { diff --git a/app/src/main/java/me/impy/aegis/ui/views/EntryAdapter.java b/app/src/main/java/me/impy/aegis/ui/views/EntryAdapter.java index b3675ca5..3cd5dc6e 100644 --- a/app/src/main/java/me/impy/aegis/ui/views/EntryAdapter.java +++ b/app/src/main/java/me/impy/aegis/ui/views/EntryAdapter.java @@ -43,6 +43,11 @@ public class EntryAdapter extends RecyclerView.Adapter implements I } } + public void addEntries(List entries) { + _entries.addAll(entries); + notifyDataSetChanged(); + } + public void removeEntry(DatabaseEntry entry) { entry = getEntryByUUID(entry.getUUID()); int position = _entries.indexOf(entry); diff --git a/app/src/main/java/me/impy/aegis/ui/views/EntryHolder.java b/app/src/main/java/me/impy/aegis/ui/views/EntryHolder.java index 5025d04c..3b088765 100644 --- a/app/src/main/java/me/impy/aegis/ui/views/EntryHolder.java +++ b/app/src/main/java/me/impy/aegis/ui/views/EntryHolder.java @@ -76,7 +76,7 @@ public class EntryHolder extends RecyclerView.ViewHolder { _profileIssuer.setText(" - " + entry.getIssuer()); } - if (entry.getIcon() != null) { + if (_entry.hasIcon()) { byte[] imageBytes = entry.getIcon(); Bitmap image = BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.length); _profileDrawable.setImageBitmap(image); diff --git a/app/src/main/java/me/impy/aegis/ui/views/EntryListView.java b/app/src/main/java/me/impy/aegis/ui/views/EntryListView.java index 3a652b2e..a0597075 100644 --- a/app/src/main/java/me/impy/aegis/ui/views/EntryListView.java +++ b/app/src/main/java/me/impy/aegis/ui/views/EntryListView.java @@ -10,6 +10,8 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import java.util.List; + import me.impy.aegis.R; import me.impy.aegis.db.DatabaseEntry; import me.impy.aegis.helpers.SimpleItemTouchHelperCallback; @@ -135,6 +137,11 @@ public class EntryListView extends Fragment implements EntryAdapter.Listener { checkPeriodUniformity(); } + public void addEntries(List entries) { + _adapter.addEntries(entries); + checkPeriodUniformity(); + } + public void removeEntry(DatabaseEntry entry) { _adapter.removeEntry(entry); checkPeriodUniformity(); From 4e74c5beb9084d4be90ca50154115370d1c067e3 Mon Sep 17 00:00:00 2001 From: Alexander Bakker Date: Thu, 7 Jun 2018 15:23:23 +0200 Subject: [PATCH 11/14] Fix a bug that caused TextDrawable to not be displayed --- .../main/java/me/impy/aegis/helpers/TextDrawableHelper.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/me/impy/aegis/helpers/TextDrawableHelper.java b/app/src/main/java/me/impy/aegis/helpers/TextDrawableHelper.java index 181e5fb5..08bce32c 100644 --- a/app/src/main/java/me/impy/aegis/helpers/TextDrawableHelper.java +++ b/app/src/main/java/me/impy/aegis/helpers/TextDrawableHelper.java @@ -20,8 +20,8 @@ public class TextDrawableHelper { int color = ColorGenerator.MATERIAL.getColor(text); return TextDrawable.builder().beginConfig() - .width(view.getWidth()) - .height(view.getHeight()) + .width(view.getLayoutParams().width) + .height(view.getLayoutParams().height) .endConfig() .buildRect(text.substring(0, 1).toUpperCase(), color); } From cae77b085c4a67932cec515722032204a9d0b079 Mon Sep 17 00:00:00 2001 From: Alexander Bakker Date: Thu, 7 Jun 2018 17:34:55 +0200 Subject: [PATCH 12/14] Update testdata --- testdata/aegis_export.json | 25 ++++++++----------------- testdata/aegis_export_plain.json | 12 +++++++++++- 2 files changed, 19 insertions(+), 18 deletions(-) diff --git a/testdata/aegis_export.json b/testdata/aegis_export.json index 821c98e1..f5ff8548 100644 --- a/testdata/aegis_export.json +++ b/testdata/aegis_export.json @@ -4,31 +4,22 @@ "slots": [ { "type": 1, - "uuid": "faa80a1d-1f64-4983-90c8-67d8b0a09509", - "key": "4ecda6896ea0713e270021c6e7878765a2569fa00f1e12ebd65c866ee1738bde", + "uuid": "a61de6ba-32df-4255-957e-ae8906b95005", + "key": "b40c6151822db86a9da0298259c049a508f716f0076511ba2dc65f794071613a", "key_params": { - "nonce": "d7bfdff7de45aa7c6166d595", - "tag": "07dedd167226d49a1fca347ef0d0f885" + "nonce": "f34a5ac011e908c817365946", + "tag": "8a8ad4d9b15258f2f170650032beb0b1" }, "n": 32768, "r": 8, "p": 1, - "salt": "20b7f2a7029f3d35b5fa3cf0435414f8a8b84099b93cf75ee4871b266b2b5e27" - }, - { - "type": 2, - "uuid": "b56dcbd4-0533-4288-8119-6dc2ef82d23b", - "key": "f32f816e1d43099832c7a23110f1349304ea1489ff65ce6e29ea79c0d42d38f4", - "key_params": { - "nonce": "65b342b6780c02d1d22b1505", - "tag": "940a05c01838a6f1163f984c38f58c1e" - } + "salt": "3fa5200a3817933ed6d962370e5332b9905e2e13023935d1918e4b9e890fb588" } ], "params": { - "nonce": "5598c18c429ce521f46c68ab", - "tag": "60d612995b5d44f8be41399dad3d2734" + "nonce": "aa3e68aa6f18e78dc13edaf3", + "tag": "8afcb2f93f6a36e6866c898adb201821" } }, - "db": "ILPzlJEAurVJJUrCgUDDLrkz4Yy45HhUPumMwr3Us0rC8NHMQgVmJcEKxxq7zPfBdOBWS\/hv0sj1PmqlHi4c0rAN0rXQqKcT7beK7QaszVRq8kW0gfV7PwN9uF+am9IKBVgs\/mtCec1S1eFMHDcU+mawfwNAea7n0dM+eLk89gBp2kiMBlCYW3f+ucjLgicUX2Rl8hiThZSrhK\/UCxmOO4hPLO0\/viVgpFy9y3V+LOefpJHdYyd6wymKSXx6cDX9iiVqczc2jM9RRazZ9ve6Ks2rndZvmIsmOugAXXS3f2\/Q9iLcXBO4y39O3v9h7nfugl5\/NbwL\/JQrPT8bcEAI9x1uoVqpPlsBzpjyq79LkXSa+wMuzaX4xq\/ox1zuVMZgzudE4BvlSBgAzXuM4KL4Ra7CIUbf0RJV5BtwH+2j7zt2Xh8lkP7BY1mbqnN+Vg8z8MTnwo6G\/WOo8zaz6gbA4yCvPO0xegeJZmbggQveC3YkZT9RQ45zD8StS7dkB2dcNMH9qUnA1RyTlrGyJX5G5MTSLsW8QunqikFmElWkNsgV9Ex+M+3z1TIu9f8hT9yF\/iQAIC0tNERgT5RcDtPVLiMSUl0uWZhZ56\/m+k18nN\/8oEf0FZGYBzKR8cNcvK+cM6Inu6VpEqjfpx951SXF+sSo5j80xqDZFbWycgQzBrS1f+mfsV\/S1V3RR\/aG5HVntB8NtwH0PlGIi155QE8Yu+jnUCl7yz5L9QhJN4TVqmSIxXCT3EBN3EhB6MYw4LpPPJc3yTIKK6ltDhtp3yrBWSfzgZiwZL1jLLpJ9V\/fCtdzuC33AQbxgjPIVBJ8bW2G1\/Qp8SQKGRdVX6MR8L6XK03tvYasRgnhRo4\/8RtW\/tzhUUaRPGO66sF9ztLoeMwR8blgUcLcDRTFbZKOgmyPqo+a23jCi32H8+WJsB04XyltGSkAPN1jZJsdQ+2FCG2pW34KkPxUvl5+pULXaLOs1twsR\/K7iCbs3lOLvA4bDoZ+5EyvFcJDhmguP2s3Su64mXdfcQqh68UegDdyTutOt9TjLQhGfby8URyLVilFs8gUoCLr5E7tHlSg9GZthTWew0+jOmr06HWytD5Eu9N\/aUPcxadeM6js9XSH5OC4VUv+qZeUtfsmfGyYd8kIU5e4wz4lQZj4kbbZGsYzFlQI2OT4yTEsfwcee10FafOiCM86yfPnPKPQEnLxUV6PNx\/MmIq2UgGHT8xn9IttwwUa4KJZ9dgeB6iVk0MexzLaOHEa\/wK5dkQxvKxKe+sbdHIFbsLm3eOU5o3ourPIRYd0HTVcAjuOcnHdS6CiGgga4PqH0wJ7ZQ6R1cbCsMagW2FpivyBbJ2Y8hwrQyYCKmcR9cGEom1UTHSHPbUXw6Mmz3j85f5eQGzfDH6HW1YuGcKtgvjUoiW96PFInZxymg5opWnnvpH9+p9XLhObxOmDDhKGnz\/VfflvjqepvA7d6tNRg34uQF2bxykvfb8\/a9TGNVckLfcV02W6R4p+pLK2nVyewds9LBhNAl+PpW0dVFwKo4spn4Nwop1A657NL31ojNCnB3JowTD5g4sqSI4oc43EZgLspi\/\/Pw2meHlLhrhwGICJgyeoTISnw16agdrVnqFsuAYuHM5NlYy8+2UlwOGatGBumbgmbHq7z4VmRbmaGWXPirKO6P4sHaMq9Antqw2T3xjgFEVxFCWnY\/BsAQUE+pNzNCCAKoVlBk3S1CYgpB2ZyQYXOv98Y7MwSrsObem7p1Rdd7elvjE8CkGd3UfUFkbXoV8e+hwUUDk325ND68jzsfP4m1iQIH4B92Gces04oNT3T\/RcS3HJxs6\/\/2\/wUPOpRELys9YNqbOGB3FSse66nJheYqGTEaVacu9zEy5Ye9b8dUE5axbXvbtS+vlKCMrjlW7hBeO5tOGtvZf1BM0hbK\/unpW9MCk\/7YVoQckHuA0mq9z0FgTfdlMZ376OYI8ZWQPyiYxcw0AfiDKMGt0qe+Mcjgwcpj6ilM\/YvJSaD6zq1siuVwSDU7Ep1JBC\/rBw+OsIfgELsKU\/zpbhl6tEau3qiTetl\/XvU\/wz5derqzAZDimPVN0BSWl7foP4V17VFjENz\/BfEf28sQYuh59Y2OvMCcSu5MHyxY6frVUPshPGoo7zv809I47uXedbTVBd5Z9Zg\/GGhpc7TDasWUYPLF6ErHIGC+OQN3Thx2P7sv3SLFbh4+yIutB4EPOo8anw7wIJv+1veWGgYGSCb9E51ZXv6IxW5i2JbJil98vnTpHH+b0miCbUFNlZ8eu+MopZosaZ8CFJkLUSDhAT4Adc1TIuzj\/8FhnH\/z5n98ClyWjbnYDH7yFluUDsA9\/\/jZXbHaZKzN5dDr2AQzKArnGz\/JGASBfbNBwfQ5Y2X00tS+9VoBBFqV8gi0L4QqYiYRkxTiL4fRrbKdMohdCmZ\/R\/DRJJs1nHIT\/J2zpAaNTTuEwwCuBj2lPfPiMOpkPY2WeZELY51x7tvhTZD6tXA+K1VBldeWMcUddxg\/KdWlV5vryvR3fh8nhkTjn3S5Wnto0v9jTItxpQfAzytOurNdGa4sMJIWpcLZ\/e15KQXTnDTOb+6gwaUCDYM9CfbK+RJsdBowUNGTmLRcWh\/I45SMPMrrjAvCekM1yTfDhwmIT\/rZMKCkZOlM2hKtFnzttrVTRE8Nh+AgXc3nVeflnAoXK+5b0aKDRgppFPdmZcxvuy0TZgMDS+zptdPOysrQ6L1jTmMoTfjm4BZOYIEvrEV70aqlHfaET8wVGEFeeOxyewYt\/n3l55VhUo155bc3zYUJdJOTLsLD\/0NxaQEgLUyKUsXNFwETQPJU60WtxpvvM05x\/S09qfPCHtgcwLI+cP77D3L46QT8kZlkGesXzb96wHPf2717+yZxqdI\/tWfgq\/MMF\/lqGTRPzsvLY\/3dglqN\/\/hAJtZ\/RS1JFI7Yw0QUb2Dj3cwWkMnXjN7w3YC\/qi7G+tr+knsSE7zgBa5ooRFIQMDl8xj4uOR2VT\/aXvrBmblqmjJv1H5CxCG5XyxBkTPr9Ju\/8QMABS1in24HUrB9v2VP2jjv1l16aGJZpwSwlJtuY4eT06X3od6k5ZBY\/sPoHj\/9tkdqw9UgNO8IWXRIH9lXuplAVtE9R5BRLMcD9xFrWweXK+YW4Vlxqncbtg3IQvLhvdaCUqG6qfR8ml9bCqVqU4PXLXaVBOYU0BUjZV4UqkRPn3JA8RzlxAebthnPEnhb8xevhUAHcZSkNrZoICPL06hXn7KUBCnQMuOLYoPe2tbd+Mz8j8F5KMmAa8m2IRLeFeIU51U25Uq6f6ON1N+GuXjjvXGG8UD+OC8o1HjzH+cWDFTppxu7twZoLYoY3qPYClI1FCHIdWat1juaFjdfXxaCW8z26Vnv\/+lPwfdb6XXw3VIlhi5PCltTOPyJ\/LaaWAeQ9lkb7qoQB3dOgnRwF+IP7VztnsT4cyJlbld5qWfY3XUvKQEO0jg5f93MM6MCnso9SdC5mBkWY6UuULZYxSTgYDX\/uCm0iuV4l8Z+amKspLYWvbCq8IFIjTZ+95bDNroQJkNgYpZBj0cl3GyMCW6cmcSf2SmhnchKqdHfQrZ4kQoafr5ACkPrx0tLbjgCh1c6fGZ1aRUd+nWFNz2P7xVS8G8RvTV3xdulk+3KfdqZzpiY6b0LiKT0yjyWC++X64hHeh3S9M72k6rQmzwc+4P97jVPYUVt0K2EdjM9+0eRxeQoB4EFiit3+vB7Chpj91oqs\/pz2DMQOSEpuIzIgBLDOnqYYQFEW0s\/9OBnx6j0IwH9dmU3DOGjBRrU8T35rft+15W7M5RdC3rr2Z66MqNnrHDzhAnxJuZDOXA7BYMpkq0nlNxpc2pRnZEPUkjzDfpwVmv7foMLSAGeYoQdlrhrbSa0A7skF6FGMUDT7baYoJucTE+EoPUELFE86ZxxoLCSg2PTtCI25AeABjYm7TaapbicxTQb9GtvCy7mBzOo1C5rtDq\/5CiwxZDcCuVfGvaJT7nOJvXvD42m0F7rQNPh+DJhxfCs+rfW6wmxqW8kz57ssiSfQ5lJwMbCBMRjYu5fDtl8uLN0HrnEz6XGS83GnGqK9Q+flGyQhpZ5aBuSrOxjuO43BDpXKrB+dbgUJp3jZIK41fFTZr8YcGiBeGq9f+zE\/oeAfcvH0twRQzO5vsZUqp\/OK4dClEpsPsQmR8bUqbdrj2ETGoH2Ih2i8ijBhGyc+7uMOox6XgySFvy8sVaMfryINUgt6OCSH4Xu7RQwkDbYDzNbw1KS3fXJ5TWyOaIZJTUlVJ\/UWQLjGvxNrVlmZPmJMJ\/lUaansai1BlLViY0gmfqavLDAU2qpudgW7C1Ncm\/3gP6\/DZiWDq+P0RCZ2xcAm9GjC8PvZGLtQSCrxEzalQWPrMVe+zwlPoU3lkv4lFc2SGIKlyBKZ+NjMwoDd2a7rRvsQlynPpJqQXlFy+sewQqngjbXZ0LYkKwCjEnqUb4ip8YkkIS1GAFZe5vp3aqBXEF5ID2YdYnZEJWLCNSoTGr6d9XMNLXB62sSoxgeacZtLrNuZ2mi7CrRVj7ee4mVPnN0LedBweBy6sxYdhAIcWAwYTA2htM93ppT36m8qifXcledgiqzDmlYRRIJXITMtt1xlR683RfySVnBmp\/CoaOHpjrllbU9y69yzzIwt7umhf0nMxx8tO1lngdcLWlUkLK5rkDeDby2mvFOHs9awTPFdgVjdwGKtBUvlt64\/JOrbKeNu3Lv2a84RccV\/IbKkqjhTKulbHuqM7Kgq3Ju7deH7Xe91kZFf5JUo050s9z3hMqgbjeDRGjGy6kF7eKv900ejtGuibx7kqFIOBrinc6QrrsG1bPKulSAiJe34cmM19sXfNmo0WMBMaVvJ6xgu9FRwJXoZ1jSRCfWLF79dC2Oin0Zn9TTMeGKz9+sogAiEUIw==" + "db": "Ejfokh6cZBFh8k0n+fq3ioUJzvvjtAqaJVuWBWgvKNlk\/ffNW8B9B8EwCVP\/wX87vCyiE4onbdw7RHyKUiMtmqMjTTAXr2fnwx\/oAgg4F1AthXt0rZDW6xX3PNBwQNHFZ1rFdWT8J90xd719qLY0+UWdyp2XaAXTdvY9yXUilH\/tG5PbNfP4x6vHeqzFrpfw98cS1k+dwRLU5iHF8O\/HHpv+ldwsTgT3ij4ARvmcvW9rFR9qtVspUDnqvO5U9\/lGv7exNjF7KtD72yi\/II\/i7VhdGN26LMzzqEFqhlkhpG2jBmRN+1bqL1lTMA4qjZNGaVlMpC7Ufy\/n8hTBhQrO1uEVb1lB4kCuFnsGWWd4cI9As3iSBmGq+bXsQe67RgDLSwdtdKmOrFTsYyBN8ywSVEFdd4CZcVfWREeY9LoRYJj2UgccrgHtp7zPHg9hkJN7uMB6Es75S1NCgdybkLbuTmyT78c+mXL9XNlz9bkDY5vcbqebmC6zJNqDbFH7u84+2BkZv\/3fOX9YlM\/S6iPRodhwMxwLKc6WY24XRwrR9bXUxAiY5pOInSR6Z9r4MLatubBP2m1WkED9cLlMH0oDYi7JnjtoS7SFnZJOKD2YBPUTT1boyp\/hDraethiEgJc9RGzNcUVu8cfmQdJBXwZ18DxHaxApAmjUm8fPLFpudfOOfyykrFBCJZ+ep6aeIfmAyG71DG+PSLkJeSd82vLiVHUB3GrNg+VuJxsDP4bfybGMXgflGqJnx4ht9gr8\/R7nvS4AHQas5eKO7HfpcuqGT\/AgpT570GAmyCFsQbbYlS0qHE\/IYZdB6vM5f2ItkvDsXzxVupU8XMlfmFOx+AMeADZGyIaeBxJac3tsda4J8JgA0gba39xtSBeonjgPCjElOlpfY\/KBU5OKMteoNkKZPvBT73MCZwmD7PwCtBLDWCfvvnRFnciuA79MwbSIgvDhLGk652shMvac5g\/L69BkXiBQ5IT4+0AiKsMvJ77CxAkR4CkDaU3tRZYLKDAqllsuY6Ds+yvNE1p+7RXgQC37swa1ogYq0dE0GjJeZJMxtaDyMamdvfbuQ9Pc9EH37j1vbyfJ4Ty9U5nSi8zZAhlLbu71VecagZG1Ti0wrxnaMwk1AjLC\/Viw0qBY+IKQ2zRO0K0KsflMqLrylwbzzwkr0VJBzaVDwQi2UtlPdGpNJVrcPyDyeNrFthg+cazfaCgWFezt8cRscckU7cZ2i5ZlqUd44Vb+253Fi38UDz0bDyUm4pytIIH2Nm8bmTtnGdyvDeKtErLGsnxKVRgYGm3rQq4WLyJrYsFNdiZriEY\/E206fFW30jG30hWrK+nSgsl96oa9k2W7bX+QmCnrCQ8oULGEE7GCRbhNzXhoTX1MMe1R7k2q\/8S4u5VrE2Uhr3\/UAh5qR\/2BWuSRTWoONP0xO5q9YazRgYcQmrx\/p0LzWuf2TPjyEGpfQrJhBVQpuywlN5i3na+E6q\/gfJbOWC8K16GP\/2orZ2s\/cMVY8XFWtOaPog8x3Sb5eYIEMp8KBmyFYkzjfF7nMlfztcP49sYgyvNI+fUk1x4iL6ZNMLtvjtNxBIPPqt334o0RHF\/8XMd0vu7OKYG3fS84zdI9jsDCSphmp\/XPFXXd2UDNA9NLsFWhiQy8JpMY3MDEjh1MDCB9Q5Gsy8xGIPeef5NSnPtTxgTjYjwC1wYUFOahECnrgrhCiqKL6ktp2Z8OkmFWyYmUBgpkOBb3EgyUxgn2MmJsEVKYNkFwFpenMVb\/R+VZu0CCgTtD5Dk8zohJGbwa+ZbEAq\/peBTvf8hwU+CgeeUntxsi4JcEdKcn4Av7nyVPwuiK0KFdcYVDYkUTQc+\/49wrWvbBCNVFzOVTu6MK67fhUNcU3vA1PPwmYLhRGU3nXqDVSe7e445m5ONg\/UfoX94Ke75NLReuiwWEAUhPgBJO+mM6OTUfJNVMMZliY0Lx5mv7GTCSiiiekw8bhys2gBXjZCM7+KDL15JlmnxsftrEtinJc54GmYijdVUhM10YlQLmLvngpXUDm6ltbzBwvUBM6DJNM6OZR1KAs4SOiSKI80jVp3PLiXXz\/ebk\/tBUMtg1GG044Wn136elDK70LIVJ+NKfA69ry62YeZw9waBIxV7qWkysG8AJNO5hyCZFhobW0PKS1V2Nz+mmtRddaadsv8+zAJPZep\/j37+DetN65oHW2ncsGA\/zJl6HJ3ITiFl2WuiPEBU69O3JYvFgjshmqBixaGE5TOO+6M5TU7tRE\/8KFCwxoO05tJqD\/JHk3KEorL8HfBZ6K1yvGkyRVS6MFBC7sAfEk6WvRgzd4paShGzBmL9iIs4kx2emoZMyQj1i4WFtzq7m97+Lkfwvz05uOCdYICYY+ahEURLUS05e92CvakAeQZJ7Sff5g4k2v\/H6TOdRPSxCdBIf494L0fXX+u9J+lXgtepPIb0xiq6pfWNLr\/UP0HGWgPHJ+lWVxVOXUh0y9To+u\/HaH0frnnKkp58QQKqd1hMPubuU1z1AkE1oVfJmhLApFW78wqiwzM80o4gDKwjq3QW8ymy29bG+ubLeb\/LLTtm+qO1gFnP1awH21dFnaR5S8a3vWlqQLcFI2Ir2ZffryQq+DkbOX849QoHh\/MclmQs2z3y+q\/IKwBoCy8ft\/AXvOHycoIFym5k+6s7yhd3YI8l8C+hqBMgPfj2o6ESZuuYCI+FemWAlvz6CHyfvFujT8pLjEHjZU5lSgIfPmV4se125lutxhh\/o9RhL0VT2aa7rgxr2Qwdq5fuLWpiedRrysCOKzetnGKhUZWnJe\/94WAwdDyLa961uFZzRIU\/KfDSkQ3AkXEjXOiDnIxhFNupS1O9rt9U3BcrLH\/WqzkvXZZxt5mgtumTgQTaWwGczcwPrcACTuJZjrgJXnf+woTedpSxWZMh10b7vVG+\/F\/X\/6kuu3ZEP45kMy4jCmU5ILOyf8F8r3B5w0nfW\/aBRPOWujVMMg7CbOP\/CxM2qV0Q9eNic\/b24CT8Bf6QLOy0NR1hKnPc4VKNZelHvKzqyJwqjMPYL0wBYPgRy9GbYl\/lYnfqoFUXi5K8b93d1gHx83aPvQ4zJi0GkzsPUp\/lNpDEJrsPm7+x3M1maG8sd3O\/tq64b24PnmRz2MdNzaXsU1s5ByPAYv04UVVrkUJTqu\/DgSnAGfGQpZGl10qcFkyKW6Z23PFthp1SKMvBZYNqWyp\/RoMMM6u3B6Hm4dyV1yV5sqpnOSt\/LkQhCGl++XXI6yZcHUZLB7jAqWsT6lweNCX9KB47xna+7xQflRAFerWtlzBxV1Ks9CIsDvJpCuRT+3zwFnz15taytNXavSyJtKMGWgS6pXmtXI+ks4NA5PGxmrYwgW2Z7s5qu9aBZE6pdkSXKkAKpNfYgmbwYFwO\/76smjiZ1+Bt68eAX1jnu7AjXDDhaD2nH3jp2EU1CIxh3BTEQV5GE6\/aj4S3edN53Ncq\/evjmLcAK9AhjARlDRl5SWkGSXJTUeuiwpcYOGeBJY07oEGcEZeEF+Z4QTJLTugURp4aVzhWPeKDa4fkBwvjtPtpyIWVueCX1zlD3N9a+KsCapMFPVEWeLkib3Fl0oFXAt1As\/fQRbsTI35xDjO1qIxqaLdy9LMKQyzqZB6hSrPrWaXzVfS\/\/JEETpg\/tH9pfUZGEk02Yf89ngOFlNUyThzVZN5cR6kvtVc5cPCpwqEJV+jiKEkawmxuBnjsdz47IMwAvnn8DCmY2dzHzBuXbsesCZtuDmKa\/cOZJ46n8IJ9ks0EqsWn74q5Tkd0eO5945ilmh0BbIj6To00SfoZpDiif5joLoh54NePmn7PF\/mAnv9T6rLhY4\/JYmgL3IqrI\/HdAuJkBbA7kcVrigMFpp20Zts38YDZXNvMwW\/8zGge744o55w7tiwmcQJYdgc8Vpw0POnmAXae91lznpbk73uLdhfEffizs9ngZZY00ykOtFV1Tsbs2ypcTVpmImLfXDuQCiKyB1FHLTSZOSBfwE6yqM+z9qpaUZ72bF2O9zlDMyxLnB0\/y+I2rrjfEb\/pva9GocgF6WlzUO0h8NQ6CpDQWT1V6CkFRZCDclUtufK4uOkiU9BCtHW\/IofTWjqXLj8WD1Iuoorv6ffk7dwgffRnzD\/6K\/obrd1IgIYfWETeQ\/U\/gAMlRIPFdftsus31SaXTkMwR7VZPV1EmCwKLXCqcbAF6frDjcJxYFSrVszSwBze40BGsb5tVnWsHf9kw4dfReMNvDQSTPlNFN5iDO9icc0UN3V3mD7AZw6yvmKdEZfRRcHDbN1ch1+7TscaotKeOg7alBMb4E9GFLXNRBu1eJdJ+yPE08SWdFj3rkea501yMGD96hnwYKx3ZpFyuTasLkrQebBDNTNyB9WLKazdqmw3sDlipWSs6sBnazPDkaTi9m6\/BWc4KqZcRiWhY3dhzfa6hWXI76JajH4MFtPlPqwSrar95WNZFUcjMVMM8+d+34gDEy2djjzH0Er9vIjBYgwEknBQr8ASDMP59LXgrelVDAKlbm+rEHqumqSCChSTF6g2ZihiajYlg+sMbdkaFZNRI+4VQR5H9ufFMwqCpDAePW5RHDw8FcVnp6DvpY4CjBm4D5Yx5rwiRc0wJE31ZaSciVKhnK+1StvjMoFn9yxf\/2SdZG4SzdYjqs6oIxUKUiVSj+x3rfILGKbAf8wDoqmmXj1HEm3HQY501h8roOyrwrH9Ql0glfRffjymqwGQpEeLhKO6ldTH6VP6ds8dsnM1oUFLBnRLM8Bpq5XqSSAcfj+eMd0wt1MGDdXRMWJzVcQBpuptPle\/kt\/INmBid\/zrANw+ChhJgAznOekdL5YKWDHcrgI9R6aF20YczckBK+WSpx4OJ1Z0eozNWM7IcG\/KAqwm3+c\/iPDL3cMpCTQnhLM9bSMakMYpDVKTwyY1TsyXEX4ZCc9ZAdZQ53b0yxGBkX+lM\/HeHw8nOeu9qN8JtgAi00iHolNEyiohZupxeXYKoc3WpJ\/HgerkxWTT1VhuwtRuy8EzG888il93HtehFPUbyZKW5Q6Fys5q\/Q4sfOr+Wc4aztSf5JW\/ESa3xRi7x1gLuwADIUfaFZCG0wPL9I7sN8Vqe4qrehP+bVBOqx3UOXXxOIMi80NV\/9EEZiPpHOu+Qb\/k\/EBOCYAWaBxeWujR7ps7A3iUpZf1W6Y6jtXH3T\/pzPH27ikd+yM2aR1ofhBbawUfkKE5T5vju8S8t61QKVfAp3UxJFEvCpROcbsWthd40v5mr4e2VMy2wgLcpVsR4mT93Dlg==" } \ No newline at end of file diff --git a/testdata/aegis_export_plain.json b/testdata/aegis_export_plain.json index a3ab399d..10d03a95 100644 --- a/testdata/aegis_export_plain.json +++ b/testdata/aegis_export_plain.json @@ -12,6 +12,7 @@ "uuid": "8e986927-a7a3-4d35-88fb-509ae7960155", "name": "Bob", "issuer": "Google", + "icon": null, "info": { "secret": "KD3WHMYQ7K7DGV5QFJNN2ZUATBC44C7F", "algo": "SHA1", @@ -24,6 +25,7 @@ "uuid": "97155de0-fb6a-4dfa-ac59-2abe54f5d059", "name": "Henk", "issuer": "Scaleway", + "icon": null, "info": { "secret": "MBQX47S3XOSOF7YT2CO3LZNACULZNY4P", "algo": "SHA256", @@ -36,6 +38,7 @@ "uuid": "a6276843-3c95-43b7-a3ef-e824c5534801", "name": "nodejsc0d3r", "issuer": "Github", + "icon": null, "info": { "secret": "642GK5EROWKUAEBFRH6FWSMM4FRKS5IA", "algo": "SHA1", @@ -48,11 +51,12 @@ "uuid": "1748b48c-7496-4722-9048-17248e843773", "name": "Lil' Droplet", "issuer": "DigitalOcean", + "icon": null, "info": { "secret": "6CAIGVYB5MQ6TSZLJ56HJBWU5S3H7FUC", "algo": "SHA512", "digits": 6, - "counter": 96 + "counter": 102 } }, { @@ -60,6 +64,7 @@ "uuid": "9eef3fa3-bdde-4954-bf37-58bf1d5d6e5f", "name": "alex", "issuer": "TTRSS", + "icon": null, "info": { "secret": "BEBXDJJVXKX3ZMAZLJUU5I5PONI4IYAL", "algo": "SHA1", @@ -72,6 +77,7 @@ "uuid": "159b3e5f-fff4-4ff5-997a-b8d1263ee446", "name": "MoneroMan", "issuer": "Poloniex", + "icon": null, "info": { "secret": "NUSLOF6CFEWNPAARBVJ5WFA5YRRQU4FG", "algo": "SHA256", @@ -84,6 +90,7 @@ "uuid": "8cd843e5-4122-48e1-8089-a3d0c769741f", "name": "givemeabucket", "issuer": "Bitbucket", + "icon": null, "info": { "secret": "5KY3D2N53MRMIOMNKLLTNF3TDQJRDMEY", "algo": "SHA1", @@ -96,6 +103,7 @@ "uuid": "77c6267a-b38a-40b9-a3a7-5a5ce11230bb", "name": "Pepe", "issuer": "4chan", + "icon": null, "info": { "secret": "EIQMT7NHFYJUMBKQ35P34JGLG3MO7L2W", "algo": "SHA1", @@ -108,6 +116,7 @@ "uuid": "435a3542-c566-4cc0-a5f4-39cd6ffe316d", "name": "Delete Me", "issuer": "Facebook", + "icon": null, "info": { "secret": "GSQ7E5FO3UFFVANS3NSMFE7RTMRMYNCV", "algo": "SHA1", @@ -120,6 +129,7 @@ "uuid": "7dca76af-fa6a-4585-8d47-5a8b78130c9c", "name": "Oh wait, they don't have TOTP", "issuer": "Namecheap", + "icon": null, "info": { "secret": "HIMV4HX3REXMUG236OOLN4GS7URI247Y", "algo": "SHA512", From 476643a81c96d9591c9eaa5070b70cca60b41de9 Mon Sep 17 00:00:00 2001 From: Alexander Bakker Date: Thu, 7 Jun 2018 18:00:47 +0200 Subject: [PATCH 13/14] Try to fix progressbar visibility one last time --- app/src/main/res/layout/fragment_entry_list_view.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/res/layout/fragment_entry_list_view.xml b/app/src/main/res/layout/fragment_entry_list_view.xml index 39186e44..6809001a 100644 --- a/app/src/main/res/layout/fragment_entry_list_view.xml +++ b/app/src/main/res/layout/fragment_entry_list_view.xml @@ -11,6 +11,7 @@ android:layout_width="match_parent" android:layout_height="4dp" android:id="@+id/progressBar" + android:visibility="gone" android:max="1000"/> Date: Thu, 7 Jun 2018 18:39:44 +0200 Subject: [PATCH 14/14] Fix a crash that would occur while moving an entry during a refresh --- .idea/misc.xml | 2 +- .../java/me/impy/aegis/ui/MainActivity.java | 2 +- .../me/impy/aegis/ui/views/EntryAdapter.java | 18 +++++++++++++++++- .../me/impy/aegis/ui/views/EntryListView.java | 11 ++++++----- 4 files changed, 25 insertions(+), 8 deletions(-) diff --git a/.idea/misc.xml b/.idea/misc.xml index 53a3fb16..635999df 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -24,7 +24,7 @@ - + diff --git a/app/src/main/java/me/impy/aegis/ui/MainActivity.java b/app/src/main/java/me/impy/aegis/ui/MainActivity.java index 7bd36484..dba22e3c 100644 --- a/app/src/main/java/me/impy/aegis/ui/MainActivity.java +++ b/app/src/main/java/me/impy/aegis/ui/MainActivity.java @@ -327,7 +327,7 @@ public class MainActivity extends AegisActivity implements EntryListView.Listene updateLockIcon(); // refresh all codes to prevent showing old ones - _entryListView.refresh(); + _entryListView.refresh(true); } private BottomSheetDialog createBottomSheet(final DatabaseEntry entry) { diff --git a/app/src/main/java/me/impy/aegis/ui/views/EntryAdapter.java b/app/src/main/java/me/impy/aegis/ui/views/EntryAdapter.java index 3cd5dc6e..6268f57b 100644 --- a/app/src/main/java/me/impy/aegis/ui/views/EntryAdapter.java +++ b/app/src/main/java/me/impy/aegis/ui/views/EntryAdapter.java @@ -23,8 +23,12 @@ public class EntryAdapter extends RecyclerView.Adapter implements I private static Listener _listener; private boolean _showIssuer; + // keeps track of the viewholders that are currently bound + private List _holders; + public EntryAdapter(Listener listener) { _entries = new ArrayList<>(); + _holders = new ArrayList<>(); _listener = listener; } @@ -76,6 +80,16 @@ public class EntryAdapter extends RecyclerView.Adapter implements I throw new AssertionError("no entry found with the same id"); } + public void refresh(boolean hard) { + if (hard) { + notifyDataSetChanged(); + } else { + for (EntryHolder holder : _holders) { + holder.refreshCode(); + } + } + } + @Override public void onItemDismiss(int position) { @@ -105,7 +119,7 @@ public class EntryAdapter extends RecyclerView.Adapter implements I @Override public void onViewRecycled(EntryHolder holder) { holder.stopRefreshLoop(); - super.onViewRecycled(holder); + _holders.remove(holder); } @Override @@ -149,6 +163,8 @@ public class EntryAdapter extends RecyclerView.Adapter implements I holder.refreshCode(); } }); + + _holders.add(holder); } public int getUniformPeriod() { diff --git a/app/src/main/java/me/impy/aegis/ui/views/EntryListView.java b/app/src/main/java/me/impy/aegis/ui/views/EntryListView.java index a0597075..c4406f7d 100644 --- a/app/src/main/java/me/impy/aegis/ui/views/EntryListView.java +++ b/app/src/main/java/me/impy/aegis/ui/views/EntryListView.java @@ -53,7 +53,7 @@ public class EntryListView extends Fragment implements EntryAdapter.Listener { _refresher = new UiRefresher(new UiRefresher.Listener() { @Override public void onRefresh() { - refresh(); + refresh(false); } @Override @@ -65,11 +65,11 @@ public class EntryListView extends Fragment implements EntryAdapter.Listener { return view; } - public void refresh() { + public void refresh(boolean hard) { if (_showProgress) { _progressBar.refresh(); } - _adapter.notifyDataSetChanged(); + _adapter.refresh(hard); } private void checkPeriodUniformity() { @@ -90,11 +90,12 @@ public class EntryListView extends Fragment implements EntryAdapter.Listener { } private void startRefreshLoop() { + refresh(true); _refresher.start(); } private void stopRefreshLoop() { - refresh(); + refresh(true); _refresher.stop(); } @@ -129,7 +130,7 @@ public class EntryListView extends Fragment implements EntryAdapter.Listener { public void setShowIssuer(boolean showIssuer) { _adapter.setShowIssuer(showIssuer); - _adapter.notifyDataSetChanged(); + _adapter.refresh(true); } public void addEntry(DatabaseEntry entry) {