mirror of
https://github.com/Kunzisoft/KeePassDX.git
synced 2025-12-04 15:49:33 +01:00
Merge branch 'feature/Manually_Save_Satabase' into develop
This commit is contained in:
@@ -329,9 +329,9 @@ class EntryActivity : LockingHideActivity() {
|
|||||||
val inflater = menuInflater
|
val inflater = menuInflater
|
||||||
MenuUtil.contributionMenuInflater(inflater, menu)
|
MenuUtil.contributionMenuInflater(inflater, menu)
|
||||||
inflater.inflate(R.menu.entry, menu)
|
inflater.inflate(R.menu.entry, menu)
|
||||||
inflater.inflate(R.menu.database_lock, menu)
|
inflater.inflate(R.menu.database, menu)
|
||||||
|
|
||||||
if (mReadOnly) {
|
if (mReadOnly) {
|
||||||
|
menu.findItem(R.id.menu_save_database)?.isVisible = false
|
||||||
menu.findItem(R.id.menu_edit)?.isVisible = false
|
menu.findItem(R.id.menu_edit)?.isVisible = false
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -400,21 +400,18 @@ class EntryActivity : LockingHideActivity() {
|
|||||||
MenuUtil.onContributionItemSelected(this)
|
MenuUtil.onContributionItemSelected(this)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
R.id.menu_toggle_pass -> {
|
R.id.menu_toggle_pass -> {
|
||||||
mShowPassword = !mShowPassword
|
mShowPassword = !mShowPassword
|
||||||
changeShowPasswordIcon(item)
|
changeShowPasswordIcon(item)
|
||||||
entryContentsView?.setHiddenPasswordStyle(!mShowPassword)
|
entryContentsView?.setHiddenPasswordStyle(!mShowPassword)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
R.id.menu_edit -> {
|
R.id.menu_edit -> {
|
||||||
mEntry?.let {
|
mEntry?.let {
|
||||||
EntryEditActivity.launch(this@EntryActivity, it)
|
EntryEditActivity.launch(this@EntryActivity, it)
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
R.id.menu_goto_url -> {
|
R.id.menu_goto_url -> {
|
||||||
var url: String = mEntry?.url ?: ""
|
var url: String = mEntry?.url ?: ""
|
||||||
|
|
||||||
@@ -424,18 +421,17 @@ class EntryActivity : LockingHideActivity() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
UriUtil.gotoUrl(this, url)
|
UriUtil.gotoUrl(this, url)
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
R.id.menu_lock -> {
|
R.id.menu_lock -> {
|
||||||
lockAndExit()
|
lockAndExit()
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
R.id.menu_save_database -> {
|
||||||
|
mProgressDialogThread?.startDatabaseSave(!mReadOnly)
|
||||||
|
}
|
||||||
android.R.id.home -> finish() // close this activity and return to preview activity (if there is any)
|
android.R.id.home -> finish() // close this activity and return to preview activity (if there is any)
|
||||||
}
|
}
|
||||||
|
|
||||||
return super.onOptionsItemSelected(item)
|
return super.onOptionsItemSelected(item)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -33,7 +33,6 @@ import com.kunzisoft.keepass.activities.dialogs.SetOTPDialogFragment
|
|||||||
import com.kunzisoft.keepass.activities.dialogs.GeneratePasswordDialogFragment
|
import com.kunzisoft.keepass.activities.dialogs.GeneratePasswordDialogFragment
|
||||||
import com.kunzisoft.keepass.activities.dialogs.IconPickerDialogFragment
|
import com.kunzisoft.keepass.activities.dialogs.IconPickerDialogFragment
|
||||||
import com.kunzisoft.keepass.activities.lock.LockingHideActivity
|
import com.kunzisoft.keepass.activities.lock.LockingHideActivity
|
||||||
import com.kunzisoft.keepass.database.action.ProgressDialogThread
|
|
||||||
import com.kunzisoft.keepass.database.element.*
|
import com.kunzisoft.keepass.database.element.*
|
||||||
import com.kunzisoft.keepass.education.EntryEditActivityEducation
|
import com.kunzisoft.keepass.education.EntryEditActivityEducation
|
||||||
import com.kunzisoft.keepass.notifications.ClipboardEntryNotificationService
|
import com.kunzisoft.keepass.notifications.ClipboardEntryNotificationService
|
||||||
@@ -67,9 +66,6 @@ class EntryEditActivity : LockingHideActivity(),
|
|||||||
private var entryEditContentsView: EntryEditContentsView? = null
|
private var entryEditContentsView: EntryEditContentsView? = null
|
||||||
private var saveView: View? = null
|
private var saveView: View? = null
|
||||||
|
|
||||||
// Dialog thread
|
|
||||||
private var progressDialogThread: ProgressDialogThread? = null
|
|
||||||
|
|
||||||
// Education
|
// Education
|
||||||
private var entryEditActivityEducation: EntryEditActivityEducation? = null
|
private var entryEditActivityEducation: EntryEditActivityEducation? = null
|
||||||
|
|
||||||
@@ -176,7 +172,7 @@ class EntryEditActivity : LockingHideActivity(),
|
|||||||
entryEditActivityEducation = EntryEditActivityEducation(this)
|
entryEditActivityEducation = EntryEditActivityEducation(this)
|
||||||
|
|
||||||
// Create progress dialog
|
// Create progress dialog
|
||||||
progressDialogThread = ProgressDialogThread(this) { actionTask, result ->
|
mProgressDialogThread?.onActionFinish = { actionTask, result ->
|
||||||
when (actionTask) {
|
when (actionTask) {
|
||||||
ACTION_DATABASE_CREATE_ENTRY_TASK,
|
ACTION_DATABASE_CREATE_ENTRY_TASK,
|
||||||
ACTION_DATABASE_UPDATE_ENTRY_TASK -> {
|
ACTION_DATABASE_UPDATE_ENTRY_TASK -> {
|
||||||
@@ -273,18 +269,18 @@ class EntryEditActivity : LockingHideActivity(),
|
|||||||
// Open a progress dialog and save entry
|
// Open a progress dialog and save entry
|
||||||
if (mIsNew) {
|
if (mIsNew) {
|
||||||
mParent?.let { parent ->
|
mParent?.let { parent ->
|
||||||
progressDialogThread?.startDatabaseCreateEntry(
|
mProgressDialogThread?.startDatabaseCreateEntry(
|
||||||
newEntry,
|
newEntry,
|
||||||
parent,
|
parent,
|
||||||
!mReadOnly
|
!mReadOnly && mAutoSaveEnable
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
mEntry?.let { oldEntry ->
|
mEntry?.let { oldEntry ->
|
||||||
progressDialogThread?.startDatabaseUpdateEntry(
|
mProgressDialogThread?.startDatabaseUpdateEntry(
|
||||||
oldEntry,
|
oldEntry,
|
||||||
newEntry,
|
newEntry,
|
||||||
!mReadOnly
|
!mReadOnly && mAutoSaveEnable
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -292,23 +288,13 @@ class EntryEditActivity : LockingHideActivity(),
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onResume() {
|
|
||||||
super.onResume()
|
|
||||||
|
|
||||||
progressDialogThread?.registerProgressTask()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onPause() {
|
|
||||||
progressDialogThread?.unregisterProgressTask()
|
|
||||||
|
|
||||||
super.onPause()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
||||||
super.onCreateOptionsMenu(menu)
|
super.onCreateOptionsMenu(menu)
|
||||||
|
|
||||||
val inflater = menuInflater
|
val inflater = menuInflater
|
||||||
inflater.inflate(R.menu.database_lock, menu)
|
inflater.inflate(R.menu.database, menu)
|
||||||
|
// Save database not needed here
|
||||||
|
menu.findItem(R.id.menu_save_database)?.isVisible = false
|
||||||
MenuUtil.contributionMenuInflater(inflater, menu)
|
MenuUtil.contributionMenuInflater(inflater, menu)
|
||||||
if (mDatabase?.allowOTP == true)
|
if (mDatabase?.allowOTP == true)
|
||||||
inflater.inflate(R.menu.entry_otp, menu)
|
inflater.inflate(R.menu.entry_otp, menu)
|
||||||
@@ -352,12 +338,13 @@ class EntryEditActivity : LockingHideActivity(),
|
|||||||
lockAndExit()
|
lockAndExit()
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
R.id.menu_save_database -> {
|
||||||
|
mProgressDialogThread?.startDatabaseSave(!mReadOnly)
|
||||||
|
}
|
||||||
R.id.menu_contribute -> {
|
R.id.menu_contribute -> {
|
||||||
MenuUtil.onContributionItemSelected(this)
|
MenuUtil.onContributionItemSelected(this)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
R.id.menu_add_otp -> {
|
R.id.menu_add_otp -> {
|
||||||
// Retrieve the current otpElement if exists
|
// Retrieve the current otpElement if exists
|
||||||
// and open the dialog to set up the OTP
|
// and open the dialog to set up the OTP
|
||||||
@@ -365,7 +352,6 @@ class EntryEditActivity : LockingHideActivity(),
|
|||||||
.show(supportFragmentManager, "addOTPDialog")
|
.show(supportFragmentManager, "addOTPDialog")
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
android.R.id.home -> finish()
|
android.R.id.home -> finish()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ class FileDatabaseSelectActivity : StylishActivity(),
|
|||||||
|
|
||||||
private var mOpenFileHelper: OpenFileHelper? = null
|
private var mOpenFileHelper: OpenFileHelper? = null
|
||||||
|
|
||||||
private var progressDialogThread: ProgressDialogThread? = null
|
private var mProgressDialogThread: ProgressDialogThread? = null
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
@@ -163,7 +163,7 @@ class FileDatabaseSelectActivity : StylishActivity(),
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Attach the dialog thread to this activity
|
// Attach the dialog thread to this activity
|
||||||
progressDialogThread = ProgressDialogThread(this) { actionTask, _ ->
|
mProgressDialogThread?.onActionFinish = { actionTask, _ ->
|
||||||
when (actionTask) {
|
when (actionTask) {
|
||||||
ACTION_DATABASE_CREATE_TASK -> {
|
ACTION_DATABASE_CREATE_TASK -> {
|
||||||
// TODO Check
|
// TODO Check
|
||||||
@@ -296,12 +296,12 @@ class FileDatabaseSelectActivity : StylishActivity(),
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Register progress task
|
// Register progress task
|
||||||
progressDialogThread?.registerProgressTask()
|
mProgressDialogThread?.registerProgressTask()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onPause() {
|
override fun onPause() {
|
||||||
// Unregister progress task
|
// Unregister progress task
|
||||||
progressDialogThread?.unregisterProgressTask()
|
mProgressDialogThread?.unregisterProgressTask()
|
||||||
|
|
||||||
super.onPause()
|
super.onPause()
|
||||||
}
|
}
|
||||||
@@ -329,7 +329,7 @@ class FileDatabaseSelectActivity : StylishActivity(),
|
|||||||
mDatabaseFileUri?.let { databaseUri ->
|
mDatabaseFileUri?.let { databaseUri ->
|
||||||
|
|
||||||
// Create the new database
|
// Create the new database
|
||||||
progressDialogThread?.startDatabaseCreate(
|
mProgressDialogThread?.startDatabaseCreate(
|
||||||
databaseUri,
|
databaseUri,
|
||||||
masterPasswordChecked,
|
masterPasswordChecked,
|
||||||
masterPassword,
|
masterPassword,
|
||||||
|
|||||||
@@ -49,7 +49,6 @@ import com.kunzisoft.keepass.activities.lock.LockingActivity
|
|||||||
import com.kunzisoft.keepass.adapters.SearchEntryCursorAdapter
|
import com.kunzisoft.keepass.adapters.SearchEntryCursorAdapter
|
||||||
import com.kunzisoft.keepass.autofill.AutofillHelper
|
import com.kunzisoft.keepass.autofill.AutofillHelper
|
||||||
import com.kunzisoft.keepass.database.SortNodeEnum
|
import com.kunzisoft.keepass.database.SortNodeEnum
|
||||||
import com.kunzisoft.keepass.database.action.ProgressDialogThread
|
|
||||||
import com.kunzisoft.keepass.database.element.*
|
import com.kunzisoft.keepass.database.element.*
|
||||||
import com.kunzisoft.keepass.education.GroupActivityEducation
|
import com.kunzisoft.keepass.education.GroupActivityEducation
|
||||||
import com.kunzisoft.keepass.icons.assignDatabaseIcon
|
import com.kunzisoft.keepass.icons.assignDatabaseIcon
|
||||||
@@ -94,8 +93,6 @@ class GroupActivity : LockingActivity(),
|
|||||||
private var mListNodesFragment: ListNodesFragment? = null
|
private var mListNodesFragment: ListNodesFragment? = null
|
||||||
private var mCurrentGroupIsASearch: Boolean = false
|
private var mCurrentGroupIsASearch: Boolean = false
|
||||||
|
|
||||||
private var progressDialogThread: ProgressDialogThread? = null
|
|
||||||
|
|
||||||
// Nodes
|
// Nodes
|
||||||
private var mRootGroup: GroupVersioned? = null
|
private var mRootGroup: GroupVersioned? = null
|
||||||
private var mCurrentGroup: GroupVersioned? = null
|
private var mCurrentGroup: GroupVersioned? = null
|
||||||
@@ -205,7 +202,7 @@ class GroupActivity : LockingActivity(),
|
|||||||
mSearchSuggestionAdapter = SearchEntryCursorAdapter(this, database)
|
mSearchSuggestionAdapter = SearchEntryCursorAdapter(this, database)
|
||||||
|
|
||||||
// Init dialog thread
|
// Init dialog thread
|
||||||
progressDialogThread = ProgressDialogThread(this) { actionTask, result ->
|
mProgressDialogThread?.onActionFinish = { actionTask, result ->
|
||||||
|
|
||||||
var oldNodes: List<NodeVersioned> = ArrayList()
|
var oldNodes: List<NodeVersioned> = ArrayList()
|
||||||
result.data?.getBundle(OLD_NODES_KEY)?.let { oldNodesBundle ->
|
result.data?.getBundle(OLD_NODES_KEY)?.let { oldNodesBundle ->
|
||||||
@@ -569,20 +566,20 @@ class GroupActivity : LockingActivity(),
|
|||||||
ListNodesFragment.PasteMode.PASTE_FROM_COPY -> {
|
ListNodesFragment.PasteMode.PASTE_FROM_COPY -> {
|
||||||
// Copy
|
// Copy
|
||||||
mCurrentGroup?.let { newParent ->
|
mCurrentGroup?.let { newParent ->
|
||||||
progressDialogThread?.startDatabaseCopyNodes(
|
mProgressDialogThread?.startDatabaseCopyNodes(
|
||||||
nodes,
|
nodes,
|
||||||
newParent,
|
newParent,
|
||||||
!mReadOnly
|
!mReadOnly && mAutoSaveEnable
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ListNodesFragment.PasteMode.PASTE_FROM_MOVE -> {
|
ListNodesFragment.PasteMode.PASTE_FROM_MOVE -> {
|
||||||
// Move
|
// Move
|
||||||
mCurrentGroup?.let { newParent ->
|
mCurrentGroup?.let { newParent ->
|
||||||
progressDialogThread?.startDatabaseMoveNodes(
|
mProgressDialogThread?.startDatabaseMoveNodes(
|
||||||
nodes,
|
nodes,
|
||||||
newParent,
|
newParent,
|
||||||
!mReadOnly
|
!mReadOnly && mAutoSaveEnable
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -598,9 +595,9 @@ class GroupActivity : LockingActivity(),
|
|||||||
&& database.isRecycleBinEnabled
|
&& database.isRecycleBinEnabled
|
||||||
&& database.recycleBin != mCurrentGroup) {
|
&& database.recycleBin != mCurrentGroup) {
|
||||||
// If recycle bin enabled and not in recycle bin, move in recycle bin
|
// If recycle bin enabled and not in recycle bin, move in recycle bin
|
||||||
progressDialogThread?.startDatabaseDeleteNodes(
|
mProgressDialogThread?.startDatabaseDeleteNodes(
|
||||||
nodes,
|
nodes,
|
||||||
!mReadOnly
|
!mReadOnly && mAutoSaveEnable
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
// open the dialog to confirm deletion
|
// open the dialog to confirm deletion
|
||||||
@@ -612,9 +609,9 @@ class GroupActivity : LockingActivity(),
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun permanentlyDeleteNodes(nodes: List<NodeVersioned>) {
|
override fun permanentlyDeleteNodes(nodes: List<NodeVersioned>) {
|
||||||
progressDialogThread?.startDatabaseDeleteNodes(
|
mProgressDialogThread?.startDatabaseDeleteNodes(
|
||||||
nodes,
|
nodes,
|
||||||
!mReadOnly
|
!mReadOnly && mAutoSaveEnable
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -624,13 +621,9 @@ class GroupActivity : LockingActivity(),
|
|||||||
assignGroupViewElements()
|
assignGroupViewElements()
|
||||||
// Refresh suggestions to change preferences
|
// Refresh suggestions to change preferences
|
||||||
mSearchSuggestionAdapter?.reInit(this)
|
mSearchSuggestionAdapter?.reInit(this)
|
||||||
|
|
||||||
progressDialogThread?.registerProgressTask()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onPause() {
|
override fun onPause() {
|
||||||
progressDialogThread?.unregisterProgressTask()
|
|
||||||
|
|
||||||
super.onPause()
|
super.onPause()
|
||||||
|
|
||||||
finishNodeAction()
|
finishNodeAction()
|
||||||
@@ -640,7 +633,10 @@ class GroupActivity : LockingActivity(),
|
|||||||
|
|
||||||
val inflater = menuInflater
|
val inflater = menuInflater
|
||||||
inflater.inflate(R.menu.search, menu)
|
inflater.inflate(R.menu.search, menu)
|
||||||
inflater.inflate(R.menu.database_lock, menu)
|
inflater.inflate(R.menu.database, menu)
|
||||||
|
if (mReadOnly) {
|
||||||
|
menu.findItem(R.id.menu_save_database)?.isVisible = false
|
||||||
|
}
|
||||||
if (!mSelectionMode) {
|
if (!mSelectionMode) {
|
||||||
inflater.inflate(R.menu.default_menu, menu)
|
inflater.inflate(R.menu.default_menu, menu)
|
||||||
MenuUtil.contributionMenuInflater(inflater, menu)
|
MenuUtil.contributionMenuInflater(inflater, menu)
|
||||||
@@ -760,6 +756,10 @@ class GroupActivity : LockingActivity(),
|
|||||||
lockAndExit()
|
lockAndExit()
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
R.id.menu_save_database -> {
|
||||||
|
mProgressDialogThread?.startDatabaseSave(!mReadOnly)
|
||||||
|
return true
|
||||||
|
}
|
||||||
R.id.menu_empty_recycle_bin -> {
|
R.id.menu_empty_recycle_bin -> {
|
||||||
mCurrentGroup?.getChildren()?.let { listChildren ->
|
mCurrentGroup?.getChildren()?.let { listChildren ->
|
||||||
// Automatically delete all elements
|
// Automatically delete all elements
|
||||||
@@ -791,8 +791,11 @@ class GroupActivity : LockingActivity(),
|
|||||||
// Not really needed here because added in runnable but safe
|
// Not really needed here because added in runnable but safe
|
||||||
newGroup.parent = currentGroup
|
newGroup.parent = currentGroup
|
||||||
|
|
||||||
progressDialogThread?.startDatabaseCreateGroup(
|
mProgressDialogThread?.startDatabaseCreateGroup(
|
||||||
newGroup, currentGroup, !mReadOnly)
|
newGroup,
|
||||||
|
currentGroup,
|
||||||
|
!mReadOnly && mAutoSaveEnable
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -810,8 +813,11 @@ class GroupActivity : LockingActivity(),
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// If group updated save it in the database
|
// If group updated save it in the database
|
||||||
progressDialogThread?.startDatabaseUpdateGroup(
|
mProgressDialogThread?.startDatabaseUpdateGroup(
|
||||||
oldGroupToUpdate, updateGroup, !mReadOnly)
|
oldGroupToUpdate,
|
||||||
|
updateGroup,
|
||||||
|
!mReadOnly && mAutoSaveEnable
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else -> {}
|
else -> {}
|
||||||
|
|||||||
@@ -163,7 +163,8 @@ class PasswordActivity : StylishActivity() {
|
|||||||
enableOrNotTheConfirmationButton()
|
enableOrNotTheConfirmationButton()
|
||||||
}
|
}
|
||||||
|
|
||||||
progressDialogThread = ProgressDialogThread(this) { actionTask, result ->
|
progressDialogThread = ProgressDialogThread(this).apply {
|
||||||
|
onActionFinish = { actionTask, result ->
|
||||||
when (actionTask) {
|
when (actionTask) {
|
||||||
ACTION_DATABASE_LOAD_TASK -> {
|
ACTION_DATABASE_LOAD_TASK -> {
|
||||||
// Recheck biometric if error
|
// Recheck biometric if error
|
||||||
@@ -231,6 +232,7 @@ class PasswordActivity : StylishActivity() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun launchGroupActivity() {
|
private fun launchGroupActivity() {
|
||||||
EntrySelectionHelper.doEntrySelectionAction(intent,
|
EntrySelectionHelper.doEntrySelectionAction(intent,
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ import android.view.ViewGroup
|
|||||||
import com.kunzisoft.keepass.activities.helpers.EntrySelectionHelper
|
import com.kunzisoft.keepass.activities.helpers.EntrySelectionHelper
|
||||||
import com.kunzisoft.keepass.activities.helpers.ReadOnlyHelper
|
import com.kunzisoft.keepass.activities.helpers.ReadOnlyHelper
|
||||||
import com.kunzisoft.keepass.activities.stylish.StylishActivity
|
import com.kunzisoft.keepass.activities.stylish.StylishActivity
|
||||||
|
import com.kunzisoft.keepass.database.action.ProgressDialogThread
|
||||||
import com.kunzisoft.keepass.database.element.Database
|
import com.kunzisoft.keepass.database.element.Database
|
||||||
import com.kunzisoft.keepass.notifications.KeyboardEntryNotificationService
|
import com.kunzisoft.keepass.notifications.KeyboardEntryNotificationService
|
||||||
import com.kunzisoft.keepass.magikeyboard.MagikIME
|
import com.kunzisoft.keepass.magikeyboard.MagikIME
|
||||||
@@ -63,6 +64,10 @@ abstract class LockingActivity : StylishActivity() {
|
|||||||
return field || mSelectionMode
|
return field || mSelectionMode
|
||||||
}
|
}
|
||||||
protected var mSelectionMode: Boolean = false
|
protected var mSelectionMode: Boolean = false
|
||||||
|
protected var mAutoSaveEnable: Boolean = true
|
||||||
|
|
||||||
|
var mProgressDialogThread: ProgressDialogThread? = null
|
||||||
|
private set
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
@@ -86,6 +91,8 @@ abstract class LockingActivity : StylishActivity() {
|
|||||||
|
|
||||||
mExitLock = false
|
mExitLock = false
|
||||||
mReadOnly = ReadOnlyHelper.retrieveReadOnlyFromInstanceStateOrIntent(savedInstanceState, intent)
|
mReadOnly = ReadOnlyHelper.retrieveReadOnlyFromInstanceStateOrIntent(savedInstanceState, intent)
|
||||||
|
|
||||||
|
mProgressDialogThread = ProgressDialogThread(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||||
@@ -101,8 +108,13 @@ abstract class LockingActivity : StylishActivity() {
|
|||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
super.onResume()
|
super.onResume()
|
||||||
|
|
||||||
|
mProgressDialogThread?.registerProgressTask()
|
||||||
|
|
||||||
// To refresh when back to normal workflow from selection workflow
|
// To refresh when back to normal workflow from selection workflow
|
||||||
mSelectionMode = EntrySelectionHelper.retrieveEntrySelectionModeFromIntent(intent)
|
mSelectionMode = EntrySelectionHelper.retrieveEntrySelectionModeFromIntent(intent)
|
||||||
|
mAutoSaveEnable = PreferencesUtil.isAutoSaveDatabaseEnabled(this)
|
||||||
|
|
||||||
|
invalidateOptionsMenu()
|
||||||
|
|
||||||
if (mTimeoutEnable) {
|
if (mTimeoutEnable) {
|
||||||
// End activity if database not loaded
|
// End activity if database not loaded
|
||||||
@@ -119,8 +131,6 @@ abstract class LockingActivity : StylishActivity() {
|
|||||||
if (!mExitLock)
|
if (!mExitLock)
|
||||||
TimeoutHelper.recordTime(this)
|
TimeoutHelper.recordTime(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
invalidateOptionsMenu()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onSaveInstanceState(outState: Bundle) {
|
override fun onSaveInstanceState(outState: Bundle) {
|
||||||
@@ -130,6 +140,8 @@ abstract class LockingActivity : StylishActivity() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onPause() {
|
override fun onPause() {
|
||||||
|
mProgressDialogThread?.unregisterProgressTask()
|
||||||
|
|
||||||
super.onPause()
|
super.onPause()
|
||||||
|
|
||||||
if (mTimeoutEnable) {
|
if (mTimeoutEnable) {
|
||||||
|
|||||||
@@ -21,18 +21,18 @@ import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Compa
|
|||||||
import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_LOAD_TASK
|
import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_LOAD_TASK
|
||||||
import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_MOVE_NODES_TASK
|
import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_MOVE_NODES_TASK
|
||||||
import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_SAVE
|
import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_SAVE
|
||||||
import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_SAVE_COLOR_TASK
|
import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_UPDATE_COLOR_TASK
|
||||||
import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_SAVE_COMPRESSION_TASK
|
import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_UPDATE_COMPRESSION_TASK
|
||||||
import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_SAVE_DEFAULT_USERNAME_TASK
|
import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_UPDATE_DEFAULT_USERNAME_TASK
|
||||||
import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_SAVE_DESCRIPTION_TASK
|
import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_UPDATE_DESCRIPTION_TASK
|
||||||
import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_SAVE_ENCRYPTION_TASK
|
import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_UPDATE_ENCRYPTION_TASK
|
||||||
import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_SAVE_ITERATIONS_TASK
|
import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_UPDATE_ITERATIONS_TASK
|
||||||
import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_SAVE_KEY_DERIVATION_TASK
|
import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_UPDATE_KEY_DERIVATION_TASK
|
||||||
import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_SAVE_MAX_HISTORY_ITEMS_TASK
|
import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_UPDATE_MAX_HISTORY_ITEMS_TASK
|
||||||
import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_SAVE_MAX_HISTORY_SIZE_TASK
|
import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_UPDATE_MAX_HISTORY_SIZE_TASK
|
||||||
import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_SAVE_MEMORY_USAGE_TASK
|
import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_UPDATE_MEMORY_USAGE_TASK
|
||||||
import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_SAVE_NAME_TASK
|
import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_UPDATE_NAME_TASK
|
||||||
import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_SAVE_PARALLELISM_TASK
|
import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_UPDATE_PARALLELISM_TASK
|
||||||
import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_UPDATE_ENTRY_TASK
|
import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_UPDATE_ENTRY_TASK
|
||||||
import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_UPDATE_GROUP_TASK
|
import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_UPDATE_GROUP_TASK
|
||||||
import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.getBundleFromListNodes
|
import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.getBundleFromListNodes
|
||||||
@@ -45,10 +45,10 @@ import com.kunzisoft.keepass.utils.DATABASE_STOP_TASK_ACTION
|
|||||||
import java.util.*
|
import java.util.*
|
||||||
import kotlin.collections.ArrayList
|
import kotlin.collections.ArrayList
|
||||||
|
|
||||||
|
class ProgressDialogThread(private val activity: FragmentActivity) {
|
||||||
|
|
||||||
class ProgressDialogThread(private val activity: FragmentActivity,
|
var onActionFinish: ((actionTask: String,
|
||||||
var onActionFinish: (actionTask: String,
|
result: ActionRunnable.Result) -> Unit)? = null
|
||||||
result: ActionRunnable.Result) -> Unit) {
|
|
||||||
|
|
||||||
private var intentDatabaseTask = Intent(activity, DatabaseTaskNotificationService::class.java)
|
private var intentDatabaseTask = Intent(activity, DatabaseTaskNotificationService::class.java)
|
||||||
|
|
||||||
@@ -69,7 +69,7 @@ class ProgressDialogThread(private val activity: FragmentActivity,
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onStopAction(actionTask: String, result: ActionRunnable.Result) {
|
override fun onStopAction(actionTask: String, result: ActionRunnable.Result) {
|
||||||
onActionFinish.invoke(actionTask, result)
|
onActionFinish?.invoke(actionTask, result)
|
||||||
// Remove the progress task
|
// Remove the progress task
|
||||||
ProgressTaskDialogFragment.stop(activity)
|
ProgressTaskDialogFragment.stop(activity)
|
||||||
TimeoutHelper.releaseTemporarilyDisableTimeoutAndLockIfTimeout(activity)
|
TimeoutHelper.releaseTemporarilyDisableTimeoutAndLockIfTimeout(activity)
|
||||||
@@ -357,7 +357,7 @@ class ProgressDialogThread(private val activity: FragmentActivity,
|
|||||||
putString(DatabaseTaskNotificationService.NEW_ELEMENT_KEY, newName)
|
putString(DatabaseTaskNotificationService.NEW_ELEMENT_KEY, newName)
|
||||||
putBoolean(DatabaseTaskNotificationService.SAVE_DATABASE_KEY, save)
|
putBoolean(DatabaseTaskNotificationService.SAVE_DATABASE_KEY, save)
|
||||||
}
|
}
|
||||||
, ACTION_DATABASE_SAVE_NAME_TASK)
|
, ACTION_DATABASE_UPDATE_NAME_TASK)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun startDatabaseSaveDescription(oldDescription: String,
|
fun startDatabaseSaveDescription(oldDescription: String,
|
||||||
@@ -368,7 +368,7 @@ class ProgressDialogThread(private val activity: FragmentActivity,
|
|||||||
putString(DatabaseTaskNotificationService.NEW_ELEMENT_KEY, newDescription)
|
putString(DatabaseTaskNotificationService.NEW_ELEMENT_KEY, newDescription)
|
||||||
putBoolean(DatabaseTaskNotificationService.SAVE_DATABASE_KEY, save)
|
putBoolean(DatabaseTaskNotificationService.SAVE_DATABASE_KEY, save)
|
||||||
}
|
}
|
||||||
, ACTION_DATABASE_SAVE_DESCRIPTION_TASK)
|
, ACTION_DATABASE_UPDATE_DESCRIPTION_TASK)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun startDatabaseSaveDefaultUsername(oldDefaultUsername: String,
|
fun startDatabaseSaveDefaultUsername(oldDefaultUsername: String,
|
||||||
@@ -379,7 +379,7 @@ class ProgressDialogThread(private val activity: FragmentActivity,
|
|||||||
putString(DatabaseTaskNotificationService.NEW_ELEMENT_KEY, newDefaultUsername)
|
putString(DatabaseTaskNotificationService.NEW_ELEMENT_KEY, newDefaultUsername)
|
||||||
putBoolean(DatabaseTaskNotificationService.SAVE_DATABASE_KEY, save)
|
putBoolean(DatabaseTaskNotificationService.SAVE_DATABASE_KEY, save)
|
||||||
}
|
}
|
||||||
, ACTION_DATABASE_SAVE_DEFAULT_USERNAME_TASK)
|
, ACTION_DATABASE_UPDATE_DEFAULT_USERNAME_TASK)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun startDatabaseSaveColor(oldColor: String,
|
fun startDatabaseSaveColor(oldColor: String,
|
||||||
@@ -390,7 +390,7 @@ class ProgressDialogThread(private val activity: FragmentActivity,
|
|||||||
putString(DatabaseTaskNotificationService.NEW_ELEMENT_KEY, newColor)
|
putString(DatabaseTaskNotificationService.NEW_ELEMENT_KEY, newColor)
|
||||||
putBoolean(DatabaseTaskNotificationService.SAVE_DATABASE_KEY, save)
|
putBoolean(DatabaseTaskNotificationService.SAVE_DATABASE_KEY, save)
|
||||||
}
|
}
|
||||||
, ACTION_DATABASE_SAVE_COLOR_TASK)
|
, ACTION_DATABASE_UPDATE_COLOR_TASK)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun startDatabaseSaveCompression(oldCompression: PwCompressionAlgorithm,
|
fun startDatabaseSaveCompression(oldCompression: PwCompressionAlgorithm,
|
||||||
@@ -401,7 +401,7 @@ class ProgressDialogThread(private val activity: FragmentActivity,
|
|||||||
putSerializable(DatabaseTaskNotificationService.NEW_ELEMENT_KEY, newCompression)
|
putSerializable(DatabaseTaskNotificationService.NEW_ELEMENT_KEY, newCompression)
|
||||||
putBoolean(DatabaseTaskNotificationService.SAVE_DATABASE_KEY, save)
|
putBoolean(DatabaseTaskNotificationService.SAVE_DATABASE_KEY, save)
|
||||||
}
|
}
|
||||||
, ACTION_DATABASE_SAVE_COMPRESSION_TASK)
|
, ACTION_DATABASE_UPDATE_COMPRESSION_TASK)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun startDatabaseSaveMaxHistoryItems(oldMaxHistoryItems: Int,
|
fun startDatabaseSaveMaxHistoryItems(oldMaxHistoryItems: Int,
|
||||||
@@ -412,7 +412,7 @@ class ProgressDialogThread(private val activity: FragmentActivity,
|
|||||||
putInt(DatabaseTaskNotificationService.NEW_ELEMENT_KEY, newMaxHistoryItems)
|
putInt(DatabaseTaskNotificationService.NEW_ELEMENT_KEY, newMaxHistoryItems)
|
||||||
putBoolean(DatabaseTaskNotificationService.SAVE_DATABASE_KEY, save)
|
putBoolean(DatabaseTaskNotificationService.SAVE_DATABASE_KEY, save)
|
||||||
}
|
}
|
||||||
, ACTION_DATABASE_SAVE_MAX_HISTORY_ITEMS_TASK)
|
, ACTION_DATABASE_UPDATE_MAX_HISTORY_ITEMS_TASK)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun startDatabaseSaveMaxHistorySize(oldMaxHistorySize: Long,
|
fun startDatabaseSaveMaxHistorySize(oldMaxHistorySize: Long,
|
||||||
@@ -423,7 +423,7 @@ class ProgressDialogThread(private val activity: FragmentActivity,
|
|||||||
putLong(DatabaseTaskNotificationService.NEW_ELEMENT_KEY, newMaxHistorySize)
|
putLong(DatabaseTaskNotificationService.NEW_ELEMENT_KEY, newMaxHistorySize)
|
||||||
putBoolean(DatabaseTaskNotificationService.SAVE_DATABASE_KEY, save)
|
putBoolean(DatabaseTaskNotificationService.SAVE_DATABASE_KEY, save)
|
||||||
}
|
}
|
||||||
, ACTION_DATABASE_SAVE_MAX_HISTORY_SIZE_TASK)
|
, ACTION_DATABASE_UPDATE_MAX_HISTORY_SIZE_TASK)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -440,7 +440,7 @@ class ProgressDialogThread(private val activity: FragmentActivity,
|
|||||||
putSerializable(DatabaseTaskNotificationService.NEW_ELEMENT_KEY, newEncryption)
|
putSerializable(DatabaseTaskNotificationService.NEW_ELEMENT_KEY, newEncryption)
|
||||||
putBoolean(DatabaseTaskNotificationService.SAVE_DATABASE_KEY, save)
|
putBoolean(DatabaseTaskNotificationService.SAVE_DATABASE_KEY, save)
|
||||||
}
|
}
|
||||||
, ACTION_DATABASE_SAVE_ENCRYPTION_TASK)
|
, ACTION_DATABASE_UPDATE_ENCRYPTION_TASK)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun startDatabaseSaveKeyDerivation(oldKeyDerivation: KdfEngine,
|
fun startDatabaseSaveKeyDerivation(oldKeyDerivation: KdfEngine,
|
||||||
@@ -451,7 +451,7 @@ class ProgressDialogThread(private val activity: FragmentActivity,
|
|||||||
putSerializable(DatabaseTaskNotificationService.NEW_ELEMENT_KEY, newKeyDerivation)
|
putSerializable(DatabaseTaskNotificationService.NEW_ELEMENT_KEY, newKeyDerivation)
|
||||||
putBoolean(DatabaseTaskNotificationService.SAVE_DATABASE_KEY, save)
|
putBoolean(DatabaseTaskNotificationService.SAVE_DATABASE_KEY, save)
|
||||||
}
|
}
|
||||||
, ACTION_DATABASE_SAVE_KEY_DERIVATION_TASK)
|
, ACTION_DATABASE_UPDATE_KEY_DERIVATION_TASK)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun startDatabaseSaveIterations(oldIterations: Long,
|
fun startDatabaseSaveIterations(oldIterations: Long,
|
||||||
@@ -462,7 +462,7 @@ class ProgressDialogThread(private val activity: FragmentActivity,
|
|||||||
putLong(DatabaseTaskNotificationService.NEW_ELEMENT_KEY, newIterations)
|
putLong(DatabaseTaskNotificationService.NEW_ELEMENT_KEY, newIterations)
|
||||||
putBoolean(DatabaseTaskNotificationService.SAVE_DATABASE_KEY, save)
|
putBoolean(DatabaseTaskNotificationService.SAVE_DATABASE_KEY, save)
|
||||||
}
|
}
|
||||||
, ACTION_DATABASE_SAVE_ITERATIONS_TASK)
|
, ACTION_DATABASE_UPDATE_ITERATIONS_TASK)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun startDatabaseSaveMemoryUsage(oldMemoryUsage: Long,
|
fun startDatabaseSaveMemoryUsage(oldMemoryUsage: Long,
|
||||||
@@ -473,7 +473,7 @@ class ProgressDialogThread(private val activity: FragmentActivity,
|
|||||||
putLong(DatabaseTaskNotificationService.NEW_ELEMENT_KEY, newMemoryUsage)
|
putLong(DatabaseTaskNotificationService.NEW_ELEMENT_KEY, newMemoryUsage)
|
||||||
putBoolean(DatabaseTaskNotificationService.SAVE_DATABASE_KEY, save)
|
putBoolean(DatabaseTaskNotificationService.SAVE_DATABASE_KEY, save)
|
||||||
}
|
}
|
||||||
, ACTION_DATABASE_SAVE_MEMORY_USAGE_TASK)
|
, ACTION_DATABASE_UPDATE_MEMORY_USAGE_TASK)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun startDatabaseSaveParallelism(oldParallelism: Int,
|
fun startDatabaseSaveParallelism(oldParallelism: Int,
|
||||||
@@ -484,7 +484,7 @@ class ProgressDialogThread(private val activity: FragmentActivity,
|
|||||||
putInt(DatabaseTaskNotificationService.NEW_ELEMENT_KEY, newParallelism)
|
putInt(DatabaseTaskNotificationService.NEW_ELEMENT_KEY, newParallelism)
|
||||||
putBoolean(DatabaseTaskNotificationService.SAVE_DATABASE_KEY, save)
|
putBoolean(DatabaseTaskNotificationService.SAVE_DATABASE_KEY, save)
|
||||||
}
|
}
|
||||||
, ACTION_DATABASE_SAVE_PARALLELISM_TASK)
|
, ACTION_DATABASE_UPDATE_PARALLELISM_TASK)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -70,17 +70,28 @@ class DatabaseTaskNotificationService : NotificationService(), ProgressTaskUpdat
|
|||||||
|
|
||||||
val intentAction = intent.action
|
val intentAction = intent.action
|
||||||
|
|
||||||
|
var saveAction = true
|
||||||
|
if (intent.hasExtra(SAVE_DATABASE_KEY)) {
|
||||||
|
saveAction = intent.getBooleanExtra(SAVE_DATABASE_KEY, saveAction)
|
||||||
|
}
|
||||||
|
|
||||||
val titleId: Int = when (intentAction) {
|
val titleId: Int = when (intentAction) {
|
||||||
ACTION_DATABASE_CREATE_TASK -> R.string.creating_database
|
ACTION_DATABASE_CREATE_TASK -> R.string.creating_database
|
||||||
ACTION_DATABASE_LOAD_TASK -> R.string.loading_database
|
ACTION_DATABASE_LOAD_TASK -> R.string.loading_database
|
||||||
else -> R.string.saving_database
|
else -> {
|
||||||
|
if (saveAction)
|
||||||
|
R.string.saving_database
|
||||||
|
else
|
||||||
|
R.string.command_execution
|
||||||
|
}
|
||||||
}
|
}
|
||||||
val messageId: Int? = when (intentAction) {
|
val messageId: Int? = when (intentAction) {
|
||||||
ACTION_DATABASE_LOAD_TASK -> null
|
ACTION_DATABASE_LOAD_TASK -> null
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
val warningId: Int? =
|
val warningId: Int? =
|
||||||
if (intentAction == ACTION_DATABASE_LOAD_TASK)
|
if (!saveAction
|
||||||
|
|| intentAction == ACTION_DATABASE_LOAD_TASK)
|
||||||
null
|
null
|
||||||
else
|
else
|
||||||
R.string.do_not_kill_app
|
R.string.do_not_kill_app
|
||||||
@@ -96,19 +107,20 @@ class DatabaseTaskNotificationService : NotificationService(), ProgressTaskUpdat
|
|||||||
ACTION_DATABASE_COPY_NODES_TASK -> buildDatabaseCopyNodesActionTask(intent)
|
ACTION_DATABASE_COPY_NODES_TASK -> buildDatabaseCopyNodesActionTask(intent)
|
||||||
ACTION_DATABASE_MOVE_NODES_TASK -> buildDatabaseMoveNodesActionTask(intent)
|
ACTION_DATABASE_MOVE_NODES_TASK -> buildDatabaseMoveNodesActionTask(intent)
|
||||||
ACTION_DATABASE_DELETE_NODES_TASK -> buildDatabaseDeleteNodesActionTask(intent)
|
ACTION_DATABASE_DELETE_NODES_TASK -> buildDatabaseDeleteNodesActionTask(intent)
|
||||||
ACTION_DATABASE_SAVE_NAME_TASK,
|
ACTION_DATABASE_UPDATE_NAME_TASK,
|
||||||
ACTION_DATABASE_SAVE_DESCRIPTION_TASK,
|
ACTION_DATABASE_UPDATE_DESCRIPTION_TASK,
|
||||||
ACTION_DATABASE_SAVE_DEFAULT_USERNAME_TASK,
|
ACTION_DATABASE_UPDATE_DEFAULT_USERNAME_TASK,
|
||||||
ACTION_DATABASE_SAVE_COLOR_TASK,
|
ACTION_DATABASE_UPDATE_COLOR_TASK,
|
||||||
ACTION_DATABASE_SAVE_COMPRESSION_TASK,
|
ACTION_DATABASE_UPDATE_COMPRESSION_TASK,
|
||||||
ACTION_DATABASE_SAVE_MAX_HISTORY_ITEMS_TASK,
|
ACTION_DATABASE_UPDATE_MAX_HISTORY_ITEMS_TASK,
|
||||||
ACTION_DATABASE_SAVE_MAX_HISTORY_SIZE_TASK,
|
ACTION_DATABASE_UPDATE_MAX_HISTORY_SIZE_TASK,
|
||||||
ACTION_DATABASE_SAVE_ENCRYPTION_TASK,
|
ACTION_DATABASE_UPDATE_ENCRYPTION_TASK,
|
||||||
ACTION_DATABASE_SAVE_KEY_DERIVATION_TASK,
|
ACTION_DATABASE_UPDATE_KEY_DERIVATION_TASK,
|
||||||
ACTION_DATABASE_SAVE_MEMORY_USAGE_TASK,
|
ACTION_DATABASE_UPDATE_MEMORY_USAGE_TASK,
|
||||||
ACTION_DATABASE_SAVE_PARALLELISM_TASK,
|
ACTION_DATABASE_UPDATE_PARALLELISM_TASK,
|
||||||
ACTION_DATABASE_SAVE_ITERATIONS_TASK -> buildDatabaseSaveElementActionTask(intent)
|
ACTION_DATABASE_UPDATE_ITERATIONS_TASK -> buildDatabaseUpdateElementActionTask(intent)
|
||||||
else -> buildDatabaseSave(intent)
|
ACTION_DATABASE_SAVE -> buildDatabaseSave(intent)
|
||||||
|
else -> null
|
||||||
}
|
}
|
||||||
|
|
||||||
actionRunnable?.let { actionRunnableNotNull ->
|
actionRunnable?.let { actionRunnableNotNull ->
|
||||||
@@ -397,7 +409,7 @@ class DatabaseTaskNotificationService : NotificationService(), ProgressTaskUpdat
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun buildDatabaseSaveElementActionTask(intent: Intent): ActionRunnable? {
|
private fun buildDatabaseUpdateElementActionTask(intent: Intent): ActionRunnable? {
|
||||||
return if (intent.hasExtra(SAVE_DATABASE_KEY)) {
|
return if (intent.hasExtra(SAVE_DATABASE_KEY)) {
|
||||||
return SaveDatabaseRunnable(this,
|
return SaveDatabaseRunnable(this,
|
||||||
Database.getInstance(),
|
Database.getInstance(),
|
||||||
@@ -472,18 +484,18 @@ class DatabaseTaskNotificationService : NotificationService(), ProgressTaskUpdat
|
|||||||
const val ACTION_DATABASE_COPY_NODES_TASK = "ACTION_DATABASE_COPY_NODES_TASK"
|
const val ACTION_DATABASE_COPY_NODES_TASK = "ACTION_DATABASE_COPY_NODES_TASK"
|
||||||
const val ACTION_DATABASE_MOVE_NODES_TASK = "ACTION_DATABASE_MOVE_NODES_TASK"
|
const val ACTION_DATABASE_MOVE_NODES_TASK = "ACTION_DATABASE_MOVE_NODES_TASK"
|
||||||
const val ACTION_DATABASE_DELETE_NODES_TASK = "ACTION_DATABASE_DELETE_NODES_TASK"
|
const val ACTION_DATABASE_DELETE_NODES_TASK = "ACTION_DATABASE_DELETE_NODES_TASK"
|
||||||
const val ACTION_DATABASE_SAVE_NAME_TASK = "ACTION_DATABASE_SAVE_NAME_TASK"
|
const val ACTION_DATABASE_UPDATE_NAME_TASK = "ACTION_DATABASE_UPDATE_NAME_TASK"
|
||||||
const val ACTION_DATABASE_SAVE_DESCRIPTION_TASK = "ACTION_DATABASE_SAVE_DESCRIPTION_TASK"
|
const val ACTION_DATABASE_UPDATE_DESCRIPTION_TASK = "ACTION_DATABASE_UPDATE_DESCRIPTION_TASK"
|
||||||
const val ACTION_DATABASE_SAVE_DEFAULT_USERNAME_TASK = "ACTION_DATABASE_SAVE_DEFAULT_USERNAME_TASK"
|
const val ACTION_DATABASE_UPDATE_DEFAULT_USERNAME_TASK = "ACTION_DATABASE_UPDATE_DEFAULT_USERNAME_TASK"
|
||||||
const val ACTION_DATABASE_SAVE_COLOR_TASK = "ACTION_DATABASE_SAVE_COLOR_TASK"
|
const val ACTION_DATABASE_UPDATE_COLOR_TASK = "ACTION_DATABASE_UPDATE_COLOR_TASK"
|
||||||
const val ACTION_DATABASE_SAVE_COMPRESSION_TASK = "ACTION_DATABASE_SAVE_COMPRESSION_TASK"
|
const val ACTION_DATABASE_UPDATE_COMPRESSION_TASK = "ACTION_DATABASE_UPDATE_COMPRESSION_TASK"
|
||||||
const val ACTION_DATABASE_SAVE_MAX_HISTORY_ITEMS_TASK = "ACTION_DATABASE_SAVE_MAX_HISTORY_ITEMS_TASK"
|
const val ACTION_DATABASE_UPDATE_MAX_HISTORY_ITEMS_TASK = "ACTION_DATABASE_UPDATE_MAX_HISTORY_ITEMS_TASK"
|
||||||
const val ACTION_DATABASE_SAVE_MAX_HISTORY_SIZE_TASK = "ACTION_DATABASE_SAVE_MAX_HISTORY_SIZE_TASK"
|
const val ACTION_DATABASE_UPDATE_MAX_HISTORY_SIZE_TASK = "ACTION_DATABASE_UPDATE_MAX_HISTORY_SIZE_TASK"
|
||||||
const val ACTION_DATABASE_SAVE_ENCRYPTION_TASK = "ACTION_DATABASE_SAVE_ENCRYPTION_TASK"
|
const val ACTION_DATABASE_UPDATE_ENCRYPTION_TASK = "ACTION_DATABASE_UPDATE_ENCRYPTION_TASK"
|
||||||
const val ACTION_DATABASE_SAVE_KEY_DERIVATION_TASK = "ACTION_DATABASE_SAVE_KEY_DERIVATION_TASK"
|
const val ACTION_DATABASE_UPDATE_KEY_DERIVATION_TASK = "ACTION_DATABASE_UPDATE_KEY_DERIVATION_TASK"
|
||||||
const val ACTION_DATABASE_SAVE_MEMORY_USAGE_TASK = "ACTION_DATABASE_SAVE_MEMORY_USAGE_TASK"
|
const val ACTION_DATABASE_UPDATE_MEMORY_USAGE_TASK = "ACTION_DATABASE_UPDATE_MEMORY_USAGE_TASK"
|
||||||
const val ACTION_DATABASE_SAVE_PARALLELISM_TASK = "ACTION_DATABASE_SAVE_PARALLELISM_TASK"
|
const val ACTION_DATABASE_UPDATE_PARALLELISM_TASK = "ACTION_DATABASE_UPDATE_PARALLELISM_TASK"
|
||||||
const val ACTION_DATABASE_SAVE_ITERATIONS_TASK = "ACTION_DATABASE_SAVE_ITERATIONS_TASK"
|
const val ACTION_DATABASE_UPDATE_ITERATIONS_TASK = "ACTION_DATABASE_UPDATE_ITERATIONS_TASK"
|
||||||
const val ACTION_DATABASE_SAVE = "ACTION_DATABASE_SAVE"
|
const val ACTION_DATABASE_SAVE = "ACTION_DATABASE_SAVE"
|
||||||
|
|
||||||
const val DATABASE_URI_KEY = "DATABASE_URI_KEY"
|
const val DATABASE_URI_KEY = "DATABASE_URI_KEY"
|
||||||
|
|||||||
@@ -0,0 +1,351 @@
|
|||||||
|
package com.kunzisoft.keepass.settings
|
||||||
|
|
||||||
|
import android.content.ActivityNotFoundException
|
||||||
|
import android.content.Intent
|
||||||
|
import android.net.Uri
|
||||||
|
import android.os.Build
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.provider.Settings
|
||||||
|
import android.util.Log
|
||||||
|
import android.view.autofill.AutofillManager
|
||||||
|
import android.widget.Toast
|
||||||
|
import androidx.annotation.RequiresApi
|
||||||
|
import androidx.appcompat.app.AlertDialog
|
||||||
|
import androidx.biometric.BiometricManager
|
||||||
|
import androidx.preference.ListPreference
|
||||||
|
import androidx.preference.Preference
|
||||||
|
import androidx.preference.SwitchPreference
|
||||||
|
import com.kunzisoft.keepass.BuildConfig
|
||||||
|
import com.kunzisoft.keepass.R
|
||||||
|
import com.kunzisoft.keepass.activities.dialogs.ProFeatureDialogFragment
|
||||||
|
import com.kunzisoft.keepass.activities.dialogs.UnavailableFeatureDialogFragment
|
||||||
|
import com.kunzisoft.keepass.activities.stylish.Stylish
|
||||||
|
import com.kunzisoft.keepass.app.database.CipherDatabaseAction
|
||||||
|
import com.kunzisoft.keepass.app.database.FileDatabaseHistoryAction
|
||||||
|
import com.kunzisoft.keepass.biometric.BiometricUnlockDatabaseHelper
|
||||||
|
import com.kunzisoft.keepass.education.Education
|
||||||
|
import com.kunzisoft.keepass.icons.IconPackChooser
|
||||||
|
import com.kunzisoft.keepass.settings.preference.IconPackListPreference
|
||||||
|
import com.kunzisoft.keepass.utils.UriUtil
|
||||||
|
|
||||||
|
class NestedAppSettingsFragment : NestedSettingsFragment() {
|
||||||
|
|
||||||
|
override fun onCreateScreenPreference(screen: Screen, savedInstanceState: Bundle?, rootKey: String?) {
|
||||||
|
|
||||||
|
// Load the preferences from an XML resource
|
||||||
|
when (screen) {
|
||||||
|
Screen.APPLICATION -> {
|
||||||
|
onCreateApplicationPreferences(rootKey)
|
||||||
|
}
|
||||||
|
Screen.FORM_FILLING -> {
|
||||||
|
onCreateFormFillingPreference(rootKey)
|
||||||
|
}
|
||||||
|
Screen.ADVANCED_UNLOCK -> {
|
||||||
|
onCreateAdvancedUnlockPreferences(rootKey)
|
||||||
|
}
|
||||||
|
Screen.APPEARANCE -> {
|
||||||
|
onCreateAppearancePreferences(rootKey)
|
||||||
|
}
|
||||||
|
else -> {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun onCreateApplicationPreferences(rootKey: String?) {
|
||||||
|
setPreferencesFromResource(R.xml.preferences_application, rootKey)
|
||||||
|
|
||||||
|
activity?.let { activity ->
|
||||||
|
allowCopyPassword()
|
||||||
|
|
||||||
|
findPreference<Preference>(getString(R.string.keyfile_key))?.setOnPreferenceChangeListener { _, newValue ->
|
||||||
|
if (!(newValue as Boolean)) {
|
||||||
|
FileDatabaseHistoryAction.getInstance(activity.applicationContext).deleteAllKeyFiles()
|
||||||
|
}
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
findPreference<Preference>(getString(R.string.recentfile_key))?.setOnPreferenceChangeListener { _, newValue ->
|
||||||
|
if (!(newValue as Boolean)) {
|
||||||
|
FileDatabaseHistoryAction.getInstance(activity.applicationContext).deleteAll()
|
||||||
|
}
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun onCreateFormFillingPreference(rootKey: String?) {
|
||||||
|
setPreferencesFromResource(R.xml.preferences_form_filling, rootKey)
|
||||||
|
|
||||||
|
activity?.let { activity ->
|
||||||
|
val autoFillEnablePreference: SwitchPreference? = findPreference(getString(R.string.settings_autofill_enable_key))
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||||
|
val autofillManager = activity.getSystemService(AutofillManager::class.java)
|
||||||
|
if (autofillManager != null && autofillManager.hasEnabledAutofillServices())
|
||||||
|
autoFillEnablePreference?.isChecked = autofillManager.hasEnabledAutofillServices()
|
||||||
|
autoFillEnablePreference?.onPreferenceClickListener = object : Preference.OnPreferenceClickListener {
|
||||||
|
@RequiresApi(api = Build.VERSION_CODES.O)
|
||||||
|
override fun onPreferenceClick(preference: Preference): Boolean {
|
||||||
|
if ((preference as SwitchPreference).isChecked) {
|
||||||
|
try {
|
||||||
|
startEnableService()
|
||||||
|
} catch (e: ActivityNotFoundException) {
|
||||||
|
val error = getString(R.string.error_autofill_enable_service)
|
||||||
|
preference.isChecked = false
|
||||||
|
Log.d(javaClass.name, error, e)
|
||||||
|
Toast.makeText(context, error, Toast.LENGTH_SHORT).show()
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
disableService()
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequiresApi(api = Build.VERSION_CODES.O)
|
||||||
|
private fun disableService() {
|
||||||
|
if (autofillManager != null && autofillManager.hasEnabledAutofillServices()) {
|
||||||
|
autofillManager.disableAutofillServices()
|
||||||
|
} else {
|
||||||
|
Log.d(javaClass.name, "Sample service already disabled.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequiresApi(api = Build.VERSION_CODES.O)
|
||||||
|
@Throws(ActivityNotFoundException::class)
|
||||||
|
private fun startEnableService() {
|
||||||
|
if (autofillManager != null && !autofillManager.hasEnabledAutofillServices()) {
|
||||||
|
val intent = Intent(Settings.ACTION_REQUEST_SET_AUTOFILL_SERVICE)
|
||||||
|
// TODO Autofill
|
||||||
|
intent.data = Uri.parse("package:com.example.android.autofill.service")
|
||||||
|
Log.d(javaClass.name, "enableService(): intent=$intent")
|
||||||
|
startActivityForResult(intent, REQUEST_CODE_AUTOFILL)
|
||||||
|
} else {
|
||||||
|
Log.d(javaClass.name, "Sample service already enabled.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
autoFillEnablePreference?.setOnPreferenceClickListener { preference ->
|
||||||
|
(preference as SwitchPreference).isChecked = false
|
||||||
|
val fragmentManager = fragmentManager!!
|
||||||
|
UnavailableFeatureDialogFragment.getInstance(Build.VERSION_CODES.O)
|
||||||
|
.show(fragmentManager, "unavailableFeatureDialog")
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
findPreference<Preference>(getString(R.string.magic_keyboard_explanation_key))?.setOnPreferenceClickListener {
|
||||||
|
UriUtil.gotoUrl(context!!, R.string.magic_keyboard_explanation_url)
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
findPreference<Preference>(getString(R.string.magic_keyboard_key))?.setOnPreferenceClickListener {
|
||||||
|
startActivity(Intent(Settings.ACTION_INPUT_METHOD_SETTINGS).apply {
|
||||||
|
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||||
|
})
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
findPreference<Preference>(getString(R.string.magic_keyboard_preference_key))?.setOnPreferenceClickListener {
|
||||||
|
startActivity(Intent(context, MagikIMESettings::class.java))
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
findPreference<Preference>(getString(R.string.clipboard_explanation_key))?.setOnPreferenceClickListener {
|
||||||
|
UriUtil.gotoUrl(context!!, R.string.clipboard_explanation_url)
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
findPreference<Preference>(getString(R.string.autofill_explanation_key))?.setOnPreferenceClickListener {
|
||||||
|
UriUtil.gotoUrl(context!!, R.string.autofill_explanation_url)
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Present in two places
|
||||||
|
allowCopyPassword()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun allowCopyPassword() {
|
||||||
|
val copyPasswordPreference: SwitchPreference? = findPreference(getString(R.string.allow_copy_password_key))
|
||||||
|
copyPasswordPreference?.setOnPreferenceChangeListener { _, newValue ->
|
||||||
|
if (newValue as Boolean && context != null) {
|
||||||
|
val message = getString(R.string.allow_copy_password_warning) +
|
||||||
|
"\n\n" +
|
||||||
|
getString(R.string.clipboard_warning)
|
||||||
|
AlertDialog
|
||||||
|
.Builder(context!!)
|
||||||
|
.setMessage(message)
|
||||||
|
.create()
|
||||||
|
.apply {
|
||||||
|
setButton(AlertDialog.BUTTON_POSITIVE, getText(R.string.enable))
|
||||||
|
{ dialog, _ ->
|
||||||
|
dialog.dismiss()
|
||||||
|
}
|
||||||
|
setButton(AlertDialog.BUTTON_NEGATIVE, getText(R.string.disable))
|
||||||
|
{ dialog, _ ->
|
||||||
|
copyPasswordPreference.isChecked = false
|
||||||
|
dialog.dismiss()
|
||||||
|
}
|
||||||
|
show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun onCreateAdvancedUnlockPreferences(rootKey: String?) {
|
||||||
|
setPreferencesFromResource(R.xml.preferences_advanced_unlock, rootKey)
|
||||||
|
|
||||||
|
activity?.let { activity ->
|
||||||
|
val biometricUnlockEnablePreference: SwitchPreference? = findPreference(getString(R.string.biometric_unlock_enable_key))
|
||||||
|
// < M solve verifyError exception
|
||||||
|
var biometricUnlockSupported = false
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||||
|
val biometricCanAuthenticate = BiometricManager.from(activity).canAuthenticate()
|
||||||
|
biometricUnlockSupported = biometricCanAuthenticate == BiometricManager.BIOMETRIC_ERROR_NONE_ENROLLED
|
||||||
|
|| biometricCanAuthenticate == BiometricManager.BIOMETRIC_SUCCESS
|
||||||
|
}
|
||||||
|
if (!biometricUnlockSupported) {
|
||||||
|
// False if under Marshmallow
|
||||||
|
biometricUnlockEnablePreference?.apply {
|
||||||
|
isChecked = false
|
||||||
|
setOnPreferenceClickListener { preference ->
|
||||||
|
fragmentManager?.let { fragmentManager ->
|
||||||
|
(preference as SwitchPreference).isChecked = false
|
||||||
|
UnavailableFeatureDialogFragment.getInstance(Build.VERSION_CODES.M)
|
||||||
|
.show(fragmentManager, "unavailableFeatureDialog")
|
||||||
|
}
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val deleteKeysFingerprints: Preference? = findPreference(getString(R.string.biometric_delete_all_key_key))
|
||||||
|
if (!biometricUnlockSupported) {
|
||||||
|
deleteKeysFingerprints?.isEnabled = false
|
||||||
|
} else {
|
||||||
|
deleteKeysFingerprints?.setOnPreferenceClickListener {
|
||||||
|
context?.let { context ->
|
||||||
|
AlertDialog.Builder(context)
|
||||||
|
.setMessage(resources.getString(R.string.biometric_delete_all_key_warning))
|
||||||
|
.setIcon(android.R.drawable.ic_dialog_alert)
|
||||||
|
.setPositiveButton(resources.getString(android.R.string.yes)
|
||||||
|
) { _, _ ->
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||||
|
BiometricUnlockDatabaseHelper.deleteEntryKeyInKeystoreForBiometric(
|
||||||
|
activity,
|
||||||
|
object : BiometricUnlockDatabaseHelper.BiometricUnlockErrorCallback {
|
||||||
|
override fun onInvalidKeyException(e: Exception) {}
|
||||||
|
|
||||||
|
override fun onBiometricException(e: Exception) {
|
||||||
|
Toast.makeText(context,
|
||||||
|
getString(R.string.biometric_scanning_error, e.localizedMessage),
|
||||||
|
Toast.LENGTH_SHORT).show()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
CipherDatabaseAction.getInstance(context.applicationContext).deleteAll()
|
||||||
|
}
|
||||||
|
.setNegativeButton(resources.getString(android.R.string.no))
|
||||||
|
{ _, _ -> }.show()
|
||||||
|
}
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
findPreference<Preference>(getString(R.string.advanced_unlock_explanation_key))?.setOnPreferenceClickListener {
|
||||||
|
UriUtil.gotoUrl(context!!, R.string.advanced_unlock_explanation_url)
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun onCreateAppearancePreferences(rootKey: String?) {
|
||||||
|
setPreferencesFromResource(R.xml.preferences_appearance, rootKey)
|
||||||
|
|
||||||
|
activity?.let { activity ->
|
||||||
|
findPreference<ListPreference>(getString(R.string.setting_style_key))?.setOnPreferenceChangeListener { _, newValue ->
|
||||||
|
var styleEnabled = true
|
||||||
|
val styleIdString = newValue as String
|
||||||
|
if (BuildConfig.CLOSED_STORE || !Education.isEducationScreenReclickedPerformed(context!!))
|
||||||
|
for (themeIdDisabled in BuildConfig.STYLES_DISABLED) {
|
||||||
|
if (themeIdDisabled == styleIdString) {
|
||||||
|
styleEnabled = false
|
||||||
|
fragmentManager?.let { fragmentManager ->
|
||||||
|
ProFeatureDialogFragment().show(fragmentManager, "pro_feature_dialog")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (styleEnabled) {
|
||||||
|
Stylish.assignStyle(styleIdString)
|
||||||
|
activity.recreate()
|
||||||
|
}
|
||||||
|
styleEnabled
|
||||||
|
}
|
||||||
|
|
||||||
|
findPreference<IconPackListPreference>(getString(R.string.setting_icon_pack_choose_key))?.setOnPreferenceChangeListener { _, newValue ->
|
||||||
|
var iconPackEnabled = true
|
||||||
|
val iconPackId = newValue as String
|
||||||
|
if (BuildConfig.CLOSED_STORE || !Education.isEducationScreenReclickedPerformed(context!!))
|
||||||
|
for (iconPackIdDisabled in BuildConfig.ICON_PACKS_DISABLED) {
|
||||||
|
if (iconPackIdDisabled == iconPackId) {
|
||||||
|
iconPackEnabled = false
|
||||||
|
fragmentManager?.let { fragmentManager ->
|
||||||
|
ProFeatureDialogFragment().show(fragmentManager, "pro_feature_dialog")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (iconPackEnabled) {
|
||||||
|
IconPackChooser.setSelectedIconPack(iconPackId)
|
||||||
|
}
|
||||||
|
iconPackEnabled
|
||||||
|
}
|
||||||
|
|
||||||
|
findPreference<Preference>(getString(R.string.reset_education_screens_key))?.setOnPreferenceClickListener {
|
||||||
|
// To allow only one toast
|
||||||
|
if (mCount == 0) {
|
||||||
|
val sharedPreferences = Education.getEducationSharedPreferences(context!!)
|
||||||
|
val editor = sharedPreferences.edit()
|
||||||
|
for (resourceId in Education.educationResourcesKeys) {
|
||||||
|
editor.putBoolean(getString(resourceId), false)
|
||||||
|
}
|
||||||
|
editor.apply()
|
||||||
|
Toast.makeText(context, R.string.reset_education_screens_text, Toast.LENGTH_SHORT).show()
|
||||||
|
}
|
||||||
|
mCount++
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onResume() {
|
||||||
|
super.onResume()
|
||||||
|
|
||||||
|
activity?.let { activity ->
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||||
|
val autoFillEnablePreference: SwitchPreference? = findPreference(getString(R.string.settings_autofill_enable_key))
|
||||||
|
if (autoFillEnablePreference != null) {
|
||||||
|
val autofillManager = activity.getSystemService(AutofillManager::class.java)
|
||||||
|
autoFillEnablePreference.isChecked = autofillManager != null
|
||||||
|
&& autofillManager.hasEnabledAutofillServices()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private var mCount = 0
|
||||||
|
override fun onStop() {
|
||||||
|
super.onStop()
|
||||||
|
activity?.let { activity ->
|
||||||
|
if (mCount == 10) {
|
||||||
|
Education.getEducationSharedPreferences(activity).edit()
|
||||||
|
.putBoolean(getString(R.string.education_screen_reclicked_key), true).apply()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
|
||||||
|
private const val REQUEST_CODE_AUTOFILL = 5201
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,566 @@
|
|||||||
|
package com.kunzisoft.keepass.settings
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.graphics.Color
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.util.Log
|
||||||
|
import android.view.*
|
||||||
|
import androidx.fragment.app.DialogFragment
|
||||||
|
import androidx.preference.Preference
|
||||||
|
import androidx.preference.PreferenceCategory
|
||||||
|
import androidx.preference.SwitchPreference
|
||||||
|
import com.kunzisoft.androidclearchroma.ChromaUtil
|
||||||
|
import com.kunzisoft.keepass.R
|
||||||
|
import com.kunzisoft.keepass.activities.dialogs.AssignMasterKeyDialogFragment
|
||||||
|
import com.kunzisoft.keepass.activities.helpers.ReadOnlyHelper
|
||||||
|
import com.kunzisoft.keepass.activities.lock.lock
|
||||||
|
import com.kunzisoft.keepass.crypto.keyDerivation.KdfEngine
|
||||||
|
import com.kunzisoft.keepass.database.action.ProgressDialogThread
|
||||||
|
import com.kunzisoft.keepass.database.element.Database
|
||||||
|
import com.kunzisoft.keepass.database.element.PwCompressionAlgorithm
|
||||||
|
import com.kunzisoft.keepass.database.element.PwEncryptionAlgorithm
|
||||||
|
import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService
|
||||||
|
import com.kunzisoft.keepass.settings.preference.*
|
||||||
|
import com.kunzisoft.keepass.settings.preferencedialogfragment.*
|
||||||
|
import com.kunzisoft.keepass.tasks.ActionRunnable
|
||||||
|
import com.kunzisoft.keepass.utils.MenuUtil
|
||||||
|
|
||||||
|
class NestedDatabaseSettingsFragment : NestedSettingsFragment() {
|
||||||
|
|
||||||
|
private var mDatabase: Database = Database.getInstance()
|
||||||
|
private var mDatabaseReadOnly: Boolean = false
|
||||||
|
private var mDatabaseAutoSaveEnabled: Boolean = true
|
||||||
|
|
||||||
|
private var dbNamePref: InputTextPreference? = null
|
||||||
|
private var dbDescriptionPref: InputTextPreference? = null
|
||||||
|
private var dbDefaultUsername: InputTextPreference? = null
|
||||||
|
private var dbCustomColorPref: DialogColorPreference? = null
|
||||||
|
private var dbDataCompressionPref: Preference? = null
|
||||||
|
private var recycleBinGroupPref: Preference? = null
|
||||||
|
private var dbMaxHistoryItemsPref: InputNumberPreference? = null
|
||||||
|
private var dbMaxHistorySizePref: InputNumberPreference? = null
|
||||||
|
private var mEncryptionAlgorithmPref: DialogListExplanationPreference? = null
|
||||||
|
private var mKeyDerivationPref: DialogListExplanationPreference? = null
|
||||||
|
private var mRoundPref: InputKdfNumberPreference? = null
|
||||||
|
private var mMemoryPref: InputKdfNumberPreference? = null
|
||||||
|
private var mParallelismPref: InputKdfNumberPreference? = null
|
||||||
|
|
||||||
|
override fun onCreateScreenPreference(screen: Screen, savedInstanceState: Bundle?, rootKey: String?) {
|
||||||
|
setHasOptionsMenu(true)
|
||||||
|
|
||||||
|
mDatabaseReadOnly = mDatabase.isReadOnly
|
||||||
|
|| ReadOnlyHelper.retrieveReadOnlyFromInstanceStateOrArguments(savedInstanceState, arguments)
|
||||||
|
|
||||||
|
// Load the preferences from an XML resource
|
||||||
|
when (screen) {
|
||||||
|
Screen.DATABASE -> {
|
||||||
|
onCreateDatabasePreference(rootKey)
|
||||||
|
}
|
||||||
|
Screen.DATABASE_SECURITY -> {
|
||||||
|
onCreateDatabaseSecurityPreference(rootKey)
|
||||||
|
}
|
||||||
|
Screen.DATABASE_MASTER_KEY -> {
|
||||||
|
onCreateDatabaseMasterKeyPreference(rootKey)
|
||||||
|
}
|
||||||
|
else -> {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun onCreateDatabasePreference(rootKey: String?) {
|
||||||
|
setPreferencesFromResource(R.xml.preferences_database, rootKey)
|
||||||
|
|
||||||
|
if (mDatabase.loaded) {
|
||||||
|
|
||||||
|
val dbGeneralPrefCategory: PreferenceCategory? = findPreference(getString(R.string.database_category_general_key))
|
||||||
|
|
||||||
|
// Database name
|
||||||
|
dbNamePref = findPreference(getString(R.string.database_name_key))
|
||||||
|
if (mDatabase.allowName) {
|
||||||
|
dbNamePref?.summary = mDatabase.name
|
||||||
|
} else {
|
||||||
|
dbGeneralPrefCategory?.removePreference(dbNamePref)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Database description
|
||||||
|
dbDescriptionPref = findPreference(getString(R.string.database_description_key))
|
||||||
|
if (mDatabase.allowDescription) {
|
||||||
|
dbDescriptionPref?.summary = mDatabase.description
|
||||||
|
} else {
|
||||||
|
dbGeneralPrefCategory?.removePreference(dbDescriptionPref)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Database default username
|
||||||
|
dbDefaultUsername = findPreference(getString(R.string.database_default_username_key))
|
||||||
|
if (mDatabase.allowDefaultUsername) {
|
||||||
|
dbDefaultUsername?.summary = mDatabase.defaultUsername
|
||||||
|
} else {
|
||||||
|
dbDefaultUsername?.isEnabled = false
|
||||||
|
// TODO dbGeneralPrefCategory?.removePreference(dbDefaultUsername)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Database custom color
|
||||||
|
dbCustomColorPref = findPreference(getString(R.string.database_custom_color_key))
|
||||||
|
if (mDatabase.allowCustomColor) {
|
||||||
|
dbCustomColorPref?.apply {
|
||||||
|
try {
|
||||||
|
color = Color.parseColor(mDatabase.customColor)
|
||||||
|
summary = mDatabase.customColor
|
||||||
|
} catch (e: Exception) {
|
||||||
|
color = DialogColorPreference.DISABLE_COLOR
|
||||||
|
summary = ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
dbCustomColorPref?.isEnabled = false
|
||||||
|
// TODO dbGeneralPrefCategory?.removePreference(dbCustomColorPref)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Version
|
||||||
|
findPreference<Preference>(getString(R.string.database_version_key))
|
||||||
|
?.summary = mDatabase.version
|
||||||
|
|
||||||
|
val dbCompressionPrefCategory: PreferenceCategory? = findPreference(getString(R.string.database_category_compression_key))
|
||||||
|
|
||||||
|
// Database compression
|
||||||
|
dbDataCompressionPref = findPreference(getString(R.string.database_data_compression_key))
|
||||||
|
if (mDatabase.allowDataCompression) {
|
||||||
|
dbDataCompressionPref?.summary = (mDatabase.compressionAlgorithm
|
||||||
|
?: PwCompressionAlgorithm.None).getName(resources)
|
||||||
|
} else {
|
||||||
|
dbCompressionPrefCategory?.isVisible = false
|
||||||
|
}
|
||||||
|
|
||||||
|
val dbRecycleBinPrefCategory: PreferenceCategory? = findPreference(getString(R.string.database_category_recycle_bin_key))
|
||||||
|
recycleBinGroupPref = findPreference(getString(R.string.recycle_bin_group_key))
|
||||||
|
|
||||||
|
// Recycle bin
|
||||||
|
if (mDatabase.allowRecycleBin) {
|
||||||
|
val recycleBinEnablePref: SwitchPreference? = findPreference(getString(R.string.recycle_bin_enable_key))
|
||||||
|
recycleBinEnablePref?.apply {
|
||||||
|
isChecked = mDatabase.isRecycleBinEnabled
|
||||||
|
isEnabled = if (!mDatabaseReadOnly) {
|
||||||
|
setOnPreferenceChangeListener { _, newValue ->
|
||||||
|
val recycleBinEnabled = newValue as Boolean
|
||||||
|
mDatabase.isRecycleBinEnabled = recycleBinEnabled
|
||||||
|
if (recycleBinEnabled) {
|
||||||
|
mDatabase.ensureRecycleBinExists(resources)
|
||||||
|
} else {
|
||||||
|
mDatabase.removeRecycleBin()
|
||||||
|
}
|
||||||
|
refreshRecycleBinGroup()
|
||||||
|
// Save the database if not in readonly mode
|
||||||
|
(context as SettingsActivity?)?.
|
||||||
|
mProgressDialogThread?.startDatabaseSave(mDatabaseAutoSaveEnabled)
|
||||||
|
true
|
||||||
|
}
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Recycle Bin group
|
||||||
|
refreshRecycleBinGroup()
|
||||||
|
} else {
|
||||||
|
dbRecycleBinPrefCategory?.isVisible = false
|
||||||
|
}
|
||||||
|
|
||||||
|
// History
|
||||||
|
findPreference<PreferenceCategory>(getString(R.string.database_category_history_key))
|
||||||
|
?.isVisible = mDatabase.manageHistory == true
|
||||||
|
|
||||||
|
// Max history items
|
||||||
|
dbMaxHistoryItemsPref = findPreference<InputNumberPreference>(getString(R.string.max_history_items_key))?.apply {
|
||||||
|
summary = mDatabase.historyMaxItems.toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Max history size
|
||||||
|
dbMaxHistorySizePref = findPreference<InputNumberPreference>(getString(R.string.max_history_size_key))?.apply {
|
||||||
|
summary = mDatabase.historyMaxSize.toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
Log.e(javaClass.name, "Database isn't ready")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun refreshRecycleBinGroup() {
|
||||||
|
recycleBinGroupPref?.apply {
|
||||||
|
if (mDatabase.isRecycleBinEnabled) {
|
||||||
|
summary = mDatabase.recycleBin?.title
|
||||||
|
isEnabled = true
|
||||||
|
} else {
|
||||||
|
summary = null
|
||||||
|
isEnabled = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun onCreateDatabaseSecurityPreference(rootKey: String?) {
|
||||||
|
setPreferencesFromResource(R.xml.preferences_database_security, rootKey)
|
||||||
|
|
||||||
|
if (mDatabase.loaded) {
|
||||||
|
// Encryption Algorithm
|
||||||
|
mEncryptionAlgorithmPref = findPreference<DialogListExplanationPreference>(getString(R.string.encryption_algorithm_key))?.apply {
|
||||||
|
summary = mDatabase.getEncryptionAlgorithmName(resources)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Key derivation function
|
||||||
|
mKeyDerivationPref = findPreference<DialogListExplanationPreference>(getString(R.string.key_derivation_function_key))?.apply {
|
||||||
|
summary = mDatabase.getKeyDerivationName(resources)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Round encryption
|
||||||
|
mRoundPref = findPreference<InputKdfNumberPreference>(getString(R.string.transform_rounds_key))?.apply {
|
||||||
|
summary = mDatabase.numberKeyEncryptionRounds.toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Memory Usage
|
||||||
|
mMemoryPref = findPreference<InputKdfNumberPreference>(getString(R.string.memory_usage_key))?.apply {
|
||||||
|
summary = mDatabase.memoryUsage.toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parallelism
|
||||||
|
mParallelismPref = findPreference<InputKdfNumberPreference>(getString(R.string.parallelism_key))?.apply {
|
||||||
|
summary = mDatabase.parallelism.toString()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Log.e(javaClass.name, "Database isn't ready")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun onCreateDatabaseMasterKeyPreference(rootKey: String?) {
|
||||||
|
setPreferencesFromResource(R.xml.preferences_database_master_key, rootKey)
|
||||||
|
|
||||||
|
if (mDatabase.loaded) {
|
||||||
|
findPreference<Preference>(getString(R.string.settings_database_change_credentials_key))?.apply {
|
||||||
|
isEnabled = if (!mDatabaseReadOnly) {
|
||||||
|
onPreferenceClickListener = Preference.OnPreferenceClickListener {
|
||||||
|
fragmentManager?.let { fragmentManager ->
|
||||||
|
AssignMasterKeyDialogFragment.getInstance(mDatabase.allowNoMasterKey)
|
||||||
|
.show(fragmentManager, "passwordDialog")
|
||||||
|
}
|
||||||
|
false
|
||||||
|
}
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Log.e(javaClass.name, "Database isn't ready")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val colorSelectedListener: ((Boolean, Int)-> Unit)? = { enable, color ->
|
||||||
|
dbCustomColorPref?.summary = ChromaUtil.getFormattedColorString(color, false)
|
||||||
|
if (enable) {
|
||||||
|
dbCustomColorPref?.color = color
|
||||||
|
} else {
|
||||||
|
dbCustomColorPref?.color = DialogColorPreference.DISABLE_COLOR
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||||
|
val view = super.onCreateView(inflater, container, savedInstanceState)
|
||||||
|
|
||||||
|
try {
|
||||||
|
// To reassign color listener after orientation change
|
||||||
|
val chromaDialog = fragmentManager?.findFragmentByTag(TAG_PREF_FRAGMENT) as DatabaseColorPreferenceDialogFragmentCompat?
|
||||||
|
chromaDialog?.onColorSelectedListener = colorSelectedListener
|
||||||
|
} catch (e: Exception) {}
|
||||||
|
|
||||||
|
return view
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onProgressDialogThreadResult(actionTask: String,
|
||||||
|
result: ActionRunnable.Result) {
|
||||||
|
result.data?.let { data ->
|
||||||
|
if (data.containsKey(DatabaseTaskNotificationService.OLD_ELEMENT_KEY)
|
||||||
|
&& data.containsKey(DatabaseTaskNotificationService.NEW_ELEMENT_KEY)) {
|
||||||
|
when (actionTask) {
|
||||||
|
/*
|
||||||
|
--------
|
||||||
|
Main preferences
|
||||||
|
--------
|
||||||
|
*/
|
||||||
|
DatabaseTaskNotificationService.ACTION_DATABASE_UPDATE_NAME_TASK -> {
|
||||||
|
val oldName = data.getString(DatabaseTaskNotificationService.OLD_ELEMENT_KEY)!!
|
||||||
|
val newName = data.getString(DatabaseTaskNotificationService.NEW_ELEMENT_KEY)!!
|
||||||
|
val nameToShow =
|
||||||
|
if (result.isSuccess) {
|
||||||
|
newName
|
||||||
|
} else {
|
||||||
|
mDatabase.name = oldName
|
||||||
|
oldName
|
||||||
|
}
|
||||||
|
dbNamePref?.summary = nameToShow
|
||||||
|
}
|
||||||
|
DatabaseTaskNotificationService.ACTION_DATABASE_UPDATE_DESCRIPTION_TASK -> {
|
||||||
|
val oldDescription = data.getString(DatabaseTaskNotificationService.OLD_ELEMENT_KEY)!!
|
||||||
|
val newDescription = data.getString(DatabaseTaskNotificationService.NEW_ELEMENT_KEY)!!
|
||||||
|
val descriptionToShow =
|
||||||
|
if (result.isSuccess) {
|
||||||
|
newDescription
|
||||||
|
} else {
|
||||||
|
mDatabase.description = oldDescription
|
||||||
|
oldDescription
|
||||||
|
}
|
||||||
|
dbDescriptionPref?.summary = descriptionToShow
|
||||||
|
}
|
||||||
|
DatabaseTaskNotificationService.ACTION_DATABASE_UPDATE_DEFAULT_USERNAME_TASK -> {
|
||||||
|
val oldDefaultUsername = data.getString(DatabaseTaskNotificationService.OLD_ELEMENT_KEY)!!
|
||||||
|
val newDefaultUsername = data.getString(DatabaseTaskNotificationService.NEW_ELEMENT_KEY)!!
|
||||||
|
val defaultUsernameToShow =
|
||||||
|
if (result.isSuccess) {
|
||||||
|
newDefaultUsername
|
||||||
|
} else {
|
||||||
|
mDatabase.defaultUsername = oldDefaultUsername
|
||||||
|
oldDefaultUsername
|
||||||
|
}
|
||||||
|
dbDefaultUsername?.summary = defaultUsernameToShow
|
||||||
|
}
|
||||||
|
DatabaseTaskNotificationService.ACTION_DATABASE_UPDATE_COLOR_TASK -> {
|
||||||
|
val oldColor = data.getString(DatabaseTaskNotificationService.OLD_ELEMENT_KEY)!!
|
||||||
|
val newColor = data.getString(DatabaseTaskNotificationService.NEW_ELEMENT_KEY)!!
|
||||||
|
|
||||||
|
val defaultColorToShow =
|
||||||
|
if (result.isSuccess) {
|
||||||
|
newColor
|
||||||
|
} else {
|
||||||
|
mDatabase.customColor = oldColor
|
||||||
|
oldColor
|
||||||
|
}
|
||||||
|
dbCustomColorPref?.summary = defaultColorToShow
|
||||||
|
}
|
||||||
|
DatabaseTaskNotificationService.ACTION_DATABASE_UPDATE_COMPRESSION_TASK -> {
|
||||||
|
val oldCompression = data.getSerializable(DatabaseTaskNotificationService.OLD_ELEMENT_KEY) as PwCompressionAlgorithm
|
||||||
|
val newCompression = data.getSerializable(DatabaseTaskNotificationService.NEW_ELEMENT_KEY) as PwCompressionAlgorithm
|
||||||
|
val algorithmToShow =
|
||||||
|
if (result.isSuccess) {
|
||||||
|
newCompression
|
||||||
|
} else {
|
||||||
|
mDatabase.compressionAlgorithm = oldCompression
|
||||||
|
oldCompression
|
||||||
|
}
|
||||||
|
dbDataCompressionPref?.summary = algorithmToShow.getName(resources)
|
||||||
|
}
|
||||||
|
DatabaseTaskNotificationService.ACTION_DATABASE_UPDATE_MAX_HISTORY_ITEMS_TASK -> {
|
||||||
|
val oldMaxHistoryItems = data.getInt(DatabaseTaskNotificationService.OLD_ELEMENT_KEY)
|
||||||
|
val newMaxHistoryItems = data.getInt(DatabaseTaskNotificationService.NEW_ELEMENT_KEY)
|
||||||
|
val maxHistoryItemsToShow =
|
||||||
|
if (result.isSuccess) {
|
||||||
|
newMaxHistoryItems
|
||||||
|
} else {
|
||||||
|
mDatabase.historyMaxItems = oldMaxHistoryItems
|
||||||
|
oldMaxHistoryItems
|
||||||
|
}
|
||||||
|
dbMaxHistoryItemsPref?.summary = maxHistoryItemsToShow.toString()
|
||||||
|
}
|
||||||
|
DatabaseTaskNotificationService.ACTION_DATABASE_UPDATE_MAX_HISTORY_SIZE_TASK -> {
|
||||||
|
val oldMaxHistorySize = data.getLong(DatabaseTaskNotificationService.OLD_ELEMENT_KEY)
|
||||||
|
val newMaxHistorySize = data.getLong(DatabaseTaskNotificationService.NEW_ELEMENT_KEY)
|
||||||
|
val maxHistorySizeToShow =
|
||||||
|
if (result.isSuccess) {
|
||||||
|
newMaxHistorySize
|
||||||
|
} else {
|
||||||
|
mDatabase.historyMaxSize = oldMaxHistorySize
|
||||||
|
oldMaxHistorySize
|
||||||
|
}
|
||||||
|
dbMaxHistorySizePref?.summary = maxHistorySizeToShow.toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
--------
|
||||||
|
Security
|
||||||
|
--------
|
||||||
|
*/
|
||||||
|
DatabaseTaskNotificationService.ACTION_DATABASE_UPDATE_ENCRYPTION_TASK -> {
|
||||||
|
val oldEncryption = data.getSerializable(DatabaseTaskNotificationService.OLD_ELEMENT_KEY) as PwEncryptionAlgorithm
|
||||||
|
val newEncryption = data.getSerializable(DatabaseTaskNotificationService.NEW_ELEMENT_KEY) as PwEncryptionAlgorithm
|
||||||
|
val algorithmToShow =
|
||||||
|
if (result.isSuccess) {
|
||||||
|
newEncryption
|
||||||
|
} else {
|
||||||
|
mDatabase.encryptionAlgorithm = oldEncryption
|
||||||
|
oldEncryption
|
||||||
|
}
|
||||||
|
mEncryptionAlgorithmPref?.summary = algorithmToShow.getName(resources)
|
||||||
|
}
|
||||||
|
DatabaseTaskNotificationService.ACTION_DATABASE_UPDATE_KEY_DERIVATION_TASK -> {
|
||||||
|
val oldKeyDerivationEngine = data.getSerializable(DatabaseTaskNotificationService.OLD_ELEMENT_KEY) as KdfEngine
|
||||||
|
val newKeyDerivationEngine = data.getSerializable(DatabaseTaskNotificationService.NEW_ELEMENT_KEY) as KdfEngine
|
||||||
|
val kdfEngineToShow =
|
||||||
|
if (result.isSuccess) {
|
||||||
|
newKeyDerivationEngine
|
||||||
|
} else {
|
||||||
|
mDatabase.kdfEngine = oldKeyDerivationEngine
|
||||||
|
oldKeyDerivationEngine
|
||||||
|
}
|
||||||
|
mKeyDerivationPref?.summary = kdfEngineToShow.getName(resources)
|
||||||
|
|
||||||
|
mRoundPref?.summary = kdfEngineToShow.defaultKeyRounds.toString()
|
||||||
|
// Disable memory and parallelism if not available
|
||||||
|
mMemoryPref?.summary = kdfEngineToShow.defaultMemoryUsage.toString()
|
||||||
|
mParallelismPref?.summary = kdfEngineToShow.defaultParallelism.toString()
|
||||||
|
}
|
||||||
|
DatabaseTaskNotificationService.ACTION_DATABASE_UPDATE_ITERATIONS_TASK -> {
|
||||||
|
val oldIterations = data.getLong(DatabaseTaskNotificationService.OLD_ELEMENT_KEY)
|
||||||
|
val newIterations = data.getLong(DatabaseTaskNotificationService.NEW_ELEMENT_KEY)
|
||||||
|
val roundsToShow =
|
||||||
|
if (result.isSuccess) {
|
||||||
|
newIterations
|
||||||
|
} else {
|
||||||
|
mDatabase.numberKeyEncryptionRounds = oldIterations
|
||||||
|
oldIterations
|
||||||
|
}
|
||||||
|
mRoundPref?.summary = roundsToShow.toString()
|
||||||
|
}
|
||||||
|
DatabaseTaskNotificationService.ACTION_DATABASE_UPDATE_MEMORY_USAGE_TASK -> {
|
||||||
|
val oldMemoryUsage = data.getLong(DatabaseTaskNotificationService.OLD_ELEMENT_KEY)
|
||||||
|
val newMemoryUsage = data.getLong(DatabaseTaskNotificationService.NEW_ELEMENT_KEY)
|
||||||
|
val memoryToShow =
|
||||||
|
if (result.isSuccess) {
|
||||||
|
newMemoryUsage
|
||||||
|
} else {
|
||||||
|
mDatabase.memoryUsage = oldMemoryUsage
|
||||||
|
oldMemoryUsage
|
||||||
|
}
|
||||||
|
mMemoryPref?.summary = memoryToShow.toString()
|
||||||
|
}
|
||||||
|
DatabaseTaskNotificationService.ACTION_DATABASE_UPDATE_PARALLELISM_TASK -> {
|
||||||
|
val oldParallelism = data.getInt(DatabaseTaskNotificationService.OLD_ELEMENT_KEY)
|
||||||
|
val newParallelism = data.getInt(DatabaseTaskNotificationService.NEW_ELEMENT_KEY)
|
||||||
|
val parallelismToShow =
|
||||||
|
if (result.isSuccess) {
|
||||||
|
newParallelism
|
||||||
|
} else {
|
||||||
|
mDatabase.parallelism = oldParallelism
|
||||||
|
oldParallelism
|
||||||
|
}
|
||||||
|
mParallelismPref?.summary = parallelismToShow.toString()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDisplayPreferenceDialog(preference: Preference?) {
|
||||||
|
|
||||||
|
var otherDialogFragment = false
|
||||||
|
|
||||||
|
fragmentManager?.let { fragmentManager ->
|
||||||
|
preference?.let { preference ->
|
||||||
|
var dialogFragment: DialogFragment? = null
|
||||||
|
when {
|
||||||
|
// Main Preferences
|
||||||
|
preference.key == getString(R.string.database_name_key) -> {
|
||||||
|
dialogFragment = DatabaseNamePreferenceDialogFragmentCompat.newInstance(preference.key)
|
||||||
|
}
|
||||||
|
preference.key == getString(R.string.database_description_key) -> {
|
||||||
|
dialogFragment = DatabaseDescriptionPreferenceDialogFragmentCompat.newInstance(preference.key)
|
||||||
|
}
|
||||||
|
preference.key == getString(R.string.database_default_username_key) -> {
|
||||||
|
dialogFragment = DatabaseDefaultUsernamePreferenceDialogFragmentCompat.newInstance(preference.key)
|
||||||
|
}
|
||||||
|
preference.key == getString(R.string.database_custom_color_key) -> {
|
||||||
|
dialogFragment = DatabaseColorPreferenceDialogFragmentCompat.newInstance(preference.key).apply {
|
||||||
|
onColorSelectedListener = colorSelectedListener
|
||||||
|
}
|
||||||
|
}
|
||||||
|
preference.key == getString(R.string.database_data_compression_key) -> {
|
||||||
|
dialogFragment = DatabaseDataCompressionPreferenceDialogFragmentCompat.newInstance(preference.key)
|
||||||
|
}
|
||||||
|
preference.key == getString(R.string.max_history_items_key) -> {
|
||||||
|
dialogFragment = MaxHistoryItemsPreferenceDialogFragmentCompat.newInstance(preference.key)
|
||||||
|
}
|
||||||
|
preference.key == getString(R.string.max_history_size_key) -> {
|
||||||
|
dialogFragment = MaxHistorySizePreferenceDialogFragmentCompat.newInstance(preference.key)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Security
|
||||||
|
preference.key == getString(R.string.encryption_algorithm_key) -> {
|
||||||
|
dialogFragment = DatabaseEncryptionAlgorithmPreferenceDialogFragmentCompat.newInstance(preference.key)
|
||||||
|
}
|
||||||
|
preference.key == getString(R.string.key_derivation_function_key) -> {
|
||||||
|
val keyDerivationDialogFragment = DatabaseKeyDerivationPreferenceDialogFragmentCompat.newInstance(preference.key)
|
||||||
|
// Add other prefs to manage
|
||||||
|
keyDerivationDialogFragment.setRoundPreference(mRoundPref)
|
||||||
|
keyDerivationDialogFragment.setMemoryPreference(mMemoryPref)
|
||||||
|
keyDerivationDialogFragment.setParallelismPreference(mParallelismPref)
|
||||||
|
dialogFragment = keyDerivationDialogFragment
|
||||||
|
}
|
||||||
|
preference.key == getString(R.string.transform_rounds_key) -> {
|
||||||
|
dialogFragment = RoundsPreferenceDialogFragmentCompat.newInstance(preference.key)
|
||||||
|
}
|
||||||
|
preference.key == getString(R.string.memory_usage_key) -> {
|
||||||
|
dialogFragment = MemoryUsagePreferenceDialogFragmentCompat.newInstance(preference.key)
|
||||||
|
}
|
||||||
|
preference.key == getString(R.string.parallelism_key) -> {
|
||||||
|
dialogFragment = ParallelismPreferenceDialogFragmentCompat.newInstance(preference.key)
|
||||||
|
}
|
||||||
|
else -> otherDialogFragment = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dialogFragment != null && !mDatabaseReadOnly) {
|
||||||
|
dialogFragment.setTargetFragment(this, 0)
|
||||||
|
dialogFragment.show(fragmentManager, TAG_PREF_FRAGMENT)
|
||||||
|
}
|
||||||
|
// Could not be handled here. Try with the super method.
|
||||||
|
else if (otherDialogFragment) {
|
||||||
|
super.onDisplayPreferenceDialog(preference)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onResume() {
|
||||||
|
super.onResume()
|
||||||
|
|
||||||
|
context?.let { context ->
|
||||||
|
mDatabaseAutoSaveEnabled = PreferencesUtil.isAutoSaveDatabaseEnabled(context)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
|
||||||
|
super.onCreateOptionsMenu(menu, inflater)
|
||||||
|
|
||||||
|
inflater.inflate(R.menu.database, menu)
|
||||||
|
if (mDatabaseReadOnly) {
|
||||||
|
menu.findItem(R.id.menu_save_database)?.isVisible = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||||
|
|
||||||
|
val settingActivity = activity as SettingsActivity?
|
||||||
|
|
||||||
|
when (item.itemId) {
|
||||||
|
R.id.menu_lock -> {
|
||||||
|
settingActivity?.lock()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
R.id.menu_save_database -> {
|
||||||
|
settingActivity?.mProgressDialogThread?.startDatabaseSave(!mDatabaseReadOnly)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> {
|
||||||
|
// Check the time lock before launching settings
|
||||||
|
settingActivity?.let {
|
||||||
|
MenuUtil.onDefaultMenuOptionsItemSelected(it, item, mDatabaseReadOnly, true)
|
||||||
|
}
|
||||||
|
return super.onOptionsItemSelected(item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onSaveInstanceState(outState: Bundle) {
|
||||||
|
ReadOnlyHelper.onSaveInstanceState(outState, mDatabaseReadOnly)
|
||||||
|
super.onSaveInstanceState(outState)
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
|
||||||
|
private const val TAG_PREF_FRAGMENT = "TAG_PREF_FRAGMENT"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -19,588 +19,37 @@
|
|||||||
*/
|
*/
|
||||||
package com.kunzisoft.keepass.settings
|
package com.kunzisoft.keepass.settings
|
||||||
|
|
||||||
import android.content.ActivityNotFoundException
|
|
||||||
import android.content.Intent
|
|
||||||
import android.content.res.Resources
|
import android.content.res.Resources
|
||||||
import android.graphics.Color
|
|
||||||
import android.net.Uri
|
|
||||||
import android.os.Build
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.provider.Settings
|
import androidx.preference.Preference
|
||||||
import android.util.Log
|
import androidx.preference.PreferenceFragmentCompat
|
||||||
import android.view.LayoutInflater
|
import androidx.preference.SwitchPreference
|
||||||
import android.view.View
|
|
||||||
import android.view.ViewGroup
|
|
||||||
import android.view.autofill.AutofillManager
|
|
||||||
import android.widget.Toast
|
|
||||||
import androidx.annotation.RequiresApi
|
|
||||||
import androidx.appcompat.app.AlertDialog
|
|
||||||
import androidx.biometric.BiometricManager
|
|
||||||
import androidx.fragment.app.DialogFragment
|
|
||||||
import androidx.preference.*
|
|
||||||
import com.kunzisoft.androidclearchroma.ChromaUtil
|
|
||||||
import com.kunzisoft.keepass.BuildConfig
|
|
||||||
import com.kunzisoft.keepass.R
|
import com.kunzisoft.keepass.R
|
||||||
import com.kunzisoft.keepass.activities.dialogs.*
|
import com.kunzisoft.keepass.activities.dialogs.UnderDevelopmentFeatureDialogFragment
|
||||||
import com.kunzisoft.keepass.activities.helpers.ReadOnlyHelper
|
import com.kunzisoft.keepass.activities.helpers.ReadOnlyHelper
|
||||||
import com.kunzisoft.keepass.activities.stylish.Stylish
|
|
||||||
import com.kunzisoft.keepass.app.database.CipherDatabaseAction
|
|
||||||
import com.kunzisoft.keepass.app.database.FileDatabaseHistoryAction
|
|
||||||
import com.kunzisoft.keepass.biometric.BiometricUnlockDatabaseHelper
|
|
||||||
import com.kunzisoft.keepass.crypto.keyDerivation.KdfEngine
|
|
||||||
import com.kunzisoft.keepass.database.element.Database
|
|
||||||
import com.kunzisoft.keepass.database.element.PwCompressionAlgorithm
|
|
||||||
import com.kunzisoft.keepass.database.element.PwEncryptionAlgorithm
|
|
||||||
import com.kunzisoft.keepass.education.Education
|
|
||||||
import com.kunzisoft.keepass.icons.IconPackChooser
|
|
||||||
import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_SAVE_COLOR_TASK
|
|
||||||
import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_SAVE_COMPRESSION_TASK
|
|
||||||
import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_SAVE_DEFAULT_USERNAME_TASK
|
|
||||||
import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_SAVE_DESCRIPTION_TASK
|
|
||||||
import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_SAVE_ENCRYPTION_TASK
|
|
||||||
import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_SAVE_ITERATIONS_TASK
|
|
||||||
import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_SAVE_KEY_DERIVATION_TASK
|
|
||||||
import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_SAVE_MAX_HISTORY_ITEMS_TASK
|
|
||||||
import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_SAVE_MAX_HISTORY_SIZE_TASK
|
|
||||||
import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_SAVE_MEMORY_USAGE_TASK
|
|
||||||
import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_SAVE_NAME_TASK
|
|
||||||
import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_SAVE_PARALLELISM_TASK
|
|
||||||
import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.NEW_ELEMENT_KEY
|
|
||||||
import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.OLD_ELEMENT_KEY
|
|
||||||
import com.kunzisoft.keepass.settings.preference.*
|
|
||||||
import com.kunzisoft.keepass.settings.preference.DialogColorPreference.Companion.DISABLE_COLOR
|
|
||||||
import com.kunzisoft.keepass.settings.preferencedialogfragment.*
|
|
||||||
import com.kunzisoft.keepass.tasks.ActionRunnable
|
import com.kunzisoft.keepass.tasks.ActionRunnable
|
||||||
import com.kunzisoft.keepass.utils.UriUtil
|
|
||||||
|
|
||||||
class NestedSettingsFragment : PreferenceFragmentCompat() {
|
abstract class NestedSettingsFragment : PreferenceFragmentCompat() {
|
||||||
|
|
||||||
private var mDatabase: Database = Database.getInstance()
|
|
||||||
private var mDatabaseReadOnly: Boolean = false
|
|
||||||
|
|
||||||
private var mCount = 0
|
|
||||||
|
|
||||||
private var dbNamePref: InputTextPreference? = null
|
|
||||||
private var dbDescriptionPref: InputTextPreference? = null
|
|
||||||
private var dbDefaultUsername: InputTextPreference? = null
|
|
||||||
private var dbCustomColorPref: DialogColorPreference? = null
|
|
||||||
private var dbDataCompressionPref: Preference? = null
|
|
||||||
private var recycleBinGroupPref: Preference? = null
|
|
||||||
private var dbMaxHistoryItemsPref: InputNumberPreference? = null
|
|
||||||
private var dbMaxHistorySizePref: InputNumberPreference? = null
|
|
||||||
private var mEncryptionAlgorithmPref: DialogListExplanationPreference? = null
|
|
||||||
private var mKeyDerivationPref: DialogListExplanationPreference? = null
|
|
||||||
private var mRoundPref: InputKdfNumberPreference? = null
|
|
||||||
private var mMemoryPref: InputKdfNumberPreference? = null
|
|
||||||
private var mParallelismPref: InputKdfNumberPreference? = null
|
|
||||||
|
|
||||||
enum class Screen {
|
enum class Screen {
|
||||||
APPLICATION, FORM_FILLING, ADVANCED_UNLOCK, APPEARANCE, DATABASE, DATABASE_SECURITY, DATABASE_MASTER_KEY
|
APPLICATION, FORM_FILLING, ADVANCED_UNLOCK, APPEARANCE, DATABASE, DATABASE_SECURITY, DATABASE_MASTER_KEY
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onResume() {
|
|
||||||
super.onResume()
|
|
||||||
|
|
||||||
activity?.let { activity ->
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
|
||||||
val autoFillEnablePreference: SwitchPreference? = findPreference(getString(R.string.settings_autofill_enable_key))
|
|
||||||
if (autoFillEnablePreference != null) {
|
|
||||||
val autofillManager = activity.getSystemService(AutofillManager::class.java)
|
|
||||||
autoFillEnablePreference.isChecked = autofillManager != null
|
|
||||||
&& autofillManager.hasEnabledAutofillServices()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
||||||
|
|
||||||
var key = 0
|
var key = 0
|
||||||
if (arguments != null)
|
if (arguments != null)
|
||||||
key = arguments!!.getInt(TAG_KEY)
|
key = arguments!!.getInt(TAG_KEY)
|
||||||
|
|
||||||
mDatabaseReadOnly = mDatabase.isReadOnly
|
onCreateScreenPreference(Screen.values()[key], savedInstanceState, rootKey)
|
||||||
|| ReadOnlyHelper.retrieveReadOnlyFromInstanceStateOrArguments(savedInstanceState, arguments)
|
|
||||||
|
|
||||||
// Load the preferences from an XML resource
|
|
||||||
when (Screen.values()[key]) {
|
|
||||||
Screen.APPLICATION -> {
|
|
||||||
onCreateApplicationPreferences(rootKey)
|
|
||||||
}
|
|
||||||
Screen.FORM_FILLING -> {
|
|
||||||
onCreateFormFillingPreference(rootKey)
|
|
||||||
}
|
|
||||||
Screen.ADVANCED_UNLOCK -> {
|
|
||||||
onCreateAdvancedUnlockPreferences(rootKey)
|
|
||||||
}
|
|
||||||
Screen.APPEARANCE -> {
|
|
||||||
onCreateAppearancePreferences(rootKey)
|
|
||||||
}
|
|
||||||
Screen.DATABASE -> {
|
|
||||||
onCreateDatabasePreference(rootKey)
|
|
||||||
}
|
|
||||||
Screen.DATABASE_SECURITY -> {
|
|
||||||
onCreateDatabaseSecurityPreference(rootKey)
|
|
||||||
}
|
|
||||||
Screen.DATABASE_MASTER_KEY -> {
|
|
||||||
onCreateDatabaseMasterKeyPreference(rootKey)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun onCreateApplicationPreferences(rootKey: String?) {
|
abstract fun onCreateScreenPreference(screen: Screen, savedInstanceState: Bundle?, rootKey: String?)
|
||||||
setPreferencesFromResource(R.xml.preferences_application, rootKey)
|
|
||||||
|
|
||||||
activity?.let { activity ->
|
open fun onProgressDialogThreadResult(actionTask: String,
|
||||||
allowCopyPassword()
|
result: ActionRunnable.Result) {}
|
||||||
|
|
||||||
findPreference<Preference>(getString(R.string.keyfile_key))?.setOnPreferenceChangeListener { _, newValue ->
|
protected fun preferenceInDevelopment(preferenceInDev: Preference) {
|
||||||
if (!(newValue as Boolean)) {
|
|
||||||
FileDatabaseHistoryAction.getInstance(activity.applicationContext).deleteAllKeyFiles()
|
|
||||||
}
|
|
||||||
true
|
|
||||||
}
|
|
||||||
|
|
||||||
findPreference<Preference>(getString(R.string.recentfile_key))?.setOnPreferenceChangeListener { _, newValue ->
|
|
||||||
if (!(newValue as Boolean)) {
|
|
||||||
FileDatabaseHistoryAction.getInstance(activity.applicationContext).deleteAll()
|
|
||||||
}
|
|
||||||
true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun onCreateFormFillingPreference(rootKey: String?) {
|
|
||||||
setPreferencesFromResource(R.xml.preferences_form_filling, rootKey)
|
|
||||||
|
|
||||||
activity?.let { activity ->
|
|
||||||
val autoFillEnablePreference: SwitchPreference? = findPreference(getString(R.string.settings_autofill_enable_key))
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
|
||||||
val autofillManager = activity.getSystemService(AutofillManager::class.java)
|
|
||||||
if (autofillManager != null && autofillManager.hasEnabledAutofillServices())
|
|
||||||
autoFillEnablePreference?.isChecked = autofillManager.hasEnabledAutofillServices()
|
|
||||||
autoFillEnablePreference?.onPreferenceClickListener = object : Preference.OnPreferenceClickListener {
|
|
||||||
@RequiresApi(api = Build.VERSION_CODES.O)
|
|
||||||
override fun onPreferenceClick(preference: Preference): Boolean {
|
|
||||||
if ((preference as SwitchPreference).isChecked) {
|
|
||||||
try {
|
|
||||||
startEnableService()
|
|
||||||
} catch (e: ActivityNotFoundException) {
|
|
||||||
val error = getString(R.string.error_autofill_enable_service)
|
|
||||||
preference.isChecked = false
|
|
||||||
Log.d(javaClass.name, error, e)
|
|
||||||
Toast.makeText(context, error, Toast.LENGTH_SHORT).show()
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
disableService()
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
@RequiresApi(api = Build.VERSION_CODES.O)
|
|
||||||
private fun disableService() {
|
|
||||||
if (autofillManager != null && autofillManager.hasEnabledAutofillServices()) {
|
|
||||||
autofillManager.disableAutofillServices()
|
|
||||||
} else {
|
|
||||||
Log.d(javaClass.name, "Sample service already disabled.")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@RequiresApi(api = Build.VERSION_CODES.O)
|
|
||||||
@Throws(ActivityNotFoundException::class)
|
|
||||||
private fun startEnableService() {
|
|
||||||
if (autofillManager != null && !autofillManager.hasEnabledAutofillServices()) {
|
|
||||||
val intent = Intent(Settings.ACTION_REQUEST_SET_AUTOFILL_SERVICE)
|
|
||||||
// TODO Autofill
|
|
||||||
intent.data = Uri.parse("package:com.example.android.autofill.service")
|
|
||||||
Log.d(javaClass.name, "enableService(): intent=$intent")
|
|
||||||
startActivityForResult(intent, REQUEST_CODE_AUTOFILL)
|
|
||||||
} else {
|
|
||||||
Log.d(javaClass.name, "Sample service already enabled.")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
autoFillEnablePreference?.setOnPreferenceClickListener { preference ->
|
|
||||||
(preference as SwitchPreference).isChecked = false
|
|
||||||
val fragmentManager = fragmentManager!!
|
|
||||||
UnavailableFeatureDialogFragment.getInstance(Build.VERSION_CODES.O)
|
|
||||||
.show(fragmentManager, "unavailableFeatureDialog")
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
findPreference<Preference>(getString(R.string.magic_keyboard_explanation_key))?.setOnPreferenceClickListener {
|
|
||||||
UriUtil.gotoUrl(context!!, R.string.magic_keyboard_explanation_url)
|
|
||||||
false
|
|
||||||
}
|
|
||||||
|
|
||||||
findPreference<Preference>(getString(R.string.magic_keyboard_key))?.setOnPreferenceClickListener {
|
|
||||||
startActivity(Intent(Settings.ACTION_INPUT_METHOD_SETTINGS).apply {
|
|
||||||
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
|
||||||
})
|
|
||||||
false
|
|
||||||
}
|
|
||||||
|
|
||||||
findPreference<Preference>(getString(R.string.magic_keyboard_preference_key))?.setOnPreferenceClickListener {
|
|
||||||
startActivity(Intent(context, MagikIMESettings::class.java))
|
|
||||||
false
|
|
||||||
}
|
|
||||||
|
|
||||||
findPreference<Preference>(getString(R.string.clipboard_explanation_key))?.setOnPreferenceClickListener {
|
|
||||||
UriUtil.gotoUrl(context!!, R.string.clipboard_explanation_url)
|
|
||||||
false
|
|
||||||
}
|
|
||||||
|
|
||||||
findPreference<Preference>(getString(R.string.autofill_explanation_key))?.setOnPreferenceClickListener {
|
|
||||||
UriUtil.gotoUrl(context!!, R.string.autofill_explanation_url)
|
|
||||||
false
|
|
||||||
}
|
|
||||||
|
|
||||||
// Present in two places
|
|
||||||
allowCopyPassword()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun onCreateAdvancedUnlockPreferences(rootKey: String?) {
|
|
||||||
setPreferencesFromResource(R.xml.preferences_advanced_unlock, rootKey)
|
|
||||||
|
|
||||||
activity?.let { activity ->
|
|
||||||
val biometricUnlockEnablePreference: SwitchPreference? = findPreference(getString(R.string.biometric_unlock_enable_key))
|
|
||||||
// < M solve verifyError exception
|
|
||||||
var biometricUnlockSupported = false
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
|
||||||
val biometricCanAuthenticate = BiometricManager.from(activity).canAuthenticate()
|
|
||||||
biometricUnlockSupported = biometricCanAuthenticate == BiometricManager.BIOMETRIC_ERROR_NONE_ENROLLED
|
|
||||||
|| biometricCanAuthenticate == BiometricManager.BIOMETRIC_SUCCESS
|
|
||||||
}
|
|
||||||
if (!biometricUnlockSupported) {
|
|
||||||
// False if under Marshmallow
|
|
||||||
biometricUnlockEnablePreference?.apply {
|
|
||||||
isChecked = false
|
|
||||||
setOnPreferenceClickListener { preference ->
|
|
||||||
fragmentManager?.let { fragmentManager ->
|
|
||||||
(preference as SwitchPreference).isChecked = false
|
|
||||||
UnavailableFeatureDialogFragment.getInstance(Build.VERSION_CODES.M)
|
|
||||||
.show(fragmentManager, "unavailableFeatureDialog")
|
|
||||||
}
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val deleteKeysFingerprints: Preference? = findPreference(getString(R.string.biometric_delete_all_key_key))
|
|
||||||
if (!biometricUnlockSupported) {
|
|
||||||
deleteKeysFingerprints?.isEnabled = false
|
|
||||||
} else {
|
|
||||||
deleteKeysFingerprints?.setOnPreferenceClickListener {
|
|
||||||
context?.let { context ->
|
|
||||||
AlertDialog.Builder(context)
|
|
||||||
.setMessage(resources.getString(R.string.biometric_delete_all_key_warning))
|
|
||||||
.setIcon(android.R.drawable.ic_dialog_alert)
|
|
||||||
.setPositiveButton(resources.getString(android.R.string.yes)
|
|
||||||
) { _, _ ->
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
|
||||||
BiometricUnlockDatabaseHelper.deleteEntryKeyInKeystoreForBiometric(
|
|
||||||
activity,
|
|
||||||
object : BiometricUnlockDatabaseHelper.BiometricUnlockErrorCallback {
|
|
||||||
override fun onInvalidKeyException(e: Exception) {}
|
|
||||||
|
|
||||||
override fun onBiometricException(e: Exception) {
|
|
||||||
Toast.makeText(context,
|
|
||||||
getString(R.string.biometric_scanning_error, e.localizedMessage),
|
|
||||||
Toast.LENGTH_SHORT).show()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
CipherDatabaseAction.getInstance(context.applicationContext).deleteAll()
|
|
||||||
}
|
|
||||||
.setNegativeButton(resources.getString(android.R.string.no))
|
|
||||||
{ _, _ -> }.show()
|
|
||||||
}
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
findPreference<Preference>(getString(R.string.advanced_unlock_explanation_key))?.setOnPreferenceClickListener {
|
|
||||||
UriUtil.gotoUrl(context!!, R.string.advanced_unlock_explanation_url)
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun onCreateAppearancePreferences(rootKey: String?) {
|
|
||||||
setPreferencesFromResource(R.xml.preferences_appearance, rootKey)
|
|
||||||
|
|
||||||
activity?.let { activity ->
|
|
||||||
findPreference<ListPreference>(getString(R.string.setting_style_key))?.setOnPreferenceChangeListener { _, newValue ->
|
|
||||||
var styleEnabled = true
|
|
||||||
val styleIdString = newValue as String
|
|
||||||
if (BuildConfig.CLOSED_STORE || !Education.isEducationScreenReclickedPerformed(context!!))
|
|
||||||
for (themeIdDisabled in BuildConfig.STYLES_DISABLED) {
|
|
||||||
if (themeIdDisabled == styleIdString) {
|
|
||||||
styleEnabled = false
|
|
||||||
fragmentManager?.let { fragmentManager ->
|
|
||||||
ProFeatureDialogFragment().show(fragmentManager, "pro_feature_dialog")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (styleEnabled) {
|
|
||||||
Stylish.assignStyle(styleIdString)
|
|
||||||
activity.recreate()
|
|
||||||
}
|
|
||||||
styleEnabled
|
|
||||||
}
|
|
||||||
|
|
||||||
findPreference<IconPackListPreference>(getString(R.string.setting_icon_pack_choose_key))?.setOnPreferenceChangeListener { _, newValue ->
|
|
||||||
var iconPackEnabled = true
|
|
||||||
val iconPackId = newValue as String
|
|
||||||
if (BuildConfig.CLOSED_STORE || !Education.isEducationScreenReclickedPerformed(context!!))
|
|
||||||
for (iconPackIdDisabled in BuildConfig.ICON_PACKS_DISABLED) {
|
|
||||||
if (iconPackIdDisabled == iconPackId) {
|
|
||||||
iconPackEnabled = false
|
|
||||||
fragmentManager?.let { fragmentManager ->
|
|
||||||
ProFeatureDialogFragment().show(fragmentManager, "pro_feature_dialog")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (iconPackEnabled) {
|
|
||||||
IconPackChooser.setSelectedIconPack(iconPackId)
|
|
||||||
}
|
|
||||||
iconPackEnabled
|
|
||||||
}
|
|
||||||
|
|
||||||
findPreference<Preference>(getString(R.string.reset_education_screens_key))?.setOnPreferenceClickListener {
|
|
||||||
// To allow only one toast
|
|
||||||
if (mCount == 0) {
|
|
||||||
val sharedPreferences = Education.getEducationSharedPreferences(context!!)
|
|
||||||
val editor = sharedPreferences.edit()
|
|
||||||
for (resourceId in Education.educationResourcesKeys) {
|
|
||||||
editor.putBoolean(getString(resourceId), false)
|
|
||||||
}
|
|
||||||
editor.apply()
|
|
||||||
Toast.makeText(context, R.string.reset_education_screens_text, Toast.LENGTH_SHORT).show()
|
|
||||||
}
|
|
||||||
mCount++
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun onCreateDatabasePreference(rootKey: String?) {
|
|
||||||
setPreferencesFromResource(R.xml.preferences_database, rootKey)
|
|
||||||
|
|
||||||
if (mDatabase.loaded) {
|
|
||||||
|
|
||||||
val dbGeneralPrefCategory: PreferenceCategory? = findPreference(getString(R.string.database_category_general_key))
|
|
||||||
|
|
||||||
// Database name
|
|
||||||
dbNamePref = findPreference(getString(R.string.database_name_key))
|
|
||||||
if (mDatabase.allowName) {
|
|
||||||
dbNamePref?.summary = mDatabase.name
|
|
||||||
} else {
|
|
||||||
dbGeneralPrefCategory?.removePreference(dbNamePref)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Database description
|
|
||||||
dbDescriptionPref = findPreference(getString(R.string.database_description_key))
|
|
||||||
if (mDatabase.allowDescription) {
|
|
||||||
dbDescriptionPref?.summary = mDatabase.description
|
|
||||||
} else {
|
|
||||||
dbGeneralPrefCategory?.removePreference(dbDescriptionPref)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Database default username
|
|
||||||
dbDefaultUsername = findPreference(getString(R.string.database_default_username_key))
|
|
||||||
if (mDatabase.allowDefaultUsername) {
|
|
||||||
dbDefaultUsername?.summary = mDatabase.defaultUsername
|
|
||||||
} else {
|
|
||||||
dbDefaultUsername?.isEnabled = false
|
|
||||||
// TODO dbGeneralPrefCategory?.removePreference(dbDefaultUsername)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Database custom color
|
|
||||||
dbCustomColorPref = findPreference(getString(R.string.database_custom_color_key))
|
|
||||||
if (mDatabase.allowCustomColor) {
|
|
||||||
dbCustomColorPref?.apply {
|
|
||||||
try {
|
|
||||||
color = Color.parseColor(mDatabase.customColor)
|
|
||||||
summary = mDatabase.customColor
|
|
||||||
} catch (e: Exception) {
|
|
||||||
color = DISABLE_COLOR
|
|
||||||
summary = ""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
dbCustomColorPref?.isEnabled = false
|
|
||||||
// TODO dbGeneralPrefCategory?.removePreference(dbCustomColorPref)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Version
|
|
||||||
findPreference<Preference>(getString(R.string.database_version_key))
|
|
||||||
?.summary = mDatabase.version
|
|
||||||
|
|
||||||
val dbCompressionPrefCategory: PreferenceCategory? = findPreference(getString(R.string.database_category_compression_key))
|
|
||||||
|
|
||||||
// Database compression
|
|
||||||
dbDataCompressionPref = findPreference(getString(R.string.database_data_compression_key))
|
|
||||||
if (mDatabase.allowDataCompression) {
|
|
||||||
dbDataCompressionPref?.summary = (mDatabase.compressionAlgorithm
|
|
||||||
?: PwCompressionAlgorithm.None).getName(resources)
|
|
||||||
} else {
|
|
||||||
dbCompressionPrefCategory?.isVisible = false
|
|
||||||
}
|
|
||||||
|
|
||||||
val dbRecycleBinPrefCategory: PreferenceCategory? = findPreference(getString(R.string.database_category_recycle_bin_key))
|
|
||||||
recycleBinGroupPref = findPreference(getString(R.string.recycle_bin_group_key))
|
|
||||||
|
|
||||||
// Recycle bin
|
|
||||||
if (mDatabase.allowRecycleBin) {
|
|
||||||
val recycleBinEnablePref: SwitchPreference? = findPreference(getString(R.string.recycle_bin_enable_key))
|
|
||||||
recycleBinEnablePref?.apply {
|
|
||||||
isChecked = mDatabase.isRecycleBinEnabled
|
|
||||||
isEnabled = if (!mDatabaseReadOnly) {
|
|
||||||
setOnPreferenceChangeListener { _, newValue ->
|
|
||||||
val recycleBinEnabled = newValue as Boolean
|
|
||||||
mDatabase.isRecycleBinEnabled = recycleBinEnabled
|
|
||||||
if (recycleBinEnabled) {
|
|
||||||
mDatabase.ensureRecycleBinExists(resources)
|
|
||||||
} else {
|
|
||||||
mDatabase.removeRecycleBin()
|
|
||||||
}
|
|
||||||
refreshRecycleBinGroup()
|
|
||||||
// Save the database if not in readonly mode
|
|
||||||
(context as SettingsActivity?)?.progressDialogThread?.startDatabaseSave(true)
|
|
||||||
true
|
|
||||||
}
|
|
||||||
true
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Recycle Bin group
|
|
||||||
refreshRecycleBinGroup()
|
|
||||||
} else {
|
|
||||||
dbRecycleBinPrefCategory?.isVisible = false
|
|
||||||
}
|
|
||||||
|
|
||||||
// History
|
|
||||||
findPreference<PreferenceCategory>(getString(R.string.database_category_history_key))
|
|
||||||
?.isVisible = mDatabase.manageHistory == true
|
|
||||||
|
|
||||||
// Max history items
|
|
||||||
dbMaxHistoryItemsPref = findPreference<InputNumberPreference>(getString(R.string.max_history_items_key))?.apply {
|
|
||||||
summary = mDatabase.historyMaxItems.toString()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Max history size
|
|
||||||
dbMaxHistorySizePref = findPreference<InputNumberPreference>(getString(R.string.max_history_size_key))?.apply {
|
|
||||||
summary = mDatabase.historyMaxSize.toString()
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
Log.e(javaClass.name, "Database isn't ready")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun refreshRecycleBinGroup() {
|
|
||||||
recycleBinGroupPref?.apply {
|
|
||||||
if (mDatabase.isRecycleBinEnabled) {
|
|
||||||
summary = mDatabase.recycleBin?.title
|
|
||||||
isEnabled = true
|
|
||||||
} else {
|
|
||||||
summary = null
|
|
||||||
isEnabled = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun onCreateDatabaseSecurityPreference(rootKey: String?) {
|
|
||||||
setPreferencesFromResource(R.xml.preferences_database_security, rootKey)
|
|
||||||
|
|
||||||
if (mDatabase.loaded) {
|
|
||||||
// Encryption Algorithm
|
|
||||||
mEncryptionAlgorithmPref = findPreference<DialogListExplanationPreference>(getString(R.string.encryption_algorithm_key))?.apply {
|
|
||||||
summary = mDatabase.getEncryptionAlgorithmName(resources)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Key derivation function
|
|
||||||
mKeyDerivationPref = findPreference<DialogListExplanationPreference>(getString(R.string.key_derivation_function_key))?.apply {
|
|
||||||
summary = mDatabase.getKeyDerivationName(resources)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Round encryption
|
|
||||||
mRoundPref = findPreference<InputKdfNumberPreference>(getString(R.string.transform_rounds_key))?.apply {
|
|
||||||
summary = mDatabase.numberKeyEncryptionRounds.toString()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Memory Usage
|
|
||||||
mMemoryPref = findPreference<InputKdfNumberPreference>(getString(R.string.memory_usage_key))?.apply {
|
|
||||||
summary = mDatabase.memoryUsage.toString()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parallelism
|
|
||||||
mParallelismPref = findPreference<InputKdfNumberPreference>(getString(R.string.parallelism_key))?.apply {
|
|
||||||
summary = mDatabase.parallelism.toString()
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Log.e(javaClass.name, "Database isn't ready")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun onCreateDatabaseMasterKeyPreference(rootKey: String?) {
|
|
||||||
setPreferencesFromResource(R.xml.preferences_database_master_key, rootKey)
|
|
||||||
|
|
||||||
if (mDatabase.loaded) {
|
|
||||||
findPreference<Preference>(getString(R.string.settings_database_change_credentials_key))?.apply {
|
|
||||||
isEnabled = if (!mDatabaseReadOnly) {
|
|
||||||
onPreferenceClickListener = Preference.OnPreferenceClickListener {
|
|
||||||
fragmentManager?.let { fragmentManager ->
|
|
||||||
AssignMasterKeyDialogFragment.getInstance(mDatabase.allowNoMasterKey)
|
|
||||||
.show(fragmentManager, "passwordDialog")
|
|
||||||
}
|
|
||||||
false
|
|
||||||
}
|
|
||||||
true
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Log.e(javaClass.name, "Database isn't ready")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun allowCopyPassword() {
|
|
||||||
val copyPasswordPreference: SwitchPreference? = findPreference(getString(R.string.allow_copy_password_key))
|
|
||||||
copyPasswordPreference?.setOnPreferenceChangeListener { _, newValue ->
|
|
||||||
if (newValue as Boolean && context != null) {
|
|
||||||
val message = getString(R.string.allow_copy_password_warning) +
|
|
||||||
"\n\n" +
|
|
||||||
getString(R.string.clipboard_warning)
|
|
||||||
AlertDialog
|
|
||||||
.Builder(context!!)
|
|
||||||
.setMessage(message)
|
|
||||||
.create()
|
|
||||||
.apply {
|
|
||||||
setButton(AlertDialog.BUTTON_POSITIVE, getText(R.string.enable))
|
|
||||||
{ dialog, _ ->
|
|
||||||
dialog.dismiss()
|
|
||||||
}
|
|
||||||
setButton(AlertDialog.BUTTON_NEGATIVE, getText(R.string.disable))
|
|
||||||
{ dialog, _ ->
|
|
||||||
copyPasswordPreference.isChecked = false
|
|
||||||
dialog.dismiss()
|
|
||||||
}
|
|
||||||
show()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun preferenceInDevelopment(preferenceInDev: Preference) {
|
|
||||||
preferenceInDev.setOnPreferenceClickListener { preference ->
|
preferenceInDev.setOnPreferenceClickListener { preference ->
|
||||||
fragmentManager?.let { fragmentManager ->
|
fragmentManager?.let { fragmentManager ->
|
||||||
try { // don't check if we can
|
try { // don't check if we can
|
||||||
@@ -613,295 +62,22 @@ class NestedSettingsFragment : PreferenceFragmentCompat() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onStop() {
|
|
||||||
super.onStop()
|
|
||||||
activity?.let { activity ->
|
|
||||||
if (mCount == 10) {
|
|
||||||
Education.getEducationSharedPreferences(activity).edit()
|
|
||||||
.putBoolean(getString(R.string.education_screen_reclicked_key), true).apply()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private val colorSelectedListener: ((Boolean, Int)-> Unit)? = { enable, color ->
|
|
||||||
dbCustomColorPref?.summary = ChromaUtil.getFormattedColorString(color, false)
|
|
||||||
if (enable) {
|
|
||||||
dbCustomColorPref?.color = color
|
|
||||||
} else {
|
|
||||||
dbCustomColorPref?.color = DISABLE_COLOR
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
|
||||||
val view = super.onCreateView(inflater, container, savedInstanceState)
|
|
||||||
|
|
||||||
try {
|
|
||||||
// To reassign color listener after orientation change
|
|
||||||
val chromaDialog = fragmentManager?.findFragmentByTag(TAG_PREF_FRAGMENT) as DatabaseColorPreferenceDialogFragmentCompat?
|
|
||||||
chromaDialog?.onColorSelectedListener = colorSelectedListener
|
|
||||||
} catch (e: Exception) {}
|
|
||||||
|
|
||||||
return view
|
|
||||||
}
|
|
||||||
|
|
||||||
fun onProgressDialogThreadResult(actionTask: String,
|
|
||||||
result: ActionRunnable.Result) {
|
|
||||||
result.data?.let { data ->
|
|
||||||
if (data.containsKey(OLD_ELEMENT_KEY)
|
|
||||||
&& data.containsKey(NEW_ELEMENT_KEY)) {
|
|
||||||
when (actionTask) {
|
|
||||||
/*
|
|
||||||
--------
|
|
||||||
Main preferences
|
|
||||||
--------
|
|
||||||
*/
|
|
||||||
ACTION_DATABASE_SAVE_NAME_TASK -> {
|
|
||||||
val oldName = data.getString(OLD_ELEMENT_KEY)!!
|
|
||||||
val newName = data.getString(NEW_ELEMENT_KEY)!!
|
|
||||||
val nameToShow =
|
|
||||||
if (result.isSuccess) {
|
|
||||||
newName
|
|
||||||
} else {
|
|
||||||
mDatabase.name = oldName
|
|
||||||
oldName
|
|
||||||
}
|
|
||||||
dbNamePref?.summary = nameToShow
|
|
||||||
}
|
|
||||||
ACTION_DATABASE_SAVE_DESCRIPTION_TASK -> {
|
|
||||||
val oldDescription = data.getString(OLD_ELEMENT_KEY)!!
|
|
||||||
val newDescription = data.getString(NEW_ELEMENT_KEY)!!
|
|
||||||
val descriptionToShow =
|
|
||||||
if (result.isSuccess) {
|
|
||||||
newDescription
|
|
||||||
} else {
|
|
||||||
mDatabase.description = oldDescription
|
|
||||||
oldDescription
|
|
||||||
}
|
|
||||||
dbDescriptionPref?.summary = descriptionToShow
|
|
||||||
}
|
|
||||||
ACTION_DATABASE_SAVE_DEFAULT_USERNAME_TASK -> {
|
|
||||||
val oldDefaultUsername = data.getString(OLD_ELEMENT_KEY)!!
|
|
||||||
val newDefaultUsername = data.getString(NEW_ELEMENT_KEY)!!
|
|
||||||
val defaultUsernameToShow =
|
|
||||||
if (result.isSuccess) {
|
|
||||||
newDefaultUsername
|
|
||||||
} else {
|
|
||||||
mDatabase.defaultUsername = oldDefaultUsername
|
|
||||||
oldDefaultUsername
|
|
||||||
}
|
|
||||||
dbDefaultUsername?.summary = defaultUsernameToShow
|
|
||||||
}
|
|
||||||
ACTION_DATABASE_SAVE_COLOR_TASK -> {
|
|
||||||
val oldColor = data.getString(OLD_ELEMENT_KEY)!!
|
|
||||||
val newColor = data.getString(NEW_ELEMENT_KEY)!!
|
|
||||||
|
|
||||||
val defaultColorToShow =
|
|
||||||
if (result.isSuccess) {
|
|
||||||
newColor
|
|
||||||
} else {
|
|
||||||
mDatabase.customColor = oldColor
|
|
||||||
oldColor
|
|
||||||
}
|
|
||||||
dbCustomColorPref?.summary = defaultColorToShow
|
|
||||||
}
|
|
||||||
ACTION_DATABASE_SAVE_COMPRESSION_TASK -> {
|
|
||||||
val oldCompression = data.getSerializable(OLD_ELEMENT_KEY) as PwCompressionAlgorithm
|
|
||||||
val newCompression = data.getSerializable(NEW_ELEMENT_KEY) as PwCompressionAlgorithm
|
|
||||||
val algorithmToShow =
|
|
||||||
if (result.isSuccess) {
|
|
||||||
newCompression
|
|
||||||
} else {
|
|
||||||
mDatabase.compressionAlgorithm = oldCompression
|
|
||||||
oldCompression
|
|
||||||
}
|
|
||||||
dbDataCompressionPref?.summary = algorithmToShow.getName(resources)
|
|
||||||
}
|
|
||||||
ACTION_DATABASE_SAVE_MAX_HISTORY_ITEMS_TASK -> {
|
|
||||||
val oldMaxHistoryItems = data.getInt(OLD_ELEMENT_KEY)
|
|
||||||
val newMaxHistoryItems = data.getInt(NEW_ELEMENT_KEY)
|
|
||||||
val maxHistoryItemsToShow =
|
|
||||||
if (result.isSuccess) {
|
|
||||||
newMaxHistoryItems
|
|
||||||
} else {
|
|
||||||
mDatabase.historyMaxItems = oldMaxHistoryItems
|
|
||||||
oldMaxHistoryItems
|
|
||||||
}
|
|
||||||
dbMaxHistoryItemsPref?.summary = maxHistoryItemsToShow.toString()
|
|
||||||
}
|
|
||||||
ACTION_DATABASE_SAVE_MAX_HISTORY_SIZE_TASK -> {
|
|
||||||
val oldMaxHistorySize = data.getLong(OLD_ELEMENT_KEY)
|
|
||||||
val newMaxHistorySize = data.getLong(NEW_ELEMENT_KEY)
|
|
||||||
val maxHistorySizeToShow =
|
|
||||||
if (result.isSuccess) {
|
|
||||||
newMaxHistorySize
|
|
||||||
} else {
|
|
||||||
mDatabase.historyMaxSize = oldMaxHistorySize
|
|
||||||
oldMaxHistorySize
|
|
||||||
}
|
|
||||||
dbMaxHistorySizePref?.summary = maxHistorySizeToShow.toString()
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
--------
|
|
||||||
Security
|
|
||||||
--------
|
|
||||||
*/
|
|
||||||
ACTION_DATABASE_SAVE_ENCRYPTION_TASK -> {
|
|
||||||
val oldEncryption = data.getSerializable(OLD_ELEMENT_KEY) as PwEncryptionAlgorithm
|
|
||||||
val newEncryption = data.getSerializable(NEW_ELEMENT_KEY) as PwEncryptionAlgorithm
|
|
||||||
val algorithmToShow =
|
|
||||||
if (result.isSuccess) {
|
|
||||||
newEncryption
|
|
||||||
} else {
|
|
||||||
mDatabase.encryptionAlgorithm = oldEncryption
|
|
||||||
oldEncryption
|
|
||||||
}
|
|
||||||
mEncryptionAlgorithmPref?.summary = algorithmToShow.getName(resources)
|
|
||||||
}
|
|
||||||
ACTION_DATABASE_SAVE_KEY_DERIVATION_TASK -> {
|
|
||||||
val oldKeyDerivationEngine = data.getSerializable(OLD_ELEMENT_KEY) as KdfEngine
|
|
||||||
val newKeyDerivationEngine = data.getSerializable(NEW_ELEMENT_KEY) as KdfEngine
|
|
||||||
val kdfEngineToShow =
|
|
||||||
if (result.isSuccess) {
|
|
||||||
newKeyDerivationEngine
|
|
||||||
} else {
|
|
||||||
mDatabase.kdfEngine = oldKeyDerivationEngine
|
|
||||||
oldKeyDerivationEngine
|
|
||||||
}
|
|
||||||
mKeyDerivationPref?.summary = kdfEngineToShow.getName(resources)
|
|
||||||
|
|
||||||
mRoundPref?.summary = kdfEngineToShow.defaultKeyRounds.toString()
|
|
||||||
// Disable memory and parallelism if not available
|
|
||||||
mMemoryPref?.summary = kdfEngineToShow.defaultMemoryUsage.toString()
|
|
||||||
mParallelismPref?.summary = kdfEngineToShow.defaultParallelism.toString()
|
|
||||||
}
|
|
||||||
ACTION_DATABASE_SAVE_ITERATIONS_TASK -> {
|
|
||||||
val oldIterations = data.getLong(OLD_ELEMENT_KEY)
|
|
||||||
val newIterations = data.getLong(NEW_ELEMENT_KEY)
|
|
||||||
val roundsToShow =
|
|
||||||
if (result.isSuccess) {
|
|
||||||
newIterations
|
|
||||||
} else {
|
|
||||||
mDatabase.numberKeyEncryptionRounds = oldIterations
|
|
||||||
oldIterations
|
|
||||||
}
|
|
||||||
mRoundPref?.summary = roundsToShow.toString()
|
|
||||||
}
|
|
||||||
ACTION_DATABASE_SAVE_MEMORY_USAGE_TASK -> {
|
|
||||||
val oldMemoryUsage = data.getLong(OLD_ELEMENT_KEY)
|
|
||||||
val newMemoryUsage = data.getLong(NEW_ELEMENT_KEY)
|
|
||||||
val memoryToShow =
|
|
||||||
if (result.isSuccess) {
|
|
||||||
newMemoryUsage
|
|
||||||
} else {
|
|
||||||
mDatabase.memoryUsage = oldMemoryUsage
|
|
||||||
oldMemoryUsage
|
|
||||||
}
|
|
||||||
mMemoryPref?.summary = memoryToShow.toString()
|
|
||||||
}
|
|
||||||
ACTION_DATABASE_SAVE_PARALLELISM_TASK -> {
|
|
||||||
val oldParallelism = data.getInt(OLD_ELEMENT_KEY)
|
|
||||||
val newParallelism = data.getInt(NEW_ELEMENT_KEY)
|
|
||||||
val parallelismToShow =
|
|
||||||
if (result.isSuccess) {
|
|
||||||
newParallelism
|
|
||||||
} else {
|
|
||||||
mDatabase.parallelism = oldParallelism
|
|
||||||
oldParallelism
|
|
||||||
}
|
|
||||||
mParallelismPref?.summary = parallelismToShow.toString()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onDisplayPreferenceDialog(preference: Preference?) {
|
|
||||||
|
|
||||||
var otherDialogFragment = false
|
|
||||||
|
|
||||||
fragmentManager?.let { fragmentManager ->
|
|
||||||
preference?.let { preference ->
|
|
||||||
var dialogFragment: DialogFragment? = null
|
|
||||||
when {
|
|
||||||
// Main Preferences
|
|
||||||
preference.key == getString(R.string.database_name_key) -> {
|
|
||||||
dialogFragment = DatabaseNamePreferenceDialogFragmentCompat.newInstance(preference.key)
|
|
||||||
}
|
|
||||||
preference.key == getString(R.string.database_description_key) -> {
|
|
||||||
dialogFragment = DatabaseDescriptionPreferenceDialogFragmentCompat.newInstance(preference.key)
|
|
||||||
}
|
|
||||||
preference.key == getString(R.string.database_default_username_key) -> {
|
|
||||||
dialogFragment = DatabaseDefaultUsernamePreferenceDialogFragmentCompat.newInstance(preference.key)
|
|
||||||
}
|
|
||||||
preference.key == getString(R.string.database_custom_color_key) -> {
|
|
||||||
dialogFragment = DatabaseColorPreferenceDialogFragmentCompat.newInstance(preference.key).apply {
|
|
||||||
onColorSelectedListener = colorSelectedListener
|
|
||||||
}
|
|
||||||
}
|
|
||||||
preference.key == getString(R.string.database_data_compression_key) -> {
|
|
||||||
dialogFragment = DatabaseDataCompressionPreferenceDialogFragmentCompat.newInstance(preference.key)
|
|
||||||
}
|
|
||||||
preference.key == getString(R.string.max_history_items_key) -> {
|
|
||||||
dialogFragment = MaxHistoryItemsPreferenceDialogFragmentCompat.newInstance(preference.key)
|
|
||||||
}
|
|
||||||
preference.key == getString(R.string.max_history_size_key) -> {
|
|
||||||
dialogFragment = MaxHistorySizePreferenceDialogFragmentCompat.newInstance(preference.key)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Security
|
|
||||||
preference.key == getString(R.string.encryption_algorithm_key) -> {
|
|
||||||
dialogFragment = DatabaseEncryptionAlgorithmPreferenceDialogFragmentCompat.newInstance(preference.key)
|
|
||||||
}
|
|
||||||
preference.key == getString(R.string.key_derivation_function_key) -> {
|
|
||||||
val keyDerivationDialogFragment = DatabaseKeyDerivationPreferenceDialogFragmentCompat.newInstance(preference.key)
|
|
||||||
// Add other prefs to manage
|
|
||||||
keyDerivationDialogFragment.setRoundPreference(mRoundPref)
|
|
||||||
keyDerivationDialogFragment.setMemoryPreference(mMemoryPref)
|
|
||||||
keyDerivationDialogFragment.setParallelismPreference(mParallelismPref)
|
|
||||||
dialogFragment = keyDerivationDialogFragment
|
|
||||||
}
|
|
||||||
preference.key == getString(R.string.transform_rounds_key) -> {
|
|
||||||
dialogFragment = RoundsPreferenceDialogFragmentCompat.newInstance(preference.key)
|
|
||||||
}
|
|
||||||
preference.key == getString(R.string.memory_usage_key) -> {
|
|
||||||
dialogFragment = MemoryUsagePreferenceDialogFragmentCompat.newInstance(preference.key)
|
|
||||||
}
|
|
||||||
preference.key == getString(R.string.parallelism_key) -> {
|
|
||||||
dialogFragment = ParallelismPreferenceDialogFragmentCompat.newInstance(preference.key)
|
|
||||||
}
|
|
||||||
else -> otherDialogFragment = true
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dialogFragment != null && !mDatabaseReadOnly) {
|
|
||||||
dialogFragment.setTargetFragment(this, 0)
|
|
||||||
dialogFragment.show(fragmentManager, TAG_PREF_FRAGMENT)
|
|
||||||
}
|
|
||||||
// Could not be handled here. Try with the super method.
|
|
||||||
else if (otherDialogFragment) {
|
|
||||||
super.onDisplayPreferenceDialog(preference)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onSaveInstanceState(outState: Bundle) {
|
|
||||||
ReadOnlyHelper.onSaveInstanceState(outState, mDatabaseReadOnly)
|
|
||||||
super.onSaveInstanceState(outState)
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
private const val TAG_KEY = "NESTED_KEY"
|
private const val TAG_KEY = "NESTED_KEY"
|
||||||
|
|
||||||
private const val TAG_PREF_FRAGMENT = "TAG_PREF_FRAGMENT"
|
|
||||||
|
|
||||||
private const val REQUEST_CODE_AUTOFILL = 5201
|
|
||||||
|
|
||||||
@JvmOverloads
|
@JvmOverloads
|
||||||
fun newInstance(key: Screen, databaseReadOnly: Boolean = ReadOnlyHelper.READ_ONLY_DEFAULT)
|
fun newInstance(key: Screen, databaseReadOnly: Boolean = ReadOnlyHelper.READ_ONLY_DEFAULT)
|
||||||
: NestedSettingsFragment {
|
: NestedSettingsFragment {
|
||||||
val fragment = NestedSettingsFragment()
|
val fragment: NestedSettingsFragment = when (key) {
|
||||||
|
Screen.APPLICATION,
|
||||||
|
Screen.FORM_FILLING,
|
||||||
|
Screen.ADVANCED_UNLOCK,
|
||||||
|
Screen.APPEARANCE -> NestedAppSettingsFragment()
|
||||||
|
Screen.DATABASE,
|
||||||
|
Screen.DATABASE_SECURITY,
|
||||||
|
Screen.DATABASE_MASTER_KEY -> NestedDatabaseSettingsFragment()
|
||||||
|
}
|
||||||
// supply arguments to bundle.
|
// supply arguments to bundle.
|
||||||
val args = Bundle()
|
val args = Bundle()
|
||||||
args.putInt(TAG_KEY, key.ordinal)
|
args.putInt(TAG_KEY, key.ordinal)
|
||||||
|
|||||||
@@ -134,6 +134,12 @@ object PreferencesUtil {
|
|||||||
context.resources.getBoolean(R.bool.lock_database_back_root_default))
|
context.resources.getBoolean(R.bool.lock_database_back_root_default))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun isAutoSaveDatabaseEnabled(context: Context): Boolean {
|
||||||
|
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||||
|
return prefs.getBoolean(context.getString(R.string.enable_auto_save_database_key),
|
||||||
|
context.resources.getBoolean(R.bool.enable_auto_save_database_default))
|
||||||
|
}
|
||||||
|
|
||||||
fun isPersistentNotificationEnable(context: Context): Boolean {
|
fun isPersistentNotificationEnable(context: Context): Boolean {
|
||||||
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||||
return prefs.getBoolean(context.getString(R.string.persistent_notification_key),
|
return prefs.getBoolean(context.getString(R.string.persistent_notification_key),
|
||||||
|
|||||||
@@ -33,7 +33,6 @@ import com.kunzisoft.keepass.activities.dialogs.AssignMasterKeyDialogFragment
|
|||||||
import com.kunzisoft.keepass.activities.dialogs.PasswordEncodingDialogFragment
|
import com.kunzisoft.keepass.activities.dialogs.PasswordEncodingDialogFragment
|
||||||
import com.kunzisoft.keepass.activities.helpers.ReadOnlyHelper
|
import com.kunzisoft.keepass.activities.helpers.ReadOnlyHelper
|
||||||
import com.kunzisoft.keepass.activities.lock.LockingActivity
|
import com.kunzisoft.keepass.activities.lock.LockingActivity
|
||||||
import com.kunzisoft.keepass.database.action.ProgressDialogThread
|
|
||||||
import com.kunzisoft.keepass.database.element.Database
|
import com.kunzisoft.keepass.database.element.Database
|
||||||
import com.kunzisoft.keepass.timeout.TimeoutHelper
|
import com.kunzisoft.keepass.timeout.TimeoutHelper
|
||||||
|
|
||||||
@@ -46,8 +45,6 @@ open class SettingsActivity
|
|||||||
|
|
||||||
private var toolbar: Toolbar? = null
|
private var toolbar: Toolbar? = null
|
||||||
|
|
||||||
var progressDialogThread: ProgressDialogThread? = null
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
private const val TAG_NESTED = "TAG_NESTED"
|
private const val TAG_NESTED = "TAG_NESTED"
|
||||||
@@ -90,7 +87,7 @@ open class SettingsActivity
|
|||||||
|
|
||||||
backupManager = BackupManager(this)
|
backupManager = BackupManager(this)
|
||||||
|
|
||||||
progressDialogThread = ProgressDialogThread(this) { actionTask, result ->
|
mProgressDialogThread?.onActionFinish = { actionTask, result ->
|
||||||
// Call result in fragment
|
// Call result in fragment
|
||||||
(supportFragmentManager
|
(supportFragmentManager
|
||||||
.findFragmentByTag(TAG_NESTED) as NestedSettingsFragment?)
|
.findFragmentByTag(TAG_NESTED) as NestedSettingsFragment?)
|
||||||
@@ -98,19 +95,6 @@ open class SettingsActivity
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onResume() {
|
|
||||||
super.onResume()
|
|
||||||
|
|
||||||
progressDialogThread?.registerProgressTask()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onPause() {
|
|
||||||
|
|
||||||
progressDialogThread?.unregisterProgressTask()
|
|
||||||
|
|
||||||
super.onPause()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||||
when (item.itemId) {
|
when (item.itemId) {
|
||||||
android.R.id.home -> onBackPressed()
|
android.R.id.home -> onBackPressed()
|
||||||
@@ -132,7 +116,7 @@ open class SettingsActivity
|
|||||||
database.fileUri?.let { databaseUri ->
|
database.fileUri?.let { databaseUri ->
|
||||||
// Show the progress dialog now or after dialog confirmation
|
// Show the progress dialog now or after dialog confirmation
|
||||||
if (database.validatePasswordEncoding(masterPassword, keyFileChecked)) {
|
if (database.validatePasswordEncoding(masterPassword, keyFileChecked)) {
|
||||||
progressDialogThread?.startDatabaseAssignPassword(
|
mProgressDialogThread?.startDatabaseAssignPassword(
|
||||||
databaseUri,
|
databaseUri,
|
||||||
masterPasswordChecked,
|
masterPasswordChecked,
|
||||||
masterPassword,
|
masterPassword,
|
||||||
@@ -142,7 +126,7 @@ open class SettingsActivity
|
|||||||
} else {
|
} else {
|
||||||
PasswordEncodingDialogFragment().apply {
|
PasswordEncodingDialogFragment().apply {
|
||||||
positiveButtonClickListener = DialogInterface.OnClickListener { _, _ ->
|
positiveButtonClickListener = DialogInterface.OnClickListener { _, _ ->
|
||||||
progressDialogThread?.startDatabaseAssignPassword(
|
mProgressDialogThread?.startDatabaseAssignPassword(
|
||||||
databaseUri,
|
databaseUri,
|
||||||
masterPasswordChecked,
|
masterPasswordChecked,
|
||||||
masterPassword,
|
masterPassword,
|
||||||
|
|||||||
@@ -87,7 +87,7 @@ class DatabaseColorPreferenceDialogFragmentCompat : DatabaseSavePreferenceDialog
|
|||||||
}
|
}
|
||||||
val oldColor = database.customColor
|
val oldColor = database.customColor
|
||||||
database.customColor = newColor
|
database.customColor = newColor
|
||||||
progressDialogThread?.startDatabaseSaveColor(oldColor, newColor, true)
|
mProgressDialogThread?.startDatabaseSaveColor(oldColor, newColor, mDatabaseAutoSaveEnable)
|
||||||
}
|
}
|
||||||
|
|
||||||
onDialogClosed(true)
|
onDialogClosed(true)
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ class DatabaseDataCompressionPreferenceDialogFragmentCompat
|
|||||||
database.compressionAlgorithm = newCompression
|
database.compressionAlgorithm = newCompression
|
||||||
|
|
||||||
if (oldCompression != null && newCompression != null)
|
if (oldCompression != null && newCompression != null)
|
||||||
progressDialogThread?.startDatabaseSaveCompression(oldCompression, newCompression, true)
|
mProgressDialogThread?.startDatabaseSaveCompression(oldCompression, newCompression, mDatabaseAutoSaveEnable)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ class DatabaseDefaultUsernamePreferenceDialogFragmentCompat : DatabaseSavePrefer
|
|||||||
val newDefaultUsername = inputText
|
val newDefaultUsername = inputText
|
||||||
val oldDefaultUsername = database.defaultUsername
|
val oldDefaultUsername = database.defaultUsername
|
||||||
database.defaultUsername = newDefaultUsername
|
database.defaultUsername = newDefaultUsername
|
||||||
progressDialogThread?.startDatabaseSaveDefaultUsername(oldDefaultUsername, newDefaultUsername, true)
|
mProgressDialogThread?.startDatabaseSaveDefaultUsername(oldDefaultUsername, newDefaultUsername, mDatabaseAutoSaveEnable)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ class DatabaseDescriptionPreferenceDialogFragmentCompat : DatabaseSavePreference
|
|||||||
val newDescription = inputText
|
val newDescription = inputText
|
||||||
val oldDescription = database.description
|
val oldDescription = database.description
|
||||||
database.description = newDescription
|
database.description = newDescription
|
||||||
progressDialogThread?.startDatabaseSaveDescription(oldDescription, newDescription, true)
|
mProgressDialogThread?.startDatabaseSaveDescription(oldDescription, newDescription, mDatabaseAutoSaveEnable)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ class DatabaseEncryptionAlgorithmPreferenceDialogFragmentCompat
|
|||||||
database.encryptionAlgorithm = newAlgorithm
|
database.encryptionAlgorithm = newAlgorithm
|
||||||
|
|
||||||
if (oldAlgorithm != null && newAlgorithm != null)
|
if (oldAlgorithm != null && newAlgorithm != null)
|
||||||
progressDialogThread?.startDatabaseSaveEncryption(oldAlgorithm, newAlgorithm, true)
|
mProgressDialogThread?.startDatabaseSaveEncryption(oldAlgorithm, newAlgorithm, mDatabaseAutoSaveEnable)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ class DatabaseKeyDerivationPreferenceDialogFragmentCompat
|
|||||||
val oldKdfEngine = database.kdfEngine
|
val oldKdfEngine = database.kdfEngine
|
||||||
if (newKdfEngine != null && oldKdfEngine != null) {
|
if (newKdfEngine != null && oldKdfEngine != null) {
|
||||||
database.kdfEngine = newKdfEngine
|
database.kdfEngine = newKdfEngine
|
||||||
progressDialogThread?.startDatabaseSaveKeyDerivation(oldKdfEngine, newKdfEngine, true)
|
mProgressDialogThread?.startDatabaseSaveKeyDerivation(oldKdfEngine, newKdfEngine, mDatabaseAutoSaveEnable)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ class DatabaseNamePreferenceDialogFragmentCompat : DatabaseSavePreferenceDialogF
|
|||||||
val newName = inputText
|
val newName = inputText
|
||||||
val oldName = database.name
|
val oldName = database.name
|
||||||
database.name = newName
|
database.name = newName
|
||||||
progressDialogThread?.startDatabaseSaveName(oldName, newName, true)
|
mProgressDialogThread?.startDatabaseSaveName(oldName, newName, mDatabaseAutoSaveEnable)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,13 +23,14 @@ import android.content.Context
|
|||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import com.kunzisoft.keepass.database.action.ProgressDialogThread
|
import com.kunzisoft.keepass.database.action.ProgressDialogThread
|
||||||
import com.kunzisoft.keepass.database.element.Database
|
import com.kunzisoft.keepass.database.element.Database
|
||||||
|
import com.kunzisoft.keepass.settings.PreferencesUtil
|
||||||
import com.kunzisoft.keepass.settings.SettingsActivity
|
import com.kunzisoft.keepass.settings.SettingsActivity
|
||||||
|
|
||||||
abstract class DatabaseSavePreferenceDialogFragmentCompat : InputPreferenceDialogFragmentCompat() {
|
abstract class DatabaseSavePreferenceDialogFragmentCompat : InputPreferenceDialogFragmentCompat() {
|
||||||
|
|
||||||
protected var database: Database? = null
|
protected var database: Database? = null
|
||||||
|
protected var mDatabaseAutoSaveEnable = true
|
||||||
protected var progressDialogThread: ProgressDialogThread? = null
|
protected var mProgressDialogThread: ProgressDialogThread? = null
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
@@ -41,8 +42,10 @@ abstract class DatabaseSavePreferenceDialogFragmentCompat : InputPreferenceDialo
|
|||||||
super.onAttach(context)
|
super.onAttach(context)
|
||||||
// Attach dialog thread to start action
|
// Attach dialog thread to start action
|
||||||
if (context is SettingsActivity) {
|
if (context is SettingsActivity) {
|
||||||
progressDialogThread = context.progressDialogThread
|
mProgressDialogThread = context.mProgressDialogThread
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.mDatabaseAutoSaveEnable = PreferencesUtil.isAutoSaveDatabaseEnabled(context)
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ class MaxHistoryItemsPreferenceDialogFragmentCompat : DatabaseSavePreferenceDial
|
|||||||
// Remove all history items
|
// Remove all history items
|
||||||
database.removeOldestHistoryForEachEntry()
|
database.removeOldestHistoryForEachEntry()
|
||||||
|
|
||||||
progressDialogThread?.startDatabaseSaveMaxHistoryItems(oldMaxHistoryItems, maxHistoryItems, true)
|
mProgressDialogThread?.startDatabaseSaveMaxHistoryItems(oldMaxHistoryItems, maxHistoryItems, mDatabaseAutoSaveEnable)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ class MaxHistorySizePreferenceDialogFragmentCompat : DatabaseSavePreferenceDialo
|
|||||||
val oldMaxHistorySize = database.historyMaxSize
|
val oldMaxHistorySize = database.historyMaxSize
|
||||||
database.historyMaxSize = maxHistorySize
|
database.historyMaxSize = maxHistorySize
|
||||||
|
|
||||||
progressDialogThread?.startDatabaseSaveMaxHistorySize(oldMaxHistorySize, maxHistorySize, true)
|
mProgressDialogThread?.startDatabaseSaveMaxHistorySize(oldMaxHistorySize, maxHistorySize, mDatabaseAutoSaveEnable)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ class MemoryUsagePreferenceDialogFragmentCompat : DatabaseSavePreferenceDialogFr
|
|||||||
val oldMemoryUsage = database.memoryUsage
|
val oldMemoryUsage = database.memoryUsage
|
||||||
database.memoryUsage = memoryUsage
|
database.memoryUsage = memoryUsage
|
||||||
|
|
||||||
progressDialogThread?.startDatabaseSaveMemoryUsage(oldMemoryUsage, memoryUsage, true)
|
mProgressDialogThread?.startDatabaseSaveMemoryUsage(oldMemoryUsage, memoryUsage, mDatabaseAutoSaveEnable)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ class ParallelismPreferenceDialogFragmentCompat : DatabaseSavePreferenceDialogFr
|
|||||||
val oldParallelism = database.parallelism
|
val oldParallelism = database.parallelism
|
||||||
database.parallelism = parallelism
|
database.parallelism = parallelism
|
||||||
|
|
||||||
progressDialogThread?.startDatabaseSaveParallelism(oldParallelism, parallelism, true)
|
mProgressDialogThread?.startDatabaseSaveParallelism(oldParallelism, parallelism, mDatabaseAutoSaveEnable)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ class RoundsPreferenceDialogFragmentCompat : DatabaseSavePreferenceDialogFragmen
|
|||||||
database.numberKeyEncryptionRounds = Long.MAX_VALUE
|
database.numberKeyEncryptionRounds = Long.MAX_VALUE
|
||||||
}
|
}
|
||||||
|
|
||||||
progressDialogThread?.startDatabaseSaveIterations(oldRounds, rounds, true)
|
mProgressDialogThread?.startDatabaseSaveIterations(oldRounds, rounds, mDatabaseAutoSaveEnable)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,6 +19,8 @@
|
|||||||
*/
|
*/
|
||||||
package com.kunzisoft.keepass.utils
|
package com.kunzisoft.keepass.utils
|
||||||
|
|
||||||
|
import android.app.Activity
|
||||||
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.view.Menu
|
import android.view.Menu
|
||||||
import android.view.MenuInflater
|
import android.view.MenuInflater
|
||||||
@@ -27,10 +29,8 @@ import com.kunzisoft.keepass.BuildConfig
|
|||||||
import com.kunzisoft.keepass.R
|
import com.kunzisoft.keepass.R
|
||||||
import com.kunzisoft.keepass.activities.AboutActivity
|
import com.kunzisoft.keepass.activities.AboutActivity
|
||||||
import com.kunzisoft.keepass.activities.helpers.ReadOnlyHelper.READ_ONLY_DEFAULT
|
import com.kunzisoft.keepass.activities.helpers.ReadOnlyHelper.READ_ONLY_DEFAULT
|
||||||
import com.kunzisoft.keepass.activities.stylish.StylishActivity
|
|
||||||
import com.kunzisoft.keepass.settings.SettingsActivity
|
import com.kunzisoft.keepass.settings.SettingsActivity
|
||||||
|
|
||||||
|
|
||||||
object MenuUtil {
|
object MenuUtil {
|
||||||
|
|
||||||
fun contributionMenuInflater(inflater: MenuInflater, menu: Menu) {
|
fun contributionMenuInflater(inflater: MenuInflater, menu: Menu) {
|
||||||
@@ -43,33 +43,33 @@ object MenuUtil {
|
|||||||
inflater.inflate(R.menu.default_menu, menu)
|
inflater.inflate(R.menu.default_menu, menu)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onContributionItemSelected(activity: StylishActivity) {
|
fun onContributionItemSelected(context: Context) {
|
||||||
UriUtil.gotoUrl(activity, R.string.contribution_url)
|
UriUtil.gotoUrl(context, R.string.contribution_url)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @param checkLock Check the time lock before launch settings in LockingActivity
|
* @param checkLock Check the time lock before launch settings in LockingActivity
|
||||||
*/
|
*/
|
||||||
@JvmOverloads
|
@JvmOverloads
|
||||||
fun onDefaultMenuOptionsItemSelected(activity: StylishActivity, item: MenuItem, readOnly: Boolean = READ_ONLY_DEFAULT, timeoutEnable: Boolean = false): Boolean {
|
fun onDefaultMenuOptionsItemSelected(activity: Activity,
|
||||||
|
item: MenuItem,
|
||||||
|
readOnly: Boolean = READ_ONLY_DEFAULT,
|
||||||
|
timeoutEnable: Boolean = false): Boolean {
|
||||||
when (item.itemId) {
|
when (item.itemId) {
|
||||||
R.id.menu_contribute -> {
|
R.id.menu_contribute -> {
|
||||||
onContributionItemSelected(activity)
|
onContributionItemSelected(activity)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
R.id.menu_app_settings -> {
|
R.id.menu_app_settings -> {
|
||||||
// To avoid flickering when launch settings in a LockingActivity
|
// To avoid flickering when launch settings in a LockingActivity
|
||||||
SettingsActivity.launch(activity, readOnly, timeoutEnable)
|
SettingsActivity.launch(activity, readOnly, timeoutEnable)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
R.id.menu_about -> {
|
R.id.menu_about -> {
|
||||||
val intent = Intent(activity, AboutActivity::class.java)
|
val intent = Intent(activity, AboutActivity::class.java)
|
||||||
activity.startActivity(intent)
|
activity.startActivity(intent)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> return true
|
else -> return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,4 +24,9 @@
|
|||||||
android:title="@string/menu_lock"
|
android:title="@string/menu_lock"
|
||||||
android:orderInCategory="81"
|
android:orderInCategory="81"
|
||||||
app:showAsAction="always" />
|
app:showAsAction="always" />
|
||||||
|
<item android:id="@+id/menu_save_database"
|
||||||
|
android:icon="@drawable/ic_save_white_24dp"
|
||||||
|
android:title="@string/menu_save_database"
|
||||||
|
android:orderInCategory="95"
|
||||||
|
app:showAsAction="ifRoom" />
|
||||||
</menu>
|
</menu>
|
||||||
@@ -63,10 +63,12 @@
|
|||||||
|
|
||||||
<string name="allow_no_password_key" translatable="false">allow_no_password_key</string>
|
<string name="allow_no_password_key" translatable="false">allow_no_password_key</string>
|
||||||
<bool name="allow_no_password_default" translatable="false">false</bool>
|
<bool name="allow_no_password_default" translatable="false">false</bool>
|
||||||
<string name="enable_read_only_key" translatable="false">enable_read_only_key</string>
|
|
||||||
<bool name="enable_read_only_default" translatable="false">false</bool>
|
|
||||||
<string name="delete_entered_password_key" translatable="false">delete_entered_password_key</string>
|
<string name="delete_entered_password_key" translatable="false">delete_entered_password_key</string>
|
||||||
<bool name="delete_entered_password_default" translatable="false">true</bool>
|
<bool name="delete_entered_password_default" translatable="false">true</bool>
|
||||||
|
<string name="enable_read_only_key" translatable="false">enable_read_only_key</string>
|
||||||
|
<bool name="enable_read_only_default" translatable="false">false</bool>
|
||||||
|
<string name="enable_auto_save_database_key" translatable="false">enable_auto_save_database_key</string>
|
||||||
|
<bool name="enable_auto_save_database_default" translatable="false">true</bool>
|
||||||
<string name="omitbackup_key" translatable="false">omitbackup</string>
|
<string name="omitbackup_key" translatable="false">omitbackup</string>
|
||||||
<bool name="omitbackup_default" translatable="false">true</bool>
|
<bool name="omitbackup_default" translatable="false">true</bool>
|
||||||
<string name="app_timeout_key" translatable="false">app_timeout_key</string>
|
<string name="app_timeout_key" translatable="false">app_timeout_key</string>
|
||||||
|
|||||||
@@ -176,6 +176,7 @@
|
|||||||
<string name="menu_cancel">Cancel</string>
|
<string name="menu_cancel">Cancel</string>
|
||||||
<string name="menu_hide_password">Hide password</string>
|
<string name="menu_hide_password">Hide password</string>
|
||||||
<string name="menu_lock">Lock database</string>
|
<string name="menu_lock">Lock database</string>
|
||||||
|
<string name="menu_save_database">Save database</string>
|
||||||
<string name="menu_open">Open</string>
|
<string name="menu_open">Open</string>
|
||||||
<string name="menu_search">Search</string>
|
<string name="menu_search">Search</string>
|
||||||
<string name="menu_showpass">Show password</string>
|
<string name="menu_showpass">Show password</string>
|
||||||
@@ -217,6 +218,7 @@
|
|||||||
<string name="parallelism">Parallelism</string>
|
<string name="parallelism">Parallelism</string>
|
||||||
<string name="parallelism_explanation">Degree of parallelism (i.e. number of threads) used by the key derivation function.</string>
|
<string name="parallelism_explanation">Degree of parallelism (i.e. number of threads) used by the key derivation function.</string>
|
||||||
<string name="saving_database">Saving database…</string>
|
<string name="saving_database">Saving database…</string>
|
||||||
|
<string name="command_execution">Executing the command…</string>
|
||||||
<string name="do_not_kill_app">Do not kill the app…</string>
|
<string name="do_not_kill_app">Do not kill the app…</string>
|
||||||
<string name="space">Space</string>
|
<string name="space">Space</string>
|
||||||
<string name="search_label">Search</string>
|
<string name="search_label">Search</string>
|
||||||
@@ -365,10 +367,12 @@
|
|||||||
<string name="keyboard_key_sound_title">Sound on keypress</string>
|
<string name="keyboard_key_sound_title">Sound on keypress</string>
|
||||||
<string name="allow_no_password_title">Allow no master key</string>
|
<string name="allow_no_password_title">Allow no master key</string>
|
||||||
<string name="allow_no_password_summary">Enable the \"Open\" button if no credentials are selected</string>
|
<string name="allow_no_password_summary">Enable the \"Open\" button if no credentials are selected</string>
|
||||||
<string name="enable_read_only_title">Write-protected</string>
|
|
||||||
<string name="enable_read_only_summary">Open your database read-only by default</string>
|
|
||||||
<string name="delete_entered_password_title">Delete password</string>
|
<string name="delete_entered_password_title">Delete password</string>
|
||||||
<string name="delete_entered_password_summary">Deletes the password entered after a connection attempt</string>
|
<string name="delete_entered_password_summary">Deletes the password entered after a connection attempt</string>
|
||||||
|
<string name="enable_read_only_title">Write-protected</string>
|
||||||
|
<string name="enable_read_only_summary">Open your database read-only by default</string>
|
||||||
|
<string name="enable_auto_save_database_title">Auto save database</string>
|
||||||
|
<string name="enable_auto_save_database_summary">Automatically save the database after an important action (only in \"Modifiable\" mode)</string>
|
||||||
<string name="enable_education_screens_title">Educational screens</string>
|
<string name="enable_education_screens_title">Educational screens</string>
|
||||||
<string name="enable_education_screens_summary">Highlight the elements to learn how the app works</string>
|
<string name="enable_education_screens_summary">Highlight the elements to learn how the app works</string>
|
||||||
<string name="reset_education_screens_title">Reset educational screens</string>
|
<string name="reset_education_screens_title">Reset educational screens</string>
|
||||||
|
|||||||
@@ -28,16 +28,21 @@
|
|||||||
android:title="@string/allow_no_password_title"
|
android:title="@string/allow_no_password_title"
|
||||||
android:summary="@string/allow_no_password_summary"
|
android:summary="@string/allow_no_password_summary"
|
||||||
android:defaultValue="@bool/allow_no_password_default"/>
|
android:defaultValue="@bool/allow_no_password_default"/>
|
||||||
|
<SwitchPreference
|
||||||
|
android:key="@string/delete_entered_password_key"
|
||||||
|
android:title="@string/delete_entered_password_title"
|
||||||
|
android:summary="@string/delete_entered_password_summary"
|
||||||
|
android:defaultValue="@bool/delete_entered_password_default"/>
|
||||||
<SwitchPreference
|
<SwitchPreference
|
||||||
android:key="@string/enable_read_only_key"
|
android:key="@string/enable_read_only_key"
|
||||||
android:title="@string/enable_read_only_title"
|
android:title="@string/enable_read_only_title"
|
||||||
android:summary="@string/enable_read_only_summary"
|
android:summary="@string/enable_read_only_summary"
|
||||||
android:defaultValue="@bool/enable_read_only_default"/>
|
android:defaultValue="@bool/enable_read_only_default"/>
|
||||||
<SwitchPreference
|
<SwitchPreference
|
||||||
android:key="@string/delete_entered_password_key"
|
android:key="@string/enable_auto_save_database_key"
|
||||||
android:title="@string/delete_entered_password_title"
|
android:title="@string/enable_auto_save_database_title"
|
||||||
android:summary="@string/delete_entered_password_summary"
|
android:summary="@string/enable_auto_save_database_summary"
|
||||||
android:defaultValue="@bool/delete_entered_password_default"/>
|
android:defaultValue="@bool/enable_auto_save_database_default"/>
|
||||||
|
|
||||||
</PreferenceCategory>
|
</PreferenceCategory>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user