summaryrefslogtreecommitdiff
path: root/app/src
diff options
context:
space:
mode:
authortest@dangofactory.cos <you@example.com>2026-08-21 14:30:20 +0000
committertest@dangofactory.cos <you@example.com>2026-08-21 14:30:20 +0000
commit112e4d709b56fb64e38d6af2b4309d9089c3b6ee (patch)
tree24020c1674a3f001b7aaf7eebc98f7438181744d /app/src
parentb78a78c2a1a1dbd10550f055b6311eb0cc4d7890 (diff)
downloadSidePhOnelauncher-112e4d709b56fb64e38d6af2b4309d9089c3b6ee.tar.gz
SidePhOnelauncher-112e4d709b56fb64e38d6af2b4309d9089c3b6ee.tar.bz2
SidePhOnelauncher-112e4d709b56fb64e38d6af2b4309d9089c3b6ee.zip
claude
Diffstat (limited to 'app/src')
-rw-r--r--app/src/main/java/app/sidephonelauncher/data/Prefs.kt7
-rw-r--r--app/src/main/java/app/sidephonelauncher/ui/AppDrawerAdapter.kt46
-rw-r--r--app/src/main/java/app/sidephonelauncher/ui/HomeFragment.kt83
3 files changed, 128 insertions, 8 deletions
diff --git a/app/src/main/java/app/sidephonelauncher/data/Prefs.kt b/app/src/main/java/app/sidephonelauncher/data/Prefs.kt
index dc7b631..1938994 100644
--- a/app/src/main/java/app/sidephonelauncher/data/Prefs.kt
+++ b/app/src/main/java/app/sidephonelauncher/data/Prefs.kt
@@ -148,7 +148,11 @@ class Prefs(context: Context) {
set(value) = prefs.edit { putBoolean(LOCK_MODE, value).apply() }
var autoShowKeyboard: Boolean
- get() = prefs.getBoolean(AUTO_SHOW_KEYBOARD, true)
+ // Default to false so the app list underneath the search box receives
+ // initial focus when the drawer opens, instead of the keyboard/search
+ // box grabbing focus first. Users who prefer keyboard-first search can
+ // still re-enable this from Settings.
+ get() = prefs.getBoolean(AUTO_SHOW_KEYBOARD, false)
set(value) = prefs.edit { putBoolean(AUTO_SHOW_KEYBOARD, value).apply() }
var keyboardMessageShown: Boolean
@@ -686,3 +690,4 @@ class Prefs(context: Context) {
fun setAppRenameLabel(appPackage: String, renameLabel: String) = prefs.edit { putString(appPackage, renameLabel) }
}
+
diff --git a/app/src/main/java/app/sidephonelauncher/ui/AppDrawerAdapter.kt b/app/src/main/java/app/sidephonelauncher/ui/AppDrawerAdapter.kt
index 9bc0da2..6c8c0a0 100644
--- a/app/src/main/java/app/sidephonelauncher/ui/AppDrawerAdapter.kt
+++ b/app/src/main/java/app/sidephonelauncher/ui/AppDrawerAdapter.kt
@@ -301,8 +301,36 @@ class AppDrawerAdapter(
}
updateFocusAppearance(root.context, appTitle, otherProfileIndicator, appRow.isFocused, focusIndicatorStyle)
+ // On the plain app drawer / hidden-apps list, long-press opens the
+ // hide/rename overlay. But when this list is being used as a picker
+ // (setting a home slot / seed-dial app, swipe app, clock app, etc.)
+ // that overlay makes no sense here: long-press should just be
+ // disabled for that purpose and instead cancel back out of the
+ // picker, leaving DPAD-center short-press as the only way to
+ // confirm a selection.
+ val isPickerFlag = flag != Constants.FLAG_LAUNCH_APP && flag != Constants.FLAG_HIDDEN_APPS
+
+ // Tracks whether the current DPAD-center/Enter press-and-hold has
+ // already fired a long click, and whether we've actually seen a
+ // *fresh* key-down (repeatCount == 0) for this row. Without this,
+ // KeyEvent.ACTION_UP always reports repeatCount == 0 (release
+ // events don't carry the hold count), so the old `repeatCount ==
+ // 0` check on ACTION_UP fired performClick() every single time -
+ // even right after a long click had just been triggered, or when
+ // a press was still being held down from a previous screen (e.g.
+ // the long-press on the home slot that opened this list as a
+ // picker) and simply carried over onto the newly focused row.
+ // That's what caused holding DPAD-center to launch/select an app
+ // immediately instead of respecting long-press-first semantics.
+ var dpadFreshPress = false
+ var dpadLongPressTriggered = false
+
appRow.setOnClickListener { clickListener(appModel) }
appRow.setOnLongClickListener {
+ if (isPickerFlag) {
+ appBackListener()
+ return@setOnLongClickListener true
+ }
if (isSpecialActionItem) return@setOnLongClickListener true
if (appModel.appPackage.isNotEmpty()) {
appDelete.alpha = when (
@@ -335,14 +363,27 @@ class AppDrawerAdapter(
KeyEvent.KEYCODE_NUMPAD_ENTER -> {
when (event.action) {
KeyEvent.ACTION_DOWN -> {
- if (event.repeatCount > 0) {
+ if (event.repeatCount == 0) {
+ // Genuine new press on this row.
+ dpadFreshPress = true
+ dpadLongPressTriggered = false
+ } else if (dpadFreshPress && !dpadLongPressTriggered) {
+ dpadLongPressTriggered = true
appRow.performLongClick()
}
+ // If repeatCount > 0 but we never saw a fresh
+ // down (dpadFreshPress == false), this is a
+ // held-over key repeat from before this row
+ // had focus - swallow it instead of acting.
true
}
KeyEvent.ACTION_UP -> {
- if (event.repeatCount == 0) appRow.performClick()
+ if (dpadFreshPress && !dpadLongPressTriggered) {
+ appRow.performClick()
+ }
+ dpadFreshPress = false
+ dpadLongPressTriggered = false
true
}
@@ -494,3 +535,4 @@ class AppDrawerAdapter(
}
}
}
+
diff --git a/app/src/main/java/app/sidephonelauncher/ui/HomeFragment.kt b/app/src/main/java/app/sidephonelauncher/ui/HomeFragment.kt
index 25b4376..858af5c 100644
--- a/app/src/main/java/app/sidephonelauncher/ui/HomeFragment.kt
+++ b/app/src/main/java/app/sidephonelauncher/ui/HomeFragment.kt
@@ -297,6 +297,20 @@ class HomeFragment : Fragment(), View.OnClickListener, View.OnLongClickListener
val binding = _binding ?: return false
val visibleApps = getVisibleHomeApps()
+ if (event.action == KeyEvent.ACTION_DOWN && event.repeatCount == 0) {
+ val appIndex = when (keyCode) {
+ KeyEvent.KEYCODE_F1 -> 1
+ KeyEvent.KEYCODE_F2 -> 2
+ KeyEvent.KEYCODE_F3 -> 3
+ KeyEvent.KEYCODE_F4 -> 4
+ else -> 0
+ }
+ if (appIndex != 0) {
+ homeAppClicked(appIndex)
+ return true
+ }
+ }
+
if (activity?.currentFocus == binding.mainLayout) {
when (keyCode) {
KeyEvent.KEYCODE_DPAD_UP,
@@ -504,6 +518,12 @@ class HomeFragment : Fragment(), View.OnClickListener, View.OnLongClickListener
binding.tvScreenTime.setOnLongClickListener(this)
listOf(binding.clock, binding.date).forEach { headerView ->
+ // See the matching comment in AppDrawerAdapter: ACTION_UP always
+ // reports repeatCount == 0, so without this tracking a long
+ // press-and-hold on DPAD-center would fire performClick() again
+ // on release right after performLongClick() had already fired.
+ var dpadFreshPress = false
+ var dpadLongPressTriggered = false
headerView.setOnKeyListener { view, keyCode, event ->
when (keyCode) {
KeyEvent.KEYCODE_DPAD_UP -> {
@@ -512,6 +532,14 @@ class HomeFragment : Fragment(), View.OnClickListener, View.OnLongClickListener
val currentIndex = headerTargets.indexOf(view)
if (currentIndex > 0) {
headerTargets[currentIndex - 1].requestFocus()
+ } else {
+ // Already at the topmost header item: there's nothing
+ // further up to focus, so treat DPAD-up here the same
+ // as the existing swipe-down-from-top touch gesture,
+ // making the status/notification bar reachable
+ // without touch (e.g. when the status bar is shown
+ // but the system swipe gesture is unavailable).
+ swipeDownAction()
}
true
}
@@ -551,14 +579,20 @@ class HomeFragment : Fragment(), View.OnClickListener, View.OnLongClickListener
KeyEvent.KEYCODE_NUMPAD_ENTER -> {
when (event.action) {
KeyEvent.ACTION_DOWN -> {
- if (event.repeatCount > 0) {
+ if (event.repeatCount == 0) {
+ dpadFreshPress = true
+ dpadLongPressTriggered = false
+ } else if (dpadFreshPress && !dpadLongPressTriggered) {
+ dpadLongPressTriggered = true
view.performLongClick()
}
true
}
KeyEvent.ACTION_UP -> {
- if (event.repeatCount == 0) view.performClick()
+ if (dpadFreshPress && !dpadLongPressTriggered) view.performClick()
+ dpadFreshPress = false
+ dpadLongPressTriggered = false
true
}
@@ -586,6 +620,8 @@ class HomeFragment : Fragment(), View.OnClickListener, View.OnLongClickListener
homeApp.onFocusChangeListener = View.OnFocusChangeListener { view, hasFocus ->
rememberHomeFocus(view, hasFocus)
}
+ var dpadFreshPress = false
+ var dpadLongPressTriggered = false
homeApp.setOnKeyListener { view, keyCode, event ->
when (keyCode) {
KeyEvent.KEYCODE_DPAD_DOWN -> {
@@ -619,14 +655,31 @@ class HomeFragment : Fragment(), View.OnClickListener, View.OnLongClickListener
KeyEvent.KEYCODE_NUMPAD_ENTER -> {
when (event.action) {
KeyEvent.ACTION_DOWN -> {
- if (event.repeatCount > 0) {
+ if (event.repeatCount == 0) {
+ dpadFreshPress = true
+ dpadLongPressTriggered = false
+ } else if (dpadFreshPress && !dpadLongPressTriggered) {
+ // Long-press: opens the AppDrawer as a
+ // picker for this home slot (seed-dial
+ // style assignment). Short click (below,
+ // on release) launches the assigned app.
+ dpadLongPressTriggered = true
view.performLongClick()
}
true
}
KeyEvent.ACTION_UP -> {
- if (event.repeatCount == 0) view.performClick()
+ // Only launch on release if this row never
+ // fired a long click for this press. This is
+ // also what stops a DPAD-center held over
+ // from a previous screen (e.g. still down
+ // right as the picker opens) from being
+ // misread as "confirm" on whatever item ends
+ // up focused first.
+ if (dpadFreshPress && !dpadLongPressTriggered) view.performClick()
+ dpadFreshPress = false
+ dpadLongPressTriggered = false
true
}
@@ -1110,7 +1163,26 @@ class HomeFragment : Fragment(), View.OnClickListener, View.OnLongClickListener
private fun swipeDownAction() {
when (prefs.swipeDownAction) {
Constants.SwipeDownAction.SEARCH -> openSearch(requireContext())
- else -> expandNotificationDrawer(requireContext())
+ else -> {
+ // When prefs.showStatusBar is off, the status bar surface is
+ // hidden (immersive mode), so there is no bar for the
+ // notification shade to render into: expandNotificationsPanel()
+ // was being invoked successfully but had nothing visible to
+ // expand, which is why the panel never appeared. Reveal the
+ // status bar surface first so the DPAD-triggered "swipe down"
+ // can actually show it, same as it would if the user were
+ // allowed to swipe down from the top edge by touch.
+ if (!prefs.showStatusBar) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
+ requireActivity().window.insetsController?.show(WindowInsets.Type.statusBars())
+ } else {
+ @Suppress("DEPRECATION")
+ requireActivity().window.decorView.systemUiVisibility =
+ View.SYSTEM_UI_FLAG_LAYOUT_STABLE or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
+ }
+ }
+ expandNotificationDrawer(requireContext())
+ }
}
}
@@ -1289,3 +1361,4 @@ class HomeFragment : Fragment(), View.OnClickListener, View.OnLongClickListener
_binding = null
}
}
+