diff --git a/app/build.gradle b/app/build.gradle index 79df083ee..d5a6eb523 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -6,7 +6,6 @@ apply plugin: 'kotlin-kapt' android { compileSdkVersion 32 buildToolsVersion "32.0.0" - ndkVersion "21.4.7075529" defaultConfig { applicationId "com.kunzisoft.keepass" @@ -129,11 +128,10 @@ dependencies { implementation 'commons-codec:commons-codec:1.15' // Password generator implementation 'me.gosimple:nbvcxz:1.5.0' - // Encrypt lib - implementation project(path: ':crypto') - // Icon pack - implementation project(path: ':icon-pack-classic') - implementation project(path: ':icon-pack-material') + + // Modules import + implementation project(path: ':database') + implementation project(path: ':icon-pack') // Tests androidTestImplementation "androidx.test:runner:$android_test_version" diff --git a/app/src/main/java/com/kunzisoft/keepass/activities/AboutActivity.kt b/app/src/main/java/com/kunzisoft/keepass/activities/AboutActivity.kt index fe5e1e3e6..462f74276 100644 --- a/app/src/main/java/com/kunzisoft/keepass/activities/AboutActivity.kt +++ b/app/src/main/java/com/kunzisoft/keepass/activities/AboutActivity.kt @@ -30,7 +30,7 @@ import androidx.core.text.HtmlCompat import com.kunzisoft.keepass.BuildConfig import com.kunzisoft.keepass.R import com.kunzisoft.keepass.activities.stylish.StylishActivity -import com.kunzisoft.keepass.utils.UriUtil +import com.kunzisoft.keepass.utils.UriUtil.isContributingUser import org.joda.time.DateTime class AboutActivity : StylishActivity() { @@ -46,7 +46,7 @@ class AboutActivity : StylishActivity() { supportActionBar?.setDisplayHomeAsUpEnabled(true) supportActionBar?.setDisplayShowHomeEnabled(true) - val appName = if (UriUtil.contributingUser(this)) + val appName = if (this.isContributingUser()) getString(R.string.app_name) + " " + getString(R.string.app_name_part3) else getString(R.string.app_name) diff --git a/app/src/main/java/com/kunzisoft/keepass/activities/AutofillLauncherActivity.kt b/app/src/main/java/com/kunzisoft/keepass/activities/AutofillLauncherActivity.kt index 44e0dda98..1570514e3 100644 --- a/app/src/main/java/com/kunzisoft/keepass/activities/AutofillLauncherActivity.kt +++ b/app/src/main/java/com/kunzisoft/keepass/activities/AutofillLauncherActivity.kt @@ -36,11 +36,12 @@ import com.kunzisoft.keepass.autofill.AutofillComponent import com.kunzisoft.keepass.autofill.AutofillHelper import com.kunzisoft.keepass.autofill.CompatInlineSuggestionsRequest import com.kunzisoft.keepass.autofill.KeeAutofillService -import com.kunzisoft.keepass.database.element.Database -import com.kunzisoft.keepass.database.search.SearchHelper +import com.kunzisoft.keepass.database.ContextualDatabase +import com.kunzisoft.keepass.database.helper.SearchHelper import com.kunzisoft.keepass.model.RegisterInfo import com.kunzisoft.keepass.model.SearchInfo import com.kunzisoft.keepass.settings.PreferencesUtil +import com.kunzisoft.keepass.utils.WebDomain @RequiresApi(api = Build.VERSION_CODES.O) class AutofillLauncherActivity : DatabaseModeActivity() { @@ -58,7 +59,7 @@ class AutofillLauncherActivity : DatabaseModeActivity() { return true } - override fun onDatabaseRetrieved(database: Database?) { + override fun onDatabaseRetrieved(database: ContextualDatabase?) { super.onDatabaseRetrieved(database) // Retrieve selection mode @@ -73,7 +74,7 @@ class AutofillLauncherActivity : DatabaseModeActivity() { } // Build search param bundle.getParcelable(KEY_SEARCH_INFO)?.let { searchInfo -> - SearchInfo.getConcreteWebDomain( + WebDomain.getConcreteWebDomain( this, searchInfo.webDomain ) { concreteWebDomain -> @@ -101,7 +102,7 @@ class AutofillLauncherActivity : DatabaseModeActivity() { // To register info val registerInfo = intent.getParcelableExtra(KEY_REGISTER_INFO) val searchInfo = SearchInfo(registerInfo?.searchInfo) - SearchInfo.getConcreteWebDomain(this, searchInfo.webDomain) { concreteWebDomain -> + WebDomain.getConcreteWebDomain(this, searchInfo.webDomain) { concreteWebDomain -> searchInfo.webDomain = concreteWebDomain launchRegistration(database, searchInfo, registerInfo) } @@ -115,7 +116,7 @@ class AutofillLauncherActivity : DatabaseModeActivity() { } } - private fun launchSelection(database: Database?, + private fun launchSelection(database: ContextualDatabase?, autofillComponent: AutofillComponent?, searchInfo: SearchInfo) { if (autofillComponent == null) { @@ -158,7 +159,7 @@ class AutofillLauncherActivity : DatabaseModeActivity() { } } - private fun launchRegistration(database: Database?, + private fun launchRegistration(database: ContextualDatabase?, searchInfo: SearchInfo, registerInfo: RegisterInfo?) { if (!KeeAutofillService.autofillAllowedFor(searchInfo.applicationId, diff --git a/app/src/main/java/com/kunzisoft/keepass/activities/EntryActivity.kt b/app/src/main/java/com/kunzisoft/keepass/activities/EntryActivity.kt index 73e63978b..888d41624 100644 --- a/app/src/main/java/com/kunzisoft/keepass/activities/EntryActivity.kt +++ b/app/src/main/java/com/kunzisoft/keepass/activities/EntryActivity.kt @@ -36,11 +36,11 @@ import androidx.activity.result.ActivityResultLauncher import androidx.activity.viewModels import androidx.appcompat.widget.Toolbar import androidx.coordinatorlayout.widget.CoordinatorLayout -import androidx.recyclerview.widget.LinearLayoutManager -import androidx.recyclerview.widget.RecyclerView import androidx.core.graphics.BlendModeColorFilterCompat import androidx.core.graphics.BlendModeCompat import androidx.core.graphics.ColorUtils +import androidx.recyclerview.widget.LinearLayoutManager +import androidx.recyclerview.widget.RecyclerView import com.google.android.material.appbar.AppBarLayout import com.google.android.material.appbar.CollapsingToolbarLayout import com.google.android.material.progressindicator.LinearProgressIndicator @@ -51,8 +51,8 @@ import com.kunzisoft.keepass.activities.helpers.ExternalFileHelper import com.kunzisoft.keepass.activities.helpers.SpecialMode import com.kunzisoft.keepass.activities.legacy.DatabaseLockActivity import com.kunzisoft.keepass.adapters.TagsAdapter +import com.kunzisoft.keepass.database.ContextualDatabase import com.kunzisoft.keepass.database.element.Attachment -import com.kunzisoft.keepass.database.element.Database import com.kunzisoft.keepass.database.element.icon.IconImage import com.kunzisoft.keepass.database.element.node.NodeId import com.kunzisoft.keepass.education.EntryActivityEducation @@ -67,14 +67,14 @@ import com.kunzisoft.keepass.settings.PreferencesUtil import com.kunzisoft.keepass.tasks.ActionRunnable import com.kunzisoft.keepass.tasks.AttachmentFileBinderManager import com.kunzisoft.keepass.timeout.TimeoutHelper -import com.kunzisoft.keepass.utils.UriUtil +import com.kunzisoft.keepass.utils.UriUtil.openUrl import com.kunzisoft.keepass.utils.UuidUtil import com.kunzisoft.keepass.view.changeControlColor import com.kunzisoft.keepass.view.changeTitleColor import com.kunzisoft.keepass.view.hideByFading import com.kunzisoft.keepass.view.showActionErrorIfNeeded import com.kunzisoft.keepass.viewmodels.EntryViewModel -import java.util.* +import java.util.UUID class EntryActivity : DatabaseLockActivity() { @@ -310,14 +310,14 @@ class EntryActivity : DatabaseLockActivity() { return coordinatorLayout } - override fun onDatabaseRetrieved(database: Database?) { + override fun onDatabaseRetrieved(database: ContextualDatabase?) { super.onDatabaseRetrieved(database) mEntryViewModel.loadDatabase(database) } override fun onDatabaseActionFinished( - database: Database, + database: ContextualDatabase, actionTask: String, result: ActionRunnable.Result ) { @@ -376,7 +376,7 @@ class EntryActivity : DatabaseLockActivity() { .createBlendModeColorFilterCompat(backgroundDarker, BlendModeCompat.SRC_IN) mIcon?.let { icon -> titleIconView?.let { iconView -> - mIconDrawableFactory?.assignDatabaseIcon( + mDatabase?.iconDrawableFactory?.assignDatabaseIcon( iconView, icon, mForegroundColor ?: mColorAccent @@ -473,7 +473,7 @@ class EntryActivity : DatabaseLockActivity() { } R.id.menu_goto_url -> { mUrl?.let { url -> - UriUtil.gotoUrl(this, url) + this.openUrl(url) } return true } @@ -526,7 +526,7 @@ class EntryActivity : DatabaseLockActivity() { * Open standard Entry activity */ fun launch(activity: Activity, - database: Database, + database: ContextualDatabase, entryId: NodeId, activityResultLauncher: ActivityResultLauncher) { if (database.loaded) { @@ -542,7 +542,7 @@ class EntryActivity : DatabaseLockActivity() { * Open history Entry activity */ fun launch(activity: Activity, - database: Database, + database: ContextualDatabase, entryId: NodeId, historyPosition: Int, activityResultLauncher: ActivityResultLauncher) { diff --git a/app/src/main/java/com/kunzisoft/keepass/activities/EntryEditActivity.kt b/app/src/main/java/com/kunzisoft/keepass/activities/EntryEditActivity.kt index 89e0252f5..89adbc471 100644 --- a/app/src/main/java/com/kunzisoft/keepass/activities/EntryEditActivity.kt +++ b/app/src/main/java/com/kunzisoft/keepass/activities/EntryEditActivity.kt @@ -32,7 +32,11 @@ import android.util.Log import android.view.Menu import android.view.MenuItem import android.view.View -import android.widget.* +import android.widget.AdapterView +import android.widget.DatePicker +import android.widget.ProgressBar +import android.widget.Spinner +import android.widget.TimePicker import androidx.activity.result.ActivityResultLauncher import androidx.activity.result.contract.ActivityResultContracts import androidx.activity.viewModels @@ -46,8 +50,14 @@ import androidx.fragment.app.Fragment import androidx.fragment.app.FragmentActivity import com.google.android.material.snackbar.Snackbar import com.kunzisoft.keepass.R -import com.kunzisoft.keepass.activities.dialogs.* +import com.kunzisoft.keepass.activities.dialogs.ColorPickerDialogFragment +import com.kunzisoft.keepass.activities.dialogs.DatePickerFragment +import com.kunzisoft.keepass.activities.dialogs.EntryCustomFieldDialogFragment +import com.kunzisoft.keepass.activities.dialogs.FileTooBigDialogFragment import com.kunzisoft.keepass.activities.dialogs.FileTooBigDialogFragment.Companion.MAX_WARNING_BINARY_FILE +import com.kunzisoft.keepass.activities.dialogs.ReplaceFileDialogFragment +import com.kunzisoft.keepass.activities.dialogs.SetOTPDialogFragment +import com.kunzisoft.keepass.activities.dialogs.TimePickerFragment import com.kunzisoft.keepass.activities.fragments.EntryEditFragment import com.kunzisoft.keepass.activities.helpers.EntrySelectionHelper import com.kunzisoft.keepass.activities.helpers.ExternalFileHelper @@ -55,7 +65,11 @@ import com.kunzisoft.keepass.activities.legacy.DatabaseLockActivity import com.kunzisoft.keepass.adapters.TemplatesSelectorAdapter import com.kunzisoft.keepass.autofill.AutofillComponent import com.kunzisoft.keepass.autofill.AutofillHelper -import com.kunzisoft.keepass.database.element.* +import com.kunzisoft.keepass.database.ContextualDatabase +import com.kunzisoft.keepass.database.element.Attachment +import com.kunzisoft.keepass.database.element.DateInstant +import com.kunzisoft.keepass.database.element.Entry +import com.kunzisoft.keepass.database.element.Field import com.kunzisoft.keepass.database.element.node.Node import com.kunzisoft.keepass.database.element.node.NodeId import com.kunzisoft.keepass.database.element.template.Template @@ -76,12 +90,16 @@ import com.kunzisoft.keepass.settings.PreferencesUtil import com.kunzisoft.keepass.tasks.ActionRunnable import com.kunzisoft.keepass.tasks.AttachmentFileBinderManager import com.kunzisoft.keepass.timeout.TimeoutHelper -import com.kunzisoft.keepass.utils.UriUtil -import com.kunzisoft.keepass.view.* +import com.kunzisoft.keepass.utils.UriUtil.getDocumentFile +import com.kunzisoft.keepass.view.ToolbarAction +import com.kunzisoft.keepass.view.asError +import com.kunzisoft.keepass.view.hideByFading +import com.kunzisoft.keepass.view.showActionErrorIfNeeded +import com.kunzisoft.keepass.view.updateLockPaddingLeft import com.kunzisoft.keepass.viewmodels.ColorPickerViewModel import com.kunzisoft.keepass.viewmodels.EntryEditViewModel import org.joda.time.DateTime -import java.util.* +import java.util.UUID class EntryEditActivity : DatabaseLockActivity(), EntryCustomFieldDialogFragment.EntryCustomFieldListener, @@ -185,7 +203,7 @@ class EntryEditActivity : DatabaseLockActivity(), mExternalFileHelper = ExternalFileHelper(this) mExternalFileHelper?.buildOpenDocument { uri -> uri?.let { attachmentToUploadUri -> - UriUtil.getFileData(this, attachmentToUploadUri)?.also { documentFile -> + attachmentToUploadUri.getDocumentFile(this)?.also { documentFile -> documentFile.name?.let { fileName -> if (documentFile.length() > MAX_WARNING_BINARY_FILE) { FileTooBigDialogFragment.build(attachmentToUploadUri, fileName) @@ -221,7 +239,7 @@ class EntryEditActivity : DatabaseLockActivity(), this@EntryEditActivity, templates ).apply { - iconDrawableFactory = mIconDrawableFactory + iconDrawableFactory = mDatabase?.iconDrawableFactory } adapter = mTemplatesSelectorAdapter val selectedTemplate = if (mTemplate != null) @@ -368,19 +386,19 @@ class EntryEditActivity : DatabaseLockActivity(), return true } - override fun onDatabaseRetrieved(database: Database?) { + override fun onDatabaseRetrieved(database: ContextualDatabase?) { super.onDatabaseRetrieved(database) mAllowCustomFields = database?.allowEntryCustomFields() == true mAllowOTP = database?.allowOTP == true mEntryEditViewModel.loadDatabase(database) mTemplatesSelectorAdapter?.apply { - iconDrawableFactory = mIconDrawableFactory + iconDrawableFactory = mDatabase?.iconDrawableFactory notifyDataSetChanged() } } override fun onDatabaseActionFinished( - database: Database, + database: ContextualDatabase, actionTask: String, result: ActionRunnable.Result ) { @@ -433,7 +451,7 @@ class EntryEditActivity : DatabaseLockActivity(), finishForEntryResult(entry) } - private fun entryValidatedForKeyboardSelection(database: Database, entry: Entry) { + private fun entryValidatedForKeyboardSelection(database: ContextualDatabase, entry: Entry) { // Populate Magikeyboard with entry MagikeyboardService.populateKeyboardAndMoveAppToBackground( this, @@ -444,7 +462,7 @@ class EntryEditActivity : DatabaseLockActivity(), finishForEntryResult(entry) } - private fun entryValidatedForAutofillSelection(database: Database, entry: Entry) { + private fun entryValidatedForAutofillSelection(database: ContextualDatabase, entry: Entry) { // Build Autofill response with the entry selected if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { AutofillHelper.buildResponseAndSetResult(this@EntryEditActivity, @@ -759,7 +777,7 @@ class EntryEditActivity : DatabaseLockActivity(), * Launch EntryEditActivity to update an existing entry by his [entryId] */ fun launchToUpdate(activity: Activity, - database: Database, + database: ContextualDatabase, entryId: NodeId, activityResultLauncher: ActivityResultLauncher) { if (database.loaded && !database.isReadOnly) { @@ -775,7 +793,7 @@ class EntryEditActivity : DatabaseLockActivity(), * Launch EntryEditActivity to add a new entry in an existent group */ fun launchToCreate(activity: Activity, - database: Database, + database: ContextualDatabase, groupId: NodeId<*>, activityResultLauncher: ActivityResultLauncher) { if (database.loaded && !database.isReadOnly) { @@ -788,7 +806,7 @@ class EntryEditActivity : DatabaseLockActivity(), } fun launchToUpdateForSave(context: Context, - database: Database, + database: ContextualDatabase, entryId: NodeId, searchInfo: SearchInfo) { if (database.loaded && !database.isReadOnly) { @@ -805,7 +823,7 @@ class EntryEditActivity : DatabaseLockActivity(), } fun launchToCreateForSave(context: Context, - database: Database, + database: ContextualDatabase, groupId: NodeId<*>, searchInfo: SearchInfo) { if (database.loaded && !database.isReadOnly) { @@ -825,7 +843,7 @@ class EntryEditActivity : DatabaseLockActivity(), * Launch EntryEditActivity to add a new entry in keyboard selection */ fun launchForKeyboardSelectionResult(context: Context, - database: Database, + database: ContextualDatabase, groupId: NodeId<*>, searchInfo: SearchInfo? = null) { if (database.loaded && !database.isReadOnly) { @@ -846,7 +864,7 @@ class EntryEditActivity : DatabaseLockActivity(), */ @RequiresApi(api = Build.VERSION_CODES.O) fun launchForAutofillResult(activity: AppCompatActivity, - database: Database, + database: ContextualDatabase, activityResultLauncher: ActivityResultLauncher?, autofillComponent: AutofillComponent, groupId: NodeId<*>, @@ -870,7 +888,7 @@ class EntryEditActivity : DatabaseLockActivity(), * Launch EntryEditActivity to register an updated entry (from autofill) */ fun launchToUpdateForRegistration(context: Context, - database: Database, + database: ContextualDatabase, entryId: NodeId, registerInfo: RegisterInfo? = null) { if (database.loaded && !database.isReadOnly) { @@ -890,7 +908,7 @@ class EntryEditActivity : DatabaseLockActivity(), * Launch EntryEditActivity to register a new entry (from autofill) */ fun launchToCreateForRegistration(context: Context, - database: Database, + database: ContextualDatabase, groupId: NodeId<*>, registerInfo: RegisterInfo? = null) { if (database.loaded && !database.isReadOnly) { diff --git a/app/src/main/java/com/kunzisoft/keepass/activities/EntrySelectionLauncherActivity.kt b/app/src/main/java/com/kunzisoft/keepass/activities/EntrySelectionLauncherActivity.kt index 9433054e8..9029e6c21 100644 --- a/app/src/main/java/com/kunzisoft/keepass/activities/EntrySelectionLauncherActivity.kt +++ b/app/src/main/java/com/kunzisoft/keepass/activities/EntrySelectionLauncherActivity.kt @@ -26,11 +26,12 @@ import android.os.Bundle import android.widget.Toast import com.kunzisoft.keepass.R import com.kunzisoft.keepass.activities.legacy.DatabaseModeActivity -import com.kunzisoft.keepass.database.element.Database -import com.kunzisoft.keepass.database.search.SearchHelper +import com.kunzisoft.keepass.database.ContextualDatabase +import com.kunzisoft.keepass.database.helper.SearchHelper import com.kunzisoft.keepass.magikeyboard.MagikeyboardService import com.kunzisoft.keepass.model.SearchInfo import com.kunzisoft.keepass.otp.OtpEntryFields +import com.kunzisoft.keepass.utils.WebDomain /** * Activity to search or select entry in database, @@ -46,7 +47,7 @@ class EntrySelectionLauncherActivity : DatabaseModeActivity() { return false } - override fun onDatabaseRetrieved(database: Database?) { + override fun onDatabaseRetrieved(database: ContextualDatabase?) { super.onDatabaseRetrieved(database) val keySelectionBundle = intent.getBundleExtra(KEY_SELECTION_BUNDLE) @@ -95,7 +96,7 @@ class EntrySelectionLauncherActivity : DatabaseModeActivity() { finish() } - private fun launchSelection(database: Database?, + private fun launchSelection(database: ContextualDatabase?, sharedWebDomain: String?, otpString: String?) { // Build domain search param @@ -104,13 +105,13 @@ class EntrySelectionLauncherActivity : DatabaseModeActivity() { this.otpString = otpString } - SearchInfo.getConcreteWebDomain(this, searchInfo.webDomain) { concreteWebDomain -> + WebDomain.getConcreteWebDomain(this, searchInfo.webDomain) { concreteWebDomain -> searchInfo.webDomain = concreteWebDomain launch(database, searchInfo) } } - private fun launch(database: Database?, + private fun launch(database: ContextualDatabase?, searchInfo: SearchInfo) { // Setting to integrate Magikeyboard diff --git a/app/src/main/java/com/kunzisoft/keepass/activities/FileDatabaseSelectActivity.kt b/app/src/main/java/com/kunzisoft/keepass/activities/FileDatabaseSelectActivity.kt index e10721e04..62913ec9f 100644 --- a/app/src/main/java/com/kunzisoft/keepass/activities/FileDatabaseSelectActivity.kt +++ b/app/src/main/java/com/kunzisoft/keepass/activities/FileDatabaseSelectActivity.kt @@ -53,9 +53,9 @@ import com.kunzisoft.keepass.adapters.FileDatabaseHistoryAdapter import com.kunzisoft.keepass.app.database.FileDatabaseHistoryAction import com.kunzisoft.keepass.autofill.AutofillComponent import com.kunzisoft.keepass.autofill.AutofillHelper -import com.kunzisoft.keepass.database.element.Database +import com.kunzisoft.keepass.database.ContextualDatabase +import com.kunzisoft.keepass.database.MainCredential import com.kunzisoft.keepass.education.FileDatabaseSelectActivityEducation -import com.kunzisoft.keepass.database.element.MainCredential import com.kunzisoft.keepass.hardware.HardwareKey import com.kunzisoft.keepass.model.RegisterInfo import com.kunzisoft.keepass.model.SearchInfo @@ -65,7 +65,12 @@ import com.kunzisoft.keepass.services.DatabaseTaskNotificationService.Companion. import com.kunzisoft.keepass.services.DatabaseTaskNotificationService.Companion.DATABASE_URI_KEY import com.kunzisoft.keepass.settings.PreferencesUtil import com.kunzisoft.keepass.tasks.ActionRunnable -import com.kunzisoft.keepass.utils.* +import com.kunzisoft.keepass.utils.DexUtil +import com.kunzisoft.keepass.utils.MagikeyboardUtil +import com.kunzisoft.keepass.utils.MenuUtil +import com.kunzisoft.keepass.utils.UriHelper.parseUri +import com.kunzisoft.keepass.utils.UriUtil.isContributingUser +import com.kunzisoft.keepass.utils.UriUtil.openUrl import com.kunzisoft.keepass.view.asError import com.kunzisoft.keepass.view.showActionErrorIfNeeded import com.kunzisoft.keepass.viewmodels.DatabaseFilesViewModel @@ -179,7 +184,7 @@ class FileDatabaseSelectActivity : DatabaseModeActivity(), && savedInstanceState.getBoolean(EXTRA_STAY, false))) { val databasePath = PreferencesUtil.getDefaultDatabasePath(this) - UriUtil.parse(databasePath)?.let { databaseFileUri -> + databasePath?.parseUri()?.let { databaseFileUri -> launchPasswordActivityWithPath(databaseFileUri) } ?: run { Log.i(TAG, "No default database to prepare") @@ -228,7 +233,7 @@ class FileDatabaseSelectActivity : DatabaseModeActivity(), } } - override fun onDatabaseRetrieved(database: Database?) { + override fun onDatabaseRetrieved(database: ContextualDatabase?) { super.onDatabaseRetrieved(database) if (database != null) { launchGroupActivityIfLoaded(database) @@ -236,7 +241,7 @@ class FileDatabaseSelectActivity : DatabaseModeActivity(), } override fun onDatabaseActionFinished( - database: Database, + database: ContextualDatabase, actionTask: String, result: ActionRunnable.Result ) { @@ -304,7 +309,7 @@ class FileDatabaseSelectActivity : DatabaseModeActivity(), mAutofillActivityResultLauncher) } - private fun launchGroupActivityIfLoaded(database: Database) { + private fun launchGroupActivityIfLoaded(database: ContextualDatabase) { if (database.loaded) { GroupActivity.launch(this, database, @@ -326,7 +331,7 @@ class FileDatabaseSelectActivity : DatabaseModeActivity(), super.onResume() // Define special title - specialTitle?.isVisible = UriUtil.contributingUser(this) + specialTitle?.isVisible = this.isContributingUser() // Show open and create button or special mode when (mSpecialMode) { @@ -426,7 +431,7 @@ class FileDatabaseSelectActivity : DatabaseModeActivity(), override fun onOptionsItemSelected(item: MenuItem): Boolean { when (item.itemId) { - android.R.id.home -> UriUtil.gotoUrl(this, R.string.file_manager_explanation_url) + android.R.id.home -> this.openUrl(R.string.file_manager_explanation_url) } MenuUtil.onDefaultMenuOptionsItemSelected(this, item) return super.onOptionsItemSelected(item) diff --git a/app/src/main/java/com/kunzisoft/keepass/activities/GroupActivity.kt b/app/src/main/java/com/kunzisoft/keepass/activities/GroupActivity.kt index b658afdcd..f95a22e70 100644 --- a/app/src/main/java/com/kunzisoft/keepass/activities/GroupActivity.kt +++ b/app/src/main/java/com/kunzisoft/keepass/activities/GroupActivity.kt @@ -27,13 +27,23 @@ import android.content.Context import android.content.Intent import android.graphics.PorterDuff import android.net.Uri -import android.os.* +import android.os.Build +import android.os.Bundle +import android.os.Handler +import android.os.Looper +import android.os.Parcel +import android.os.Parcelable import android.util.Log import android.view.Menu import android.view.MenuItem import android.view.View import android.view.ViewGroup -import android.widget.* +import android.widget.DatePicker +import android.widget.ImageView +import android.widget.ProgressBar +import android.widget.TextView +import android.widget.TimePicker +import android.widget.Toast import androidx.activity.result.ActivityResultLauncher import androidx.activity.viewModels import androidx.annotation.RequiresApi @@ -50,7 +60,12 @@ import androidx.core.view.isVisible import androidx.drawerlayout.widget.DrawerLayout import androidx.recyclerview.widget.RecyclerView import com.kunzisoft.keepass.R -import com.kunzisoft.keepass.activities.dialogs.* +import com.kunzisoft.keepass.activities.dialogs.DatePickerFragment +import com.kunzisoft.keepass.activities.dialogs.GroupDialogFragment +import com.kunzisoft.keepass.activities.dialogs.GroupEditDialogFragment +import com.kunzisoft.keepass.activities.dialogs.MainCredentialDialogFragment +import com.kunzisoft.keepass.activities.dialogs.SortDialogFragment +import com.kunzisoft.keepass.activities.dialogs.TimePickerFragment import com.kunzisoft.keepass.activities.fragments.GroupFragment import com.kunzisoft.keepass.activities.helpers.EntrySelectionHelper import com.kunzisoft.keepass.activities.helpers.ExternalFileHelper @@ -59,17 +74,21 @@ import com.kunzisoft.keepass.activities.legacy.DatabaseLockActivity import com.kunzisoft.keepass.adapters.BreadcrumbAdapter import com.kunzisoft.keepass.autofill.AutofillComponent import com.kunzisoft.keepass.autofill.AutofillHelper -import com.kunzisoft.keepass.database.element.* +import com.kunzisoft.keepass.database.ContextualDatabase +import com.kunzisoft.keepass.database.MainCredential +import com.kunzisoft.keepass.database.element.DateInstant +import com.kunzisoft.keepass.database.element.Entry +import com.kunzisoft.keepass.database.element.Group +import com.kunzisoft.keepass.database.element.SortNodeEnum import com.kunzisoft.keepass.database.element.node.Node import com.kunzisoft.keepass.database.element.node.NodeId import com.kunzisoft.keepass.database.element.node.NodeIdUUID import com.kunzisoft.keepass.database.element.node.Type -import com.kunzisoft.keepass.database.search.SearchHelper +import com.kunzisoft.keepass.database.helper.SearchHelper import com.kunzisoft.keepass.database.search.SearchParameters import com.kunzisoft.keepass.education.GroupActivityEducation import com.kunzisoft.keepass.magikeyboard.MagikeyboardService import com.kunzisoft.keepass.model.GroupInfo -import com.kunzisoft.keepass.database.element.MainCredential import com.kunzisoft.keepass.model.RegisterInfo import com.kunzisoft.keepass.model.SearchInfo import com.kunzisoft.keepass.services.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_UPDATE_ENTRY_TASK @@ -81,8 +100,14 @@ import com.kunzisoft.keepass.settings.SettingsActivity import com.kunzisoft.keepass.tasks.ActionRunnable import com.kunzisoft.keepass.timeout.TimeoutHelper import com.kunzisoft.keepass.utils.BACK_PREVIOUS_KEYBOARD_ACTION -import com.kunzisoft.keepass.utils.UriUtil -import com.kunzisoft.keepass.view.* +import com.kunzisoft.keepass.utils.UriUtil.openUrl +import com.kunzisoft.keepass.view.AddNodeButtonView +import com.kunzisoft.keepass.view.NavigationDatabaseView +import com.kunzisoft.keepass.view.SearchFiltersView +import com.kunzisoft.keepass.view.ToolbarAction +import com.kunzisoft.keepass.view.hideByFading +import com.kunzisoft.keepass.view.showActionErrorIfNeeded +import com.kunzisoft.keepass.view.updateLockPaddingLeft import com.kunzisoft.keepass.viewmodels.GroupEditViewModel import com.kunzisoft.keepass.viewmodels.GroupViewModel import org.joda.time.DateTime @@ -302,7 +327,7 @@ class GroupActivity : DatabaseLockActivity(), lockAndExit() } R.id.menu_contribute -> { - UriUtil.gotoUrl(this@GroupActivity, R.string.contribution_url) + this@GroupActivity.openUrl(R.string.contribution_url) } R.id.menu_about -> { startActivity(Intent(this@GroupActivity, AboutActivity::class.java)) @@ -570,7 +595,7 @@ class GroupActivity : DatabaseLockActivity(), } } - override fun onDatabaseRetrieved(database: Database?) { + override fun onDatabaseRetrieved(database: ContextualDatabase?) { super.onDatabaseRetrieved(database) mGroupEditViewModel.setGroupNamesNotAllowed(database?.groupNamesNotAllowed) @@ -614,7 +639,7 @@ class GroupActivity : DatabaseLockActivity(), } override fun onDatabaseActionFinished( - database: Database, + database: ContextualDatabase, actionTask: String, result: ActionRunnable.Result ) { @@ -800,7 +825,7 @@ class GroupActivity : DatabaseLockActivity(), } override fun onNodeClick( - database: Database, + database: ContextualDatabase, node: Node ) { when (node.type) { @@ -873,7 +898,7 @@ class GroupActivity : DatabaseLockActivity(), reloadGroupIfSearch() } - private fun entrySelectedForSave(database: Database, entry: Entry, searchInfo: SearchInfo) { + private fun entrySelectedForSave(database: ContextualDatabase, entry: Entry, searchInfo: SearchInfo) { reloadCurrentGroup() // Save to update the entry EntryEditActivity.launchToUpdateForSave( @@ -885,7 +910,7 @@ class GroupActivity : DatabaseLockActivity(), onLaunchActivitySpecialMode() } - private fun entrySelectedForKeyboardSelection(database: Database, entry: Entry) { + private fun entrySelectedForKeyboardSelection(database: ContextualDatabase, entry: Entry) { reloadCurrentGroup() // Populate Magikeyboard with entry MagikeyboardService.populateKeyboardAndMoveAppToBackground( @@ -895,7 +920,7 @@ class GroupActivity : DatabaseLockActivity(), onValidateSpecialMode() } - private fun entrySelectedForAutofillSelection(database: Database, entry: Entry) { + private fun entrySelectedForAutofillSelection(database: ContextualDatabase, entry: Entry) { // Build response with the entry selected if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { AutofillHelper.buildResponseAndSetResult( @@ -908,7 +933,7 @@ class GroupActivity : DatabaseLockActivity(), } private fun entrySelectedForRegistration( - database: Database, + database: ContextualDatabase, entry: Entry, registerInfo: RegisterInfo? ) { @@ -924,7 +949,7 @@ class GroupActivity : DatabaseLockActivity(), } private fun updateEntryWithSearchInfo( - database: Database, + database: ContextualDatabase, entry: Entry, searchInfo: SearchInfo ) { @@ -964,7 +989,7 @@ class GroupActivity : DatabaseLockActivity(), } override fun onNodeSelected( - database: Database, + database: ContextualDatabase, nodes: List ): Boolean { if (nodes.isNotEmpty()) { @@ -990,7 +1015,7 @@ class GroupActivity : DatabaseLockActivity(), } override fun onOpenMenuClick( - database: Database, + database: ContextualDatabase, node: Node ): Boolean { finishNodeAction() @@ -999,7 +1024,7 @@ class GroupActivity : DatabaseLockActivity(), } override fun onEditMenuClick( - database: Database, + database: ContextualDatabase, node: Node ): Boolean { finishNodeAction() @@ -1047,7 +1072,7 @@ class GroupActivity : DatabaseLockActivity(), } override fun onCopyMenuClick( - database: Database, + database: ContextualDatabase, nodes: List ): Boolean { actionNodeMode?.invalidate() @@ -1057,7 +1082,7 @@ class GroupActivity : DatabaseLockActivity(), } override fun onMoveMenuClick( - database: Database, + database: ContextualDatabase, nodes: List ): Boolean { actionNodeMode?.invalidate() @@ -1067,7 +1092,7 @@ class GroupActivity : DatabaseLockActivity(), } override fun onPasteMenuClick( - database: Database, + database: ContextualDatabase, pasteMode: GroupFragment.PasteMode?, nodes: List ): Boolean { @@ -1092,7 +1117,7 @@ class GroupActivity : DatabaseLockActivity(), } override fun onDeleteMenuClick( - database: Database, + database: ContextualDatabase, nodes: List ): Boolean { deleteNodes(nodes) @@ -1101,15 +1126,19 @@ class GroupActivity : DatabaseLockActivity(), return true } - override fun onAskMainCredentialDialogPositiveClick(databaseUri: Uri?, - mainCredential: MainCredential) { + override fun onAskMainCredentialDialogPositiveClick( + databaseUri: Uri?, + mainCredential: MainCredential + ) { databaseUri?.let { mergeDatabaseFrom(it, mainCredential) } } - override fun onAskMainCredentialDialogNegativeClick(databaseUri: Uri?, - mainCredential: MainCredential) { } + override fun onAskMainCredentialDialogNegativeClick( + databaseUri: Uri?, + mainCredential: MainCredential + ) { } override fun onResume() { super.onResume() @@ -1475,7 +1504,7 @@ class GroupActivity : DatabaseLockActivity(), * ------------------------- */ fun launch(context: Context, - database: Database, + database: ContextualDatabase, autoSearch: Boolean = false) { if (database.loaded) { checkTimeAndBuildIntent(context, null) { intent -> @@ -1491,7 +1520,7 @@ class GroupActivity : DatabaseLockActivity(), * ------------------------- */ fun launchForSearchResult(context: Context, - database: Database, + database: ContextualDatabase, searchInfo: SearchInfo, autoSearch: Boolean = false) { if (database.loaded) { @@ -1512,7 +1541,7 @@ class GroupActivity : DatabaseLockActivity(), * ------------------------- */ fun launchForSaveResult(context: Context, - database: Database, + database: ContextualDatabase, searchInfo: SearchInfo, autoSearch: Boolean = false) { if (database.loaded && !database.isReadOnly) { @@ -1533,7 +1562,7 @@ class GroupActivity : DatabaseLockActivity(), * ------------------------- */ fun launchForKeyboardSelectionResult(context: Context, - database: Database, + database: ContextualDatabase, searchInfo: SearchInfo? = null, autoSearch: Boolean = false) { if (database.loaded) { @@ -1555,7 +1584,7 @@ class GroupActivity : DatabaseLockActivity(), */ @RequiresApi(api = Build.VERSION_CODES.O) fun launchForAutofillResult(activity: AppCompatActivity, - database: Database, + database: ContextualDatabase, activityResultLaunch: ActivityResultLauncher?, autofillComponent: AutofillComponent, searchInfo: SearchInfo? = null, @@ -1580,7 +1609,7 @@ class GroupActivity : DatabaseLockActivity(), * ------------------------- */ fun launchForRegistration(context: Context, - database: Database, + database: ContextualDatabase, registerInfo: RegisterInfo? = null) { if (database.loaded && !database.isReadOnly) { checkTimeAndBuildIntent(context, null) { intent -> @@ -1600,7 +1629,7 @@ class GroupActivity : DatabaseLockActivity(), * ------------------------- */ fun launch(activity: AppCompatActivity, - database: Database, + database: ContextualDatabase, onValidateSpecialMode: () -> Unit, onCancelSpecialMode: () -> Unit, onLaunchActivitySpecialMode: () -> Unit, diff --git a/app/src/main/java/com/kunzisoft/keepass/activities/IconPickerActivity.kt b/app/src/main/java/com/kunzisoft/keepass/activities/IconPickerActivity.kt index 93cf4b9a9..250837774 100644 --- a/app/src/main/java/com/kunzisoft/keepass/activities/IconPickerActivity.kt +++ b/app/src/main/java/com/kunzisoft/keepass/activities/IconPickerActivity.kt @@ -41,16 +41,22 @@ import com.kunzisoft.keepass.activities.fragments.IconPickerFragment import com.kunzisoft.keepass.activities.helpers.ExternalFileHelper import com.kunzisoft.keepass.activities.helpers.setOpenDocumentClickListener import com.kunzisoft.keepass.activities.legacy.DatabaseLockActivity -import com.kunzisoft.keepass.database.element.Database +import com.kunzisoft.keepass.database.ContextualDatabase import com.kunzisoft.keepass.database.element.icon.IconImage import com.kunzisoft.keepass.database.element.icon.IconImageCustom import com.kunzisoft.keepass.settings.PreferencesUtil import com.kunzisoft.keepass.tasks.BinaryDatabaseManager -import com.kunzisoft.keepass.utils.UriUtil +import com.kunzisoft.keepass.utils.UriUtil.getDocumentFile +import com.kunzisoft.keepass.utils.UriUtil.openUrl import com.kunzisoft.keepass.view.asError import com.kunzisoft.keepass.view.updateLockPaddingLeft import com.kunzisoft.keepass.viewmodels.IconPickerViewModel -import kotlinx.coroutines.* +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Deferred +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.async +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext class IconPickerActivity : DatabaseLockActivity() { @@ -166,7 +172,7 @@ class IconPickerActivity : DatabaseLockActivity() { return true } - override fun onDatabaseRetrieved(database: Database?) { + override fun onDatabaseRetrieved(database: ContextualDatabase?) { super.onDatabaseRetrieved(database) if (database?.allowCustomIcons == true) { @@ -243,7 +249,7 @@ class IconPickerActivity : DatabaseLockActivity() { } } R.id.menu_external_icon -> { - UriUtil.gotoUrl(this, R.string.external_icon_url) + this.openUrl(R.string.external_icon_url) } } @@ -257,7 +263,7 @@ class IconPickerActivity : DatabaseLockActivity() { // on Progress with thread val asyncResult: Deferred = async { val iconCustomState = IconPickerViewModel.IconCustomState(null, true, R.string.error_upload_file) - UriUtil.getFileData(this@IconPickerActivity, iconToUploadUri)?.also { documentFile -> + iconToUploadUri?.getDocumentFile(this@IconPickerActivity)?.also { documentFile -> if (documentFile.length() > MAX_ICON_SIZE) { iconCustomState.errorStringId = R.string.error_file_to_big } else { diff --git a/app/src/main/java/com/kunzisoft/keepass/activities/ImageViewerActivity.kt b/app/src/main/java/com/kunzisoft/keepass/activities/ImageViewerActivity.kt index 9cc56f9f5..c2787cbdc 100644 --- a/app/src/main/java/com/kunzisoft/keepass/activities/ImageViewerActivity.kt +++ b/app/src/main/java/com/kunzisoft/keepass/activities/ImageViewerActivity.kt @@ -33,8 +33,8 @@ import androidx.appcompat.widget.Toolbar import com.igreenwood.loupe.Loupe import com.kunzisoft.keepass.R import com.kunzisoft.keepass.activities.legacy.DatabaseLockActivity +import com.kunzisoft.keepass.database.ContextualDatabase import com.kunzisoft.keepass.database.element.Attachment -import com.kunzisoft.keepass.database.element.Database import com.kunzisoft.keepass.tasks.BinaryDatabaseManager import kotlin.math.max @@ -100,7 +100,7 @@ class ImageViewerActivity : DatabaseLockActivity() { return true } - override fun onDatabaseRetrieved(database: Database?) { + override fun onDatabaseRetrieved(database: ContextualDatabase?) { super.onDatabaseRetrieved(database) try { diff --git a/app/src/main/java/com/kunzisoft/keepass/activities/MainCredentialActivity.kt b/app/src/main/java/com/kunzisoft/keepass/activities/MainCredentialActivity.kt index 371a321ea..382ce1ce8 100644 --- a/app/src/main/java/com/kunzisoft/keepass/activities/MainCredentialActivity.kt +++ b/app/src/main/java/com/kunzisoft/keepass/activities/MainCredentialActivity.kt @@ -55,8 +55,8 @@ import com.kunzisoft.keepass.autofill.AutofillComponent import com.kunzisoft.keepass.autofill.AutofillHelper import com.kunzisoft.keepass.biometric.AdvancedUnlockFragment import com.kunzisoft.keepass.biometric.AdvancedUnlockManager -import com.kunzisoft.keepass.database.element.Database -import com.kunzisoft.keepass.database.element.MainCredential +import com.kunzisoft.keepass.database.ContextualDatabase +import com.kunzisoft.keepass.database.MainCredential import com.kunzisoft.keepass.database.exception.DuplicateUuidDatabaseException import com.kunzisoft.keepass.database.exception.FileNotFoundDatabaseException import com.kunzisoft.keepass.education.PasswordActivityEducation @@ -72,7 +72,7 @@ import com.kunzisoft.keepass.settings.SettingsAdvancedUnlockActivity import com.kunzisoft.keepass.tasks.ActionRunnable import com.kunzisoft.keepass.utils.BACK_PREVIOUS_KEYBOARD_ACTION import com.kunzisoft.keepass.utils.MenuUtil -import com.kunzisoft.keepass.utils.UriUtil +import com.kunzisoft.keepass.utils.UriUtil.getUri import com.kunzisoft.keepass.view.MainCredentialView import com.kunzisoft.keepass.view.asError import com.kunzisoft.keepass.view.showActionErrorIfNeeded @@ -262,7 +262,7 @@ class MainCredentialActivity : DatabaseModeActivity(), AdvancedUnlockFragment.Bu } } - override fun onDatabaseRetrieved(database: Database?) { + override fun onDatabaseRetrieved(database: ContextualDatabase?) { super.onDatabaseRetrieved(database) if (database != null) { // Trying to load another database @@ -279,7 +279,7 @@ class MainCredentialActivity : DatabaseModeActivity(), AdvancedUnlockFragment.Bu } override fun onDatabaseActionFinished( - database: Database, + database: ContextualDatabase, actionTask: String, result: ActionRunnable.Result ) { @@ -344,7 +344,7 @@ class MainCredentialActivity : DatabaseModeActivity(), AdvancedUnlockFragment.Bu if (action == VIEW_INTENT) { fillCredentials( intent.data, - UriUtil.getUriFromIntent(intent, KEY_KEYFILE), + intent.getUri(KEY_KEYFILE), HardwareKey.getHardwareKeyFromString(intent.getStringExtra(KEY_HARDWARE_KEY)) ) } else { @@ -357,7 +357,7 @@ class MainCredentialActivity : DatabaseModeActivity(), AdvancedUnlockFragment.Bu try { intent?.removeExtra(KEY_KEYFILE) intent?.removeExtra(KEY_HARDWARE_KEY) - } catch (e: Exception) {} + } catch (_: Exception) {} mDatabaseFileUri?.let { mDatabaseFileViewModel.checkIfIsDefaultDatabase(it) } @@ -376,7 +376,7 @@ class MainCredentialActivity : DatabaseModeActivity(), AdvancedUnlockFragment.Bu getUriFromIntent(intent) } - private fun launchGroupActivityIfLoaded(database: Database) { + private fun launchGroupActivityIfLoaded(database: ContextualDatabase) { // Check if database really loaded if (database.loaded) { clearCredentialsViews(clearKeyFile = true, clearHardwareKey = true) diff --git a/app/src/main/java/com/kunzisoft/keepass/activities/dialogs/DatabaseChangedDialogFragment.kt b/app/src/main/java/com/kunzisoft/keepass/activities/dialogs/DatabaseChangedDialogFragment.kt index e4bb7915c..26f24dd6f 100644 --- a/app/src/main/java/com/kunzisoft/keepass/activities/dialogs/DatabaseChangedDialogFragment.kt +++ b/app/src/main/java/com/kunzisoft/keepass/activities/dialogs/DatabaseChangedDialogFragment.kt @@ -78,7 +78,8 @@ class DatabaseChangedDialogFragment : DatabaseDialogFragment() { private const val NEW_FILE_DATABASE_INFO = "NEW_FILE_DATABASE_INFO" fun getInstance(oldSnapFileDatabaseInfo: SnapFileDatabaseInfo, - newSnapFileDatabaseInfo: SnapFileDatabaseInfo) + newSnapFileDatabaseInfo: SnapFileDatabaseInfo + ) : DatabaseChangedDialogFragment { val fragment = DatabaseChangedDialogFragment() fragment.arguments = Bundle().apply { diff --git a/app/src/main/java/com/kunzisoft/keepass/activities/dialogs/DatabaseDialogFragment.kt b/app/src/main/java/com/kunzisoft/keepass/activities/dialogs/DatabaseDialogFragment.kt index fc3708205..d3c1ea348 100644 --- a/app/src/main/java/com/kunzisoft/keepass/activities/dialogs/DatabaseDialogFragment.kt +++ b/app/src/main/java/com/kunzisoft/keepass/activities/dialogs/DatabaseDialogFragment.kt @@ -5,7 +5,8 @@ import androidx.fragment.app.DialogFragment import androidx.fragment.app.activityViewModels import com.kunzisoft.keepass.activities.legacy.DatabaseRetrieval import com.kunzisoft.keepass.activities.legacy.resetAppTimeoutWhenViewTouchedOrFocused -import com.kunzisoft.keepass.database.element.Database +import com.kunzisoft.keepass.database.ContextualDatabase +import com.kunzisoft.keepass.icons.IconDrawableFactory import com.kunzisoft.keepass.tasks.ActionRunnable import com.kunzisoft.keepass.timeout.TimeoutHelper import com.kunzisoft.keepass.viewmodels.DatabaseViewModel @@ -13,7 +14,9 @@ import com.kunzisoft.keepass.viewmodels.DatabaseViewModel abstract class DatabaseDialogFragment : DialogFragment(), DatabaseRetrieval { private val mDatabaseViewModel: DatabaseViewModel by activityViewModels() - private var mDatabase: Database? = null + private var mDatabase: ContextualDatabase? = null + + protected var mIconDrawableFactory: IconDrawableFactory? = null override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -36,12 +39,12 @@ abstract class DatabaseDialogFragment : DialogFragment(), DatabaseRetrieval { resetAppTimeoutOnTouchOrFocus() } - override fun onDatabaseRetrieved(database: Database?) { + override fun onDatabaseRetrieved(database: ContextualDatabase?) { // Can be overridden by a subclass } override fun onDatabaseActionFinished( - database: Database, + database: ContextualDatabase, actionTask: String, result: ActionRunnable.Result ) { diff --git a/app/src/main/java/com/kunzisoft/keepass/activities/dialogs/FileManagerDialogFragment.kt b/app/src/main/java/com/kunzisoft/keepass/activities/dialogs/FileManagerDialogFragment.kt index 6fa85a817..3b6d5bf7c 100644 --- a/app/src/main/java/com/kunzisoft/keepass/activities/dialogs/FileManagerDialogFragment.kt +++ b/app/src/main/java/com/kunzisoft/keepass/activities/dialogs/FileManagerDialogFragment.kt @@ -21,12 +21,12 @@ package com.kunzisoft.keepass.activities.dialogs import android.app.Dialog import android.os.Bundle -import androidx.fragment.app.DialogFragment -import androidx.appcompat.app.AlertDialog import android.widget.Button import android.widget.TextView +import androidx.appcompat.app.AlertDialog +import androidx.fragment.app.DialogFragment import com.kunzisoft.keepass.R -import com.kunzisoft.keepass.utils.UriUtil +import com.kunzisoft.keepass.utils.UriUtil.openUrl class FileManagerDialogFragment : DialogFragment() { @@ -42,7 +42,7 @@ class FileManagerDialogFragment : DialogFragment() { textDescription.text = getString(R.string.file_manager_install_description) root.findViewById