Feature: Added the ability to change swipeThreshold.

This commit is contained in:
HeCodes2Much
2024-11-29 20:18:29 +00:00
parent 8c5b17ab55
commit 8bcec489e9
13 changed files with 172 additions and 45 deletions

View File

@@ -115,6 +115,10 @@ class PreferenceHelper @Inject constructor(@ApplicationContext context: Context)
get() = prefs.getInt(Constants.FILTER_STRENGTH, 25)
set(value) = prefs.edit().putInt(Constants.FILTER_STRENGTH, value).apply()
var swipeThreshold: Int
get() = prefs.getInt(Constants.SWIPE_THRESHOLD, 100)
set(value) = prefs.edit().putInt(Constants.SWIPE_THRESHOLD, value).apply()
var homeAppAlignment: Int
get() = prefs.getInt(Constants.HOME_APP_ALIGNMENT, Gravity.START)
set(value) = prefs.edit().putInt(Constants.HOME_APP_ALIGNMENT, value).apply()

View File

@@ -7,6 +7,7 @@ import android.view.GestureDetector.SimpleOnGestureListener
import android.view.MotionEvent
import android.view.View
import android.view.View.OnTouchListener
import com.github.droidworksstudio.launcher.helper.PreferenceHelper
import com.github.droidworksstudio.launcher.utils.Constants
import java.util.*
import kotlin.concurrent.schedule
@@ -20,7 +21,7 @@ import kotlin.math.abs
* The original code has been modified to fit the specific requirements of this project.
*/
internal open class OnSwipeTouchListener(c: Context?) : OnTouchListener {
internal open class OnSwipeTouchListener(context: Context?, private val preferenceHelper: PreferenceHelper) : OnTouchListener {
private var longPressOn = false
private var doubleTapOn = false
private val gestureDetector: GestureDetector
@@ -33,23 +34,23 @@ internal open class OnSwipeTouchListener(c: Context?) : OnTouchListener {
}
private inner class GestureListener : SimpleOnGestureListener() {
private val swipeThreshold: Int = 100
private val swipeVelocityThreshold: Int = 100
private val swipeScrollThreshold: Int = 100
private val swipeThreshold: Int = preferenceHelper.swipeThreshold
private val swipeVelocityThreshold: Int = (preferenceHelper.swipeThreshold / 2)
private val swipeScrollThreshold: Int = (preferenceHelper.swipeThreshold / 2)
override fun onDown(e: MotionEvent): Boolean {
override fun onDown(event: MotionEvent): Boolean {
return true
}
override fun onSingleTapUp(e: MotionEvent): Boolean {
override fun onSingleTapUp(event: MotionEvent): Boolean {
if (doubleTapOn) {
doubleTapOn = false
onTripleClick()
}
return super.onSingleTapUp(e)
return super.onSingleTapUp(event)
}
override fun onDoubleTap(e: MotionEvent): Boolean {
override fun onDoubleTap(event: MotionEvent): Boolean {
doubleTapOn = true
Timer().schedule(Constants.TRIPLE_TAP_DELAY_MS.toLong()) {
if (doubleTapOn) {
@@ -57,15 +58,15 @@ internal open class OnSwipeTouchListener(c: Context?) : OnTouchListener {
onDoubleClick()
}
}
return super.onDoubleTap(e)
return super.onDoubleTap(event)
}
override fun onLongPress(e: MotionEvent) {
override fun onLongPress(event: MotionEvent) {
longPressOn = true
Timer().schedule(Constants.LONG_PRESS_DELAY_MS.toLong()) {
if (longPressOn) onLongClick()
}
super.onLongPress(e)
super.onLongPress(event)
}
// Detecting swipe or drag movement
@@ -73,7 +74,7 @@ internal open class OnSwipeTouchListener(c: Context?) : OnTouchListener {
event1: MotionEvent?,
event2: MotionEvent,
distanceX: Float,
distanceY: Float
distanceY: Float,
): Boolean {
try {
if (event1 == null) return false
@@ -103,7 +104,7 @@ internal open class OnSwipeTouchListener(c: Context?) : OnTouchListener {
event1: MotionEvent?,
event2: MotionEvent,
velocityX: Float,
velocityY: Float
velocityY: Float,
): Boolean {
try {
val diffY = event2.y - event1!!.y
@@ -133,6 +134,6 @@ internal open class OnSwipeTouchListener(c: Context?) : OnTouchListener {
open fun onTripleClick() {}
init {
gestureDetector = GestureDetector(c, GestureListener())
gestureDetector = GestureDetector(context, GestureListener())
}
}

View File

@@ -81,7 +81,7 @@ class DrawFragment : Fragment(),
private lateinit var context: Context
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
savedInstanceState: Bundle?,
): View {
_binding = FragmentDrawBinding.inflate(inflater, container, false)
@@ -235,7 +235,7 @@ class DrawFragment : Fragment(),
private fun getSwipeGestureListener(context: Context): View.OnTouchListener {
return object : OnSwipeTouchListener(context) {
return object : OnSwipeTouchListener(context, preferenceHelper) {
override fun onSwipeLeft() {
super.onSwipeLeft()
val actionTypeNavOptions: NavOptions? =

View File

@@ -62,7 +62,7 @@ class FavoriteFragment : Fragment(),
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
savedInstanceState: Bundle?,
): View {
_binding = FragmentFavoriteBinding.inflate(inflater, container, false)
@@ -136,7 +136,7 @@ class FavoriteFragment : Fragment(),
override fun onChildDraw(
canvas: Canvas, recyclerView: RecyclerView,
viewHolder: RecyclerView.ViewHolder, dX: Float,
dY: Float, actionState: Int, isCurrentlyActive: Boolean
dY: Float, actionState: Int, isCurrentlyActive: Boolean,
) {
if (isCurrentlyActive) {
viewHolder.itemView.alpha = 0.5f
@@ -152,7 +152,7 @@ class FavoriteFragment : Fragment(),
override fun getMovementFlags(
recyclerView: RecyclerView,
viewHolder: RecyclerView.ViewHolder
viewHolder: RecyclerView.ViewHolder,
): Int {
val dragFlags = ItemTouchHelper.UP or ItemTouchHelper.DOWN
val swipeFlags = 0
@@ -161,7 +161,7 @@ class FavoriteFragment : Fragment(),
override fun onMove(
recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder,
target: RecyclerView.ViewHolder
target: RecyclerView.ViewHolder,
): Boolean {
val oldPosition = viewHolder.bindingAdapterPosition
@@ -199,7 +199,7 @@ class FavoriteFragment : Fragment(),
}
private fun getSwipeGestureListener(context: Context): View.OnTouchListener {
return object : OnSwipeTouchListener(context) {
return object : OnSwipeTouchListener(context, preferenceHelper) {
override fun onSwipeLeft() {
super.onSwipeLeft()
findNavController().navigateUp()

View File

@@ -56,7 +56,7 @@ class HiddenFragment : Fragment(),
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
savedInstanceState: Bundle?,
): View {
_binding = FragmentHiddenBinding.inflate(inflater, container, false)
@@ -116,7 +116,7 @@ class HiddenFragment : Fragment(),
}
private fun getSwipeGestureListener(context: Context): View.OnTouchListener {
return object : OnSwipeTouchListener(context) {
return object : OnSwipeTouchListener(context, preferenceHelper) {
override fun onSwipeLeft() {
super.onSwipeLeft()
findNavController().navigateUp()

View File

@@ -92,7 +92,7 @@ class HomeFragment : Fragment(),
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
savedInstanceState: Bundle?,
): View {
_binding = FragmentHomeBinding.inflate(inflater, container, false)
@@ -344,7 +344,7 @@ class HomeFragment : Fragment(),
}
private fun getSwipeGestureListener(context: Context): View.OnTouchListener {
return object : OnSwipeTouchListener(context) {
return object : OnSwipeTouchListener(context, preferenceHelper) {
override fun onLongClick() {
super.onLongClick()
trySettings()
@@ -403,7 +403,8 @@ class HomeFragment : Fragment(),
Constants.Swipe.Up,
Constants.Swipe.Down,
Constants.Swipe.Left,
Constants.Swipe.Right -> {
Constants.Swipe.Right,
-> {
val packageName = when (actionType) {
Constants.Swipe.DoubleTap -> preferenceHelper.doubleTapApp
Constants.Swipe.Up -> preferenceHelper.swipeUpApp
@@ -526,7 +527,7 @@ class HomeFragment : Fragment(),
object : BiometricPrompt.AuthenticationCallback() {
override fun onAuthenticationError(
errorCode: Int,
errString: CharSequence
errString: CharSequence,
) {
when (errorCode) {
BiometricPrompt.ERROR_USER_CANCELED -> requireContext().showLongToast(

View File

@@ -56,7 +56,7 @@ class SettingsFeaturesFragment : Fragment(),
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
savedInstanceState: Bundle?,
): View {
// Inflate the layout for this fragment
_binding = FragmentSettingsFeaturesBinding.inflate(inflater, container, false)
@@ -82,6 +82,7 @@ class SettingsFeaturesFragment : Fragment(),
miscellaneousSearchEngineControl.text = preferenceHelper.searchEngines.getString(context)
miscellaneousAppLanguageControl.text = preferenceHelper.appLanguage.name
miscellaneousFilterStrengthControl.text = "${preferenceHelper.filterStrength}"
miscellaneousSwipeThresholdControl.text = "${preferenceHelper.swipeThreshold}"
}
val actions = listOf(
@@ -102,7 +103,7 @@ class SettingsFeaturesFragment : Fragment(),
context: Context,
action: Constants.Action,
appPackageName: String?,
textView: TextView
textView: TextView,
) {
val actionText = if (action == Constants.Action.OpenApp) {
val appName = appPackageName?.let { context.getAppNameFromPackageName(it) }
@@ -161,12 +162,16 @@ class SettingsFeaturesFragment : Fragment(),
showSearchEngineDialog()
}
miscellaneousAppLanguageControl.setOnClickListener {
showAppLanguageDialog()
}
miscellaneousFilterStrengthControl.setOnClickListener {
showFilterStrengthDialog()
}
miscellaneousAppLanguageControl.setOnClickListener {
showAppLanguageDialog()
miscellaneousSwipeThresholdControl.setOnClickListener {
showSwipeThresholdDialog()
}
}
}
@@ -282,7 +287,7 @@ class SettingsFeaturesFragment : Fragment(),
val dialogBuilder = MaterialAlertDialogBuilder(context).apply {
setTitle(getString(R.string.settings_select_filter_strength))
setView(seekBarLayout) // Add the slider directly to the dialog
setPositiveButton("ok") { _, _ ->
setPositiveButton(getString(R.string.settings_ok)) { _, _ ->
// Save the slider value when OK is pressed
preferenceViewModel.setFilterStrength(currentValue)
binding.miscellaneousFilterStrengthControl.text = "$currentValue"
@@ -290,7 +295,7 @@ class SettingsFeaturesFragment : Fragment(),
val feedbackType = "select"
appHelper.triggerHapticFeedback(context, feedbackType)
}
setNegativeButton("cancel", null)
setNegativeButton(getString(R.string.settings_cancel), null)
}
// Assign the created dialog to launcherFontDialog
@@ -298,6 +303,74 @@ class SettingsFeaturesFragment : Fragment(),
filterStrengthDialog?.show()
}
private var swipeThresholdDialog: AlertDialog? = null
@RequiresApi(Build.VERSION_CODES.Q)
private fun showSwipeThresholdDialog() {
// Dismiss any existing dialog to prevent multiple dialogs open simultaneously
swipeThresholdDialog?.dismiss()
var currentValue = preferenceHelper.swipeThreshold
// Create a layout to hold the SeekBar and the value display
val seekBarLayout = LinearLayout(context).apply {
orientation = LinearLayout.VERTICAL
gravity = Gravity.CENTER
setPadding(16, 16, 16, 16)
// TextView to display the current value
val valueText = TextView(context).apply {
text = "$currentValue"
textSize = 16f
gravity = Gravity.CENTER
}
// SeekBar for horizontal number selection
val seekBar = SeekBar(context).apply {
min = Constants.SWIPE_THRESHOLD_MIN // Maximum value
max = Constants.SWIPE_THRESHOLD_MAX // Maximum value
progress = currentValue // Default value
setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
currentValue = progress
valueText.text = "$currentValue"
}
override fun onStartTrackingTouch(seekBar: SeekBar) {
// Not used
}
override fun onStopTrackingTouch(seekBar: SeekBar) {
// Not used
}
})
}
// Add TextView and SeekBar to the layout
addView(valueText)
addView(seekBar)
}
// Create the dialog
val dialogBuilder = MaterialAlertDialogBuilder(context).apply {
setTitle(getString(R.string.settings_select_swipe_threshold))
setView(seekBarLayout) // Add the slider directly to the dialog
setPositiveButton(getString(R.string.settings_ok)) { _, _ ->
// Save the slider value when OK is pressed
preferenceViewModel.setSwipeThreshold(currentValue)
binding.miscellaneousSwipeThresholdControl.text = "$currentValue"
val feedbackType = "select"
appHelper.triggerHapticFeedback(context, feedbackType)
}
setNegativeButton(getString(R.string.settings_cancel), null)
}
// Assign the created dialog to launcherFontDialog
swipeThresholdDialog = dialogBuilder.create()
swipeThresholdDialog?.show()
}
private var appSelectionDialog: AlertDialog? = null
@RequiresApi(Build.VERSION_CODES.Q)
@@ -323,7 +396,8 @@ class SettingsFeaturesFragment : Fragment(),
Constants.Swipe.Up,
Constants.Swipe.Down,
Constants.Swipe.Left,
Constants.Swipe.Right -> handleSwipeAction(swipeType, selectedPackageName)
Constants.Swipe.Right,
-> handleSwipeAction(swipeType, selectedPackageName)
}
val feedbackType = "select"
appHelper.triggerHapticFeedback(context, feedbackType)
@@ -497,6 +571,7 @@ class SettingsFeaturesFragment : Fragment(),
swipeActionDialog?.dismiss()
searchEngineDialog?.dismiss()
filterStrengthDialog?.dismiss()
swipeThresholdDialog?.dismiss()
appSelectionDialog?.dismiss()
}
}

View File

@@ -68,7 +68,7 @@ class WidgetFragment : Fragment(),
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
savedInstanceState: Bundle?,
): View {
// Inflate the layout for this fragment
_binding = FragmentWidgetsBinding.inflate(inflater, container, false)
@@ -386,7 +386,7 @@ class WidgetFragment : Fragment(),
}
private fun getSwipeGestureListener(context: Context): View.OnTouchListener {
return object : OnSwipeTouchListener(context) {
return object : OnSwipeTouchListener(context, preferenceHelper) {
override fun onLongClick() {
super.onLongClick()
val actionTypeNavOptions: NavOptions? =

View File

@@ -16,13 +16,13 @@ import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.github.droidworksstudio.common.hasInternetPermission
import com.github.droidworksstudio.launcher.R
import com.github.droidworksstudio.launcher.adapter.numberpicker.NumberPickerAdapter
import com.github.droidworksstudio.launcher.databinding.FragmentSettingsWidgetsBinding
import com.github.droidworksstudio.launcher.helper.AppHelper
import com.github.droidworksstudio.launcher.helper.PreferenceHelper
import com.github.droidworksstudio.launcher.listener.OnSwipeTouchListener
import com.github.droidworksstudio.launcher.listener.ScrollEventListener
import com.github.droidworksstudio.launcher.ui.bottomsheetdialog.ColorBottomSheetDialogFragment
import com.github.droidworksstudio.launcher.adapter.numberpicker.NumberPickerAdapter
import com.github.droidworksstudio.launcher.utils.Constants
import com.github.droidworksstudio.launcher.viewmodel.PreferenceViewModel
import com.google.android.material.dialog.MaterialAlertDialogBuilder
@@ -50,7 +50,7 @@ class SettingsFragment : Fragment(),
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
savedInstanceState: Bundle?,
): View {
// Inflate the layout for this fragment
_binding = FragmentSettingsWidgetsBinding.inflate(inflater, container, false)
@@ -80,7 +80,7 @@ class SettingsFragment : Fragment(),
weatherSwitchCompat.isChecked = preferenceHelper.showWeatherWidget
weatherSunsetSunriseSwitchCompat.isChecked = preferenceHelper.showWeatherWidgetSunSetRise
weatherOrderControl.text = preferenceHelper.weatherOrderNumber.toString()
weatherOrderControl.text = "${preferenceHelper.weatherOrderNumber}"
if (!context.hasInternetPermission()) {
weatherSettings.visibility = View.GONE
@@ -94,7 +94,7 @@ class SettingsFragment : Fragment(),
// Battery stuff here
batterySwitchCompat.isChecked = preferenceHelper.showBatteryWidget
batteryOrderControl.text = preferenceHelper.batteryOrderNumber.toString()
batteryOrderControl.text = "${preferenceHelper.batteryOrderNumber}"
val batteryVisibility = if (batterySwitchCompat.isChecked) View.VISIBLE else View.GONE
batteryOrderMenu.visibility = batteryVisibility
@@ -158,7 +158,7 @@ class SettingsFragment : Fragment(),
}
private fun getSwipeGestureListener(context: Context): View.OnTouchListener {
return object : OnSwipeTouchListener(context) {
return object : OnSwipeTouchListener(context, preferenceHelper) {
override fun onSwipeLeft() {
super.onSwipeLeft()
findNavController().navigateUp()
@@ -187,7 +187,7 @@ class SettingsFragment : Fragment(),
val adapter = NumberPickerAdapter(numbers) { selectedNumber ->
// Save the order number to SharedPreferences or ViewModel
preferenceViewModel.setWeatherOrderNumber(selectedNumber)
binding.weatherOrderControl.text = preferenceHelper.weatherOrderNumber.toString()
binding.weatherOrderControl.text = "${preferenceHelper.weatherOrderNumber}"
numberPickerDialog.dismiss()
}
@@ -198,7 +198,7 @@ class SettingsFragment : Fragment(),
val adapter = NumberPickerAdapter(numbers) { selectedNumber ->
// Save the order number to SharedPreferences or ViewModel
preferenceViewModel.setBatteryOrderNumber(selectedNumber)
binding.batteryOrderControl.text = preferenceHelper.batteryOrderNumber.toString()
binding.batteryOrderControl.text = "${preferenceHelper.batteryOrderNumber}"
numberPickerDialog.dismiss()
}

View File

@@ -57,12 +57,12 @@ object Constants {
const val APP_TEXT_PADDING = "APP_TEXT_PADDING"
const val SHOW_APP_ICON = "SHOW_APP_ICON"
const val SHOW_APP_ICON_DOTS = "SHOW_APP_ICON_DOTS"
const val AUTOMATIC_KEYBOARD = "AUTOMATIC_KEYBOARD"
const val AUTOMATIC_OPEN_APP = "AUTOMATIC_OPEN_APP"
const val SEARCH_FROM_START = "SEARCH_FROM_START"
const val FILTER_STRENGTH = "FILTER_STRENGTH"
const val SWIPE_THRESHOLD = "SWIPE_THRESHOLD"
const val HOME_ALLIGNMENT_BOTTOM = "HOME_ALLIGNMENT_BOTTOM"
const val TOGGLE_SETTING_LOCK = "TOGGLE_SETTING_LOCK"
const val DISABLE_ANIMATIONS = "DISABLE_ANIMATIONS"
@@ -100,6 +100,9 @@ object Constants {
const val FILTER_STRENGTH_MIN = 0
const val FILTER_STRENGTH_MAX = 100
const val SWIPE_THRESHOLD_MIN = 10
const val SWIPE_THRESHOLD_MAX = 255
const val APP_GROUP_PADDING_MIN = 0.0
const val APP_GROUP_PADDING_MAX = 1000.0

View File

@@ -9,7 +9,7 @@ import javax.inject.Inject
@HiltViewModel
class PreferenceViewModel @Inject constructor(
private val preferenceHelper: PreferenceHelper
private val preferenceHelper: PreferenceHelper,
) : ViewModel() {
private val firstLaunchLiveData: MutableLiveData<Boolean> = MutableLiveData()
@@ -54,6 +54,7 @@ class PreferenceViewModel @Inject constructor(
private val weatherOrderNumberLiveData: MutableLiveData<Int> = MutableLiveData()
private val batteryOrderNumberLiveData: MutableLiveData<Int> = MutableLiveData()
private val filterStrengthLiveData: MutableLiveData<Int> = MutableLiveData()
private val swipeThresholdLiveData: MutableLiveData<Int> = MutableLiveData()
private val appLanguageLiveData: MutableLiveData<Constants.Language> = MutableLiveData()
private val searchEngineLiveData: MutableLiveData<Constants.SearchEngines> = MutableLiveData()
@@ -310,6 +311,11 @@ class PreferenceViewModel @Inject constructor(
filterStrengthLiveData.postValue((preferenceHelper.filterStrength))
}
fun setSwipeThreshold(swipeThreshold: Int) {
preferenceHelper.swipeThreshold = swipeThreshold
swipeThresholdLiveData.postValue((preferenceHelper.swipeThreshold))
}
fun setLauncherFont(launcherFont: Constants.Fonts) {
preferenceHelper.launcherFont = launcherFont
launcherFontLiveData.postValue((preferenceHelper.launcherFont))

View File

@@ -536,6 +536,38 @@
</androidx.appcompat.widget.LinearLayoutCompat>
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginVertical="10dp"
android:orientation="horizontal"
tools:ignore="MissingConstraints">
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/miscellaneous_swipeThreshold_text"
style="@style/TextDefaultStyle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="left|center"
android:text="@string/settings_swipe_threshold"
android:textSize="@dimen/text_large"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="RtlHardcoded" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/miscellaneous_swipeThreshold_control"
style="@style/TextDefaultStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="left|center"
android:text="@string/settings_swipe_threshold"
android:textSize="@dimen/text_large"
tools:ignore="RtlHardcoded" />
</androidx.appcompat.widget.LinearLayoutCompat>
</androidx.appcompat.widget.LinearLayoutCompat>
</androidx.appcompat.widget.LinearLayoutCompat>
</com.github.droidworksstudio.launcher.view.GestureNestedScrollView>

View File

@@ -140,6 +140,9 @@
<string name="settings_select_filter_strength">Select a Filter Strength</string>
<string name="settings_filter_strength">Filter Strength</string>
<string name="settings_select_swipe_threshold">Select a Swipe Threshold</string>
<string name="settings_swipe_threshold">Swipe Threshold</string>
<string name="settings_select_launcher_font">Select a Font Family</string>
<string name="settings_launcher_font">Font Family</string>
@@ -172,6 +175,8 @@
<string name="settings_units_imperial">Imperial</string>
<string name="settings_system">System</string>
<string name="settings_ok">Ok</string>
<string name="settings_cancel">Cancel</string>
<string name="authentication_title">Authentication</string>
<string name="authentication_subtitle">Log in using your biometric credentials.</string>