From 9cddace27a378ac945e40ae4cf3072bcd056d260 Mon Sep 17 00:00:00 2001 From: HeCodes2Much Date: Sun, 19 May 2024 20:20:56 +0100 Subject: [PATCH] Refactor: Refactor settings menu for cleaner look. --- .../droidworksstudio/launcher/Constants.kt | 2 + .../launcher/helper/FingerprintHelper.kt | 59 ++++ .../launcher/helper/PreferenceHelper.kt | 4 + .../launcher/ui/home/HomeFragment.kt | 58 +++- .../launcher/ui/settings/SettingsFragment.kt | 5 +- .../launcher/viewmodel/PreferenceViewModel.kt | 6 + app/src/main/res/drawable/app_launcher.xml | 55 ++-- app/src/main/res/layout/fragment_settings.xml | 286 +++++++++++------- app/src/main/res/values/strings.xml | 6 +- .../android/en-US/full_description.txt | 14 +- 10 files changed, 353 insertions(+), 142 deletions(-) diff --git a/app/src/main/java/com/github/droidworksstudio/launcher/Constants.kt b/app/src/main/java/com/github/droidworksstudio/launcher/Constants.kt index c886f64..5d98300 100644 --- a/app/src/main/java/com/github/droidworksstudio/launcher/Constants.kt +++ b/app/src/main/java/com/github/droidworksstudio/launcher/Constants.kt @@ -50,5 +50,7 @@ object Constants { const val QUICKSETTINGS_MANAGER = "android.app.StatusBarManager" const val QUICKSETTINGS_METHOD = "expandSettingsPanel" + const val TOGGLE_SETTING_LOCK = "TOGGLE_SETTING_LOCK" + const val REQUEST_CODE_ENABLE_ADMIN = 123 } \ No newline at end of file diff --git a/app/src/main/java/com/github/droidworksstudio/launcher/helper/FingerprintHelper.kt b/app/src/main/java/com/github/droidworksstudio/launcher/helper/FingerprintHelper.kt index c10bb99..697e2cf 100644 --- a/app/src/main/java/com/github/droidworksstudio/launcher/helper/FingerprintHelper.kt +++ b/app/src/main/java/com/github/droidworksstudio/launcher/helper/FingerprintHelper.kt @@ -1,5 +1,6 @@ package com.github.droidworksstudio.launcher.helper +import android.content.Intent import androidx.biometric.BiometricManager import androidx.biometric.BiometricPrompt import androidx.core.content.ContextCompat @@ -12,6 +13,9 @@ class FingerprintHelper @Inject constructor(private val fragment: Fragment) { private lateinit var callback: Callback + @Inject + lateinit var appHelper: AppHelper + interface Callback { fun onAuthenticationSucceeded(appInfo: AppInfo) fun onAuthenticationFailed() @@ -40,6 +44,8 @@ class FingerprintHelper @Inject constructor(private val fragment: Fragment) { val promptInfo = BiometricPrompt.PromptInfo.Builder() .setTitle(fragment.getString(R.string.authentication_title)) + .setSubtitle(fragment.getString(R.string.authentication_subtitle)) + .setAllowedAuthenticators(BiometricManager.Authenticators.BIOMETRIC_WEAK or BiometricManager.Authenticators.DEVICE_CREDENTIAL) .setNegativeButtonText(fragment.getString(R.string.authentication_cancel)) .build() @@ -49,4 +55,57 @@ class FingerprintHelper @Inject constructor(private val fragment: Fragment) { biometricPrompt.authenticate(promptInfo) } } + + fun startFingerprintSettingsAuth(targetClass: Class<*>) { + val executor = ContextCompat.getMainExecutor(fragment.requireContext()) + + val biometricPrompt = BiometricPrompt(fragment, executor, object : BiometricPrompt.AuthenticationCallback() { + override fun onAuthenticationSucceeded(result: BiometricPrompt.AuthenticationResult) { + sendToTargetActivity(targetClass) + } + + override fun onAuthenticationFailed() { + appHelper.showToast(fragment.requireContext(), fragment.getString(R.string.authentication_failed)) + } + + override fun onAuthenticationError(errorCode: Int, errorMessage: CharSequence) { + when (errorCode) { + BiometricPrompt.ERROR_USER_CANCELED -> appHelper.showToast(fragment.requireContext(), fragment.getString(R.string.authentication_cancel)) + else -> appHelper.showToast(fragment.requireContext(), fragment.getString(R.string.authentication_error).format(errorMessage, errorCode)) + } + } + }) + + val promptInfoBuilder = BiometricPrompt.PromptInfo.Builder() + .setTitle(fragment.getString(R.string.authentication_title)) + .setSubtitle(fragment.getString(R.string.authentication_subtitle)) + + val authenticators = BiometricManager.Authenticators.BIOMETRIC_WEAK or BiometricManager.Authenticators.DEVICE_CREDENTIAL + val canAuthenticate = BiometricManager.from(fragment.requireContext()).canAuthenticate(authenticators) + + if (canAuthenticate == BiometricManager.BIOMETRIC_SUCCESS) { + promptInfoBuilder.setAllowedAuthenticators(authenticators) + } else { + promptInfoBuilder.setNegativeButtonText(fragment.getString(R.string.authentication_cancel)) + } + + val promptInfo = promptInfoBuilder.build() + + when (canAuthenticate) { + BiometricManager.BIOMETRIC_SUCCESS -> biometricPrompt.authenticate(promptInfo) + BiometricManager.BIOMETRIC_ERROR_NO_HARDWARE, + BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE, + BiometricManager.BIOMETRIC_ERROR_NONE_ENROLLED -> sendToTargetActivity(targetClass) + else -> appHelper.showToast(fragment.requireContext(), fragment.getString(R.string.authentication_failed)) + } + } + + fun sendToTargetActivity(targetClass: Class<*>) { + try { + val intent = Intent(fragment.requireActivity(), targetClass) + fragment.requireActivity().startActivity(intent) + } catch (e: Exception) { + appHelper.showToast(fragment.requireContext(), fragment.getString(R.string.authentication_failed)) + } + } } diff --git a/app/src/main/java/com/github/droidworksstudio/launcher/helper/PreferenceHelper.kt b/app/src/main/java/com/github/droidworksstudio/launcher/helper/PreferenceHelper.kt index 51e877b..b78804d 100644 --- a/app/src/main/java/com/github/droidworksstudio/launcher/helper/PreferenceHelper.kt +++ b/app/src/main/java/com/github/droidworksstudio/launcher/helper/PreferenceHelper.kt @@ -110,6 +110,10 @@ class PreferenceHelper @Inject constructor(@ApplicationContext context: Context) get() = prefs.getBoolean(Constants.DOUBLE_TAP_LOCK, false) set(value) = prefs.edit().putBoolean(Constants.DOUBLE_TAP_LOCK, value).apply() + var settingsLock: Boolean + get() = prefs.getBoolean(Constants.TOGGLE_SETTING_LOCK, false) + set(value) = prefs.edit().putBoolean(Constants.TOGGLE_SETTING_LOCK, value).apply() + var swipeNotification: Boolean get() = prefs.getBoolean(Constants.SWIPE_NOTIFICATION, true) set(value) = prefs.edit().putBoolean(Constants.SWIPE_NOTIFICATION, value).apply() diff --git a/app/src/main/java/com/github/droidworksstudio/launcher/ui/home/HomeFragment.kt b/app/src/main/java/com/github/droidworksstudio/launcher/ui/home/HomeFragment.kt index 5b068a0..5abd5b2 100644 --- a/app/src/main/java/com/github/droidworksstudio/launcher/ui/home/HomeFragment.kt +++ b/app/src/main/java/com/github/droidworksstudio/launcher/ui/home/HomeFragment.kt @@ -12,10 +12,11 @@ import android.text.format.DateFormat import android.util.Log import android.view.* import androidx.annotation.RequiresApi +import androidx.biometric.BiometricPrompt +import androidx.core.content.ContextCompat import androidx.fragment.app.Fragment import androidx.fragment.app.viewModels import androidx.lifecycle.lifecycleScope -import androidx.navigation.findNavController import androidx.recyclerview.widget.StaggeredGridLayoutManager import com.github.droidworksstudio.launcher.R import com.github.droidworksstudio.launcher.accessibility.MyAccessibilityService @@ -34,6 +35,7 @@ import com.github.droidworksstudio.launcher.viewmodel.PreferenceViewModel import dagger.hilt.android.AndroidEntryPoint import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.flowOn +import kotlinx.coroutines.launch import java.util.Locale import javax.inject.Inject @@ -67,6 +69,7 @@ class HomeFragment : Fragment(), OnItemClickedListener.OnAppsClickedListener, private val homeAdapter: HomeAdapter by lazy { HomeAdapter(this, this, preferenceHelper) } private lateinit var batteryReceiver: BroadcastReceiver + private lateinit var biometricPrompt: BiometricPrompt private lateinit var context: Context @@ -228,8 +231,7 @@ class HomeFragment : Fragment(), OnItemClickedListener.OnAppsClickedListener, return object : OnSwipeTouchListener(context) { override fun onLongClick() { super.onLongClick() - val intent = Intent(requireActivity(), SettingsActivity::class.java) - requireActivity().startActivity(intent) + trySettings() return } @@ -246,6 +248,51 @@ class HomeFragment : Fragment(), OnItemClickedListener.OnAppsClickedListener, } } + private fun trySettings() { + lifecycleScope.launch(Dispatchers.Main) { + biometricPrompt = BiometricPrompt(this@HomeFragment, + ContextCompat.getMainExecutor(requireContext()), + object : BiometricPrompt.AuthenticationCallback() { + override fun onAuthenticationError( + errorCode: Int, + errString: CharSequence + ) { + when (errorCode) { + BiometricPrompt.ERROR_USER_CANCELED -> appHelper.showToast( + requireContext(), + getString(R.string.authentication_cancel) + ) + + else -> appHelper.showToast( + requireContext(), + getString(R.string.authentication_error).format( + errString, + errorCode + ) + ) + } + } + + override fun onAuthenticationSucceeded(result: BiometricPrompt.AuthenticationResult) { + fingerHelper.sendToTargetActivity(SettingsActivity::class.java) + } + + override fun onAuthenticationFailed() { + appHelper.showToast( + requireContext(), + getString(R.string.authentication_failed) + ) + } + }) + + if (preferenceHelper.settingsLock) { + fingerHelper.startFingerprintSettingsAuth(SettingsActivity::class.java) + } else { + fingerHelper.sendToTargetActivity(SettingsActivity::class.java) + } + } + } + override fun onDestroyView() { super.onDestroyView() _binding = null @@ -291,7 +338,10 @@ class HomeFragment : Fragment(), OnItemClickedListener.OnAppsClickedListener, } override fun onAuthenticationError(errorCode: Int, errorMessage: CharSequence?) { - appHelper.showToast(context, getString(R.string.authentication_error)) + when (errorCode) { + BiometricPrompt.ERROR_USER_CANCELED -> appHelper.showToast(requireContext(), getString(R.string.authentication_cancel)) + else -> appHelper.showToast(requireContext(), getString(R.string.authentication_error).format(errorMessage, errorCode)) + } } override fun onTopReached() { diff --git a/app/src/main/java/com/github/droidworksstudio/launcher/ui/settings/SettingsFragment.kt b/app/src/main/java/com/github/droidworksstudio/launcher/ui/settings/SettingsFragment.kt index 83c9309..49c00e1 100644 --- a/app/src/main/java/com/github/droidworksstudio/launcher/ui/settings/SettingsFragment.kt +++ b/app/src/main/java/com/github/droidworksstudio/launcher/ui/settings/SettingsFragment.kt @@ -82,6 +82,7 @@ class SettingsFragment : Fragment(), ScrollEventListener { binding.gesturesLockSwitchCompat.isChecked = preferenceHelper.tapLockScreen binding.gesturesNotificationSwitchCompat.isChecked = preferenceHelper.swipeNotification binding.gesturesSearchSwitchCompat.isChecked = preferenceHelper.swipeSearch + binding.lockSettingsSwitchCompat.isChecked = preferenceHelper.settingsLock } private fun observeClickListener() { @@ -184,7 +185,9 @@ class SettingsFragment : Fragment(), ScrollEventListener { preferenceViewModel.setAutoOpenApp(isChecked) } - + binding.lockSettingsSwitchCompat.setOnCheckedChangeListener { _, isChecked -> + preferenceViewModel.setLockSettings(isChecked) + } } override fun onTopReached() { diff --git a/app/src/main/java/com/github/droidworksstudio/launcher/viewmodel/PreferenceViewModel.kt b/app/src/main/java/com/github/droidworksstudio/launcher/viewmodel/PreferenceViewModel.kt index f7f5b75..27661ce 100644 --- a/app/src/main/java/com/github/droidworksstudio/launcher/viewmodel/PreferenceViewModel.kt +++ b/app/src/main/java/com/github/droidworksstudio/launcher/viewmodel/PreferenceViewModel.kt @@ -36,6 +36,7 @@ class PreferenceViewModel @Inject constructor( val swipeSearchLiveData: MutableLiveData = MutableLiveData() val autoOpenAppsLiveData: MutableLiveData = MutableLiveData() val autoKeyboardLiveData: MutableLiveData = MutableLiveData() + val lockSettingsLiveData: MutableLiveData = MutableLiveData() val appPaddingSizeLiveData: MutableLiveData = MutableLiveData() fun setFirstLaunch(firstLaunch: Boolean) { @@ -167,4 +168,9 @@ class PreferenceViewModel @Inject constructor( preferenceHelper.automaticOpenApp = autoOpenApp autoOpenAppsLiveData.postValue((preferenceHelper.automaticOpenApp)) } + + fun setLockSettings(lockSettings: Boolean){ + preferenceHelper.settingsLock = lockSettings + lockSettingsLiveData.postValue((preferenceHelper.settingsLock)) + } } \ No newline at end of file diff --git a/app/src/main/res/drawable/app_launcher.xml b/app/src/main/res/drawable/app_launcher.xml index e6ec518..1bbdcbd 100644 --- a/app/src/main/res/drawable/app_launcher.xml +++ b/app/src/main/res/drawable/app_launcher.xml @@ -4,22 +4,41 @@ android:width="1024sp" android:viewportHeight="1024" android:viewportWidth="1024"> - - - - - - - - + + + + + + + + + + + diff --git a/app/src/main/res/layout/fragment_settings.xml b/app/src/main/res/layout/fragment_settings.xml index 499f712..f538ba4 100644 --- a/app/src/main/res/layout/fragment_settings.xml +++ b/app/src/main/res/layout/fragment_settings.xml @@ -54,6 +54,176 @@ android:textSize="@dimen/text_large" style="@style/TextDefaultStyle"/> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Home Display + Behavior Appearance Date Style Time Style @@ -40,6 +41,7 @@ Show App Icons Auto Show Keyboard Auto Open Last App + Lock Settings Size Color @@ -74,11 +76,11 @@ Github Authentication - Please login to get access + Log in using your biometric credentials. Authentication Cancel Authentication Succeeded Authentication Failed - Authentication Error + Authentication Error: %1$s(code %2$d) Star Center diff --git a/fastlane/metadata/android/en-US/full_description.txt b/fastlane/metadata/android/en-US/full_description.txt index 6c6a00d..7cac925 100644 --- a/fastlane/metadata/android/en-US/full_description.txt +++ b/fastlane/metadata/android/en-US/full_description.txt @@ -1 +1,13 @@ -Coming Soon. \ No newline at end of file +EasyLauncher - Minimal and Clutter Free Android launcher + + Features: + +- You can rename apps in the app-drawer. (Sync with home screen) +- No use of INTERNET permissions. +- Lock settings behind biometrics (toggle). + +Possible actions now include: + +- Clicking on the Battery Level +- Clicking on the Clock +- Clicking on the Date \ No newline at end of file