mirror of
https://github.com/Kunzisoft/KeePassDX.git
synced 2025-12-04 15:49:33 +01:00
Merge branch 'feature/ViewModel' into develop
This commit is contained in:
@@ -101,10 +101,9 @@ dependencies {
|
||||
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
|
||||
implementation 'androidx.documentfile:documentfile:1.0.1'
|
||||
implementation 'androidx.biometric:biometric:1.0.1'
|
||||
implementation 'androidx.core:core-ktx:1.2.0'
|
||||
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.3'
|
||||
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.3'
|
||||
// TODO #538 implementation "androidx.lifecycle:lifecycle-runtime-ktx:2.2.0"
|
||||
// Lifecycle - LiveData - ViewModel - Coroutines
|
||||
implementation "androidx.core:core-ktx:1.2.0"
|
||||
implementation 'androidx.fragment:fragment-ktx:1.2.4'
|
||||
// To upgrade with style
|
||||
implementation 'com.google.android.material:material:1.0.0'
|
||||
// Database
|
||||
|
||||
@@ -140,7 +140,7 @@ class EntryActivity : LockingActivity() {
|
||||
// Init attachment service binder manager
|
||||
mAttachmentFileBinderManager = AttachmentFileBinderManager(this)
|
||||
|
||||
mProgressDialogThread?.onActionFinish = { actionTask, result ->
|
||||
mProgressDatabaseTaskProvider?.onActionFinish = { actionTask, result ->
|
||||
when (actionTask) {
|
||||
ACTION_DATABASE_RESTORE_ENTRY_HISTORY,
|
||||
ACTION_DATABASE_DELETE_ENTRY_HISTORY -> {
|
||||
@@ -523,7 +523,7 @@ class EntryActivity : LockingActivity() {
|
||||
}
|
||||
R.id.menu_restore_entry_history -> {
|
||||
mEntryLastVersion?.let { mainEntry ->
|
||||
mProgressDialogThread?.startDatabaseRestoreEntryHistory(
|
||||
mProgressDatabaseTaskProvider?.startDatabaseRestoreEntryHistory(
|
||||
mainEntry,
|
||||
mEntryHistoryPosition,
|
||||
!mReadOnly && mAutoSaveEnable)
|
||||
@@ -531,14 +531,14 @@ class EntryActivity : LockingActivity() {
|
||||
}
|
||||
R.id.menu_delete_entry_history -> {
|
||||
mEntryLastVersion?.let { mainEntry ->
|
||||
mProgressDialogThread?.startDatabaseDeleteEntryHistory(
|
||||
mProgressDatabaseTaskProvider?.startDatabaseDeleteEntryHistory(
|
||||
mainEntry,
|
||||
mEntryHistoryPosition,
|
||||
!mReadOnly && mAutoSaveEnable)
|
||||
}
|
||||
}
|
||||
R.id.menu_save_database -> {
|
||||
mProgressDialogThread?.startDatabaseSave(!mReadOnly)
|
||||
mProgressDatabaseTaskProvider?.startDatabaseSave(!mReadOnly)
|
||||
}
|
||||
android.R.id.home -> finish() // close this activity and return to preview activity (if there is any)
|
||||
}
|
||||
|
||||
@@ -28,7 +28,6 @@ import android.util.Log
|
||||
import android.view.Menu
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import android.view.WindowManager
|
||||
import android.widget.DatePicker
|
||||
import android.widget.TimePicker
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
@@ -253,7 +252,7 @@ class EntryEditActivity : LockingActivity(),
|
||||
entryEditActivityEducation = EntryEditActivityEducation(this)
|
||||
|
||||
// Create progress dialog
|
||||
mProgressDialogThread?.onActionFinish = { actionTask, result ->
|
||||
mProgressDatabaseTaskProvider?.onActionFinish = { actionTask, result ->
|
||||
when (actionTask) {
|
||||
ACTION_DATABASE_CREATE_ENTRY_TASK,
|
||||
ACTION_DATABASE_UPDATE_ENTRY_TASK -> {
|
||||
@@ -397,7 +396,7 @@ class EntryEditActivity : LockingActivity(),
|
||||
// Open a progress dialog and save entry
|
||||
if (mIsNew) {
|
||||
mParent?.let { parent ->
|
||||
mProgressDialogThread?.startDatabaseCreateEntry(
|
||||
mProgressDatabaseTaskProvider?.startDatabaseCreateEntry(
|
||||
newEntry,
|
||||
parent,
|
||||
!mReadOnly && mAutoSaveEnable
|
||||
@@ -405,7 +404,7 @@ class EntryEditActivity : LockingActivity(),
|
||||
}
|
||||
} else {
|
||||
mEntry?.let { oldEntry ->
|
||||
mProgressDialogThread?.startDatabaseUpdateEntry(
|
||||
mProgressDatabaseTaskProvider?.startDatabaseUpdateEntry(
|
||||
oldEntry,
|
||||
newEntry,
|
||||
!mReadOnly && mAutoSaveEnable
|
||||
@@ -473,7 +472,7 @@ class EntryEditActivity : LockingActivity(),
|
||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||
when (item.itemId) {
|
||||
R.id.menu_save_database -> {
|
||||
mProgressDialogThread?.startDatabaseSave(!mReadOnly)
|
||||
mProgressDatabaseTaskProvider?.startDatabaseSave(!mReadOnly)
|
||||
}
|
||||
R.id.menu_contribute -> {
|
||||
MenuUtil.onContributionItemSelected(this)
|
||||
|
||||
@@ -32,9 +32,11 @@ import android.util.Log
|
||||
import android.view.Menu
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import androidx.activity.viewModels
|
||||
import androidx.annotation.RequiresApi
|
||||
import androidx.appcompat.widget.Toolbar
|
||||
import androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||
import androidx.lifecycle.Observer
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import androidx.recyclerview.widget.SimpleItemAnimator
|
||||
@@ -48,14 +50,17 @@ import com.kunzisoft.keepass.activities.selection.SpecialModeActivity
|
||||
import com.kunzisoft.keepass.adapters.FileDatabaseHistoryAdapter
|
||||
import com.kunzisoft.keepass.app.database.FileDatabaseHistoryAction
|
||||
import com.kunzisoft.keepass.autofill.AutofillHelper
|
||||
import com.kunzisoft.keepass.database.action.ProgressDialogThread
|
||||
import com.kunzisoft.keepass.database.action.ProgressDatabaseTaskProvider
|
||||
import com.kunzisoft.keepass.database.element.Database
|
||||
import com.kunzisoft.keepass.education.FileDatabaseSelectActivityEducation
|
||||
import com.kunzisoft.keepass.model.SearchInfo
|
||||
import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_CREATE_TASK
|
||||
import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.DATABASE_URI_KEY
|
||||
import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.KEY_FILE_URI_KEY
|
||||
import com.kunzisoft.keepass.settings.PreferencesUtil
|
||||
import com.kunzisoft.keepass.utils.*
|
||||
import com.kunzisoft.keepass.view.asError
|
||||
import com.kunzisoft.keepass.viewmodels.DatabaseFilesViewModel
|
||||
import kotlinx.android.synthetic.main.activity_file_selection.*
|
||||
import java.io.FileNotFoundException
|
||||
|
||||
@@ -68,6 +73,8 @@ class FileDatabaseSelectActivity : SpecialModeActivity(),
|
||||
private var createDatabaseButtonView: View? = null
|
||||
private var openDatabaseButtonView: View? = null
|
||||
|
||||
private val databaseFilesViewModel: DatabaseFilesViewModel by viewModels()
|
||||
|
||||
// Adapter to manage database history list
|
||||
private var mAdapterDatabaseHistory: FileDatabaseHistoryAdapter? = null
|
||||
|
||||
@@ -77,7 +84,7 @@ class FileDatabaseSelectActivity : SpecialModeActivity(),
|
||||
|
||||
private var mOpenFileHelper: OpenFileHelper? = null
|
||||
|
||||
private var mProgressDialogThread: ProgressDialogThread? = null
|
||||
private var mProgressDatabaseTaskProvider: ProgressDatabaseTaskProvider? = null
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
@@ -118,25 +125,21 @@ class FileDatabaseSelectActivity : SpecialModeActivity(),
|
||||
// Construct adapter with listeners
|
||||
mAdapterDatabaseHistory = FileDatabaseHistoryAdapter(this)
|
||||
mAdapterDatabaseHistory?.setOnFileDatabaseHistoryOpenListener { fileDatabaseHistoryEntityToOpen ->
|
||||
UriUtil.parse(fileDatabaseHistoryEntityToOpen.databaseUri)?.let { databaseFileUri ->
|
||||
fileDatabaseHistoryEntityToOpen.databaseUri?.let { databaseFileUri ->
|
||||
launchPasswordActivity(
|
||||
databaseFileUri,
|
||||
UriUtil.parse(fileDatabaseHistoryEntityToOpen.keyFileUri))
|
||||
fileDatabaseHistoryEntityToOpen.keyFileUri
|
||||
)
|
||||
}
|
||||
}
|
||||
mAdapterDatabaseHistory?.setOnFileDatabaseHistoryDeleteListener { fileDatabaseHistoryToDelete ->
|
||||
// Remove from app database
|
||||
mFileDatabaseHistoryAction?.deleteFileDatabaseHistory(fileDatabaseHistoryToDelete) { fileHistoryDeleted ->
|
||||
// Remove from adapter
|
||||
fileHistoryDeleted?.let { databaseFileHistoryDeleted ->
|
||||
mAdapterDatabaseHistory?.deleteDatabaseFileHistory(databaseFileHistoryDeleted)
|
||||
mAdapterDatabaseHistory?.notifyDataSetChanged()
|
||||
}
|
||||
}
|
||||
databaseFilesViewModel.deleteDatabaseFile(fileDatabaseHistoryToDelete)
|
||||
true
|
||||
}
|
||||
mAdapterDatabaseHistory?.setOnSaveAliasListener { fileDatabaseHistoryWithNewAlias ->
|
||||
mFileDatabaseHistoryAction?.addOrUpdateFileDatabaseHistory(fileDatabaseHistoryWithNewAlias)
|
||||
// Update in app database
|
||||
databaseFilesViewModel.updateDatabaseFile(fileDatabaseHistoryWithNewAlias)
|
||||
}
|
||||
fileDatabaseHistoryRecyclerView.adapter = mAdapterDatabaseHistory
|
||||
|
||||
@@ -159,12 +162,45 @@ class FileDatabaseSelectActivity : SpecialModeActivity(),
|
||||
mDatabaseFileUri = savedInstanceState.getParcelable(EXTRA_DATABASE_URI)
|
||||
}
|
||||
|
||||
// Observe list of databases
|
||||
databaseFilesViewModel.databaseFilesLoaded.observe(this, Observer { databaseFiles ->
|
||||
when (databaseFiles.databaseFileAction) {
|
||||
DatabaseFilesViewModel.DatabaseFileAction.NONE -> {
|
||||
mAdapterDatabaseHistory?.replaceAllDatabaseFileHistoryList(databaseFiles.databaseFileList)
|
||||
mAdapterDatabaseHistory?.notifyDataSetChanged()
|
||||
}
|
||||
DatabaseFilesViewModel.DatabaseFileAction.ADD -> {
|
||||
databaseFiles.databaseFileToActivate?.let { databaseFileToAdd ->
|
||||
// TODO notify unique element
|
||||
mAdapterDatabaseHistory?.notifyDataSetChanged()
|
||||
}
|
||||
GroupActivity.launch(this@FileDatabaseSelectActivity)
|
||||
}
|
||||
DatabaseFilesViewModel.DatabaseFileAction.UPDATE -> {
|
||||
databaseFiles.databaseFileToActivate?.let { databaseFileToUpdate ->
|
||||
// TODO notify unique element
|
||||
mAdapterDatabaseHistory?.notifyDataSetChanged()
|
||||
}
|
||||
}
|
||||
DatabaseFilesViewModel.DatabaseFileAction.DELETE -> {
|
||||
databaseFiles.databaseFileToActivate?.let { databaseFileToDelete ->
|
||||
mAdapterDatabaseHistory?.deleteDatabaseFileHistory(databaseFileToDelete)
|
||||
mAdapterDatabaseHistory?.notifyDataSetChanged()
|
||||
}
|
||||
}
|
||||
}
|
||||
databaseFilesViewModel.consumeAction()
|
||||
})
|
||||
|
||||
// Attach the dialog thread to this activity
|
||||
mProgressDialogThread = ProgressDialogThread(this).apply {
|
||||
onActionFinish = { actionTask, _ ->
|
||||
mProgressDatabaseTaskProvider = ProgressDatabaseTaskProvider(this).apply {
|
||||
onActionFinish = { actionTask, result ->
|
||||
when (actionTask) {
|
||||
ACTION_DATABASE_CREATE_TASK -> {
|
||||
GroupActivity.launch(this@FileDatabaseSelectActivity)
|
||||
result.data?.getParcelable<Uri?>(DATABASE_URI_KEY)?.let { databaseUri ->
|
||||
val keyFileUri = result.data?.getParcelable<Uri?>(KEY_FILE_URI_KEY)
|
||||
databaseFilesViewModel.addDatabaseFile(databaseUri, keyFileUri)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -286,34 +322,20 @@ class FileDatabaseSelectActivity : SpecialModeActivity(),
|
||||
} else {
|
||||
// Construct adapter with listeners
|
||||
if (PreferencesUtil.showRecentFiles(this)) {
|
||||
mFileDatabaseHistoryAction?.getAllFileDatabaseHistories { databaseFileHistoryList ->
|
||||
databaseFileHistoryList?.let { historyList ->
|
||||
val hideBrokenLocations = PreferencesUtil.hideBrokenLocations(this@FileDatabaseSelectActivity)
|
||||
mAdapterDatabaseHistory?.addDatabaseFileHistoryList(
|
||||
// Show only uri accessible
|
||||
historyList.filter {
|
||||
if (hideBrokenLocations) {
|
||||
FileDatabaseInfo(this@FileDatabaseSelectActivity,
|
||||
it.databaseUri).exists
|
||||
} else
|
||||
true
|
||||
})
|
||||
mAdapterDatabaseHistory?.notifyDataSetChanged()
|
||||
}
|
||||
}
|
||||
databaseFilesViewModel.loadListOfDatabases()
|
||||
} else {
|
||||
mAdapterDatabaseHistory?.clearDatabaseFileHistoryList()
|
||||
mAdapterDatabaseHistory?.notifyDataSetChanged()
|
||||
}
|
||||
|
||||
// Register progress task
|
||||
mProgressDialogThread?.registerProgressTask()
|
||||
mProgressDatabaseTaskProvider?.registerProgressTask()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
// Unregister progress task
|
||||
mProgressDialogThread?.unregisterProgressTask()
|
||||
mProgressDatabaseTaskProvider?.unregisterProgressTask()
|
||||
|
||||
super.onPause()
|
||||
}
|
||||
@@ -334,7 +356,7 @@ class FileDatabaseSelectActivity : SpecialModeActivity(),
|
||||
mDatabaseFileUri?.let { databaseUri ->
|
||||
|
||||
// Create the new database
|
||||
mProgressDialogThread?.startDatabaseCreate(
|
||||
mProgressDatabaseTaskProvider?.startDatabaseCreate(
|
||||
databaseUri,
|
||||
masterPasswordChecked,
|
||||
masterPassword,
|
||||
@@ -362,8 +384,7 @@ class FileDatabaseSelectActivity : SpecialModeActivity(),
|
||||
AutofillHelper.onActivityResultSetResultAndFinish(this, requestCode, resultCode, data)
|
||||
}
|
||||
|
||||
mOpenFileHelper?.onActivityResultCallback(requestCode, resultCode, data
|
||||
) { uri ->
|
||||
mOpenFileHelper?.onActivityResultCallback(requestCode, resultCode, data) { uri ->
|
||||
if (uri != null) {
|
||||
launchPasswordActivityWithPath(uri)
|
||||
}
|
||||
|
||||
@@ -221,7 +221,7 @@ class GroupActivity : LockingActivity(),
|
||||
mSearchSuggestionAdapter = SearchEntryCursorAdapter(this, database)
|
||||
|
||||
// Init dialog thread
|
||||
mProgressDialogThread?.onActionFinish = { actionTask, result ->
|
||||
mProgressDatabaseTaskProvider?.onActionFinish = { actionTask, result ->
|
||||
|
||||
var oldNodes: List<Node> = ArrayList()
|
||||
result.data?.getBundle(OLD_NODES_KEY)?.let { oldNodesBundle ->
|
||||
@@ -632,7 +632,7 @@ class GroupActivity : LockingActivity(),
|
||||
ListNodesFragment.PasteMode.PASTE_FROM_COPY -> {
|
||||
// Copy
|
||||
mCurrentGroup?.let { newParent ->
|
||||
mProgressDialogThread?.startDatabaseCopyNodes(
|
||||
mProgressDatabaseTaskProvider?.startDatabaseCopyNodes(
|
||||
nodes,
|
||||
newParent,
|
||||
!mReadOnly && mAutoSaveEnable
|
||||
@@ -642,7 +642,7 @@ class GroupActivity : LockingActivity(),
|
||||
ListNodesFragment.PasteMode.PASTE_FROM_MOVE -> {
|
||||
// Move
|
||||
mCurrentGroup?.let { newParent ->
|
||||
mProgressDialogThread?.startDatabaseMoveNodes(
|
||||
mProgressDatabaseTaskProvider?.startDatabaseMoveNodes(
|
||||
nodes,
|
||||
newParent,
|
||||
!mReadOnly && mAutoSaveEnable
|
||||
@@ -676,7 +676,7 @@ class GroupActivity : LockingActivity(),
|
||||
&& database.isRecycleBinEnabled
|
||||
&& database.recycleBin != mCurrentGroup) {
|
||||
|
||||
mProgressDialogThread?.startDatabaseDeleteNodes(
|
||||
mProgressDatabaseTaskProvider?.startDatabaseDeleteNodes(
|
||||
nodes,
|
||||
!mReadOnly && mAutoSaveEnable
|
||||
)
|
||||
@@ -691,7 +691,7 @@ class GroupActivity : LockingActivity(),
|
||||
}
|
||||
|
||||
override fun permanentlyDeleteNodes(nodes: List<Node>) {
|
||||
mProgressDialogThread?.startDatabaseDeleteNodes(
|
||||
mProgressDatabaseTaskProvider?.startDatabaseDeleteNodes(
|
||||
nodes,
|
||||
!mReadOnly && mAutoSaveEnable
|
||||
)
|
||||
@@ -852,7 +852,7 @@ class GroupActivity : LockingActivity(),
|
||||
//onSearchRequested();
|
||||
return true
|
||||
R.id.menu_save_database -> {
|
||||
mProgressDialogThread?.startDatabaseSave(!mReadOnly)
|
||||
mProgressDatabaseTaskProvider?.startDatabaseSave(!mReadOnly)
|
||||
return true
|
||||
}
|
||||
R.id.menu_empty_recycle_bin -> {
|
||||
@@ -886,7 +886,7 @@ class GroupActivity : LockingActivity(),
|
||||
// Not really needed here because added in runnable but safe
|
||||
newGroup.parent = currentGroup
|
||||
|
||||
mProgressDialogThread?.startDatabaseCreateGroup(
|
||||
mProgressDatabaseTaskProvider?.startDatabaseCreateGroup(
|
||||
newGroup,
|
||||
currentGroup,
|
||||
!mReadOnly && mAutoSaveEnable
|
||||
@@ -908,7 +908,7 @@ class GroupActivity : LockingActivity(),
|
||||
}
|
||||
}
|
||||
// If group updated save it in the database
|
||||
mProgressDialogThread?.startDatabaseUpdateGroup(
|
||||
mProgressDatabaseTaskProvider?.startDatabaseUpdateGroup(
|
||||
oldGroupToUpdate,
|
||||
updateGroup,
|
||||
!mReadOnly && mAutoSaveEnable
|
||||
|
||||
@@ -34,10 +34,12 @@ import android.util.Log
|
||||
import android.view.*
|
||||
import android.view.inputmethod.EditorInfo.IME_ACTION_DONE
|
||||
import android.widget.*
|
||||
import androidx.activity.viewModels
|
||||
import androidx.annotation.RequiresApi
|
||||
import androidx.appcompat.widget.Toolbar
|
||||
import androidx.biometric.BiometricManager
|
||||
import androidx.core.app.ActivityCompat
|
||||
import androidx.lifecycle.Observer
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import com.kunzisoft.keepass.R
|
||||
import com.kunzisoft.keepass.activities.dialogs.DuplicateUuidDialog
|
||||
@@ -48,10 +50,9 @@ import com.kunzisoft.keepass.activities.helpers.ReadOnlyHelper
|
||||
import com.kunzisoft.keepass.activities.lock.LockingActivity
|
||||
import com.kunzisoft.keepass.activities.selection.SpecialModeActivity
|
||||
import com.kunzisoft.keepass.app.database.CipherDatabaseEntity
|
||||
import com.kunzisoft.keepass.app.database.FileDatabaseHistoryAction
|
||||
import com.kunzisoft.keepass.autofill.AutofillHelper
|
||||
import com.kunzisoft.keepass.biometric.AdvancedUnlockedManager
|
||||
import com.kunzisoft.keepass.database.action.ProgressDialogThread
|
||||
import com.kunzisoft.keepass.database.action.ProgressDatabaseTaskProvider
|
||||
import com.kunzisoft.keepass.database.element.Database
|
||||
import com.kunzisoft.keepass.database.exception.DuplicateUuidDatabaseException
|
||||
import com.kunzisoft.keepass.database.search.SearchHelper
|
||||
@@ -60,7 +61,7 @@ import com.kunzisoft.keepass.model.SearchInfo
|
||||
import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_LOAD_TASK
|
||||
import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.CIPHER_ENTITY_KEY
|
||||
import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.DATABASE_URI_KEY
|
||||
import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.KEY_FILE_KEY
|
||||
import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.KEY_FILE_URI_KEY
|
||||
import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.MASTER_PASSWORD_KEY
|
||||
import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.READ_ONLY_KEY
|
||||
import com.kunzisoft.keepass.settings.PreferencesUtil
|
||||
@@ -68,6 +69,7 @@ import com.kunzisoft.keepass.utils.*
|
||||
import com.kunzisoft.keepass.view.AdvancedUnlockInfoView
|
||||
import com.kunzisoft.keepass.view.KeyFileSelectionView
|
||||
import com.kunzisoft.keepass.view.asError
|
||||
import com.kunzisoft.keepass.viewmodels.DatabaseFileViewModel
|
||||
import kotlinx.android.synthetic.main.activity_password.*
|
||||
import java.io.FileNotFoundException
|
||||
|
||||
@@ -86,6 +88,8 @@ open class PasswordActivity : SpecialModeActivity() {
|
||||
private var infoContainerView: ViewGroup? = null
|
||||
private var enableButtonOnCheckedChangeListener: CompoundButton.OnCheckedChangeListener? = null
|
||||
|
||||
private val databaseFileViewModel: DatabaseFileViewModel by viewModels()
|
||||
|
||||
private var mDatabaseFileUri: Uri? = null
|
||||
private var mDatabaseKeyFileUri: Uri? = null
|
||||
|
||||
@@ -105,7 +109,7 @@ open class PasswordActivity : SpecialModeActivity() {
|
||||
field = value
|
||||
}
|
||||
|
||||
private var mProgressDialogThread: ProgressDialogThread? = null
|
||||
private var mProgressDatabaseTaskProvider: ProgressDatabaseTaskProvider? = null
|
||||
|
||||
private var advancedUnlockedManager: AdvancedUnlockedManager? = null
|
||||
private var mAllowAutoOpenBiometricPrompt: Boolean = true
|
||||
@@ -133,6 +137,7 @@ open class PasswordActivity : SpecialModeActivity() {
|
||||
|
||||
mPermissionAsked = savedInstanceState?.getBoolean(KEY_PERMISSION_ASKED) ?: mPermissionAsked
|
||||
readOnly = ReadOnlyHelper.retrieveReadOnlyFromInstanceStateOrPreference(this, savedInstanceState)
|
||||
mRememberKeyFile = PreferencesUtil.rememberKeyFileLocations(this)
|
||||
|
||||
mOpenFileHelper = OpenFileHelper(this@PasswordActivity)
|
||||
keyFileSelectionView?.apply {
|
||||
@@ -163,12 +168,34 @@ open class PasswordActivity : SpecialModeActivity() {
|
||||
if (savedInstanceState?.containsKey(KEY_KEYFILE) == true) {
|
||||
mDatabaseKeyFileUri = UriUtil.parse(savedInstanceState.getString(KEY_KEYFILE))
|
||||
}
|
||||
|
||||
if (savedInstanceState?.containsKey(ALLOW_AUTO_OPEN_BIOMETRIC_PROMPT) == true) {
|
||||
mAllowAutoOpenBiometricPrompt = savedInstanceState.getBoolean(ALLOW_AUTO_OPEN_BIOMETRIC_PROMPT)
|
||||
}
|
||||
|
||||
mProgressDialogThread = ProgressDialogThread(this).apply {
|
||||
// Observe database file change
|
||||
databaseFileViewModel.databaseFileLoaded.observe(this, Observer { databaseFile ->
|
||||
// Force read only if the file does not exists
|
||||
mForceReadOnly = databaseFile?.let {
|
||||
!it.databaseFileExists
|
||||
} ?: true
|
||||
invalidateOptionsMenu()
|
||||
|
||||
// Post init uri with KeyFile only if needed
|
||||
val keyFileUri =
|
||||
if (mRememberKeyFile
|
||||
&& (mDatabaseKeyFileUri == null || mDatabaseKeyFileUri.toString().isEmpty())) {
|
||||
databaseFile?.keyFileUri
|
||||
} else {
|
||||
mDatabaseKeyFileUri
|
||||
}
|
||||
|
||||
// Define title
|
||||
filenameView?.text = databaseFile?.databaseAlias ?: ""
|
||||
|
||||
onDatabaseFileLoaded(databaseFile?.databaseUri, keyFileUri)
|
||||
})
|
||||
|
||||
mProgressDatabaseTaskProvider = ProgressDatabaseTaskProvider(this).apply {
|
||||
onActionFinish = { actionTask, result ->
|
||||
when (actionTask) {
|
||||
ACTION_DATABASE_LOAD_TASK -> {
|
||||
@@ -205,7 +232,7 @@ open class PasswordActivity : SpecialModeActivity() {
|
||||
result.data?.let { resultData ->
|
||||
databaseUri = resultData.getParcelable(DATABASE_URI_KEY)
|
||||
masterPassword = resultData.getString(MASTER_PASSWORD_KEY)
|
||||
keyFileUri = resultData.getParcelable(KEY_FILE_KEY)
|
||||
keyFileUri = resultData.getParcelable(KEY_FILE_URI_KEY)
|
||||
readOnly = resultData.getBoolean(READ_ONLY_KEY)
|
||||
cipherEntity = resultData.getParcelable(CIPHER_ENTITY_KEY)
|
||||
}
|
||||
@@ -351,7 +378,7 @@ open class PasswordActivity : SpecialModeActivity() {
|
||||
clearCredentialsViews()
|
||||
}
|
||||
|
||||
mProgressDialogThread?.registerProgressTask()
|
||||
mProgressDatabaseTaskProvider?.registerProgressTask()
|
||||
|
||||
// Back to previous keyboard is setting activated
|
||||
if (PreferencesUtil.isKeyboardPreviousDatabaseCredentialsEnable(this)) {
|
||||
@@ -364,45 +391,15 @@ open class PasswordActivity : SpecialModeActivity() {
|
||||
else
|
||||
mAllowAutoOpenBiometricPrompt
|
||||
|
||||
initUriFromIntent()
|
||||
mDatabaseFileUri?.let { databaseFileUri ->
|
||||
databaseFileViewModel.loadDatabaseFile(databaseFileUri)
|
||||
}
|
||||
|
||||
checkPermission()
|
||||
}
|
||||
}
|
||||
|
||||
private fun initUriFromIntent() {
|
||||
/*
|
||||
// "canXrite" doesn't work with Google Drive, don't really know why?
|
||||
mForceReadOnly = mDatabaseFileUri?.let {
|
||||
!FileDatabaseInfo(this, it).canWrite
|
||||
} ?: false
|
||||
*/
|
||||
mForceReadOnly = mDatabaseFileUri?.let {
|
||||
!FileDatabaseInfo(this, it).exists
|
||||
} ?: true
|
||||
|
||||
// Post init uri with KeyFile if needed
|
||||
if (mRememberKeyFile && (mDatabaseKeyFileUri == null || mDatabaseKeyFileUri.toString().isEmpty())) {
|
||||
// Retrieve KeyFile in a thread
|
||||
mDatabaseFileUri?.let { databaseUri ->
|
||||
FileDatabaseHistoryAction.getInstance(applicationContext)
|
||||
.getKeyFileUriByDatabaseUri(databaseUri) {
|
||||
onPostInitUri(databaseUri, it)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
onPostInitUri(mDatabaseFileUri, mDatabaseKeyFileUri)
|
||||
}
|
||||
}
|
||||
|
||||
private fun onPostInitUri(databaseFileUri: Uri?, keyFileUri: Uri?) {
|
||||
// Define title
|
||||
databaseFileUri?.let {
|
||||
FileDatabaseInfo(this, it).retrieveDatabaseTitle { title ->
|
||||
filenameView?.text = title
|
||||
}
|
||||
}
|
||||
|
||||
private fun onDatabaseFileLoaded(databaseFileUri: Uri?, keyFileUri: Uri?) {
|
||||
// Define Key File text
|
||||
if (mRememberKeyFile) {
|
||||
populateKeyFileTextView(keyFileUri)
|
||||
@@ -533,7 +530,7 @@ open class PasswordActivity : SpecialModeActivity() {
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
mProgressDialogThread?.unregisterProgressTask()
|
||||
mProgressDatabaseTaskProvider?.unregisterProgressTask()
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
advancedUnlockedManager?.destroy()
|
||||
@@ -608,7 +605,7 @@ open class PasswordActivity : SpecialModeActivity() {
|
||||
readOnly: Boolean,
|
||||
cipherDatabaseEntity: CipherDatabaseEntity?,
|
||||
fixDuplicateUUID: Boolean) {
|
||||
mProgressDialogThread?.startDatabaseLoad(
|
||||
mProgressDatabaseTaskProvider?.startDatabaseLoad(
|
||||
databaseUri,
|
||||
password,
|
||||
keyFile,
|
||||
|
||||
@@ -27,7 +27,7 @@ import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import com.kunzisoft.keepass.activities.helpers.ReadOnlyHelper
|
||||
import com.kunzisoft.keepass.activities.selection.SpecialModeActivity
|
||||
import com.kunzisoft.keepass.database.action.ProgressDialogThread
|
||||
import com.kunzisoft.keepass.database.action.ProgressDatabaseTaskProvider
|
||||
import com.kunzisoft.keepass.database.element.Database
|
||||
import com.kunzisoft.keepass.settings.PreferencesUtil
|
||||
import com.kunzisoft.keepass.timeout.TimeoutHelper
|
||||
@@ -51,7 +51,7 @@ abstract class LockingActivity : SpecialModeActivity() {
|
||||
private var mReadOnlyToSave: Boolean = false
|
||||
protected var mAutoSaveEnable: Boolean = true
|
||||
|
||||
var mProgressDialogThread: ProgressDialogThread? = null
|
||||
var mProgressDatabaseTaskProvider: ProgressDatabaseTaskProvider? = null
|
||||
private set
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
@@ -80,7 +80,7 @@ abstract class LockingActivity : SpecialModeActivity() {
|
||||
|
||||
mExitLock = false
|
||||
|
||||
mProgressDialogThread = ProgressDialogThread(this)
|
||||
mProgressDatabaseTaskProvider = ProgressDatabaseTaskProvider(this)
|
||||
}
|
||||
|
||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||
@@ -96,7 +96,7 @@ abstract class LockingActivity : SpecialModeActivity() {
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
|
||||
mProgressDialogThread?.registerProgressTask()
|
||||
mProgressDatabaseTaskProvider?.registerProgressTask()
|
||||
|
||||
// To refresh when back to normal workflow from selection workflow
|
||||
mReadOnlyToSave = ReadOnlyHelper.retrieveReadOnlyFromIntent(intent)
|
||||
@@ -131,7 +131,7 @@ abstract class LockingActivity : SpecialModeActivity() {
|
||||
override fun onPause() {
|
||||
LOCKING_ACTIVITY_UI_VISIBLE = false
|
||||
|
||||
mProgressDialogThread?.unregisterProgressTask()
|
||||
mProgressDatabaseTaskProvider?.unregisterProgressTask()
|
||||
|
||||
super.onPause()
|
||||
|
||||
|
||||
@@ -31,19 +31,17 @@ import android.widget.ImageView
|
||||
import android.widget.TextView
|
||||
import android.widget.ViewSwitcher
|
||||
import com.kunzisoft.keepass.R
|
||||
import com.kunzisoft.keepass.app.database.FileDatabaseHistoryEntity
|
||||
import com.kunzisoft.keepass.utils.FileDatabaseInfo
|
||||
import com.kunzisoft.keepass.utils.UriUtil
|
||||
import com.kunzisoft.keepass.model.DatabaseFile
|
||||
|
||||
class FileDatabaseHistoryAdapter(private val context: Context)
|
||||
class FileDatabaseHistoryAdapter(context: Context)
|
||||
: RecyclerView.Adapter<FileDatabaseHistoryAdapter.FileDatabaseHistoryViewHolder>() {
|
||||
|
||||
private val inflater: LayoutInflater = LayoutInflater.from(context)
|
||||
private var fileItemOpenListener: ((FileDatabaseHistoryEntity)->Unit)? = null
|
||||
private var fileSelectClearListener: ((FileDatabaseHistoryEntity)->Boolean)? = null
|
||||
private var saveAliasListener: ((FileDatabaseHistoryEntity)->Unit)? = null
|
||||
private var fileItemOpenListener: ((DatabaseFile)->Unit)? = null
|
||||
private var fileSelectClearListener: ((DatabaseFile)->Boolean)? = null
|
||||
private var saveAliasListener: ((DatabaseFile)->Unit)? = null
|
||||
|
||||
private val listDatabaseFiles = ArrayList<FileDatabaseHistoryEntity>()
|
||||
private val listDatabaseFiles = ArrayList<DatabaseFile>()
|
||||
|
||||
private var mExpandedPosition = -1
|
||||
private var mPreviousExpandedPosition = -1
|
||||
@@ -69,29 +67,28 @@ class FileDatabaseHistoryAdapter(private val context: Context)
|
||||
|
||||
override fun onBindViewHolder(holder: FileDatabaseHistoryViewHolder, position: Int) {
|
||||
// Get info from position
|
||||
val fileHistoryEntity = listDatabaseFiles[position]
|
||||
val fileDatabaseInfo = FileDatabaseInfo(context, fileHistoryEntity.databaseUri)
|
||||
val databaseFile = listDatabaseFiles[position]
|
||||
|
||||
// Click item to open file
|
||||
if (fileItemOpenListener != null)
|
||||
holder.fileContainer.setOnClickListener {
|
||||
fileItemOpenListener?.invoke(fileHistoryEntity)
|
||||
fileItemOpenListener?.invoke(databaseFile)
|
||||
}
|
||||
|
||||
// File alias
|
||||
holder.fileAlias.text = fileDatabaseInfo.retrieveDatabaseAlias(fileHistoryEntity.databaseAlias)
|
||||
holder.fileAlias.text = databaseFile.databaseAlias
|
||||
|
||||
// File path
|
||||
holder.filePath.text = UriUtil.decode(fileDatabaseInfo.fileUri?.toString())
|
||||
holder.filePath.text = databaseFile.databaseDecodedPath
|
||||
|
||||
if (fileDatabaseInfo.exists) {
|
||||
if (databaseFile.databaseFileExists) {
|
||||
holder.fileInformation.clearColorFilter()
|
||||
} else {
|
||||
holder.fileInformation.setColorFilter(Color.RED, PorterDuff.Mode.MULTIPLY)
|
||||
}
|
||||
|
||||
// Modification
|
||||
fileDatabaseInfo.getModificationString()?.let {
|
||||
databaseFile.databaseLastModified?.let {
|
||||
holder.fileModification.text = it
|
||||
holder.fileModification.visibility = View.VISIBLE
|
||||
} ?: run {
|
||||
@@ -99,7 +96,7 @@ class FileDatabaseHistoryAdapter(private val context: Context)
|
||||
}
|
||||
|
||||
// Size
|
||||
fileDatabaseInfo.getSizeString()?.let {
|
||||
databaseFile.databaseSize?.let {
|
||||
holder.fileSize.text = it
|
||||
holder.fileSize.visibility = View.VISIBLE
|
||||
} ?: run {
|
||||
@@ -114,8 +111,8 @@ class FileDatabaseHistoryAdapter(private val context: Context)
|
||||
// Save alias modification
|
||||
holder.fileAliasCloseButton.setOnClickListener {
|
||||
// Change the alias
|
||||
fileHistoryEntity.databaseAlias = holder.fileAliasEdit.text.toString()
|
||||
saveAliasListener?.invoke(fileHistoryEntity)
|
||||
databaseFile.databaseAlias = holder.fileAliasEdit.text.toString()
|
||||
saveAliasListener?.invoke(databaseFile)
|
||||
|
||||
// Finish save mode
|
||||
holder.fileMainSwitcher.showPrevious()
|
||||
@@ -130,7 +127,7 @@ class FileDatabaseHistoryAdapter(private val context: Context)
|
||||
}
|
||||
|
||||
holder.fileDeleteButton.setOnClickListener {
|
||||
fileSelectClearListener?.invoke(fileHistoryEntity)
|
||||
fileSelectClearListener?.invoke(databaseFile)
|
||||
}
|
||||
|
||||
if (isExpanded) {
|
||||
@@ -160,24 +157,24 @@ class FileDatabaseHistoryAdapter(private val context: Context)
|
||||
listDatabaseFiles.clear()
|
||||
}
|
||||
|
||||
fun addDatabaseFileHistoryList(listFileDatabaseHistoryToAdd: List<FileDatabaseHistoryEntity>) {
|
||||
fun replaceAllDatabaseFileHistoryList(listFileDatabaseHistoryToAdd: List<DatabaseFile>) {
|
||||
listDatabaseFiles.clear()
|
||||
listDatabaseFiles.addAll(listFileDatabaseHistoryToAdd)
|
||||
}
|
||||
|
||||
fun deleteDatabaseFileHistory(fileDatabaseHistoryToDelete: FileDatabaseHistoryEntity) {
|
||||
fun deleteDatabaseFileHistory(fileDatabaseHistoryToDelete: DatabaseFile) {
|
||||
listDatabaseFiles.remove(fileDatabaseHistoryToDelete)
|
||||
}
|
||||
|
||||
fun setOnFileDatabaseHistoryOpenListener(listener : ((FileDatabaseHistoryEntity)->Unit)?) {
|
||||
fun setOnFileDatabaseHistoryOpenListener(listener : ((DatabaseFile)->Unit)?) {
|
||||
this.fileItemOpenListener = listener
|
||||
}
|
||||
|
||||
fun setOnFileDatabaseHistoryDeleteListener(listener : ((FileDatabaseHistoryEntity)->Boolean)?) {
|
||||
fun setOnFileDatabaseHistoryDeleteListener(listener : ((DatabaseFile)->Boolean)?) {
|
||||
this.fileSelectClearListener = listener
|
||||
}
|
||||
|
||||
fun setOnSaveAliasListener(listener : ((FileDatabaseHistoryEntity)->Unit)?) {
|
||||
fun setOnSaveAliasListener(listener : ((DatabaseFile)->Unit)?) {
|
||||
this.saveAliasListener = listener
|
||||
}
|
||||
|
||||
|
||||
@@ -21,24 +21,37 @@ package com.kunzisoft.keepass.app.database
|
||||
|
||||
import android.content.Context
|
||||
import android.net.Uri
|
||||
import com.kunzisoft.keepass.model.DatabaseFile
|
||||
import com.kunzisoft.keepass.settings.PreferencesUtil
|
||||
import com.kunzisoft.keepass.utils.SingletonHolderParameter
|
||||
import com.kunzisoft.keepass.utils.UriUtil
|
||||
import com.kunzisoft.keepass.viewmodels.FileDatabaseInfo
|
||||
|
||||
class FileDatabaseHistoryAction(applicationContext: Context) {
|
||||
class FileDatabaseHistoryAction(private val applicationContext: Context) {
|
||||
|
||||
private val databaseFileHistoryDao =
|
||||
AppDatabase
|
||||
.getDatabase(applicationContext)
|
||||
.fileDatabaseHistoryDao()
|
||||
|
||||
fun getFileDatabaseHistory(databaseUri: Uri,
|
||||
fileHistoryResultListener: (fileDatabaseHistoryResult: FileDatabaseHistoryEntity?) -> Unit) {
|
||||
fun getDatabaseFile(databaseUri: Uri,
|
||||
databaseFileResult: (DatabaseFile?) -> Unit) {
|
||||
IOActionTask(
|
||||
{
|
||||
databaseFileHistoryDao.getByDatabaseUri(databaseUri.toString())
|
||||
val fileDatabaseHistoryEntity = databaseFileHistoryDao.getByDatabaseUri(databaseUri.toString())
|
||||
val fileDatabaseInfo = FileDatabaseInfo(applicationContext, databaseUri)
|
||||
DatabaseFile(
|
||||
databaseUri,
|
||||
UriUtil.parse(fileDatabaseHistoryEntity?.keyFileUri),
|
||||
UriUtil.decode(fileDatabaseHistoryEntity?.databaseUri),
|
||||
fileDatabaseInfo.retrieveDatabaseAlias(fileDatabaseHistoryEntity?.databaseAlias ?: ""),
|
||||
fileDatabaseInfo.exists,
|
||||
fileDatabaseInfo.getModificationString(),
|
||||
fileDatabaseInfo.getSizeString()
|
||||
)
|
||||
},
|
||||
{
|
||||
fileHistoryResultListener.invoke(it)
|
||||
databaseFileResult.invoke(it)
|
||||
}
|
||||
).execute()
|
||||
}
|
||||
@@ -59,55 +72,110 @@ class FileDatabaseHistoryAction(applicationContext: Context) {
|
||||
).execute()
|
||||
}
|
||||
|
||||
fun getAllFileDatabaseHistories(fileHistoryResultListener: (fileDatabaseHistoryResult: List<FileDatabaseHistoryEntity>?) -> Unit) {
|
||||
fun getDatabaseFileList(databaseFileListResult: (List<DatabaseFile>) -> Unit) {
|
||||
IOActionTask(
|
||||
{
|
||||
databaseFileHistoryDao.getAll()
|
||||
val hideBrokenLocations = PreferencesUtil.hideBrokenLocations(applicationContext)
|
||||
// Show only uri accessible
|
||||
val databaseFileListLoaded = ArrayList<DatabaseFile>()
|
||||
databaseFileHistoryDao.getAll().forEach { fileDatabaseHistoryEntity ->
|
||||
val fileDatabaseInfo = FileDatabaseInfo(applicationContext, fileDatabaseHistoryEntity.databaseUri)
|
||||
if (hideBrokenLocations && fileDatabaseInfo.exists
|
||||
|| !hideBrokenLocations) {
|
||||
databaseFileListLoaded.add(
|
||||
DatabaseFile(
|
||||
UriUtil.parse(fileDatabaseHistoryEntity.databaseUri),
|
||||
UriUtil.parse(fileDatabaseHistoryEntity.keyFileUri),
|
||||
UriUtil.decode(fileDatabaseHistoryEntity.databaseUri),
|
||||
fileDatabaseInfo.retrieveDatabaseAlias(fileDatabaseHistoryEntity.databaseAlias),
|
||||
fileDatabaseInfo.exists,
|
||||
fileDatabaseInfo.getModificationString(),
|
||||
fileDatabaseInfo.getSizeString()
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
databaseFileListLoaded
|
||||
},
|
||||
{
|
||||
fileHistoryResultListener.invoke(it)
|
||||
}
|
||||
).execute()
|
||||
}
|
||||
|
||||
fun addOrUpdateDatabaseUri(databaseUri: Uri, keyFileUri: Uri? = null) {
|
||||
addOrUpdateFileDatabaseHistory(FileDatabaseHistoryEntity(
|
||||
databaseUri.toString(),
|
||||
"",
|
||||
keyFileUri?.toString(),
|
||||
System.currentTimeMillis()
|
||||
), true)
|
||||
}
|
||||
|
||||
fun addOrUpdateFileDatabaseHistory(fileDatabaseHistory: FileDatabaseHistoryEntity, unmodifiedAlias: Boolean = false) {
|
||||
IOActionTask(
|
||||
{
|
||||
val fileDatabaseHistoryRetrieve = databaseFileHistoryDao.getByDatabaseUri(fileDatabaseHistory.databaseUri)
|
||||
|
||||
if (unmodifiedAlias) {
|
||||
fileDatabaseHistory.databaseAlias = fileDatabaseHistoryRetrieve?.databaseAlias ?: ""
|
||||
}
|
||||
// Update values if history element not yet in the database
|
||||
if (fileDatabaseHistoryRetrieve == null) {
|
||||
databaseFileHistoryDao.add(fileDatabaseHistory)
|
||||
} else {
|
||||
databaseFileHistoryDao.update(fileDatabaseHistory)
|
||||
databaseFileList ->
|
||||
databaseFileList?.let {
|
||||
databaseFileListResult.invoke(it)
|
||||
}
|
||||
}
|
||||
).execute()
|
||||
}
|
||||
|
||||
fun deleteFileDatabaseHistory(fileDatabaseHistory: FileDatabaseHistoryEntity,
|
||||
fileHistoryDeletedResult: (FileDatabaseHistoryEntity?) -> Unit) {
|
||||
fun addOrUpdateDatabaseUri(databaseUri: Uri, keyFileUri: Uri? = null,
|
||||
databaseFileAddedOrUpdatedResult: ((DatabaseFile?) -> Unit)? = null) {
|
||||
addOrUpdateDatabaseFile(DatabaseFile(
|
||||
databaseUri,
|
||||
keyFileUri
|
||||
), databaseFileAddedOrUpdatedResult)
|
||||
}
|
||||
|
||||
fun addOrUpdateDatabaseFile(databaseFileToAddOrUpdate: DatabaseFile,
|
||||
databaseFileAddedOrUpdatedResult: ((DatabaseFile?) -> Unit)? = null) {
|
||||
IOActionTask(
|
||||
{
|
||||
databaseFileHistoryDao.delete(fileDatabaseHistory)
|
||||
databaseFileToAddOrUpdate.databaseUri?.let { databaseUri ->
|
||||
val fileDatabaseHistory = FileDatabaseHistoryEntity(
|
||||
databaseUri.toString(),
|
||||
databaseFileToAddOrUpdate.databaseAlias ?: "",
|
||||
databaseFileToAddOrUpdate.keyFileUri?.toString(),
|
||||
System.currentTimeMillis()
|
||||
)
|
||||
|
||||
val fileDatabaseHistoryRetrieve = databaseFileHistoryDao.getByDatabaseUri(fileDatabaseHistory.databaseUri)
|
||||
|
||||
// Update values if history element not yet in the database
|
||||
if (fileDatabaseHistoryRetrieve == null) {
|
||||
databaseFileHistoryDao.add(fileDatabaseHistory)
|
||||
} else {
|
||||
databaseFileHistoryDao.update(fileDatabaseHistory)
|
||||
}
|
||||
|
||||
val fileDatabaseInfo = FileDatabaseInfo(applicationContext,
|
||||
fileDatabaseHistory.databaseUri)
|
||||
DatabaseFile(
|
||||
UriUtil.parse(fileDatabaseHistory.databaseUri),
|
||||
UriUtil.parse(fileDatabaseHistory.keyFileUri),
|
||||
UriUtil.decode(fileDatabaseHistory.databaseUri),
|
||||
fileDatabaseInfo.retrieveDatabaseAlias(fileDatabaseHistory.databaseAlias),
|
||||
fileDatabaseInfo.exists,
|
||||
fileDatabaseInfo.getModificationString(),
|
||||
fileDatabaseInfo.getSizeString()
|
||||
)
|
||||
}
|
||||
},
|
||||
{
|
||||
if (it != null && it > 0)
|
||||
fileHistoryDeletedResult.invoke(fileDatabaseHistory)
|
||||
else
|
||||
fileHistoryDeletedResult.invoke(null)
|
||||
databaseFileAddedOrUpdatedResult?.invoke(it)
|
||||
}
|
||||
).execute()
|
||||
}
|
||||
|
||||
fun deleteDatabaseFile(databaseFileToDelete: DatabaseFile,
|
||||
databaseFileDeletedResult: (DatabaseFile?) -> Unit) {
|
||||
IOActionTask(
|
||||
{
|
||||
databaseFileToDelete.databaseUri?.let { databaseUri ->
|
||||
databaseFileHistoryDao.getByDatabaseUri(databaseUri.toString())?.let { fileDatabaseHistory ->
|
||||
val returnValue = databaseFileHistoryDao.delete(fileDatabaseHistory)
|
||||
if (returnValue > 0) {
|
||||
DatabaseFile(
|
||||
UriUtil.parse(fileDatabaseHistory.databaseUri),
|
||||
UriUtil.parse(fileDatabaseHistory.keyFileUri),
|
||||
UriUtil.decode(fileDatabaseHistory.databaseUri),
|
||||
databaseFileToDelete.databaseAlias
|
||||
)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
databaseFileDeletedResult.invoke(it)
|
||||
}
|
||||
).execute()
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ open class AssignPasswordInDatabaseRunnable (
|
||||
: SaveDatabaseRunnable(context, database, true) {
|
||||
|
||||
private var mMasterPassword: String? = null
|
||||
protected var mKeyFile: Uri? = null
|
||||
protected var mKeyFileUri: Uri? = null
|
||||
|
||||
private var mBackupKey: ByteArray? = null
|
||||
|
||||
@@ -45,7 +45,7 @@ open class AssignPasswordInDatabaseRunnable (
|
||||
if (withMasterPassword)
|
||||
this.mMasterPassword = masterPassword
|
||||
if (withKeyFile)
|
||||
this.mKeyFile = keyFile
|
||||
this.mKeyFileUri = keyFile
|
||||
}
|
||||
|
||||
override fun onStartRun() {
|
||||
@@ -55,7 +55,7 @@ open class AssignPasswordInDatabaseRunnable (
|
||||
mBackupKey = ByteArray(database.masterKey.size)
|
||||
System.arraycopy(database.masterKey, 0, mBackupKey!!, 0, mBackupKey!!.size)
|
||||
|
||||
val uriInputStream = UriUtil.getUriInputStream(context.contentResolver, mKeyFile)
|
||||
val uriInputStream = UriUtil.getUriInputStream(context.contentResolver, mKeyFileUri)
|
||||
database.retrieveMasterKey(mMasterPassword, uriInputStream)
|
||||
} catch (e: Exception) {
|
||||
erase(mBackupKey)
|
||||
|
||||
@@ -34,7 +34,8 @@ class CreateDatabaseRunnable(context: Context,
|
||||
withMasterPassword: Boolean,
|
||||
masterPassword: String?,
|
||||
withKeyFile: Boolean,
|
||||
keyFile: Uri?)
|
||||
keyFile: Uri?,
|
||||
private val createDatabaseResult: ((Result) -> Unit)?)
|
||||
: AssignPasswordInDatabaseRunnable(context, mDatabase, databaseUri, withMasterPassword, masterPassword, withKeyFile, keyFile) {
|
||||
|
||||
override fun onStartRun() {
|
||||
@@ -53,18 +54,24 @@ class CreateDatabaseRunnable(context: Context,
|
||||
super.onStartRun()
|
||||
}
|
||||
|
||||
override fun onFinishRun() {
|
||||
super.onFinishRun()
|
||||
override fun onActionRun() {
|
||||
super.onActionRun()
|
||||
|
||||
if (result.isSuccess) {
|
||||
// Add database to recent files
|
||||
if (PreferencesUtil.rememberDatabaseLocations(context)) {
|
||||
FileDatabaseHistoryAction.getInstance(context.applicationContext)
|
||||
.addOrUpdateDatabaseUri(mDatabaseUri,
|
||||
if (PreferencesUtil.rememberKeyFileLocations(context)) mKeyFile else null)
|
||||
if (PreferencesUtil.rememberKeyFileLocations(context)) mKeyFileUri else null)
|
||||
}
|
||||
} else {
|
||||
Log.e("CreateDatabaseRunnable", "Unable to create the database")
|
||||
}
|
||||
}
|
||||
|
||||
override fun onFinishRun() {
|
||||
super.onFinishRun()
|
||||
|
||||
createDatabaseResult?.invoke(result)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ class LoadDatabaseRunnable(private val context: Context,
|
||||
private val mCipherEntity: CipherDatabaseEntity?,
|
||||
private val mFixDuplicateUUID: Boolean,
|
||||
private val progressTaskUpdater: ProgressTaskUpdater?,
|
||||
private val mDuplicateUuidAction: ((Result) -> Unit)?)
|
||||
private val mLoadDatabaseResult: ((Result) -> Unit)?)
|
||||
: ActionRunnable() {
|
||||
|
||||
private val cacheDirectory = context.applicationContext.filesDir
|
||||
@@ -60,15 +60,12 @@ class LoadDatabaseRunnable(private val context: Context,
|
||||
progressTaskUpdater)
|
||||
}
|
||||
catch (e: DuplicateUuidDatabaseException) {
|
||||
mDuplicateUuidAction?.invoke(result)
|
||||
setError(e)
|
||||
}
|
||||
catch (e: LoadDatabaseException) {
|
||||
setError(e)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onFinishRun() {
|
||||
if (result.isSuccess) {
|
||||
// Save keyFile in app database
|
||||
if (PreferencesUtil.rememberDatabaseLocations(context)) {
|
||||
@@ -89,4 +86,8 @@ class LoadDatabaseRunnable(private val context: Context,
|
||||
mDatabase.closeAndClear(cacheDirectory)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onFinishRun() {
|
||||
mLoadDatabaseResult?.invoke(result)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,7 +71,7 @@ import com.kunzisoft.keepass.utils.DATABASE_STOP_TASK_ACTION
|
||||
import java.util.*
|
||||
import kotlin.collections.ArrayList
|
||||
|
||||
class ProgressDialogThread(private val activity: FragmentActivity) {
|
||||
class ProgressDatabaseTaskProvider(private val activity: FragmentActivity) {
|
||||
|
||||
var onActionFinish: ((actionTask: String,
|
||||
result: ActionRunnable.Result) -> Unit)? = null
|
||||
@@ -241,7 +241,7 @@ class ProgressDialogThread(private val activity: FragmentActivity) {
|
||||
putBoolean(DatabaseTaskNotificationService.MASTER_PASSWORD_CHECKED_KEY, masterPasswordChecked)
|
||||
putString(DatabaseTaskNotificationService.MASTER_PASSWORD_KEY, masterPassword)
|
||||
putBoolean(DatabaseTaskNotificationService.KEY_FILE_CHECKED_KEY, keyFileChecked)
|
||||
putParcelable(DatabaseTaskNotificationService.KEY_FILE_KEY, keyFile)
|
||||
putParcelable(DatabaseTaskNotificationService.KEY_FILE_URI_KEY, keyFile)
|
||||
}
|
||||
, ACTION_DATABASE_CREATE_TASK)
|
||||
}
|
||||
@@ -255,7 +255,7 @@ class ProgressDialogThread(private val activity: FragmentActivity) {
|
||||
start(Bundle().apply {
|
||||
putParcelable(DatabaseTaskNotificationService.DATABASE_URI_KEY, databaseUri)
|
||||
putString(DatabaseTaskNotificationService.MASTER_PASSWORD_KEY, masterPassword)
|
||||
putParcelable(DatabaseTaskNotificationService.KEY_FILE_KEY, keyFile)
|
||||
putParcelable(DatabaseTaskNotificationService.KEY_FILE_URI_KEY, keyFile)
|
||||
putBoolean(DatabaseTaskNotificationService.READ_ONLY_KEY, readOnly)
|
||||
putParcelable(DatabaseTaskNotificationService.CIPHER_ENTITY_KEY, cipherEntity)
|
||||
putBoolean(DatabaseTaskNotificationService.FIX_DUPLICATE_UUID_KEY, fixDuplicateUuid)
|
||||
@@ -274,7 +274,7 @@ class ProgressDialogThread(private val activity: FragmentActivity) {
|
||||
putBoolean(DatabaseTaskNotificationService.MASTER_PASSWORD_CHECKED_KEY, masterPasswordChecked)
|
||||
putString(DatabaseTaskNotificationService.MASTER_PASSWORD_KEY, masterPassword)
|
||||
putBoolean(DatabaseTaskNotificationService.KEY_FILE_CHECKED_KEY, keyFileChecked)
|
||||
putParcelable(DatabaseTaskNotificationService.KEY_FILE_KEY, keyFile)
|
||||
putParcelable(DatabaseTaskNotificationService.KEY_FILE_URI_KEY, keyFile)
|
||||
}
|
||||
, ACTION_DATABASE_ASSIGN_PASSWORD_TASK)
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package com.kunzisoft.keepass.model
|
||||
|
||||
import android.net.Uri
|
||||
|
||||
data class DatabaseFile(var databaseUri: Uri? = null,
|
||||
var keyFileUri: Uri? = null,
|
||||
var databaseDecodedPath: String? = null,
|
||||
var databaseAlias: String? = null,
|
||||
var databaseFileExists: Boolean = false,
|
||||
var databaseLastModified: String? = null,
|
||||
var databaseSize: String? = null) {
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
if (other !is DatabaseFile) return false
|
||||
|
||||
if (databaseUri == null) return false
|
||||
if (databaseUri != other.databaseUri) return false
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
return databaseUri?.hashCode() ?: 0
|
||||
}
|
||||
}
|
||||
@@ -295,7 +295,7 @@ open class DatabaseTaskNotificationService : LockNotificationService(), Progress
|
||||
intent?.removeExtra(MASTER_PASSWORD_CHECKED_KEY)
|
||||
intent?.removeExtra(MASTER_PASSWORD_KEY)
|
||||
intent?.removeExtra(KEY_FILE_CHECKED_KEY)
|
||||
intent?.removeExtra(KEY_FILE_KEY)
|
||||
intent?.removeExtra(KEY_FILE_URI_KEY)
|
||||
intent?.removeExtra(READ_ONLY_KEY)
|
||||
intent?.removeExtra(CIPHER_ENTITY_KEY)
|
||||
intent?.removeExtra(FIX_DUPLICATE_UUID_KEY)
|
||||
@@ -380,10 +380,10 @@ open class DatabaseTaskNotificationService : LockNotificationService(), Progress
|
||||
&& intent.hasExtra(MASTER_PASSWORD_CHECKED_KEY)
|
||||
&& intent.hasExtra(MASTER_PASSWORD_KEY)
|
||||
&& intent.hasExtra(KEY_FILE_CHECKED_KEY)
|
||||
&& intent.hasExtra(KEY_FILE_KEY)
|
||||
&& intent.hasExtra(KEY_FILE_URI_KEY)
|
||||
) {
|
||||
val databaseUri: Uri? = intent.getParcelableExtra(DATABASE_URI_KEY)
|
||||
val keyFileUri: Uri? = intent.getParcelableExtra(KEY_FILE_KEY)
|
||||
val keyFileUri: Uri? = intent.getParcelableExtra(KEY_FILE_URI_KEY)
|
||||
|
||||
if (databaseUri == null)
|
||||
return null
|
||||
@@ -397,7 +397,12 @@ open class DatabaseTaskNotificationService : LockNotificationService(), Progress
|
||||
intent.getStringExtra(MASTER_PASSWORD_KEY),
|
||||
intent.getBooleanExtra(KEY_FILE_CHECKED_KEY, false),
|
||||
keyFileUri
|
||||
)
|
||||
) { result ->
|
||||
result.data = Bundle().apply {
|
||||
putParcelable(DATABASE_URI_KEY, databaseUri)
|
||||
putParcelable(KEY_FILE_URI_KEY, keyFileUri)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return null
|
||||
}
|
||||
@@ -407,14 +412,14 @@ open class DatabaseTaskNotificationService : LockNotificationService(), Progress
|
||||
|
||||
if (intent.hasExtra(DATABASE_URI_KEY)
|
||||
&& intent.hasExtra(MASTER_PASSWORD_KEY)
|
||||
&& intent.hasExtra(KEY_FILE_KEY)
|
||||
&& intent.hasExtra(KEY_FILE_URI_KEY)
|
||||
&& intent.hasExtra(READ_ONLY_KEY)
|
||||
&& intent.hasExtra(CIPHER_ENTITY_KEY)
|
||||
&& intent.hasExtra(FIX_DUPLICATE_UUID_KEY)
|
||||
) {
|
||||
val databaseUri: Uri? = intent.getParcelableExtra(DATABASE_URI_KEY)
|
||||
val masterPassword: String? = intent.getStringExtra(MASTER_PASSWORD_KEY)
|
||||
val keyFileUri: Uri? = intent.getParcelableExtra(KEY_FILE_KEY)
|
||||
val keyFileUri: Uri? = intent.getParcelableExtra(KEY_FILE_URI_KEY)
|
||||
val readOnly: Boolean = intent.getBooleanExtra(READ_ONLY_KEY, true)
|
||||
val cipherEntity: CipherDatabaseEntity? = intent.getParcelableExtra(CIPHER_ENTITY_KEY)
|
||||
|
||||
@@ -436,7 +441,7 @@ open class DatabaseTaskNotificationService : LockNotificationService(), Progress
|
||||
result.data = Bundle().apply {
|
||||
putParcelable(DATABASE_URI_KEY, databaseUri)
|
||||
putString(MASTER_PASSWORD_KEY, masterPassword)
|
||||
putParcelable(KEY_FILE_KEY, keyFileUri)
|
||||
putParcelable(KEY_FILE_URI_KEY, keyFileUri)
|
||||
putBoolean(READ_ONLY_KEY, readOnly)
|
||||
putParcelable(CIPHER_ENTITY_KEY, cipherEntity)
|
||||
}
|
||||
@@ -451,7 +456,7 @@ open class DatabaseTaskNotificationService : LockNotificationService(), Progress
|
||||
&& intent.hasExtra(MASTER_PASSWORD_CHECKED_KEY)
|
||||
&& intent.hasExtra(MASTER_PASSWORD_KEY)
|
||||
&& intent.hasExtra(KEY_FILE_CHECKED_KEY)
|
||||
&& intent.hasExtra(KEY_FILE_KEY)
|
||||
&& intent.hasExtra(KEY_FILE_URI_KEY)
|
||||
) {
|
||||
val databaseUri: Uri = intent.getParcelableExtra(DATABASE_URI_KEY) ?: return null
|
||||
AssignPasswordInDatabaseRunnable(this,
|
||||
@@ -460,7 +465,7 @@ open class DatabaseTaskNotificationService : LockNotificationService(), Progress
|
||||
intent.getBooleanExtra(MASTER_PASSWORD_CHECKED_KEY, false),
|
||||
intent.getStringExtra(MASTER_PASSWORD_KEY),
|
||||
intent.getBooleanExtra(KEY_FILE_CHECKED_KEY, false),
|
||||
intent.getParcelableExtra(KEY_FILE_KEY)
|
||||
intent.getParcelableExtra(KEY_FILE_URI_KEY)
|
||||
)
|
||||
} else {
|
||||
null
|
||||
@@ -766,7 +771,7 @@ open class DatabaseTaskNotificationService : LockNotificationService(), Progress
|
||||
const val MASTER_PASSWORD_CHECKED_KEY = "MASTER_PASSWORD_CHECKED_KEY"
|
||||
const val MASTER_PASSWORD_KEY = "MASTER_PASSWORD_KEY"
|
||||
const val KEY_FILE_CHECKED_KEY = "KEY_FILE_CHECKED_KEY"
|
||||
const val KEY_FILE_KEY = "KEY_FILE_KEY"
|
||||
const val KEY_FILE_URI_KEY = "KEY_FILE_URI_KEY"
|
||||
const val READ_ONLY_KEY = "READ_ONLY_KEY"
|
||||
const val CIPHER_ENTITY_KEY = "CIPHER_ENTITY_KEY"
|
||||
const val FIX_DUPLICATE_UUID_KEY = "FIX_DUPLICATE_UUID_KEY"
|
||||
|
||||
@@ -166,7 +166,7 @@ class NestedDatabaseSettingsFragment : NestedSettingsFragment() {
|
||||
refreshRecycleBinGroup()
|
||||
// Save the database if not in readonly mode
|
||||
(context as SettingsActivity?)?.
|
||||
mProgressDialogThread?.startDatabaseSave(mDatabaseAutoSaveEnabled)
|
||||
mProgressDatabaseTaskProvider?.startDatabaseSave(mDatabaseAutoSaveEnabled)
|
||||
true
|
||||
}
|
||||
true
|
||||
@@ -546,7 +546,7 @@ class NestedDatabaseSettingsFragment : NestedSettingsFragment() {
|
||||
|
||||
return when (item.itemId) {
|
||||
R.id.menu_save_database -> {
|
||||
settingActivity?.mProgressDialogThread?.startDatabaseSave(!mDatabaseReadOnly)
|
||||
settingActivity?.mProgressDatabaseTaskProvider?.startDatabaseSave(!mDatabaseReadOnly)
|
||||
true
|
||||
}
|
||||
|
||||
|
||||
@@ -105,7 +105,7 @@ open class SettingsActivity
|
||||
|
||||
backupManager = BackupManager(this)
|
||||
|
||||
mProgressDialogThread?.onActionFinish = { actionTask, result ->
|
||||
mProgressDatabaseTaskProvider?.onActionFinish = { actionTask, result ->
|
||||
// Call result in fragment
|
||||
(supportFragmentManager
|
||||
.findFragmentByTag(TAG_NESTED) as NestedSettingsFragment?)
|
||||
@@ -136,7 +136,7 @@ open class SettingsActivity
|
||||
database.fileUri?.let { databaseUri ->
|
||||
// Show the progress dialog now or after dialog confirmation
|
||||
if (database.validatePasswordEncoding(masterPassword, keyFileChecked)) {
|
||||
mProgressDialogThread?.startDatabaseAssignPassword(
|
||||
mProgressDatabaseTaskProvider?.startDatabaseAssignPassword(
|
||||
databaseUri,
|
||||
masterPasswordChecked,
|
||||
masterPassword,
|
||||
@@ -146,7 +146,7 @@ open class SettingsActivity
|
||||
} else {
|
||||
PasswordEncodingDialogFragment().apply {
|
||||
positiveButtonClickListener = DialogInterface.OnClickListener { _, _ ->
|
||||
mProgressDialogThread?.startDatabaseAssignPassword(
|
||||
mProgressDatabaseTaskProvider?.startDatabaseAssignPassword(
|
||||
databaseUri,
|
||||
masterPasswordChecked,
|
||||
masterPassword,
|
||||
|
||||
@@ -86,7 +86,7 @@ class DatabaseColorPreferenceDialogFragmentCompat : DatabaseSavePreferenceDialog
|
||||
}
|
||||
val oldColor = database.customColor
|
||||
database.customColor = newColor
|
||||
mProgressDialogThread?.startDatabaseSaveColor(oldColor, newColor, mDatabaseAutoSaveEnable)
|
||||
mProgressDatabaseTaskProvider?.startDatabaseSaveColor(oldColor, newColor, mDatabaseAutoSaveEnable)
|
||||
}
|
||||
|
||||
onDialogClosed(true)
|
||||
|
||||
@@ -64,7 +64,7 @@ class DatabaseDataCompressionPreferenceDialogFragmentCompat
|
||||
database.compressionAlgorithm = newCompression
|
||||
|
||||
if (oldCompression != null && newCompression != null)
|
||||
mProgressDialogThread?.startDatabaseSaveCompression(oldCompression, newCompression, mDatabaseAutoSaveEnable)
|
||||
mProgressDatabaseTaskProvider?.startDatabaseSaveCompression(oldCompression, newCompression, mDatabaseAutoSaveEnable)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ class DatabaseDefaultUsernamePreferenceDialogFragmentCompat : DatabaseSavePrefer
|
||||
val newDefaultUsername = inputText
|
||||
val oldDefaultUsername = database.defaultUsername
|
||||
database.defaultUsername = newDefaultUsername
|
||||
mProgressDialogThread?.startDatabaseSaveDefaultUsername(oldDefaultUsername, newDefaultUsername, mDatabaseAutoSaveEnable)
|
||||
mProgressDatabaseTaskProvider?.startDatabaseSaveDefaultUsername(oldDefaultUsername, newDefaultUsername, mDatabaseAutoSaveEnable)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ class DatabaseDescriptionPreferenceDialogFragmentCompat : DatabaseSavePreference
|
||||
val newDescription = inputText
|
||||
val oldDescription = database.description
|
||||
database.description = newDescription
|
||||
mProgressDialogThread?.startDatabaseSaveDescription(oldDescription, newDescription, mDatabaseAutoSaveEnable)
|
||||
mProgressDatabaseTaskProvider?.startDatabaseSaveDescription(oldDescription, newDescription, mDatabaseAutoSaveEnable)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,7 +65,7 @@ class DatabaseEncryptionAlgorithmPreferenceDialogFragmentCompat
|
||||
database.encryptionAlgorithm = newAlgorithm
|
||||
|
||||
if (oldAlgorithm != null && newAlgorithm != null)
|
||||
mProgressDialogThread?.startDatabaseSaveEncryption(oldAlgorithm, newAlgorithm, mDatabaseAutoSaveEnable)
|
||||
mProgressDatabaseTaskProvider?.startDatabaseSaveEncryption(oldAlgorithm, newAlgorithm, mDatabaseAutoSaveEnable)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,7 +66,7 @@ class DatabaseKeyDerivationPreferenceDialogFragmentCompat
|
||||
val oldKdfEngine = database.kdfEngine
|
||||
if (newKdfEngine != null && oldKdfEngine != null) {
|
||||
database.kdfEngine = newKdfEngine
|
||||
mProgressDialogThread?.startDatabaseSaveKeyDerivation(oldKdfEngine, newKdfEngine, mDatabaseAutoSaveEnable)
|
||||
mProgressDatabaseTaskProvider?.startDatabaseSaveKeyDerivation(oldKdfEngine, newKdfEngine, mDatabaseAutoSaveEnable)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ class DatabaseNamePreferenceDialogFragmentCompat : DatabaseSavePreferenceDialogF
|
||||
val newName = inputText
|
||||
val oldName = database.name
|
||||
database.name = newName
|
||||
mProgressDialogThread?.startDatabaseSaveName(oldName, newName, mDatabaseAutoSaveEnable)
|
||||
mProgressDatabaseTaskProvider?.startDatabaseSaveName(oldName, newName, mDatabaseAutoSaveEnable)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ package com.kunzisoft.keepass.settings.preferencedialogfragment
|
||||
|
||||
import android.content.Context
|
||||
import android.os.Bundle
|
||||
import com.kunzisoft.keepass.database.action.ProgressDialogThread
|
||||
import com.kunzisoft.keepass.database.action.ProgressDatabaseTaskProvider
|
||||
import com.kunzisoft.keepass.database.element.Database
|
||||
import com.kunzisoft.keepass.settings.PreferencesUtil
|
||||
import com.kunzisoft.keepass.settings.SettingsActivity
|
||||
@@ -30,7 +30,7 @@ abstract class DatabaseSavePreferenceDialogFragmentCompat : InputPreferenceDialo
|
||||
|
||||
protected var database: Database? = null
|
||||
protected var mDatabaseAutoSaveEnable = true
|
||||
protected var mProgressDialogThread: ProgressDialogThread? = null
|
||||
protected var mProgressDatabaseTaskProvider: ProgressDatabaseTaskProvider? = null
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
@@ -42,7 +42,7 @@ abstract class DatabaseSavePreferenceDialogFragmentCompat : InputPreferenceDialo
|
||||
super.onAttach(context)
|
||||
// Attach dialog thread to start action
|
||||
if (context is SettingsActivity) {
|
||||
mProgressDialogThread = context.mProgressDialogThread
|
||||
mProgressDatabaseTaskProvider = context.mProgressDatabaseTaskProvider
|
||||
}
|
||||
|
||||
this.mDatabaseAutoSaveEnable = PreferencesUtil.isAutoSaveDatabaseEnabled(context)
|
||||
|
||||
@@ -60,7 +60,7 @@ class MaxHistoryItemsPreferenceDialogFragmentCompat : DatabaseSavePreferenceDial
|
||||
// Remove all history items
|
||||
database.removeOldestHistoryForEachEntry()
|
||||
|
||||
mProgressDialogThread?.startDatabaseSaveMaxHistoryItems(oldMaxHistoryItems, maxHistoryItems, mDatabaseAutoSaveEnable)
|
||||
mProgressDatabaseTaskProvider?.startDatabaseSaveMaxHistoryItems(oldMaxHistoryItems, maxHistoryItems, mDatabaseAutoSaveEnable)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ class MaxHistorySizePreferenceDialogFragmentCompat : DatabaseSavePreferenceDialo
|
||||
val oldMaxHistorySize = database.historyMaxSize
|
||||
database.historyMaxSize = maxHistorySize
|
||||
|
||||
mProgressDialogThread?.startDatabaseSaveMaxHistorySize(oldMaxHistorySize, maxHistorySize, mDatabaseAutoSaveEnable)
|
||||
mProgressDatabaseTaskProvider?.startDatabaseSaveMaxHistorySize(oldMaxHistorySize, maxHistorySize, mDatabaseAutoSaveEnable)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ class MemoryUsagePreferenceDialogFragmentCompat : DatabaseSavePreferenceDialogFr
|
||||
val oldMemoryUsage = database.memoryUsage
|
||||
database.memoryUsage = memoryUsage
|
||||
|
||||
mProgressDialogThread?.startDatabaseSaveMemoryUsage(oldMemoryUsage, memoryUsage, mDatabaseAutoSaveEnable)
|
||||
mProgressDatabaseTaskProvider?.startDatabaseSaveMemoryUsage(oldMemoryUsage, memoryUsage, mDatabaseAutoSaveEnable)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ class ParallelismPreferenceDialogFragmentCompat : DatabaseSavePreferenceDialogFr
|
||||
val oldParallelism = database.parallelism
|
||||
database.parallelism = parallelism
|
||||
|
||||
mProgressDialogThread?.startDatabaseSaveParallelism(
|
||||
mProgressDatabaseTaskProvider?.startDatabaseSaveParallelism(
|
||||
oldParallelism,
|
||||
parallelism,
|
||||
mDatabaseAutoSaveEnable)
|
||||
|
||||
@@ -54,7 +54,7 @@ class RoundsPreferenceDialogFragmentCompat : DatabaseSavePreferenceDialogFragmen
|
||||
database.numberKeyEncryptionRounds = Long.MAX_VALUE
|
||||
}
|
||||
|
||||
mProgressDialogThread?.startDatabaseSaveIterations(oldRounds, rounds, mDatabaseAutoSaveEnable)
|
||||
mProgressDatabaseTaskProvider?.startDatabaseSaveIterations(oldRounds, rounds, mDatabaseAutoSaveEnable)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.kunzisoft.keepass.viewmodels
|
||||
|
||||
import android.app.Application
|
||||
import android.net.Uri
|
||||
import androidx.lifecycle.AndroidViewModel
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import com.kunzisoft.keepass.app.database.FileDatabaseHistoryAction
|
||||
import com.kunzisoft.keepass.model.DatabaseFile
|
||||
|
||||
class DatabaseFileViewModel(application: Application) : AndroidViewModel(application) {
|
||||
|
||||
private var mFileDatabaseHistoryAction: FileDatabaseHistoryAction? = null
|
||||
|
||||
init {
|
||||
mFileDatabaseHistoryAction = FileDatabaseHistoryAction.getInstance(application.applicationContext)
|
||||
}
|
||||
|
||||
val databaseFileLoaded: MutableLiveData<DatabaseFile> by lazy {
|
||||
MutableLiveData<DatabaseFile>()
|
||||
}
|
||||
|
||||
fun loadDatabaseFile(databaseUri: Uri) {
|
||||
mFileDatabaseHistoryAction?.getDatabaseFile(databaseUri) { databaseFileRetrieved ->
|
||||
databaseFileLoaded.value = databaseFileRetrieved
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
package com.kunzisoft.keepass.viewmodels
|
||||
|
||||
import android.app.Application
|
||||
import android.net.Uri
|
||||
import androidx.lifecycle.AndroidViewModel
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import com.kunzisoft.keepass.app.database.FileDatabaseHistoryAction
|
||||
import com.kunzisoft.keepass.model.DatabaseFile
|
||||
|
||||
class DatabaseFilesViewModel(application: Application) : AndroidViewModel(application) {
|
||||
|
||||
private var mFileDatabaseHistoryAction: FileDatabaseHistoryAction? = null
|
||||
|
||||
init {
|
||||
mFileDatabaseHistoryAction = FileDatabaseHistoryAction.getInstance(application.applicationContext)
|
||||
}
|
||||
|
||||
val databaseFilesLoaded: MutableLiveData<DatabaseFileData> by lazy {
|
||||
MutableLiveData<DatabaseFileData>()
|
||||
}
|
||||
|
||||
fun loadListOfDatabases() {
|
||||
mFileDatabaseHistoryAction?.getDatabaseFileList { databaseFileListRetrieved ->
|
||||
var newValue = databaseFilesLoaded.value
|
||||
if (newValue == null) {
|
||||
newValue = DatabaseFileData()
|
||||
}
|
||||
newValue.apply {
|
||||
databaseFileAction = DatabaseFileAction.NONE
|
||||
databaseFileToActivate = null
|
||||
databaseFileList.apply {
|
||||
clear()
|
||||
addAll(databaseFileListRetrieved)
|
||||
}
|
||||
}
|
||||
databaseFilesLoaded.value = newValue
|
||||
}
|
||||
}
|
||||
|
||||
fun addDatabaseFile(databaseUri: Uri, keyFileUri: Uri?) {
|
||||
mFileDatabaseHistoryAction?.addOrUpdateDatabaseUri(databaseUri, keyFileUri) { databaseFileAdded ->
|
||||
databaseFileAdded?.let { _ ->
|
||||
databaseFilesLoaded.value = databaseFilesLoaded.value?.apply {
|
||||
this.databaseFileAction = DatabaseFileAction.ADD
|
||||
this.databaseFileList.add(databaseFileAdded)
|
||||
this.databaseFileToActivate = databaseFileAdded
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun updateDatabaseFile(databaseFileToUpdate: DatabaseFile) {
|
||||
mFileDatabaseHistoryAction?.addOrUpdateDatabaseFile(databaseFileToUpdate) { databaseFileUpdated ->
|
||||
databaseFileUpdated?.let { _ ->
|
||||
databaseFilesLoaded.value = databaseFilesLoaded.value?.apply {
|
||||
this.databaseFileAction = DatabaseFileAction.UPDATE
|
||||
this.databaseFileList
|
||||
.find { it.databaseUri == databaseFileUpdated.databaseUri }
|
||||
?.apply {
|
||||
keyFileUri = databaseFileUpdated.keyFileUri
|
||||
databaseAlias = databaseFileUpdated.databaseAlias
|
||||
databaseFileExists = databaseFileUpdated.databaseFileExists
|
||||
databaseLastModified = databaseFileUpdated.databaseLastModified
|
||||
databaseSize = databaseFileUpdated.databaseSize
|
||||
}
|
||||
this.databaseFileToActivate = databaseFileUpdated
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun deleteDatabaseFile(databaseFileToDelete: DatabaseFile) {
|
||||
mFileDatabaseHistoryAction?.deleteDatabaseFile(databaseFileToDelete) { databaseFileDeleted ->
|
||||
databaseFileDeleted?.let { _ ->
|
||||
databaseFilesLoaded.value = databaseFilesLoaded.value?.apply {
|
||||
databaseFileAction = DatabaseFileAction.DELETE
|
||||
databaseFileToActivate = databaseFileDeleted
|
||||
databaseFileList.remove(databaseFileDeleted)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun consumeAction() {
|
||||
databaseFilesLoaded.value?.apply {
|
||||
databaseFileAction = DatabaseFileAction.NONE
|
||||
databaseFileToActivate = null
|
||||
}
|
||||
}
|
||||
|
||||
class DatabaseFileData {
|
||||
val databaseFileList = ArrayList<DatabaseFile>()
|
||||
|
||||
var databaseFileToActivate: DatabaseFile? = null
|
||||
var databaseFileAction: DatabaseFileAction = DatabaseFileAction.NONE
|
||||
}
|
||||
|
||||
enum class DatabaseFileAction {
|
||||
NONE, ADD, UPDATE, DELETE
|
||||
}
|
||||
}
|
||||
@@ -17,14 +17,14 @@
|
||||
* along with KeePassDX. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
package com.kunzisoft.keepass.utils
|
||||
package com.kunzisoft.keepass.viewmodels
|
||||
|
||||
import android.content.Context
|
||||
import android.net.Uri
|
||||
import android.text.format.Formatter
|
||||
import androidx.documentfile.provider.DocumentFile
|
||||
import com.kunzisoft.keepass.app.database.FileDatabaseHistoryAction
|
||||
import com.kunzisoft.keepass.settings.PreferencesUtil
|
||||
import com.kunzisoft.keepass.utils.UriUtil
|
||||
import java.io.Serializable
|
||||
import java.text.DateFormat
|
||||
import java.util.*
|
||||
@@ -58,18 +58,6 @@ class FileDatabaseInfo : Serializable {
|
||||
}
|
||||
private set
|
||||
|
||||
var canRead: Boolean = false
|
||||
get() {
|
||||
return documentFile?.canRead() ?: field
|
||||
}
|
||||
private set
|
||||
|
||||
var canWrite: Boolean = false
|
||||
get() {
|
||||
return documentFile?.canWrite() ?: field
|
||||
}
|
||||
private set
|
||||
|
||||
fun getModificationString(): String? {
|
||||
return documentFile?.lastModified()?.let {
|
||||
DateFormat.getDateTimeInstance()
|
||||
@@ -83,21 +71,11 @@ class FileDatabaseInfo : Serializable {
|
||||
}
|
||||
}
|
||||
|
||||
fun retrieveDatabaseAlias(alias: String): String {
|
||||
fun retrieveDatabaseAlias(alias: String): String? {
|
||||
return when {
|
||||
alias.isNotEmpty() -> alias
|
||||
PreferencesUtil.isFullFilePathEnable(context) -> fileUri?.path ?: ""
|
||||
else -> if (exists) documentFile?.name ?: "" else fileUri?.path ?: ""
|
||||
}
|
||||
}
|
||||
|
||||
fun retrieveDatabaseTitle(titleCallback: (String)->Unit) {
|
||||
fileUri?.let { fileUri ->
|
||||
FileDatabaseHistoryAction.getInstance(context.applicationContext)
|
||||
.getFileDatabaseHistory(fileUri) { fileDatabaseHistoryEntity ->
|
||||
titleCallback.invoke(retrieveDatabaseAlias(fileDatabaseHistoryEntity?.databaseAlias
|
||||
?: ""))
|
||||
}
|
||||
PreferencesUtil.isFullFilePathEnable(context) -> fileUri?.path
|
||||
else -> if (exists) documentFile?.name else fileUri?.path
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user