rename back to current names
This commit is contained in:
127
src/keepass2android-app/fileselect/FileChooserFileProvider.cs
Normal file
127
src/keepass2android-app/fileselect/FileChooserFileProvider.cs
Normal file
@@ -0,0 +1,127 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Android.Content;
|
||||
using KeePassLib.Serialization;
|
||||
#if !EXCLUDE_FILECHOOSER
|
||||
using Keepass2android.Kp2afilechooser;
|
||||
#endif
|
||||
using keepass2android.Io;
|
||||
|
||||
namespace keepass2android
|
||||
{
|
||||
#if !EXCLUDE_FILECHOOSER
|
||||
[ContentProvider(new[] { "keepass2android." + AppNames.PackagePart + ".kp2afilechooser.kp2afile" }, Exported = false)]
|
||||
public class FileChooserFileProvider : Kp2aFileProvider
|
||||
{
|
||||
/*int taskId, final String dirName,
|
||||
final boolean showHiddenFiles, final int filterMode,
|
||||
final int limit, String positiveRegex, String negativeRegex,
|
||||
final List<FileEntry> results, final boolean hasMoreFiles[]*/
|
||||
|
||||
public override string Authority
|
||||
{
|
||||
get { return TheAuthority; }
|
||||
}
|
||||
|
||||
public static string TheAuthority
|
||||
{
|
||||
get { return "keepass2android." + AppNames.PackagePart + ".kp2afilechooser.kp2afile"; }
|
||||
}
|
||||
|
||||
protected override bool CreateDirectory(string parentDirectory, string newDirName)
|
||||
{
|
||||
|
||||
try
|
||||
{
|
||||
App.Kp2a.GetFileStorage(parentDirectory).CreateDirectory(ConvertPathToIoc(parentDirectory), newDirName);
|
||||
return true;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Kp2aLog.LogUnexpectedError(e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private IOConnectionInfo ConvertPathToIoc(string path)
|
||||
{
|
||||
return new IOConnectionInfo() { Path = path };
|
||||
}
|
||||
|
||||
protected override bool DeletePath(string path, bool recursive)
|
||||
{
|
||||
try
|
||||
{
|
||||
App.Kp2a.GetFileStorage(path).Delete(ConvertPathToIoc(path));
|
||||
return true;
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
Kp2aLog.LogUnexpectedError(e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
protected override FileEntry GetFileEntry(string filename, Java.Lang.StringBuilder errorMessageBuilder)
|
||||
{
|
||||
try
|
||||
{
|
||||
return ConvertFileDescription(App.Kp2a.GetFileStorage(filename).GetFileDescription(ConvertPathToIoc(filename)));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
if (errorMessageBuilder != null)
|
||||
errorMessageBuilder.Append(e.Message);
|
||||
Kp2aLog.Log(e.ToString());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected override void ListFiles(int taskId, string dirName, bool showHiddenFiles, int filterMode, int limit, string positiveRegex,
|
||||
string negativeRegex, IList<FileEntry> fileList, bool[] hasMoreFiles)
|
||||
{
|
||||
try
|
||||
{
|
||||
var dirContents = App.Kp2a.GetFileStorage(dirName).ListContents(ConvertPathToIoc(dirName));
|
||||
foreach (FileDescription e in dirContents)
|
||||
{
|
||||
fileList.Add(ConvertFileDescription(e));
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Kp2aLog.LogUnexpectedError(e);
|
||||
}
|
||||
}
|
||||
|
||||
private FileEntry ConvertFileDescription(FileDescription e)
|
||||
{
|
||||
return new FileEntry
|
||||
{
|
||||
CanRead = e.CanRead,
|
||||
CanWrite = e.CanWrite,
|
||||
DisplayName = e.DisplayName,
|
||||
IsDirectory = e.IsDirectory,
|
||||
LastModifiedTime = CSharpTimeToJava(e.LastModified),
|
||||
Path = e.Path,
|
||||
SizeInBytes = e.SizeInBytes
|
||||
};
|
||||
}
|
||||
|
||||
private long CSharpTimeToJava(DateTime dateTime)
|
||||
{
|
||||
try
|
||||
{
|
||||
return (long)dateTime.Subtract(new DateTime(1970, 1, 1)).TotalMilliseconds;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
305
src/keepass2android-app/fileselect/FileDbHelper.cs
Normal file
305
src/keepass2android-app/fileselect/FileDbHelper.cs
Normal file
@@ -0,0 +1,305 @@
|
||||
/*
|
||||
This file is part of Keepass2Android, Copyright 2013 Philipp Crocoll. This file is based on Keepassdroid, Copyright Brian Pellin.
|
||||
|
||||
Keepass2Android is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Keepass2Android is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Keepass2Android. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using Android.Content;
|
||||
using Android.Database;
|
||||
using Android.Database.Sqlite;
|
||||
using KeePassLib.Serialization;
|
||||
|
||||
namespace keepass2android
|
||||
{
|
||||
/// <summary>
|
||||
/// Class to store the recent files in a database
|
||||
/// </summary>
|
||||
public class FileDbHelper {
|
||||
|
||||
public const String LastFilename = "lastFile";
|
||||
public const String LastKeyfile = "lastKey";
|
||||
|
||||
private const String DatabaseName = "keepass2android";
|
||||
private const String FileTable = "files";
|
||||
private const int DatabaseVersion = 2;
|
||||
|
||||
private const int MaxFiles = 1000;
|
||||
|
||||
public const String KeyFileId = "_id";
|
||||
public const String KeyFileFilename = "fileName";
|
||||
public const String KeyFileDisplayname = "displayname";
|
||||
public const String KeyFileUsername = "username";
|
||||
public const String KeyFilePassword = "password";
|
||||
public const String KeyFileCredsavemode = "credSaveMode";
|
||||
public const String KeyFileKeyfile = "keyFile";
|
||||
public const String KeyFileUpdated = "updated";
|
||||
|
||||
private const String DatabaseCreate =
|
||||
"create table " + FileTable + " ( " + KeyFileId + " integer primary key autoincrement, "
|
||||
+ KeyFileFilename + " text not null, "
|
||||
+ KeyFileKeyfile + " text, "
|
||||
+ KeyFileUsername + " text, "
|
||||
+ KeyFilePassword + " text, "
|
||||
+ KeyFileCredsavemode + " integer not null,"
|
||||
+ KeyFileUpdated + " integer not null,"
|
||||
+ KeyFileDisplayname + " text "
|
||||
+");";
|
||||
|
||||
private readonly Context mCtx;
|
||||
private DatabaseHelper mDbHelper;
|
||||
private SQLiteDatabase mDb;
|
||||
|
||||
private class DatabaseHelper : SQLiteOpenHelper {
|
||||
public DatabaseHelper(Context ctx): base(ctx, FileDbHelper.DatabaseName, null, DatabaseVersion) {
|
||||
}
|
||||
|
||||
|
||||
public override void OnCreate(SQLiteDatabase db) {
|
||||
db.ExecSQL(DatabaseCreate);
|
||||
|
||||
}
|
||||
|
||||
|
||||
public override void OnUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
|
||||
if (oldVersion == 1)
|
||||
{
|
||||
db.ExecSQL("alter table " + FileTable + " add column " + KeyFileDisplayname + " text ");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public FileDbHelper(Context ctx) {
|
||||
mCtx = ctx;
|
||||
}
|
||||
|
||||
public FileDbHelper Open() {
|
||||
mDbHelper = new DatabaseHelper(mCtx);
|
||||
mDb = mDbHelper.WritableDatabase;
|
||||
return this;
|
||||
}
|
||||
|
||||
public bool IsOpen() {
|
||||
return mDb.IsOpen;
|
||||
}
|
||||
|
||||
public void Close() {
|
||||
mDb.Close();
|
||||
}
|
||||
|
||||
public long CreateFile(IOConnectionInfo ioc, string keyFile, bool updateLastUsageTimestamp, string displayName = "") {
|
||||
|
||||
// Check to see if this filename is already used
|
||||
ICursor cursor;
|
||||
try {
|
||||
cursor = mDb.Query(true, FileTable, new[] {KeyFileId},
|
||||
KeyFileFilename + "=?", new[] {ioc.Path}, null, null, null, null);
|
||||
} catch (Exception ) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
IOConnectionInfo iocToStore = ioc.CloneDeep();
|
||||
if (ioc.CredSaveMode != IOCredSaveMode.SaveCred)
|
||||
iocToStore.Password = "";
|
||||
if (ioc.CredSaveMode == IOCredSaveMode.NoSave)
|
||||
iocToStore.UserName = "";
|
||||
|
||||
iocToStore.Obfuscate(true);
|
||||
|
||||
long result;
|
||||
// If there is an existing entry update it
|
||||
if ( cursor.Count > 0 ) {
|
||||
cursor.MoveToFirst();
|
||||
long id = cursor.GetLong(cursor.GetColumnIndexOrThrow(KeyFileId));
|
||||
|
||||
var vals = new ContentValues();
|
||||
vals.Put(KeyFileKeyfile, keyFile);
|
||||
if (updateLastUsageTimestamp)
|
||||
vals.Put(KeyFileUpdated, Java.Lang.JavaSystem.CurrentTimeMillis());
|
||||
|
||||
vals.Put(KeyFileUsername, iocToStore.UserName);
|
||||
vals.Put(KeyFilePassword, iocToStore.Password);
|
||||
vals.Put(KeyFileCredsavemode, (int)iocToStore.CredSaveMode);
|
||||
vals.Put(KeyFileDisplayname, displayName);
|
||||
|
||||
result = mDb.Update(FileTable, vals, KeyFileId + " = " + id, null);
|
||||
|
||||
// Otherwise add the new entry
|
||||
} else {
|
||||
var vals = new ContentValues();
|
||||
vals.Put(KeyFileFilename, ioc.Path);
|
||||
vals.Put(KeyFileKeyfile, keyFile);
|
||||
vals.Put(KeyFileUsername, iocToStore.UserName);
|
||||
vals.Put(KeyFilePassword, iocToStore.Password);
|
||||
vals.Put(KeyFileCredsavemode, (int)iocToStore.CredSaveMode);
|
||||
vals.Put(KeyFileUpdated, updateLastUsageTimestamp ? Java.Lang.JavaSystem.CurrentTimeMillis(): 0);
|
||||
vals.Put(KeyFileDisplayname, displayName);
|
||||
|
||||
result = mDb.Insert(FileTable, null, vals);
|
||||
|
||||
}
|
||||
// Delete all but the last X records
|
||||
try {
|
||||
DeleteAllBut(MaxFiles);
|
||||
} catch (Exception ex) {
|
||||
Android.Util.Log.Error("ex",ex.StackTrace);
|
||||
|
||||
}
|
||||
|
||||
cursor.Close();
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
private void DeleteAllBut(int limit) {
|
||||
ICursor cursor = mDb.Query(FileTable, new[] {KeyFileUpdated}, null, null, null, null, KeyFileUpdated);
|
||||
|
||||
if ( cursor.Count > limit ) {
|
||||
cursor.MoveToFirst();
|
||||
long time = cursor.GetLong(cursor.GetColumnIndexOrThrow(KeyFileUpdated));
|
||||
|
||||
mDb.ExecSQL("DELETE FROM " + FileTable + " WHERE " + KeyFileUpdated + "<" + time + ";");
|
||||
}
|
||||
|
||||
cursor.Close();
|
||||
|
||||
}
|
||||
|
||||
public void DeleteAllKeys() {
|
||||
var vals = new ContentValues();
|
||||
vals.Put(KeyFileKeyfile, "");
|
||||
|
||||
mDb.Update(FileTable, vals, null, null);
|
||||
}
|
||||
|
||||
public void DeleteFile(String filename) {
|
||||
mDb.Delete(FileTable, KeyFileFilename + " = ?", new[] {filename});
|
||||
}
|
||||
public void DeleteAll()
|
||||
{
|
||||
mDb.Delete(FileTable, null, null);
|
||||
}
|
||||
|
||||
static string[] GetColumnList()
|
||||
{
|
||||
return new[] {
|
||||
KeyFileId,
|
||||
KeyFileFilename,
|
||||
KeyFileKeyfile,
|
||||
KeyFileUsername,
|
||||
KeyFilePassword,
|
||||
KeyFileCredsavemode,
|
||||
KeyFileDisplayname
|
||||
};
|
||||
}
|
||||
|
||||
public ICursor FetchAllFiles()
|
||||
{
|
||||
ICursor ret = mDb.Query(FileTable, GetColumnList(),
|
||||
null, null, null, null, KeyFileUpdated + " DESC", MaxFiles.ToString(CultureInfo.InvariantCulture));
|
||||
return ret;
|
||||
}
|
||||
|
||||
public ICursor FetchFile(long fileId) {
|
||||
ICursor cursor = mDb.Query(true, FileTable, GetColumnList(),
|
||||
KeyFileId + "=" + fileId, null, null, null, null, null);
|
||||
|
||||
if ( cursor != null ) {
|
||||
cursor.MoveToFirst();
|
||||
}
|
||||
|
||||
return cursor;
|
||||
|
||||
}
|
||||
|
||||
public ICursor FetchFileByName(string fileName)
|
||||
{
|
||||
|
||||
ICursor cursor = mDb.Query(true, FileTable, GetColumnList(),
|
||||
KeyFileFilename + " like " + DatabaseUtils.SqlEscapeString(fileName) , null, null, null, null, null);
|
||||
|
||||
if ( cursor != null ) {
|
||||
cursor.MoveToFirst();
|
||||
}
|
||||
|
||||
return cursor;
|
||||
|
||||
}
|
||||
|
||||
public String GetKeyFileForFile(String name) {
|
||||
ICursor cursor = mDb.Query(true, FileTable, GetColumnList(),
|
||||
KeyFileFilename + "= ?", new[] {name}, null, null, null, null);
|
||||
|
||||
if ( cursor == null ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String keyfileFilename;
|
||||
|
||||
if ( cursor.MoveToFirst() ) {
|
||||
keyfileFilename = cursor.GetString(cursor.GetColumnIndexOrThrow(KeyFileKeyfile));
|
||||
} else {
|
||||
// Cursor is empty
|
||||
keyfileFilename = null;
|
||||
}
|
||||
cursor.Close();
|
||||
if (keyfileFilename == "")
|
||||
return null;
|
||||
return keyfileFilename;
|
||||
}
|
||||
|
||||
public bool HasRecentFiles()
|
||||
{
|
||||
return NumberOfRecentFiles() > 0;
|
||||
}
|
||||
|
||||
public int NumberOfRecentFiles()
|
||||
{
|
||||
ICursor cursor = FetchAllFiles();
|
||||
|
||||
int numRecent = cursor.Count;
|
||||
cursor.Close();
|
||||
|
||||
return numRecent;
|
||||
}
|
||||
|
||||
public IOConnectionInfo CursorToIoc(ICursor cursor)
|
||||
{
|
||||
if (cursor == null)
|
||||
return null;
|
||||
var ioc = new IOConnectionInfo
|
||||
{
|
||||
Path = cursor.GetString(cursor
|
||||
.GetColumnIndexOrThrow(KeyFileFilename)),
|
||||
UserName = cursor.GetString(cursor
|
||||
.GetColumnIndexOrThrow(KeyFileUsername)),
|
||||
Password = cursor.GetString(cursor
|
||||
.GetColumnIndexOrThrow(KeyFilePassword)),
|
||||
CredSaveMode = (IOCredSaveMode) cursor.GetInt(cursor
|
||||
.GetColumnIndexOrThrow(KeyFileCredsavemode)),
|
||||
CredProtMode = IOCredProtMode.Obf
|
||||
};
|
||||
|
||||
ioc.Obfuscate(false);
|
||||
|
||||
return ioc;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
596
src/keepass2android-app/fileselect/FileSelectActivity.cs
Normal file
596
src/keepass2android-app/fileselect/FileSelectActivity.cs
Normal file
@@ -0,0 +1,596 @@
|
||||
/*
|
||||
This file is part of Keepass2Android, Copyright 2013 Philipp Crocoll. This file is based on Keepassdroid, Copyright Brian Pellin.
|
||||
|
||||
Keepass2Android is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Keepass2Android is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Keepass2Android. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Android.App;
|
||||
using Android.Content;
|
||||
using Android.Database;
|
||||
using Android.OS;
|
||||
using Android.Preferences;
|
||||
using Android.Runtime;
|
||||
using Android.Views;
|
||||
using Android.Widget;
|
||||
using Android.Content.PM;
|
||||
using Java.IO;
|
||||
using KeePassLib.Serialization;
|
||||
using Keepass2android.Pluginsdk;
|
||||
using keepass2android.Io;
|
||||
using keepass2android;
|
||||
using Console = System.Console;
|
||||
using Environment = Android.OS.Environment;
|
||||
using Google.Android.Material.AppBar;
|
||||
using Android.Util;
|
||||
|
||||
namespace keepass2android
|
||||
{
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Activity to select the file to use
|
||||
/// </summary>
|
||||
[Activity (Label = "@string/app_name",
|
||||
ConfigurationChanges=ConfigChanges.Orientation|
|
||||
ConfigChanges.KeyboardHidden,
|
||||
Theme = "@style/Kp2aTheme_BlueNoActionBar")]
|
||||
public class FileSelectActivity : AndroidX.AppCompat.App.AppCompatActivity
|
||||
{
|
||||
private readonly ActivityDesign _design;
|
||||
public FileSelectActivity (IntPtr javaReference, JniHandleOwnership transfer)
|
||||
: base(javaReference, transfer)
|
||||
{
|
||||
_design = new ActivityDesign(this);
|
||||
}
|
||||
|
||||
public FileSelectActivity()
|
||||
{
|
||||
_design = new ActivityDesign(this);
|
||||
}
|
||||
|
||||
private const int CmenuClear = Menu.First;
|
||||
|
||||
const string BundleKeyRecentMode = "RecentMode";
|
||||
|
||||
private FileDbHelper _dbHelper;
|
||||
|
||||
private bool _recentMode;
|
||||
|
||||
|
||||
private const int RequestCodeSelectIoc = 456;
|
||||
private const int RequestCodeEditIoc = 457;
|
||||
|
||||
public const string NoForwardToPasswordActivity = "NoForwardToPasswordActivity";
|
||||
|
||||
protected override void OnCreate(Bundle savedInstanceState)
|
||||
{
|
||||
_design.ApplyTheme();
|
||||
base.OnCreate(savedInstanceState);
|
||||
|
||||
|
||||
Kp2aLog.Log("FileSelect.OnCreate");
|
||||
|
||||
|
||||
|
||||
_dbHelper = App.Kp2a.FileDbHelper;
|
||||
SetContentView(Resource.Layout.file_selection);
|
||||
|
||||
var collapsingToolbar = FindViewById<CollapsingToolbarLayout>(Resource.Id.collapsing_toolbar);
|
||||
collapsingToolbar.Title = "";
|
||||
SetSupportActionBar(FindViewById<AndroidX.AppCompat.Widget.Toolbar>(Resource.Id.toolbar));
|
||||
SupportActionBar.Title = "";
|
||||
|
||||
|
||||
if (ShowRecentFiles())
|
||||
{
|
||||
_recentMode = true;
|
||||
|
||||
|
||||
FindViewById(Resource.Id.recent_files).Visibility = ViewStates.Visible;
|
||||
Android.Util.Log.Debug("KP2A", "Recent files visible");
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
FindViewById(Resource.Id.recent_files).Visibility = ViewStates.Invisible;
|
||||
Android.Util.Log.Debug("KP2A", "Recent files invisible");
|
||||
#if NoNet
|
||||
ImageView imgView = FindViewById(Resource.Id.splashlogo) as ImageView;
|
||||
if (imgView != null)
|
||||
{
|
||||
imgView.SetImageDrawable(Resources.GetDrawable(Resource.Drawable.splashlogo_offline));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
Button openFileButton = (Button)FindViewById(Resource.Id.start_open_file);
|
||||
|
||||
EventHandler openFileButtonClick = (sender, e) =>
|
||||
{
|
||||
Intent intent = new Intent(this, typeof(SelectStorageLocationActivity));
|
||||
intent.PutExtra(FileStorageSelectionActivity.AllowThirdPartyAppGet, true);
|
||||
intent.PutExtra(FileStorageSelectionActivity.AllowThirdPartyAppSend, false);
|
||||
intent.PutExtra(SelectStorageLocationActivity.ExtraKeyWritableRequirements, (int) SelectStorageLocationActivity.WritableRequirements.WriteDesired);
|
||||
intent.PutExtra(FileStorageSetupDefs.ExtraIsForSave, false);
|
||||
StartActivityForResult(intent, RequestCodeSelectIoc);
|
||||
};
|
||||
openFileButton.Click += openFileButtonClick;
|
||||
|
||||
//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)
|
||||
Intent i = new Intent(this, typeof (CreateDatabaseActivity));
|
||||
i.PutExtra("MakeCurrent", Intent.GetBooleanExtra("MakeCurrent", true));
|
||||
|
||||
i.SetFlags(ActivityFlags.ForwardResult);
|
||||
StartActivity(i);
|
||||
Finish();
|
||||
};
|
||||
createNewButton.Click += createNewButtonClick;
|
||||
|
||||
/*//CREATE + IMPORT
|
||||
Button createImportButton = (Button)FindViewById(Resource.Id.start_create_import);
|
||||
createImportButton.Click += (object sender, EventArgs e) =>
|
||||
{
|
||||
openButton.Visibility = ViewStates.Gone;
|
||||
createButton.Visibility = ViewStates.Visible;
|
||||
enterFilenameDetails.Text = GetString(Resource.String.enter_filename_details_create_import);
|
||||
enterFilenameDetails.Visibility = enterFilenameDetails.Text == "" ? ViewStates.Gone : ViewStates.Visible;
|
||||
// Set the initial value of the filename
|
||||
EditText filename = (EditText)FindViewById(Resource.Id.file_filename);
|
||||
filename.Text = Android.OS.Environment.ExternalStorageDirectory + GetString(Resource.String.default_file_path);
|
||||
|
||||
};*/
|
||||
|
||||
FindViewById<Switch>(Resource.Id.local_backups_switch).CheckedChange += (sender, args) => {FillData();};
|
||||
|
||||
FillData();
|
||||
|
||||
if (savedInstanceState != null)
|
||||
{
|
||||
_recentMode = savedInstanceState.GetBoolean(BundleKeyRecentMode, _recentMode);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private bool ShowRecentFiles()
|
||||
{
|
||||
if (!RememberRecentFiles())
|
||||
{
|
||||
_dbHelper.DeleteAll();
|
||||
}
|
||||
|
||||
return _dbHelper.HasRecentFiles();
|
||||
}
|
||||
|
||||
private bool RememberRecentFiles()
|
||||
{
|
||||
return PreferenceManager.GetDefaultSharedPreferences(this).GetBoolean(GetString(Resource.String.RememberRecentFiles_key), Resources.GetBoolean(Resource.Boolean.RememberRecentFiles_default));
|
||||
}
|
||||
|
||||
|
||||
protected override void OnSaveInstanceState(Bundle outState)
|
||||
{
|
||||
base.OnSaveInstanceState(outState);
|
||||
|
||||
outState.PutBoolean(BundleKeyRecentMode, _recentMode);
|
||||
|
||||
}
|
||||
|
||||
class MyCursorAdapter: CursorAdapter
|
||||
{
|
||||
private LayoutInflater cursorInflater;
|
||||
private readonly FileSelectActivity _activity;
|
||||
private IKp2aApp _app;
|
||||
|
||||
public MyCursorAdapter(IntPtr javaReference, JniHandleOwnership transfer) : base(javaReference, transfer)
|
||||
{
|
||||
}
|
||||
|
||||
public MyCursorAdapter(FileSelectActivity activity, ICursor c, IKp2aApp app) : base(activity, c)
|
||||
{
|
||||
_activity = activity;
|
||||
_app = app;
|
||||
}
|
||||
|
||||
public MyCursorAdapter(Context context, ICursor c, bool autoRequery) : base(context, c, autoRequery)
|
||||
{
|
||||
}
|
||||
|
||||
public MyCursorAdapter(Context context, ICursor c, CursorAdapterFlags flags) : base(context, c, flags)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public override void BindView(View view, Context context, ICursor cursor)
|
||||
{
|
||||
|
||||
String path = cursor.GetString(1);
|
||||
|
||||
TextView textView = view.FindViewById<TextView>(Resource.Id.file_filename);
|
||||
IOConnectionInfo ioc = new IOConnectionInfo { Path = path };
|
||||
var fileStorage = _app.GetFileStorage(ioc);
|
||||
|
||||
String displayName = cursor.GetString(6);
|
||||
if (string.IsNullOrEmpty(displayName))
|
||||
{
|
||||
displayName = fileStorage.GetDisplayName(ioc);
|
||||
|
||||
}
|
||||
|
||||
textView.Text = displayName;
|
||||
textView.Tag = ioc.Path;
|
||||
|
||||
}
|
||||
|
||||
public override View NewView(Context context, ICursor cursor, ViewGroup parent)
|
||||
{
|
||||
if (cursorInflater == null)
|
||||
cursorInflater = (LayoutInflater)context.GetSystemService( Context.LayoutInflaterService);
|
||||
View view = cursorInflater.Inflate(Resource.Layout.file_row, parent, false);
|
||||
|
||||
view.FindViewById(Resource.Id.group_name_vdots).Click += (sender, args) =>
|
||||
{
|
||||
Handler handler = new Handler(Looper.MainLooper);
|
||||
handler.Post(() =>
|
||||
{
|
||||
PopupMenu popupMenu = new PopupMenu(context, view.FindViewById(Resource.Id.group_name_vdots));
|
||||
|
||||
AccessManager.PreparePopup(popupMenu);
|
||||
int remove = 0;
|
||||
int edit = 1;
|
||||
popupMenu.Menu.Add(0, remove, 0, context.GetString(Resource.String.remove_from_filelist)).SetIcon(Resource.Drawable.baseline_delete_24);
|
||||
|
||||
TextView textView = view.FindViewById<TextView>(Resource.Id.file_filename);
|
||||
|
||||
String filename = (string)textView.Tag;
|
||||
IOConnectionInfo ioc = new IOConnectionInfo { Path = filename };
|
||||
if (FileSelectHelper.CanEditIoc(ioc))
|
||||
{
|
||||
popupMenu.Menu.Add(0, edit, 0, context.GetString(Resource.String.edit)).SetIcon(Resource.Drawable.baseline_edit_24);
|
||||
}
|
||||
|
||||
|
||||
popupMenu.MenuItemClick += delegate(object sender2, PopupMenu.MenuItemClickEventArgs args2)
|
||||
{
|
||||
if (args2.Item.ItemId == remove)
|
||||
{
|
||||
if (new LocalFileStorage(App.Kp2a).IsLocalBackup(IOConnectionInfo.FromPath(filename)))
|
||||
{
|
||||
try
|
||||
{
|
||||
Java.IO.File file = new Java.IO.File(filename);
|
||||
file.Delete();
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
Kp2aLog.LogUnexpectedError(exception);
|
||||
}
|
||||
}
|
||||
|
||||
App.Kp2a.FileDbHelper.DeleteFile(filename);
|
||||
|
||||
cursor.Requery();
|
||||
}
|
||||
if (args2.Item.ItemId == edit)
|
||||
{
|
||||
var fsh = new FileSelectHelper(_activity, false, false, RequestCodeEditIoc);
|
||||
fsh.OnOpen += (o, newConnectionInfo) =>
|
||||
{
|
||||
_activity.EditFileEntry(filename, newConnectionInfo);
|
||||
};
|
||||
fsh.PerformManualFileSelect(filename);
|
||||
|
||||
}
|
||||
};
|
||||
popupMenu.Show();
|
||||
});
|
||||
};
|
||||
|
||||
view.FindViewById(Resource.Id.file_filename).Click += (sender, args) =>
|
||||
{
|
||||
TextView textView = view.FindViewById<TextView>(Resource.Id.file_filename);
|
||||
|
||||
String filename = (string)textView.Tag;
|
||||
IOConnectionInfo ioc = new IOConnectionInfo { Path = filename };
|
||||
|
||||
App.Kp2a.GetFileStorage(ioc)
|
||||
.PrepareFileUsage(new FileStorageSetupInitiatorActivity(_activity, _activity.OnActivityResult, null), ioc, 0, false);
|
||||
};
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
private void EditFileEntry(string filename, IOConnectionInfo newConnectionInfo)
|
||||
{
|
||||
try
|
||||
{
|
||||
App.Kp2a.GetFileStorage(newConnectionInfo);
|
||||
}
|
||||
catch (NoFileStorageFoundException)
|
||||
{
|
||||
Toast.MakeText(this, "Don't know how to handle " + newConnectionInfo.Path, ToastLength.Long).Show();
|
||||
return;
|
||||
}
|
||||
|
||||
_dbHelper.CreateFile(newConnectionInfo, _dbHelper.GetKeyFileForFile(filename), false);
|
||||
_dbHelper.DeleteFile(filename);
|
||||
|
||||
LaunchPasswordActivityForIoc(newConnectionInfo);
|
||||
|
||||
}
|
||||
|
||||
|
||||
private void FillData()
|
||||
{
|
||||
// Get all of the rows from the database and create the item list
|
||||
ICursor filesCursor = _dbHelper.FetchAllFiles();
|
||||
|
||||
|
||||
|
||||
if (FindViewById<Switch>(Resource.Id.local_backups_switch).Checked == false)
|
||||
{
|
||||
var fileStorage = new LocalFileStorage(App.Kp2a);
|
||||
filesCursor = new FilteredCursor(filesCursor, cursor => !fileStorage.IsLocalBackup(IOConnectionInfo.FromPath(cursor.GetString(1))));
|
||||
}
|
||||
|
||||
StartManagingCursor(filesCursor);
|
||||
|
||||
FragmentManager.FindFragmentById<RecentFilesFragment>(Resource.Id.recent_files).SetAdapter(new MyCursorAdapter(this, filesCursor,App.Kp2a));
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
void LaunchPasswordActivityForIoc(IOConnectionInfo ioc)
|
||||
{
|
||||
IFileStorage fileStorage = App.Kp2a.GetFileStorage(ioc);
|
||||
|
||||
if (fileStorage.RequiresCredentials(ioc))
|
||||
{
|
||||
Util.QueryCredentials(ioc, AfterQueryCredentials, this);
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
PasswordActivity.Launch(this, ioc, new ActivityLaunchModeForward(), Intent.GetBooleanExtra("MakeCurrent",true));
|
||||
Finish();
|
||||
} catch (Java.IO.FileNotFoundException)
|
||||
{
|
||||
Toast.MakeText(this, Resource.String.FileNotFound, ToastLength.Long).Show();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
private void AfterQueryCredentials(IOConnectionInfo ioc)
|
||||
{
|
||||
PasswordActivity.Launch(this, ioc, new ActivityLaunchModeForward(), Intent.GetBooleanExtra("MakeCurrent", true));
|
||||
Finish();
|
||||
}
|
||||
|
||||
|
||||
protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)
|
||||
{
|
||||
base.OnActivityResult(requestCode, resultCode, data);
|
||||
|
||||
if (resultCode == KeePass.ExitCloseAfterTaskComplete)
|
||||
{
|
||||
//no need to set the result ExitCloseAfterTaskComplete here, there's no parent Activity on the stack
|
||||
Finish();
|
||||
return;
|
||||
}
|
||||
|
||||
FillData();
|
||||
|
||||
|
||||
if (resultCode == (Result)FileStorageResults.FileUsagePrepared)
|
||||
{
|
||||
IOConnectionInfo ioc = new IOConnectionInfo();
|
||||
Util.SetIoConnectionFromIntent(ioc, data);
|
||||
LaunchPasswordActivityForIoc(ioc);
|
||||
}
|
||||
|
||||
if ((resultCode == Result.Ok) && (requestCode == RequestCodeSelectIoc))
|
||||
{
|
||||
IOConnectionInfo ioc = new IOConnectionInfo();
|
||||
Util.SetIoConnectionFromIntent(ioc, data);
|
||||
LaunchPasswordActivityForIoc(ioc);
|
||||
}
|
||||
|
||||
if ((resultCode == Result.Ok) && (requestCode == RequestCodeEditIoc))
|
||||
{
|
||||
string filename = Util.IntentToFilename(data, this);
|
||||
|
||||
LaunchPasswordActivityForIoc(IOConnectionInfo.FromPath(filename));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected override void OnResume()
|
||||
{
|
||||
base.OnResume();
|
||||
App.Kp2a.OfflineMode = false; //no matter what the preferences are, file selection or db creation is performed offline. PasswordActivity might set this to true.
|
||||
Kp2aLog.Log("FileSelect.OnResume");
|
||||
|
||||
_design.ReapplyTheme();
|
||||
|
||||
// Check to see if we need to change modes
|
||||
if (ShowRecentFiles() != _recentMode)
|
||||
{
|
||||
// Restart the activity
|
||||
Recreate();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
protected override void OnStart()
|
||||
{
|
||||
base.OnStart();
|
||||
Kp2aLog.Log("FileSelect.OnStart");
|
||||
|
||||
|
||||
//if no database is loaded: load the most recent database
|
||||
if ( (Intent.GetBooleanExtra(NoForwardToPasswordActivity, false)==false) && _dbHelper.HasRecentFiles() && !App.Kp2a.OpenDatabases.Any())
|
||||
{
|
||||
var fileStorage = new LocalFileStorage(App.Kp2a);
|
||||
ICursor filesCursor = _dbHelper.FetchAllFiles();
|
||||
filesCursor = new FilteredCursor(filesCursor, cursor => !fileStorage.IsLocalBackup(IOConnectionInfo.FromPath(cursor.GetString(1))));
|
||||
StartManagingCursor(filesCursor);
|
||||
if (filesCursor.Count > 0)
|
||||
{
|
||||
filesCursor.MoveToFirst();
|
||||
IOConnectionInfo ioc = _dbHelper.CursorToIoc(filesCursor);
|
||||
if (App.Kp2a.GetFileStorage(ioc).RequiresSetup(ioc) == false)
|
||||
{
|
||||
LaunchPasswordActivityForIoc(ioc);
|
||||
}
|
||||
else
|
||||
{
|
||||
App.Kp2a.GetFileStorage(ioc)
|
||||
.PrepareFileUsage(new FileStorageSetupInitiatorActivity(this, OnActivityResult, null), ioc, 0, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
public override bool OnCreateOptionsMenu(IMenu menu) {
|
||||
base.OnCreateOptionsMenu(menu);
|
||||
|
||||
MenuInflater inflater = MenuInflater;
|
||||
inflater.Inflate(Resource.Menu.fileselect, menu);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override void OnPause()
|
||||
{
|
||||
base.OnPause();
|
||||
Kp2aLog.Log("FileSelect.OnPause");
|
||||
}
|
||||
|
||||
protected override void OnDestroy()
|
||||
{
|
||||
base.OnDestroy();
|
||||
GC.Collect();
|
||||
Kp2aLog.Log("FileSelect.OnDestroy"+IsFinishing.ToString());
|
||||
}
|
||||
|
||||
protected override void OnStop()
|
||||
{
|
||||
base.OnStop();
|
||||
Kp2aLog.Log("FileSelect.OnStop");
|
||||
}
|
||||
|
||||
public override bool OnOptionsItemSelected(IMenuItem item) {
|
||||
switch (item.ItemId) {
|
||||
case Resource.Id.menu_donate:
|
||||
return Util.GotoDonateUrl(this);
|
||||
case Resource.Id.menu_about:
|
||||
AboutDialog dialog = new AboutDialog(this);
|
||||
dialog.Show();
|
||||
return true;
|
||||
|
||||
case Resource.Id.menu_app_settings:
|
||||
AppSettingsActivity.Launch(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
return base.OnOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
public class NonScrollListView : ListView
|
||||
{
|
||||
public NonScrollListView(Context context) : base(context)
|
||||
{
|
||||
}
|
||||
|
||||
public NonScrollListView(Context context, IAttributeSet attrs) : base(context, attrs)
|
||||
{
|
||||
}
|
||||
|
||||
public NonScrollListView(Context context, IAttributeSet attrs, int defStyle) : base(context, attrs, defStyle)
|
||||
{
|
||||
}
|
||||
|
||||
protected override void OnMeasure(int widthMeasureSpec, int heightMeasureSpec)
|
||||
{
|
||||
// Custom height measure spec to make ListView non-scrollable
|
||||
int heightMeasureSpecCustom = MeasureSpec.MakeMeasureSpec(int.MaxValue >> 2, MeasureSpecMode.AtMost);
|
||||
base.OnMeasure(widthMeasureSpec, heightMeasureSpecCustom);
|
||||
|
||||
// Set the height of the ListView to the measured height
|
||||
ViewGroup.LayoutParams layoutParams = LayoutParameters;
|
||||
if (layoutParams != null)
|
||||
{
|
||||
layoutParams.Height = MeasuredHeight;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class RecentFilesFragment : ListFragment
|
||||
{
|
||||
public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
|
||||
{
|
||||
var view = inflater.Inflate(Resource.Layout.recent_files, container, false);
|
||||
Android.Util.Log.Debug("KP2A", "OnCreateView");
|
||||
return view;
|
||||
}
|
||||
|
||||
public void SetAdapter(BaseAdapter adapter)
|
||||
{
|
||||
ListAdapter = adapter;
|
||||
Android.Util.Log.Debug("KP2A", "SetAdapter");
|
||||
}
|
||||
|
||||
public override void OnActivityCreated(Bundle savedInstanceState)
|
||||
{
|
||||
base.OnActivityCreated(savedInstanceState);
|
||||
Android.Util.Log.Debug("KP2A", "OnActCreated");
|
||||
|
||||
RefreshList();
|
||||
RegisterForContextMenu(ListView);
|
||||
|
||||
}
|
||||
|
||||
public void RefreshList()
|
||||
{
|
||||
Android.Util.Log.Debug("KP2A", "RefreshList");
|
||||
CursorAdapter ca = (CursorAdapter)ListAdapter;
|
||||
ICursor cursor = ca.Cursor;
|
||||
cursor.Requery();
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
121
src/keepass2android-app/fileselect/FileStorageSetupActivity.cs
Normal file
121
src/keepass2android-app/fileselect/FileStorageSetupActivity.cs
Normal file
@@ -0,0 +1,121 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
using Android.App;
|
||||
using Android.Content;
|
||||
using Android.Content.PM;
|
||||
using Android.OS;
|
||||
using Android.Runtime;
|
||||
using Android.Views;
|
||||
using Android.Widget;
|
||||
using KeePassLib.Serialization;
|
||||
using keepass2android.Io;
|
||||
using keepass2android;
|
||||
|
||||
namespace keepass2android.fileselect
|
||||
{
|
||||
[Activity(Label = "@string/filestorage_setup_title", Theme = "@style/Kp2aTheme_ActionBar", ConfigurationChanges = ConfigChanges.Orientation |
|
||||
ConfigChanges.KeyboardHidden)]
|
||||
public class FileStorageSetupActivity : Activity, IFileStorageSetupActivity
|
||||
#if !EXCLUDE_JAVAFILESTORAGE
|
||||
#if !NoNet
|
||||
,Keepass2android.Javafilestorage.IJavaFileStorage.IFileStorageSetupActivity
|
||||
#endif
|
||||
#endif
|
||||
{
|
||||
private bool _isRecreated = false;
|
||||
|
||||
private ActivityDesign _design;
|
||||
|
||||
public FileStorageSetupActivity()
|
||||
{
|
||||
_design = new ActivityDesign(this);
|
||||
}
|
||||
|
||||
protected override void OnCreate(Bundle bundle)
|
||||
{
|
||||
_design.ApplyTheme();
|
||||
base.OnCreate(bundle);
|
||||
|
||||
|
||||
SetContentView(Resource.Layout.file_storage_setup);
|
||||
|
||||
Ioc = new IOConnectionInfo();
|
||||
Util.SetIoConnectionFromIntent(Ioc, Intent);
|
||||
|
||||
Kp2aLog.Log("FSSA.OnCreate");
|
||||
|
||||
ProcessName = Intent.GetStringExtra(FileStorageSetupDefs.ExtraProcessName);
|
||||
IsForSave = Intent.GetBooleanExtra(FileStorageSetupDefs.ExtraIsForSave, false);
|
||||
if (bundle == null)
|
||||
State = new Bundle();
|
||||
else
|
||||
{
|
||||
State = (Bundle) bundle.Clone();
|
||||
_isRecreated = true;
|
||||
}
|
||||
|
||||
if (!_isRecreated)
|
||||
App.Kp2a.GetFileStorage(Ioc).OnCreate(this, bundle);
|
||||
|
||||
}
|
||||
|
||||
protected override void OnRestart()
|
||||
{
|
||||
base.OnRestart();
|
||||
_isRecreated = true;
|
||||
}
|
||||
|
||||
protected override void OnStart()
|
||||
{
|
||||
base.OnStart();
|
||||
if (!_isRecreated)
|
||||
App.Kp2a.GetFileStorage(Ioc).OnStart(this);
|
||||
}
|
||||
|
||||
protected override void OnResume()
|
||||
{
|
||||
base.OnResume();
|
||||
_design.ReapplyTheme();
|
||||
App.Kp2a.GetFileStorage(Ioc).OnResume(this);
|
||||
}
|
||||
|
||||
protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)
|
||||
{
|
||||
base.OnActivityResult(requestCode, resultCode, data);
|
||||
App.Kp2a.GetFileStorage(Ioc).OnActivityResult(this, requestCode, (int) resultCode, data);
|
||||
}
|
||||
|
||||
public override void OnRequestPermissionsResult(int requestCode, string[] permissions, Permission[] grantResults)
|
||||
{
|
||||
base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
|
||||
var fileStorage = App.Kp2a.GetFileStorage(Ioc);
|
||||
if (fileStorage is IPermissionRequestingFileStorage)
|
||||
{
|
||||
((IPermissionRequestingFileStorage)fileStorage).OnRequestPermissionsResult(this, requestCode, permissions, grantResults);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected override void OnSaveInstanceState(Bundle outState)
|
||||
{
|
||||
base.OnSaveInstanceState(outState);
|
||||
|
||||
outState.PutAll(State);
|
||||
}
|
||||
|
||||
public IOConnectionInfo Ioc { get; private set; }
|
||||
public string Path
|
||||
{
|
||||
get
|
||||
{
|
||||
return App.Kp2a.GetFileStorage(Ioc).IocToPath(Ioc);
|
||||
}
|
||||
}
|
||||
public string ProcessName { get; private set; }
|
||||
public bool IsForSave { get; private set; }
|
||||
public Bundle State { get; private set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
using System;
|
||||
using Android.App;
|
||||
using Android.Content;
|
||||
using KeePassLib.Serialization;
|
||||
using keepass2android.Io;
|
||||
using keepass2android.fileselect;
|
||||
|
||||
namespace keepass2android
|
||||
{
|
||||
public class FileStorageSetupInitiatorActivity:
|
||||
#if !EXCLUDE_JAVAFILESTORAGE
|
||||
Java.Lang.Object
|
||||
#if !NoNet
|
||||
,Keepass2android.Javafilestorage.IJavaFileStorage.IFileStorageSetupInitiatorActivity
|
||||
#endif
|
||||
,
|
||||
#endif
|
||||
IFileStorageSetupInitiatorActivity
|
||||
{
|
||||
private readonly Activity _activity;
|
||||
private readonly Action<int, Result, Intent> _onActivityResult;
|
||||
private readonly Action<string> _startManualFileSelect;
|
||||
|
||||
public FileStorageSetupInitiatorActivity(Activity activity,
|
||||
Action<int,Result,Intent> onActivityResult,
|
||||
Action<String> startManualFileSelect)
|
||||
{
|
||||
_activity = activity;
|
||||
_onActivityResult = onActivityResult;
|
||||
_startManualFileSelect = startManualFileSelect;
|
||||
}
|
||||
|
||||
public void StartSelectFileProcess(IOConnectionInfo ioc, bool isForSave, int requestCode)
|
||||
{
|
||||
Kp2aLog.Log("FSSIA: StartSelectFileProcess ");
|
||||
Intent fileStorageSetupIntent = new Intent(_activity, typeof(FileStorageSetupActivity));
|
||||
fileStorageSetupIntent.PutExtra(FileStorageSetupDefs.ExtraProcessName, FileStorageSetupDefs.ProcessNameSelectfile);
|
||||
fileStorageSetupIntent.PutExtra(FileStorageSetupDefs.ExtraIsForSave, isForSave);
|
||||
Util.PutIoConnectionToIntent(ioc, fileStorageSetupIntent);
|
||||
|
||||
_activity.StartActivityForResult(fileStorageSetupIntent, requestCode);
|
||||
}
|
||||
|
||||
public void StartFileUsageProcess(IOConnectionInfo ioc, int requestCode, bool alwaysReturnSuccess)
|
||||
{
|
||||
Intent fileStorageSetupIntent = new Intent(_activity, typeof(FileStorageSetupActivity));
|
||||
fileStorageSetupIntent.PutExtra(FileStorageSetupDefs.ExtraProcessName, FileStorageSetupDefs.ProcessNameFileUsageSetup);
|
||||
fileStorageSetupIntent.PutExtra(FileStorageSetupDefs.ExtraAlwaysReturnSuccess, alwaysReturnSuccess);
|
||||
Util.PutIoConnectionToIntent(ioc, fileStorageSetupIntent);
|
||||
|
||||
_activity.StartActivityForResult(fileStorageSetupIntent, requestCode);
|
||||
}
|
||||
|
||||
public void OnImmediateResult(int requestCode, int result, Intent intent)
|
||||
{
|
||||
_onActivityResult(requestCode, (Result)result, intent);
|
||||
}
|
||||
|
||||
public Activity Activity {
|
||||
get { return _activity; }
|
||||
}
|
||||
|
||||
public void IocToIntent(Intent intent, IOConnectionInfo ioc)
|
||||
{
|
||||
Util.PutIoConnectionToIntent(ioc, intent);
|
||||
}
|
||||
|
||||
public void PerformManualFileSelect(bool isForSave, int requestCode, string protocolId)
|
||||
{
|
||||
_startManualFileSelect(protocolId + "://");
|
||||
}
|
||||
|
||||
public void StartFileUsageProcess(string path, int requestCode, bool alwaysReturnSuccess)
|
||||
{
|
||||
StartFileUsageProcess(new IOConnectionInfo() { Path = path }, requestCode, alwaysReturnSuccess);
|
||||
}
|
||||
|
||||
public void StartSelectFileProcess(string p0, bool p1, int p2)
|
||||
{
|
||||
StartSelectFileProcess(new IOConnectionInfo() { Path = p0 }, p1, p2);
|
||||
}
|
||||
}
|
||||
}
|
||||
118
src/keepass2android-app/fileselect/FilteredCursor.cs
Normal file
118
src/keepass2android-app/fileselect/FilteredCursor.cs
Normal file
@@ -0,0 +1,118 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Android.Database;
|
||||
using Android.Runtime;
|
||||
|
||||
namespace keepass2android
|
||||
{
|
||||
public class FilteredCursor : CursorWrapper
|
||||
{
|
||||
private readonly Predicate<ICursor> _filter;
|
||||
private List<int> _indicesToKeep;
|
||||
private int _pos;
|
||||
|
||||
public override bool Requery()
|
||||
{
|
||||
bool result = base.Requery();
|
||||
UpdateFilterIndices();
|
||||
return result;
|
||||
}
|
||||
|
||||
protected FilteredCursor(IntPtr javaReference, JniHandleOwnership transfer) : base(javaReference, transfer)
|
||||
{
|
||||
}
|
||||
|
||||
public FilteredCursor(ICursor cursor, Predicate<ICursor> filter) : base(cursor)
|
||||
{
|
||||
_filter = filter;
|
||||
UpdateFilterIndices();
|
||||
}
|
||||
|
||||
private void UpdateFilterIndices()
|
||||
{
|
||||
_indicesToKeep = new List<int>();
|
||||
int index = 0;
|
||||
for (base.WrappedCursor.MoveToFirst(); !base.WrappedCursor.IsAfterLast; base.WrappedCursor.MoveToNext())
|
||||
{
|
||||
if (_filter(base.WrappedCursor))
|
||||
_indicesToKeep.Add(index);
|
||||
index++;
|
||||
}
|
||||
_pos = -1;
|
||||
}
|
||||
|
||||
public override int Count
|
||||
{
|
||||
get
|
||||
{
|
||||
return _indicesToKeep.Count;
|
||||
}
|
||||
}
|
||||
|
||||
public override bool MoveToPosition(int position)
|
||||
{
|
||||
if (position >= Count)
|
||||
{
|
||||
_pos = Count;
|
||||
return false;
|
||||
}
|
||||
if (position < 0)
|
||||
{
|
||||
_pos = -1;
|
||||
return false;
|
||||
}
|
||||
return base.MoveToPosition(_indicesToKeep[position]);
|
||||
}
|
||||
|
||||
public override bool Move(int offset)
|
||||
{
|
||||
return MoveToPosition(_pos+offset);
|
||||
}
|
||||
|
||||
public override bool MoveToFirst()
|
||||
{
|
||||
return MoveToPosition(0);
|
||||
}
|
||||
|
||||
public override bool MoveToNext()
|
||||
{
|
||||
return MoveToPosition(_pos+1);
|
||||
}
|
||||
|
||||
public override bool MoveToLast()
|
||||
{
|
||||
return MoveToPosition(Count-1);
|
||||
}
|
||||
|
||||
public override bool MoveToPrevious()
|
||||
{
|
||||
return MoveToPosition(_pos-1);
|
||||
}
|
||||
|
||||
public override bool IsAfterLast
|
||||
{
|
||||
get { return _pos >= Count; }
|
||||
}
|
||||
|
||||
public override bool IsBeforeFirst
|
||||
{
|
||||
get { return _pos < 0; }
|
||||
}
|
||||
|
||||
public override bool IsFirst
|
||||
{
|
||||
get { return _pos == 0; }
|
||||
}
|
||||
|
||||
public override bool IsLast
|
||||
{
|
||||
get { return _pos == Count-1; }
|
||||
}
|
||||
|
||||
public override int Position
|
||||
{
|
||||
get { return _pos; }
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user