From 9f6f21946c8e755093827ec3dfc7cb281a59381d Mon Sep 17 00:00:00 2001
From: Charles Lombardo <clombardo169@gmail.com>
Date: Mon, 1 May 2023 02:26:47 -0400
Subject: [PATCH] android: Add navigation rail

---
 .../features/settings/ui/SettingsActivity.kt  | 31 ++++++---
 .../fragments/HomeSettingsFragment.kt         | 46 ++++++++++----
 .../yuzu/yuzu_emu/fragments/SearchFragment.kt | 63 +++++++++++--------
 .../org/yuzu/yuzu_emu/ui/GamesFragment.kt     | 32 ++++++----
 .../org/yuzu/yuzu_emu/ui/main/MainActivity.kt | 36 +++++------
 .../org/yuzu/yuzu_emu/utils/InsetsHelper.kt   | 10 ---
 .../main/res/layout-w600dp/activity_main.xml  | 46 ++++++++++++++
 .../app/src/main/res/layout/activity_main.xml |  2 +-
 .../res/layout/fragment_home_settings.xml     |  1 +
 .../src/main/res/layout/fragment_search.xml   |  7 ++-
 .../main/res/menu-w600dp/menu_navigation.xml  | 19 ++++++
 .../app/src/main/res/values-w600dp/dimens.xml |  5 ++
 .../app/src/main/res/values/dimens.xml        |  1 +
 .../app/src/main/res/values/themes.xml        |  2 +-
 14 files changed, 208 insertions(+), 93 deletions(-)
 create mode 100644 src/android/app/src/main/res/layout-w600dp/activity_main.xml
 create mode 100644 src/android/app/src/main/res/menu-w600dp/menu_navigation.xml
 create mode 100644 src/android/app/src/main/res/values-w600dp/dimens.xml

diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsActivity.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsActivity.kt
index a92fc1075..ea3d47d82 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsActivity.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsActivity.kt
@@ -15,6 +15,7 @@ import androidx.appcompat.app.AppCompatActivity
 import androidx.core.view.ViewCompat
 import androidx.core.view.WindowCompat
 import androidx.core.view.WindowInsetsCompat
+import android.view.ViewGroup.MarginLayoutParams
 import androidx.core.view.updatePadding
 import com.google.android.material.color.MaterialColors
 import org.yuzu.yuzu_emu.NativeLibrary
@@ -52,12 +53,14 @@ class SettingsActivity : AppCompatActivity(), SettingsActivityView {
         setSupportActionBar(binding.toolbarSettings)
         supportActionBar!!.setDisplayHomeAsUpEnabled(true)
 
-        binding.navigationBarShade.setBackgroundColor(
-            ThemeHelper.getColorWithOpacity(
-                MaterialColors.getColor(binding.navigationBarShade, R.attr.colorSurface),
-                ThemeHelper.SYSTEM_BAR_ALPHA
+        if (InsetsHelper.getSystemGestureType(applicationContext) != InsetsHelper.GESTURE_NAVIGATION) {
+            binding.navigationBarShade.setBackgroundColor(
+                ThemeHelper.getColorWithOpacity(
+                    MaterialColors.getColor(binding.navigationBarShade, R.attr.colorSurface),
+                    ThemeHelper.SYSTEM_BAR_ALPHA
+                )
             )
-        )
+        }
 
         setInsets()
     }
@@ -164,12 +167,20 @@ class SettingsActivity : AppCompatActivity(), SettingsActivityView {
 
     private fun setInsets() {
         ViewCompat.setOnApplyWindowInsetsListener(binding.frameContent) { view: View, windowInsets: WindowInsetsCompat ->
-            val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
-            view.updatePadding(left = insets.left, right = insets.right)
-            InsetsHelper.insetAppBar(insets, binding.appbarSettings)
+            val barInsets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
+            val cutoutInsets = windowInsets.getInsets(WindowInsetsCompat.Type.displayCutout())
+            view.updatePadding(
+                left = barInsets.left + cutoutInsets.left,
+                right = barInsets.right + cutoutInsets.right
+            )
 
-            val mlpShade = binding.navigationBarShade.layoutParams as ViewGroup.MarginLayoutParams
-            mlpShade.height = insets.bottom
+            val mlpAppBar = binding.appbarSettings.layoutParams as MarginLayoutParams
+            mlpAppBar.leftMargin = barInsets.left + cutoutInsets.left
+            mlpAppBar.rightMargin = barInsets.right + cutoutInsets.right
+            binding.appbarSettings.layoutParams = mlpAppBar
+
+            val mlpShade = binding.navigationBarShade.layoutParams as MarginLayoutParams
+            mlpShade.height = barInsets.bottom
             binding.navigationBarShade.layoutParams = mlpShade
 
             windowInsets
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/HomeSettingsFragment.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/HomeSettingsFragment.kt
index eb29d6c96..d651732bf 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/HomeSettingsFragment.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/HomeSettingsFragment.kt
@@ -20,6 +20,7 @@ import androidx.core.app.NotificationCompat
 import androidx.core.app.NotificationManagerCompat
 import androidx.core.view.ViewCompat
 import androidx.core.view.WindowInsetsCompat
+import androidx.core.view.updatePadding
 import androidx.fragment.app.Fragment
 import androidx.fragment.app.activityViewModels
 import androidx.recyclerview.widget.LinearLayoutManager
@@ -107,26 +108,30 @@ class HomeSettingsFragment : Fragment() {
         try {
             startActivity(getFileManagerIntentOnDocumentProvider(Intent.ACTION_VIEW))
             return
-        } catch (_: ActivityNotFoundException) {}
+        } catch (_: ActivityNotFoundException) {
+        }
 
         try {
             startActivity(getFileManagerIntentOnDocumentProvider("android.provider.action.BROWSE"))
             return
-        } catch (_: ActivityNotFoundException) {}
+        } catch (_: ActivityNotFoundException) {
+        }
 
         // Just try to open the file manager, try the package name used on "normal" phones
         try {
             startActivity(getFileManagerIntent("com.google.android.documentsui"))
             showNoLinkNotification()
             return
-        } catch (_: ActivityNotFoundException) {}
+        } catch (_: ActivityNotFoundException) {
+        }
 
         try {
             // Next, try the AOSP package name
             startActivity(getFileManagerIntent("com.android.documentsui"))
             showNoLinkNotification()
             return
-        } catch (_: ActivityNotFoundException) {}
+        } catch (_: ActivityNotFoundException) {
+        }
 
         Toast.makeText(
             requireContext(),
@@ -153,7 +158,10 @@ class HomeSettingsFragment : Fragment() {
     }
 
     private fun showNoLinkNotification() {
-        val builder = NotificationCompat.Builder(requireContext(), getString(R.string.notice_notification_channel_id))
+        val builder = NotificationCompat.Builder(
+            requireContext(),
+            getString(R.string.notice_notification_channel_id)
+        )
             .setSmallIcon(R.drawable.ic_stat_notification_logo)
             .setContentTitle(getString(R.string.notification_no_directory_link))
             .setContentText(getString(R.string.notification_no_directory_link_description))
@@ -204,14 +212,28 @@ class HomeSettingsFragment : Fragment() {
     }
 
     private fun setInsets() =
-        ViewCompat.setOnApplyWindowInsetsListener(binding.scrollViewSettings) { view: View, windowInsets: WindowInsetsCompat ->
-            val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
-            view.setPadding(
-                insets.left,
-                insets.top,
-                insets.right,
-                insets.bottom + resources.getDimensionPixelSize(R.dimen.spacing_navigation)
+        ViewCompat.setOnApplyWindowInsetsListener(binding.root) { view: View, windowInsets: WindowInsetsCompat ->
+            val barInsets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
+            val cutoutInsets = windowInsets.getInsets(WindowInsetsCompat.Type.displayCutout())
+            val spacingNavigation = resources.getDimensionPixelSize(R.dimen.spacing_navigation)
+            val spacingNavigationRail =
+                resources.getDimensionPixelSize(R.dimen.spacing_navigation_rail)
+
+            binding.scrollViewSettings.setPadding(
+                barInsets.left + cutoutInsets.left,
+                barInsets.top,
+                barInsets.right + cutoutInsets.right,
+                barInsets.bottom
             )
+
+            binding.linearLayoutSettings.updatePadding(bottom = spacingNavigation)
+
+            if (ViewCompat.getLayoutDirection(view) == ViewCompat.LAYOUT_DIRECTION_LTR) {
+                binding.linearLayoutSettings.updatePadding(left = spacingNavigationRail)
+            } else {
+                binding.linearLayoutSettings.updatePadding(right = spacingNavigationRail)
+            }
+
             windowInsets
         }
 }
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/SearchFragment.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/SearchFragment.kt
index 5babd9bbf..f6aa370f0 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/SearchFragment.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/SearchFragment.kt
@@ -141,7 +141,8 @@ class SearchFragment : Fragment() {
         }
 
         if (binding.searchText.text.toString().isEmpty()
-            && binding.chipGroup.checkedChipId != View.NO_ID) {
+            && binding.chipGroup.checkedChipId != View.NO_ID
+        ) {
             gamesViewModel.setSearchedGames(filteredList)
             return
         }
@@ -182,41 +183,51 @@ class SearchFragment : Fragment() {
     }
 
     private fun setInsets() =
-        ViewCompat.setOnApplyWindowInsetsListener(binding.root) { _: View, windowInsets: WindowInsetsCompat ->
-            val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
+        ViewCompat.setOnApplyWindowInsetsListener(binding.root) { view: View, windowInsets: WindowInsetsCompat ->
+            val barInsets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
+            val cutoutInsets = windowInsets.getInsets(WindowInsetsCompat.Type.displayCutout())
             val extraListSpacing = resources.getDimensionPixelSize(R.dimen.spacing_med)
-            val navigationSpacing = resources.getDimensionPixelSize(R.dimen.spacing_navigation)
+            val spacingNavigation = resources.getDimensionPixelSize(R.dimen.spacing_navigation)
+            val spacingNavigationRail =
+                resources.getDimensionPixelSize(R.dimen.spacing_navigation_rail)
             val chipSpacing = resources.getDimensionPixelSize(R.dimen.spacing_chip)
 
-            binding.frameSearch.updatePadding(
-                left = insets.left,
-                top = insets.top,
-                right = insets.right
+            binding.constraintSearch.updatePadding(
+                left = barInsets.left + cutoutInsets.left,
+                top = barInsets.top,
+                right = barInsets.right + cutoutInsets.right
             )
 
-            binding.gridGamesSearch.setPadding(
-                insets.left,
-                extraListSpacing,
-                insets.right,
-                insets.bottom + resources.getDimensionPixelSize(R.dimen.spacing_navigation) + extraListSpacing
-            )
-
-            binding.noResultsView.updatePadding(
-                left = insets.left,
-                right = insets.right,
-                bottom = insets.bottom + navigationSpacing
+            binding.gridGamesSearch.updatePadding(
+                top = extraListSpacing,
+                bottom = barInsets.bottom + spacingNavigation + extraListSpacing
             )
+            binding.noResultsView.updatePadding(bottom = spacingNavigation + barInsets.bottom)
 
             val mlpDivider = binding.divider.layoutParams as ViewGroup.MarginLayoutParams
-            mlpDivider.leftMargin = insets.left + chipSpacing
-            mlpDivider.rightMargin = insets.right + chipSpacing
+            if (ViewCompat.getLayoutDirection(view) == ViewCompat.LAYOUT_DIRECTION_LTR) {
+                binding.frameSearch.updatePadding(left = spacingNavigationRail)
+                binding.gridGamesSearch.updatePadding(left = spacingNavigationRail)
+                binding.noResultsView.updatePadding(left = spacingNavigationRail)
+                binding.chipGroup.updatePadding(
+                    left = chipSpacing + spacingNavigationRail,
+                    right = chipSpacing
+                )
+                mlpDivider.leftMargin = chipSpacing + spacingNavigationRail
+                mlpDivider.rightMargin = chipSpacing
+            } else {
+                binding.frameSearch.updatePadding(right = spacingNavigationRail)
+                binding.gridGamesSearch.updatePadding(right = spacingNavigationRail)
+                binding.noResultsView.updatePadding(right = spacingNavigationRail)
+                binding.chipGroup.updatePadding(
+                    left = chipSpacing,
+                    right = chipSpacing + spacingNavigationRail
+                )
+                mlpDivider.leftMargin = chipSpacing
+                mlpDivider.rightMargin = chipSpacing + spacingNavigationRail
+            }
             binding.divider.layoutParams = mlpDivider
 
-            binding.chipGroup.updatePadding(
-                left = insets.left + chipSpacing,
-                right = insets.right + chipSpacing
-            )
-
             windowInsets
         }
 }
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/GamesFragment.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/GamesFragment.kt
index 6f9e04f7e..cc17b8626 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/GamesFragment.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/GamesFragment.kt
@@ -8,27 +8,20 @@ import android.view.LayoutInflater
 import android.view.View
 import android.view.ViewGroup
 import android.view.ViewGroup.MarginLayoutParams
-import androidx.activity.OnBackPressedCallback
 import androidx.appcompat.app.AppCompatActivity
 import androidx.core.view.ViewCompat
 import androidx.core.view.WindowInsetsCompat
 import androidx.core.view.updatePadding
-import androidx.core.widget.doOnTextChanged
 import androidx.fragment.app.Fragment
 import androidx.fragment.app.activityViewModels
 import com.google.android.material.color.MaterialColors
-import com.google.android.material.search.SearchView
-import com.google.android.material.search.SearchView.TransitionState
 import com.google.android.material.transition.MaterialFadeThrough
-import info.debatty.java.stringsimilarity.Jaccard
 import org.yuzu.yuzu_emu.R
 import org.yuzu.yuzu_emu.adapters.GameAdapter
 import org.yuzu.yuzu_emu.databinding.FragmentGamesBinding
 import org.yuzu.yuzu_emu.layout.AutofitGridLayoutManager
-import org.yuzu.yuzu_emu.model.Game
 import org.yuzu.yuzu_emu.model.GamesViewModel
 import org.yuzu.yuzu_emu.model.HomeViewModel
-import java.util.Locale
 
 class GamesFragment : Fragment() {
     private var _binding: FragmentGamesBinding? = null
@@ -127,24 +120,37 @@ class GamesFragment : Fragment() {
 
     private fun setInsets() =
         ViewCompat.setOnApplyWindowInsetsListener(binding.root) { view: View, windowInsets: WindowInsetsCompat ->
-            val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
+            val barInsets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
+            val cutoutInsets = windowInsets.getInsets(WindowInsetsCompat.Type.displayCutout())
             val extraListSpacing = resources.getDimensionPixelSize(R.dimen.spacing_large)
+            val spacingNavigation = resources.getDimensionPixelSize(R.dimen.spacing_navigation)
+            val spacingNavigationRail =
+                resources.getDimensionPixelSize(R.dimen.spacing_navigation_rail)
 
             binding.gridGames.updatePadding(
-                top = insets.top + extraListSpacing,
-                bottom = insets.bottom + resources.getDimensionPixelSize(R.dimen.spacing_navigation) + extraListSpacing
+                top = barInsets.top + extraListSpacing,
+                bottom = barInsets.bottom + spacingNavigation + extraListSpacing
             )
 
             binding.swipeRefresh.setProgressViewEndTarget(
                 false,
-                insets.top + resources.getDimensionPixelSize(R.dimen.spacing_refresh_end)
+                barInsets.top + resources.getDimensionPixelSize(R.dimen.spacing_refresh_end)
             )
 
+            val leftInsets = barInsets.left + cutoutInsets.left
+            val rightInsets = barInsets.right + cutoutInsets.right
             val mlpSwipe = binding.swipeRefresh.layoutParams as MarginLayoutParams
-            mlpSwipe.rightMargin = insets.right
-            mlpSwipe.leftMargin = insets.left
+            if (ViewCompat.getLayoutDirection(view) == ViewCompat.LAYOUT_DIRECTION_LTR) {
+                mlpSwipe.leftMargin = leftInsets + spacingNavigationRail
+                mlpSwipe.rightMargin = rightInsets
+            } else {
+                mlpSwipe.leftMargin = leftInsets
+                mlpSwipe.rightMargin = rightInsets + spacingNavigationRail
+            }
             binding.swipeRefresh.layoutParams = mlpSwipe
 
+            binding.noticeText.updatePadding(bottom = spacingNavigation)
+
             windowInsets
         }
 }
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/main/MainActivity.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/main/MainActivity.kt
index 35b66d1f2..c620c3c7c 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/main/MainActivity.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/main/MainActivity.kt
@@ -67,16 +67,16 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
             ContextCompat.getColor(applicationContext, android.R.color.transparent)
         ThemeHelper.setNavigationBarColor(
             this,
-            ElevationOverlayProvider(binding.navigationBar.context).compositeOverlay(
-                MaterialColors.getColor(binding.navigationBar, R.attr.colorSurface),
-                binding.navigationBar.elevation
+            ElevationOverlayProvider(binding.navigationView.context).compositeOverlay(
+                MaterialColors.getColor(binding.navigationView, R.attr.colorSurface),
+                binding.navigationView.elevation
             )
         )
 
         val navHostFragment =
             supportFragmentManager.findFragmentById(R.id.fragment_container) as NavHostFragment
         setUpNavigation(navHostFragment.navController)
-        (binding.navigationBar as NavigationBarView).setOnItemReselectedListener {
+        (binding.navigationView as NavigationBarView).setOnItemReselectedListener {
             when (it.itemId) {
                 R.id.gamesFragment -> gamesViewModel.setShouldScrollToTop(true)
                 R.id.searchFragment -> gamesViewModel.setSearchFocused(true)
@@ -95,7 +95,7 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
 
         // Prevents navigation from being drawn for a short time on recreation if set to hidden
         if (!homeViewModel.navigationVisible.value?.first!!) {
-            binding.navigationBar.visibility = View.INVISIBLE
+            binding.navigationView.visibility = View.INVISIBLE
             binding.statusBarShade.visibility = View.INVISIBLE
         }
 
@@ -114,14 +114,14 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
 
     fun finishSetup(navController: NavController) {
         navController.navigate(R.id.action_firstTimeSetupFragment_to_gamesFragment)
-        binding.navigationBar.setupWithNavController(navController)
+        (binding.navigationView as NavigationBarView).setupWithNavController(navController)
         showNavigation(visible = true, animated = true)
 
         ThemeHelper.setNavigationBarColor(
             this,
-            ElevationOverlayProvider(binding.navigationBar.context).compositeOverlay(
-                MaterialColors.getColor(binding.navigationBar, R.attr.colorSurface),
-                binding.navigationBar.elevation
+            ElevationOverlayProvider(binding.navigationView.context).compositeOverlay(
+                MaterialColors.getColor(binding.navigationView, R.attr.colorSurface),
+                binding.navigationView.elevation
             )
         )
     }
@@ -134,35 +134,35 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
             navController.navigate(R.id.firstTimeSetupFragment)
             homeViewModel.navigatedToSetup = true
         } else {
-            binding.navigationBar.setupWithNavController(navController)
+            (binding.navigationView as NavigationBarView).setupWithNavController(navController)
         }
     }
 
     private fun showNavigation(visible: Boolean, animated: Boolean) {
         if (!animated) {
             if (visible) {
-                binding.navigationBar.visibility = View.VISIBLE
+                binding.navigationView.visibility = View.VISIBLE
             } else {
-                binding.navigationBar.visibility = View.INVISIBLE
+                binding.navigationView.visibility = View.INVISIBLE
             }
             return
         }
 
-        binding.navigationBar.animate().apply {
+        binding.navigationView.animate().apply {
             if (visible) {
-                binding.navigationBar.visibility = View.VISIBLE
-                binding.navigationBar.translationY = binding.navigationBar.height.toFloat() * 2
+                binding.navigationView.visibility = View.VISIBLE
+                binding.navigationView.translationY = binding.navigationView.height.toFloat() * 2
                 duration = 300
                 translationY(0f)
                 interpolator = PathInterpolator(0.05f, 0.7f, 0.1f, 1f)
             } else {
                 duration = 300
-                translationY(binding.navigationBar.height.toFloat() * 2)
+                translationY(binding.navigationView.height.toFloat() * 2)
                 interpolator = PathInterpolator(0.3f, 0f, 0.8f, 0.15f)
             }
         }.withEndAction {
             if (!visible) {
-                binding.navigationBar.visibility = View.INVISIBLE
+                binding.navigationView.visibility = View.INVISIBLE
             }
         }.start()
     }
@@ -177,7 +177,7 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
                 interpolator = PathInterpolator(0.05f, 0.7f, 0.1f, 1f)
             } else {
                 duration = 300
-                translationY(binding.navigationBar.height.toFloat() * -2)
+                translationY(binding.navigationView.height.toFloat() * -2)
                 interpolator = PathInterpolator(0.3f, 0f, 0.8f, 0.15f)
             }
         }.withEndAction {
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/InsetsHelper.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/InsetsHelper.kt
index e7a04d917..e587fea06 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/InsetsHelper.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/InsetsHelper.kt
@@ -4,22 +4,12 @@ import android.annotation.SuppressLint
 import android.app.Activity
 import android.content.Context
 import android.graphics.Rect
-import android.view.ViewGroup.MarginLayoutParams
-import androidx.core.graphics.Insets
-import com.google.android.material.appbar.AppBarLayout
 
 object InsetsHelper {
     const val THREE_BUTTON_NAVIGATION = 0
     const val TWO_BUTTON_NAVIGATION = 1
     const val GESTURE_NAVIGATION = 2
 
-    fun insetAppBar(insets: Insets, appBarLayout: AppBarLayout) {
-        val mlpAppBar = appBarLayout.layoutParams as MarginLayoutParams
-        mlpAppBar.leftMargin = insets.left
-        mlpAppBar.rightMargin = insets.right
-        appBarLayout.layoutParams = mlpAppBar
-    }
-
     @SuppressLint("DiscouragedApi")
     fun getSystemGestureType(context: Context): Int {
         val resources = context.resources
diff --git a/src/android/app/src/main/res/layout-w600dp/activity_main.xml b/src/android/app/src/main/res/layout-w600dp/activity_main.xml
new file mode 100644
index 000000000..39b61a13e
--- /dev/null
+++ b/src/android/app/src/main/res/layout-w600dp/activity_main.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="utf-8"?>
+<androidx.constraintlayout.widget.ConstraintLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:id="@+id/coordinator_main"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+
+    <androidx.fragment.app.FragmentContainerView
+        android:id="@+id/fragment_container"
+        android:name="androidx.navigation.fragment.NavHostFragment"
+        android:layout_width="0dp"
+        android:layout_height="0dp"
+        app:defaultNavHost="true"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toTopOf="parent"
+        app:navGraph="@navigation/home_navigation"
+        tools:layout="@layout/fragment_games" />
+
+    <com.google.android.material.navigationrail.NavigationRailView
+        android:id="@+id/navigation_view"
+        android:layout_width="wrap_content"
+        android:layout_height="match_parent"
+        android:visibility="invisible"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toTopOf="parent"
+        app:labelVisibilityMode="selected"
+        app:menu="@menu/menu_navigation"
+        tools:visibility="visible" />
+
+    <View
+        android:id="@+id/status_bar_shade"
+        android:layout_width="0dp"
+        android:layout_height="1px"
+        android:background="@android:color/transparent"
+        android:clickable="false"
+        android:focusable="false"
+        app:layout_constraintTop_toTopOf="parent"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="parent" />
+
+</androidx.constraintlayout.widget.ConstraintLayout>
diff --git a/src/android/app/src/main/res/layout/activity_main.xml b/src/android/app/src/main/res/layout/activity_main.xml
index 6ca426b54..214acb041 100644
--- a/src/android/app/src/main/res/layout/activity_main.xml
+++ b/src/android/app/src/main/res/layout/activity_main.xml
@@ -21,7 +21,7 @@
         tools:layout="@layout/fragment_games" />
 
     <com.google.android.material.bottomnavigation.BottomNavigationView
-        android:id="@+id/navigation_bar"
+        android:id="@+id/navigation_view"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:visibility="invisible"
diff --git a/src/android/app/src/main/res/layout/fragment_home_settings.xml b/src/android/app/src/main/res/layout/fragment_home_settings.xml
index e0c609309..82b037010 100644
--- a/src/android/app/src/main/res/layout/fragment_home_settings.xml
+++ b/src/android/app/src/main/res/layout/fragment_home_settings.xml
@@ -8,6 +8,7 @@
     android:clipToPadding="false">
 
     <androidx.appcompat.widget.LinearLayoutCompat
+        android:id="@+id/linear_layout_settings"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
         android:orientation="vertical"
diff --git a/src/android/app/src/main/res/layout/fragment_search.xml b/src/android/app/src/main/res/layout/fragment_search.xml
index 3b1aefdfb..b8d54d947 100644
--- a/src/android/app/src/main/res/layout/fragment_search.xml
+++ b/src/android/app/src/main/res/layout/fragment_search.xml
@@ -3,9 +3,11 @@
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:app="http://schemas.android.com/apk/res-auto"
     xmlns:tools="http://schemas.android.com/tools"
+    android:id="@+id/constraint_search"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
-    android:background="?attr/colorSurface">
+    android:background="?attr/colorSurface"
+    android:clipToPadding="false">
 
     <RelativeLayout
         android:layout_width="0dp"
@@ -52,7 +54,8 @@
         android:id="@+id/frame_search"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:layout_margin="20dp"
+        android:layout_marginTop="12dp"
+        android:layout_marginHorizontal="20dp"
         app:layout_constraintEnd_toEndOf="parent"
         app:layout_constraintStart_toStartOf="parent"
         app:layout_constraintTop_toTopOf="parent">
diff --git a/src/android/app/src/main/res/menu-w600dp/menu_navigation.xml b/src/android/app/src/main/res/menu-w600dp/menu_navigation.xml
new file mode 100644
index 000000000..073d00cab
--- /dev/null
+++ b/src/android/app/src/main/res/menu-w600dp/menu_navigation.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <item
+        android:id="@+id/homeSettingsFragment"
+        android:icon="@drawable/ic_settings"
+        android:title="@string/home_settings" />
+
+    <item
+        android:id="@+id/searchFragment"
+        android:icon="@drawable/ic_search"
+        android:title="@string/home_search" />
+
+    <item
+        android:id="@+id/gamesFragment"
+        android:icon="@drawable/ic_controller"
+        android:title="@string/home_games" />
+
+</menu>
diff --git a/src/android/app/src/main/res/values-w600dp/dimens.xml b/src/android/app/src/main/res/values-w600dp/dimens.xml
new file mode 100644
index 000000000..128319e27
--- /dev/null
+++ b/src/android/app/src/main/res/values-w600dp/dimens.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <dimen name="spacing_navigation">0dp</dimen>
+    <dimen name="spacing_navigation_rail">80dp</dimen>
+</resources>
diff --git a/src/android/app/src/main/res/values/dimens.xml b/src/android/app/src/main/res/values/dimens.xml
index 28a6d25cf..00757e5e8 100644
--- a/src/android/app/src/main/res/values/dimens.xml
+++ b/src/android/app/src/main/res/values/dimens.xml
@@ -7,6 +7,7 @@
     <dimen name="spacing_list">64dp</dimen>
     <dimen name="spacing_chip">20dp</dimen>
     <dimen name="spacing_navigation">80dp</dimen>
+    <dimen name="spacing_navigation_rail">0dp</dimen>
     <dimen name="spacing_search">128dp</dimen>
     <dimen name="spacing_refresh_end">72dp</dimen>
     <dimen name="menu_width">256dp</dimen>
diff --git a/src/android/app/src/main/res/values/themes.xml b/src/android/app/src/main/res/values/themes.xml
index f32e2f5d0..60388b71e 100644
--- a/src/android/app/src/main/res/values/themes.xml
+++ b/src/android/app/src/main/res/values/themes.xml
@@ -42,7 +42,7 @@
         <item name="sliderStyle">@style/YuzuSlider</item>
         <item name="materialAlertDialogTheme">@style/YuzuMaterialDialog</item>
 
-        <item name="android:windowLayoutInDisplayCutoutMode">default</item>
+        <item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item>
 
         <item name="android:enforceStatusBarContrast">false</item>
         <item name="android:enforceNavigationBarContrast">false</item>