From efc6e72b246dba1c4d294f0fea9afb5610e5891b Mon Sep 17 00:00:00 2001 From: John Trujillo Date: Tue, 31 Mar 2026 16:42:15 -0500 Subject: [PATCH 1/3] feat(editor): implement swipe-down gesture to reveal top bar Expose showTopBar and add downward fling detection to gesture listener. --- .../activities/editor/BaseEditorActivity.kt | 20 ++++++++++++++++--- .../editor/LandscapeImmersiveController.kt | 2 +- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/com/itsaky/androidide/activities/editor/BaseEditorActivity.kt b/app/src/main/java/com/itsaky/androidide/activities/editor/BaseEditorActivity.kt index 1c1f5420e6..7a9f4f26d3 100644 --- a/app/src/main/java/com/itsaky/androidide/activities/editor/BaseEditorActivity.kt +++ b/app/src/main/java/com/itsaky/androidide/activities/editor/BaseEditorActivity.kt @@ -1436,16 +1436,30 @@ abstract class BaseEditorActivity : velocityX: Float, velocityY: Float, ): Boolean { + if (e1 == null) return false + + val diffX = e2.x - e1.x + val diffY = e2.y - e1.y + + // Check for a swipe down (to show top bar) + // This is placed before the noFilesOpen check so it works while editing + if (diffY > flingDistanceThreshold && abs(velocityY) > flingVelocityThreshold && abs(diffY) > abs(diffX)) { + val topEdgeThreshold = SizeUtils.dp2px(60f) + if (e1.y < topEdgeThreshold) { + immersiveController?.showTopBar() + return true + } + } + // Check if no files are open by looking at the displayedChild of the view flipper val noFilesOpen = content.viewContainer.displayedChild == 1 if (!noFilesOpen) { return false // If files are open, do nothing } - val diffX = e2.x - (e1?.x ?: 0f) - // Check for a right swipe (to open left drawer) - This part is still correct - if (diffX > flingDistanceThreshold && abs(velocityX) > flingVelocityThreshold) { + // Added abs(diffX) > abs(diffY) to prevent diagonal swipes from triggering this + if (diffX > flingDistanceThreshold && abs(velocityX) > flingVelocityThreshold && abs(diffX) > abs(diffY)) { // Use the correct binding for the drawer layout binding.editorDrawerLayout.openDrawer(GravityCompat.START) return true diff --git a/app/src/main/java/com/itsaky/androidide/activities/editor/LandscapeImmersiveController.kt b/app/src/main/java/com/itsaky/androidide/activities/editor/LandscapeImmersiveController.kt index 73db69f422..1f5ad0d776 100644 --- a/app/src/main/java/com/itsaky/androidide/activities/editor/LandscapeImmersiveController.kt +++ b/app/src/main/java/com/itsaky/androidide/activities/editor/LandscapeImmersiveController.kt @@ -230,7 +230,7 @@ class LandscapeImmersiveController( bottomToggle.isVisible = visible } - private fun showTopBar(animate: Boolean = true) { + fun showTopBar(animate: Boolean = true) { isTopBarRequestedVisible = true topBar.setExpanded(true, animate) } From db1755a00a6b7b2db565674f388f6e86d1e3996f Mon Sep 17 00:00:00 2001 From: John Trujillo Date: Tue, 31 Mar 2026 17:00:58 -0500 Subject: [PATCH 2/3] fix: restrict swipe-down gesture to landscape mode --- .../activities/editor/BaseEditorActivity.kt | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/com/itsaky/androidide/activities/editor/BaseEditorActivity.kt b/app/src/main/java/com/itsaky/androidide/activities/editor/BaseEditorActivity.kt index 7a9f4f26d3..b7d328efd7 100644 --- a/app/src/main/java/com/itsaky/androidide/activities/editor/BaseEditorActivity.kt +++ b/app/src/main/java/com/itsaky/androidide/activities/editor/BaseEditorActivity.kt @@ -1443,12 +1443,12 @@ abstract class BaseEditorActivity : // Check for a swipe down (to show top bar) // This is placed before the noFilesOpen check so it works while editing - if (diffY > flingDistanceThreshold && abs(velocityY) > flingVelocityThreshold && abs(diffY) > abs(diffX)) { - val topEdgeThreshold = SizeUtils.dp2px(60f) - if (e1.y < topEdgeThreshold) { - immersiveController?.showTopBar() - return true - } + val isLandscape = resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE + val topEdgeThreshold = SizeUtils.dp2px(60f) + + if (isLandscape && e1.y < topEdgeThreshold && diffY > flingDistanceThreshold && abs(velocityY) > flingVelocityThreshold && abs(diffY) > abs(diffX)) { + immersiveController?.showTopBar() + return true } // Check if no files are open by looking at the displayedChild of the view flipper From 4621f720ace431af57119b9c139640782cb7b787 Mon Sep 17 00:00:00 2001 From: John Trujillo Date: Wed, 1 Apr 2026 09:38:12 -0500 Subject: [PATCH 3/3] refactor: improve gesture detection readability and reusability --- .../activities/editor/BaseEditorActivity.kt | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/com/itsaky/androidide/activities/editor/BaseEditorActivity.kt b/app/src/main/java/com/itsaky/androidide/activities/editor/BaseEditorActivity.kt index b7d328efd7..d480abdec0 100644 --- a/app/src/main/java/com/itsaky/androidide/activities/editor/BaseEditorActivity.kt +++ b/app/src/main/java/com/itsaky/androidide/activities/editor/BaseEditorActivity.kt @@ -178,6 +178,7 @@ abstract class BaseEditorActivity : private val fileManagerViewModel by viewModels() private var feedbackButtonManager: FeedbackButtonManager? = null private var immersiveController: LandscapeImmersiveController? = null + private val topEdgeThreshold by lazy { SizeUtils.dp2px(TOP_EDGE_SWIPE_THRESHOLD_DP) } var isDestroying = false protected set @@ -398,6 +399,7 @@ abstract class BaseEditorActivity : protected val log: Logger = LoggerFactory.getLogger(BaseEditorActivity::class.java) private const val OPTIONS_MENU_INVALIDATION_DELAY = 150L + private const val TOP_EDGE_SWIPE_THRESHOLD_DP = 60f const val EDITOR_CONTAINER_SCALE_FACTOR = 0.87f const val KEY_BOTTOM_SHEET_SHOWN = "editor_bottomSheetShown" @@ -1441,12 +1443,21 @@ abstract class BaseEditorActivity : val diffX = e2.x - e1.x val diffY = e2.y - e1.y + val isVerticalSwipe = abs(diffY) > abs(diffX) + val isHorizontalSwipe = abs(diffX) > abs(diffY) + + val hasDownFlingDistance = diffY > flingDistanceThreshold + val hasRightFlingDistance = diffX > flingDistanceThreshold + + val hasVerticalVelocity = abs(velocityY) > flingVelocityThreshold + val hasHorizontalVelocity = abs(velocityX) > flingVelocityThreshold + // Check for a swipe down (to show top bar) // This is placed before the noFilesOpen check so it works while editing val isLandscape = resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE - val topEdgeThreshold = SizeUtils.dp2px(60f) + val startedNearTopEdge = e1.y < topEdgeThreshold - if (isLandscape && e1.y < topEdgeThreshold && diffY > flingDistanceThreshold && abs(velocityY) > flingVelocityThreshold && abs(diffY) > abs(diffX)) { + if (isLandscape && startedNearTopEdge && hasDownFlingDistance && hasVerticalVelocity && isVerticalSwipe) { immersiveController?.showTopBar() return true } @@ -1459,7 +1470,7 @@ abstract class BaseEditorActivity : // Check for a right swipe (to open left drawer) - This part is still correct // Added abs(diffX) > abs(diffY) to prevent diagonal swipes from triggering this - if (diffX > flingDistanceThreshold && abs(velocityX) > flingVelocityThreshold && abs(diffX) > abs(diffY)) { + if (hasRightFlingDistance && hasHorizontalVelocity && isHorizontalSwipe) { // Use the correct binding for the drawer layout binding.editorDrawerLayout.openDrawer(GravityCompat.START) return true