From 1e5b935b5cfb03f60ba04890be44c3fbfbc56649 Mon Sep 17 00:00:00 2001 From: Naveen Singh Date: Sun, 15 Sep 2024 14:58:22 +0530 Subject: [PATCH] Implement global app locking - Added a full screen activity for unlocking app - Added app lock manager for managing global lock state - Added new FossifyApp base application class that apps must subclass. This will help remedy issues like https://github.com/FossifyOrg/Gallery/issues/126 --- commons/build.gradle.kts | 2 +- commons/src/main/AndroidManifest.xml | 4 + .../kotlin/org/fossify/commons/FossifyApp.kt | 19 ++ .../commons/activities/AboutActivity.kt | 3 +- .../commons/activities/AppLockActivity.kt | 104 +++++++ .../commons/activities/BaseComposeActivity.kt | 12 + .../commons/activities/BaseSimpleActivity.kt | 9 +- .../activities/ContributorsActivity.kt | 3 +- .../commons/activities/DonationActivity.kt | 3 +- .../fossify/commons/activities/FAQActivity.kt | 3 +- .../commons/activities/LicenseActivity.kt | 3 +- .../commons/adapters/AppLockAdapter.kt | 65 +++++ .../fossify/commons/dialogs/SecurityDialog.kt | 12 +- .../fossify/commons/extensions/Activity.kt | 10 + .../org/fossify/commons/extensions/Context.kt | 12 + .../org/fossify/commons/extensions/Window.kt | 13 + .../fossify/commons/helpers/AppLockManager.kt | 73 +++++ .../org/fossify/commons/helpers/BaseConfig.kt | 8 + .../org/fossify/commons/helpers/Constants.kt | 5 +- .../commons/interfaces/BaseSecurityTab.kt | 4 +- .../fossify/commons/interfaces/SecurityTab.kt | 2 +- .../fossify/commons/views/BiometricIdTab.kt | 2 +- .../fossify/commons/views/FingerprintTab.kt | 2 +- .../org/fossify/commons/views/PatternTab.kt | 11 +- .../org/fossify/commons/views/PinTab.kt | 7 +- commons/src/main/res/anim/fadein.xml | 6 + commons/src/main/res/anim/fadeout.xml | 6 + .../res/drawable/ic_lock_outlined_vector.xml | 10 +- .../src/main/res/layout/activity_app_lock.xml | 17 ++ commons/src/main/res/layout/tab_pattern.xml | 37 +-- commons/src/main/res/layout/tab_pin.xml | 275 ++++++++---------- commons/src/main/res/values/dimens.xml | 5 +- gradle/libs.versions.toml | 5 +- 33 files changed, 544 insertions(+), 208 deletions(-) create mode 100644 commons/src/main/kotlin/org/fossify/commons/FossifyApp.kt create mode 100644 commons/src/main/kotlin/org/fossify/commons/activities/AppLockActivity.kt create mode 100644 commons/src/main/kotlin/org/fossify/commons/activities/BaseComposeActivity.kt create mode 100644 commons/src/main/kotlin/org/fossify/commons/adapters/AppLockAdapter.kt create mode 100644 commons/src/main/kotlin/org/fossify/commons/helpers/AppLockManager.kt create mode 100644 commons/src/main/res/anim/fadein.xml create mode 100644 commons/src/main/res/anim/fadeout.xml create mode 100644 commons/src/main/res/layout/activity_app_lock.xml diff --git a/commons/build.gradle.kts b/commons/build.gradle.kts index 17b8228aa..340422409 100644 --- a/commons/build.gradle.kts +++ b/commons/build.gradle.kts @@ -82,9 +82,9 @@ dependencies { implementation(libs.androidx.swiperefreshlayout) implementation(libs.androidx.exifinterface) implementation(libs.androidx.biometric.ktx) + implementation(libs.androidx.lifecycle.process) implementation(libs.ez.vcard) - implementation(libs.bundles.lifecycle) implementation(libs.bundles.compose) implementation(libs.compose.view.binding) diff --git a/commons/src/main/AndroidManifest.xml b/commons/src/main/AndroidManifest.xml index 1c15af909..28dcb3531 100644 --- a/commons/src/main/AndroidManifest.xml +++ b/commons/src/main/AndroidManifest.xml @@ -62,6 +62,10 @@ android:exported="false" android:label="@string/donate_to_fossify" /> + + () { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { + val view = LayoutInflater.from(context).inflate(layoutSelection(viewType), parent, false) + view.layoutParams = ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT) + return ViewHolder(view) + } + + override fun onBindViewHolder(holder: ViewHolder, position: Int) = holder.bind() + + override fun getItemCount(): Int = if (showBiometricIdTab) 3 else 2 + + override fun getItemViewType(position: Int) = position + + private fun layoutSelection(position: Int): Int = when (position) { + PROTECTION_PATTERN -> R.layout.tab_pattern + PROTECTION_PIN -> R.layout.tab_pin + PROTECTION_FINGERPRINT -> if (isRPlus()) R.layout.tab_biometric_id else R.layout.tab_fingerprint + else -> throw RuntimeException("Only 3 tabs allowed") + } + + fun isTabVisible(position: Int, isVisible: Boolean) { + val viewHolder = (viewPager.getChildAt(0) as? RecyclerView)?.findViewHolderForAdapterPosition(position) as? ViewHolder + viewHolder?.itemView?.let { + (it as SecurityTab).visibilityChanged(isVisible) + } + } + + inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + fun bind() { + (itemView as SecurityTab).initTab( + requiredHash = requiredHash, + listener = hashListener, + scrollView = null, + biometricPromptHost = biometricPromptHost, + showBiometricAuthentication = showBiometricAuthentication + ) + } + } +} diff --git a/commons/src/main/kotlin/org/fossify/commons/dialogs/SecurityDialog.kt b/commons/src/main/kotlin/org/fossify/commons/dialogs/SecurityDialog.kt index 7e32906b7..9250e5517 100644 --- a/commons/src/main/kotlin/org/fossify/commons/dialogs/SecurityDialog.kt +++ b/commons/src/main/kotlin/org/fossify/commons/dialogs/SecurityDialog.kt @@ -34,7 +34,7 @@ class SecurityDialog( hashListener = this@SecurityDialog, scrollView = dialogScrollview, biometricPromptHost = AuthPromptHost(activity as FragmentActivity), - showBiometricIdTab = shouldShowBiometricIdTab(), + showBiometricIdTab = activity.isBiometricAuthSupported(), showBiometricAuthentication = showTabIndex == PROTECTION_FINGERPRINT && isRPlus() ) viewPager.adapter = tabsAdapter @@ -49,7 +49,7 @@ class SecurityDialog( if (showTabIndex == SHOW_ALL_TABS) { val textColor = root.context.getProperTextColor() - if (shouldShowBiometricIdTab()) { + if (activity.isBiometricAuthSupported()) { val tabTitle = if (isRPlus()) R.string.biometrics else R.string.fingerprint dialogTabLayout.addTab(dialogTabLayout.newTab().setText(tabTitle), PROTECTION_FINGERPRINT) } @@ -107,12 +107,4 @@ class SecurityDialog( tabsAdapter.isTabVisible(i, viewPager.currentItem == i) } } - - private fun shouldShowBiometricIdTab(): Boolean { - return if (isRPlus()) { - activity.isBiometricIdAvailable() - } else { - activity.isFingerPrintSensorAvailable() - } - } } diff --git a/commons/src/main/kotlin/org/fossify/commons/extensions/Activity.kt b/commons/src/main/kotlin/org/fossify/commons/extensions/Activity.kt index 83cf1f94e..57fbe91b7 100644 --- a/commons/src/main/kotlin/org/fossify/commons/extensions/Activity.kt +++ b/commons/src/main/kotlin/org/fossify/commons/extensions/Activity.kt @@ -1643,3 +1643,13 @@ fun Activity.onApplyWindowInsets(callback: (WindowInsetsCompat) -> Unit) { insets } } + +fun Activity.overrideActivityTransition(enterAnim: Int, exitAnim: Int, exiting: Boolean = false) { + if (isUpsideDownCakePlus()) { + val overrideType = if (exiting) Activity.OVERRIDE_TRANSITION_CLOSE else Activity.OVERRIDE_TRANSITION_OPEN + overrideActivityTransition(overrideType, enterAnim, exitAnim) + } else { + @Suppress("DEPRECATION") + overridePendingTransition(enterAnim, exitAnim) + } +} diff --git a/commons/src/main/kotlin/org/fossify/commons/extensions/Context.kt b/commons/src/main/kotlin/org/fossify/commons/extensions/Context.kt index 900ae8b6c..660979c22 100644 --- a/commons/src/main/kotlin/org/fossify/commons/extensions/Context.kt +++ b/commons/src/main/kotlin/org/fossify/commons/extensions/Context.kt @@ -3,6 +3,7 @@ package org.fossify.commons.extensions import android.Manifest import android.annotation.TargetApi import android.app.Activity +import android.app.Application import android.app.NotificationManager import android.app.role.RoleManager import android.content.* @@ -57,6 +58,9 @@ val Context.isRTLLayout: Boolean get() = resources.configuration.layoutDirection val Context.areSystemAnimationsEnabled: Boolean get() = Settings.Global.getFloat(contentResolver, Settings.Global.ANIMATOR_DURATION_SCALE, 0f) > 0f +val Context.appLockManager + get() = AppLockManager.getInstance(applicationContext as Application) + fun Context.toast(id: Int, length: Int = Toast.LENGTH_SHORT) { toast(getString(id), length) } @@ -104,6 +108,14 @@ fun Context.isBiometricIdAvailable(): Boolean = when (BiometricManager.from(this else -> false } +fun Context.isBiometricAuthSupported(): Boolean { + return if (isRPlus()) { + isBiometricIdAvailable() + } else { + isFingerPrintSensorAvailable() + } +} + fun Context.getLatestMediaId(uri: Uri = Files.getContentUri("external")): Long { val projection = arrayOf( BaseColumns._ID diff --git a/commons/src/main/kotlin/org/fossify/commons/extensions/Window.kt b/commons/src/main/kotlin/org/fossify/commons/extensions/Window.kt index 5501d53f2..1d2b55d8e 100644 --- a/commons/src/main/kotlin/org/fossify/commons/extensions/Window.kt +++ b/commons/src/main/kotlin/org/fossify/commons/extensions/Window.kt @@ -5,6 +5,19 @@ import android.view.Window import org.fossify.commons.helpers.DARK_GREY import org.fossify.commons.helpers.isOreoPlus +fun Window.updateStatusBarColors(backgroundColor: Int) { + statusBarColor = backgroundColor + updateStatusBarForegroundColor(backgroundColor) +} + +fun Window.updateStatusBarForegroundColor(backgroundColor: Int) { + if (backgroundColor.getContrastColor() == DARK_GREY) { + decorView.systemUiVisibility = decorView.systemUiVisibility.addBit(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR) + } else { + decorView.systemUiVisibility = decorView.systemUiVisibility.removeBit(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR) + } +} + fun Window.updateNavigationBarColors(backgroundColor: Int) { navigationBarColor = backgroundColor updateNavigationBarForegroundColor(backgroundColor) diff --git a/commons/src/main/kotlin/org/fossify/commons/helpers/AppLockManager.kt b/commons/src/main/kotlin/org/fossify/commons/helpers/AppLockManager.kt new file mode 100644 index 000000000..aac12503b --- /dev/null +++ b/commons/src/main/kotlin/org/fossify/commons/helpers/AppLockManager.kt @@ -0,0 +1,73 @@ +package org.fossify.commons.helpers + +import android.app.Application +import androidx.lifecycle.DefaultLifecycleObserver +import androidx.lifecycle.LifecycleOwner +import org.fossify.commons.compose.extensions.config + +class AppLockManager( + private val context: Application, + private val config: BaseConfig = context.config +) : DefaultLifecycleObserver { + + @Volatile + private var isLocked: Boolean = config.isAppPasswordProtectionOn + + @Volatile + private var shouldUpdateLockState: Boolean = true + + fun lock() { + isLocked = true + resetUnlockTimestamp(0L) + } + + fun unlock() { + isLocked = false + resetUnlockTimestamp() + } + + fun isLocked(): Boolean { + updateLockState() + return isLocked + } + + override fun onResume(owner: LifecycleOwner) = updateLockState() + + override fun onStop(owner: LifecycleOwner) { + shouldUpdateLockState = true + if (!isLocked) { + resetUnlockTimestamp() + } + } + + private fun updateLockState() { + if (config.isAppPasswordProtectionOn) { + val now = System.currentTimeMillis() + val unlockExpired = now - config.lastUnlockTimestampMs > config.unlockTimeoutDurationMs + if (unlockExpired && shouldUpdateLockState) { + isLocked = true + shouldUpdateLockState = false + } else { + resetUnlockTimestamp(now) + } + } else { + isLocked = false + } + } + + private fun resetUnlockTimestamp(timestamp: Long = System.currentTimeMillis()) { + config.lastUnlockTimestampMs = timestamp + } + + companion object { + @Volatile + private var instance: AppLockManager? = null + + fun getInstance(appContext: Application): AppLockManager { + return instance ?: synchronized(this) { + instance ?: AppLockManager(appContext).also { instance = it } + } + } + } +} + diff --git a/commons/src/main/kotlin/org/fossify/commons/helpers/BaseConfig.kt b/commons/src/main/kotlin/org/fossify/commons/helpers/BaseConfig.kt index 55ae1f49a..ffc2b39b2 100644 --- a/commons/src/main/kotlin/org/fossify/commons/helpers/BaseConfig.kt +++ b/commons/src/main/kotlin/org/fossify/commons/helpers/BaseConfig.kt @@ -170,6 +170,14 @@ open class BaseConfig(val context: Context) { get() = prefs.getInt(APP_PROTECTION_TYPE, PROTECTION_PATTERN) set(appProtectionType) = prefs.edit().putInt(APP_PROTECTION_TYPE, appProtectionType).apply() + var lastUnlockTimestampMs: Long + get() = prefs.getLong(LAST_UNLOCK_TIMESTAMP_MS, 0L) + set(value) = prefs.edit().putLong(LAST_UNLOCK_TIMESTAMP_MS, value).apply() + + var unlockTimeoutDurationMs: Long + get() = prefs.getLong(UNLOCK_TIMEOUT_DURATION_MS, DEFAULT_UNLOCK_TIMEOUT_DURATION) + set(value) = prefs.edit().putLong(UNLOCK_TIMEOUT_DURATION_MS, value).apply() + // file delete and move protection var isDeletePasswordProtectionOn: Boolean get() = prefs.getBoolean(DELETE_PASSWORD_PROTECTION, false) diff --git a/commons/src/main/kotlin/org/fossify/commons/helpers/Constants.kt b/commons/src/main/kotlin/org/fossify/commons/helpers/Constants.kt index 82c9bfb87..4eef4c230 100644 --- a/commons/src/main/kotlin/org/fossify/commons/helpers/Constants.kt +++ b/commons/src/main/kotlin/org/fossify/commons/helpers/Constants.kt @@ -195,10 +195,13 @@ const val AUTO_BACKUP_FILENAME = "auto_backup_filename" const val LAST_AUTO_BACKUP_TIME = "last_auto_backup_time" const val PASSWORD_RETRY_COUNT = "password_retry_count" const val PASSWORD_COUNTDOWN_START_MS = "password_count_down_start_ms" +const val LAST_UNLOCK_TIMESTAMP_MS = "last_unlock_timestamp_ms" +const val UNLOCK_TIMEOUT_DURATION_MS = "unlock_timeout_duration_ms" const val MAX_PASSWORD_RETRY_COUNT = 3 const val DEFAULT_PASSWORD_COUNTDOWN = 5 const val MINIMUM_PIN_LENGTH = 4 +const val DEFAULT_UNLOCK_TIMEOUT_DURATION = 30000L // contact grid view constants const val CONTACTS_GRID_MAX_COLUMNS_COUNT = 10 @@ -268,6 +271,7 @@ const val SELECT_EXPORT_SETTINGS_FILE_INTENT = 1006 const val REQUEST_CODE_SET_DEFAULT_DIALER = 1007 const val CREATE_DOCUMENT_SDK_30 = 1008 const val REQUEST_CODE_SET_DEFAULT_CALLER_ID = 1010 +const val REQUEST_APP_UNLOCK = 1012 // sorting const val SORT_ORDER = "sort_order" @@ -293,7 +297,6 @@ const val SORT_BY_CUSTOM = 131072 const val SORT_BY_DATE_CREATED = 262144 // security -const val WAS_PROTECTION_HANDLED = "was_protection_handled" const val PROTECTION_NONE = -1 const val PROTECTION_PATTERN = 0 const val PROTECTION_PIN = 1 diff --git a/commons/src/main/kotlin/org/fossify/commons/interfaces/BaseSecurityTab.kt b/commons/src/main/kotlin/org/fossify/commons/interfaces/BaseSecurityTab.kt index 7e4fd724b..f1261207c 100644 --- a/commons/src/main/kotlin/org/fossify/commons/interfaces/BaseSecurityTab.kt +++ b/commons/src/main/kotlin/org/fossify/commons/interfaces/BaseSecurityTab.kt @@ -4,9 +4,9 @@ import android.content.Context import android.os.Handler import android.os.Looper import android.util.AttributeSet -import android.widget.RelativeLayout import android.widget.TextView import androidx.annotation.ColorInt +import androidx.constraintlayout.widget.ConstraintLayout import androidx.core.os.postDelayed import org.fossify.commons.R import org.fossify.commons.extensions.baseConfig @@ -15,7 +15,7 @@ import org.fossify.commons.extensions.getProperTextColor import org.fossify.commons.helpers.DEFAULT_PASSWORD_COUNTDOWN import org.fossify.commons.helpers.MAX_PASSWORD_RETRY_COUNT -abstract class BaseSecurityTab(context: Context, attrs: AttributeSet) : RelativeLayout(context, attrs), SecurityTab { +abstract class BaseSecurityTab(context: Context, attrs: AttributeSet) : ConstraintLayout(context, attrs), SecurityTab { abstract val protectionType: Int abstract val defaultTextRes: Int diff --git a/commons/src/main/kotlin/org/fossify/commons/interfaces/SecurityTab.kt b/commons/src/main/kotlin/org/fossify/commons/interfaces/SecurityTab.kt index 39534a900..457806f6e 100644 --- a/commons/src/main/kotlin/org/fossify/commons/interfaces/SecurityTab.kt +++ b/commons/src/main/kotlin/org/fossify/commons/interfaces/SecurityTab.kt @@ -7,7 +7,7 @@ interface SecurityTab { fun initTab( requiredHash: String, listener: HashListener, - scrollView: MyScrollView, + scrollView: MyScrollView?, biometricPromptHost: AuthPromptHost, showBiometricAuthentication: Boolean ) diff --git a/commons/src/main/kotlin/org/fossify/commons/views/BiometricIdTab.kt b/commons/src/main/kotlin/org/fossify/commons/views/BiometricIdTab.kt index 563933796..2fc1f3c50 100644 --- a/commons/src/main/kotlin/org/fossify/commons/views/BiometricIdTab.kt +++ b/commons/src/main/kotlin/org/fossify/commons/views/BiometricIdTab.kt @@ -33,7 +33,7 @@ class BiometricIdTab(context: Context, attrs: AttributeSet) : ConstraintLayout(c override fun initTab( requiredHash: String, listener: HashListener, - scrollView: MyScrollView, + scrollView: MyScrollView?, biometricPromptHost: AuthPromptHost, showBiometricAuthentication: Boolean ) { diff --git a/commons/src/main/kotlin/org/fossify/commons/views/FingerprintTab.kt b/commons/src/main/kotlin/org/fossify/commons/views/FingerprintTab.kt index 584476f30..fc25df3dc 100644 --- a/commons/src/main/kotlin/org/fossify/commons/views/FingerprintTab.kt +++ b/commons/src/main/kotlin/org/fossify/commons/views/FingerprintTab.kt @@ -40,7 +40,7 @@ class FingerprintTab(context: Context, attrs: AttributeSet) : RelativeLayout(con override fun initTab( requiredHash: String, listener: HashListener, - scrollView: MyScrollView, + scrollView: MyScrollView?, biometricPromptHost: AuthPromptHost, showBiometricAuthentication: Boolean ) { diff --git a/commons/src/main/kotlin/org/fossify/commons/views/PatternTab.kt b/commons/src/main/kotlin/org/fossify/commons/views/PatternTab.kt index c6975eb36..f2851cea6 100644 --- a/commons/src/main/kotlin/org/fossify/commons/views/PatternTab.kt +++ b/commons/src/main/kotlin/org/fossify/commons/views/PatternTab.kt @@ -2,18 +2,23 @@ package org.fossify.commons.views import android.annotation.SuppressLint import android.content.Context +import android.content.res.ColorStateList import android.os.Handler import android.util.AttributeSet import android.view.MotionEvent import android.widget.TextView import androidx.biometric.auth.AuthPromptHost import androidx.core.os.postDelayed +import androidx.core.widget.TextViewCompat import com.andrognito.patternlockview.PatternLockView import com.andrognito.patternlockview.listener.PatternLockViewListener import com.andrognito.patternlockview.utils.PatternLockUtils import org.fossify.commons.R import org.fossify.commons.databinding.TabPatternBinding -import org.fossify.commons.extensions.* +import org.fossify.commons.extensions.getProperPrimaryColor +import org.fossify.commons.extensions.getProperTextColor +import org.fossify.commons.extensions.performHapticFeedback +import org.fossify.commons.extensions.updateTextColors import org.fossify.commons.helpers.PROTECTION_PATTERN import org.fossify.commons.interfaces.BaseSecurityTab import org.fossify.commons.interfaces.HashListener @@ -59,14 +64,14 @@ class PatternTab(context: Context, attrs: AttributeSet) : BaseSecurityTab(contex override fun onProgress(progressPattern: MutableList?) {} }) - binding.patternLockIcon.applyColorFilter(textColor) + TextViewCompat.setCompoundDrawableTintList(binding.patternLockTitle, ColorStateList.valueOf(textColor)) maybeShowCountdown() } override fun initTab( requiredHash: String, listener: HashListener, - scrollView: MyScrollView, + scrollView: MyScrollView?, biometricPromptHost: AuthPromptHost, showBiometricAuthentication: Boolean ) { diff --git a/commons/src/main/kotlin/org/fossify/commons/views/PinTab.kt b/commons/src/main/kotlin/org/fossify/commons/views/PinTab.kt index b679bca53..53da948bf 100644 --- a/commons/src/main/kotlin/org/fossify/commons/views/PinTab.kt +++ b/commons/src/main/kotlin/org/fossify/commons/views/PinTab.kt @@ -1,10 +1,12 @@ package org.fossify.commons.views import android.content.Context +import android.content.res.ColorStateList import android.util.AttributeSet import android.widget.TextView import android.widget.Toast import androidx.biometric.auth.AuthPromptHost +import androidx.core.widget.TextViewCompat import org.fossify.commons.R import org.fossify.commons.databinding.TabPinBinding import org.fossify.commons.extensions.* @@ -47,14 +49,15 @@ class PinTab(context: Context, attrs: AttributeSet) : BaseSecurityTab(context, a binding.pinC.setOnClickListener { clear() } binding.pinOk.setOnClickListener { confirmPIN() } binding.pinOk.applyColorFilter(textColor) - binding.pinLockIcon.applyColorFilter(textColor) + + TextViewCompat.setCompoundDrawableTintList(binding.pinLockTitle, ColorStateList.valueOf(textColor)) maybeShowCountdown() } override fun initTab( requiredHash: String, listener: HashListener, - scrollView: MyScrollView, + scrollView: MyScrollView?, biometricPromptHost: AuthPromptHost, showBiometricAuthentication: Boolean ) { diff --git a/commons/src/main/res/anim/fadein.xml b/commons/src/main/res/anim/fadein.xml new file mode 100644 index 000000000..10a5a5c68 --- /dev/null +++ b/commons/src/main/res/anim/fadein.xml @@ -0,0 +1,6 @@ + + diff --git a/commons/src/main/res/anim/fadeout.xml b/commons/src/main/res/anim/fadeout.xml new file mode 100644 index 000000000..4b400e176 --- /dev/null +++ b/commons/src/main/res/anim/fadeout.xml @@ -0,0 +1,6 @@ + + diff --git a/commons/src/main/res/drawable/ic_lock_outlined_vector.xml b/commons/src/main/res/drawable/ic_lock_outlined_vector.xml index 3b97d02fe..6be03fb2c 100644 --- a/commons/src/main/res/drawable/ic_lock_outlined_vector.xml +++ b/commons/src/main/res/drawable/ic_lock_outlined_vector.xml @@ -1,3 +1,9 @@ - - + + diff --git a/commons/src/main/res/layout/activity_app_lock.xml b/commons/src/main/res/layout/activity_app_lock.xml new file mode 100644 index 000000000..8c18ed97c --- /dev/null +++ b/commons/src/main/res/layout/activity_app_lock.xml @@ -0,0 +1,17 @@ + + + + + + diff --git a/commons/src/main/res/layout/tab_pattern.xml b/commons/src/main/res/layout/tab_pattern.xml index bce550bb3..7f789af75 100644 --- a/commons/src/main/res/layout/tab_pattern.xml +++ b/commons/src/main/res/layout/tab_pattern.xml @@ -1,24 +1,17 @@ - - + android:layout_height="match_parent"> + android:textSize="@dimen/bigger_text_size" + app:layout_constraintBottom_toTopOf="@id/pattern_lock_view" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent" /> + android:layout_width="0dp" + android:layout_height="0dp" + android:layout_marginTop="@dimen/activity_margin" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintDimensionRatio="1" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintHeight_min="@dimen/app_lock_view_min_size" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@+id/pattern_lock_title" + app:layout_constraintWidth_max="@dimen/app_lock_view_max_size" /> diff --git a/commons/src/main/res/layout/tab_pin.xml b/commons/src/main/res/layout/tab_pin.xml index 9c3a0dbdf..cb8f76e1e 100644 --- a/commons/src/main/res/layout/tab_pin.xml +++ b/commons/src/main/res/layout/tab_pin.xml @@ -1,25 +1,18 @@ - - + android:layout_height="match_parent"> + android:textSize="@dimen/bigger_text_size" + app:layout_constraintBottom_toTopOf="@id/pin_lock_current_pin" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent" /> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + app:constraint_referenced_ids="pin_1,pin_2,pin_3,pin_4,pin_5,pin_6,pin_7,pin_8,pin_9,pin_c,pin_0,pin_ok" + app:flow_horizontalGap="@dimen/medium_margin" + app:flow_horizontalStyle="spread_inside" + app:flow_maxElementsWrap="3" + app:flow_verticalGap="@dimen/medium_margin" + app:flow_wrapMode="aligned" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintDimensionRatio="7:6" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintHeight_min="@dimen/app_lock_view_min_size" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@id/pin_lock_current_pin" + app:layout_constraintWidth_max="@dimen/app_lock_view_max_size" /> + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/commons/src/main/res/values/dimens.xml b/commons/src/main/res/values/dimens.xml index 84d957489..c2d54e4be 100644 --- a/commons/src/main/res/values/dimens.xml +++ b/commons/src/main/res/values/dimens.xml @@ -61,6 +61,9 @@ 85dp 4dp 2px - + 100dp + + 350dp + 250dp diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 4c5c3784f..d4db21fcd 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -8,7 +8,7 @@ ksp = "1.9.23-1.0.19" #Androidx androidx-customView = "1.2.0-alpha02" androidx-customViewPooling = "1.0.0" -androidx-lifecycle = "2.7.0" +androidx-lifecycle = "2.8.5" androidx-constraintlayout = "2.1.4" androidx-documentfile = "1.0.1" androidx-biometricKtx = "1.2.0-alpha05" @@ -66,6 +66,7 @@ androidx-lifecycle-runtime = { module = "androidx.lifecycle:lifecycle-runtime-kt androidx-lifecycle-viewModel = { module = "androidx.lifecycle:lifecycle-viewmodel-ktx", version.ref = "androidx-lifecycle" } androidx-lifecycle-viewModel-compose = { module = "androidx.lifecycle:lifecycle-viewmodel-compose", version.ref = "androidx-lifecycle" } androidx-lifecycle-compose = { module = "androidx.lifecycle:lifecycle-runtime-compose", version.ref = "androidx-lifecycle" } +androidx-lifecycle-process = { module = "androidx.lifecycle:lifecycle-process", version.ref = "androidx-lifecycle" } #Room androidx-room-runtime = { module = "androidx.room:room-runtime", version.ref = "room" } androidx-room-ktx = { module = "androidx.room:room-ktx", version.ref = "room" } @@ -92,7 +93,7 @@ material = { module = "com.google.android.material:material", version.ref = "mat #Helpers patternLockView = { module = "com.github.aritraroy:patternLockView", version.ref = "patternLockView" } reprint = { module = "com.github.tibbi:reprint", version.ref = "reprint" } -recyclerView-FastScroller = { module = "com.github.tibbi:RecyclerView-FastScroller", version.ref = "recyclerviewFastscroller" } +recyclerView-fastScroller = { module = "com.github.tibbi:RecyclerView-FastScroller", version.ref = "recyclerviewFastscroller" } rtl-viewpager = { module = "com.github.duolingo:rtl-viewpager", version.ref = "rtlViewpager" } ez-vcard = { module = "com.googlecode.ez-vcard:ez-vcard", version.ref = "ezVcard" } gson = { module = "com.google.code.gson:gson", version.ref = "gson" }