Bimba.git

commit a4d42896f5a3c0087b0fd129e8a304cdc5585637

Author: Adam Evyčędo <git@apiote.xyz>

fix edge-to-edge on all screens

%!v(PANIC=String method: strings: negative Repeat count)


diff --git a/app/src/main/java/xyz/apiote/bimba/czwek/AboutActivity.kt b/app/src/main/java/xyz/apiote/bimba/czwek/AboutActivity.kt
index 836b721962f4c3a6f6056cffb95c1897a5d31ca6..cee5e4e154d8391de4925ee64a6afa39e1afce80 100644
--- a/app/src/main/java/xyz/apiote/bimba/czwek/AboutActivity.kt
+++ b/app/src/main/java/xyz/apiote/bimba/czwek/AboutActivity.kt
@@ -7,29 +7,49 @@
 import android.content.Intent
 import android.net.Uri
 import android.os.Bundle
+import androidx.activity.enableEdgeToEdge
 import androidx.appcompat.app.AppCompatActivity
+import androidx.core.view.ViewCompat
+import androidx.core.view.WindowInsetsCompat
+import androidx.core.view.updatePadding
 import xyz.apiote.bimba.czwek.databinding.ActivityAboutBinding
+import kotlin.math.max
 
 
 class AboutActivity : AppCompatActivity() {
-    private var _binding: ActivityAboutBinding? = null
-    private val binding get() = _binding!!
-    override fun onCreate(savedInstanceState: Bundle?) {
-        super.onCreate(savedInstanceState)
-        _binding = ActivityAboutBinding.inflate(layoutInflater)
-        setContentView(binding.root)
+	private var _binding: ActivityAboutBinding? = null
+	private val binding get() = _binding!!
+	override fun onCreate(savedInstanceState: Bundle?) {
+		enableEdgeToEdge()
+		super.onCreate(savedInstanceState)
+		_binding = ActivityAboutBinding.inflate(layoutInflater)
+		setContentView(binding.root)
 
-        binding.mastodon.setOnClickListener {
-            startActivity(Intent(Intent.ACTION_VIEW, Uri.parse("https://floss.social/@bimba")))
-        }
-        binding.website.setOnClickListener {
-            startActivity(Intent(Intent.ACTION_VIEW, Uri.parse("https://bimba.apiote.xyz")))
-        }
-        binding.code.setOnClickListener {
-            startActivity(Intent(Intent.ACTION_VIEW, Uri.parse("https://git.apiote.xyz/Bimba.git")))
-        }
-        binding.translate.setOnClickListener {
-            startActivity(Intent(Intent.ACTION_VIEW, Uri.parse("https://hosted.weblate.org/projects/bimba/")))
-        }
-    }
+		ViewCompat.setOnApplyWindowInsetsListener(binding.root) { v, windowInsets ->
+			val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
+			val l = max(windowInsets.displayCutout?.safeInsetLeft ?: 0, insets.left)
+			val r = max(windowInsets.displayCutout?.safeInsetRight ?: 0, insets.right)
+			val t = max(windowInsets.displayCutout?.safeInsetTop ?: 0, insets.top)
+			v.updatePadding(left = l, right = r, top = t)
+			windowInsets
+		}
+
+		binding.mastodon.setOnClickListener {
+			startActivity(Intent(Intent.ACTION_VIEW, Uri.parse("https://floss.social/@bimba")))
+		}
+		binding.website.setOnClickListener {
+			startActivity(Intent(Intent.ACTION_VIEW, Uri.parse("https://bimba.apiote.xyz")))
+		}
+		binding.code.setOnClickListener {
+			startActivity(Intent(Intent.ACTION_VIEW, Uri.parse("https://git.apiote.xyz/Bimba.git")))
+		}
+		binding.translate.setOnClickListener {
+			startActivity(
+				Intent(
+					Intent.ACTION_VIEW,
+					Uri.parse("https://hosted.weblate.org/projects/bimba/")
+				)
+			)
+		}
+	}
 }




diff --git a/app/src/main/java/xyz/apiote/bimba/czwek/dashboard/MainActivity.kt b/app/src/main/java/xyz/apiote/bimba/czwek/dashboard/MainActivity.kt
index 090e870cac6a76658ce555f4a8e7a0eac3f98355..e984a11476a6821e66bd4cc898785c56136f6b80 100644
--- a/app/src/main/java/xyz/apiote/bimba/czwek/dashboard/MainActivity.kt
+++ b/app/src/main/java/xyz/apiote/bimba/czwek/dashboard/MainActivity.kt
@@ -11,14 +11,17 @@ import android.os.Bundle
 import android.view.View
 import android.widget.Toast
 import androidx.activity.OnBackPressedCallback
+import androidx.activity.enableEdgeToEdge
 import androidx.activity.result.ActivityResultLauncher
 import androidx.activity.result.contract.ActivityResultContracts
 import androidx.appcompat.app.AppCompatActivity
 import androidx.appcompat.content.res.AppCompatResources
 import androidx.core.content.ContextCompat
 import androidx.core.content.edit
-import androidx.core.view.WindowCompat
+import androidx.core.view.ViewCompat
+import androidx.core.view.WindowInsetsCompat
 import androidx.core.view.get
+import androidx.core.view.updatePadding
 import androidx.drawerlayout.widget.DrawerLayout.DrawerListener
 import androidx.fragment.app.Fragment
 import androidx.fragment.app.FragmentManager
@@ -47,12 +50,20 @@ 	private lateinit var permissionAsker: Fragment
 	private var locationPermissionDialogShown = false
 
 	override fun onCreate(savedInstanceState: Bundle?) {
+		enableEdgeToEdge()
 		super.onCreate(savedInstanceState)
 		binding = ActivityMainBinding.inflate(layoutInflater)
 		setContentView(binding.root)
 
 		getSharedPreferences("shp", MODE_PRIVATE).edit(true) {
 			putBoolean("firstRun", false)
+		}
+
+		ViewCompat.setOnApplyWindowInsetsListener(binding.root) { _, windowInsets ->
+			val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
+			val l = windowInsets.displayCutout?.safeInsetLeft?.takeIf { it > 0 } ?: insets.left
+			binding.navigationDrawer.updatePadding(left = l)
+			windowInsets
 		}
 
 		supportFragmentManager.registerFragmentLifecycleCallbacks(
@@ -105,7 +116,6 @@ 			}
 			false
 		}
 
-		WindowCompat.setDecorFitsSystemWindows(window, false)
 		val navView: BottomNavigationView = binding.bottomNavigation
 		val navHostFragment =
 			supportFragmentManager.findFragmentById(R.id.nav_host_fragment_activity_main) as NavHostFragment
@@ -117,7 +127,7 @@ 			ActivityResultContracts.RequestMultiplePermissions()
 		) { permissions ->
 			when {
 				permissions[Manifest.permission.ACCESS_FINE_LOCATION] ?: false ||
-								permissions[Manifest.permission.ACCESS_COARSE_LOCATION] ?: false -> {
+					permissions[Manifest.permission.ACCESS_COARSE_LOCATION] ?: false -> {
 					when (permissionAsker) {
 						is HomeFragment -> {
 							showResults(ResultsActivity.Mode.MODE_LOCATION)
@@ -133,10 +143,15 @@ 				else -> {
 					if (locationPermissionDialogShown) {
 						return@registerForActivityResult
 					}
-					MaterialAlertDialogBuilder(this).setIcon(AppCompatResources.getDrawable(this, R.drawable.error_gps))
+					MaterialAlertDialogBuilder(this).setIcon(
+						AppCompatResources.getDrawable(
+							this,
+							R.drawable.error_gps
+						)
+					)
 						.setTitle(getString(R.string.no_location_access))
 						.setMessage(getString(R.string.no_location_message))
-						.setPositiveButton(resources.getString(R.string.ok)) { _, _ ->}
+						.setPositiveButton(resources.getString(R.string.ok)) { _, _ -> }
 						.show()
 					locationPermissionDialogShown = true
 				}




diff --git a/app/src/main/java/xyz/apiote/bimba/czwek/dashboard/ui/home/HomeFragment.kt b/app/src/main/java/xyz/apiote/bimba/czwek/dashboard/ui/home/HomeFragment.kt
index 937651e34f7d64ab76dc0caeecf9ae19f23374ce..3089cee929f485486c900ebe1234828452685a44 100644
--- a/app/src/main/java/xyz/apiote/bimba/czwek/dashboard/ui/home/HomeFragment.kt
+++ b/app/src/main/java/xyz/apiote/bimba/czwek/dashboard/ui/home/HomeFragment.kt
@@ -9,17 +9,19 @@ import android.view.KeyEvent
 import android.view.LayoutInflater
 import android.view.View
 import android.view.ViewGroup
-import android.widget.FrameLayout
 import android.widget.TextView
 import androidx.activity.OnBackPressedCallback
 import androidx.core.view.ViewCompat
 import androidx.core.view.WindowInsetsCompat
+import androidx.core.view.updateLayoutParams
+import androidx.core.view.updatePadding
 import androidx.fragment.app.Fragment
 import androidx.lifecycle.ViewModelProvider
 import androidx.recyclerview.widget.LinearLayoutManager
 import com.google.android.material.search.SearchView
 import xyz.apiote.bimba.czwek.dashboard.MainActivity
 import xyz.apiote.bimba.czwek.databinding.FragmentHomeBinding
+import xyz.apiote.bimba.czwek.dpToPixelI
 import xyz.apiote.bimba.czwek.search.BimbaResultsAdapter
 
 class HomeFragment : Fragment() {
@@ -41,15 +43,6 @@ 		homeViewModel.queryables.observe(viewLifecycleOwner) {
 			adapter.feedsSettings = homeViewModel.feedsSettings
 			adapter.feeds = homeViewModel.feeds
 			adapter.update(it)
-		}
-
-		val root = binding.root
-		ViewCompat.setOnApplyWindowInsetsListener(root) { view, windowInsets ->
-			val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
-			view.layoutParams = (view.layoutParams as FrameLayout.LayoutParams).apply {
-				topMargin = insets.top
-			}
-			WindowInsetsCompat.CONSUMED
 		}
 
 		val onBackPressedCallback = object :
@@ -94,6 +87,25 @@ 		}
 
 		binding.floatingActionButton.setOnClickListener {
 			(context as MainActivity).onGpsClicked(this)
+		}
+
+		ViewCompat.setOnApplyWindowInsetsListener(binding.root) { _, windowInsets ->
+			val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
+			binding.floatingActionButton.updateLayoutParams<ViewGroup.MarginLayoutParams> {
+				rightMargin = insets.right + dpToPixelI(16f)
+			}
+			binding.searchBar.updateLayoutParams<ViewGroup.MarginLayoutParams> {
+				rightMargin = insets.right + dpToPixelI(8f)
+				leftMargin = insets.left + dpToPixelI(8f)
+				topMargin = insets.top + dpToPixelI(8f)
+			}
+			binding.suggestionsRecycler.updatePadding(left = insets.left, right = insets.right)
+			windowInsets.displayCutout?.safeInsetLeft?.let {
+				binding.suggestionsRecycler.updateLayoutParams<ViewGroup.MarginLayoutParams> {
+					leftMargin = it
+				}
+			}
+			windowInsets
 		}
 
 		return binding.root




diff --git a/app/src/main/java/xyz/apiote/bimba/czwek/dashboard/ui/map/MapFragment.kt b/app/src/main/java/xyz/apiote/bimba/czwek/dashboard/ui/map/MapFragment.kt
index 5ac3de0f96d50708abd7e8c71f2e31aaaa772966..5de90c71a88961a4d3bfaab1a44276da62cd189c 100644
--- a/app/src/main/java/xyz/apiote/bimba/czwek/dashboard/ui/map/MapFragment.kt
+++ b/app/src/main/java/xyz/apiote/bimba/czwek/dashboard/ui/map/MapFragment.kt
@@ -16,7 +16,6 @@ import android.os.Handler
 import android.os.Looper
 import android.text.Html
 import android.text.method.LinkMovementMethod
-import android.util.Log
 import android.view.Gravity
 import android.view.LayoutInflater
 import android.view.View
@@ -27,6 +26,9 @@ import androidx.appcompat.content.res.AppCompatResources
 import androidx.coordinatorlayout.widget.CoordinatorLayout
 import androidx.core.content.edit
 import androidx.core.graphics.drawable.toBitmap
+import androidx.core.view.ViewCompat
+import androidx.core.view.WindowInsetsCompat
+import androidx.core.view.updateLayoutParams
 import androidx.fragment.app.Fragment
 import androidx.lifecycle.ViewModelProvider
 import com.google.android.material.snackbar.Snackbar
@@ -145,12 +147,22 @@ 			layoutParams
 		)
 		attributionOverlay.bringToFront()
 
+		ViewCompat.setOnApplyWindowInsetsListener(binding.root) { _, windowInsets ->
+			val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
+			binding.floatingActionButton.updateLayoutParams<ViewGroup.MarginLayoutParams> {
+				rightMargin += insets.right
+			}
+			attributionOverlay.updateLayoutParams<ViewGroup.MarginLayoutParams> {
+				rightMargin += insets.right
+			}
+			windowInsets
+		}
+
 		return root
 	}
 
 	private fun onMapMove() {
 		snack?.dismiss()
-		Log.i("ZOOM", "${binding.map.zoomLevelDouble}")
 		delayGetLocatables()
 	}
 
@@ -263,9 +275,9 @@ 		locationOverlay.disableMyLocation()
 		val centre = binding.map.mapCenter
 		context?.let { ctx ->
 			ctx.getSharedPreferences("shp", MODE_PRIVATE).edit(true) {
-				this.putFloat("mapCentreLat", centre.latitude.toFloat())
-				this.putFloat("mapCentreLon", centre.longitude.toFloat())
-				this.putFloat("mapZoom", binding.map.zoomLevelDouble.toFloat())
+				putFloat("mapCentreLat", centre.latitude.toFloat())
+				putFloat("mapCentreLon", centre.longitude.toFloat())
+				putFloat("mapZoom", binding.map.zoomLevelDouble.toFloat())
 			}
 		}
 		handler.removeCallbacks(workRunnable)




diff --git a/app/src/main/java/xyz/apiote/bimba/czwek/departures/Departures.kt b/app/src/main/java/xyz/apiote/bimba/czwek/departures/Departures.kt
index 498c142721249c64f9bc154b7c78a7e3b5760618..c4e0c76fc338134ce0c4aebe9abef6fbfb0a5b26 100644
--- a/app/src/main/java/xyz/apiote/bimba/czwek/departures/Departures.kt
+++ b/app/src/main/java/xyz/apiote/bimba/czwek/departures/Departures.kt
@@ -257,7 +257,7 @@ 	}
 
 	fun update(departure: Departure) {
 		this.departure = departure
-		this.view?.let { context?.let { ctx -> setContent(it, ctx, true) } }
+		view?.let { context?.let { ctx -> setContent(it, ctx, true) } }
 	}
 
 	private fun setContent(view: View, ctx: Context, updating: Boolean = false) {




diff --git a/app/src/main/java/xyz/apiote/bimba/czwek/departures/DeparturesActivity.kt b/app/src/main/java/xyz/apiote/bimba/czwek/departures/DeparturesActivity.kt
index be0393f6b640339f4117d8582a6f3826c5027550..a84d76aaee54c1de7f43a086a45b106a46c7ea7e 100644
--- a/app/src/main/java/xyz/apiote/bimba/czwek/departures/DeparturesActivity.kt
+++ b/app/src/main/java/xyz/apiote/bimba/czwek/departures/DeparturesActivity.kt
@@ -63,7 +63,6 @@ 	private var timePickerStart: MaterialTimePicker? = null
 	private var timePickerEnd: MaterialTimePicker? = null
 	private var linePicker: MaterialAlertDialogBuilder? = null
 	private val linesFilterTemporary = mutableMapOf<String, Boolean>()
-	private var alertDescriptions: String = ""
 
 	// TODO [elizabeth] millisInFuture from header Cache-Control max-age
 	private val countdown =
@@ -84,8 +83,9 @@ 		super.onCreate(savedInstanceState)
 		_binding = ActivityDeparturesBinding.inflate(layoutInflater)
 		setContentView(binding.root)
 
-		// TODO camera inset
 		ViewCompat.setOnApplyWindowInsetsListener(binding.departuresRecycler) { v, windowInsets ->
+			windowInsets.displayCutout?.safeInsetRight?.let { v.updatePadding(right = it) }
+			windowInsets.displayCutout?.safeInsetLeft?.let { v.updatePadding(left = it) }
 			val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
 			v.updatePadding(bottom = insets.bottom)
 			WindowInsetsCompat.CONSUMED




diff --git a/app/src/main/java/xyz/apiote/bimba/czwek/onboarding/OnboardingActivity.kt b/app/src/main/java/xyz/apiote/bimba/czwek/onboarding/OnboardingActivity.kt
index 4656071ec4e4d07508c2520557cbbdd9d46e7604..7833875ef94ce6fe166c7f4536871d0827d49e19 100644
--- a/app/src/main/java/xyz/apiote/bimba/czwek/onboarding/OnboardingActivity.kt
+++ b/app/src/main/java/xyz/apiote/bimba/czwek/onboarding/OnboardingActivity.kt
@@ -12,8 +12,12 @@ import android.text.SpannableStringBuilder
 import android.text.style.RelativeSizeSpan
 import android.text.style.StyleSpan
 import android.widget.Button
+import androidx.activity.enableEdgeToEdge
 import androidx.activity.result.contract.ActivityResultContracts
 import androidx.appcompat.app.AppCompatActivity
+import androidx.core.view.ViewCompat
+import androidx.core.view.WindowInsetsCompat
+import androidx.core.view.updatePadding
 import xyz.apiote.bimba.czwek.R
 import xyz.apiote.bimba.czwek.databinding.ActivityOnboardingBinding
 import xyz.apiote.bimba.czwek.settings.ServerChooserActivity
@@ -30,10 +34,16 @@ 			}
 		}
 
 	override fun onCreate(savedInstanceState: Bundle?) {
+		enableEdgeToEdge()
 		super.onCreate(savedInstanceState)
 		_binding = ActivityOnboardingBinding.inflate(layoutInflater)
 		setContentView(binding.root)
 
+		ViewCompat.setOnApplyWindowInsetsListener(binding.root) { v, windowInsets ->
+			val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
+			v.updatePadding(right = insets.right, left = insets.left, bottom = insets.bottom)
+			windowInsets
+		}
 
 		prepareButton(
 			binding.buttonSimple,




diff --git a/app/src/main/java/xyz/apiote/bimba/czwek/search/LineGraphActivity.kt b/app/src/main/java/xyz/apiote/bimba/czwek/search/LineGraphActivity.kt
index 128a2199a685110c6bfd442bf81ed6509cbda12f..280697cf61759672e9809e22babc5fda4b001137 100644
--- a/app/src/main/java/xyz/apiote/bimba/czwek/search/LineGraphActivity.kt
+++ b/app/src/main/java/xyz/apiote/bimba/czwek/search/LineGraphActivity.kt
@@ -7,8 +7,12 @@
 import android.os.Bundle
 import android.util.Log
 import android.view.View
+import androidx.activity.enableEdgeToEdge
 import androidx.appcompat.app.AppCompatActivity
 import androidx.appcompat.content.res.AppCompatResources
+import androidx.core.view.ViewCompat
+import androidx.core.view.WindowInsetsCompat
+import androidx.core.view.updatePadding
 import androidx.viewpager.widget.ViewPager
 import com.google.android.material.tabs.TabLayout
 import kotlinx.coroutines.MainScope
@@ -24,10 +28,17 @@ 	private lateinit var binding: ActivityLineGraphBinding
 	private lateinit var sectionsPagerAdapter: SectionsPagerAdapter
 
 	override fun onCreate(savedInstanceState: Bundle?) {
+		enableEdgeToEdge()
 		super.onCreate(savedInstanceState)
 
 		binding = ActivityLineGraphBinding.inflate(layoutInflater)
 		setContentView(binding.root)
+
+		ViewCompat.setOnApplyWindowInsetsListener(binding.root) { v, windowInsets ->
+			val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
+			v.updatePadding(top = insets.top, left = insets.left, right = insets.right)
+			windowInsets
+		}
 
 		val lineName = intent.getStringExtra("lineName")!!
 		val lineID = intent.getStringExtra("lineID")!!




diff --git a/app/src/main/java/xyz/apiote/bimba/czwek/search/ResultsActivity.kt b/app/src/main/java/xyz/apiote/bimba/czwek/search/ResultsActivity.kt
index 95054348f2de4faf524e27245737e784f1222b45..fe83369df4782fe86f711d835f11bc427d3d9bae 100644
--- a/app/src/main/java/xyz/apiote/bimba/czwek/search/ResultsActivity.kt
+++ b/app/src/main/java/xyz/apiote/bimba/czwek/search/ResultsActivity.kt
@@ -14,9 +14,14 @@ import android.os.Handler
 import android.os.Looper
 import android.util.Log
 import android.view.View
+import android.view.ViewGroup.MarginLayoutParams
+import androidx.activity.enableEdgeToEdge
 import androidx.appcompat.app.AppCompatActivity
 import androidx.appcompat.content.res.AppCompatResources
-import androidx.core.view.WindowCompat
+import androidx.core.view.ViewCompat
+import androidx.core.view.WindowInsetsCompat
+import androidx.core.view.updateLayoutParams
+import androidx.core.view.updatePadding
 import androidx.recyclerview.widget.LinearLayoutManager
 import kotlinx.coroutines.MainScope
 import kotlinx.coroutines.Runnable
@@ -45,18 +50,31 @@ 	private val handler = Handler(Looper.getMainLooper())
 	private var runnable = Runnable {}
 
 	override fun onCreate(savedInstanceState: Bundle?) {
+		enableEdgeToEdge()
 		super.onCreate(savedInstanceState)
 		_binding = ActivityResultsBinding.inflate(layoutInflater)
 		setContentView(binding.root)
 
+		ViewCompat.setOnApplyWindowInsetsListener(binding.resultsRecycler) { v, windowInsets ->
+
+			windowInsets.displayCutout?.safeInsetLeft?.let {
+				v.updateLayoutParams<MarginLayoutParams> {
+					leftMargin = it
+				}
+			}
+			val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
+			v.updatePadding(right = insets.right, left = insets.left)
+			windowInsets
+		}
+		ViewCompat.setOnApplyWindowInsetsListener(binding.topAppBar) { v, windowInsets ->
+			val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
+			v.updatePadding(right = insets.right, left = insets.left)
+			windowInsets
+		}
+
 		binding.resultsRecycler.layoutManager = LinearLayoutManager(this)
 		adapter = BimbaResultsAdapter(layoutInflater, this, listOf())
 		binding.resultsRecycler.adapter = adapter
-		setSupportActionBar(binding.topAppBar)
-
-		WindowCompat.setDecorFitsSystemWindows(window, false)
-
-
 
 		when (getMode()) {
 			Mode.MODE_LOCATION -> {




diff --git a/app/src/main/java/xyz/apiote/bimba/czwek/search/ui/LineGraphFragment.kt b/app/src/main/java/xyz/apiote/bimba/czwek/search/ui/LineGraphFragment.kt
index 84c6285e11884e3a4ff364dbe0b27f128f519785..ffb32d9486fbf7056c3629add6fdf2d58550898e 100644
--- a/app/src/main/java/xyz/apiote/bimba/czwek/search/ui/LineGraphFragment.kt
+++ b/app/src/main/java/xyz/apiote/bimba/czwek/search/ui/LineGraphFragment.kt
@@ -14,6 +14,9 @@ import android.os.Bundle
 import android.view.LayoutInflater
 import android.view.View
 import android.view.ViewGroup
+import androidx.core.view.ViewCompat
+import androidx.core.view.WindowInsetsCompat
+import androidx.core.view.updatePadding
 import androidx.fragment.app.Fragment
 import androidx.lifecycle.ViewModelProvider
 import dev.bandb.graphview.AbstractGraphAdapter
@@ -51,6 +54,12 @@ 		inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
 	): View {
 
 		_binding = FragmentLineGraphBinding.inflate(inflater, container, false)
+
+		ViewCompat.setOnApplyWindowInsetsListener(binding.recycler) { v, windowInsets ->
+			val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
+			v.updatePadding(right = insets.right, left = insets.left, top = insets.top, bottom = insets.bottom)
+			windowInsets
+		}
 
 		val configuration = SugiyamaConfiguration.Builder()
 			.setLevelSeparation(100)




diff --git a/app/src/main/java/xyz/apiote/bimba/czwek/settings/ServerChooserActivity.kt b/app/src/main/java/xyz/apiote/bimba/czwek/settings/ServerChooserActivity.kt
index 2780cb83d4dea6903fe6a720c6ad8c95622ddc0b..ce3a7df9ef1132e3a0770d837b341475da295535 100644
--- a/app/src/main/java/xyz/apiote/bimba/czwek/settings/ServerChooserActivity.kt
+++ b/app/src/main/java/xyz/apiote/bimba/czwek/settings/ServerChooserActivity.kt
@@ -11,10 +11,14 @@ import android.graphics.Color
 import android.net.ConnectivityManager
 import android.os.Bundle
 import android.util.Log
+import androidx.activity.enableEdgeToEdge
 import androidx.activity.result.contract.ActivityResultContracts
 import androidx.appcompat.app.AppCompatActivity
 import androidx.appcompat.content.res.AppCompatResources
 import androidx.core.content.edit
+import androidx.core.view.ViewCompat
+import androidx.core.view.WindowInsetsCompat
+import androidx.core.view.updatePadding
 import androidx.core.widget.addTextChangedListener
 import com.google.android.material.dialog.MaterialAlertDialogBuilder
 import kotlinx.coroutines.Dispatchers
@@ -44,7 +48,9 @@
 	private lateinit var preferences: SharedPreferences
 
 	override fun onCreate(savedInstanceState: Bundle?) {
+		enableEdgeToEdge()
 		super.onCreate(savedInstanceState)
+
 		preferences = getSharedPreferences("shp", MODE_PRIVATE)
 
 		if (intent.getBooleanExtra("simple", false)) {
@@ -53,6 +59,12 @@ 			checkServer(true)
 		} else {
 			_binding = ActivityServerChooserBinding.inflate(layoutInflater)
 			setContentView(binding.root)
+
+			ViewCompat.setOnApplyWindowInsetsListener(binding.root) { v, windowInsets ->
+				val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
+				v.updatePadding(right = insets.right, left = insets.left, top = insets.top)
+				windowInsets
+			}
 
 			preferences.edit(true) {
 				putBoolean("inFeedsTransaction", true)




diff --git a/app/src/main/java/xyz/apiote/bimba/czwek/settings/feeds/FeedChooserActivity.kt b/app/src/main/java/xyz/apiote/bimba/czwek/settings/feeds/FeedChooserActivity.kt
index c01d13f54ea0addd2b246d3d070d96aac3aed5f0..09f4dd40f4c2eca59f1f092a66042214f88f14a6 100644
--- a/app/src/main/java/xyz/apiote/bimba/czwek/settings/feeds/FeedChooserActivity.kt
+++ b/app/src/main/java/xyz/apiote/bimba/czwek/settings/feeds/FeedChooserActivity.kt
@@ -7,9 +7,13 @@
 import android.content.Intent
 import android.os.Bundle
 import android.view.View
+import androidx.activity.enableEdgeToEdge
 import androidx.appcompat.app.AppCompatActivity
 import androidx.appcompat.content.res.AppCompatResources
 import androidx.core.content.edit
+import androidx.core.view.ViewCompat
+import androidx.core.view.WindowInsetsCompat
+import androidx.core.view.updatePadding
 import androidx.core.widget.doAfterTextChanged
 import androidx.lifecycle.ViewModelProvider
 import androidx.recyclerview.widget.LinearLayoutManager
@@ -32,9 +36,23 @@
 	private lateinit var adapter: BimbaFeedInfoAdapter
 
 	override fun onCreate(savedInstanceState: Bundle?) {
+		enableEdgeToEdge()
 		super.onCreate(savedInstanceState)
 		_binding = ActivityFeedChooserBinding.inflate(layoutInflater)
 		setContentView(binding.root)
+
+		ViewCompat.setOnApplyWindowInsetsListener(binding.root) { v, windowInsets ->
+			windowInsets.displayCutout?.safeInsetRight?.let { binding.resultsRecycler.updatePadding(right = it) }
+			windowInsets.displayCutout?.safeInsetLeft?.let { binding.resultsRecycler.updatePadding(left = it) }
+			val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
+			v.updatePadding(
+				right = insets.right,
+				left = insets.left,
+				top = insets.top,
+				bottom = insets.bottom
+			)
+			windowInsets
+		}
 
 		viewModel = ViewModelProvider(this)[FeedsViewModel::class.java]
 




diff --git a/app/src/main/res/layout/activity_results.xml b/app/src/main/res/layout/activity_results.xml
index c4813dace5058c3fffcf5bb325f8ddd75ba24e33..92b758af8e0a7d62e6b0a9ac97749e09f7b443a5 100644
--- a/app/src/main/res/layout/activity_results.xml
+++ b/app/src/main/res/layout/activity_results.xml
@@ -13,6 +13,20 @@ 	android:layout_width="match_parent"
 	android:layout_height="match_parent"
 	android:paddingBottom="16dp">
 
+	<com.google.android.material.appbar.AppBarLayout
+		android:id="@+id/app_bar_layout"
+		android:layout_width="match_parent"
+		android:layout_height="wrap_content"
+		android:fitsSystemWindows="true">
+
+		<com.google.android.material.appbar.MaterialToolbar
+			android:id="@+id/top_app_bar"
+			android:layout_width="match_parent"
+			android:layout_height="?attr/actionBarSize"
+			app:title="@string/title_activity_results" />
+
+	</com.google.android.material.appbar.AppBarLayout>
+
 	<androidx.constraintlayout.widget.ConstraintLayout
 		android:id="@+id/results_overlay"
 		android:layout_width="match_parent"
@@ -56,20 +70,6 @@ 			app:layout_constraintTop_toBottomOf="@+id/error_image"
 			tool:text="No connection" />
 
 	</androidx.constraintlayout.widget.ConstraintLayout>
-
-	<com.google.android.material.appbar.AppBarLayout
-		android:layout_width="match_parent"
-		android:layout_height="wrap_content"
-		android:fitsSystemWindows="true"
-		app:liftOnScroll="true">
-
-		<com.google.android.material.appbar.MaterialToolbar
-			android:id="@+id/top_app_bar"
-			android:layout_width="match_parent"
-			android:layout_height="?attr/actionBarSize"
-			app:title="@string/title_activity_results" />
-
-	</com.google.android.material.appbar.AppBarLayout>
 
 	<androidx.recyclerview.widget.RecyclerView
 		android:id="@+id/results_recycler"




diff --git a/app/src/main/res/layout/fragment_home.xml b/app/src/main/res/layout/fragment_home.xml
index eb621f767365a76f5fa26f83738325eaefa828dc..d2f52f4c6ae0429875e78dcf95f6498c2d8e7ed7 100644
--- a/app/src/main/res/layout/fragment_home.xml
+++ b/app/src/main/res/layout/fragment_home.xml
@@ -77,7 +77,5 @@ 		android:layout_gravity="bottom|end"
 		android:layout_margin="16dp"
 		android:contentDescription="@string/home_fab_description"
 		android:src="@drawable/gps_black"
-		app:layout_constraintBottom_toBottomOf="parent"
-		app:layout_constraintEnd_toEndOf="parent"
 		tool:ignore="ImageContrastCheck" />
 </androidx.coordinatorlayout.widget.CoordinatorLayout>
\ No newline at end of file