Refactor: change window insets handling approach

master
Koitharu 1 year ago
parent a7caf9848e
commit b27d6dbe9a
Signed by: Koitharu
GPG Key ID: 676DEE768C17A9D7

@ -1,11 +1,10 @@
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.graphics.Insets
import androidx.core.view.updatePadding
import coil3.ImageLoader
import dagger.hilt.android.AndroidEntryPoint
import org.koitharu.kotatsu.R
@ -16,6 +15,7 @@ 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.observe
import org.koitharu.kotatsu.core.util.ext.observeEvent
import org.koitharu.kotatsu.databinding.ActivityAlternativesBinding
@ -50,6 +50,7 @@ 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
@ -64,16 +65,6 @@ class AlternativesActivity : BaseActivity<ActivityAlternativesBinding>(),
}
}
override fun onWindowInsetsChanged(insets: Insets) {
viewBinding.root.updatePadding(
left = insets.left,
right = insets.right,
)
viewBinding.recyclerView.updatePadding(
bottom = insets.bottom + viewBinding.recyclerView.paddingTop,
)
}
override fun onItemClick(item: MangaAlternativeModel, view: View) {
when (view.id) {
R.id.chip_source -> router.openSearch(item.manga.source, viewModel.manga.title)

@ -2,8 +2,6 @@ package org.koitharu.kotatsu.bookmarks.ui
import android.os.Bundle
import androidx.coordinatorlayout.widget.CoordinatorLayout
import androidx.core.graphics.Insets
import androidx.core.view.updatePadding
import androidx.fragment.app.commit
import com.google.android.material.appbar.AppBarLayout
import dagger.hilt.android.AndroidEntryPoint
@ -37,11 +35,4 @@ class AllBookmarksActivity :
}
}
}
override fun onWindowInsetsChanged(insets: Insets) {
viewBinding.root.updatePadding(
left = insets.left,
right = insets.right,
)
}
}

@ -1,6 +1,7 @@
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
@ -9,9 +10,6 @@ import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.appcompat.view.ActionMode
import androidx.core.graphics.Insets
import androidx.core.view.updateLayoutParams
import androidx.core.view.updatePadding
import androidx.fragment.app.viewModels
import androidx.recyclerview.widget.GridLayoutManager
import coil3.ImageLoader
@ -28,6 +26,7 @@ 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.findAppCompatDelegate
import org.koitharu.kotatsu.core.util.ext.observe
import org.koitharu.kotatsu.core.util.ext.observeEvent
@ -86,6 +85,7 @@ 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))
@ -177,16 +177,6 @@ class AllBookmarksFragment :
}
}
override fun onWindowInsetsChanged(insets: Insets) {
val rv = requireViewBinding().recyclerView
rv.updatePadding(
bottom = insets.bottom + rv.paddingTop,
)
rv.fastScroller.updateLayoutParams<ViewGroup.MarginLayoutParams> {
bottomMargin = insets.bottom
}
}
private inner class SpanSizeLookup : GridLayoutManager.SpanSizeLookup(), Runnable {
init {

@ -1,11 +1,10 @@
package org.koitharu.kotatsu.browser
import android.os.Bundle
import android.view.Gravity
import android.view.Menu
import android.view.MenuItem
import androidx.core.graphics.Insets
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
@ -17,6 +16,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.databinding.ActivityBrowserBinding
import javax.inject.Inject
import com.google.android.material.R as materialR
@ -42,6 +42,7 @@ 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)
@ -114,15 +115,4 @@ class BrowserActivity : BaseActivity<ActivityBrowserBinding>(), BrowserCallback
override fun onHistoryChanged() {
onBackPressedCallback.onHistoryChanged()
}
override fun onWindowInsetsChanged(insets: Insets) {
viewBinding.appbar.updatePadding(
top = insets.top,
)
viewBinding.root.updatePadding(
left = insets.left,
right = insets.right,
bottom = insets.bottom,
)
}
}

@ -3,13 +3,12 @@ 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 androidx.activity.result.contract.ActivityResultContract
import androidx.core.graphics.Insets
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
@ -26,6 +25,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.databinding.ActivityBrowserBinding
import org.koitharu.kotatsu.parsers.network.CloudFlareHelper
import javax.inject.Inject
@ -58,6 +58,7 @@ 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)
@ -83,17 +84,6 @@ class CloudFlareActivity : BaseActivity<ActivityBrowserBinding>(), CloudFlareCal
return super.onCreateOptionsMenu(menu)
}
override fun onWindowInsetsChanged(insets: Insets) {
viewBinding.appbar.updatePadding(
top = insets.top,
)
viewBinding.root.updatePadding(
left = insets.left,
right = insets.right,
bottom = insets.bottom,
)
}
override fun onOptionsItemSelected(item: MenuItem): Boolean = when (item.itemId) {
android.R.id.home -> {
viewBinding.webView.stopLoading()

@ -8,13 +8,13 @@ import android.os.Bundle
import android.view.KeyEvent
import android.view.View
import android.widget.Toast
import androidx.activity.enableEdgeToEdge
import androidx.annotation.CallSuper
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.app.AppCompatDelegate
import androidx.appcompat.view.ActionMode
import androidx.appcompat.widget.Toolbar
import androidx.core.app.ActivityCompat
import androidx.core.view.WindowCompat
import androidx.fragment.app.FragmentManager
import androidx.viewbinding.ViewBinding
import dagger.hilt.android.EntryPointAccessors
@ -25,15 +25,13 @@ import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.exceptions.resolve.ExceptionResolver
import org.koitharu.kotatsu.core.nav.AppRouter
import org.koitharu.kotatsu.core.ui.util.ActionModeDelegate
import org.koitharu.kotatsu.core.ui.util.WindowInsetsDelegate
import org.koitharu.kotatsu.core.util.ext.isWebViewUnavailable
import org.koitharu.kotatsu.main.ui.protect.ScreenshotPolicyHelper
abstract class BaseActivity<B : ViewBinding> :
AppCompatActivity(),
ExceptionResolver.Host,
ScreenshotPolicyHelper.ContentContainer,
WindowInsetsDelegate.WindowInsetsListener {
ScreenshotPolicyHelper.ContentContainer {
private var isAmoledTheme = false
@ -43,9 +41,6 @@ abstract class BaseActivity<B : ViewBinding> :
protected lateinit var exceptionResolver: ExceptionResolver
private set
@JvmField
protected val insetsDelegate = WindowInsetsDelegate()
@JvmField
val actionModeDelegate = ActionModeDelegate()
@ -68,10 +63,8 @@ abstract class BaseActivity<B : ViewBinding> :
}
putDataToExtras(intent)
exceptionResolver = entryPoint.exceptionResolverFactory.create(this)
enableEdgeToEdge()
super.onCreate(savedInstanceState)
WindowCompat.setDecorFitsSystemWindows(window, false)
insetsDelegate.handleImeInsets = true
insetsDelegate.addInsetsListener(this)
}
override fun onPostCreate(savedInstanceState: Bundle?) {
@ -105,7 +98,6 @@ abstract class BaseActivity<B : ViewBinding> :
super.setContentView(binding.root)
val toolbar = (binding.root.findViewById<View>(R.id.toolbar) as? Toolbar)
toolbar?.let(this::setSupportActionBar)
insetsDelegate.onViewCreated(binding.root)
}
override fun onSupportNavigateUp(): Boolean {

@ -10,12 +10,10 @@ import androidx.viewbinding.ViewBinding
import dagger.hilt.android.EntryPointAccessors
import org.koitharu.kotatsu.core.exceptions.resolve.ExceptionResolver
import org.koitharu.kotatsu.core.ui.util.ActionModeDelegate
import org.koitharu.kotatsu.core.ui.util.WindowInsetsDelegate
abstract class BaseFragment<B : ViewBinding> :
Fragment(),
ExceptionResolver.Host,
WindowInsetsDelegate.WindowInsetsListener {
ExceptionResolver.Host {
var viewBinding: B? = null
private set
@ -23,9 +21,6 @@ abstract class BaseFragment<B : ViewBinding> :
protected lateinit var exceptionResolver: ExceptionResolver
private set
@JvmField
protected val insetsDelegate = WindowInsetsDelegate()
protected val actionModeDelegate: ActionModeDelegate
get() = (requireActivity() as BaseActivity<*>).actionModeDelegate
@ -47,15 +42,11 @@ abstract class BaseFragment<B : ViewBinding> :
final override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
insetsDelegate.onViewCreated(view)
insetsDelegate.addInsetsListener(this)
onViewBindingCreated(requireViewBinding(), savedInstanceState)
}
override fun onDestroyView() {
viewBinding = null
insetsDelegate.removeInsetsListener(this)
insetsDelegate.onDestroyView()
super.onDestroyView()
}

@ -2,11 +2,9 @@ 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.CallSuper
import androidx.annotation.StringRes
import androidx.core.graphics.Insets
import androidx.core.view.updatePadding
import androidx.preference.Preference
import androidx.preference.PreferenceFragmentCompat
import androidx.preference.PreferenceScreen
@ -17,7 +15,7 @@ import dagger.hilt.android.EntryPointAccessors
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.ui.util.WindowInsetsDelegate
import org.koitharu.kotatsu.core.util.ext.consumeInsetsAsPadding
import org.koitharu.kotatsu.core.util.ext.getThemeColor
import org.koitharu.kotatsu.core.util.ext.getThemeDrawable
import org.koitharu.kotatsu.core.util.ext.parentView
@ -28,7 +26,6 @@ import com.google.android.material.R as materialR
@AndroidEntryPoint
abstract class BasePreferenceFragment(@StringRes private val titleId: Int) :
PreferenceFragmentCompat(),
WindowInsetsDelegate.WindowInsetsListener,
RecyclerViewOwner,
ExceptionResolver.Host {
@ -38,9 +35,6 @@ abstract class BasePreferenceFragment(@StringRes private val titleId: Int) :
@Inject
lateinit var settings: AppSettings
@JvmField
protected val insetsDelegate = WindowInsetsDelegate()
override val recyclerView: RecyclerView
get() = listView
@ -55,14 +49,7 @@ abstract class BasePreferenceFragment(@StringRes private val titleId: Int) :
val themedContext = (view.parentView ?: view).context
view.setBackgroundColor(themedContext.getThemeColor(android.R.attr.colorBackground))
listView.clipToPadding = false
insetsDelegate.onViewCreated(view)
insetsDelegate.addInsetsListener(this)
}
override fun onDestroyView() {
insetsDelegate.removeInsetsListener(this)
insetsDelegate.onDestroyView()
super.onDestroyView()
listView.consumeInsetsAsPadding(Gravity.BOTTOM or Gravity.START or Gravity.END)
}
override fun onResume() {
@ -74,13 +61,6 @@ abstract class BasePreferenceFragment(@StringRes private val titleId: Int) :
}
}
@CallSuper
override fun onWindowInsetsChanged(insets: Insets) {
listView.updatePadding(
bottom = insets.bottom,
)
}
protected open fun setTitle(title: CharSequence?) {
(activity as? SettingsActivity)?.setSectionTitle(title)
}

@ -1,8 +1,5 @@
package org.koitharu.kotatsu.core.ui.dialog
import android.content.ClipData
import android.content.ClipboardManager
import android.content.Context
import android.os.Bundle
import android.view.LayoutInflater
import android.view.ViewGroup
@ -14,6 +11,7 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder
import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.nav.AppRouter
import org.koitharu.kotatsu.core.ui.AlertDialogFragment
import org.koitharu.kotatsu.core.util.ext.copyToClipboard
import org.koitharu.kotatsu.core.util.ext.getCauseUrl
import org.koitharu.kotatsu.core.util.ext.isReportable
import org.koitharu.kotatsu.core.util.ext.report
@ -53,7 +51,7 @@ class ErrorDetailsDialog : AlertDialogFragment<DialogErrorDetailsBinding>() {
.setNegativeButton(android.R.string.cancel, null)
.setTitle(R.string.error_occurred)
.setNeutralButton(androidx.preference.R.string.copy) { _, _ ->
copyToClipboard()
context?.copyToClipboard(getString(R.string.error), exception.stackTraceToString())
}
if (exception.isReportable()) {
builder.setPositiveButton(R.string.report) { _, _ ->
@ -63,12 +61,4 @@ class ErrorDetailsDialog : AlertDialogFragment<DialogErrorDetailsBinding>() {
}
return builder
}
private fun copyToClipboard() {
val clipboardManager = context?.getSystemService(Context.CLIPBOARD_SERVICE) as? ClipboardManager
?: return
clipboardManager.setPrimaryClip(
ClipData.newPlainText(getString(R.string.error), exception.stackTraceToString()),
)
}
}

@ -0,0 +1,39 @@
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.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,
) : OnApplyWindowInsetsListener {
override fun onApplyWindowInsets(v: View, insets: WindowInsetsCompat): WindowInsetsCompat {
val barsInsets = insets.getInsets(WindowInsetsCompat.Type.systemBars())
v.updateLayoutParams<ViewGroup.MarginLayoutParams> {
if (sides and Gravity.START == Gravity.START) marginStart = barsInsets.start(v)
if (sides and Gravity.TOP == Gravity.TOP) topMargin = barsInsets.top
if (sides and Gravity.END == Gravity.END) marginEnd = barsInsets.end(v)
if (sides and Gravity.BOTTOM == Gravity.BOTTOM) bottomMargin = barsInsets.bottom
}
return WindowInsetsCompat.Builder(insets)
.setInsets(
WindowInsetsCompat.Type.systemBars(),
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()
}
}

@ -0,0 +1,37 @@
package org.koitharu.kotatsu.core.ui.util
import android.view.Gravity
import android.view.View
import androidx.annotation.GravityInt
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,
) : OnApplyWindowInsetsListener {
override fun onApplyWindowInsets(v: View, insets: WindowInsetsCompat): WindowInsetsCompat {
val barsInsets = insets.getInsets(WindowInsetsCompat.Type.systemBars())
v.setPaddingRelative(
/* start = */ if (sides and Gravity.START == Gravity.START) barsInsets.start(v) else v.paddingStart,
/* top = */ if (sides and Gravity.TOP == Gravity.TOP) barsInsets.top else v.paddingTop,
/* end = */ if (sides and Gravity.END == Gravity.END) barsInsets.end(v) else v.paddingEnd,
/* bottom = */ if (sides and Gravity.BOTTOM == Gravity.BOTTOM) barsInsets.bottom else v.paddingBottom,
)
return WindowInsetsCompat.Builder(insets)
.setInsets(
WindowInsetsCompat.Type.systemBars(),
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,78 +0,0 @@
package org.koitharu.kotatsu.core.ui.util
import android.view.View
import androidx.core.graphics.Insets
import androidx.core.view.OnApplyWindowInsetsListener
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import java.util.LinkedList
@Deprecated("")
class WindowInsetsDelegate : OnApplyWindowInsetsListener, View.OnLayoutChangeListener {
@JvmField
var handleImeInsets: Boolean = false
@JvmField
var interceptingWindowInsetsListener: OnApplyWindowInsetsListener? = null
private val listeners = LinkedList<WindowInsetsListener>()
private var lastInsets: Insets? = null
override fun onApplyWindowInsets(v: View, insets: WindowInsetsCompat): WindowInsetsCompat {
val handledInsets = interceptingWindowInsetsListener?.onApplyWindowInsets(v, insets) ?: insets
val newInsets = if (handleImeInsets) {
Insets.max(
handledInsets.getInsets(WindowInsetsCompat.Type.systemBars()),
handledInsets.getInsets(WindowInsetsCompat.Type.ime()),
)
} else {
handledInsets.getInsets(WindowInsetsCompat.Type.systemBars())
}
if (newInsets != lastInsets) {
listeners.forEach { it.onWindowInsetsChanged(newInsets) }
lastInsets = newInsets
}
return handledInsets
}
override fun onLayoutChange(
view: View,
left: Int,
top: Int,
right: Int,
bottom: Int,
oldLeft: Int,
oldTop: Int,
oldRight: Int,
oldBottom: Int,
) {
view.removeOnLayoutChangeListener(this)
if (lastInsets == null) { // Listener may not be called
onApplyWindowInsets(view, ViewCompat.getRootWindowInsets(view) ?: return)
}
}
fun addInsetsListener(listener: WindowInsetsListener) {
listeners.add(listener)
lastInsets?.let { listener.onWindowInsetsChanged(it) }
}
fun removeInsetsListener(listener: WindowInsetsListener) {
listeners.remove(listener)
}
fun onViewCreated(view: View) {
ViewCompat.setOnApplyWindowInsetsListener(view, this)
view.addOnLayoutChangeListener(this)
}
fun onDestroyView() {
lastInsets = null
}
fun interface WindowInsetsListener {
fun onWindowInsetsChanged(insets: Insets)
}
}

@ -6,6 +6,8 @@ import android.app.Activity
import android.app.ActivityManager
import android.app.ActivityManager.MemoryInfo
import android.app.LocaleConfig
import android.content.ClipData
import android.content.ClipboardManager
import android.content.ComponentName
import android.content.Context
import android.content.Context.ACTIVITY_SERVICE
@ -247,3 +249,8 @@ private fun PowerManager?.newPartialWakeLock(tag: String): PowerManager.WakeLock
null
}
}
fun Context.copyToClipboard(label: String, content: String) {
val clipboardManager = getSystemService(Context.CLIPBOARD_SERVICE) as? ClipboardManager ?: return
clipboardManager.setPrimaryClip(ClipData.newPlainText(label, content))
}

@ -10,3 +10,29 @@ fun Insets.end(view: View): Int {
fun Insets.start(view: View): Int {
return if (view.isRtl) right else left
}
fun Insets.consume(
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,
)
fun Insets.consumeRelative(
view: View,
start: Boolean = false,
top: Boolean = false,
end: Boolean = false,
bottom: Boolean = false,
): Insets = Insets.of(
/* left = */ if (if (view.isRtl) end else start) 0 else this.left,
/* top = */ if (top) 0 else this.top,
/* right = */ if (if (view.isRtl) start else end) 0 else this.right,
/* bottom = */ if (bottom) 0 else this.bottom,
)

@ -6,8 +6,10 @@ 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.view.ViewCompat
import androidx.core.view.children
import androidx.core.view.descendants
import androidx.core.view.isVisible
@ -22,6 +24,8 @@ 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 {
@ -182,3 +186,13 @@ fun Chip.setProgressIcon() {
chipIcon = progressDrawable
progressDrawable.start()
}
fun View.consumeInsetsAsPadding(@GravityInt sides: Int) = ViewCompat.setOnApplyWindowInsetsListener(
this,
InsetsToPaddingListener(sides),
)
fun View.consumeInsetsAsMargins(@GravityInt sides: Int) = ViewCompat.setOnApplyWindowInsetsListener(
this,
InsetsToMarginsListener(sides),
)

@ -6,17 +6,20 @@ import android.transition.TransitionManager
import android.view.Gravity
import android.view.MenuItem
import android.view.View
import android.view.ViewGroup.MarginLayoutParams
import android.view.ViewGroup
import android.view.ViewTreeObserver
import android.widget.Toast
import androidx.activity.viewModels
import androidx.appcompat.widget.PopupMenu
import androidx.core.graphics.Insets
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
import androidx.core.view.updateLayoutParams
import androidx.core.view.updatePadding
import androidx.core.view.updatePaddingRelative
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
import coil3.ImageLoader
import coil3.request.ImageRequest
@ -57,6 +60,7 @@ import org.koitharu.kotatsu.core.parser.favicon.faviconUri
import org.koitharu.kotatsu.core.ui.BaseActivity
import org.koitharu.kotatsu.core.ui.BaseListAdapter
import org.koitharu.kotatsu.core.ui.OnContextClickListenerCompat
import org.koitharu.kotatsu.core.ui.dialog.buildAlertDialog
import org.koitharu.kotatsu.core.ui.image.CoverSizeResolver
import org.koitharu.kotatsu.core.ui.image.FaviconDrawable
import org.koitharu.kotatsu.core.ui.image.TextDrawable
@ -68,10 +72,13 @@ 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.copyToClipboard
import org.koitharu.kotatsu.core.util.ext.crossfade
import org.koitharu.kotatsu.core.util.ext.defaultPlaceholders
import org.koitharu.kotatsu.core.util.ext.drawable
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.isTextTruncated
@ -80,6 +87,7 @@ import org.koitharu.kotatsu.core.util.ext.mangaSourceExtra
import org.koitharu.kotatsu.core.util.ext.observe
import org.koitharu.kotatsu.core.util.ext.observeEvent
import org.koitharu.kotatsu.core.util.ext.parentView
import org.koitharu.kotatsu.core.util.ext.start
import org.koitharu.kotatsu.core.util.ext.textAndVisible
import org.koitharu.kotatsu.databinding.ActivityDetailsBinding
import org.koitharu.kotatsu.databinding.LayoutDetailsTableBinding
@ -101,6 +109,7 @@ import org.koitharu.kotatsu.list.ui.size.StaticItemSizeResolver
import org.koitharu.kotatsu.parsers.model.Manga
import org.koitharu.kotatsu.parsers.model.MangaTag
import org.koitharu.kotatsu.parsers.util.ifNullOrEmpty
import org.koitharu.kotatsu.parsers.util.nullIfEmpty
import org.koitharu.kotatsu.scrobbling.common.domain.model.ScrobblingInfo
import org.koitharu.kotatsu.search.domain.SearchKind
import javax.inject.Inject
@ -110,7 +119,7 @@ import com.google.android.material.R as materialR
@AndroidEntryPoint
class DetailsActivity :
BaseActivity<ActivityDetailsBinding>(),
View.OnClickListener,
View.OnClickListener, OnApplyWindowInsetsListener,
View.OnLongClickListener, PopupMenu.OnMenuItemClickListener, View.OnLayoutChangeListener,
ViewTreeObserver.OnDrawListener, ChipsView.OnChipClickListener, OnListItemClickListener<Bookmark>,
OnContextClickListenerCompat, SwipeRefreshLayout.OnRefreshListener {
@ -141,6 +150,7 @@ class DetailsActivity :
infoBinding.textViewAuthor.setOnClickListener(this)
infoBinding.textViewSource.setOnClickListener(this)
viewBinding.imageViewCover.setOnClickListener(this)
viewBinding.textViewTitle.setOnClickListener(this)
viewBinding.buttonDescriptionMore.setOnClickListener(this)
viewBinding.buttonScrobblingMore.setOnClickListener(this)
viewBinding.buttonRelatedMore.setOnClickListener(this)
@ -151,12 +161,13 @@ class DetailsActivity :
viewBinding.chipsTags.onChipClickListener = this
TitleScrollCoordinator(viewBinding.textViewTitle).attach(viewBinding.scrollView)
viewBinding.containerBottomSheet?.let { sheet ->
sheet.addOnLayoutChangeListener(this)
onBackPressedDispatcher.addCallback(BottomSheetCollapseCallback(sheet))
BottomSheetBehavior.from(sheet).addBottomSheetCallback(
DetailsBottomSheetCallback(viewBinding.swipeRefreshLayout, checkNotNull(viewBinding.navbarDim)),
)
}
TitleExpandListener(viewBinding.textViewTitle).attach()
ViewCompat.setOnApplyWindowInsetsListener(viewBinding.root, this)
val appRouter = router
viewModel.mangaDetails.filterNotNull().observe(this, ::onMangaUpdated)
@ -253,6 +264,17 @@ class DetailsActivity :
val manga = viewModel.manga.value ?: return
router.openRelated(manga)
}
R.id.textView_title -> {
val title = viewModel.manga.value?.title?.nullIfEmpty() ?: return
buildAlertDialog(this) {
setMessage(title)
setNegativeButton(R.string.close, null)
setPositiveButton(androidx.preference.R.string.copy) { _, _ ->
copyToClipboard(getString(R.string.content_type_manga), title)
}
}.show()
}
}
}
@ -324,6 +346,38 @@ class DetailsActivity :
) {
with(viewBinding) {
buttonDescriptionMore.isVisible = textViewDescription.isTextTruncated
containerBottomSheet?.let { sheet ->
val peekHeight = BottomSheetBehavior.from(sheet).peekHeight
if (scrollView.paddingBottom != peekHeight) {
scrollView.updatePadding(bottom = peekHeight)
}
}
}
}
override fun onApplyWindowInsets(v: View, insets: WindowInsetsCompat): WindowInsetsCompat {
val barsInsets = insets.getInsets(WindowInsetsCompat.Type.systemBars())
if (viewBinding.cardChapters != null) {
// landscape
viewBinding.cardChapters?.updateLayoutParams<ViewGroup.MarginLayoutParams> {
topMargin = barsInsets.top + resources.getDimensionPixelOffset(R.dimen.grid_spacing_outer)
marginEnd = barsInsets.end(v) + resources.getDimensionPixelOffset(R.dimen.side_card_offset)
bottomMargin = barsInsets.bottom + resources.getDimensionPixelOffset(R.dimen.side_card_offset)
}
viewBinding.scrollView.updatePaddingRelative(
bottom = barsInsets.bottom,
start = barsInsets.start(v),
)
viewBinding.appbar.updatePaddingRelative(
start = barsInsets.start(v),
)
return WindowInsetsCompat.Builder(insets)
.setInsets(
WindowInsetsCompat.Type.systemBars(),
barsInsets.consumeRelative(v, end = true, bottom = true),
).build()
} else {
return insets
}
}
@ -452,21 +506,6 @@ class DetailsActivity :
finishAfterTransition()
}
override fun onWindowInsetsChanged(insets: Insets) {
viewBinding.root.updatePadding(
left = insets.left,
right = insets.right,
)
viewBinding.cardChapters?.updateLayoutParams<MarginLayoutParams> {
val baseOffset = leftMargin
bottomMargin = insets.bottom + baseOffset
topMargin = insets.bottom + baseOffset
}
viewBinding.scrollView.updatePadding(
bottom = insets.bottom,
)
}
private fun onHistoryChanged(info: HistoryInfo, isLoading: Boolean) = with(infoBinding) {
textViewChapters.text = when {
isLoading -> getString(R.string.loading_)

@ -1,45 +0,0 @@
package org.koitharu.kotatsu.details.ui
import android.annotation.SuppressLint
import android.transition.TransitionManager
import android.view.GestureDetector
import android.view.MotionEvent
import android.view.View
import android.view.View.OnTouchListener
import android.view.ViewGroup
import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.ui.widgets.SelectableTextView
import org.koitharu.kotatsu.core.util.ext.isAnimationsEnabled
@SuppressLint("ClickableViewAccessibility")
class TitleExpandListener(
private val textView: SelectableTextView,
) : GestureDetector.SimpleOnGestureListener(), OnTouchListener {
private val gestureDetector = GestureDetector(textView.context, this)
private val linesExpanded = textView.resources.getInteger(R.integer.details_description_lines)
private val linesCollapsed = textView.resources.getInteger(R.integer.details_title_lines)
override fun onTouch(v: View?, event: MotionEvent) = gestureDetector.onTouchEvent(event)
override fun onSingleTapConfirmed(e: MotionEvent): Boolean {
if (textView.context.isAnimationsEnabled) {
TransitionManager.beginDelayedTransition(textView.parent as ViewGroup)
}
if (textView.maxLines in 1 until Integer.MAX_VALUE) {
textView.maxLines = Integer.MAX_VALUE
} else {
textView.maxLines = linesCollapsed
}
return true
}
override fun onLongPress(e: MotionEvent) {
textView.maxLines = Integer.MAX_VALUE
textView.selectAll()
}
fun attach() {
textView.setOnTouchListener(this)
}
}

@ -1,6 +1,7 @@
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
@ -8,8 +9,6 @@ import android.view.MenuItem
import android.view.View
import android.view.ViewGroup
import androidx.appcompat.view.ActionMode
import androidx.core.graphics.Insets
import androidx.core.view.updatePadding
import androidx.fragment.app.viewModels
import androidx.recyclerview.widget.GridLayoutManager
import coil3.ImageLoader
@ -28,6 +27,7 @@ import org.koitharu.kotatsu.core.ui.list.ListSelectionController
import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener
import org.koitharu.kotatsu.core.ui.util.PagerNestedScrollHelper
import org.koitharu.kotatsu.core.ui.util.ReversibleActionObserver
import org.koitharu.kotatsu.core.util.ext.consumeInsetsAsPadding
import org.koitharu.kotatsu.core.util.ext.findAppCompatDelegate
import org.koitharu.kotatsu.core.util.ext.findParentCallback
import org.koitharu.kotatsu.core.util.ext.observe
@ -42,7 +42,8 @@ import javax.inject.Inject
@AndroidEntryPoint
class BookmarksFragment : BaseFragment<FragmentMangaBookmarksBinding>(),
OnListItemClickListener<Bookmark>, ListSelectionController.Callback {
OnListItemClickListener<Bookmark>,
ListSelectionController.Callback {
private val activityViewModel by ChaptersPagesViewModel.ActivityVMLazy(this)
private val viewModel by viewModels<BookmarksViewModel>()
@ -87,6 +88,7 @@ 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,14 +118,6 @@ class BookmarksFragment : BaseFragment<FragmentMangaBookmarksBinding>(),
super.onDestroyView()
}
override fun onWindowInsetsChanged(insets: Insets) {
with (viewBinding ?: return) {
recyclerView.updatePadding(
bottom = insets.bottom
)
}
}
override fun onItemClick(item: Bookmark, view: View) {
if (selectionController?.onItemClick(item.pageId) == true) {
return

@ -4,7 +4,9 @@ import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
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
import androidx.core.view.updatePadding
@ -44,7 +46,9 @@ import kotlin.math.roundToInt
@AndroidEntryPoint
class ChaptersFragment :
BaseFragment<FragmentChaptersBinding>(),
OnListItemClickListener<ChapterListItem>, ChipsView.OnChipClickListener {
OnListItemClickListener<ChapterListItem>,
OnApplyWindowInsetsListener,
ChipsView.OnChipClickListener {
private val viewModel by ChaptersPagesViewModel.ActivityVMLazy(this)
@ -74,6 +78,7 @@ class ChaptersFragment :
LinearLayoutManager(context)
}
}
ViewCompat.setOnApplyWindowInsetsListener(binding.root, this)
with(binding.recyclerViewChapters) {
addItemDecoration(TypedListSpacingDecoration(context, true))
checkNotNull(selectionController).attachToRecyclerView(this)
@ -130,12 +135,23 @@ class ChaptersFragment :
viewModel.setSelectedBranch(data.titleText)
}
override fun onWindowInsetsChanged(insets: Insets) {
with (viewBinding ?: return) {
override fun onApplyWindowInsets(
v: View,
insets: WindowInsetsCompat
): WindowInsetsCompat {
viewBinding?.run {
val bars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
recyclerViewChapters.updatePadding(
bottom = insets.bottom
left = bars.left,
right = bars.right,
bottom = bars.bottom,
)
chipsFilter.updatePadding(
left = bars.left,
right = bars.right,
)
}
return WindowInsetsCompat.CONSUMED
}
private fun onChaptersChanged(list: List<ListModel>) {

@ -1,6 +1,7 @@
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
@ -9,10 +10,8 @@ import android.view.View
import android.view.ViewGroup
import androidx.appcompat.view.ActionMode
import androidx.collection.ArraySet
import androidx.core.graphics.Insets
import androidx.core.view.isInvisible
import androidx.core.view.isVisible
import androidx.core.view.updatePadding
import androidx.fragment.app.viewModels
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.RecyclerView
@ -33,6 +32,7 @@ import org.koitharu.kotatsu.core.ui.list.ListSelectionController
import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener
import org.koitharu.kotatsu.core.ui.util.PagerNestedScrollHelper
import org.koitharu.kotatsu.core.util.RecyclerViewScrollCallback
import org.koitharu.kotatsu.core.util.ext.consumeInsetsAsPadding
import org.koitharu.kotatsu.core.util.ext.findAppCompatDelegate
import org.koitharu.kotatsu.core.util.ext.findParentCallback
import org.koitharu.kotatsu.core.util.ext.observe
@ -54,7 +54,8 @@ import kotlin.math.roundToInt
@AndroidEntryPoint
class PagesFragment :
BaseFragment<FragmentPagesBinding>(),
OnListItemClickListener<PageThumbnail>, ListSelectionController.Callback {
OnListItemClickListener<PageThumbnail>,
ListSelectionController.Callback {
@Inject
lateinit var coil: ImageLoader
@ -112,6 +113,7 @@ 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)
@ -143,14 +145,6 @@ class PagesFragment :
super.onDestroyView()
}
override fun onWindowInsetsChanged(insets: Insets) {
with (viewBinding ?: return) {
recyclerView.updatePadding(
bottom = insets.bottom
)
}
}
override fun onItemClick(item: PageThumbnail, view: View) {
if (selectionController?.onItemClick(item.page.id) == true) {
return

@ -1,8 +1,6 @@
package org.koitharu.kotatsu.details.ui.related
import android.os.Bundle
import androidx.core.graphics.Insets
import androidx.core.view.updatePadding
import androidx.fragment.app.commit
import com.google.android.material.appbar.AppBarLayout
import dagger.hilt.android.AndroidEntryPoint
@ -29,11 +27,4 @@ class RelatedMangaActivity : BaseActivity<ActivityContainerBinding>(), AppBarOwn
}
}
}
override fun onWindowInsetsChanged(insets: Insets) {
viewBinding.root.updatePadding(
left = insets.left,
right = insets.right,
)
}
}

@ -1,14 +1,13 @@
package org.koitharu.kotatsu.download.ui.list
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.graphics.Insets
import androidx.core.view.updatePadding
import coil3.ImageLoader
import dagger.hilt.android.AndroidEntryPoint
import org.koitharu.kotatsu.R
@ -18,6 +17,7 @@ import org.koitharu.kotatsu.core.ui.list.ListSelectionController
import org.koitharu.kotatsu.core.ui.list.RecyclerScrollKeeper
import org.koitharu.kotatsu.core.ui.util.MenuInvalidator
import org.koitharu.kotatsu.core.ui.util.ReversibleActionObserver
import org.koitharu.kotatsu.core.util.ext.consumeInsetsAsPadding
import org.koitharu.kotatsu.core.util.ext.observe
import org.koitharu.kotatsu.core.util.ext.observeEvent
import org.koitharu.kotatsu.databinding.ActivityDownloadsBinding
@ -52,6 +52,7 @@ class DownloadsActivity : BaseActivity<ActivityDownloadsBinding>(),
callback = this,
)
with(viewBinding.recyclerView) {
consumeInsetsAsPadding(Gravity.START or Gravity.END or Gravity.BOTTOM)
setHasFixedSize(true)
addItemDecoration(decoration)
adapter = downloadsAdapter
@ -67,19 +68,6 @@ class DownloadsActivity : BaseActivity<ActivityDownloadsBinding>(),
viewModel.hasCancellableWorks.observe(this, menuInvalidator)
}
override fun onWindowInsetsChanged(insets: Insets) {
val rv = viewBinding.recyclerView
rv.updatePadding(
left = insets.left + rv.paddingTop,
right = insets.right + rv.paddingTop,
bottom = insets.bottom,
)
viewBinding.toolbar.updatePadding(
left = insets.left,
right = insets.right,
)
}
override fun onItemClick(item: DownloadItemModel, view: View) {
if (selectionController.onItemClick(item.id.mostSignificantBits)) {
return

@ -5,6 +5,7 @@ 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
@ -12,8 +13,6 @@ import android.view.MenuItem
import android.view.View
import android.view.ViewGroup
import androidx.appcompat.view.ActionMode
import androidx.core.graphics.Insets
import androidx.core.view.updatePadding
import androidx.fragment.app.viewModels
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.LinearLayoutManager
@ -33,6 +32,7 @@ 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.findAppCompatDelegate
import org.koitharu.kotatsu.core.util.ext.observe
import org.koitharu.kotatsu.core.util.ext.observeEvent
@ -79,6 +79,7 @@ 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()
@ -102,13 +103,6 @@ class ExploreFragment :
exploreAdapter = null
}
override fun onWindowInsetsChanged(insets: Insets) {
val rv = requireViewBinding().recyclerView
rv.updatePadding(
bottom = insets.bottom + rv.paddingTop,
)
}
override fun onListHeaderClick(item: ListHeader, view: View) {
if (item.payload == R.id.nav_suggestions) {
router.openSuggestions()

@ -1,8 +1,6 @@
package org.koitharu.kotatsu.favourites.ui
import android.os.Bundle
import androidx.core.graphics.Insets
import androidx.core.view.updatePadding
import androidx.fragment.app.commit
import dagger.hilt.android.AndroidEntryPoint
import org.koitharu.kotatsu.R
@ -32,11 +30,4 @@ class FavouritesActivity : BaseActivity<ActivityContainerBinding>() {
}
}
}
override fun onWindowInsetsChanged(insets: Insets) {
viewBinding.root.updatePadding(
left = insets.left,
right = insets.right,
)
}
}

@ -1,13 +1,10 @@
package org.koitharu.kotatsu.favourites.ui.categories
import android.os.Bundle
import android.view.Gravity
import android.view.View
import android.view.ViewGroup
import androidx.activity.viewModels
import androidx.appcompat.view.ActionMode
import androidx.core.graphics.Insets
import androidx.core.view.updateLayoutParams
import androidx.core.view.updatePadding
import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.RecyclerView
import coil3.ImageLoader
@ -18,6 +15,7 @@ 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.observe
import org.koitharu.kotatsu.core.util.ext.observeEvent
import org.koitharu.kotatsu.databinding.ActivityCategoriesBinding
@ -55,6 +53,7 @@ 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))
@ -127,21 +126,6 @@ class FavouriteCategoriesActivity :
override fun onEmptyActionClick() = Unit
override fun onWindowInsetsChanged(insets: Insets) {
viewBinding.fabAdd.updateLayoutParams<ViewGroup.MarginLayoutParams> {
rightMargin = topMargin + insets.right
leftMargin = topMargin + insets.left
bottomMargin = topMargin + insets.bottom
}
viewBinding.root.updatePadding(
left = insets.left,
right = insets.right,
)
viewBinding.recyclerView.updatePadding(
bottom = insets.bottom + viewBinding.recyclerView.paddingTop,
)
}
private suspend fun onCategoriesChanged(categories: List<ListModel>) {
adapter.emit(categories)
invalidateOptionsMenu()

@ -4,15 +4,11 @@ import android.content.Context
import android.os.Bundle
import android.text.Editable
import android.view.View
import android.view.ViewGroup
import android.widget.AdapterView
import android.widget.ArrayAdapter
import android.widget.Filter
import androidx.activity.viewModels
import androidx.core.graphics.Insets
import androidx.core.view.isVisible
import androidx.core.view.updateLayoutParams
import androidx.core.view.updatePadding
import dagger.hilt.android.AndroidEntryPoint
import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.model.FavouriteCategory
@ -87,19 +83,6 @@ class FavouritesCategoryEditActivity :
viewBinding.buttonDone.isEnabled = !s.isNullOrBlank()
}
override fun onWindowInsetsChanged(insets: Insets) {
viewBinding.root.updatePadding(
left = insets.left,
right = insets.right,
)
viewBinding.scrollView.updatePadding(
bottom = insets.bottom,
)
viewBinding.toolbar.updateLayoutParams<ViewGroup.MarginLayoutParams> {
topMargin = insets.top
}
}
override fun onItemClick(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
selectedSortOrder = sortOrders.getOrNull(position)
}

@ -6,10 +6,8 @@ import android.view.View
import android.view.ViewGroup
import android.view.ViewStub
import androidx.appcompat.view.ActionMode
import androidx.core.graphics.Insets
import androidx.core.view.isGone
import androidx.core.view.isVisible
import androidx.core.view.updatePadding
import androidx.fragment.app.viewModels
import coil3.ImageLoader
import com.google.android.material.tabs.TabLayoutMediator
@ -69,13 +67,6 @@ class FavouritesContainerFragment : BaseFragment<FragmentFavouritesContainerBind
super.onDestroyView()
}
override fun onWindowInsetsChanged(insets: Insets) {
viewBinding?.tabs?.updatePadding(
left = insets.left,
right = insets.right,
)
}
override fun onActionModeStarted(mode: ActionMode) {
viewBinding?.run {
pager.isUserInputEnabled = false

@ -3,7 +3,6 @@ package org.koitharu.kotatsu.filter.ui
import android.os.Bundle
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.core.graphics.Insets
import androidx.core.view.isVisible
import com.google.android.material.chip.Chip
import dagger.hilt.android.AndroidEntryPoint
@ -48,8 +47,6 @@ class FilterHeaderFragment : BaseFragment<FragmentFilterHeaderBinding>(), ChipsV
.observe(viewLifecycleOwner, ::onDataChanged)
}
override fun onWindowInsetsChanged(insets: Insets) = Unit
override fun onChipClick(chip: Chip, data: Any?) {
when (data) {
is MangaTag -> filter.toggleTag(data, !chip.isChecked)
@ -65,6 +62,7 @@ class FilterHeaderFragment : BaseFragment<FragmentFilterHeaderBinding>(), ChipsV
} else {
filter.setQuery(null)
}
is ContentRating -> filter.toggleContentRating(data, false)
is Demographic -> filter.toggleDemographic(data, false)
is ContentType -> filter.toggleContentType(data, false)

@ -1,8 +1,6 @@
package org.koitharu.kotatsu.history.ui
import android.os.Bundle
import androidx.core.graphics.Insets
import androidx.core.view.updatePadding
import androidx.fragment.app.commit
import com.google.android.material.appbar.AppBarLayout
import dagger.hilt.android.AndroidEntryPoint
@ -32,11 +30,4 @@ class HistoryActivity :
}
}
}
override fun onWindowInsetsChanged(insets: Insets) {
viewBinding.root.updatePadding(
left = insets.left,
right = insets.right,
)
}
}

@ -6,8 +6,10 @@ import android.os.Bundle
import android.view.View
import android.view.ViewGroup
import androidx.activity.viewModels
import androidx.core.graphics.Insets
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
import androidx.swiperefreshlayout.widget.CircularProgressDrawable
@ -31,6 +33,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.end
import org.koitharu.kotatsu.core.util.ext.enqueueWith
import org.koitharu.kotatsu.core.util.ext.getDisplayIcon
import org.koitharu.kotatsu.core.util.ext.getDisplayMessage
@ -38,13 +41,17 @@ import org.koitharu.kotatsu.core.util.ext.getThemeColor
import org.koitharu.kotatsu.core.util.ext.mangaSourceExtra
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.databinding.ActivityImageBinding
import org.koitharu.kotatsu.databinding.ItemErrorStateBinding
import javax.inject.Inject
import com.google.android.material.R as materialR
@AndroidEntryPoint
class ImageActivity : BaseActivity<ActivityImageBinding>(), ImageRequest.Listener, View.OnClickListener {
class ImageActivity : BaseActivity<ActivityImageBinding>(),
ImageRequest.Listener,
OnApplyWindowInsetsListener,
View.OnClickListener {
@Inject
lateinit var coil: ImageLoader
@ -56,6 +63,7 @@ class ImageActivity : BaseActivity<ActivityImageBinding>(), ImageRequest.Listene
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)
@ -72,19 +80,6 @@ class ImageActivity : BaseActivity<ActivityImageBinding>(), ImageRequest.Listene
loadImage(imageUrl)
}
override fun onWindowInsetsChanged(insets: Insets) {
viewBinding.buttonBack.updateLayoutParams<ViewGroup.MarginLayoutParams> {
topMargin = insets.top + bottomMargin
leftMargin = insets.left + bottomMargin
rightMargin = insets.right + bottomMargin
}
viewBinding.buttonMenu.updateLayoutParams<ViewGroup.MarginLayoutParams> {
topMargin = insets.top + bottomMargin
leftMargin = insets.left + bottomMargin
rightMargin = insets.right + bottomMargin
}
}
override fun onClick(v: View) {
when (v.id) {
R.id.button_back -> dispatchNavigateUp()
@ -115,6 +110,19 @@ class ImageActivity : BaseActivity<ActivityImageBinding>(), ImageRequest.Listene
(errorBinding?.root ?: viewBinding.stubError).isVisible = false
}
override fun onApplyWindowInsets(v: View, insets: WindowInsetsCompat): WindowInsetsCompat {
val barsInsets = insets.getInsets(WindowInsetsCompat.Type.systemBars())
viewBinding.buttonMenu.updateLayoutParams<ViewGroup.MarginLayoutParams> {
marginEnd = barsInsets.end(v)
topMargin = barsInsets.top
}
viewBinding.buttonBack.updateLayoutParams<ViewGroup.MarginLayoutParams> {
marginStart = barsInsets.start(v)
topMargin = barsInsets.top
}
return insets
}
private fun loadImage(url: Uri?) {
ImageRequest.Builder(this)
.data(url)

@ -1,19 +1,16 @@
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
import android.view.MenuItem
import android.view.View
import android.view.ViewGroup
import android.view.ViewGroup.MarginLayoutParams
import androidx.annotation.CallSuper
import androidx.appcompat.view.ActionMode
import androidx.collection.ArraySet
import androidx.core.graphics.Insets
import androidx.core.view.updateLayoutParams
import androidx.core.view.updatePadding
import androidx.recyclerview.widget.GridLayoutManager
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
import coil3.ImageLoader
@ -38,11 +35,10 @@ 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.findAppCompatDelegate
import org.koitharu.kotatsu.core.util.ext.measureHeight
import org.koitharu.kotatsu.core.util.ext.observe
import org.koitharu.kotatsu.core.util.ext.observeEvent
import org.koitharu.kotatsu.core.util.ext.resolveDp
import org.koitharu.kotatsu.core.util.ext.viewLifecycleScope
import org.koitharu.kotatsu.databinding.FragmentListBinding
import org.koitharu.kotatsu.list.domain.ListFilterOption
@ -55,7 +51,6 @@ import org.koitharu.kotatsu.list.ui.model.ListHeader
import org.koitharu.kotatsu.list.ui.model.ListModel
import org.koitharu.kotatsu.list.ui.model.MangaListModel
import org.koitharu.kotatsu.list.ui.size.DynamicItemSizeResolver
import org.koitharu.kotatsu.main.ui.MainActivity
import org.koitharu.kotatsu.main.ui.owners.AppBarOwner
import org.koitharu.kotatsu.parsers.model.Manga
import org.koitharu.kotatsu.parsers.model.MangaTag
@ -109,6 +104,7 @@ 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)
@ -212,24 +208,6 @@ abstract class MangaListFragment :
)
}
override fun onWindowInsetsChanged(insets: Insets) {
val rv = requireViewBinding().recyclerView
rv.updatePadding(
bottom = insets.bottom + rv.paddingTop,
)
rv.fastScroller.updateLayoutParams<MarginLayoutParams> {
bottomMargin = insets.bottom
}
if (activity is MainActivity) {
val headerHeight = (activity as? AppBarOwner)?.appBar?.measureHeight() ?: insets.top
requireViewBinding().swipeRefreshLayout.setProgressViewOffset(
true,
headerHeight + resources.resolveDp(-72),
headerHeight + resources.resolveDp(10),
)
}
}
override fun onFilterOptionClick(option: ListFilterOption) {
selectionController?.clear()
(viewModel as? QuickFilterListener)?.toggleFilterOption(option)

@ -5,7 +5,6 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.core.graphics.Insets
import androidx.core.text.method.LinkMovementMethodCompat
import androidx.core.view.isVisible
import androidx.fragment.app.viewModels
@ -89,8 +88,6 @@ class PreviewFragment : BaseFragment<FragmentPreviewBinding>(), View.OnClickList
}
}
override fun onWindowInsetsChanged(insets: Insets) = Unit
override fun onChipClick(chip: Chip, data: Any?) {
val tag = data as? MangaTag ?: return
val filter = (activity as? FilterCoordinator.Owner)?.filterCoordinator

@ -14,9 +14,11 @@ import androidx.activity.viewModels
import androidx.appcompat.view.ActionMode
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import androidx.core.graphics.Insets
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
import androidx.core.view.isInvisible
@ -50,8 +52,11 @@ 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.end
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.databinding.ActivityMainBinding
import org.koitharu.kotatsu.details.service.MangaPrefetchService
import org.koitharu.kotatsu.favourites.ui.container.FavouritesContainerFragment
@ -76,8 +81,11 @@ private const val TAG_SEARCH = "search"
@AndroidEntryPoint
class MainActivity : BaseActivity<ActivityMainBinding>(), AppBarOwner, BottomNavOwner,
View.OnClickListener,
View.OnFocusChangeListener, SearchSuggestionListener,
MainNavigationDelegate.OnFragmentChangedListener, View.OnLayoutChangeListener {
View.OnFocusChangeListener,
SearchSuggestionListener,
OnApplyWindowInsetsListener,
MainNavigationDelegate.OnFragmentChangedListener,
View.OnLayoutChangeListener {
@Inject
lateinit var settings: AppSettings
@ -98,6 +106,7 @@ 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
@ -204,12 +213,24 @@ class MainActivity : BaseActivity<ActivityMainBinding>(), AppBarOwner, BottomNav
}
}
override fun onWindowInsetsChanged(insets: Insets) {
viewBinding.root.updatePadding(
left = insets.left,
right = insets.right,
)
viewBinding.bottomNav?.updatePadding(bottom = insets.bottom)
override fun onApplyWindowInsets(v: View, insets: WindowInsetsCompat): WindowInsetsCompat {
val barsInsets = insets.getInsets(WindowInsetsCompat.Type.systemBars())
viewBinding.toolbarCard.updateLayoutParams<MarginLayoutParams> {
marginEnd = barsInsets.end(v)
marginStart = if (viewBinding.navRail != null) {
0
} else {
barsInsets.start(v)
}
}
return viewBinding.navRail?.let { navRail ->
navRail.updateLayoutParams<MarginLayoutParams> {
marginStart = barsInsets.start(v)
}
WindowInsetsCompat.Builder(insets)
.setInsets(WindowInsetsCompat.Type.systemBars(), barsInsets.consumeRelative(v, start = true))
.build()
} ?: insets
}
override fun onLayoutChange(

@ -15,7 +15,6 @@ 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.graphics.Insets
import com.google.android.material.textfield.TextInputLayout
import dagger.hilt.android.AndroidEntryPoint
import org.koitharu.kotatsu.R
@ -71,16 +70,6 @@ class ProtectActivity :
}
}
override fun onWindowInsetsChanged(insets: Insets) {
val basePadding = resources.getDimensionPixelOffset(R.dimen.screen_padding)
viewBinding.root.setPadding(
basePadding + insets.left,
basePadding + insets.top,
basePadding + insets.right,
basePadding + insets.bottom,
)
}
override fun onClick(v: View) {
when (v.id) {
R.id.button_next -> viewModel.tryUnlock(viewBinding.editPassword.text?.toString().orEmpty())

@ -16,6 +16,7 @@ import androidx.activity.viewModels
import androidx.core.graphics.Insets
import androidx.core.view.MenuHost
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
@ -122,10 +123,10 @@ class ReaderActivity :
viewBinding.slider.setLabelFormatter(PageLabelFormatter())
viewBinding.zoomControl.listener = this
ReaderSliderListener(viewModel, this).attachToSlider(viewBinding.slider)
insetsDelegate.interceptingWindowInsetsListener = this
idlingDetector.bindToLifecycle(this)
viewBinding.buttonPrev.setOnClickListener(controlDelegate)
viewBinding.buttonNext.setOnClickListener(controlDelegate)
ViewCompat.setOnApplyWindowInsetsListener(viewBinding.root, this)
viewModel.onError.observeEvent(
this,
@ -353,8 +354,6 @@ class ReaderActivity :
.build()
}
override fun onWindowInsetsChanged(insets: Insets) = Unit
override fun switchPageBy(delta: Int) {
readerManager.currentReader?.switchPageBy(delta)
}

@ -4,12 +4,8 @@ import android.content.res.Resources
import android.graphics.Bitmap
import android.os.Bundle
import android.view.View
import android.view.ViewGroup
import android.widget.CompoundButton
import androidx.activity.viewModels
import androidx.core.graphics.Insets
import androidx.core.view.updateLayoutParams
import androidx.core.view.updatePadding
import coil3.ImageLoader
import coil3.request.ImageRequest
import coil3.request.bitmapConfig
@ -99,19 +95,6 @@ class ColorFilterConfigActivity :
}
}
override fun onWindowInsetsChanged(insets: Insets) {
viewBinding.root.updatePadding(
left = insets.left,
right = insets.right,
)
viewBinding.scrollView.updatePadding(
bottom = insets.bottom,
)
viewBinding.toolbar.updateLayoutParams<ViewGroup.MarginLayoutParams> {
topMargin = insets.top
}
}
fun showSaveConfirmation() {
MaterialAlertDialogBuilder(this)
.setTitle(R.string.apply)

@ -1,7 +1,6 @@
package org.koitharu.kotatsu.reader.ui.pager
import android.os.Bundle
import androidx.core.graphics.Insets
import androidx.fragment.app.activityViewModels
import androidx.viewbinding.ViewBinding
import org.koitharu.kotatsu.core.prefs.ReaderAnimation
@ -51,8 +50,6 @@ abstract class BaseReaderFragment<B : ViewBinding> : BaseFragment<B>(), ZoomCont
return context?.isAnimationsEnabled == true && viewModel.pageAnimation.value != ReaderAnimation.NONE
}
override fun onWindowInsetsChanged(insets: Insets) = Unit
abstract fun switchPageBy(delta: Int)
abstract fun switchPageTo(position: Int, smooth: Boolean)

@ -2,10 +2,9 @@ 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.graphics.Insets
import androidx.core.view.updatePadding
import coil3.ImageLoader
import coil3.request.error
import coil3.request.fallback
@ -17,6 +16,7 @@ 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.disposeImageRequest
import org.koitharu.kotatsu.core.util.ext.enqueueWith
import org.koitharu.kotatsu.core.util.ext.newImageRequest
@ -48,6 +48,7 @@ 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)
@ -72,15 +73,6 @@ class ScrobblerConfigActivity : BaseActivity<ActivityScrobblerConfigBinding>(),
processIntent(intent)
}
override fun onWindowInsetsChanged(insets: Insets) {
val rv = viewBinding.recyclerView
rv.updatePadding(
left = insets.left + rv.paddingTop,
right = insets.right + rv.paddingTop,
bottom = insets.bottom + rv.paddingTop,
)
}
override fun onItemClick(item: ScrobblingInfo, view: View) {
router.openDetails(item.mangaId)
}

@ -5,7 +5,6 @@ import android.content.Intent
import android.os.Bundle
import android.text.Editable
import android.view.View
import androidx.core.graphics.Insets
import androidx.core.net.toUri
import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.ui.BaseActivity
@ -26,16 +25,6 @@ class KitsuAuthActivity : BaseActivity<ActivityKitsuAuthBinding>(), View.OnClick
viewBinding.editPassword.addTextChangedListener(this)
}
override fun onWindowInsetsChanged(insets: Insets) {
val basePadding = resources.getDimensionPixelOffset(R.dimen.screen_padding)
viewBinding.root.setPadding(
basePadding + insets.left,
basePadding + insets.top,
basePadding + insets.right,
basePadding + insets.bottom,
)
}
override fun onClick(v: View) {
when (v.id) {
R.id.button_cancel -> finish()

@ -2,12 +2,14 @@ package org.koitharu.kotatsu.search.ui
import android.os.Bundle
import android.view.View
import android.view.ViewGroup.MarginLayoutParams
import androidx.core.graphics.Insets
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.updatePadding
import androidx.core.view.updatePaddingRelative
import androidx.fragment.app.Fragment
import androidx.fragment.app.commit
import com.google.android.material.appbar.AppBarLayout
@ -30,11 +32,14 @@ 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.end
import org.koitharu.kotatsu.core.util.ext.getParcelableExtraCompat
import org.koitharu.kotatsu.core.util.ext.getSerializableExtraCompat
import org.koitharu.kotatsu.core.util.ext.getThemeColor
import org.koitharu.kotatsu.core.util.ext.observe
import org.koitharu.kotatsu.core.util.ext.setTextAndVisible
import org.koitharu.kotatsu.core.util.ext.start
import org.koitharu.kotatsu.databinding.ActivityMangaListBinding
import org.koitharu.kotatsu.filter.ui.FilterCoordinator
import org.koitharu.kotatsu.filter.ui.FilterHeaderFragment
@ -53,7 +58,10 @@ import com.google.android.material.R as materialR
@AndroidEntryPoint
class MangaListActivity :
BaseActivity<ActivityMangaListBinding>(),
AppBarOwner, View.OnClickListener, FilterCoordinator.Owner, AppBarLayout.OnOffsetChangedListener {
AppBarOwner, View.OnClickListener,
FilterCoordinator.Owner,
OnApplyWindowInsetsListener,
AppBarLayout.OnOffsetChangedListener {
override val appBar: AppBarLayout
get() = viewBinding.appbar
@ -74,6 +82,8 @@ 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)
@ -82,17 +92,6 @@ class MangaListActivity :
override fun isNsfwContent(): Flow<Boolean> = flowOf(source.isNsfw())
override fun onWindowInsetsChanged(insets: Insets) {
viewBinding.root.updatePadding(
left = insets.left,
right = insets.right,
)
viewBinding.cardSide?.updateLayoutParams<MarginLayoutParams> {
bottomMargin = marginStart + insets.bottom
topMargin = marginStart + insets.top
}
}
override fun onOffsetChanged(appBarLayout: AppBarLayout, verticalOffset: Int) {
val container = viewBinding.containerFilterHeader ?: return
container.background = if (verticalOffset.absoluteValue < appBarLayout.totalScrollRange) {
@ -102,6 +101,31 @@ class MangaListActivity :
}
}
/**
* Only for landscape
*/
override fun onApplyWindowInsets(v: View, insets: WindowInsetsCompat): WindowInsetsCompat {
val barsInsets = insets.getInsets(WindowInsetsCompat.Type.systemBars())
viewBinding.cardSide?.updateLayoutParams<ViewGroup.MarginLayoutParams> {
marginEnd = barsInsets.end(v) + resources.getDimensionPixelOffset(R.dimen.side_card_offset)
topMargin = barsInsets.top + resources.getDimensionPixelOffset(R.dimen.grid_spacing_outer_double)
bottomMargin = barsInsets.bottom + resources.getDimensionPixelOffset(R.dimen.side_card_offset)
}
viewBinding.appbar.updatePaddingRelative(
top = barsInsets.top,
start = barsInsets.start(v),
)
return WindowInsetsCompat.Builder(insets)
.setInsets(
WindowInsetsCompat.Type.systemBars(),
barsInsets.consumeRelative(
v,
top = true,
end = true,
),
).build()
}
override fun onClick(v: View) {
when (v.id) {
R.id.button_order -> router.showFilterSheet()

@ -1,14 +1,13 @@
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.graphics.Insets
import androidx.core.view.updatePadding
import coil3.ImageLoader
import dagger.hilt.android.AndroidEntryPoint
import org.koitharu.kotatsu.R
@ -20,6 +19,7 @@ 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.invalidateNestedItemDecorations
import org.koitharu.kotatsu.core.util.ext.observe
import org.koitharu.kotatsu.core.util.ext.observeEvent
@ -91,6 +91,7 @@ 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))
@ -105,16 +106,6 @@ class SearchActivity :
viewModel.onError.observeEvent(this, SnackbarErrorObserver(viewBinding.recyclerView, null))
}
override fun onWindowInsetsChanged(insets: Insets) {
viewBinding.root.updatePadding(
left = insets.left,
right = insets.right,
)
viewBinding.recyclerView.updatePadding(
bottom = insets.bottom + viewBinding.recyclerView.paddingTop,
)
}
override fun onItemClick(item: Manga, view: View) {
if (!selectionController.onItemClick(item.id)) {
router.openDetails(item)

@ -1,18 +1,17 @@
package org.koitharu.kotatsu.search.ui.suggestion
import android.os.Bundle
import android.view.Gravity
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.core.graphics.Insets
import androidx.core.view.updatePadding
import androidx.fragment.app.activityViewModels
import androidx.recyclerview.widget.ItemTouchHelper
import coil3.ImageLoader
import dagger.hilt.android.AndroidEntryPoint
import org.koitharu.kotatsu.R
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.observe
import org.koitharu.kotatsu.databinding.FragmentSearchSuggestionBinding
import org.koitharu.kotatsu.search.ui.suggestion.adapter.SearchSuggestionAdapter
@ -48,21 +47,12 @@ 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 onWindowInsetsChanged(insets: Insets) {
val extraPadding = resources.getDimensionPixelOffset(R.dimen.list_spacing)
requireViewBinding().root.updatePadding(
top = extraPadding,
right = insets.right,
left = insets.left,
bottom = insets.bottom,
)
}
override fun onRemoveQuery(query: String) {
viewModel.deleteQuery(query)
}

@ -2,12 +2,8 @@ package org.koitharu.kotatsu.settings
import android.content.Intent
import android.os.Bundle
import android.view.ViewGroup.MarginLayoutParams
import androidx.activity.viewModels
import androidx.core.graphics.Insets
import androidx.core.view.isVisible
import androidx.core.view.updateLayoutParams
import androidx.core.view.updatePadding
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentFactory
import androidx.fragment.app.FragmentTransaction
@ -86,16 +82,6 @@ class SettingsActivity :
return true
}
override fun onWindowInsetsChanged(insets: Insets) {
viewBinding.root.updatePadding(
left = insets.left,
right = insets.right,
)
viewBinding.textViewHeader?.updateLayoutParams<MarginLayoutParams> {
topMargin = screenPadding + insets.top
}
}
fun setSectionTitle(title: CharSequence?) {
viewBinding.textViewHeader?.apply {
textAndVisible = title

@ -14,7 +14,6 @@ import android.widget.TextView
import androidx.activity.result.contract.ActivityResultContracts
import androidx.activity.viewModels
import androidx.core.content.ContextCompat
import androidx.core.graphics.Insets
import androidx.core.text.buildSpannedString
import com.google.android.material.snackbar.Snackbar
import dagger.hilt.android.AndroidEntryPoint
@ -91,16 +90,6 @@ class AppUpdateActivity : BaseActivity<ActivityAppUpdateBinding>(), View.OnClick
}
}
override fun onWindowInsetsChanged(insets: Insets) {
val basePadding = resources.getDimensionPixelOffset(R.dimen.screen_padding)
viewBinding.root.setPadding(
basePadding + insets.left,
basePadding + insets.top,
basePadding + insets.right,
basePadding + insets.bottom,
)
}
private suspend fun onNextVersionChanged(version: AppVersion?) {
viewBinding.buttonUpdate.isEnabled = version != null && !viewModel.isLoading.value
if (version == null) {

@ -5,8 +5,6 @@ import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.core.graphics.Insets
import androidx.core.view.updatePadding
import androidx.fragment.app.viewModels
import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.RecyclerView
@ -72,14 +70,6 @@ class NavConfigFragment : BaseFragment<FragmentSettingsSourcesBinding>(), Recycl
super.onDestroyView()
}
override fun onWindowInsetsChanged(insets: Insets) {
requireViewBinding().recyclerView.updatePadding(
bottom = insets.bottom,
left = insets.left,
right = insets.right,
)
}
override fun onClick(v: View) {
var dialog: DialogInterface? = null
val listener = OnListItemClickListener<NavItem> { item, _ ->

@ -11,7 +11,6 @@ import android.view.inputmethod.EditorInfo
import android.widget.CompoundButton
import android.widget.TextView
import androidx.activity.viewModels
import androidx.core.graphics.Insets
import androidx.core.view.isGone
import androidx.core.view.isVisible
import dagger.hilt.android.AndroidEntryPoint
@ -58,16 +57,6 @@ class ProtectSetupActivity :
}
}
override fun onWindowInsetsChanged(insets: Insets) {
val basePadding = resources.getDimensionPixelOffset(R.dimen.screen_padding)
viewBinding.root.setPadding(
basePadding + insets.left,
basePadding + insets.top,
basePadding + insets.right,
basePadding + insets.bottom,
)
}
override fun onClick(v: View) {
when (v.id) {
R.id.button_cancel -> finish()

@ -1,24 +1,24 @@
package org.koitharu.kotatsu.settings.reader
import android.content.DialogInterface
import android.graphics.drawable.ColorDrawable
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
import android.widget.TextView
import androidx.activity.viewModels
import androidx.core.graphics.ColorUtils
import androidx.core.graphics.Insets
import androidx.core.graphics.drawable.toDrawable
import androidx.core.text.bold
import androidx.core.text.buildSpannedString
import androidx.core.view.updatePadding
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.findKeyByValue
import org.koitharu.kotatsu.core.util.ext.getThemeDrawable
import org.koitharu.kotatsu.core.util.ext.observe
@ -39,6 +39,7 @@ class ReaderTapGridConfigActivity : BaseActivity<ActivityReaderTapActionsBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(ActivityReaderTapActionsBinding.inflate(layoutInflater))
viewBinding.root.consumeInsetsAsPadding(Gravity.START or Gravity.END or Gravity.BOTTOM or Gravity.TOP)
supportActionBar?.setDisplayHomeAsUpEnabled(true)
controls[TapGridArea.TOP_LEFT] = viewBinding.textViewTopLeft
controls[TapGridArea.TOP_CENTER] = viewBinding.textViewTopCenter
@ -79,15 +80,6 @@ class ReaderTapGridConfigActivity : BaseActivity<ActivityReaderTapActionsBinding
}
}
override fun onWindowInsetsChanged(insets: Insets) {
viewBinding.root.updatePadding(
left = insets.left,
top = insets.top,
right = insets.right,
bottom = insets.bottom,
)
}
override fun onClick(v: View) {
val area = controls.findKeyByValue(v) ?: return
showActionSelector(area, isLongTap = false)
@ -116,7 +108,8 @@ class ReaderTapGridConfigActivity : BaseActivity<ActivityReaderTapActionsBinding
view.background = createBackground(actions?.tapAction)
}
}
// lint bug
// lint bug
private fun TapAction?.getText(): String = if (this != null) {
getString(nameStringResId)
} else {
@ -157,7 +150,7 @@ class ReaderTapGridConfigActivity : BaseActivity<ActivityReaderTapActionsBinding
return if (action == null) {
ripple
} else {
LayerDrawable(arrayOf(ripple, ColorDrawable(ColorUtils.setAlphaComponent(action.color, 40))))
LayerDrawable(arrayOf(ripple, ColorUtils.setAlphaComponent(action.color, 40).toDrawable()))
}
}
}

@ -4,13 +4,10 @@ import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.core.graphics.Insets
import androidx.core.view.updatePadding
import androidx.fragment.app.activityViewModels
import androidx.recyclerview.widget.AsyncListDiffer.ListListener
import androidx.recyclerview.widget.LinearLayoutManager
import dagger.hilt.android.AndroidEntryPoint
import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.ui.BaseFragment
import org.koitharu.kotatsu.core.ui.BaseListAdapter
import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener
@ -39,16 +36,6 @@ class SettingsSearchFragment : BaseFragment<FragmentSearchSuggestionBinding>(),
viewModel.content.observe(viewLifecycleOwner, adapter)
}
override fun onWindowInsetsChanged(insets: Insets) {
val extraPadding = resources.getDimensionPixelOffset(R.dimen.list_spacing)
requireViewBinding().root.updatePadding(
top = extraPadding,
right = insets.right,
left = insets.left,
bottom = insets.bottom,
)
}
override fun onItemClick(item: SettingsItem, view: View) = viewModel.navigateToPreference(item)
override fun onCurrentListChanged(

@ -7,9 +7,7 @@ import android.os.Bundle
import android.view.MenuItem
import android.widget.Toast
import androidx.activity.result.contract.ActivityResultContract
import androidx.core.graphics.Insets
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
@ -125,11 +123,6 @@ class SourceAuthActivity : BaseActivity<ActivityBrowserBinding>(), BrowserCallba
onBackPressedCallback.onHistoryChanged()
}
override fun onWindowInsetsChanged(insets: Insets) {
viewBinding.appbar.updatePadding(top = insets.top)
viewBinding.webView.updatePadding(bottom = insets.bottom)
}
class Contract : ActivityResultContract<MangaSource, Boolean>() {
override fun createIntent(context: Context, input: MangaSource): Intent {
return AppRouter.sourceAuthIntent(context, input)

@ -1,14 +1,13 @@
package org.koitharu.kotatsu.settings.sources.catalog
import android.os.Bundle
import android.view.Gravity
import android.view.Menu
import android.view.MenuItem
import android.view.View
import androidx.activity.viewModels
import androidx.appcompat.widget.PopupMenu
import androidx.appcompat.widget.SearchView
import androidx.core.graphics.Insets
import androidx.core.view.updatePadding
import coil3.ImageLoader
import com.google.android.material.appbar.AppBarLayout
import com.google.android.material.chip.Chip
@ -24,6 +23,7 @@ import org.koitharu.kotatsu.core.ui.util.ReversibleActionObserver
import org.koitharu.kotatsu.core.ui.widgets.ChipsView
import org.koitharu.kotatsu.core.ui.widgets.ChipsView.ChipModel
import org.koitharu.kotatsu.core.util.LocaleComparator
import org.koitharu.kotatsu.core.util.ext.consumeInsetsAsPadding
import org.koitharu.kotatsu.core.util.ext.getDisplayName
import org.koitharu.kotatsu.core.util.ext.observe
import org.koitharu.kotatsu.core.util.ext.observeEvent
@ -53,6 +53,7 @@ class SourcesCatalogActivity : BaseActivity<ActivitySourcesCatalogBinding>(),
supportActionBar?.setDisplayHomeAsUpEnabled(true)
val sourcesAdapter = SourcesCatalogAdapter(this, coil, this)
with(viewBinding.recyclerView) {
consumeInsetsAsPadding(Gravity.START or Gravity.END or Gravity.BOTTOM)
setHasFixedSize(true)
addItemDecoration(TypedListSpacingDecoration(context, false))
adapter = sourcesAdapter
@ -70,16 +71,6 @@ class SourcesCatalogActivity : BaseActivity<ActivitySourcesCatalogBinding>(),
addMenuProvider(SourcesCatalogMenuProvider(this, viewModel, this))
}
override fun onWindowInsetsChanged(insets: Insets) {
viewBinding.root.updatePadding(
left = insets.left,
right = insets.right,
)
viewBinding.recyclerView.updatePadding(
bottom = insets.bottom,
)
}
override fun onChipClick(chip: Chip, data: Any?) {
when (data) {
is ContentType -> viewModel.setContentType(data, !chip.isChecked)

@ -1,15 +1,14 @@
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.ViewGroup
import androidx.appcompat.widget.SearchView
import androidx.core.graphics.Insets
import androidx.core.view.MenuProvider
import androidx.core.view.updatePadding
import androidx.fragment.app.viewModels
import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.RecyclerView
@ -24,6 +23,7 @@ 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.getItem
import org.koitharu.kotatsu.core.util.ext.observe
import org.koitharu.kotatsu.core.util.ext.observeEvent
@ -72,6 +72,7 @@ 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)
@ -96,14 +97,6 @@ class SourcesManageFragment :
super.onDestroyView()
}
override fun onWindowInsetsChanged(insets: Insets) {
requireViewBinding().recyclerView.updatePadding(
bottom = insets.bottom,
left = insets.left,
right = insets.right,
)
}
override fun onItemSettingsClick(item: SourceConfigItem.SourceItem) {
(activity as? SettingsActivity)?.openFragment(
fragmentClass = SourceSettingsFragment::class.java,

@ -9,6 +9,9 @@ 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
import androidx.core.view.updatePadding
@ -30,7 +33,7 @@ import org.koitharu.kotatsu.settings.storage.RequestStorageManagerPermissionCont
@AndroidEntryPoint
class MangaDirectoriesActivity : BaseActivity<ActivityMangaDirectoriesBinding>(),
OnListItemClickListener<DirectoryModel>, View.OnClickListener {
OnListItemClickListener<DirectoryModel>, View.OnClickListener, OnApplyWindowInsetsListener {
private val viewModel: MangaDirectoriesViewModel by viewModels()
private val pickFileTreeLauncher = OpenDocumentTreeHelper(
@ -61,6 +64,7 @@ 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
@ -87,18 +91,22 @@ class MangaDirectoriesActivity : BaseActivity<ActivityMangaDirectoriesBinding>()
}
}
override fun onWindowInsetsChanged(insets: Insets) {
override fun onApplyWindowInsets(v: View, insets: WindowInsetsCompat): WindowInsetsCompat {
val barsInsets = insets.getInsets(WindowInsetsCompat.Type.systemBars())
viewBinding.fabAdd.updateLayoutParams<ViewGroup.MarginLayoutParams> {
rightMargin = topMargin + insets.right
leftMargin = topMargin + insets.left
bottomMargin = topMargin + insets.bottom
rightMargin = topMargin + barsInsets.right
leftMargin = topMargin + barsInsets.left
bottomMargin = topMargin + barsInsets.bottom
}
viewBinding.root.updatePadding(
left = insets.left,
right = insets.right,
left = barsInsets.left,
right = barsInsets.right,
)
viewBinding.recyclerView.updatePadding(
bottom = insets.bottom,
bottom = barsInsets.bottom,
)
return WindowInsetsCompat.Builder(insets)
.setInsets(WindowInsetsCompat.Type.systemBars(), Insets.NONE)
.build()
}
}

@ -8,7 +8,6 @@ import android.view.ViewStub
import android.widget.CompoundButton
import androidx.activity.viewModels
import androidx.appcompat.widget.PopupMenu
import androidx.core.graphics.Insets
import androidx.core.view.isGone
import androidx.core.view.isVisible
import androidx.recyclerview.widget.AsyncListDiffer
@ -89,8 +88,6 @@ class StatsActivity : BaseActivity<ActivityStatsBinding>(),
}
}
override fun onWindowInsetsChanged(insets: Insets) = Unit
override fun onClick(v: View) {
when (v.id) {
R.id.chip_period -> showPeriodSelector()

@ -1,8 +1,6 @@
package org.koitharu.kotatsu.suggestions.ui
import android.os.Bundle
import androidx.core.graphics.Insets
import androidx.core.view.updatePadding
import androidx.fragment.app.commit
import com.google.android.material.appbar.AppBarLayout
import dagger.hilt.android.AndroidEntryPoint
@ -31,11 +29,4 @@ class SuggestionsActivity :
}
}
}
override fun onWindowInsetsChanged(insets: Insets) {
viewBinding.root.updatePadding(
left = insets.left,
right = insets.right,
)
}
}

@ -11,7 +11,6 @@ import android.widget.Button
import android.widget.Toast
import androidx.activity.OnBackPressedCallback
import androidx.activity.viewModels
import androidx.core.graphics.Insets
import androidx.core.view.isVisible
import androidx.fragment.app.FragmentResultListener
import androidx.transition.Fade
@ -66,16 +65,6 @@ class SyncAuthActivity : BaseActivity<ActivitySyncAuthBinding>(), View.OnClickLi
pageBackCallback.update()
}
override fun onWindowInsetsChanged(insets: Insets) {
val basePadding = resources.getDimensionPixelOffset(R.dimen.screen_padding)
viewBinding.root.setPadding(
basePadding + insets.left,
basePadding + insets.top,
basePadding + insets.right,
basePadding + insets.bottom,
)
}
override fun onClick(v: View) {
when (v.id) {
R.id.button_cancel -> {

@ -1,16 +1,16 @@
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.graphics.Insets
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.observe
import org.koitharu.kotatsu.databinding.ActivityTrackerDebugBinding
import org.koitharu.kotatsu.list.ui.adapter.ListItemType
@ -32,6 +32,7 @@ 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))
@ -39,19 +40,6 @@ class TrackerDebugActivity : BaseActivity<ActivityTrackerDebugBinding>(), OnList
viewModel.content.observe(this, tracksAdapter)
}
override fun onWindowInsetsChanged(insets: Insets) {
val rv = viewBinding.recyclerView
rv.updatePadding(
left = insets.left + rv.paddingTop,
right = insets.right + rv.paddingTop,
bottom = insets.bottom,
)
viewBinding.toolbar.updatePadding(
left = insets.left,
right = insets.right,
)
}
override fun onItemClick(item: TrackDebugItem, view: View) {
router.openDetails(item.manga)
}

@ -4,8 +4,6 @@ import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.core.graphics.Insets
import androidx.core.view.updatePadding
import androidx.fragment.app.viewModels
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
@ -79,13 +77,6 @@ class FeedFragment :
viewModel.isRunning.observe(viewLifecycleOwner, this::onIsTrackerRunningChanged)
}
override fun onWindowInsetsChanged(insets: Insets) {
val rv = requireViewBinding().recyclerView
rv.updatePadding(
bottom = insets.bottom + rv.paddingTop,
)
}
override fun onRefresh() {
viewModel.update()
}

@ -1,8 +1,6 @@
package org.koitharu.kotatsu.tracker.ui.updates
import android.os.Bundle
import androidx.core.graphics.Insets
import androidx.core.view.updatePadding
import androidx.fragment.app.commit
import com.google.android.material.appbar.AppBarLayout
import dagger.hilt.android.AndroidEntryPoint
@ -32,11 +30,4 @@ class UpdatesActivity :
}
}
}
override fun onWindowInsetsChanged(insets: Insets) {
viewBinding.root.updatePadding(
left = insets.left,
right = insets.right,
)
}
}

@ -3,13 +3,13 @@ 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.graphics.Insets
import androidx.core.view.updatePadding
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.databinding.ActivityAppwidgetRecentBinding
import com.google.android.material.R as materialR
@ -28,6 +28,7 @@ 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,
@ -54,15 +55,6 @@ class RecentWidgetConfigActivity :
}
}
override fun onWindowInsetsChanged(insets: Insets) {
viewBinding.root.updatePadding(
left = insets.left,
right = insets.right,
bottom = insets.bottom,
top = insets.top,
)
}
private fun updateWidget() {
val intent = Intent(this, RecentWidgetProvider::class.java)
intent.action = AppWidgetManager.ACTION_APPWIDGET_UPDATE

@ -1,21 +1,18 @@
package org.koitharu.kotatsu.widget.shelf
import android.app.Activity
import android.appwidget.AppWidgetManager
import android.content.Intent
import android.os.Bundle
import android.view.Gravity
import android.view.View
import android.view.ViewGroup
import androidx.activity.viewModels
import androidx.core.graphics.Insets
import androidx.core.view.updateLayoutParams
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.observe
import org.koitharu.kotatsu.core.util.ext.observeEvent
import org.koitharu.kotatsu.databinding.ActivityAppwidgetShelfBinding
@ -43,6 +40,7 @@ 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,
@ -79,23 +77,6 @@ class ShelfWidgetConfigActivity :
viewModel.checkedId = item.id
}
override fun onWindowInsetsChanged(insets: Insets) {
viewBinding.recyclerView.updatePadding(
left = insets.left,
right = insets.right,
bottom = insets.bottom,
)
with(viewBinding.toolbar) {
updatePadding(
left = insets.left,
right = insets.right,
)
updateLayoutParams<ViewGroup.MarginLayoutParams> {
topMargin = insets.top
}
}
}
private fun updateWidget() {
val intent = Intent(this, ShelfWidgetProvider::class.java)
intent.action = AppWidgetManager.ACTION_APPWIDGET_UPDATE

@ -50,7 +50,8 @@
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
android:layout_height="match_parent"
android:paddingBottom="@dimen/margin_normal">
<com.google.android.material.imageview.ShapeableImageView
android:id="@+id/imageView_cover"
@ -328,7 +329,7 @@
android:id="@+id/card_chapters"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginTop="2dp"
android:layout_marginTop="@dimen/grid_spacing_outer"
android:layout_marginEnd="@dimen/side_card_offset"
android:layout_marginBottom="@dimen/side_card_offset"
app:layout_constraintBottom_toBottomOf="parent"

@ -34,18 +34,17 @@
android:layout_height="wrap_content"
android:clipToPadding="false"
android:fitsSystemWindows="false"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:paddingHorizontal="@dimen/margin_normal"
android:stateListAnimator="@null"
app:liftOnScrollColor="@null"
app:liftOnScroll="false">
app:liftOnScroll="false"
app:liftOnScrollColor="@null">
<org.koitharu.kotatsu.core.ui.widgets.WindowInsetHolder
android:id="@+id/insetsHolder"
android:fitsSystemWindows="true"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="top"
android:fitsSystemWindows="true"
app:layout_scrollFlags="scroll|enterAlways|snap" />
<FrameLayout

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

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

@ -43,7 +43,7 @@
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/details_bs_peek_height">
android:paddingBottom="@dimen/margin_normal">
<com.google.android.material.imageview.ShapeableImageView
android:id="@+id/imageView_cover"

@ -20,7 +20,7 @@
android:layout_height="wrap_content"
android:clipToPadding="false"
android:fitsSystemWindows="false"
android:paddingHorizontal="16dp"
android:paddingHorizontal="@dimen/margin_normal"
android:stateListAnimator="@null"
app:liftOnScroll="false"
app:liftOnScrollColor="@null">
@ -37,8 +37,8 @@
android:id="@+id/toolbar_card"
android:layout_width="match_parent"
android:layout_height="56dp"
android:layout_marginTop="16dp"
android:layout_marginBottom="8dp"
android:layout_marginTop="@dimen/margin_normal"
android:layout_marginBottom="@dimen/margin_small"
android:background="@drawable/search_bar_background"
android:theme="@style/ThemeOverlay.Kotatsu.MainToolbar"
app:layout_scrollFlags="scroll|enterAlways|snap">

Loading…
Cancel
Save