Add support for selecting SVG icons through the file selection dialog

Fixes #724
pull/735/head
Alexander Bakker 4 years ago
parent b195d0dadd
commit a5d3de55a2

@ -26,6 +26,7 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AlertDialog;
import androidx.documentfile.provider.DocumentFile;
import com.amulyakhare.textdrawable.TextDrawable;
import com.avito.android.krop.KropView;
@ -47,6 +48,7 @@ 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.tasks.ImportFileTask;
import com.beemdevelopment.aegis.ui.views.IconAdapter;
import com.beemdevelopment.aegis.util.Cloner;
import com.beemdevelopment.aegis.util.IOUtils;
@ -61,6 +63,7 @@ import com.google.android.material.textfield.TextInputEditText;
import com.google.android.material.textfield.TextInputLayout;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
@ -439,18 +442,7 @@ public class EditEntryActivity extends AegisActivity {
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);
selectIcon(icon);
}
@Override
@ -461,6 +453,21 @@ public class EditEntryActivity extends AegisActivity {
Dialogs.showSecureDialog(dialog);
}
private void selectIcon(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);
}
private void startEditingIcon(Uri data) {
Glide.with(this)
.asBitmap()
@ -546,7 +553,21 @@ public class EditEntryActivity extends AegisActivity {
@Override
protected void onActivityResult(int requestCode, final int resultCode, Intent data) {
if (requestCode == PICK_IMAGE_REQUEST && resultCode == RESULT_OK && data != null && data.getData() != null) {
startEditingIcon(data.getData());
DocumentFile file = DocumentFile.fromSingleUri(this, data.getData());
if (file.getType().equals(IconType.SVG.toMimeType())) {
ImportFileTask.Params params = new ImportFileTask.Params(data.getData(), "icon", null);
ImportFileTask task = new ImportFileTask(this, result -> {
if (result.getException() == null) {
CustomSvgIcon icon = new CustomSvgIcon(result.getFile());
selectIcon(icon);
} else {
Dialogs.showErrorDialog(this, R.string.reading_file_error, result.getException());
}
});
task.execute(getLifecycle(), params);
} else {
startEditingIcon(data.getData());
}
}
super.onActivityResult(requestCode, resultCode, data);
@ -641,8 +662,7 @@ public class EditEntryActivity extends AegisActivity {
try (FileInputStream inStream = new FileInputStream(_selectedIcon.getFile())){
iconBytes = IOUtils.readFile(inStream);
} catch (IOException e) {
// TODO: show dialog
throw new RuntimeException(e);
throw new ParseException(e.getMessage());
}
entry.setIcon(iconBytes, _selectedIcon.getIconType());
@ -714,4 +734,23 @@ public class EditEntryActivity extends AegisActivity {
super(message);
}
}
private static class CustomSvgIcon extends IconPack.Icon {
private final File _file;
protected CustomSvgIcon(File file) {
super(file.getAbsolutePath(), null, null);
_file = file;
}
@Nullable
public File getFile() {
return _file;
}
@Override
public IconType getIconType() {
return IconType.SVG;
}
}
}

@ -112,6 +112,7 @@ public class ImportExportPreferencesFragment extends PreferencesFragment {
return;
}
ImportFileTask.Params params = new ImportFileTask.Params(uri, "import", null);
ImportFileTask task = new ImportFileTask(getContext(), result -> {
if (result.getException() == null) {
startImportEntriesActivity(_importerType, result.getFile());
@ -119,7 +120,7 @@ public class ImportExportPreferencesFragment extends PreferencesFragment {
Dialogs.showErrorDialog(getContext(), R.string.reading_file_error, result.getException());
}
});
task.execute(getLifecycle(), uri);
task.execute(getLifecycle(), params);
}
private void startImportEntriesActivity(Class<? extends DatabaseImporter> importerType, File file) {

@ -15,7 +15,7 @@ import java.io.InputStream;
* ImportFileTask reads an SAF file from a background thread and
* writes it to a temporary file in the cache directory.
*/
public class ImportFileTask extends ProgressDialogTask<Uri, ImportFileTask.Result> {
public class ImportFileTask extends ProgressDialogTask<ImportFileTask.Params, ImportFileTask.Result> {
private final Callback _cb;
public ImportFileTask(Context context, Callback cb) {
@ -24,11 +24,15 @@ public class ImportFileTask extends ProgressDialogTask<Uri, ImportFileTask.Resul
}
@Override
protected Result doInBackground(Uri... uris) {
protected Result doInBackground(Params... params) {
Context context = getDialog().getContext();
try (InputStream inStream = context.getContentResolver().openInputStream(uris[0])) {
File tempFile = File.createTempFile("import-", "", context.getCacheDir());
Params p = params[0];
try (InputStream inStream = context.getContentResolver().openInputStream(p.getUri())) {
String prefix = p.getNamePrefix() != null ? p.getNamePrefix() + "-" : "";
String suffix = p.getNameSuffix() != null ? "-" + p.getNameSuffix() : "";
File tempFile = File.createTempFile(prefix, suffix, context.getCacheDir());
try (FileOutputStream outStream = new FileOutputStream(tempFile)) {
IOUtils.copy(inStream, outStream);
}
@ -50,6 +54,30 @@ public class ImportFileTask extends ProgressDialogTask<Uri, ImportFileTask.Resul
void onTaskFinished(Result result);
}
public static class Params {
private final Uri _uri;
private final String _namePrefix;
private final String _nameSuffix;
public Params(Uri uri, String namePrefix, String nameSuffix) {
_uri = uri;
_namePrefix = namePrefix;
_nameSuffix = nameSuffix;
}
public Uri getUri() {
return _uri;
}
public String getNamePrefix() {
return _namePrefix;
}
public String getNameSuffix() {
return _nameSuffix;
}
}
public static class Result {
private final File _file;
private final Exception _e;

Loading…
Cancel
Save