mirror of
https://github.com/Kunzisoft/KeePassDX.git
synced 2025-12-04 15:49:33 +01:00
Merge branch 'feature/RefactorProgress' into develop #98
This commit is contained in:
@@ -1,3 +1,9 @@
|
|||||||
|
KeepassDX (2.5.0.0beta10)
|
||||||
|
* Upgrade translations
|
||||||
|
* Fix classic dark theme
|
||||||
|
* Add Material Icon Pack to the Free version
|
||||||
|
* Fix bugs
|
||||||
|
|
||||||
KeepassDX (2.5.0.0beta9)
|
KeepassDX (2.5.0.0beta9)
|
||||||
* Education Screens to learn how to use the app
|
* Education Screens to learn how to use the app
|
||||||
* New designs
|
* New designs
|
||||||
|
|||||||
@@ -8,8 +8,8 @@ android {
|
|||||||
applicationId "com.kunzisoft.keepass"
|
applicationId "com.kunzisoft.keepass"
|
||||||
minSdkVersion 14
|
minSdkVersion 14
|
||||||
targetSdkVersion 27
|
targetSdkVersion 27
|
||||||
versionCode = 9
|
versionCode = 10
|
||||||
versionName = "2.5.0.0beta9"
|
versionName = "2.5.0.0beta10"
|
||||||
multiDexEnabled true
|
multiDexEnabled true
|
||||||
|
|
||||||
testApplicationId = "com.kunzisoft.keepass.tests"
|
testApplicationId = "com.kunzisoft.keepass.tests"
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ import com.kunzisoft.keepass.database.PwDatabaseV3;
|
|||||||
import com.kunzisoft.keepass.database.PwEntry;
|
import com.kunzisoft.keepass.database.PwEntry;
|
||||||
import com.kunzisoft.keepass.database.PwEntryV3;
|
import com.kunzisoft.keepass.database.PwEntryV3;
|
||||||
import com.kunzisoft.keepass.database.PwGroup;
|
import com.kunzisoft.keepass.database.PwGroup;
|
||||||
import com.kunzisoft.keepass.database.edit.DeleteGroup;
|
import com.kunzisoft.keepass.database.action.DeleteGroupRunnable;
|
||||||
import com.kunzisoft.keepass.search.SearchDbHelper;
|
import com.kunzisoft.keepass.search.SearchDbHelper;
|
||||||
|
|
||||||
public class DeleteEntry extends AndroidTestCase {
|
public class DeleteEntry extends AndroidTestCase {
|
||||||
@@ -60,7 +60,7 @@ public class DeleteEntry extends AndroidTestCase {
|
|||||||
assertNotNull("Could not find group1", group1);
|
assertNotNull("Could not find group1", group1);
|
||||||
|
|
||||||
// Delete the group
|
// Delete the group
|
||||||
DeleteGroup task = new DeleteGroup(null, db, group1, null, true);
|
DeleteGroupRunnable task = new DeleteGroupRunnable(null, db, group1, null, true);
|
||||||
task.run();
|
task.run();
|
||||||
|
|
||||||
// Verify the entries were deleted
|
// Verify the entries were deleted
|
||||||
|
|||||||
@@ -49,16 +49,17 @@ import com.kunzisoft.keepass.database.PwEntry;
|
|||||||
import com.kunzisoft.keepass.database.PwGroup;
|
import com.kunzisoft.keepass.database.PwGroup;
|
||||||
import com.kunzisoft.keepass.database.PwGroupId;
|
import com.kunzisoft.keepass.database.PwGroupId;
|
||||||
import com.kunzisoft.keepass.database.PwIconStandard;
|
import com.kunzisoft.keepass.database.PwIconStandard;
|
||||||
import com.kunzisoft.keepass.database.edit.AddEntry;
|
import com.kunzisoft.keepass.database.action.AddEntryRunnable;
|
||||||
import com.kunzisoft.keepass.database.edit.OnFinish;
|
import com.kunzisoft.keepass.database.action.OnFinishRunnable;
|
||||||
import com.kunzisoft.keepass.database.edit.RunnableOnFinish;
|
import com.kunzisoft.keepass.database.action.RunnableOnFinish;
|
||||||
import com.kunzisoft.keepass.database.edit.UpdateEntry;
|
import com.kunzisoft.keepass.database.action.UpdateEntryRunnable;
|
||||||
import com.kunzisoft.keepass.database.security.ProtectedString;
|
import com.kunzisoft.keepass.database.security.ProtectedString;
|
||||||
import com.kunzisoft.keepass.dialogs.GeneratePasswordDialogFragment;
|
import com.kunzisoft.keepass.dialogs.GeneratePasswordDialogFragment;
|
||||||
import com.kunzisoft.keepass.dialogs.IconPickerDialogFragment;
|
import com.kunzisoft.keepass.dialogs.IconPickerDialogFragment;
|
||||||
import com.kunzisoft.keepass.icons.IconPackChooser;
|
import com.kunzisoft.keepass.icons.IconPackChooser;
|
||||||
import com.kunzisoft.keepass.settings.PreferencesUtil;
|
import com.kunzisoft.keepass.settings.PreferencesUtil;
|
||||||
import com.kunzisoft.keepass.tasks.ProgressTask;
|
import com.kunzisoft.keepass.tasks.SaveDatabaseProgressTaskDialogFragment;
|
||||||
|
import com.kunzisoft.keepass.tasks.UpdateProgressTaskStatus;
|
||||||
import com.kunzisoft.keepass.utils.MenuUtil;
|
import com.kunzisoft.keepass.utils.MenuUtil;
|
||||||
import com.kunzisoft.keepass.utils.Types;
|
import com.kunzisoft.keepass.utils.Types;
|
||||||
import com.kunzisoft.keepass.utils.Util;
|
import com.kunzisoft.keepass.utils.Util;
|
||||||
@@ -249,16 +250,21 @@ public class EntryEditActivity extends LockingHideActivity
|
|||||||
}
|
}
|
||||||
mCallbackNewEntry = populateNewEntry();
|
mCallbackNewEntry = populateNewEntry();
|
||||||
|
|
||||||
OnFinish onFinish = new AfterSave();
|
// Open a progress dialog and save entry
|
||||||
|
OnFinishRunnable onFinish = new AfterSave();
|
||||||
EntryEditActivity act = EntryEditActivity.this;
|
EntryEditActivity act = EntryEditActivity.this;
|
||||||
RunnableOnFinish task;
|
RunnableOnFinish task;
|
||||||
if ( mIsNew ) {
|
if ( mIsNew ) {
|
||||||
task = new AddEntry(act, App.getDB(), mCallbackNewEntry, onFinish);
|
task = new AddEntryRunnable(act, App.getDB(), mCallbackNewEntry, onFinish);
|
||||||
} else {
|
} else {
|
||||||
task = new UpdateEntry(act, App.getDB(), mEntry, mCallbackNewEntry, onFinish);
|
task = new UpdateEntryRunnable(act, App.getDB(), mEntry, mCallbackNewEntry, onFinish);
|
||||||
}
|
}
|
||||||
ProgressTask pt = new ProgressTask(act, task, R.string.saving_database);
|
task.setUpdateProgressTaskStatus(
|
||||||
pt.run();
|
new UpdateProgressTaskStatus(this,
|
||||||
|
SaveDatabaseProgressTaskDialogFragment.start(
|
||||||
|
getSupportFragmentManager())
|
||||||
|
));
|
||||||
|
new Thread(task).start();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -554,7 +560,7 @@ public class EntryEditActivity extends LockingHideActivity
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private final class AfterSave extends OnFinish {
|
private final class AfterSave extends OnFinishRunnable {
|
||||||
|
|
||||||
AfterSave() {
|
AfterSave() {
|
||||||
super(new Handler());
|
super(new Handler());
|
||||||
@@ -562,11 +568,15 @@ public class EntryEditActivity extends LockingHideActivity
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
if ( mSuccess ) {
|
runOnUiThread(() -> {
|
||||||
finish();
|
if ( mSuccess ) {
|
||||||
} else {
|
finish();
|
||||||
displayMessage(EntryEditActivity.this);
|
} else {
|
||||||
}
|
displayMessage(EntryEditActivity.this);
|
||||||
|
}
|
||||||
|
|
||||||
|
SaveDatabaseProgressTaskDialogFragment.stop(getSupportFragmentManager());
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -57,10 +57,10 @@ import com.kunzisoft.keepass.database.PwIcon;
|
|||||||
import com.kunzisoft.keepass.database.PwIconStandard;
|
import com.kunzisoft.keepass.database.PwIconStandard;
|
||||||
import com.kunzisoft.keepass.database.PwNode;
|
import com.kunzisoft.keepass.database.PwNode;
|
||||||
import com.kunzisoft.keepass.database.SortNodeEnum;
|
import com.kunzisoft.keepass.database.SortNodeEnum;
|
||||||
import com.kunzisoft.keepass.database.edit.AddGroup;
|
import com.kunzisoft.keepass.database.action.AddGroupRunnable;
|
||||||
import com.kunzisoft.keepass.database.edit.DeleteEntry;
|
import com.kunzisoft.keepass.database.action.DeleteEntryRunnable;
|
||||||
import com.kunzisoft.keepass.database.edit.DeleteGroup;
|
import com.kunzisoft.keepass.database.action.DeleteGroupRunnable;
|
||||||
import com.kunzisoft.keepass.database.edit.UpdateGroup;
|
import com.kunzisoft.keepass.database.action.UpdateGroupRunnable;
|
||||||
import com.kunzisoft.keepass.dialogs.AssignMasterKeyDialogFragment;
|
import com.kunzisoft.keepass.dialogs.AssignMasterKeyDialogFragment;
|
||||||
import com.kunzisoft.keepass.dialogs.GroupEditDialogFragment;
|
import com.kunzisoft.keepass.dialogs.GroupEditDialogFragment;
|
||||||
import com.kunzisoft.keepass.dialogs.IconPickerDialogFragment;
|
import com.kunzisoft.keepass.dialogs.IconPickerDialogFragment;
|
||||||
@@ -68,7 +68,8 @@ import com.kunzisoft.keepass.dialogs.ReadOnlyDialog;
|
|||||||
import com.kunzisoft.keepass.icons.IconPackChooser;
|
import com.kunzisoft.keepass.icons.IconPackChooser;
|
||||||
import com.kunzisoft.keepass.search.SearchResultsActivity;
|
import com.kunzisoft.keepass.search.SearchResultsActivity;
|
||||||
import com.kunzisoft.keepass.settings.PreferencesUtil;
|
import com.kunzisoft.keepass.settings.PreferencesUtil;
|
||||||
import com.kunzisoft.keepass.tasks.ProgressTask;
|
import com.kunzisoft.keepass.tasks.SaveDatabaseProgressTaskDialogFragment;
|
||||||
|
import com.kunzisoft.keepass.tasks.UpdateProgressTaskStatus;
|
||||||
import com.kunzisoft.keepass.view.AddNodeButtonView;
|
import com.kunzisoft.keepass.view.AddNodeButtonView;
|
||||||
|
|
||||||
public class GroupActivity extends ListNodesActivity
|
public class GroupActivity extends ListNodesActivity
|
||||||
@@ -435,19 +436,27 @@ public class GroupActivity extends ListNodesActivity
|
|||||||
|
|
||||||
private void deleteEntry(PwEntry entry) {
|
private void deleteEntry(PwEntry entry) {
|
||||||
Handler handler = new Handler();
|
Handler handler = new Handler();
|
||||||
DeleteEntry task = new DeleteEntry(this, App.getDB(), entry,
|
DeleteEntryRunnable task = new DeleteEntryRunnable(this, App.getDB(), entry,
|
||||||
new AfterDeleteNode(handler, entry));
|
new AfterDeleteNode(handler, entry));
|
||||||
ProgressTask pt = new ProgressTask(this, task, R.string.saving_database);
|
task.setUpdateProgressTaskStatus(
|
||||||
pt.run();
|
new UpdateProgressTaskStatus(this,
|
||||||
|
SaveDatabaseProgressTaskDialogFragment.start(
|
||||||
|
getSupportFragmentManager())
|
||||||
|
));
|
||||||
|
new Thread(task).start();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void deleteGroup(PwGroup group) {
|
private void deleteGroup(PwGroup group) {
|
||||||
//TODO Verify trash recycle bin
|
//TODO Verify trash recycle bin
|
||||||
Handler handler = new Handler();
|
Handler handler = new Handler();
|
||||||
DeleteGroup task = new DeleteGroup(this, App.getDB(), group,
|
DeleteGroupRunnable task = new DeleteGroupRunnable(this, App.getDB(), group,
|
||||||
new AfterDeleteNode(handler, group));
|
new AfterDeleteNode(handler, group));
|
||||||
ProgressTask pt = new ProgressTask(this, task, R.string.saving_database);
|
task.setUpdateProgressTaskStatus(
|
||||||
pt.run();
|
new UpdateProgressTaskStatus(this,
|
||||||
|
SaveDatabaseProgressTaskDialogFragment.start(
|
||||||
|
getSupportFragmentManager())
|
||||||
|
));
|
||||||
|
new Thread(task).start();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -548,16 +557,21 @@ public class GroupActivity extends ListNodesActivity
|
|||||||
newGroup.setName(name);
|
newGroup.setName(name);
|
||||||
try {
|
try {
|
||||||
iconStandard = (PwIconStandard) icon;
|
iconStandard = (PwIconStandard) icon;
|
||||||
} catch (Exception e) {} // TODO custom icon
|
} catch (Exception ignored) {} // TODO custom icon
|
||||||
newGroup.setIcon(iconStandard);
|
newGroup.setIcon(iconStandard);
|
||||||
|
|
||||||
new ProgressTask(this,
|
// If group created save it in the database
|
||||||
new AddGroup(this,
|
AddGroupRunnable addGroupRunnable = new AddGroupRunnable(this,
|
||||||
App.getDB(),
|
App.getDB(),
|
||||||
newGroup,
|
newGroup,
|
||||||
new AfterAddNode(new Handler())),
|
new AfterAddNode(new Handler()));
|
||||||
R.string.saving_database)
|
addGroupRunnable.setUpdateProgressTaskStatus(
|
||||||
.run();
|
new UpdateProgressTaskStatus(this,
|
||||||
|
SaveDatabaseProgressTaskDialogFragment.start(
|
||||||
|
getSupportFragmentManager())
|
||||||
|
));
|
||||||
|
new Thread(addGroupRunnable).start();
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case UPDATE:
|
case UPDATE:
|
||||||
// If update add new elements
|
// If update add new elements
|
||||||
@@ -566,20 +580,23 @@ public class GroupActivity extends ListNodesActivity
|
|||||||
updateGroup.setName(name);
|
updateGroup.setName(name);
|
||||||
try {
|
try {
|
||||||
iconStandard = (PwIconStandard) icon;
|
iconStandard = (PwIconStandard) icon;
|
||||||
} catch (Exception e) {} // TODO custom icon
|
} catch (Exception ignored) {} // TODO custom icon
|
||||||
updateGroup.setIcon(iconStandard);
|
updateGroup.setIcon(iconStandard);
|
||||||
|
|
||||||
mAdapter.removeNode(oldGroupToUpdate);
|
mAdapter.removeNode(oldGroupToUpdate);
|
||||||
// If group update
|
|
||||||
new ProgressTask(this,
|
|
||||||
new UpdateGroup(this,
|
|
||||||
App.getDB(),
|
|
||||||
oldGroupToUpdate,
|
|
||||||
updateGroup,
|
|
||||||
new AfterUpdateNode(new Handler())),
|
|
||||||
R.string.saving_database)
|
|
||||||
.run();
|
|
||||||
|
|
||||||
|
// If group updated save it in the database
|
||||||
|
UpdateGroupRunnable updateGroupRunnable = new UpdateGroupRunnable(this,
|
||||||
|
App.getDB(),
|
||||||
|
oldGroupToUpdate,
|
||||||
|
updateGroup,
|
||||||
|
new AfterUpdateNode(new Handler()));
|
||||||
|
updateGroupRunnable.setUpdateProgressTaskStatus(
|
||||||
|
new UpdateProgressTaskStatus(this,
|
||||||
|
SaveDatabaseProgressTaskDialogFragment.start(
|
||||||
|
getSupportFragmentManager())
|
||||||
|
));
|
||||||
|
new Thread(updateGroupRunnable).start();
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -49,12 +49,13 @@ import com.kunzisoft.keepass.database.PwEntry;
|
|||||||
import com.kunzisoft.keepass.database.PwGroup;
|
import com.kunzisoft.keepass.database.PwGroup;
|
||||||
import com.kunzisoft.keepass.database.PwNode;
|
import com.kunzisoft.keepass.database.PwNode;
|
||||||
import com.kunzisoft.keepass.database.SortNodeEnum;
|
import com.kunzisoft.keepass.database.SortNodeEnum;
|
||||||
import com.kunzisoft.keepass.database.edit.AfterActionNodeOnFinish;
|
import com.kunzisoft.keepass.database.action.AfterActionNodeOnFinish;
|
||||||
import com.kunzisoft.keepass.database.edit.OnFinish;
|
import com.kunzisoft.keepass.database.action.OnFinishRunnable;
|
||||||
import com.kunzisoft.keepass.dialogs.AssignMasterKeyDialogFragment;
|
import com.kunzisoft.keepass.dialogs.AssignMasterKeyDialogFragment;
|
||||||
import com.kunzisoft.keepass.dialogs.SortDialogFragment;
|
import com.kunzisoft.keepass.dialogs.SortDialogFragment;
|
||||||
import com.kunzisoft.keepass.password.AssignPasswordHelper;
|
import com.kunzisoft.keepass.password.AssignPasswordHelper;
|
||||||
import com.kunzisoft.keepass.settings.PreferencesUtil;
|
import com.kunzisoft.keepass.settings.PreferencesUtil;
|
||||||
|
import com.kunzisoft.keepass.tasks.SaveDatabaseProgressTaskDialogFragment;
|
||||||
import com.kunzisoft.keepass.tasks.UIToastTask;
|
import com.kunzisoft.keepass.tasks.UIToastTask;
|
||||||
import com.kunzisoft.keepass.utils.MenuUtil;
|
import com.kunzisoft.keepass.utils.MenuUtil;
|
||||||
|
|
||||||
@@ -307,11 +308,16 @@ public abstract class ListNodesActivity extends LockingActivity
|
|||||||
|
|
||||||
public void run(PwNode oldNode, PwNode newNode) {
|
public void run(PwNode oldNode, PwNode newNode) {
|
||||||
super.run();
|
super.run();
|
||||||
if (mSuccess) {
|
|
||||||
mAdapter.addNode(newNode);
|
runOnUiThread(() -> {
|
||||||
} else {
|
if (mSuccess) {
|
||||||
displayMessage(ListNodesActivity.this);
|
mAdapter.addNode(newNode);
|
||||||
}
|
} else {
|
||||||
|
displayMessage(ListNodesActivity.this);
|
||||||
|
}
|
||||||
|
|
||||||
|
SaveDatabaseProgressTaskDialogFragment.stop(getSupportFragmentManager());
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -322,15 +328,20 @@ public abstract class ListNodesActivity extends LockingActivity
|
|||||||
|
|
||||||
public void run(PwNode oldNode, PwNode newNode) {
|
public void run(PwNode oldNode, PwNode newNode) {
|
||||||
super.run();
|
super.run();
|
||||||
if (mSuccess) {
|
|
||||||
mAdapter.updateNode(oldNode, newNode);
|
runOnUiThread(() -> {
|
||||||
} else {
|
if (mSuccess) {
|
||||||
displayMessage(ListNodesActivity.this);
|
mAdapter.updateNode(oldNode, newNode);
|
||||||
}
|
} else {
|
||||||
|
displayMessage(ListNodesActivity.this);
|
||||||
|
}
|
||||||
|
|
||||||
|
SaveDatabaseProgressTaskDialogFragment.stop(getSupportFragmentManager());
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class AfterDeleteNode extends OnFinish {
|
class AfterDeleteNode extends OnFinishRunnable {
|
||||||
private PwNode pwNode;
|
private PwNode pwNode;
|
||||||
|
|
||||||
AfterDeleteNode(Handler handler, PwNode pwNode) {
|
AfterDeleteNode(Handler handler, PwNode pwNode) {
|
||||||
@@ -340,27 +351,33 @@ public abstract class ListNodesActivity extends LockingActivity
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
if ( mSuccess) {
|
super.run();
|
||||||
mAdapter.removeNode(pwNode);
|
|
||||||
PwGroup parent = pwNode.getParent();
|
runOnUiThread(() -> {
|
||||||
Database db = App.getDB();
|
if ( mSuccess) {
|
||||||
PwDatabase database = db.getPwDatabase();
|
mAdapter.removeNode(pwNode);
|
||||||
if (db.isRecycleBinAvailable() &&
|
PwGroup parent = pwNode.getParent();
|
||||||
db.isRecycleBinEnabled()) {
|
Database db = App.getDB();
|
||||||
PwGroup recycleBin = database.getRecycleBin();
|
PwDatabase database = db.getPwDatabase();
|
||||||
// Add trash if it doesn't exists
|
if (db.isRecycleBinAvailable() &&
|
||||||
if (parent.equals(recycleBin)
|
db.isRecycleBinEnabled()) {
|
||||||
&& mCurrentGroup != null
|
PwGroup recycleBin = database.getRecycleBin();
|
||||||
&& mCurrentGroup.getParent() == null
|
// Add trash if it doesn't exists
|
||||||
&& !mCurrentGroup.equals(recycleBin)) {
|
if (parent.equals(recycleBin)
|
||||||
mAdapter.addNode(parent);
|
&& mCurrentGroup != null
|
||||||
|
&& mCurrentGroup.getParent() == null
|
||||||
|
&& !mCurrentGroup.equals(recycleBin)) {
|
||||||
|
mAdapter.addNode(parent);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
mHandler.post(new UIToastTask(ListNodesActivity.this, "Unrecoverable error: " + mMessage));
|
||||||
|
App.setShutdown();
|
||||||
|
finish();
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
mHandler.post(new UIToastTask(ListNodesActivity.this, "Unrecoverable error: " + mMessage));
|
SaveDatabaseProgressTaskDialogFragment.stop(getSupportFragmentManager());
|
||||||
App.setShutdown();
|
});
|
||||||
finish();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ import com.kunzisoft.keepass.database.load.ImporterFactory;
|
|||||||
import com.kunzisoft.keepass.database.save.PwDbOutput;
|
import com.kunzisoft.keepass.database.save.PwDbOutput;
|
||||||
import com.kunzisoft.keepass.icons.IconDrawableFactory;
|
import com.kunzisoft.keepass.icons.IconDrawableFactory;
|
||||||
import com.kunzisoft.keepass.search.SearchDbHelper;
|
import com.kunzisoft.keepass.search.SearchDbHelper;
|
||||||
import com.kunzisoft.keepass.tasks.UpdateStatus;
|
import com.kunzisoft.keepass.tasks.ProgressTaskUpdater;
|
||||||
import com.kunzisoft.keepass.utils.UriUtil;
|
import com.kunzisoft.keepass.utils.UriUtil;
|
||||||
|
|
||||||
import java.io.BufferedInputStream;
|
import java.io.BufferedInputStream;
|
||||||
@@ -99,19 +99,11 @@ public class Database {
|
|||||||
loaded = true;
|
loaded = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void loadData(Context ctx, InputStream is, String password, InputStream keyInputStream) throws IOException, InvalidDBException {
|
public void loadData(Context ctx, Uri uri, String password, Uri keyfile, ProgressTaskUpdater status) throws IOException, FileNotFoundException, InvalidDBException {
|
||||||
loadData(ctx, is, password, keyInputStream, new UpdateStatus(), !Importer.DEBUG);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void loadData(Context ctx, Uri uri, String password, Uri keyfile) throws IOException, FileNotFoundException, InvalidDBException {
|
|
||||||
loadData(ctx, uri, password, keyfile, new UpdateStatus(), !Importer.DEBUG);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void loadData(Context ctx, Uri uri, String password, Uri keyfile, UpdateStatus status) throws IOException, FileNotFoundException, InvalidDBException {
|
|
||||||
loadData(ctx, uri, password, keyfile, status, !Importer.DEBUG);
|
loadData(ctx, uri, password, keyfile, status, !Importer.DEBUG);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void loadData(Context ctx, Uri uri, String password, Uri keyfile, UpdateStatus status, boolean debug) throws IOException, FileNotFoundException, InvalidDBException {
|
public void loadData(Context ctx, Uri uri, String password, Uri keyfile, ProgressTaskUpdater status, boolean debug) throws IOException, FileNotFoundException, InvalidDBException {
|
||||||
mUri = uri;
|
mUri = uri;
|
||||||
readOnly = false;
|
readOnly = false;
|
||||||
if (uri.getScheme().equals("file")) {
|
if (uri.getScheme().equals("file")) {
|
||||||
@@ -138,7 +130,7 @@ public class Database {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void passUrisAsInputStreams(Context ctx, Uri uri, String password, Uri keyfile, UpdateStatus status, boolean debug, long roundsFix) throws IOException, FileNotFoundException, InvalidDBException {
|
private void passUrisAsInputStreams(Context ctx, Uri uri, String password, Uri keyfile, ProgressTaskUpdater status, boolean debug, long roundsFix) throws IOException, FileNotFoundException, InvalidDBException {
|
||||||
InputStream is, kfIs;
|
InputStream is, kfIs;
|
||||||
try {
|
try {
|
||||||
is = UriUtil.getUriInputStream(ctx, uri);
|
is = UriUtil.getUriInputStream(ctx, uri);
|
||||||
@@ -157,14 +149,10 @@ public class Database {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void loadData(Context ctx, InputStream is, String password, InputStream kfIs, boolean debug) throws IOException, InvalidDBException {
|
public void loadData(Context ctx, InputStream is, String password, InputStream kfIs, boolean debug) throws IOException, InvalidDBException {
|
||||||
loadData(ctx, is, password, kfIs, new UpdateStatus(), debug);
|
loadData(ctx, is, password, kfIs, null, debug, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void loadData(Context ctx, InputStream is, String password, InputStream kfIs, UpdateStatus status, boolean debug) throws IOException, InvalidDBException {
|
private void loadData(Context ctx, InputStream is, String password, InputStream kfIs, ProgressTaskUpdater progressTaskUpdater, boolean debug, long roundsFix) throws IOException, InvalidDBException {
|
||||||
loadData(ctx, is, password, kfIs, status, debug, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void loadData(Context ctx, InputStream is, String password, InputStream kfIs, UpdateStatus status, boolean debug, long roundsFix) throws IOException, InvalidDBException {
|
|
||||||
BufferedInputStream bis = new BufferedInputStream(is);
|
BufferedInputStream bis = new BufferedInputStream(is);
|
||||||
|
|
||||||
if ( ! bis.markSupported() ) {
|
if ( ! bis.markSupported() ) {
|
||||||
@@ -178,7 +166,7 @@ public class Database {
|
|||||||
|
|
||||||
bis.reset(); // Return to the start
|
bis.reset(); // Return to the start
|
||||||
|
|
||||||
pm = imp.openDatabase(bis, password, kfIs, status, roundsFix);
|
pm = imp.openDatabase(bis, password, kfIs, progressTaskUpdater, roundsFix);
|
||||||
if ( pm != null ) {
|
if ( pm != null ) {
|
||||||
try {
|
try {
|
||||||
switch (pm.getVersion()) {
|
switch (pm.getVersion()) {
|
||||||
@@ -222,19 +210,23 @@ public class Database {
|
|||||||
saveData(ctx, mUri);
|
saveData(ctx, mUri);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void saveData(Context ctx, Uri uri) throws IOException, PwDbOutputException {
|
private void saveData(Context ctx, Uri uri) throws IOException, PwDbOutputException {
|
||||||
if (uri.getScheme().equals("file")) {
|
if (uri.getScheme().equals("file")) {
|
||||||
String filename = uri.getPath();
|
String filename = uri.getPath();
|
||||||
File tempFile = new File(filename + ".tmp");
|
File tempFile = new File(filename + ".tmp");
|
||||||
FileOutputStream fos = new FileOutputStream(tempFile);
|
|
||||||
//BufferedOutputStream bos = new BufferedOutputStream(fos);
|
|
||||||
|
|
||||||
//PwDbV3Output pmo = new PwDbV3Output(pm, bos, App.getCalendar());
|
FileOutputStream fos = null;
|
||||||
PwDbOutput pmo = PwDbOutput.getInstance(pm, fos);
|
try {
|
||||||
pmo.output();
|
fos = new FileOutputStream(tempFile);
|
||||||
//bos.flush();
|
PwDbOutput pmo = PwDbOutput.getInstance(pm, fos);
|
||||||
//bos.close();
|
if (pmo != null)
|
||||||
fos.close();
|
pmo.output();
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new IOException("Failed to store database.");
|
||||||
|
} finally {
|
||||||
|
if (fos != null)
|
||||||
|
fos.close();
|
||||||
|
}
|
||||||
|
|
||||||
// Force data to disk before continuing
|
// Force data to disk before continuing
|
||||||
try {
|
try {
|
||||||
@@ -250,16 +242,18 @@ public class Database {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
OutputStream os;
|
OutputStream os = null;
|
||||||
try {
|
try {
|
||||||
os = ctx.getContentResolver().openOutputStream(uri);
|
os = ctx.getContentResolver().openOutputStream(uri);
|
||||||
|
PwDbOutput pmo = PwDbOutput.getInstance(pm, os);
|
||||||
|
if (pmo != null)
|
||||||
|
pmo.output();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new IOException("Failed to store database.");
|
throw new IOException("Failed to store database.");
|
||||||
|
} finally {
|
||||||
|
if (os != null)
|
||||||
|
os.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
PwDbOutput pmo = PwDbOutput.getInstance(pm, os);
|
|
||||||
pmo.output();
|
|
||||||
os.close();
|
|
||||||
}
|
}
|
||||||
mUri = uri;
|
mUri = uri;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -100,25 +100,6 @@ public abstract class PwDatabase<PwGroupDB extends PwGroup<PwGroupDB, PwGroupDB,
|
|||||||
return finalKey;
|
return finalKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void makeFinalKey(byte[] masterSeed, byte[] masterSeed2, long numRounds) throws IOException {
|
|
||||||
|
|
||||||
// Write checksum Checksum
|
|
||||||
MessageDigest md;
|
|
||||||
try {
|
|
||||||
md = MessageDigest.getInstance("SHA-256");
|
|
||||||
} catch (NoSuchAlgorithmException e) {
|
|
||||||
throw new IOException("SHA-256 not implemented here.");
|
|
||||||
}
|
|
||||||
NullOutputStream nos = new NullOutputStream();
|
|
||||||
DigestOutputStream dos = new DigestOutputStream(nos, md);
|
|
||||||
|
|
||||||
byte[] transformedMasterKey = transformMasterKey(masterSeed2, masterKey, numRounds);
|
|
||||||
dos.write(masterSeed);
|
|
||||||
dos.write(transformedMasterKey);
|
|
||||||
|
|
||||||
finalKey = md.digest();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Encrypt the master key a few times to make brute-force key-search harder
|
* Encrypt the master key a few times to make brute-force key-search harder
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
|
|||||||
@@ -47,9 +47,13 @@ package com.kunzisoft.keepass.database;
|
|||||||
|
|
||||||
import com.kunzisoft.keepass.crypto.keyDerivation.AesKdf;
|
import com.kunzisoft.keepass.crypto.keyDerivation.AesKdf;
|
||||||
import com.kunzisoft.keepass.database.exception.InvalidKeyFileException;
|
import com.kunzisoft.keepass.database.exception.InvalidKeyFileException;
|
||||||
|
import com.kunzisoft.keepass.stream.NullOutputStream;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
import java.security.DigestOutputStream;
|
||||||
|
import java.security.MessageDigest;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
@@ -250,6 +254,25 @@ public class PwDatabaseV3 extends PwDatabase<PwGroupV3, PwEntryV3> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void makeFinalKey(byte[] masterSeed, byte[] masterSeed2, long numRounds) throws IOException {
|
||||||
|
|
||||||
|
// Write checksum Checksum
|
||||||
|
MessageDigest md;
|
||||||
|
try {
|
||||||
|
md = MessageDigest.getInstance("SHA-256");
|
||||||
|
} catch (NoSuchAlgorithmException e) {
|
||||||
|
throw new IOException("SHA-256 not implemented here.");
|
||||||
|
}
|
||||||
|
NullOutputStream nos = new NullOutputStream();
|
||||||
|
DigestOutputStream dos = new DigestOutputStream(nos, md);
|
||||||
|
|
||||||
|
byte[] transformedMasterKey = transformMasterKey(masterSeed2, masterKey, numRounds);
|
||||||
|
dos.write(masterSeed);
|
||||||
|
dos.write(transformedMasterKey);
|
||||||
|
|
||||||
|
finalKey = md.digest();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected String getPasswordEncoding() {
|
protected String getPasswordEncoding() {
|
||||||
return "ISO-8859-1";
|
return "ISO-8859-1";
|
||||||
|
|||||||
@@ -362,28 +362,6 @@ public class PwDatabaseV4 extends PwDatabase<PwGroupV4, PwEntryV4> {
|
|||||||
return md.digest(fKey);
|
return md.digest(fKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void makeFinalKey(byte[] masterSeed, byte[] masterSeed2, long numRounds) throws IOException {
|
|
||||||
|
|
||||||
byte[] transformedMasterKey = transformMasterKey(masterSeed2, masterKey, numRounds);
|
|
||||||
|
|
||||||
|
|
||||||
byte[] cmpKey = new byte[65];
|
|
||||||
System.arraycopy(masterSeed, 0, cmpKey, 0, 32);
|
|
||||||
System.arraycopy(transformedMasterKey, 0, cmpKey, 32, 32);
|
|
||||||
finalKey = CryptoUtil.resizeKey(cmpKey, 0, 64, dataEngine.keyLength());
|
|
||||||
|
|
||||||
MessageDigest md;
|
|
||||||
try {
|
|
||||||
md = MessageDigest.getInstance("SHA-512");
|
|
||||||
cmpKey[64] = 1;
|
|
||||||
hmacKey = md.digest(cmpKey);
|
|
||||||
} catch (NoSuchAlgorithmException e) {
|
|
||||||
throw new IOException("No SHA-512 implementation");
|
|
||||||
} finally {
|
|
||||||
Arrays.fill(cmpKey, (byte)0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public void makeFinalKey(byte[] masterSeed, KdfParameters kdfP) throws IOException {
|
public void makeFinalKey(byte[] masterSeed, KdfParameters kdfP) throws IOException {
|
||||||
makeFinalKey(masterSeed, kdfP, 0);
|
makeFinalKey(masterSeed, kdfP, 0);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,25 +17,25 @@
|
|||||||
* along with KeePass DX. If not, see <http://www.gnu.org/licenses/>.
|
* along with KeePass DX. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
package com.kunzisoft.keepass.database.edit;
|
package com.kunzisoft.keepass.database.action;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
|
||||||
import com.kunzisoft.keepass.database.Database;
|
import com.kunzisoft.keepass.database.Database;
|
||||||
import com.kunzisoft.keepass.database.PwEntry;
|
import com.kunzisoft.keepass.database.PwEntry;
|
||||||
|
|
||||||
public class AddEntry extends RunnableOnFinish {
|
public class AddEntryRunnable extends RunnableOnFinish {
|
||||||
|
|
||||||
protected Database mDb;
|
protected Database mDb;
|
||||||
private PwEntry mEntry;
|
private PwEntry mEntry;
|
||||||
private Context ctx;
|
private Context ctx;
|
||||||
private boolean mDontSave;
|
private boolean mDontSave;
|
||||||
|
|
||||||
public AddEntry(Context ctx, Database db, PwEntry entry, OnFinish finish) {
|
public AddEntryRunnable(Context ctx, Database db, PwEntry entry, OnFinishRunnable finish) {
|
||||||
this(ctx, db, entry, finish, false);
|
this(ctx, db, entry, finish, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public AddEntry(Context ctx, Database db, PwEntry entry, OnFinish finish, boolean dontSave) {
|
public AddEntryRunnable(Context ctx, Database db, PwEntry entry, OnFinishRunnable finish, boolean dontSave) {
|
||||||
super(finish);
|
super(finish);
|
||||||
|
|
||||||
this.mDb = db;
|
this.mDb = db;
|
||||||
@@ -51,13 +51,13 @@ public class AddEntry extends RunnableOnFinish {
|
|||||||
mDb.addEntryTo(mEntry, mEntry.getParent());
|
mDb.addEntryTo(mEntry, mEntry.getParent());
|
||||||
|
|
||||||
// Commit to disk
|
// Commit to disk
|
||||||
SaveDB save = new SaveDB(ctx, mDb, mFinish, mDontSave);
|
SaveDBRunnable save = new SaveDBRunnable(ctx, mDb, mFinish, mDontSave);
|
||||||
save.run();
|
save.run();
|
||||||
}
|
}
|
||||||
|
|
||||||
private class AfterAdd extends OnFinish {
|
private class AfterAdd extends OnFinishRunnable {
|
||||||
|
|
||||||
AfterAdd(OnFinish finish) {
|
AfterAdd(OnFinishRunnable finish) {
|
||||||
super(finish);
|
super(finish);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -17,26 +17,26 @@
|
|||||||
* along with KeePass DX. If not, see <http://www.gnu.org/licenses/>.
|
* along with KeePass DX. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
package com.kunzisoft.keepass.database.edit;
|
package com.kunzisoft.keepass.database.action;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
|
||||||
import com.kunzisoft.keepass.database.Database;
|
import com.kunzisoft.keepass.database.Database;
|
||||||
import com.kunzisoft.keepass.database.PwGroup;
|
import com.kunzisoft.keepass.database.PwGroup;
|
||||||
|
|
||||||
public class AddGroup extends RunnableOnFinish {
|
public class AddGroupRunnable extends RunnableOnFinish {
|
||||||
|
|
||||||
protected Database mDb;
|
protected Database mDb;
|
||||||
private PwGroup mNewGroup;
|
private PwGroup mNewGroup;
|
||||||
private Context ctx;
|
private Context ctx;
|
||||||
private boolean mDontSave;
|
private boolean mDontSave;
|
||||||
|
|
||||||
public AddGroup(Context ctx, Database db, PwGroup newGroup, AfterActionNodeOnFinish afterAddNode) {
|
public AddGroupRunnable(Context ctx, Database db, PwGroup newGroup, AfterActionNodeOnFinish afterAddNode) {
|
||||||
this(ctx, db, newGroup, afterAddNode, false);
|
this(ctx, db, newGroup, afterAddNode, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public AddGroup(Context ctx, Database db, PwGroup newGroup, AfterActionNodeOnFinish afterAddNode,
|
public AddGroupRunnable(Context ctx, Database db, PwGroup newGroup, AfterActionNodeOnFinish afterAddNode,
|
||||||
boolean dontSave) {
|
boolean dontSave) {
|
||||||
super(afterAddNode);
|
super(afterAddNode);
|
||||||
|
|
||||||
this.mDb = db;
|
this.mDb = db;
|
||||||
@@ -52,13 +52,13 @@ public class AddGroup extends RunnableOnFinish {
|
|||||||
mDb.addGroupTo(mNewGroup, mNewGroup.getParent());
|
mDb.addGroupTo(mNewGroup, mNewGroup.getParent());
|
||||||
|
|
||||||
// Commit to disk
|
// Commit to disk
|
||||||
SaveDB save = new SaveDB(ctx, mDb, mFinish, mDontSave);
|
SaveDBRunnable save = new SaveDBRunnable(ctx, mDb, mFinish, mDontSave);
|
||||||
save.run();
|
save.run();
|
||||||
}
|
}
|
||||||
|
|
||||||
private class AfterAdd extends OnFinish {
|
private class AfterAdd extends OnFinishRunnable {
|
||||||
|
|
||||||
AfterAdd(OnFinish finish) {
|
AfterAdd(OnFinishRunnable finish) {
|
||||||
super(finish);
|
super(finish);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -17,13 +17,13 @@
|
|||||||
* along with KeePass DX. If not, see <http://www.gnu.org/licenses/>.
|
* along with KeePass DX. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
package com.kunzisoft.keepass.database.edit;
|
package com.kunzisoft.keepass.database.action;
|
||||||
|
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
|
|
||||||
import com.kunzisoft.keepass.database.PwNode;
|
import com.kunzisoft.keepass.database.PwNode;
|
||||||
|
|
||||||
public abstract class AfterActionNodeOnFinish extends OnFinish {
|
public abstract class AfterActionNodeOnFinish extends OnFinishRunnable {
|
||||||
public AfterActionNodeOnFinish(Handler handler) {
|
public AfterActionNodeOnFinish(Handler handler) {
|
||||||
super(handler);
|
super(handler);
|
||||||
}
|
}
|
||||||
@@ -17,22 +17,20 @@
|
|||||||
* along with KeePass DX. If not, see <http://www.gnu.org/licenses/>.
|
* along with KeePass DX. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
package com.kunzisoft.keepass.database.edit;
|
package com.kunzisoft.keepass.database.action;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.DialogInterface;
|
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
|
|
||||||
import com.kunzisoft.keepass.database.Database;
|
import com.kunzisoft.keepass.database.Database;
|
||||||
import com.kunzisoft.keepass.database.PwDatabase;
|
import com.kunzisoft.keepass.database.PwDatabase;
|
||||||
import com.kunzisoft.keepass.database.exception.InvalidKeyFileException;
|
import com.kunzisoft.keepass.database.exception.InvalidKeyFileException;
|
||||||
import com.kunzisoft.keepass.dialogs.PasswordEncodingDialogHelper;
|
|
||||||
import com.kunzisoft.keepass.utils.UriUtil;
|
import com.kunzisoft.keepass.utils.UriUtil;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
|
||||||
public class SetPassword extends RunnableOnFinish {
|
public class AssignPasswordInDBRunnable extends RunnableOnFinish {
|
||||||
|
|
||||||
private String mPassword;
|
private String mPassword;
|
||||||
private Uri mKeyfile;
|
private Uri mKeyfile;
|
||||||
@@ -40,12 +38,12 @@ public class SetPassword extends RunnableOnFinish {
|
|||||||
private boolean mDontSave;
|
private boolean mDontSave;
|
||||||
private Context ctx;
|
private Context ctx;
|
||||||
|
|
||||||
public SetPassword(Context ctx, Database db, String password, Uri keyfile, OnFinish finish) {
|
public AssignPasswordInDBRunnable(Context ctx, Database db, String password, Uri keyfile, OnFinishRunnable finish) {
|
||||||
this(ctx, db, password, keyfile, finish, false);
|
this(ctx, db, password, keyfile, finish, false);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public SetPassword(Context ctx, Database db, String password, Uri keyfile, OnFinish finish, boolean dontSave) {
|
public AssignPasswordInDBRunnable(Context ctx, Database db, String password, Uri keyfile, OnFinishRunnable finish, boolean dontSave) {
|
||||||
super(finish);
|
super(finish);
|
||||||
|
|
||||||
mDb = db;
|
mDb = db;
|
||||||
@@ -55,16 +53,6 @@ public class SetPassword extends RunnableOnFinish {
|
|||||||
this.ctx = ctx;
|
this.ctx = ctx;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean validatePassword(Context ctx, DialogInterface.OnClickListener onclick) {
|
|
||||||
if (!mDb.getPwDatabase().validatePasswordEncoding(mPassword)) {
|
|
||||||
PasswordEncodingDialogHelper dialog = new PasswordEncodingDialogHelper();
|
|
||||||
dialog.show(ctx, onclick, true);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
PwDatabase pm = mDb.getPwDatabase();
|
PwDatabase pm = mDb.getPwDatabase();
|
||||||
@@ -88,14 +76,14 @@ public class SetPassword extends RunnableOnFinish {
|
|||||||
|
|
||||||
// Save Database
|
// Save Database
|
||||||
mFinish = new AfterSave(backupKey, mFinish);
|
mFinish = new AfterSave(backupKey, mFinish);
|
||||||
SaveDB save = new SaveDB(ctx, mDb, mFinish, mDontSave);
|
SaveDBRunnable save = new SaveDBRunnable(ctx, mDb, mFinish, mDontSave);
|
||||||
save.run();
|
save.run();
|
||||||
}
|
}
|
||||||
|
|
||||||
private class AfterSave extends OnFinish {
|
private class AfterSave extends OnFinishRunnable {
|
||||||
private byte[] mBackup;
|
private byte[] mBackup;
|
||||||
|
|
||||||
public AfterSave(byte[] backup, OnFinish finish) {
|
public AfterSave(byte[] backup, OnFinishRunnable finish) {
|
||||||
super(finish);
|
super(finish);
|
||||||
|
|
||||||
mBackup = backup;
|
mBackup = backup;
|
||||||
@@ -17,7 +17,7 @@
|
|||||||
* along with KeePass DX. If not, see <http://www.gnu.org/licenses/>.
|
* along with KeePass DX. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
package com.kunzisoft.keepass.database.edit;
|
package com.kunzisoft.keepass.database.action;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
|
||||||
@@ -26,13 +26,13 @@ import com.kunzisoft.keepass.database.Database;
|
|||||||
import com.kunzisoft.keepass.database.PwDatabase;
|
import com.kunzisoft.keepass.database.PwDatabase;
|
||||||
import com.kunzisoft.keepass.utils.UriUtil;
|
import com.kunzisoft.keepass.utils.UriUtil;
|
||||||
|
|
||||||
public class CreateDB extends RunnableOnFinish {
|
public class CreateDBRunnable extends RunnableOnFinish {
|
||||||
|
|
||||||
private String mFilename;
|
private String mFilename;
|
||||||
private boolean mDontSave;
|
private boolean mDontSave;
|
||||||
private Context ctx;
|
private Context ctx;
|
||||||
|
|
||||||
public CreateDB(Context ctx, String filename, OnFinish finish, boolean dontSave) {
|
public CreateDBRunnable(Context ctx, String filename, OnFinishRunnable finish, boolean dontSave) {
|
||||||
super(finish);
|
super(finish);
|
||||||
|
|
||||||
mFilename = filename;
|
mFilename = filename;
|
||||||
@@ -56,7 +56,7 @@ public class CreateDB extends RunnableOnFinish {
|
|||||||
App.clearShutdown();
|
App.clearShutdown();
|
||||||
|
|
||||||
// Commit changes
|
// Commit changes
|
||||||
SaveDB save = new SaveDB(ctx, db, mFinish, mDontSave);
|
SaveDBRunnable save = new SaveDBRunnable(ctx, db, mFinish, mDontSave);
|
||||||
mFinish = null;
|
mFinish = null;
|
||||||
save.run();
|
save.run();
|
||||||
}
|
}
|
||||||
@@ -17,7 +17,7 @@
|
|||||||
* along with KeePass DX. If not, see <http://www.gnu.org/licenses/>.
|
* along with KeePass DX. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
package com.kunzisoft.keepass.database.edit;
|
package com.kunzisoft.keepass.database.action;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
|
||||||
@@ -29,18 +29,18 @@ import com.kunzisoft.keepass.database.PwGroup;
|
|||||||
* @author bpellin
|
* @author bpellin
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class DeleteEntry extends RunnableOnFinish {
|
public class DeleteEntryRunnable extends RunnableOnFinish {
|
||||||
|
|
||||||
private Database mDb;
|
private Database mDb;
|
||||||
private PwEntry mEntry;
|
private PwEntry mEntry;
|
||||||
private boolean mDontSave;
|
private boolean mDontSave;
|
||||||
private Context ctx;
|
private Context ctx;
|
||||||
|
|
||||||
public DeleteEntry(Context ctx, Database db, PwEntry entry, OnFinish finish) {
|
public DeleteEntryRunnable(Context ctx, Database db, PwEntry entry, OnFinishRunnable finish) {
|
||||||
this(ctx, db, entry, finish, false);
|
this(ctx, db, entry, finish, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public DeleteEntry(Context ctx, Database db, PwEntry entry, OnFinish finish, boolean dontSave) {
|
public DeleteEntryRunnable(Context ctx, Database db, PwEntry entry, OnFinishRunnable finish, boolean dontSave) {
|
||||||
super(finish);
|
super(finish);
|
||||||
|
|
||||||
this.mDb = db;
|
this.mDb = db;
|
||||||
@@ -67,17 +67,17 @@ public class DeleteEntry extends RunnableOnFinish {
|
|||||||
mFinish = new AfterDelete(mFinish, parent, mEntry, recycle);
|
mFinish = new AfterDelete(mFinish, parent, mEntry, recycle);
|
||||||
|
|
||||||
// Commit database
|
// Commit database
|
||||||
SaveDB save = new SaveDB(ctx, mDb, mFinish, mDontSave);
|
SaveDBRunnable save = new SaveDBRunnable(ctx, mDb, mFinish, mDontSave);
|
||||||
save.run();
|
save.run();
|
||||||
}
|
}
|
||||||
|
|
||||||
private class AfterDelete extends OnFinish {
|
private class AfterDelete extends OnFinishRunnable {
|
||||||
|
|
||||||
private PwGroup mParent;
|
private PwGroup mParent;
|
||||||
private PwEntry mEntry;
|
private PwEntry mEntry;
|
||||||
private boolean recycled;
|
private boolean recycled;
|
||||||
|
|
||||||
AfterDelete(OnFinish finish, PwGroup parent, PwEntry entry, boolean r) {
|
AfterDelete(OnFinishRunnable finish, PwGroup parent, PwEntry entry, boolean r) {
|
||||||
super(finish);
|
super(finish);
|
||||||
|
|
||||||
mParent = parent;
|
mParent = parent;
|
||||||
@@ -17,7 +17,7 @@
|
|||||||
* along with KeePass DX. If not, see <http://www.gnu.org/licenses/>.
|
* along with KeePass DX. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
package com.kunzisoft.keepass.database.edit;
|
package com.kunzisoft.keepass.database.action;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
|
||||||
@@ -29,19 +29,19 @@ import com.kunzisoft.keepass.database.PwGroup;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class DeleteGroup extends RunnableOnFinish {
|
public class DeleteGroupRunnable extends RunnableOnFinish {
|
||||||
|
|
||||||
private Context mContext;
|
private Context mContext;
|
||||||
private Database mDb;
|
private Database mDb;
|
||||||
private PwGroup<PwGroup, PwGroup, PwEntry> mGroup;
|
private PwGroup<PwGroup, PwGroup, PwEntry> mGroup;
|
||||||
private boolean mDontSave;
|
private boolean mDontSave;
|
||||||
|
|
||||||
public DeleteGroup(Context ctx, Database db, PwGroup<PwGroup, PwGroup, PwEntry> group, OnFinish finish) {
|
public DeleteGroupRunnable(Context ctx, Database db, PwGroup<PwGroup, PwGroup, PwEntry> group, OnFinishRunnable finish) {
|
||||||
super(finish);
|
super(finish);
|
||||||
setMembers(ctx, db, group, false);
|
setMembers(ctx, db, group, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public DeleteGroup(Context ctx, Database db, PwGroup<PwGroup, PwGroup, PwEntry> group, OnFinish finish, boolean dontSave) {
|
public DeleteGroupRunnable(Context ctx, Database db, PwGroup<PwGroup, PwGroup, PwEntry> group, OnFinishRunnable finish, boolean dontSave) {
|
||||||
super(finish);
|
super(finish);
|
||||||
setMembers(ctx, db, group, dontSave);
|
setMembers(ctx, db, group, dontSave);
|
||||||
}
|
}
|
||||||
@@ -67,14 +67,14 @@ public class DeleteGroup extends RunnableOnFinish {
|
|||||||
// Remove child entries
|
// Remove child entries
|
||||||
List<PwEntry> childEnt = new ArrayList<>(mGroup.getChildEntries()); // TODO new Methods
|
List<PwEntry> childEnt = new ArrayList<>(mGroup.getChildEntries()); // TODO new Methods
|
||||||
for ( int i = 0; i < childEnt.size(); i++ ) {
|
for ( int i = 0; i < childEnt.size(); i++ ) {
|
||||||
DeleteEntry task = new DeleteEntry(mContext, mDb, childEnt.get(i), null, true);
|
DeleteEntryRunnable task = new DeleteEntryRunnable(mContext, mDb, childEnt.get(i), null, true);
|
||||||
task.run();
|
task.run();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove child groups
|
// Remove child groups
|
||||||
List<PwGroup> childGrp = new ArrayList<>(mGroup.getChildGroups());
|
List<PwGroup> childGrp = new ArrayList<>(mGroup.getChildGroups());
|
||||||
for ( int i = 0; i < childGrp.size(); i++ ) {
|
for ( int i = 0; i < childGrp.size(); i++ ) {
|
||||||
DeleteGroup task = new DeleteGroup(mContext, mDb, childGrp.get(i), null, true);
|
DeleteGroupRunnable task = new DeleteGroupRunnable(mContext, mDb, childGrp.get(i), null, true);
|
||||||
task.run();
|
task.run();
|
||||||
}
|
}
|
||||||
mDb.deleteGroup(mGroup);
|
mDb.deleteGroup(mGroup);
|
||||||
@@ -88,17 +88,17 @@ public class DeleteGroup extends RunnableOnFinish {
|
|||||||
mFinish = new AfterDelete(mFinish, parent, mGroup, recycle);
|
mFinish = new AfterDelete(mFinish, parent, mGroup, recycle);
|
||||||
|
|
||||||
// Commit Database
|
// Commit Database
|
||||||
SaveDB save = new SaveDB(mContext, mDb, mFinish, mDontSave);
|
SaveDBRunnable save = new SaveDBRunnable(mContext, mDb, mFinish, mDontSave);
|
||||||
save.run();
|
save.run();
|
||||||
}
|
}
|
||||||
|
|
||||||
private class AfterDelete extends OnFinish {
|
private class AfterDelete extends OnFinishRunnable {
|
||||||
|
|
||||||
private PwGroup mParent;
|
private PwGroup mParent;
|
||||||
private PwGroup mGroup;
|
private PwGroup mGroup;
|
||||||
private boolean recycled;
|
private boolean recycled;
|
||||||
|
|
||||||
AfterDelete(OnFinish finish, PwGroup parent, PwGroup mGroup, boolean recycle) {
|
AfterDelete(OnFinishRunnable finish, PwGroup parent, PwGroup mGroup, boolean recycle) {
|
||||||
super(finish);
|
super(finish);
|
||||||
|
|
||||||
this.mParent = parent;
|
this.mParent = parent;
|
||||||
@@ -17,17 +17,17 @@
|
|||||||
* along with KeePass DX. If not, see <http://www.gnu.org/licenses/>.
|
* along with KeePass DX. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
package com.kunzisoft.keepass.database.edit;
|
package com.kunzisoft.keepass.database.action;
|
||||||
|
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
|
||||||
public class FileOnFinish extends OnFinish implements Serializable {
|
public class FileOnFinishRunnable extends OnFinishRunnable implements Serializable {
|
||||||
private Uri mFilename = null;
|
private Uri mFilename = null;
|
||||||
protected FileOnFinish mOnFinish;
|
protected FileOnFinishRunnable mOnFinish;
|
||||||
|
|
||||||
public FileOnFinish(FileOnFinish finish) {
|
public FileOnFinishRunnable(FileOnFinishRunnable finish) {
|
||||||
super(finish);
|
super(finish);
|
||||||
|
|
||||||
mOnFinish = finish;
|
mOnFinish = finish;
|
||||||
@@ -17,7 +17,7 @@
|
|||||||
* along with KeePass DX. If not, see <http://www.gnu.org/licenses/>.
|
* along with KeePass DX. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
package com.kunzisoft.keepass.database.edit;
|
package com.kunzisoft.keepass.database.action;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
@@ -40,7 +40,7 @@ import com.kunzisoft.keepass.database.exception.KeyFileEmptyException;
|
|||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
public class LoadDB extends RunnableOnFinish {
|
public class LoadDBRunnable extends RunnableOnFinish {
|
||||||
private Uri mUri;
|
private Uri mUri;
|
||||||
private String mPass;
|
private String mPass;
|
||||||
private Uri mKey;
|
private Uri mKey;
|
||||||
@@ -48,7 +48,7 @@ public class LoadDB extends RunnableOnFinish {
|
|||||||
private Context mCtx;
|
private Context mCtx;
|
||||||
private boolean mRememberKeyfile;
|
private boolean mRememberKeyfile;
|
||||||
|
|
||||||
public LoadDB(Database db, Context ctx, Uri uri, String pass, Uri key, OnFinish finish) {
|
public LoadDBRunnable(Database db, Context ctx, Uri uri, String pass, Uri key, OnFinishRunnable finish) {
|
||||||
super(finish);
|
super(finish);
|
||||||
|
|
||||||
mDb = db;
|
mDb = db;
|
||||||
@@ -17,7 +17,7 @@
|
|||||||
* along with KeePass DX. If not, see <http://www.gnu.org/licenses/>.
|
* along with KeePass DX. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
package com.kunzisoft.keepass.database.edit;
|
package com.kunzisoft.keepass.database.action;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
@@ -29,27 +29,27 @@ import android.widget.Toast;
|
|||||||
* @author bpellin
|
* @author bpellin
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class OnFinish implements Runnable {
|
public class OnFinishRunnable implements Runnable {
|
||||||
protected boolean mSuccess;
|
protected boolean mSuccess;
|
||||||
protected String mMessage;
|
protected String mMessage;
|
||||||
|
|
||||||
protected OnFinish mOnFinish;
|
protected OnFinishRunnable mOnFinish;
|
||||||
protected Handler mHandler;
|
protected Handler mHandler;
|
||||||
|
|
||||||
public OnFinish() {
|
public OnFinishRunnable() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public OnFinish(Handler handler) {
|
public OnFinishRunnable(Handler handler) {
|
||||||
mOnFinish = null;
|
mOnFinish = null;
|
||||||
mHandler = handler;
|
mHandler = handler;
|
||||||
}
|
}
|
||||||
|
|
||||||
public OnFinish(OnFinish finish, Handler handler) {
|
public OnFinishRunnable(OnFinishRunnable finish, Handler handler) {
|
||||||
mOnFinish = finish;
|
mOnFinish = finish;
|
||||||
mHandler = handler;
|
mHandler = handler;
|
||||||
}
|
}
|
||||||
|
|
||||||
public OnFinish(OnFinish finish) {
|
public OnFinishRunnable(OnFinishRunnable finish) {
|
||||||
mOnFinish = finish;
|
mOnFinish = finish;
|
||||||
mHandler = null;
|
mHandler = null;
|
||||||
}
|
}
|
||||||
@@ -75,7 +75,8 @@ public class OnFinish implements Runnable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO Move
|
||||||
protected void displayMessage(Context ctx) {
|
protected void displayMessage(Context ctx) {
|
||||||
if ( mMessage != null && mMessage.length() > 0 ) {
|
if ( mMessage != null && mMessage.length() > 0 ) {
|
||||||
Toast.makeText(ctx, mMessage, Toast.LENGTH_LONG).show();
|
Toast.makeText(ctx, mMessage, Toast.LENGTH_LONG).show();
|
||||||
@@ -17,17 +17,17 @@
|
|||||||
* along with KeePass DX. If not, see <http://www.gnu.org/licenses/>.
|
* along with KeePass DX. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
package com.kunzisoft.keepass.database.edit;
|
package com.kunzisoft.keepass.database.action;
|
||||||
|
|
||||||
import com.kunzisoft.keepass.tasks.UpdateStatus;
|
import com.kunzisoft.keepass.tasks.ProgressTaskUpdater;
|
||||||
|
|
||||||
|
|
||||||
public abstract class RunnableOnFinish implements Runnable {
|
public abstract class RunnableOnFinish implements Runnable {
|
||||||
|
|
||||||
public OnFinish mFinish;
|
public OnFinishRunnable mFinish;
|
||||||
public UpdateStatus mStatus;
|
public ProgressTaskUpdater mStatus;
|
||||||
|
|
||||||
public RunnableOnFinish(OnFinish finish) {
|
public RunnableOnFinish(OnFinishRunnable finish) {
|
||||||
mFinish = finish;
|
mFinish = finish;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -45,7 +45,7 @@ public abstract class RunnableOnFinish implements Runnable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setStatus(UpdateStatus status) {
|
public void setUpdateProgressTaskStatus(ProgressTaskUpdater status) {
|
||||||
mStatus = status;
|
mStatus = status;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -17,7 +17,7 @@
|
|||||||
* along with KeePass DX. If not, see <http://www.gnu.org/licenses/>.
|
* along with KeePass DX. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
package com.kunzisoft.keepass.database.edit;
|
package com.kunzisoft.keepass.database.action;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
|
||||||
@@ -26,12 +26,12 @@ import com.kunzisoft.keepass.database.exception.PwDbOutputException;
|
|||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
public class SaveDB extends RunnableOnFinish {
|
public class SaveDBRunnable extends RunnableOnFinish {
|
||||||
private Database mDb;
|
private Database mDb;
|
||||||
private boolean mDontSave;
|
private boolean mDontSave;
|
||||||
private Context mCtx;
|
private Context mCtx;
|
||||||
|
|
||||||
public SaveDB(Context ctx, Database db, OnFinish finish, boolean dontSave) {
|
public SaveDBRunnable(Context ctx, Database db, OnFinishRunnable finish, boolean dontSave) {
|
||||||
super(finish);
|
super(finish);
|
||||||
|
|
||||||
mDb = db;
|
mDb = db;
|
||||||
@@ -39,7 +39,7 @@ public class SaveDB extends RunnableOnFinish {
|
|||||||
mCtx = ctx;
|
mCtx = ctx;
|
||||||
}
|
}
|
||||||
|
|
||||||
public SaveDB(Context ctx, Database db, OnFinish finish) {
|
public SaveDBRunnable(Context ctx, Database db, OnFinishRunnable finish) {
|
||||||
super(finish);
|
super(finish);
|
||||||
|
|
||||||
mDb = db;
|
mDb = db;
|
||||||
@@ -17,14 +17,14 @@
|
|||||||
* along with KeePass DX. If not, see <http://www.gnu.org/licenses/>.
|
* along with KeePass DX. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
package com.kunzisoft.keepass.database.edit;
|
package com.kunzisoft.keepass.database.action;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
|
||||||
import com.kunzisoft.keepass.database.Database;
|
import com.kunzisoft.keepass.database.Database;
|
||||||
import com.kunzisoft.keepass.database.PwEntry;
|
import com.kunzisoft.keepass.database.PwEntry;
|
||||||
|
|
||||||
public class UpdateEntry extends RunnableOnFinish {
|
public class UpdateEntryRunnable extends RunnableOnFinish {
|
||||||
|
|
||||||
private Database mDb;
|
private Database mDb;
|
||||||
private PwEntry mOldE;
|
private PwEntry mOldE;
|
||||||
@@ -32,11 +32,11 @@ public class UpdateEntry extends RunnableOnFinish {
|
|||||||
private Context ctx;
|
private Context ctx;
|
||||||
private boolean mDontSave;
|
private boolean mDontSave;
|
||||||
|
|
||||||
public UpdateEntry(Context ctx, Database db, PwEntry oldE, PwEntry newE, OnFinish finish) {
|
public UpdateEntryRunnable(Context ctx, Database db, PwEntry oldE, PwEntry newE, OnFinishRunnable finish) {
|
||||||
this(ctx, db, oldE, newE, finish, false);
|
this(ctx, db, oldE, newE, finish, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public UpdateEntry(Context ctx, Database db, PwEntry oldE, PwEntry newE, OnFinish finish, boolean dontSave) {
|
public UpdateEntryRunnable(Context ctx, Database db, PwEntry oldE, PwEntry newE, OnFinishRunnable finish, boolean dontSave) {
|
||||||
super(finish);
|
super(finish);
|
||||||
|
|
||||||
this.mDb = db;
|
this.mDb = db;
|
||||||
@@ -59,14 +59,14 @@ public class UpdateEntry extends RunnableOnFinish {
|
|||||||
mOldE.touch(true, true);
|
mOldE.touch(true, true);
|
||||||
|
|
||||||
// Commit to disk
|
// Commit to disk
|
||||||
SaveDB save = new SaveDB(ctx, mDb, mFinish, mDontSave);
|
SaveDBRunnable save = new SaveDBRunnable(ctx, mDb, mFinish, mDontSave);
|
||||||
save.run();
|
save.run();
|
||||||
}
|
}
|
||||||
|
|
||||||
private class AfterUpdate extends OnFinish {
|
private class AfterUpdate extends OnFinishRunnable {
|
||||||
private PwEntry mBackup;
|
private PwEntry mBackup;
|
||||||
|
|
||||||
AfterUpdate(PwEntry backup, OnFinish finish) {
|
AfterUpdate(PwEntry backup, OnFinishRunnable finish) {
|
||||||
super(finish);
|
super(finish);
|
||||||
mBackup = backup;
|
mBackup = backup;
|
||||||
}
|
}
|
||||||
@@ -17,14 +17,14 @@
|
|||||||
* along with KeePass DX. If not, see <http://www.gnu.org/licenses/>.
|
* along with KeePass DX. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
package com.kunzisoft.keepass.database.edit;
|
package com.kunzisoft.keepass.database.action;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
|
||||||
import com.kunzisoft.keepass.database.Database;
|
import com.kunzisoft.keepass.database.Database;
|
||||||
import com.kunzisoft.keepass.database.PwGroup;
|
import com.kunzisoft.keepass.database.PwGroup;
|
||||||
|
|
||||||
public class UpdateGroup extends RunnableOnFinish {
|
public class UpdateGroupRunnable extends RunnableOnFinish {
|
||||||
|
|
||||||
private Database mDb;
|
private Database mDb;
|
||||||
private PwGroup mOldGroup;
|
private PwGroup mOldGroup;
|
||||||
@@ -32,11 +32,11 @@ public class UpdateGroup extends RunnableOnFinish {
|
|||||||
private Context ctx;
|
private Context ctx;
|
||||||
private boolean mDontSave;
|
private boolean mDontSave;
|
||||||
|
|
||||||
public UpdateGroup(Context ctx, Database db, PwGroup oldGroup, PwGroup newGroup, AfterActionNodeOnFinish finish) {
|
public UpdateGroupRunnable(Context ctx, Database db, PwGroup oldGroup, PwGroup newGroup, AfterActionNodeOnFinish finish) {
|
||||||
this(ctx, db, oldGroup, newGroup, finish, false);
|
this(ctx, db, oldGroup, newGroup, finish, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public UpdateGroup(Context ctx, Database db, PwGroup oldGroup, PwGroup newGroup, AfterActionNodeOnFinish finish, boolean dontSave) {
|
public UpdateGroupRunnable(Context ctx, Database db, PwGroup oldGroup, PwGroup newGroup, AfterActionNodeOnFinish finish, boolean dontSave) {
|
||||||
super(finish);
|
super(finish);
|
||||||
|
|
||||||
this.mDb = db;
|
this.mDb = db;
|
||||||
@@ -59,13 +59,13 @@ public class UpdateGroup extends RunnableOnFinish {
|
|||||||
mOldGroup.touch(true, true);
|
mOldGroup.touch(true, true);
|
||||||
|
|
||||||
// Commit to disk
|
// Commit to disk
|
||||||
new SaveDB(ctx, mDb, mFinish, mDontSave).run();
|
new SaveDBRunnable(ctx, mDb, mFinish, mDontSave).run();
|
||||||
}
|
}
|
||||||
|
|
||||||
private class AfterUpdate extends OnFinish {
|
private class AfterUpdate extends OnFinishRunnable {
|
||||||
private PwGroup mBackup;
|
private PwGroup mBackup;
|
||||||
|
|
||||||
AfterUpdate(PwGroup backup, OnFinish finish) {
|
AfterUpdate(PwGroup backup, OnFinishRunnable finish) {
|
||||||
super(finish);
|
super(finish);
|
||||||
mBackup = backup;
|
mBackup = backup;
|
||||||
}
|
}
|
||||||
@@ -21,7 +21,7 @@ package com.kunzisoft.keepass.database.load;
|
|||||||
|
|
||||||
import com.kunzisoft.keepass.database.PwDatabase;
|
import com.kunzisoft.keepass.database.PwDatabase;
|
||||||
import com.kunzisoft.keepass.database.exception.InvalidDBException;
|
import com.kunzisoft.keepass.database.exception.InvalidDBException;
|
||||||
import com.kunzisoft.keepass.tasks.UpdateStatus;
|
import com.kunzisoft.keepass.tasks.ProgressTaskUpdater;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
@@ -33,8 +33,7 @@ public abstract class Importer {
|
|||||||
public abstract PwDatabase openDatabase(InputStream inStream, String password, InputStream keyInputStream)
|
public abstract PwDatabase openDatabase(InputStream inStream, String password, InputStream keyInputStream)
|
||||||
throws IOException, InvalidDBException;
|
throws IOException, InvalidDBException;
|
||||||
|
|
||||||
public abstract PwDatabase openDatabase(InputStream inStream, String password, InputStream keyInputStream, UpdateStatus status, long roundsFix)
|
public abstract PwDatabase openDatabase(InputStream inStream, String password, InputStream keyInputStream, ProgressTaskUpdater updater, long roundsFix)
|
||||||
throws IOException, InvalidDBException;
|
throws IOException, InvalidDBException;
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ import com.kunzisoft.keepass.database.exception.InvalidPasswordException;
|
|||||||
import com.kunzisoft.keepass.stream.LEDataInputStream;
|
import com.kunzisoft.keepass.stream.LEDataInputStream;
|
||||||
import com.kunzisoft.keepass.stream.LEDataOutputStream;
|
import com.kunzisoft.keepass.stream.LEDataOutputStream;
|
||||||
import com.kunzisoft.keepass.stream.NullOutputStream;
|
import com.kunzisoft.keepass.stream.NullOutputStream;
|
||||||
import com.kunzisoft.keepass.tasks.UpdateStatus;
|
import com.kunzisoft.keepass.tasks.ProgressTaskUpdater;
|
||||||
import com.kunzisoft.keepass.utils.Types;
|
import com.kunzisoft.keepass.utils.Types;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@@ -124,15 +124,15 @@ public class ImporterV3 extends Importer {
|
|||||||
* @throws InvalidAlgorithmParameterException if error decrypting main file body.
|
* @throws InvalidAlgorithmParameterException if error decrypting main file body.
|
||||||
* @throws ShortBufferException if error decrypting main file body.
|
* @throws ShortBufferException if error decrypting main file body.
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public PwDatabaseV3 openDatabase( InputStream inStream, String password, InputStream kfIs)
|
public PwDatabaseV3 openDatabase( InputStream inStream, String password, InputStream kfIs)
|
||||||
throws IOException, InvalidDBException
|
throws IOException, InvalidDBException {
|
||||||
{
|
return openDatabase(inStream, password, kfIs, null, 0);
|
||||||
return openDatabase(inStream, password, kfIs, new UpdateStatus(), 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public PwDatabaseV3 openDatabase( InputStream inStream, String password, InputStream kfIs, UpdateStatus status, long roundsFix)
|
@Override
|
||||||
throws IOException, InvalidDBException
|
public PwDatabaseV3 openDatabase(InputStream inStream, String password, InputStream kfIs, ProgressTaskUpdater progressTaskUpdater, long roundsFix)
|
||||||
{
|
throws IOException, InvalidDBException {
|
||||||
PwDatabaseV3 newManager;
|
PwDatabaseV3 newManager;
|
||||||
|
|
||||||
|
|
||||||
@@ -156,7 +156,8 @@ public class ImporterV3 extends Importer {
|
|||||||
throw new InvalidDBVersionException();
|
throw new InvalidDBVersionException();
|
||||||
}
|
}
|
||||||
|
|
||||||
status.updateMessage(R.string.creating_db_key);
|
if (progressTaskUpdater != null)
|
||||||
|
progressTaskUpdater.updateMessage(R.string.creating_db_key);
|
||||||
newManager = createDB();
|
newManager = createDB();
|
||||||
newManager.setMasterKey(password, kfIs);
|
newManager.setMasterKey(password, kfIs);
|
||||||
|
|
||||||
@@ -177,7 +178,8 @@ public class ImporterV3 extends Importer {
|
|||||||
// Generate transformedMasterKey from masterKey
|
// Generate transformedMasterKey from masterKey
|
||||||
newManager.makeFinalKey(hdr.masterSeed, hdr.transformSeed, newManager.getNumberKeyEncryptionRounds());
|
newManager.makeFinalKey(hdr.masterSeed, hdr.transformSeed, newManager.getNumberKeyEncryptionRounds());
|
||||||
|
|
||||||
status.updateMessage(R.string.decrypting_db);
|
if (progressTaskUpdater != null)
|
||||||
|
progressTaskUpdater.updateMessage(R.string.decrypting_db);
|
||||||
// Initialize Rijndael algorithm
|
// Initialize Rijndael algorithm
|
||||||
Cipher cipher;
|
Cipher cipher;
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ package com.kunzisoft.keepass.database.load;
|
|||||||
|
|
||||||
import com.kunzisoft.keepass.database.PwDatabaseV3Debug;
|
import com.kunzisoft.keepass.database.PwDatabaseV3Debug;
|
||||||
import com.kunzisoft.keepass.database.exception.InvalidDBException;
|
import com.kunzisoft.keepass.database.exception.InvalidDBException;
|
||||||
import com.kunzisoft.keepass.tasks.UpdateStatus;
|
import com.kunzisoft.keepass.tasks.ProgressTaskUpdater;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
@@ -35,7 +35,7 @@ public class ImporterV3Debug extends ImporterV3 {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PwDatabaseV3Debug openDatabase(InputStream inStream, String password,
|
public PwDatabaseV3Debug openDatabase(InputStream inStream, String password,
|
||||||
InputStream keyInputStream, UpdateStatus status, long roundsFix) throws IOException,
|
InputStream keyInputStream, ProgressTaskUpdater status, long roundsFix) throws IOException,
|
||||||
InvalidDBException {
|
InvalidDBException {
|
||||||
return (PwDatabaseV3Debug) super.openDatabase(inStream, password, keyInputStream, status,
|
return (PwDatabaseV3Debug) super.openDatabase(inStream, password, keyInputStream, status,
|
||||||
roundsFix);
|
roundsFix);
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
*/
|
*/
|
||||||
package com.kunzisoft.keepass.database.load;
|
package com.kunzisoft.keepass.database.load;
|
||||||
|
|
||||||
|
import com.kunzisoft.keepass.R;
|
||||||
import com.kunzisoft.keepass.crypto.CipherFactory;
|
import com.kunzisoft.keepass.crypto.CipherFactory;
|
||||||
import com.kunzisoft.keepass.crypto.PwStreamCipherFactory;
|
import com.kunzisoft.keepass.crypto.PwStreamCipherFactory;
|
||||||
import com.kunzisoft.keepass.crypto.engine.CipherEngine;
|
import com.kunzisoft.keepass.crypto.engine.CipherEngine;
|
||||||
@@ -42,7 +43,7 @@ import com.kunzisoft.keepass.stream.BetterCipherInputStream;
|
|||||||
import com.kunzisoft.keepass.stream.HashedBlockInputStream;
|
import com.kunzisoft.keepass.stream.HashedBlockInputStream;
|
||||||
import com.kunzisoft.keepass.stream.HmacBlockInputStream;
|
import com.kunzisoft.keepass.stream.HmacBlockInputStream;
|
||||||
import com.kunzisoft.keepass.stream.LEDataInputStream;
|
import com.kunzisoft.keepass.stream.LEDataInputStream;
|
||||||
import com.kunzisoft.keepass.tasks.UpdateStatus;
|
import com.kunzisoft.keepass.tasks.ProgressTaskUpdater;
|
||||||
import com.kunzisoft.keepass.utils.DateUtil;
|
import com.kunzisoft.keepass.utils.DateUtil;
|
||||||
import com.kunzisoft.keepass.utils.EmptyUtils;
|
import com.kunzisoft.keepass.utils.EmptyUtils;
|
||||||
import com.kunzisoft.keepass.utils.MemUtil;
|
import com.kunzisoft.keepass.utils.MemUtil;
|
||||||
@@ -97,13 +98,16 @@ public class ImporterV4 extends Importer {
|
|||||||
public PwDatabaseV4 openDatabase(InputStream inStream, String password,
|
public PwDatabaseV4 openDatabase(InputStream inStream, String password,
|
||||||
InputStream keyInputStream) throws IOException, InvalidDBException {
|
InputStream keyInputStream) throws IOException, InvalidDBException {
|
||||||
|
|
||||||
return openDatabase(inStream, password, keyInputStream, new UpdateStatus(), 0);
|
return openDatabase(inStream, password, keyInputStream, null, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PwDatabaseV4 openDatabase(InputStream inStream, String password,
|
public PwDatabaseV4 openDatabase(InputStream inStream, String password,
|
||||||
InputStream keyInputStream, UpdateStatus status, long roundsFix) throws IOException,
|
InputStream keyInputStream, ProgressTaskUpdater progressTaskUpdater, long roundsFix) throws IOException,
|
||||||
InvalidDBException {
|
InvalidDBException {
|
||||||
|
|
||||||
|
if (progressTaskUpdater != null)
|
||||||
|
progressTaskUpdater.updateMessage(R.string.creating_db_key);
|
||||||
db = createDB();
|
db = createDB();
|
||||||
|
|
||||||
PwDbHeaderV4 header = new PwDbHeaderV4(db);
|
PwDbHeaderV4 header = new PwDbHeaderV4(db);
|
||||||
@@ -118,6 +122,8 @@ public class ImporterV4 extends Importer {
|
|||||||
db.setMasterKey(password, keyInputStream);
|
db.setMasterKey(password, keyInputStream);
|
||||||
db.makeFinalKey(header.masterSeed, db.getKdfParameters(), roundsFix);
|
db.makeFinalKey(header.masterSeed, db.getKdfParameters(), roundsFix);
|
||||||
|
|
||||||
|
if (progressTaskUpdater != null)
|
||||||
|
progressTaskUpdater.updateMessage(R.string.decrypting_db);
|
||||||
CipherEngine engine;
|
CipherEngine engine;
|
||||||
Cipher cipher;
|
Cipher cipher;
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -51,8 +51,8 @@ import com.kunzisoft.keepass.R;
|
|||||||
import com.kunzisoft.keepass.activities.GroupActivity;
|
import com.kunzisoft.keepass.activities.GroupActivity;
|
||||||
import com.kunzisoft.keepass.app.App;
|
import com.kunzisoft.keepass.app.App;
|
||||||
import com.kunzisoft.keepass.autofill.AutofillHelper;
|
import com.kunzisoft.keepass.autofill.AutofillHelper;
|
||||||
import com.kunzisoft.keepass.database.edit.CreateDB;
|
import com.kunzisoft.keepass.database.action.CreateDBRunnable;
|
||||||
import com.kunzisoft.keepass.database.edit.FileOnFinish;
|
import com.kunzisoft.keepass.database.action.FileOnFinishRunnable;
|
||||||
import com.kunzisoft.keepass.database.exception.ContentFileNotFoundException;
|
import com.kunzisoft.keepass.database.exception.ContentFileNotFoundException;
|
||||||
import com.kunzisoft.keepass.dialogs.AssignMasterKeyDialogFragment;
|
import com.kunzisoft.keepass.dialogs.AssignMasterKeyDialogFragment;
|
||||||
import com.kunzisoft.keepass.dialogs.CreateFileDialogFragment;
|
import com.kunzisoft.keepass.dialogs.CreateFileDialogFragment;
|
||||||
@@ -60,7 +60,8 @@ import com.kunzisoft.keepass.password.AssignPasswordHelper;
|
|||||||
import com.kunzisoft.keepass.password.PasswordActivity;
|
import com.kunzisoft.keepass.password.PasswordActivity;
|
||||||
import com.kunzisoft.keepass.settings.PreferencesUtil;
|
import com.kunzisoft.keepass.settings.PreferencesUtil;
|
||||||
import com.kunzisoft.keepass.stylish.StylishActivity;
|
import com.kunzisoft.keepass.stylish.StylishActivity;
|
||||||
import com.kunzisoft.keepass.tasks.ProgressTask;
|
import com.kunzisoft.keepass.tasks.ProgressTaskDialogFragment;
|
||||||
|
import com.kunzisoft.keepass.tasks.UpdateProgressTaskStatus;
|
||||||
import com.kunzisoft.keepass.utils.EmptyUtils;
|
import com.kunzisoft.keepass.utils.EmptyUtils;
|
||||||
import com.kunzisoft.keepass.utils.MenuUtil;
|
import com.kunzisoft.keepass.utils.MenuUtil;
|
||||||
import com.kunzisoft.keepass.utils.UriUtil;
|
import com.kunzisoft.keepass.utils.UriUtil;
|
||||||
@@ -515,22 +516,26 @@ public class FileSelectActivity extends StylishActivity implements
|
|||||||
|
|
||||||
// Prep an object to collect a password once the database has
|
// Prep an object to collect a password once the database has
|
||||||
// been created
|
// been created
|
||||||
FileOnFinish launchActivityOnFinish = new FileOnFinish(
|
FileOnFinishRunnable launchActivityOnFinish = new FileOnFinishRunnable(
|
||||||
new LaunchGroupActivity(databaseFilename));
|
new LaunchGroupActivity(databaseFilename));
|
||||||
AssignPasswordOnFinish assignPasswordOnFinish =
|
AssignPasswordOnFinish assignPasswordOnFinish =
|
||||||
new AssignPasswordOnFinish(launchActivityOnFinish);
|
new AssignPasswordOnFinish(launchActivityOnFinish);
|
||||||
|
|
||||||
// Create the new database
|
// Initialize the password helper assigner to set the password after the database creation
|
||||||
CreateDB create = new CreateDB(FileSelectActivity.this,
|
|
||||||
databaseFilename, assignPasswordOnFinish, true);
|
|
||||||
|
|
||||||
ProgressTask createTask = new ProgressTask(
|
|
||||||
FileSelectActivity.this, create,
|
|
||||||
R.string.progress_create);
|
|
||||||
createTask.run();
|
|
||||||
|
|
||||||
assignPasswordHelper = new AssignPasswordHelper(this,
|
assignPasswordHelper = new AssignPasswordHelper(this,
|
||||||
masterPasswordChecked, masterPassword, keyFileChecked, keyFile);
|
masterPasswordChecked, masterPassword, keyFileChecked, keyFile);
|
||||||
|
assignPasswordHelper.setCreateProgressDialog(false);
|
||||||
|
|
||||||
|
// Create the new database
|
||||||
|
CreateDBRunnable createDBTask = new CreateDBRunnable(FileSelectActivity.this,
|
||||||
|
databaseFilename, assignPasswordOnFinish, true);
|
||||||
|
createDBTask.setUpdateProgressTaskStatus(
|
||||||
|
new UpdateProgressTaskStatus(this,
|
||||||
|
ProgressTaskDialogFragment.start(
|
||||||
|
getSupportFragmentManager(),
|
||||||
|
R.string.progress_create)
|
||||||
|
));
|
||||||
|
new Thread(createDBTask).start();
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
String error = "Unable to create database with this password and key file";
|
String error = "Unable to create database with this password and key file";
|
||||||
@@ -546,21 +551,23 @@ public class FileSelectActivity extends StylishActivity implements
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private class AssignPasswordOnFinish extends FileOnFinish {
|
private class AssignPasswordOnFinish extends FileOnFinishRunnable {
|
||||||
|
|
||||||
AssignPasswordOnFinish(FileOnFinish fileOnFinish) {
|
AssignPasswordOnFinish(FileOnFinishRunnable fileOnFinish) {
|
||||||
super(fileOnFinish);
|
super(fileOnFinish);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
if (mSuccess) {
|
if (mSuccess) {
|
||||||
assignPasswordHelper.assignPasswordInDatabase(mOnFinish);
|
// Dont use ProgressTaskDialogFragment.stop(getSupportFragmentManager());
|
||||||
|
// assignPasswordHelper do it
|
||||||
|
runOnUiThread(() -> assignPasswordHelper.assignPasswordInDatabase(mOnFinish));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class LaunchGroupActivity extends FileOnFinish {
|
private class LaunchGroupActivity extends FileOnFinishRunnable {
|
||||||
private Uri mUri;
|
private Uri mUri;
|
||||||
|
|
||||||
LaunchGroupActivity(String filename) {
|
LaunchGroupActivity(String filename) {
|
||||||
|
|||||||
@@ -19,25 +19,30 @@
|
|||||||
*/
|
*/
|
||||||
package com.kunzisoft.keepass.password;
|
package com.kunzisoft.keepass.password;
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
|
import android.support.v7.app.AppCompatActivity;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
import com.kunzisoft.keepass.R;
|
|
||||||
import com.kunzisoft.keepass.app.App;
|
import com.kunzisoft.keepass.app.App;
|
||||||
import com.kunzisoft.keepass.database.edit.FileOnFinish;
|
import com.kunzisoft.keepass.database.action.AssignPasswordInDBRunnable;
|
||||||
import com.kunzisoft.keepass.database.edit.OnFinish;
|
import com.kunzisoft.keepass.database.action.FileOnFinishRunnable;
|
||||||
import com.kunzisoft.keepass.database.edit.SetPassword;
|
import com.kunzisoft.keepass.database.action.OnFinishRunnable;
|
||||||
import com.kunzisoft.keepass.tasks.ProgressTask;
|
import com.kunzisoft.keepass.dialogs.PasswordEncodingDialogHelper;
|
||||||
|
import com.kunzisoft.keepass.tasks.ProgressTaskDialogFragment;
|
||||||
|
import com.kunzisoft.keepass.tasks.SaveDatabaseProgressTaskDialogFragment;
|
||||||
|
import com.kunzisoft.keepass.tasks.UpdateProgressTaskStatus;
|
||||||
|
|
||||||
public class AssignPasswordHelper {
|
public class AssignPasswordHelper {
|
||||||
|
|
||||||
private Context context;
|
private AppCompatActivity context;
|
||||||
|
|
||||||
private String masterPassword = null;
|
private String masterPassword = null;
|
||||||
private Uri keyfile = null;
|
private Uri keyfile = null;
|
||||||
|
|
||||||
public AssignPasswordHelper(Context context,
|
private boolean createProgressDialog;
|
||||||
|
|
||||||
|
public AssignPasswordHelper(AppCompatActivity context,
|
||||||
boolean withMasterPassword,
|
boolean withMasterPassword,
|
||||||
String masterPassword,
|
String masterPassword,
|
||||||
boolean withKeyFile,
|
boolean withKeyFile,
|
||||||
@@ -47,36 +52,66 @@ public class AssignPasswordHelper {
|
|||||||
this.masterPassword = masterPassword;
|
this.masterPassword = masterPassword;
|
||||||
if (withKeyFile)
|
if (withKeyFile)
|
||||||
this.keyfile = keyfile;
|
this.keyfile = keyfile;
|
||||||
|
|
||||||
|
createProgressDialog = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void assignPasswordInDatabase(FileOnFinish fileOnFinish) {
|
public void setCreateProgressDialog(boolean createProgressDialog) {
|
||||||
SetPassword sp = new SetPassword(context, App.getDB(), masterPassword, keyfile, new AfterSave(fileOnFinish, new Handler()));
|
this.createProgressDialog = createProgressDialog;
|
||||||
final ProgressTask pt = new ProgressTask(context, sp, R.string.saving_database);
|
}
|
||||||
boolean valid = sp.validatePassword(context, (dialog, which) -> pt.run());
|
|
||||||
|
|
||||||
if (valid) {
|
public void assignPasswordInDatabase(FileOnFinishRunnable fileOnFinish) {
|
||||||
pt.run();
|
AssignPasswordInDBRunnable assignPasswordInDBRunnable = new AssignPasswordInDBRunnable(
|
||||||
|
context,
|
||||||
|
App.getDB(),
|
||||||
|
masterPassword,
|
||||||
|
keyfile,
|
||||||
|
new AfterSave(fileOnFinish, new Handler())
|
||||||
|
);
|
||||||
|
if (createProgressDialog) {
|
||||||
|
assignPasswordInDBRunnable.setUpdateProgressTaskStatus(
|
||||||
|
new UpdateProgressTaskStatus(context,
|
||||||
|
SaveDatabaseProgressTaskDialogFragment.start(
|
||||||
|
context.getSupportFragmentManager())
|
||||||
|
));
|
||||||
|
}
|
||||||
|
Thread taskThread = new Thread(assignPasswordInDBRunnable);
|
||||||
|
|
||||||
|
// Show the progress dialog now or after dialog confirmation
|
||||||
|
if (App.getDB().getPwDatabase().validatePasswordEncoding(masterPassword)) {
|
||||||
|
taskThread.start();
|
||||||
|
} else {
|
||||||
|
PasswordEncodingDialogHelper dialog = new PasswordEncodingDialogHelper();
|
||||||
|
dialog.show(context, (newDialog, which) -> taskThread.start(), true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class AfterSave extends OnFinish {
|
private class AfterSave extends OnFinishRunnable {
|
||||||
private FileOnFinish mFinish;
|
private FileOnFinishRunnable mFinish;
|
||||||
|
|
||||||
public AfterSave(FileOnFinish finish, Handler handler) {
|
AfterSave(FileOnFinishRunnable finish, Handler handler) {
|
||||||
super(finish, handler);
|
super(finish, handler);
|
||||||
mFinish = finish;
|
mFinish = finish;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
if ( mSuccess ) {
|
|
||||||
if ( mFinish != null ) {
|
|
||||||
mFinish.setFilename(keyfile);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
displayMessage(context);
|
|
||||||
}
|
|
||||||
super.run();
|
super.run();
|
||||||
|
|
||||||
|
context.runOnUiThread(() -> {
|
||||||
|
if ( mSuccess ) {
|
||||||
|
if ( mFinish != null ) {
|
||||||
|
mFinish.setFilename(keyfile);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if ( mMessage != null && mMessage.length() > 0 ) {
|
||||||
|
Toast.makeText(context, mMessage, Toast.LENGTH_LONG).show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// To remove progress task
|
||||||
|
ProgressTaskDialogFragment.stop(context.getSupportFragmentManager());
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -62,8 +62,8 @@ import com.kunzisoft.keepass.compat.BackupManagerCompat;
|
|||||||
import com.kunzisoft.keepass.compat.ClipDataCompat;
|
import com.kunzisoft.keepass.compat.ClipDataCompat;
|
||||||
import com.kunzisoft.keepass.compat.EditorCompat;
|
import com.kunzisoft.keepass.compat.EditorCompat;
|
||||||
import com.kunzisoft.keepass.database.Database;
|
import com.kunzisoft.keepass.database.Database;
|
||||||
import com.kunzisoft.keepass.database.edit.LoadDB;
|
import com.kunzisoft.keepass.database.action.LoadDBRunnable;
|
||||||
import com.kunzisoft.keepass.database.edit.OnFinish;
|
import com.kunzisoft.keepass.database.action.OnFinishRunnable;
|
||||||
import com.kunzisoft.keepass.dialogs.PasswordEncodingDialogHelper;
|
import com.kunzisoft.keepass.dialogs.PasswordEncodingDialogHelper;
|
||||||
import com.kunzisoft.keepass.fileselect.KeyFileHelper;
|
import com.kunzisoft.keepass.fileselect.KeyFileHelper;
|
||||||
import com.kunzisoft.keepass.fingerprint.FingerPrintAnimatedVector;
|
import com.kunzisoft.keepass.fingerprint.FingerPrintAnimatedVector;
|
||||||
@@ -71,7 +71,8 @@ import com.kunzisoft.keepass.fingerprint.FingerPrintDialog;
|
|||||||
import com.kunzisoft.keepass.fingerprint.FingerPrintHelper;
|
import com.kunzisoft.keepass.fingerprint.FingerPrintHelper;
|
||||||
import com.kunzisoft.keepass.settings.PreferencesUtil;
|
import com.kunzisoft.keepass.settings.PreferencesUtil;
|
||||||
import com.kunzisoft.keepass.stylish.StylishActivity;
|
import com.kunzisoft.keepass.stylish.StylishActivity;
|
||||||
import com.kunzisoft.keepass.tasks.ProgressTask;
|
import com.kunzisoft.keepass.tasks.ProgressTaskDialogFragment;
|
||||||
|
import com.kunzisoft.keepass.tasks.UpdateProgressTaskStatus;
|
||||||
import com.kunzisoft.keepass.utils.EmptyUtils;
|
import com.kunzisoft.keepass.utils.EmptyUtils;
|
||||||
import com.kunzisoft.keepass.utils.MenuUtil;
|
import com.kunzisoft.keepass.utils.MenuUtil;
|
||||||
import com.kunzisoft.keepass.utils.UriUtil;
|
import com.kunzisoft.keepass.utils.UriUtil;
|
||||||
@@ -122,6 +123,8 @@ public class PasswordActivity extends StylishActivity
|
|||||||
private CompoundButton checkboxKeyfileView;
|
private CompoundButton checkboxKeyfileView;
|
||||||
private CompoundButton checkboxDefaultDatabaseView;
|
private CompoundButton checkboxDefaultDatabaseView;
|
||||||
|
|
||||||
|
private ProgressTaskDialogFragment loadingDatabaseDialog;
|
||||||
|
|
||||||
private DefaultCheckChange defaultCheckChange;
|
private DefaultCheckChange defaultCheckChange;
|
||||||
private ValidateButtonViewClickListener validateButtonViewClickListener;
|
private ValidateButtonViewClickListener validateButtonViewClickListener;
|
||||||
|
|
||||||
@@ -808,20 +811,86 @@ public class PasswordActivity extends StylishActivity
|
|||||||
loadDatabase(password, keyUri);
|
loadDatabase(password, keyUri);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void loadDatabase(String pass, Uri keyfile) {
|
private void loadDatabase(String password, Uri keyfile) {
|
||||||
// Clear before we load
|
// Clear before we load
|
||||||
Database db = App.getDB();
|
Database database = App.getDB();
|
||||||
db.clear();
|
database.clear();
|
||||||
|
|
||||||
// Clear the shutdown flag
|
// Clear the shutdown flag
|
||||||
App.clearShutdown();
|
App.clearShutdown();
|
||||||
|
|
||||||
|
// Show the progress dialog
|
||||||
Handler handler = new Handler();
|
Handler handler = new Handler();
|
||||||
AfterLoad afterLoad = new AfterLoad(handler, db);
|
AfterLoadingDatabase afterLoad = new AfterLoadingDatabase(handler, database);
|
||||||
|
LoadDBRunnable databaseLoadingTask = new LoadDBRunnable(
|
||||||
|
database,
|
||||||
|
PasswordActivity.this,
|
||||||
|
mDbUri,
|
||||||
|
password,
|
||||||
|
keyfile,
|
||||||
|
afterLoad);
|
||||||
|
databaseLoadingTask.setUpdateProgressTaskStatus(
|
||||||
|
new UpdateProgressTaskStatus(this,
|
||||||
|
handler,
|
||||||
|
ProgressTaskDialogFragment.start(
|
||||||
|
getSupportFragmentManager(),
|
||||||
|
R.string.loading_database)
|
||||||
|
));
|
||||||
|
Thread t = new Thread(databaseLoadingTask);
|
||||||
|
t.start();
|
||||||
|
}
|
||||||
|
|
||||||
LoadDB task = new LoadDB(db, PasswordActivity.this, mDbUri, pass, keyfile, afterLoad);
|
/**
|
||||||
ProgressTask pt = new ProgressTask(PasswordActivity.this, task, R.string.loading_database);
|
* Called after verify and try to opening the database
|
||||||
pt.run();
|
*/
|
||||||
|
private final class AfterLoadingDatabase extends OnFinishRunnable {
|
||||||
|
|
||||||
|
protected Database db;
|
||||||
|
|
||||||
|
AfterLoadingDatabase(
|
||||||
|
Handler handler,
|
||||||
|
Database db) {
|
||||||
|
super(handler);
|
||||||
|
|
||||||
|
this.db = db;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
runOnUiThread(() -> {
|
||||||
|
// Recheck fingerprint if error
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||||
|
// Stay with the same mode
|
||||||
|
reInitWithFingerprintMode();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (db.isPasswordEncodingError()) {
|
||||||
|
PasswordEncodingDialogHelper dialog = new PasswordEncodingDialogHelper();
|
||||||
|
dialog.show(PasswordActivity.this, (dialog1, which) -> launchGroupActivity());
|
||||||
|
} else if (mSuccess) {
|
||||||
|
launchGroupActivity();
|
||||||
|
} else {
|
||||||
|
if ( mMessage != null && mMessage.length() > 0 ) {
|
||||||
|
Toast.makeText(PasswordActivity.this, mMessage, Toast.LENGTH_LONG).show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// To remove progress task
|
||||||
|
ProgressTaskDialogFragment.stop(getSupportFragmentManager());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void launchGroupActivity() {
|
||||||
|
AssistStructure assistStructure = null;
|
||||||
|
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
|
||||||
|
assistStructure = autofillHelper.getAssistStructure();
|
||||||
|
if (assistStructure != null) {
|
||||||
|
GroupActivity.launch(PasswordActivity.this, assistStructure);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (assistStructure == null) {
|
||||||
|
GroupActivity.launch(PasswordActivity.this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -863,54 +932,6 @@ public class PasswordActivity extends StylishActivity
|
|||||||
PasswordActivityPermissionsDispatcher.onRequestPermissionsResult(this, requestCode, grantResults);
|
PasswordActivityPermissionsDispatcher.onRequestPermissionsResult(this, requestCode, grantResults);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Called after verify and try to opening the database
|
|
||||||
*/
|
|
||||||
private final class AfterLoad extends OnFinish {
|
|
||||||
|
|
||||||
protected Database db;
|
|
||||||
|
|
||||||
AfterLoad(
|
|
||||||
Handler handler,
|
|
||||||
Database db) {
|
|
||||||
super(handler);
|
|
||||||
|
|
||||||
this.db = db;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
|
|
||||||
// Recheck fingerprint if error
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
|
||||||
// Stay with the same mode
|
|
||||||
reInitWithFingerprintMode();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (db.isPasswordEncodingError()) {
|
|
||||||
PasswordEncodingDialogHelper dialog = new PasswordEncodingDialogHelper();
|
|
||||||
dialog.show(PasswordActivity.this, (dialog1, which) -> launchGroupActivity());
|
|
||||||
} else if (mSuccess) {
|
|
||||||
launchGroupActivity();
|
|
||||||
} else {
|
|
||||||
displayMessage(PasswordActivity.this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void launchGroupActivity() {
|
|
||||||
AssistStructure assistStructure = null;
|
|
||||||
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
|
|
||||||
assistStructure = autofillHelper.getAssistStructure();
|
|
||||||
if (assistStructure != null) {
|
|
||||||
GroupActivity.launch(PasswordActivity.this, assistStructure);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (assistStructure == null) {
|
|
||||||
GroupActivity.launch(PasswordActivity.this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class UriIntentInitTask extends AsyncTask<Intent, Void, Integer> {
|
private static class UriIntentInitTask extends AsyncTask<Intent, Void, Integer> {
|
||||||
|
|
||||||
static final String KEY_FILENAME = "fileName";
|
static final String KEY_FILENAME = "fileName";
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
package com.kunzisoft.keepass.settings.preferenceDialogFragment;
|
package com.kunzisoft.keepass.settings.preferenceDialogFragment;
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
|
import android.support.v7.app.AppCompatActivity;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
|
||||||
import com.kunzisoft.keepass.database.edit.OnFinish;
|
import com.kunzisoft.keepass.database.action.OnFinishRunnable;
|
||||||
|
import com.kunzisoft.keepass.tasks.SaveDatabaseProgressTaskDialogFragment;
|
||||||
|
|
||||||
public class DatabaseDescriptionPreferenceDialogFragmentCompat extends DatabaseSavePreferenceDialogFragmentCompat {
|
public class DatabaseDescriptionPreferenceDialogFragmentCompat extends DatabaseSavePreferenceDialogFragmentCompat {
|
||||||
|
|
||||||
@@ -37,22 +38,22 @@ public class DatabaseDescriptionPreferenceDialogFragmentCompat extends DatabaseS
|
|||||||
database.assignDescription(dbDescription);
|
database.assignDescription(dbDescription);
|
||||||
|
|
||||||
Handler handler = new Handler();
|
Handler handler = new Handler();
|
||||||
setAfterSaveDatabase(new AfterDescriptionSave(getContext(), handler, dbDescription, oldDescription));
|
setAfterSaveDatabase(new AfterDescriptionSave((AppCompatActivity) getActivity(), handler, dbDescription, oldDescription));
|
||||||
}
|
}
|
||||||
|
|
||||||
super.onDialogClosed(positiveResult);
|
super.onDialogClosed(positiveResult);
|
||||||
}
|
}
|
||||||
|
|
||||||
private class AfterDescriptionSave extends OnFinish {
|
private class AfterDescriptionSave extends OnFinishRunnable {
|
||||||
|
|
||||||
|
private AppCompatActivity mActivity;
|
||||||
private String mNewDescription;
|
private String mNewDescription;
|
||||||
private String mOldDescription;
|
private String mOldDescription;
|
||||||
private Context mCtx;
|
|
||||||
|
|
||||||
AfterDescriptionSave(Context ctx, Handler handler, String newDescription, String oldDescription) {
|
AfterDescriptionSave(AppCompatActivity ctx, Handler handler, String newDescription, String oldDescription) {
|
||||||
super(handler);
|
super(handler);
|
||||||
|
|
||||||
mCtx = ctx;
|
mActivity = ctx;
|
||||||
mNewDescription = newDescription;
|
mNewDescription = newDescription;
|
||||||
mOldDescription = oldDescription;
|
mOldDescription = oldDescription;
|
||||||
}
|
}
|
||||||
@@ -62,12 +63,18 @@ public class DatabaseDescriptionPreferenceDialogFragmentCompat extends DatabaseS
|
|||||||
String descriptionToShow = mNewDescription;
|
String descriptionToShow = mNewDescription;
|
||||||
|
|
||||||
if (!mSuccess) {
|
if (!mSuccess) {
|
||||||
displayMessage(mCtx);
|
displayMessage(mActivity);
|
||||||
database.assignDescription(mOldDescription);
|
database.assignDescription(mOldDescription);
|
||||||
database.assignDescription(mOldDescription);
|
database.assignDescription(mOldDescription);
|
||||||
}
|
}
|
||||||
|
|
||||||
getPreference().setSummary(descriptionToShow);
|
if (mActivity != null) {
|
||||||
|
mActivity.runOnUiThread(() -> {
|
||||||
|
getPreference().setSummary(descriptionToShow);
|
||||||
|
SaveDatabaseProgressTaskDialogFragment.stop(
|
||||||
|
mActivity.getSupportFragmentManager());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
super.run();
|
super.run();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
package com.kunzisoft.keepass.settings.preferenceDialogFragment;
|
package com.kunzisoft.keepass.settings.preferenceDialogFragment;
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
|
import android.support.v7.app.AppCompatActivity;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
|
||||||
import com.kunzisoft.keepass.database.edit.OnFinish;
|
import com.kunzisoft.keepass.database.action.OnFinishRunnable;
|
||||||
|
import com.kunzisoft.keepass.tasks.SaveDatabaseProgressTaskDialogFragment;
|
||||||
|
|
||||||
public class DatabaseNamePreferenceDialogFragmentCompat extends DatabaseSavePreferenceDialogFragmentCompat {
|
public class DatabaseNamePreferenceDialogFragmentCompat extends DatabaseSavePreferenceDialogFragmentCompat {
|
||||||
|
|
||||||
@@ -37,22 +38,22 @@ public class DatabaseNamePreferenceDialogFragmentCompat extends DatabaseSavePref
|
|||||||
database.assignName(dbName);
|
database.assignName(dbName);
|
||||||
|
|
||||||
Handler handler = new Handler();
|
Handler handler = new Handler();
|
||||||
setAfterSaveDatabase(new AfterNameSave(getContext(), handler, dbName, oldName));
|
setAfterSaveDatabase(new AfterNameSave((AppCompatActivity) getActivity(), handler, dbName, oldName));
|
||||||
}
|
}
|
||||||
|
|
||||||
super.onDialogClosed(positiveResult);
|
super.onDialogClosed(positiveResult);
|
||||||
}
|
}
|
||||||
|
|
||||||
private class AfterNameSave extends OnFinish {
|
private class AfterNameSave extends OnFinishRunnable {
|
||||||
|
|
||||||
private String mNewName;
|
private String mNewName;
|
||||||
private String mOldName;
|
private String mOldName;
|
||||||
private Context mCtx;
|
private AppCompatActivity mActivity;
|
||||||
|
|
||||||
AfterNameSave(Context ctx, Handler handler, String newName, String oldName) {
|
AfterNameSave(AppCompatActivity ctx, Handler handler, String newName, String oldName) {
|
||||||
super(handler);
|
super(handler);
|
||||||
|
|
||||||
mCtx = ctx;
|
mActivity = ctx;
|
||||||
mNewName = newName;
|
mNewName = newName;
|
||||||
mOldName = oldName;
|
mOldName = oldName;
|
||||||
}
|
}
|
||||||
@@ -62,11 +63,18 @@ public class DatabaseNamePreferenceDialogFragmentCompat extends DatabaseSavePref
|
|||||||
String nameToShow = mNewName;
|
String nameToShow = mNewName;
|
||||||
|
|
||||||
if (!mSuccess) {
|
if (!mSuccess) {
|
||||||
displayMessage(mCtx);
|
displayMessage(mActivity);
|
||||||
database.assignName(mOldName);
|
database.assignName(mOldName);
|
||||||
}
|
}
|
||||||
|
|
||||||
getPreference().setSummary(nameToShow);
|
|
||||||
|
if (mActivity != null) {
|
||||||
|
mActivity.runOnUiThread(() -> {
|
||||||
|
getPreference().setSummary(nameToShow);
|
||||||
|
SaveDatabaseProgressTaskDialogFragment.stop(
|
||||||
|
mActivity.getSupportFragmentManager());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
super.run();
|
super.run();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,18 +2,18 @@ package com.kunzisoft.keepass.settings.preferenceDialogFragment;
|
|||||||
|
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
|
||||||
import com.kunzisoft.keepass.R;
|
|
||||||
import com.kunzisoft.keepass.app.App;
|
import com.kunzisoft.keepass.app.App;
|
||||||
import com.kunzisoft.keepass.database.Database;
|
import com.kunzisoft.keepass.database.Database;
|
||||||
import com.kunzisoft.keepass.database.edit.OnFinish;
|
import com.kunzisoft.keepass.database.action.OnFinishRunnable;
|
||||||
import com.kunzisoft.keepass.database.edit.SaveDB;
|
import com.kunzisoft.keepass.database.action.SaveDBRunnable;
|
||||||
import com.kunzisoft.keepass.tasks.ProgressTask;
|
import com.kunzisoft.keepass.tasks.SaveDatabaseProgressTaskDialogFragment;
|
||||||
|
import com.kunzisoft.keepass.tasks.UpdateProgressTaskStatus;
|
||||||
|
|
||||||
public abstract class DatabaseSavePreferenceDialogFragmentCompat extends InputPreferenceDialogFragmentCompat {
|
public abstract class DatabaseSavePreferenceDialogFragmentCompat extends InputPreferenceDialogFragmentCompat {
|
||||||
|
|
||||||
protected Database database;
|
protected Database database;
|
||||||
|
|
||||||
private OnFinish afterSaveDatabase;
|
private OnFinishRunnable afterSaveDatabase;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onBindDialogView(View view) {
|
protected void onBindDialogView(View view) {
|
||||||
@@ -25,17 +25,21 @@ public abstract class DatabaseSavePreferenceDialogFragmentCompat extends InputP
|
|||||||
@Override
|
@Override
|
||||||
public void onDialogClosed(boolean positiveResult) {
|
public void onDialogClosed(boolean positiveResult) {
|
||||||
if ( positiveResult ) {
|
if ( positiveResult ) {
|
||||||
assert getContext() != null;
|
assert getActivity() != null;
|
||||||
|
|
||||||
if (database != null && afterSaveDatabase != null) {
|
if (database != null && afterSaveDatabase != null) {
|
||||||
SaveDB save = new SaveDB(getContext(), database, afterSaveDatabase);
|
SaveDBRunnable saveDBRunnable = new SaveDBRunnable(getContext(), database, afterSaveDatabase);
|
||||||
ProgressTask pt = new ProgressTask(getContext(), save, R.string.saving_database);
|
saveDBRunnable.setUpdateProgressTaskStatus(
|
||||||
pt.run();
|
new UpdateProgressTaskStatus(getContext(),
|
||||||
|
SaveDatabaseProgressTaskDialogFragment.start(
|
||||||
|
getActivity().getSupportFragmentManager())
|
||||||
|
));
|
||||||
|
new Thread(saveDBRunnable).start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setAfterSaveDatabase(OnFinish afterSaveDatabase) {
|
public void setAfterSaveDatabase(OnFinishRunnable afterSaveDatabase) {
|
||||||
this.afterSaveDatabase = afterSaveDatabase;
|
this.afterSaveDatabase = afterSaveDatabase;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,14 +19,15 @@
|
|||||||
*/
|
*/
|
||||||
package com.kunzisoft.keepass.settings.preferenceDialogFragment;
|
package com.kunzisoft.keepass.settings.preferenceDialogFragment;
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
|
import android.support.v7.app.AppCompatActivity;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import com.kunzisoft.keepass.R;
|
import com.kunzisoft.keepass.R;
|
||||||
import com.kunzisoft.keepass.database.edit.OnFinish;
|
import com.kunzisoft.keepass.database.action.OnFinishRunnable;
|
||||||
|
import com.kunzisoft.keepass.tasks.SaveDatabaseProgressTaskDialogFragment;
|
||||||
|
|
||||||
public class RoundsPreferenceDialogFragmentCompat extends DatabaseSavePreferenceDialogFragmentCompat {
|
public class RoundsPreferenceDialogFragmentCompat extends DatabaseSavePreferenceDialogFragmentCompat {
|
||||||
|
|
||||||
@@ -76,22 +77,22 @@ public class RoundsPreferenceDialogFragmentCompat extends DatabaseSavePreference
|
|||||||
}
|
}
|
||||||
|
|
||||||
Handler handler = new Handler();
|
Handler handler = new Handler();
|
||||||
setAfterSaveDatabase(new AfterRoundSave(getContext(), handler, rounds, oldRounds));
|
setAfterSaveDatabase(new AfterRoundSave((AppCompatActivity) getActivity(), handler, rounds, oldRounds));
|
||||||
}
|
}
|
||||||
|
|
||||||
super.onDialogClosed(positiveResult);
|
super.onDialogClosed(positiveResult);
|
||||||
}
|
}
|
||||||
|
|
||||||
private class AfterRoundSave extends OnFinish {
|
private class AfterRoundSave extends OnFinishRunnable {
|
||||||
|
|
||||||
private long mNewRounds;
|
private long mNewRounds;
|
||||||
private long mOldRounds;
|
private long mOldRounds;
|
||||||
private Context mCtx;
|
private AppCompatActivity mActivity;
|
||||||
|
|
||||||
AfterRoundSave(Context ctx, Handler handler, long newRounds, long oldRounds) {
|
AfterRoundSave(AppCompatActivity ctx, Handler handler, long newRounds, long oldRounds) {
|
||||||
super(handler);
|
super(handler);
|
||||||
|
|
||||||
mCtx = ctx;
|
mActivity = ctx;
|
||||||
mNewRounds = newRounds;
|
mNewRounds = newRounds;
|
||||||
mOldRounds = oldRounds;
|
mOldRounds = oldRounds;
|
||||||
}
|
}
|
||||||
@@ -101,11 +102,17 @@ public class RoundsPreferenceDialogFragmentCompat extends DatabaseSavePreference
|
|||||||
long roundsToShow = mNewRounds;
|
long roundsToShow = mNewRounds;
|
||||||
|
|
||||||
if (!mSuccess) {
|
if (!mSuccess) {
|
||||||
displayMessage(mCtx);
|
displayMessage(mActivity);
|
||||||
database.setNumberKeyEncryptionRounds(mOldRounds);
|
database.setNumberKeyEncryptionRounds(mOldRounds);
|
||||||
}
|
}
|
||||||
|
|
||||||
getPreference().setSummary(String.valueOf(roundsToShow));
|
if (mActivity != null) {
|
||||||
|
mActivity.runOnUiThread(() -> {
|
||||||
|
getPreference().setSummary(String.valueOf(roundsToShow));
|
||||||
|
SaveDatabaseProgressTaskDialogFragment.stop(
|
||||||
|
mActivity.getSupportFragmentManager());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
super.run();
|
super.run();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,92 +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 3 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.kunzisoft.keepass.tasks;
|
|
||||||
|
|
||||||
import android.app.ProgressDialog;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.os.Handler;
|
|
||||||
|
|
||||||
import com.kunzisoft.keepass.R;
|
|
||||||
import com.kunzisoft.keepass.database.edit.OnFinish;
|
|
||||||
import com.kunzisoft.keepass.database.edit.RunnableOnFinish;
|
|
||||||
|
|
||||||
/** Designed to Pop up a progress dialog, run a thread in the background,
|
|
||||||
* run cleanup in the current thread, close the dialog. Without blocking
|
|
||||||
* the current thread.
|
|
||||||
*
|
|
||||||
* @author bpellin
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class ProgressTask implements Runnable {
|
|
||||||
private Context mCtx;
|
|
||||||
private Handler mHandler;
|
|
||||||
private RunnableOnFinish mTask;
|
|
||||||
private ProgressDialog mPd;
|
|
||||||
|
|
||||||
public ProgressTask(Context ctx, RunnableOnFinish task, int messageId) {
|
|
||||||
mCtx = ctx;
|
|
||||||
mTask = task;
|
|
||||||
mHandler = new Handler();
|
|
||||||
|
|
||||||
// Show process dialog
|
|
||||||
mPd = new ProgressDialog(mCtx);
|
|
||||||
mPd.setCanceledOnTouchOutside(false);
|
|
||||||
mPd.setTitle(ctx.getText(R.string.progress_title));
|
|
||||||
mPd.setMessage(ctx.getText(messageId));
|
|
||||||
|
|
||||||
// Set code to run when this is finished
|
|
||||||
mTask.setStatus(new UpdateStatus(ctx, mHandler, mPd));
|
|
||||||
mTask.mFinish = new AfterTask(task.mFinish, mHandler);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public void run() {
|
|
||||||
// Show process dialog
|
|
||||||
mPd.show();
|
|
||||||
|
|
||||||
// Start Thread to Run task
|
|
||||||
Thread t = new Thread(mTask);
|
|
||||||
t.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
private class AfterTask extends OnFinish {
|
|
||||||
|
|
||||||
public AfterTask(OnFinish finish, Handler handler) {
|
|
||||||
super(finish, handler);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
super.run();
|
|
||||||
// Remove the progress dialog
|
|
||||||
mHandler.post(new CloseProcessDialog());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private class CloseProcessDialog implements Runnable {
|
|
||||||
public void run() {
|
|
||||||
if (mPd != null && mPd.isShowing()) {
|
|
||||||
mPd.dismiss();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,144 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018 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 3 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.kunzisoft.keepass.tasks;
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint;
|
||||||
|
import android.app.Dialog;
|
||||||
|
import android.content.DialogInterface;
|
||||||
|
import android.content.pm.ActivityInfo;
|
||||||
|
import android.content.res.Configuration;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.support.annotation.NonNull;
|
||||||
|
import android.support.annotation.StringRes;
|
||||||
|
import android.support.v4.app.DialogFragment;
|
||||||
|
import android.support.v4.app.Fragment;
|
||||||
|
import android.support.v4.app.FragmentManager;
|
||||||
|
import android.support.v7.app.AlertDialog;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.ProgressBar;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import com.kunzisoft.keepass.R;
|
||||||
|
|
||||||
|
public class ProgressTaskDialogFragment extends DialogFragment implements ProgressTaskUpdater{
|
||||||
|
|
||||||
|
public static final String PROGRESS_TASK_DIALOG_TAG = "progressDialogFragment";
|
||||||
|
|
||||||
|
private static final int UNDEFINED = -1;
|
||||||
|
|
||||||
|
private @StringRes int title = UNDEFINED;
|
||||||
|
private @StringRes int message = UNDEFINED;
|
||||||
|
|
||||||
|
private TextView titleView;
|
||||||
|
private TextView messageView;
|
||||||
|
private ProgressBar progressView;
|
||||||
|
|
||||||
|
public static ProgressTaskDialogFragment start(FragmentManager fragmentManager, @StringRes int titleId) {
|
||||||
|
// Create an instance of the dialog fragment and show it
|
||||||
|
ProgressTaskDialogFragment dialog = new ProgressTaskDialogFragment();
|
||||||
|
dialog.updateTitle(titleId);
|
||||||
|
dialog.show(fragmentManager, PROGRESS_TASK_DIALOG_TAG);
|
||||||
|
return dialog;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||||
|
assert getActivity() != null;
|
||||||
|
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
|
||||||
|
// Get the layout inflater
|
||||||
|
LayoutInflater inflater = getActivity().getLayoutInflater();
|
||||||
|
|
||||||
|
// Inflate and set the layout for the dialog
|
||||||
|
// Pass null as the parent view because its going in the dialog layout
|
||||||
|
@SuppressLint("InflateParams")
|
||||||
|
View root = inflater.inflate(R.layout.progress_dialog, null);
|
||||||
|
builder.setView(root);
|
||||||
|
|
||||||
|
titleView = root.findViewById(R.id.progress_dialog_title);
|
||||||
|
messageView = root.findViewById(R.id.progress_dialog_message);
|
||||||
|
progressView = root.findViewById(R.id.progress_dialog_bar);
|
||||||
|
|
||||||
|
updateTitle(title);
|
||||||
|
updateMessage(message);
|
||||||
|
|
||||||
|
setCancelable(false);
|
||||||
|
lockScreenOrientation();
|
||||||
|
|
||||||
|
return builder.create();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDismiss(DialogInterface dialog) {
|
||||||
|
super.onDismiss(dialog);
|
||||||
|
unlockScreenOrientation();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void stop(FragmentManager fragmentManager) {
|
||||||
|
Fragment fragmentTask = fragmentManager.findFragmentByTag(PROGRESS_TASK_DIALOG_TAG);
|
||||||
|
if (fragmentTask != null) {
|
||||||
|
ProgressTaskDialogFragment loadingDatabaseDialog = (ProgressTaskDialogFragment) fragmentTask;
|
||||||
|
loadingDatabaseDialog.dismissAllowingStateLoss();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void lockScreenOrientation() {
|
||||||
|
if (getActivity() != null) {
|
||||||
|
int currentOrientation = getResources().getConfiguration().orientation;
|
||||||
|
if (currentOrientation == Configuration.ORIENTATION_PORTRAIT) {
|
||||||
|
getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
|
||||||
|
} else {
|
||||||
|
getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void unlockScreenOrientation() {
|
||||||
|
if (getActivity() != null)
|
||||||
|
getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTitle(@StringRes int titleId) {
|
||||||
|
this.title = titleId;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateView(TextView textView, @StringRes int resId) {
|
||||||
|
if (textView != null) {
|
||||||
|
if (resId == UNDEFINED) {
|
||||||
|
textView.setVisibility(View.GONE);
|
||||||
|
} else {
|
||||||
|
textView.setText(resId);
|
||||||
|
textView.setVisibility(View.VISIBLE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateTitle(int resId) {
|
||||||
|
this.title = resId;
|
||||||
|
updateView(titleView, title);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateMessage(int resId) {
|
||||||
|
this.message = resId;
|
||||||
|
updateView(messageView, message);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018 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 3 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.kunzisoft.keepass.tasks;
|
||||||
|
|
||||||
|
public interface ProgressTaskUpdater {
|
||||||
|
void updateMessage(int resId);
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package com.kunzisoft.keepass.tasks;
|
||||||
|
|
||||||
|
import android.support.v4.app.FragmentManager;
|
||||||
|
|
||||||
|
import com.kunzisoft.keepass.R;
|
||||||
|
|
||||||
|
public class SaveDatabaseProgressTaskDialogFragment extends ProgressTaskDialogFragment {
|
||||||
|
|
||||||
|
public static SaveDatabaseProgressTaskDialogFragment start(FragmentManager fragmentManager) {
|
||||||
|
// Create an instance of the dialog fragment and show it
|
||||||
|
SaveDatabaseProgressTaskDialogFragment dialog = new SaveDatabaseProgressTaskDialogFragment();
|
||||||
|
dialog.updateTitle(R.string.saving_database);
|
||||||
|
dialog.show(fragmentManager, PROGRESS_TASK_DIALOG_TAG);
|
||||||
|
return dialog;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -19,27 +19,27 @@
|
|||||||
*/
|
*/
|
||||||
package com.kunzisoft.keepass.tasks;
|
package com.kunzisoft.keepass.tasks;
|
||||||
|
|
||||||
import android.app.ProgressDialog;
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
|
|
||||||
public class UpdateStatus {
|
public class UpdateProgressTaskStatus implements ProgressTaskUpdater {
|
||||||
private ProgressDialog mPD;
|
private Context mContext;
|
||||||
private Context mCtx;
|
private ProgressTaskUpdater mProgressTaskUpdater;
|
||||||
private Handler mHandler;
|
private Handler mHandler;
|
||||||
|
|
||||||
public UpdateStatus() {
|
public UpdateProgressTaskStatus(Context context, ProgressTaskUpdater progressTaskUpdater) {
|
||||||
|
this(context, new Handler(), progressTaskUpdater);
|
||||||
}
|
}
|
||||||
|
|
||||||
public UpdateStatus(Context ctx, Handler handler, ProgressDialog pd) {
|
public UpdateProgressTaskStatus(Context context, Handler handler, ProgressTaskUpdater progressTaskUpdater) {
|
||||||
mCtx = ctx;
|
this.mContext = context;
|
||||||
mPD = pd;
|
this.mProgressTaskUpdater = progressTaskUpdater;
|
||||||
mHandler = handler;
|
this.mHandler = handler;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void updateMessage(int resId) {
|
public void updateMessage(int resId) {
|
||||||
if ( mCtx != null && mPD != null && mHandler != null ) {
|
if ( mContext != null && mProgressTaskUpdater != null && mHandler != null ) {
|
||||||
mHandler.post(new UpdateMessage(resId));
|
mHandler.post(new UpdateMessage(resId));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -47,13 +47,12 @@ public class UpdateStatus {
|
|||||||
private class UpdateMessage implements Runnable {
|
private class UpdateMessage implements Runnable {
|
||||||
private int mResId;
|
private int mResId;
|
||||||
|
|
||||||
public UpdateMessage(int resId) {
|
UpdateMessage(int resId) {
|
||||||
mResId = resId;
|
mResId = resId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void run() {
|
public void run() {
|
||||||
mPD.setMessage(mCtx.getString(mResId));
|
mProgressTaskUpdater.updateMessage(mResId);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -190,6 +190,17 @@
|
|||||||
|
|
||||||
</android.support.design.widget.CoordinatorLayout>
|
</android.support.design.widget.CoordinatorLayout>
|
||||||
|
|
||||||
|
<ProgressBar
|
||||||
|
android:id="@+id/progress_dialog_bar"
|
||||||
|
style="?android:attr/progressBarStyleHorizontal"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:indeterminate="true"
|
||||||
|
android:max="100"
|
||||||
|
android:backgroundTint="@color/white"
|
||||||
|
android:visibility="gone"
|
||||||
|
android:layout_above="@+id/pass_ok"/>
|
||||||
|
|
||||||
<android.support.v7.widget.AppCompatButton
|
<android.support.v7.widget.AppCompatButton
|
||||||
android:id="@+id/pass_ok"
|
android:id="@+id/pass_ok"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
|
|||||||
38
app/src/main/res/layout/progress_dialog.xml
Normal file
38
app/src/main/res/layout/progress_dialog.xml
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:orientation="vertical" android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/progress_dialog_title"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="20dp"
|
||||||
|
android:layout_marginLeft="20dp"
|
||||||
|
android:layout_marginRight="20dp"
|
||||||
|
android:layout_marginStart="20dp"
|
||||||
|
android:layout_marginEnd="20dp"
|
||||||
|
style="@style/KeepassDXStyle.TextAppearance.Title"
|
||||||
|
android:textColor="?android:attr/textColor"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/progress_dialog_message"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="20dp"
|
||||||
|
android:layout_marginLeft="20dp"
|
||||||
|
android:layout_marginRight="20dp"
|
||||||
|
android:layout_marginStart="20dp"
|
||||||
|
android:layout_marginEnd="20dp"
|
||||||
|
style="@style/KeepassDXStyle.TextAppearance.SmallTitle"/>
|
||||||
|
|
||||||
|
<ProgressBar
|
||||||
|
android:id="@+id/progress_dialog_bar"
|
||||||
|
style="?android:attr/progressBarStyleHorizontal"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="12dp"
|
||||||
|
android:indeterminate="true"
|
||||||
|
android:max="100"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
4
fastlane/metadata/android/en-US/changelogs/10.txt
Normal file
4
fastlane/metadata/android/en-US/changelogs/10.txt
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
* Upgrade translations
|
||||||
|
* Fix classic dark theme
|
||||||
|
* Add Material Icon Pack to the Free version
|
||||||
|
* Fix bugs
|
||||||
4
fastlane/metadata/android/fr-FR/changelogs/10.txt
Normal file
4
fastlane/metadata/android/fr-FR/changelogs/10.txt
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
* Mise à jour des traductions
|
||||||
|
* Correction du thème sombre classic
|
||||||
|
* Ajout du Pack d'Icones Material à la version gratuite
|
||||||
|
* Corrections de bugs
|
||||||
Reference in New Issue
Block a user