mirror of
https://github.com/beemdevelopment/Aegis.git
synced 2025-05-14 14:02:49 +00:00
Introduce support for icon packs
This commit is contained in:
parent
c977b9a064
commit
4f38988c0d
44 changed files with 2128 additions and 54 deletions
|
@ -34,7 +34,10 @@ import com.beemdevelopment.aegis.encoding.Base32;
|
|||
import com.beemdevelopment.aegis.encoding.EncodingException;
|
||||
import com.beemdevelopment.aegis.helpers.DropdownHelper;
|
||||
import com.beemdevelopment.aegis.helpers.EditTextHelper;
|
||||
import com.beemdevelopment.aegis.helpers.IconViewHelper;
|
||||
import com.beemdevelopment.aegis.helpers.TextDrawableHelper;
|
||||
import com.beemdevelopment.aegis.icons.IconPack;
|
||||
import com.beemdevelopment.aegis.icons.IconType;
|
||||
import com.beemdevelopment.aegis.otp.GoogleAuthInfo;
|
||||
import com.beemdevelopment.aegis.otp.HotpInfo;
|
||||
import com.beemdevelopment.aegis.otp.OtpInfo;
|
||||
|
@ -42,23 +45,32 @@ import com.beemdevelopment.aegis.otp.OtpInfoException;
|
|||
import com.beemdevelopment.aegis.otp.SteamInfo;
|
||||
import com.beemdevelopment.aegis.otp.TotpInfo;
|
||||
import com.beemdevelopment.aegis.ui.dialogs.Dialogs;
|
||||
import com.beemdevelopment.aegis.ui.dialogs.IconPickerDialog;
|
||||
import com.beemdevelopment.aegis.ui.glide.IconLoader;
|
||||
import com.beemdevelopment.aegis.ui.views.IconAdapter;
|
||||
import com.beemdevelopment.aegis.util.Cloner;
|
||||
import com.beemdevelopment.aegis.util.IOUtils;
|
||||
import com.beemdevelopment.aegis.vault.VaultEntry;
|
||||
import com.beemdevelopment.aegis.vault.VaultManager;
|
||||
import com.bumptech.glide.Glide;
|
||||
import com.bumptech.glide.load.engine.DiskCacheStrategy;
|
||||
import com.bumptech.glide.request.target.CustomTarget;
|
||||
import com.bumptech.glide.request.transition.Transition;
|
||||
import com.google.android.material.bottomsheet.BottomSheetDialog;
|
||||
import com.google.android.material.textfield.TextInputEditText;
|
||||
import com.google.android.material.textfield.TextInputLayout;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.TreeSet;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import de.hdodenhof.circleimageview.CircleImageView;
|
||||
|
||||
|
@ -72,6 +84,7 @@ public class EditEntryActivity extends AegisActivity {
|
|||
private boolean _hasCustomIcon = false;
|
||||
// keep track of icon changes separately as the generated jpeg's are not deterministic
|
||||
private boolean _hasChangedIcon = false;
|
||||
private IconPack.Icon _selectedIcon;
|
||||
private boolean _isEditingIcon;
|
||||
private CircleImageView _iconView;
|
||||
private ImageView _saveImageButton;
|
||||
|
@ -165,9 +178,11 @@ public class EditEntryActivity extends AegisActivity {
|
|||
|
||||
// fill the fields with values if possible
|
||||
if (_origEntry.hasIcon()) {
|
||||
IconViewHelper.setLayerType(_iconView, _origEntry.getIconType());
|
||||
Glide.with(this)
|
||||
.asDrawable()
|
||||
.load(_origEntry)
|
||||
.set(IconLoader.ICON_TYPE, _origEntry.getIconType())
|
||||
.diskCacheStrategy(DiskCacheStrategy.NONE)
|
||||
.skipMemoryCache(false)
|
||||
.into(_iconView);
|
||||
|
@ -237,7 +252,7 @@ public class EditEntryActivity extends AegisActivity {
|
|||
});
|
||||
|
||||
_iconView.setOnClickListener(v -> {
|
||||
startIconSelectionActivity();
|
||||
startIconSelection();
|
||||
});
|
||||
|
||||
_dropdownGroup.setOnItemClickListener(new AdapterView.OnItemClickListener() {
|
||||
|
@ -384,11 +399,13 @@ public class EditEntryActivity extends AegisActivity {
|
|||
});
|
||||
break;
|
||||
case R.id.action_edit_icon:
|
||||
startIconSelectionActivity();
|
||||
startIconSelection();
|
||||
break;
|
||||
case R.id.action_default_icon:
|
||||
TextDrawable drawable = TextDrawableHelper.generate(_origEntry.getIssuer(), _origEntry.getName(), _iconView);
|
||||
_iconView.setImageDrawable(drawable);
|
||||
|
||||
_selectedIcon = null;
|
||||
_hasCustomIcon = false;
|
||||
_hasChangedIcon = true;
|
||||
default:
|
||||
|
@ -398,7 +415,7 @@ public class EditEntryActivity extends AegisActivity {
|
|||
return true;
|
||||
}
|
||||
|
||||
private void startIconSelectionActivity() {
|
||||
private void startImageSelectionActivity() {
|
||||
Intent galleryIntent = new Intent(Intent.ACTION_PICK);
|
||||
galleryIntent.setDataAndType(android.provider.MediaStore.Images.Media.INTERNAL_CONTENT_URI, "image/*");
|
||||
|
||||
|
@ -410,6 +427,40 @@ public class EditEntryActivity extends AegisActivity {
|
|||
startActivityForResult(chooserIntent, PICK_IMAGE_REQUEST);
|
||||
}
|
||||
|
||||
private void startIconSelection() {
|
||||
List<IconPack> iconPacks = getApp().getIconPackManager().getIconPacks().stream()
|
||||
.sorted(Comparator.comparing(IconPack::getName))
|
||||
.collect(Collectors.toList());
|
||||
if (iconPacks.size() == 0) {
|
||||
startImageSelectionActivity();
|
||||
return;
|
||||
}
|
||||
|
||||
BottomSheetDialog dialog = IconPickerDialog.create(this, iconPacks, _textIssuer.getText().toString(), new IconAdapter.Listener() {
|
||||
@Override
|
||||
public void onIconSelected(IconPack.Icon icon) {
|
||||
_selectedIcon = icon;
|
||||
_hasCustomIcon = true;
|
||||
_hasChangedIcon = true;
|
||||
|
||||
IconViewHelper.setLayerType(_iconView, icon.getIconType());
|
||||
Glide.with(EditEntryActivity.this)
|
||||
.asDrawable()
|
||||
.load(icon.getFile())
|
||||
.set(IconLoader.ICON_TYPE, icon.getIconType())
|
||||
.diskCacheStrategy(DiskCacheStrategy.NONE)
|
||||
.skipMemoryCache(false)
|
||||
.into(_iconView);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCustomSelected() {
|
||||
startImageSelectionActivity();
|
||||
}
|
||||
});
|
||||
Dialogs.showSecureDialog(dialog);
|
||||
}
|
||||
|
||||
private void startEditingIcon(Uri data) {
|
||||
Glide.with(this)
|
||||
.asBitmap()
|
||||
|
@ -438,11 +489,12 @@ public class EditEntryActivity extends AegisActivity {
|
|||
}
|
||||
|
||||
private void stopEditingIcon(boolean save) {
|
||||
if (save) {
|
||||
if (save && _selectedIcon == null) {
|
||||
_iconView.setImageBitmap(_kropView.getCroppedBitmap());
|
||||
}
|
||||
_iconView.setVisibility(View.VISIBLE);
|
||||
_kropView.setVisibility(View.GONE);
|
||||
|
||||
_hasCustomIcon = _hasCustomIcon || save;
|
||||
_hasChangedIcon = save;
|
||||
_isEditingIcon = false;
|
||||
|
@ -577,13 +629,26 @@ public class EditEntryActivity extends AegisActivity {
|
|||
|
||||
if (_hasChangedIcon) {
|
||||
if (_hasCustomIcon) {
|
||||
Bitmap bitmap = ((BitmapDrawable) _iconView.getDrawable()).getBitmap();
|
||||
ByteArrayOutputStream stream = new ByteArrayOutputStream();
|
||||
bitmap.compress(Bitmap.CompressFormat.JPEG, 90, stream);
|
||||
byte[] data = stream.toByteArray();
|
||||
entry.setIcon(data);
|
||||
if (_selectedIcon == null) {
|
||||
Bitmap bitmap = ((BitmapDrawable) _iconView.getDrawable()).getBitmap();
|
||||
ByteArrayOutputStream stream = new ByteArrayOutputStream();
|
||||
// the quality parameter is ignored for PNG
|
||||
bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream);
|
||||
byte[] data = stream.toByteArray();
|
||||
entry.setIcon(data, IconType.PNG);
|
||||
} else {
|
||||
byte[] iconBytes;
|
||||
try (FileInputStream inStream = new FileInputStream(_selectedIcon.getFile())){
|
||||
iconBytes = IOUtils.readFile(inStream);
|
||||
} catch (IOException e) {
|
||||
// TODO: show dialog
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
entry.setIcon(iconBytes, _selectedIcon.getIconType());
|
||||
}
|
||||
} else {
|
||||
entry.setIcon(null);
|
||||
entry.setIcon(null, IconType.INVALID);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -626,7 +691,7 @@ public class EditEntryActivity extends AegisActivity {
|
|||
}
|
||||
}
|
||||
|
||||
private TextWatcher _iconChangeListener = new TextWatcher() {
|
||||
private final TextWatcher _iconChangeListener = new TextWatcher() {
|
||||
@Override
|
||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue