fix: Database workflow

This commit is contained in:
J-Jamet
2025-10-09 19:41:36 +02:00
parent 366e8bf1d7
commit e5595a3275
49 changed files with 308 additions and 310 deletions

View File

@@ -330,9 +330,8 @@ class EntryActivity : DatabaseLockActivity() {
return coordinatorLayout return coordinatorLayout
} }
override fun onDatabaseRetrieved(database: ContextualDatabase?) { override fun onDatabaseRetrieved(database: ContextualDatabase) {
super.onDatabaseRetrieved(database) super.onDatabaseRetrieved(database)
mEntryViewModel.loadDatabase(database) mEntryViewModel.loadDatabase(database)
} }

View File

@@ -444,13 +444,13 @@ class EntryEditActivity : DatabaseLockActivity(),
return true return true
} }
override fun onDatabaseRetrieved(database: ContextualDatabase?) { override fun onDatabaseRetrieved(database: ContextualDatabase) {
super.onDatabaseRetrieved(database) super.onDatabaseRetrieved(database)
mAllowCustomFields = database?.allowEntryCustomFields() == true mAllowCustomFields = database.allowEntryCustomFields() == true
mAllowOTP = database?.allowOTP == true mAllowOTP = database.allowOTP == true
mEntryEditViewModel.loadTemplateEntry(database) mEntryEditViewModel.loadTemplateEntry(database)
mTemplatesSelectorAdapter?.apply { mTemplatesSelectorAdapter?.apply {
iconDrawableFactory = mDatabase?.iconDrawableFactory iconDrawableFactory = database.iconDrawableFactory
notifyDataSetChanged() notifyDataSetChanged()
} }
} }

View File

@@ -216,10 +216,8 @@ class FileDatabaseSelectActivity : DatabaseModeActivity(),
} }
} }
override fun onDatabaseRetrieved(database: ContextualDatabase?) { override fun onDatabaseRetrieved(database: ContextualDatabase) {
if (database != null) { launchGroupActivityIfLoaded(database)
launchGroupActivityIfLoaded(database)
}
} }
override fun onDatabaseActionFinished( override fun onDatabaseActionFinished(

View File

@@ -578,7 +578,7 @@ class GroupActivity : DatabaseLockActivity(),
} }
} }
override fun onDatabaseRetrieved(database: ContextualDatabase?) { override fun onDatabaseRetrieved(database: ContextualDatabase) {
super.onDatabaseRetrieved(database) super.onDatabaseRetrieved(database)
mBreadcrumbAdapter = BreadcrumbAdapter(this, database).apply { mBreadcrumbAdapter = BreadcrumbAdapter(this, database).apply {
@@ -618,18 +618,16 @@ class GroupActivity : DatabaseLockActivity(),
adapter = mBreadcrumbAdapter adapter = mBreadcrumbAdapter
} }
mGroupEditViewModel.setGroupNamesNotAllowed(database?.groupNamesNotAllowed) mGroupEditViewModel.setGroupNamesNotAllowed(database.groupNamesNotAllowed)
mRecyclingBinEnabled = !mDatabaseReadOnly mRecyclingBinEnabled = !mDatabaseReadOnly
&& database?.isRecycleBinEnabled == true && database.isRecycleBinEnabled == true
mRootGroup = database?.rootGroup mRootGroup = database.rootGroup
loadGroup() loadGroup()
// Update view // Update view
database?.let { mBreadcrumbAdapter?.iconDrawableFactory = database.iconDrawableFactory
mBreadcrumbAdapter?.iconDrawableFactory = it.iconDrawableFactory
}
refreshDatabaseViews() refreshDatabaseViews()
invalidateOptionsMenu() invalidateOptionsMenu()
} }

View File

@@ -174,10 +174,10 @@ class IconPickerActivity : DatabaseLockActivity() {
return true return true
} }
override fun onDatabaseRetrieved(database: ContextualDatabase?) { override fun onDatabaseRetrieved(database: ContextualDatabase) {
super.onDatabaseRetrieved(database) super.onDatabaseRetrieved(database)
if (database?.allowCustomIcons == true) { if (database.allowCustomIcons) {
uploadButton.setOpenDocumentClickListener(mExternalFileHelper) uploadButton.setOpenDocumentClickListener(mExternalFileHelper)
} else { } else {
uploadButton.visibility = View.GONE uploadButton.visibility = View.GONE

View File

@@ -101,7 +101,7 @@ class ImageViewerActivity : DatabaseLockActivity() {
return true return true
} }
override fun onDatabaseRetrieved(database: ContextualDatabase?) { override fun onDatabaseRetrieved(database: ContextualDatabase) {
super.onDatabaseRetrieved(database) super.onDatabaseRetrieved(database)
try { try {
@@ -119,18 +119,16 @@ class ImageViewerActivity : DatabaseLockActivity() {
resources.displayMetrics.heightPixels * 2 resources.displayMetrics.heightPixels * 2
) )
database?.let { database -> BinaryDatabaseManager.loadBitmap(
BinaryDatabaseManager.loadBitmap( database,
database, attachment.binaryData,
attachment.binaryData, mImagePreviewMaxWidth
mImagePreviewMaxWidth ) { bitmapLoaded ->
) { bitmapLoaded -> if (bitmapLoaded == null) {
if (bitmapLoaded == null) { finish()
finish() } else {
} else { progressView.visibility = View.GONE
progressView.visibility = View.GONE imageView.setImageBitmap(bitmapLoaded)
imageView.setImageBitmap(bitmapLoaded)
}
} }
} }
} ?: finish() } ?: finish()

View File

@@ -306,20 +306,18 @@ class MainCredentialActivity : DatabaseModeActivity() {
} }
} }
override fun onDatabaseRetrieved(database: ContextualDatabase?) { override fun onDatabaseRetrieved(database: ContextualDatabase) {
super.onDatabaseRetrieved(database) super.onDatabaseRetrieved(database)
if (database != null) { // Trying to load another database
// Trying to load another database if (mDatabaseFileUri != null
if (mDatabaseFileUri != null && database.fileUri != null
&& database.fileUri != null && mDatabaseFileUri != database.fileUri) {
&& mDatabaseFileUri != database.fileUri) { Toast.makeText(this,
Toast.makeText(this, R.string.warning_database_already_opened,
R.string.warning_database_already_opened, Toast.LENGTH_LONG
Toast.LENGTH_LONG ).show()
).show()
}
launchGroupActivityIfLoaded(database)
} }
launchGroupActivityIfLoaded(database)
} }
override fun onDatabaseActionFinished( override fun onDatabaseActionFinished(

View File

@@ -44,7 +44,9 @@ abstract class DatabaseDialogFragment : DialogFragment(), DatabaseRetrieval {
lifecycleScope.launch { lifecycleScope.launch {
repeatOnLifecycle(Lifecycle.State.RESUMED) { repeatOnLifecycle(Lifecycle.State.RESUMED) {
mDatabaseViewModel.databaseState.collect { database -> mDatabaseViewModel.databaseState.collect { database ->
onDatabaseRetrieved(database) database?.let {
onDatabaseRetrieved(database)
}
} }
} }
} }
@@ -70,7 +72,7 @@ abstract class DatabaseDialogFragment : DialogFragment(), DatabaseRetrieval {
resetAppTimeoutOnTouchOrFocus() resetAppTimeoutOnTouchOrFocus()
} }
override fun onDatabaseRetrieved(database: ContextualDatabase?) { override fun onDatabaseRetrieved(database: ContextualDatabase) {
// Can be overridden by a subclass // Can be overridden by a subclass
} }

View File

@@ -62,14 +62,14 @@ class GroupDialogFragment : DatabaseDialogFragment() {
private lateinit var uuidContainerView: ViewGroup private lateinit var uuidContainerView: ViewGroup
private lateinit var uuidReferenceView: TextView private lateinit var uuidReferenceView: TextView
override fun onDatabaseRetrieved(database: ContextualDatabase?) { override fun onDatabaseRetrieved(database: ContextualDatabase) {
super.onDatabaseRetrieved(database) super.onDatabaseRetrieved(database)
mPopulateIconMethod = { imageView, icon -> mPopulateIconMethod = { imageView, icon ->
database?.iconDrawableFactory?.assignDatabaseIcon(imageView, icon, mIconColor) database.iconDrawableFactory.assignDatabaseIcon(imageView, icon, mIconColor)
} }
mPopulateIconMethod?.invoke(iconView, mGroupInfo.icon) mPopulateIconMethod?.invoke(iconView, mGroupInfo.icon)
if (database?.allowCustomSearchableGroup() == true) { if (database.allowCustomSearchableGroup()) {
searchableLabelView.visibility = View.VISIBLE searchableLabelView.visibility = View.VISIBLE
searchableView.visibility = View.VISIBLE searchableView.visibility = View.VISIBLE
} else { } else {

View File

@@ -112,32 +112,32 @@ class GroupEditDialogFragment : DatabaseDialogFragment() {
} }
} }
override fun onDatabaseRetrieved(database: ContextualDatabase?) { override fun onDatabaseRetrieved(database: ContextualDatabase) {
super.onDatabaseRetrieved(database) super.onDatabaseRetrieved(database)
mPopulateIconMethod = { imageView, icon -> mPopulateIconMethod = { imageView, icon ->
database?.iconDrawableFactory?.assignDatabaseIcon(imageView, icon, mIconColor) database.iconDrawableFactory.assignDatabaseIcon(imageView, icon, mIconColor)
} }
mPopulateIconMethod?.invoke(iconButtonView, mGroupInfo.icon) mPopulateIconMethod?.invoke(iconButtonView, mGroupInfo.icon)
searchableContainerView.visibility = if (database?.allowCustomSearchableGroup() == true) { searchableContainerView.visibility = if (database.allowCustomSearchableGroup()) {
View.VISIBLE View.VISIBLE
} else { } else {
View.GONE View.GONE
} }
if (database?.allowAutoType() == true) { if (database.allowAutoType()) {
autoTypeContainerView.visibility = View.VISIBLE autoTypeContainerView.visibility = View.VISIBLE
} else { } else {
autoTypeContainerView.visibility = View.GONE autoTypeContainerView.visibility = View.GONE
} }
tagsAdapter = TagsProposalAdapter(requireContext(), database?.tagPool) tagsAdapter = TagsProposalAdapter(requireContext(), database.tagPool)
tagsCompletionView.apply { tagsCompletionView.apply {
threshold = 1 threshold = 1
setAdapter(tagsAdapter) setAdapter(tagsAdapter)
} }
tagsContainerView.visibility = if (database?.allowTags() == true) View.VISIBLE else View.GONE tagsContainerView.visibility = if (database.allowTags()) View.VISIBLE else View.GONE
} }
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {

View File

@@ -45,10 +45,10 @@ class IconEditDialogFragment : DatabaseDialogFragment() {
private var mCustomIcon: IconImageCustom? = null private var mCustomIcon: IconImageCustom? = null
override fun onDatabaseRetrieved(database: ContextualDatabase?) { override fun onDatabaseRetrieved(database: ContextualDatabase) {
super.onDatabaseRetrieved(database) super.onDatabaseRetrieved(database)
mPopulateIconMethod = { imageView, icon -> mPopulateIconMethod = { imageView, icon ->
database?.iconDrawableFactory?.assignDatabaseIcon(imageView, icon) database.iconDrawableFactory.assignDatabaseIcon(imageView, icon)
} }
mCustomIcon?.let { customIcon -> mCustomIcon?.let { customIcon ->
populateViewsWithCustomIcon(customIcon) populateViewsWithCustomIcon(customIcon)

View File

@@ -43,7 +43,9 @@ abstract class DatabaseFragment : Fragment(), DatabaseRetrieval {
lifecycleScope.launch { lifecycleScope.launch {
repeatOnLifecycle(Lifecycle.State.RESUMED) { repeatOnLifecycle(Lifecycle.State.RESUMED) {
mDatabaseViewModel.databaseState.collect { database -> mDatabaseViewModel.databaseState.collect { database ->
onDatabaseRetrieved(database) database?.let {
onDatabaseRetrieved(database)
}
} }
} }
} }

View File

@@ -273,13 +273,13 @@ class EntryEditFragment: DatabaseFragment() {
} }
} }
override fun onDatabaseRetrieved(database: ContextualDatabase?) { override fun onDatabaseRetrieved(database: ContextualDatabase) {
templateView.populateIconMethod = { imageView, icon -> templateView.populateIconMethod = { imageView, icon ->
database?.iconDrawableFactory?.assignDatabaseIcon(imageView, icon, mIconColor) database.iconDrawableFactory.assignDatabaseIcon(imageView, icon, mIconColor)
} }
mAllowMultipleAttachments = database?.allowMultipleAttachments == true mAllowMultipleAttachments = database.allowMultipleAttachments == true
attachmentsAdapter?.database = database attachmentsAdapter?.database = database
attachmentsAdapter?.onListSizeChangedListener = { previousSize, newSize -> attachmentsAdapter?.onListSizeChangedListener = { previousSize, newSize ->
@@ -290,12 +290,12 @@ class EntryEditFragment: DatabaseFragment() {
} }
} }
tagsAdapter = TagsProposalAdapter(requireContext(), database?.tagPool) tagsAdapter = TagsProposalAdapter(requireContext(), database.tagPool)
tagsCompletionView.apply { tagsCompletionView.apply {
threshold = 1 threshold = 1
setAdapter(tagsAdapter) setAdapter(tagsAdapter)
} }
tagsContainerView.visibility = if (database?.allowTags() == true) View.VISIBLE else View.GONE tagsContainerView.visibility = if (database.allowTags()) View.VISIBLE else View.GONE
} }
private fun assignEntryInfo(entryInfo: EntryInfo?) { private fun assignEntryInfo(entryInfo: EntryInfo?) {

View File

@@ -133,7 +133,7 @@ class EntryFragment: DatabaseFragment() {
} }
} }
override fun onDatabaseRetrieved(database: ContextualDatabase?) { override fun onDatabaseRetrieved(database: ContextualDatabase) {
context?.let { context -> context?.let { context ->
attachmentsAdapter = EntryAttachmentsItemsAdapter(context) attachmentsAdapter = EntryAttachmentsItemsAdapter(context)
attachmentsAdapter?.database = database attachmentsAdapter?.database = database

View File

@@ -154,46 +154,44 @@ class GroupFragment : DatabaseFragment(), SortDialogFragment.SortSelectionListen
super.onDetach() super.onDetach()
} }
override fun onDatabaseRetrieved(database: ContextualDatabase?) { override fun onDatabaseRetrieved(database: ContextualDatabase) {
context?.let { context -> context?.let { context ->
database?.let { database -> mAdapter = NodesAdapter(context, database).apply {
mAdapter = NodesAdapter(context, database).apply { setOnNodeClickListener(object : NodesAdapter.NodeClickCallback {
setOnNodeClickListener(object : NodesAdapter.NodeClickCallback { override fun onNodeClick(database: ContextualDatabase, node: Node) {
override fun onNodeClick(database: ContextualDatabase, node: Node) { if (nodeActionSelectionMode) {
if (nodeActionSelectionMode) { if (listActionNodes.contains(node)) {
if (listActionNodes.contains(node)) { // Remove selected item if already selected
// Remove selected item if already selected listActionNodes.remove(node)
listActionNodes.remove(node)
} else {
// Add selected item if not already selected
listActionNodes.add(node)
}
nodeClickListener?.onNodeSelected(database, listActionNodes)
setActionNodes(listActionNodes)
notifyNodeChanged(node)
} else { } else {
nodeClickListener?.onNodeClick(database, node) // Add selected item if not already selected
listActionNodes.add(node)
} }
nodeClickListener?.onNodeSelected(database, listActionNodes)
setActionNodes(listActionNodes)
notifyNodeChanged(node)
} else {
nodeClickListener?.onNodeClick(database, node)
} }
}
override fun onNodeLongClick(database: ContextualDatabase, node: Node): Boolean { override fun onNodeLongClick(database: ContextualDatabase, node: Node): Boolean {
if (nodeActionPasteMode == PasteMode.UNDEFINED) { if (nodeActionPasteMode == PasteMode.UNDEFINED) {
// Select the first item after a long click // Select the first item after a long click
if (!listActionNodes.contains(node)) if (!listActionNodes.contains(node))
listActionNodes.add(node) listActionNodes.add(node)
nodeClickListener?.onNodeSelected(database, listActionNodes) nodeClickListener?.onNodeSelected(database, listActionNodes)
setActionNodes(listActionNodes) setActionNodes(listActionNodes)
notifyNodeChanged(node) notifyNodeChanged(node)
activity?.hideKeyboard() activity?.hideKeyboard()
}
return true
} }
}) return true
} }
mNodesRecyclerView?.adapter = mAdapter })
} }
mNodesRecyclerView?.adapter = mAdapter
} }
} }

View File

@@ -71,8 +71,8 @@ abstract class IconFragment<T: IconImageDraw> : DatabaseFragment(),
resetAppTimeoutWhenViewFocusedOrChanged(view) resetAppTimeoutWhenViewFocusedOrChanged(view)
} }
override fun onDatabaseRetrieved(database: ContextualDatabase?) { override fun onDatabaseRetrieved(database: ContextualDatabase) {
iconPickerAdapter.iconDrawableFactory = database?.iconDrawableFactory iconPickerAdapter.iconDrawableFactory = database.iconDrawableFactory
CoroutineScope(Dispatchers.IO).launch { CoroutineScope(Dispatchers.IO).launch {
val populateList = launch { val populateList = launch {

View File

@@ -48,9 +48,9 @@ class IconPickerFragment : DatabaseFragment() {
} }
} }
override fun onDatabaseRetrieved(database: ContextualDatabase?) { override fun onDatabaseRetrieved(database: ContextualDatabase) {
iconPickerPagerAdapter = IconPickerPagerAdapter(this, iconPickerPagerAdapter = IconPickerPagerAdapter(this,
if (database?.allowCustomIcons == true) 2 else 1) if (database.allowCustomIcons) 2 else 1)
viewPager.adapter = iconPickerPagerAdapter viewPager.adapter = iconPickerPagerAdapter
TabLayoutMediator(tabLayout, viewPager) { tab, position -> TabLayoutMediator(tabLayout, viewPager) { tab, position ->
tab.text = when (position) { tab.text = when (position) {

View File

@@ -107,7 +107,7 @@ class KeyGeneratorFragment : DatabaseFragment() {
super.onDestroyView() super.onDestroyView()
} }
override fun onDatabaseRetrieved(database: ContextualDatabase?) { override fun onDatabaseRetrieved(database: ContextualDatabase) {
// Nothing here // Nothing here
} }

View File

@@ -244,7 +244,7 @@ class PassphraseGeneratorFragment : DatabaseFragment() {
} }
} }
override fun onDatabaseRetrieved(database: ContextualDatabase?) { override fun onDatabaseRetrieved(database: ContextualDatabase) {
// Nothing here // Nothing here
} }

View File

@@ -320,7 +320,7 @@ class PasswordGeneratorFragment : DatabaseFragment() {
super.onDestroy() super.onDestroy()
} }
override fun onDatabaseRetrieved(database: ContextualDatabase?) { override fun onDatabaseRetrieved(database: ContextualDatabase) {
// Nothing here // Nothing here
} }

View File

@@ -111,13 +111,24 @@ abstract class DatabaseActivity : StylishActivity(), DatabaseRetrieval {
lifecycleScope.launch { lifecycleScope.launch {
repeatOnLifecycle(Lifecycle.State.RESUMED) { repeatOnLifecycle(Lifecycle.State.RESUMED) {
mDatabaseViewModel.databaseState.collect { database -> mDatabaseViewModel.databaseState.collect { database ->
onDatabaseRetrieved(database) // Nullable function
onUnknownDatabaseRetrieved(database)
database?.let {
onDatabaseRetrieved(database)
}
} }
} }
} }
} }
override fun onDatabaseRetrieved(database: ContextualDatabase?) { /**
* Nullable function to retrieve a database
*/
open fun onUnknownDatabaseRetrieved(database: ContextualDatabase?) {
// optional method implementation
}
override fun onDatabaseRetrieved(database: ContextualDatabase) {
// optional method implementation // optional method implementation
} }

View File

@@ -90,48 +90,41 @@ abstract class DatabaseLockActivity : DatabaseModeActivity(),
mExitLock = false mExitLock = false
} }
open fun finishActivityIfDatabaseNotLoaded(): Boolean { override fun onDatabaseRetrieved(database: ContextualDatabase) {
return true
}
override fun onDatabaseRetrieved(database: ContextualDatabase?) {
// End activity if database not loaded // End activity if database not loaded
if (finishActivityIfDatabaseNotLoaded() && (database != null && !database.loaded)) { if (database.loaded.not())
finish() finish()
}
// Focus view to reinitialize timeout, // Focus view to reinitialize timeout,
// view is not necessary loaded so retry later in resume // view is not necessary loaded so retry later in resume
viewToInvalidateTimeout() viewToInvalidateTimeout()
?.resetAppTimeoutWhenViewTouchedOrFocused(this, database?.loaded) ?.resetAppTimeoutWhenViewTouchedOrFocused(this, database.loaded)
database?.let { // check timeout
// check timeout if (mTimeoutEnable) {
if (mTimeoutEnable) { if (mLockReceiver == null) {
if (mLockReceiver == null) { mLockReceiver = LockReceiver {
mLockReceiver = LockReceiver { closeDatabase(database)
closeDatabase(database) mExitLock = true
mExitLock = true closeOptionsMenu()
closeOptionsMenu() finish()
finish()
}
registerLockReceiver(mLockReceiver)
} }
registerLockReceiver(mLockReceiver)
// After the first creation
// or If simply swipe with another application
// If the time is out -> close the Activity
TimeoutHelper.checkTimeAndLockIfTimeout(this)
// If onCreate already record time
if (!mExitLock)
TimeoutHelper.recordTime(this, database.loaded)
} }
mDatabaseReadOnly = database.isReadOnly // After the first creation
mMergeDataAllowed = database.isMergeDataAllowed() // or If simply swipe with another application
// If the time is out -> close the Activity
checkRegister() TimeoutHelper.checkTimeAndLockIfTimeout(this)
// If onCreate already record time
if (!mExitLock)
TimeoutHelper.recordTime(this, database.loaded)
} }
mDatabaseReadOnly = database.isReadOnly
mMergeDataAllowed = database.isMergeDataAllowed()
checkRegister()
} }
override fun finish() { override fun finish() {

View File

@@ -4,8 +4,11 @@ import com.kunzisoft.keepass.database.ContextualDatabase
import com.kunzisoft.keepass.tasks.ActionRunnable import com.kunzisoft.keepass.tasks.ActionRunnable
interface DatabaseRetrieval { interface DatabaseRetrieval {
fun onDatabaseRetrieved(database: ContextualDatabase?) fun onDatabaseRetrieved(database: ContextualDatabase)
fun onDatabaseActionFinished(database: ContextualDatabase,
actionTask: String, fun onDatabaseActionFinished(
result: ActionRunnable.Result) database: ContextualDatabase,
actionTask: String,
result: ActionRunnable.Result
)
} }

View File

@@ -152,8 +152,8 @@ class AutofillLauncherActivity : DatabaseModeActivity() {
} }
} }
override fun onDatabaseRetrieved(database: ContextualDatabase?) { override fun onUnknownDatabaseRetrieved(database: ContextualDatabase?) {
super.onDatabaseRetrieved(database) super.onUnknownDatabaseRetrieved(database)
autofillLauncherViewModel.launchActionIfNeeded(intent, mSpecialMode, database) autofillLauncherViewModel.launchActionIfNeeded(intent, mSpecialMode, database)
} }

View File

@@ -51,8 +51,8 @@ class EntrySelectionLauncherActivity : DatabaseModeActivity() {
return false return false
} }
override fun onDatabaseRetrieved(database: ContextualDatabase?) { override fun onUnknownDatabaseRetrieved(database: ContextualDatabase?) {
super.onDatabaseRetrieved(database) super.onUnknownDatabaseRetrieved(database)
val keySelectionBundle = intent.getBundleExtra(KEY_SELECTION_BUNDLE) val keySelectionBundle = intent.getBundleExtra(KEY_SELECTION_BUNDLE)
if (keySelectionBundle != null) { if (keySelectionBundle != null) {

View File

@@ -81,10 +81,6 @@ class PasskeyLauncherActivity : DatabaseLockActivity() {
return false return false
} }
override fun finishActivityIfDatabaseNotLoaded(): Boolean {
return false
}
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
lifecycleScope.launch { lifecycleScope.launch {
@@ -167,11 +163,9 @@ class PasskeyLauncherActivity : DatabaseLockActivity() {
} }
} }
override fun onDatabaseRetrieved(database: ContextualDatabase?) { override fun onUnknownDatabaseRetrieved(database: ContextualDatabase?) {
super.onDatabaseRetrieved(database) super.onUnknownDatabaseRetrieved(database)
if (database != null) { passkeyLauncherViewModel.launchActionIfNeeded(intent, mSpecialMode, database)
passkeyLauncherViewModel.launchActionIfNeeded(intent, mSpecialMode, database)
}
} }
override fun onDatabaseActionFinished( override fun onDatabaseActionFinished(

View File

@@ -99,11 +99,11 @@ class PasskeyProviderService : CredentialProviderService() {
override fun onBeginGetCredentialRequest( override fun onBeginGetCredentialRequest(
request: BeginGetCredentialRequest, request: BeginGetCredentialRequest,
cancellationSignal: CancellationSignal, cancellationSignal: CancellationSignal,
callback: OutcomeReceiver<BeginGetCredentialResponse, GetCredentialException>, callback: OutcomeReceiver<BeginGetCredentialResponse, GetCredentialException>
) { ) {
Log.d(javaClass.simpleName, "onBeginGetCredentialRequest called") Log.d(javaClass.simpleName, "onBeginGetCredentialRequest called")
try { try {
processGetCredentialsRequest(request)?.let { response -> processGetCredentialsRequest(request) { response ->
callback.onResult(response) callback.onResult(response)
} }
} catch (e: Exception) { } catch (e: Exception) {
@@ -112,19 +112,24 @@ class PasskeyProviderService : CredentialProviderService() {
} }
} }
private fun processGetCredentialsRequest(request: BeginGetCredentialRequest): BeginGetCredentialResponse? { private fun processGetCredentialsRequest(
val credentialEntries: MutableList<CredentialEntry> = mutableListOf() request: BeginGetCredentialRequest,
callback: (BeginGetCredentialResponse?) -> Unit
) {
var knownOption = false
for (option in request.beginGetCredentialOptions) { for (option in request.beginGetCredentialOptions) {
when (option) { when (option) {
is BeginGetPublicKeyCredentialOption -> { is BeginGetPublicKeyCredentialOption -> {
knownOption = true
populatePasskeyData(option) { listCredentials -> populatePasskeyData(option) { listCredentials ->
credentialEntries.addAll(listCredentials) callback(BeginGetCredentialResponse(listCredentials))
} }
return BeginGetCredentialResponse(credentialEntries)
} }
} }
} }
throw IOException("unknown type of beginGetCredentialOption") if (knownOption.not()) {
throw IOException("unknown type of beginGetCredentialOption")
}
} }
private fun populatePasskeyData( private fun populatePasskeyData(

View File

@@ -38,7 +38,6 @@ import java.io.IOException
class AutofillLauncherViewModel(application: Application): CredentialLauncherViewModel(application) { class AutofillLauncherViewModel(application: Application): CredentialLauncherViewModel(application) {
private var mAutofillComponent: AutofillComponent? = null private var mAutofillComponent: AutofillComponent? = null
private var mSelectionResult: ActivityResult? = null
private var mLockDatabaseAfterSelection: Boolean = false private var mLockDatabaseAfterSelection: Boolean = false
@@ -52,16 +51,6 @@ class AutofillLauncherViewModel(application: Application): CredentialLauncherVie
override fun onResult() { override fun onResult() {
super.onResult() super.onResult()
mAutofillComponent = null mAutofillComponent = null
mSelectionResult = null
}
override fun onDatabaseRetrieved(database: ContextualDatabase?) {
super.onDatabaseRetrieved(database)
if (database != null) {
mSelectionResult?.let { selectionResult ->
manageSelectionResult(database, selectionResult)
}
}
} }
override suspend fun launchAction( override suspend fun launchAction(
@@ -151,26 +140,11 @@ class AutofillLauncherViewModel(application: Application): CredentialLauncherVie
} }
} }
override fun manageSelectionResult(activityResult: ActivityResult) { override fun manageSelectionResult(
// Waiting for the database if needed
when (activityResult.resultCode) {
RESULT_OK -> {
mSelectionResult = activityResult
mDatabase?.let { database ->
manageSelectionResult(database, activityResult)
}
}
RESULT_CANCELED -> {
cancelResult()
}
}
}
private fun manageSelectionResult(
database: ContextualDatabase, database: ContextualDatabase,
activityResult: ActivityResult activityResult: ActivityResult
) { ) {
mSelectionResult = null super.manageSelectionResult(database, activityResult)
val intent = activityResult.data val intent = activityResult.data
viewModelScope.launch(CoroutineExceptionHandler { _, e -> viewModelScope.launch(CoroutineExceptionHandler { _, e ->
Log.e(TAG, "Unable to create selection response for autofill", e) Log.e(TAG, "Unable to create selection response for autofill", e)

View File

@@ -23,6 +23,7 @@ abstract class CredentialLauncherViewModel(application: Application): AndroidVie
protected var mDatabase: ContextualDatabase? = null protected var mDatabase: ContextualDatabase? = null
protected var isResultLauncherRegistered: Boolean = false protected var isResultLauncherRegistered: Boolean = false
private var mSelectionResult: ActivityResult? = null
protected val mCredentialUiState = MutableStateFlow<UIState>(UIState.Loading) protected val mCredentialUiState = MutableStateFlow<UIState>(UIState.Loading)
val credentialUiState: StateFlow<UIState> = mCredentialUiState val credentialUiState: StateFlow<UIState> = mCredentialUiState
@@ -34,6 +35,7 @@ abstract class CredentialLauncherViewModel(application: Application): AndroidVie
open fun onResult() { open fun onResult() {
isResultLauncherRegistered = false isResultLauncherRegistered = false
mSelectionResult = null
} }
fun setResult(intent: Intent, lockDatabase: Boolean = false) { fun setResult(intent: Intent, lockDatabase: Boolean = false) {
@@ -54,11 +56,31 @@ abstract class CredentialLauncherViewModel(application: Application): AndroidVie
) )
} }
open fun onDatabaseRetrieved(database: ContextualDatabase?) { private fun onDatabaseRetrieved(database: ContextualDatabase) {
mDatabase = database mDatabase = database
mSelectionResult?.let { selectionResult ->
manageSelectionResult(database, selectionResult)
}
} }
abstract fun manageSelectionResult(activityResult: ActivityResult) fun manageSelectionResult(activityResult: ActivityResult) {
// Waiting for the database if needed
when (activityResult.resultCode) {
RESULT_OK -> {
mSelectionResult = activityResult
mDatabase?.let { database ->
manageSelectionResult(database, activityResult)
}
}
RESULT_CANCELED -> {
cancelResult()
}
}
}
open fun manageSelectionResult(database: ContextualDatabase, activityResult: ActivityResult) {
mSelectionResult = null
}
abstract fun manageRegistrationResult(activityResult: ActivityResult) abstract fun manageRegistrationResult(activityResult: ActivityResult)
@@ -66,12 +88,14 @@ abstract class CredentialLauncherViewModel(application: Application): AndroidVie
showError(e) showError(e)
} }
fun launchActionIfNeeded( open fun launchActionIfNeeded(
intent: Intent, intent: Intent,
specialMode: SpecialMode, specialMode: SpecialMode,
database: ContextualDatabase? database: ContextualDatabase?
) { ) {
onDatabaseRetrieved(database) database?.let {
onDatabaseRetrieved(database)
}
if (isResultLauncherRegistered.not()) { if (isResultLauncherRegistered.not()) {
isResultLauncherRegistered = true isResultLauncherRegistered = true
viewModelScope.launch(CoroutineExceptionHandler { _, e -> viewModelScope.launch(CoroutineExceptionHandler { _, e ->

View File

@@ -147,6 +147,17 @@ class PasskeyLauncherViewModel(application: Application): CredentialLauncherView
} }
} }
override fun launchActionIfNeeded(
intent: Intent,
specialMode: SpecialMode,
database: ContextualDatabase?
) {
// Launch with database when a nodeId is present
if (database != null || intent.retrieveNodeId() == null) {
super.launchActionIfNeeded(intent, specialMode, database)
}
}
override suspend fun launchAction( override suspend fun launchAction(
intent: Intent, intent: Intent,
specialMode: SpecialMode, specialMode: SpecialMode,
@@ -305,7 +316,11 @@ class PasskeyLauncherViewModel(application: Application): CredentialLauncherView
} }
} }
override fun manageSelectionResult(activityResult: ActivityResult) { override fun manageSelectionResult(
database: ContextualDatabase,
activityResult: ActivityResult
) {
super.manageSelectionResult(database, activityResult)
val intent = activityResult.data val intent = activityResult.data
viewModelScope.launch(CoroutineExceptionHandler { _, e -> viewModelScope.launch(CoroutineExceptionHandler { _, e ->
Log.e(TAG, "Unable to create selection response for passkey", e) Log.e(TAG, "Unable to create selection response for passkey", e)

View File

@@ -48,7 +48,7 @@ class HardwareKeyActivity: DatabaseModeActivity(){
return false return false
} }
override fun onDatabaseRetrieved(database: ContextualDatabase?) { override fun onDatabaseRetrieved(database: ContextualDatabase) {
val hardwareKey = HardwareKey.getHardwareKeyFromString( val hardwareKey = HardwareKey.getHardwareKeyFromString(
intent.getStringExtra(DATA_HARDWARE_KEY) intent.getStringExtra(DATA_HARDWARE_KEY)
) )

View File

@@ -165,7 +165,9 @@ class NestedDatabaseSettingsFragment : NestedSettingsFragment(), DatabaseRetriev
lifecycleScope.launch { lifecycleScope.launch {
repeatOnLifecycle(Lifecycle.State.RESUMED) { repeatOnLifecycle(Lifecycle.State.RESUMED) {
mDatabaseViewModel.databaseState.collect { database -> mDatabaseViewModel.databaseState.collect { database ->
onDatabaseRetrieved(database) database?.let {
onDatabaseRetrieved(database)
}
} }
} }
} }
@@ -221,28 +223,26 @@ class NestedDatabaseSettingsFragment : NestedSettingsFragment(), DatabaseRetriev
mDatabaseViewModel.reloadDatabase(false) mDatabaseViewModel.reloadDatabase(false)
} }
override fun onDatabaseRetrieved(database: ContextualDatabase?) { override fun onDatabaseRetrieved(database: ContextualDatabase) {
mDatabaseReadOnly = database?.isReadOnly == true mDatabaseReadOnly = database.isReadOnly
mMergeDataAllowed = database?.isMergeDataAllowed() == true mMergeDataAllowed = database.isMergeDataAllowed()
database?.let { if (database.loaded) {
if (it.loaded) { when (mScreen) {
when (mScreen) { Screen.DATABASE -> {
Screen.DATABASE -> { onCreateDatabasePreference(database)
onCreateDatabasePreference(it) }
} Screen.DATABASE_SECURITY -> {
Screen.DATABASE_SECURITY -> { onCreateDatabaseSecurityPreference(database)
onCreateDatabaseSecurityPreference(it) }
} Screen.DATABASE_MASTER_KEY -> {
Screen.DATABASE_MASTER_KEY -> { onCreateDatabaseMasterKeyPreference(database)
onCreateDatabaseMasterKeyPreference(it) }
} else -> {
else -> {
}
} }
} else {
Log.e(javaClass.name, "Database isn't ready")
} }
} else {
Log.e(javaClass.name, "Database isn't ready")
} }
} }

View File

@@ -159,10 +159,6 @@ open class SettingsActivity
return coordinatorLayout return coordinatorLayout
} }
override fun finishActivityIfDatabaseNotLoaded(): Boolean {
return false
}
override fun onDatabaseActionFinished( override fun onDatabaseActionFinished(
database: ContextualDatabase, database: ContextualDatabase,
actionTask: String, actionTask: String,

View File

@@ -95,18 +95,16 @@ class DatabaseColorPreferenceDialogFragmentCompat : DatabaseSavePreferenceDialog
return dialog return dialog
} }
override fun onDatabaseRetrieved(database: ContextualDatabase?) { override fun onDatabaseRetrieved(database: ContextualDatabase) {
database?.let { var initColor = database.customColor
var initColor = it.customColor if (initColor != null) {
if (initColor != null) { enableSwitchView.isChecked = true
enableSwitchView.isChecked = true } else {
} else { enableSwitchView.isChecked = false
enableSwitchView.isChecked = false initColor = DEFAULT_COLOR
initColor = DEFAULT_COLOR
}
chromaColorView.currentColor = initColor
arguments?.putInt(ARG_INITIAL_COLOR, initColor)
} }
chromaColorView.currentColor = initColor
arguments?.putInt(ARG_INITIAL_COLOR, initColor)
} }
override fun onDialogClosed(database: ContextualDatabase?, positiveResult: Boolean) { override fun onDialogClosed(database: ContextualDatabase?, positiveResult: Boolean) {

View File

@@ -50,15 +50,14 @@ class DatabaseDataCompressionPreferenceDialogFragmentCompat
} }
} }
override fun onDatabaseRetrieved(database: ContextualDatabase?) { override fun onDatabaseRetrieved(database: ContextualDatabase) {
setExplanationText(R.string.database_data_compression_summary) setExplanationText(R.string.database_data_compression_summary)
mRecyclerView?.adapter = mCompressionAdapter mRecyclerView?.adapter = mCompressionAdapter
compressionSelected = database.compressionAlgorithm
database?.let { mCompressionAdapter?.setItems(
compressionSelected = it.compressionAlgorithm items = database.availableCompressionAlgorithms,
mCompressionAdapter?.setItems(it.availableCompressionAlgorithms, compressionSelected) itemUsed = compressionSelected
} )
} }
override fun onDialogClosed(database: ContextualDatabase?, positiveResult: Boolean) { override fun onDialogClosed(database: ContextualDatabase?, positiveResult: Boolean) {

View File

@@ -24,8 +24,8 @@ import com.kunzisoft.keepass.database.ContextualDatabase
class DatabaseDefaultUsernamePreferenceDialogFragmentCompat : DatabaseSavePreferenceDialogFragmentCompat() { class DatabaseDefaultUsernamePreferenceDialogFragmentCompat : DatabaseSavePreferenceDialogFragmentCompat() {
override fun onDatabaseRetrieved(database: ContextualDatabase?) { override fun onDatabaseRetrieved(database: ContextualDatabase) {
inputText = database?.defaultUsername?: "" inputText = database.defaultUsername
} }
override fun onDialogClosed(database: ContextualDatabase?, positiveResult: Boolean) { override fun onDialogClosed(database: ContextualDatabase?, positiveResult: Boolean) {

View File

@@ -24,8 +24,8 @@ import com.kunzisoft.keepass.database.ContextualDatabase
class DatabaseDescriptionPreferenceDialogFragmentCompat : DatabaseSavePreferenceDialogFragmentCompat() { class DatabaseDescriptionPreferenceDialogFragmentCompat : DatabaseSavePreferenceDialogFragmentCompat() {
override fun onDatabaseRetrieved(database: ContextualDatabase?) { override fun onDatabaseRetrieved(database: ContextualDatabase) {
inputText = database?.description ?: "" inputText = database.description
} }
override fun onDialogClosed(database: ContextualDatabase?, positiveResult: Boolean) { override fun onDialogClosed(database: ContextualDatabase?, positiveResult: Boolean) {

View File

@@ -51,11 +51,9 @@ class DatabaseEncryptionAlgorithmPreferenceDialogFragmentCompat
} }
} }
override fun onDatabaseRetrieved(database: ContextualDatabase?) { override fun onDatabaseRetrieved(database: ContextualDatabase) {
database?.let { algorithmSelected = database.encryptionAlgorithm
algorithmSelected = database.encryptionAlgorithm mEncryptionAlgorithmAdapter?.setItems(database.availableEncryptionAlgorithms, algorithmSelected)
mEncryptionAlgorithmAdapter?.setItems(database.availableEncryptionAlgorithms, algorithmSelected)
}
} }
override fun onDialogClosed(database: ContextualDatabase?, positiveResult: Boolean) { override fun onDialogClosed(database: ContextualDatabase?, positiveResult: Boolean) {

View File

@@ -54,11 +54,12 @@ class DatabaseKeyDerivationPreferenceDialogFragmentCompat
} }
} }
override fun onDatabaseRetrieved(database: ContextualDatabase?) { override fun onDatabaseRetrieved(database: ContextualDatabase) {
database?.let { kdfEngineSelected = database.kdfEngine
kdfEngineSelected = database.kdfEngine mKdfAdapter?.setItems(
mKdfAdapter?.setItems(database.availableKdfEngines, kdfEngineSelected) items = database.availableKdfEngines,
} itemUsed = kdfEngineSelected
)
} }
override fun onDialogClosed(database: ContextualDatabase?, positiveResult: Boolean) { override fun onDialogClosed(database: ContextualDatabase?, positiveResult: Boolean) {

View File

@@ -31,18 +31,17 @@ class DatabaseMaxHistoryItemsPreferenceDialogFragmentCompat : DatabaseSavePrefer
setExplanationText(R.string.max_history_items_summary) setExplanationText(R.string.max_history_items_summary)
} }
override fun onDatabaseRetrieved(database: ContextualDatabase?) { override fun onDatabaseRetrieved(database: ContextualDatabase) {
database?.historyMaxItems?.let { maxItemsDatabase -> val maxItemsDatabase = database.historyMaxItems
inputText = maxItemsDatabase.toString() inputText = maxItemsDatabase.toString()
setSwitchAction({ isChecked -> setSwitchAction({ isChecked ->
inputText = if (!isChecked) { inputText = if (!isChecked) {
NONE_MAX_HISTORY_ITEMS.toString() NONE_MAX_HISTORY_ITEMS.toString()
} else { } else {
DEFAULT_MAX_HISTORY_ITEMS.toString() DEFAULT_MAX_HISTORY_ITEMS.toString()
} }
showInputText(isChecked) showInputText(isChecked)
}, maxItemsDatabase > NONE_MAX_HISTORY_ITEMS) }, maxItemsDatabase > NONE_MAX_HISTORY_ITEMS)
}
} }
override fun onDialogClosed(database: ContextualDatabase?, positiveResult: Boolean) { override fun onDialogClosed(database: ContextualDatabase?, positiveResult: Boolean) {

View File

@@ -34,30 +34,29 @@ class DatabaseMaxHistorySizePreferenceDialogFragmentCompat : DatabaseSavePrefere
setExplanationText(R.string.max_history_size_summary) setExplanationText(R.string.max_history_size_summary)
} }
override fun onDatabaseRetrieved(database: ContextualDatabase?) { override fun onDatabaseRetrieved(database: ContextualDatabase) {
database?.historyMaxSize?.let { maxItemsDatabase -> val maxItemsDatabase = database.historyMaxSize
dataByte = DataByte(maxItemsDatabase, DataByte.ByteFormat.BYTE) dataByte = DataByte(maxItemsDatabase, DataByte.ByteFormat.BYTE)
.toBetterByteFormat() .toBetterByteFormat()
inputText = dataByte.number.toString() inputText = dataByte.number.toString()
if (dataByte.number >= 0) { if (dataByte.number >= 0) {
setUnitText(dataByte.format.stringId) setUnitText(dataByte.format.stringId)
} else { } else {
unitText = null unitText = null
}
setSwitchAction({ isChecked ->
if (!isChecked) {
dataByte = INFINITE_MAX_HISTORY_SIZE_DATA_BYTE
inputText = INFINITE_MAX_HISTORY_SIZE.toString()
unitText = null
} else {
dataByte = DEFAULT_MAX_HISTORY_SIZE_DATA_BYTE
inputText = dataByte.number.toString()
setUnitText(dataByte.format.stringId)
}
showInputText(isChecked)
}, maxItemsDatabase > INFINITE_MAX_HISTORY_SIZE)
} }
setSwitchAction({ isChecked ->
if (!isChecked) {
dataByte = INFINITE_MAX_HISTORY_SIZE_DATA_BYTE
inputText = INFINITE_MAX_HISTORY_SIZE.toString()
unitText = null
} else {
dataByte = DEFAULT_MAX_HISTORY_SIZE_DATA_BYTE
inputText = dataByte.number.toString()
setUnitText(dataByte.format.stringId)
}
showInputText(isChecked)
}, maxItemsDatabase > INFINITE_MAX_HISTORY_SIZE)
} }
override fun onDialogClosed(database: ContextualDatabase?, positiveResult: Boolean) { override fun onDialogClosed(database: ContextualDatabase?, positiveResult: Boolean) {

View File

@@ -34,14 +34,12 @@ class DatabaseMemoryUsagePreferenceDialogFragmentCompat : DatabaseSavePreference
setExplanationText(R.string.memory_usage_explanation) setExplanationText(R.string.memory_usage_explanation)
} }
override fun onDatabaseRetrieved(database: ContextualDatabase?) { override fun onDatabaseRetrieved(database: ContextualDatabase) {
database?.let { val memoryBytes = database.memoryUsage
val memoryBytes = database.memoryUsage dataByte = DataByte(memoryBytes, DataByte.ByteFormat.BYTE)
dataByte = DataByte(memoryBytes, DataByte.ByteFormat.BYTE) .toBetterByteFormat()
.toBetterByteFormat() inputText = dataByte.number.toString()
inputText = dataByte.number.toString() setUnitText(dataByte.format.stringId)
setUnitText(dataByte.format.stringId)
}
} }
override fun onDialogClosed(database: ContextualDatabase?, positiveResult: Boolean) { override fun onDialogClosed(database: ContextualDatabase?, positiveResult: Boolean) {

View File

@@ -24,8 +24,8 @@ import com.kunzisoft.keepass.database.ContextualDatabase
class DatabaseNamePreferenceDialogFragmentCompat : DatabaseSavePreferenceDialogFragmentCompat() { class DatabaseNamePreferenceDialogFragmentCompat : DatabaseSavePreferenceDialogFragmentCompat() {
override fun onDatabaseRetrieved(database: ContextualDatabase?) { override fun onDatabaseRetrieved(database: ContextualDatabase) {
inputText = database?.name ?: "" inputText = database.name
} }
override fun onDialogClosed(database: ContextualDatabase?, positiveResult: Boolean) { override fun onDialogClosed(database: ContextualDatabase?, positiveResult: Boolean) {

View File

@@ -31,8 +31,8 @@ class DatabaseParallelismPreferenceDialogFragmentCompat : DatabaseSavePreference
setExplanationText(R.string.parallelism_explanation) setExplanationText(R.string.parallelism_explanation)
} }
override fun onDatabaseRetrieved(database: ContextualDatabase?) { override fun onDatabaseRetrieved(database: ContextualDatabase) {
inputText = database?.parallelism?.toString() ?: MIN_PARALLELISM.toString() inputText = database.parallelism.toString()
} }
override fun onDialogClosed(database: ContextualDatabase?, positiveResult: Boolean) { override fun onDialogClosed(database: ContextualDatabase?, positiveResult: Boolean) {

View File

@@ -48,11 +48,9 @@ class DatabaseRecycleBinGroupPreferenceDialogFragmentCompat
} }
} }
override fun onDatabaseRetrieved(database: ContextualDatabase?) { override fun onDatabaseRetrieved(database: ContextualDatabase) {
database?.let { mGroupRecycleBin = database.recycleBin
mGroupRecycleBin = database.recycleBin mGroupsAdapter?.setItems(database.getAllGroupsWithoutRoot(), mGroupRecycleBin)
mGroupsAdapter?.setItems(database.getAllGroupsWithoutRoot(), mGroupRecycleBin)
}
} }
override fun onItemSelected(item: Group) { override fun onItemSelected(item: Group) {

View File

@@ -46,7 +46,7 @@ class DatabaseRemoveUnlinkedDataPreferenceDialogFragmentCompat : DatabaseSavePre
} }
} }
override fun onDatabaseRetrieved(database: ContextualDatabase?) {} override fun onDatabaseRetrieved(database: ContextualDatabase) {}
companion object { companion object {

View File

@@ -32,8 +32,8 @@ class DatabaseRoundsPreferenceDialogFragmentCompat : DatabaseSavePreferenceDialo
explanationText = getString(R.string.rounds_explanation) explanationText = getString(R.string.rounds_explanation)
} }
override fun onDatabaseRetrieved(database: ContextualDatabase?) { override fun onDatabaseRetrieved(database: ContextualDatabase) {
inputText = database?.numberKeyEncryptionRounds?.toString() ?: MIN_ITERATIONS.toString() inputText = database.numberKeyEncryptionRounds.toString()
} }
override fun onDialogClosed(database: ContextualDatabase?, positiveResult: Boolean) { override fun onDialogClosed(database: ContextualDatabase?, positiveResult: Boolean) {

View File

@@ -72,7 +72,9 @@ abstract class DatabaseSavePreferenceDialogFragmentCompat
lifecycleScope.launch { lifecycleScope.launch {
repeatOnLifecycle(Lifecycle.State.RESUMED) { repeatOnLifecycle(Lifecycle.State.RESUMED) {
mDatabaseViewModel.databaseState.collect { database -> mDatabaseViewModel.databaseState.collect { database ->
onDatabaseRetrieved(database) database?.let {
onDatabaseRetrieved(database)
}
} }
} }
} }

View File

@@ -48,11 +48,9 @@ class DatabaseTemplatesGroupPreferenceDialogFragmentCompat
} }
} }
override fun onDatabaseRetrieved(database: ContextualDatabase?) { override fun onDatabaseRetrieved(database: ContextualDatabase) {
database?.let { mGroupTemplates = database.templatesGroup
mGroupTemplates = database.templatesGroup mGroupsAdapter?.setItems(database.getAllGroupsWithoutRoot(), mGroupTemplates)
mGroupsAdapter?.setItems(database.getAllGroupsWithoutRoot(), mGroupTemplates)
}
} }
override fun onItemSelected(item: Group) { override fun onItemSelected(item: Group) {