mirror of
https://github.com/beemdevelopment/Aegis.git
synced 2025-04-23 07:19:13 +00:00
Merge 0d5ba3c0ab
into 337cb74f72
This commit is contained in:
commit
0ad392709d
10 changed files with 164 additions and 20 deletions
|
@ -142,10 +142,20 @@ public class OverallTest extends AegisTest {
|
||||||
onView(withId(R.id.action_share_qr)).perform(click());
|
onView(withId(R.id.action_share_qr)).perform(click());
|
||||||
onView(withId(R.id.btnNext)).perform(click()).perform(click()).perform(click());
|
onView(withId(R.id.btnNext)).perform(click()).perform(click()).perform(click());
|
||||||
|
|
||||||
onView(withId(R.id.rvKeyProfiles)).perform(RecyclerViewActions.actionOnItemAtPosition(entryPosOffset + 0, longClick()));
|
onView(withId(R.id.rvKeyProfiles)).perform(RecyclerViewActions.actionOnItemAtPosition(entryPosOffset, longClick()));
|
||||||
|
onView(withId(R.id.rvKeyProfiles)).perform(RecyclerViewActions.actionOnItemAtPosition(entryPosOffset + 1, click()));
|
||||||
onView(allOf(isDescendantOfA(withClassName(containsString("ActionBarContextView"))), withClassName(containsString("OverflowMenuButton")))).perform(click());
|
onView(allOf(isDescendantOfA(withClassName(containsString("ActionBarContextView"))), withClassName(containsString("OverflowMenuButton")))).perform(click());
|
||||||
onView(withText(R.string.action_delete)).perform(click());
|
onView(withText(R.string.action_delete)).perform(click());
|
||||||
onView(withId(android.R.id.button1)).perform(click());
|
onView(withId(android.R.id.button1)).perform(click());
|
||||||
|
onView(withText(R.string.archive)).perform(click());
|
||||||
|
onView(withId(R.id.rvKeyProfiles)).perform(RecyclerViewActions.actionOnItemAtPosition(entryPosOffset, longClick()));
|
||||||
|
onView(allOf(isDescendantOfA(withClassName(containsString("ActionBarContextView"))), withClassName(containsString("OverflowMenuButton")))).perform(click());
|
||||||
|
onView(withText(R.string.action_delete)).perform(click());
|
||||||
|
onView(withId(android.R.id.button1)).perform(click());
|
||||||
|
onView(withId(R.id.rvKeyProfiles)).perform(RecyclerViewActions.actionOnItemAtPosition(entryPosOffset, longClick()));
|
||||||
|
onView(allOf(isDescendantOfA(withClassName(containsString("ActionBarContextView"))), withClassName(containsString("OverflowMenuButton")))).perform(click());
|
||||||
|
onView(withText(R.string.action_restore)).perform(click());
|
||||||
|
onView(withText(R.string.archive)).perform(click());
|
||||||
|
|
||||||
openContextualActionModeOverflowMenu();
|
openContextualActionModeOverflowMenu();
|
||||||
onView(withText(R.string.lock)).perform(click());
|
onView(withText(R.string.lock)).perform(click());
|
||||||
|
|
|
@ -96,6 +96,7 @@ public class MainActivity extends AegisActivity implements EntryListView.Listene
|
||||||
private boolean _isDPadPressed;
|
private boolean _isDPadPressed;
|
||||||
private boolean _isDoingIntro;
|
private boolean _isDoingIntro;
|
||||||
private boolean _isAuthenticating;
|
private boolean _isAuthenticating;
|
||||||
|
private boolean _isArchiveEnabled;
|
||||||
|
|
||||||
private String _submittedSearchQuery;
|
private String _submittedSearchQuery;
|
||||||
private String _pendingSearchQuery;
|
private String _pendingSearchQuery;
|
||||||
|
@ -187,6 +188,7 @@ public class MainActivity extends AegisActivity implements EntryListView.Listene
|
||||||
_isDPadPressed = false;
|
_isDPadPressed = false;
|
||||||
_isDoingIntro = false;
|
_isDoingIntro = false;
|
||||||
_isAuthenticating = false;
|
_isAuthenticating = false;
|
||||||
|
_isArchiveEnabled = false;
|
||||||
if (savedInstanceState != null) {
|
if (savedInstanceState != null) {
|
||||||
_isRecreated = true;
|
_isRecreated = true;
|
||||||
_pendingSearchQuery = savedInstanceState.getString("pendingSearchQuery");
|
_pendingSearchQuery = savedInstanceState.getString("pendingSearchQuery");
|
||||||
|
@ -249,7 +251,6 @@ public class MainActivity extends AegisActivity implements EntryListView.Listene
|
||||||
|
|
||||||
public void setGroups(Collection<VaultGroup> groups) {
|
public void setGroups(Collection<VaultGroup> groups) {
|
||||||
_groups = groups;
|
_groups = groups;
|
||||||
_groupChip.setVisibility(_groups.isEmpty() ? View.GONE : View.VISIBLE);
|
|
||||||
|
|
||||||
if (_prefGroupFilter != null) {
|
if (_prefGroupFilter != null) {
|
||||||
Set<UUID> groupFilter = cleanGroupFilter(_prefGroupFilter);
|
Set<UUID> groupFilter = cleanGroupFilter(_prefGroupFilter);
|
||||||
|
@ -273,14 +274,18 @@ public class MainActivity extends AegisActivity implements EntryListView.Listene
|
||||||
private void initializeGroups() {
|
private void initializeGroups() {
|
||||||
_groupChip.removeAllViews();
|
_groupChip.removeAllViews();
|
||||||
|
|
||||||
|
addArchiveChip(_groupChip);
|
||||||
|
|
||||||
for (VaultGroup group : _groups) {
|
for (VaultGroup group : _groups) {
|
||||||
addChipTo(_groupChip, new VaultGroupModel(group));
|
addChipTo(_groupChip, new VaultGroupModel(group));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!_groups.isEmpty()) {
|
||||||
GroupPlaceholderType placeholderType = GroupPlaceholderType.NO_GROUP;
|
GroupPlaceholderType placeholderType = GroupPlaceholderType.NO_GROUP;
|
||||||
addChipTo(_groupChip, new VaultGroupModel(this, placeholderType));
|
addChipTo(_groupChip, new VaultGroupModel(this, placeholderType));
|
||||||
addSaveChip(_groupChip);
|
addSaveChip(_groupChip);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private Set<UUID> cleanGroupFilter(Set<UUID> groupFilter) {
|
private Set<UUID> cleanGroupFilter(Set<UUID> groupFilter) {
|
||||||
Set<UUID> groupUuids = _groups.stream().map(UUIDMap.Value::getUUID).collect(Collectors.toSet());
|
Set<UUID> groupUuids = _groups.stream().map(UUIDMap.Value::getUUID).collect(Collectors.toSet());
|
||||||
|
@ -290,6 +295,21 @@ public class MainActivity extends AegisActivity implements EntryListView.Listene
|
||||||
.collect(Collectors.toSet());
|
.collect(Collectors.toSet());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void addArchiveChip(ChipGroup chipGroup) {
|
||||||
|
Chip chip = (Chip) getLayoutInflater().inflate(R.layout.chip_group_filter, null, false);
|
||||||
|
chip.setText(getString(R.string.archive));
|
||||||
|
chip.setCheckedIconVisible(false);
|
||||||
|
chip.setOnCheckedChangeListener((button, isChecked) -> {
|
||||||
|
_isArchiveEnabled = isChecked;
|
||||||
|
if (_actionMode != null) {
|
||||||
|
_actionMode.finish();
|
||||||
|
}
|
||||||
|
chip.setChecked(isChecked);
|
||||||
|
_entryListView.enableArchive(isChecked);
|
||||||
|
});
|
||||||
|
chipGroup.addView(chip);
|
||||||
|
}
|
||||||
|
|
||||||
private void addChipTo(ChipGroup chipGroup, VaultGroupModel group) {
|
private void addChipTo(ChipGroup chipGroup, VaultGroupModel group) {
|
||||||
Chip chip = (Chip) getLayoutInflater().inflate(R.layout.chip_group_filter, null, false);
|
Chip chip = (Chip) getLayoutInflater().inflate(R.layout.chip_group_filter, null, false);
|
||||||
chip.setText(group.getName());
|
chip.setText(group.getName());
|
||||||
|
@ -1149,6 +1169,7 @@ public class MainActivity extends AegisActivity implements EntryListView.Listene
|
||||||
} else {
|
} else {
|
||||||
setFavoriteMenuItemVisiblity();
|
setFavoriteMenuItemVisiblity();
|
||||||
setIsMultipleSelected(_selectedEntries.size() > 1);
|
setIsMultipleSelected(_selectedEntries.size() > 1);
|
||||||
|
setRestoreMenuItemVisibility();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1191,6 +1212,11 @@ public class MainActivity extends AegisActivity implements EntryListView.Listene
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void setRestoreMenuItemVisibility() {
|
||||||
|
MenuItem restoreMenuItem = _actionMode.getMenu().findItem(R.id.action_restore);
|
||||||
|
restoreMenuItem.setVisible(_isArchiveEnabled);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onLongEntryClick(VaultEntry entry) {
|
public void onLongEntryClick(VaultEntry entry) {
|
||||||
if (!_selectedEntries.isEmpty()) {
|
if (!_selectedEntries.isEmpty()) {
|
||||||
|
@ -1207,6 +1233,7 @@ public class MainActivity extends AegisActivity implements EntryListView.Listene
|
||||||
_actionModeBackPressHandler.setEnabled(true);
|
_actionModeBackPressHandler.setEnabled(true);
|
||||||
setFavoriteMenuItemVisiblity();
|
setFavoriteMenuItemVisiblity();
|
||||||
setAssignIconsMenuItemVisibility();
|
setAssignIconsMenuItemVisibility();
|
||||||
|
setRestoreMenuItemVisibility();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -1294,6 +1321,40 @@ public class MainActivity extends AegisActivity implements EntryListView.Listene
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void onActionRestore(ActionMode mode) {
|
||||||
|
for (VaultEntry entry : _selectedEntries) {
|
||||||
|
entry.setIsArchived(false);
|
||||||
|
}
|
||||||
|
saveAndBackupVault();
|
||||||
|
_entryListView.setGroups(_vaultManager.getVault().getUsedGroups());
|
||||||
|
_entryListView.setEntries(_vaultManager.getVault().getEntries());
|
||||||
|
mode.finish();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onActionDelete(ActionMode mode) {
|
||||||
|
if (_isArchiveEnabled) {
|
||||||
|
Dialogs.showDeleteEntriesDialog(MainActivity.this, _selectedEntries, (d, which) -> {
|
||||||
|
for (VaultEntry entry : _selectedEntries) {
|
||||||
|
_vaultManager.getVault().removeEntry(entry);
|
||||||
|
}
|
||||||
|
saveAndBackupVault();
|
||||||
|
_entryListView.setGroups(_vaultManager.getVault().getUsedGroups());
|
||||||
|
_entryListView.setEntries(_vaultManager.getVault().getEntries());
|
||||||
|
mode.finish();
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
Dialogs.showArchiveEntriesDialog(MainActivity.this, _selectedEntries.size(), (dialog, which) -> {
|
||||||
|
for (VaultEntry entry : _selectedEntries) {
|
||||||
|
entry.setIsArchived(true);
|
||||||
|
}
|
||||||
|
saveAndBackupVault();
|
||||||
|
_entryListView.setGroups(_vaultManager.getVault().getUsedGroups());
|
||||||
|
_entryListView.setEntries(_vaultManager.getVault().getEntries());
|
||||||
|
mode.finish();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private class SearchViewBackPressHandler extends OnBackPressedCallback {
|
private class SearchViewBackPressHandler extends OnBackPressedCallback {
|
||||||
public SearchViewBackPressHandler() {
|
public SearchViewBackPressHandler() {
|
||||||
super(false);
|
super(false);
|
||||||
|
@ -1390,16 +1451,10 @@ public class MainActivity extends AegisActivity implements EntryListView.Listene
|
||||||
startActivity(intent);
|
startActivity(intent);
|
||||||
|
|
||||||
mode.finish();
|
mode.finish();
|
||||||
|
} else if (itemId == R.id.action_restore) {
|
||||||
|
onActionRestore(mode);
|
||||||
} else if (itemId == R.id.action_delete) {
|
} else if (itemId == R.id.action_delete) {
|
||||||
Dialogs.showDeleteEntriesDialog(MainActivity.this, _selectedEntries, (d, which) -> {
|
onActionDelete(mode);
|
||||||
for (VaultEntry entry : _selectedEntries) {
|
|
||||||
_vaultManager.getVault().removeEntry(entry);
|
|
||||||
}
|
|
||||||
saveAndBackupVault();
|
|
||||||
_entryListView.setGroups(_vaultManager.getVault().getUsedGroups());
|
|
||||||
_entryListView.setEntries(_vaultManager.getVault().getEntries());
|
|
||||||
mode.finish();
|
|
||||||
});
|
|
||||||
} else if (itemId == R.id.action_select_all) {
|
} else if (itemId == R.id.action_select_all) {
|
||||||
_selectedEntries = _entryListView.selectAllEntries();
|
_selectedEntries = _entryListView.selectAllEntries();
|
||||||
setFavoriteMenuItemVisiblity();
|
setFavoriteMenuItemVisiblity();
|
||||||
|
|
|
@ -96,6 +96,19 @@ public class Dialogs {
|
||||||
.create());
|
.create());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void showArchiveEntriesDialog(Context context, int count, DialogInterface.OnClickListener onArchive) {
|
||||||
|
String title = context.getResources().getQuantityString(R.plurals.archive_entry, count);
|
||||||
|
String message = context.getResources().getQuantityString(R.plurals.archive_entry_description, count);
|
||||||
|
Dialog dialog = new MaterialAlertDialogBuilder(context, R.style.ThemeOverlay_Aegis_AlertDialog_Warning)
|
||||||
|
.setTitle(title)
|
||||||
|
.setMessage(message)
|
||||||
|
.setIconAttribute(android.R.attr.alertDialogIcon)
|
||||||
|
.setPositiveButton(android.R.string.ok, onArchive)
|
||||||
|
.setNegativeButton(android.R.string.no, null)
|
||||||
|
.create();
|
||||||
|
showSecureDialog(dialog);
|
||||||
|
}
|
||||||
|
|
||||||
private static String getVaultEntryName(Context context, VaultEntry entry) {
|
private static String getVaultEntryName(Context context, VaultEntry entry) {
|
||||||
if (!entry.getIssuer().isEmpty() && !entry.getName().isEmpty()) {
|
if (!entry.getIssuer().isEmpty() && !entry.getName().isEmpty()) {
|
||||||
return String.format("%s (%s)", entry.getIssuer(), entry.getName());
|
return String.format("%s (%s)", entry.getIssuer(), entry.getName());
|
||||||
|
|
|
@ -79,6 +79,7 @@ public class EntryAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
|
||||||
private Handler _dimHandler;
|
private Handler _dimHandler;
|
||||||
private Handler _doubleTapHandler;
|
private Handler _doubleTapHandler;
|
||||||
private boolean _pauseFocused;
|
private boolean _pauseFocused;
|
||||||
|
private boolean _isArchiveEnabled;
|
||||||
|
|
||||||
// keeps track of the EntryHolders that are currently bound
|
// keeps track of the EntryHolders that are currently bound
|
||||||
private List<EntryHolder> _holders;
|
private List<EntryHolder> _holders;
|
||||||
|
@ -196,7 +197,13 @@ public class EntryAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
|
||||||
String name = entry.getName().toLowerCase();
|
String name = entry.getName().toLowerCase();
|
||||||
String note = entry.getNote().toLowerCase();
|
String note = entry.getNote().toLowerCase();
|
||||||
|
|
||||||
if (!_groupFilter.isEmpty()) {
|
if (!_isArchiveEnabled && entry.isArchived()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_isArchiveEnabled && !entry.isArchived()) {
|
||||||
|
return true;
|
||||||
|
} else if (!_groupFilter.isEmpty()) {
|
||||||
if (groups.isEmpty() && !_groupFilter.contains(null)) {
|
if (groups.isEmpty() && !_groupFilter.contains(null)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -774,6 +781,11 @@ public class EntryAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
|
||||||
return _entryList.isErrorCardShown();
|
return _entryList.isErrorCardShown();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void enableArchive(boolean enable) {
|
||||||
|
_isArchiveEnabled = enable;
|
||||||
|
refreshEntryList();
|
||||||
|
}
|
||||||
|
|
||||||
private class FooterView extends RecyclerView.ViewHolder {
|
private class FooterView extends RecyclerView.ViewHolder {
|
||||||
View _footerView;
|
View _footerView;
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,7 @@ import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.view.animation.LayoutAnimationController;
|
import android.view.animation.LayoutAnimationController;
|
||||||
import android.widget.LinearLayout;
|
import android.widget.LinearLayout;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
import androidx.annotation.AttrRes;
|
import androidx.annotation.AttrRes;
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
@ -72,6 +73,8 @@ public class EntryListView extends Fragment implements EntryAdapter.Listener {
|
||||||
private boolean _showExpirationState;
|
private boolean _showExpirationState;
|
||||||
private ViewMode _viewMode;
|
private ViewMode _viewMode;
|
||||||
private LinearLayout _emptyStateView;
|
private LinearLayout _emptyStateView;
|
||||||
|
private boolean _isArchiveEnabled;
|
||||||
|
private TextView _archiveEmptyText;
|
||||||
|
|
||||||
private UiRefresher _refresher;
|
private UiRefresher _refresher;
|
||||||
|
|
||||||
|
@ -150,6 +153,7 @@ public class EntryListView extends Fragment implements EntryAdapter.Listener {
|
||||||
});
|
});
|
||||||
|
|
||||||
_emptyStateView = view.findViewById(R.id.vEmptyList);
|
_emptyStateView = view.findViewById(R.id.vEmptyList);
|
||||||
|
_archiveEmptyText = view.findViewById(R.id.archive_empty_text);
|
||||||
return view;
|
return view;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -471,6 +475,12 @@ public class EntryListView extends Fragment implements EntryAdapter.Listener {
|
||||||
_recyclerView.scheduleLayoutAnimation();
|
_recyclerView.scheduleLayoutAnimation();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void enableArchive(boolean enable) {
|
||||||
|
_isArchiveEnabled = enable;
|
||||||
|
_adapter.enableArchive(enable);
|
||||||
|
updateEmptyState();
|
||||||
|
}
|
||||||
|
|
||||||
private void setShowProgress(boolean showProgress) {
|
private void setShowProgress(boolean showProgress) {
|
||||||
_showProgress = showProgress;
|
_showProgress = showProgress;
|
||||||
updateDividerDecoration();
|
updateDividerDecoration();
|
||||||
|
@ -495,9 +505,12 @@ public class EntryListView extends Fragment implements EntryAdapter.Listener {
|
||||||
if (_adapter.getShownEntriesCount() > 0) {
|
if (_adapter.getShownEntriesCount() > 0) {
|
||||||
_recyclerView.setVisibility(View.VISIBLE);
|
_recyclerView.setVisibility(View.VISIBLE);
|
||||||
_emptyStateView.setVisibility(View.GONE);
|
_emptyStateView.setVisibility(View.GONE);
|
||||||
} else {
|
_archiveEmptyText.setVisibility(View.GONE);
|
||||||
if (Strings.isNullOrEmpty(_adapter.getSearchFilter())) {
|
} else if (Strings.isNullOrEmpty(_adapter.getSearchFilter())) {
|
||||||
_recyclerView.setVisibility(View.GONE);
|
_recyclerView.setVisibility(View.GONE);
|
||||||
|
if (_isArchiveEnabled) {
|
||||||
|
_archiveEmptyText.setVisibility(View.VISIBLE);
|
||||||
|
} else {
|
||||||
_emptyStateView.setVisibility(View.VISIBLE);
|
_emptyStateView.setVisibility(View.VISIBLE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,6 +27,7 @@ public class VaultEntry extends UUIDMap.Value {
|
||||||
private String _note = "";
|
private String _note = "";
|
||||||
private String _oldGroup;
|
private String _oldGroup;
|
||||||
private Set<UUID> _groups = new TreeSet<>();
|
private Set<UUID> _groups = new TreeSet<>();
|
||||||
|
private boolean _isArchived;
|
||||||
|
|
||||||
private VaultEntry(UUID uuid, OtpInfo info) {
|
private VaultEntry(UUID uuid, OtpInfo info) {
|
||||||
super(uuid);
|
super(uuid);
|
||||||
|
@ -66,6 +67,7 @@ public class VaultEntry extends UUIDMap.Value {
|
||||||
groupUuids.put(uuid.toString());
|
groupUuids.put(uuid.toString());
|
||||||
}
|
}
|
||||||
obj.put("groups", groupUuids);
|
obj.put("groups", groupUuids);
|
||||||
|
obj.put("archived", _isArchived);
|
||||||
|
|
||||||
} catch (JSONException e) {
|
} catch (JSONException e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
|
@ -90,6 +92,7 @@ public class VaultEntry extends UUIDMap.Value {
|
||||||
entry.setIssuer(obj.getString("issuer"));
|
entry.setIssuer(obj.getString("issuer"));
|
||||||
entry.setNote(obj.optString("note", ""));
|
entry.setNote(obj.optString("note", ""));
|
||||||
entry.setIsFavorite(obj.optBoolean("favorite", false));
|
entry.setIsFavorite(obj.optBoolean("favorite", false));
|
||||||
|
entry.setIsArchived(obj.optBoolean("archived", false));
|
||||||
|
|
||||||
// If the entry contains a list of group UUID's, assume conversion from the
|
// If the entry contains a list of group UUID's, assume conversion from the
|
||||||
// old group system has already taken place and ignore the old group field.
|
// old group system has already taken place and ignore the old group field.
|
||||||
|
@ -148,6 +151,10 @@ public class VaultEntry extends UUIDMap.Value {
|
||||||
return _isFavorite;
|
return _isFavorite;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isArchived() {
|
||||||
|
return _isArchived;
|
||||||
|
}
|
||||||
|
|
||||||
public void setName(String name) {
|
public void setName(String name) {
|
||||||
_name = name;
|
_name = name;
|
||||||
}
|
}
|
||||||
|
@ -200,6 +207,10 @@ public class VaultEntry extends UUIDMap.Value {
|
||||||
_isFavorite = isFavorite;
|
_isFavorite = isFavorite;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setIsArchived(boolean isArchived) {
|
||||||
|
_isArchived = isArchived;
|
||||||
|
}
|
||||||
|
|
||||||
void setOldGroup(String oldGroup) {
|
void setOldGroup(String oldGroup) {
|
||||||
_oldGroup = oldGroup;
|
_oldGroup = oldGroup;
|
||||||
}
|
}
|
||||||
|
@ -230,7 +241,8 @@ public class VaultEntry extends UUIDMap.Value {
|
||||||
&& Objects.equals(getIcon(), entry.getIcon())
|
&& Objects.equals(getIcon(), entry.getIcon())
|
||||||
&& getNote().equals(entry.getNote())
|
&& getNote().equals(entry.getNote())
|
||||||
&& isFavorite() == entry.isFavorite()
|
&& isFavorite() == entry.isFavorite()
|
||||||
&& getGroups().equals(entry.getGroups());
|
&& getGroups().equals(entry.getGroups())
|
||||||
|
&& isArchived() == entry.isArchived();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -321,8 +321,10 @@ public class VaultRepository {
|
||||||
public Collection<VaultGroup> getUsedGroups() {
|
public Collection<VaultGroup> getUsedGroups() {
|
||||||
Set<UUID> usedGroups = new HashSet<>();
|
Set<UUID> usedGroups = new HashSet<>();
|
||||||
for (VaultEntry entry : getEntries()) {
|
for (VaultEntry entry : getEntries()) {
|
||||||
|
if (!entry.isArchived()) {
|
||||||
usedGroups.addAll(entry.getGroups());
|
usedGroups.addAll(entry.getGroups());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return getGroups().stream()
|
return getGroups().stream()
|
||||||
.filter(vg -> usedGroups.contains(vg.getUUID()))
|
.filter(vg -> usedGroups.contains(vg.getUUID()))
|
||||||
|
|
|
@ -63,4 +63,13 @@
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/archive_empty_text"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:text="@string/archive_empty"
|
||||||
|
android:gravity="center"
|
||||||
|
android:visibility="gone" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
|
@ -46,6 +46,13 @@
|
||||||
android:icon="@drawable/ic_outline_qr_code_2_24"
|
android:icon="@drawable/ic_outline_qr_code_2_24"
|
||||||
app:showAsAction="always"/>
|
app:showAsAction="always"/>
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_restore"
|
||||||
|
android:title="@string/action_restore"
|
||||||
|
android:orderInCategory="120"
|
||||||
|
android:icon="@drawable/ic_outline_refresh_24"
|
||||||
|
app:showAsAction="ifRoom"/>
|
||||||
|
|
||||||
<item
|
<item
|
||||||
android:id="@+id/action_delete"
|
android:id="@+id/action_delete"
|
||||||
android:title="@string/action_delete"
|
android:title="@string/action_delete"
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
<string name="action_settings">Settings</string>
|
<string name="action_settings">Settings</string>
|
||||||
<string name="action_about">About</string>
|
<string name="action_about">About</string>
|
||||||
<string name="action_delete">Delete</string>
|
<string name="action_delete">Delete</string>
|
||||||
|
<string name="action_restore">Restore</string>
|
||||||
<string name="action_transfer">Transfer</string>
|
<string name="action_transfer">Transfer</string>
|
||||||
<string name="action_edit_icon">Edit icon</string>
|
<string name="action_edit_icon">Edit icon</string>
|
||||||
<string name="action_reset_usage_count">Reset usage count</string>
|
<string name="action_reset_usage_count">Reset usage count</string>
|
||||||
|
@ -253,6 +254,14 @@
|
||||||
<item quantity="one">Are you sure you want to delete %d entry?</item>
|
<item quantity="one">Are you sure you want to delete %d entry?</item>
|
||||||
<item quantity="other">Are you sure you want to delete %d entries?</item>
|
<item quantity="other">Are you sure you want to delete %d entries?</item>
|
||||||
</plurals>
|
</plurals>
|
||||||
|
<plurals name="archive_entry">
|
||||||
|
<item quantity="one">Archive entry</item>
|
||||||
|
<item quantity="other">Archive entries</item>
|
||||||
|
</plurals>
|
||||||
|
<plurals name="archive_entry_description">
|
||||||
|
<item quantity="one">Are you sure you want to archive this entry?</item>
|
||||||
|
<item quantity="other">Are you sure you want to archive these entries?</item>
|
||||||
|
</plurals>
|
||||||
<string name="discard_changes">Discard changes?</string>
|
<string name="discard_changes">Discard changes?</string>
|
||||||
<string name="discard_changes_description">Your changes have not been saved</string>
|
<string name="discard_changes_description">Your changes have not been saved</string>
|
||||||
<string name="saving_profile_error">Error saving profile</string>
|
<string name="saving_profile_error">Error saving profile</string>
|
||||||
|
@ -476,6 +485,7 @@
|
||||||
|
|
||||||
<string name="empty_list">There are no codes to be shown. Start adding entries by tapping the plus sign in the bottom right corner</string>
|
<string name="empty_list">There are no codes to be shown. Start adding entries by tapping the plus sign in the bottom right corner</string>
|
||||||
<string name="empty_list_title">No entries found</string>
|
<string name="empty_list_title">No entries found</string>
|
||||||
|
<string name="archive_empty">Archive is empty</string>
|
||||||
<string name="empty_group_list">There are no groups to be shown. Add groups in the edit screen of an entry</string>
|
<string name="empty_group_list">There are no groups to be shown. Add groups in the edit screen of an entry</string>
|
||||||
<string name="empty_group_list_title">No groups found</string>
|
<string name="empty_group_list_title">No groups found</string>
|
||||||
<string name="no_icon_packs">No icon packs have been imported yet. Tap the plus sign to import one. Tip: try <a href="https://aegis-icons.github.io">aegis-icons</a>.</string>
|
<string name="no_icon_packs">No icon packs have been imported yet. Tap the plus sign to import one. Tip: try <a href="https://aegis-icons.github.io">aegis-icons</a>.</string>
|
||||||
|
@ -554,6 +564,7 @@
|
||||||
|
|
||||||
<string name="importer_help_direct">Import entries directly from %s. This requires the app to be installed on this device and for root access to be granted to Aegis.</string>
|
<string name="importer_help_direct">Import entries directly from %s. This requires the app to be installed on this device and for root access to be granted to Aegis.</string>
|
||||||
<string name="groups">Groups</string>
|
<string name="groups">Groups</string>
|
||||||
|
<string name="archive">Archive</string>
|
||||||
<string name="pref_focus_search">Focus search on app start</string>
|
<string name="pref_focus_search">Focus search on app start</string>
|
||||||
<string name="pref_focus_search_summary">Focus the search immediately after opening the app.</string>
|
<string name="pref_focus_search_summary">Focus the search immediately after opening the app.</string>
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue