mirror of
https://github.com/beemdevelopment/Aegis.git
synced 2025-04-24 07:46:07 +00:00
Write entries to the vault directly in EditEntryActivity
This makes it so that EditEntryActivity directly saves entries to the vault, instead of passing them back to MainActivity through an Intent first. This prevents crashes that can occur when an entry has a large icon and the Bundle inside the Intent becomes too large. This is the first part of a series of patches I plan on submitting, where I try to repair the damage done by my misguided obsession of only touching the global state in certain places.
This commit is contained in:
parent
9b328893f7
commit
301476ff5c
6 changed files with 116 additions and 84 deletions
|
@ -8,13 +8,14 @@ import android.provider.Settings;
|
|||
import android.view.WindowManager;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.CallSuper;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
import com.beemdevelopment.aegis.AegisApplication;
|
||||
import com.beemdevelopment.aegis.Preferences;
|
||||
import com.beemdevelopment.aegis.R;
|
||||
import com.beemdevelopment.aegis.Theme;
|
||||
|
||||
import androidx.annotation.CallSuper;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import com.beemdevelopment.aegis.vault.VaultManagerException;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
|
@ -126,6 +127,16 @@ public abstract class AegisActivity extends AppCompatActivity implements AegisAp
|
|||
this.getResources().updateConfiguration(config, this.getResources().getDisplayMetrics());
|
||||
}
|
||||
|
||||
protected boolean saveVault() {
|
||||
try {
|
||||
getApp().getVaultManager().save();
|
||||
return true;
|
||||
} catch (VaultManagerException e) {
|
||||
Toast.makeText(this, getString(R.string.saving_error), Toast.LENGTH_LONG).show();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reports whether this Activity has been resumed. (i.e. onResume was called)
|
||||
*/
|
||||
|
|
|
@ -31,7 +31,6 @@ import androidx.appcompat.app.AlertDialog;
|
|||
import com.amulyakhare.textdrawable.TextDrawable;
|
||||
import com.avito.android.krop.KropView;
|
||||
import com.beemdevelopment.aegis.R;
|
||||
import com.beemdevelopment.aegis.vault.VaultEntry;
|
||||
import com.beemdevelopment.aegis.encoding.Base32;
|
||||
import com.beemdevelopment.aegis.encoding.EncodingException;
|
||||
import com.beemdevelopment.aegis.helpers.EditTextHelper;
|
||||
|
@ -43,16 +42,18 @@ import com.beemdevelopment.aegis.otp.OtpInfoException;
|
|||
import com.beemdevelopment.aegis.otp.SteamInfo;
|
||||
import com.beemdevelopment.aegis.otp.TotpInfo;
|
||||
import com.beemdevelopment.aegis.util.Cloner;
|
||||
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 java.io.ByteArrayOutputStream;
|
||||
import java.text.Collator;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.TreeSet;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import de.hdodenhof.circleimageview.CircleImageView;
|
||||
|
@ -89,22 +90,28 @@ public class EditEntryActivity extends AegisActivity {
|
|||
private RelativeLayout _advancedSettingsHeader;
|
||||
private RelativeLayout _advancedSettings;
|
||||
|
||||
private VaultManager _vault;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_edit_entry);
|
||||
|
||||
_vault = getApp().getVaultManager();
|
||||
_groups = _vault.getGroups();
|
||||
|
||||
ActionBar bar = getSupportActionBar();
|
||||
bar.setHomeAsUpIndicator(R.drawable.ic_close);
|
||||
bar.setDisplayHomeAsUpEnabled(true);
|
||||
|
||||
// retrieve info from the calling activity
|
||||
Intent intent = getIntent();
|
||||
_origEntry = (VaultEntry) intent.getSerializableExtra("entry");
|
||||
_isNew = intent.getBooleanExtra("isNew", false);
|
||||
_groups = new TreeSet<>(Collator.getInstance());
|
||||
_groups.addAll(intent.getStringArrayListExtra("groups"));
|
||||
if (_isNew) {
|
||||
UUID entryUUID = (UUID) intent.getSerializableExtra("entryUUID");
|
||||
if (entryUUID != null) {
|
||||
_origEntry = _vault.getEntryByUUID(entryUUID);
|
||||
} else {
|
||||
_origEntry = (VaultEntry) intent.getSerializableExtra("newEntry");
|
||||
_isNew = true;
|
||||
setTitle(R.string.add_new_entry);
|
||||
}
|
||||
|
||||
|
@ -185,9 +192,8 @@ public class EditEntryActivity extends AegisActivity {
|
|||
_spinnerType.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
|
||||
@Override
|
||||
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
|
||||
String type = _spinnerType.getSelectedItem().toString();
|
||||
|
||||
switch (type.toLowerCase()) {
|
||||
String type = _spinnerType.getSelectedItem().toString().toLowerCase();
|
||||
switch (type) {
|
||||
case TotpInfo.ID:
|
||||
case SteamInfo.ID:
|
||||
_rowCounter.setVisibility(View.GONE);
|
||||
|
@ -251,7 +257,6 @@ public class EditEntryActivity extends AegisActivity {
|
|||
// automatically open advanced settings since 'Secret' is required.
|
||||
if (_isNew) {
|
||||
openAdvancedSettings();
|
||||
|
||||
setGroup(selectedGroup);
|
||||
}
|
||||
}
|
||||
|
@ -264,6 +269,7 @@ public class EditEntryActivity extends AegisActivity {
|
|||
int pos = _groups.contains(groupName) ? _groups.headSet(groupName).size() : -1;
|
||||
_spinnerGroup.setSelection(pos + 1, false);
|
||||
}
|
||||
|
||||
private void openAdvancedSettings() {
|
||||
Animation fadeOut = new AlphaAnimation(1, 0);
|
||||
fadeOut.setInterpolator(new AccelerateInterpolator());
|
||||
|
@ -344,7 +350,7 @@ public class EditEntryActivity extends AegisActivity {
|
|||
return;
|
||||
}
|
||||
|
||||
finish(entry.get(), false);
|
||||
addAndFinish(entry.get());
|
||||
},
|
||||
(dialog, which) -> super.onBackPressed()
|
||||
);
|
||||
|
@ -361,7 +367,7 @@ public class EditEntryActivity extends AegisActivity {
|
|||
break;
|
||||
case R.id.action_delete:
|
||||
Dialogs.showDeleteEntryDialog(this, (dialog, which) -> {
|
||||
finish(_origEntry, true);
|
||||
deleteAndFinish(_origEntry);
|
||||
});
|
||||
break;
|
||||
case R.id.action_default_icon:
|
||||
|
@ -389,12 +395,30 @@ public class EditEntryActivity extends AegisActivity {
|
|||
return true;
|
||||
}
|
||||
|
||||
private void finish(VaultEntry entry, boolean delete) {
|
||||
private void addAndFinish(VaultEntry entry) {
|
||||
if (_isNew) {
|
||||
_vault.addEntry(entry);
|
||||
} else {
|
||||
_vault.replaceEntry(entry);
|
||||
}
|
||||
|
||||
saveAndFinish(entry, false);
|
||||
}
|
||||
|
||||
private void deleteAndFinish(VaultEntry entry) {
|
||||
_vault.removeEntry(entry);
|
||||
saveAndFinish(entry, true);
|
||||
}
|
||||
|
||||
private void saveAndFinish(VaultEntry entry, boolean delete) {
|
||||
Intent intent = new Intent();
|
||||
intent.putExtra("entry", entry);
|
||||
intent.putExtra("entryUUID", entry.getUUID());
|
||||
intent.putExtra("delete", delete);
|
||||
setResult(RESULT_OK, intent);
|
||||
finish();
|
||||
|
||||
if (saveVault()) {
|
||||
setResult(RESULT_OK, intent);
|
||||
finish();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -540,7 +564,7 @@ public class EditEntryActivity extends AegisActivity {
|
|||
return false;
|
||||
}
|
||||
|
||||
finish(entry, false);
|
||||
addAndFinish(entry);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -51,17 +51,17 @@ import java.io.InputStream;
|
|||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.TreeSet;
|
||||
import java.util.UUID;
|
||||
|
||||
public class MainActivity extends AegisActivity implements EntryListView.Listener {
|
||||
// activity request codes
|
||||
private static final int CODE_SCAN = 0;
|
||||
private static final int CODE_ADD_ENTRY = 1;
|
||||
private static final int CODE_EDIT_ENTRY = 2;
|
||||
private static final int CODE_ENTER_ENTRY = 3;
|
||||
private static final int CODE_DO_INTRO = 4;
|
||||
private static final int CODE_DECRYPT = 5;
|
||||
private static final int CODE_PREFERENCES = 6;
|
||||
private static final int CODE_SCAN_IMAGE = 7;
|
||||
private static final int CODE_DO_INTRO = 3;
|
||||
private static final int CODE_DECRYPT = 4;
|
||||
private static final int CODE_PREFERENCES = 5;
|
||||
private static final int CODE_SCAN_IMAGE = 6;
|
||||
|
||||
// permission request codes
|
||||
private static final int CODE_PERM_CAMERA = 0;
|
||||
|
@ -112,7 +112,7 @@ public class MainActivity extends AegisActivity implements EntryListView.Listene
|
|||
_fabMenu = findViewById(R.id.fab);
|
||||
findViewById(R.id.fab_enter).setOnClickListener(view -> {
|
||||
_fabMenu.collapse();
|
||||
startEditProfileActivity(CODE_ENTER_ENTRY, null, true);
|
||||
startEditEntryActivity(CODE_ADD_ENTRY, null, true);
|
||||
});
|
||||
findViewById(R.id.fab_scan_image).setOnClickListener(view -> {
|
||||
_fabMenu.collapse();
|
||||
|
@ -179,9 +179,6 @@ public class MainActivity extends AegisActivity implements EntryListView.Listene
|
|||
case CODE_EDIT_ENTRY:
|
||||
onEditEntryResult(resultCode, data);
|
||||
break;
|
||||
case CODE_ENTER_ENTRY:
|
||||
onEnterEntryResult(resultCode, data);
|
||||
break;
|
||||
case CODE_DO_INTRO:
|
||||
onDoIntroResult(resultCode, data);
|
||||
break;
|
||||
|
@ -238,50 +235,42 @@ public class MainActivity extends AegisActivity implements EntryListView.Listene
|
|||
}
|
||||
}
|
||||
|
||||
private void startEditProfileActivity(int requestCode, VaultEntry entry, boolean isNew) {
|
||||
private void startEditEntryActivity(int requestCode, VaultEntry entry, boolean isNew) {
|
||||
Intent intent = new Intent(this, EditEntryActivity.class);
|
||||
intent.putExtra("entry", entry != null ? entry : VaultEntry.getDefault());
|
||||
intent.putExtra("isNew", isNew);
|
||||
if (isNew) {
|
||||
intent.putExtra("newEntry", entry != null ? entry : VaultEntry.getDefault());
|
||||
} else {
|
||||
intent.putExtra("entryUUID", entry.getUUID());
|
||||
}
|
||||
intent.putExtra("selectedGroup", _selectedGroup);
|
||||
intent.putExtra("groups", new ArrayList<>(_vault.getGroups()));
|
||||
startActivityForResult(intent, requestCode);
|
||||
}
|
||||
|
||||
private void onScanResult(int resultCode, Intent data) {
|
||||
if (resultCode == RESULT_OK) {
|
||||
VaultEntry entry = (VaultEntry) data.getSerializableExtra("entry");
|
||||
startEditProfileActivity(CODE_ADD_ENTRY, entry, true);
|
||||
startEditEntryActivity(CODE_ADD_ENTRY, entry, true);
|
||||
}
|
||||
}
|
||||
|
||||
private void onAddEntryResult(int resultCode, Intent data) {
|
||||
if (resultCode == RESULT_OK) {
|
||||
VaultEntry entry = (VaultEntry) data.getSerializableExtra("entry");
|
||||
addEntry(entry);
|
||||
saveVault();
|
||||
UUID entryUUID = (UUID) data.getSerializableExtra("entryUUID");
|
||||
VaultEntry entry = _vault.getEntryByUUID(entryUUID);
|
||||
_entryListView.addEntry(entry);
|
||||
}
|
||||
}
|
||||
|
||||
private void onEditEntryResult(int resultCode, Intent data) {
|
||||
if (resultCode == RESULT_OK) {
|
||||
VaultEntry entry = (VaultEntry) data.getSerializableExtra("entry");
|
||||
if (data.getBooleanExtra("delete", false)) {
|
||||
deleteEntry(entry);
|
||||
} else {
|
||||
// this profile has been serialized/deserialized and is no longer the same instance it once was
|
||||
// to deal with this, the replaceEntry functions are used
|
||||
VaultEntry oldEntry = _vault.replaceEntry(entry);
|
||||
_entryListView.replaceEntry(oldEntry, entry);
|
||||
saveVault();
|
||||
}
|
||||
}
|
||||
}
|
||||
UUID entryUUID = (UUID) data.getSerializableExtra("entryUUID");
|
||||
|
||||
private void onEnterEntryResult(int resultCode, Intent data) {
|
||||
if (resultCode == RESULT_OK) {
|
||||
VaultEntry entry = (VaultEntry) data.getSerializableExtra("entry");
|
||||
addEntry(entry);
|
||||
saveVault();
|
||||
if (data.getBooleanExtra("delete", false)) {
|
||||
_entryListView.removeEntry(entryUUID);
|
||||
} else {
|
||||
VaultEntry entry = _vault.getEntryByUUID(entryUUID);
|
||||
_entryListView.replaceEntry(entryUUID, entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -309,7 +298,7 @@ public class MainActivity extends AegisActivity implements EntryListView.Listene
|
|||
GoogleAuthInfo info = GoogleAuthInfo.parseUri(result.getText());
|
||||
VaultEntry entry = new VaultEntry(info);
|
||||
|
||||
startEditProfileActivity(CODE_ADD_ENTRY, entry, true);
|
||||
startEditEntryActivity(CODE_ADD_ENTRY, entry, true);
|
||||
} catch (NotFoundException | IOException | ChecksumException | FormatException | GoogleAuthInfoException e) {
|
||||
Toast.makeText(this, getString(R.string.unable_to_read_qrcode), Toast.LENGTH_SHORT).show();
|
||||
e.printStackTrace();
|
||||
|
@ -359,11 +348,6 @@ public class MainActivity extends AegisActivity implements EntryListView.Listene
|
|||
_entryListView.setGroupFilter(group, true);
|
||||
}
|
||||
|
||||
private void addEntry(VaultEntry entry) {
|
||||
_vault.addEntry(entry);
|
||||
_entryListView.addEntry(entry);
|
||||
}
|
||||
|
||||
private void onDoIntroResult(int resultCode, Intent data) {
|
||||
if (resultCode == IntroActivity.RESULT_EXCEPTION) {
|
||||
// TODO: user feedback
|
||||
|
@ -442,10 +426,9 @@ public class MainActivity extends AegisActivity implements EntryListView.Listene
|
|||
|
||||
if (info != null) {
|
||||
VaultEntry entry = new VaultEntry(info);
|
||||
startEditProfileActivity(CODE_ADD_ENTRY, entry, true);
|
||||
startEditEntryActivity(CODE_ADD_ENTRY, entry, true);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -511,13 +494,6 @@ public class MainActivity extends AegisActivity implements EntryListView.Listene
|
|||
saveVault();
|
||||
}
|
||||
|
||||
private void deleteEntry(VaultEntry entry) {
|
||||
VaultEntry oldEntry = _vault.removeEntry(entry);
|
||||
saveVault();
|
||||
|
||||
_entryListView.removeEntry(oldEntry);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
_menu = menu;
|
||||
|
@ -662,14 +638,6 @@ public class MainActivity extends AegisActivity implements EntryListView.Listene
|
|||
startActivityForResult(intent, CODE_DECRYPT);
|
||||
}
|
||||
|
||||
private void saveVault() {
|
||||
try {
|
||||
_vault.save();
|
||||
} catch (VaultManagerException e) {
|
||||
Toast.makeText(this, getString(R.string.saving_error), Toast.LENGTH_LONG).show();
|
||||
}
|
||||
}
|
||||
|
||||
private void updateLockIcon() {
|
||||
// hide the lock icon if the vault is not unlocked
|
||||
if (_menu != null && !_vault.isLocked()) {
|
||||
|
@ -784,7 +752,7 @@ public class MainActivity extends AegisActivity implements EntryListView.Listene
|
|||
return true;
|
||||
|
||||
case R.id.action_edit:
|
||||
startEditProfileActivity(CODE_EDIT_ENTRY, _selectedEntries.get(0), false);
|
||||
startEditEntryActivity(CODE_EDIT_ENTRY, _selectedEntries.get(0), false);
|
||||
mode.finish();
|
||||
return true;
|
||||
|
||||
|
|
|
@ -10,12 +10,12 @@ import androidx.recyclerview.widget.RecyclerView;
|
|||
import com.beemdevelopment.aegis.R;
|
||||
import com.beemdevelopment.aegis.SortCategory;
|
||||
import com.beemdevelopment.aegis.ViewMode;
|
||||
import com.beemdevelopment.aegis.vault.VaultEntry;
|
||||
import com.beemdevelopment.aegis.helpers.ItemTouchHelperAdapter;
|
||||
import com.beemdevelopment.aegis.otp.HotpInfo;
|
||||
import com.beemdevelopment.aegis.otp.OtpInfo;
|
||||
import com.beemdevelopment.aegis.otp.OtpInfoException;
|
||||
import com.beemdevelopment.aegis.otp.TotpInfo;
|
||||
import com.beemdevelopment.aegis.vault.VaultEntry;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
|
@ -23,6 +23,7 @@ import java.util.Comparator;
|
|||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
public class EntryAdapter extends RecyclerView.Adapter<EntryHolder> implements ItemTouchHelperAdapter {
|
||||
private EntryListView _view;
|
||||
|
@ -144,6 +145,11 @@ public class EntryAdapter extends RecyclerView.Adapter<EntryHolder> implements I
|
|||
checkPeriodUniformity();
|
||||
}
|
||||
|
||||
public void removeEntry(UUID uuid) {
|
||||
VaultEntry entry = getEntryByUUID(uuid);
|
||||
removeEntry(entry);
|
||||
}
|
||||
|
||||
public void clearEntries() {
|
||||
_entries.clear();
|
||||
_shownEntries.clear();
|
||||
|
@ -151,7 +157,8 @@ public class EntryAdapter extends RecyclerView.Adapter<EntryHolder> implements I
|
|||
checkPeriodUniformity();
|
||||
}
|
||||
|
||||
public void replaceEntry(VaultEntry oldEntry, VaultEntry newEntry) {
|
||||
public void replaceEntry(UUID uuid, VaultEntry newEntry) {
|
||||
VaultEntry oldEntry = getEntryByUUID(uuid);
|
||||
_entries.set(_entries.indexOf(oldEntry), newEntry);
|
||||
|
||||
if (_shownEntries.contains(oldEntry)) {
|
||||
|
@ -174,6 +181,16 @@ public class EntryAdapter extends RecyclerView.Adapter<EntryHolder> implements I
|
|||
checkPeriodUniformity();
|
||||
}
|
||||
|
||||
private VaultEntry getEntryByUUID(UUID uuid) {
|
||||
for (VaultEntry entry : _entries) {
|
||||
if (entry.getUUID().equals(uuid)) {
|
||||
return entry;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private boolean isEntryFiltered(VaultEntry entry) {
|
||||
String group = entry.getGroup();
|
||||
String issuer = entry.getIssuer().toLowerCase();
|
||||
|
|
|
@ -22,10 +22,10 @@ import androidx.recyclerview.widget.RecyclerView;
|
|||
import com.beemdevelopment.aegis.R;
|
||||
import com.beemdevelopment.aegis.SortCategory;
|
||||
import com.beemdevelopment.aegis.ViewMode;
|
||||
import com.beemdevelopment.aegis.vault.VaultEntry;
|
||||
import com.beemdevelopment.aegis.helpers.SimpleItemTouchHelperCallback;
|
||||
import com.beemdevelopment.aegis.helpers.UiRefresher;
|
||||
import com.beemdevelopment.aegis.otp.TotpInfo;
|
||||
import com.beemdevelopment.aegis.vault.VaultEntry;
|
||||
import com.bumptech.glide.Glide;
|
||||
import com.bumptech.glide.ListPreloader;
|
||||
import com.bumptech.glide.RequestBuilder;
|
||||
|
@ -35,6 +35,7 @@ import com.bumptech.glide.util.ViewPreloadSizeProvider;
|
|||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
public class EntryListView extends Fragment implements EntryAdapter.Listener {
|
||||
private EntryAdapter _adapter;
|
||||
|
@ -262,12 +263,17 @@ public class EntryListView extends Fragment implements EntryAdapter.Listener {
|
|||
updateEmptyState();
|
||||
}
|
||||
|
||||
public void removeEntry(UUID uuid) {
|
||||
_adapter.removeEntry(uuid);
|
||||
updateEmptyState();
|
||||
}
|
||||
|
||||
public void clearEntries() {
|
||||
_adapter.clearEntries();
|
||||
}
|
||||
|
||||
public void replaceEntry(VaultEntry oldEntry, VaultEntry newEntry) {
|
||||
_adapter.replaceEntry(oldEntry, newEntry);
|
||||
public void replaceEntry(UUID uuid, VaultEntry newEntry) {
|
||||
_adapter.replaceEntry(uuid, newEntry);
|
||||
}
|
||||
|
||||
public void runEntriesAnimation() {
|
||||
|
|
|
@ -17,6 +17,7 @@ import java.io.OutputStream;
|
|||
import java.text.Collator;
|
||||
import java.util.Collection;
|
||||
import java.util.TreeSet;
|
||||
import java.util.UUID;
|
||||
|
||||
public class VaultManager {
|
||||
public static final String FILENAME = "aegis.json";
|
||||
|
@ -144,6 +145,11 @@ public class VaultManager {
|
|||
_vault.getEntries().add(entry);
|
||||
}
|
||||
|
||||
public VaultEntry getEntryByUUID(UUID uuid) {
|
||||
assertState(false, true);
|
||||
return _vault.getEntries().getByUUID(uuid);
|
||||
}
|
||||
|
||||
public VaultEntry removeEntry(VaultEntry entry) {
|
||||
assertState(false, true);
|
||||
return _vault.getEntries().remove(entry);
|
||||
|
|
Loading…
Add table
Reference in a new issue