mirror of
https://github.com/moparisthebest/keepass2android
synced 2024-11-21 16:55:01 -05:00
Add toolbar to Settings (involves reorganization of Settings into Fragmnt which removes duplicate code in both activities)
This commit is contained in:
parent
15f73257fa
commit
fabe0904c0
Binary file not shown.
After Width: | Height: | Size: 152 B |
Binary file not shown.
After Width: | Height: | Size: 118 B |
Binary file not shown.
After Width: | Height: | Size: 151 B |
Binary file not shown.
After Width: | Height: | Size: 188 B |
Binary file not shown.
After Width: | Height: | Size: 231 B |
15
src/keepass2android/Resources/layout/preference.axml
Normal file
15
src/keepass2android/Resources/layout/preference.axml
Normal file
@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
<include
|
||||
android:id="@+id/toolbar"
|
||||
layout="@layout/toolbar" />
|
||||
<fragment
|
||||
android:name="keepass2android.SettingsFragment"
|
||||
android:id="@+id/settings_fragment"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_below="@id/toolbar" />
|
||||
</RelativeLayout>
|
10
src/keepass2android/Resources/layout/toolbar.axml
Normal file
10
src/keepass2android/Resources/layout/toolbar.axml
Normal file
@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<android.support.v7.widget.Toolbar xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:local="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:minHeight="?attr/actionBarSize"
|
||||
android:background="?attr/colorPrimary"
|
||||
local:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
|
||||
local:popupTheme="@style/ThemeOverlay.AppCompat.Light" />
|
@ -18,11 +18,15 @@
|
||||
along with Keepass2Android. If not, see <http://www.gnu.org/licenses/>.
|
||||
-->
|
||||
<PreferenceScreen
|
||||
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:key="mainprefs">
|
||||
<PreferenceScreen
|
||||
android:key="@string/db_key"
|
||||
android:title="@string/database"
|
||||
android:summary="@string/menu_db_settings">
|
||||
<keepass2android.ToolbarPreference
|
||||
android:key="@string/db_key"
|
||||
android:title="@string/database" />
|
||||
<EditTextPreference
|
||||
android:title="@string/database_name"
|
||||
android:persistent="false"
|
||||
@ -72,11 +76,16 @@
|
||||
android:key="@string/app_key"
|
||||
android:title="@string/application"
|
||||
android:summary="@string/application_settings">
|
||||
|
||||
<keepass2android.ToolbarPreference
|
||||
android:key="@string/app_key"
|
||||
android:title="@string/application" />
|
||||
<PreferenceScreen
|
||||
android:key="@string/security_prefs_key"
|
||||
android:title="@string/security_prefs"
|
||||
>
|
||||
<keepass2android.ToolbarPreference
|
||||
android:key="@string/security_prefs_key"
|
||||
android:title="@string/security_prefs" />
|
||||
|
||||
<ListPreference
|
||||
android:key="@string/clipboard_timeout_key"
|
||||
@ -142,6 +151,9 @@
|
||||
android:key="@string/display_prefs_key"
|
||||
android:title="@string/display_prefs"
|
||||
>
|
||||
<keepass2android.ToolbarPreference
|
||||
android:key="@string/display_prefs_key"
|
||||
android:title="@string/display_prefs" />
|
||||
<CheckBoxPreference
|
||||
android:enabled="true"
|
||||
android:persistent="true"
|
||||
@ -187,15 +199,6 @@
|
||||
android:title="@string/ViewDatabaseSecure_title"
|
||||
android:key="@string/ViewDatabaseSecure_key" />
|
||||
|
||||
|
||||
<ListPreference
|
||||
android:key="@string/design_key"
|
||||
android:title="@string/design_title"
|
||||
android:entries="@array/design_options"
|
||||
android:entryValues="@array/design_values"
|
||||
android:dialogTitle="@string/design_title"
|
||||
android:defaultValue="@string/design_default"/>
|
||||
|
||||
<CheckBoxPreference
|
||||
android:enabled="true"
|
||||
android:persistent="true"
|
||||
@ -209,6 +212,9 @@
|
||||
android:key="@string/password_access_prefs_key"
|
||||
android:title="@string/password_access_prefs"
|
||||
>
|
||||
<keepass2android.ToolbarPreference
|
||||
android:key="@string/password_access_prefs_key"
|
||||
android:title="@string/password_access_prefs" />
|
||||
<CheckBoxPreference
|
||||
android:enabled="true"
|
||||
android:persistent="true"
|
||||
@ -236,8 +242,10 @@
|
||||
android:key="@string/keyboardswitch_prefs_key"
|
||||
android:title="@string/keyboardswitch_prefs"
|
||||
android:dependency="@string/UseKp2aKeyboard_key"
|
||||
|
||||
>
|
||||
<keepass2android.ToolbarPreference
|
||||
android:key="@string/keyboardswitch_prefs_key"
|
||||
android:title="@string/keyboardswitch_prefs"/>
|
||||
<CheckBoxPreference
|
||||
android:key="kp2a_switch_rooted"
|
||||
android:title="@string/kp2a_switch_rooted"
|
||||
@ -289,6 +297,9 @@
|
||||
android:key="@string/QuickUnlock_prefs_key"
|
||||
android:title="@string/QuickUnlock_prefs"
|
||||
>
|
||||
<keepass2android.ToolbarPreference
|
||||
android:key="@string/QuickUnlock_prefs_key"
|
||||
android:title="@string/QuickUnlock_prefs"/>
|
||||
<CheckBoxPreference
|
||||
android:enabled="true"
|
||||
android:persistent="true"
|
||||
@ -323,6 +334,9 @@
|
||||
android:key="@string/FileHandling_prefs_key"
|
||||
android:title="@string/FileHandling_prefs"
|
||||
>
|
||||
<keepass2android.ToolbarPreference
|
||||
android:key="@string/FileHandling_prefs_key"
|
||||
android:title="@string/FileHandling_prefs"/>
|
||||
|
||||
<EditTextPreference
|
||||
android:enabled="true"
|
||||
@ -395,7 +409,10 @@
|
||||
android:key="@string/TrayTotp_prefs_key"
|
||||
android:title="@string/TrayTotp_prefs"
|
||||
>
|
||||
|
||||
<keepass2android.ToolbarPreference
|
||||
android:key="@string/TrayTotp_prefs_key"
|
||||
android:title="@string/TrayTotp_prefs"/>
|
||||
|
||||
<EditTextPreference
|
||||
android:enabled="true"
|
||||
android:persistent="true"
|
||||
|
@ -432,48 +432,19 @@ namespace keepass2android
|
||||
activity.Finish();
|
||||
}
|
||||
|
||||
public static void PrepareNoDonatePreference(Context ctx, Preference preference)
|
||||
{
|
||||
ISharedPreferences prefs = PreferenceManager.GetDefaultSharedPreferences(ctx);
|
||||
public static void PrepareDonateOptionMenu(IMenu menu, Context ctx)
|
||||
{
|
||||
var donateItem = menu.FindItem(Resource.Id.menu_donate);
|
||||
if (donateItem != null)
|
||||
{
|
||||
donateItem.SetVisible(
|
||||
!PreferenceManager.GetDefaultSharedPreferences(ctx)
|
||||
.GetBoolean(ctx.GetString(Resource.String.NoDonateOption_key), false)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
long usageCount = prefs.GetLong(ctx.GetString(Resource.String.UsageCount_key), 0);
|
||||
|
||||
#if DEBUG
|
||||
preference.Enabled = (usageCount > 1);
|
||||
#else
|
||||
preference.Enabled = (usageCount > 50);
|
||||
#endif
|
||||
preference.PreferenceChange += delegate(object sender, Preference.PreferenceChangeEventArgs args)
|
||||
{
|
||||
if ((bool) args.NewValue)
|
||||
{
|
||||
new AlertDialog.Builder(ctx)
|
||||
.SetTitle(ctx.GetString(AppNames.AppNameResource))
|
||||
.SetCancelable(false)
|
||||
.SetPositiveButton(Android.Resource.String.Ok, delegate(object o, DialogClickEventArgs eventArgs)
|
||||
{
|
||||
GotoDonateUrl(ctx);
|
||||
((Dialog) o).Dismiss();
|
||||
})
|
||||
.SetMessage(Resource.String.NoDonateOption_question)
|
||||
.Create().Show();
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
public static void PrepareDonateOptionMenu(IMenu menu, Context ctx)
|
||||
{
|
||||
var donateItem = menu.FindItem(Resource.Id.menu_donate);
|
||||
if (donateItem != null)
|
||||
{
|
||||
donateItem.SetVisible(
|
||||
!PreferenceManager.GetDefaultSharedPreferences(ctx)
|
||||
.GetBoolean(ctx.GetString(Resource.String.NoDonateOption_key), false)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -264,6 +264,12 @@
|
||||
<AndroidResource Include="Resources\layout\EntryEditButtonDelete.axml">
|
||||
<SubType>AndroidResource</SubType>
|
||||
</AndroidResource>
|
||||
<AndroidResource Include="Resources\layout\preference.axml">
|
||||
<SubType>AndroidResource</SubType>
|
||||
</AndroidResource>
|
||||
<AndroidResource Include="Resources\layout\toolbar.axml">
|
||||
<SubType>AndroidResource</SubType>
|
||||
</AndroidResource>
|
||||
<None Include="settings\RoundsPreference %28Kopie%29.cs">
|
||||
<Visible>False</Visible>
|
||||
</None>
|
||||
@ -1310,4 +1316,19 @@
|
||||
<ItemGroup>
|
||||
<AndroidResource Include="Resources\drawable-xhdpi\ic_nav_about.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<AndroidResource Include="Resources\drawable-mhdpi\ic_arrow_back_white_24dp.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<AndroidResource Include="Resources\drawable-hdpi\ic_arrow_back_white_24dp.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<AndroidResource Include="Resources\drawable-xhdpi\ic_arrow_back_white_24dp.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<AndroidResource Include="Resources\drawable-xxhdpi\ic_arrow_back_white_24dp.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<AndroidResource Include="Resources\drawable-xxxhdpi\ic_arrow_back_white_24dp.png" />
|
||||
</ItemGroup>
|
||||
</Project>
|
@ -21,20 +21,70 @@ using Android.App;
|
||||
using Android.Content;
|
||||
using Android.OS;
|
||||
using Android.Preferences;
|
||||
using Android.Runtime;
|
||||
using Android.Util;
|
||||
using Android.Views;
|
||||
using Android.Widget;
|
||||
using keepass2android.Io;
|
||||
using Toolbar = Android.Support.V7.Widget.Toolbar;
|
||||
|
||||
namespace keepass2android
|
||||
{
|
||||
public class ToolbarPreference : Preference
|
||||
{
|
||||
#region constructors
|
||||
protected ToolbarPreference(IntPtr javaReference, JniHandleOwnership transfer) : base(javaReference, transfer)
|
||||
{
|
||||
}
|
||||
|
||||
public ToolbarPreference(Context context) : base(context)
|
||||
{
|
||||
}
|
||||
|
||||
public ToolbarPreference(Context context, IAttributeSet attrs) : base(context, attrs)
|
||||
{
|
||||
}
|
||||
|
||||
public ToolbarPreference(Context context, IAttributeSet attrs, int defStyleAttr) : base(context, attrs, defStyleAttr)
|
||||
{
|
||||
}
|
||||
|
||||
public ToolbarPreference(Context context, IAttributeSet attrs, int defStyleAttr, int defStyleRes) : base(context, attrs, defStyleAttr, defStyleRes)
|
||||
{
|
||||
}
|
||||
#endregion
|
||||
|
||||
protected override View OnCreateView(ViewGroup parent)
|
||||
{
|
||||
parent.SetPadding(0, 0, 0, 0);
|
||||
|
||||
LayoutInflater inflater = (LayoutInflater) Context.GetSystemService(Context.LayoutInflaterService);
|
||||
View layout = inflater.Inflate(Resource.Layout.toolbar, parent, false);
|
||||
|
||||
Toolbar toolbar = (Toolbar) layout.FindViewById<Toolbar>(Resource.Id.toolbar);
|
||||
toolbar.SetNavigationIcon(Resource.Drawable.ic_arrow_back_white_24dp);
|
||||
toolbar.Title = Title;
|
||||
toolbar.NavigationClick += (sender, args) =>
|
||||
{
|
||||
PreferenceScreen prefScreen = (PreferenceScreen) PreferenceManager.FindPreference(Key);
|
||||
if (prefScreen == null)
|
||||
throw new Exception("didn't find preference " + Key);
|
||||
prefScreen.Dialog.Dismiss();
|
||||
};
|
||||
|
||||
return layout;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Activity to configure the application, without database settings. Does not require an unlocked database, or close when the database is locked
|
||||
/// </summary>
|
||||
[Activity(Label = "@string/app_name", Theme = "@style/MyTheme_ActionBar")]
|
||||
public class AppSettingsActivity : LockingPreferenceActivity
|
||||
[Activity(Label = "@string/app_name", Theme = "@style/MyTheme")]
|
||||
public class AppSettingsActivity : LockingActivity
|
||||
{
|
||||
private ActivityDesign _design;
|
||||
private KeyboardSwitchPrefManager _switchPrefManager;
|
||||
|
||||
|
||||
public AppSettingsActivity()
|
||||
{
|
||||
_design = new ActivityDesign(this);
|
||||
@ -47,223 +97,16 @@ namespace keepass2android
|
||||
|
||||
protected override void OnCreate(Bundle savedInstanceState)
|
||||
{
|
||||
_design.ApplyTheme();
|
||||
base.OnCreate(savedInstanceState);
|
||||
|
||||
SetContentView(Resource.Layout.preference);
|
||||
|
||||
SetSupportActionBar(FindViewById<Android.Support.V7.Widget.Toolbar>(Resource.Id.toolbar));
|
||||
|
||||
FragmentManager.FindFragmentById<SettingsFragment>(Resource.Id.settings_fragment).FindPreference(GetString(Resource.String.db_key)).Enabled = false;
|
||||
|
||||
AddPreferencesFromResource(Resource.Xml.preferences);
|
||||
|
||||
FindPreference(GetString(Resource.String.keyfile_key)).PreferenceChange += OnRememberKeyFileHistoryChanged;
|
||||
Preference designPref = FindPreference(GetString(Resource.String.design_key));
|
||||
if (!_design.HasThemes())
|
||||
{
|
||||
try
|
||||
{
|
||||
((PreferenceScreen)FindPreference(GetString(Resource.String.display_prefs_key))).RemovePreference(designPref);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Kp2aLog.Log(ex.ToString());
|
||||
throw;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
designPref.PreferenceChange += (sender, args) => Recreate();
|
||||
}
|
||||
|
||||
Util.PrepareNoDonatePreference(this, FindPreference(GetString(Resource.String.NoDonateOption_key)));
|
||||
|
||||
Preference cachingPreference = FindPreference(GetString(Resource.String.UseOfflineCache_key));
|
||||
cachingPreference.PreferenceChange += OnUseOfflineCacheChanged;
|
||||
|
||||
#if NoNet
|
||||
try
|
||||
{
|
||||
((PreferenceScreen) FindPreference(GetString(Resource.String.FileHandling_prefs_key))).RemovePreference(cachingPreference);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Kp2aLog.Log(ex.ToString());
|
||||
}
|
||||
#endif
|
||||
try
|
||||
{
|
||||
//depending on Android version, we offer to use a transparent icon for QuickUnlock or use the notification priority (since API level 16)
|
||||
Preference hideQuickUnlockTranspIconPref = FindPreference(GetString(Resource.String.QuickUnlockIconHidden_key));
|
||||
Preference hideQuickUnlockIconPref = FindPreference(GetString(Resource.String.QuickUnlockIconHidden16_key));
|
||||
var quickUnlockScreen = ((PreferenceScreen) FindPreference(GetString(Resource.String.QuickUnlock_prefs_key)));
|
||||
if ((int) Android.OS.Build.VERSION.SdkInt >= 16)
|
||||
{
|
||||
quickUnlockScreen.RemovePreference(hideQuickUnlockTranspIconPref);
|
||||
FindPreference(GetString(Resource.String.ShowUnlockedNotification_key)).PreferenceChange += (sender, args) => App.Kp2a.UpdateOngoingNotification();
|
||||
hideQuickUnlockIconPref.PreferenceChange += OnQuickUnlockHiddenChanged;
|
||||
}
|
||||
else
|
||||
{
|
||||
//old version: only show transparent quickUnlock and no option to hide unlocked icon:
|
||||
quickUnlockScreen.RemovePreference(hideQuickUnlockIconPref);
|
||||
FindPreference(GetString(Resource.String.QuickUnlockIconHidden_key)).PreferenceChange +=
|
||||
delegate { App.Kp2a.UpdateOngoingNotification(); };
|
||||
((PreferenceScreen) FindPreference(GetString(Resource.String.display_prefs_key))).RemovePreference(
|
||||
FindPreference(GetString(Resource.String.ShowUnlockedNotification_key)));
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Kp2aLog.Log(ex.ToString());
|
||||
}
|
||||
|
||||
FindPreference(GetString(Resource.String.db_key)).Enabled = false;
|
||||
_switchPrefManager = new KeyboardSwitchPrefManager(this);
|
||||
|
||||
PrepareSeparateNotificationsPreference(this);
|
||||
|
||||
}
|
||||
|
||||
public static void PrepareSeparateNotificationsPreference(PreferenceActivity preferenceActivity)
|
||||
{
|
||||
try
|
||||
{
|
||||
//depending on Android version, we offer to show a combined notification (with action buttons) (since API level 16)
|
||||
Preference separateNotificationsPref = preferenceActivity.FindPreference(preferenceActivity.GetString(Resource.String.ShowSeparateNotifications_key));
|
||||
var passwordAccessScreen = ((PreferenceScreen)preferenceActivity.FindPreference(preferenceActivity.GetString(Resource.String.password_access_prefs_key)));
|
||||
if ((int)Build.VERSION.SdkInt < 16)
|
||||
{
|
||||
passwordAccessScreen.RemovePreference(separateNotificationsPref);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Kp2aLog.Log(ex.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
public class KeyboardSwitchPrefManager
|
||||
{
|
||||
private readonly PreferenceActivity _act;
|
||||
private CheckBoxPreference _switchPref;
|
||||
private CheckBoxPreference _openKp2aAutoPref;
|
||||
private CheckBoxPreference _openOnlyOnSearchPref;
|
||||
private CheckBoxPreference _switchBackPref;
|
||||
private PreferenceScreen _screen;
|
||||
|
||||
public KeyboardSwitchPrefManager(PreferenceActivity act)
|
||||
{
|
||||
this._act = act;
|
||||
|
||||
_switchPref = (CheckBoxPreference)_act.FindPreference("kp2a_switch_rooted");
|
||||
_openKp2aAutoPref =
|
||||
(CheckBoxPreference)act.FindPreference(act.GetString(Resource.String.OpenKp2aKeyboardAutomatically_key));
|
||||
_openOnlyOnSearchPref =
|
||||
(CheckBoxPreference)
|
||||
act.FindPreference(act.GetString(Resource.String.OpenKp2aKeyboardAutomaticallyOnlyAfterSearch_key));
|
||||
_switchBackPref =
|
||||
(CheckBoxPreference)act.FindPreference(act.GetString(Resource.String.AutoSwitchBackKeyboard_key));
|
||||
_screen = (PreferenceScreen)act.FindPreference(act.GetString(Resource.String.keyboardswitch_prefs_key));
|
||||
EnableSwitchPreferences(_switchPref.Checked);
|
||||
|
||||
_switchPref.PreferenceChange += (sender, args) =>
|
||||
{
|
||||
bool switchOnRooted = (bool)args.NewValue;
|
||||
EnableSwitchPreferences(switchOnRooted);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
private void EnableSwitchPreferences(bool switchOnRooted)
|
||||
{
|
||||
if (!switchOnRooted)
|
||||
{
|
||||
if (_act.FindPreference(_act.GetString(Resource.String.OpenKp2aKeyboardAutomatically_key)) == null)
|
||||
{
|
||||
_screen.AddPreference(_openKp2aAutoPref);
|
||||
}
|
||||
if (_act.FindPreference(_act.GetString(Resource.String.OpenKp2aKeyboardAutomaticallyOnlyAfterSearch_key)) != null)
|
||||
{
|
||||
_screen.RemovePreference(_openOnlyOnSearchPref);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_act.FindPreference(_act.GetString(Resource.String.OpenKp2aKeyboardAutomatically_key)) != null)
|
||||
{
|
||||
_screen.RemovePreference(_openKp2aAutoPref);
|
||||
}
|
||||
if (_act.FindPreference(_act.GetString(Resource.String.OpenKp2aKeyboardAutomaticallyOnlyAfterSearch_key)) == null)
|
||||
{
|
||||
_screen.AddPreference(_openOnlyOnSearchPref);
|
||||
}
|
||||
}
|
||||
/*_openKp2aAutoPref.Enabled = !switchOnRooted;
|
||||
|
||||
_openOnlyOnSearchPref.Enabled = switchOnRooted;
|
||||
|
||||
_switchBackPref.Enabled = switchOnRooted;*/
|
||||
}
|
||||
}
|
||||
|
||||
private void OnDesignChange(object sender, Preference.PreferenceChangeEventArgs preferenceChangeEventArgs)
|
||||
{
|
||||
Recreate();
|
||||
}
|
||||
|
||||
private void OnQuickUnlockHiddenChanged(object sender, Preference.PreferenceChangeEventArgs e)
|
||||
{
|
||||
App.Kp2a.UpdateOngoingNotification();
|
||||
}
|
||||
|
||||
private void OnUseOfflineCacheChanged(object sender, Preference.PreferenceChangeEventArgs e)
|
||||
{
|
||||
//ensure the user gets a matching database
|
||||
if (App.Kp2a.GetDb().Loaded && !App.Kp2a.GetDb().Ioc.IsLocalFile())
|
||||
App.Kp2a.LockDatabase(false);
|
||||
|
||||
if (!(bool)e.NewValue)
|
||||
{
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
||||
builder.SetTitle(GetString(Resource.String.ClearOfflineCache_title));
|
||||
|
||||
builder.SetMessage(GetString(Resource.String.ClearOfflineCache_question));
|
||||
|
||||
builder.SetPositiveButton(App.Kp2a.GetResourceString(UiStringKey.yes), (o, args) =>
|
||||
{
|
||||
try
|
||||
{
|
||||
App.Kp2a.ClearOfflineCache();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Kp2aLog.Log(ex.ToString());
|
||||
Toast.MakeText(Application.Context, ex.Message, ToastLength.Long).Show();
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
builder.SetNegativeButton(App.Kp2a.GetResourceString(UiStringKey.no), (o, args) =>
|
||||
{
|
||||
}
|
||||
);
|
||||
builder.SetCancelable(false);
|
||||
Dialog dialog = builder.Create();
|
||||
dialog.Show();
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
internal static void OnRememberKeyFileHistoryChanged(object sender, Preference.PreferenceChangeEventArgs eventArgs)
|
||||
{
|
||||
if (!(bool)eventArgs.NewValue)
|
||||
{
|
||||
App.Kp2a.FileDbHelper.DeleteAllKeys();
|
||||
}
|
||||
}
|
||||
|
||||
internal static void OnShowUnlockedNotificationChanged(object sender, Preference.PreferenceChangeEventArgs eventArgs)
|
||||
{
|
||||
App.Kp2a.UpdateOngoingNotification();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -22,6 +22,7 @@ using Android.Content;
|
||||
using Android.OS;
|
||||
using Android.Widget;
|
||||
using Android.Preferences;
|
||||
using Android.Views;
|
||||
using Java.IO;
|
||||
using KeePassLib.Cryptography.Cipher;
|
||||
using KeePassLib.Keys;
|
||||
@ -32,18 +33,570 @@ using keepass2android.Utils;
|
||||
|
||||
namespace keepass2android
|
||||
{
|
||||
//http://stackoverflow.com/a/27422401/292233
|
||||
public class SettingsFragment : PreferenceFragment
|
||||
{
|
||||
|
||||
public class KeyboardSwitchPrefManager
|
||||
{
|
||||
private readonly Activity _act;
|
||||
private CheckBoxPreference _switchPref;
|
||||
private CheckBoxPreference _openKp2aAutoPref;
|
||||
private CheckBoxPreference _openOnlyOnSearchPref;
|
||||
private CheckBoxPreference _switchBackPref;
|
||||
private PreferenceScreen _screen;
|
||||
private PreferenceFragment _fragment;
|
||||
|
||||
public KeyboardSwitchPrefManager(PreferenceFragment fragment)
|
||||
{
|
||||
var act = fragment.Activity;
|
||||
this._act = act;
|
||||
this._fragment = fragment;
|
||||
|
||||
_switchPref = (CheckBoxPreference)_fragment.FindPreference("kp2a_switch_rooted");
|
||||
_openKp2aAutoPref =
|
||||
(CheckBoxPreference)_fragment.FindPreference(act.GetString(Resource.String.OpenKp2aKeyboardAutomatically_key));
|
||||
_openOnlyOnSearchPref =
|
||||
(CheckBoxPreference)
|
||||
_fragment.FindPreference(act.GetString(Resource.String.OpenKp2aKeyboardAutomaticallyOnlyAfterSearch_key));
|
||||
_switchBackPref =
|
||||
(CheckBoxPreference)_fragment.FindPreference(act.GetString(Resource.String.AutoSwitchBackKeyboard_key));
|
||||
_screen = (PreferenceScreen)_fragment.FindPreference(act.GetString(Resource.String.keyboardswitch_prefs_key));
|
||||
EnableSwitchPreferences(_switchPref.Checked);
|
||||
|
||||
_switchPref.PreferenceChange += (sender, args) =>
|
||||
{
|
||||
bool switchOnRooted = (bool)args.NewValue;
|
||||
EnableSwitchPreferences(switchOnRooted);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
private void EnableSwitchPreferences(bool switchOnRooted)
|
||||
{
|
||||
if (!switchOnRooted)
|
||||
{
|
||||
if (_fragment.FindPreference(_act.GetString(Resource.String.OpenKp2aKeyboardAutomatically_key)) == null)
|
||||
{
|
||||
_screen.AddPreference(_openKp2aAutoPref);
|
||||
}
|
||||
if (_fragment.FindPreference(_act.GetString(Resource.String.OpenKp2aKeyboardAutomaticallyOnlyAfterSearch_key)) != null)
|
||||
{
|
||||
_screen.RemovePreference(_openOnlyOnSearchPref);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
{
|
||||
_screen.RemovePreference(_openKp2aAutoPref);
|
||||
}
|
||||
if (_fragment.FindPreference(_act.GetString(Resource.String.OpenKp2aKeyboardAutomaticallyOnlyAfterSearch_key)) == null)
|
||||
{
|
||||
_screen.AddPreference(_openOnlyOnSearchPref);
|
||||
}
|
||||
}
|
||||
/*_openKp2aAutoPref.Enabled = !switchOnRooted;
|
||||
|
||||
_openOnlyOnSearchPref.Enabled = switchOnRooted;
|
||||
|
||||
_switchBackPref.Enabled = switchOnRooted;*/
|
||||
}
|
||||
}
|
||||
|
||||
private KeyboardSwitchPrefManager _switchPrefManager;
|
||||
|
||||
void OnRememberKeyFileHistoryChanged(object sender, Preference.PreferenceChangeEventArgs eventArgs)
|
||||
{
|
||||
if (!(bool)eventArgs.NewValue)
|
||||
{
|
||||
App.Kp2a.FileDbHelper.DeleteAllKeys();
|
||||
}
|
||||
}
|
||||
|
||||
void OnShowUnlockedNotificationChanged(object sender, Preference.PreferenceChangeEventArgs eventArgs)
|
||||
{
|
||||
App.Kp2a.UpdateOngoingNotification();
|
||||
}
|
||||
|
||||
|
||||
public override void OnCreate(Bundle savedInstanceState)
|
||||
{
|
||||
base.OnCreate(savedInstanceState);
|
||||
AddPreferencesFromResource(Resource.Xml.preferences);
|
||||
|
||||
// Re-use the change handlers for the application settings
|
||||
FindPreference(GetString(Resource.String.keyfile_key)).PreferenceChange += OnRememberKeyFileHistoryChanged;
|
||||
FindPreference(GetString(Resource.String.ShowUnlockedNotification_key)).PreferenceChange += OnShowUnlockedNotificationChanged;
|
||||
PrepareNoDonatePreference(Activity, FindPreference(GetString(Resource.String.NoDonateOption_key)));
|
||||
|
||||
Database db = App.Kp2a.GetDb();
|
||||
if (db.Loaded)
|
||||
{
|
||||
Preference rounds = FindPreference(GetString(Resource.String.rounds_key));
|
||||
rounds.PreferenceChange += (sender, e) => SetRounds(db, e.Preference);
|
||||
rounds.Enabled = db.CanWrite;
|
||||
SetRounds(db, rounds);
|
||||
|
||||
PrepareDefaultUsername(db);
|
||||
PrepareDatabaseName(db);
|
||||
PrepareMasterPassword();
|
||||
|
||||
Preference algorithm = FindPreference(GetString(Resource.String.algorithm_key));
|
||||
SetAlgorithm(db, algorithm);
|
||||
|
||||
UpdateImportDbPref();
|
||||
UpdateImportKeyfilePref();
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
//depending on Android version, we offer to use a transparent icon for QuickUnlock or use the notification priority (since API level 16)
|
||||
Preference hideQuickUnlockTranspIconPref = FindPreference(GetString(Resource.String.QuickUnlockIconHidden_key));
|
||||
Preference hideQuickUnlockIconPref = FindPreference(GetString(Resource.String.QuickUnlockIconHidden16_key));
|
||||
var quickUnlockScreen = ((PreferenceScreen)FindPreference(GetString(Resource.String.QuickUnlock_prefs_key)));
|
||||
if ((int)Android.OS.Build.VERSION.SdkInt >= 16)
|
||||
{
|
||||
quickUnlockScreen.RemovePreference(hideQuickUnlockTranspIconPref);
|
||||
FindPreference(GetString(Resource.String.ShowUnlockedNotification_key)).PreferenceChange += (sender, args) => App.Kp2a.UpdateOngoingNotification();
|
||||
hideQuickUnlockIconPref.PreferenceChange += delegate { App.Kp2a.UpdateOngoingNotification(); };
|
||||
}
|
||||
else
|
||||
{
|
||||
//old version: only show transparent quickUnlock and no option to hide unlocked icon:
|
||||
quickUnlockScreen.RemovePreference(hideQuickUnlockIconPref);
|
||||
FindPreference(GetString(Resource.String.QuickUnlockIconHidden_key)).PreferenceChange +=
|
||||
delegate { App.Kp2a.UpdateOngoingNotification(); };
|
||||
|
||||
((PreferenceScreen)FindPreference(GetString(Resource.String.display_prefs_key))).RemovePreference(
|
||||
FindPreference(GetString(Resource.String.ShowUnlockedNotification_key)));
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Kp2aLog.Log(ex.ToString());
|
||||
}
|
||||
|
||||
|
||||
|
||||
//AppSettingsActivity.PrepareKeyboardSwitchingPreferences(this);
|
||||
_switchPrefManager = new KeyboardSwitchPrefManager(this);
|
||||
PrepareSeparateNotificationsPreference();
|
||||
|
||||
Preference cachingPreference = FindPreference(GetString(Resource.String.UseOfflineCache_key));
|
||||
cachingPreference.PreferenceChange += OnUseOfflineCacheChanged;
|
||||
|
||||
#if NoNet
|
||||
try
|
||||
{
|
||||
((PreferenceScreen) FindPreference(GetString(Resource.String.FileHandling_prefs_key))).RemovePreference(cachingPreference);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Kp2aLog.Log(ex.ToString());
|
||||
}
|
||||
#endif
|
||||
|
||||
try
|
||||
{
|
||||
//depending on Android version, we offer to use a transparent icon for QuickUnlock or use the notification priority (since API level 16)
|
||||
Preference hideQuickUnlockTranspIconPref = FindPreference(GetString(Resource.String.QuickUnlockIconHidden_key));
|
||||
Preference hideQuickUnlockIconPref = FindPreference(GetString(Resource.String.QuickUnlockIconHidden16_key));
|
||||
var quickUnlockScreen = ((PreferenceScreen)FindPreference(GetString(Resource.String.QuickUnlock_prefs_key)));
|
||||
if ((int)Android.OS.Build.VERSION.SdkInt >= 16)
|
||||
{
|
||||
quickUnlockScreen.RemovePreference(hideQuickUnlockTranspIconPref);
|
||||
FindPreference(GetString(Resource.String.ShowUnlockedNotification_key)).PreferenceChange += (sender, args) => App.Kp2a.UpdateOngoingNotification();
|
||||
hideQuickUnlockIconPref.PreferenceChange += OnQuickUnlockHiddenChanged;
|
||||
}
|
||||
else
|
||||
{
|
||||
//old version: only show transparent quickUnlock and no option to hide unlocked icon:
|
||||
quickUnlockScreen.RemovePreference(hideQuickUnlockIconPref);
|
||||
FindPreference(GetString(Resource.String.QuickUnlockIconHidden_key)).PreferenceChange +=
|
||||
delegate { App.Kp2a.UpdateOngoingNotification(); };
|
||||
((PreferenceScreen)FindPreference(GetString(Resource.String.display_prefs_key))).RemovePreference(
|
||||
FindPreference(GetString(Resource.String.ShowUnlockedNotification_key)));
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Kp2aLog.Log(ex.ToString());
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
private void PrepareMasterPassword()
|
||||
{
|
||||
Preference changeMaster = FindPreference(GetString(Resource.String.master_pwd_key));
|
||||
if (App.Kp2a.GetDb().CanWrite)
|
||||
{
|
||||
changeMaster.Enabled = true;
|
||||
changeMaster.PreferenceClick += delegate { new SetPasswordDialog(Activity).Show(); };
|
||||
}
|
||||
}
|
||||
|
||||
private void PrepareDatabaseName(Database db)
|
||||
{
|
||||
Preference databaseName = FindPreference(GetString(Resource.String.database_name_key));
|
||||
if (!db.DatabaseFormat.HasDatabaseName)
|
||||
{
|
||||
((PreferenceScreen) FindPreference(GetString(Resource.String.db_key))).RemovePreference(databaseName);
|
||||
}
|
||||
else
|
||||
{
|
||||
databaseName.Enabled = db.CanWrite;
|
||||
((EditTextPreference) databaseName).EditText.Text = db.KpDatabase.Name;
|
||||
((EditTextPreference) databaseName).Text = db.KpDatabase.Name;
|
||||
databaseName.PreferenceChange += (sender, e) =>
|
||||
{
|
||||
DateTime previousNameChanged = db.KpDatabase.NameChanged;
|
||||
String previousName = db.KpDatabase.Name;
|
||||
db.KpDatabase.Name = e.NewValue.ToString();
|
||||
|
||||
SaveDb save = new SaveDb(Activity, App.Kp2a, new ActionOnFinish((success, message) =>
|
||||
{
|
||||
if (!success)
|
||||
{
|
||||
db.KpDatabase.Name = previousName;
|
||||
db.KpDatabase.NameChanged = previousNameChanged;
|
||||
Toast.MakeText(Activity, message, ToastLength.Long).Show();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Name is reflected in notification, so update it
|
||||
App.Kp2a.UpdateOngoingNotification();
|
||||
}
|
||||
}));
|
||||
ProgressTask pt = new ProgressTask(App.Kp2a, Activity, save);
|
||||
pt.Run();
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private void PrepareDefaultUsername(Database db)
|
||||
{
|
||||
Preference defaultUser = FindPreference(GetString(Resource.String.default_username_key));
|
||||
if (!db.DatabaseFormat.HasDefaultUsername)
|
||||
{
|
||||
((PreferenceScreen) FindPreference(GetString(Resource.String.db_key))).RemovePreference(defaultUser);
|
||||
}
|
||||
else
|
||||
{
|
||||
defaultUser.Enabled = db.CanWrite;
|
||||
((EditTextPreference) defaultUser).EditText.Text = db.KpDatabase.DefaultUserName;
|
||||
((EditTextPreference) defaultUser).Text = db.KpDatabase.DefaultUserName;
|
||||
defaultUser.PreferenceChange += (sender, e) =>
|
||||
{
|
||||
DateTime previousUsernameChanged = db.KpDatabase.DefaultUserNameChanged;
|
||||
String previousUsername = db.KpDatabase.DefaultUserName;
|
||||
db.KpDatabase.DefaultUserName = e.NewValue.ToString();
|
||||
|
||||
SaveDb save = new SaveDb(Activity, App.Kp2a, new ActionOnFinish((success, message) =>
|
||||
{
|
||||
if (!success)
|
||||
{
|
||||
db.KpDatabase.DefaultUserName = previousUsername;
|
||||
db.KpDatabase.DefaultUserNameChanged = previousUsernameChanged;
|
||||
Toast.MakeText(Activity, message, ToastLength.Long).Show();
|
||||
}
|
||||
}));
|
||||
ProgressTask pt = new ProgressTask(App.Kp2a, Activity, save);
|
||||
pt.Run();
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public void PrepareSeparateNotificationsPreference()
|
||||
{
|
||||
try
|
||||
{
|
||||
//depending on Android version, we offer to show a combined notification (with action buttons) (since API level 16)
|
||||
Preference separateNotificationsPref = FindPreference(Activity.GetString(Resource.String.ShowSeparateNotifications_key));
|
||||
var passwordAccessScreen = ((PreferenceScreen)FindPreference(Activity.GetString(Resource.String.password_access_prefs_key)));
|
||||
if ((int)Build.VERSION.SdkInt < 16)
|
||||
{
|
||||
passwordAccessScreen.RemovePreference(separateNotificationsPref);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Kp2aLog.Log(ex.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
private void OnQuickUnlockHiddenChanged(object sender, Preference.PreferenceChangeEventArgs e)
|
||||
{
|
||||
App.Kp2a.UpdateOngoingNotification();
|
||||
}
|
||||
|
||||
private void OnUseOfflineCacheChanged(object sender, Preference.PreferenceChangeEventArgs e)
|
||||
{
|
||||
//ensure the user gets a matching database
|
||||
if (App.Kp2a.GetDb().Loaded && !App.Kp2a.GetDb().Ioc.IsLocalFile())
|
||||
App.Kp2a.LockDatabase(false);
|
||||
|
||||
if (!(bool)e.NewValue)
|
||||
{
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(Activity);
|
||||
builder.SetTitle(GetString(Resource.String.ClearOfflineCache_title));
|
||||
|
||||
builder.SetMessage(GetString(Resource.String.ClearOfflineCache_question));
|
||||
|
||||
builder.SetPositiveButton(App.Kp2a.GetResourceString(UiStringKey.yes), (o, args) =>
|
||||
{
|
||||
try
|
||||
{
|
||||
App.Kp2a.ClearOfflineCache();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Kp2aLog.Log(ex.ToString());
|
||||
Toast.MakeText(Application.Context, ex.Message, ToastLength.Long).Show();
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
builder.SetNegativeButton(App.Kp2a.GetResourceString(UiStringKey.no), (o, args) =>
|
||||
{
|
||||
}
|
||||
);
|
||||
builder.SetCancelable(false);
|
||||
Dialog dialog = builder.Create();
|
||||
dialog.Show();
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateImportKeyfilePref()
|
||||
{
|
||||
var prefs = PreferenceManager.GetDefaultSharedPreferences(Activity);
|
||||
var rememberKeyfile = prefs.GetBoolean(GetString(Resource.String.keyfile_key), Resources.GetBoolean(Resource.Boolean.keyfile_default));
|
||||
|
||||
Preference importDb = FindPreference("import_keyfile_prefs");
|
||||
importDb.Summary = "";
|
||||
|
||||
if (!rememberKeyfile)
|
||||
{
|
||||
importDb.Summary = GetString(Resource.String.KeyfileMoveRequiresRememberKeyfile);
|
||||
importDb.Enabled = false;
|
||||
return;
|
||||
}
|
||||
CompositeKey masterKey = App.Kp2a.GetDb().KpDatabase.MasterKey;
|
||||
if (masterKey.ContainsType(typeof(KcpKeyFile)))
|
||||
{
|
||||
IOConnectionInfo iocKeyfile = ((KcpKeyFile)masterKey.GetUserKey(typeof(KcpKeyFile))).Ioc;
|
||||
if (iocKeyfile.IsLocalFile() && IoUtil.IsInInternalDirectory(iocKeyfile.Path, Activity))
|
||||
{
|
||||
importDb.Enabled = false;
|
||||
importDb.Summary = GetString(Resource.String.FileIsInInternalDirectory);
|
||||
}
|
||||
else
|
||||
{
|
||||
importDb.Enabled = true;
|
||||
importDb.PreferenceClick += (sender, args) => { MoveKeyfileToInternalFolder(); };
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
importDb.Enabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void MoveKeyfileToInternalFolder()
|
||||
{
|
||||
Func<Action> copyAndReturnPostExecute = () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
CompositeKey masterKey = App.Kp2a.GetDb().KpDatabase.MasterKey;
|
||||
var sourceIoc = ((KcpKeyFile)masterKey.GetUserKey(typeof(KcpKeyFile))).Ioc;
|
||||
var newIoc = ImportFileToInternalDirectory(sourceIoc);
|
||||
((KcpKeyFile)masterKey.GetUserKey(typeof(KcpKeyFile))).ResetIoc(newIoc);
|
||||
var keyfileString = IOConnectionInfo.SerializeToString(newIoc);
|
||||
App.Kp2a.StoreOpenedFileAsRecent(App.Kp2a.GetDb().Ioc, keyfileString);
|
||||
return () =>
|
||||
{
|
||||
UpdateImportKeyfilePref();
|
||||
var builder = new AlertDialog.Builder(Activity);
|
||||
builder
|
||||
.SetMessage(Resource.String.KeyfileMoved);
|
||||
builder.SetPositiveButton(Android.Resource.String.Ok, (sender, args) => { });
|
||||
builder.Show();
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
return () =>
|
||||
{
|
||||
Toast.MakeText(Activity, App.Kp2a.GetResourceString(UiStringKey.ErrorOcurred) + " " + e.Message, ToastLength.Long).Show();
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
new SimpleLoadingDialog(Activity, GetString(Resource.String.CopyingFile), false,
|
||||
copyAndReturnPostExecute
|
||||
).Execute();
|
||||
|
||||
}
|
||||
private void UpdateImportDbPref()
|
||||
{
|
||||
//Import db/key file preferences:
|
||||
Preference importDb = FindPreference("import_db_prefs");
|
||||
if (!App.Kp2a.GetDb().Ioc.IsLocalFile())
|
||||
{
|
||||
importDb.Summary = GetString(Resource.String.OnlyAvailableForLocalFiles);
|
||||
importDb.Enabled = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (IoUtil.IsInInternalDirectory(App.Kp2a.GetDb().Ioc.Path, Activity))
|
||||
{
|
||||
importDb.Summary = GetString(Resource.String.FileIsInInternalDirectory);
|
||||
importDb.Enabled = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
importDb.Enabled = true;
|
||||
importDb.PreferenceClick += delegate { MoveDbToInternalFolder(); };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void MoveDbToInternalFolder()
|
||||
{
|
||||
Func<Action> copyAndReturnPostExecute = () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
var sourceIoc = App.Kp2a.GetDb().Ioc;
|
||||
var newIoc = ImportFileToInternalDirectory(sourceIoc);
|
||||
return () =>
|
||||
{
|
||||
var builder = new AlertDialog.Builder(Activity);
|
||||
builder
|
||||
.SetMessage(Resource.String.DatabaseFileMoved);
|
||||
builder.SetPositiveButton(Android.Resource.String.Ok, (sender, args) =>
|
||||
PasswordActivity.Launch(Activity, newIoc, new NullTask()));
|
||||
builder.Show();
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
return () =>
|
||||
{
|
||||
Toast.MakeText(Activity, App.Kp2a.GetResourceString(UiStringKey.ErrorOcurred) + " " + e.Message, ToastLength.Long).Show();
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
new SimpleLoadingDialog(Activity, GetString(Resource.String.CopyingFile), false,
|
||||
copyAndReturnPostExecute
|
||||
).Execute();
|
||||
|
||||
}
|
||||
|
||||
private IOConnectionInfo ImportFileToInternalDirectory(IOConnectionInfo sourceIoc)
|
||||
{
|
||||
string targetPath = UrlUtil.GetFileName(sourceIoc.Path);
|
||||
targetPath = targetPath.Trim("|\\?*<\":>+[]/'".ToCharArray());
|
||||
if (targetPath == "")
|
||||
targetPath = "imported";
|
||||
if (new File(Activity.FilesDir, targetPath).Exists())
|
||||
{
|
||||
int c = 1;
|
||||
var ext = UrlUtil.GetExtension(targetPath);
|
||||
var filenameWithoutExt = UrlUtil.StripExtension(targetPath);
|
||||
do
|
||||
{
|
||||
c++;
|
||||
targetPath = filenameWithoutExt + c;
|
||||
if (!String.IsNullOrEmpty(ext))
|
||||
targetPath += "." + ext;
|
||||
} while (new File(Activity.FilesDir, targetPath).Exists());
|
||||
}
|
||||
var targetIoc = IOConnectionInfo.FromPath(new File(Activity.FilesDir, targetPath).CanonicalPath);
|
||||
|
||||
IoUtil.Copy(targetIoc, sourceIoc, App.Kp2a);
|
||||
return targetIoc;
|
||||
}
|
||||
|
||||
|
||||
private void SetRounds(Database db, Preference rounds)
|
||||
{
|
||||
rounds.Summary = db.KpDatabase.KeyEncryptionRounds.ToString(CultureInfo.InvariantCulture);
|
||||
}
|
||||
|
||||
private void SetAlgorithm(Database db, Preference algorithm)
|
||||
{
|
||||
algorithm.Summary = CipherPool.GlobalPool.GetCipher(db.KpDatabase.DataCipherUuid).DisplayName;
|
||||
}
|
||||
|
||||
public void PrepareNoDonatePreference(Context ctx, Preference preference)
|
||||
{
|
||||
ISharedPreferences prefs = PreferenceManager.GetDefaultSharedPreferences(ctx);
|
||||
|
||||
long usageCount = prefs.GetLong(ctx.GetString(Resource.String.UsageCount_key), 0);
|
||||
|
||||
#if DEBUG
|
||||
preference.Enabled = (usageCount > 1);
|
||||
#else
|
||||
preference.Enabled = (usageCount > 50);
|
||||
#endif
|
||||
preference.PreferenceChange += delegate(object sender, Preference.PreferenceChangeEventArgs args)
|
||||
{
|
||||
if ((bool)args.NewValue)
|
||||
{
|
||||
new AlertDialog.Builder(ctx)
|
||||
.SetTitle(ctx.GetString(AppNames.AppNameResource))
|
||||
.SetCancelable(false)
|
||||
.SetPositiveButton(Android.Resource.String.Ok, delegate(object o, DialogClickEventArgs eventArgs)
|
||||
{
|
||||
Util.GotoDonateUrl(ctx);
|
||||
((Dialog)o).Dismiss();
|
||||
})
|
||||
.SetMessage(Resource.String.NoDonateOption_question)
|
||||
.Create().Show();
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
/// <summary>
|
||||
/// Activity to configure the application and database settings. The database must be unlocked, and this activity will close if it becomes locked.
|
||||
/// </summary>
|
||||
[Activity(Label = "@string/app_name", Theme = "@style/MyTheme_ActionBar")]
|
||||
public class DatabaseSettingsActivity : LockingClosePreferenceActivity
|
||||
[Activity(Label = "@string/app_name", Theme = "@style/MyTheme")]
|
||||
public class DatabaseSettingsActivity : LockCloseActivity
|
||||
{
|
||||
private ActivityDesign _design;
|
||||
private AppSettingsActivity.KeyboardSwitchPrefManager _switchPrefManager;
|
||||
|
||||
public DatabaseSettingsActivity()
|
||||
{
|
||||
_design = new ActivityDesign(this);
|
||||
|
||||
}
|
||||
|
||||
public static void Launch(Activity ctx)
|
||||
@ -51,338 +604,15 @@ namespace keepass2android
|
||||
ctx.StartActivity(new Intent(ctx, typeof(DatabaseSettingsActivity)));
|
||||
}
|
||||
|
||||
protected override void OnCreate(Bundle savedInstanceState)
|
||||
{
|
||||
_design.ApplyTheme();
|
||||
protected override void OnCreate(Bundle savedInstanceState)
|
||||
{
|
||||
base.OnCreate(savedInstanceState);
|
||||
SetContentView(Resource.Layout.preference);
|
||||
|
||||
base.OnCreate(savedInstanceState);
|
||||
|
||||
AddPreferencesFromResource(Resource.Xml.preferences);
|
||||
SetSupportActionBar(FindViewById<Android.Support.V7.Widget.Toolbar>(Resource.Id.toolbar));
|
||||
|
||||
// Re-use the change handlers for the application settings
|
||||
FindPreference(GetString(Resource.String.keyfile_key)).PreferenceChange += AppSettingsActivity.OnRememberKeyFileHistoryChanged;
|
||||
FindPreference(GetString(Resource.String.ShowUnlockedNotification_key)).PreferenceChange += AppSettingsActivity.OnShowUnlockedNotificationChanged;
|
||||
Util.PrepareNoDonatePreference(this, FindPreference(GetString(Resource.String.NoDonateOption_key)));
|
||||
Preference designPref = FindPreference(GetString(Resource.String.design_key));
|
||||
if (!_design.HasThemes())
|
||||
{
|
||||
try
|
||||
{
|
||||
((PreferenceScreen)FindPreference(GetString(Resource.String.display_prefs_key))).RemovePreference(designPref);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Kp2aLog.Log(ex.ToString());
|
||||
throw;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
designPref.PreferenceChange += (sender, args) => Recreate();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Database db = App.Kp2a.GetDb();
|
||||
|
||||
Preference rounds = FindPreference(GetString(Resource.String.rounds_key));
|
||||
rounds.PreferenceChange += (sender, e) => SetRounds(db, e.Preference);
|
||||
rounds.Enabled = db.CanWrite;
|
||||
|
||||
Preference defaultUser = FindPreference(GetString(Resource.String.default_username_key));
|
||||
if (!db.DatabaseFormat.HasDefaultUsername)
|
||||
{
|
||||
((PreferenceScreen) FindPreference(GetString(Resource.String.db_key))).RemovePreference(defaultUser);
|
||||
}
|
||||
else
|
||||
{
|
||||
defaultUser.Enabled = db.CanWrite;
|
||||
((EditTextPreference)defaultUser).EditText.Text = db.KpDatabase.DefaultUserName;
|
||||
((EditTextPreference)defaultUser).Text = db.KpDatabase.DefaultUserName;
|
||||
defaultUser.PreferenceChange += (sender, e) =>
|
||||
{
|
||||
DateTime previousUsernameChanged = db.KpDatabase.DefaultUserNameChanged;
|
||||
String previousUsername = db.KpDatabase.DefaultUserName;
|
||||
db.KpDatabase.DefaultUserName = e.NewValue.ToString();
|
||||
|
||||
SaveDb save = new SaveDb(this, App.Kp2a, new ActionOnFinish((success, message) =>
|
||||
{
|
||||
if (!success)
|
||||
{
|
||||
db.KpDatabase.DefaultUserName = previousUsername;
|
||||
db.KpDatabase.DefaultUserNameChanged = previousUsernameChanged;
|
||||
Toast.MakeText(this, message, ToastLength.Long).Show();
|
||||
}
|
||||
}));
|
||||
ProgressTask pt = new ProgressTask(App.Kp2a, this, save);
|
||||
pt.Run();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
Preference databaseName = FindPreference(GetString(Resource.String.database_name_key));
|
||||
if (!db.DatabaseFormat.HasDatabaseName)
|
||||
{
|
||||
((PreferenceScreen) FindPreference(GetString(Resource.String.db_key))).RemovePreference(databaseName);
|
||||
}
|
||||
else
|
||||
{
|
||||
databaseName.Enabled = db.CanWrite;
|
||||
((EditTextPreference) databaseName).EditText.Text = db.KpDatabase.Name;
|
||||
((EditTextPreference) databaseName).Text = db.KpDatabase.Name;
|
||||
databaseName.PreferenceChange += (sender, e) =>
|
||||
{
|
||||
DateTime previousNameChanged = db.KpDatabase.NameChanged;
|
||||
String previousName = db.KpDatabase.Name;
|
||||
db.KpDatabase.Name = e.NewValue.ToString();
|
||||
|
||||
SaveDb save = new SaveDb(this, App.Kp2a, new ActionOnFinish((success, message) =>
|
||||
{
|
||||
if (!success)
|
||||
{
|
||||
db.KpDatabase.Name = previousName;
|
||||
db.KpDatabase.NameChanged = previousNameChanged;
|
||||
Toast.MakeText(this, message, ToastLength.Long).Show();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Name is reflected in notification, so update it
|
||||
App.Kp2a.UpdateOngoingNotification();
|
||||
}
|
||||
}));
|
||||
ProgressTask pt = new ProgressTask(App.Kp2a, this, save);
|
||||
pt.Run();
|
||||
};
|
||||
}
|
||||
Preference changeMaster = FindPreference(GetString(Resource.String.master_pwd_key));
|
||||
if (App.Kp2a.GetDb().CanWrite)
|
||||
{
|
||||
changeMaster.Enabled = true;
|
||||
changeMaster.PreferenceClick += delegate {
|
||||
new SetPasswordDialog(this).Show();
|
||||
};
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
//depending on Android version, we offer to use a transparent icon for QuickUnlock or use the notification priority (since API level 16)
|
||||
Preference hideQuickUnlockTranspIconPref = FindPreference(GetString(Resource.String.QuickUnlockIconHidden_key));
|
||||
Preference hideQuickUnlockIconPref = FindPreference(GetString(Resource.String.QuickUnlockIconHidden16_key));
|
||||
var quickUnlockScreen = ((PreferenceScreen)FindPreference(GetString(Resource.String.QuickUnlock_prefs_key)));
|
||||
if ((int)Android.OS.Build.VERSION.SdkInt >= 16)
|
||||
{
|
||||
quickUnlockScreen.RemovePreference(hideQuickUnlockTranspIconPref);
|
||||
FindPreference(GetString(Resource.String.ShowUnlockedNotification_key)).PreferenceChange += (sender, args) => App.Kp2a.UpdateOngoingNotification();
|
||||
hideQuickUnlockIconPref.PreferenceChange += delegate { App.Kp2a.UpdateOngoingNotification(); };
|
||||
}
|
||||
else
|
||||
{
|
||||
//old version: only show transparent quickUnlock and no option to hide unlocked icon:
|
||||
quickUnlockScreen.RemovePreference(hideQuickUnlockIconPref);
|
||||
FindPreference(GetString(Resource.String.QuickUnlockIconHidden_key)).PreferenceChange +=
|
||||
delegate { App.Kp2a.UpdateOngoingNotification(); };
|
||||
|
||||
((PreferenceScreen)FindPreference(GetString(Resource.String.display_prefs_key))).RemovePreference(
|
||||
FindPreference(GetString(Resource.String.ShowUnlockedNotification_key)));
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Kp2aLog.Log(ex.ToString());
|
||||
}
|
||||
|
||||
SetRounds(db, rounds);
|
||||
|
||||
Preference algorithm = FindPreference(GetString(Resource.String.algorithm_key));
|
||||
SetAlgorithm(db, algorithm);
|
||||
|
||||
UpdateImportDbPref();
|
||||
UpdateImportKeyfilePref();
|
||||
//AppSettingsActivity.PrepareKeyboardSwitchingPreferences(this);
|
||||
_switchPrefManager = new AppSettingsActivity.KeyboardSwitchPrefManager(this);
|
||||
AppSettingsActivity.PrepareSeparateNotificationsPreference(this);
|
||||
}
|
||||
|
||||
private void UpdateImportKeyfilePref()
|
||||
{
|
||||
var prefs = PreferenceManager.GetDefaultSharedPreferences(this);
|
||||
var rememberKeyfile = prefs.GetBoolean(GetString(Resource.String.keyfile_key), Resources.GetBoolean(Resource.Boolean.keyfile_default));
|
||||
|
||||
Preference importDb = FindPreference("import_keyfile_prefs");
|
||||
importDb.Summary = "";
|
||||
|
||||
if (!rememberKeyfile)
|
||||
{
|
||||
importDb.Summary = GetString(Resource.String.KeyfileMoveRequiresRememberKeyfile);
|
||||
importDb.Enabled = false;
|
||||
return;
|
||||
}
|
||||
CompositeKey masterKey = App.Kp2a.GetDb().KpDatabase.MasterKey;
|
||||
if (masterKey.ContainsType(typeof (KcpKeyFile)))
|
||||
{
|
||||
IOConnectionInfo iocKeyfile = ((KcpKeyFile)masterKey.GetUserKey(typeof (KcpKeyFile))).Ioc;
|
||||
if (iocKeyfile.IsLocalFile() && IoUtil.IsInInternalDirectory(iocKeyfile.Path, this))
|
||||
{
|
||||
importDb.Enabled = false;
|
||||
importDb.Summary = GetString(Resource.String.FileIsInInternalDirectory);
|
||||
}
|
||||
else
|
||||
{
|
||||
importDb.Enabled = true;
|
||||
importDb.PreferenceClick += (sender, args) => { MoveKeyfileToInternalFolder();};
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
importDb.Enabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void MoveKeyfileToInternalFolder()
|
||||
{
|
||||
Func<Action> copyAndReturnPostExecute = () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
CompositeKey masterKey = App.Kp2a.GetDb().KpDatabase.MasterKey;
|
||||
var sourceIoc = ((KcpKeyFile)masterKey.GetUserKey(typeof(KcpKeyFile))).Ioc;
|
||||
var newIoc = ImportFileToInternalDirectory(sourceIoc);
|
||||
((KcpKeyFile)masterKey.GetUserKey(typeof(KcpKeyFile))).ResetIoc(newIoc);
|
||||
var keyfileString = IOConnectionInfo.SerializeToString(newIoc);
|
||||
App.Kp2a.StoreOpenedFileAsRecent(App.Kp2a.GetDb().Ioc, keyfileString);
|
||||
return () =>
|
||||
{
|
||||
UpdateImportKeyfilePref();
|
||||
var builder = new AlertDialog.Builder(this);
|
||||
builder
|
||||
.SetMessage(Resource.String.KeyfileMoved);
|
||||
builder.SetPositiveButton(Android.Resource.String.Ok, (sender, args) => { });
|
||||
builder.Show();
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
return () =>
|
||||
{
|
||||
Toast.MakeText(this, App.Kp2a.GetResourceString(UiStringKey.ErrorOcurred) + " " + e.Message, ToastLength.Long).Show();
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
new SimpleLoadingDialog(this, GetString(Resource.String.CopyingFile), false,
|
||||
copyAndReturnPostExecute
|
||||
).Execute();
|
||||
|
||||
}
|
||||
private void UpdateImportDbPref()
|
||||
{
|
||||
//Import db/key file preferences:
|
||||
Preference importDb = FindPreference("import_db_prefs");
|
||||
if (!App.Kp2a.GetDb().Ioc.IsLocalFile())
|
||||
{
|
||||
importDb.Summary = GetString(Resource.String.OnlyAvailableForLocalFiles);
|
||||
importDb.Enabled = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (IoUtil.IsInInternalDirectory(App.Kp2a.GetDb().Ioc.Path, this))
|
||||
{
|
||||
importDb.Summary = GetString(Resource.String.FileIsInInternalDirectory);
|
||||
importDb.Enabled = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
importDb.Enabled = true;
|
||||
importDb.PreferenceClick += delegate { MoveDbToInternalFolder(); };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void MoveDbToInternalFolder()
|
||||
{
|
||||
Func<Action> copyAndReturnPostExecute = () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
var sourceIoc = App.Kp2a.GetDb().Ioc;
|
||||
var newIoc = ImportFileToInternalDirectory(sourceIoc);
|
||||
return () =>
|
||||
{
|
||||
var builder = new AlertDialog.Builder(this);
|
||||
builder
|
||||
.SetMessage(Resource.String.DatabaseFileMoved);
|
||||
builder.SetPositiveButton(Android.Resource.String.Ok, (sender, args) =>
|
||||
PasswordActivity.Launch(this, newIoc, new NullTask()));
|
||||
builder.Show();
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
return () =>
|
||||
{
|
||||
Toast.MakeText(this, App.Kp2a.GetResourceString(UiStringKey.ErrorOcurred) + " " + e.Message, ToastLength.Long).Show();
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
new SimpleLoadingDialog(this, GetString(Resource.String.CopyingFile), false,
|
||||
copyAndReturnPostExecute
|
||||
).Execute();
|
||||
|
||||
}
|
||||
|
||||
private IOConnectionInfo ImportFileToInternalDirectory(IOConnectionInfo sourceIoc)
|
||||
{
|
||||
string targetPath = UrlUtil.GetFileName(sourceIoc.Path);
|
||||
targetPath = targetPath.Trim("|\\?*<\":>+[]/'".ToCharArray());
|
||||
if (targetPath == "")
|
||||
targetPath = "imported";
|
||||
if (new File(FilesDir, targetPath).Exists())
|
||||
{
|
||||
int c = 1;
|
||||
var ext = UrlUtil.GetExtension(targetPath);
|
||||
var filenameWithoutExt = UrlUtil.StripExtension(targetPath);
|
||||
do
|
||||
{
|
||||
c++;
|
||||
targetPath = filenameWithoutExt + c;
|
||||
if (!String.IsNullOrEmpty(ext))
|
||||
targetPath += "." + ext;
|
||||
} while (new File(FilesDir, targetPath).Exists());
|
||||
}
|
||||
var targetIoc = IOConnectionInfo.FromPath(new File(FilesDir, targetPath).CanonicalPath);
|
||||
|
||||
IoUtil.Copy(targetIoc, sourceIoc, App.Kp2a);
|
||||
return targetIoc;
|
||||
}
|
||||
|
||||
private void SetRounds(Database db, Preference rounds)
|
||||
{
|
||||
rounds.Summary = db.KpDatabase.KeyEncryptionRounds.ToString(CultureInfo.InvariantCulture);
|
||||
}
|
||||
|
||||
private void SetAlgorithm(Database db, Preference algorithm)
|
||||
{
|
||||
algorithm.Summary = CipherPool.GlobalPool.GetCipher(db.KpDatabase.DataCipherUuid).DisplayName;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user