mirror of
https://github.com/moparisthebest/keepass2android
synced 2024-11-25 10:42:17 -05:00
Drastically improved UI for creating a new database (own activity, file browser for key files, explanation texts, password generator, show password button)
Added DejaVuSansMono.ttf for password display in EntryActivity
This commit is contained in:
parent
2f3bbff841
commit
c81ca4268e
@ -30,6 +30,7 @@ namespace keepass2android
|
||||
private readonly bool _dontSave;
|
||||
private readonly Context _ctx;
|
||||
private readonly IKp2aApp _app;
|
||||
private CompositeKey _key;
|
||||
|
||||
public CreateDb(IKp2aApp app, Context ctx, IOConnectionInfo ioc, OnFinish finish, bool dontSave): base(finish) {
|
||||
_ctx = ctx;
|
||||
@ -38,16 +39,29 @@ namespace keepass2android
|
||||
_app = app;
|
||||
}
|
||||
|
||||
public CreateDb(IKp2aApp app, Context ctx, IOConnectionInfo ioc, OnFinish finish, bool dontSave, CompositeKey key)
|
||||
: base(finish)
|
||||
{
|
||||
_ctx = ctx;
|
||||
_ioc = ioc;
|
||||
_dontSave = dontSave;
|
||||
_app = app;
|
||||
_key = key;
|
||||
}
|
||||
|
||||
|
||||
public override void Run() {
|
||||
StatusLogger.UpdateMessage(UiStringKey.progress_create);
|
||||
Database db = _app.CreateNewDatabase();
|
||||
|
||||
db.KpDatabase = new KeePassLib.PwDatabase();
|
||||
//Key will be changed/created immediately after creation:
|
||||
CompositeKey tempKey = new CompositeKey();
|
||||
db.KpDatabase.New(_ioc, tempKey);
|
||||
|
||||
if (_key == null)
|
||||
{
|
||||
_key = new CompositeKey(); //use a temporary key which should be changed after creation
|
||||
}
|
||||
|
||||
db.KpDatabase.New(_ioc, _key);
|
||||
|
||||
db.KpDatabase.KeyEncryptionRounds = DefaultEncryptionRounds;
|
||||
db.KpDatabase.Name = "Keepass2Android Password Database";
|
||||
|
BIN
src/keepass2android/Assets/DejaVuSansMono.ttf
Normal file
BIN
src/keepass2android/Assets/DejaVuSansMono.ttf
Normal file
Binary file not shown.
99
src/keepass2android/Assets/LICENSE_dejavu
Normal file
99
src/keepass2android/Assets/LICENSE_dejavu
Normal file
@ -0,0 +1,99 @@
|
||||
Fonts are (c) Bitstream (see below). DejaVu changes are in public domain.
|
||||
Glyphs imported from Arev fonts are (c) Tavmjong Bah (see below)
|
||||
|
||||
Bitstream Vera Fonts Copyright
|
||||
------------------------------
|
||||
|
||||
Copyright (c) 2003 by Bitstream, Inc. All Rights Reserved. Bitstream Vera is
|
||||
a trademark of Bitstream, Inc.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of the fonts accompanying this license ("Fonts") and associated
|
||||
documentation files (the "Font Software"), to reproduce and distribute the
|
||||
Font Software, including without limitation the rights to use, copy, merge,
|
||||
publish, distribute, and/or sell copies of the Font Software, and to permit
|
||||
persons to whom the Font Software is furnished to do so, subject to the
|
||||
following conditions:
|
||||
|
||||
The above copyright and trademark notices and this permission notice shall
|
||||
be included in all copies of one or more of the Font Software typefaces.
|
||||
|
||||
The Font Software may be modified, altered, or added to, and in particular
|
||||
the designs of glyphs or characters in the Fonts may be modified and
|
||||
additional glyphs or characters may be added to the Fonts, only if the fonts
|
||||
are renamed to names not containing either the words "Bitstream" or the word
|
||||
"Vera".
|
||||
|
||||
This License becomes null and void to the extent applicable to Fonts or Font
|
||||
Software that has been modified and is distributed under the "Bitstream
|
||||
Vera" names.
|
||||
|
||||
The Font Software may be sold as part of a larger software package but no
|
||||
copy of one or more of the Font Software typefaces may be sold by itself.
|
||||
|
||||
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT,
|
||||
TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL BITSTREAM OR THE GNOME
|
||||
FOUNDATION BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING
|
||||
ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES,
|
||||
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
|
||||
THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE
|
||||
FONT SOFTWARE.
|
||||
|
||||
Except as contained in this notice, the names of Gnome, the Gnome
|
||||
Foundation, and Bitstream Inc., shall not be used in advertising or
|
||||
otherwise to promote the sale, use or other dealings in this Font Software
|
||||
without prior written authorization from the Gnome Foundation or Bitstream
|
||||
Inc., respectively. For further information, contact: fonts at gnome dot
|
||||
org.
|
||||
|
||||
Arev Fonts Copyright
|
||||
------------------------------
|
||||
|
||||
Copyright (c) 2006 by Tavmjong Bah. All Rights Reserved.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of the fonts accompanying this license ("Fonts") and
|
||||
associated documentation files (the "Font Software"), to reproduce
|
||||
and distribute the modifications to the Bitstream Vera Font Software,
|
||||
including without limitation the rights to use, copy, merge, publish,
|
||||
distribute, and/or sell copies of the Font Software, and to permit
|
||||
persons to whom the Font Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright and trademark notices and this permission notice
|
||||
shall be included in all copies of one or more of the Font Software
|
||||
typefaces.
|
||||
|
||||
The Font Software may be modified, altered, or added to, and in
|
||||
particular the designs of glyphs or characters in the Fonts may be
|
||||
modified and additional glyphs or characters may be added to the
|
||||
Fonts, only if the fonts are renamed to names not containing either
|
||||
the words "Tavmjong Bah" or the word "Arev".
|
||||
|
||||
This License becomes null and void to the extent applicable to Fonts
|
||||
or Font Software that has been modified and is distributed under the
|
||||
"Tavmjong Bah Arev" names.
|
||||
|
||||
The Font Software may be sold as part of a larger software package but
|
||||
no copy of one or more of the Font Software typefaces may be sold by
|
||||
itself.
|
||||
|
||||
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
||||
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL
|
||||
TAVMJONG BAH BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
||||
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
|
||||
OTHER DEALINGS IN THE FONT SOFTWARE.
|
||||
|
||||
Except as contained in this notice, the name of Tavmjong Bah shall not
|
||||
be used in advertising or otherwise to promote the sale, use or other
|
||||
dealings in this Font Software without prior written authorization
|
||||
from Tavmjong Bah. For further information, contact: tavmjong @ free
|
||||
. fr.
|
||||
|
||||
$Id: LICENSE 2133 2007-11-28 02:46:28Z lechimp $
|
BIN
src/keepass2android/Assets/fontawesome-webfont.ttf
Normal file
BIN
src/keepass2android/Assets/fontawesome-webfont.ttf
Normal file
Binary file not shown.
490
src/keepass2android/CreateDatabaseActivity.cs
Normal file
490
src/keepass2android/CreateDatabaseActivity.cs
Normal file
@ -0,0 +1,490 @@
|
||||
using System;
|
||||
using Android.App;
|
||||
using Android.Content;
|
||||
using Android.Content.PM;
|
||||
using Android.Graphics.Drawables;
|
||||
using Android.OS;
|
||||
using Android.Preferences;
|
||||
using Android.Text;
|
||||
using Android.Views;
|
||||
using Android.Widget;
|
||||
using Java.IO;
|
||||
using KeePassLib.Keys;
|
||||
using KeePassLib.Serialization;
|
||||
using keepass2android.Io;
|
||||
using Environment = Android.OS.Environment;
|
||||
using IOException = Java.IO.IOException;
|
||||
|
||||
namespace keepass2android
|
||||
{
|
||||
[Activity(Label = "@string/app_name",
|
||||
ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.KeyboardHidden,
|
||||
Theme = "@style/Base")]
|
||||
public class CreateDatabaseActivity : Activity
|
||||
{
|
||||
private IOConnectionInfo _ioc;
|
||||
private string _keyfileFilename;
|
||||
private bool _restoringInstanceState;
|
||||
private bool _showPassword;
|
||||
|
||||
|
||||
private const int RequestCodeKeyFile = 0;
|
||||
private const int RequestCodeDbFilename = 1;
|
||||
private const string KeyfilefilenameBundleKey = "KeyfileFilename";
|
||||
|
||||
protected override void OnSaveInstanceState(Bundle outState)
|
||||
{
|
||||
base.OnSaveInstanceState(outState);
|
||||
outState.PutString(PasswordActivity.KeyFilename, _ioc.Path);
|
||||
outState.PutString(PasswordActivity.KeyServerusername, _ioc.UserName);
|
||||
outState.PutString(PasswordActivity.KeyServerpassword, _ioc.Password);
|
||||
outState.PutInt(PasswordActivity.KeyServercredmode, (int)_ioc.CredSaveMode);
|
||||
|
||||
if (_keyfileFilename != null)
|
||||
outState.PutString(KeyfilefilenameBundleKey, _keyfileFilename);
|
||||
}
|
||||
|
||||
protected override void OnCreate(Bundle bundle)
|
||||
{
|
||||
base.OnCreate(bundle);
|
||||
|
||||
SetContentView(Resource.Layout.create_database);
|
||||
|
||||
|
||||
SetDefaultIoc();
|
||||
|
||||
FindViewById(Resource.Id.keyfile_filename).Visibility = ViewStates.Gone;
|
||||
|
||||
|
||||
var keyfileCheckbox = FindViewById<CheckBox>(Resource.Id.use_keyfile);
|
||||
|
||||
if (bundle != null)
|
||||
{
|
||||
_keyfileFilename = bundle.GetString(KeyfilefilenameBundleKey, null);
|
||||
if (_keyfileFilename != null)
|
||||
{
|
||||
FindViewById<TextView>(Resource.Id.keyfile_filename).Text = ConvertFilenameToIocPath(_keyfileFilename);
|
||||
FindViewById(Resource.Id.keyfile_filename).Visibility = ViewStates.Visible;
|
||||
keyfileCheckbox.Checked = true;
|
||||
}
|
||||
|
||||
if (bundle.GetString(PasswordActivity.KeyFilename, null) != null)
|
||||
{
|
||||
_ioc = new IOConnectionInfo
|
||||
{
|
||||
Path = bundle.GetString(PasswordActivity.KeyFilename),
|
||||
UserName = bundle.GetString(PasswordActivity.KeyServerusername),
|
||||
Password = bundle.GetString(PasswordActivity.KeyServerpassword),
|
||||
CredSaveMode = (IOCredSaveMode) bundle.GetInt(PasswordActivity.KeyServercredmode),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
UpdateIocView();
|
||||
|
||||
keyfileCheckbox.CheckedChange += (sender, args) =>
|
||||
{
|
||||
if (keyfileCheckbox.Checked)
|
||||
{
|
||||
if (_restoringInstanceState)
|
||||
return;
|
||||
|
||||
string defaulFilename = _keyfileFilename;
|
||||
if (_keyfileFilename == null)
|
||||
{
|
||||
defaulFilename = _keyfileFilename = SdDir + "keepass/keyfile.txt";
|
||||
if (defaulFilename.StartsWith("file://") == false)
|
||||
defaulFilename = "file://" + defaulFilename;
|
||||
}
|
||||
|
||||
StartFileChooser(defaulFilename, RequestCodeKeyFile, false);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
FindViewById(Resource.Id.keyfile_filename).Visibility = ViewStates.Gone;
|
||||
_keyfileFilename = null;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
FindViewById(Resource.Id.btn_change_location).Click += (sender, args) =>
|
||||
{
|
||||
Intent intent = new Intent(this, typeof(FileStorageSelectionActivity));
|
||||
StartActivityForResult(intent, 0);
|
||||
};
|
||||
|
||||
Button generatePassword = (Button)FindViewById(Resource.Id.generate_button);
|
||||
generatePassword.Click += (sender, e) =>
|
||||
{
|
||||
GeneratePasswordActivity.LaunchWithoutLockCheck(this);
|
||||
};
|
||||
|
||||
FindViewById(Resource.Id.btn_create).Click += (sender, evt) =>
|
||||
{
|
||||
CreateDatabase();
|
||||
};
|
||||
|
||||
ImageButton btnTogglePassword = (ImageButton)FindViewById(Resource.Id.toggle_password);
|
||||
btnTogglePassword.Click += (sender, e) =>
|
||||
{
|
||||
_showPassword = !_showPassword;
|
||||
MakePasswordMaskedOrVisible();
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
private void MakePasswordMaskedOrVisible()
|
||||
{
|
||||
TextView password = (TextView)FindViewById(Resource.Id.entry_password);
|
||||
TextView confpassword = (TextView)FindViewById(Resource.Id.entry_confpassword);
|
||||
if (_showPassword)
|
||||
{
|
||||
password.InputType = InputTypes.ClassText | InputTypes.TextVariationVisiblePassword;
|
||||
confpassword.Visibility = ViewStates.Gone;
|
||||
}
|
||||
else
|
||||
{
|
||||
password.InputType = InputTypes.ClassText | InputTypes.TextVariationPassword;
|
||||
confpassword.Visibility = ViewStates.Visible;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void CreateDatabase()
|
||||
{
|
||||
var keyfileCheckbox = FindViewById<CheckBox>(Resource.Id.use_keyfile);
|
||||
string password;
|
||||
if (!TryGetPassword(out password)) return;
|
||||
|
||||
|
||||
// Verify that a password or keyfile is set
|
||||
if (password.Length == 0 && !keyfileCheckbox.Checked)
|
||||
{
|
||||
Toast.MakeText(this, Resource.String.error_nopass, ToastLength.Long).Show();
|
||||
return;
|
||||
}
|
||||
|
||||
//create the key
|
||||
CompositeKey newKey = new CompositeKey();
|
||||
if (String.IsNullOrEmpty(password) == false)
|
||||
{
|
||||
newKey.AddUserKey(new KcpPassword(password));
|
||||
}
|
||||
if (String.IsNullOrEmpty(_keyfileFilename) == false)
|
||||
{
|
||||
try
|
||||
{
|
||||
newKey.AddUserKey(new KcpKeyFile(_keyfileFilename));
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
Toast.MakeText(this, Resource.String.error_adding_keyfile, ToastLength.Long).Show();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Create the new database
|
||||
CreateDb create = new CreateDb(App.Kp2a, this, _ioc, new LaunchGroupActivity(_ioc, this), false, newKey);
|
||||
ProgressTask createTask = new ProgressTask(
|
||||
App.Kp2a,
|
||||
this, create);
|
||||
createTask.Run();
|
||||
}
|
||||
|
||||
private bool TryGetPassword(out string pass)
|
||||
{
|
||||
TextView passView = (TextView)FindViewById(Resource.Id.entry_password);
|
||||
pass = passView.Text;
|
||||
|
||||
if (_showPassword)
|
||||
return true;
|
||||
|
||||
TextView passConfView = (TextView) FindViewById(Resource.Id.entry_confpassword);
|
||||
String confpass = passConfView.Text;
|
||||
|
||||
// Verify that passwords match
|
||||
if (! pass.Equals(confpass))
|
||||
{
|
||||
// Passwords do not match
|
||||
Toast.MakeText(this, Resource.String.error_pass_match, ToastLength.Long).Show();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override void OnRestoreInstanceState(Bundle savedInstanceState)
|
||||
{
|
||||
_restoringInstanceState = true;
|
||||
base.OnRestoreInstanceState(savedInstanceState);
|
||||
_restoringInstanceState = false;
|
||||
}
|
||||
|
||||
private void StartFileChooser(string defaultPath, int requestCode, bool forSave)
|
||||
{
|
||||
#if !EXCLUDE_FILECHOOSER
|
||||
Kp2aLog.Log("FSA: defaultPath=" + defaultPath);
|
||||
string fileProviderAuthority = FileChooserFileProvider.TheAuthority;
|
||||
if (defaultPath.StartsWith("file://"))
|
||||
{
|
||||
fileProviderAuthority = "keepass2android.keepass2android.android-filechooser.localfile";
|
||||
}
|
||||
Intent i = Keepass2android.Kp2afilechooser.Kp2aFileChooserBridge.GetLaunchFileChooserIntent(this, fileProviderAuthority,
|
||||
defaultPath);
|
||||
|
||||
if (forSave)
|
||||
i.PutExtra("group.pals.android.lib.ui.filechooser.FileChooserActivity.save_dialog", true);
|
||||
|
||||
StartActivityForResult(i, requestCode);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
private void UpdateIocView()
|
||||
{
|
||||
int protocolSeparatorPos = _ioc.Path.IndexOf("://", StringComparison.Ordinal);
|
||||
string protocolId = protocolSeparatorPos < 0 ?
|
||||
"file" : _ioc.Path.Substring(0, protocolSeparatorPos);
|
||||
Drawable drawable = App.Kp2a.GetResourceDrawable("ic_storage_" + protocolId);
|
||||
FindViewById<ImageView>(Resource.Id.filestorage_logo).SetImageDrawable(drawable);
|
||||
|
||||
String title = App.Kp2a.GetResourceString("filestoragename_" + protocolId);
|
||||
FindViewById<TextView>(Resource.Id.filestorage_label).Text = title;
|
||||
|
||||
FindViewById<TextView>(Resource.Id.label_filename).Text = protocolSeparatorPos < 0 ?
|
||||
_ioc.Path :
|
||||
_ioc.Path.Substring(protocolSeparatorPos + 3);
|
||||
|
||||
}
|
||||
|
||||
private void SetDefaultIoc()
|
||||
{
|
||||
var sdDir = SdDir;
|
||||
string filename = sdDir + "keepass/keepass.kdbx";
|
||||
filename = ConvertFilenameToIocPath(filename);
|
||||
int count = 2;
|
||||
while (new File(filename).Exists())
|
||||
{
|
||||
filename = ConvertFilenameToIocPath(sdDir + "keepass/keepass" + count + ".kdbx");
|
||||
count++;
|
||||
}
|
||||
|
||||
_ioc = new IOConnectionInfo()
|
||||
{
|
||||
Path = filename
|
||||
};
|
||||
}
|
||||
|
||||
private static string SdDir
|
||||
{
|
||||
get
|
||||
{
|
||||
string sdDir = Environment.ExternalStorageDirectory.AbsolutePath;
|
||||
if (!sdDir.EndsWith("/"))
|
||||
sdDir += "/";
|
||||
if (!sdDir.StartsWith("file://"))
|
||||
sdDir = "file://" + sdDir;
|
||||
return sdDir;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)
|
||||
{
|
||||
base.OnActivityResult(requestCode, resultCode, data);
|
||||
|
||||
if (resultCode == KeePass.ResultOkPasswordGenerator)
|
||||
{
|
||||
String generatedPassword = data.GetStringExtra("keepass2android.password.generated_password");
|
||||
FindViewById<TextView>(Resource.Id.entry_password).Text = generatedPassword;
|
||||
FindViewById<TextView>(Resource.Id.entry_confpassword).Text = generatedPassword;
|
||||
}
|
||||
|
||||
if (resultCode == KeePass.ExitFileStorageSelectionOk)
|
||||
{
|
||||
string protocolId = data.GetStringExtra("protocolId");
|
||||
App.Kp2a.GetFileStorage(protocolId).StartSelectFile(new FileStorageSetupInitiatorActivity(this,
|
||||
OnActivityResult,
|
||||
defaultPath =>
|
||||
{
|
||||
Util.ShowFilenameDialog(this, OnCreateButton, null, false, defaultPath, GetString(Resource.String.enter_filename_details_url),
|
||||
Intents.RequestCodeFileBrowseForOpen);
|
||||
}
|
||||
), true, RequestCodeDbFilename, protocolId);
|
||||
}
|
||||
|
||||
if (resultCode == Result.Ok)
|
||||
{
|
||||
if (requestCode == RequestCodeKeyFile)
|
||||
{
|
||||
string filename = Util.IntentToFilename(data, this);
|
||||
if (filename != null)
|
||||
{
|
||||
_keyfileFilename = ConvertFilenameToIocPath(filename);
|
||||
FindViewById<TextView>(Resource.Id.keyfile_filename).Text = _keyfileFilename;
|
||||
FindViewById(Resource.Id.keyfile_filename).Visibility = ViewStates.Visible;
|
||||
}
|
||||
}
|
||||
if (requestCode == RequestCodeDbFilename)
|
||||
{
|
||||
string filename = Util.IntentToFilename(data, this);
|
||||
filename = ConvertFilenameToIocPath(filename);
|
||||
if (filename != null)
|
||||
{
|
||||
_ioc = new IOConnectionInfo() {Path = filename};
|
||||
UpdateIocView();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
if (resultCode == (Result)FileStorageResults.FileUsagePrepared)
|
||||
{
|
||||
_ioc = new IOConnectionInfo();
|
||||
PasswordActivity.SetIoConnectionFromIntent(_ioc, data);
|
||||
UpdateIocView();
|
||||
}
|
||||
if (resultCode == (Result)FileStorageResults.FileChooserPrepared)
|
||||
{
|
||||
IOConnectionInfo ioc = new IOConnectionInfo();
|
||||
PasswordActivity.SetIoConnectionFromIntent(ioc, data);
|
||||
StartFileChooser(ioc.Path, RequestCodeDbFilename, true);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static string ConvertFilenameToIocPath(string filename)
|
||||
{
|
||||
if (filename.StartsWith("file://"))
|
||||
{
|
||||
filename = filename.Substring(7);
|
||||
}
|
||||
filename = Java.Net.URLDecoder.Decode(filename);
|
||||
return filename;
|
||||
}
|
||||
|
||||
private void OnCreateButton(object sender, EventArgs evt)
|
||||
{
|
||||
Dialog dialog = (Dialog)sender;
|
||||
|
||||
String filename = ((EditText)dialog.FindViewById(Resource.Id.file_filename)).Text;
|
||||
|
||||
// Make sure file name exists
|
||||
if (filename.Length == 0)
|
||||
{
|
||||
Toast.MakeText(this,
|
||||
Resource.String.error_filename_required,
|
||||
ToastLength.Long).Show();
|
||||
return;
|
||||
}
|
||||
|
||||
IOConnectionInfo ioc = new IOConnectionInfo() { Path = filename };
|
||||
try
|
||||
{
|
||||
App.Kp2a.GetFileStorage(ioc);
|
||||
}
|
||||
catch (NoFileStorageFoundException)
|
||||
{
|
||||
Toast.MakeText(this,
|
||||
"Unexpected scheme in "+filename,
|
||||
ToastLength.Long).Show();
|
||||
return;
|
||||
}
|
||||
|
||||
if (ioc.IsLocalFile())
|
||||
{
|
||||
// Try to create the file
|
||||
Java.IO.File file = new Java.IO.File(filename);
|
||||
try
|
||||
{
|
||||
Java.IO.File parent = file.ParentFile;
|
||||
|
||||
if (parent == null || (parent.Exists() && !parent.IsDirectory))
|
||||
{
|
||||
Toast.MakeText(this,
|
||||
Resource.String.error_invalid_path,
|
||||
ToastLength.Long).Show();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!parent.Exists())
|
||||
{
|
||||
// Create parent dircetory
|
||||
if (!parent.Mkdirs())
|
||||
{
|
||||
Toast.MakeText(this,
|
||||
Resource.String.error_could_not_create_parent,
|
||||
ToastLength.Long).Show();
|
||||
return;
|
||||
|
||||
}
|
||||
}
|
||||
System.IO.File.Create(filename);
|
||||
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
Toast.MakeText(
|
||||
this,
|
||||
GetText(Resource.String.error_file_not_create) + " "
|
||||
+ ex.LocalizedMessage,
|
||||
ToastLength.Long).Show();
|
||||
return;
|
||||
}
|
||||
|
||||
_ioc = ioc;
|
||||
UpdateIocView();
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private class LaunchGroupActivity : FileOnFinish
|
||||
{
|
||||
readonly CreateDatabaseActivity _activity;
|
||||
private readonly IOConnectionInfo _ioc;
|
||||
|
||||
public LaunchGroupActivity(IOConnectionInfo ioc, CreateDatabaseActivity activity)
|
||||
: base(null)
|
||||
{
|
||||
_activity = activity;
|
||||
_ioc = ioc;
|
||||
}
|
||||
|
||||
public override void Run()
|
||||
{
|
||||
if (Success)
|
||||
{
|
||||
// Update the ongoing notification
|
||||
_activity.StartService(new Intent(_activity, typeof(OngoingNotificationsService)));
|
||||
|
||||
if (PreferenceManager.GetDefaultSharedPreferences(_activity).GetBoolean(_activity.GetString(Resource.String.RememberRecentFiles_key), _activity.Resources.GetBoolean(Resource.Boolean.RememberRecentFiles_default)))
|
||||
{
|
||||
// Add to recent files
|
||||
FileDbHelper dbHelper = App.Kp2a.FileDbHelper;
|
||||
|
||||
|
||||
//TODO: getFilename always returns "" -> bug?
|
||||
dbHelper.CreateFile(_ioc, Filename);
|
||||
}
|
||||
|
||||
GroupActivity.Launch(_activity, new NullTask());
|
||||
_activity.Finish();
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
DisplayMessage(_activity);
|
||||
try
|
||||
{
|
||||
App.Kp2a.GetFileStorage(_ioc).Delete(_ioc);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Kp2aLog.Log(e.ToString());
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -45,6 +45,7 @@ namespace keepass2android
|
||||
public const String KeyRefreshPos = "refresh_pos";
|
||||
public const String KeyCloseAfterCreate = "close_after_create";
|
||||
|
||||
private static Typeface _passwordFont;
|
||||
|
||||
public static void Launch(Activity act, PwEntry pw, int pos, AppTask appTask) {
|
||||
Intent i = new Intent(act, typeof(EntryActivity));
|
||||
@ -205,7 +206,7 @@ namespace keepass2android
|
||||
TextView valueView = (TextView)LayoutInflater.Inflate(Resource.Layout.entry_extrastring_value, null);
|
||||
if (value != null)
|
||||
valueView.Text = value;
|
||||
valueView.Typeface = Typeface.Monospace;
|
||||
SetPasswordTypeface(valueView);
|
||||
if (isProtected)
|
||||
RegisterProtectedTextView(valueView);
|
||||
|
||||
@ -399,6 +400,8 @@ namespace keepass2android
|
||||
PopulateText(Resource.Id.entry_url, Resource.Id.entry_url_label, Entry.Strings.ReadSafe(PwDefs.UrlField));
|
||||
PopulateText(Resource.Id.entry_password, Resource.Id.entry_password_label, Entry.Strings.ReadSafe(PwDefs.PasswordField));
|
||||
RegisterProtectedTextView(FindViewById<TextView>(Resource.Id.entry_password));
|
||||
SetPasswordTypeface(FindViewById<TextView>(Resource.Id.entry_password));
|
||||
|
||||
|
||||
PopulateText(Resource.Id.entry_created, Resource.Id.entry_created_label, getDateTime(Entry.CreationTime));
|
||||
PopulateText(Resource.Id.entry_modified, Resource.Id.entry_modified_label, getDateTime(Entry.LastModificationTime));
|
||||
@ -424,6 +427,13 @@ namespace keepass2android
|
||||
SetPasswordStyle();
|
||||
}
|
||||
|
||||
private void SetPasswordTypeface(TextView textView)
|
||||
{
|
||||
if (_passwordFont == null)
|
||||
_passwordFont = Typeface.CreateFromAsset(Assets, "DejaVuSansMono.ttf" );
|
||||
textView.Typeface = _passwordFont;
|
||||
}
|
||||
|
||||
private void PopulateText(int viewId, int headerViewId,int resId) {
|
||||
View header = FindViewById(headerViewId);
|
||||
TextView tv = (TextView)FindViewById(viewId);
|
||||
|
@ -40,7 +40,7 @@ namespace keepass2android
|
||||
public const String KeyParent = "parent";
|
||||
|
||||
public const int ResultOkIconPicker = (int)Result.FirstUser + 1000;
|
||||
public const int ResultOkPasswordGenerator = ResultOkIconPicker + 1;
|
||||
|
||||
|
||||
const string IntentContinueWithEditing = "ContinueWithEditing";
|
||||
|
||||
@ -594,9 +594,9 @@ namespace keepass2android
|
||||
|
||||
protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)
|
||||
{
|
||||
switch ((int)resultCode)
|
||||
switch (resultCode)
|
||||
{
|
||||
case ResultOkIconPicker:
|
||||
case (Result)ResultOkIconPicker:
|
||||
State.SelectedIconId = (PwIcon) data.Extras.GetInt(IconPickerActivity.KeyIconId);
|
||||
State.SelectedCustomIconId = PwUuid.Zero;
|
||||
String customIconIdString = data.Extras.GetString(IconPickerActivity.KeyCustomIconId);
|
||||
@ -607,7 +607,7 @@ namespace keepass2android
|
||||
Reload();
|
||||
break;
|
||||
|
||||
case ResultOkPasswordGenerator:
|
||||
case KeePass.ResultOkPasswordGenerator:
|
||||
String generatedPassword = data.GetStringExtra("keepass2android.password.generated_password");
|
||||
|
||||
byte[] password = StrUtil.Utf8.GetBytes(generatedPassword);
|
||||
@ -618,7 +618,7 @@ namespace keepass2android
|
||||
State.EntryModified = true;
|
||||
Reload();
|
||||
break;
|
||||
case (int)Result.Ok:
|
||||
case Result.Ok:
|
||||
if (requestCode == Intents.RequestCodeFileBrowseForBinary)
|
||||
{
|
||||
string filename = Util.IntentToFilename(data, this);
|
||||
@ -635,7 +635,7 @@ namespace keepass2android
|
||||
|
||||
|
||||
break;
|
||||
case (int)Result.Canceled:
|
||||
case Result.Canceled:
|
||||
Reload();
|
||||
break;
|
||||
}
|
||||
|
@ -34,6 +34,15 @@ namespace keepass2android
|
||||
act.StartActivityForResult(i, 0);
|
||||
}
|
||||
|
||||
public static void LaunchWithoutLockCheck(Activity act)
|
||||
{
|
||||
Intent i = new Intent(act, typeof(GeneratePasswordActivity));
|
||||
|
||||
i.PutExtra(NoLockCheck, true);
|
||||
|
||||
act.StartActivityForResult(i, 0);
|
||||
}
|
||||
|
||||
|
||||
protected override void OnCreate(Bundle savedInstanceState) {
|
||||
base.OnCreate(savedInstanceState);
|
||||
@ -69,7 +78,7 @@ namespace keepass2android
|
||||
Intent intent = new Intent();
|
||||
intent.PutExtra("keepass2android.password.generated_password", password.Text);
|
||||
|
||||
SetResult((Result)EntryEditActivity.ResultOkPasswordGenerator, intent);
|
||||
SetResult(KeePass.ResultOkPasswordGenerator, intent);
|
||||
|
||||
Finish();
|
||||
};
|
||||
|
@ -43,6 +43,7 @@ namespace keepass2android
|
||||
public const Result ExitReloadDb = Result.FirstUser+6;
|
||||
public const Result ExitClose = Result.FirstUser + 7;
|
||||
public const Result ExitFileStorageSelectionOk = Result.FirstUser + 8;
|
||||
public const Result ResultOkPasswordGenerator = Result.FirstUser + 9;
|
||||
|
||||
AppTask _appTask;
|
||||
|
||||
|
@ -15,10 +15,8 @@ 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 Android.Content;
|
||||
using Android.OS;
|
||||
using Android.App;
|
||||
using KeePassLib.Serialization;
|
||||
|
||||
namespace keepass2android
|
||||
@ -29,6 +27,10 @@ namespace keepass2android
|
||||
/// Checks in OnResume whether the timeout occured and the database must be locked/closed.
|
||||
public class LockCloseActivity : LockingActivity {
|
||||
|
||||
//the check if the database was locked/closed can be disabled by the caller for activities
|
||||
//which may be used "outside" the database (e.g. GeneratePassword for creating a master password)
|
||||
protected const string NoLockCheck = "NO_LOCK_CHECK";
|
||||
|
||||
private IOConnectionInfo _ioc;
|
||||
private BroadcastReceiver _intentReceiver;
|
||||
|
||||
@ -37,6 +39,9 @@ namespace keepass2android
|
||||
base.OnCreate(savedInstanceState);
|
||||
_ioc = App.Kp2a.GetDb().Ioc;
|
||||
|
||||
if (Intent.GetBooleanExtra(NoLockCheck, false))
|
||||
return;
|
||||
|
||||
_intentReceiver = new LockCloseActivityBroadcastReceiver(this);
|
||||
IntentFilter filter = new IntentFilter();
|
||||
filter.AddAction(Intents.DatabaseLocked);
|
||||
@ -44,8 +49,14 @@ namespace keepass2android
|
||||
}
|
||||
|
||||
protected override void OnDestroy()
|
||||
{
|
||||
if (Intent.GetBooleanExtra(NoLockCheck, false) == false)
|
||||
{
|
||||
UnregisterReceiver(_intentReceiver);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
base.OnDestroy();
|
||||
}
|
||||
@ -55,6 +66,9 @@ namespace keepass2android
|
||||
{
|
||||
base.OnResume();
|
||||
|
||||
if (Intent.GetBooleanExtra(NoLockCheck, false))
|
||||
return;
|
||||
|
||||
if (TimeoutHelper.CheckShutdown(this, _ioc))
|
||||
return;
|
||||
|
||||
|
48
src/keepass2android/Properties/AndroidManifest_light.xml
Normal file
48
src/keepass2android/Properties/AndroidManifest_light.xml
Normal file
@ -0,0 +1,48 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="23" android:versionName="0.8.6" package="keepass2android.keepass2android" android:installLocation="auto">
|
||||
<uses-sdk android:minSdkVersion="8" android:targetSdkVersion="14" />
|
||||
<application android:label="keepass2android" android:icon="@drawable/ic_launcher">
|
||||
<activity android:name="com.dropbox.client2.android.AuthActivity" android:launchMode="singleTask" android:configChanges="orientation|keyboard">
|
||||
<intent-filter>
|
||||
<!-- Change this to be db- followed by your app key -->
|
||||
<data android:scheme="db-i8shu7v1hgh7ynt" />
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity android:configChanges="keyboardHidden|orientation" android:label="@string/app_name" android:theme="@style/Base" android:name="keepass2android.PasswordActivity">
|
||||
<intent-filter android:label="@string/app_name">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
<data android:scheme="file" />
|
||||
<data android:mimeType="*/*" />
|
||||
<data android:host="*" />
|
||||
<data android:pathPattern=".*\\.kdbp" />
|
||||
<data android:pathPattern=".*\\..*\\.kdbp" />
|
||||
<data android:pathPattern=".*\\..*\\..*\\.kdbp" />
|
||||
<data android:pathPattern=".*\\..*\\..*\\..*\\.kdbp" />
|
||||
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\.kdbp" />
|
||||
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\.kdbp" />
|
||||
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\.kdbp" />
|
||||
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.kdbp" />
|
||||
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.kdbp" />
|
||||
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.kdbp" />
|
||||
<data android:pathPattern=".*\\.kdbx" />
|
||||
<data android:pathPattern=".*\\..*\\.kdbx" />
|
||||
<data android:pathPattern=".*\\..*\\..*\\.kdbx" />
|
||||
<data android:pathPattern=".*\\..*\\..*\\..*\\.kdbx" />
|
||||
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\.kdbx" />
|
||||
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\.kdbx" />
|
||||
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\.kdbx" />
|
||||
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.kdbx" />
|
||||
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.kdbx" />
|
||||
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.kdbx" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
</application>
|
||||
<uses-permission android:name="android.permission.VIBRATE" />
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
</manifest>
|
4438
src/keepass2android/Resources/Resource.designer.cs
generated
4438
src/keepass2android/Resources/Resource.designer.cs
generated
File diff suppressed because it is too large
Load Diff
@ -39,6 +39,8 @@
|
||||
style="@style/BottomBarActionButton"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?android:attr/selectableItemBackground"
|
||||
android:clickable="true"
|
||||
android:layout_weight="1">
|
||||
<TextView
|
||||
style="?android:actionBarTabTextStyle"
|
||||
|
165
src/keepass2android/Resources/layout/create_database.xml
Normal file
165
src/keepass2android/Resources/layout/create_database.xml
Normal file
@ -0,0 +1,165 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:layout_margin="12dip">
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="fill_parent"
|
||||
android:orientation="vertical"
|
||||
android:layout_height="wrap_content">
|
||||
<TextView
|
||||
android:id="@+id/version_title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/divider1"
|
||||
style="@style/InfoHeader"
|
||||
android:text="@string/database_location" />
|
||||
|
||||
<keepass2android.views.TextWithHelp
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:help_text="@string/help_database_location"
|
||||
android:text="@string/hint_database_location"
|
||||
/>
|
||||
|
||||
|
||||
<LinearLayout
|
||||
android:orientation="horizontal"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/filestorage_logo"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:src="@drawable/ic_storage_file"
|
||||
android:padding="5dp"
|
||||
|
||||
/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/filestorage_label"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="10dp"
|
||||
android:text="Local file (TODO!)"
|
||||
android:textSize="16dp" >
|
||||
</TextView>
|
||||
</LinearLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/label_filename"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="/keepass/keepass.kdbx"
|
||||
android:layout_marginLeft="18dp"
|
||||
/>
|
||||
|
||||
<Button android:id="@+id/btn_change_location"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/button_change_location"
|
||||
style="@style/TextAppearance_SubElement"
|
||||
/>
|
||||
|
||||
|
||||
<TextView
|
||||
android:id="@+id/password_title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/divider1"
|
||||
style="@style/InfoHeader"
|
||||
android:text="@string/master_password" />
|
||||
|
||||
|
||||
<keepass2android.views.TextWithHelp
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:help_text="@string/help_master_password"
|
||||
android:text="@string/hint_master_password"
|
||||
/>
|
||||
|
||||
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<Button
|
||||
android:id="@+id/generate_button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentRight="true"
|
||||
android:text="@string/ellipsis" />
|
||||
<ImageButton
|
||||
android:id="@+id/toggle_password"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:src="@drawable/ic_menu_view"
|
||||
android:layout_alignTop="@id/generate_button"
|
||||
android:layout_toLeftOf="@id/generate_button"
|
||||
/>
|
||||
<EditText
|
||||
android:id="@+id/entry_password"
|
||||
style="@style/TextAppearance_EditEntry_Value"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignTop="@id/generate_button"
|
||||
android:layout_toLeftOf="@id/toggle_password"
|
||||
android:hint="@string/hint_pass"
|
||||
android:inputType="textPassword"
|
||||
android:singleLine="true"
|
||||
android:typeface="monospace" />
|
||||
<!-- Confirm Password -->
|
||||
<EditText
|
||||
android:id="@+id/entry_confpassword"
|
||||
style="@style/TextAppearance_EditEntry_Value"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/entry_password"
|
||||
android:hint="@string/hint_conf_pass"
|
||||
android:inputType="textPassword"
|
||||
android:singleLine="true"
|
||||
android:typeface="monospace" />
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/keyfile_title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/divider1"
|
||||
style="@style/InfoHeader"
|
||||
android:text="@string/key_file" />
|
||||
|
||||
<keepass2android.views.TextWithHelp
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:help_text="@string/help_key_file"
|
||||
android:text="@string/hint_key_file"
|
||||
/>
|
||||
/>
|
||||
|
||||
<CheckBox
|
||||
android:id="@+id/use_keyfile"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="12dp"
|
||||
android:text="@string/use_key_file" />
|
||||
<TextView
|
||||
android:id="@+id/keyfile_filename"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
style="@style/TextAppearance_SubElement"
|
||||
android:text="/sdcard/bla/blubb.txt"
|
||||
/>
|
||||
|
||||
<Button android:id="@+id/btn_create"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/create_database"
|
||||
/>
|
||||
|
||||
</LinearLayout>
|
||||
</ScrollView>
|
@ -12,12 +12,34 @@
|
||||
<ScrollView
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent">
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="fill_parent"
|
||||
android:orientation="vertical"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/imglogo"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginBottom="12dp"
|
||||
android:scaleType="fitXY"
|
||||
android:src="@drawable/ic_keepass2android" />
|
||||
<TextView
|
||||
android:id="@+id/label_test"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
|
||||
android:layout_gravity="center"
|
||||
android:text="Welcome to Keepass2Android!"
|
||||
android:visibility="visible" />
|
||||
|
||||
|
||||
<keepass2android.view.FileSelectButtons
|
||||
android:id="@+id/file_select"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
</LinearLayout>
|
||||
</ScrollView>
|
||||
</LinearLayout>
|
||||
<!-- Small hack because I need to include a list since this is a list activity -->
|
||||
|
30
src/keepass2android/Resources/layout/text_with_help.xml
Normal file
30
src/keepass2android/Resources/layout/text_with_help.xml
Normal file
@ -0,0 +1,30 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<RelativeLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
|
||||
<keepass2android.views.Kp2aShortHelpView
|
||||
android:id="@+id/help"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="right"
|
||||
style="@style/TextAppearance_Help"
|
||||
android:textColor="@color/light_gray"
|
||||
android:layout_alignParentRight="true"
|
||||
android:background="?android:attr/selectableItemBackground"
|
||||
/>
|
||||
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_toLeftOf="@id/help"
|
||||
style="@style/TextAppearance_SubElement"
|
||||
|
||||
/>
|
||||
|
||||
</RelativeLayout>
|
@ -27,4 +27,7 @@
|
||||
|
||||
<color name="element_being_moved">#a8a8a8</color>
|
||||
|
||||
<color name="emphasis">#31b6e7</color>
|
||||
<color name="emphasis2">#4f7a8a</color>
|
||||
|
||||
</resources>
|
||||
|
@ -87,7 +87,7 @@
|
||||
</style>
|
||||
|
||||
<style name="BottomBarActionButton" parent="android:style/Widget.Holo.Light.ActionButton">
|
||||
<item name="android:background">#c8c8c8</item>
|
||||
<item name="android:background">?android:attr/selectableItemBackground</item>
|
||||
</style>
|
||||
|
||||
<style name="TextAppearance_EditEntry_Small">
|
||||
@ -131,6 +131,26 @@
|
||||
<item name="android:layout_marginBottom">-12dip</item>
|
||||
</style>
|
||||
|
||||
<style name="TextAppearance_SubElement">
|
||||
<item name="android:textAppearance">?android:attr/textAppearanceMedium</item>
|
||||
<item name="android:textSize">18sp</item>
|
||||
<item name="android:textColor">#FF333333</item>
|
||||
<item name="android:gravity">center_vertical</item>
|
||||
<item name="android:layout_gravity">center_vertical</item>
|
||||
<item name="android:layout_marginRight">12dip</item>
|
||||
<item name="android:layout_marginLeft">12dip</item>
|
||||
</style>
|
||||
|
||||
<style name="TextAppearance_Help">
|
||||
<item name="android:textAppearance">?android:attr/textAppearanceSmall</item>
|
||||
<item name="android:textSize">24sp</item>
|
||||
<item name="android:padding">12sp</item>
|
||||
<item name="android:gravity">center_vertical</item>
|
||||
<item name="android:layout_gravity">center_vertical</item>
|
||||
<item name="android:layout_marginRight">12dip</item>
|
||||
<item name="android:layout_marginLeft">12dip</item>
|
||||
</style>
|
||||
|
||||
|
||||
<style name="EditEntryButton">
|
||||
<item name="android:textAppearance">?android:attr/textAppearanceSmall</item>
|
||||
|
@ -18,6 +18,19 @@
|
||||
along with Keepass2Android. If not, see <http://www.gnu.org/licenses/>.
|
||||
-->
|
||||
<resources>
|
||||
|
||||
<attr name="help_text" format="string" />
|
||||
<declare-styleable name="Kp2aShortHelpView">
|
||||
<attr name="android:text"/>
|
||||
<attr name="help_text" />
|
||||
</declare-styleable>
|
||||
<declare-styleable name="TextWithHelp">
|
||||
<attr name="android:text"/>
|
||||
<attr name="help_text" />
|
||||
</declare-styleable>
|
||||
|
||||
<string name="icon_info"></string>
|
||||
|
||||
<string name="library_name"></string>
|
||||
<string name="default_file_path">/keepass/keepass.kdbx</string>
|
||||
<string name="donate_url"><![CDATA[http://philipp.crocoll.net/donate.php?lang=%1$s&app=%2$s]]></string>
|
||||
|
@ -153,6 +153,7 @@
|
||||
<string name="pass_filename">KeePass database filename</string>
|
||||
<string name="password_title">Enter database password</string>
|
||||
<string name="progress_create">Creating new database…</string>
|
||||
<string name="create_database">Create database</string>
|
||||
<string name="progress_title">Working…</string>
|
||||
<string name="remember_keyfile_summary">Remembers the location of keyfiles</string>
|
||||
<string name="remember_keyfile_title">Save keyfile</string>
|
||||
@ -333,9 +334,25 @@
|
||||
|
||||
<string name="filestorage_setup_title">File access initialization</string>
|
||||
|
||||
<string name="database_location">Database location</string>
|
||||
<string name="help_database_location">You can store your database locally on your Android device or in the cloud (non-Offline version only). Keepass2Android makes the database available even if you are offline. As the database is securely encrypted with AES 256 bit encryption, nobody will be able to access your passwords except you. We recommend to select Dropbox: It\'s accessible on all your devices and even provides backups of previous file versions.</string>
|
||||
<string name="hint_database_location">Select where you want to store the database:</string>
|
||||
<string name="button_change_location">Change location</string>
|
||||
|
||||
<string name="master_password">Master password</string>
|
||||
<string name="help_master_password">Your database is encrypted with the password you enter here. Choose a strong password in order to keep the database safe! Tip: Make up a sentence or two and use the first letters of the words as password. Include punctuation marks.</string>
|
||||
<string name="hint_master_password">Select a master password to protect your database:</string>
|
||||
|
||||
<string name="key_file">Key file</string>
|
||||
<string name="help_key_file">A key file is basically a password stored in a file. Key files are typically stronger than master passwords, because the key can be a lot more complicated; however it\'s also harder to keep them secret. If you store your database in the cloud, don\'t store the key file there as well! This would make it completely useless! Important: Do not change the contents of the key file after creating the database!</string>
|
||||
<string name="hint_key_file">Choose if you want to use a key file in addition to your master password:</string>
|
||||
<string name="use_key_file">Use key file</string>
|
||||
|
||||
<string name="error_adding_keyfile">Error while adding the keyfile!</string>
|
||||
|
||||
<string name="ChangeLog_title">Change log</string>
|
||||
|
||||
|
||||
<string name="ChangeLog_0_9">
|
||||
<b>Version 0.9 preview</b>\n
|
||||
* Integrated Dropbox support (read/write databases; Keepass2Android regular edition only)\n
|
||||
|
@ -22,8 +22,10 @@ using Android.App;
|
||||
using Android.Content;
|
||||
using Android.Database;
|
||||
using Android.Provider;
|
||||
using Android.Views;
|
||||
using Android.Widget;
|
||||
using Android.Content.PM;
|
||||
using KeePassLib.Serialization;
|
||||
using Uri = Android.Net.Uri;
|
||||
|
||||
namespace keepass2android
|
||||
@ -203,6 +205,52 @@ namespace keepass2android
|
||||
//Actionbar is available since 11, but the layout has its own "pseudo actionbar" until 13
|
||||
return ((int)Android.OS.Build.VERSION.SdkInt >= 14) && (activity.ActionBar != null);
|
||||
}
|
||||
|
||||
|
||||
public static void ShowFilenameDialog(Activity activity, EventHandler onOpen, EventHandler onCreate, bool showBrowseButton,
|
||||
string defaultFilename, string detailsText, int requestCodeBrowse)
|
||||
{
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
|
||||
builder.SetView(activity.LayoutInflater.Inflate(Resource.Layout.file_selection_filename, null));
|
||||
Dialog dialog = builder.Create();
|
||||
dialog.Show();
|
||||
|
||||
Button openButton = (Button) dialog.FindViewById(Resource.Id.open);
|
||||
Button createButton = (Button) dialog.FindViewById(Resource.Id.create);
|
||||
TextView enterFilenameDetails = (TextView) dialog.FindViewById(Resource.Id.label_open_by_filename_details);
|
||||
openButton.Visibility = onOpen != null ? ViewStates.Visible : ViewStates.Gone;
|
||||
createButton.Visibility = onCreate != null? ViewStates.Visible : ViewStates.Gone;
|
||||
// Set the initial value of the filename
|
||||
EditText editFilename = (EditText) dialog.FindViewById(Resource.Id.file_filename);
|
||||
editFilename.Text = defaultFilename;
|
||||
enterFilenameDetails.Text = detailsText;
|
||||
enterFilenameDetails.Visibility = enterFilenameDetails.Text == "" ? ViewStates.Gone : ViewStates.Visible;
|
||||
|
||||
// Open button
|
||||
if (onOpen != null)
|
||||
openButton.Click += onOpen;
|
||||
|
||||
// Create button
|
||||
if (onCreate != null)
|
||||
createButton.Click += onCreate;
|
||||
|
||||
Button cancelButton = (Button) dialog.FindViewById(Resource.Id.fnv_cancel);
|
||||
cancelButton.Click += (sender, e) => dialog.Dismiss();
|
||||
|
||||
ImageButton browseButton = (ImageButton) dialog.FindViewById(Resource.Id.browse_button);
|
||||
if (!showBrowseButton)
|
||||
{
|
||||
browseButton.Visibility = ViewStates.Invisible;
|
||||
}
|
||||
browseButton.Click += (sender, evt) =>
|
||||
{
|
||||
string filename = ((EditText) dialog.FindViewById(Resource.Id.file_filename)).Text;
|
||||
|
||||
Util.ShowBrowseDialog(filename, activity, requestCodeBrowse, onCreate != null);
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -42,6 +42,7 @@ namespace keepass2android
|
||||
public static class AppNames
|
||||
{
|
||||
public const string AppName = "@string/app_name_nonet";
|
||||
public const int AppNameResource = Resource.String.app_name_nonet;
|
||||
public const string AppNameShort = "@string/short_app_name_nonet";
|
||||
public const string AppLauncherTitle = "@string/short_app_name_nonet";
|
||||
public const string PackagePart = "keepass2android_nonet";
|
||||
@ -56,6 +57,7 @@ namespace keepass2android
|
||||
public static class AppNames
|
||||
{
|
||||
public const string AppName = "@string/app_name";
|
||||
public const int AppNameResource = Resource.String.app_name;
|
||||
public const string AppNameShort = "@string/short_app_name";
|
||||
public const string AppLauncherTitle = "@string/app_name";
|
||||
public const string PackagePart = "keepass2android";
|
||||
@ -377,7 +379,7 @@ namespace keepass2android
|
||||
|
||||
}
|
||||
//TODO: catch!
|
||||
throw new Exception("Unknown protocol " + iocInfo.Path);
|
||||
throw new NoFileStorageFoundException("Unknown protocol " + iocInfo.Path);
|
||||
}
|
||||
|
||||
public IEnumerable<IFileStorage> FileStorages
|
||||
|
34
src/keepass2android/app/NoFileStorageFoundException.cs
Normal file
34
src/keepass2android/app/NoFileStorageFoundException.cs
Normal file
@ -0,0 +1,34 @@
|
||||
using System;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
namespace keepass2android
|
||||
{
|
||||
[Serializable]
|
||||
public class NoFileStorageFoundException : Exception
|
||||
{
|
||||
//
|
||||
// For guidelines regarding the creation of new exception types, see
|
||||
// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpgenref/html/cpconerrorraisinghandlingguidelines.asp
|
||||
// and
|
||||
// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dncscol/html/csharp07192001.asp
|
||||
//
|
||||
|
||||
public NoFileStorageFoundException()
|
||||
{
|
||||
}
|
||||
|
||||
public NoFileStorageFoundException(string message) : base(message)
|
||||
{
|
||||
}
|
||||
|
||||
public NoFileStorageFoundException(string message, Exception inner) : base(message, inner)
|
||||
{
|
||||
}
|
||||
|
||||
protected NoFileStorageFoundException(
|
||||
SerializationInfo info,
|
||||
StreamingContext context) : base(info, context)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
@ -66,132 +66,6 @@ namespace keepass2android
|
||||
|
||||
public const string NoForwardToPasswordActivity = "NoForwardToPasswordActivity";
|
||||
|
||||
void ShowFilenameDialog(bool showOpenButton, bool showCreateButton, bool showBrowseButton, string defaultFilename, string detailsText, int requestCodeBrowse)
|
||||
{
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
||||
builder.SetView(LayoutInflater.Inflate(Resource.Layout.file_selection_filename, null));
|
||||
Dialog dialog = builder.Create();
|
||||
dialog.Show();
|
||||
|
||||
Button openButton = (Button)dialog.FindViewById(Resource.Id.open);
|
||||
Button createButton = (Button)dialog.FindViewById(Resource.Id.create);
|
||||
TextView enterFilenameDetails = (TextView)dialog.FindViewById(Resource.Id.label_open_by_filename_details);
|
||||
openButton.Visibility = showOpenButton ? ViewStates.Visible : ViewStates.Gone;
|
||||
createButton.Visibility = showCreateButton ? ViewStates.Visible : ViewStates.Gone;
|
||||
// Set the initial value of the filename
|
||||
EditText editFilename = (EditText)dialog.FindViewById(Resource.Id.file_filename);
|
||||
editFilename.Text = defaultFilename;
|
||||
enterFilenameDetails.Text = detailsText;
|
||||
enterFilenameDetails.Visibility = enterFilenameDetails.Text == "" ? ViewStates.Gone : ViewStates.Visible;
|
||||
|
||||
// Open button
|
||||
|
||||
openButton.Click += ( sender, evt) => {
|
||||
String fileName = ((EditText)dialog.FindViewById(Resource.Id.file_filename)).Text;
|
||||
|
||||
IOConnectionInfo ioc = new IOConnectionInfo
|
||||
{
|
||||
Path = fileName
|
||||
};
|
||||
|
||||
LaunchPasswordActivityForIoc(ioc);
|
||||
};
|
||||
|
||||
|
||||
|
||||
// Create button
|
||||
createButton.Click += (sender, evt) => {
|
||||
String filename = ((EditText)dialog.FindViewById(Resource.Id.file_filename)).Text;
|
||||
|
||||
|
||||
//TODO: allow non-local files?
|
||||
|
||||
// Make sure file name exists
|
||||
if (filename.Length == 0)
|
||||
{
|
||||
Toast
|
||||
.MakeText(this,
|
||||
Resource.String.error_filename_required,
|
||||
ToastLength.Long).Show();
|
||||
return;
|
||||
}
|
||||
|
||||
// Try to create the file
|
||||
Java.IO.File file = new Java.IO.File(filename);
|
||||
try
|
||||
{
|
||||
if (file.Exists())
|
||||
{
|
||||
Toast.MakeText(this,
|
||||
Resource.String.error_database_exists,
|
||||
ToastLength.Long).Show();
|
||||
return;
|
||||
}
|
||||
Java.IO.File parent = file.ParentFile;
|
||||
|
||||
if (parent == null || (parent.Exists() && ! parent.IsDirectory))
|
||||
{
|
||||
Toast.MakeText(this,
|
||||
Resource.String.error_invalid_path,
|
||||
ToastLength.Long).Show();
|
||||
return;
|
||||
}
|
||||
|
||||
if (! parent.Exists())
|
||||
{
|
||||
// Create parent dircetory
|
||||
if (! parent.Mkdirs())
|
||||
{
|
||||
Toast.MakeText(this,
|
||||
Resource.String.error_could_not_create_parent,
|
||||
ToastLength.Long).Show();
|
||||
return;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
file.CreateNewFile();
|
||||
} catch (Java.IO.IOException ex)
|
||||
{
|
||||
Toast.MakeText(
|
||||
this,
|
||||
GetText(Resource.String.error_file_not_create) + " "
|
||||
+ ex.LocalizedMessage,
|
||||
ToastLength.Long).Show();
|
||||
return;
|
||||
}
|
||||
|
||||
// Prep an object to collect a password once the database has been created
|
||||
CollectPassword collectPassword = new CollectPassword(
|
||||
new LaunchGroupActivity(IOConnectionInfo.FromPath(filename), this), this);
|
||||
|
||||
// Create the new database
|
||||
CreateDb create = new CreateDb(App.Kp2a, this, IOConnectionInfo.FromPath(filename), collectPassword, true);
|
||||
ProgressTask createTask = new ProgressTask(
|
||||
App.Kp2a,
|
||||
this, create);
|
||||
createTask.Run();
|
||||
|
||||
|
||||
};
|
||||
|
||||
Button cancelButton = (Button)dialog.FindViewById(Resource.Id.fnv_cancel);
|
||||
cancelButton.Click += (sender, e) => dialog.Dismiss();
|
||||
|
||||
ImageButton browseButton = (ImageButton)dialog.FindViewById(Resource.Id.browse_button);
|
||||
if (!showBrowseButton)
|
||||
{
|
||||
browseButton.Visibility = ViewStates.Invisible;
|
||||
}
|
||||
browseButton.Click += (sender, evt) => {
|
||||
string filename = ((EditText)dialog.FindViewById(Resource.Id.file_filename)).Text;
|
||||
|
||||
Util.ShowBrowseDialog(filename, this, requestCodeBrowse, showCreateButton);
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
protected override void OnCreate(Bundle savedInstanceState)
|
||||
{
|
||||
base.OnCreate(savedInstanceState);
|
||||
@ -248,7 +122,11 @@ namespace keepass2android
|
||||
|
||||
//CREATE NEW
|
||||
Button createNewButton = (Button)FindViewById(Resource.Id.start_create);
|
||||
EventHandler createNewButtonClick = (sender, e) => ShowFilenameDialog(false, true, true, Android.OS.Environment.ExternalStorageDirectory + GetString(Resource.String.default_file_path), "", Intents.RequestCodeFileBrowseForCreate);
|
||||
EventHandler createNewButtonClick = (sender, e) =>
|
||||
{
|
||||
//ShowFilenameDialog(false, true, true, Android.OS.Environment.ExternalStorageDirectory + GetString(Resource.String.default_file_path), "", Intents.RequestCodeFileBrowseForCreate)
|
||||
StartActivityForResult(typeof (CreateDatabaseActivity), 0);
|
||||
};
|
||||
createNewButton.Click += createNewButtonClick;
|
||||
|
||||
/*//CREATE + IMPORT
|
||||
@ -301,55 +179,8 @@ namespace keepass2android
|
||||
|
||||
}
|
||||
|
||||
private class LaunchGroupActivity : FileOnFinish {
|
||||
readonly FileSelectActivity _activity;
|
||||
private readonly IOConnectionInfo _ioc;
|
||||
|
||||
public LaunchGroupActivity(IOConnectionInfo ioc, FileSelectActivity activity): base(null) {
|
||||
|
||||
_activity = activity;
|
||||
_ioc = ioc;
|
||||
}
|
||||
|
||||
public override void Run() {
|
||||
if (Success) {
|
||||
// Update the ongoing notification
|
||||
_activity.StartService(new Intent(_activity, typeof(OngoingNotificationsService)));
|
||||
|
||||
|
||||
if (_activity.RememberRecentFiles())
|
||||
{
|
||||
// Add to recent files
|
||||
FileDbHelper dbHelper = App.Kp2a.FileDbHelper;
|
||||
|
||||
|
||||
//TODO: getFilename always returns "" -> bug?
|
||||
dbHelper.CreateFile(_ioc, Filename);
|
||||
}
|
||||
|
||||
GroupActivity.Launch(_activity, _activity.AppTask);
|
||||
|
||||
} else {
|
||||
App.Kp2a.GetFileStorage(_ioc).Delete(_ioc);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class CollectPassword: FileOnFinish {
|
||||
readonly FileSelectActivity _activity;
|
||||
readonly FileOnFinish _fileOnFinish;
|
||||
public CollectPassword(FileOnFinish finish,FileSelectActivity activity):base(finish) {
|
||||
_activity = activity;
|
||||
_fileOnFinish = finish;
|
||||
}
|
||||
|
||||
public override void Run() {
|
||||
SetPasswordDialog password = new SetPasswordDialog(_activity, _fileOnFinish);
|
||||
password.Show();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void FillData()
|
||||
{
|
||||
@ -428,8 +259,19 @@ namespace keepass2android
|
||||
LaunchPasswordActivityForIoc(ioc);
|
||||
|
||||
}
|
||||
private void OnOpenButton(object sender, EventArgs evt)
|
||||
{
|
||||
Dialog dialog = (Dialog) sender;
|
||||
String fileName = ((EditText)dialog.FindViewById(Resource.Id.file_filename)).Text;
|
||||
|
||||
IOConnectionInfo ioc = new IOConnectionInfo
|
||||
{
|
||||
Path = fileName
|
||||
};
|
||||
|
||||
LaunchPasswordActivityForIoc(ioc);
|
||||
|
||||
}
|
||||
|
||||
protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)
|
||||
{
|
||||
@ -460,7 +302,8 @@ namespace keepass2android
|
||||
OnActivityResult,
|
||||
defaultPath =>
|
||||
{
|
||||
ShowFilenameDialog(true, false, false, defaultPath, GetString(Resource.String.enter_filename_details_url),
|
||||
|
||||
Util.ShowFilenameDialog(this, OnOpenButton, null, false, defaultPath, GetString(Resource.String.enter_filename_details_url),
|
||||
Intents.RequestCodeFileBrowseForOpen);
|
||||
}
|
||||
), false, 0, protocolId);
|
||||
@ -490,10 +333,7 @@ namespace keepass2android
|
||||
LaunchPasswordActivityForIoc(ioc);
|
||||
}
|
||||
|
||||
if (requestCode == Intents.RequestCodeFileBrowseForCreate)
|
||||
{
|
||||
ShowFilenameDialog(false, true, true, filename, "", Intents.RequestCodeFileBrowseForCreate);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@ -521,7 +361,6 @@ namespace keepass2android
|
||||
if (defaultPath.StartsWith("file://"))
|
||||
{
|
||||
fileProviderAuthority = "keepass2android.keepass2android.android-filechooser.localfile";
|
||||
defaultPath = Environment.ExternalStorageDirectory + GetString(Resource.String.default_file_path);
|
||||
}
|
||||
Intent i = Keepass2android.Kp2afilechooser.Kp2aFileChooserBridge.GetLaunchFileChooserIntent(this, fileProviderAuthority,
|
||||
defaultPath);
|
||||
@ -664,10 +503,6 @@ namespace keepass2android
|
||||
Android.Database.ICursor cursor = ca.Cursor;
|
||||
cursor.Requery();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -24,7 +24,7 @@
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>False</Optimize>
|
||||
<OutputPath>bin\Debug</OutputPath>
|
||||
<DefineConstants>DEBUG;EXCLUDE_TWOFISH;EXCLUDE_KEYBOARD;EXCLUDE_KEYTRANSFORM;EXCLUDE_FILECHOOSER;EXCLUDE_JAVAFILESTORAGE</DefineConstants>
|
||||
<DefineConstants>DEBUG;EXCLUDE_TWOFISH;EXCLUDE_KEYBOARD;EXCLUDE_KEYTRANSFORM;INCLUDE_FILECHOOSER;EXCLUDE_JAVAFILESTORAGE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<ConsolePause>False</ConsolePause>
|
||||
@ -78,6 +78,8 @@
|
||||
<Reference Include="Mono.Android.Support.v4" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="app\NoFileStorageFoundException.cs" />
|
||||
<Compile Include="CreateDatabaseActivity.cs" />
|
||||
<Compile Include="fileselect\FileChooserFileProvider.cs" />
|
||||
<Compile Include="fileselect\FileStorageSetupActivity.cs" />
|
||||
<Compile Include="fileselect\FileStorageSetupInitiatorActivity.cs" />
|
||||
@ -108,6 +110,7 @@
|
||||
<Compile Include="views\GroupRootView.cs" />
|
||||
<Compile Include="PwGroupListAdapter.cs" />
|
||||
<Compile Include="views\FileStorageView.cs" />
|
||||
<Compile Include="views\Kp2aShortHelpView.cs" />
|
||||
<Compile Include="views\PwGroupView.cs" />
|
||||
<Compile Include="settings\PrefsUtil.cs" />
|
||||
<Compile Include="views\PwEntryView.cs" />
|
||||
@ -150,9 +153,13 @@
|
||||
<Compile Include="Utils\Spr\SprEngine.cs" />
|
||||
<Compile Include="Utils\Spr\SprEngine.PickChars.cs" />
|
||||
<Compile Include="Utils\EntryUtil.cs" />
|
||||
<Compile Include="views\TextWithHelp.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<AndroidResource Include="Resources\xml\searchable.xml" />
|
||||
<AndroidAsset Include="Assets\fontawesome-webfont.ttf" />
|
||||
<AndroidAsset Include="Assets\DejaVuSansMono.ttf" />
|
||||
<AndroidAsset Include="Assets\LICENSE_dejavu" />
|
||||
<None Include="Resources\AboutResources.txt" />
|
||||
<None Include="Resources\drawable\Thumbs.db">
|
||||
<Visible>False</Visible>
|
||||
@ -654,7 +661,7 @@
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildExtensionsPath)\Novell\Novell.MonoDroid.CSharp.targets" />
|
||||
<ItemGroup>
|
||||
<Folder Include="Assets\" />
|
||||
<Folder Include="Resources\color\" />
|
||||
<Folder Include="SupportLib\" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
@ -841,4 +848,12 @@
|
||||
<ItemGroup>
|
||||
<AndroidResource Include="Resources\drawable\ic_keepass2android_nonet.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<AndroidResource Include="Resources\layout\create_database.xml">
|
||||
<SubType>Designer</SubType>
|
||||
</AndroidResource>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<AndroidResource Include="Resources\layout\text_with_help.xml" />
|
||||
</ItemGroup>
|
||||
</Project>
|
@ -64,7 +64,7 @@ namespace keepass2android.view
|
||||
|
||||
|
||||
} else {
|
||||
tv.Visibility = ViewStates.Invisible;
|
||||
tv.Visibility = ViewStates.Gone;
|
||||
|
||||
}
|
||||
|
||||
|
@ -32,13 +32,8 @@ namespace keepass2android.view
|
||||
{
|
||||
public sealed class FileStorageView : ClickView
|
||||
{
|
||||
private readonly Activity _activity;
|
||||
|
||||
private readonly TextView _textView;
|
||||
private readonly TextView _textviewDetails;
|
||||
private int _pos;
|
||||
|
||||
private int? _defaultTextColor;
|
||||
|
||||
|
||||
public FileStorageView(IntPtr javaReference, JniHandleOwnership transfer)
|
||||
@ -50,8 +45,6 @@ namespace keepass2android.view
|
||||
public FileStorageView(Activity activity, string protocolId, int pos)
|
||||
: base(activity)
|
||||
{
|
||||
_activity = activity;
|
||||
|
||||
View ev = Inflate(activity, Resource.Layout.entry_list_entry, null);
|
||||
_textView = (TextView)ev.FindViewById(Resource.Id.entry_text);
|
||||
_textView.TextSize = PrefsUtil.GetListTextSize(activity);
|
||||
@ -69,9 +62,6 @@ namespace keepass2android.view
|
||||
|
||||
private void PopulateView(View ev, string protocolId, int pos)
|
||||
{
|
||||
|
||||
_pos = pos;
|
||||
|
||||
ImageView iv = (ImageView)ev.FindViewById(Resource.Id.entry_icon);
|
||||
|
||||
Drawable drawable = App.Kp2a.GetResourceDrawable("ic_storage_" + protocolId);
|
||||
|
98
src/keepass2android/views/Kp2aShortHelpView.cs
Normal file
98
src/keepass2android/views/Kp2aShortHelpView.cs
Normal file
@ -0,0 +1,98 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
using Android.App;
|
||||
using Android.Content;
|
||||
using Android.Content.Res;
|
||||
using Android.Graphics;
|
||||
using Android.OS;
|
||||
using Android.Runtime;
|
||||
using Android.Text;
|
||||
using Android.Text.Method;
|
||||
using Android.Text.Style;
|
||||
using Android.Text.Util;
|
||||
using Android.Util;
|
||||
using Android.Views;
|
||||
using Android.Widget;
|
||||
|
||||
namespace keepass2android.views
|
||||
{
|
||||
public class Kp2aShortHelpView: TextView
|
||||
{
|
||||
private string _helpText;
|
||||
private static Typeface _iconFont;
|
||||
|
||||
protected Kp2aShortHelpView(IntPtr javaReference, JniHandleOwnership transfer) : base(javaReference, transfer)
|
||||
{
|
||||
}
|
||||
|
||||
public Kp2aShortHelpView(Context context) : base(context)
|
||||
{
|
||||
}
|
||||
|
||||
public Kp2aShortHelpView(Context context, IAttributeSet attrs) : base(context, attrs)
|
||||
{
|
||||
Initialize(attrs);
|
||||
}
|
||||
|
||||
public Kp2aShortHelpView(Context context, IAttributeSet attrs, int defStyle) : base(context, attrs, defStyle)
|
||||
{
|
||||
Initialize(attrs);
|
||||
}
|
||||
|
||||
public string HelpText
|
||||
{
|
||||
get { return _helpText; }
|
||||
set { _helpText = value;
|
||||
UpdateView();
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateView()
|
||||
{
|
||||
if (!String.IsNullOrEmpty(_helpText))
|
||||
{
|
||||
Text = Context.GetString(Resource.String.icon_info);
|
||||
Clickable = true;
|
||||
|
||||
|
||||
if (_iconFont == null)
|
||||
_iconFont = Typeface.CreateFromAsset(Context.Assets, "fontawesome-webfont.ttf");
|
||||
|
||||
System.Diagnostics.Debug.Assert(_iconFont != null, "_iconFont != null");
|
||||
|
||||
SetTypeface(_iconFont, TypefaceStyle.Normal);
|
||||
//TextFormatted = Html.FromHtml("<a>" + Text + "</a>");
|
||||
//var spannableString = new SpannableString(Text);
|
||||
//spannableString.SetSpan(new UnderlineSpan(), 0, Text.Length, SpanTypes.ExclusiveExclusive);
|
||||
//TextFormatted = spannableString;
|
||||
|
||||
MovementMethod = LinkMovementMethod.Instance;
|
||||
Click += (sender, args) =>
|
||||
{
|
||||
new AlertDialog.Builder(Context)
|
||||
.SetTitle(Context.GetString(AppNames.AppNameResource))
|
||||
.SetMessage(_helpText)
|
||||
.SetPositiveButton(Android.Resource.String.Ok, (o, eventArgs) => { })
|
||||
.Show();
|
||||
};
|
||||
Visibility = ViewStates.Visible;
|
||||
}
|
||||
else
|
||||
{
|
||||
Visibility = ViewStates.Gone;
|
||||
}
|
||||
}
|
||||
|
||||
void Initialize(IAttributeSet attrs)
|
||||
{
|
||||
TypedArray a = Context.ObtainStyledAttributes(
|
||||
attrs,
|
||||
Resource.Styleable.Kp2aShortHelpView);
|
||||
HelpText = a.GetString(Resource.Styleable.Kp2aShortHelpView_help_text);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
46
src/keepass2android/views/TextWithHelp.cs
Normal file
46
src/keepass2android/views/TextWithHelp.cs
Normal file
@ -0,0 +1,46 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
using Android.App;
|
||||
using Android.Content;
|
||||
using Android.Content.Res;
|
||||
using Android.OS;
|
||||
using Android.Runtime;
|
||||
using Android.Util;
|
||||
using Android.Views;
|
||||
using Android.Widget;
|
||||
|
||||
namespace keepass2android.views
|
||||
{
|
||||
public class TextWithHelp : RelativeLayout
|
||||
{
|
||||
public TextWithHelp(Context context, IAttributeSet attrs) :
|
||||
base(context, attrs)
|
||||
{
|
||||
Initialize(attrs);
|
||||
}
|
||||
|
||||
public TextWithHelp(Context context, IAttributeSet attrs, int defStyle) :
|
||||
base(context, attrs, defStyle)
|
||||
{
|
||||
Initialize(attrs);
|
||||
}
|
||||
|
||||
private void Initialize(IAttributeSet attrs)
|
||||
{
|
||||
LayoutInflater inflater = (LayoutInflater)Context.GetSystemService(Context.LayoutInflaterService);
|
||||
inflater.Inflate(Resource.Layout.text_with_help, this);
|
||||
|
||||
TypedArray a = Context.ObtainStyledAttributes(
|
||||
attrs,
|
||||
Resource.Styleable.TextWithHelp);
|
||||
((Kp2aShortHelpView)FindViewById(Resource.Id.help)).HelpText = a.GetString(Resource.Styleable.TextWithHelp_help_text);
|
||||
|
||||
const string xmlns = "http://schemas.android.com/apk/res/android";
|
||||
((TextView)FindViewById(Resource.Id.text)).Text = Context.GetString(attrs.GetAttributeResourceValue(xmlns, "text",Resource.String.ellipsis));
|
||||
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user