Improve window insets handling

master
Koitharu 1 year ago
parent 7cec7f5359
commit 0981ba771a
Signed by: Koitharu
GPG Key ID: 676DEE768C17A9D7

@ -1,10 +1,11 @@
package org.koitharu.kotatsu.alternatives.ui
import android.os.Bundle
import android.view.Gravity
import android.view.View
import android.widget.Toast
import androidx.activity.viewModels
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.updatePadding
import coil3.ImageLoader
import dagger.hilt.android.AndroidEntryPoint
import org.koitharu.kotatsu.R
@ -15,9 +16,10 @@ import org.koitharu.kotatsu.core.ui.BaseActivity
import org.koitharu.kotatsu.core.ui.BaseListAdapter
import org.koitharu.kotatsu.core.ui.dialog.buildAlertDialog
import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener
import org.koitharu.kotatsu.core.util.ext.consumeInsetsAsPadding
import org.koitharu.kotatsu.core.util.ext.consumeAllSystemBarsInsets
import org.koitharu.kotatsu.core.util.ext.observe
import org.koitharu.kotatsu.core.util.ext.observeEvent
import org.koitharu.kotatsu.core.util.ext.systemBarsInsets
import org.koitharu.kotatsu.databinding.ActivityAlternativesBinding
import org.koitharu.kotatsu.list.ui.adapter.ListItemType
import org.koitharu.kotatsu.list.ui.adapter.TypedListSpacingDecoration
@ -50,7 +52,6 @@ class AlternativesActivity : BaseActivity<ActivityAlternativesBinding>(),
.addDelegate(ListItemType.FOOTER_LOADING, loadingFooterAD())
.addDelegate(ListItemType.STATE_LOADING, loadingStateAD())
with(viewBinding.recyclerView) {
consumeInsetsAsPadding(Gravity.START or Gravity.END or Gravity.BOTTOM)
setHasFixedSize(true)
addItemDecoration(TypedListSpacingDecoration(context, addHorizontalPadding = false))
adapter = listAdapter
@ -65,6 +66,24 @@ class AlternativesActivity : BaseActivity<ActivityAlternativesBinding>(),
}
}
override fun onApplyWindowInsets(
v: View,
insets: WindowInsetsCompat
): WindowInsetsCompat {
val barsInsets = insets.systemBarsInsets
viewBinding.recyclerView.updatePadding(
left = barsInsets.left,
right = barsInsets.right,
bottom = barsInsets.bottom,
)
viewBinding.appbar.updatePadding(
left = barsInsets.left,
right = barsInsets.right,
top = barsInsets.top,
)
return insets.consumeAllSystemBarsInsets()
}
override fun onItemClick(item: MangaAlternativeModel, view: View) {
when (view.id) {
R.id.chip_source -> router.openSearch(item.manga.source, viewModel.manga.title)

@ -1,7 +1,6 @@
package org.koitharu.kotatsu.bookmarks.ui
import android.os.Bundle
import android.view.Gravity
import android.view.LayoutInflater
import android.view.Menu
import android.view.MenuInflater
@ -10,6 +9,7 @@ import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.appcompat.view.ActionMode
import androidx.core.view.WindowInsetsCompat
import androidx.fragment.app.viewModels
import androidx.recyclerview.widget.GridLayoutManager
import coil3.ImageLoader
@ -26,10 +26,11 @@ import org.koitharu.kotatsu.core.ui.list.ListSelectionController
import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener
import org.koitharu.kotatsu.core.ui.list.fastscroll.FastScroller
import org.koitharu.kotatsu.core.ui.util.ReversibleActionObserver
import org.koitharu.kotatsu.core.util.ext.consumeInsetsAsPadding
import org.koitharu.kotatsu.core.util.ext.consumeAllSystemBarsInsets
import org.koitharu.kotatsu.core.util.ext.findAppCompatDelegate
import org.koitharu.kotatsu.core.util.ext.observe
import org.koitharu.kotatsu.core.util.ext.observeEvent
import org.koitharu.kotatsu.core.util.ext.systemBarsInsets
import org.koitharu.kotatsu.databinding.FragmentListSimpleBinding
import org.koitharu.kotatsu.list.ui.GridSpanResolver
import org.koitharu.kotatsu.list.ui.adapter.ListHeaderClickListener
@ -85,7 +86,6 @@ class AllBookmarksFragment :
)
val spanSizeLookup = SpanSizeLookup()
with(binding.recyclerView) {
consumeInsetsAsPadding(Gravity.BOTTOM or Gravity.START or Gravity.END)
setHasFixedSize(true)
val spanResolver = GridSpanResolver(resources)
addItemDecoration(TypedListSpacingDecoration(context, false))
@ -107,6 +107,18 @@ class AllBookmarksFragment :
viewModel.onActionDone.observeEvent(viewLifecycleOwner, ReversibleActionObserver(binding.recyclerView))
}
override fun onApplyWindowInsets(v: View, insets: WindowInsetsCompat): WindowInsetsCompat {
val barsInsets = insets.systemBarsInsets
val basePadding = resources.getDimensionPixelOffset(R.dimen.list_spacing_normal)
viewBinding?.recyclerView?.setPadding(
barsInsets.left + basePadding,
barsInsets.top + basePadding,
barsInsets.right + basePadding,
barsInsets.bottom + basePadding,
)
return insets.consumeAllSystemBarsInsets()
}
override fun onDestroyView() {
super.onDestroyView()
bookmarksAdapter = null

@ -1,10 +1,12 @@
package org.koitharu.kotatsu.browser
import android.os.Bundle
import android.view.Gravity
import android.view.Menu
import android.view.MenuItem
import android.view.View
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.isVisible
import androidx.core.view.updatePadding
import com.google.android.material.snackbar.Snackbar
import dagger.hilt.android.AndroidEntryPoint
import org.koitharu.kotatsu.R
@ -16,7 +18,7 @@ import org.koitharu.kotatsu.core.parser.MangaRepository
import org.koitharu.kotatsu.core.parser.ParserMangaRepository
import org.koitharu.kotatsu.core.ui.BaseActivity
import org.koitharu.kotatsu.core.util.ext.configureForParser
import org.koitharu.kotatsu.core.util.ext.consumeInsetsAsPadding
import org.koitharu.kotatsu.core.util.ext.consumeAll
import org.koitharu.kotatsu.databinding.ActivityBrowserBinding
import javax.inject.Inject
import com.google.android.material.R as materialR
@ -42,7 +44,6 @@ class BrowserActivity : BaseActivity<ActivityBrowserBinding>(), BrowserCallback
val repository = mangaRepositoryFactory.create(mangaSource) as? ParserMangaRepository
val userAgent = repository?.getRequestHeaders()?.get(CommonHeaders.USER_AGENT)
viewBinding.webView.configureForParser(userAgent)
viewBinding.webView.consumeInsetsAsPadding(Gravity.START or Gravity.END or Gravity.BOTTOM)
viewBinding.webView.webViewClient = BrowserClient(this)
viewBinding.webView.webChromeClient = ProgressChromeClient(viewBinding.progressBar)
onBackPressedCallback = WebViewBackPressedCallback(viewBinding.webView)
@ -62,6 +63,25 @@ class BrowserActivity : BaseActivity<ActivityBrowserBinding>(), BrowserCallback
}
}
override fun onApplyWindowInsets(
v: View,
insets: WindowInsetsCompat
): WindowInsetsCompat {
val type = WindowInsetsCompat.Type.systemBars() or WindowInsetsCompat.Type.ime()
val barsInsets = insets.getInsets(type)
viewBinding.webView.updatePadding(
left = barsInsets.left,
right = barsInsets.right,
bottom = barsInsets.bottom,
)
viewBinding.appbar.updatePadding(
left = barsInsets.left,
right = barsInsets.right,
top = barsInsets.top,
)
return insets.consumeAll(type)
}
override fun onCreateOptionsMenu(menu: Menu): Boolean {
super.onCreateOptionsMenu(menu)
menuInflater.inflate(R.menu.opt_browser, menu)

@ -3,12 +3,14 @@ package org.koitharu.kotatsu.browser.cloudflare
import android.content.Context
import android.content.Intent
import android.os.Bundle
import android.view.Gravity
import android.view.Menu
import android.view.MenuItem
import android.view.View
import androidx.activity.result.contract.ActivityResultContract
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.isInvisible
import androidx.core.view.isVisible
import androidx.core.view.updatePadding
import androidx.lifecycle.lifecycleScope
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.Dispatchers
@ -25,7 +27,7 @@ import org.koitharu.kotatsu.core.nav.AppRouter
import org.koitharu.kotatsu.core.network.cookies.MutableCookieJar
import org.koitharu.kotatsu.core.ui.BaseActivity
import org.koitharu.kotatsu.core.util.ext.configureForParser
import org.koitharu.kotatsu.core.util.ext.consumeInsetsAsPadding
import org.koitharu.kotatsu.core.util.ext.consumeAll
import org.koitharu.kotatsu.databinding.ActivityBrowserBinding
import org.koitharu.kotatsu.parsers.network.CloudFlareHelper
import javax.inject.Inject
@ -58,7 +60,6 @@ class CloudFlareActivity : BaseActivity<ActivityBrowserBinding>(), CloudFlareCal
}
cfClient = CloudFlareClient(cookieJar, this, url)
viewBinding.webView.configureForParser(intent?.getStringExtra(AppRouter.KEY_USER_AGENT))
viewBinding.webView.consumeInsetsAsPadding(Gravity.START or Gravity.END or Gravity.BOTTOM)
viewBinding.webView.webViewClient = cfClient
onBackPressedCallback = WebViewBackPressedCallback(viewBinding.webView).also {
onBackPressedDispatcher.addCallback(it)
@ -69,6 +70,25 @@ class CloudFlareActivity : BaseActivity<ActivityBrowserBinding>(), CloudFlareCal
}
}
override fun onApplyWindowInsets(
v: View,
insets: WindowInsetsCompat
): WindowInsetsCompat {
val type = WindowInsetsCompat.Type.systemBars() or WindowInsetsCompat.Type.ime()
val barsInsets = insets.getInsets(type)
viewBinding.webView.updatePadding(
left = barsInsets.left,
right = barsInsets.right,
bottom = barsInsets.bottom,
)
viewBinding.appbar.updatePadding(
left = barsInsets.left,
right = barsInsets.right,
top = barsInsets.top,
)
return insets.consumeAll(type)
}
override fun onDestroy() {
runCatching {
viewBinding.webView

@ -15,6 +15,8 @@ import androidx.appcompat.app.AppCompatDelegate
import androidx.appcompat.view.ActionMode
import androidx.appcompat.widget.Toolbar
import androidx.core.app.ActivityCompat
import androidx.core.view.OnApplyWindowInsetsListener
import androidx.core.view.ViewCompat
import androidx.fragment.app.FragmentManager
import androidx.viewbinding.ViewBinding
import dagger.hilt.android.EntryPointAccessors
@ -31,6 +33,7 @@ import org.koitharu.kotatsu.main.ui.protect.ScreenshotPolicyHelper
abstract class BaseActivity<B : ViewBinding> :
AppCompatActivity(),
ExceptionResolver.Host,
OnApplyWindowInsetsListener,
ScreenshotPolicyHelper.ContentContainer {
private var isAmoledTheme = false
@ -78,16 +81,10 @@ abstract class BaseActivity<B : ViewBinding> :
}
@Deprecated("Use ViewBinding", level = DeprecationLevel.ERROR)
override fun setContentView(layoutResID: Int) {
super.setContentView(layoutResID)
setupToolbar()
}
override fun setContentView(layoutResID: Int) = throw UnsupportedOperationException()
@Deprecated("Use ViewBinding", level = DeprecationLevel.ERROR)
override fun setContentView(view: View?) {
super.setContentView(view)
setupToolbar()
}
override fun setContentView(view: View?) = throw UnsupportedOperationException()
override fun getContext() = this
@ -96,6 +93,7 @@ abstract class BaseActivity<B : ViewBinding> :
protected fun setContentView(binding: B) {
this.viewBinding = binding
super.setContentView(binding.root)
ViewCompat.setOnApplyWindowInsetsListener(binding.root, this)
val toolbar = (binding.root.findViewById<View>(R.id.toolbar) as? Toolbar)
toolbar?.let(this::setSupportActionBar)
}
@ -125,10 +123,6 @@ abstract class BaseActivity<B : ViewBinding> :
return super.onKeyDown(keyCode, event)
}
private fun setupToolbar() {
(findViewById<View>(R.id.toolbar) as? Toolbar)?.let(this::setSupportActionBar)
}
protected fun isDarkAmoledTheme(): Boolean {
val uiMode = resources.configuration.uiMode
val isNight = uiMode and Configuration.UI_MODE_NIGHT_MASK == Configuration.UI_MODE_NIGHT_YES

@ -5,6 +5,8 @@ import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.core.view.OnApplyWindowInsetsListener
import androidx.core.view.ViewCompat
import androidx.fragment.app.Fragment
import androidx.viewbinding.ViewBinding
import dagger.hilt.android.EntryPointAccessors
@ -12,6 +14,7 @@ import org.koitharu.kotatsu.core.exceptions.resolve.ExceptionResolver
import org.koitharu.kotatsu.core.ui.util.ActionModeDelegate
abstract class BaseFragment<B : ViewBinding> :
OnApplyWindowInsetsListener,
Fragment(),
ExceptionResolver.Host {
@ -42,6 +45,7 @@ abstract class BaseFragment<B : ViewBinding> :
final override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
ViewCompat.setOnApplyWindowInsetsListener(view, this)
onViewBindingCreated(requireViewBinding(), savedInstanceState)
}

@ -2,11 +2,11 @@ package org.koitharu.kotatsu.core.ui
import android.content.Context
import android.os.Bundle
import android.view.Gravity
import android.view.View
import androidx.annotation.StringRes
import androidx.core.view.ancestors
import androidx.fragment.app.FragmentContainerView
import androidx.core.view.OnApplyWindowInsetsListener
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import androidx.preference.Preference
import androidx.preference.PreferenceFragmentCompat
import androidx.preference.PreferenceScreen
@ -18,10 +18,14 @@ import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.exceptions.resolve.ExceptionResolver
import org.koitharu.kotatsu.core.prefs.AppSettings
import org.koitharu.kotatsu.core.ui.util.RecyclerViewOwner
import org.koitharu.kotatsu.core.util.ext.consumeInsetsAsPadding
import org.koitharu.kotatsu.core.util.ext.consumeAllSystemBarsInsets
import org.koitharu.kotatsu.core.util.ext.container
import org.koitharu.kotatsu.core.util.ext.end
import org.koitharu.kotatsu.core.util.ext.getThemeColor
import org.koitharu.kotatsu.core.util.ext.getThemeDrawable
import org.koitharu.kotatsu.core.util.ext.parentView
import org.koitharu.kotatsu.core.util.ext.start
import org.koitharu.kotatsu.core.util.ext.systemBarsInsets
import org.koitharu.kotatsu.settings.SettingsActivity
import javax.inject.Inject
import com.google.android.material.R as materialR
@ -29,6 +33,7 @@ import com.google.android.material.R as materialR
@AndroidEntryPoint
abstract class BasePreferenceFragment(@StringRes private val titleId: Int) :
PreferenceFragmentCompat(),
OnApplyWindowInsetsListener,
RecyclerViewOwner,
ExceptionResolver.Host {
@ -49,15 +54,23 @@ abstract class BasePreferenceFragment(@StringRes private val titleId: Int) :
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
ViewCompat.setOnApplyWindowInsetsListener(view, this)
val themedContext = (view.parentView ?: view).context
view.setBackgroundColor(themedContext.getThemeColor(android.R.attr.colorBackground))
listView.clipToPadding = false
val insetsEdges = Gravity.BOTTOM or when {
!resources.getBoolean(R.bool.is_tablet) -> Gravity.FILL_HORIZONTAL
isMaster() -> Gravity.START
else -> Gravity.END
}
listView.consumeInsetsAsPadding(insetsEdges)
}
override fun onApplyWindowInsets(v: View, insets: WindowInsetsCompat): WindowInsetsCompat {
val barsInsets = insets.systemBarsInsets
val isTablet = !resources.getBoolean(R.bool.is_tablet)
val isMaster = container?.id == R.id.container_master
listView.setPaddingRelative(
if (isTablet && !isMaster) 0 else barsInsets.start(v),
0,
if (isTablet && isMaster) 0 else barsInsets.end(v),
barsInsets.bottom,
)
return insets.consumeAllSystemBarsInsets()
}
override fun onResume() {
@ -99,9 +112,4 @@ abstract class BasePreferenceFragment(@StringRes private val titleId: Int) :
}
return -1
}
private fun isMaster(): Boolean {
val container = view?.ancestors?.firstNotNullOfOrNull { it as? FragmentContainerView } ?: return false
return container.id == R.id.container_master
}
}

@ -3,8 +3,6 @@ package org.koitharu.kotatsu.core.ui
import android.os.Bundle
import android.view.View
import androidx.coordinatorlayout.widget.CoordinatorLayout
import androidx.core.view.OnApplyWindowInsetsListener
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.updatePadding
import androidx.fragment.app.Fragment
@ -12,6 +10,7 @@ import androidx.fragment.app.commit
import com.google.android.material.appbar.AppBarLayout
import dagger.hilt.android.AndroidEntryPoint
import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.util.ext.consumeSystemBarsInsets
import org.koitharu.kotatsu.databinding.ActivityContainerBinding
import org.koitharu.kotatsu.main.ui.owners.AppBarOwner
import org.koitharu.kotatsu.main.ui.owners.SnackbarOwner
@ -19,7 +18,6 @@ import org.koitharu.kotatsu.main.ui.owners.SnackbarOwner
@AndroidEntryPoint
abstract class FragmentContainerActivity(private val fragmentClass: Class<out Fragment>) :
BaseActivity<ActivityContainerBinding>(),
OnApplyWindowInsetsListener,
AppBarOwner,
SnackbarOwner {
@ -33,7 +31,6 @@ abstract class FragmentContainerActivity(private val fragmentClass: Class<out Fr
super.onCreate(savedInstanceState)
setContentView(ActivityContainerBinding.inflate(layoutInflater))
supportActionBar?.setDisplayHomeAsUpEnabled(true)
ViewCompat.setOnApplyWindowInsetsListener(viewBinding.root, this)
val fm = supportFragmentManager
if (fm.findFragmentById(R.id.container) == null) {
fm.commit {
@ -50,7 +47,7 @@ abstract class FragmentContainerActivity(private val fragmentClass: Class<out Fr
right = bars.right,
top = bars.top,
)
return insets
return insets.consumeSystemBarsInsets(top = true)
}
protected open fun getFragmentExtras(): Bundle? = intent.extras

@ -14,6 +14,8 @@ import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.app.AppCompatDialog
import androidx.appcompat.app.AppCompatDialogFragment
import androidx.appcompat.view.ActionMode
import androidx.core.view.OnApplyWindowInsetsListener
import androidx.core.view.ViewCompat
import androidx.core.view.updateLayoutParams
import androidx.lifecycle.DefaultLifecycleObserver
import androidx.lifecycle.LifecycleOwner
@ -29,7 +31,9 @@ import org.koitharu.kotatsu.core.ui.BaseActivityEntryPoint
import org.koitharu.kotatsu.core.ui.util.ActionModeDelegate
import com.google.android.material.R as materialR
abstract class BaseAdaptiveSheet<B : ViewBinding> : AppCompatDialogFragment(), ExceptionResolver.Host {
abstract class BaseAdaptiveSheet<B : ViewBinding> : AppCompatDialogFragment(),
OnApplyWindowInsetsListener,
ExceptionResolver.Host {
private var waitingForDismissAllowingStateLoss = false
private var isFitToContentsDisabled = false
@ -74,6 +78,7 @@ abstract class BaseAdaptiveSheet<B : ViewBinding> : AppCompatDialogFragment(), E
final override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
ViewCompat.setOnApplyWindowInsetsListener(view, this)
val binding = requireViewBinding()
if (actionModeDelegate == null) {
actionModeDelegate = (activity as? BaseActivity<*>)?.actionModeDelegate

@ -1,51 +0,0 @@
package org.koitharu.kotatsu.core.ui.util
import android.view.Gravity
import android.view.View
import android.view.ViewGroup
import androidx.annotation.GravityInt
import androidx.core.graphics.Insets
import androidx.core.view.OnApplyWindowInsetsListener
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.updateLayoutParams
import org.koitharu.kotatsu.core.util.ext.consumeRelative
import org.koitharu.kotatsu.core.util.ext.end
import org.koitharu.kotatsu.core.util.ext.start
class InsetsToMarginsListener(
@GravityInt
private val sides: Int,
private val baseMargins: Insets,
) : OnApplyWindowInsetsListener {
private val insetType = WindowInsetsCompat.Type.systemBars()
override fun onApplyWindowInsets(v: View, insets: WindowInsetsCompat): WindowInsetsCompat {
val barsInsets = insets.getInsets(insetType)
v.updateLayoutParams<ViewGroup.MarginLayoutParams> {
if (sides and Gravity.START == Gravity.START) {
marginStart = barsInsets.start(v) + baseMargins.start(v)
}
if (sides and Gravity.TOP == Gravity.TOP) {
topMargin = barsInsets.top + baseMargins.top
}
if (sides and Gravity.END == Gravity.END) {
marginEnd = barsInsets.end(v) + baseMargins.end(v)
}
if (sides and Gravity.BOTTOM == Gravity.BOTTOM) {
bottomMargin = barsInsets.bottom + baseMargins.bottom
}
}
return WindowInsetsCompat.Builder(insets)
.setInsets(
insetType,
barsInsets.consumeRelative(
v,
start = sides and Gravity.START == Gravity.START,
top = sides and Gravity.TOP == Gravity.TOP,
end = sides and Gravity.END == Gravity.END,
bottom = sides and Gravity.BOTTOM == Gravity.BOTTOM,
),
).build()
}
}

@ -1,61 +0,0 @@
package org.koitharu.kotatsu.core.ui.util
import android.view.Gravity
import android.view.View
import androidx.annotation.GravityInt
import androidx.core.graphics.Insets
import androidx.core.view.OnApplyWindowInsetsListener
import androidx.core.view.WindowInsetsCompat
import org.koitharu.kotatsu.core.util.ext.consumeRelative
import org.koitharu.kotatsu.core.util.ext.end
import org.koitharu.kotatsu.core.util.ext.start
class InsetsToPaddingListener(
@GravityInt
private val sides: Int,
private val basePaddings: Insets,
) : OnApplyWindowInsetsListener {
private val insetType = WindowInsetsCompat.Type.systemBars()
override fun onApplyWindowInsets(v: View, insets: WindowInsetsCompat): WindowInsetsCompat {
val barsInsets = insets.getInsets(insetType)
v.setPaddingRelative(
/* start = */
if (sides and Gravity.START == Gravity.START) {
barsInsets.start(v) + basePaddings.start(v)
} else {
v.paddingStart
},
/* top = */
if (sides and Gravity.TOP == Gravity.TOP) {
barsInsets.top + basePaddings.top
} else {
v.paddingTop
},
/* end = */
if (sides and Gravity.END == Gravity.END) {
barsInsets.end(v) + basePaddings.end(v)
} else {
v.paddingEnd
},
/* bottom = */
if (sides and Gravity.BOTTOM == Gravity.BOTTOM) {
barsInsets.bottom + basePaddings.bottom
} else {
v.paddingBottom
},
)
return WindowInsetsCompat.Builder(insets)
.setInsets(
insetType,
barsInsets.consumeRelative(
v,
start = sides and Gravity.START == Gravity.START,
top = sides and Gravity.TOP == Gravity.TOP,
end = sides and Gravity.END == Gravity.END,
bottom = sides and Gravity.BOTTOM == Gravity.BOTTOM,
),
).build()
}
}

@ -10,6 +10,8 @@ import android.widget.LinearLayout
import androidx.annotation.AttrRes
import androidx.coordinatorlayout.widget.CoordinatorLayout
import androidx.core.view.WindowInsetsCompat
import org.koitharu.kotatsu.core.util.ext.end
import org.koitharu.kotatsu.core.util.ext.start
class WindowInsetHolder @JvmOverloads constructor(
context: Context,
@ -24,9 +26,9 @@ class WindowInsetHolder @JvmOverloads constructor(
val barsInsets = WindowInsetsCompat.toWindowInsetsCompat(insets, this)
.getInsets(WindowInsetsCompat.Type.systemBars())
val gravity = getLayoutGravity()
val newWidth = when (gravity and Gravity.HORIZONTAL_GRAVITY_MASK) {
Gravity.LEFT -> barsInsets.left
Gravity.RIGHT -> barsInsets.right
val newWidth = when (gravity and Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK) {
Gravity.START -> barsInsets.start(this)
Gravity.END -> barsInsets.end(this)
else -> 0
}
val newHeight = when (gravity and Gravity.VERTICAL_GRAVITY_MASK) {

@ -2,7 +2,9 @@ package org.koitharu.kotatsu.core.util.ext
import android.os.Bundle
import androidx.core.view.MenuProvider
import androidx.core.view.ancestors
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentContainerView
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.coroutineScope
@ -29,3 +31,8 @@ tailrec fun <T> Fragment.findParentCallback(cls: Class<T>): T? {
else -> parent.findParentCallback(cls)
}
}
val Fragment.container: FragmentContainerView?
get() = view?.ancestors?.firstNotNullOfOrNull {
it as? FragmentContainerView // TODO check if direct parent
}

@ -2,6 +2,8 @@ package org.koitharu.kotatsu.core.util.ext
import android.view.View
import androidx.core.graphics.Insets
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.WindowInsetsCompat.Type.InsetsType
fun Insets.end(view: View): Int {
return if (view.isRtl) left else right
@ -11,20 +13,69 @@ fun Insets.start(view: View): Int {
return if (view.isRtl) right else left
}
fun Insets.consume(
@Deprecated("")
val WindowInsetsCompat.systemBarsInsets: Insets
get() = getInsets(WindowInsetsCompat.Type.systemBars())
@Deprecated("")
fun WindowInsetsCompat.consumeSystemBarsInsets(
left: Boolean = false,
top: Boolean = false,
right: Boolean = false,
bottom: Boolean = false,
): Insets = Insets.of(
/* left = */ if (left) 0 else this.left,
/* top = */ if (top) 0 else this.top,
/* right = */ if (right) 0 else this.right,
/* bottom = */ if (bottom) 0 else this.bottom,
)
): WindowInsetsCompat {
val barsInsets = systemBarsInsets
val insets = Insets.of(
if (left) 0 else barsInsets.left,
if (top) 0 else barsInsets.top,
if (right) 0 else barsInsets.right,
if (bottom) 0 else barsInsets.bottom,
)
return WindowInsetsCompat.Builder(this)
.setInsets(WindowInsetsCompat.Type.systemBars(), insets)
.build()
}
fun WindowInsetsCompat.consume(
v: View,
@InsetsType typeMask: Int,
start: Boolean = false,
top: Boolean = false,
end: Boolean = false,
bottom: Boolean = false,
): WindowInsetsCompat {
val insets = getInsets(typeMask)
val newInsets = Insets.of(
/* left = */ if (if (v.isRtl) end else start) 0 else insets.left,
/* top = */ if (top) 0 else insets.top,
/* right = */ if (if (v.isRtl) start else end) 0 else insets.right,
/* bottom = */ if (bottom) 0 else insets.bottom,
)
return WindowInsetsCompat.Builder(this)
.setInsets(typeMask, newInsets)
.build()
}
fun WindowInsetsCompat.consumeAll(
@InsetsType typeMask: Int,
): WindowInsetsCompat = WindowInsetsCompat.Builder(this)
.setInsets(typeMask, Insets.NONE)
.build()
@Deprecated("")
fun WindowInsetsCompat.consumeSystemBarsInsets(
view: View,
start: Boolean = false,
top: Boolean = false,
end: Boolean = false,
bottom: Boolean = false,
): WindowInsetsCompat = consume(view, WindowInsetsCompat.Type.systemBars(), start, top, end, bottom)
fun Insets.consumeRelative(
@Deprecated("")
fun WindowInsetsCompat.consumeAllSystemBarsInsets() = consumeAll(WindowInsetsCompat.Type.systemBars())
@Deprecated("")
fun Insets.consume(
view: View,
start: Boolean = false,
top: Boolean = false,

@ -6,11 +6,8 @@ import android.view.View
import android.view.View.MeasureSpec
import android.view.ViewGroup
import android.widget.Checkable
import androidx.annotation.GravityInt
import androidx.appcompat.widget.ActionMenuView
import androidx.appcompat.widget.Toolbar
import androidx.core.graphics.Insets
import androidx.core.view.ViewCompat
import androidx.core.view.children
import androidx.core.view.descendants
import androidx.core.view.isVisible
@ -27,8 +24,6 @@ import com.google.android.material.slider.RangeSlider
import com.google.android.material.slider.Slider
import com.google.android.material.tabs.TabLayout
import org.koitharu.kotatsu.core.ui.OnContextClickListenerCompat
import org.koitharu.kotatsu.core.ui.util.InsetsToMarginsListener
import org.koitharu.kotatsu.core.ui.util.InsetsToPaddingListener
import kotlin.math.roundToInt
fun View.hasGlobalPoint(x: Int, y: Int): Boolean {
@ -194,19 +189,3 @@ fun Chip.setProgressIcon() {
chipIcon = progressDrawable
progressDrawable.start()
}
private fun View.marginsSnapshot(): Insets = (layoutParams as? ViewGroup.MarginLayoutParams)?.let { lp ->
Insets.of(lp.leftMargin, lp.topMargin, lp.rightMargin, lp.bottomMargin)
} ?: Insets.NONE
private fun View.paddingSnapshot(): Insets = Insets.of(paddingLeft, paddingTop, paddingRight, paddingBottom)
fun View.consumeInsetsAsPadding(@GravityInt sides: Int) = ViewCompat.setOnApplyWindowInsetsListener(
this,
InsetsToPaddingListener(sides, paddingSnapshot()),
)
fun View.consumeInsetsAsMargins(@GravityInt sides: Int) = ViewCompat.setOnApplyWindowInsetsListener(
this,
InsetsToMarginsListener(sides, marginsSnapshot()),
)

@ -2,7 +2,6 @@ package org.koitharu.kotatsu.details.ui
import android.content.Context
import android.os.Bundle
import android.transition.TransitionManager
import android.view.Gravity
import android.view.View
import android.view.ViewGroup
@ -10,8 +9,6 @@ import android.view.ViewTreeObserver
import android.widget.Toast
import androidx.activity.viewModels
import androidx.core.text.method.LinkMovementMethodCompat
import androidx.core.view.OnApplyWindowInsetsListener
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.isGone
import androidx.core.view.isVisible
@ -19,6 +16,7 @@ import androidx.core.view.updateLayoutParams
import androidx.core.view.updatePadding
import androidx.core.view.updatePaddingRelative
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
import androidx.transition.TransitionManager
import coil3.ImageLoader
import coil3.request.ImageRequest
import coil3.request.SuccessResult
@ -68,7 +66,7 @@ import org.koitharu.kotatsu.core.ui.util.ReversibleActionObserver
import org.koitharu.kotatsu.core.ui.widgets.ChipsView
import org.koitharu.kotatsu.core.util.FileSize
import org.koitharu.kotatsu.core.util.LocaleUtils
import org.koitharu.kotatsu.core.util.ext.consumeRelative
import org.koitharu.kotatsu.core.util.ext.consume
import org.koitharu.kotatsu.core.util.ext.copyToClipboard
import org.koitharu.kotatsu.core.util.ext.crossfade
import org.koitharu.kotatsu.core.util.ext.defaultPlaceholders
@ -77,6 +75,7 @@ import org.koitharu.kotatsu.core.util.ext.drawableStart
import org.koitharu.kotatsu.core.util.ext.end
import org.koitharu.kotatsu.core.util.ext.enqueueWith
import org.koitharu.kotatsu.core.util.ext.getQuantityStringSafe
import org.koitharu.kotatsu.core.util.ext.isAnimationsEnabled
import org.koitharu.kotatsu.core.util.ext.isTextTruncated
import org.koitharu.kotatsu.core.util.ext.joinToStringWithLimit
import org.koitharu.kotatsu.core.util.ext.mangaSourceExtra
@ -114,7 +113,7 @@ import com.google.android.material.R as materialR
@AndroidEntryPoint
class DetailsActivity :
BaseActivity<ActivityDetailsBinding>(),
View.OnClickListener, OnApplyWindowInsetsListener,
View.OnClickListener,
View.OnLayoutChangeListener, ViewTreeObserver.OnDrawListener,
ChipsView.OnChipClickListener, OnListItemClickListener<Bookmark>,
SwipeRefreshLayout.OnRefreshListener {
@ -162,7 +161,6 @@ class DetailsActivity :
DetailsBottomSheetCallback(viewBinding.swipeRefreshLayout, checkNotNull(viewBinding.navbarDim)),
)
}
ViewCompat.setOnApplyWindowInsetsListener(viewBinding.root, this)
val appRouter = router
viewModel.mangaDetails.filterNotNull().observe(this, ::onMangaUpdated)
@ -244,7 +242,11 @@ class DetailsActivity :
R.id.button_description_more -> {
val tv = viewBinding.textViewDescription
TransitionManager.beginDelayedTransition(tv.parentView)
if (tv.context.isAnimationsEnabled) {
tv.parentView?.let {
TransitionManager.beginDelayedTransition(it)
}
}
if (tv.maxLines in 1 until Integer.MAX_VALUE) {
tv.maxLines = Integer.MAX_VALUE
} else {
@ -319,7 +321,8 @@ class DetailsActivity :
}
override fun onApplyWindowInsets(v: View, insets: WindowInsetsCompat): WindowInsetsCompat {
val barsInsets = insets.getInsets(WindowInsetsCompat.Type.systemBars())
val typeMask = WindowInsetsCompat.Type.systemBars()
val barsInsets = insets.getInsets(typeMask)
if (viewBinding.cardChapters != null) {
// landscape
viewBinding.cardChapters?.updateLayoutParams<ViewGroup.MarginLayoutParams> {
@ -334,12 +337,11 @@ class DetailsActivity :
viewBinding.appbar.updatePaddingRelative(
start = barsInsets.start(v),
)
return WindowInsetsCompat.Builder(insets)
.setInsets(
WindowInsetsCompat.Type.systemBars(),
barsInsets.consumeRelative(v, end = true, bottom = true),
).build()
return insets.consume(v, typeMask, bottom = true, end = true)
} else {
viewBinding.navbarDim?.updateLayoutParams {
height = barsInsets.bottom
}
return insets
}
}

@ -3,11 +3,10 @@ package org.koitharu.kotatsu.details.ui
import android.view.View
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
import com.google.android.material.bottomsheet.BottomSheetBehavior
import org.koitharu.kotatsu.core.ui.widgets.WindowInsetHolder
class DetailsBottomSheetCallback(
private val swipeRefreshLayout: SwipeRefreshLayout,
private val navbarDimView: WindowInsetHolder,
private val navbarDimView: View,
) : BottomSheetBehavior.BottomSheetCallback() {
override fun onStateChanged(bottomSheet: View, newState: Int) {

@ -5,7 +5,9 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.appcompat.view.ActionMode
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.isVisible
import androidx.transition.TransitionManager
import com.google.android.material.tabs.TabLayout
import com.google.android.material.tabs.TabLayoutMediator
import dagger.hilt.android.AndroidEntryPoint
@ -25,6 +27,7 @@ import org.koitharu.kotatsu.core.ui.util.RecyclerViewOwner
import org.koitharu.kotatsu.core.ui.util.ReversibleActionObserver
import org.koitharu.kotatsu.core.util.ext.doOnPageChanged
import org.koitharu.kotatsu.core.util.ext.findCurrentPagerFragment
import org.koitharu.kotatsu.core.util.ext.isAnimationsEnabled
import org.koitharu.kotatsu.core.util.ext.menuView
import org.koitharu.kotatsu.core.util.ext.observe
import org.koitharu.kotatsu.core.util.ext.observeEvent
@ -95,12 +98,17 @@ class ChaptersPagesSheet : BaseAdaptiveSheet<SheetChaptersPagesBinding>(),
}
}
override fun onApplyWindowInsets(v: View, insets: WindowInsetsCompat): WindowInsetsCompat = insets
override fun onStateChanged(sheet: View, newState: Int) {
if (newState == STATE_DRAGGING || newState == STATE_SETTLING) {
return
}
val binding = viewBinding ?: return
val isActionModeStarted = actionModeDelegate?.isActionModeStarted == true
if (sheet.context.isAnimationsEnabled) {
TransitionManager.beginDelayedTransition(binding.toolbar)
}
binding.toolbar.menuView?.isVisible = newState == STATE_EXPANDED && !isActionModeStarted
binding.splitButtonRead.isVisible = newState != STATE_EXPANDED && !isActionModeStarted
&& viewModel is DetailsViewModel

@ -1,7 +1,6 @@
package org.koitharu.kotatsu.details.ui.pager.bookmarks
import android.os.Bundle
import android.view.Gravity
import android.view.LayoutInflater
import android.view.Menu
import android.view.MenuInflater
@ -9,6 +8,7 @@ import android.view.MenuItem
import android.view.View
import android.view.ViewGroup
import androidx.appcompat.view.ActionMode
import androidx.core.view.WindowInsetsCompat
import androidx.fragment.app.viewModels
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.RecyclerView
@ -29,11 +29,12 @@ import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener
import org.koitharu.kotatsu.core.ui.util.PagerNestedScrollHelper
import org.koitharu.kotatsu.core.ui.util.RecyclerViewOwner
import org.koitharu.kotatsu.core.ui.util.ReversibleActionObserver
import org.koitharu.kotatsu.core.util.ext.consumeInsetsAsPadding
import org.koitharu.kotatsu.core.util.ext.consumeAllSystemBarsInsets
import org.koitharu.kotatsu.core.util.ext.findAppCompatDelegate
import org.koitharu.kotatsu.core.util.ext.findParentCallback
import org.koitharu.kotatsu.core.util.ext.observe
import org.koitharu.kotatsu.core.util.ext.observeEvent
import org.koitharu.kotatsu.core.util.ext.systemBarsInsets
import org.koitharu.kotatsu.databinding.FragmentMangaBookmarksBinding
import org.koitharu.kotatsu.details.ui.pager.ChaptersPagesViewModel
import org.koitharu.kotatsu.list.ui.GridSpanResolver
@ -94,7 +95,6 @@ class BookmarksFragment : BaseFragment<FragmentMangaBookmarksBinding>(),
headerClickListener = null,
)
viewModel.gridScale.observe(viewLifecycleOwner, ::onGridScaleChanged) // before rv initialization
binding.recyclerView.consumeInsetsAsPadding(Gravity.START or Gravity.BOTTOM or Gravity.END)
with(binding.recyclerView) {
addItemDecoration(TypedListSpacingDecoration(context, false))
setHasFixedSize(true)
@ -116,6 +116,17 @@ class BookmarksFragment : BaseFragment<FragmentMangaBookmarksBinding>(),
viewModel.onActionDone.observeEvent(viewLifecycleOwner, ReversibleActionObserver(binding.recyclerView))
}
override fun onApplyWindowInsets(v: View, insets: WindowInsetsCompat): WindowInsetsCompat {
val barsInsets = insets.systemBarsInsets
viewBinding?.recyclerView?.setPadding(
barsInsets.left,
barsInsets.top,
barsInsets.right,
barsInsets.bottom,
)
return insets.consumeAllSystemBarsInsets()
}
override fun onDestroyView() {
spanResolver = null
bookmarksAdapter = null

@ -4,8 +4,6 @@ import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.core.view.OnApplyWindowInsetsListener
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.isGone
import androidx.core.view.isVisible
@ -49,7 +47,6 @@ import kotlin.math.roundToInt
class ChaptersFragment :
BaseFragment<FragmentChaptersBinding>(),
OnListItemClickListener<ChapterListItem>,
OnApplyWindowInsetsListener,
RecyclerViewOwner,
ChipsView.OnChipClickListener {
@ -84,7 +81,6 @@ class ChaptersFragment :
LinearLayoutManager(context)
}
}
ViewCompat.setOnApplyWindowInsetsListener(binding.root, this)
with(binding.recyclerViewChapters) {
addItemDecoration(TypedListSpacingDecoration(context, true))
checkNotNull(selectionController).attachToRecyclerView(this)

@ -1,7 +1,6 @@
package org.koitharu.kotatsu.details.ui.pager.pages
import android.os.Bundle
import android.view.Gravity
import android.view.LayoutInflater
import android.view.Menu
import android.view.MenuInflater
@ -10,6 +9,7 @@ import android.view.View
import android.view.ViewGroup
import androidx.appcompat.view.ActionMode
import androidx.collection.ArraySet
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.isInvisible
import androidx.core.view.isVisible
import androidx.fragment.app.viewModels
@ -33,7 +33,7 @@ import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener
import org.koitharu.kotatsu.core.ui.util.PagerNestedScrollHelper
import org.koitharu.kotatsu.core.ui.util.RecyclerViewOwner
import org.koitharu.kotatsu.core.util.RecyclerViewScrollCallback
import org.koitharu.kotatsu.core.util.ext.consumeInsetsAsPadding
import org.koitharu.kotatsu.core.util.ext.consumeAll
import org.koitharu.kotatsu.core.util.ext.findAppCompatDelegate
import org.koitharu.kotatsu.core.util.ext.findParentCallback
import org.koitharu.kotatsu.core.util.ext.observe
@ -118,7 +118,6 @@ class PagesFragment :
clickListener = this@PagesFragment,
)
viewModel.gridScale.observe(viewLifecycleOwner, ::onGridScaleChanged) // before rv initialization
binding.recyclerView.consumeInsetsAsPadding(Gravity.START or Gravity.BOTTOM or Gravity.END)
with(binding.recyclerView) {
addItemDecoration(TypedListSpacingDecoration(context, false))
checkNotNull(selectionController).attachToRecyclerView(this)
@ -150,6 +149,18 @@ class PagesFragment :
super.onDestroyView()
}
override fun onApplyWindowInsets(v: View, insets: WindowInsetsCompat): WindowInsetsCompat {
val typeBask = WindowInsetsCompat.Type.systemBars()
val barsInsets = insets.getInsets(typeBask)
viewBinding?.recyclerView?.setPadding(
barsInsets.left,
barsInsets.top,
barsInsets.right,
barsInsets.bottom,
)
return insets.consumeAll(typeBask)
}
override fun onItemClick(item: PageThumbnail, view: View) {
if (selectionController?.onItemClick(item.page.id) == true) {
return

@ -10,6 +10,8 @@ import android.widget.RatingBar
import android.widget.Toast
import androidx.appcompat.widget.PopupMenu
import androidx.core.text.method.LinkMovementMethodCompat
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.updatePadding
import androidx.fragment.app.activityViewModels
import coil3.ImageLoader
import com.google.android.material.snackbar.Snackbar
@ -18,6 +20,7 @@ import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.nav.AppRouter
import org.koitharu.kotatsu.core.nav.router
import org.koitharu.kotatsu.core.ui.sheet.BaseAdaptiveSheet
import org.koitharu.kotatsu.core.util.ext.consume
import org.koitharu.kotatsu.core.util.ext.defaultPlaceholders
import org.koitharu.kotatsu.core.util.ext.enqueueWith
import org.koitharu.kotatsu.core.util.ext.getDisplayMessage
@ -81,6 +84,15 @@ class ScrobblingInfoSheet :
menu = null
}
override fun onApplyWindowInsets(v: View, insets: WindowInsetsCompat): WindowInsetsCompat {
val typeMask = WindowInsetsCompat.Type.systemBars()
viewBinding?.root?.updatePadding(
bottom = insets.getInsets(typeMask).bottom,
)
return insets.consume(v, typeMask, bottom = true)
}
override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
viewModel.updateScrobbling(
index = scrobblerIndex,

@ -8,8 +8,6 @@ import android.view.View
import androidx.activity.viewModels
import androidx.appcompat.view.ActionMode
import androidx.core.graphics.Insets
import androidx.core.view.OnApplyWindowInsetsListener
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.updatePadding
import coil3.ImageLoader
@ -31,7 +29,6 @@ import javax.inject.Inject
@AndroidEntryPoint
class DownloadsActivity : BaseActivity<ActivityDownloadsBinding>(),
DownloadItemListener,
OnApplyWindowInsetsListener,
ListSelectionController.Callback {
@Inject
@ -47,7 +44,6 @@ class DownloadsActivity : BaseActivity<ActivityDownloadsBinding>(),
super.onCreate(savedInstanceState)
setContentView(ActivityDownloadsBinding.inflate(layoutInflater))
supportActionBar?.setDisplayHomeAsUpEnabled(true)
ViewCompat.setOnApplyWindowInsetsListener(viewBinding.root, this)
val downloadsAdapter = DownloadsAdapter(this, coil, this)
val decoration = TypedListSpacingDecoration(this, false)
selectionController = ListSelectionController(

@ -5,7 +5,6 @@ import android.content.Intent
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.view.Gravity
import android.view.LayoutInflater
import android.view.Menu
import android.view.MenuInflater
@ -13,6 +12,7 @@ import android.view.MenuItem
import android.view.View
import android.view.ViewGroup
import androidx.appcompat.view.ActionMode
import androidx.core.view.WindowInsetsCompat
import androidx.fragment.app.viewModels
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.LinearLayoutManager
@ -32,10 +32,11 @@ import org.koitharu.kotatsu.core.ui.util.RecyclerViewOwner
import org.koitharu.kotatsu.core.ui.util.ReversibleActionObserver
import org.koitharu.kotatsu.core.ui.util.SpanSizeResolver
import org.koitharu.kotatsu.core.util.ext.addMenuProvider
import org.koitharu.kotatsu.core.util.ext.consumeInsetsAsPadding
import org.koitharu.kotatsu.core.util.ext.consumeAllSystemBarsInsets
import org.koitharu.kotatsu.core.util.ext.findAppCompatDelegate
import org.koitharu.kotatsu.core.util.ext.observe
import org.koitharu.kotatsu.core.util.ext.observeEvent
import org.koitharu.kotatsu.core.util.ext.systemBarsInsets
import org.koitharu.kotatsu.databinding.FragmentExploreBinding
import org.koitharu.kotatsu.explore.ui.adapter.ExploreAdapter
import org.koitharu.kotatsu.explore.ui.adapter.ExploreListEventListener
@ -79,7 +80,6 @@ class ExploreFragment :
callback = this,
)
with(binding.recyclerView) {
consumeInsetsAsPadding(Gravity.BOTTOM or Gravity.START or Gravity.END)
adapter = exploreAdapter
setHasFixedSize(true)
SpanSizeResolver(this, resources.getDimensionPixelSize(R.dimen.explore_grid_width)).attach()
@ -97,6 +97,18 @@ class ExploreFragment :
}
}
override fun onApplyWindowInsets(v: View, insets: WindowInsetsCompat): WindowInsetsCompat {
val barsInsets = insets.systemBarsInsets
val basePadding = v.resources.getDimensionPixelOffset(R.dimen.list_spacing_normal)
viewBinding?.recyclerView?.setPadding(
/* left = */ barsInsets.left + basePadding,
/* top = */ basePadding,
/* right = */ barsInsets.right + basePadding,
/* bottom = */ barsInsets.bottom + basePadding,
)
return insets.consumeAllSystemBarsInsets()
}
override fun onDestroyView() {
super.onDestroyView()
sourceSelectionController = null

@ -1,10 +1,13 @@
package org.koitharu.kotatsu.favourites.ui.categories
import android.os.Bundle
import android.view.Gravity
import android.view.View
import android.view.ViewGroup.MarginLayoutParams
import androidx.activity.viewModels
import androidx.appcompat.view.ActionMode
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.updateLayoutParams
import androidx.core.view.updatePadding
import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.RecyclerView
import coil3.ImageLoader
@ -15,9 +18,11 @@ import org.koitharu.kotatsu.core.model.FavouriteCategory
import org.koitharu.kotatsu.core.nav.router
import org.koitharu.kotatsu.core.ui.BaseActivity
import org.koitharu.kotatsu.core.ui.list.ListSelectionController
import org.koitharu.kotatsu.core.util.ext.consumeInsetsAsPadding
import org.koitharu.kotatsu.core.util.ext.consumeAllSystemBarsInsets
import org.koitharu.kotatsu.core.util.ext.end
import org.koitharu.kotatsu.core.util.ext.observe
import org.koitharu.kotatsu.core.util.ext.observeEvent
import org.koitharu.kotatsu.core.util.ext.systemBarsInsets
import org.koitharu.kotatsu.databinding.ActivityCategoriesBinding
import org.koitharu.kotatsu.favourites.ui.categories.adapter.CategoriesAdapter
import org.koitharu.kotatsu.list.ui.adapter.ListStateHolderListener
@ -53,7 +58,6 @@ class FavouriteCategoriesActivity :
callback = CategoriesSelectionCallback(viewBinding.recyclerView, viewModel),
)
selectionController.attachToRecyclerView(viewBinding.recyclerView)
viewBinding.recyclerView.consumeInsetsAsPadding(Gravity.START or Gravity.END or Gravity.BOTTOM)
viewBinding.recyclerView.setHasFixedSize(true)
viewBinding.recyclerView.adapter = adapter
viewBinding.recyclerView.addItemDecoration(TypedListSpacingDecoration(this, false))
@ -67,6 +71,28 @@ class FavouriteCategoriesActivity :
viewModel.onError.observeEvent(this, SnackbarErrorObserver(viewBinding.recyclerView, null))
}
override fun onApplyWindowInsets(
v: View,
insets: WindowInsetsCompat
): WindowInsetsCompat {
val barsInsets = insets.systemBarsInsets
viewBinding.recyclerView.updatePadding(
left = barsInsets.left,
right = barsInsets.right,
bottom = barsInsets.bottom,
)
viewBinding.appbar.updatePadding(
left = barsInsets.left,
right = barsInsets.right,
top = barsInsets.top,
)
viewBinding.fabAdd.updateLayoutParams<MarginLayoutParams> {
marginEnd = topMargin + barsInsets.end(v)
bottomMargin = topMargin + barsInsets.bottom
}
return insets.consumeAllSystemBarsInsets()
}
override fun onClick(v: View) {
when (v.id) {
R.id.fab_add -> router.openFavoriteCategoryCreate()

@ -8,18 +8,21 @@ import android.widget.AdapterView
import android.widget.ArrayAdapter
import android.widget.Filter
import androidx.activity.viewModels
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.isVisible
import dagger.hilt.android.AndroidEntryPoint
import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.model.FavouriteCategory
import org.koitharu.kotatsu.core.ui.BaseActivity
import org.koitharu.kotatsu.core.ui.util.DefaultTextWatcher
import org.koitharu.kotatsu.core.util.ext.consumeAllSystemBarsInsets
import org.koitharu.kotatsu.core.util.ext.getDisplayMessage
import org.koitharu.kotatsu.core.util.ext.getSerializableCompat
import org.koitharu.kotatsu.core.util.ext.observe
import org.koitharu.kotatsu.core.util.ext.observeEvent
import org.koitharu.kotatsu.core.util.ext.setChecked
import org.koitharu.kotatsu.core.util.ext.sortedByOrdinal
import org.koitharu.kotatsu.core.util.ext.systemBarsInsets
import org.koitharu.kotatsu.databinding.ActivityCategoryEditBinding
import org.koitharu.kotatsu.list.domain.ListSortOrder
import com.google.android.material.R as materialR
@ -56,6 +59,20 @@ class FavouritesCategoryEditActivity :
}
}
override fun onApplyWindowInsets(
v: View,
insets: WindowInsetsCompat
): WindowInsetsCompat {
val barsInsets = insets.systemBarsInsets
viewBinding.root.setPadding(
barsInsets.left,
barsInsets.top,
barsInsets.right,
barsInsets.bottom,
)
return insets.consumeAllSystemBarsInsets()
}
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
outState.putSerializable(KEY_SORT_ORDER, selectedSortOrder)

@ -6,6 +6,7 @@ import android.view.View
import android.view.ViewGroup
import android.view.ViewStub
import androidx.appcompat.view.ActionMode
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.isGone
import androidx.core.view.isVisible
import androidx.fragment.app.Fragment
@ -77,6 +78,8 @@ class FavouritesContainerFragment : BaseFragment<FragmentFavouritesContainerBind
super.onDestroyView()
}
override fun onApplyWindowInsets(v: View, insets: WindowInsetsCompat): WindowInsetsCompat = insets
override fun onActionModeStarted(mode: ActionMode) {
viewBinding?.run {
pager.isUserInputEnabled = false

@ -2,7 +2,9 @@ package org.koitharu.kotatsu.filter.ui
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.isVisible
import com.google.android.material.chip.Chip
import dagger.hilt.android.AndroidEntryPoint
@ -47,6 +49,8 @@ class FilterHeaderFragment : BaseFragment<FragmentFilterHeaderBinding>(), ChipsV
.observe(viewLifecycleOwner, ::onDataChanged)
}
override fun onApplyWindowInsets(v: View, insets: WindowInsetsCompat): WindowInsetsCompat = insets
override fun onChipClick(chip: Chip, data: Any?) {
when (data) {
is MangaTag -> filter.toggleTag(data, !chip.isChecked)

@ -7,6 +7,7 @@ import android.view.View
import android.view.ViewGroup
import android.widget.AdapterView
import android.widget.ArrayAdapter
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.isGone
import androidx.core.view.updatePadding
import com.google.android.material.chip.Chip
@ -18,6 +19,7 @@ import org.koitharu.kotatsu.core.nav.router
import org.koitharu.kotatsu.core.ui.model.titleRes
import org.koitharu.kotatsu.core.ui.sheet.BaseAdaptiveSheet
import org.koitharu.kotatsu.core.ui.widgets.ChipsView
import org.koitharu.kotatsu.core.util.ext.consume
import org.koitharu.kotatsu.core.util.ext.getDisplayMessage
import org.koitharu.kotatsu.core.util.ext.getDisplayName
import org.koitharu.kotatsu.core.util.ext.observe
@ -92,6 +94,14 @@ class FilterSheetFragment : BaseAdaptiveSheet<SheetFilterBinding>(),
}
}
override fun onApplyWindowInsets(v: View, insets: WindowInsetsCompat): WindowInsetsCompat {
val typeMask = WindowInsetsCompat.Type.systemBars()
viewBinding?.scrollView?.updatePadding(
bottom = insets.getInsets(typeMask).bottom,
)
return insets.consume(v, typeMask, bottom = true)
}
override fun onItemSelected(parent: AdapterView<*>, view: View?, position: Int, id: Long) {
val filter = requireFilter()
when (parent.id) {

@ -8,6 +8,7 @@ import android.view.View
import android.view.ViewGroup
import android.view.inputmethod.EditorInfo
import android.widget.TextView
import androidx.core.view.WindowInsetsCompat
import androidx.fragment.app.viewModels
import dagger.hilt.android.AndroidEntryPoint
import dagger.hilt.android.lifecycle.withCreationCallback
@ -17,6 +18,7 @@ import org.koitharu.kotatsu.core.ui.sheet.AdaptiveSheetBehavior
import org.koitharu.kotatsu.core.ui.sheet.AdaptiveSheetCallback
import org.koitharu.kotatsu.core.ui.sheet.BaseAdaptiveSheet
import org.koitharu.kotatsu.core.ui.util.DefaultTextWatcher
import org.koitharu.kotatsu.core.util.ext.consumeAll
import org.koitharu.kotatsu.core.util.ext.observe
import org.koitharu.kotatsu.databinding.SheetTagsBinding
import org.koitharu.kotatsu.filter.ui.FilterCoordinator
@ -59,6 +61,18 @@ class TagsCatalogSheet : BaseAdaptiveSheet<SheetTagsBinding>(),
disableFitToContents()
}
override fun onApplyWindowInsets(v: View, insets: WindowInsetsCompat): WindowInsetsCompat {
val typeBask = WindowInsetsCompat.Type.systemBars()
val barsInsets = insets.getInsets(typeBask)
viewBinding?.recyclerView?.setPadding(
barsInsets.left,
barsInsets.top,
barsInsets.right,
barsInsets.bottom,
)
return insets.consumeAll(typeBask)
}
override fun onItemClick(item: TagCatalogItem, view: View) {
viewModel.handleTagClick(item.tag, item.isChecked)
}

@ -7,8 +7,6 @@ import android.view.View
import android.view.ViewGroup
import androidx.activity.viewModels
import androidx.core.graphics.drawable.toBitmap
import androidx.core.view.OnApplyWindowInsetsListener
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.isVisible
import androidx.core.view.updateLayoutParams
@ -33,6 +31,7 @@ import org.koitharu.kotatsu.core.nav.AppRouter
import org.koitharu.kotatsu.core.ui.BaseActivity
import org.koitharu.kotatsu.core.ui.util.PopupMenuMediator
import org.koitharu.kotatsu.core.util.ShareHelper
import org.koitharu.kotatsu.core.util.ext.consumeAll
import org.koitharu.kotatsu.core.util.ext.end
import org.koitharu.kotatsu.core.util.ext.enqueueWith
import org.koitharu.kotatsu.core.util.ext.getDisplayIcon
@ -50,7 +49,6 @@ import com.google.android.material.R as materialR
@AndroidEntryPoint
class ImageActivity : BaseActivity<ActivityImageBinding>(),
ImageRequest.Listener,
OnApplyWindowInsetsListener,
View.OnClickListener {
@Inject
@ -63,7 +61,6 @@ class ImageActivity : BaseActivity<ActivityImageBinding>(),
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(ActivityImageBinding.inflate(layoutInflater))
ViewCompat.setOnApplyWindowInsetsListener(viewBinding.root, this)
viewBinding.buttonBack.setOnClickListener(this)
viewBinding.buttonMenu.setOnClickListener(this)
val imageUrl = requireNotNull(intent.data)
@ -111,16 +108,18 @@ class ImageActivity : BaseActivity<ActivityImageBinding>(),
}
override fun onApplyWindowInsets(v: View, insets: WindowInsetsCompat): WindowInsetsCompat {
val barsInsets = insets.getInsets(WindowInsetsCompat.Type.systemBars())
val typeMask = WindowInsetsCompat.Type.systemBars()
val barsInsets = insets.getInsets(typeMask)
val baseMargin = v.resources.getDimensionPixelOffset(R.dimen.screen_padding)
viewBinding.buttonMenu.updateLayoutParams<ViewGroup.MarginLayoutParams> {
marginEnd = barsInsets.end(v)
topMargin = barsInsets.top
marginEnd = barsInsets.end(v) + baseMargin
topMargin = barsInsets.top + baseMargin
}
viewBinding.buttonBack.updateLayoutParams<ViewGroup.MarginLayoutParams> {
marginStart = barsInsets.start(v)
topMargin = barsInsets.top
marginStart = barsInsets.start(v) + baseMargin
topMargin = barsInsets.top + baseMargin
}
return insets
return insets.consumeAll(typeMask)
}
private fun loadImage(url: Uri?) {

@ -1,7 +1,6 @@
package org.koitharu.kotatsu.list.ui
import android.os.Bundle
import android.view.Gravity
import android.view.LayoutInflater
import android.view.Menu
import android.view.MenuInflater
@ -11,6 +10,7 @@ import android.view.ViewGroup
import androidx.annotation.CallSuper
import androidx.appcompat.view.ActionMode
import androidx.collection.ArraySet
import androidx.core.view.WindowInsetsCompat
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.RecyclerView
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
@ -37,7 +37,7 @@ import org.koitharu.kotatsu.core.ui.util.ReversibleActionObserver
import org.koitharu.kotatsu.core.ui.widgets.TipView
import org.koitharu.kotatsu.core.util.ShareHelper
import org.koitharu.kotatsu.core.util.ext.addMenuProvider
import org.koitharu.kotatsu.core.util.ext.consumeInsetsAsPadding
import org.koitharu.kotatsu.core.util.ext.consumeAll
import org.koitharu.kotatsu.core.util.ext.findAppCompatDelegate
import org.koitharu.kotatsu.core.util.ext.observe
import org.koitharu.kotatsu.core.util.ext.observeEvent
@ -110,7 +110,6 @@ abstract class MangaListFragment :
)
paginationListener = PaginationScrollListener(4, this)
with(binding.recyclerView) {
consumeInsetsAsPadding(Gravity.START or Gravity.BOTTOM or Gravity.END)
setHasFixedSize(true)
adapter = listAdapter
checkNotNull(selectionController).attachToRecyclerView(this)
@ -132,6 +131,19 @@ abstract class MangaListFragment :
viewModel.onActionDone.observeEvent(viewLifecycleOwner, ReversibleActionObserver(binding.recyclerView))
}
override fun onApplyWindowInsets(v: View, insets: WindowInsetsCompat): WindowInsetsCompat {
val typeMask = WindowInsetsCompat.Type.systemBars()
val barsInsets = insets.getInsets(typeMask)
val basePadding = v.resources.getDimensionPixelOffset(R.dimen.list_spacing_normal)
viewBinding?.recyclerView?.setPadding(
left = barsInsets.left + basePadding,
top = basePadding,
right = barsInsets.right + basePadding,
bottom = barsInsets.bottom + basePadding,
)
return insets.consumeAll(typeMask)
}
override fun onDestroyView() {
listAdapter = null
paginationListener = null

@ -7,7 +7,9 @@ import android.view.ViewGroup
import android.widget.AdapterView
import android.widget.ArrayAdapter
import android.widget.CompoundButton
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.isVisible
import androidx.core.view.updatePadding
import androidx.fragment.app.viewModels
import com.google.android.material.button.MaterialButtonToggleGroup
import com.google.android.material.slider.Slider
@ -15,6 +17,7 @@ import dagger.hilt.android.AndroidEntryPoint
import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.prefs.ListMode
import org.koitharu.kotatsu.core.ui.sheet.BaseAdaptiveSheet
import org.koitharu.kotatsu.core.util.ext.consume
import org.koitharu.kotatsu.core.util.ext.setValueRounded
import org.koitharu.kotatsu.core.util.progress.IntPercentLabelFormatter
import org.koitharu.kotatsu.databinding.SheetListModeBinding
@ -73,6 +76,14 @@ class ListConfigBottomSheet :
}
}
override fun onApplyWindowInsets(v: View, insets: WindowInsetsCompat): WindowInsetsCompat {
val typeMask = WindowInsetsCompat.Type.systemBars()
viewBinding?.scrollView?.updatePadding(
bottom = insets.getInsets(typeMask).bottom,
)
return insets.consume(v, typeMask, bottom = true)
}
override fun onButtonChecked(group: MaterialButtonToggleGroup?, checkedId: Int, isChecked: Boolean) {
if (!isChecked) {
return

@ -6,6 +6,7 @@ import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.core.text.method.LinkMovementMethodCompat
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.isVisible
import androidx.fragment.app.viewModels
import coil3.ImageLoader
@ -68,6 +69,8 @@ class PreviewFragment : BaseFragment<FragmentPreviewBinding>(), View.OnClickList
viewModel.description.observe(viewLifecycleOwner, ::onDescriptionChanged)
}
override fun onApplyWindowInsets(v: View, insets: WindowInsetsCompat): WindowInsetsCompat = insets
override fun onClick(v: View) {
val manga = viewModel.manga.value
when (v.id) {

@ -15,9 +15,7 @@ import androidx.appcompat.view.ActionMode
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import androidx.core.net.toUri
import androidx.core.view.OnApplyWindowInsetsListener
import androidx.core.view.SoftwareKeyboardControllerCompat
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.children
import androidx.core.view.inputmethod.EditorInfoCompat
@ -25,7 +23,6 @@ import androidx.core.view.isInvisible
import androidx.core.view.isVisible
import androidx.core.view.updateLayoutParams
import androidx.core.view.updatePadding
import androidx.core.view.updatePaddingRelative
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentTransaction
import androidx.fragment.app.commit
@ -53,7 +50,7 @@ import org.koitharu.kotatsu.core.ui.util.FadingAppbarMediator
import org.koitharu.kotatsu.core.ui.util.MenuInvalidator
import org.koitharu.kotatsu.core.ui.util.OptionsMenuBadgeHelper
import org.koitharu.kotatsu.core.ui.widgets.SlidingBottomNavigationView
import org.koitharu.kotatsu.core.util.ext.consumeRelative
import org.koitharu.kotatsu.core.util.ext.consume
import org.koitharu.kotatsu.core.util.ext.end
import org.koitharu.kotatsu.core.util.ext.observe
import org.koitharu.kotatsu.core.util.ext.observeEvent
@ -84,7 +81,6 @@ class MainActivity : BaseActivity<ActivityMainBinding>(), AppBarOwner, BottomNav
View.OnClickListener,
View.OnFocusChangeListener,
SearchSuggestionListener,
OnApplyWindowInsetsListener,
MainNavigationDelegate.OnFragmentChangedListener,
View.OnLayoutChangeListener {
@ -107,7 +103,6 @@ class MainActivity : BaseActivity<ActivityMainBinding>(), AppBarOwner, BottomNav
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(ActivityMainBinding.inflate(layoutInflater))
ViewCompat.setOnApplyWindowInsetsListener(viewBinding.root, this)
with(viewBinding.searchView) {
onFocusChangeListener = this@MainActivity
@ -216,7 +211,8 @@ class MainActivity : BaseActivity<ActivityMainBinding>(), AppBarOwner, BottomNav
}
override fun onApplyWindowInsets(v: View, insets: WindowInsetsCompat): WindowInsetsCompat {
val barsInsets = insets.getInsets(WindowInsetsCompat.Type.systemBars())
val typeMask = WindowInsetsCompat.Type.systemBars()
val barsInsets = insets.getInsets(typeMask)
viewBinding.toolbarCard.updateLayoutParams<MarginLayoutParams> {
marginEnd = barsInsets.end(v)
marginStart = if (viewBinding.navRail != null) {
@ -230,16 +226,12 @@ class MainActivity : BaseActivity<ActivityMainBinding>(), AppBarOwner, BottomNav
right = barsInsets.right,
bottom = barsInsets.bottom,
)
return viewBinding.navRail?.let { navRail ->
navRail.updateLayoutParams<MarginLayoutParams> {
marginStart = barsInsets.start(v)
topMargin = barsInsets.top
bottomMargin = barsInsets.bottom
}
WindowInsetsCompat.Builder(insets)
.setInsets(WindowInsetsCompat.Type.systemBars(), barsInsets.consumeRelative(v, start = true))
.build()
} ?: insets
viewBinding.navRail?.updateLayoutParams<MarginLayoutParams> {
marginStart = barsInsets.start(v)
topMargin = barsInsets.top
bottomMargin = barsInsets.bottom
}
return insets.consume(v, typeMask, start = viewBinding.navRail != null)
}
override fun onLayoutChange(

@ -58,13 +58,16 @@ class MainNavigationDelegate(
}
override fun onNavigationItemSelected(item: MenuItem): Boolean {
return onNavigationItemSelected(item.itemId)
return if (onNavigationItemSelected(item.itemId)) {
item.isChecked = true
true
} else {
false
}
}
override fun onNavigationItemReselected(item: MenuItem) {
val fragment = fragmentManager.findFragmentByTag(TAG_PRIMARY)
val recyclerView = (fragment as? RecyclerViewOwner)?.recyclerView ?: return
recyclerView.smoothScrollToTop()
onNavigationItemReselected()
}
override fun handleOnBackPressed() {
@ -137,19 +140,22 @@ class MainNavigationDelegate(
}
private fun onNavigationItemSelected(@IdRes itemId: Int): Boolean {
return setPrimaryFragment(
when (itemId) {
R.id.nav_history -> HistoryListFragment::class.java
R.id.nav_favorites -> FavouritesContainerFragment::class.java
R.id.nav_explore -> ExploreFragment::class.java
R.id.nav_feed -> FeedFragment::class.java
R.id.nav_local -> LocalListFragment::class.java
R.id.nav_suggestions -> SuggestionsFragment::class.java
R.id.nav_bookmarks -> AllBookmarksFragment::class.java
R.id.nav_updated -> UpdatesFragment::class.java
else -> return false
},
)
val newFragment = when (itemId) {
R.id.nav_history -> HistoryListFragment::class.java
R.id.nav_favorites -> FavouritesContainerFragment::class.java
R.id.nav_explore -> ExploreFragment::class.java
R.id.nav_feed -> FeedFragment::class.java
R.id.nav_local -> LocalListFragment::class.java
R.id.nav_suggestions -> SuggestionsFragment::class.java
R.id.nav_bookmarks -> AllBookmarksFragment::class.java
R.id.nav_updated -> UpdatesFragment::class.java
else -> return false
}
if (!setPrimaryFragment(newFragment)) {
// probably already selected
onNavigationItemReselected()
}
return true
}
private fun getItemId(fragment: Fragment) = when (fragment) {
@ -178,6 +184,11 @@ class MainNavigationDelegate(
return true
}
private fun onNavigationItemReselected() {
val recyclerView = (primaryFragment as? RecyclerViewOwner)?.recyclerView ?: return
recyclerView.smoothScrollToTop()
}
private fun onFragmentChanged(fragment: Fragment, fromUser: Boolean) {
isEnabled = getItemId(fragment) != firstItem()?.itemId
listeners.forEach { it.onFragmentChanged(fragment, fromUser) }

@ -4,7 +4,6 @@ import android.content.Context
import android.content.Intent
import android.os.Bundle
import android.text.Editable
import android.view.Gravity
import android.view.KeyEvent
import android.view.View
import android.view.WindowManager
@ -16,16 +15,18 @@ import androidx.biometric.BiometricManager.Authenticators.BIOMETRIC_WEAK
import androidx.biometric.BiometricManager.BIOMETRIC_SUCCESS
import androidx.biometric.BiometricPrompt
import androidx.biometric.BiometricPrompt.AuthenticationCallback
import androidx.core.view.WindowInsetsCompat
import com.google.android.material.textfield.TextInputLayout
import dagger.hilt.android.AndroidEntryPoint
import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.ui.BaseActivity
import org.koitharu.kotatsu.core.ui.util.DefaultTextWatcher
import org.koitharu.kotatsu.core.util.ext.consumeInsetsAsPadding
import org.koitharu.kotatsu.core.util.ext.consumeAllSystemBarsInsets
import org.koitharu.kotatsu.core.util.ext.getDisplayMessage
import org.koitharu.kotatsu.core.util.ext.getParcelableExtraCompat
import org.koitharu.kotatsu.core.util.ext.observe
import org.koitharu.kotatsu.core.util.ext.observeEvent
import org.koitharu.kotatsu.core.util.ext.systemBarsInsets
import org.koitharu.kotatsu.databinding.ActivityProtectBinding
import com.google.android.material.R as materialR
@ -43,7 +44,6 @@ class ProtectActivity :
super.onCreate(savedInstanceState)
window.addFlags(WindowManager.LayoutParams.FLAG_SECURE)
setContentView(ActivityProtectBinding.inflate(layoutInflater))
viewBinding.root.consumeInsetsAsPadding(Gravity.FILL)
viewBinding.editPassword.setOnEditorActionListener(this)
viewBinding.editPassword.addTextChangedListener(this)
viewBinding.buttonNext.setOnClickListener(this)
@ -64,6 +64,18 @@ class ProtectActivity :
}
}
override fun onApplyWindowInsets(v: View, insets: WindowInsetsCompat): WindowInsetsCompat {
val barsInsets = insets.systemBarsInsets
val basePadding = resources.getDimensionPixelOffset(R.dimen.screen_padding)
viewBinding.root.setPadding(
barsInsets.left + basePadding,
barsInsets.top + basePadding,
barsInsets.right + basePadding,
barsInsets.bottom + basePadding,
)
return insets.consumeAllSystemBarsInsets()
}
override fun onStart() {
super.onStart()
canUseBiometric = useFingerprint()

@ -8,7 +8,9 @@ import android.view.View
import android.view.ViewGroup
import androidx.activity.result.ActivityResultCallback
import androidx.activity.result.contract.ActivityResultContracts
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.isGone
import androidx.core.view.updatePadding
import androidx.fragment.app.viewModels
import com.google.android.material.chip.Chip
import com.google.android.material.snackbar.Snackbar
@ -18,6 +20,7 @@ import org.koitharu.kotatsu.core.model.titleResId
import org.koitharu.kotatsu.core.nav.router
import org.koitharu.kotatsu.core.ui.sheet.BaseAdaptiveSheet
import org.koitharu.kotatsu.core.ui.widgets.ChipsView
import org.koitharu.kotatsu.core.util.ext.consume
import org.koitharu.kotatsu.core.util.ext.getDisplayName
import org.koitharu.kotatsu.core.util.ext.observe
import org.koitharu.kotatsu.core.util.ext.tryLaunch
@ -53,6 +56,14 @@ class WelcomeSheet : BaseAdaptiveSheet<SheetWelcomeBinding>(), ChipsView.OnChipC
viewModel.types.observe(viewLifecycleOwner, ::onTypesChanged)
}
override fun onApplyWindowInsets(v: View, insets: WindowInsetsCompat): WindowInsetsCompat {
val typeMask = WindowInsetsCompat.Type.systemBars()
viewBinding?.scrollView?.updatePadding(
bottom = insets.getInsets(typeMask).bottom,
)
return insets.consume(v, typeMask, bottom = true)
}
override fun onChipClick(chip: Chip, data: Any?) {
when (data) {
is ContentType -> viewModel.setTypeChecked(data, !chip.isChecked)

@ -2,10 +2,6 @@ package org.koitharu.kotatsu.reader.ui
import android.content.Intent
import android.os.Bundle
import android.transition.Fade
import android.transition.Slide
import android.transition.TransitionManager
import android.transition.TransitionSet
import android.view.Gravity
import android.view.KeyEvent
import android.view.MotionEvent
@ -14,8 +10,6 @@ import android.view.ViewGroup
import android.view.WindowManager
import androidx.activity.viewModels
import androidx.core.graphics.Insets
import androidx.core.view.OnApplyWindowInsetsListener
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.isGone
import androidx.core.view.isVisible
@ -23,6 +17,10 @@ import androidx.core.view.updateLayoutParams
import androidx.core.view.updatePadding
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.lifecycleScope
import androidx.transition.Fade
import androidx.transition.Slide
import androidx.transition.TransitionManager
import androidx.transition.TransitionSet
import com.google.android.material.snackbar.Snackbar
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.Dispatchers
@ -63,7 +61,6 @@ class ReaderActivity :
TapGridDispatcher.OnGridTouchListener,
ReaderConfigSheet.Callback,
ReaderControlDelegate.OnInteractionListener,
OnApplyWindowInsetsListener,
ReaderNavigationCallback,
IdlingDetector.Callback,
ZoomControl.ZoomControlListener {
@ -116,7 +113,6 @@ class ReaderActivity :
viewBinding.zoomControl.listener = this
viewBinding.actionsView.listener = this
idlingDetector.bindToLifecycle(this)
ViewCompat.setOnApplyWindowInsetsListener(viewBinding.root, this)
screenOrientationHelper.applySettings()
viewModel.onError.observeEvent(
@ -297,7 +293,9 @@ class ReaderActivity :
.setOrdering(TransitionSet.ORDERING_TOGETHER)
.addTransition(Slide(Gravity.TOP).addTarget(viewBinding.appbarTop))
.addTransition(Fade().addTarget(viewBinding.infoBar))
.addTransition(Slide(Gravity.BOTTOM).addTarget(viewBinding.toolbarDocked))
viewBinding.toolbarDocked?.let {
transition.addTransition(Slide(Gravity.BOTTOM).addTarget(it))
}
TransitionManager.beginDelayedTransition(viewBinding.root, transition)
}
val isFullscreen = settings.isReaderFullscreenEnabled

@ -3,10 +3,10 @@ package org.koitharu.kotatsu.reader.ui.colorfilter
import android.content.res.Resources
import android.graphics.Bitmap
import android.os.Bundle
import android.view.Gravity
import android.view.View
import android.widget.CompoundButton
import androidx.activity.viewModels
import androidx.core.view.WindowInsetsCompat
import coil3.ImageLoader
import coil3.request.ImageRequest
import coil3.request.bitmapConfig
@ -19,7 +19,7 @@ import com.google.android.material.slider.Slider
import dagger.hilt.android.AndroidEntryPoint
import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.ui.BaseActivity
import org.koitharu.kotatsu.core.util.ext.consumeInsetsAsPadding
import org.koitharu.kotatsu.core.util.ext.consumeAllSystemBarsInsets
import org.koitharu.kotatsu.core.util.ext.decodeRegion
import org.koitharu.kotatsu.core.util.ext.enqueueWith
import org.koitharu.kotatsu.core.util.ext.indicator
@ -28,6 +28,7 @@ import org.koitharu.kotatsu.core.util.ext.observe
import org.koitharu.kotatsu.core.util.ext.observeEvent
import org.koitharu.kotatsu.core.util.ext.setChecked
import org.koitharu.kotatsu.core.util.ext.setValueRounded
import org.koitharu.kotatsu.core.util.ext.systemBarsInsets
import org.koitharu.kotatsu.databinding.ActivityColorFilterBinding
import org.koitharu.kotatsu.parsers.model.MangaPage
import org.koitharu.kotatsu.parsers.util.format
@ -54,7 +55,6 @@ class ColorFilterConfigActivity :
setDisplayHomeAsUpEnabled(true)
setHomeAsUpIndicator(materialR.drawable.abc_ic_clear_material)
}
viewBinding.root.consumeInsetsAsPadding(Gravity.FILL)
viewBinding.sliderBrightness.addOnChangeListener(this)
viewBinding.sliderContrast.addOnChangeListener(this)
val formatter = PercentLabelFormatter(resources)
@ -75,6 +75,20 @@ class ColorFilterConfigActivity :
loadPreview(viewModel.preview)
}
override fun onApplyWindowInsets(
v: View,
insets: WindowInsetsCompat
): WindowInsetsCompat {
val barsInsets = insets.systemBarsInsets
viewBinding.root.setPadding(
barsInsets.left,
barsInsets.top,
barsInsets.right,
barsInsets.bottom,
)
return insets.consumeAllSystemBarsInsets()
}
override fun onValueChange(slider: Slider, value: Float, fromUser: Boolean) {
if (fromUser) {
when (slider.id) {

@ -5,8 +5,10 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.CompoundButton
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.isGone
import androidx.core.view.isVisible
import androidx.core.view.updatePadding
import androidx.fragment.app.activityViewModels
import androidx.lifecycle.lifecycleScope
import com.google.android.material.button.MaterialButtonToggleGroup
@ -25,6 +27,7 @@ import org.koitharu.kotatsu.core.prefs.AppSettings
import org.koitharu.kotatsu.core.prefs.ReaderMode
import org.koitharu.kotatsu.core.prefs.observeAsStateFlow
import org.koitharu.kotatsu.core.ui.sheet.BaseAdaptiveSheet
import org.koitharu.kotatsu.core.util.ext.consume
import org.koitharu.kotatsu.core.util.ext.findParentCallback
import org.koitharu.kotatsu.core.util.ext.observe
import org.koitharu.kotatsu.core.util.ext.viewLifecycleScope
@ -123,6 +126,14 @@ class ReaderConfigSheet :
}
}
override fun onApplyWindowInsets(v: View, insets: WindowInsetsCompat): WindowInsetsCompat {
val typeMask = WindowInsetsCompat.Type.systemBars()
viewBinding?.scrollView?.updatePadding(
bottom = insets.getInsets(typeMask).bottom,
)
return insets.consume(v, typeMask, bottom = true)
}
override fun onClick(v: View) {
when (v.id) {
R.id.button_settings -> {

@ -1,6 +1,8 @@
package org.koitharu.kotatsu.reader.ui.pager
import android.os.Bundle
import android.view.View
import androidx.core.view.WindowInsetsCompat
import androidx.fragment.app.activityViewModels
import androidx.viewbinding.ViewBinding
import org.koitharu.kotatsu.core.prefs.ReaderAnimation
@ -31,6 +33,8 @@ abstract class BaseReaderFragment<B : ViewBinding> : BaseFragment<B>(), ZoomCont
}
}
override fun onApplyWindowInsets(v: View, insets: WindowInsetsCompat): WindowInsetsCompat = insets
override fun onPause() {
super.onPause()
viewModel.saveCurrentState(getCurrentState())

@ -2,9 +2,10 @@ package org.koitharu.kotatsu.scrobbling.common.ui.config
import android.content.Intent
import android.os.Bundle
import android.view.Gravity
import android.view.View
import androidx.activity.viewModels
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.updatePadding
import coil3.ImageLoader
import coil3.request.error
import coil3.request.fallback
@ -16,13 +17,14 @@ import org.koitharu.kotatsu.core.exceptions.resolve.SnackbarErrorObserver
import org.koitharu.kotatsu.core.nav.router
import org.koitharu.kotatsu.core.ui.BaseActivity
import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener
import org.koitharu.kotatsu.core.util.ext.consumeInsetsAsPadding
import org.koitharu.kotatsu.core.util.ext.consumeAllSystemBarsInsets
import org.koitharu.kotatsu.core.util.ext.disposeImageRequest
import org.koitharu.kotatsu.core.util.ext.enqueueWith
import org.koitharu.kotatsu.core.util.ext.newImageRequest
import org.koitharu.kotatsu.core.util.ext.observe
import org.koitharu.kotatsu.core.util.ext.observeEvent
import org.koitharu.kotatsu.core.util.ext.showOrHide
import org.koitharu.kotatsu.core.util.ext.systemBarsInsets
import org.koitharu.kotatsu.databinding.ActivityScrobblerConfigBinding
import org.koitharu.kotatsu.list.ui.adapter.TypedListSpacingDecoration
import org.koitharu.kotatsu.scrobbling.common.domain.model.ScrobblerUser
@ -48,7 +50,6 @@ class ScrobblerConfigActivity : BaseActivity<ActivityScrobblerConfigBinding>(),
val listAdapter = ScrobblingMangaAdapter(this, coil, this)
with(viewBinding.recyclerView) {
consumeInsetsAsPadding(Gravity.START or Gravity.END or Gravity.BOTTOM)
adapter = listAdapter
setHasFixedSize(true)
val decoration = TypedListSpacingDecoration(context, false)
@ -73,6 +74,23 @@ class ScrobblerConfigActivity : BaseActivity<ActivityScrobblerConfigBinding>(),
processIntent(intent)
}
override fun onApplyWindowInsets(v: View, insets: WindowInsetsCompat): WindowInsetsCompat {
val barsInsets = insets.systemBarsInsets
val basePadding = v.resources.getDimensionPixelOffset(R.dimen.list_spacing_normal)
viewBinding.appbar.updatePadding(
top = barsInsets.top,
left = barsInsets.left,
right = barsInsets.right,
)
viewBinding.recyclerView.setPadding(
barsInsets.left + basePadding,
barsInsets.top + basePadding,
barsInsets.right + basePadding,
barsInsets.bottom + basePadding,
)
return insets.consumeAllSystemBarsInsets()
}
override fun onItemClick(item: ScrobblingInfo, view: View) {
router.openDetails(item.mangaId)
}

@ -7,6 +7,8 @@ import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.appcompat.widget.SearchView
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.updatePadding
import androidx.fragment.app.viewModels
import androidx.recyclerview.widget.AsyncListDiffer
import androidx.recyclerview.widget.RecyclerView.NO_ID
@ -22,6 +24,7 @@ import org.koitharu.kotatsu.core.ui.list.PaginationScrollListener
import org.koitharu.kotatsu.core.ui.sheet.BaseAdaptiveSheet
import org.koitharu.kotatsu.core.ui.util.CollapseActionViewCallback
import org.koitharu.kotatsu.core.util.RecyclerViewScrollCallback
import org.koitharu.kotatsu.core.util.ext.consume
import org.koitharu.kotatsu.core.util.ext.firstVisibleItemPosition
import org.koitharu.kotatsu.core.util.ext.getDisplayMessage
import org.koitharu.kotatsu.core.util.ext.observe
@ -114,6 +117,15 @@ class ScrobblingSelectorSheet :
paginationScrollListener = null
}
override fun onApplyWindowInsets(v: View, insets: WindowInsetsCompat): WindowInsetsCompat {
val typeMask = WindowInsetsCompat.Type.systemBars()
val basePadding = v.resources.getDimensionPixelOffset(R.dimen.list_spacing_normal)
viewBinding?.recyclerView?.updatePadding(
bottom = basePadding + insets.getInsets(typeMask).bottom,
)
return insets.consume(v, typeMask, bottom = true)
}
override fun onCurrentListChanged(previousList: MutableList<ListModel>, currentList: MutableList<ListModel>) {
if (previousList.singleOrNull() is LoadingFooter) {
val rv = viewBinding?.recyclerView ?: return

@ -4,13 +4,14 @@ import android.annotation.SuppressLint
import android.content.Intent
import android.os.Bundle
import android.text.Editable
import android.view.Gravity
import android.view.View
import androidx.core.net.toUri
import androidx.core.view.WindowInsetsCompat
import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.ui.BaseActivity
import org.koitharu.kotatsu.core.ui.util.DefaultTextWatcher
import org.koitharu.kotatsu.core.util.ext.consumeInsetsAsPadding
import org.koitharu.kotatsu.core.util.ext.consumeAllSystemBarsInsets
import org.koitharu.kotatsu.core.util.ext.systemBarsInsets
import org.koitharu.kotatsu.databinding.ActivityKitsuAuthBinding
import org.koitharu.kotatsu.parsers.util.urlEncoded
@ -21,13 +22,27 @@ class KitsuAuthActivity : BaseActivity<ActivityKitsuAuthBinding>(), View.OnClick
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(ActivityKitsuAuthBinding.inflate(layoutInflater))
viewBinding.root.consumeInsetsAsPadding(Gravity.FILL)
viewBinding.buttonCancel.setOnClickListener(this)
viewBinding.buttonDone.setOnClickListener(this)
viewBinding.editEmail.addTextChangedListener(this)
viewBinding.editPassword.addTextChangedListener(this)
}
override fun onApplyWindowInsets(
v: View,
insets: WindowInsetsCompat
): WindowInsetsCompat {
val barsInsets = insets.systemBarsInsets
val basePadding = resources.getDimensionPixelOffset(R.dimen.screen_padding)
viewBinding.root.setPadding(
barsInsets.left + basePadding,
barsInsets.top + basePadding,
barsInsets.right + basePadding,
barsInsets.bottom + basePadding,
)
return insets.consumeAllSystemBarsInsets()
}
override fun onClick(v: View) {
when (v.id) {
R.id.button_cancel -> finish()

@ -5,8 +5,6 @@ import android.view.View
import android.view.ViewGroup
import androidx.core.graphics.drawable.toDrawable
import androidx.core.os.bundleOf
import androidx.core.view.OnApplyWindowInsetsListener
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.updateLayoutParams
import androidx.core.view.updatePaddingRelative
@ -32,7 +30,7 @@ import org.koitharu.kotatsu.core.nav.router
import org.koitharu.kotatsu.core.ui.BaseActivity
import org.koitharu.kotatsu.core.ui.model.titleRes
import org.koitharu.kotatsu.core.util.ViewBadge
import org.koitharu.kotatsu.core.util.ext.consumeRelative
import org.koitharu.kotatsu.core.util.ext.consumeSystemBarsInsets
import org.koitharu.kotatsu.core.util.ext.end
import org.koitharu.kotatsu.core.util.ext.getParcelableExtraCompat
import org.koitharu.kotatsu.core.util.ext.getSerializableExtraCompat
@ -60,7 +58,6 @@ class MangaListActivity :
BaseActivity<ActivityMangaListBinding>(),
AppBarOwner, View.OnClickListener,
FilterCoordinator.Owner,
OnApplyWindowInsetsListener,
AppBarLayout.OnOffsetChangedListener {
override val appBar: AppBarLayout
@ -82,8 +79,6 @@ class MangaListActivity :
supportActionBar?.setDisplayHomeAsUpEnabled(true)
if (viewBinding.containerFilterHeader != null) {
viewBinding.appbar.addOnOffsetChangedListener(this)
} else {
ViewCompat.setOnApplyWindowInsetsListener(viewBinding.root, this)
}
viewBinding.buttonOrder?.setOnClickListener(this)
title = source.getTitle(this)
@ -113,17 +108,10 @@ class MangaListActivity :
}
viewBinding.appbar.updatePaddingRelative(
top = barsInsets.top,
end = if (viewBinding.cardSide == null) barsInsets.end(v) else 0,
start = barsInsets.start(v),
)
return WindowInsetsCompat.Builder(insets)
.setInsets(
WindowInsetsCompat.Type.systemBars(),
barsInsets.consumeRelative(
v,
top = true,
end = true,
),
).build()
return insets.consumeSystemBarsInsets(v, top = true, end = true)
}
override fun onClick(v: View) {

@ -1,13 +1,14 @@
package org.koitharu.kotatsu.search.ui.multi
import android.os.Bundle
import android.view.Gravity
import android.view.Menu
import android.view.MenuInflater
import android.view.MenuItem
import android.view.View
import androidx.activity.viewModels
import androidx.appcompat.view.ActionMode
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.updatePadding
import coil3.ImageLoader
import dagger.hilt.android.AndroidEntryPoint
import org.koitharu.kotatsu.R
@ -19,10 +20,11 @@ import org.koitharu.kotatsu.core.ui.list.ListSelectionController
import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener
import org.koitharu.kotatsu.core.ui.widgets.TipView
import org.koitharu.kotatsu.core.util.ShareHelper
import org.koitharu.kotatsu.core.util.ext.consumeInsetsAsPadding
import org.koitharu.kotatsu.core.util.ext.consumeAllSystemBarsInsets
import org.koitharu.kotatsu.core.util.ext.invalidateNestedItemDecorations
import org.koitharu.kotatsu.core.util.ext.observe
import org.koitharu.kotatsu.core.util.ext.observeEvent
import org.koitharu.kotatsu.core.util.ext.systemBarsInsets
import org.koitharu.kotatsu.databinding.ActivitySearchBinding
import org.koitharu.kotatsu.list.domain.ListFilterOption
import org.koitharu.kotatsu.list.ui.MangaSelectionDecoration
@ -91,7 +93,6 @@ class SearchActivity :
selectionDecoration = selectionDecoration,
)
viewBinding.recyclerView.adapter = adapter
viewBinding.recyclerView.consumeInsetsAsPadding(Gravity.START or Gravity.END or Gravity.BOTTOM)
viewBinding.recyclerView.setHasFixedSize(true)
viewBinding.recyclerView.addItemDecoration(TypedListSpacingDecoration(this, true))
@ -106,6 +107,22 @@ class SearchActivity :
viewModel.onError.observeEvent(this, SnackbarErrorObserver(viewBinding.recyclerView, null))
}
override fun onApplyWindowInsets(v: View, insets: WindowInsetsCompat): WindowInsetsCompat {
val barsInsets = insets.systemBarsInsets
viewBinding.appbar.updatePadding(
top = barsInsets.top,
left = barsInsets.left,
right = barsInsets.right,
)
viewBinding.recyclerView.setPadding(
barsInsets.left,
barsInsets.top,
barsInsets.right,
barsInsets.bottom,
)
return insets.consumeAllSystemBarsInsets()
}
override fun onItemClick(item: Manga, view: View) {
if (!selectionController.onItemClick(item.id)) {
router.openDetails(item)

@ -1,9 +1,10 @@
package org.koitharu.kotatsu.search.ui.suggestion
import android.os.Bundle
import android.view.Gravity
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.core.view.WindowInsetsCompat
import androidx.fragment.app.activityViewModels
import androidx.recyclerview.widget.ItemTouchHelper
import coil3.ImageLoader
@ -11,7 +12,7 @@ import dagger.hilt.android.AndroidEntryPoint
import org.koitharu.kotatsu.core.os.VoiceInputContract
import org.koitharu.kotatsu.core.ui.BaseFragment
import org.koitharu.kotatsu.core.util.ext.addMenuProvider
import org.koitharu.kotatsu.core.util.ext.consumeInsetsAsPadding
import org.koitharu.kotatsu.core.util.ext.consumeAllSystemBarsInsets
import org.koitharu.kotatsu.core.util.ext.observe
import org.koitharu.kotatsu.databinding.FragmentSearchSuggestionBinding
import org.koitharu.kotatsu.search.ui.suggestion.adapter.SearchSuggestionAdapter
@ -47,12 +48,22 @@ class SearchSuggestionFragment :
addMenuProvider(SearchSuggestionMenuProvider(binding.root.context, voiceInputLauncher, viewModel))
binding.root.adapter = adapter
binding.root.setHasFixedSize(true)
binding.root.consumeInsetsAsPadding(Gravity.BOTTOM or Gravity.START or Gravity.END)
viewModel.suggestion.observe(viewLifecycleOwner, adapter)
ItemTouchHelper(SearchSuggestionItemCallback(this))
.attachToRecyclerView(binding.root)
}
override fun onApplyWindowInsets(v: View, insets: WindowInsetsCompat): WindowInsetsCompat {
val barsInsets = insets.getInsets(WindowInsetsCompat.Type.ime() or WindowInsetsCompat.Type.systemBars())
v.setPadding(
barsInsets.left,
0,
barsInsets.right,
barsInsets.bottom,
)
return insets.consumeAllSystemBarsInsets()
}
override fun onRemoveQuery(query: String) {
viewModel.deleteQuery(query)
}

@ -5,8 +5,6 @@ import android.os.Bundle
import android.view.View
import android.view.ViewGroup
import androidx.activity.viewModels
import androidx.core.view.OnApplyWindowInsetsListener
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.isVisible
import androidx.core.view.updateLayoutParams
@ -45,7 +43,6 @@ import org.koitharu.kotatsu.settings.userdata.UserDataSettingsFragment
@AndroidEntryPoint
class SettingsActivity :
BaseActivity<ActivitySettingsBinding>(),
OnApplyWindowInsetsListener,
PreferenceFragmentCompat.OnPreferenceStartFragmentCallback,
AppBarOwner {
@ -60,7 +57,6 @@ class SettingsActivity :
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(ActivitySettingsBinding.inflate(layoutInflater))
ViewCompat.setOnApplyWindowInsetsListener(viewBinding.root, this)
supportActionBar?.setDisplayHomeAsUpEnabled(true)
val fm = supportFragmentManager
val currentFragment = fm.findFragmentById(R.id.container)

@ -15,6 +15,7 @@ import androidx.activity.result.contract.ActivityResultContracts
import androidx.activity.viewModels
import androidx.core.content.ContextCompat
import androidx.core.text.buildSpannedString
import androidx.core.view.WindowInsetsCompat
import com.google.android.material.snackbar.Snackbar
import dagger.hilt.android.AndroidEntryPoint
import io.noties.markwon.Markwon
@ -26,12 +27,14 @@ import org.koitharu.kotatsu.core.github.AppVersion
import org.koitharu.kotatsu.core.nav.router
import org.koitharu.kotatsu.core.ui.BaseActivity
import org.koitharu.kotatsu.core.util.FileSize
import org.koitharu.kotatsu.core.util.ext.consumeAllSystemBarsInsets
import org.koitharu.kotatsu.core.util.ext.getDisplayMessage
import org.koitharu.kotatsu.core.util.ext.observe
import org.koitharu.kotatsu.core.util.ext.observeEvent
import org.koitharu.kotatsu.core.util.ext.printStackTraceDebug
import org.koitharu.kotatsu.core.util.ext.setTextAndVisible
import org.koitharu.kotatsu.core.util.ext.showOrHide
import org.koitharu.kotatsu.core.util.ext.systemBarsInsets
import org.koitharu.kotatsu.core.util.ext.textAndVisible
import org.koitharu.kotatsu.databinding.ActivityAppUpdateBinding
@ -83,6 +86,21 @@ class AppUpdateActivity : BaseActivity<ActivityAppUpdateBinding>(), View.OnClick
super.onDestroy()
}
override fun onApplyWindowInsets(
v: View,
insets: WindowInsetsCompat
): WindowInsetsCompat {
val barsInsets = insets.systemBarsInsets
val basePadding = resources.getDimensionPixelOffset(R.dimen.screen_padding)
viewBinding.root.setPadding(
barsInsets.left + basePadding,
barsInsets.top + basePadding,
barsInsets.right + basePadding,
barsInsets.bottom + basePadding,
)
return insets.consumeAllSystemBarsInsets()
}
override fun onClick(v: View) {
when (v.id) {
R.id.button_cancel -> finishAfterTransition()

@ -5,6 +5,7 @@ import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.core.view.WindowInsetsCompat
import androidx.fragment.app.viewModels
import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.RecyclerView
@ -17,7 +18,12 @@ import org.koitharu.kotatsu.core.ui.dialog.buildAlertDialog
import org.koitharu.kotatsu.core.ui.dialog.setRecyclerViewList
import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener
import org.koitharu.kotatsu.core.ui.util.RecyclerViewOwner
import org.koitharu.kotatsu.core.util.ext.consumeAllSystemBarsInsets
import org.koitharu.kotatsu.core.util.ext.container
import org.koitharu.kotatsu.core.util.ext.end
import org.koitharu.kotatsu.core.util.ext.observe
import org.koitharu.kotatsu.core.util.ext.start
import org.koitharu.kotatsu.core.util.ext.systemBarsInsets
import org.koitharu.kotatsu.databinding.FragmentSettingsSourcesBinding
import org.koitharu.kotatsu.list.ui.adapter.ListItemType
import org.koitharu.kotatsu.list.ui.model.ListModel
@ -60,6 +66,19 @@ class NavConfigFragment : BaseFragment<FragmentSettingsSourcesBinding>(), Recycl
viewModel.content.observe(viewLifecycleOwner, navConfigAdapter)
}
override fun onApplyWindowInsets(v: View, insets: WindowInsetsCompat): WindowInsetsCompat {
val barsInsets = insets.systemBarsInsets
val isTablet = !resources.getBoolean(R.bool.is_tablet)
val isMaster = container?.id == R.id.container_master
v.setPaddingRelative(
if (isTablet && !isMaster) 0 else barsInsets.start(v),
0,
if (isTablet && isMaster) 0 else barsInsets.end(v),
barsInsets.bottom,
)
return insets.consumeAllSystemBarsInsets()
}
override fun onResume() {
super.onResume()
activity?.setTitle(R.string.main_screen_sections)

@ -4,7 +4,6 @@ import android.content.pm.PackageManager
import android.os.Build
import android.os.Bundle
import android.text.Editable
import android.view.Gravity
import android.view.KeyEvent
import android.view.View
import android.view.WindowManager
@ -12,15 +11,17 @@ import android.view.inputmethod.EditorInfo
import android.widget.CompoundButton
import android.widget.TextView
import androidx.activity.viewModels
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.isGone
import androidx.core.view.isVisible
import dagger.hilt.android.AndroidEntryPoint
import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.ui.BaseActivity
import org.koitharu.kotatsu.core.ui.util.DefaultTextWatcher
import org.koitharu.kotatsu.core.util.ext.consumeInsetsAsPadding
import org.koitharu.kotatsu.core.util.ext.consumeAllSystemBarsInsets
import org.koitharu.kotatsu.core.util.ext.observe
import org.koitharu.kotatsu.core.util.ext.observeEvent
import org.koitharu.kotatsu.core.util.ext.systemBarsInsets
import org.koitharu.kotatsu.databinding.ActivitySetupProtectBinding
private const val MIN_PASSWORD_LENGTH = 4
@ -39,7 +40,6 @@ class ProtectSetupActivity :
super.onCreate(savedInstanceState)
window.addFlags(WindowManager.LayoutParams.FLAG_SECURE)
setContentView(ActivitySetupProtectBinding.inflate(layoutInflater))
viewBinding.root.consumeInsetsAsPadding(Gravity.FILL)
viewBinding.editPassword.addTextChangedListener(this)
viewBinding.editPassword.setOnEditorActionListener(this)
viewBinding.buttonNext.setOnClickListener(this)
@ -60,6 +60,18 @@ class ProtectSetupActivity :
}
}
override fun onApplyWindowInsets(v: View, insets: WindowInsetsCompat): WindowInsetsCompat {
val barsInsets = insets.systemBarsInsets
val basePadding = resources.getDimensionPixelOffset(R.dimen.screen_padding)
viewBinding.root.setPadding(
barsInsets.left + basePadding,
barsInsets.top + basePadding,
barsInsets.right + basePadding,
barsInsets.bottom + basePadding,
)
return insets.consumeAllSystemBarsInsets()
}
override fun onClick(v: View) {
when (v.id) {
R.id.button_cancel -> finish()

@ -4,7 +4,6 @@ import android.content.DialogInterface
import android.graphics.drawable.Drawable
import android.graphics.drawable.LayerDrawable
import android.os.Bundle
import android.view.Gravity
import android.view.Menu
import android.view.MenuItem
import android.view.View
@ -14,14 +13,16 @@ import androidx.core.graphics.ColorUtils
import androidx.core.graphics.drawable.toDrawable
import androidx.core.text.bold
import androidx.core.text.buildSpannedString
import androidx.core.view.WindowInsetsCompat
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import dagger.hilt.android.AndroidEntryPoint
import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.ui.BaseActivity
import org.koitharu.kotatsu.core.util.ext.consumeInsetsAsPadding
import org.koitharu.kotatsu.core.util.ext.consumeAllSystemBarsInsets
import org.koitharu.kotatsu.core.util.ext.findKeyByValue
import org.koitharu.kotatsu.core.util.ext.getThemeDrawable
import org.koitharu.kotatsu.core.util.ext.observe
import org.koitharu.kotatsu.core.util.ext.systemBarsInsets
import org.koitharu.kotatsu.databinding.ActivityReaderTapActionsBinding
import org.koitharu.kotatsu.reader.domain.TapGridArea
import org.koitharu.kotatsu.reader.ui.tapgrid.TapAction
@ -39,7 +40,6 @@ class ReaderTapGridConfigActivity : BaseActivity<ActivityReaderTapActionsBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(ActivityReaderTapActionsBinding.inflate(layoutInflater))
viewBinding.root.consumeInsetsAsPadding(Gravity.FILL)
supportActionBar?.setDisplayHomeAsUpEnabled(true)
controls[TapGridArea.TOP_LEFT] = viewBinding.textViewTopLeft
controls[TapGridArea.TOP_CENTER] = viewBinding.textViewTopCenter
@ -59,6 +59,17 @@ class ReaderTapGridConfigActivity : BaseActivity<ActivityReaderTapActionsBinding
viewModel.content.observe(this, ::onContentChanged)
}
override fun onApplyWindowInsets(v: View, insets: WindowInsetsCompat): WindowInsetsCompat {
val barsInsets = insets.systemBarsInsets
viewBinding.root.setPadding(
barsInsets.left,
barsInsets.top,
barsInsets.right,
barsInsets.bottom,
)
return insets.consumeAllSystemBarsInsets()
}
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
menuInflater.inflate(R.menu.opt_tap_grid_config, menu)
return super.onCreateOptionsMenu(menu)

@ -1,10 +1,10 @@
package org.koitharu.kotatsu.settings.search
import android.os.Bundle
import android.view.Gravity
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.core.view.WindowInsetsCompat
import androidx.fragment.app.activityViewModels
import androidx.recyclerview.widget.AsyncListDiffer.ListListener
import androidx.recyclerview.widget.LinearLayoutManager
@ -12,7 +12,7 @@ import dagger.hilt.android.AndroidEntryPoint
import org.koitharu.kotatsu.core.ui.BaseFragment
import org.koitharu.kotatsu.core.ui.BaseListAdapter
import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener
import org.koitharu.kotatsu.core.util.ext.consumeInsetsAsPadding
import org.koitharu.kotatsu.core.util.ext.consumeAll
import org.koitharu.kotatsu.core.util.ext.observe
import org.koitharu.kotatsu.databinding.FragmentSearchSuggestionBinding
import org.koitharu.kotatsu.list.ui.adapter.ListItemType
@ -30,7 +30,6 @@ class SettingsSearchFragment : BaseFragment<FragmentSearchSuggestionBinding>(),
override fun onViewBindingCreated(binding: FragmentSearchSuggestionBinding, savedInstanceState: Bundle?) {
super.onViewBindingCreated(binding, savedInstanceState)
binding.root.consumeInsetsAsPadding(Gravity.FILL_HORIZONTAL or Gravity.BOTTOM)
val adapter = BaseListAdapter<SettingsItem>()
.addDelegate(ListItemType.NAV_ITEM, settingsItemAD(this))
adapter.addListListener(this)
@ -39,6 +38,18 @@ class SettingsSearchFragment : BaseFragment<FragmentSearchSuggestionBinding>(),
viewModel.content.observe(viewLifecycleOwner, adapter)
}
override fun onApplyWindowInsets(v: View, insets: WindowInsetsCompat): WindowInsetsCompat {
val type = WindowInsetsCompat.Type.ime() or WindowInsetsCompat.Type.systemBars()
val barsInsets = insets.getInsets(type)
v.setPadding(
barsInsets.left,
0,
barsInsets.right,
barsInsets.bottom,
)
return insets.consumeAll(type)
}
override fun onItemClick(item: SettingsItem, view: View) = viewModel.navigateToPreference(item)
override fun onCurrentListChanged(

@ -5,9 +5,12 @@ import android.content.Context
import android.content.Intent
import android.os.Bundle
import android.view.MenuItem
import android.view.View
import android.widget.Toast
import androidx.activity.result.contract.ActivityResultContract
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.isVisible
import androidx.core.view.updatePadding
import dagger.hilt.android.AndroidEntryPoint
import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.browser.BrowserCallback
@ -21,6 +24,7 @@ import org.koitharu.kotatsu.core.parser.MangaRepository
import org.koitharu.kotatsu.core.parser.ParserMangaRepository
import org.koitharu.kotatsu.core.ui.BaseActivity
import org.koitharu.kotatsu.core.util.ext.configureForParser
import org.koitharu.kotatsu.core.util.ext.consumeAll
import org.koitharu.kotatsu.databinding.ActivityBrowserBinding
import org.koitharu.kotatsu.parsers.MangaParserAuthProvider
import org.koitharu.kotatsu.parsers.model.MangaParserSource
@ -84,6 +88,25 @@ class SourceAuthActivity : BaseActivity<ActivityBrowserBinding>(), BrowserCallba
viewBinding.webView.destroy()
}
override fun onApplyWindowInsets(
v: View,
insets: WindowInsetsCompat
): WindowInsetsCompat {
val type = WindowInsetsCompat.Type.systemBars() or WindowInsetsCompat.Type.ime()
val barsInsets = insets.getInsets(type)
viewBinding.webView.updatePadding(
left = barsInsets.left,
right = barsInsets.right,
bottom = barsInsets.bottom,
)
viewBinding.appbar.updatePadding(
left = barsInsets.left,
right = barsInsets.right,
top = barsInsets.top,
)
return insets.consumeAll(type)
}
override fun onOptionsItemSelected(item: MenuItem): Boolean = when (item.itemId) {
android.R.id.home -> {
viewBinding.webView.stopLoading()

@ -8,8 +8,6 @@ import androidx.activity.viewModels
import androidx.appcompat.widget.PopupMenu
import androidx.appcompat.widget.SearchView
import androidx.core.graphics.Insets
import androidx.core.view.OnApplyWindowInsetsListener
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.updatePadding
import coil3.ImageLoader
@ -40,7 +38,6 @@ import javax.inject.Inject
@AndroidEntryPoint
class SourcesCatalogActivity : BaseActivity<ActivitySourcesCatalogBinding>(),
OnListItemClickListener<SourceCatalogItem.Source>,
OnApplyWindowInsetsListener,
AppBarOwner,
MenuItem.OnActionExpandListener,
ChipsView.OnChipClickListener {
@ -57,7 +54,6 @@ class SourcesCatalogActivity : BaseActivity<ActivitySourcesCatalogBinding>(),
super.onCreate(savedInstanceState)
setContentView(ActivitySourcesCatalogBinding.inflate(layoutInflater))
supportActionBar?.setDisplayHomeAsUpEnabled(true)
ViewCompat.setOnApplyWindowInsetsListener(viewBinding.root, this)
val sourcesAdapter = SourcesCatalogAdapter(this, coil, this)
with(viewBinding.recyclerView) {
setHasFixedSize(true)

@ -1,14 +1,15 @@
package org.koitharu.kotatsu.settings.sources.manage
import android.os.Bundle
import android.view.Gravity
import android.view.LayoutInflater
import android.view.Menu
import android.view.MenuInflater
import android.view.MenuItem
import android.view.View
import android.view.ViewGroup
import androidx.appcompat.widget.SearchView
import androidx.core.view.MenuProvider
import androidx.core.view.WindowInsetsCompat
import androidx.fragment.app.viewModels
import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.RecyclerView
@ -23,10 +24,14 @@ import org.koitharu.kotatsu.core.ui.BaseFragment
import org.koitharu.kotatsu.core.ui.util.RecyclerViewOwner
import org.koitharu.kotatsu.core.ui.util.ReversibleActionObserver
import org.koitharu.kotatsu.core.util.ext.addMenuProvider
import org.koitharu.kotatsu.core.util.ext.consumeInsetsAsPadding
import org.koitharu.kotatsu.core.util.ext.consumeAllSystemBarsInsets
import org.koitharu.kotatsu.core.util.ext.container
import org.koitharu.kotatsu.core.util.ext.end
import org.koitharu.kotatsu.core.util.ext.getItem
import org.koitharu.kotatsu.core.util.ext.observe
import org.koitharu.kotatsu.core.util.ext.observeEvent
import org.koitharu.kotatsu.core.util.ext.start
import org.koitharu.kotatsu.core.util.ext.systemBarsInsets
import org.koitharu.kotatsu.core.util.ext.viewLifecycleScope
import org.koitharu.kotatsu.databinding.FragmentSettingsSourcesBinding
import org.koitharu.kotatsu.main.ui.owners.AppBarOwner
@ -72,7 +77,6 @@ class SourcesManageFragment :
sourcesAdapter = SourceConfigAdapter(this, coil, viewLifecycleOwner)
with(binding.recyclerView) {
setHasFixedSize(true)
consumeInsetsAsPadding(Gravity.START or Gravity.END or Gravity.BOTTOM)
adapter = sourcesAdapter
reorderHelper = ItemTouchHelper(SourcesReorderCallback()).also {
it.attachToRecyclerView(this)
@ -86,6 +90,19 @@ class SourcesManageFragment :
addMenuProvider(SourcesMenuProvider())
}
override fun onApplyWindowInsets(v: View, insets: WindowInsetsCompat): WindowInsetsCompat {
val barsInsets = insets.systemBarsInsets
val isTablet = !resources.getBoolean(R.bool.is_tablet)
val isMaster = container?.id == R.id.container_master
v.setPaddingRelative(
if (isTablet && !isMaster) 0 else barsInsets.start(v),
0,
if (isTablet && isMaster) 0 else barsInsets.end(v),
barsInsets.bottom,
)
return insets.consumeAllSystemBarsInsets()
}
override fun onResume() {
super.onResume()
activity?.setTitle(R.string.manage_sources)

@ -8,9 +8,6 @@ import android.view.View
import android.view.ViewGroup
import androidx.activity.result.contract.ActivityResultContracts
import androidx.activity.viewModels
import androidx.core.graphics.Insets
import androidx.core.view.OnApplyWindowInsetsListener
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.isVisible
import androidx.core.view.updateLayoutParams
@ -23,6 +20,7 @@ import org.koitharu.kotatsu.core.exceptions.resolve.SnackbarErrorObserver
import org.koitharu.kotatsu.core.os.OpenDocumentTreeHelper
import org.koitharu.kotatsu.core.ui.BaseActivity
import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener
import org.koitharu.kotatsu.core.util.ext.consumeAllSystemBarsInsets
import org.koitharu.kotatsu.core.util.ext.observe
import org.koitharu.kotatsu.core.util.ext.observeEvent
import org.koitharu.kotatsu.core.util.ext.tryLaunch
@ -33,7 +31,7 @@ import org.koitharu.kotatsu.settings.storage.RequestStorageManagerPermissionCont
@AndroidEntryPoint
class MangaDirectoriesActivity : BaseActivity<ActivityMangaDirectoriesBinding>(),
OnListItemClickListener<DirectoryModel>, View.OnClickListener, OnApplyWindowInsetsListener {
OnListItemClickListener<DirectoryModel>, View.OnClickListener {
private val viewModel: MangaDirectoriesViewModel by viewModels()
private val pickFileTreeLauncher = OpenDocumentTreeHelper(
@ -64,7 +62,6 @@ class MangaDirectoriesActivity : BaseActivity<ActivityMangaDirectoriesBinding>()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(ActivityMangaDirectoriesBinding.inflate(layoutInflater))
ViewCompat.setOnApplyWindowInsetsListener(viewBinding.root, this)
supportActionBar?.setDisplayHomeAsUpEnabled(true)
val adapter = AsyncListDifferDelegationAdapter(DirectoryDiffCallback(), directoryConfigAD(this))
viewBinding.recyclerView.adapter = adapter
@ -105,8 +102,6 @@ class MangaDirectoriesActivity : BaseActivity<ActivityMangaDirectoriesBinding>()
viewBinding.recyclerView.updatePadding(
bottom = barsInsets.bottom,
)
return WindowInsetsCompat.Builder(insets)
.setInsets(WindowInsetsCompat.Type.systemBars(), Insets.NONE)
.build()
return insets.consumeAllSystemBarsInsets()
}
}

@ -4,12 +4,15 @@ import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.updatePadding
import androidx.fragment.app.viewModels
import dagger.hilt.android.AndroidEntryPoint
import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.model.FavouriteCategory
import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener
import org.koitharu.kotatsu.core.ui.sheet.BaseAdaptiveSheet
import org.koitharu.kotatsu.core.util.ext.consume
import org.koitharu.kotatsu.core.util.ext.observe
import org.koitharu.kotatsu.databinding.SheetBaseBinding
@ -33,6 +36,14 @@ class TrackerCategoriesConfigSheet :
viewModel.content.observe(viewLifecycleOwner, adapter)
}
override fun onApplyWindowInsets(v: View, insets: WindowInsetsCompat): WindowInsetsCompat {
val typeMask = WindowInsetsCompat.Type.systemBars()
viewBinding?.recyclerView?.updatePadding(
bottom = insets.getInsets(typeMask).bottom,
)
return insets.consume(v, typeMask, bottom = true)
}
override fun onItemClick(item: FavouriteCategory, view: View) {
viewModel.toggleItem(item)
}

@ -10,8 +10,6 @@ import android.widget.CompoundButton
import androidx.activity.viewModels
import androidx.appcompat.widget.PopupMenu
import androidx.core.graphics.Insets
import androidx.core.view.OnApplyWindowInsetsListener
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.isGone
import androidx.core.view.isVisible
@ -50,7 +48,6 @@ import javax.inject.Inject
@AndroidEntryPoint
class StatsActivity : BaseActivity<ActivityStatsBinding>(),
OnApplyWindowInsetsListener,
OnListItemClickListener<Manga>,
PieChartView.OnSegmentClickListener,
AsyncListDiffer.ListListener<StatsRecord>,
@ -67,7 +64,6 @@ class StatsActivity : BaseActivity<ActivityStatsBinding>(),
super.onCreate(savedInstanceState)
setContentView(ActivityStatsBinding.inflate(layoutInflater))
supportActionBar?.setDisplayHomeAsUpEnabled(true)
ViewCompat.setOnApplyWindowInsetsListener(viewBinding.root, this)
val adapter = BaseListAdapter<StatsRecord>()
.addDelegate(ListItemType.FEED, statsAD(this))
.addListListener(this)

@ -5,12 +5,15 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.collection.IntList
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.updatePadding
import androidx.fragment.app.viewModels
import dagger.hilt.android.AndroidEntryPoint
import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.nav.router
import org.koitharu.kotatsu.core.ui.sheet.BaseAdaptiveSheet
import org.koitharu.kotatsu.core.util.KotatsuColors
import org.koitharu.kotatsu.core.util.ext.consume
import org.koitharu.kotatsu.core.util.ext.observe
import org.koitharu.kotatsu.core.util.ext.textAndVisible
import org.koitharu.kotatsu.databinding.SheetStatsMangaBinding
@ -40,6 +43,14 @@ class MangaStatsSheet : BaseAdaptiveSheet<SheetStatsMangaBinding>(), View.OnClic
binding.buttonOpen.setOnClickListener(this)
}
override fun onApplyWindowInsets(v: View, insets: WindowInsetsCompat): WindowInsetsCompat {
val typeMask = WindowInsetsCompat.Type.systemBars()
viewBinding?.scrollView?.updatePadding(
bottom = insets.getInsets(typeMask).bottom,
)
return insets.consume(v, typeMask, bottom = true)
}
override fun onClick(v: View) {
router.openDetails(viewModel.manga)
}

@ -6,12 +6,12 @@ import android.accounts.AccountManager
import android.os.Bundle
import android.text.Editable
import android.text.TextWatcher
import android.view.Gravity
import android.view.View
import android.widget.Button
import android.widget.Toast
import androidx.activity.OnBackPressedCallback
import androidx.activity.viewModels
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.isVisible
import androidx.fragment.app.FragmentResultListener
import androidx.transition.Fade
@ -21,11 +21,12 @@ import dagger.hilt.android.AndroidEntryPoint
import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.ui.BaseActivity
import org.koitharu.kotatsu.core.ui.util.DefaultTextWatcher
import org.koitharu.kotatsu.core.util.ext.consumeInsetsAsPadding
import org.koitharu.kotatsu.core.util.ext.consumeAllSystemBarsInsets
import org.koitharu.kotatsu.core.util.ext.getDisplayMessage
import org.koitharu.kotatsu.core.util.ext.getParcelableExtraCompat
import org.koitharu.kotatsu.core.util.ext.observe
import org.koitharu.kotatsu.core.util.ext.observeEvent
import org.koitharu.kotatsu.core.util.ext.systemBarsInsets
import org.koitharu.kotatsu.databinding.ActivitySyncAuthBinding
import org.koitharu.kotatsu.sync.data.SyncSettings
import org.koitharu.kotatsu.sync.domain.SyncAuthResult
@ -42,7 +43,6 @@ class SyncAuthActivity : BaseActivity<ActivitySyncAuthBinding>(), View.OnClickLi
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(ActivitySyncAuthBinding.inflate(layoutInflater))
viewBinding.root.consumeInsetsAsPadding(Gravity.FILL)
accountAuthenticatorResponse =
intent.getParcelableExtraCompat(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE)
accountAuthenticatorResponse?.onRequestContinued()
@ -68,6 +68,18 @@ class SyncAuthActivity : BaseActivity<ActivitySyncAuthBinding>(), View.OnClickLi
pageBackCallback.update()
}
override fun onApplyWindowInsets(v: View, insets: WindowInsetsCompat): WindowInsetsCompat {
val barsInsets = insets.systemBarsInsets
val basePadding = resources.getDimensionPixelOffset(R.dimen.screen_padding)
viewBinding.root.setPadding(
barsInsets.left + basePadding,
barsInsets.top + basePadding,
barsInsets.right + basePadding,
barsInsets.bottom + basePadding,
)
return insets.consumeAllSystemBarsInsets()
}
override fun onClick(v: View) {
when (v.id) {
R.id.button_cancel -> {

@ -1,17 +1,19 @@
package org.koitharu.kotatsu.tracker.ui.debug
import android.os.Bundle
import android.view.Gravity
import android.view.View
import androidx.activity.viewModels
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.updatePadding
import coil3.ImageLoader
import dagger.hilt.android.AndroidEntryPoint
import org.koitharu.kotatsu.core.nav.router
import org.koitharu.kotatsu.core.ui.BaseActivity
import org.koitharu.kotatsu.core.ui.BaseListAdapter
import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener
import org.koitharu.kotatsu.core.util.ext.consumeInsetsAsPadding
import org.koitharu.kotatsu.core.util.ext.consumeAllSystemBarsInsets
import org.koitharu.kotatsu.core.util.ext.observe
import org.koitharu.kotatsu.core.util.ext.systemBarsInsets
import org.koitharu.kotatsu.databinding.ActivityTrackerDebugBinding
import org.koitharu.kotatsu.list.ui.adapter.ListItemType
import org.koitharu.kotatsu.list.ui.adapter.TypedListSpacingDecoration
@ -32,7 +34,6 @@ class TrackerDebugActivity : BaseActivity<ActivityTrackerDebugBinding>(), OnList
val tracksAdapter = BaseListAdapter<TrackDebugItem>()
.addDelegate(ListItemType.FEED, trackDebugAD(this, coil, this))
with(viewBinding.recyclerView) {
consumeInsetsAsPadding(Gravity.START or Gravity.END or Gravity.BOTTOM)
setHasFixedSize(true)
adapter = tracksAdapter
addItemDecoration(TypedListSpacingDecoration(context, false))
@ -40,6 +41,21 @@ class TrackerDebugActivity : BaseActivity<ActivityTrackerDebugBinding>(), OnList
viewModel.content.observe(this, tracksAdapter)
}
override fun onApplyWindowInsets(v: View, insets: WindowInsetsCompat): WindowInsetsCompat {
val barsInsets = insets.systemBarsInsets
viewBinding.recyclerView.updatePadding(
left = barsInsets.left,
right = barsInsets.right,
bottom = barsInsets.bottom,
)
viewBinding.appbar.updatePadding(
left = barsInsets.left,
right = barsInsets.right,
top = barsInsets.top,
)
return insets.consumeAllSystemBarsInsets()
}
override fun onItemClick(item: TrackDebugItem, view: View) {
router.openDetails(item.manga)
}

@ -4,6 +4,7 @@ import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.core.view.WindowInsetsCompat
import androidx.fragment.app.viewModels
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
@ -22,6 +23,7 @@ import org.koitharu.kotatsu.core.ui.util.RecyclerViewOwner
import org.koitharu.kotatsu.core.ui.util.ReversibleActionObserver
import org.koitharu.kotatsu.core.ui.widgets.TipView
import org.koitharu.kotatsu.core.util.ext.addMenuProvider
import org.koitharu.kotatsu.core.util.ext.consumeAll
import org.koitharu.kotatsu.core.util.ext.observe
import org.koitharu.kotatsu.core.util.ext.observeEvent
import org.koitharu.kotatsu.databinding.FragmentListBinding
@ -83,6 +85,19 @@ class FeedFragment :
viewModel.isRunning.observe(viewLifecycleOwner, this::onIsTrackerRunningChanged)
}
override fun onApplyWindowInsets(v: View, insets: WindowInsetsCompat): WindowInsetsCompat {
val typeMask = WindowInsetsCompat.Type.systemBars()
val barsInsets = insets.getInsets(typeMask)
val basePadding = v.resources.getDimensionPixelOffset(R.dimen.list_spacing_normal)
viewBinding?.recyclerView?.setPadding(
left = barsInsets.left + basePadding,
top = basePadding,
right = barsInsets.right + basePadding,
bottom = barsInsets.bottom + basePadding,
)
return insets.consumeAll(typeMask)
}
override fun onRefresh() {
viewModel.update()
}

@ -3,13 +3,14 @@ package org.koitharu.kotatsu.widget.recent
import android.appwidget.AppWidgetManager
import android.content.Intent
import android.os.Bundle
import android.view.Gravity
import android.view.View
import androidx.core.view.WindowInsetsCompat
import dagger.hilt.android.AndroidEntryPoint
import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.prefs.AppWidgetConfig
import org.koitharu.kotatsu.core.ui.BaseActivity
import org.koitharu.kotatsu.core.util.ext.consumeInsetsAsPadding
import org.koitharu.kotatsu.core.util.ext.consumeAllSystemBarsInsets
import org.koitharu.kotatsu.core.util.ext.systemBarsInsets
import org.koitharu.kotatsu.databinding.ActivityAppwidgetRecentBinding
import com.google.android.material.R as materialR
@ -28,7 +29,6 @@ class RecentWidgetConfigActivity :
setHomeAsUpIndicator(materialR.drawable.abc_ic_clear_material)
}
viewBinding.buttonDone.setOnClickListener(this)
viewBinding.root.consumeInsetsAsPadding(Gravity.START or Gravity.END or Gravity.BOTTOM or Gravity.TOP)
val appWidgetId = intent?.getIntExtra(
AppWidgetManager.EXTRA_APPWIDGET_ID,
AppWidgetManager.INVALID_APPWIDGET_ID,
@ -41,6 +41,17 @@ class RecentWidgetConfigActivity :
viewBinding.switchBackground.isChecked = config.hasBackground
}
override fun onApplyWindowInsets(v: View, insets: WindowInsetsCompat): WindowInsetsCompat {
val barsInsets = insets.systemBarsInsets
viewBinding.root.setPadding(
barsInsets.left,
barsInsets.top,
barsInsets.right,
barsInsets.bottom,
)
return insets.consumeAllSystemBarsInsets()
}
override fun onClick(v: View) {
when (v.id) {
R.id.button_done -> {

@ -3,18 +3,20 @@ package org.koitharu.kotatsu.widget.shelf
import android.appwidget.AppWidgetManager
import android.content.Intent
import android.os.Bundle
import android.view.Gravity
import android.view.View
import androidx.activity.viewModels
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.updatePadding
import dagger.hilt.android.AndroidEntryPoint
import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.exceptions.resolve.SnackbarErrorObserver
import org.koitharu.kotatsu.core.prefs.AppWidgetConfig
import org.koitharu.kotatsu.core.ui.BaseActivity
import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener
import org.koitharu.kotatsu.core.util.ext.consumeInsetsAsPadding
import org.koitharu.kotatsu.core.util.ext.consumeAllSystemBarsInsets
import org.koitharu.kotatsu.core.util.ext.observe
import org.koitharu.kotatsu.core.util.ext.observeEvent
import org.koitharu.kotatsu.core.util.ext.systemBarsInsets
import org.koitharu.kotatsu.databinding.ActivityAppwidgetShelfBinding
import org.koitharu.kotatsu.widget.shelf.adapter.CategorySelectAdapter
import org.koitharu.kotatsu.widget.shelf.model.CategoryItem
@ -40,7 +42,6 @@ class ShelfWidgetConfigActivity :
}
adapter = CategorySelectAdapter(this)
viewBinding.recyclerView.adapter = adapter
viewBinding.recyclerView.consumeInsetsAsPadding(Gravity.START or Gravity.END or Gravity.BOTTOM)
viewBinding.buttonDone.setOnClickListener(this)
val appWidgetId = intent?.getIntExtra(
AppWidgetManager.EXTRA_APPWIDGET_ID,
@ -58,6 +59,21 @@ class ShelfWidgetConfigActivity :
viewModel.onError.observeEvent(this, SnackbarErrorObserver(viewBinding.recyclerView, null))
}
override fun onApplyWindowInsets(v: View, insets: WindowInsetsCompat): WindowInsetsCompat {
val barsInsets = insets.systemBarsInsets
viewBinding.recyclerView.updatePadding(
left = barsInsets.left,
right = barsInsets.right,
bottom = barsInsets.bottom,
)
viewBinding.appbar.updatePadding(
left = barsInsets.left,
right = barsInsets.right,
top = barsInsets.top,
)
return insets.consumeAllSystemBarsInsets()
}
override fun onClick(v: View) {
when (v.id) {
R.id.button_done -> {

@ -10,7 +10,7 @@
android:id="@+id/appbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fitsSystemWindows="true">
android:fitsSystemWindows="false">
<com.google.android.material.appbar.CollapsingToolbarLayout
android:id="@+id/collapsingToolbarLayout"

@ -10,7 +10,7 @@
android:id="@+id/appbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fitsSystemWindows="true">
android:fitsSystemWindows="false">
<com.google.android.material.appbar.MaterialToolbar
android:id="@id/toolbar"

@ -31,7 +31,7 @@
android:id="@+id/appbar"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:fitsSystemWindows="true"
android:fitsSystemWindows="false"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">

@ -10,7 +10,7 @@
android:id="@+id/appbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fitsSystemWindows="true">
android:fitsSystemWindows="false">
<com.google.android.material.appbar.CollapsingToolbarLayout
android:id="@+id/collapsingToolbarLayout"

@ -318,7 +318,7 @@
app:paddingBottomSystemWindowInsets="false"
tools:layout="@layout/sheet_chapters_pages" />
<org.koitharu.kotatsu.core.ui.widgets.WindowInsetHolder
<View
android:id="@+id/navbarDim"
android:layout_width="match_parent"
android:layout_height="wrap_content"

@ -37,7 +37,7 @@
android:id="@+id/toolbar_card"
android:layout_width="match_parent"
android:layout_height="56dp"
android:layout_marginTop="@dimen/margin_normal"
android:layout_marginTop="@dimen/margin_small"
android:layout_marginBottom="@dimen/margin_small"
android:background="@drawable/search_bar_background"
android:theme="@style/ThemeOverlay.Kotatsu.MainToolbar"

@ -10,7 +10,7 @@
android:id="@+id/appbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fitsSystemWindows="true">
android:fitsSystemWindows="false">
<com.google.android.material.appbar.CollapsingToolbarLayout
android:id="@+id/collapsingToolbarLayout"

@ -10,7 +10,7 @@
android:id="@+id/appbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fitsSystemWindows="true">
android:fitsSystemWindows="false">
<com.google.android.material.appbar.CollapsingToolbarLayout
android:id="@+id/collapsingToolbarLayout"

@ -13,12 +13,6 @@
app:elevation="0dp"
app:liftOnScroll="false">
<org.koitharu.kotatsu.core.ui.widgets.WindowInsetHolder
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="top"
app:layout_scrollFlags="scroll|enterAlways|snap" />
<com.google.android.material.appbar.MaterialToolbar
android:id="@id/toolbar"
android:layout_width="match_parent"

@ -10,7 +10,7 @@
android:id="@+id/appbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fitsSystemWindows="true">
android:fitsSystemWindows="false">
<com.google.android.material.appbar.CollapsingToolbarLayout
android:id="@+id/collapsingToolbarLayout"

@ -17,6 +17,7 @@
android:id="@+id/scrollView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="false"
android:scrollIndicators="top"
tools:ignore="UnusedAttribute">

@ -15,8 +15,10 @@
app:title="@string/list_options" />
<androidx.core.widget.NestedScrollView
android:id="@+id/scrollView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clipToPadding="false"
android:scrollIndicators="top"
android:scrollbars="vertical">

@ -14,8 +14,10 @@
app:title="@string/options" />
<androidx.core.widget.NestedScrollView
android:id="@+id/scrollView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clipToPadding="false"
android:scrollIndicators="top">
<LinearLayout

@ -4,7 +4,8 @@
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content">
android:layout_height="wrap_content"
android:clipToPadding="false">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"

@ -18,6 +18,7 @@
android:id="@+id/scrollView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clipToPadding="false"
android:scrollIndicators="top">
<LinearLayout

@ -15,7 +15,8 @@
<androidx.core.widget.NestedScrollView
android:id="@+id/scrollView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_height="wrap_content"
android:clipToPadding="false"
android:scrollIndicators="top">
<LinearLayout

@ -36,6 +36,13 @@
<style name="ThemeOverlay.Kotatsu.BottomSheetDialog" parent="ThemeOverlay.Material3.BottomSheetDialog">
<item name="android:windowAnimationStyle">@style/Animation.Kotatsu.BottomSheetDialog</item>
<item name="bottomSheetStyle">@style/Widget.Kotatsu.BottomSheet.Modal</item>
</style>
<style name="ThemeOverlay.Kotatsu.SideSheetDialog" parent="ThemeOverlay.Material3.SideSheetDialog" />
<style name="Widget.Kotatsu.BottomSheet.Modal" parent="Widget.Material3.BottomSheet.Modal">
<item name="paddingBottomSystemWindowInsets">false</item>
</style>
<style name="Widget.Kotatsu.BottomSheet.DragHandle" parent="Widget.Material3.BottomSheet.DragHandle">

@ -58,6 +58,7 @@
<item name="android:itemTextAppearance">@style/TextAppearance.Widget.Menu</item>
<item name="alertDialogTheme">@style/ThemeOverlay.Kotatsu.AlertDialog</item>
<item name="bottomSheetDialogTheme">@style/ThemeOverlay.Kotatsu.BottomSheetDialog</item>
<item name="sideSheetDialogTheme">@style/ThemeOverlay.Kotatsu.SideSheetDialog</item>
<item name="textAppearanceButton">@style/TextAppearance.Kotatsu.Button</item>
<item name="android:buttonStyle">?attr/borderlessButtonStyle</item>
<item name="android:backgroundDimAmount">0.32</item>

Loading…
Cancel
Save