ListView as RecyclerView,

Update SearchView,
Create Activity package
This commit is contained in:
Jeremy
2018-02-09 12:45:45 +01:00
parent a9e12cb518
commit 3a71f635f0
28 changed files with 438 additions and 620 deletions

View File

@@ -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"

View File

@@ -91,11 +91,11 @@
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.kdbx" />
</intent-filter>
</activity>
<activity android:name="com.keepassdroid.GroupActivityV3" android:configChanges="orientation|keyboardHidden">
<activity android:name="com.keepassdroid.activity.GroupActivityV3" android:configChanges="orientation|keyboardHidden">
<meta-data android:name="android.app.default_searchable"
android:value="com.keepassdroid.search.SearchResults" />
</activity>
<activity android:name="com.keepassdroid.GroupActivityV4" android:configChanges="orientation|keyboardHidden">
<activity android:name="com.keepassdroid.activity.GroupActivityV4" android:configChanges="orientation|keyboardHidden">
<meta-data android:name="android.app.default_searchable"
android:value="com.keepassdroid.search.SearchResults"
android:exported="false" />

View File

@@ -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;

View File

@@ -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 <http://www.gnu.org/licenses/>.
*
*/
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<PwGroup> groupsForViewing;
private List<PwEntry> entriesForViewing;
private Comparator<PwEntry> entryComp = new PwEntry.EntryNameComparator();
private Comparator<PwGroup> 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<PwEntry>();
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<PwGroup>(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;
}
}

View File

@@ -17,7 +17,7 @@
* along with KeePass DX. If not, see <http://www.gnu.org/licenses/>.
*
*/
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);

View File

@@ -17,7 +17,7 @@
* along with KeePass DX. If not, see <http://www.gnu.org/licenses/>.
*
*/
package com.keepassdroid;
package com.keepassdroid.activity;
import android.content.Intent;

View File

@@ -17,7 +17,7 @@
* along with KeePass DX. If not, see <http://www.gnu.org/licenses/>.
*
*/
package com.keepassdroid;
package com.keepassdroid.activity;
import java.util.UUID;

View File

@@ -17,7 +17,7 @@
* along with KeePass DX. If not, see <http://www.gnu.org/licenses/>.
*
*/
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,28 +137,25 @@ 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
public void onGroupClicked(PwGroup group) {
GroupActivity.Launch(this, group);
}
@Override
public void onEntryClicked(PwEntry entry, int position) {
EntryActivity.Launch(this, entry, position);
}
@Override
@@ -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

View File

@@ -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 = "<TAN>";

View File

@@ -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<PwGroup> childGroups = new ArrayList<PwGroup>();
public List<PwEntry> childEntries = new ArrayList<PwEntry>();
public String name = "";

View File

@@ -0,0 +1,4 @@
package com.keepassdroid.database;
public class PwNode {
}

View File

@@ -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;

View File

@@ -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;

View File

@@ -52,7 +52,7 @@ public class FileSelectAdapter extends RecyclerView.Adapter<FileSelectViewHolder
int warningColor;
FileSelectAdapter(Context context, List<String> listFiles) {
inflater = LayoutInflater.from(context);
this.inflater = LayoutInflater.from(context);
this.context = context;
this.listFiles = listFiles;
@@ -65,6 +65,7 @@ public class FileSelectAdapter extends RecyclerView.Adapter<FileSelectViewHolder
@Override
public FileSelectViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = inflater.inflate(R.layout.file_row, parent, false);
if (mOnClickListener != null)
view.setOnClickListener(mOnClickListener);
return new FileSelectViewHolder(view);
}
@@ -146,15 +147,15 @@ public class FileSelectAdapter extends RecyclerView.Adapter<FileSelectViewHolder
private MenuItem.OnMenuItemClickListener mOnMyActionClickListener = new MenuItem.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
if (item.getItemId() == MENU_CLEAR) {
return fileSelectClearListener.onFileSelectClearListener(fileSelectBean);
}
if (fileSelectClearListener == null)
return false;
switch ( item.getItemId() ) {
case MENU_CLEAR:
return fileSelectClearListener.onFileSelectClearListener(fileSelectBean);
default:
return false;
}
}
};
}
}

View File

@@ -0,0 +1,18 @@
package com.keepassdroid.groupentity;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
// TODO Refactor
public abstract class BasicViewHolder extends RecyclerView.ViewHolder {
View container;
ImageView icon;
TextView text;
BasicViewHolder(View itemView) {
super(itemView);
}
}

View File

@@ -0,0 +1,17 @@
package com.keepassdroid.groupentity;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import com.kunzisoft.keepass.R;
public class EntryViewHolder extends BasicViewHolder {
EntryViewHolder(View itemView) {
super(itemView);
container = itemView.findViewById(R.id.entry_container);
icon = (ImageView) itemView.findViewById(R.id.entry_icon);
text = (TextView) itemView.findViewById(R.id.entry_text);
}
}

View File

@@ -0,0 +1,17 @@
package com.keepassdroid.groupentity;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import com.kunzisoft.keepass.R;
public class GroupViewHolder extends BasicViewHolder {
GroupViewHolder(View itemView) {
super(itemView);
container = itemView.findViewById(R.id.group_container);
icon = (ImageView) itemView.findViewById(R.id.group_icon);
text = (TextView) itemView.findViewById(R.id.group_text);
}
}

View File

@@ -0,0 +1,238 @@
package com.keepassdroid.groupentity;
import android.content.Context;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import android.support.v7.widget.RecyclerView;
import android.view.ContextMenu;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import com.keepassdroid.app.App;
import com.keepassdroid.database.PwEntry;
import com.keepassdroid.database.PwGroup;
import com.keepassdroid.database.PwNode;
import com.keepassdroid.settings.PrefsUtil;
import com.kunzisoft.keepass.R;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class NodeAdapter extends RecyclerView.Adapter<BasicViewHolder> {
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<PwGroup> groupsForViewing;
private List<PwEntry> entriesForViewing;
private Comparator<PwEntry> entryComp = new PwEntry.EntryNameComparator();
private Comparator<PwGroup> 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;
}
}
};
}
}

View File

@@ -53,6 +53,7 @@ public class DrawableFactory {
public void assignDrawableTo(ImageView iv, Resources res, PwIcon icon) {
Drawable draw = getIconDrawable(res, icon);
if (iv != null && draw != null)
iv.setImageDrawable(draw);
}

View File

@@ -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) {

View File

@@ -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 <http://www.gnu.org/licenses/>.
*
*/
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;
}
}
}

View File

@@ -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 <http://www.gnu.org/licenses/>.
*
*/
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;
}
}
}

View File

@@ -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 <http://www.gnu.org/licenses/>.
*
*/
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;
}
}

View File

@@ -43,12 +43,10 @@
android:layout_below="@+id/toolbar" />
</android.support.v7.widget.Toolbar>
<ListView android:id="@+id/group_list"
<android.support.v7.widget.RecyclerView android:id="@+id/group_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/toolbar"
android:divider="@null"
android:dividerHeight="0dp"/>
android:layout_below="@+id/toolbar" />
<android.support.design.widget.FloatingActionButton
android:id="@+id/add_button"

View File

@@ -1,36 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
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 <http://www.gnu.org/licenses/>.
-->
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.keepassdroid.view.GroupHeaderView
android:id="@+id/group_header"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<ListView android:id="@+id/group_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/group_header"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/group_list"
android:text="@string/no_results"/>
</RelativeLayout>

View File

@@ -18,9 +18,11 @@
along with KeePass DX. If not, see <http://www.gnu.org/licenses/>.
-->
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/entry_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center_vertical">
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:background="?android:attr/selectableItemBackground" >
<android.support.v7.widget.AppCompatImageView android:id="@+id/entry_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"

View File

@@ -18,12 +18,14 @@
along with KeePass DX. If not, see <http://www.gnu.org/licenses/>.
-->
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/group_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center_vertical">
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:background="?android:attr/selectableItemBackground" >
<android.support.v7.widget.AppCompatImageView
android:id="@+id/ic_arrow"
android:id="@+id/group_arrow"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_arrow_right_white_24dp"
@@ -46,8 +48,8 @@
android:scaleType="fitXY"
android:src="@drawable/ic99_blank"
android:layout_centerVertical="true"
android:layout_toRightOf="@+id/ic_arrow"
android:layout_toEndOf="@+id/ic_arrow" />
android:layout_toRightOf="@+id/group_arrow"
android:layout_toEndOf="@+id/group_arrow" />
<TextView android:id="@+id/group_text"
android:layout_width="wrap_content"
@@ -57,20 +59,6 @@
android:paddingBottom="2dp"
style="@style/KeepassDXStyle.TextAppearance.FolderTitle"
android:layout_centerVertical="true"
android:layout_toLeftOf="@+id/group_label"
android:layout_toStartOf="@+id/group_label"
android:layout_toRightOf="@+id/group_icon"
android:layout_toEndOf="@+id/group_icon" />
<TextView android:id="@+id/group_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:text="@string/group"
android:layout_margin="@dimen/default_margin"
style="@style/KeepassDXStyle.TextAppearance.SecondaryText"
android:visibility="gone"
android:layout_centerVertical="true"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true" />
</RelativeLayout>

View File

@@ -29,12 +29,25 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@+id/toolbar">
<android.support.v7.widget.AppCompatImageView android:id="@+id/img_not_found"
<LinearLayout
android:id="@+id/not_found_container"
android:layout_gravity="center"
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<android.support.v7.widget.AppCompatImageView
android:id="@+id/not_found_img"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:src="@drawable/img_not_found"/>
<ListView android:id="@+id/group_list"
<TextView
android:id="@+id/not_found_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/no_results"/>
</LinearLayout>
<android.support.v7.widget.RecyclerView android:id="@+id/group_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:divider="@null"