mirror of
https://github.com/beemdevelopment/Aegis.git
synced 2025-04-25 08:16:07 +00:00
Merge pull request #671 from michaelschattgen/feature/chips
Start working on bottomsheet for group chips
This commit is contained in:
commit
29ea2df696
16 changed files with 255 additions and 66 deletions
|
@ -153,7 +153,7 @@ dependencies {
|
||||||
implementation "com.github.topjohnwu.libsu:core:${libsuVersion}"
|
implementation "com.github.topjohnwu.libsu:core:${libsuVersion}"
|
||||||
implementation "com.github.topjohnwu.libsu:io:${libsuVersion}"
|
implementation "com.github.topjohnwu.libsu:io:${libsuVersion}"
|
||||||
implementation "com.google.guava:guava:${guavaVersion}-android"
|
implementation "com.google.guava:guava:${guavaVersion}-android"
|
||||||
implementation 'com.google.android.material:material:1.0.0'
|
implementation 'com.google.android.material:material:1.2.1'
|
||||||
implementation 'com.google.protobuf:protobuf-javalite:3.14.0'
|
implementation 'com.google.protobuf:protobuf-javalite:3.14.0'
|
||||||
implementation 'com.google.zxing:core:3.4.1'
|
implementation 'com.google.zxing:core:3.4.1'
|
||||||
implementation "com.mikepenz:iconics-core:3.2.5"
|
implementation "com.mikepenz:iconics-core:3.2.5"
|
||||||
|
|
|
@ -41,6 +41,8 @@ import com.beemdevelopment.aegis.vault.VaultManager;
|
||||||
import com.beemdevelopment.aegis.vault.VaultManagerException;
|
import com.beemdevelopment.aegis.vault.VaultManagerException;
|
||||||
import com.google.android.material.bottomsheet.BottomSheetDialog;
|
import com.google.android.material.bottomsheet.BottomSheetDialog;
|
||||||
import com.google.android.material.floatingactionbutton.FloatingActionButton;
|
import com.google.android.material.floatingactionbutton.FloatingActionButton;
|
||||||
|
import com.google.android.material.chip.Chip;
|
||||||
|
import com.google.android.material.chip.ChipGroup;
|
||||||
import com.google.zxing.BinaryBitmap;
|
import com.google.zxing.BinaryBitmap;
|
||||||
import com.google.zxing.ChecksumException;
|
import com.google.zxing.ChecksumException;
|
||||||
import com.google.zxing.FormatException;
|
import com.google.zxing.FormatException;
|
||||||
|
@ -58,6 +60,7 @@ import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.TreeSet;
|
import java.util.TreeSet;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
public class MainActivity extends AegisActivity implements EntryListView.Listener {
|
public class MainActivity extends AegisActivity implements EntryListView.Listener {
|
||||||
// activity request codes
|
// activity request codes
|
||||||
|
@ -76,7 +79,7 @@ public class MainActivity extends AegisActivity implements EntryListView.Listene
|
||||||
private AegisApplication _app;
|
private AegisApplication _app;
|
||||||
private VaultManager _vault;
|
private VaultManager _vault;
|
||||||
private boolean _loaded;
|
private boolean _loaded;
|
||||||
private String _selectedGroup;
|
private List<String> _selectedGroups;
|
||||||
private boolean _searchSubmitted;
|
private boolean _searchSubmitted;
|
||||||
|
|
||||||
private boolean _isAuthenticating;
|
private boolean _isAuthenticating;
|
||||||
|
@ -247,7 +250,7 @@ public class MainActivity extends AegisActivity implements EntryListView.Listene
|
||||||
} else {
|
} else {
|
||||||
intent.putExtra("entryUUID", entry.getUUID());
|
intent.putExtra("entryUUID", entry.getUUID());
|
||||||
}
|
}
|
||||||
intent.putExtra("selectedGroup", _selectedGroup);
|
intent.putExtra("selectedGroup", (ArrayList<String>) _selectedGroups);
|
||||||
startActivityForResult(intent, requestCode);
|
startActivityForResult(intent, requestCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -319,45 +322,13 @@ public class MainActivity extends AegisActivity implements EntryListView.Listene
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateGroupFilterMenu() {
|
|
||||||
SubMenu menu = _menu.findItem(R.id.action_filter).getSubMenu();
|
|
||||||
for (int i = menu.size() - 1; i >= 0; i--) {
|
|
||||||
MenuItem item = menu.getItem(i);
|
|
||||||
if (item.getItemId() == R.id.menu_filter_all) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
menu.removeItem(item.getItemId());
|
|
||||||
}
|
|
||||||
|
|
||||||
// if the group no longer exists, switch back to 'All'
|
|
||||||
TreeSet<String> groups = _vault.getGroups();
|
|
||||||
if (_selectedGroup != null && !groups.contains(_selectedGroup)) {
|
|
||||||
menu.findItem(R.id.menu_filter_all).setChecked(true);
|
|
||||||
setGroupFilter(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (String group : groups) {
|
|
||||||
MenuItem item = menu.add(R.id.action_filter_group, Menu.NONE, Menu.NONE, group);
|
|
||||||
if (group.equals(_selectedGroup)) {
|
|
||||||
item.setChecked(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (groups.size() > 0) {
|
|
||||||
menu.add(R.id.action_filter_group, Menu.NONE, 10, R.string.filter_ungrouped);
|
|
||||||
}
|
|
||||||
|
|
||||||
menu.setGroupCheckable(R.id.action_filter_group, true, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateSortCategoryMenu() {
|
private void updateSortCategoryMenu() {
|
||||||
SortCategory category = getPreferences().getCurrentSortCategory();
|
SortCategory category = getPreferences().getCurrentSortCategory();
|
||||||
_menu.findItem(category.getMenuItem()).setChecked(true);
|
_menu.findItem(category.getMenuItem()).setChecked(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setGroupFilter(String group) {
|
private void setGroupFilter(List<String> group) {
|
||||||
getSupportActionBar().setSubtitle(group);
|
_selectedGroups = group;
|
||||||
_selectedGroup = group;
|
|
||||||
_entryListView.setGroupFilter(group, true);
|
_entryListView.setGroupFilter(group, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -492,7 +463,7 @@ public class MainActivity extends AegisActivity implements EntryListView.Listene
|
||||||
} else if (_loaded) {
|
} else if (_loaded) {
|
||||||
// update the list of groups in the filter menu
|
// update the list of groups in the filter menu
|
||||||
if (_menu != null) {
|
if (_menu != null) {
|
||||||
updateGroupFilterMenu();
|
_entryListView.setGroups(_vault.getGroups());
|
||||||
}
|
}
|
||||||
|
|
||||||
// refresh all codes to prevent showing old ones
|
// refresh all codes to prevent showing old ones
|
||||||
|
@ -516,7 +487,7 @@ public class MainActivity extends AegisActivity implements EntryListView.Listene
|
||||||
|
|
||||||
collapseSearchView();
|
collapseSearchView();
|
||||||
setTitle("Aegis");
|
setTitle("Aegis");
|
||||||
setGroupFilter(_selectedGroup);
|
setGroupFilter(_selectedGroups);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -543,7 +514,7 @@ public class MainActivity extends AegisActivity implements EntryListView.Listene
|
||||||
getMenuInflater().inflate(R.menu.menu_main, menu);
|
getMenuInflater().inflate(R.menu.menu_main, menu);
|
||||||
updateLockIcon();
|
updateLockIcon();
|
||||||
if (_loaded) {
|
if (_loaded) {
|
||||||
updateGroupFilterMenu();
|
_entryListView.setGroups(_vault.getGroups());
|
||||||
updateSortCategoryMenu();
|
updateSortCategoryMenu();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -596,7 +567,7 @@ public class MainActivity extends AegisActivity implements EntryListView.Listene
|
||||||
_app.lock(true);
|
_app.lock(true);
|
||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
if (item.getGroupId() == R.id.action_filter_group) {
|
/*if (item.getGroupId() == R.id.action_filter_group) {
|
||||||
item.setChecked(true);
|
item.setChecked(true);
|
||||||
|
|
||||||
String group = null;
|
String group = null;
|
||||||
|
@ -604,7 +575,7 @@ public class MainActivity extends AegisActivity implements EntryListView.Listene
|
||||||
group = item.getTitle().toString();
|
group = item.getTitle().toString();
|
||||||
}
|
}
|
||||||
setGroupFilter(group);
|
setGroupFilter(group);
|
||||||
}
|
}*/
|
||||||
|
|
||||||
if (item.getGroupId() == R.id.action_sort_category) {
|
if (item.getGroupId() == R.id.action_sort_category) {
|
||||||
item.setChecked(true);
|
item.setChecked(true);
|
||||||
|
@ -811,7 +782,7 @@ public class MainActivity extends AegisActivity implements EntryListView.Listene
|
||||||
for (VaultEntry entry : _selectedEntries) {
|
for (VaultEntry entry : _selectedEntries) {
|
||||||
if (entry.getGroup() != null) {
|
if (entry.getGroup() != null) {
|
||||||
if (!_vault.getGroups().contains(entry.getGroup())) {
|
if (!_vault.getGroups().contains(entry.getGroup())) {
|
||||||
updateGroupFilterMenu();
|
_entryListView.setGroups(_vault.getGroups());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,7 @@ import java.util.Comparator;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.TreeSet;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
public class EntryAdapter extends RecyclerView.Adapter<EntryHolder> implements ItemTouchHelperAdapter {
|
public class EntryAdapter extends RecyclerView.Adapter<EntryHolder> implements ItemTouchHelperAdapter {
|
||||||
|
@ -40,7 +41,7 @@ public class EntryAdapter extends RecyclerView.Adapter<EntryHolder> implements I
|
||||||
private boolean _tapToReveal;
|
private boolean _tapToReveal;
|
||||||
private int _tapToRevealTime;
|
private int _tapToRevealTime;
|
||||||
private boolean _copyOnTap;
|
private boolean _copyOnTap;
|
||||||
private String _groupFilter;
|
private List<String> _groupFilter;
|
||||||
private SortCategory _sortCategory;
|
private SortCategory _sortCategory;
|
||||||
private ViewMode _viewMode;
|
private ViewMode _viewMode;
|
||||||
private String _searchFilter;
|
private String _searchFilter;
|
||||||
|
@ -56,6 +57,7 @@ public class EntryAdapter extends RecyclerView.Adapter<EntryHolder> implements I
|
||||||
_entries = new ArrayList<>();
|
_entries = new ArrayList<>();
|
||||||
_shownEntries = new ArrayList<>();
|
_shownEntries = new ArrayList<>();
|
||||||
_selectedEntries = new ArrayList<>();
|
_selectedEntries = new ArrayList<>();
|
||||||
|
_groupFilter = new ArrayList<>();
|
||||||
_holders = new ArrayList<>();
|
_holders = new ArrayList<>();
|
||||||
_dimHandler = new Handler();
|
_dimHandler = new Handler();
|
||||||
_view = view;
|
_view = view;
|
||||||
|
@ -207,12 +209,12 @@ public class EntryAdapter extends RecyclerView.Adapter<EntryHolder> implements I
|
||||||
String issuer = entry.getIssuer().toLowerCase();
|
String issuer = entry.getIssuer().toLowerCase();
|
||||||
String name = entry.getName().toLowerCase();
|
String name = entry.getName().toLowerCase();
|
||||||
|
|
||||||
if (_groupFilter != null) {
|
if (!_groupFilter.isEmpty()) {
|
||||||
if (group == null && _groupFilter.equals(_view.getContext().getString(R.string.filter_ungrouped))) {
|
if (group == null && _groupFilter.contains(_view.getContext().getString(R.string.filter_ungrouped))) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (group == null || !group.equals(_groupFilter)) {
|
if (group == null || !_groupFilter.contains(group)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -234,11 +236,16 @@ public class EntryAdapter extends RecyclerView.Adapter<EntryHolder> implements I
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setGroupFilter(String group, boolean apply) {
|
public void setGroupFilter(List<String> groups, boolean apply) {
|
||||||
if (_groupFilter != null && _groupFilter.equals(group)) {
|
if(groups == null) {
|
||||||
|
groups = new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_groupFilter.equals(groups)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_groupFilter = group;
|
|
||||||
|
_groupFilter = groups;
|
||||||
if (apply) {
|
if (apply) {
|
||||||
updateShownEntries();
|
updateShownEntries();
|
||||||
checkPeriodUniformity();
|
checkPeriodUniformity();
|
||||||
|
@ -286,6 +293,10 @@ public class EntryAdapter extends RecyclerView.Adapter<EntryHolder> implements I
|
||||||
_viewMode = viewMode;
|
_viewMode = viewMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setGroups(TreeSet<String> groups) {
|
||||||
|
_view.setGroups(groups);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onItemDismiss(int position) {
|
public void onItemDismiss(int position) {
|
||||||
|
|
||||||
|
@ -294,7 +305,7 @@ public class EntryAdapter extends RecyclerView.Adapter<EntryHolder> implements I
|
||||||
@Override
|
@Override
|
||||||
public void onItemDrop(int position) {
|
public void onItemDrop(int position) {
|
||||||
// moving entries is not allowed when a filter is applied
|
// moving entries is not allowed when a filter is applied
|
||||||
if (_groupFilter != null) {
|
if (!_groupFilter.isEmpty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -304,7 +315,7 @@ public class EntryAdapter extends RecyclerView.Adapter<EntryHolder> implements I
|
||||||
@Override
|
@Override
|
||||||
public void onItemMove(int firstPosition, int secondPosition) {
|
public void onItemMove(int firstPosition, int secondPosition) {
|
||||||
// moving entries is not allowed when a filter is applied
|
// moving entries is not allowed when a filter is applied
|
||||||
if (_groupFilter != null) {
|
if (!_groupFilter.isEmpty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -591,7 +602,7 @@ public class EntryAdapter extends RecyclerView.Adapter<EntryHolder> implements I
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isDragAndDropAllowed() {
|
public boolean isDragAndDropAllowed() {
|
||||||
return _sortCategory == SortCategory.CUSTOM && _groupFilter == null && _searchFilter == null;
|
return _sortCategory == SortCategory.CUSTOM && _groupFilter.isEmpty() && _searchFilter == null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isPeriodUniform() {
|
public boolean isPeriodUniform() {
|
||||||
|
|
|
@ -2,6 +2,7 @@ package com.beemdevelopment.aegis.ui.views;
|
||||||
|
|
||||||
import android.annotation.SuppressLint;
|
import android.annotation.SuppressLint;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.content.res.ColorStateList;
|
||||||
import android.graphics.Rect;
|
import android.graphics.Rect;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
|
@ -10,6 +11,7 @@ import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.view.animation.AnimationUtils;
|
import android.view.animation.AnimationUtils;
|
||||||
import android.view.animation.LayoutAnimationController;
|
import android.view.animation.LayoutAnimationController;
|
||||||
|
import android.widget.Button;
|
||||||
import android.widget.LinearLayout;
|
import android.widget.LinearLayout;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
@ -28,6 +30,7 @@ import com.beemdevelopment.aegis.helpers.MetricsHelper;
|
||||||
import com.beemdevelopment.aegis.helpers.SimpleItemTouchHelperCallback;
|
import com.beemdevelopment.aegis.helpers.SimpleItemTouchHelperCallback;
|
||||||
import com.beemdevelopment.aegis.helpers.UiRefresher;
|
import com.beemdevelopment.aegis.helpers.UiRefresher;
|
||||||
import com.beemdevelopment.aegis.otp.TotpInfo;
|
import com.beemdevelopment.aegis.otp.TotpInfo;
|
||||||
|
import com.beemdevelopment.aegis.ui.Dialogs;
|
||||||
import com.beemdevelopment.aegis.vault.VaultEntry;
|
import com.beemdevelopment.aegis.vault.VaultEntry;
|
||||||
import com.bumptech.glide.Glide;
|
import com.bumptech.glide.Glide;
|
||||||
import com.bumptech.glide.ListPreloader;
|
import com.bumptech.glide.ListPreloader;
|
||||||
|
@ -35,11 +38,17 @@ import com.bumptech.glide.RequestBuilder;
|
||||||
import com.bumptech.glide.integration.recyclerview.RecyclerViewPreloader;
|
import com.bumptech.glide.integration.recyclerview.RecyclerViewPreloader;
|
||||||
import com.bumptech.glide.load.engine.DiskCacheStrategy;
|
import com.bumptech.glide.load.engine.DiskCacheStrategy;
|
||||||
import com.bumptech.glide.util.ViewPreloadSizeProvider;
|
import com.bumptech.glide.util.ViewPreloadSizeProvider;
|
||||||
|
import com.google.android.material.bottomsheet.BottomSheetDialog;
|
||||||
|
import com.google.android.material.chip.Chip;
|
||||||
|
import com.google.android.material.chip.ChipGroup;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.TreeSet;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
public class EntryListView extends Fragment implements EntryAdapter.Listener {
|
public class EntryListView extends Fragment implements EntryAdapter.Listener {
|
||||||
private EntryAdapter _adapter;
|
private EntryAdapter _adapter;
|
||||||
|
@ -53,7 +62,10 @@ public class EntryListView extends Fragment implements EntryAdapter.Listener {
|
||||||
private TotpProgressBar _progressBar;
|
private TotpProgressBar _progressBar;
|
||||||
private boolean _showProgress;
|
private boolean _showProgress;
|
||||||
private ViewMode _viewMode;
|
private ViewMode _viewMode;
|
||||||
|
private TreeSet<String> _groups;
|
||||||
private LinearLayout _emptyStateView;
|
private LinearLayout _emptyStateView;
|
||||||
|
private Chip _groupChip;
|
||||||
|
private List<String> _groupFilter;
|
||||||
|
|
||||||
private UiRefresher _refresher;
|
private UiRefresher _refresher;
|
||||||
|
|
||||||
|
@ -74,6 +86,7 @@ public class EntryListView extends Fragment implements EntryAdapter.Listener {
|
||||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||||
View view = inflater.inflate(R.layout.fragment_entry_list_view, container, false);
|
View view = inflater.inflate(R.layout.fragment_entry_list_view, container, false);
|
||||||
_progressBar = view.findViewById(R.id.progressBar);
|
_progressBar = view.findViewById(R.id.progressBar);
|
||||||
|
_groupChip = view.findViewById(R.id.chip_group);
|
||||||
|
|
||||||
// set up the recycler view
|
// set up the recycler view
|
||||||
_recyclerView = view.findViewById(R.id.rvKeyProfiles);
|
_recyclerView = view.findViewById(R.id.rvKeyProfiles);
|
||||||
|
@ -129,7 +142,7 @@ public class EntryListView extends Fragment implements EntryAdapter.Listener {
|
||||||
super.onDestroyView();
|
super.onDestroyView();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setGroupFilter(String group, boolean apply) {
|
public void setGroupFilter(List<String> group, boolean apply) {
|
||||||
_adapter.setGroupFilter(group, apply);
|
_adapter.setGroupFilter(group, apply);
|
||||||
_touchCallback.setIsLongPressDragEnabled(_adapter.isDragAndDropAllowed());
|
_touchCallback.setIsLongPressDragEnabled(_adapter.isDragAndDropAllowed());
|
||||||
|
|
||||||
|
@ -339,11 +352,67 @@ public class EntryListView extends Fragment implements EntryAdapter.Listener {
|
||||||
_recyclerView.scheduleLayoutAnimation();
|
_recyclerView.scheduleLayoutAnimation();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void initializeGroupChip() {
|
||||||
|
if (_groups.isEmpty()) {
|
||||||
|
_groupChip.setVisibility(View.GONE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
View view = getLayoutInflater().inflate(R.layout.dialog_select_groups, null);
|
||||||
|
BottomSheetDialog dialog = new BottomSheetDialog(getContext());
|
||||||
|
dialog.setContentView(view);
|
||||||
|
|
||||||
|
ColorStateList colorStateList = ContextCompat.getColorStateList(getContext(), R.color.bg_chip_text_color);
|
||||||
|
|
||||||
|
ChipGroup chipGroup = view.findViewById(R.id.groupChipGroup);
|
||||||
|
String groupChipText = _groupChip.getText().toString();
|
||||||
|
chipGroup.removeAllViews();
|
||||||
|
for (String group : _groups) {
|
||||||
|
Chip chip = new Chip(getContext());
|
||||||
|
chip.setText(group);
|
||||||
|
chip.setCheckable(true);
|
||||||
|
chip.setCheckedIconVisible(false);
|
||||||
|
chip.setChipBackgroundColorResource(R.color.bg_chip_color);
|
||||||
|
chip.setTextColor(colorStateList);
|
||||||
|
chip.setOnCheckedChangeListener((group1, checkedId) -> {
|
||||||
|
List<String> groupFilter = chipGroup.getCheckedChipIds().stream()
|
||||||
|
.map(i -> ((Chip) view.findViewById(i)).getText().toString())
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
_groupFilter = groupFilter;
|
||||||
|
setGroupFilter(groupFilter, true);
|
||||||
|
|
||||||
|
if (_groupFilter.isEmpty()) {
|
||||||
|
_groupChip.setText(groupChipText);
|
||||||
|
} else {
|
||||||
|
_groupChip.setText(String.format("%s (%d)", getString(R.string.groups), _groupFilter.size()));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
chipGroup.addView(chip);
|
||||||
|
}
|
||||||
|
|
||||||
|
Button clearButton = view.findViewById(R.id.btnClear);
|
||||||
|
clearButton.setOnClickListener(v -> {
|
||||||
|
chipGroup.clearCheck();
|
||||||
|
setGroupFilter(null, true);
|
||||||
|
dialog.dismiss();
|
||||||
|
});
|
||||||
|
|
||||||
|
_groupChip.setOnClickListener(v -> {
|
||||||
|
Dialogs.showSecureDialog(dialog);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
private void setShowProgress(boolean showProgress) {
|
private void setShowProgress(boolean showProgress) {
|
||||||
_showProgress = showProgress;
|
_showProgress = showProgress;
|
||||||
updateDividerDecoration();
|
updateDividerDecoration();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setGroups(TreeSet<String> groups) {
|
||||||
|
_groups = groups;
|
||||||
|
initializeGroupChip();
|
||||||
|
}
|
||||||
|
|
||||||
private void updateDividerDecoration() {
|
private void updateDividerDecoration() {
|
||||||
if (_dividerDecoration != null) {
|
if (_dividerDecoration != null) {
|
||||||
_recyclerView.removeItemDecoration(_dividerDecoration);
|
_recyclerView.removeItemDecoration(_dividerDecoration);
|
||||||
|
@ -394,10 +463,6 @@ public class EntryListView extends Fragment implements EntryAdapter.Listener {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void getItemOffsets(@NonNull Rect outRect, @NonNull View view, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) {
|
public void getItemOffsets(@NonNull Rect outRect, @NonNull View view, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) {
|
||||||
if (parent.getChildAdapterPosition(view) == 0) {
|
|
||||||
// the first item should also have a top margin
|
|
||||||
outRect.top = _height;
|
|
||||||
}
|
|
||||||
outRect.bottom = _height;
|
outRect.bottom = _height;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
5
app/src/main/res/color/bg_chip_color.xml
Normal file
5
app/src/main/res/color/bg_chip_color.xml
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<item android:color="#D7E3EF" android:state_checked="true" />
|
||||||
|
<item android:color="@color/background" />
|
||||||
|
</selector>
|
5
app/src/main/res/color/bg_chip_text_color.xml
Normal file
5
app/src/main/res/color/bg_chip_text_color.xml
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<item android:color="@color/colorPrimary" android:state_checked="true" />
|
||||||
|
<item android:color="@color/primary_text" />
|
||||||
|
</selector>
|
8
app/src/main/res/drawable-v24/rounded_dialog.xml
Normal file
8
app/src/main/res/drawable-v24/rounded_dialog.xml
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:shape="rectangle">
|
||||||
|
<solid android:color="@android:color/white"/>
|
||||||
|
<corners android:topLeftRadius="16dp"
|
||||||
|
android:topRightRadius="16dp"/>
|
||||||
|
|
||||||
|
</shape>
|
13
app/src/main/res/drawable/drag_handle.xml
Normal file
13
app/src/main/res/drawable/drag_handle.xml
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:shape="rectangle">
|
||||||
|
<solid android:color="@color/divider2"/>
|
||||||
|
<size android:height=".1dp"/>
|
||||||
|
|
||||||
|
<padding android:left="1dp"
|
||||||
|
android:top="1dp"
|
||||||
|
android:right="1dp"
|
||||||
|
android:bottom="1dp" />
|
||||||
|
|
||||||
|
<corners android:radius="7dp" />
|
||||||
|
</shape>
|
|
@ -6,4 +6,5 @@
|
||||||
<path
|
<path
|
||||||
android:fillColor="#FFFFFF"
|
android:fillColor="#FFFFFF"
|
||||||
android:pathData="M10,18h4v-2h-4v2zM3,6v2h18L21,6L3,6zM6,13h12v-2L6,11v2z"/>
|
android:pathData="M10,18h4v-2h-4v2zM3,6v2h18L21,6L3,6zM6,13h12v-2L6,11v2z"/>
|
||||||
|
|
||||||
</vector>
|
</vector>
|
||||||
|
|
|
@ -38,6 +38,13 @@
|
||||||
android:layout_marginStart="5dp" />
|
android:layout_marginStart="5dp" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
<com.google.android.material.chip.ChipGroup
|
||||||
|
android:id="@+id/groupChipGroup"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
</com.google.android.material.chip.ChipGroup>
|
||||||
|
|
||||||
<fragment
|
<fragment
|
||||||
android:name="com.beemdevelopment.aegis.ui.views.EntryListView"
|
android:name="com.beemdevelopment.aegis.ui.views.EntryListView"
|
||||||
android:id="@+id/key_profiles"
|
android:id="@+id/key_profiles"
|
||||||
|
|
|
@ -4,8 +4,7 @@
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical">
|
||||||
android:background="?attr/background">
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:id="@+id/fab_scan"
|
android:id="@+id/fab_scan"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
|
55
app/src/main/res/layout/dialog_select_groups.xml
Normal file
55
app/src/main/res/layout/dialog_select_groups.xml
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:paddingTop="12dp"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:layout_width="16dp"
|
||||||
|
android:layout_height="2dp"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:background="@drawable/drag_handle" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:paddingTop="8dp"
|
||||||
|
android:paddingBottom="16dp"
|
||||||
|
android:textSize="17sp"
|
||||||
|
android:gravity="center"
|
||||||
|
android:id="@+id/textView3"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textColor="?attr/primaryText"
|
||||||
|
android:text="Groups" />
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="1dp"
|
||||||
|
android:background="@color/divider2" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:minHeight="150dp"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<com.google.android.material.chip.ChipGroup
|
||||||
|
android:id="@+id/groupChipGroup"
|
||||||
|
android:paddingLeft="8dp"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
</com.google.android.material.chip.ChipGroup>
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/btnClear"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="end"
|
||||||
|
style="?android:attr/borderlessButtonStyle"
|
||||||
|
android:textColor="@color/colorSecondary"
|
||||||
|
android:paddingEnd="16dp"
|
||||||
|
android:text="Clear" />
|
||||||
|
</LinearLayout>
|
|
@ -15,6 +15,24 @@
|
||||||
android:visibility="gone"
|
android:visibility="gone"
|
||||||
android:max="5000"/>
|
android:max="5000"/>
|
||||||
|
|
||||||
|
<com.google.android.material.chip.Chip
|
||||||
|
android:id="@+id/chip_group"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/groups"
|
||||||
|
android:layout_gravity="end"
|
||||||
|
android:layout_marginEnd="8dp"
|
||||||
|
android:textAppearance="@style/AppTheme.ActionChip"
|
||||||
|
android:textColor="?attr/primaryText"
|
||||||
|
app:chipBackgroundColor="?attr/cardBackground"
|
||||||
|
app:chipEndPadding="6dp"
|
||||||
|
app:chipIcon="@drawable/ic_baseline_filter_list_24dp"
|
||||||
|
app:chipIconSize="18dp"
|
||||||
|
app:chipIconTint="?attr/primaryText"
|
||||||
|
app:chipStrokeColor="@color/hint_text_dark"
|
||||||
|
app:chipStrokeWidth="1dp"
|
||||||
|
app:iconStartPadding="6dp" />
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="0dp"
|
android:layout_height="0dp"
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
<color name="secondary_text_inverted">#efefef</color>b
|
<color name="secondary_text_inverted">#efefef</color>b
|
||||||
<color name="icons">#FFFFFF</color>
|
<color name="icons">#FFFFFF</color>
|
||||||
<color name="divider">#BDBDBD</color>
|
<color name="divider">#BDBDBD</color>
|
||||||
|
<color name="divider2">#DADADA</color>
|
||||||
<color name="background">#f2f2f2</color>
|
<color name="background">#f2f2f2</color>
|
||||||
<color name="card_background">#ffffff</color>
|
<color name="card_background">#ffffff</color>
|
||||||
<color name="card_background_focused">#DBDBDB</color>
|
<color name="card_background_focused">#DBDBDB</color>
|
||||||
|
|
|
@ -353,4 +353,5 @@
|
||||||
<string name="importer_help_winauth">Supply a WinAuth export file.</string>
|
<string name="importer_help_winauth">Supply a WinAuth export file.</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="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>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
|
|
||||||
<style name="AppTheme.PopupOverlay" parent="ThemeOverlay.AppCompat.Light" />
|
<style name="AppTheme.PopupOverlay" parent="ThemeOverlay.AppCompat.Light" />
|
||||||
|
|
||||||
<style name="AppThemeBase" parent="Theme.AppCompat.Light.DarkActionBar">
|
<style name="AppThemeBase" parent="Theme.MaterialComponents.Light.DarkActionBar">
|
||||||
<item name="primaryText">@color/primary_text</item>
|
<item name="primaryText">@color/primary_text</item>
|
||||||
<item name="secondaryText">@color/secondary_text</item>
|
<item name="secondaryText">@color/secondary_text</item>
|
||||||
<item name="cardBackground">@color/card_background</item>
|
<item name="cardBackground">@color/card_background</item>
|
||||||
|
@ -26,6 +26,7 @@
|
||||||
<item name="colorAccent">@color/colorAccent</item>
|
<item name="colorAccent">@color/colorAccent</item>
|
||||||
<item name="background">@color/background</item>
|
<item name="background">@color/background</item>
|
||||||
<item name="divider">@color/divider</item>
|
<item name="divider">@color/divider</item>
|
||||||
|
<item name="bottomSheetDialogTheme">@style/BottomSheetDialog_Rounded</item>
|
||||||
|
|
||||||
<item name="iconColorPrimary">@color/icon_primary</item>
|
<item name="iconColorPrimary">@color/icon_primary</item>
|
||||||
<item name="iconColorInverted">@color/icon_primary_inverted</item>
|
<item name="iconColorInverted">@color/icon_primary_inverted</item>
|
||||||
|
@ -62,6 +63,7 @@
|
||||||
<item name="primaryText">@color/primary_text_dark</item>
|
<item name="primaryText">@color/primary_text_dark</item>
|
||||||
<item name="background">@color/background_dark</item>
|
<item name="background">@color/background_dark</item>
|
||||||
<item name="authText">@color/primary_text_inverted</item>
|
<item name="authText">@color/primary_text_inverted</item>
|
||||||
|
<item name="bottomSheetDialogTheme">@style/BottomSheetDialog_Rounded</item>
|
||||||
|
|
||||||
<item name="android:navigationBarColor" tools:targetApi="o_mr1">@color/background_dark</item>
|
<item name="android:navigationBarColor" tools:targetApi="o_mr1">@color/background_dark</item>
|
||||||
<item name="android:windowLightNavigationBar" tools:targetApi="o_mr1">true</item>
|
<item name="android:windowLightNavigationBar" tools:targetApi="o_mr1">true</item>
|
||||||
|
@ -75,6 +77,7 @@
|
||||||
<item name="primaryText">@color/primary_text_dark</item>
|
<item name="primaryText">@color/primary_text_dark</item>
|
||||||
<item name="background">@color/background_true_dark</item>
|
<item name="background">@color/background_true_dark</item>
|
||||||
<item name="authText">@color/primary_text_inverted</item>
|
<item name="authText">@color/primary_text_inverted</item>
|
||||||
|
<item name="bottomSheetDialogTheme">@style/BottomSheetDialog_Rounded</item>
|
||||||
|
|
||||||
<item name="android:navigationBarColor" tools:targetApi="lollipop">@color/background_true_dark</item>
|
<item name="android:navigationBarColor" tools:targetApi="lollipop">@color/background_true_dark</item>
|
||||||
<item name="android:windowLightNavigationBar" tools:targetApi="o_mr1">false</item>
|
<item name="android:windowLightNavigationBar" tools:targetApi="o_mr1">false</item>
|
||||||
|
@ -109,7 +112,7 @@
|
||||||
<item name="android:textColor">@android:color/white</item>
|
<item name="android:textColor">@android:color/white</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style name="AppTheme.NoActionBar" parent="Theme.AppCompat.DayNight.NoActionBar">
|
<style name="AppTheme.NoActionBar" parent="Theme.MaterialComponents.DayNight.NoActionBar">
|
||||||
<item name="android:windowDrawsSystemBarBackgrounds" tools:targetApi="lollipop">true</item>
|
<item name="android:windowDrawsSystemBarBackgrounds" tools:targetApi="lollipop">true</item>
|
||||||
<item name="android:statusBarColor" tools:targetApi="lollipop">@android:color/transparent</item>
|
<item name="android:statusBarColor" tools:targetApi="lollipop">@android:color/transparent</item>
|
||||||
</style>
|
</style>
|
||||||
|
@ -126,7 +129,7 @@
|
||||||
<item name="android:windowNoTitle">true</item>
|
<item name="android:windowNoTitle">true</item>
|
||||||
<item name="android:windowFullscreen">true</item>
|
<item name="android:windowFullscreen">true</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style name="AppTheme.Fullscreen.Dark" parent="AppTheme.Dark">
|
<style name="AppTheme.Fullscreen.Dark" parent="AppTheme.Dark">
|
||||||
<!-- AppTheme.TransparentActionBar-->
|
<!-- AppTheme.TransparentActionBar-->
|
||||||
<item name="android:actionBarStyle">@style/ThemeActionBar</item>
|
<item name="android:actionBarStyle">@style/ThemeActionBar</item>
|
||||||
|
@ -151,7 +154,7 @@
|
||||||
<item name="android:windowFullscreen">true</item>
|
<item name="android:windowFullscreen">true</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style name="AppTheme.Dark" parent="Theme.AppCompat">
|
<style name="AppTheme.Dark" parent="Theme.MaterialComponents">
|
||||||
<item name="primaryText">@color/primary_text_dark</item>
|
<item name="primaryText">@color/primary_text_dark</item>
|
||||||
<item name="secondaryText">@color/secondary_text_dark</item>
|
<item name="secondaryText">@color/secondary_text_dark</item>
|
||||||
<item name="cardBackground">@color/card_background_dark</item>
|
<item name="cardBackground">@color/card_background_dark</item>
|
||||||
|
@ -207,13 +210,13 @@
|
||||||
<item name="android:textColor">#FFFFFF</item>
|
<item name="android:textColor">#FFFFFF</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style name="DialogStyle" parent="Theme.AppCompat.Light.Dialog.Alert">
|
<style name="DialogStyle" parent="Theme.MaterialComponents.Light.Dialog.Alert">
|
||||||
<item name="android:background">@color/card_background</item>
|
<item name="android:background">@color/card_background</item>
|
||||||
<item name="colorAccent">@color/colorAccent</item>
|
<item name="colorAccent">@color/colorAccent</item>
|
||||||
<item name="textColorAlertDialogListItem">@color/primary_text</item>
|
<item name="textColorAlertDialogListItem">@color/primary_text</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style name="DialogStyle.Dark" parent="Theme.AppCompat.Dialog">
|
<style name="DialogStyle.Dark" parent="Theme.MaterialComponents.Dialog">
|
||||||
<item name="android:background">@color/card_background_dark</item>
|
<item name="android:background">@color/card_background_dark</item>
|
||||||
<item name="colorAccent">@color/colorAccent</item>
|
<item name="colorAccent">@color/colorAccent</item>
|
||||||
<item name="textColorAlertDialogListItem">@color/primary_text_dark</item>
|
<item name="textColorAlertDialogListItem">@color/primary_text_dark</item>
|
||||||
|
@ -239,4 +242,30 @@
|
||||||
<style name="ActionBarTheme" parent="@style/ThemeOverlay.AppCompat.Dark.ActionBar">
|
<style name="ActionBarTheme" parent="@style/ThemeOverlay.AppCompat.Dark.ActionBar">
|
||||||
<item name="android:tint">?attr/iconColorInverted</item>
|
<item name="android:tint">?attr/iconColorInverted</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
<style name="AppTheme.ActionChip" parent="TextAppearance.MaterialComponents.Chip">
|
||||||
|
<item name="android:textSize">12sp</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style name="BottomSheetDialog_Rounded" parent="@style/ThemeOverlay.MaterialComponents.BottomSheetDialog">
|
||||||
|
<item name="bottomSheetStyle">@style/BottomSheet_Rounded</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style name="BottomSheet_Rounded" parent="Widget.MaterialComponents.BottomSheet">
|
||||||
|
<item name="shapeAppearanceOverlay">@style/ShapeAppearanceBottomSheetDialog_Rounded</item>
|
||||||
|
<item name="android:background">@android:color/transparent</item>
|
||||||
|
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style name="ChipUncheckedText" parent="TextAppearance.MaterialComponents.Chip">
|
||||||
|
<item name="android:textColor">@color/card_background</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style name="ShapeAppearanceBottomSheetDialog_Rounded" parent="">
|
||||||
|
<item name="cornerFamily">rounded</item>
|
||||||
|
<item name="cornerSizeTopRight">10dp</item>
|
||||||
|
<item name="cornerSizeTopLeft">10dp</item>
|
||||||
|
<item name="cornerSizeBottomRight">0dp</item>
|
||||||
|
<item name="cornerSizeBottomLeft">0dp</item>
|
||||||
|
</style>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
Loading…
Add table
Reference in a new issue