refactoring: interface IAppTask -> abstract class AppTask (allows to implement empty default behaviour in base class, removal of static helper class)

preparations for new task (select entry then close)
This commit is contained in:
Philipp Crocoll 2013-05-30 08:29:08 +02:00
parent f080f13b20
commit bf139d9059
8 changed files with 161 additions and 146 deletions

View File

@ -50,7 +50,7 @@ namespace keepass2android
public const String KEY_CLOSE_AFTER_CREATE = "close_after_create"; public const String KEY_CLOSE_AFTER_CREATE = "close_after_create";
public static void Launch(Activity act, PwEntry pw, int pos, IAppTask appTask) { public static void Launch(Activity act, PwEntry pw, int pos, AppTask appTask) {
Intent i; Intent i;
i = new Intent(act, typeof(EntryActivity)); i = new Intent(act, typeof(EntryActivity));
@ -69,7 +69,7 @@ namespace keepass2android
private bool mShowPassword; private bool mShowPassword;
private int mPos; private int mPos;
IAppTask mAppTask; AppTask mAppTask;
protected void setEntryView() { protected void setEntryView() {

View File

@ -74,6 +74,8 @@ namespace keepass2android
bool mCloseForReload; bool mCloseForReload;
AppTask mAppTask;
protected override void OnCreate(Bundle savedInstanceState) protected override void OnCreate(Bundle savedInstanceState)
{ {
base.OnCreate(savedInstanceState); base.OnCreate(savedInstanceState);
@ -86,6 +88,8 @@ namespace keepass2android
return; return;
} }
mAppTask = AppTask.GetTaskInOnCreate(savedInstanceState, Intent);
SetContentView(Resource.Layout.entry_edit); SetContentView(Resource.Layout.entry_edit);
mCloseForReload = false; mCloseForReload = false;
@ -234,9 +238,7 @@ namespace keepass2android
} }
save.Click += (object sender, EventArgs e) => save.Click += (object sender, EventArgs e) =>
{ {
OnFinish onFinish = new AfterSave(new Handler(), this); SaveEntry();
SaveEntry(onFinish);
}; };
@ -284,7 +286,7 @@ namespace keepass2android
} }
void SaveEntry(OnFinish onFinish) void SaveEntry()
{ {
Database db = App.getDB(); Database db = App.getDB();
EntryEditActivity act = this; EntryEditActivity act = this;
@ -359,8 +361,6 @@ namespace keepass2android
newEntry.MaintainBackups(db.pm); newEntry.MaintainBackups(db.pm);
//if ( newEntry.Strings.ReadSafe (PwDefs.TitleField).Equals(State.mEntry.Strings.ReadSafe (PwDefs.TitleField)) ) { //if ( newEntry.Strings.ReadSafe (PwDefs.TitleField).Equals(State.mEntry.Strings.ReadSafe (PwDefs.TitleField)) ) {
// SetResult(KeePass.EXIT_REFRESH); // SetResult(KeePass.EXIT_REFRESH);
//} else { //} else {
@ -368,15 +368,30 @@ namespace keepass2android
SetResult(KeePass.EXIT_REFRESH_TITLE); SetResult(KeePass.EXIT_REFRESH_TITLE);
//} //}
RunnableOnFinish task; RunnableOnFinish runnable;
ActionOnFinish closeOrShowError = new ActionOnFinish((success, message) => {
if (success)
{
Finish();
} else
{
OnFinish.displayMessage(this, message);
}
});
ActionOnFinish afterAddEntry = new ActionOnFinish((success, message) =>
{
if (success)
mAppTask.AfterAddNewEntry(this);
},closeOrShowError);
if ( State.mIsNew ) { if ( State.mIsNew ) {
task = AddEntry.getInstance(this, App.getDB(), newEntry, State.parentGroup, onFinish); runnable = AddEntry.getInstance(this, App.getDB(), newEntry, State.parentGroup, afterAddEntry);
} else { } else {
task = new UpdateEntry(this, App.getDB(), initialEntry, newEntry, onFinish); runnable = new UpdateEntry(this, App.getDB(), initialEntry, newEntry, closeOrShowError);
} }
ProgressTask pt = new ProgressTask(act, task, Resource.String.saving_database); ProgressTask pt = new ProgressTask(act, runnable, Resource.String.saving_database);
pt.run(); pt.run();
@ -535,6 +550,12 @@ namespace keepass2android
populateBinaries(); populateBinaries();
} }
protected override void OnSaveInstanceState(Bundle outState)
{
base.OnSaveInstanceState(outState);
mAppTask.ToBundle(outState);
}
public override void OnBackPressed() public override void OnBackPressed()
{ {
if (State.mEntryModified == false) if (State.mEntryModified == false)
@ -901,22 +922,6 @@ namespace keepass2android
} }
private class AfterSave : OnFinish {
Activity act;
public AfterSave(Handler handler, Activity act): base(handler) {
this.act = act;
}
public override void run() {
if ( mSuccess ) {
act.Finish();
} else {
displayMessage(act);
}
}
}
} }

View File

@ -45,11 +45,11 @@ namespace keepass2android
private const String TAG = "Group Activity:"; private const String TAG = "Group Activity:";
public static void Launch(Activity act, IAppTask appTask) { public static void Launch(Activity act, AppTask appTask) {
Launch(act, null, appTask); Launch(act, null, appTask);
} }
public static void Launch (Activity act, PwGroup g, IAppTask appTask) public static void Launch (Activity act, PwGroup g, AppTask appTask)
{ {
Intent i; Intent i;

View File

@ -63,7 +63,7 @@ namespace keepass2android
protected PwGroup mGroup; protected PwGroup mGroup;
internal IAppTask mAppTask; internal AppTask mAppTask;
protected override void OnResume() { protected override void OnResume() {
base.OnResume(); base.OnResume();

View File

@ -87,7 +87,7 @@ namespace keepass2android
ioc.CredSaveMode = (IOCredSaveMode)i.GetIntExtra(KEY_SERVERCREDMODE, (int) IOCredSaveMode.NoSave); ioc.CredSaveMode = (IOCredSaveMode)i.GetIntExtra(KEY_SERVERCREDMODE, (int) IOCredSaveMode.NoSave);
} }
public static void Launch(Activity act, String fileName, IAppTask appTask) { public static void Launch(Activity act, String fileName, AppTask appTask) {
Java.IO.File dbFile = new Java.IO.File(fileName); Java.IO.File dbFile = new Java.IO.File(fileName);
if ( ! dbFile.Exists() ) { if ( ! dbFile.Exists() ) {
throw new Java.IO.FileNotFoundException(); throw new Java.IO.FileNotFoundException();
@ -108,7 +108,7 @@ namespace keepass2android
} }
public static void Launch(Activity act, IOConnectionInfo ioc, IAppTask appTask) public static void Launch(Activity act, IOConnectionInfo ioc, AppTask appTask)
{ {
if (ioc.IsLocalFile()) if (ioc.IsLocalFile())
{ {
@ -279,7 +279,7 @@ namespace keepass2android
} }
internal IAppTask mAppTask; internal AppTask mAppTask;
protected override void OnCreate(Bundle savedInstanceState) protected override void OnCreate(Bundle savedInstanceState)
{ {

View File

@ -62,131 +62,48 @@ namespace keepass2android
} }
/// <summary> /// <summary>
/// interface for "tasks": this are things the user wants to do and which require several activities /// base class for "tasks": this are things the user wants to do and which require several activities
/// </summary> /// </summary>
public interface IAppTask public abstract class AppTask
{ {
/// <summary> /// <summary>
/// Loads the parameters of the task from the given bundle /// Loads the parameters of the task from the given bundle
/// </summary> /// </summary>
void Setup(Bundle b); public virtual void Setup(Bundle b)
{}
/// <summary> /// <summary>
/// Returns the parameters of the task for storage in a bundle or intent /// Returns the parameters of the task for storage in a bundle or intent
/// </summary> /// </summary>
/// <value>The extras.</value> /// <value>The extras.</value>
IEnumerable<IExtra> Extras { get;} public virtual IEnumerable<IExtra> Extras {
void AfterUnlockDatabase(PasswordActivity act);
bool CloseEntryActivityAfterCreate
{
get;
}
}
/// <summary>
/// Implementation of IAppTask for "no task currently active" (Null pattern)
/// </summary>
public class NullTask: IAppTask
{
public void Setup(Bundle b)
{
}
public IEnumerable<IExtra> Extras
{
get get
{ {
yield break; yield break;
} }
} }
public virtual void AfterUnlockDatabase(PasswordActivity act)
public void AfterUnlockDatabase(PasswordActivity act)
{ {
GroupActivity.Launch(act, this); GroupActivity.Launch(act, this);
} }
public bool CloseEntryActivityAfterCreate
public virtual void AfterAddNewEntry(EntryEditActivity entryEditActivity)
{
}
public virtual bool CloseEntryActivityAfterCreate
{ {
get { return false;} get { return false;}
} }
}
/// <summary>
/// User is about to search an entry for a given URL
/// </summary>
public class SearchUrlTask: IAppTask
{
public const String UrlToSearch_key = "UrlToSearch";
public string UrlToSearchFor
{
get;
set;
}
public void Setup(Bundle b)
{
UrlToSearchFor = b.GetString(UrlToSearch_key);
}
public IEnumerable<IExtra> Extras
{
get
{
yield return new StringExtra() { Key=UrlToSearch_key, Value = UrlToSearchFor };
}
}
public void AfterUnlockDatabase(PasswordActivity act)
{
ShareUrlResults.Launch(act, this);
}
public bool CloseEntryActivityAfterCreate
{
get { return true;}
}
}
/// <summary>
/// User is about to select an entry for use in another app
/// </summary>
public class SelectEntryTask: IAppTask
{
public void Setup(Bundle b)
{
}
public IEnumerable<IExtra> Extras
{
get
{
yield break;
}
}
public void AfterUnlockDatabase(PasswordActivity act)
{
GroupActivity.Launch(act, this);
}
public bool CloseEntryActivityAfterCreate
{
//keypoint here: close the app after selecting the entry
get { return true;}
}
}
/// <summary>
///
/// </summary>
public static class AppTask
{
public const String AppTask_key = "KP2A_APPTASK"; public const String AppTask_key = "KP2A_APPTASK";
/// <summary> /// <summary>
/// Should be used in OnCreate to (re)create a task /// Should be used in OnCreate to (re)create a task
/// if savedInstanceState is not null, the task is recreated from there. Otherwise it's taken from the intent. /// if savedInstanceState is not null, the task is recreated from there. Otherwise it's taken from the intent.
/// </summary> /// </summary>
public static IAppTask GetTaskInOnCreate(Bundle savedInstanceState, Intent intent) public static AppTask GetTaskInOnCreate(Bundle savedInstanceState, Intent intent)
{ {
if (savedInstanceState != null) if (savedInstanceState != null)
{ {
@ -198,12 +115,12 @@ namespace keepass2android
} }
} }
public static IAppTask CreateFromIntent(Intent i) public static AppTask CreateFromIntent(Intent i)
{ {
return CreateFromBundle(i.Extras); return CreateFromBundle(i.Extras);
} }
public static IAppTask CreateFromBundle(Bundle b) public static AppTask CreateFromBundle(Bundle b)
{ {
if (b == null) if (b == null)
return new NullTask(); return new NullTask();
@ -219,7 +136,7 @@ namespace keepass2android
{ {
if (taskType == type.Name) if (taskType == type.Name)
{ {
IAppTask task = (IAppTask)Activator.CreateInstance(type); AppTask task = (AppTask)Activator.CreateInstance(type);
task.Setup(b); task.Setup(b);
return task; return task;
} }
@ -231,11 +148,11 @@ namespace keepass2android
/// <summary> /// <summary>
/// Adds the extras of the task to the intent /// Adds the extras of the task to the intent
/// </summary> /// </summary>
public static void ToIntent(this IAppTask task, Intent intent) public void ToIntent(Intent intent)
{ {
AppTask.GetTypeExtra(task.GetType()).ToIntent(intent); AppTask.GetTypeExtra(GetType()).ToIntent(intent);
foreach (IExtra extra in task.Extras) foreach (IExtra extra in Extras)
{ {
extra.ToIntent(intent); extra.ToIntent(intent);
} }
@ -244,11 +161,11 @@ namespace keepass2android
/// <summary> /// <summary>
/// Adds the extras of the task to the bundle /// Adds the extras of the task to the bundle
/// </summary> /// </summary>
public static void ToBundle(this IAppTask task, Bundle bundle) public void ToBundle(Bundle bundle)
{ {
AppTask.GetTypeExtra(task.GetType()).ToBundle(bundle); AppTask.GetTypeExtra(GetType()).ToBundle(bundle);
foreach (IExtra extra in task.Extras) foreach (IExtra extra in Extras)
{ {
extra.ToBundle(bundle); extra.ToBundle(bundle);
} }
@ -264,5 +181,94 @@ namespace keepass2android
} }
} }
/// <summary>
/// Implementation of AppTask for "no task currently active" (Null pattern)
/// </summary>
public class NullTask: AppTask
{
}
/// <summary>
/// User is about to search an entry for a given URL
/// </summary>
public class SearchUrlTask: AppTask
{
public const String UrlToSearch_key = "UrlToSearch";
public string UrlToSearchFor
{
get;
set;
}
public override void Setup(Bundle b)
{
UrlToSearchFor = b.GetString(UrlToSearch_key);
}
public override IEnumerable<IExtra> Extras
{
get
{
yield return new StringExtra() { Key=UrlToSearch_key, Value = UrlToSearchFor };
}
}
public override void AfterUnlockDatabase(PasswordActivity act)
{
ShareUrlResults.Launch(act, this);
}
public override bool CloseEntryActivityAfterCreate
{
get { return true;}
}
}
/// <summary>
/// User is about to select an entry for use in another app
/// </summary>
public class SelectEntryTask: AppTask
{
public override bool CloseEntryActivityAfterCreate
{
//keypoint here: close the app after selecting the entry
get { return true;}
}
}
/// <summary>
/// User is about to create a new entry. The task might already "know" some information about the contents.
/// </summary>
public class CreateEntryThenCloseTask: AppTask
{
public const String Url_key = "CreateEntry_Url";
public string Url
{
get;
set;
}
public override void Setup(Bundle b)
{
Url = b.GetString(Url_key);
}
public override IEnumerable<IExtra> Extras
{
get
{
yield return new StringExtra() { Key = Url_key, Value = Url };
yield break;
}
}
public override bool CloseEntryActivityAfterCreate
{
//if the user selects an entry before creating the new one, we're not closing the app
get { return false;}
}
}
} }

View File

@ -78,11 +78,15 @@ namespace keepass2android
} }
protected void displayMessage(Context ctx) { protected void displayMessage(Context ctx) {
if ( mMessage != null && mMessage.Length > 0 ) { displayMessage(ctx, mMessage);
Toast.MakeText(ctx, mMessage, ToastLength.Long).Show(); }
}
} public static void displayMessage(Context ctx, string message)
{
if ( !String.IsNullOrEmpty(message) ) {
Toast.MakeText(ctx, message, ToastLength.Long).Show();
}
}
} }
} }

View File

@ -64,7 +64,7 @@ namespace keepass2android
view.FileSelectButtons fileSelectButtons; view.FileSelectButtons fileSelectButtons;
bool createdWithActivityResult = false; bool createdWithActivityResult = false;
internal IAppTask mAppTask; internal AppTask mAppTask;
IOConnectionInfo loadIoc(string defaultFileName) IOConnectionInfo loadIoc(string defaultFileName)
{ {