From 8b280ddbb0b46b8ccce217801266e6c1acedd694 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20Sch=C3=A4ttgen?= Date: Wed, 6 Jun 2018 18:01:35 +0200 Subject: [PATCH 1/8] Added minor improvements to the Intro --- .../java/me/impy/aegis/ui/IntroActivity.java | 17 +--- .../ui/slides/CustomAuthenticationSlide.java | 7 +- .../res/color/disabled_textview_colors.xml | 11 +++ app/src/main/res/drawable/ic_id_card.xml | 23 +++++ .../layout/fragment_authentication_slide.xml | 95 +++++++++++-------- app/src/main/res/values/strings.xml | 4 +- 6 files changed, 100 insertions(+), 57 deletions(-) create mode 100644 app/src/main/res/color/disabled_textview_colors.xml create mode 100644 app/src/main/res/drawable/ic_id_card.xml diff --git a/app/src/main/java/me/impy/aegis/ui/IntroActivity.java b/app/src/main/java/me/impy/aegis/ui/IntroActivity.java index 81d81645..877d1234 100644 --- a/app/src/main/java/me/impy/aegis/ui/IntroActivity.java +++ b/app/src/main/java/me/impy/aegis/ui/IntroActivity.java @@ -58,7 +58,9 @@ public class IntroActivity extends AppIntro implements DerivationTask.Callback { getWindow().addFlags(WindowManager.LayoutParams.FLAG_SECURE); } + setWizardMode(true); showSkipButton(false); + pager.setPagingEnabled(false); //showPagerIndicator(false); setGoBackLock(true); @@ -69,19 +71,6 @@ public class IntroActivity extends AppIntro implements DerivationTask.Callback { homeSliderPage.setBgColor(getResources().getColor(R.color.colorPrimary)); addSlide(AppIntroFragment.newInstance(homeSliderPage)); - SliderPage permSliderPage = new SliderPage(); - permSliderPage.setTitle("Permissions"); - permSliderPage.setDescription("Aegis needs permission to use your camera in order to scan QR codes. " + - "It also needs access to external storage to able to export the database."); - permSliderPage.setImageDrawable(R.drawable.intro_scanner); - permSliderPage.setBgColor(getResources().getColor(R.color.colorAccent)); - addSlide(AppIntroFragment.newInstance(permSliderPage)); - askForPermissions(new String[]{ - Manifest.permission.CAMERA, - Manifest.permission.READ_EXTERNAL_STORAGE, - Manifest.permission.WRITE_EXTERNAL_STORAGE - }, 2); - _authenticationSlide = new CustomAuthenticationSlide(); _authenticationSlide.setBgColor(getResources().getColor(R.color.colorHeaderSuccess)); addSlide(_authenticationSlide); @@ -124,7 +113,7 @@ public class IntroActivity extends AppIntro implements DerivationTask.Callback { // skip to the last slide if no encryption will be used if (cryptType == CustomAuthenticationSlide.CRYPT_TYPE_NONE) { // TODO: no magic indices - getPager().setCurrentItem(5); + getPager().setCurrentItem(4); } } } 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 f3b8144d..b46f7421 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,8 +8,10 @@ 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; @@ -23,6 +25,7 @@ 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; @@ -38,8 +41,8 @@ public class CustomAuthenticationSlide extends Fragment implements ISlidePolicy, if (manager != null) { RadioButton button = view.findViewById(R.id.rb_fingerprint); TextView text = view.findViewById(R.id.text_rb_fingerprint); - button.setVisibility(View.VISIBLE); - text.setVisibility(View.VISIBLE); + button.setEnabled(false); + text.setEnabled(false); } view.findViewById(R.id.main).setBackgroundColor(_bgColor); diff --git a/app/src/main/res/color/disabled_textview_colors.xml b/app/src/main/res/color/disabled_textview_colors.xml new file mode 100644 index 00000000..adbd5b7e --- /dev/null +++ b/app/src/main/res/color/disabled_textview_colors.xml @@ -0,0 +1,11 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_id_card.xml b/app/src/main/res/drawable/ic_id_card.xml new file mode 100644 index 00000000..724573e4 --- /dev/null +++ b/app/src/main/res/drawable/ic_id_card.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/fragment_authentication_slide.xml b/app/src/main/res/layout/fragment_authentication_slide.xml index cae4dc7d..030c0f2e 100644 --- a/app/src/main/res/layout/fragment_authentication_slide.xml +++ b/app/src/main/res/layout/fragment_authentication_slide.xml @@ -1,5 +1,6 @@ + android:textSize="24sp" + android:layout_marginTop="30dp" + android:textStyle="bold" /> + + + android:layout_alignParentBottom="true" + android:layout_marginTop="12dp" + android:orientation="horizontal"> + + android:text="@string/authentication_method_none" + android:textSize="16sp" /> + + + + + + - - - - - + android:layout_marginTop="-5dp" + + android:text="@string/authentication_method_fingerprint_description" + android:textColor="@color/disabled_textview_colors" + /> + The database will be stored in plain text Password The database will be encrypted with a key derived from a password - Password & Fingerprint + Fingerprint In addition to a password, fingerprints registered on this device can be used to decrypt the database Password Enter your password @@ -45,7 +45,7 @@ None Password - Password & Fingerprint + Fingerprint 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 2/8] 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 3/8] 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 4/8] 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 5/8] 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 6/8] 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 7/8] 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 8/8] 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());