diff --git a/app/build.gradle b/app/build.gradle index f8c77f4ed..8c736e683 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -33,7 +33,6 @@ android { buildTypes { release { minifyEnabled = false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 44a807414..42eba5a23 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -160,9 +160,11 @@ android:configChanges="keyboardHidden" android:excludeFromRecents="true"/> + android:name="com.kunzisoft.keepass.settings.AdvancedUnlockSettingsActivity" /> + 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 df2177a9d..84adc6cfa 100644 --- a/app/src/main/java/com/kunzisoft/keepass/activities/EntryActivity.kt +++ b/app/src/main/java/com/kunzisoft/keepass/activities/EntryActivity.kt @@ -112,9 +112,9 @@ class EntryActivity : DatabaseLockActivity() { } private var mIcon: IconImage? = null - private var mColorAccent: Int = 0 - private var mControlColor: Int = 0 - private var mColorPrimary: Int = 0 + private var mColorSecondary: Int = 0 + private var mColorSurface: Int = 0 + private var mColorOnSurface: Int = 0 private var mColorBackground: Int = 0 private var mBackgroundColor: Int? = null private var mForegroundColor: Int? = null @@ -146,17 +146,17 @@ class EntryActivity : DatabaseLockActivity() { toolbar?.title = " " // Retrieve the textColor to tint the toolbar - val taColorAccent = theme.obtainStyledAttributes(intArrayOf(R.attr.colorAccent)) - val taControlColor = theme.obtainStyledAttributes(intArrayOf(R.attr.toolbarColorControl)) - val taColorPrimary = theme.obtainStyledAttributes(intArrayOf(R.attr.colorPrimary)) + val taColorSecondary = theme.obtainStyledAttributes(intArrayOf(R.attr.colorSecondary)) + val taColorSurface = theme.obtainStyledAttributes(intArrayOf(R.attr.colorSurface)) + val taColorOnSurface = theme.obtainStyledAttributes(intArrayOf(R.attr.colorOnSurface)) val taColorBackground = theme.obtainStyledAttributes(intArrayOf(android.R.attr.windowBackground)) - mColorAccent = taColorAccent.getColor(0, Color.BLACK) - mControlColor = taControlColor.getColor(0, Color.BLACK) - mColorPrimary = taColorPrimary.getColor(0, Color.BLACK) + mColorSecondary = taColorSecondary.getColor(0, Color.BLACK) + mColorSurface = taColorSurface.getColor(0, Color.BLACK) + mColorOnSurface = taColorOnSurface.getColor(0, Color.BLACK) mColorBackground = taColorBackground.getColor(0, Color.BLACK) - taColorAccent.recycle() - taControlColor.recycle() - taColorPrimary.recycle() + taColorSecondary.recycle() + taColorSurface.recycle() + taColorOnSurface.recycle() taColorBackground.recycle() // Init Tags adapter @@ -225,10 +225,10 @@ class EntryActivity : DatabaseLockActivity() { this.mEntryIsHistory = entryIsHistory // Assign history dedicated view historyView?.visibility = if (entryIsHistory) View.VISIBLE else View.GONE + // TODO History badge + /* if (entryIsHistory) { - collapsingToolbarLayout?.contentScrim = - ColorDrawable(mColorAccent) - } + }*/ val entryInfo = entryInfoHistory.entryInfo // Manage entry copy to start notification if allowed (at the first start) @@ -366,8 +366,8 @@ class EntryActivity : DatabaseLockActivity() { } private fun applyToolbarColors() { - appBarLayout?.setBackgroundColor(mBackgroundColor ?: mColorPrimary) - collapsingToolbarLayout?.contentScrim = ColorDrawable(mBackgroundColor ?: mColorPrimary) + collapsingToolbarLayout?.setBackgroundColor(mBackgroundColor ?: mColorSurface) + collapsingToolbarLayout?.contentScrim = ColorDrawable(mBackgroundColor ?: mColorSurface) val backgroundDarker = if (mBackgroundColor != null) { ColorUtils.blendARGB(mBackgroundColor!!, Color.WHITE, 0.1f) } else { @@ -380,12 +380,12 @@ class EntryActivity : DatabaseLockActivity() { mDatabase?.iconDrawableFactory?.assignDatabaseIcon( iconView, icon, - mForegroundColor ?: mColorAccent + mForegroundColor ?: mColorSecondary ) } } - toolbar?.changeControlColor(mForegroundColor ?: mControlColor) - collapsingToolbarLayout?.changeTitleColor(mForegroundColor ?: mControlColor) + toolbar?.changeControlColor(mForegroundColor ?: mColorOnSurface) + collapsingToolbarLayout?.changeTitleColor(mForegroundColor ?: mColorOnSurface) } override fun onCreateOptionsMenu(menu: Menu): Boolean { 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 7408c9f89..b04c8091f 100644 --- a/app/src/main/java/com/kunzisoft/keepass/activities/EntryEditActivity.kt +++ b/app/src/main/java/com/kunzisoft/keepass/activities/EntryEditActivity.kt @@ -19,8 +19,6 @@ package com.kunzisoft.keepass.activities import android.app.Activity -import android.app.DatePickerDialog -import android.app.TimePickerDialog import android.content.Context import android.content.Intent import android.net.Uri @@ -33,10 +31,8 @@ import android.view.Menu import android.view.MenuItem import android.view.View 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 @@ -48,16 +44,16 @@ import androidx.core.view.isVisible import androidx.core.widget.NestedScrollView import androidx.fragment.app.Fragment import androidx.fragment.app.FragmentActivity +import com.google.android.material.datepicker.MaterialDatePicker import com.google.android.material.snackbar.Snackbar +import com.google.android.material.timepicker.MaterialTimePicker import com.kunzisoft.keepass.R 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 @@ -90,8 +86,8 @@ 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.getParcelableExtraCompat import com.kunzisoft.keepass.utils.UriUtil.getDocumentFile +import com.kunzisoft.keepass.utils.getParcelableExtraCompat import com.kunzisoft.keepass.view.ToolbarAction import com.kunzisoft.keepass.view.asError import com.kunzisoft.keepass.view.hideByFading @@ -99,14 +95,11 @@ 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.UUID class EntryEditActivity : DatabaseLockActivity(), EntryCustomFieldDialogFragment.EntryCustomFieldListener, SetOTPDialogFragment.CreateOtpListener, - DatePickerDialog.OnDateSetListener, - TimePickerDialog.OnTimeSetListener, FileTooBigDialogFragment.ActionChooseListener, ReplaceFileDialogFragment.ActionChooseListener { @@ -291,14 +284,20 @@ class EntryEditActivity : DatabaseLockActivity(), mEntryEditViewModel.requestDateTimeSelection.observe(this) { dateInstant -> if (dateInstant.type == DateInstant.Type.TIME) { // Launch the time picker - val dateTime = DateTime(dateInstant.date) - TimePickerFragment.getInstance(dateTime.hourOfDay, dateTime.minuteOfHour) - .show(supportFragmentManager, "TimePickerFragment") + MaterialTimePicker.Builder().build().apply { + addOnPositiveButtonClickListener { + mEntryEditViewModel.selectTime(this.hour, this.minute) + } + show(supportFragmentManager, "TimePickerFragment") + } } else { // Launch the date picker - val dateTime = DateTime(dateInstant.date) - DatePickerFragment.getInstance(dateTime.year, dateTime.monthOfYear - 1, dateTime.dayOfMonth) - .show(supportFragmentManager, "DatePickerFragment") + MaterialDatePicker.Builder.datePicker().build().apply { + addOnPositiveButtonClickListener { + mEntryEditViewModel.selectDate(it) + } + show(supportFragmentManager, "DatePickerFragment") + } } } @@ -684,18 +683,6 @@ class EntryEditActivity : DatabaseLockActivity(), return super.onOptionsItemSelected(item) } - override fun onDateSet(datePicker: DatePicker?, year: Int, month: Int, day: Int) { - // To fix android 4.4 issue - // https://stackoverflow.com/questions/12436073/datepicker-ondatechangedlistener-called-twice - if (datePicker?.isShown == true) { - mEntryEditViewModel.selectDate(year, month, day) - } - } - - override fun onTimeSet(timePicker: TimePicker?, hours: Int, minutes: Int) { - mEntryEditViewModel.selectTime(hours, minutes) - } - override fun onBackPressed() { onApprovedBackPressed { super@EntryEditActivity.onBackPressed() 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 c766bf550..2bba90ec0 100644 --- a/app/src/main/java/com/kunzisoft/keepass/activities/GroupActivity.kt +++ b/app/src/main/java/com/kunzisoft/keepass/activities/GroupActivity.kt @@ -19,9 +19,7 @@ package com.kunzisoft.keepass.activities import android.app.Activity -import android.app.DatePickerDialog import android.app.SearchManager -import android.app.TimePickerDialog import android.content.ComponentName import android.content.Context import android.content.Intent @@ -38,11 +36,9 @@ import android.view.Menu import android.view.MenuItem import android.view.View import android.view.ViewGroup -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 @@ -59,13 +55,13 @@ import androidx.core.view.WindowInsetsControllerCompat import androidx.core.view.isVisible import androidx.drawerlayout.widget.DrawerLayout import androidx.recyclerview.widget.RecyclerView +import com.google.android.material.datepicker.MaterialDatePicker +import com.google.android.material.timepicker.MaterialTimePicker import com.kunzisoft.keepass.R -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 @@ -100,12 +96,12 @@ 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.openUrl import com.kunzisoft.keepass.utils.getParcelableCompat import com.kunzisoft.keepass.utils.getParcelableExtraCompat import com.kunzisoft.keepass.utils.getParcelableList import com.kunzisoft.keepass.utils.putParcelableList import com.kunzisoft.keepass.utils.readParcelableCompat -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 @@ -115,12 +111,9 @@ 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 class GroupActivity : DatabaseLockActivity(), - DatePickerDialog.OnDateSetListener, - TimePickerDialog.OnTimeSetListener, GroupFragment.NodeClickListener, GroupFragment.NodesActionMenuListener, GroupFragment.OnScrollListener, @@ -140,7 +133,6 @@ class GroupActivity : DatabaseLockActivity(), private var databaseNameView: TextView? = null private var searchView: SearchView? = null private var searchFiltersView: SearchFiltersView? = null - private var toolbarBreadcrumb: Toolbar? = null private var toolbarAction: ToolbarAction? = null private var numberChildrenView: TextView? = null private var addNodeButtonView: AddNodeButtonView? = null @@ -277,7 +269,6 @@ class GroupActivity : DatabaseLockActivity(), databaseColorView = findViewById(R.id.database_color) databaseNameView = findViewById(R.id.database_name) searchFiltersView = findViewById(R.id.search_filters) - toolbarBreadcrumb = findViewById(R.id.toolbar_breadcrumb) breadcrumbListView = findViewById(R.id.breadcrumb_list) toolbarAction = findViewById(R.id.toolbar_action) lockView = findViewById(R.id.lock_button) @@ -459,18 +450,20 @@ class GroupActivity : DatabaseLockActivity(), mGroupEditViewModel.requestDateTimeSelection.observe(this) { dateInstant -> if (dateInstant.type == DateInstant.Type.TIME) { // Launch the time picker - val dateTime = DateTime(dateInstant.date) - TimePickerFragment.getInstance(dateTime.hourOfDay, dateTime.minuteOfHour) - .show(supportFragmentManager, "TimePickerFragment") + MaterialTimePicker.Builder().build().apply { + addOnPositiveButtonClickListener { + mGroupEditViewModel.selectTime(this.hour, this.minute) + } + show(supportFragmentManager, "TimePickerFragment") + } } else { // Launch the date picker - val dateTime = DateTime(dateInstant.date) - DatePickerFragment.getInstance( - dateTime.year, - dateTime.monthOfYear - 1, - dateTime.dayOfMonth - ) - .show(supportFragmentManager, "DatePickerFragment") + MaterialDatePicker.Builder.datePicker().build().apply { + addOnPositiveButtonClickListener { + mGroupEditViewModel.selectDate(it) + } + show(supportFragmentManager, "DatePickerFragment") + } } } @@ -970,18 +963,6 @@ class GroupActivity : DatabaseLockActivity(), } } - override fun onDateSet(datePicker: DatePicker?, year: Int, month: Int, day: Int) { - // To fix android 4.4 issue - // https://stackoverflow.com/questions/12436073/datepicker-ondatechangedlistener-called-twice - if (datePicker?.isShown == true) { - mGroupEditViewModel.selectDate(year, month, day) - } - } - - override fun onTimeSet(view: TimePicker?, hours: Int, minutes: Int) { - mGroupEditViewModel.selectTime(hours, minutes) - } - private fun finishNodeAction() { actionNodeMode?.finish() } @@ -1228,11 +1209,11 @@ class GroupActivity : DatabaseLockActivity(), } } if (it.isActionViewExpanded) { - toolbarBreadcrumb?.visibility = View.GONE + breadcrumbListView?.visibility = View.GONE searchFiltersView?.visibility = View.VISIBLE } else { searchFiltersView?.visibility = View.GONE - toolbarBreadcrumb?.visibility = View.VISIBLE + breadcrumbListView?.visibility = View.VISIBLE } mLockSearchListeners = false } 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 4f26c8dfe..7095ea30c 100644 --- a/app/src/main/java/com/kunzisoft/keepass/activities/MainCredentialActivity.kt +++ b/app/src/main/java/com/kunzisoft/keepass/activities/MainCredentialActivity.kt @@ -1,6 +1,6 @@ /* * Copyright 2019 Jeremy Jamet / Kunzisoft. - * + * * This file is part of KeePassDX. * * KeePassDX is free software: you can redistribute it and/or modify @@ -67,14 +67,15 @@ import com.kunzisoft.keepass.services.DatabaseTaskNotificationService.Companion. import com.kunzisoft.keepass.services.DatabaseTaskNotificationService.Companion.DATABASE_URI_KEY import com.kunzisoft.keepass.services.DatabaseTaskNotificationService.Companion.MAIN_CREDENTIAL_KEY import com.kunzisoft.keepass.services.DatabaseTaskNotificationService.Companion.READ_ONLY_KEY +import com.kunzisoft.keepass.settings.AdvancedUnlockSettingsActivity +import com.kunzisoft.keepass.settings.AppearanceSettingsActivity import com.kunzisoft.keepass.settings.PreferencesUtil -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.getUri import com.kunzisoft.keepass.utils.getParcelableCompat import com.kunzisoft.keepass.utils.getParcelableExtraCompat -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 @@ -88,6 +89,7 @@ class MainCredentialActivity : DatabaseModeActivity(), AdvancedUnlockFragment.Bu // Views private var toolbar: Toolbar? = null private var filenameView: TextView? = null + private var logotypeButton: View? = null private var advancedUnlockButton: View? = null private var mainCredentialView: MainCredentialView? = null private var confirmButtonView: Button? = null @@ -128,7 +130,8 @@ class MainCredentialActivity : DatabaseModeActivity(), AdvancedUnlockFragment.Bu supportActionBar?.setDisplayShowHomeEnabled(true) filenameView = findViewById(R.id.filename) - advancedUnlockButton = findViewById(R.id.activity_password_advanced_unlock_button) + logotypeButton = findViewById(R.id.activity_password_logotype) + advancedUnlockButton = findViewById(R.id.fragment_advanced_unlock_container_view) mainCredentialView = findViewById(R.id.activity_password_credentials) confirmButtonView = findViewById(R.id.activity_password_open_button) infoContainerView = findViewById(R.id.activity_password_info_container) @@ -157,10 +160,15 @@ class MainCredentialActivity : DatabaseModeActivity(), AdvancedUnlockFragment.Bu // If is a view intent getUriFromIntent(intent) + // Show appearance + logotypeButton?.setOnClickListener { + startActivity(Intent(this, AppearanceSettingsActivity::class.java)) + } + // Init Biometric elements if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { advancedUnlockButton?.setOnClickListener { - startActivity(Intent(this, SettingsAdvancedUnlockActivity::class.java)) + startActivity(Intent(this, AdvancedUnlockSettingsActivity::class.java)) } } advancedUnlockFragment = supportFragmentManager @@ -647,7 +655,7 @@ class MainCredentialActivity : DatabaseModeActivity(), AdvancedUnlockFragment.Bu startActivity( Intent( this, - SettingsAdvancedUnlockActivity::class.java + AdvancedUnlockSettingsActivity::class.java ) ) }, 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 d3c1ea348..3c83c7750 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 @@ -6,7 +6,6 @@ import androidx.fragment.app.activityViewModels import com.kunzisoft.keepass.activities.legacy.DatabaseRetrieval import com.kunzisoft.keepass.activities.legacy.resetAppTimeoutWhenViewTouchedOrFocused 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 @@ -16,8 +15,6 @@ abstract class DatabaseDialogFragment : DialogFragment(), DatabaseRetrieval { private val mDatabaseViewModel: DatabaseViewModel by activityViewModels() private var mDatabase: ContextualDatabase? = null - protected var mIconDrawableFactory: IconDrawableFactory? = null - override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) diff --git a/app/src/main/java/com/kunzisoft/keepass/activities/dialogs/DatePickerFragment.kt b/app/src/main/java/com/kunzisoft/keepass/activities/dialogs/DatePickerFragment.kt deleted file mode 100644 index 86081c301..000000000 --- a/app/src/main/java/com/kunzisoft/keepass/activities/dialogs/DatePickerFragment.kt +++ /dev/null @@ -1,67 +0,0 @@ -package com.kunzisoft.keepass.activities.dialogs - -import android.app.DatePickerDialog -import android.app.Dialog -import android.content.Context -import android.os.Bundle -import androidx.fragment.app.DialogFragment - -// Not as DatabaseDialogFragment because crash on KitKat -class DatePickerFragment : DialogFragment() { - - private var mDefaultYear: Int = 2000 - private var mDefaultMonth: Int = 1 - private var mDefaultDay: Int = 1 - - private var mListener: DatePickerDialog.OnDateSetListener? = null - - override fun onAttach(context: Context) { - super.onAttach(context) - try { - mListener = context as DatePickerDialog.OnDateSetListener - } catch (e: ClassCastException) { - throw ClassCastException(context.toString() - + " must implement " + DatePickerDialog.OnDateSetListener::class.java.name) - } - } - - override fun onDetach() { - mListener = null - super.onDetach() - } - - override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { - // Create a new instance of DatePickerDialog and return it - return context?.let { - arguments?.apply { - if (containsKey(DEFAULT_YEAR_BUNDLE_KEY)) - mDefaultYear = getInt(DEFAULT_YEAR_BUNDLE_KEY) - if (containsKey(DEFAULT_MONTH_BUNDLE_KEY)) - mDefaultMonth = getInt(DEFAULT_MONTH_BUNDLE_KEY) - if (containsKey(DEFAULT_DAY_BUNDLE_KEY)) - mDefaultDay = getInt(DEFAULT_DAY_BUNDLE_KEY) - } - - DatePickerDialog(it, mListener, mDefaultYear, mDefaultMonth, mDefaultDay) - } ?: super.onCreateDialog(savedInstanceState) - } - - companion object { - - private const val DEFAULT_YEAR_BUNDLE_KEY = "DEFAULT_YEAR_BUNDLE_KEY" - private const val DEFAULT_MONTH_BUNDLE_KEY = "DEFAULT_MONTH_BUNDLE_KEY" - private const val DEFAULT_DAY_BUNDLE_KEY = "DEFAULT_DAY_BUNDLE_KEY" - - fun getInstance(defaultYear: Int, - defaultMonth: Int, - defaultDay: Int): DatePickerFragment { - return DatePickerFragment().apply { - arguments = Bundle().apply { - putInt(DEFAULT_YEAR_BUNDLE_KEY, defaultYear) - putInt(DEFAULT_MONTH_BUNDLE_KEY, defaultMonth) - putInt(DEFAULT_DAY_BUNDLE_KEY, defaultDay) - } - } - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/kunzisoft/keepass/activities/dialogs/GroupDialogFragment.kt b/app/src/main/java/com/kunzisoft/keepass/activities/dialogs/GroupDialogFragment.kt index 31679f85d..593a99d6f 100644 --- a/app/src/main/java/com/kunzisoft/keepass/activities/dialogs/GroupDialogFragment.kt +++ b/app/src/main/java/com/kunzisoft/keepass/activities/dialogs/GroupDialogFragment.kt @@ -35,9 +35,9 @@ import com.kunzisoft.keepass.database.ContextualDatabase import com.kunzisoft.keepass.database.element.icon.IconImage import com.kunzisoft.keepass.model.GroupInfo import com.kunzisoft.keepass.settings.PreferencesUtil -import com.kunzisoft.keepass.utils.getParcelableCompat import com.kunzisoft.keepass.utils.TimeUtil.getDateTimeString import com.kunzisoft.keepass.utils.UuidUtil +import com.kunzisoft.keepass.utils.getParcelableCompat import com.kunzisoft.keepass.view.DateTimeFieldView class GroupDialogFragment : DatabaseDialogFragment() { @@ -65,7 +65,7 @@ class GroupDialogFragment : DatabaseDialogFragment() { override fun onDatabaseRetrieved(database: ContextualDatabase?) { super.onDatabaseRetrieved(database) mPopulateIconMethod = { imageView, icon -> - mIconDrawableFactory?.assignDatabaseIcon(imageView, icon, mIconColor) + database?.iconDrawableFactory?.assignDatabaseIcon(imageView, icon, mIconColor) } mPopulateIconMethod?.invoke(iconView, mGroupInfo.icon) @@ -108,7 +108,7 @@ class GroupDialogFragment : DatabaseDialogFragment() { uuidReferenceView = root.findViewById(R.id.group_UUID_reference) // Retrieve the textColor to tint the icon - val ta = activity.theme.obtainStyledAttributes(intArrayOf(R.attr.colorAccent)) + val ta = activity.theme.obtainStyledAttributes(intArrayOf(R.attr.colorSecondary)) mIconColor = ta.getColor(0, Color.WHITE) ta.recycle() diff --git a/app/src/main/java/com/kunzisoft/keepass/activities/dialogs/GroupEditDialogFragment.kt b/app/src/main/java/com/kunzisoft/keepass/activities/dialogs/GroupEditDialogFragment.kt index 9ffc40d3d..46894e1d5 100644 --- a/app/src/main/java/com/kunzisoft/keepass/activities/dialogs/GroupEditDialogFragment.kt +++ b/app/src/main/java/com/kunzisoft/keepass/activities/dialogs/GroupEditDialogFragment.kt @@ -90,13 +90,11 @@ class GroupEditDialogFragment : DatabaseDialogFragment() { mPopulateIconMethod?.invoke(iconButtonView, mGroupInfo.icon) } - mGroupEditViewModel.onDateSelected.observe(this) { viewModelDate -> + mGroupEditViewModel.onDateSelected.observe(this) { dateMilliseconds -> // Save the date mGroupInfo.expiryTime = DateInstant( DateTime(mGroupInfo.expiryTime.date) - .withYear(viewModelDate.year) - .withMonthOfYear(viewModelDate.month + 1) - .withDayOfMonth(viewModelDate.day) + .withMillis(dateMilliseconds) .toDate()) expirationView.dateTime = mGroupInfo.expiryTime if (expirationView.dateTime.type == DateInstant.Type.DATE_TIME) { diff --git a/app/src/main/java/com/kunzisoft/keepass/activities/dialogs/MainCredentialDialogFragment.kt b/app/src/main/java/com/kunzisoft/keepass/activities/dialogs/MainCredentialDialogFragment.kt index 1ea3d50da..e00d39563 100644 --- a/app/src/main/java/com/kunzisoft/keepass/activities/dialogs/MainCredentialDialogFragment.kt +++ b/app/src/main/java/com/kunzisoft/keepass/activities/dialogs/MainCredentialDialogFragment.kt @@ -28,8 +28,8 @@ import androidx.appcompat.app.AlertDialog import com.kunzisoft.keepass.R import com.kunzisoft.keepass.activities.helpers.ExternalFileHelper import com.kunzisoft.keepass.database.MainCredential -import com.kunzisoft.keepass.utils.getParcelableCompat import com.kunzisoft.keepass.utils.UriUtil.getDocumentFile +import com.kunzisoft.keepass.utils.getParcelableCompat import com.kunzisoft.keepass.view.MainCredentialView class MainCredentialDialogFragment : DatabaseDialogFragment() { diff --git a/app/src/main/java/com/kunzisoft/keepass/activities/dialogs/SetOTPDialogFragment.kt b/app/src/main/java/com/kunzisoft/keepass/activities/dialogs/SetOTPDialogFragment.kt index 560f1b7a1..167386b81 100644 --- a/app/src/main/java/com/kunzisoft/keepass/activities/dialogs/SetOTPDialogFragment.kt +++ b/app/src/main/java/com/kunzisoft/keepass/activities/dialogs/SetOTPDialogFragment.kt @@ -44,9 +44,9 @@ import com.kunzisoft.keepass.otp.OtpElement.Companion.MIN_TOTP_PERIOD import com.kunzisoft.keepass.otp.OtpTokenType import com.kunzisoft.keepass.otp.OtpType import com.kunzisoft.keepass.otp.TokenCalculator -import com.kunzisoft.keepass.utils.getParcelableCompat import com.kunzisoft.keepass.utils.UriUtil.isContributingUser import com.kunzisoft.keepass.utils.UriUtil.openUrl +import com.kunzisoft.keepass.utils.getParcelableCompat import java.util.* class SetOTPDialogFragment : DatabaseDialogFragment() { diff --git a/app/src/main/java/com/kunzisoft/keepass/activities/dialogs/TimePickerFragment.kt b/app/src/main/java/com/kunzisoft/keepass/activities/dialogs/TimePickerFragment.kt deleted file mode 100644 index 9e6a0ebc7..000000000 --- a/app/src/main/java/com/kunzisoft/keepass/activities/dialogs/TimePickerFragment.kt +++ /dev/null @@ -1,63 +0,0 @@ -package com.kunzisoft.keepass.activities.dialogs - -import android.app.DatePickerDialog -import android.app.Dialog -import android.app.TimePickerDialog -import android.content.Context -import android.os.Bundle -import android.text.format.DateFormat -import androidx.fragment.app.DialogFragment - -// Not as DatabaseDialogFragment because crash on KitKat -class TimePickerFragment : DialogFragment() { - - private var defaultHour: Int = 0 - private var defaultMinute: Int = 0 - - private var mListener: TimePickerDialog.OnTimeSetListener? = null - - override fun onAttach(context: Context) { - super.onAttach(context) - try { - mListener = context as TimePickerDialog.OnTimeSetListener - } catch (e: ClassCastException) { - throw ClassCastException(context.toString() - + " must implement " + DatePickerDialog.OnDateSetListener::class.java.name) - } - } - - override fun onDetach() { - mListener = null - super.onDetach() - } - - override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { - // Create a new instance of DatePickerDialog and return it - return context?.let { - arguments?.apply { - if (containsKey(DEFAULT_HOUR_BUNDLE_KEY)) - defaultHour = getInt(DEFAULT_HOUR_BUNDLE_KEY) - if (containsKey(DEFAULT_MINUTE_BUNDLE_KEY)) - defaultMinute = getInt(DEFAULT_MINUTE_BUNDLE_KEY) - } - - TimePickerDialog(it, mListener, defaultHour, defaultMinute, DateFormat.is24HourFormat(activity)) - } ?: super.onCreateDialog(savedInstanceState) - } - - companion object { - - private const val DEFAULT_HOUR_BUNDLE_KEY = "DEFAULT_HOUR_BUNDLE_KEY" - private const val DEFAULT_MINUTE_BUNDLE_KEY = "DEFAULT_MINUTE_BUNDLE_KEY" - - fun getInstance(defaultHour: Int, - defaultMinute: Int): TimePickerFragment { - return TimePickerFragment().apply { - arguments = Bundle().apply { - putInt(DEFAULT_HOUR_BUNDLE_KEY, defaultHour) - putInt(DEFAULT_MINUTE_BUNDLE_KEY, defaultMinute) - } - } - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/kunzisoft/keepass/activities/dialogs/UnavailableFeatureDialogFragment.kt b/app/src/main/java/com/kunzisoft/keepass/activities/dialogs/UnavailableFeatureDialogFragment.kt index 9632021cd..7072b58f9 100644 --- a/app/src/main/java/com/kunzisoft/keepass/activities/dialogs/UnavailableFeatureDialogFragment.kt +++ b/app/src/main/java/com/kunzisoft/keepass/activities/dialogs/UnavailableFeatureDialogFragment.kt @@ -22,12 +22,12 @@ package com.kunzisoft.keepass.activities.dialogs import android.app.Dialog import android.os.Build import android.os.Bundle -import androidx.fragment.app.DialogFragment -import androidx.appcompat.app.AlertDialog import android.text.SpannableStringBuilder import android.text.method.LinkMovementMethod import android.widget.TextView +import androidx.appcompat.app.AlertDialog import androidx.core.text.HtmlCompat +import androidx.fragment.app.DialogFragment import com.kunzisoft.keepass.R class UnavailableFeatureDialogFragment : DialogFragment() { diff --git a/app/src/main/java/com/kunzisoft/keepass/activities/legacy/DatabaseModeActivity.kt b/app/src/main/java/com/kunzisoft/keepass/activities/legacy/DatabaseModeActivity.kt index 3ecb9eabf..2688700eb 100644 --- a/app/src/main/java/com/kunzisoft/keepass/activities/legacy/DatabaseModeActivity.kt +++ b/app/src/main/java/com/kunzisoft/keepass/activities/legacy/DatabaseModeActivity.kt @@ -9,7 +9,7 @@ import com.kunzisoft.keepass.activities.helpers.SpecialMode import com.kunzisoft.keepass.activities.helpers.TypeMode import com.kunzisoft.keepass.model.SearchInfo import com.kunzisoft.keepass.settings.PreferencesUtil -import com.kunzisoft.keepass.view.SpecialModeView +import com.kunzisoft.keepass.view.ToolbarSpecial /** @@ -20,7 +20,7 @@ abstract class DatabaseModeActivity : DatabaseActivity() { protected var mSpecialMode: SpecialMode = SpecialMode.DEFAULT private var mTypeMode: TypeMode = TypeMode.DEFAULT - private var mSpecialModeView: SpecialModeView? = null + private var mToolbarSpecial: ToolbarSpecial? = null override fun onBackPressed() { if (mSpecialMode != SpecialMode.DEFAULT) @@ -113,8 +113,8 @@ abstract class DatabaseModeActivity : DatabaseActivity() { ?: EntrySelectionHelper.retrieveSearchInfoFromIntent(intent) // To show the selection mode - mSpecialModeView = findViewById(R.id.special_mode_view) - mSpecialModeView?.apply { + mToolbarSpecial = findViewById(R.id.special_mode_view) + mToolbarSpecial?.apply { // Populate title val selectionModeStringId = when (mSpecialMode) { SpecialMode.DEFAULT, // Not important because hidden diff --git a/app/src/main/java/com/kunzisoft/keepass/adapters/BreadcrumbAdapter.kt b/app/src/main/java/com/kunzisoft/keepass/adapters/BreadcrumbAdapter.kt index f87576716..5e39ebf00 100644 --- a/app/src/main/java/com/kunzisoft/keepass/adapters/BreadcrumbAdapter.kt +++ b/app/src/main/java/com/kunzisoft/keepass/adapters/BreadcrumbAdapter.kt @@ -39,10 +39,10 @@ class BreadcrumbAdapter(val context: Context) mShowNumberEntries = PreferencesUtil.showNumberEntries(context) mShowUUID = PreferencesUtil.showUUID(context) - // Retrieve the textColor to tint the icon - val taTextColor = context.theme.obtainStyledAttributes(intArrayOf(R.attr.textColorInverse)) - mIconColor = taTextColor.getColor(0, Color.WHITE) - taTextColor.recycle() + // Retrieve the color to tint the icon + val taIconColor = context.theme.obtainStyledAttributes(intArrayOf(R.attr.colorOnSurface)) + mIconColor = taIconColor.getColor(0, Color.WHITE) + taIconColor.recycle() } @SuppressLint("NotifyDataSetChanged") @@ -71,7 +71,7 @@ class BreadcrumbAdapter(val context: Context) override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BreadcrumbGroupViewHolder { return BreadcrumbGroupViewHolder(inflater.inflate( when (viewType) { - 0 -> R.layout.item_group + 0 -> R.layout.item_breadcrumb_important else -> R.layout.item_breadcrumb }, parent, false) ) diff --git a/app/src/main/java/com/kunzisoft/keepass/adapters/EntryAttachmentsItemsAdapter.kt b/app/src/main/java/com/kunzisoft/keepass/adapters/EntryAttachmentsItemsAdapter.kt index 6d9f9dab7..deb11bb98 100644 --- a/app/src/main/java/com/kunzisoft/keepass/adapters/EntryAttachmentsItemsAdapter.kt +++ b/app/src/main/java/com/kunzisoft/keepass/adapters/EntryAttachmentsItemsAdapter.kt @@ -27,9 +27,9 @@ import android.util.TypedValue import android.view.View import android.view.ViewGroup import android.widget.ImageView -import android.widget.ProgressBar import android.widget.TextView import androidx.recyclerview.widget.RecyclerView +import com.google.android.material.progressindicator.CircularProgressIndicator import com.kunzisoft.keepass.R import com.kunzisoft.keepass.activities.ImageViewerActivity import com.kunzisoft.keepass.database.ContextualDatabase @@ -38,6 +38,7 @@ import com.kunzisoft.keepass.database.helper.getLocalizedName import com.kunzisoft.keepass.model.AttachmentState import com.kunzisoft.keepass.model.EntryAttachmentState import com.kunzisoft.keepass.model.StreamDirection +import com.kunzisoft.keepass.services.AttachmentFileNotificationService.Companion.FILE_PROGRESSION_MAX import com.kunzisoft.keepass.tasks.BinaryDatabaseManager import com.kunzisoft.keepass.view.expand import kotlin.math.max @@ -138,6 +139,7 @@ class EntryAttachmentsItemsAdapter(context: Context) visibility = View.GONE } } + holder.binaryFileProgress.max = FILE_PROGRESSION_MAX when (entryAttachmentState.streamDirection) { StreamDirection.UPLOAD -> { holder.binaryFileProgressIcon.isActivated = true @@ -182,7 +184,7 @@ class EntryAttachmentsItemsAdapter(context: Context) AttachmentState.START, AttachmentState.IN_PROGRESS -> View.VISIBLE } - progress = entryAttachmentState.downloadProgression + setProgressCompat(entryAttachmentState.downloadProgression, true) } holder.binaryFileInfo.setOnClickListener { onItemClickListener?.invoke(entryAttachmentState) @@ -201,7 +203,7 @@ class EntryAttachmentsItemsAdapter(context: Context) var binaryFileCompression: TextView = itemView.findViewById(R.id.item_attachment_compression) var binaryFileProgressContainer: View = itemView.findViewById(R.id.item_attachment_progress_container) var binaryFileProgressIcon: ImageView = itemView.findViewById(R.id.item_attachment_icon) - var binaryFileProgress: ProgressBar = itemView.findViewById(R.id.item_attachment_progress) + var binaryFileProgress: CircularProgressIndicator = itemView.findViewById(R.id.item_attachment_progress) var binaryFileDeleteButton: View = itemView.findViewById(R.id.item_attachment_delete_button) } } diff --git a/app/src/main/java/com/kunzisoft/keepass/adapters/FileDatabaseHistoryAdapter.kt b/app/src/main/java/com/kunzisoft/keepass/adapters/FileDatabaseHistoryAdapter.kt index 0d16635a7..7ebdb54f5 100644 --- a/app/src/main/java/com/kunzisoft/keepass/adapters/FileDatabaseHistoryAdapter.kt +++ b/app/src/main/java/com/kunzisoft/keepass/adapters/FileDatabaseHistoryAdapter.kt @@ -23,12 +23,14 @@ import android.content.Context import android.graphics.Color import android.graphics.PorterDuff import android.net.Uri -import android.util.TypedValue import android.view.LayoutInflater import android.view.View import android.view.ViewGroup -import android.widget.* -import androidx.annotation.ColorInt +import android.widget.CompoundButton +import android.widget.EditText +import android.widget.ImageView +import android.widget.TextView +import android.widget.ViewSwitcher import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.SortedList import androidx.recyclerview.widget.SortedListAdapterCallback @@ -84,20 +86,6 @@ class FileDatabaseHistoryAdapter(context: Context) } ) - @ColorInt - private val defaultColor: Int - @ColorInt - private val warningColor: Int - - init { - val typedValue = TypedValue() - val theme = context.theme - theme.resolveAttribute(R.attr.colorAccent, typedValue, true) - warningColor = typedValue.data - theme.resolveAttribute(android.R.attr.textColorHintInverse, typedValue, true) - defaultColor = typedValue.data - } - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): FileDatabaseHistoryViewHolder { val view = inflater.inflate(R.layout.item_file_info, parent, false) return FileDatabaseHistoryViewHolder(view) diff --git a/app/src/main/java/com/kunzisoft/keepass/adapters/NodesAdapter.kt b/app/src/main/java/com/kunzisoft/keepass/adapters/NodesAdapter.kt index 61a1eaaab..8eb46ad33 100644 --- a/app/src/main/java/com/kunzisoft/keepass/adapters/NodesAdapter.kt +++ b/app/src/main/java/com/kunzisoft/keepass/adapters/NodesAdapter.kt @@ -20,6 +20,7 @@ package com.kunzisoft.keepass.adapters import android.content.Context +import android.content.res.ColorStateList import android.graphics.Color import android.util.Log import android.util.TypedValue @@ -29,6 +30,7 @@ import android.view.ViewGroup import android.widget.ImageView import android.widget.TextView import androidx.annotation.ColorInt +import androidx.core.view.ViewCompat import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.SortedList import androidx.recyclerview.widget.SortedListAdapterCallback @@ -88,6 +90,8 @@ class NodesAdapter ( private var mNodeClickCallback: NodeClickCallback? = null private var mClipboardHelper = ClipboardHelper(context) + @ColorInt + private val mColorSurfaceContainer: Int @ColorInt private val mTextColorPrimary: Int @ColorInt @@ -95,9 +99,9 @@ class NodesAdapter ( @ColorInt private val mTextColorSecondary: Int @ColorInt - private val mColorAccentLight: Int + private val mColorSecondary: Int @ColorInt - private val mColorOnAccentColor: Int + private val mColorOnSecondary: Int /** * Determine if the adapter contains or not any element @@ -114,6 +118,9 @@ class NodesAdapter ( this.mNodeSortedListCallback = NodeSortedListCallback() this.mNodeSortedList = SortedList(Node::class.java, mNodeSortedListCallback) + val taColorSurfaceContainer = context.theme.obtainStyledAttributes(intArrayOf(R.attr.colorSurfaceContainer)) + this.mColorSurfaceContainer = taColorSurfaceContainer.getColor(0, Color.BLACK) + taColorSurfaceContainer.recycle() // Retrieve the color to tint the icon val taTextColorPrimary = context.theme.obtainStyledAttributes(intArrayOf(android.R.attr.textColorPrimary)) this.mTextColorPrimary = taTextColorPrimary.getColor(0, Color.BLACK) @@ -127,13 +134,13 @@ class NodesAdapter ( this.mTextColorSecondary = taTextColorSecondary.getColor(0, Color.BLACK) taTextColorSecondary.recycle() // To get background color for selection - val taColorAccentLight = context.theme.obtainStyledAttributes(intArrayOf(R.attr.colorAccentLight)) - this.mColorAccentLight = taColorAccentLight.getColor(0, Color.GRAY) - taColorAccentLight.recycle() + val taColorSecondary = context.theme.obtainStyledAttributes(intArrayOf(R.attr.colorSecondary)) + this.mColorSecondary = taColorSecondary.getColor(0, Color.GRAY) + taColorSecondary.recycle() // To get text color for selection - val taColorOnAccentColor = context.theme.obtainStyledAttributes(intArrayOf(R.attr.colorOnAccentColor)) - this.mColorOnAccentColor = taColorOnAccentColor.getColor(0, Color.WHITE) - taColorOnAccentColor.recycle() + val taColorOnSecondary = context.theme.obtainStyledAttributes(intArrayOf(R.attr.colorOnSecondary)) + this.mColorOnSecondary = taColorOnSecondary.getColor(0, Color.WHITE) + taColorOnSecondary.recycle() } private fun assignPreferences() { @@ -380,10 +387,10 @@ class NodesAdapter ( // Assign icon colors var iconColor = if (holder.container.isSelected) - mColorOnAccentColor + mColorOnSecondary else when (subNode.type) { - Type.GROUP -> mTextColorPrimary - Type.ENTRY -> mTextColor + Type.GROUP -> mTextColor + Type.ENTRY -> mColorSecondary } // Specific elements for entry @@ -428,16 +435,8 @@ class NodesAdapter ( if (entry.containsAttachment()) View.VISIBLE else View.GONE // Assign colors - val backgroundColor = if (mShowEntryColors) entry.backgroundColor else null - if (!holder.container.isSelected) { - if (backgroundColor != null) { - holder.container.setBackgroundColor(backgroundColor) - } else { - holder.container.setBackgroundColor(Color.TRANSPARENT) - } - } else { - holder.container.setBackgroundColor(mColorAccentLight) - } + assignBackgroundColor(holder.container, entry) + assignBackgroundColor(holder.otpContainer, entry) val foregroundColor = if (mShowEntryColors) entry.foregroundColor else null if (!holder.container.isSelected) { if (foregroundColor != null) { @@ -457,12 +456,12 @@ class NodesAdapter ( holder.meta.setTextColor(mTextColor) } } else { - holder.text.setTextColor(mColorOnAccentColor) - holder.subText?.setTextColor(mColorOnAccentColor) - holder.otpToken?.setTextColor(mColorOnAccentColor) - holder.otpProgress?.setIndicatorColor(mColorOnAccentColor) - holder.attachmentIcon?.setColorFilter(mColorOnAccentColor) - holder.meta.setTextColor(mColorOnAccentColor) + holder.text.setTextColor(mColorOnSecondary) + holder.subText?.setTextColor(mColorOnSecondary) + holder.otpToken?.setTextColor(mColorOnSecondary) + holder.otpProgress?.setIndicatorColor(mColorOnSecondary) + holder.attachmentIcon?.setColorFilter(mColorOnSecondary) + holder.meta.setTextColor(mColorOnSecondary) } database.stopManageEntry(entry) @@ -528,7 +527,8 @@ class NodesAdapter ( try { mClipboardHelper.copyToClipboard( TemplateField.getLocalizedName(context, TemplateField.LABEL_TOKEN), - token + token, + true ) } catch (e: Exception) { Log.e(TAG, "Unable to copy the OTP token", e) @@ -537,6 +537,22 @@ class NodesAdapter ( } } + private fun assignBackgroundColor(view: View?, entry: Entry) { + view?.let { + ViewCompat.setBackgroundTintList( + view, + ColorStateList.valueOf( + if (!view.isSelected) { + (if (mShowEntryColors) entry.backgroundColor else null) + ?: mColorSurfaceContainer + } else { + mColorSecondary + } + ) + ) + } + } + class OtpRunnable(val view: View?): Runnable { var action: (() -> Unit)? = null diff --git a/app/src/main/java/com/kunzisoft/keepass/biometric/AdvancedUnlockFragment.kt b/app/src/main/java/com/kunzisoft/keepass/biometric/AdvancedUnlockFragment.kt index baffaf973..50dcb7472 100644 --- a/app/src/main/java/com/kunzisoft/keepass/biometric/AdvancedUnlockFragment.kt +++ b/app/src/main/java/com/kunzisoft/keepass/biometric/AdvancedUnlockFragment.kt @@ -221,8 +221,6 @@ class AdvancedUnlockFragment: StylishFragment(), AdvancedUnlockManager.AdvancedU if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { allowOpenBiometricPrompt = true if (PreferencesUtil.isBiometricUnlockEnable(context)) { - mAdvancedUnlockInfoView?.setIconResource(R.drawable.fingerprint) - // biometric not supported (by API level or hardware) so keep option hidden // or manually disable val biometricCanAuthenticate = AdvancedUnlockManager.canAuthenticate(context) @@ -241,7 +239,6 @@ class AdvancedUnlockFragment: StylishFragment(), AdvancedUnlockManager.AdvancedU } } } else if (PreferencesUtil.isDeviceCredentialUnlockEnable(context)) { - mAdvancedUnlockInfoView?.setIconResource(R.drawable.bolt) if (AdvancedUnlockManager.isDeviceSecure(context)) { selectMode() } else { @@ -297,12 +294,12 @@ class AdvancedUnlockFragment: StylishFragment(), AdvancedUnlockManager.AdvancedU private fun initNotAvailable() { showViews(false) - mAdvancedUnlockInfoView?.setIconViewClickListener(false, null) + mAdvancedUnlockInfoView?.setIconViewClickListener(null) } @RequiresApi(Build.VERSION_CODES.M) private fun openBiometricSetting() { - mAdvancedUnlockInfoView?.setIconViewClickListener(false) { + mAdvancedUnlockInfoView?.setIconViewClickListener { try { when { Build.VERSION.SDK_INT >= Build.VERSION_CODES.R -> { @@ -351,11 +348,11 @@ class AdvancedUnlockFragment: StylishFragment(), AdvancedUnlockManager.AdvancedU @RequiresApi(Build.VERSION_CODES.M) private fun initWaitData() { showViews(true) - setAdvancedUnlockedTitleView(R.string.no_credentials_stored) + setAdvancedUnlockedTitleView(R.string.unavailable) setAdvancedUnlockedMessageView("") context?.let { context -> - mAdvancedUnlockInfoView?.setIconViewClickListener(false) { + mAdvancedUnlockInfoView?.setIconViewClickListener { onAuthenticationError(BiometricPrompt.ERROR_UNABLE_TO_PROCESS, context.getString(R.string.credential_before_click_advanced_unlock_button)) } @@ -382,7 +379,7 @@ class AdvancedUnlockFragment: StylishFragment(), AdvancedUnlockManager.AdvancedU @RequiresApi(Build.VERSION_CODES.M) private fun initEncryptData() { showViews(true) - setAdvancedUnlockedTitleView(R.string.open_advanced_unlock_prompt_store_credential) + setAdvancedUnlockedTitleView(R.string.unlock_and_link_biometric) setAdvancedUnlockedMessageView("") advancedUnlockManager?.initEncryptData { cryptoPrompt -> @@ -396,7 +393,7 @@ class AdvancedUnlockFragment: StylishFragment(), AdvancedUnlockManager.AdvancedU @RequiresApi(Build.VERSION_CODES.M) private fun initDecryptData() { showViews(true) - setAdvancedUnlockedTitleView(R.string.open_advanced_unlock_prompt_unlock_database) + setAdvancedUnlockedTitleView(R.string.unlock) setAdvancedUnlockedMessageView("") advancedUnlockManager?.let { unlockHelper -> @@ -629,7 +626,7 @@ class AdvancedUnlockFragment: StylishFragment(), AdvancedUnlockManager.AdvancedU @RequiresApi(Build.VERSION_CODES.M) private fun setAdvancedUnlockedMessageView(text: CharSequence) { lifecycleScope.launch(Dispatchers.Main) { - mAdvancedUnlockInfoView?.message = text + mAdvancedUnlockInfoView?.setMessage(text) } } diff --git a/app/src/main/java/com/kunzisoft/keepass/biometric/FingerPrintAnimatedVector.kt b/app/src/main/java/com/kunzisoft/keepass/biometric/FingerPrintAnimatedVector.kt deleted file mode 100644 index 8ee09f349..000000000 --- a/app/src/main/java/com/kunzisoft/keepass/biometric/FingerPrintAnimatedVector.kt +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright 2019 Jeremy Jamet / Kunzisoft. - * - * This file is part of KeePassDX. - * - * KeePassDX is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * KeePassDX is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with KeePassDX. If not, see . - * - */ -package com.kunzisoft.keepass.biometric - -import android.content.Context -import android.graphics.drawable.Drawable -import android.os.Build -import androidx.annotation.RequiresApi -import android.widget.ImageView -import androidx.vectordrawable.graphics.drawable.Animatable2Compat -import androidx.vectordrawable.graphics.drawable.AnimatedVectorDrawableCompat - -import com.kunzisoft.keepass.R - -@RequiresApi(api = Build.VERSION_CODES.M) -class FingerPrintAnimatedVector(context: Context, imageView: ImageView) { - - private val scanFingerprint: AnimatedVectorDrawableCompat? = - AnimatedVectorDrawableCompat.create(context, R.drawable.scan_fingerprint) - - init { - imageView.setImageDrawable(scanFingerprint) - } - - private var animationCallback = object : Animatable2Compat.AnimationCallback() { - override fun onAnimationEnd(drawable: Drawable) { - imageView.post { - scanFingerprint?.start() - } - } - } - - fun startScan() { - scanFingerprint?.registerAnimationCallback(animationCallback) - - if (scanFingerprint?.isRunning != true) - scanFingerprint?.start() - } - - fun stopScan() { - scanFingerprint?.unregisterAnimationCallback(animationCallback) - - if (scanFingerprint?.isRunning == true) - scanFingerprint.stop() - } -} diff --git a/app/src/main/java/com/kunzisoft/keepass/database/DatabaseTaskProvider.kt b/app/src/main/java/com/kunzisoft/keepass/database/DatabaseTaskProvider.kt index df50724c1..ad7022312 100644 --- a/app/src/main/java/com/kunzisoft/keepass/database/DatabaseTaskProvider.kt +++ b/app/src/main/java/com/kunzisoft/keepass/database/DatabaseTaskProvider.kt @@ -20,7 +20,6 @@ package com.kunzisoft.keepass.database import android.Manifest -import android.app.AlertDialog import android.content.BroadcastReceiver import android.content.ComponentName import android.content.Context @@ -38,6 +37,7 @@ import android.os.IBinder import android.util.Log import android.widget.Toast import androidx.activity.result.contract.ActivityResultContracts +import androidx.appcompat.app.AlertDialog import androidx.core.app.ActivityCompat.shouldShowRequestPermissionRationale import androidx.core.content.ContextCompat import androidx.fragment.app.FragmentActivity @@ -107,7 +107,7 @@ class DatabaseTaskProvider( // To show dialog only if context is an activity private var activity: FragmentActivity? = try { context as? FragmentActivity? } - catch (_: Exception) { null } + catch (_: Exception) { null } var onDatabaseRetrieved: ((database: ContextualDatabase?) -> Unit)? = null @@ -252,12 +252,10 @@ class DatabaseTaskProvider( serviceConnection = object : ServiceConnection { override fun onBindingDied(name: ComponentName?) { stopDialog() - super.onBindingDied(name) } override fun onNullBinding(name: ComponentName?) { stopDialog() - super.onNullBinding(name) } override fun onServiceConnected(name: ComponentName?, serviceBinder: IBinder?) { @@ -323,10 +321,10 @@ class DatabaseTaskProvider( } } context.registerReceiver(databaseTaskBroadcastReceiver, - IntentFilter().apply { - addAction(DATABASE_START_TASK_ACTION) - addAction(DATABASE_STOP_TASK_ACTION) - } + IntentFilter().apply { + addAction(DATABASE_START_TASK_ACTION) + addAction(DATABASE_STOP_TASK_ACTION) + } ) // Check if a service is currently running else do nothing @@ -350,12 +348,12 @@ class DatabaseTaskProvider( private val requestPermissionLauncher = activity?.registerForActivityResult( ActivityResultContracts.RequestPermission() ) { _ -> - // Whether or not the user has accepted, the service can be started, - // There just won't be any notification if it's not allowed. - tempServiceParameters.removeFirstOrNull()?.let { - startService(it.first, it.second) - } + // Whether or not the user has accepted, the service can be started, + // There just won't be any notification if it's not allowed. + tempServiceParameters.removeFirstOrNull()?.let { + startService(it.first, it.second) } + } private fun start(bundle: Bundle? = null, actionTask: String) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { @@ -372,7 +370,7 @@ class DatabaseTaskProvider( // it's not the first time, so the user deliberately chooses not to display the notification startService(bundle, actionTask) } else { - AlertDialog.Builder(activity) + AlertDialog.Builder(context) .setMessage(R.string.warning_database_notification_permission) .setNegativeButton(R.string.later) { _, _ -> // Refuses the notification, so start the service @@ -414,7 +412,7 @@ class DatabaseTaskProvider( putParcelable(DatabaseTaskNotificationService.DATABASE_URI_KEY, databaseUri) putParcelable(DatabaseTaskNotificationService.MAIN_CREDENTIAL_KEY, mainCredential) } - , ACTION_DATABASE_CREATE_TASK) + , ACTION_DATABASE_CREATE_TASK) } fun startDatabaseLoad(databaseUri: Uri, @@ -429,7 +427,7 @@ class DatabaseTaskProvider( putParcelable(DatabaseTaskNotificationService.CIPHER_DATABASE_KEY, cipherEncryptDatabase) putBoolean(DatabaseTaskNotificationService.FIX_DUPLICATE_UUID_KEY, fixDuplicateUuid) } - , ACTION_DATABASE_LOAD_TASK) + , ACTION_DATABASE_LOAD_TASK) } fun startDatabaseMerge(save: Boolean, @@ -447,7 +445,7 @@ class DatabaseTaskProvider( start(Bundle().apply { putBoolean(DatabaseTaskNotificationService.FIX_DUPLICATE_UUID_KEY, fixDuplicateUuid) } - , ACTION_DATABASE_RELOAD_TASK) + , ACTION_DATABASE_RELOAD_TASK) } fun askToStartDatabaseReload(conditionToAsk: Boolean, approved: () -> Unit) { @@ -471,7 +469,7 @@ class DatabaseTaskProvider( putParcelable(DatabaseTaskNotificationService.DATABASE_URI_KEY, databaseUri) putParcelable(DatabaseTaskNotificationService.MAIN_CREDENTIAL_KEY, mainCredential) } - , ACTION_DATABASE_ASSIGN_CREDENTIAL_TASK) + , ACTION_DATABASE_ASSIGN_CREDENTIAL_TASK) } /* @@ -488,7 +486,7 @@ class DatabaseTaskProvider( putParcelable(DatabaseTaskNotificationService.PARENT_ID_KEY, parent.nodeId) putBoolean(DatabaseTaskNotificationService.SAVE_DATABASE_KEY, save) } - , ACTION_DATABASE_CREATE_GROUP_TASK) + , ACTION_DATABASE_CREATE_GROUP_TASK) } fun startDatabaseUpdateGroup(oldGroup: Group, @@ -499,7 +497,7 @@ class DatabaseTaskProvider( putParcelable(DatabaseTaskNotificationService.GROUP_KEY, groupToUpdate) putBoolean(DatabaseTaskNotificationService.SAVE_DATABASE_KEY, save) } - , ACTION_DATABASE_UPDATE_GROUP_TASK) + , ACTION_DATABASE_UPDATE_GROUP_TASK) } fun startDatabaseCreateEntry(newEntry: Entry, @@ -510,7 +508,7 @@ class DatabaseTaskProvider( putParcelable(DatabaseTaskNotificationService.PARENT_ID_KEY, parent.nodeId) putBoolean(DatabaseTaskNotificationService.SAVE_DATABASE_KEY, save) } - , ACTION_DATABASE_CREATE_ENTRY_TASK) + , ACTION_DATABASE_CREATE_ENTRY_TASK) } fun startDatabaseUpdateEntry(oldEntry: Entry, @@ -521,7 +519,7 @@ class DatabaseTaskProvider( putParcelable(DatabaseTaskNotificationService.ENTRY_KEY, entryToUpdate) putBoolean(DatabaseTaskNotificationService.SAVE_DATABASE_KEY, save) } - , ACTION_DATABASE_UPDATE_ENTRY_TASK) + , ACTION_DATABASE_UPDATE_ENTRY_TASK) } private fun startDatabaseActionListNodes(actionTask: String, @@ -550,7 +548,7 @@ class DatabaseTaskProvider( putParcelable(DatabaseTaskNotificationService.PARENT_ID_KEY, newParentId) putBoolean(DatabaseTaskNotificationService.SAVE_DATABASE_KEY, save) } - , actionTask) + , actionTask) } fun startDatabaseCopyNodes(nodesToCopy: List, @@ -584,7 +582,7 @@ class DatabaseTaskProvider( putInt(DatabaseTaskNotificationService.ENTRY_HISTORY_POSITION_KEY, entryHistoryPosition) putBoolean(DatabaseTaskNotificationService.SAVE_DATABASE_KEY, save) } - , ACTION_DATABASE_RESTORE_ENTRY_HISTORY) + , ACTION_DATABASE_RESTORE_ENTRY_HISTORY) } fun startDatabaseDeleteEntryHistory(mainEntryId: NodeId, @@ -595,7 +593,7 @@ class DatabaseTaskProvider( putInt(DatabaseTaskNotificationService.ENTRY_HISTORY_POSITION_KEY, entryHistoryPosition) putBoolean(DatabaseTaskNotificationService.SAVE_DATABASE_KEY, save) } - , ACTION_DATABASE_DELETE_ENTRY_HISTORY) + , ACTION_DATABASE_DELETE_ENTRY_HISTORY) } /* @@ -612,7 +610,7 @@ class DatabaseTaskProvider( putString(DatabaseTaskNotificationService.NEW_ELEMENT_KEY, newName) putBoolean(DatabaseTaskNotificationService.SAVE_DATABASE_KEY, save) } - , ACTION_DATABASE_UPDATE_NAME_TASK) + , ACTION_DATABASE_UPDATE_NAME_TASK) } fun startDatabaseSaveDescription(oldDescription: String, @@ -623,7 +621,7 @@ class DatabaseTaskProvider( putString(DatabaseTaskNotificationService.NEW_ELEMENT_KEY, newDescription) putBoolean(DatabaseTaskNotificationService.SAVE_DATABASE_KEY, save) } - , ACTION_DATABASE_UPDATE_DESCRIPTION_TASK) + , ACTION_DATABASE_UPDATE_DESCRIPTION_TASK) } fun startDatabaseSaveDefaultUsername(oldDefaultUsername: String, @@ -634,7 +632,7 @@ class DatabaseTaskProvider( putString(DatabaseTaskNotificationService.NEW_ELEMENT_KEY, newDefaultUsername) putBoolean(DatabaseTaskNotificationService.SAVE_DATABASE_KEY, save) } - , ACTION_DATABASE_UPDATE_DEFAULT_USERNAME_TASK) + , ACTION_DATABASE_UPDATE_DEFAULT_USERNAME_TASK) } fun startDatabaseSaveColor(oldColor: String, @@ -645,7 +643,7 @@ class DatabaseTaskProvider( putString(DatabaseTaskNotificationService.NEW_ELEMENT_KEY, newColor) putBoolean(DatabaseTaskNotificationService.SAVE_DATABASE_KEY, save) } - , ACTION_DATABASE_UPDATE_COLOR_TASK) + , ACTION_DATABASE_UPDATE_COLOR_TASK) } fun startDatabaseSaveCompression(oldCompression: CompressionAlgorithm, @@ -656,14 +654,14 @@ class DatabaseTaskProvider( putSerializable(DatabaseTaskNotificationService.NEW_ELEMENT_KEY, newCompression) putBoolean(DatabaseTaskNotificationService.SAVE_DATABASE_KEY, save) } - , ACTION_DATABASE_UPDATE_COMPRESSION_TASK) + , ACTION_DATABASE_UPDATE_COMPRESSION_TASK) } fun startDatabaseRemoveUnlinkedData(save: Boolean) { start(Bundle().apply { putBoolean(DatabaseTaskNotificationService.SAVE_DATABASE_KEY, save) } - , ACTION_DATABASE_REMOVE_UNLINKED_DATA_TASK) + , ACTION_DATABASE_REMOVE_UNLINKED_DATA_TASK) } fun startDatabaseSaveRecycleBin(oldRecycleBin: Group?, @@ -696,7 +694,7 @@ class DatabaseTaskProvider( putInt(DatabaseTaskNotificationService.NEW_ELEMENT_KEY, newMaxHistoryItems) putBoolean(DatabaseTaskNotificationService.SAVE_DATABASE_KEY, save) } - , ACTION_DATABASE_UPDATE_MAX_HISTORY_ITEMS_TASK) + , ACTION_DATABASE_UPDATE_MAX_HISTORY_ITEMS_TASK) } fun startDatabaseSaveMaxHistorySize(oldMaxHistorySize: Long, @@ -707,7 +705,7 @@ class DatabaseTaskProvider( putLong(DatabaseTaskNotificationService.NEW_ELEMENT_KEY, newMaxHistorySize) putBoolean(DatabaseTaskNotificationService.SAVE_DATABASE_KEY, save) } - , ACTION_DATABASE_UPDATE_MAX_HISTORY_SIZE_TASK) + , ACTION_DATABASE_UPDATE_MAX_HISTORY_SIZE_TASK) } /* @@ -724,7 +722,7 @@ class DatabaseTaskProvider( putSerializable(DatabaseTaskNotificationService.NEW_ELEMENT_KEY, newEncryption) putBoolean(DatabaseTaskNotificationService.SAVE_DATABASE_KEY, save) } - , ACTION_DATABASE_UPDATE_ENCRYPTION_TASK) + , ACTION_DATABASE_UPDATE_ENCRYPTION_TASK) } fun startDatabaseSaveKeyDerivation(oldKeyDerivation: KdfEngine, @@ -735,7 +733,7 @@ class DatabaseTaskProvider( putSerializable(DatabaseTaskNotificationService.NEW_ELEMENT_KEY, newKeyDerivation) putBoolean(DatabaseTaskNotificationService.SAVE_DATABASE_KEY, save) } - , ACTION_DATABASE_UPDATE_KEY_DERIVATION_TASK) + , ACTION_DATABASE_UPDATE_KEY_DERIVATION_TASK) } fun startDatabaseSaveIterations(oldIterations: Long, @@ -746,7 +744,7 @@ class DatabaseTaskProvider( putLong(DatabaseTaskNotificationService.NEW_ELEMENT_KEY, newIterations) putBoolean(DatabaseTaskNotificationService.SAVE_DATABASE_KEY, save) } - , ACTION_DATABASE_UPDATE_ITERATIONS_TASK) + , ACTION_DATABASE_UPDATE_ITERATIONS_TASK) } fun startDatabaseSaveMemoryUsage(oldMemoryUsage: Long, @@ -757,7 +755,7 @@ class DatabaseTaskProvider( putLong(DatabaseTaskNotificationService.NEW_ELEMENT_KEY, newMemoryUsage) putBoolean(DatabaseTaskNotificationService.SAVE_DATABASE_KEY, save) } - , ACTION_DATABASE_UPDATE_MEMORY_USAGE_TASK) + , ACTION_DATABASE_UPDATE_MEMORY_USAGE_TASK) } fun startDatabaseSaveParallelism(oldParallelism: Long, @@ -768,7 +766,7 @@ class DatabaseTaskProvider( putLong(DatabaseTaskNotificationService.NEW_ELEMENT_KEY, newParallelism) putBoolean(DatabaseTaskNotificationService.SAVE_DATABASE_KEY, save) } - , ACTION_DATABASE_UPDATE_PARALLELISM_TASK) + , ACTION_DATABASE_UPDATE_PARALLELISM_TASK) } /** @@ -779,14 +777,14 @@ class DatabaseTaskProvider( putBoolean(DatabaseTaskNotificationService.SAVE_DATABASE_KEY, save) putParcelable(DatabaseTaskNotificationService.DATABASE_URI_KEY, saveToUri) } - , ACTION_DATABASE_SAVE) + , ACTION_DATABASE_SAVE) } fun startChallengeResponded(response: ByteArray?) { start(Bundle().apply { putByteArray(DatabaseTaskNotificationService.DATA_BYTES, response) } - , ACTION_CHALLENGE_RESPONDED) + , ACTION_CHALLENGE_RESPONDED) } companion object { diff --git a/app/src/main/java/com/kunzisoft/keepass/education/Education.kt b/app/src/main/java/com/kunzisoft/keepass/education/Education.kt index 782b7428f..81e8d9b40 100644 --- a/app/src/main/java/com/kunzisoft/keepass/education/Education.kt +++ b/app/src/main/java/com/kunzisoft/keepass/education/Education.kt @@ -98,7 +98,7 @@ open class Education(val activity: Activity) { } protected fun getCircleColor(): Int { - val typedArray = activity.obtainStyledAttributes(intArrayOf(R.attr.educationCircleColor)) + val typedArray = activity.obtainStyledAttributes(intArrayOf(R.attr.colorPrimaryContainer)) val colorControl = typedArray.getColor(0, Color.GREEN) typedArray.recycle() return colorControl @@ -109,7 +109,7 @@ open class Education(val activity: Activity) { } protected fun getTextColor(): Int { - val typedArray = activity.obtainStyledAttributes(intArrayOf(R.attr.educationTextColor)) + val typedArray = activity.obtainStyledAttributes(intArrayOf(R.attr.colorOnPrimaryContainer)) val colorControl = typedArray.getColor(0, Color.WHITE) typedArray.recycle() return colorControl diff --git a/app/src/main/java/com/kunzisoft/keepass/education/PasswordActivityEducation.kt b/app/src/main/java/com/kunzisoft/keepass/education/PasswordActivityEducation.kt index dc4afd1d9..805e768c0 100644 --- a/app/src/main/java/com/kunzisoft/keepass/education/PasswordActivityEducation.kt +++ b/app/src/main/java/com/kunzisoft/keepass/education/PasswordActivityEducation.kt @@ -93,8 +93,9 @@ class PasswordActivityEducation(activity: Activity) activity.getString(R.string.education_advanced_unlock_summary)) .outerCircleColorInt(getCircleColor()) .outerCircleAlpha(getCircleAlpha()) + .icon(ContextCompat.getDrawable(activity, R.drawable.ic_fingerprint_24)) .textColorInt(getTextColor()) - .tintTarget(false) + .tintTarget(true) .cancelable(true), object : TapTargetView.Listener() { override fun onTargetClick(view: TapTargetView) { diff --git a/app/src/main/java/com/kunzisoft/keepass/services/AttachmentFileNotificationService.kt b/app/src/main/java/com/kunzisoft/keepass/services/AttachmentFileNotificationService.kt index b79c65ab5..c15e7988c 100644 --- a/app/src/main/java/com/kunzisoft/keepass/services/AttachmentFileNotificationService.kt +++ b/app/src/main/java/com/kunzisoft/keepass/services/AttachmentFileNotificationService.kt @@ -240,10 +240,10 @@ class AttachmentFileNotificationService: LockNotificationService() { setOngoing(true) } AttachmentState.IN_PROGRESS -> { - if (attachmentNotification.entryAttachmentState.downloadProgression > 100) { + if (attachmentNotification.entryAttachmentState.downloadProgression > FILE_PROGRESSION_MAX) { setContentText(getString(R.string.download_finalization)) } else { - setProgress(100, + setProgress(FILE_PROGRESSION_MAX, attachmentNotification.entryAttachmentState.downloadProgression, false) setContentText(getString(R.string.download_progression, @@ -446,7 +446,7 @@ class AttachmentFileNotificationService: LockNotificationService() { if (downloadState != AttachmentState.CANCELED && downloadState != AttachmentState.ERROR) { downloadState = AttachmentState.COMPLETE - downloadProgression = 100 + downloadProgression = FILE_PROGRESSION_MAX } } attachmentNotification.attachmentFileAction = null @@ -495,6 +495,8 @@ class AttachmentFileNotificationService: LockNotificationService() { const val FILE_URI_KEY = "FILE_URI_KEY" const val ATTACHMENT_KEY = "ATTACHMENT_KEY" + + const val FILE_PROGRESSION_MAX = 100 } } \ No newline at end of file diff --git a/app/src/main/java/com/kunzisoft/keepass/settings/SettingsAdvancedUnlockActivity.kt b/app/src/main/java/com/kunzisoft/keepass/settings/AdvancedUnlockSettingsActivity.kt similarity index 95% rename from app/src/main/java/com/kunzisoft/keepass/settings/SettingsAdvancedUnlockActivity.kt rename to app/src/main/java/com/kunzisoft/keepass/settings/AdvancedUnlockSettingsActivity.kt index 8ff82df74..c74e0160b 100644 --- a/app/src/main/java/com/kunzisoft/keepass/settings/SettingsAdvancedUnlockActivity.kt +++ b/app/src/main/java/com/kunzisoft/keepass/settings/AdvancedUnlockSettingsActivity.kt @@ -23,7 +23,7 @@ import android.os.Bundle import androidx.fragment.app.Fragment -class SettingsAdvancedUnlockActivity : SettingsActivity() { +class AdvancedUnlockSettingsActivity : SettingsActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) diff --git a/app/src/main/java/com/kunzisoft/keepass/settings/AppearanceSettingsActivity.kt b/app/src/main/java/com/kunzisoft/keepass/settings/AppearanceSettingsActivity.kt new file mode 100644 index 000000000..87efa3961 --- /dev/null +++ b/app/src/main/java/com/kunzisoft/keepass/settings/AppearanceSettingsActivity.kt @@ -0,0 +1,38 @@ +/* + * Copyright 2019 Jeremy Jamet / Kunzisoft. + * + * This file is part of KeePassDX. + * + * KeePassDX is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * KeePassDX is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with KeePassDX. If not, see . + * + */ +package com.kunzisoft.keepass.settings + +import android.os.Bundle +import android.view.MenuItem +import androidx.fragment.app.Fragment + + +class AppearanceSettingsActivity : SettingsActivity() { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + mTimeoutEnable = false + setTitle(NestedSettingsFragment.Screen.APPEARANCE) + } + + override fun retrieveMainFragment(): Fragment { + return NestedSettingsFragment.newInstance(NestedSettingsFragment.Screen.APPEARANCE) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/kunzisoft/keepass/settings/AutofillSettingsFragment.kt b/app/src/main/java/com/kunzisoft/keepass/settings/AutofillSettingsFragment.kt index 1e9fa538a..abd8445e9 100644 --- a/app/src/main/java/com/kunzisoft/keepass/settings/AutofillSettingsFragment.kt +++ b/app/src/main/java/com/kunzisoft/keepass/settings/AutofillSettingsFragment.kt @@ -24,7 +24,7 @@ import android.os.Bundle import androidx.fragment.app.DialogFragment import androidx.preference.Preference import androidx.preference.PreferenceFragmentCompat -import androidx.preference.SwitchPreference +import androidx.preference.TwoStatePreference import com.kunzisoft.keepass.R import com.kunzisoft.keepass.settings.preferencedialogfragment.AutofillBlocklistAppIdPreferenceDialogFragmentCompat import com.kunzisoft.keepass.settings.preferencedialogfragment.AutofillBlocklistWebDomainPreferenceDialogFragmentCompat @@ -35,7 +35,7 @@ class AutofillSettingsFragment : PreferenceFragmentCompat() { // Load the preferences from an XML resource setPreferencesFromResource(R.xml.preferences_autofill, rootKey) - val autofillInlineSuggestionsPreference: SwitchPreference? = findPreference(getString(R.string.autofill_inline_suggestions_key)) + val autofillInlineSuggestionsPreference: TwoStatePreference? = findPreference(getString(R.string.autofill_inline_suggestions_key)) if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) { autofillInlineSuggestionsPreference?.isVisible = false } diff --git a/app/src/main/java/com/kunzisoft/keepass/settings/MainPreferenceFragment.kt b/app/src/main/java/com/kunzisoft/keepass/settings/MainPreferenceFragment.kt index 0e0696858..11328513e 100644 --- a/app/src/main/java/com/kunzisoft/keepass/settings/MainPreferenceFragment.kt +++ b/app/src/main/java/com/kunzisoft/keepass/settings/MainPreferenceFragment.kt @@ -24,6 +24,7 @@ import android.os.Bundle import android.view.View import androidx.fragment.app.activityViewModels import androidx.preference.Preference +import androidx.preference.PreferenceCategory import androidx.preference.PreferenceFragmentCompat import com.kunzisoft.keepass.R import com.kunzisoft.keepass.viewmodels.DatabaseViewModel @@ -60,6 +61,9 @@ class MainPreferenceFragment : PreferenceFragmentCompat() { private fun checkDatabaseLoaded() { findPreference(getString(R.string.settings_database_key)) ?.isEnabled = mDatabaseLoaded + + findPreference(getString(R.string.settings_database_category_key)) + ?.isVisible = mDatabaseLoaded } override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { diff --git a/app/src/main/java/com/kunzisoft/keepass/settings/NestedAppSettingsFragment.kt b/app/src/main/java/com/kunzisoft/keepass/settings/NestedAppSettingsFragment.kt index c67615c42..ed2476e2f 100644 --- a/app/src/main/java/com/kunzisoft/keepass/settings/NestedAppSettingsFragment.kt +++ b/app/src/main/java/com/kunzisoft/keepass/settings/NestedAppSettingsFragment.kt @@ -34,7 +34,7 @@ import androidx.fragment.app.DialogFragment import androidx.fragment.app.FragmentActivity import androidx.preference.ListPreference import androidx.preference.Preference -import androidx.preference.SwitchPreference +import androidx.preference.TwoStatePreference import com.kunzisoft.keepass.BuildConfig import com.kunzisoft.keepass.R import com.kunzisoft.keepass.activities.dialogs.ProFeatureDialogFragment @@ -119,14 +119,14 @@ class NestedAppSettingsFragment : NestedSettingsFragment() { activity?.let { activity -> if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - val autoFillEnablePreference: SwitchPreference? = findPreference(getString(R.string.settings_autofill_enable_key)) + val autoFillEnablePreference: TwoStatePreference? = findPreference(getString(R.string.settings_autofill_enable_key)) 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) { + if ((preference as TwoStatePreference).isChecked) { try { enableService() } catch (e: ActivityNotFoundException) { @@ -208,14 +208,13 @@ class NestedAppSettingsFragment : NestedSettingsFragment() { false } - val copyPasswordPreference: SwitchPreference? = findPreference(getString(R.string.allow_copy_password_key)) + val copyPasswordPreference: TwoStatePreference? = 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(requireContext()) + AlertDialog.Builder(requireContext()) .setMessage(message) .create() .apply { @@ -240,10 +239,10 @@ class NestedAppSettingsFragment : NestedSettingsFragment() { activity?.let { activity -> - val biometricUnlockEnablePreference: SwitchPreference? = findPreference(getString(R.string.biometric_unlock_enable_key)) - val deviceCredentialUnlockEnablePreference: SwitchPreference? = findPreference(getString(R.string.device_credential_unlock_enable_key)) - val autoOpenPromptPreference: SwitchPreference? = findPreference(getString(R.string.biometric_auto_open_prompt_key)) - val tempAdvancedUnlockPreference: SwitchPreference? = findPreference(getString(R.string.temp_advanced_unlock_enable_key)) + val biometricUnlockEnablePreference: TwoStatePreference? = findPreference(getString(R.string.biometric_unlock_enable_key)) + val deviceCredentialUnlockEnablePreference: TwoStatePreference? = findPreference(getString(R.string.device_credential_unlock_enable_key)) + val autoOpenPromptPreference: TwoStatePreference? = findPreference(getString(R.string.biometric_auto_open_prompt_key)) + val tempAdvancedUnlockPreference: TwoStatePreference? = findPreference(getString(R.string.temp_advanced_unlock_enable_key)) val biometricUnlockSupported = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { AdvancedUnlockManager.biometricUnlockSupported(activity) @@ -253,7 +252,7 @@ class NestedAppSettingsFragment : NestedSettingsFragment() { if (!biometricUnlockSupported) { isChecked = false setOnPreferenceClickListener { preference -> - (preference as SwitchPreference).isChecked = false + (preference as TwoStatePreference).isChecked = false UnavailableFeatureDialogFragment.getInstance(Build.VERSION_CODES.M) .show(parentFragmentManager, "unavailableFeatureDialog") false @@ -300,7 +299,7 @@ class NestedAppSettingsFragment : NestedSettingsFragment() { if (!deviceCredentialUnlockSupported) { isChecked = false setOnPreferenceClickListener { preference -> - (preference as SwitchPreference).isChecked = false + (preference as TwoStatePreference).isChecked = false UnavailableFeatureDialogFragment.getInstance(Build.VERSION_CODES.M) .show(parentFragmentManager, "unavailableFeatureDialog") false @@ -523,7 +522,7 @@ class NestedAppSettingsFragment : NestedSettingsFragment() { super.onResume() activity?.let { activity -> if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - findPreference(getString(R.string.settings_autofill_enable_key))?.let { autoFillEnablePreference -> + findPreference(getString(R.string.settings_autofill_enable_key))?.let { autoFillEnablePreference -> val autofillManager = activity.getSystemService(AutofillManager::class.java) autoFillEnablePreference.isChecked = autofillManager != null && autofillManager.hasEnabledAutofillServices() diff --git a/app/src/main/java/com/kunzisoft/keepass/settings/NestedDatabaseSettingsFragment.kt b/app/src/main/java/com/kunzisoft/keepass/settings/NestedDatabaseSettingsFragment.kt index d8c11720f..080ece82f 100644 --- a/app/src/main/java/com/kunzisoft/keepass/settings/NestedDatabaseSettingsFragment.kt +++ b/app/src/main/java/com/kunzisoft/keepass/settings/NestedDatabaseSettingsFragment.kt @@ -28,7 +28,7 @@ import androidx.fragment.app.DialogFragment import androidx.fragment.app.activityViewModels import androidx.preference.Preference import androidx.preference.PreferenceCategory -import androidx.preference.SwitchPreference +import androidx.preference.TwoStatePreference import com.kunzisoft.androidclearchroma.ChromaUtil import com.kunzisoft.keepass.R import com.kunzisoft.keepass.activities.dialogs.SetMainCredentialDialogFragment @@ -253,7 +253,7 @@ class NestedDatabaseSettingsFragment : NestedSettingsFragment(), DatabaseRetriev // Recycle bin if (database.allowConfigurableRecycleBin) { - val recycleBinEnablePref: SwitchPreference? = findPreference(getString(R.string.recycle_bin_enable_key)) + val recycleBinEnablePref: TwoStatePreference? = findPreference(getString(R.string.recycle_bin_enable_key)) recycleBinEnablePref?.apply { isChecked = database.isRecycleBinEnabled isEnabled = if (!mDatabaseReadOnly) { @@ -286,7 +286,7 @@ class NestedDatabaseSettingsFragment : NestedSettingsFragment(), DatabaseRetriev val templatesGroupPrefCategory: PreferenceCategory? = findPreference(getString(R.string.database_category_templates_key)) templatesGroupPref = findPreference(getString(R.string.templates_group_uuid_key)) if (database.allowTemplatesGroup) { - val templatesEnablePref: SwitchPreference? = findPreference(getString(R.string.templates_group_enable_key)) + val templatesEnablePref: TwoStatePreference? = findPreference(getString(R.string.templates_group_enable_key)) templatesEnablePref?.apply { isChecked = database.isTemplatesEnabled isEnabled = if (!mDatabaseReadOnly) { diff --git a/app/src/main/java/com/kunzisoft/keepass/settings/NestedSettingsFragment.kt b/app/src/main/java/com/kunzisoft/keepass/settings/NestedSettingsFragment.kt index f7f36b872..814e50d76 100644 --- a/app/src/main/java/com/kunzisoft/keepass/settings/NestedSettingsFragment.kt +++ b/app/src/main/java/com/kunzisoft/keepass/settings/NestedSettingsFragment.kt @@ -23,7 +23,7 @@ import android.content.res.Resources import android.os.Bundle import androidx.preference.Preference import androidx.preference.PreferenceFragmentCompat -import androidx.preference.SwitchPreference +import androidx.preference.TwoStatePreference import com.kunzisoft.keepass.R import com.kunzisoft.keepass.activities.dialogs.UnderDevelopmentFeatureDialogFragment @@ -49,7 +49,7 @@ abstract class NestedSettingsFragment : PreferenceFragmentCompat() { protected fun preferenceInDevelopment(preferenceInDev: Preference) { preferenceInDev.setOnPreferenceClickListener { preference -> try { // don't check if we can - (preference as SwitchPreference).isChecked = false + (preference as TwoStatePreference).isChecked = false } catch (ignored: Exception) { } UnderDevelopmentFeatureDialogFragment().show(parentFragmentManager, "underDevFeatureDialog") diff --git a/app/src/main/java/com/kunzisoft/keepass/settings/preferencedialogfragment/InputPreferenceDialogFragmentCompat.kt b/app/src/main/java/com/kunzisoft/keepass/settings/preferencedialogfragment/InputPreferenceDialogFragmentCompat.kt index d88fa8f7f..86c83b36b 100644 --- a/app/src/main/java/com/kunzisoft/keepass/settings/preferencedialogfragment/InputPreferenceDialogFragmentCompat.kt +++ b/app/src/main/java/com/kunzisoft/keepass/settings/preferencedialogfragment/InputPreferenceDialogFragmentCompat.kt @@ -70,7 +70,7 @@ abstract class InputPreferenceDialogFragmentCompat : PreferenceDialogFragmentCom get() = textUnitView?.text?.toString() ?: "" set(unitText) { textUnitView?.apply { - if (unitText != null && unitText.isNotEmpty()) { + if (!unitText.isNullOrEmpty()) { text = unitText visibility = View.VISIBLE } else { @@ -88,7 +88,7 @@ abstract class InputPreferenceDialogFragmentCompat : PreferenceDialogFragmentCom get() = textExplanationView?.text?.toString() ?: "" set(explanationText) { textExplanationView?.apply { - if (explanationText != null && explanationText.isNotEmpty()) { + if (!explanationText.isNullOrEmpty()) { text = explanationText visibility = View.VISIBLE } else { @@ -107,7 +107,7 @@ abstract class InputPreferenceDialogFragmentCompat : PreferenceDialogFragmentCom fun setExplanationButton(explanationButtonText: String?, clickListener: View.OnClickListener) { explanationButton?.apply { - if (explanationButtonText != null && explanationButtonText.isNotEmpty()) { + if (!explanationButtonText.isNullOrEmpty()) { text = explanationButtonText visibility = View.VISIBLE setOnClickListener(clickListener) diff --git a/app/src/main/java/com/kunzisoft/keepass/timeout/ClipboardHelper.kt b/app/src/main/java/com/kunzisoft/keepass/timeout/ClipboardHelper.kt index 6e92bfb9b..9fce0d822 100644 --- a/app/src/main/java/com/kunzisoft/keepass/timeout/ClipboardHelper.kt +++ b/app/src/main/java/com/kunzisoft/keepass/timeout/ClipboardHelper.kt @@ -34,7 +34,8 @@ import android.widget.Toast import androidx.appcompat.app.AlertDialog import com.kunzisoft.keepass.R import com.kunzisoft.keepass.settings.PreferencesUtil -import java.util.* +import java.util.Timer +import java.util.TimerTask class ClipboardHelper(context: Context) { diff --git a/app/src/main/java/com/kunzisoft/keepass/view/AddNodeButtonView.kt b/app/src/main/java/com/kunzisoft/keepass/view/AddNodeButtonView.kt index b123fce8d..910abff0a 100644 --- a/app/src/main/java/com/kunzisoft/keepass/view/AddNodeButtonView.kt +++ b/app/src/main/java/com/kunzisoft/keepass/view/AddNodeButtonView.kt @@ -43,7 +43,9 @@ class AddNodeButtonView @JvmOverloads constructor(context: Context, var addButtonView: FloatingActionButton? = null private lateinit var addEntryView: View + private lateinit var fabAddEntryView: View private lateinit var addGroupView: View + private lateinit var fabAddGroupView: View private var addEntryEnable: Boolean = false private var addGroupEnable: Boolean = false @@ -77,7 +79,9 @@ class AddNodeButtonView @JvmOverloads constructor(context: Context, addButtonView = findViewById(R.id.add_button) addEntryView = findViewById(R.id.container_add_entry) + fabAddEntryView = findViewById(R.id.fab_add_entry) addGroupView = findViewById(R.id.container_add_group) + fabAddGroupView = findViewById(R.id.fab_add_group) animationDuration = 300L @@ -189,24 +193,21 @@ class AddNodeButtonView @JvmOverloads constructor(context: Context, } } + private fun onButtonClickListener(onClickListener: OnClickListener) = + OnClickListener { view -> + onClickListener.onClick(view) + closeButtonIfOpen() + } + fun setAddGroupClickListener(onClickListener: OnClickListener) { - if (addGroupEnable) - addGroupView.setOnClickListener { view -> - onClickListener.onClick(view) - closeButtonIfOpen() - } + if (addGroupEnable) { + fabAddGroupView.setOnClickListener(onButtonClickListener(onClickListener)) + } } fun setAddEntryClickListener(onClickListener: OnClickListener) { if (addEntryEnable) { - addEntryView.setOnClickListener { view -> - onClickListener.onClick(view) - closeButtonIfOpen() - } - addEntryView.setOnClickListener { view -> - onClickListener.onClick(view) - closeButtonIfOpen() - } + fabAddEntryView.setOnClickListener(onButtonClickListener(onClickListener)) } } diff --git a/app/src/main/java/com/kunzisoft/keepass/view/AdvancedUnlockInfoView.kt b/app/src/main/java/com/kunzisoft/keepass/view/AdvancedUnlockInfoView.kt index c91a7a9da..083b2be73 100644 --- a/app/src/main/java/com/kunzisoft/keepass/view/AdvancedUnlockInfoView.kt +++ b/app/src/main/java/com/kunzisoft/keepass/view/AdvancedUnlockInfoView.kt @@ -23,14 +23,12 @@ import android.content.Context import android.os.Build import android.util.AttributeSet import android.view.LayoutInflater -import android.view.View -import android.widget.ImageView +import android.widget.Button import android.widget.LinearLayout -import android.widget.TextView +import android.widget.Toast import androidx.annotation.RequiresApi import androidx.annotation.StringRes import com.kunzisoft.keepass.R -import com.kunzisoft.keepass.biometric.FingerPrintAnimatedVector @RequiresApi(api = Build.VERSION_CODES.M) class AdvancedUnlockInfoView @JvmOverloads constructor(context: Context, @@ -38,83 +36,38 @@ class AdvancedUnlockInfoView @JvmOverloads constructor(context: Context, defStyle: Int = 0) : LinearLayout(context, attrs, defStyle) { - private val unlockContainerView: View - private var unlockAnimatedVector: FingerPrintAnimatedVector? = null - private var unlockTitleTextView: TextView? = null - private var unlockMessageTextView: TextView? = null - private var unlockIconImageView: ImageView? = null + private var biometricButtonView: Button? = null init { - val inflater = context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater? inflater?.inflate(R.layout.view_advanced_unlock, this) - unlockContainerView = findViewById(R.id.fingerprint_container) - unlockTitleTextView = findViewById(R.id.biometric_title) - unlockMessageTextView = findViewById(R.id.biometric_message) - unlockIconImageView = findViewById(R.id.biometric_image) + biometricButtonView = findViewById(R.id.biometric_button) } - private fun startIconViewAnimation() { - unlockAnimatedVector?.startScan() - } - - private fun stopIconViewAnimation() { - unlockAnimatedVector?.stopScan() - } - - fun setIconResource(iconId: Int) { - unlockIconImageView?.setImageResource(iconId) - // Init the fingerprint animation - unlockAnimatedVector = when (iconId) { - R.drawable.fingerprint -> FingerPrintAnimatedVector(context, unlockIconImageView!!) - else -> null - } - } - - fun setIconViewClickListener(animation: Boolean = true, - listener: ((view: View)->Unit)?) { - var animateButton = animation - if (listener == null) - animateButton = false - if (animateButton) { - startIconViewAnimation() - unlockContainerView.alpha = 1f - } else { - stopIconViewAnimation() - unlockContainerView.alpha = 0.8f - } - unlockIconImageView?.setOnClickListener(listener) + fun setIconViewClickListener(listener: OnClickListener?) { + biometricButtonView?.setOnClickListener(listener) } var title: CharSequence get() { - return unlockTitleTextView?.text?.toString() ?: "" + return biometricButtonView?.text?.toString() ?: "" } set(value) { - unlockTitleTextView?.text = value + biometricButtonView?.text = value } fun setTitle(@StringRes textId: Int) { title = context.getString(textId) } - var message: CharSequence? - get() { - return unlockMessageTextView?.text?.toString() ?: "" - } - set(value) { - if (value == null || value.isEmpty()) { - unlockMessageTextView?.visibility = GONE - } else { - unlockMessageTextView?.visibility = VISIBLE - stopIconViewAnimation() - } - unlockMessageTextView?.text = value ?: "" - } + fun setMessage(text: CharSequence) { + if (text.isNotEmpty()) + Toast.makeText(context, text, Toast.LENGTH_LONG).show() + } fun setMessage(@StringRes textId: Int) { - message = context.getString(textId) + Toast.makeText(context, textId, Toast.LENGTH_LONG).show() } } \ No newline at end of file diff --git a/app/src/main/java/com/kunzisoft/keepass/view/DataDate.kt b/app/src/main/java/com/kunzisoft/keepass/view/DataDate.kt deleted file mode 100644 index 24f520198..000000000 --- a/app/src/main/java/com/kunzisoft/keepass/view/DataDate.kt +++ /dev/null @@ -1,3 +0,0 @@ -package com.kunzisoft.keepass.view - -data class DataDate(val year: Int, val month: Int, val day: Int) \ No newline at end of file diff --git a/app/src/main/java/com/kunzisoft/keepass/view/SearchFiltersView.kt b/app/src/main/java/com/kunzisoft/keepass/view/SearchFiltersView.kt index 434e4e715..0536b6f39 100644 --- a/app/src/main/java/com/kunzisoft/keepass/view/SearchFiltersView.kt +++ b/app/src/main/java/com/kunzisoft/keepass/view/SearchFiltersView.kt @@ -189,6 +189,8 @@ class SearchFiltersView @JvmOverloads constructor(context: Context, searchParameters.searchInTemplates = isChecked mOnParametersChangeListener?.invoke(searchParameters) } + + searchNumbers.setOnClickListener(null) } fun setNumbers(numbers: Int) { diff --git a/app/src/main/java/com/kunzisoft/keepass/view/TemplateEditView.kt b/app/src/main/java/com/kunzisoft/keepass/view/TemplateEditView.kt index 31b8f9af3..151a9a422 100644 --- a/app/src/main/java/com/kunzisoft/keepass/view/TemplateEditView.kt +++ b/app/src/main/java/com/kunzisoft/keepass/view/TemplateEditView.kt @@ -217,14 +217,12 @@ class TemplateEditView @JvmOverloads constructor(context: Context, } } - fun setCurrentDateTimeValue(date: DataDate) { + fun setCurrentDateTimeValue(dateMilliseconds: Long) { // Save the date setCurrentDateTimeSelection { instant -> val newDateInstant = DateInstant( DateTime(instant.date) - .withYear(date.year) - .withMonthOfYear(date.month + 1) - .withDayOfMonth(date.day) + .withMillis(dateMilliseconds) .toDate(), instant.type) if (instant.type == DateInstant.Type.DATE_TIME) { val instantTime = DateInstant(instant.date, DateInstant.Type.TIME) diff --git a/app/src/main/java/com/kunzisoft/keepass/view/ToolbarAction.kt b/app/src/main/java/com/kunzisoft/keepass/view/ToolbarAction.kt index 852bd9aa3..82f0fbfa1 100644 --- a/app/src/main/java/com/kunzisoft/keepass/view/ToolbarAction.kt +++ b/app/src/main/java/com/kunzisoft/keepass/view/ToolbarAction.kt @@ -31,14 +31,14 @@ import android.view.View import androidx.annotation.ColorInt import androidx.appcompat.view.ActionMode import androidx.appcompat.view.SupportMenuInflater -import androidx.appcompat.widget.Toolbar import androidx.core.content.ContextCompat +import com.google.android.material.appbar.MaterialToolbar import com.kunzisoft.keepass.R class ToolbarAction @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, - defStyle: Int = androidx.appcompat.R.attr.toolbarStyle) - : Toolbar(context, attrs, defStyle) { + defStyle: Int = R.attr.toolbarActionStyle) + : MaterialToolbar(context, attrs, defStyle) { private var mActionModeCallback: ActionMode.Callback? = null private val actionMode = NodeActionMode(this) @@ -47,7 +47,7 @@ class ToolbarAction @JvmOverloads constructor(context: Context, init { ContextCompat.getDrawable(context, R.drawable.ic_close_white_24dp)?.let { closeDrawable -> val typedValue = TypedValue() - context.theme.resolveAttribute(R.attr.colorControlNormal, typedValue, true) + context.theme.resolveAttribute(R.attr.colorOnSurface, typedValue, true) @ColorInt val colorControl = typedValue.data closeDrawable.colorFilter = PorterDuffColorFilter(colorControl, PorterDuff.Mode.SRC_ATOP) navigationIcon = closeDrawable diff --git a/app/src/main/java/com/kunzisoft/keepass/view/SpecialModeView.kt b/app/src/main/java/com/kunzisoft/keepass/view/ToolbarSpecial.kt similarity index 85% rename from app/src/main/java/com/kunzisoft/keepass/view/SpecialModeView.kt rename to app/src/main/java/com/kunzisoft/keepass/view/ToolbarSpecial.kt index 77ab72795..2da08e1dc 100644 --- a/app/src/main/java/com/kunzisoft/keepass/view/SpecialModeView.kt +++ b/app/src/main/java/com/kunzisoft/keepass/view/ToolbarSpecial.kt @@ -26,14 +26,14 @@ import android.util.AttributeSet import android.util.TypedValue import android.view.View import androidx.annotation.ColorInt -import androidx.appcompat.widget.Toolbar import androidx.core.content.ContextCompat +import com.google.android.material.appbar.MaterialToolbar import com.kunzisoft.keepass.R -class SpecialModeView @JvmOverloads constructor(context: Context, - attrs: AttributeSet? = null, - defStyle: Int = androidx.appcompat.R.attr.toolbarStyle) - : Toolbar(context, attrs, defStyle) { +class ToolbarSpecial @JvmOverloads constructor(context: Context, + attrs: AttributeSet? = null, + defStyle: Int = R.attr.toolbarSpecialStyle) + : MaterialToolbar(context, attrs, defStyle) { init { ContextCompat.getDrawable(context, R.drawable.ic_arrow_back_white_24dp)?.let { closeDrawable -> diff --git a/app/src/main/java/com/kunzisoft/keepass/viewmodels/NodeEditViewModel.kt b/app/src/main/java/com/kunzisoft/keepass/viewmodels/NodeEditViewModel.kt index 4c55af246..e649063c0 100644 --- a/app/src/main/java/com/kunzisoft/keepass/viewmodels/NodeEditViewModel.kt +++ b/app/src/main/java/com/kunzisoft/keepass/viewmodels/NodeEditViewModel.kt @@ -4,7 +4,6 @@ import androidx.lifecycle.LiveData import androidx.lifecycle.ViewModel import com.kunzisoft.keepass.database.element.DateInstant import com.kunzisoft.keepass.database.element.icon.IconImage -import com.kunzisoft.keepass.view.DataDate import com.kunzisoft.keepass.view.DataTime abstract class NodeEditViewModel : ViewModel() { @@ -24,8 +23,8 @@ abstract class NodeEditViewModel : ViewModel() { val requestDateTimeSelection : LiveData get() = _requestDateTimeSelection private val _requestDateTimeSelection = SingleLiveEvent() - val onDateSelected : LiveData get() = _onDateSelected - private val _onDateSelected = SingleLiveEvent() + val onDateSelected : LiveData get() = _onDateSelected + private val _onDateSelected = SingleLiveEvent() val onTimeSelected : LiveData get() = _onTimeSelected private val _onTimeSelected = SingleLiveEvent() @@ -58,8 +57,8 @@ abstract class NodeEditViewModel : ViewModel() { _requestDateTimeSelection.value = dateInstant } - fun selectDate(year: Int, month: Int, day: Int) { - _onDateSelected.value = DataDate(year, month, day) + fun selectDate(dateMilliseconds: Long) { + _onDateSelected.value = dateMilliseconds } fun selectTime(hours: Int, minutes: Int) { diff --git a/app/src/main/res/animator-v23/scan.xml b/app/src/main/res/animator-v23/scan.xml deleted file mode 100644 index d4965f389..000000000 --- a/app/src/main/res/animator-v23/scan.xml +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - - - diff --git a/app/src/main/res/color-v23/progress_color.xml b/app/src/main/res/color-v23/progress_color.xml deleted file mode 100644 index cc68be3d4..000000000 --- a/app/src/main/res/color-v23/progress_color.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/app/src/main/res/color/background_button_color_accent.xml b/app/src/main/res/color/background_button_color_accent.xml deleted file mode 100644 index 9af1c0e0d..000000000 --- a/app/src/main/res/color/background_button_color_accent.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/color/background_button_color_primary.xml b/app/src/main/res/color/background_button_color_primary.xml deleted file mode 100644 index 31a28d56a..000000000 --- a/app/src/main/res/color/background_button_color_primary.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/app/src/main/res/color/background_button_color_secondary.xml b/app/src/main/res/color/background_button_color_secondary.xml deleted file mode 100644 index 0a69948d9..000000000 --- a/app/src/main/res/color/background_button_color_secondary.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/app/src/main/res/color/background_color_chip.xml b/app/src/main/res/color/background_color_chip.xml deleted file mode 100644 index 18061d697..000000000 --- a/app/src/main/res/color/background_color_chip.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/app/src/main/res/color/edit_text_stroke_color.xml b/app/src/main/res/color/edit_text_stroke_color.xml deleted file mode 100644 index 1e73b070e..000000000 --- a/app/src/main/res/color/edit_text_stroke_color.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/color/list_color.xml b/app/src/main/res/color/list_color.xml deleted file mode 100644 index cc8ab381d..000000000 --- a/app/src/main/res/color/list_color.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/app/src/main/res/color/list_secondary_color.xml b/app/src/main/res/color/list_secondary_color.xml deleted file mode 100644 index 369b45e68..000000000 --- a/app/src/main/res/color/list_secondary_color.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/app/src/main/res/color/on_surface_selector.xml b/app/src/main/res/color/on_surface_selector.xml new file mode 100644 index 000000000..b4d423690 --- /dev/null +++ b/app/src/main/res/color/on_surface_selector.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/color/progress_color.xml b/app/src/main/res/color/progress_color.xml deleted file mode 100644 index 71df5c427..000000000 --- a/app/src/main/res/color/progress_color.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/app/src/main/res/color/text_color_button.xml b/app/src/main/res/color/text_color_button.xml deleted file mode 100644 index 13c44bba4..000000000 --- a/app/src/main/res/color/text_color_button.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/app/src/main/res/color/text_color_light.xml b/app/src/main/res/color/text_color_light.xml deleted file mode 100644 index 83fbc9bbf..000000000 --- a/app/src/main/res/color/text_color_light.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/app/src/main/res/color/text_color_night.xml b/app/src/main/res/color/text_color_night.xml deleted file mode 100644 index b452f1fa0..000000000 --- a/app/src/main/res/color/text_color_night.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/app/src/main/res/color/text_color_secondary_light.xml b/app/src/main/res/color/text_color_secondary_light.xml deleted file mode 100644 index 7005319e0..000000000 --- a/app/src/main/res/color/text_color_secondary_light.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/app/src/main/res/color/text_color_secondary_night.xml b/app/src/main/res/color/text_color_secondary_night.xml deleted file mode 100644 index ea11472bf..000000000 --- a/app/src/main/res/color/text_color_secondary_night.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/app/src/main/res/color/list_primary_color.xml b/app/src/main/res/color/text_primary_color.xml similarity index 70% rename from app/src/main/res/color/list_primary_color.xml rename to app/src/main/res/color/text_primary_color.xml index 06694e43a..c996c36e2 100644 --- a/app/src/main/res/color/list_primary_color.xml +++ b/app/src/main/res/color/text_primary_color.xml @@ -1,5 +1,5 @@ - - + + \ No newline at end of file diff --git a/app/src/main/res/color-v23/list_secondary_color.xml b/app/src/main/res/color/text_secondary_color.xml similarity index 100% rename from app/src/main/res/color-v23/list_secondary_color.xml rename to app/src/main/res/color/text_secondary_color.xml diff --git a/app/src/main/res/drawable-v21/background_button.xml b/app/src/main/res/drawable-v21/background_button.xml deleted file mode 100644 index efe76dbbc..000000000 --- a/app/src/main/res/drawable-v21/background_button.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/drawable-v21/background_button_small.xml b/app/src/main/res/drawable-v21/background_button_small.xml deleted file mode 100644 index a1a543eb2..000000000 --- a/app/src/main/res/drawable-v21/background_button_small.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/drawable-v21/background_icon.xml b/app/src/main/res/drawable-v21/background_icon.xml index 4bf4cf1ca..eeed6744d 100644 --- a/app/src/main/res/drawable-v21/background_icon.xml +++ b/app/src/main/res/drawable-v21/background_icon.xml @@ -11,7 +11,7 @@ android:right="12dp" android:top="12dp" android:bottom="12dp"/> - + \ No newline at end of file diff --git a/app/src/main/res/drawable-v21/background_image_button.xml b/app/src/main/res/drawable-v21/background_image_button.xml index ae42055a0..416ee142b 100644 --- a/app/src/main/res/drawable-v21/background_image_button.xml +++ b/app/src/main/res/drawable-v21/background_image_button.xml @@ -6,7 +6,7 @@ - + - - - - - + + + + + + + + + + + + + + + + - - - - - - \ No newline at end of file + \ No newline at end of file diff --git a/app/src/main/res/drawable-v23/bolt.xml b/app/src/main/res/drawable-v23/bolt.xml deleted file mode 100644 index 8684f8cf3..000000000 --- a/app/src/main/res/drawable-v23/bolt.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - diff --git a/app/src/main/res/drawable-v23/fingerprint.xml b/app/src/main/res/drawable-v23/fingerprint.xml deleted file mode 100644 index 43393ec87..000000000 --- a/app/src/main/res/drawable-v23/fingerprint.xml +++ /dev/null @@ -1,65 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/app/src/main/res/drawable-v23/fingerprint_scan.xml b/app/src/main/res/drawable-v23/fingerprint_scan.xml deleted file mode 100644 index 553792910..000000000 --- a/app/src/main/res/drawable-v23/fingerprint_scan.xml +++ /dev/null @@ -1,109 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/app/src/main/res/drawable-v23/scan_fingerprint.xml b/app/src/main/res/drawable-v23/scan_fingerprint.xml deleted file mode 100644 index 248691440..000000000 --- a/app/src/main/res/drawable-v23/scan_fingerprint.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - diff --git a/app/src/main/res/drawable/background_button.xml b/app/src/main/res/drawable/background_button.xml deleted file mode 100644 index a61486df1..000000000 --- a/app/src/main/res/drawable/background_button.xml +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/drawable/background_item_selection.xml b/app/src/main/res/drawable/background_item_selection.xml index eb60a1034..d013c67bc 100644 --- a/app/src/main/res/drawable/background_item_selection.xml +++ b/app/src/main/res/drawable/background_item_selection.xml @@ -2,12 +2,14 @@ - + + - + + \ No newline at end of file diff --git a/app/src/main/res/drawable/background_progress_circle.xml b/app/src/main/res/drawable/background_progress_circle.xml deleted file mode 100644 index 649f42f5b..000000000 --- a/app/src/main/res/drawable/background_progress_circle.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - \ No newline at end of file diff --git a/app/src/main/res/drawable/background_button_small.xml b/app/src/main/res/drawable/background_switch.xml similarity index 89% rename from app/src/main/res/drawable/background_button_small.xml rename to app/src/main/res/drawable/background_switch.xml index 3516e7b18..01d009478 100644 --- a/app/src/main/res/drawable/background_button_small.xml +++ b/app/src/main/res/drawable/background_switch.xml @@ -5,7 +5,7 @@ + android:radius="@dimen/dialog_radius" /> + android:radius="@dimen/dialog_radius" /> - - - - - \ No newline at end of file diff --git a/app/src/main/res/drawable/foreground_progress_circle_secondary.xml b/app/src/main/res/drawable/foreground_progress_circle_secondary.xml deleted file mode 100644 index 446ebc816..000000000 --- a/app/src/main/res/drawable/foreground_progress_circle_secondary.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_fingerprint_24.xml b/app/src/main/res/drawable/ic_fingerprint_24.xml new file mode 100644 index 000000000..c6427bc4b --- /dev/null +++ b/app/src/main/res/drawable/ic_fingerprint_24.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_info_hint_color_24dp.xml b/app/src/main/res/drawable/ic_info_hint_color_24dp.xml index 937c7ac22..98027c3e7 100644 --- a/app/src/main/res/drawable/ic_info_hint_color_24dp.xml +++ b/app/src/main/res/drawable/ic_info_hint_color_24dp.xml @@ -4,6 +4,6 @@ android:viewportWidth="24.0" android:viewportHeight="24.0"> diff --git a/app/src/main/res/drawable/ic_modified_white_12dp.xml b/app/src/main/res/drawable/ic_modified_white_12dp.xml index eba1bd509..23c74ec42 100644 --- a/app/src/main/res/drawable/ic_modified_white_12dp.xml +++ b/app/src/main/res/drawable/ic_modified_white_12dp.xml @@ -6,7 +6,8 @@ android:viewportHeight="24"> diff --git a/app/src/main/res/layout-v23/view_advanced_unlock.xml b/app/src/main/res/layout-v23/view_advanced_unlock.xml index 5d9fb8f0e..dba85bdb3 100644 --- a/app/src/main/res/layout-v23/view_advanced_unlock.xml +++ b/app/src/main/res/layout-v23/view_advanced_unlock.xml @@ -17,56 +17,11 @@ You should have received a copy of the GNU General Public License along with KeePassDX. If not, see . --> - - - - - - - - + style="@style/KeepassDXStyle.Button.Secondary" + app:icon="@drawable/ic_fingerprint_24" + android:text="@string/configure" /> diff --git a/app/src/main/res/layout/activity_about.xml b/app/src/main/res/layout/activity_about.xml index d6eab3c13..d956bfc9d 100644 --- a/app/src/main/res/layout/activity_about.xml +++ b/app/src/main/res/layout/activity_about.xml @@ -110,9 +110,8 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="16dp" - android:text="@string/about" - android:textStyle="bold" - style="@style/KeepassDXStyle.TextAppearance.Title"/> + android:text="@string/info" + style="@style/KeepassDXStyle.Title"/> + style="@style/KeepassDXStyle.Title"/> + style="@style/KeepassDXStyle.SubTitle"/> + style="@style/KeepassDXStyle.SubTitle"/> + style="@style/KeepassDXStyle.SubTitle"/> + android:layout_height="wrap_content"> + android:paddingBottom="12dp"> - - + android:layout_height="wrap_content" + style="@style/KeepassDXStyle.Toolbar.Transparent" + app:layout_collapseMode="pin" /> - @@ -59,7 +58,7 @@ android:layout_height="match_parent" android:paddingTop="@dimen/card_view_margin_vertical" android:paddingBottom="@dimen/card_view_margin_vertical"> - @@ -93,8 +91,7 @@ android:layout_height="wrap_content" android:contentDescription="@string/validate" android:src="@drawable/ic_check_white_24dp" - android:tint="?attr/colorOnAccentColor" - app:fabSize="mini" + app:fabCustomSize="@dimen/button_small_size" app:layout_constraintTop_toTopOf="@+id/entry_edit_bottom_bar" app:layout_constraintBottom_toTopOf="@+id/screenshot_mode_banner" app:layout_constraintEnd_toEndOf="parent" diff --git a/app/src/main/res/layout/activity_file_selection.xml b/app/src/main/res/layout/activity_file_selection.xml index 96448a944..76c0dcbc4 100644 --- a/app/src/main/res/layout/activity_file_selection.xml +++ b/app/src/main/res/layout/activity_file_selection.xml @@ -27,11 +27,10 @@ android:importantForAutofill="noExcludeDescendants" tools:targetApi="o"> - + android:layout_height="wrap_content"> + android:paddingBottom="36dp"> - - + app:layout_collapseMode="pin"/> @@ -142,57 +132,49 @@ app:layout_behavior="@string/appbar_scrolling_view_behavior"/> - - + + + +