Remove useless dirty, solve trash bug

This commit is contained in:
J-Jamet
2018-02-16 15:14:24 +01:00
parent bb353bc9d6
commit 79750c5320
9 changed files with 142 additions and 162 deletions

View File

@@ -45,7 +45,6 @@ import com.keepassdroid.adapters.NodeAdapter;
import com.keepassdroid.app.App; import com.keepassdroid.app.App;
import com.keepassdroid.compat.ActivityCompat; import com.keepassdroid.compat.ActivityCompat;
import com.keepassdroid.compat.EditorCompat; import com.keepassdroid.compat.EditorCompat;
import com.keepassdroid.database.Database;
import com.keepassdroid.database.PwEntry; import com.keepassdroid.database.PwEntry;
import com.keepassdroid.database.PwGroup; import com.keepassdroid.database.PwGroup;
import com.keepassdroid.database.PwNode; import com.keepassdroid.database.PwNode;
@@ -72,19 +71,6 @@ public abstract class GroupBaseActivity extends LockCloseListActivity
protected PwGroup mCurrentGroup; protected PwGroup mCurrentGroup;
@Override
protected void onResume() {
super.onResume();
refreshIfDirty();
}
public void refreshIfDirty() {
Database db = App.getDB();
if ( db.dirty.contains(mCurrentGroup) ) {
db.dirty.remove(mCurrentGroup);
}
}
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
@@ -252,12 +238,6 @@ public abstract class GroupBaseActivity extends LockCloseListActivity
// Refresh menu titles // Refresh menu titles
ActivityCompat.invalidateOptionsMenu(this); ActivityCompat.invalidateOptionsMenu(this);
// Mark all groups as dirty now to refresh them on load
Database db = App.getDB();
db.markAllGroupsAsDirty();
// We'll manually refresh this tree so we can remove it
db.dirty.remove(mCurrentGroup);
// Tell the adapter to refresh it's list // Tell the adapter to refresh it's list
mAdapter.notifyChangeSort(); mAdapter.notifyChangeSort();
mAdapter.rebuildList(mCurrentGroup); mAdapter.rebuildList(mCurrentGroup);
@@ -294,7 +274,6 @@ public abstract class GroupBaseActivity extends LockCloseListActivity
public void run(PwNode pwNode) { public void run(PwNode pwNode) {
super.run(); super.run();
if (mSuccess) { if (mSuccess) {
refreshIfDirty();
mAdapter.addNode(pwNode); mAdapter.addNode(pwNode);
} else { } else {
displayMessage(GroupBaseActivity.this); displayMessage(GroupBaseActivity.this);
@@ -313,11 +292,13 @@ public abstract class GroupBaseActivity extends LockCloseListActivity
@Override @Override
public void run() { public void run() {
if ( mSuccess) { if ( mSuccess) {
refreshIfDirty();
mAdapter.removeNode(pwNode); mAdapter.removeNode(pwNode);
PwGroup parent = pwNode.getParent(); PwGroup parent = pwNode.getParent();
PwGroup recycleBin = App.getDB().pm.getRecycleBin(); PwGroup recycleBin = App.getDB().pm.getRecycleBin();
if (parent.equals(recycleBin) && !mCurrentGroup.equals(recycleBin)) { // Add trash if it doesn't exists
if (parent.equals(recycleBin)
&& mCurrentGroup.getParent() == null
&& !mCurrentGroup.equals(recycleBin)) {
mAdapter.addNode(parent); mAdapter.addNode(parent);
} }
} else { } else {

View File

@@ -46,14 +46,11 @@ import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.io.SyncFailedException; import java.io.SyncFailedException;
import java.util.HashSet;
import java.util.Set;
/** /**
* @author bpellin * @author bpellin
*/ */
public class Database { public class Database {
public Set<PwGroup> dirty = new HashSet<PwGroup>();
public PwDatabase pm; public PwDatabase pm;
public Uri mUri; public Uri mUri;
public SearchDbHelper searchHelper; public SearchDbHelper searchHelper;
@@ -220,7 +217,6 @@ public class Database {
} }
public void clear() { public void clear() {
dirty.clear();
drawFactory.clear(); drawFactory.clear();
pm = null; pm = null;
@@ -228,16 +224,4 @@ public class Database {
loaded = false; loaded = false;
passwordEncodingError = false; passwordEncodingError = false;
} }
public void markAllGroupsAsDirty() {
for ( PwGroup group : pm.getGroups() ) {
dirty.add(group);
}
// TODO: This should probably be abstracted out
// The root tree in v3 is not an 'official' tree
if ( pm instanceof PwDatabaseV3 ) {
dirty.add(pm.rootGroup);
}
}
} }

View File

@@ -265,8 +265,9 @@ public abstract class PwDatabase {
public void removeGroupFrom(PwGroup remove, PwGroup parent) { public void removeGroupFrom(PwGroup remove, PwGroup parent) {
// Remove tree from parent tree // Remove tree from parent tree
parent.removeChildGroup(remove); if (parent != null) {
parent.removeChildGroup(remove);
}
groups.remove(remove.getId()); groups.remove(remove.getId());
} }
@@ -331,6 +332,11 @@ public abstract class PwDatabase {
} }
} }
/**
* Define if a Group must be delete or recycle
* @param group Group to remove
* @return true if group can be recycle, false elsewhere
*/
public boolean canRecycle(PwGroup group) { public boolean canRecycle(PwGroup group) {
return false; return false;
} }
@@ -344,20 +350,39 @@ public abstract class PwDatabase {
return false; return false;
} }
public void recycle(PwGroup group) {
// Assume calls to this are protected by calling inRecyleBin
throw new RuntimeException("Call not valid for .kdb databases.");
}
public void recycle(PwEntry entry) { public void recycle(PwEntry entry) {
// Assume calls to this are protected by calling inRecyleBin // Assume calls to this are protected by calling inRecyleBin
throw new RuntimeException("Call not valid for .kdb databases."); throw new RuntimeException("Call not valid for .kdb databases.");
} }
public void undoRecycle(PwGroup group, PwGroup origParent) {
throw new RuntimeException("Call not valid for .kdb databases.");
}
public void undoRecycle(PwEntry entry, PwGroup origParent) { public void undoRecycle(PwEntry entry, PwGroup origParent) {
throw new RuntimeException("Call not valid for .kdb databases."); throw new RuntimeException("Call not valid for .kdb databases.");
} }
public void deleteGroup(PwGroup group) {
PwGroup parent = group.getParent();
removeGroupFrom(group, parent);
parent.touch(false, true);
}
public void deleteEntry(PwEntry entry) { public void deleteEntry(PwEntry entry) {
PwGroup parent = entry.getParent(); PwGroup parent = entry.getParent();
removeEntryFrom(entry, parent); removeEntryFrom(entry, parent);
parent.touch(false, true); parent.touch(false, true);
}
// TODO Delete group
public void undoDeleteGroup(PwGroup group, PwGroup origParent) {
addGroupTo(group, origParent);
} }
public void undoDeleteEntry(PwEntry entry, PwGroup origParent) { public void undoDeleteEntry(PwEntry entry, PwGroup origParent) {

View File

@@ -366,9 +366,7 @@ public class PwDatabaseV4 extends PwDatabase {
if (!recycleBinEnabled) { if (!recycleBinEnabled) {
return false; return false;
} }
PwGroup recycle = getRecycleBin(); PwGroup recycle = getRecycleBin();
return (recycle == null) || (!group.isContainedIn(recycle)); return (recycle == null) || (!group.isContainedIn(recycle));
} }
@@ -377,11 +375,25 @@ public class PwDatabaseV4 extends PwDatabase {
if (!recycleBinEnabled) { if (!recycleBinEnabled) {
return false; return false;
} }
PwGroup parent = entry.getParent(); PwGroup parent = entry.getParent();
return (parent != null) && canRecycle(parent); return (parent != null) && canRecycle(parent);
} }
@Override
public void recycle(PwGroup group) {
ensureRecycleBin();
PwGroup parent = group.getParent();
removeGroupFrom(group, parent);
parent.touch(false, true);
PwGroup recycleBin = getRecycleBin();
addGroupTo(group, recycleBin);
group.touch(false, true);
// TODO ? group.touchLocation();
}
@Override @Override
public void recycle(PwEntry entry) { public void recycle(PwEntry entry) {
ensureRecycleBin(); ensureRecycleBin();
@@ -397,6 +409,15 @@ public class PwDatabaseV4 extends PwDatabase {
entry.touchLocation(); entry.touchLocation();
} }
@Override
public void undoRecycle(PwGroup group, PwGroup origParent) {
PwGroup recycleBin = getRecycleBin();
removeGroupFrom(group, recycleBin);
addGroupTo(group, origParent);
}
@Override @Override
public void undoRecycle(PwEntry entry, PwGroup origParent) { public void undoRecycle(PwEntry entry, PwGroup origParent) {
@@ -409,15 +430,14 @@ public class PwDatabaseV4 extends PwDatabase {
@Override @Override
public void deleteEntry(PwEntry entry) { public void deleteEntry(PwEntry entry) {
super.deleteEntry(entry); super.deleteEntry(entry);
deletedObjects.add(new PwDeletedObject(entry.getUUID())); deletedObjects.add(new PwDeletedObject(entry.getUUID()));
} }
@Override @Override
public void undoDeleteEntry(PwEntry entry, PwGroup origParent) { public void undoDeleteEntry(PwEntry entry, PwGroup origParent) {
super.undoDeleteEntry(entry, origParent); super.undoDeleteEntry(entry, origParent);
// TODO undo delete entry
deletedObjects.remove(entry); deletedObjects.remove(entry);
} }
@Override @Override

View File

@@ -24,7 +24,6 @@ import android.content.Context;
import com.keepassdroid.database.Database; import com.keepassdroid.database.Database;
import com.keepassdroid.database.PwDatabase; import com.keepassdroid.database.PwDatabase;
import com.keepassdroid.database.PwEntry; import com.keepassdroid.database.PwEntry;
import com.keepassdroid.database.PwGroup;
public class AddEntry extends RunnableOnFinish { public class AddEntry extends RunnableOnFinish {
protected Database mDb; protected Database mDb;
@@ -59,20 +58,11 @@ public class AddEntry extends RunnableOnFinish {
@Override @Override
public void run() { public void run() {
PwDatabase pm = mDb.pm; PwDatabase pm = mDb.pm;
if ( mSuccess ) { if ( !mSuccess ) {
PwGroup parent = mEntry.getParent();
// Mark parent tree dirty
mDb.dirty.add(parent);
} else {
pm.removeEntryFrom(mEntry, mEntry.getParent()); pm.removeEntryFrom(mEntry, mEntry.getParent());
} }
// TODO if add entry callback
super.run(); super.run();
} }
} }
} }

View File

@@ -73,13 +73,11 @@ public class AddGroup extends RunnableOnFinish {
@Override @Override
public void run() { public void run() {
PwDatabase pm = mDb.pm; PwDatabase pm = mDb.pm;
if ( mSuccess ) { if ( !mSuccess ) {
// Mark parent group dirty pm.removeGroupFrom(mGroup, mParent);
mDb.dirty.add(mParent);
} else {
pm.removeGroupFrom(mGroup, mParent);
} }
// TODO Better callback
AfterAddNodeOnFinish afterAddNode = AfterAddNodeOnFinish afterAddNode =
(AfterAddNodeOnFinish) super.mOnFinish; (AfterAddNodeOnFinish) super.mOnFinish;
afterAddNode.mSuccess = mSuccess; afterAddNode.mSuccess = mSuccess;

View File

@@ -71,8 +71,6 @@ public class DeleteEntry extends RunnableOnFinish {
// Commit database // Commit database
SaveDB save = new SaveDB(ctx, mDb, mFinish, mDontSave); SaveDB save = new SaveDB(ctx, mDb, mFinish, mDontSave);
save.run(); save.run();
} }
private class AfterDelete extends OnFinish { private class AfterDelete extends OnFinish {
@@ -81,7 +79,7 @@ public class DeleteEntry extends RunnableOnFinish {
private PwEntry mEntry; private PwEntry mEntry;
private boolean recycled; private boolean recycled;
public AfterDelete(OnFinish finish, PwGroup parent, PwEntry entry, boolean r) { AfterDelete(OnFinish finish, PwGroup parent, PwEntry entry, boolean r) {
super(finish); super(finish);
mParent = parent; mParent = parent;
@@ -92,18 +90,7 @@ public class DeleteEntry extends RunnableOnFinish {
@Override @Override
public void run() { public void run() {
PwDatabase pm = mDb.pm; PwDatabase pm = mDb.pm;
if ( mSuccess ) { if ( !mSuccess ) {
// Mark parent dirty
if ( mParent != null ) {
mDb.dirty.add(mParent);
}
if (recycled) {
PwGroup recycleBin = pm.getRecycleBin();
mDb.dirty.add(recycleBin);
mDb.dirty.add(mDb.pm.rootGroup);
}
} else {
if (recycled) { if (recycled) {
pm.undoRecycle(mEntry, mParent); pm.undoRecycle(mEntry, mParent);
} }
@@ -111,11 +98,9 @@ public class DeleteEntry extends RunnableOnFinish {
pm.undoDeleteEntry(mEntry, mParent); pm.undoDeleteEntry(mEntry, mParent);
} }
} }
// TODO Callback after delete entry
super.run(); super.run();
} }
} }
} }

View File

@@ -19,30 +19,32 @@
*/ */
package com.keepassdroid.database.edit; package com.keepassdroid.database.edit;
import java.util.ArrayList; import android.content.Context;
import java.util.List;
import com.keepassdroid.database.Database;
import com.keepassdroid.activities.GroupBaseActivity;
import com.keepassdroid.app.App; import com.keepassdroid.app.App;
import com.keepassdroid.database.Database;
import com.keepassdroid.database.PwDatabase;
import com.keepassdroid.database.PwEntry; import com.keepassdroid.database.PwEntry;
import com.keepassdroid.database.PwGroup; import com.keepassdroid.database.PwGroup;
import java.util.ArrayList;
import java.util.List;
public class DeleteGroup extends RunnableOnFinish { public class DeleteGroup extends RunnableOnFinish {
private Context mContext;
private Database mDb; private Database mDb;
private PwGroup mGroup; private PwGroup mGroup;
private GroupBaseActivity mAct;
private boolean mDontSave; private boolean mDontSave;
public DeleteGroup(GroupBaseActivity act, Database db, PwGroup group, OnFinish finish) { public DeleteGroup(Context ctx, Database db, PwGroup group, OnFinish finish) {
super(finish); super(finish);
setMembers(act, db, group, false); setMembers(ctx, db, group, false);
} }
public DeleteGroup(GroupBaseActivity act, Database db, PwGroup group, OnFinish finish, boolean dontSave) { public DeleteGroup(Context ctx, Database db, PwGroup group, OnFinish finish, boolean dontSave) {
super(finish); super(finish);
setMembers(act, db, group, dontSave); setMembers(ctx, db, group, dontSave);
} }
public DeleteGroup(Database db, PwGroup group, OnFinish finish, boolean dontSave) { public DeleteGroup(Database db, PwGroup group, OnFinish finish, boolean dontSave) {
@@ -50,71 +52,80 @@ public class DeleteGroup extends RunnableOnFinish {
setMembers(null, db, group, dontSave); setMembers(null, db, group, dontSave);
} }
private void setMembers(GroupBaseActivity act, Database db, PwGroup group, boolean dontSave) { private void setMembers(Context ctx, Database db, PwGroup group, boolean dontSave) {
mDb = db; mDb = db;
mGroup = group; mGroup = group;
mAct = act; mContext = ctx;
mDontSave = dontSave; mDontSave = dontSave;
mFinish = new AfterDelete(mFinish);
} }
@Override @Override
public void run() { public void run() {
PwDatabase pm = mDb.pm;
PwGroup parent = mGroup.getParent();
// Remove child entries // Remove Group from parent
List<PwEntry> childEnt = new ArrayList<>(mGroup.childEntries); boolean recycle = pm.canRecycle(mGroup);
for ( int i = 0; i < childEnt.size(); i++ ) { if (recycle) {
DeleteEntry task = new DeleteEntry(mAct, mDb, childEnt.get(i), null, true); pm.recycle(mGroup);
task.run(); }
} else {
// TODO tests
// Remove child entries
List<PwEntry> childEnt = new ArrayList<>(mGroup.childEntries);
for ( int i = 0; i < childEnt.size(); i++ ) {
DeleteEntry task = new DeleteEntry(mContext, mDb, childEnt.get(i), null, true);
task.run();
}
// Remove child groups // Remove child groups
List<PwGroup> childGrp = new ArrayList<>(mGroup.childGroups); List<PwGroup> childGrp = new ArrayList<>(mGroup.childGroups);
for ( int i = 0; i < childGrp.size(); i++ ) { for ( int i = 0; i < childGrp.size(); i++ ) {
DeleteGroup task = new DeleteGroup(mAct, mDb, childGrp.get(i), null, true); DeleteGroup task = new DeleteGroup(mContext, mDb, childGrp.get(i), null, true);
task.run(); task.run();
} }
pm.deleteGroup(mGroup);
// Remove from PwDatabaseV3
// TODO ENcapsulate
mDb.pm.getGroups().remove(mGroup);
}
// Remove from parent // Save
PwGroup parent = mGroup.getParent(); mFinish = new AfterDelete(mFinish, parent, mGroup, recycle);
if ( parent != null ) {
parent.removeChildGroup(mGroup);
}
// Remove from PwDatabaseV3 // Commit Database
mDb.pm.getGroups().remove(mGroup); SaveDB save = new SaveDB(mContext, mDb, mFinish, mDontSave);
// Save
SaveDB save = new SaveDB(mAct, mDb, mFinish, mDontSave);
save.run(); save.run();
} }
private class AfterDelete extends OnFinish { private class AfterDelete extends OnFinish {
public AfterDelete(OnFinish finish) {
private PwGroup mParent;
private PwGroup mGroup;
private boolean recycled;
AfterDelete(OnFinish finish, PwGroup parent, PwGroup mGroup, boolean recycle) {
super(finish); super(finish);
this.mParent = parent;
this.mGroup = mGroup;
this.recycled = recycle;
} }
public void run() { public void run() {
if ( mSuccess ) { PwDatabase pm = mDb.pm;
// Remove from tree global if ( !mSuccess ) {
mDb.pm.groups.remove(mGroup.getId()); if (recycled) {
pm.undoRecycle(mGroup, mParent);
// Remove tree from the dirty global (if it is present), not a big deal if this fails }
mDb.dirty.remove(mGroup); else {
// Let's not bother recovering from a failure to save a deleted tree. It is too much work.
// Mark parent dirty App.setShutdown();
PwGroup parent = mGroup.getParent(); // TODO TEST pm.undoDeleteGroup(mGroup, mParent);
if ( parent != null ) { }
mDb.dirty.add(parent); }
} // TODO Callback after delete group
mDb.dirty.add(mDb.pm.rootGroup);
} else {
// Let's not bother recovering from a failure to save a deleted tree. It is too much work.
App.setShutdown();
}
super.run(); super.run();
} }

View File

@@ -23,7 +23,6 @@ import android.content.Context;
import com.keepassdroid.database.Database; import com.keepassdroid.database.Database;
import com.keepassdroid.database.PwEntry; import com.keepassdroid.database.PwEntry;
import com.keepassdroid.database.PwGroup;
public class UpdateEntry extends RunnableOnFinish { public class UpdateEntry extends RunnableOnFinish {
private Database mDb; private Database mDb;
@@ -61,32 +60,19 @@ public class UpdateEntry extends RunnableOnFinish {
private class AfterUpdate extends OnFinish { private class AfterUpdate extends OnFinish {
private PwEntry mBackup; private PwEntry mBackup;
public AfterUpdate(PwEntry backup, OnFinish finish) { AfterUpdate(PwEntry backup, OnFinish finish) {
super(finish); super(finish);
mBackup = backup; mBackup = backup;
} }
@Override @Override
public void run() { public void run() {
if ( mSuccess ) { if ( !mSuccess ) {
// Mark group dirty if title or icon changes
if ( ! mBackup.isContentVisuallyTheSame(mNewE) ) {
PwGroup parent = mBackup.getParent();
if ( parent != null ) {
// Mark parent group dirty
mDb.dirty.add(parent);
}
}
} else {
// If we fail to save, back out changes to global structure // If we fail to save, back out changes to global structure
mOldE.assign(mBackup); mOldE.assign(mBackup);
} }
// TODO Callback for update entry
super.run(); super.run();
} }
} }
} }