@@ -177,7 +177,7 @@ abstract class BaseEditorActivity :
177177
178178 private val fileManagerViewModel by viewModels<FileManagerViewModel >()
179179 private var feedbackButtonManager: FeedbackButtonManager ? = null
180- private var immersiveController : LandscapeImmersiveController ? = null
180+ private var fullscreenManager : FullscreenManager ? = null
181181 private val topEdgeThreshold by lazy { SizeUtils .dp2px(TOP_EDGE_SWIPE_THRESHOLD_DP ) }
182182
183183 var isDestroying = false
@@ -455,8 +455,8 @@ abstract class BaseEditorActivity :
455455 editorBottomSheet = null
456456 gestureDetector = null
457457
458- immersiveController ?.destroy()
459- immersiveController = null
458+ fullscreenManager ?.destroy()
459+ fullscreenManager = null
460460
461461 _binding = null
462462
@@ -498,7 +498,6 @@ abstract class BaseEditorActivity :
498498 }
499499
500500 private fun applyStandardInsets (systemBars : Insets ) {
501- immersiveController?.onSystemBarInsetsChanged(systemBars.top)
502501 val root = _binding ?.root ? : return
503502 val initial = root.getOrStoreInitialPadding()
504503 root.updatePadding(bottom = initial.bottom + systemBars.bottom)
@@ -627,14 +626,21 @@ abstract class BaseEditorActivity :
627626 content.tabs.addOnTabSelectedListener(this )
628627
629628 setupStateObservers()
629+ setupFullscreenObserver()
630630 setupViews()
631631
632- immersiveController = LandscapeImmersiveController (
632+ fullscreenManager = FullscreenManager (
633633 contentBinding = content,
634634 bottomSheetBehavior = editorBottomSheet!! ,
635+ closeDrawerAction = {
636+ binding.editorDrawerLayout.closeDrawer(GravityCompat .START )
637+ },
638+ onFullscreenToggleRequested = {
639+ editorViewModel.toggleFullscreen()
640+ },
635641 ).also {
636642 it.bind()
637- it.onConfigurationChanged(resources.configuration )
643+ it.render(editorViewModel.isFullscreen, animate = false )
638644 }
639645
640646 setupContainers()
@@ -668,16 +674,17 @@ abstract class BaseEditorActivity :
668674
669675 override fun onConfigurationChanged (newConfig : Configuration ) {
670676 super .onConfigurationChanged(newConfig)
671- immersiveController?.onConfigurationChanged(newConfig)
672677 window?.decorView?.let { ViewCompat .requestApplyInsets(it) }
673678 reapplySystemBarInsetsFromRoot()
674679 _binding ?.content?.applyBottomSheetAnchorForOrientation(newConfig.orientation)
680+ fullscreenManager?.render(editorViewModel.isFullscreen, animate = false )
675681 }
676682
677683 private fun reapplySystemBarInsetsFromRoot () {
678684 val root = _binding ?.root ? : return
679685 val rootInsets = ViewCompat .getRootWindowInsets(root)
680686 if (rootInsets == null ) {
687+ // Insets can be temporarily unavailable right after a configuration change.
681688 root.post { reapplySystemBarInsetsFromRoot() }
682689 return
683690 }
@@ -844,7 +851,6 @@ abstract class BaseEditorActivity :
844851 }
845852
846853 override fun onPause () {
847- immersiveController?.onPause()
848854 super .onPause()
849855 memoryUsageWatcher.listener = null
850856 memoryUsageWatcher.stopWatching(false )
@@ -1223,6 +1229,16 @@ abstract class BaseEditorActivity :
12231229 }
12241230 }
12251231
1232+ private fun setupFullscreenObserver () {
1233+ lifecycleScope.launch {
1234+ repeatOnLifecycle(Lifecycle .State .STARTED ) {
1235+ editorViewModel.uiState.collectLatest { uiState ->
1236+ fullscreenManager?.render(uiState.isFullscreen, animate = true )
1237+ }
1238+ }
1239+ }
1240+ }
1241+
12261242 private fun setupViews () {
12271243 setupNoEditorView()
12281244 setupBottomSheet()
@@ -1383,7 +1399,7 @@ abstract class BaseEditorActivity :
13831399
13841400 content.apply {
13851401 viewContainer.viewTreeObserver.addOnGlobalLayoutListener(observer)
1386- bottomSheet.setOffsetAnchor(editorAppBarLayout )
1402+ applyBottomSheetAnchorForOrientation(resources.configuration.orientation )
13871403 }
13881404 }
13891405
@@ -1447,31 +1463,48 @@ abstract class BaseEditorActivity :
14471463 val isHorizontalSwipe = abs(diffX) > abs(diffY)
14481464
14491465 val hasDownFlingDistance = diffY > flingDistanceThreshold
1450- val hasRightFlingDistance = diffX > flingDistanceThreshold
1466+ val hasUpFlingDistance = diffY < - flingDistanceThreshold
14511467
14521468 val hasVerticalVelocity = abs(velocityY) > flingVelocityThreshold
14531469 val hasHorizontalVelocity = abs(velocityX) > flingVelocityThreshold
1470+ val hasRightFlingDistance = diffX > flingDistanceThreshold
1471+
1472+ val screenHeight = resources.displayMetrics.heightPixels
1473+ val bottomEdgeThreshold = screenHeight - topEdgeThreshold
14541474
1455- // Check for a swipe down (to show top bar)
1456- // This is placed before the noFilesOpen check so it works while editing
1457- val isLandscape = resources.configuration.orientation == Configuration .ORIENTATION_LANDSCAPE
14581475 val startedNearTopEdge = e1.y < topEdgeThreshold
1476+ val startedNearBottomEdge = e1.y > bottomEdgeThreshold
1477+ val isTopEdgeDismissFling = isVerticalSwipe &&
1478+ hasVerticalVelocity &&
1479+ startedNearTopEdge &&
1480+ hasDownFlingDistance
1481+ val isBottomEdgeDismissFling = isVerticalSwipe &&
1482+ hasVerticalVelocity &&
1483+ startedNearBottomEdge &&
1484+ hasUpFlingDistance
1485+ val isDrawerOpenFling = hasRightFlingDistance &&
1486+ hasHorizontalVelocity &&
1487+ isHorizontalSwipe
1488+
1489+ // Fullscreen mode can be dismissed with an inward fling from either vertical edge.
1490+ if (isTopEdgeDismissFling && editorViewModel.isFullscreen) {
1491+ editorViewModel.exitFullscreen()
1492+ return true
1493+ }
14591494
1460- if (isLandscape && startedNearTopEdge && hasDownFlingDistance && hasVerticalVelocity && isVerticalSwipe ) {
1461- immersiveController?.showTopBar ()
1495+ if (isBottomEdgeDismissFling && editorViewModel.isFullscreen ) {
1496+ editorViewModel.exitFullscreen ()
14621497 return true
14631498 }
14641499
1465- // Check if no files are open by looking at the displayedChild of the view flipper
1500+ // Preserve the editor interaction area; drawer gestures are only enabled on the empty state.
14661501 val noFilesOpen = content.viewContainer.displayedChild == 1
14671502 if (! noFilesOpen) {
1468- return false // If files are open, do nothing
1503+ return false
14691504 }
14701505
1471- // Check for a right swipe (to open left drawer) - This part is still correct
1472- // Added abs(diffX) > abs(diffY) to prevent diagonal swipes from triggering this
1473- if (hasRightFlingDistance && hasHorizontalVelocity && isHorizontalSwipe) {
1474- // Use the correct binding for the drawer layout
1506+ // Filter out diagonal flings so only an intentional right swipe opens the drawer.
1507+ if (isDrawerOpenFling) {
14751508 binding.editorDrawerLayout.openDrawer(GravityCompat .START )
14761509 return true
14771510 }
0 commit comments