Twelve: Main fragment tablet UI
diff --git a/app/src/main/java/org/lineageos/twelve/fragments/MainFragment.kt b/app/src/main/java/org/lineageos/twelve/fragments/MainFragment.kt
index 3db2677..b32eb76 100644
--- a/app/src/main/java/org/lineageos/twelve/fragments/MainFragment.kt
+++ b/app/src/main/java/org/lineageos/twelve/fragments/MainFragment.kt
@@ -7,6 +7,8 @@
 
 import android.os.Bundle
 import android.view.View
+import androidx.core.view.ViewCompat
+import androidx.core.view.WindowInsetsCompat
 import androidx.fragment.app.Fragment
 import androidx.fragment.app.viewModels
 import androidx.lifecycle.Lifecycle
@@ -17,12 +19,14 @@
 import androidx.viewpager2.adapter.FragmentStateAdapter
 import androidx.viewpager2.widget.ViewPager2
 import com.google.android.material.appbar.MaterialToolbar
-import com.google.android.material.bottomnavigation.BottomNavigationView
 import com.google.android.material.button.MaterialButton
+import com.google.android.material.navigation.NavigationBarView
 import kotlinx.coroutines.flow.collectLatest
 import kotlinx.coroutines.launch
 import org.lineageos.twelve.R
 import org.lineageos.twelve.ext.getViewProperty
+import org.lineageos.twelve.ext.isLandscape
+import org.lineageos.twelve.ext.updatePadding
 import org.lineageos.twelve.models.RequestStatus
 import org.lineageos.twelve.ui.views.NowPlayingBar
 import org.lineageos.twelve.viewmodels.NowPlayingViewModel
@@ -37,7 +41,7 @@
     private val providersViewModel by viewModels<ProvidersViewModel>()
 
     // Views
-    private val bottomNavigationView by getViewProperty<BottomNavigationView>(R.id.bottomNavigationView)
+    private val navigationBarView by getViewProperty<NavigationBarView>(R.id.navigationBarView)
     private val nowPlayingBar by getViewProperty<NowPlayingBar>(R.id.nowPlayingBar)
     private val providerMaterialButton by getViewProperty<MaterialButton>(R.id.providerMaterialButton)
     private val toolbar by getViewProperty<MaterialToolbar>(R.id.toolbar)
@@ -49,7 +53,7 @@
             override fun onPageSelected(position: Int) {
                 super.onPageSelected(position)
 
-                bottomNavigationView.menu.getItem(position).isChecked = true
+                navigationBarView.menu.getItem(position).isChecked = true
             }
         }
     }
@@ -57,6 +61,49 @@
     override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
         super.onViewCreated(view, savedInstanceState)
 
+        // Insets
+        ViewCompat.setOnApplyWindowInsetsListener(toolbar) { v, windowInsets ->
+            val insets = windowInsets.getInsets(WindowInsetsCompat.Type.displayCutout())
+
+            v.updatePadding(
+                insets,
+                start = !resources.configuration.isLandscape,
+                end = true,
+            )
+
+            windowInsets
+        }
+
+        if (resources.configuration.isLandscape) {
+            ViewCompat.setOnApplyWindowInsetsListener(navigationBarView) { v, windowInsets ->
+                // This is a navigation rail
+                val insets = windowInsets.getInsets(
+                    WindowInsetsCompat.Type.systemBars() or WindowInsetsCompat.Type.displayCutout()
+                )
+
+                v.updatePadding(
+                    insets,
+                    start = true,
+                    top = true,
+                    bottom = true,
+                )
+
+                windowInsets
+            }
+        }
+
+        ViewCompat.setOnApplyWindowInsetsListener(viewPager2) { v, windowInsets ->
+            val insets = windowInsets.getInsets(WindowInsetsCompat.Type.displayCutout())
+
+            v.updatePadding(
+                insets,
+                start = !resources.configuration.isLandscape,
+                end = true,
+            )
+
+            windowInsets
+        }
+
         toolbar.setupWithNavController(findNavController())
 
         providerMaterialButton.setOnClickListener {
@@ -73,7 +120,7 @@
         viewPager2.offscreenPageLimit = fragments.size
         viewPager2.registerOnPageChangeCallback(onPageChangeCallback)
 
-        bottomNavigationView.setOnItemSelectedListener { item ->
+        navigationBarView.setOnItemSelectedListener { item ->
             when (item.itemId) {
                 R.id.activityFragment -> {
                     viewPager2.currentItem = 0
diff --git a/app/src/main/java/org/lineageos/twelve/ui/views/NowPlayingBar.kt b/app/src/main/java/org/lineageos/twelve/ui/views/NowPlayingBar.kt
index 12df33f..24655ec 100644
--- a/app/src/main/java/org/lineageos/twelve/ui/views/NowPlayingBar.kt
+++ b/app/src/main/java/org/lineageos/twelve/ui/views/NowPlayingBar.kt
@@ -8,11 +8,15 @@
 import android.content.Context
 import android.graphics.ImageDecoder
 import android.util.AttributeSet
+import android.view.ViewGroup
 import android.widget.FrameLayout
 import android.widget.ImageButton
 import android.widget.ImageView
 import android.widget.TextView
+import androidx.core.view.ViewCompat
+import androidx.core.view.WindowInsetsCompat
 import androidx.core.view.isVisible
+import androidx.core.view.updateLayoutParams
 import androidx.media3.common.MediaItem
 import androidx.media3.common.MediaMetadata
 import com.google.android.material.card.MaterialCardView
@@ -33,9 +37,45 @@
     private val thumbnailImageView by lazy { findViewById<ImageView>(R.id.thumbnailImageView) }
     private val titleTextView by lazy { findViewById<TextView>(R.id.titleTextView) }
 
+    private var isBottomNavigationBar = false
+
     init {
         inflate(context, R.layout.now_playing_bar, this)
 
+        context.obtainStyledAttributes(attrs, R.styleable.NowPlayingBar, 0, 0).apply {
+            try {
+                isBottomNavigationBar = getBoolean(
+                    R.styleable.NowPlayingBar_isBottomNavigationBar,
+                    false
+                )
+            } finally {
+                recycle()
+            }
+        }
+
+        ViewCompat.setOnApplyWindowInsetsListener(this) { _, windowInsets ->
+            val insets = windowInsets.getInsets(
+                WindowInsetsCompat.Type.systemBars() or WindowInsetsCompat.Type.displayCutout()
+            )
+
+            updateLayoutParams<MarginLayoutParams> {
+                leftMargin = insets.left
+                rightMargin = insets.right
+            }
+
+            materialCardView.setContentPadding(
+                0,
+                0,
+                0,
+                when (isBottomNavigationBar) {
+                    true -> insets.bottom
+                    false -> 0
+                }
+            )
+
+            windowInsets
+        }
+
         circularProgressIndicator.min = 0
     }
 
diff --git a/app/src/main/res/layout-land/fragment_main.xml b/app/src/main/res/layout-land/fragment_main.xml
new file mode 100644
index 0000000..72bc605
--- /dev/null
+++ b/app/src/main/res/layout-land/fragment_main.xml
@@ -0,0 +1,72 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     SPDX-FileCopyrightText: 2024 The LineageOS Project
+     SPDX-License-Identifier: Apache-2.0
+-->
+<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:layout_width="match_parent"
+    android:layout_height="match_parent">
+
+    <com.google.android.material.appbar.AppBarLayout
+        android:id="@+id/appBarLayout"
+        android:layout_width="0dp"
+        android:layout_height="wrap_content"
+        android:fitsSystemWindows="true"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="@+id/viewPager2"
+        app:layout_constraintTop_toTopOf="parent">
+
+        <com.google.android.material.appbar.MaterialToolbar
+            android:id="@+id/toolbar"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            tools:title="@string/app_name">
+
+            <com.google.android.material.button.MaterialButton
+                android:id="@+id/providerMaterialButton"
+                style="@style/Widget.Material3.Button.TextButton"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_gravity="end"
+                android:layout_marginHorizontal="16dp"
+                tools:icon="@drawable/ic_shelves"
+                tools:text="Pixel 7 Pro" />
+
+        </com.google.android.material.appbar.MaterialToolbar>
+
+    </com.google.android.material.appbar.AppBarLayout>
+
+    <androidx.viewpager2.widget.ViewPager2
+        android:id="@+id/viewPager2"
+        android:layout_width="0dp"
+        android:layout_height="0dp"
+        app:layout_constraintBottom_toTopOf="@+id/nowPlayingBar"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toEndOf="@+id/navigationBarView"
+        app:layout_constraintTop_toBottomOf="@+id/appBarLayout" />
+
+    <org.lineageos.twelve.ui.views.NowPlayingBar
+        android:id="@+id/nowPlayingBar"
+        android:layout_width="0dp"
+        android:layout_height="wrap_content"
+        android:paddingHorizontal="24dp"
+        app:isBottomNavigationBar="true"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="parent" />
+
+    <com.google.android.material.navigationrail.NavigationRailView
+        android:id="@+id/navigationBarView"
+        android:layout_width="wrap_content"
+        android:layout_height="0dp"
+        app:layout_constraintBottom_toTopOf="@+id/nowPlayingBar"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toTopOf="parent"
+        app:menu="@menu/navigation_bar_view_fragment_main"
+        app:menuGravity="top"
+        app:paddingBottomSystemWindowInsets="false"
+        app:paddingTopSystemWindowInsets="false" />
+
+</androidx.constraintlayout.widget.ConstraintLayout>
diff --git a/app/src/main/res/layout/fragment_main.xml b/app/src/main/res/layout/fragment_main.xml
index f768670..f5bfa8e 100644
--- a/app/src/main/res/layout/fragment_main.xml
+++ b/app/src/main/res/layout/fragment_main.xml
@@ -22,7 +22,7 @@
             android:id="@+id/toolbar"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
-            tools:title="@string/app_name" >
+            tools:title="@string/app_name">
 
             <com.google.android.material.button.MaterialButton
                 android:id="@+id/providerMaterialButton"
@@ -52,17 +52,17 @@
         android:layout_width="0dp"
         android:layout_height="wrap_content"
         android:visibility="gone"
-        app:layout_constraintBottom_toTopOf="@+id/bottomNavigationView"
+        app:layout_constraintBottom_toTopOf="@+id/navigationBarView"
         app:layout_constraintEnd_toEndOf="parent"
         app:layout_constraintStart_toStartOf="parent" />
 
     <com.google.android.material.bottomnavigation.BottomNavigationView
-        android:id="@+id/bottomNavigationView"
+        android:id="@+id/navigationBarView"
         android:layout_width="0dp"
         android:layout_height="wrap_content"
         app:layout_constraintBottom_toBottomOf="parent"
         app:layout_constraintEnd_toEndOf="parent"
         app:layout_constraintStart_toStartOf="parent"
-        app:menu="@menu/bottom_navigation_view_fragment_main" />
+        app:menu="@menu/navigation_bar_view_fragment_main" />
 
 </androidx.constraintlayout.widget.ConstraintLayout>
diff --git a/app/src/main/res/menu/bottom_navigation_view_fragment_main.xml b/app/src/main/res/menu/navigation_bar_view_fragment_main.xml
similarity index 100%
rename from app/src/main/res/menu/bottom_navigation_view_fragment_main.xml
rename to app/src/main/res/menu/navigation_bar_view_fragment_main.xml
diff --git a/app/src/main/res/values/attrs_NowPlayingBar.xml b/app/src/main/res/values/attrs_NowPlayingBar.xml
new file mode 100644
index 0000000..4eed890
--- /dev/null
+++ b/app/src/main/res/values/attrs_NowPlayingBar.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     SPDX-FileCopyrightText: 2024 The LineageOS Project
+     SPDX-License-Identifier: Apache-2.0
+-->
+<resources>
+    <declare-styleable name="NowPlayingBar">
+        <attr name="isBottomNavigationBar" format="boolean" />
+    </declare-styleable>
+</resources>