From 3a71f635f0b152aeed662e5b373bc2204b95bbca Mon Sep 17 00:00:00 2001 From: Jeremy Date: Fri, 9 Feb 2018 12:45:45 +0100 Subject: [PATCH] ListView as RecyclerView, Update SearchView, Create Activity package --- app/build.gradle | 2 +- app/src/main/AndroidManifest.xml | 4 +- .../com/keepassdroid/PasswordActivity.java | 1 + .../com/keepassdroid/PwGroupListAdapter.java | 150 ----------- .../{ => activity}/GroupActivity.java | 75 ++++-- .../{ => activity}/GroupActivityV3.java | 2 +- .../{ => activity}/GroupActivityV4.java | 2 +- .../{ => activity}/GroupBaseActivity.java | 72 +++--- .../com/keepassdroid/database/PwEntry.java | 2 +- .../com/keepassdroid/database/PwGroup.java | 2 +- .../com/keepassdroid/database/PwNode.java | 4 + .../database/edit/DeleteGroup.java | 2 +- .../fileselect/FileSelectActivity.java | 2 +- .../fileselect/FileSelectAdapter.java | 19 +- .../groupentity/BasicViewHolder.java | 18 ++ .../groupentity/EntryViewHolder.java | 17 ++ .../groupentity/GroupViewHolder.java | 17 ++ .../keepassdroid/groupentity/NodeAdapter.java | 238 ++++++++++++++++++ .../keepassdroid/icons/DrawableFactory.java | 3 +- .../search/SearchResultsActivity.java | 14 +- .../com/keepassdroid/view/PwEntryView.java | 131 ---------- .../com/keepassdroid/view/PwGroupView.java | 115 --------- .../com/keepassdroid/view/PwGroupViewV3.java | 69 ----- app/src/main/res/layout/group_add_entry.xml | 6 +- app/src/main/res/layout/group_empty.xml | 36 --- .../main/res/layout/list_entries_entry.xml | 6 +- .../main/res/layout/list_entries_group.xml | 26 +- app/src/main/res/layout/search_results.xml | 23 +- 28 files changed, 438 insertions(+), 620 deletions(-) delete mode 100644 app/src/main/java/com/keepassdroid/PwGroupListAdapter.java rename app/src/main/java/com/keepassdroid/{ => activity}/GroupActivity.java (76%) rename app/src/main/java/com/keepassdroid/{ => activity}/GroupActivityV3.java (97%) rename app/src/main/java/com/keepassdroid/{ => activity}/GroupActivityV4.java (97%) rename app/src/main/java/com/keepassdroid/{ => activity}/GroupBaseActivity.java (88%) create mode 100644 app/src/main/java/com/keepassdroid/database/PwNode.java create mode 100644 app/src/main/java/com/keepassdroid/groupentity/BasicViewHolder.java create mode 100644 app/src/main/java/com/keepassdroid/groupentity/EntryViewHolder.java create mode 100644 app/src/main/java/com/keepassdroid/groupentity/GroupViewHolder.java create mode 100644 app/src/main/java/com/keepassdroid/groupentity/NodeAdapter.java delete mode 100644 app/src/main/java/com/keepassdroid/view/PwEntryView.java delete mode 100644 app/src/main/java/com/keepassdroid/view/PwGroupView.java delete mode 100644 app/src/main/java/com/keepassdroid/view/PwGroupViewV3.java delete mode 100644 app/src/main/res/layout/group_empty.xml diff --git a/app/build.gradle b/app/build.gradle index bfc601169..d2f5b7e49 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -2,7 +2,7 @@ apply plugin: 'com.android.application' android { compileSdkVersion = 25 - buildToolsVersion = "27.0.1" + buildToolsVersion = "27.0.2" defaultConfig { applicationId "com.kunzisoft.keepass" diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index cb4b5fcb9..de30edab9 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -91,11 +91,11 @@ - + - + diff --git a/app/src/main/java/com/keepassdroid/PasswordActivity.java b/app/src/main/java/com/keepassdroid/PasswordActivity.java index 8c5345a85..778eb213f 100644 --- a/app/src/main/java/com/keepassdroid/PasswordActivity.java +++ b/app/src/main/java/com/keepassdroid/PasswordActivity.java @@ -54,6 +54,7 @@ import com.keepassdroid.database.edit.OnFinish; import com.keepassdroid.dialog.PasswordEncodingDialogHelper; import com.keepassdroid.fingerprint.FingerPrintAnimatedVector; import com.keepassdroid.fingerprint.FingerPrintHelper; +import com.keepassdroid.activity.GroupActivity; import com.keepassdroid.settings.PrefsUtil; import com.keepassdroid.utils.EmptyUtils; import com.keepassdroid.utils.MenuUtil; diff --git a/app/src/main/java/com/keepassdroid/PwGroupListAdapter.java b/app/src/main/java/com/keepassdroid/PwGroupListAdapter.java deleted file mode 100644 index 771b57e42..000000000 --- a/app/src/main/java/com/keepassdroid/PwGroupListAdapter.java +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Copyright 2017 Brian Pellin, Jeremy Jamet / Kunzisoft. - * - * This file is part of KeePass DX. - * - * KeePass DX is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * KeePass DX is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with KeePass DX. If not, see . - * - */ -package com.keepassdroid; - -import android.content.SharedPreferences; -import android.preference.PreferenceManager; -import android.view.View; -import android.view.ViewGroup; -import android.widget.BaseAdapter; - -import com.keepassdroid.database.PwEntry; -import com.keepassdroid.database.PwGroup; -import com.keepassdroid.view.PwEntryView; -import com.keepassdroid.view.PwGroupView; -import com.kunzisoft.keepass.R; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.List; - -public class PwGroupListAdapter extends BaseAdapter { - - private GroupBaseActivity mAct; - private PwGroup mGroup; - private List groupsForViewing; - private List entriesForViewing; - private Comparator entryComp = new PwEntry.EntryNameComparator(); - private Comparator groupComp = new PwGroup.GroupNameComparator(); - private SharedPreferences prefs; - - public PwGroupListAdapter(GroupBaseActivity act, PwGroup group) { - mAct = act; - mGroup = group; - prefs = PreferenceManager.getDefaultSharedPreferences(act); - - filterAndSort(); - - } - - @Override - public void notifyDataSetChanged() { - super.notifyDataSetChanged(); - - filterAndSort(); - } - - @Override - public void notifyDataSetInvalidated() { - super.notifyDataSetInvalidated(); - - filterAndSort(); - } - - private void filterAndSort() { - entriesForViewing = new ArrayList(); - - if (mGroup != null) { - for (int i = 0; i < mGroup.childEntries.size(); i++) { - PwEntry entry = mGroup.childEntries.get(i); - if (!entry.isMetaStream()) { - entriesForViewing.add(entry); - } - } - - boolean sortLists = prefs.getBoolean(mAct.getString(R.string.sort_key), mAct.getResources().getBoolean(R.bool.sort_default)); - if (sortLists) { - groupsForViewing = new ArrayList(mGroup.childGroups); - - Collections.sort(entriesForViewing, entryComp); - Collections.sort(groupsForViewing, groupComp); - } else { - groupsForViewing = mGroup.childGroups; - } - } - } - - public int getCount() { - - return groupsForViewing.size() + entriesForViewing.size(); - } - - public Object getItem(int position) { - return position; - } - - public long getItemId(int position) { - return position; - } - - public View getView(int position, View convertView, ViewGroup parent) { - int size = groupsForViewing.size(); - - if ( position < size ) { - return createGroupView(position, convertView); - } else { - return createEntryView(position - size, convertView); - } - } - - private View createGroupView(int position, View convertView) { - PwGroup group = groupsForViewing.get(position); - PwGroupView gv; - - if (convertView == null || !(convertView instanceof PwGroupView)) { - - gv = PwGroupView.getInstance(mAct, group); - } - else { - gv = (PwGroupView) convertView; - gv.convertView(group); - - } - - return gv; - } - - private PwEntryView createEntryView(int position, View convertView) { - PwEntry entry = entriesForViewing.get(position); - PwEntryView ev; - - if (convertView == null || !(convertView instanceof PwEntryView)) { - ev = PwEntryView.getInstance(mAct, entry, position); - } - else { - ev = (PwEntryView) convertView; - ev.convertView(entry, position); - } - - return ev; - } - -} diff --git a/app/src/main/java/com/keepassdroid/GroupActivity.java b/app/src/main/java/com/keepassdroid/activity/GroupActivity.java similarity index 76% rename from app/src/main/java/com/keepassdroid/GroupActivity.java rename to app/src/main/java/com/keepassdroid/activity/GroupActivity.java index 622356adc..dee1e0197 100644 --- a/app/src/main/java/com/keepassdroid/GroupActivity.java +++ b/app/src/main/java/com/keepassdroid/activity/GroupActivity.java @@ -17,7 +17,7 @@ * along with KeePass DX. If not, see . * */ -package com.keepassdroid; +package com.keepassdroid.activity; import android.app.Activity; import android.app.Dialog; @@ -28,12 +28,20 @@ import android.os.Handler; import android.preference.PreferenceManager; import android.support.v7.widget.Toolbar; import android.util.Log; -import android.view.ContextMenu; -import android.view.ContextMenu.ContextMenuInfo; import android.view.MenuItem; import android.view.View; -import android.widget.AdapterView.AdapterContextMenuInfo; +import com.keepassdroid.Database; +import com.keepassdroid.EntryActivity; +import com.keepassdroid.EntryEditActivity; +import com.keepassdroid.GroupEditFragment; +import com.keepassdroid.IconPickerFragment; +import com.keepassdroid.ProgressTask; +import com.keepassdroid.database.PwEntry; +import com.keepassdroid.database.PwNode; +import com.keepassdroid.database.edit.DeleteEntry; +import com.keepassdroid.database.edit.DeleteGroup; +import com.keepassdroid.groupentity.NodeAdapter; import com.kunzisoft.keepass.KeePass; import com.kunzisoft.keepass.R; import com.keepassdroid.app.App; @@ -46,7 +54,6 @@ import com.keepassdroid.database.PwGroupV3; import com.keepassdroid.database.PwGroupV4; import com.keepassdroid.database.edit.AddGroup; import com.keepassdroid.dialog.ReadOnlyDialog; -import com.keepassdroid.view.ClickView; import com.keepassdroid.view.GroupAddEntryView; import com.keepassdroid.view.GroupRootView; import com.keepassdroid.view.GroupViewOnlyView; @@ -182,8 +189,31 @@ public abstract class GroupActivity extends GroupBaseActivity setGroupTitle(); setGroupIcon(); - setListAdapter(new PwGroupListAdapter(this, mGroup)); - registerForContextMenu(getListView()); + NodeAdapter nodeAdapter = new NodeAdapter(this, mGroup); + nodeAdapter.setOnNodeClickListener(this); + nodeAdapter.setNodeMenuListener(new NodeAdapter.NodeMenuListener() { + @Override + public boolean onOpenMenuClick(PwNode node, int position) { + // TODO CHANGE by Pattern Strategy + if (node instanceof PwEntry) { + EntryActivity.Launch(GroupActivity.this, (PwEntry) node, position); + } else if (node instanceof PwGroup) + GroupActivity.Launch(GroupActivity.this, (PwGroup) node); + return true; + } + + @Override + public boolean onDeleteMenuClick(PwNode node, int position) { + // TODO CHANGE + if(node instanceof PwEntry) + deleteEntry((PwEntry) node); + else if (node instanceof PwGroup) { + deleteGroup((PwGroup) node); + } + return true; + } + }); + setNodeAdapter(nodeAdapter); Log.w(TAG, "Finished creating tree"); if (isRoot) { @@ -191,6 +221,20 @@ public abstract class GroupActivity extends GroupBaseActivity } } + private void deleteEntry(PwEntry entry) { + Handler handler = new Handler(); + DeleteEntry task = new DeleteEntry(this, App.getDB(), entry, new RefreshTask(handler)); + ProgressTask pt = new ProgressTask(this, task, R.string.saving_database); + pt.run(); + } + + private void deleteGroup(PwGroup group) { + Handler handler = new Handler(); + DeleteGroup task = new DeleteGroup(App.getDB(), group, GroupActivity.this, new AfterDeleteGroup(handler)); + ProgressTask pt = new ProgressTask(GroupActivity.this, task, R.string.saving_database); + pt.run(); + } + @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { @@ -201,23 +245,6 @@ public abstract class GroupActivity extends GroupBaseActivity return super.onOptionsItemSelected(item); } - @Override - public void onCreateContextMenu(ContextMenu menu, View v, - ContextMenuInfo menuInfo) { - - AdapterContextMenuInfo acmi = (AdapterContextMenuInfo) menuInfo; - ClickView cv = (ClickView) acmi.targetView; - cv.onCreateMenu(menu, menuInfo); - } - - @Override - public boolean onContextItemSelected(MenuItem item) { - AdapterContextMenuInfo acmi = (AdapterContextMenuInfo) item.getMenuInfo(); - ClickView cv = (ClickView) acmi.targetView; - - return cv.onContextItemSelected(item); - } - @Override public void approveCreateGroup(Bundle bundle) { String GroupName = bundle.getString(GroupEditFragment.KEY_NAME); diff --git a/app/src/main/java/com/keepassdroid/GroupActivityV3.java b/app/src/main/java/com/keepassdroid/activity/GroupActivityV3.java similarity index 97% rename from app/src/main/java/com/keepassdroid/GroupActivityV3.java rename to app/src/main/java/com/keepassdroid/activity/GroupActivityV3.java index ed296c0c8..aabef5939 100644 --- a/app/src/main/java/com/keepassdroid/GroupActivityV3.java +++ b/app/src/main/java/com/keepassdroid/activity/GroupActivityV3.java @@ -17,7 +17,7 @@ * along with KeePass DX. If not, see . * */ -package com.keepassdroid; +package com.keepassdroid.activity; import android.content.Intent; diff --git a/app/src/main/java/com/keepassdroid/GroupActivityV4.java b/app/src/main/java/com/keepassdroid/activity/GroupActivityV4.java similarity index 97% rename from app/src/main/java/com/keepassdroid/GroupActivityV4.java rename to app/src/main/java/com/keepassdroid/activity/GroupActivityV4.java index 216d38b89..b7c1e1953 100644 --- a/app/src/main/java/com/keepassdroid/GroupActivityV4.java +++ b/app/src/main/java/com/keepassdroid/activity/GroupActivityV4.java @@ -17,7 +17,7 @@ * along with KeePass DX. If not, see . * */ -package com.keepassdroid; +package com.keepassdroid.activity; import java.util.UUID; diff --git a/app/src/main/java/com/keepassdroid/GroupBaseActivity.java b/app/src/main/java/com/keepassdroid/activity/GroupBaseActivity.java similarity index 88% rename from app/src/main/java/com/keepassdroid/GroupBaseActivity.java rename to app/src/main/java/com/keepassdroid/activity/GroupBaseActivity.java index b5bda2951..f8f613113 100644 --- a/app/src/main/java/com/keepassdroid/GroupBaseActivity.java +++ b/app/src/main/java/com/keepassdroid/activity/GroupBaseActivity.java @@ -17,7 +17,7 @@ * along with KeePass DX. If not, see . * */ -package com.keepassdroid; +package com.keepassdroid.activity; import android.app.SearchManager; import android.content.ComponentName; @@ -25,40 +25,45 @@ import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.content.SharedPreferences.Editor; -import android.os.Build; import android.net.Uri; +import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.preference.PreferenceManager; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; import android.support.v7.widget.SearchView; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; -import android.widget.AdapterView; -import android.widget.BaseAdapter; import android.widget.ImageView; -import android.widget.ListAdapter; -import android.widget.ListView; import android.widget.TextView; +import com.keepassdroid.AssignMasterKeyDialog; +import com.keepassdroid.Database; +import com.keepassdroid.EntryActivity; +import com.keepassdroid.LockCloseListActivity; +import com.keepassdroid.UIToastTask; import com.keepassdroid.app.App; import com.keepassdroid.compat.ActivityCompat; import com.keepassdroid.compat.EditorCompat; +import com.keepassdroid.database.PwEntry; import com.keepassdroid.database.PwGroup; import com.keepassdroid.database.edit.OnFinish; +import com.keepassdroid.groupentity.NodeAdapter; import com.keepassdroid.search.SearchResultsActivity; import com.keepassdroid.utils.MenuUtil; import com.keepassdroid.view.AssignPasswordHelper; -import com.keepassdroid.view.ClickView; import com.keepassdroid.view.GroupViewOnlyView; import com.kunzisoft.keepass.KeePass; import com.kunzisoft.keepass.R; public abstract class GroupBaseActivity extends LockCloseListActivity - implements AssignMasterKeyDialog.AssignPasswordDialogListener { - protected ListView mList; - protected ListAdapter mAdapter; + implements AssignMasterKeyDialog.AssignPasswordDialogListener, + NodeAdapter.OnNodeClickCallback { + protected RecyclerView mList; + protected NodeAdapter mAdapter; public static final String KEY_ENTRY = "entry"; @@ -77,16 +82,10 @@ public abstract class GroupBaseActivity extends LockCloseListActivity Database db = App.getDB(); if ( db.dirty.contains(mGroup) ) { db.dirty.remove(mGroup); - ((BaseAdapter) mAdapter).notifyDataSetChanged(); + mAdapter.notifyDataSetChangedAndSort(); } } - protected void onListItemClick(ListView l, View v, int position, long id) { - ClickView cv = (ClickView) mAdapter.getView(position, null, null); - cv.onClick(); - - } - @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -111,8 +110,7 @@ public abstract class GroupBaseActivity extends LockCloseListActivity protected void styleScrollBars() { ensureCorrectListView(); mList.setScrollBarStyle(View.SCROLLBARS_INSIDE_INSET); - mList.setTextFilterEnabled(true); - + // TODO mList.setTextFilterEnabled(true); } protected void setGroupTitle() { @@ -139,31 +137,28 @@ public abstract class GroupBaseActivity extends LockCloseListActivity } } - protected void setListAdapter(ListAdapter adapter) { + protected void setNodeAdapter(NodeAdapter adapter) { ensureCorrectListView(); mAdapter = adapter; mList.setAdapter(adapter); } - protected ListView getListView() { - ensureCorrectListView(); - return mList; + private void ensureCorrectListView(){ + mList = (RecyclerView) findViewById(R.id.group_list); + mList.setLayoutManager(new LinearLayoutManager(this)); } - private void ensureCorrectListView(){ - mList = (ListView)findViewById(R.id.group_list); - if (mList != null) { - mList.setOnItemClickListener( - new AdapterView.OnItemClickListener() { - public void onItemClick(AdapterView parent, View v, int position, long id) { - onListItemClick((ListView) parent, v, position, id); - } - } - ); - } - } - - @Override + @Override + public void onGroupClicked(PwGroup group) { + GroupActivity.Launch(this, group); + } + + @Override + public void onEntryClicked(PwEntry entry, int position) { + EntryActivity.Launch(this, entry, position); + } + + @Override public boolean onCreateOptionsMenu(Menu menu) { super.onCreateOptionsMenu(menu); @@ -266,8 +261,7 @@ public abstract class GroupBaseActivity extends LockCloseListActivity db.dirty.remove(mGroup); // Tell the adapter to refresh it's list - ((BaseAdapter) mAdapter).notifyDataSetChanged(); - + mAdapter.notifyDataSetChangedAndSort(); } @Override diff --git a/app/src/main/java/com/keepassdroid/database/PwEntry.java b/app/src/main/java/com/keepassdroid/database/PwEntry.java index ee2213301..7361143e3 100644 --- a/app/src/main/java/com/keepassdroid/database/PwEntry.java +++ b/app/src/main/java/com/keepassdroid/database/PwEntry.java @@ -26,7 +26,7 @@ import java.util.UUID; import com.keepassdroid.database.iterator.EntrySearchStringIterator; import com.keepassdroid.utils.SprEngine; -public abstract class PwEntry implements Cloneable { +public abstract class PwEntry extends PwNode implements Cloneable { protected static final String PMS_TAN_ENTRY = ""; diff --git a/app/src/main/java/com/keepassdroid/database/PwGroup.java b/app/src/main/java/com/keepassdroid/database/PwGroup.java index 2d317dfab..24388c910 100644 --- a/app/src/main/java/com/keepassdroid/database/PwGroup.java +++ b/app/src/main/java/com/keepassdroid/database/PwGroup.java @@ -27,7 +27,7 @@ import java.util.List; import com.keepassdroid.utils.StrUtil; -public abstract class PwGroup { +public abstract class PwGroup extends PwNode { public List childGroups = new ArrayList(); public List childEntries = new ArrayList(); public String name = ""; diff --git a/app/src/main/java/com/keepassdroid/database/PwNode.java b/app/src/main/java/com/keepassdroid/database/PwNode.java new file mode 100644 index 000000000..d021ab456 --- /dev/null +++ b/app/src/main/java/com/keepassdroid/database/PwNode.java @@ -0,0 +1,4 @@ +package com.keepassdroid.database; + +public class PwNode { +} diff --git a/app/src/main/java/com/keepassdroid/database/edit/DeleteGroup.java b/app/src/main/java/com/keepassdroid/database/edit/DeleteGroup.java index 8477ee55e..cfb92b4de 100644 --- a/app/src/main/java/com/keepassdroid/database/edit/DeleteGroup.java +++ b/app/src/main/java/com/keepassdroid/database/edit/DeleteGroup.java @@ -23,7 +23,7 @@ import java.util.ArrayList; import java.util.List; import com.keepassdroid.Database; -import com.keepassdroid.GroupBaseActivity; +import com.keepassdroid.activity.GroupBaseActivity; import com.keepassdroid.app.App; import com.keepassdroid.database.PwEntry; import com.keepassdroid.database.PwGroup; diff --git a/app/src/main/java/com/keepassdroid/fileselect/FileSelectActivity.java b/app/src/main/java/com/keepassdroid/fileselect/FileSelectActivity.java index 498d8dfec..3335a8a26 100644 --- a/app/src/main/java/com/keepassdroid/fileselect/FileSelectActivity.java +++ b/app/src/main/java/com/keepassdroid/fileselect/FileSelectActivity.java @@ -43,7 +43,7 @@ import android.widget.Toast; import com.keepassdroid.AssignMasterKeyDialog; import com.keepassdroid.CreateFileDialog; -import com.keepassdroid.GroupActivity; +import com.keepassdroid.activity.GroupActivity; import com.keepassdroid.PasswordActivity; import com.keepassdroid.ProgressTask; import com.keepassdroid.app.App; diff --git a/app/src/main/java/com/keepassdroid/fileselect/FileSelectAdapter.java b/app/src/main/java/com/keepassdroid/fileselect/FileSelectAdapter.java index 15f2328f9..9295a4ff5 100644 --- a/app/src/main/java/com/keepassdroid/fileselect/FileSelectAdapter.java +++ b/app/src/main/java/com/keepassdroid/fileselect/FileSelectAdapter.java @@ -52,7 +52,7 @@ public class FileSelectAdapter extends RecyclerView.Adapter listFiles) { - inflater = LayoutInflater.from(context); + this.inflater = LayoutInflater.from(context); this.context = context; this.listFiles = listFiles; @@ -65,7 +65,8 @@ public class FileSelectAdapter extends RecyclerView.Adapter { + + private enum ViewTypes { + ENTRY, GROUP + } + + private static final int MENU_OPEN = Menu.FIRST; + private static final int MENU_DELETE = MENU_OPEN + 1; + + private Context context; + private LayoutInflater inflater; + private PwGroup pwGroup; + private float textSize; + + private OnNodeClickCallback onNodeClickCallback; + private NodeMenuListener nodeMenuListener; + + private List groupsForViewing; + private List entriesForViewing; + private Comparator entryComp = new PwEntry.EntryNameComparator(); + private Comparator groupComp = new PwGroup.GroupNameComparator(); + private SharedPreferences prefs; + + public NodeAdapter(Context context, PwGroup pwGroup) { + this.inflater = LayoutInflater.from(context); + this.context = context; + this.pwGroup = pwGroup; + this.prefs = PreferenceManager.getDefaultSharedPreferences(context); + this.textSize = PrefsUtil.getListTextSize(context); + + filterAndSort(); + } + + public void notifyDataSetChangedAndSort() { + super.notifyDataSetChanged(); + filterAndSort(); + } + + @Override + public int getItemViewType(int position) { + if ( position < groupsForViewing.size() ) { + return ViewTypes.GROUP.ordinal(); + } else { + return ViewTypes.ENTRY.ordinal(); + } + } + + @Override + public BasicViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + BasicViewHolder basicViewHolder; + View view; + if (viewType == ViewTypes.GROUP.ordinal()) { + view = inflater.inflate(R.layout.list_entries_group, parent, false); + basicViewHolder = new GroupViewHolder(view); + } else { + view = inflater.inflate(R.layout.list_entries_entry, parent, false); + basicViewHolder = new EntryViewHolder(view); + } + return basicViewHolder; + } + + // TODO change location + private void filterAndSort() { + entriesForViewing = new ArrayList<>(); + + if (pwGroup != null) { + for (int i = 0; i < pwGroup.childEntries.size(); i++) { + PwEntry entry = pwGroup.childEntries.get(i); + if (!entry.isMetaStream()) { + entriesForViewing.add(entry); + } + } + + // TODO Move in prefs + boolean sortLists = prefs.getBoolean( + context.getString(R.string.sort_key), + context.getResources().getBoolean(R.bool.sort_default)); + + if (sortLists) { + groupsForViewing = new ArrayList<>(pwGroup.childGroups); + + Collections.sort(entriesForViewing, entryComp); + Collections.sort(groupsForViewing, groupComp); + } else { + groupsForViewing = pwGroup.childGroups; + } + } + } + + @Override + public void onBindViewHolder(BasicViewHolder holder, int position) { + int listGroupsSize = groupsForViewing.size(); + if ( position < listGroupsSize ) { + PwGroup group = groupsForViewing.get(position); + // Assign image + App.getDB().drawFactory.assignDrawableTo(holder.icon, + context.getResources(), group.getIcon()); + // Assign text + holder.text.setText(group.getName()); + // Assign click + holder.container.setOnClickListener( + new OnGroupClickListener(group)); + holder.container.setOnCreateContextMenuListener( + new ContextMenuBuilder(group, position, nodeMenuListener)); + } else { + int entryPosition = position - listGroupsSize; + PwEntry entry = entriesForViewing.get(entryPosition); + App.getDB().drawFactory.assignDrawableTo(holder.icon, + context.getResources(), entry.getIcon()); + // Assign text + holder.text.setText(entry.getDisplayTitle()); + // Assign click + holder.container.setOnClickListener( + new OnEntryClickListener(entry, position)); + holder.container.setOnCreateContextMenuListener( + new ContextMenuBuilder(entry, entryPosition, nodeMenuListener)); + } + // Assign text size + holder.text.setTextSize(textSize); + } + + @Override + public int getItemCount() { + return groupsForViewing.size() + entriesForViewing.size(); + } + + public void setOnNodeClickListener(OnNodeClickCallback onNodeClickCallback) { + this.onNodeClickCallback = onNodeClickCallback; + } + + public void setNodeMenuListener(NodeMenuListener nodeMenuListener) { + this.nodeMenuListener = nodeMenuListener; + } + + public interface OnNodeClickCallback { + void onGroupClicked(PwGroup group); + void onEntryClicked(PwEntry entry, int position); + } + + private class OnGroupClickListener implements View.OnClickListener { + private PwGroup group; + + OnGroupClickListener(PwGroup group) { + this.group = group; + } + + @Override + public void onClick(View v) { + if (onNodeClickCallback != null) + onNodeClickCallback.onGroupClicked(group); + } + } + + public class OnEntryClickListener implements View.OnClickListener { + private PwEntry entry; + private int position; + + OnEntryClickListener(PwEntry entry, int position) { + this.entry = entry; + this.position = position; + } + + @Override + public void onClick(View v) { + if (onNodeClickCallback != null) + onNodeClickCallback.onEntryClicked(entry, position); + } + } + + public interface NodeMenuListener { + boolean onOpenMenuClick(PwNode node, int position); + boolean onDeleteMenuClick(PwNode node, int position); + } + + private class ContextMenuBuilder implements View.OnCreateContextMenuListener { + + private PwNode node; + private int position; + private NodeMenuListener menuListener; + + public ContextMenuBuilder(PwNode node, int position, NodeMenuListener menuListener) { + this.menuListener = menuListener; + this.node = node; + this.position = position; + } + + @Override + public void onCreateContextMenu(ContextMenu contextMenu, View view, ContextMenu.ContextMenuInfo contextMenuInfo) { + MenuItem clearMenu = contextMenu.add(Menu.NONE, MENU_OPEN, Menu.NONE, R.string.menu_open); + clearMenu.setOnMenuItemClickListener(mOnMyActionClickListener); + if (!App.getDB().readOnly) { + clearMenu = contextMenu.add(Menu.NONE, MENU_DELETE, Menu.NONE, R.string.menu_delete); + clearMenu.setOnMenuItemClickListener(mOnMyActionClickListener); + } + } + + private MenuItem.OnMenuItemClickListener mOnMyActionClickListener = new MenuItem.OnMenuItemClickListener() { + @Override + public boolean onMenuItemClick(MenuItem item) { + if (menuListener == null) + return false; + switch ( item.getItemId() ) { + case MENU_OPEN: + return menuListener.onOpenMenuClick(node, position); + case MENU_DELETE: + return menuListener.onDeleteMenuClick(node, position); + default: + return false; + } + } + }; + } +} diff --git a/app/src/main/java/com/keepassdroid/icons/DrawableFactory.java b/app/src/main/java/com/keepassdroid/icons/DrawableFactory.java index 802e615e8..5f5128faa 100644 --- a/app/src/main/java/com/keepassdroid/icons/DrawableFactory.java +++ b/app/src/main/java/com/keepassdroid/icons/DrawableFactory.java @@ -53,7 +53,8 @@ public class DrawableFactory { public void assignDrawableTo(ImageView iv, Resources res, PwIcon icon) { Drawable draw = getIconDrawable(res, icon); - iv.setImageDrawable(draw); + if (iv != null && draw != null) + iv.setImageDrawable(draw); } private Drawable getIconDrawable(Resources res, PwIcon icon) { diff --git a/app/src/main/java/com/keepassdroid/search/SearchResultsActivity.java b/app/src/main/java/com/keepassdroid/search/SearchResultsActivity.java index 7ee178a66..bd83e6362 100644 --- a/app/src/main/java/com/keepassdroid/search/SearchResultsActivity.java +++ b/app/src/main/java/com/keepassdroid/search/SearchResultsActivity.java @@ -28,11 +28,11 @@ import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; +import com.keepassdroid.groupentity.NodeAdapter; import com.kunzisoft.keepass.KeePass; import com.kunzisoft.keepass.R; import com.keepassdroid.Database; -import com.keepassdroid.GroupBaseActivity; -import com.keepassdroid.PwGroupListAdapter; +import com.keepassdroid.activity.GroupBaseActivity; import com.keepassdroid.app.App; import com.keepassdroid.utils.MenuUtil; @@ -41,7 +41,7 @@ public class SearchResultsActivity extends GroupBaseActivity { private Database mDb; private View listView; - private View imageNotFoundView; + private View notFoundView; @Override protected void onCreate(Bundle savedInstanceState) { @@ -70,7 +70,7 @@ public class SearchResultsActivity extends GroupBaseActivity { getSupportActionBar().setDisplayShowHomeEnabled(true); listView = findViewById(R.id.group_list); - imageNotFoundView = findViewById(R.id.img_not_found); + notFoundView = findViewById(R.id.not_found_container); performSearch(getSearchStr(getIntent())); @@ -101,15 +101,15 @@ public class SearchResultsActivity extends GroupBaseActivity { if ( mGroup == null || mGroup.childEntries.size() < 1 ) { listView.setVisibility(View.GONE); - imageNotFoundView.setVisibility(View.VISIBLE); + notFoundView.setVisibility(View.VISIBLE); } else { listView.setVisibility(View.VISIBLE); - imageNotFoundView.setVisibility(View.GONE); + notFoundView.setVisibility(View.GONE); } setGroupTitle(); - setListAdapter(new PwGroupListAdapter(this, mGroup)); + setNodeAdapter(new NodeAdapter(this, mGroup)); } private String getSearchStr(Intent queryIntent) { diff --git a/app/src/main/java/com/keepassdroid/view/PwEntryView.java b/app/src/main/java/com/keepassdroid/view/PwEntryView.java deleted file mode 100644 index faa96c611..000000000 --- a/app/src/main/java/com/keepassdroid/view/PwEntryView.java +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Copyright 2017 Brian Pellin, Jeremy Jamet / Kunzisoft. - * - * This file is part of KeePass DX. - * - * KeePass DX is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * KeePass DX is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with KeePass DX. If not, see . - * - */ -package com.keepassdroid.view; - - -import android.os.Handler; -import android.view.ContextMenu; -import android.view.ContextMenu.ContextMenuInfo; -import android.view.Menu; -import android.view.MenuItem; -import android.view.View; -import android.widget.ImageView; -import android.widget.TextView; - -import com.kunzisoft.keepass.R; -import com.keepassdroid.EntryActivity; -import com.keepassdroid.GroupBaseActivity; -import com.keepassdroid.ProgressTask; -import com.keepassdroid.app.App; -import com.keepassdroid.database.PwEntry; -import com.keepassdroid.database.edit.DeleteEntry; -import com.keepassdroid.settings.PrefsUtil; - -public class PwEntryView extends ClickView { - - protected GroupBaseActivity mAct; - protected PwEntry mPw; - private TextView mTv; - private int mPos; - - protected static final int MENU_OPEN = Menu.FIRST; - private static final int MENU_DELETE = MENU_OPEN + 1; - - public static PwEntryView getInstance(GroupBaseActivity act, PwEntry pw, int pos) { - return new PwEntryView(act, pw, pos); - } - - protected PwEntryView(GroupBaseActivity act, PwEntry pw, int pos) { - super(act); - mAct = act; - - View ev = View.inflate(mAct, R.layout.list_entries_entry, null); - mTv = (TextView) ev.findViewById(R.id.entry_text); - mTv.setTextSize(PrefsUtil.getListTextSize(act)); - - populateView(ev, pw, pos); - - LayoutParams lp = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT); - - addView(ev, lp); - - } - - private void populateView(View ev, PwEntry pw, int pos) { - mPw = pw; - mPos = pos; - - ImageView iv = (ImageView) ev.findViewById(R.id.entry_icon); - App.getDB().drawFactory.assignDrawableTo(iv, getResources(), pw.getIcon()); - - mTv.setText(mPw.getDisplayTitle()); - } - - public void convertView(PwEntry pw, int pos) { - populateView(this, pw, pos); - } - - public void refreshTitle() { - mTv.setText(mPw.getDisplayTitle()); - } - - public void onClick() { - launchEntry(); - } - - private void launchEntry() { - EntryActivity.Launch(mAct, mPw, mPos); - - } - - private void deleteEntry() { - Handler handler = new Handler(); - DeleteEntry task = new DeleteEntry(mAct, App.getDB(), mPw, mAct.new RefreshTask(handler)); - ProgressTask pt = new ProgressTask(mAct, task, R.string.saving_database); - pt.run(); - - } - - @Override - public void onCreateMenu(ContextMenu menu, ContextMenuInfo menuInfo) { - menu.add(0, MENU_OPEN, 0, R.string.menu_open); - if (!readOnly) { - menu.add(0, MENU_DELETE, 0, R.string.menu_delete); - } - } - - @Override - public boolean onContextItemSelected(MenuItem item) { - switch ( item.getItemId() ) { - - case MENU_OPEN: - launchEntry(); - return true; - case MENU_DELETE: - deleteEntry(); - return true; - - default: - return false; - } - } - - -} diff --git a/app/src/main/java/com/keepassdroid/view/PwGroupView.java b/app/src/main/java/com/keepassdroid/view/PwGroupView.java deleted file mode 100644 index 14242ab24..000000000 --- a/app/src/main/java/com/keepassdroid/view/PwGroupView.java +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright 2017 Brian Pellin, Jeremy Jamet / Kunzisoft. - * - * This file is part of KeePass DX. - * - * KeePass DX is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * KeePass DX is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with KeePass DX. If not, see . - * - */ -package com.keepassdroid.view; - - -import android.view.ContextMenu; -import android.view.Menu; -import android.view.MenuItem; -import android.view.View; -import android.view.ContextMenu.ContextMenuInfo; -import android.widget.ImageView; -import android.widget.TextView; - -import com.kunzisoft.keepass.R; -import com.keepassdroid.GroupActivity; -import com.keepassdroid.GroupBaseActivity; -import com.keepassdroid.app.App; -import com.keepassdroid.database.PwGroup; -import com.keepassdroid.database.PwGroupV3; -import com.keepassdroid.settings.PrefsUtil; - - -public class PwGroupView extends ClickView { - - protected PwGroup mPw; - protected GroupBaseActivity mAct; - protected TextView mTv; - - protected static final int MENU_OPEN = Menu.FIRST; - - public static PwGroupView getInstance(GroupBaseActivity act, PwGroup pw) { - if ( pw instanceof PwGroupV3 ) { - return new PwGroupViewV3(act, pw); - } else { - return new PwGroupView(act, pw); - } - } - - protected PwGroupView(GroupBaseActivity act, PwGroup pw) { - super(act); - mAct = act; - - View gv = View.inflate(act, R.layout.list_entries_group, null); - - mTv = (TextView) gv.findViewById(R.id.group_text); - float size = PrefsUtil.getListTextSize(act); - mTv.setTextSize(size); - - TextView label = (TextView) gv.findViewById(R.id.group_label); - label.setTextSize(size-8); - - populateView(gv, pw); - - LayoutParams lp = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT); - - addView(gv, lp); - } - - private void populateView(View gv, PwGroup pw) { - mPw = pw; - - ImageView iv = (ImageView) gv.findViewById(R.id.group_icon); - App.getDB().drawFactory.assignDrawableTo(iv, getResources(), pw.getIcon()); - - mTv.setText(pw.getName()); - } - - public void convertView(PwGroup pw) { - populateView(this, pw); - } - - public void onClick() { - launchGroup(); - } - - private void launchGroup() { - GroupActivity.Launch(mAct, mPw); - } - - @Override - public void onCreateMenu(ContextMenu menu, ContextMenuInfo menuInfo) { - menu.add(0, MENU_OPEN, 0, R.string.menu_open); - } - - @Override - public boolean onContextItemSelected(MenuItem item) { - switch ( item.getItemId() ) { - - case MENU_OPEN: - launchGroup(); - return true; - - default: - return false; - } - } - -} \ No newline at end of file diff --git a/app/src/main/java/com/keepassdroid/view/PwGroupViewV3.java b/app/src/main/java/com/keepassdroid/view/PwGroupViewV3.java deleted file mode 100644 index 0797d419c..000000000 --- a/app/src/main/java/com/keepassdroid/view/PwGroupViewV3.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright 2017 Brian Pellin, Jeremy Jamet / Kunzisoft. - * - * This file is part of KeePass DX. - * - * KeePass DX is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * KeePass DX is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with KeePass DX. If not, see . - * - */ -package com.keepassdroid.view; - -import android.os.Handler; -import android.view.ContextMenu; -import android.view.MenuItem; -import android.view.ContextMenu.ContextMenuInfo; - -import com.kunzisoft.keepass.R; -import com.keepassdroid.GroupBaseActivity; -import com.keepassdroid.ProgressTask; -import com.keepassdroid.app.App; -import com.keepassdroid.database.PwGroup; -import com.keepassdroid.database.edit.DeleteGroup; - -public class PwGroupViewV3 extends PwGroupView { - - private static final int MENU_DELETE = MENU_OPEN + 1; - - protected PwGroupViewV3(GroupBaseActivity act, PwGroup pw) { - super(act, pw); - } - - @Override - public void onCreateMenu(ContextMenu menu, ContextMenuInfo menuInfo) { - super.onCreateMenu(menu, menuInfo); - - if (!readOnly) { - menu.add(0, MENU_DELETE, 0, R.string.menu_delete); - } - - } - - @Override - public boolean onContextItemSelected(MenuItem item) { - if ( ! super.onContextItemSelected(item) ) { - switch ( item.getItemId() ) { - case MENU_DELETE: - Handler handler = new Handler(); - DeleteGroup task = new DeleteGroup(App.getDB(), mPw, mAct, mAct.new AfterDeleteGroup(handler)); - ProgressTask pt = new ProgressTask(mAct, task, R.string.saving_database); - pt.run(); - return true; - } - - } - - return false; - } - -} diff --git a/app/src/main/res/layout/group_add_entry.xml b/app/src/main/res/layout/group_add_entry.xml index 94e7e06d4..c8c63b972 100644 --- a/app/src/main/res/layout/group_add_entry.xml +++ b/app/src/main/res/layout/group_add_entry.xml @@ -43,12 +43,10 @@ android:layout_below="@+id/toolbar" /> - + android:layout_below="@+id/toolbar" /> - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/list_entries_entry.xml b/app/src/main/res/layout/list_entries_entry.xml index 0b8913078..df85a7509 100644 --- a/app/src/main/res/layout/list_entries_entry.xml +++ b/app/src/main/res/layout/list_entries_entry.xml @@ -18,9 +18,11 @@ along with KeePass DX. If not, see . --> + android:layout_height="wrap_content" + android:layout_gravity="center_vertical" + android:background="?android:attr/selectableItemBackground" > . --> + android:layout_height="wrap_content" + android:layout_gravity="center_vertical" + android:background="?android:attr/selectableItemBackground" > + android:layout_toRightOf="@+id/group_arrow" + android:layout_toEndOf="@+id/group_arrow" /> - - \ No newline at end of file diff --git a/app/src/main/res/layout/search_results.xml b/app/src/main/res/layout/search_results.xml index adf146559..9b2c7fac1 100644 --- a/app/src/main/res/layout/search_results.xml +++ b/app/src/main/res/layout/search_results.xml @@ -29,12 +29,25 @@ android:layout_width="match_parent" android:layout_height="match_parent" android:layout_below="@+id/toolbar"> - - + + + +