bug fixes and improvements after adding multi-database support
This commit is contained in:
@@ -88,7 +88,8 @@ namespace keepass2android
|
||||
EventHandler<DialogClickEventArgs> yesHandler,
|
||||
EventHandler<DialogClickEventArgs> noHandler,
|
||||
EventHandler<DialogClickEventArgs> cancelHandler,
|
||||
Context ctx);
|
||||
Context ctx,
|
||||
string messageSuffix = "");
|
||||
|
||||
/// <summary>
|
||||
/// Asks the user the question "messageKey" with the options Yes/No/Cancel, but the yes/no strings can be selected freely, calls the handler corresponding to the answer.
|
||||
@@ -98,7 +99,8 @@ namespace keepass2android
|
||||
EventHandler<DialogClickEventArgs> yesHandler,
|
||||
EventHandler<DialogClickEventArgs> noHandler,
|
||||
EventHandler<DialogClickEventArgs> cancelHandler,
|
||||
Context ctx);
|
||||
Context ctx,
|
||||
string messageSuffix = "");
|
||||
|
||||
/// <summary>
|
||||
/// Returns a Handler object which can run tasks on the UI thread
|
||||
@@ -127,6 +129,5 @@ namespace keepass2android
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
}
|
@@ -211,6 +211,8 @@ namespace keepass2android
|
||||
}
|
||||
Entries [e.Uuid] = e;
|
||||
}
|
||||
|
||||
Groups[currentGroup.Uuid] = currentGroup;
|
||||
foreach (PwGroup g in childGroups)
|
||||
{
|
||||
if (checkForDuplicateUuids)
|
||||
@@ -222,7 +224,6 @@ namespace keepass2android
|
||||
}
|
||||
* */
|
||||
}
|
||||
Groups[g.Uuid] = g;
|
||||
PopulateGlobals(g);
|
||||
}
|
||||
}
|
||||
@@ -231,7 +232,13 @@ namespace keepass2android
|
||||
PopulateGlobals(currentGroup, _app.CheckForDuplicateUuids);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void UpdateGlobals()
|
||||
{
|
||||
Entries.Clear();
|
||||
Groups.Clear();
|
||||
PopulateGlobals(Root);
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
|
@@ -88,8 +88,10 @@ namespace keepass2android
|
||||
save.SetStatusLogger(StatusLogger);
|
||||
_onFinishToRun = null;
|
||||
save.Run();
|
||||
|
||||
|
||||
|
||||
db.UpdateGlobals();
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -21,6 +21,7 @@ namespace keepass2android
|
||||
//determine once. The property is queried for each delete operation, but might return false
|
||||
//after one entry/group is deleted (and thus in recycle bin and thus can't be recycled anymore)
|
||||
_canRecycle = DetermineCanRecycle();
|
||||
ShowDatabaseIocInStatus = true;
|
||||
}
|
||||
|
||||
private bool DetermineCanRecycle()
|
||||
|
@@ -121,25 +121,27 @@ namespace keepass2android
|
||||
|
||||
public void Start()
|
||||
{
|
||||
if (CanRecycle)
|
||||
string messageSuffix = ShowDatabaseIocInStatus ? "(" + App.GetFileStorage(Db.Ioc).GetDisplayName(Db.Ioc) + ")" : "";
|
||||
|
||||
if (CanRecycle)
|
||||
{
|
||||
App.AskYesNoCancel(UiStringKey.AskDeletePermanently_title,
|
||||
QuestionRecycleResourceId,
|
||||
(dlgSender, dlgEvt) =>
|
||||
{
|
||||
DeletePermanently = true;
|
||||
ProgressTask pt = new ProgressTask(App, Ctx, this);
|
||||
pt.Run();
|
||||
DeletePermanently = true;
|
||||
ProgressTask pt = new ProgressTask(App, Ctx, this);
|
||||
pt.Run();
|
||||
|
||||
},
|
||||
(dlgSender, dlgEvt) =>
|
||||
{
|
||||
DeletePermanently = false;
|
||||
ProgressTask pt = new ProgressTask(App, Ctx, this);
|
||||
pt.Run();
|
||||
DeletePermanently = false;
|
||||
ProgressTask pt = new ProgressTask(App, Ctx, this);
|
||||
pt.Run();
|
||||
},
|
||||
(dlgSender, dlgEvt) => { },
|
||||
Ctx);
|
||||
Ctx, messageSuffix);
|
||||
|
||||
|
||||
|
||||
@@ -150,12 +152,12 @@ namespace keepass2android
|
||||
QuestionNoRecycleResourceId,
|
||||
(dlgSender, dlgEvt) =>
|
||||
{
|
||||
ProgressTask pt = new ProgressTask(App, Ctx, this);
|
||||
pt.Run();
|
||||
ProgressTask pt = new ProgressTask(App, Ctx, this);
|
||||
pt.Run();
|
||||
},
|
||||
null,
|
||||
(dlgSender, dlgEvt) => { },
|
||||
Ctx);
|
||||
Ctx, messageSuffix);
|
||||
|
||||
|
||||
}
|
||||
@@ -234,13 +236,21 @@ namespace keepass2android
|
||||
|
||||
// Commit database
|
||||
SaveDb save = new SaveDb(Ctx, App, Db, OnFinishToRun, false);
|
||||
save.SetStatusLogger(StatusLogger);
|
||||
save.ShowDatabaseIocInStatus = ShowDatabaseIocInStatus;
|
||||
|
||||
save.SetStatusLogger(StatusLogger);
|
||||
save.Run();
|
||||
|
||||
|
||||
}
|
||||
|
||||
protected abstract void PerformDelete(List<PwGroup> touchedGroups, List<PwGroup> permanentlyDeletedGroups);
|
||||
public bool ShowDatabaseIocInStatus
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
protected abstract void PerformDelete(List<PwGroup> touchedGroups, List<PwGroup> permanentlyDeletedGroups);
|
||||
|
||||
public abstract UiStringKey StatusMessage { get; }
|
||||
|
||||
|
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using Android.App;
|
||||
@@ -50,11 +51,20 @@ namespace keepass2android.database.edit
|
||||
|
||||
}
|
||||
|
||||
HashSet<Database> removeDatabases = new HashSet<Database>();
|
||||
Database addDatabase = _app.FindDatabaseForGroupId(_targetGroup.Uuid);
|
||||
if (addDatabase == null)
|
||||
{
|
||||
Finish(false, "Did not find target database. Did you lock it?");
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var elementToMove in _elementsToMove)
|
||||
{
|
||||
|
||||
_app.DirtyGroups.Add(elementToMove.ParentGroup);
|
||||
//TODO is this safe when transferring between databases?
|
||||
|
||||
|
||||
PwGroup pgParent = elementToMove.ParentGroup;
|
||||
if (pgParent != _targetGroup)
|
||||
{
|
||||
@@ -63,8 +73,12 @@ namespace keepass2android.database.edit
|
||||
PwEntry entry = elementToMove as PwEntry;
|
||||
if (entry != null)
|
||||
{
|
||||
var dbRem = _app.FindDatabaseForEntryId(entry.Uuid);
|
||||
removeDatabases.Add(dbRem);
|
||||
dbRem.Entries.Remove(entry.Uuid);
|
||||
pgParent.Entries.Remove(entry);
|
||||
_targetGroup.AddEntry(entry, true, true);
|
||||
addDatabase.Entries.Add(entry.Uuid, entry);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -74,30 +88,58 @@ namespace keepass2android.database.edit
|
||||
Finish(false, _app.GetResourceString(UiStringKey.CannotMoveGroupHere));
|
||||
return;
|
||||
}
|
||||
|
||||
var dbRem = _app.FindDatabaseForEntryId(@group.Uuid);
|
||||
if (dbRem == null)
|
||||
{
|
||||
Finish(false, "Did not find source database. Did you lock it?");
|
||||
return;
|
||||
}
|
||||
|
||||
dbRem.Groups.Remove(group.Uuid);
|
||||
removeDatabases.Add(dbRem);
|
||||
pgParent.Groups.Remove(group);
|
||||
_targetGroup.AddGroup(group, true, true);
|
||||
addDatabase.Groups.Add(group.Uuid, group);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
_onFinishToRun = new ActionOnFinish(ActiveActivity, (success, message, activity) =>
|
||||
{
|
||||
if (!success)
|
||||
{ // Let's not bother recovering from a failure.
|
||||
_app.Lock(false);
|
||||
}
|
||||
}, OnFinishToRun);
|
||||
|
||||
//Unchecked
|
||||
//TODO save the right database
|
||||
|
||||
|
||||
|
||||
//first save the database where we added the elements
|
||||
var allDatabasesToSave = new List<Database> {addDatabase};
|
||||
//then all databases where we removed elements:
|
||||
removeDatabases.RemoveWhere(db => db == addDatabase);
|
||||
allDatabasesToSave.AddRange(removeDatabases);
|
||||
|
||||
// Save
|
||||
SaveDb save = new SaveDb(_ctx, _app, _app.CurrentDb, OnFinishToRun, false);
|
||||
save.SetStatusLogger(StatusLogger);
|
||||
save.Run();
|
||||
int indexToSave = 0;
|
||||
bool allSavesSuccess = true;
|
||||
void ContinueSave(bool success, string message, Activity activeActivity)
|
||||
{
|
||||
allSavesSuccess &= success;
|
||||
indexToSave++;
|
||||
if (indexToSave == allDatabasesToSave.Count)
|
||||
{
|
||||
OnFinishToRun.SetResult(allSavesSuccess);
|
||||
OnFinishToRun.Run();
|
||||
return;
|
||||
}
|
||||
SaveDb saveDb = new SaveDb(_ctx, _app, allDatabasesToSave[indexToSave], new ActionOnFinish(activeActivity, ContinueSave), false);
|
||||
saveDb.SetStatusLogger(StatusLogger);
|
||||
saveDb.ShowDatabaseIocInStatus = allDatabasesToSave.Count > 1;
|
||||
saveDb.Run();
|
||||
}
|
||||
|
||||
|
||||
SaveDb save = new SaveDb(_ctx, _app, allDatabasesToSave[0], new ActionOnFinish(ActiveActivity, ContinueSave), false);
|
||||
save.SetStatusLogger(StatusLogger);
|
||||
save.ShowDatabaseIocInStatus = allDatabasesToSave.Count > 1;
|
||||
save.Run();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -79,9 +79,10 @@ namespace keepass2android
|
||||
_db = db;
|
||||
_dontSave = false;
|
||||
}
|
||||
|
||||
|
||||
public override void Run ()
|
||||
|
||||
public bool ShowDatabaseIocInStatus { get; set; }
|
||||
|
||||
public override void Run ()
|
||||
{
|
||||
|
||||
if (!_dontSave)
|
||||
@@ -95,7 +96,13 @@ namespace keepass2android
|
||||
return;
|
||||
}
|
||||
|
||||
StatusLogger.UpdateMessage(UiStringKey.saving_database);
|
||||
string message = _app.GetResourceString(UiStringKey.saving_database);
|
||||
|
||||
if (ShowDatabaseIocInStatus)
|
||||
message += " (" + _app.GetFileStorage(_db.Ioc).GetDisplayName(_db.Ioc) + ")";
|
||||
|
||||
StatusLogger.UpdateMessage(message);
|
||||
|
||||
IOConnectionInfo ioc = _db.Ioc;
|
||||
IFileStorage fileStorage = _app.GetFileStorage(ioc);
|
||||
|
||||
|
50
src/keepass2android/ActivityLaunchMode.cs
Normal file
50
src/keepass2android/ActivityLaunchMode.cs
Normal file
@@ -0,0 +1,50 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
using Android.App;
|
||||
using Android.Content;
|
||||
using Android.OS;
|
||||
using Android.Runtime;
|
||||
using Android.Views;
|
||||
using Android.Widget;
|
||||
|
||||
namespace keepass2android
|
||||
{
|
||||
public abstract class ActivityLaunchMode
|
||||
{
|
||||
public abstract void Launch(Activity act, Intent i);
|
||||
}
|
||||
|
||||
public class ActivityLaunchModeForward : ActivityLaunchMode
|
||||
{
|
||||
public override void Launch(Activity act, Intent i)
|
||||
{
|
||||
i.AddFlags(ActivityFlags.ForwardResult);
|
||||
act.StartActivity(i);
|
||||
}
|
||||
}
|
||||
|
||||
public class ActivityLaunchModeRequestCode : ActivityLaunchMode
|
||||
{
|
||||
private readonly int _reqCode;
|
||||
|
||||
public ActivityLaunchModeRequestCode(int reqCode)
|
||||
{
|
||||
_reqCode = reqCode;
|
||||
}
|
||||
public override void Launch(Activity act, Intent i)
|
||||
{
|
||||
act.StartActivityForResult(i, _reqCode);
|
||||
}
|
||||
}
|
||||
|
||||
public class ActivityLaunchModeSimple : ActivityLaunchMode
|
||||
{
|
||||
public override void Launch(Activity act, Intent i)
|
||||
{
|
||||
act.StartActivity(i);
|
||||
}
|
||||
}
|
||||
}
|
@@ -497,8 +497,13 @@ namespace keepass2android
|
||||
dbHelper.CreateFile(_ioc, Filename);
|
||||
}
|
||||
|
||||
GroupActivity.Launch(_activity, _activity._appTask);
|
||||
_activity.Finish();
|
||||
Intent data = new Intent();
|
||||
data.PutExtra("ioc", IOConnectionInfo.SerializeToString(_ioc));
|
||||
|
||||
_activity.SetResult(Result.Ok, data);
|
||||
|
||||
|
||||
_activity.Finish();
|
||||
|
||||
}
|
||||
else
|
||||
|
@@ -207,7 +207,14 @@ namespace keepass2android
|
||||
{
|
||||
Kp2aLog.Log("FP: StopListening ");
|
||||
_selfCancelled = true;
|
||||
_cancellationSignal.Cancel();
|
||||
try
|
||||
{
|
||||
_cancellationSignal.Cancel();
|
||||
}
|
||||
catch (System.ObjectDisposedException e)
|
||||
{
|
||||
Kp2aLog.LogUnexpectedError(e);
|
||||
}
|
||||
_cancellationSignal = null;
|
||||
}
|
||||
}
|
||||
|
@@ -63,11 +63,11 @@ namespace keepass2android
|
||||
private const String Tag = "Group Activity:";
|
||||
private const string Askaddtemplates = "AskAddTemplates";
|
||||
|
||||
public static void Launch(Activity act, AppTask appTask) {
|
||||
Launch(act, null, appTask);
|
||||
public static void Launch(Activity act, AppTask appTask, ActivityLaunchMode launchMode) {
|
||||
Launch(act, null, appTask, launchMode);
|
||||
}
|
||||
|
||||
public static void Launch (Activity act, PwGroup g, AppTask appTask)
|
||||
public static void Launch (Activity act, PwGroup g, AppTask appTask, ActivityLaunchMode launchMode)
|
||||
{
|
||||
Intent i = new Intent(act, typeof(GroupActivity));
|
||||
|
||||
@@ -76,7 +76,7 @@ namespace keepass2android
|
||||
}
|
||||
appTask.ToIntent(i);
|
||||
|
||||
act.StartActivityForResult(i,0);
|
||||
launchMode.Launch(act, i);
|
||||
}
|
||||
|
||||
protected PwUuid RetrieveGroupId(Intent i)
|
||||
|
@@ -199,6 +199,12 @@ namespace keepass2android
|
||||
Finish();
|
||||
}
|
||||
|
||||
if (resultCode == KeePass.ExitLoadAnotherDb)
|
||||
{
|
||||
AppTask.SetActivityResult(this, KeePass.ExitLoadAnotherDb);
|
||||
Finish();
|
||||
}
|
||||
|
||||
if (resultCode == KeePass.ExitReloadDb)
|
||||
{
|
||||
AppTask.SetActivityResult(this, KeePass.ExitReloadDb);
|
||||
|
@@ -67,8 +67,7 @@ namespace keepass2android
|
||||
ConfigurationChanges = ConfigChanges.Orientation,
|
||||
LaunchMode = LaunchMode.SingleInstance,
|
||||
WindowSoftInputMode = SoftInput.AdjustResize,
|
||||
Theme = "@style/MyTheme_Blue")] /*caution: also contained in AndroidManifest.xml*/
|
||||
//CAUTION: don't add intent filters here, they must be set in the manifest xml file
|
||||
Theme = "@style/MyTheme_Blue")]
|
||||
public class PasswordActivity : LockingActivity, IFingerprintAuthCallback
|
||||
{
|
||||
|
||||
@@ -84,10 +83,9 @@ namespace keepass2android
|
||||
|
||||
public const String KeyDefaultFilename = "defaultFileName";
|
||||
|
||||
private const String KeyKeyfile = "keyFile";
|
||||
private const String KeyPassword = "password";
|
||||
public const String KeyKeyfile = "keyFile";
|
||||
public const String KeyPassword = "password";
|
||||
|
||||
private const String ViewIntent = "android.intent.action.VIEW";
|
||||
private const string ShowpasswordKey = "ShowPassword";
|
||||
private const string KeyProviderIdOtp = "KP2A-OTP";
|
||||
private const string KeyProviderIdOtpRecovery = "KP2A-OTPSecret";
|
||||
@@ -103,15 +101,16 @@ namespace keepass2android
|
||||
private const int RequestCodePrepareKeyFile = 1004;
|
||||
private const int RequestCodeSelectAuxFile = 1005;
|
||||
|
||||
public const int ResultSelectOtherFile = (int) Result.FirstUser;
|
||||
|
||||
private Task<MemoryStream> _loadDbFileTask;
|
||||
|
||||
private Task<MemoryStream> _loadDbFileTask;
|
||||
private bool _loadDbTaskOffline; //indicate if preloading was started with offline mode
|
||||
|
||||
private IOConnectionInfo _ioConnection;
|
||||
private String _keyFile;
|
||||
bool _showPassword;
|
||||
|
||||
internal AppTask AppTask;
|
||||
private bool _killOnDestroy;
|
||||
private string _password = "";
|
||||
//OTPs which should be entered into the OTP fields as soon as these become visible
|
||||
@@ -160,52 +159,31 @@ namespace keepass2android
|
||||
//can be set before launching the Activity. Will be used once to immediately open the database
|
||||
static CompositeKey compositeKeyForImmediateLoad = null;
|
||||
|
||||
public static void Launch(Activity act, IOConnectionInfo ioc, AppTask appTask, CompositeKey compositeKey)
|
||||
|
||||
public static void Launch(Activity act, IOConnectionInfo ioc, CompositeKey compositeKey, ActivityLaunchMode launchMode)
|
||||
{
|
||||
compositeKeyForImmediateLoad = compositeKey;
|
||||
Launch(act, ioc, appTask);
|
||||
Launch(act, ioc, launchMode);
|
||||
}
|
||||
|
||||
public static void Launch(Activity act, String fileName, AppTask appTask)
|
||||
{
|
||||
File dbFile = new File(fileName);
|
||||
if ( ! dbFile.Exists() ) {
|
||||
throw new FileNotFoundException();
|
||||
}
|
||||
|
||||
|
||||
Intent i = new Intent(act, typeof(PasswordActivity));
|
||||
i.SetFlags(ActivityFlags.ForwardResult);
|
||||
i.PutExtra(Util.KeyFilename, fileName);
|
||||
appTask.ToIntent(i);
|
||||
|
||||
act.StartActivity(i);
|
||||
|
||||
}
|
||||
|
||||
|
||||
public static void Launch(Activity act, IOConnectionInfo ioc, AppTask appTask)
|
||||
public static void Launch(Activity act, IOConnectionInfo ioc, ActivityLaunchMode launchMode)
|
||||
{
|
||||
if (ioc.IsLocalFile())
|
||||
{
|
||||
Launch(act, ioc.Path, appTask);
|
||||
return;
|
||||
}
|
||||
|
||||
Intent i = new Intent(act, typeof(PasswordActivity));
|
||||
|
||||
Util.PutIoConnectionToIntent(ioc, i);
|
||||
i.SetFlags(ActivityFlags.ForwardResult);
|
||||
|
||||
appTask.ToIntent(i);
|
||||
|
||||
act.StartActivity(i);
|
||||
|
||||
launchMode.Launch(act, i);
|
||||
}
|
||||
|
||||
public void LaunchNextActivity()
|
||||
{
|
||||
//StackBaseActivity will launch the next activity
|
||||
Intent data = new Intent();
|
||||
data.PutExtra("ioc", IOConnectionInfo.SerializeToString(_ioConnection));
|
||||
|
||||
SetResult(Result.Ok, data);
|
||||
|
||||
Finish();
|
||||
}
|
||||
|
||||
@@ -215,8 +193,6 @@ namespace keepass2android
|
||||
_keepPasswordInOnResume = true;
|
||||
Kp2aLog.Log("PasswordActivity.OnActivityResult "+resultCode+"/"+requestCode);
|
||||
|
||||
AppTask.TryGetFromActivityResult(data, ref AppTask);
|
||||
|
||||
switch(resultCode) {
|
||||
|
||||
|
||||
@@ -663,7 +639,7 @@ namespace keepass2android
|
||||
_activityDesign.ApplyTheme();
|
||||
base.OnCreate(savedInstanceState);
|
||||
|
||||
_intentReceiver = new PasswordActivityBroadcastReceiver(this);
|
||||
_intentReceiver = new PasswordActivityBroadcastReceiver(this);
|
||||
IntentFilter filter = new IntentFilter();
|
||||
filter.AddAction(Intent.ActionScreenOff);
|
||||
RegisterReceiver(_intentReceiver, filter);
|
||||
@@ -678,19 +654,6 @@ namespace keepass2android
|
||||
|
||||
Intent i = Intent;
|
||||
|
||||
//only load the AppTask if this is the "first" OnCreate (not because of kill/resume, i.e. savedInstanceState==null)
|
||||
// and if the activity is not launched from history (i.e. recent tasks) because this would mean that
|
||||
// the Activity was closed already (user cancelling the task or task complete) but is restarted due recent tasks.
|
||||
// Don't re-start the task (especially bad if tak was complete already)
|
||||
if (Intent.Flags.HasFlag(ActivityFlags.LaunchedFromHistory))
|
||||
{
|
||||
AppTask = new NullTask();
|
||||
}
|
||||
else
|
||||
{
|
||||
AppTask = AppTask.GetTaskInOnCreate(savedInstanceState, Intent);
|
||||
}
|
||||
|
||||
|
||||
String action = i.Action;
|
||||
|
||||
@@ -700,11 +663,7 @@ namespace keepass2android
|
||||
_ioConnection = new IOConnectionInfo();
|
||||
|
||||
|
||||
if (action != null && action.Equals(ViewIntent))
|
||||
{
|
||||
if (!GetIocFromViewIntent(i)) return;
|
||||
}
|
||||
else if ((action != null) && (action.Equals(Intents.StartWithOtp)))
|
||||
if ((action != null) && (action.Equals(Intents.StartWithOtp)))
|
||||
{
|
||||
if (!GetIocFromOtpIntent(savedInstanceState, i)) return;
|
||||
_keepPasswordInOnResume = true;
|
||||
@@ -802,11 +761,10 @@ namespace keepass2android
|
||||
RequestPermissions(new[] { Manifest.Permission.UseFingerprint }, FingerprintPermissionRequestCode);
|
||||
|
||||
|
||||
var matchingOpenDb = App.Kp2a.OpenDatabases.FirstOrDefault(db => db.Ioc.IsSameFileAs(_ioConnection));
|
||||
if (matchingOpenDb != null)
|
||||
{
|
||||
App.Kp2a.CurrentDb = matchingOpenDb;
|
||||
Finish();
|
||||
if (App.Kp2a.TrySelectCurrentDb(_ioConnection))
|
||||
{
|
||||
//database already opened. return the ioc and we're good.
|
||||
LaunchNextActivity();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1137,50 +1095,6 @@ namespace keepass2android
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool GetIocFromViewIntent(Intent i)
|
||||
{
|
||||
//started from "view" intent (e.g. from file browser)
|
||||
_ioConnection.Path = i.DataString;
|
||||
|
||||
if (_ioConnection.Path.StartsWith("file://"))
|
||||
{
|
||||
_ioConnection.Path = URLDecoder.Decode(_ioConnection.Path.Substring(7));
|
||||
|
||||
if (_ioConnection.Path.Length == 0)
|
||||
{
|
||||
// No file name
|
||||
Toast.MakeText(this, Resource.String.FileNotFound, ToastLength.Long).Show();
|
||||
Finish();
|
||||
return false;
|
||||
}
|
||||
|
||||
File dbFile = new File(_ioConnection.Path);
|
||||
if (!dbFile.Exists())
|
||||
{
|
||||
// File does not exist
|
||||
Toast.MakeText(this, Resource.String.FileNotFound, ToastLength.Long).Show();
|
||||
Finish();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!_ioConnection.Path.StartsWith("content://"))
|
||||
{
|
||||
|
||||
Toast.MakeText(this, Resource.String.error_can_not_handle_uri, ToastLength.Long).Show();
|
||||
Finish();
|
||||
return false;
|
||||
}
|
||||
IoUtil.TryTakePersistablePermissions(this.ContentResolver, i.Data);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
SetKeyProviderFromString(LoadKeyProviderStringForIoc(_ioConnection.Path));
|
||||
return true;
|
||||
}
|
||||
|
||||
private void InitializeBottomBarButtons()
|
||||
{
|
||||
@@ -1607,7 +1521,6 @@ namespace keepass2android
|
||||
CopyToClipboardService.ActivateKeyboard(this);
|
||||
}
|
||||
|
||||
AppTask.CanActivateSearchViewOnStart = true;
|
||||
DonateReminder.ShowDonateReminderIfAppropriate(this);
|
||||
|
||||
|
||||
@@ -1635,7 +1548,6 @@ namespace keepass2android
|
||||
protected override void OnSaveInstanceState(Bundle outState)
|
||||
{
|
||||
base.OnSaveInstanceState(outState);
|
||||
AppTask.ToBundle(outState);
|
||||
outState.PutBoolean(ShowpasswordKey, _showPassword);
|
||||
|
||||
outState.PutString(KeyFileOrProviderKey, GetKeyProviderString());
|
||||
@@ -1751,6 +1663,7 @@ namespace keepass2android
|
||||
killButton.Click += (sender, args) =>
|
||||
{
|
||||
_killOnDestroy = true;
|
||||
SetResult(Result.Canceled);
|
||||
Finish();
|
||||
|
||||
};
|
||||
@@ -1856,9 +1769,9 @@ namespace keepass2android
|
||||
keyboard.HideSoftInputFromWindow(pwd.WindowToken, HideSoftInputFlags.ImplicitOnly);
|
||||
}, 50);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool InitFingerprintUnlock()
|
||||
private bool InitFingerprintUnlock()
|
||||
{
|
||||
var btn = FindViewById<ImageButton>(Resource.Id.fingerprintbtn);
|
||||
try
|
||||
@@ -1986,12 +1899,8 @@ namespace keepass2android
|
||||
|
||||
private void GoToFileSelectActivity()
|
||||
{
|
||||
Intent intent = new Intent(this, typeof (FileSelectActivity));
|
||||
intent.PutExtra(FileSelectActivity.NoForwardToPasswordActivity, true);
|
||||
AppTask.ToIntent(intent);
|
||||
intent.AddFlags(ActivityFlags.ForwardResult);
|
||||
StartActivity(intent);
|
||||
Finish();
|
||||
SetResult((Result) ResultSelectOtherFile);
|
||||
Finish();
|
||||
}
|
||||
|
||||
private class AfterLoad : OnFinish {
|
||||
@@ -2014,7 +1923,6 @@ namespace keepass2android
|
||||
_act.BroadcastOpenDatabase();
|
||||
_act.InvalidCompositeKeyCount = 0;
|
||||
_act.LoadingErrorCount = 0;
|
||||
_act.Finish();
|
||||
|
||||
|
||||
GC.Collect(); // Ensure temporary memory used while loading is collected
|
||||
@@ -2080,20 +1988,22 @@ namespace keepass2android
|
||||
(sender, args) =>
|
||||
{
|
||||
((Dialog) sender).Dismiss();
|
||||
_act.LaunchNextActivity();
|
||||
})
|
||||
if (Success)
|
||||
{
|
||||
_act.LaunchNextActivity();
|
||||
}
|
||||
})
|
||||
.SetCancelable(false)
|
||||
.Show();
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
DisplayMessage(_act);
|
||||
if (Success)
|
||||
{
|
||||
_act.LaunchNextActivity();
|
||||
}
|
||||
|
||||
DisplayMessage(_act);
|
||||
if (Success)
|
||||
{
|
||||
_act.LaunchNextActivity();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -2207,6 +2117,7 @@ namespace keepass2android
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@@ -53,7 +53,7 @@
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<activity android:configChanges="orientation|keyboard|keyboardHidden" android:label="@string/app_name" android:theme="@style/MyTheme_Blue" android:name="keepass2android.PasswordActivity" android:windowSoftInputMode="adjustResize">
|
||||
<activity android:configChanges="orientation|keyboard|keyboardHidden" android:label="@string/app_name" android:theme="@style/MyTheme_Blue" android:name="keepass2android.SelectCurrentDbActivity" android:windowSoftInputMode="adjustResize">
|
||||
<intent-filter android:label="@string/app_name">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
@@ -64,7 +64,7 @@
|
||||
</intent-filter>
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="kp2a.action.PasswordActivity" />
|
||||
<action android:name="kp2a.action.SelectCurrentDbActivity" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
</intent-filter>
|
||||
|
||||
@@ -97,13 +97,15 @@
|
||||
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.kdbx" />
|
||||
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.kdbx" />
|
||||
</intent-filter>
|
||||
|
||||
<intent-filter android:label="@string/kp2a_findUrl">
|
||||
<action android:name="android.intent.action.SEND" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<data android:mimeType="text/plain" />
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW"/>
|
||||
<category android:name="android.intent.category.BROWSABLE"/>
|
||||
<data
|
||||
android:scheme="https"
|
||||
android:host="my.yubico.com"
|
||||
android:pathPrefix="/neo"/>
|
||||
<action android:name="keepass2android.ACTION_START_WITH_TASK" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<uses-library required="false" name="com.sec.android.app.multiwindow" />
|
||||
|
@@ -58,7 +58,7 @@
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity android:configChanges="orientation|keyboard|keyboardHidden" android:label="@string/app_name" android:theme="@style/MyTheme_Blue" android:name="keepass2android.PasswordActivity" android:windowSoftInputMode="adjustResize">
|
||||
<activity android:configChanges="orientation|keyboard|keyboardHidden" android:label="@string/app_name" android:theme="@style/MyTheme_Blue" android:name="keepass2android.SelectCurrentDbActivity" android:windowSoftInputMode="adjustResize">
|
||||
<intent-filter android:label="@string/app_name">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
@@ -69,7 +69,7 @@
|
||||
</intent-filter>
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="kp2a.action.PasswordActivity" />
|
||||
<action android:name="kp2a.action.SelectCurrentDbActivity" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
</intent-filter>
|
||||
|
||||
@@ -122,14 +122,15 @@
|
||||
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.kdb" />
|
||||
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.kdb" />
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW"/>
|
||||
<category android:name="android.intent.category.BROWSABLE"/>
|
||||
<data
|
||||
android:scheme="https"
|
||||
android:host="my.yubico.com"
|
||||
android:pathPrefix="/neo"/>
|
||||
</intent-filter>
|
||||
<intent-filter android:label="@string/kp2a_findUrl">
|
||||
<action android:name="android.intent.action.SEND" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<data android:mimeType="text/plain" />
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<action android:name="keepass2android.ACTION_START_WITH_TASK" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<uses-library required="false" name="com.sec.android.app.multiwindow" />
|
||||
<meta-data android:name="com.sec.android.support.multiwindow" android:value="true" />
|
||||
|
@@ -41,7 +41,7 @@
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<activity android:configChanges="orientation|keyboard|keyboardHidden" android:label="@string/app_name" android:theme="@style/MyTheme_Blue" android:name="keepass2android.PasswordActivity" android:windowSoftInputMode="adjustResize">
|
||||
<activity android:configChanges="orientation|keyboard|keyboardHidden" android:label="@string/app_name" android:theme="@style/MyTheme_Blue" android:name="keepass2android.SelectCurrentDbActivity" android:windowSoftInputMode="adjustResize">
|
||||
<intent-filter android:label="@string/app_name">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
@@ -52,7 +52,7 @@
|
||||
</intent-filter>
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="kp2a.action.PasswordActivity" />
|
||||
<action android:name="kp2a.action.SelectCurrentDbActivity" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
</intent-filter>
|
||||
|
||||
@@ -112,6 +112,16 @@
|
||||
android:host="my.yubico.com"
|
||||
android:pathPrefix="/neo"/>
|
||||
</intent-filter>
|
||||
|
||||
<intent-filter android:label="@string/kp2a_findUrl">
|
||||
<action android:name="android.intent.action.SEND" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<data android:mimeType="text/plain" />
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<action android:name="keepass2android.ACTION_START_WITH_TASK" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<uses-library required="false" name="com.sec.android.app.multiwindow" />
|
||||
<meta-data android:name="com.sec.android.support.multiwindow" android:value="true" />
|
||||
|
@@ -16,6 +16,8 @@ using Android.Text;
|
||||
using Android.Util;
|
||||
using Android.Views;
|
||||
using Android.Widget;
|
||||
using Java.IO;
|
||||
using Java.Net;
|
||||
using keepass2android.Io;
|
||||
using keepass2android.Utils;
|
||||
using KeePassLib.Keys;
|
||||
@@ -24,9 +26,12 @@ using Object = Java.Lang.Object;
|
||||
|
||||
namespace keepass2android
|
||||
{
|
||||
[Activity(Label = AppNames.AppName, MainLauncher = false, Theme = "@style/MyTheme_Blue", LaunchMode = LaunchMode.SingleInstance)]
|
||||
[Activity(Label = AppNames.AppName, MainLauncher = false, Theme = "@style/MyTheme_Blue", LaunchMode = LaunchMode.SingleInstance)] //caution, see manifest file
|
||||
public class SelectCurrentDbActivity : AppCompatActivity
|
||||
{
|
||||
private int ReqCodeOpenNewDb = 1;
|
||||
|
||||
|
||||
public class OpenDatabaseAdapter : BaseAdapter
|
||||
{
|
||||
|
||||
@@ -135,12 +140,13 @@ namespace keepass2android
|
||||
|
||||
private void OnOpenOther()
|
||||
{
|
||||
StartFileSelect();
|
||||
StartFileSelect(true);
|
||||
}
|
||||
|
||||
private void OnItemSelected(Database selectedDatabase)
|
||||
{
|
||||
App.Kp2a.CurrentDb = selectedDatabase;
|
||||
LaunchingOther = true;
|
||||
AppTask.LaunchFirstGroupActivity(this);
|
||||
}
|
||||
|
||||
@@ -155,7 +161,12 @@ namespace keepass2android
|
||||
|
||||
SupportActionBar.Title = GetString(Resource.String.select_database);
|
||||
|
||||
if ((AppTask == null) && (Intent.Flags.HasFlag(ActivityFlags.LaunchedFromHistory)))
|
||||
|
||||
//only load the AppTask if this is the "first" OnCreate (not because of kill/resume, i.e. savedInstanceState==null)
|
||||
// and if the activity is not launched from history (i.e. recent tasks) because this would mean that
|
||||
// the Activity was closed already (user cancelling the task or task complete) but is restarted due recent tasks.
|
||||
// Don't re-start the task (especially bad if tak was complete already)
|
||||
if (Intent.Flags.HasFlag(ActivityFlags.LaunchedFromHistory))
|
||||
{
|
||||
AppTask = new NullTask();
|
||||
}
|
||||
@@ -168,19 +179,91 @@ namespace keepass2android
|
||||
var gridView = FindViewById<GridView>(Resource.Id.gridview);
|
||||
gridView.ItemClick += (sender, args) => OnItemSelected(_adapter._displayedDatabases[args.Position]);
|
||||
gridView.Adapter = _adapter;
|
||||
|
||||
|
||||
if (!string.IsNullOrEmpty(Intent.GetStringExtra(Util.KeyFilename)))
|
||||
{
|
||||
//forward to password activity
|
||||
Intent i = new Intent(this, typeof(PasswordActivity));
|
||||
IOConnectionInfo ioc = new IOConnectionInfo();
|
||||
Util.SetIoConnectionFromIntent(ioc, Intent);
|
||||
Util.PutIoConnectionToIntent(ioc, i);
|
||||
i.PutExtra(PasswordActivity.KeyKeyfile, i.GetStringExtra(PasswordActivity.KeyKeyfile));
|
||||
i.PutExtra(PasswordActivity.KeyPassword, i.GetStringExtra(PasswordActivity.KeyPassword));
|
||||
LaunchingOther = true;
|
||||
StartActivityForResult(i, ReqCodeOpenNewDb);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Intent.Action == Intent.ActionView)
|
||||
{
|
||||
GetIocFromViewIntent(Intent);
|
||||
}
|
||||
else if (Intent.Action == Intent.ActionSend)
|
||||
{
|
||||
AppTask = new SearchUrlTask { UrlToSearchFor = Intent.GetStringExtra(Intent.ExtraText) };
|
||||
}
|
||||
}
|
||||
|
||||
_intentReceiver = new MyBroadcastReceiver(this);
|
||||
IntentFilter filter = new IntentFilter();
|
||||
filter.AddAction(Intents.DatabaseLocked);
|
||||
RegisterReceiver(_intentReceiver, filter);
|
||||
|
||||
}
|
||||
|
||||
|
||||
IOConnectionInfo LoadIoc(string defaultFileName)
|
||||
private bool GetIocFromViewIntent(Intent intent)
|
||||
{
|
||||
return App.Kp2a.FileDbHelper.CursorToIoc(App.Kp2a.FileDbHelper.FetchFileByName(defaultFileName));
|
||||
}
|
||||
IOConnectionInfo ioc = new IOConnectionInfo();
|
||||
|
||||
//started from "view" intent (e.g. from file browser)
|
||||
ioc.Path = intent.DataString;
|
||||
|
||||
if (ioc.Path.StartsWith("file://"))
|
||||
{
|
||||
ioc.Path = URLDecoder.Decode(ioc.Path.Substring(7));
|
||||
|
||||
if (ioc.Path.Length == 0)
|
||||
{
|
||||
// No file name
|
||||
Toast.MakeText(this, Resource.String.FileNotFound, ToastLength.Long).Show();
|
||||
return false;
|
||||
}
|
||||
|
||||
File dbFile = new File(ioc.Path);
|
||||
if (!dbFile.Exists())
|
||||
{
|
||||
// File does not exist
|
||||
Toast.MakeText(this, Resource.String.FileNotFound, ToastLength.Long).Show();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!ioc.Path.StartsWith("content://"))
|
||||
{
|
||||
Toast.MakeText(this, Resource.String.error_can_not_handle_uri, ToastLength.Long).Show();
|
||||
return false;
|
||||
}
|
||||
IoUtil.TryTakePersistablePermissions(this.ContentResolver, intent.Data);
|
||||
|
||||
|
||||
}
|
||||
|
||||
{
|
||||
Intent launchIntent = new Intent(this, typeof(PasswordActivity));
|
||||
Util.PutIoConnectionToIntent(ioc, launchIntent);
|
||||
LaunchingOther = true;
|
||||
StartActivityForResult(launchIntent, ReqCodeOpenNewDb);
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override void OnResume()
|
||||
{
|
||||
base.OnResume();
|
||||
if (!IsFinishing && !LaunchingPasswordActivity)
|
||||
if (!IsFinishing && !LaunchingOther)
|
||||
{
|
||||
if (App.Kp2a.OpenDatabases.Any() == false)
|
||||
{
|
||||
@@ -188,13 +271,6 @@ namespace keepass2android
|
||||
return;
|
||||
}
|
||||
|
||||
if (_loadAnotherDatabase)
|
||||
{
|
||||
StartFileSelect();
|
||||
_loadAnotherDatabase = false;
|
||||
return;
|
||||
}
|
||||
|
||||
//database loaded
|
||||
if (App.Kp2a.QuickLocked)
|
||||
{
|
||||
@@ -208,6 +284,7 @@ namespace keepass2android
|
||||
//database(s) unlocked
|
||||
if (App.Kp2a.OpenDatabases.Count() == 1)
|
||||
{
|
||||
LaunchingOther = true;
|
||||
AppTask.LaunchFirstGroupActivity(this);
|
||||
return;
|
||||
}
|
||||
@@ -223,21 +300,23 @@ namespace keepass2android
|
||||
|
||||
protected override void OnPause()
|
||||
{
|
||||
LaunchingPasswordActivity = false;
|
||||
LaunchingOther = false;
|
||||
base.OnPause();
|
||||
}
|
||||
|
||||
private void StartFileSelect()
|
||||
private void StartFileSelect(bool noForwardToPassword = false)
|
||||
{
|
||||
Intent intent = new Intent(this, typeof(FileSelectActivity));
|
||||
AppTask.ToIntent(intent);
|
||||
intent.AddFlags(ActivityFlags.ForwardResult);
|
||||
StartActivity(intent);
|
||||
intent.PutExtra(FileSelectActivity.NoForwardToPasswordActivity, noForwardToPassword);
|
||||
LaunchingOther = true;
|
||||
StartActivityForResult(intent, ReqCodeOpenNewDb);
|
||||
}
|
||||
|
||||
internal AppTask AppTask;
|
||||
private bool _loadAnotherDatabase;
|
||||
private OpenDatabaseAdapter _adapter;
|
||||
private MyBroadcastReceiver _intentReceiver;
|
||||
|
||||
public override void OnBackPressed()
|
||||
{
|
||||
@@ -261,6 +340,40 @@ namespace keepass2android
|
||||
|
||||
AppTask.TryGetFromActivityResult(data, ref AppTask);
|
||||
|
||||
if (requestCode == ReqCodeOpenNewDb)
|
||||
{
|
||||
switch ((int)resultCode)
|
||||
{
|
||||
case (int)Result.Ok:
|
||||
|
||||
string iocString = data?.GetStringExtra("ioc");
|
||||
IOConnectionInfo ioc = IOConnectionInfo.UnserializeFromString(iocString);
|
||||
if (App.Kp2a.TrySelectCurrentDb(ioc))
|
||||
{
|
||||
LaunchingOther = true;
|
||||
AppTask.CanActivateSearchViewOnStart = true;
|
||||
AppTask.LaunchFirstGroupActivity(this);
|
||||
}
|
||||
|
||||
|
||||
break;
|
||||
case PasswordActivity.ResultSelectOtherFile:
|
||||
StartFileSelect(true);
|
||||
break;
|
||||
case (int)Result.Canceled:
|
||||
if (App.Kp2a.OpenDatabases.Any() == false)
|
||||
{
|
||||
//don't open fileselect/password activity again
|
||||
OnBackPressed();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
switch (resultCode)
|
||||
{
|
||||
case KeePass.ExitNormal: // Returned to this screen using the Back key
|
||||
@@ -297,7 +410,7 @@ namespace keepass2android
|
||||
|
||||
break;
|
||||
case KeePass.ExitLoadAnotherDb:
|
||||
_loadAnotherDatabase = true;
|
||||
StartFileSelect(true);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -305,10 +418,39 @@ namespace keepass2android
|
||||
|
||||
private void LaunchPasswordActivityForReload(IOConnectionInfo ioc, CompositeKey compositeKey)
|
||||
{
|
||||
LaunchingPasswordActivity = true;
|
||||
PasswordActivity.Launch(this, ioc, AppTask, compositeKey);
|
||||
LaunchingOther = true;
|
||||
PasswordActivity.Launch(this, ioc, compositeKey, new ActivityLaunchModeRequestCode(ReqCodeOpenNewDb));
|
||||
}
|
||||
|
||||
public bool LaunchingPasswordActivity { get; set; }
|
||||
public bool LaunchingOther { get; set; }
|
||||
|
||||
|
||||
private class MyBroadcastReceiver : BroadcastReceiver
|
||||
{
|
||||
readonly SelectCurrentDbActivity _activity;
|
||||
public MyBroadcastReceiver(SelectCurrentDbActivity activity)
|
||||
{
|
||||
_activity = activity;
|
||||
}
|
||||
|
||||
public override void OnReceive(Context context, Intent intent)
|
||||
{
|
||||
switch (intent.Action)
|
||||
{
|
||||
case Intents.DatabaseLocked:
|
||||
_activity.OnLockDatabase();
|
||||
break;
|
||||
case Intent.ActionScreenOff:
|
||||
App.Kp2a.OnScreenOff();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void OnLockDatabase()
|
||||
{
|
||||
//app tasks are assumed to be finished/cancelled when the database is locked
|
||||
AppTask = new NullTask();
|
||||
}
|
||||
}
|
||||
}
|
@@ -56,11 +56,11 @@ namespace keepass2android
|
||||
{
|
||||
}
|
||||
|
||||
public static void Launch(Activity act, SearchUrlTask task)
|
||||
public static void Launch(Activity act, SearchUrlTask task, ActivityLaunchMode launchMode)
|
||||
{
|
||||
Intent i = new Intent(act, typeof(ShareUrlResults));
|
||||
task.ToIntent(i);
|
||||
act.StartActivityForResult(i, 0);
|
||||
launchMode.Launch(act, i);
|
||||
}
|
||||
|
||||
|
||||
@@ -171,7 +171,8 @@ namespace keepass2android
|
||||
newTask.ShowUserNotifications = currentSelectTask.ShowUserNotifications;
|
||||
|
||||
selectOtherEntry.Click += (sender, e) => {
|
||||
GroupActivity.Launch (this, newTask);
|
||||
GroupActivity.Launch (this, newTask, new ActivityLaunchModeRequestCode(0));
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -182,7 +183,7 @@ namespace keepass2android
|
||||
createUrlEntry.Visibility = ViewStates.Visible;
|
||||
createUrlEntry.Click += (sender, e) =>
|
||||
{
|
||||
GroupActivity.Launch(this, new CreateEntryThenCloseTask { Url = url, ShowUserNotifications = (AppTask as SelectEntryTask)?.ShowUserNotifications ?? true });
|
||||
GroupActivity.Launch(this, new CreateEntryThenCloseTask { Url = url, ShowUserNotifications = (AppTask as SelectEntryTask)?.ShowUserNotifications ?? true }, new ActivityLaunchModeRequestCode(0));
|
||||
Toast.MakeText(this, GetString(Resource.String.select_group_then_add, new Java.Lang.Object[] { GetString(Resource.String.add_entry) }), ToastLength.Long).Show();
|
||||
};
|
||||
}
|
||||
|
@@ -500,14 +500,10 @@ namespace keepass2android
|
||||
return Application.Context.Resources.GetDrawable((int)field.GetValue(null));
|
||||
}
|
||||
|
||||
public void AskYesNoCancel(UiStringKey titleKey, UiStringKey messageKey,
|
||||
EventHandler<DialogClickEventArgs> yesHandler,
|
||||
EventHandler<DialogClickEventArgs> noHandler,
|
||||
EventHandler<DialogClickEventArgs> cancelHandler,
|
||||
Context ctx)
|
||||
public void AskYesNoCancel(UiStringKey titleKey, UiStringKey messageKey, EventHandler<DialogClickEventArgs> yesHandler, EventHandler<DialogClickEventArgs> noHandler, EventHandler<DialogClickEventArgs> cancelHandler, Context ctx, string messageSuffix)
|
||||
{
|
||||
AskYesNoCancel(titleKey, messageKey, UiStringKey.yes, UiStringKey.no,
|
||||
yesHandler, noHandler, cancelHandler, ctx);
|
||||
yesHandler, noHandler, cancelHandler, ctx, messageSuffix);
|
||||
}
|
||||
|
||||
public void AskYesNoCancel(UiStringKey titleKey, UiStringKey messageKey,
|
||||
@@ -515,9 +511,9 @@ namespace keepass2android
|
||||
EventHandler<DialogClickEventArgs> yesHandler,
|
||||
EventHandler<DialogClickEventArgs> noHandler,
|
||||
EventHandler<DialogClickEventArgs> cancelHandler,
|
||||
Context ctx)
|
||||
Context ctx, string messageSuffix = "")
|
||||
{
|
||||
AskYesNoCancel(titleKey, messageKey, yesString, noString, yesHandler, noHandler, cancelHandler, null, ctx);
|
||||
AskYesNoCancel(titleKey, messageKey, yesString, noString, yesHandler, noHandler, cancelHandler, null, ctx, messageSuffix);
|
||||
}
|
||||
|
||||
public void AskYesNoCancel(UiStringKey titleKey, UiStringKey messageKey,
|
||||
@@ -526,7 +522,7 @@ namespace keepass2android
|
||||
EventHandler<DialogClickEventArgs> noHandler,
|
||||
EventHandler<DialogClickEventArgs> cancelHandler,
|
||||
EventHandler dismissHandler,
|
||||
Context ctx)
|
||||
Context ctx, string messageSuffix = "")
|
||||
{
|
||||
Handler handler = new Handler(Looper.MainLooper);
|
||||
handler.Post(() =>
|
||||
@@ -534,7 +530,7 @@ namespace keepass2android
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(ctx);
|
||||
builder.SetTitle(GetResourceString(titleKey));
|
||||
|
||||
builder.SetMessage(GetResourceString(messageKey));
|
||||
builder.SetMessage(GetResourceString(messageKey)+(messageSuffix != "" ? " " + messageSuffix: ""));
|
||||
|
||||
string yesText = GetResourceString(yesString);
|
||||
builder.SetPositiveButton(yesText, yesHandler);
|
||||
@@ -787,6 +783,7 @@ namespace keepass2android
|
||||
}
|
||||
|
||||
|
||||
|
||||
public class CertificateErrorHandlerImpl : Java.Lang.Object, Keepass2android.Javafilestorage.ICertificateErrorHandler
|
||||
{
|
||||
private readonly Kp2aApp _app;
|
||||
@@ -1022,9 +1019,9 @@ namespace keepass2android
|
||||
|
||||
public PwGroup FindGroup(PwUuid uuid)
|
||||
{
|
||||
PwGroup result;
|
||||
foreach (Database db in OpenDatabases)
|
||||
{
|
||||
PwGroup result;
|
||||
if (db.Groups.TryGetValue(uuid, out result))
|
||||
return result;
|
||||
}
|
||||
@@ -1044,7 +1041,19 @@ namespace keepass2android
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public bool TrySelectCurrentDb(IOConnectionInfo ioConnection)
|
||||
{
|
||||
var matchingOpenDb = App.Kp2a.OpenDatabases.FirstOrDefault(db => db.Ioc.IsSameFileAs(ioConnection));
|
||||
if (matchingOpenDb != null)
|
||||
{
|
||||
CurrentDb = matchingOpenDb;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
///Application class for Keepass2Android: Contains static Database variable to be used by all components.
|
||||
|
@@ -187,7 +187,7 @@ namespace keepass2android
|
||||
|
||||
public virtual void LaunchFirstGroupActivity(Activity act)
|
||||
{
|
||||
GroupActivity.Launch(act, this);
|
||||
GroupActivity.Launch(act, this, new ActivityLaunchModeRequestCode(0));
|
||||
}
|
||||
|
||||
public virtual void AfterAddNewEntry(EntryEditActivity entryEditActivity, PwEntry newEntry)
|
||||
@@ -403,11 +403,11 @@ namespace keepass2android
|
||||
{
|
||||
if (String.IsNullOrEmpty(UrlToSearchFor))
|
||||
{
|
||||
GroupActivity.Launch(act, new SelectEntryTask() { ShowUserNotifications = ShowUserNotifications});
|
||||
GroupActivity.Launch(act, new SelectEntryTask() { ShowUserNotifications = ShowUserNotifications}, new ActivityLaunchModeRequestCode(0));
|
||||
}
|
||||
else
|
||||
{
|
||||
ShareUrlResults.Launch(act, this);
|
||||
ShareUrlResults.Launch(act, this, new ActivityLaunchModeRequestCode(0));
|
||||
}
|
||||
|
||||
|
||||
@@ -792,7 +792,6 @@ namespace keepass2android
|
||||
#endif
|
||||
|
||||
private LinkedList<string> _groupUuid;
|
||||
private readonly Database _db;
|
||||
protected AppTask TaskToBeLaunchedAfterNavigation;
|
||||
|
||||
protected String FullGroupName {
|
||||
@@ -817,8 +816,7 @@ namespace keepass2android
|
||||
/// <param name="groups">Groups.</param>
|
||||
/// <param name="taskToBeLaunchedAfterNavigation">Task to be launched after navigation.</param>
|
||||
/// <param name="toastEnable">If set to <c>true</c>, toast will be displayed after navigation.</param>
|
||||
protected NavigateAndLaunchTask(Database db, PwGroup groups, AppTask taskToBeLaunchedAfterNavigation, bool toastEnable = false) {
|
||||
_db = db;
|
||||
protected NavigateAndLaunchTask(PwGroup groups, AppTask taskToBeLaunchedAfterNavigation, bool toastEnable = false) {
|
||||
TaskToBeLaunchedAfterNavigation = taskToBeLaunchedAfterNavigation;
|
||||
PopulateGroups (groups);
|
||||
ToastEnable = toastEnable;
|
||||
@@ -935,7 +933,7 @@ namespace keepass2android
|
||||
groupBaseActivity.StartTask (TaskToBeLaunchedAfterNavigation);
|
||||
return;
|
||||
|
||||
} else if (_groupUuid.Contains(groupBaseActivity.UuidGroup)) { // Need to go up in groups tree
|
||||
} else if (_groupUuid.Contains(groupBaseActivity.UuidGroup)) { // Need to down up in groups tree
|
||||
|
||||
// Get next Group Uuid
|
||||
var linkedListNode = _groupUuid.Find(groupBaseActivity.UuidGroup);
|
||||
@@ -947,16 +945,27 @@ namespace keepass2android
|
||||
PwUuid nextGroupPwUuid = new PwUuid (MemUtil.HexStringToByteArray (nextGroupUuid));
|
||||
|
||||
// Create Group Activity
|
||||
PwGroup nextGroup = _db.Groups[nextGroupPwUuid];
|
||||
GroupActivity.Launch (groupBaseActivity, nextGroup, this);
|
||||
PwGroup nextGroup = App.Kp2a.CurrentDb.Groups[nextGroupPwUuid];
|
||||
GroupActivity.Launch (groupBaseActivity, nextGroup, this, new ActivityLaunchModeRequestCode(0));
|
||||
}
|
||||
return;
|
||||
|
||||
} else { // Need to go down in groups tree
|
||||
SetActivityResult(groupBaseActivity, KeePass.ExitNormal);
|
||||
groupBaseActivity.Finish();
|
||||
} else { // Need to go up in groups tree
|
||||
var targetUuid = new PwUuid(MemUtil.HexStringToByteArray(_groupUuid.Last.Value));
|
||||
var targetDb = App.Kp2a.FindDatabaseForGroupId(targetUuid);
|
||||
if (App.Kp2a.CurrentDb != targetDb)
|
||||
{
|
||||
App.Kp2a.CurrentDb = targetDb;
|
||||
GroupActivity.Launch(groupBaseActivity,targetDb.Root,this,new ActivityLaunchModeForward());
|
||||
}
|
||||
else
|
||||
{
|
||||
SetActivityResult(groupBaseActivity, KeePass.ExitNormal);
|
||||
}
|
||||
groupBaseActivity.Finish();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
public override void SetupGroupBaseActivityButtons(GroupBaseActivity groupBaseActivity)
|
||||
@@ -972,19 +981,29 @@ namespace keepass2android
|
||||
|
||||
public class NavigateToFolder: NavigateAndLaunchTask {
|
||||
|
||||
public NavigateToFolder()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public NavigateToFolder(Database db, PwGroup groups, bool toastEnable = false)
|
||||
: base(db, groups, new NullTask(), toastEnable)
|
||||
|
||||
public NavigateToFolder(Database db, PwGroup groups, bool toastEnable = false)
|
||||
: base(groups, new NullTask(), toastEnable)
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class NavigateToFolderAndLaunchMoveElementTask: NavigateAndLaunchTask {
|
||||
|
||||
|
||||
public NavigateToFolderAndLaunchMoveElementTask(Database db, PwGroup groups, List<PwUuid> uuids, bool toastEnable = false)
|
||||
:base(db, groups, new MoveElementsTask() { Uuids = uuids }, toastEnable) {
|
||||
|
||||
public NavigateToFolderAndLaunchMoveElementTask()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public NavigateToFolderAndLaunchMoveElementTask(Database db, PwGroup groups, List<PwUuid> uuids, bool toastEnable = false)
|
||||
:base(groups, new MoveElementsTask() { Uuids = uuids }, toastEnable) {
|
||||
}
|
||||
|
||||
public override void Setup(Bundle b) {
|
||||
|
@@ -44,12 +44,6 @@ namespace keepass2android
|
||||
ConfigurationChanges=ConfigChanges.Orientation|
|
||||
ConfigChanges.KeyboardHidden,
|
||||
Theme = "@style/MyTheme_Blue")]
|
||||
[IntentFilter(new [] { Intent.ActionSend },
|
||||
Label = "@string/kp2a_findUrl",
|
||||
Categories=new[]{Intent.CategoryDefault},
|
||||
DataMimeType="text/plain")]
|
||||
[IntentFilter(new[] { Strings.ActionStartWithTask },
|
||||
Categories = new[] { Intent.CategoryDefault })]
|
||||
public class FileSelectActivity : AppCompatActivity
|
||||
{
|
||||
private readonly ActivityDesign _design;
|
||||
@@ -72,7 +66,7 @@ namespace keepass2android
|
||||
|
||||
private bool _recentMode;
|
||||
|
||||
internal AppTask AppTask;
|
||||
|
||||
private const int RequestCodeSelectIoc = 456;
|
||||
private const int RequestCodeEditIoc = 457;
|
||||
|
||||
@@ -85,24 +79,7 @@ namespace keepass2android
|
||||
|
||||
|
||||
Kp2aLog.Log("FileSelect.OnCreate");
|
||||
Kp2aLog.Log("FileSelect:apptask="+Intent.GetStringExtra("KP2A_APPTASK"));
|
||||
|
||||
if (Intent.Action == Intent.ActionSend)
|
||||
{
|
||||
AppTask = new SearchUrlTask { UrlToSearchFor = Intent.GetStringExtra(Intent.ExtraText) };
|
||||
}
|
||||
else
|
||||
{
|
||||
//see PasswordActivity for an explanation
|
||||
if (Intent.Flags.HasFlag(ActivityFlags.LaunchedFromHistory))
|
||||
{
|
||||
AppTask = new NullTask();
|
||||
}
|
||||
else
|
||||
{
|
||||
AppTask = AppTask.GetTaskInOnCreate(savedInstanceState, Intent);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
_dbHelper = App.Kp2a.FileDbHelper;
|
||||
@@ -150,7 +127,7 @@ namespace keepass2android
|
||||
{
|
||||
//ShowFilenameDialog(false, true, true, Android.OS.Environment.ExternalStorageDirectory + GetString(Resource.String.default_file_path), "", Intents.RequestCodeFileBrowseForCreate)
|
||||
Intent i = new Intent(this, typeof (CreateDatabaseActivity));
|
||||
this.AppTask.ToIntent(i);
|
||||
|
||||
i.SetFlags(ActivityFlags.ForwardResult);
|
||||
StartActivity(i);
|
||||
Finish();
|
||||
@@ -177,7 +154,6 @@ namespace keepass2android
|
||||
|
||||
if (savedInstanceState != null)
|
||||
{
|
||||
AppTask = AppTask.CreateFromBundle(savedInstanceState);
|
||||
_recentMode = savedInstanceState.GetBoolean(BundleKeyRecentMode, _recentMode);
|
||||
}
|
||||
|
||||
@@ -202,7 +178,7 @@ namespace keepass2android
|
||||
protected override void OnSaveInstanceState(Bundle outState)
|
||||
{
|
||||
base.OnSaveInstanceState(outState);
|
||||
AppTask.ToBundle(outState);
|
||||
|
||||
outState.PutBoolean(BundleKeyRecentMode, _recentMode);
|
||||
|
||||
}
|
||||
@@ -366,7 +342,7 @@ namespace keepass2android
|
||||
{
|
||||
try
|
||||
{
|
||||
PasswordActivity.Launch(this, ioc, AppTask);
|
||||
PasswordActivity.Launch(this, ioc, new ActivityLaunchModeForward());
|
||||
Finish();
|
||||
} catch (Java.IO.FileNotFoundException)
|
||||
{
|
||||
@@ -379,7 +355,7 @@ namespace keepass2android
|
||||
|
||||
private void AfterQueryCredentials(IOConnectionInfo ioc)
|
||||
{
|
||||
PasswordActivity.Launch(this, ioc, AppTask);
|
||||
PasswordActivity.Launch(this, ioc, new ActivityLaunchModeForward());
|
||||
Finish();
|
||||
}
|
||||
|
||||
@@ -399,11 +375,6 @@ namespace keepass2android
|
||||
{
|
||||
base.OnActivityResult(requestCode, resultCode, data);
|
||||
|
||||
//update app task.
|
||||
//this is important even if we're about to close, because then we should get a NullTask here
|
||||
//in order not to do the same task next time again!
|
||||
AppTask.TryGetFromActivityResult(data, ref AppTask);
|
||||
|
||||
if (resultCode == KeePass.ExitCloseAfterTaskComplete)
|
||||
{
|
||||
//no need to set the result ExitCloseAfterTaskComplete here, there's no parent Activity on the stack
|
||||
|
@@ -173,6 +173,7 @@
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="ActivityLaunchMode.cs" />
|
||||
<Compile Include="ChallengeXCKey.cs" />
|
||||
<Compile Include="EntryActivityClasses\ViewImagePopupItem.cs" />
|
||||
<Compile Include="FileSaveProcessManager.cs" />
|
||||
|
@@ -952,7 +952,7 @@ namespace keepass2android
|
||||
{
|
||||
var key = App.Kp2a.CurrentDb.KpDatabase.MasterKey;
|
||||
App.Kp2a.CloseDatabase(App.Kp2a.CurrentDb);
|
||||
PasswordActivity.Launch(Activity, newIoc, new NullTask(), key);
|
||||
PasswordActivity.Launch(Activity, newIoc, key, new ActivityLaunchModeSimple());
|
||||
|
||||
});
|
||||
builder.Show();
|
||||
@@ -1021,8 +1021,8 @@ namespace keepass2android
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Activity to configure the application and database settings. The database must be unlocked, and this activity will close if it becomes locked.
|
||||
/// </summary>
|
||||
|
@@ -15,6 +15,7 @@ This file is part of Keepass2Android, Copyright 2013 Philipp Crocoll. This file
|
||||
along with Keepass2Android. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Android.Graphics;
|
||||
using Android.OS;
|
||||
using Android.Runtime;
|
||||
@@ -165,6 +166,10 @@ namespace keepass2android.view
|
||||
|
||||
else {
|
||||
String groupDetail = pw.ParentGroup.GetFullPath();
|
||||
if (App.Kp2a.OpenDatabases.Count() > 1)
|
||||
{
|
||||
groupDetail += "(" + App.Kp2a.GetFileStorage(db.Ioc).GetDisplayName(db.Ioc) + ")";
|
||||
}
|
||||
|
||||
var strGroupDetail = new SpannableString (groupDetail);
|
||||
|
||||
|
@@ -130,7 +130,7 @@ namespace keepass2android.view
|
||||
|
||||
|
||||
private void LaunchGroup() {
|
||||
GroupActivity.Launch(_groupBaseActivity, _pwGroup, _groupBaseActivity.AppTask);
|
||||
GroupActivity.Launch(_groupBaseActivity, _pwGroup, _groupBaseActivity.AppTask, new ActivityLaunchModeRequestCode(0));
|
||||
//_groupBaseActivity.OverridePendingTransition(Resource.Animation.anim_enter, Resource.Animation.anim_leave);
|
||||
|
||||
}
|
||||
|
Reference in New Issue
Block a user