Update reader activity ui

This commit is contained in:
Koitharu
2023-05-30 08:49:21 +03:00
parent 2442e7cbe1
commit 3d05541f61
19 changed files with 142 additions and 80 deletions

View File

@@ -24,6 +24,7 @@ abstract class BaseFullscreenActivity<B : ViewBinding> :
WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES
}
}
insetsControllerCompat.systemBarsBehavior = WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
showSystemUI()
}

View File

@@ -4,6 +4,7 @@ import android.content.Context
import android.util.AttributeSet
import android.view.ViewGroup
import androidx.annotation.AttrRes
import androidx.core.view.isVisible
import androidx.recyclerview.widget.RecyclerView
import org.koitharu.kotatsu.R
@@ -15,6 +16,12 @@ class FastScrollRecyclerView @JvmOverloads constructor(
val fastScroller = FastScroller(context, attrs)
var isFastScrollerEnabled: Boolean = true
set(value) {
field = value
fastScroller.isVisible = value && isVisible
}
init {
fastScroller.id = R.id.fast_scroller
fastScroller.layoutParams = ViewGroup.LayoutParams(
@@ -30,7 +37,7 @@ class FastScrollRecyclerView @JvmOverloads constructor(
override fun setVisibility(visibility: Int) {
super.setVisibility(visibility)
fastScroller.visibility = visibility
fastScroller.visibility = if (isFastScrollerEnabled) visibility else GONE
}
override fun onAttachedToWindow() {

View File

@@ -14,6 +14,7 @@ import android.view.Menu
import android.view.MenuItem
import android.view.MotionEvent
import android.view.View
import android.view.ViewGroup.MarginLayoutParams
import android.view.WindowManager
import androidx.activity.viewModels
import androidx.core.graphics.Insets
@@ -21,6 +22,7 @@ import androidx.core.view.OnApplyWindowInsetsListener
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.lifecycle.lifecycleScope
import com.google.android.material.snackbar.Snackbar
@@ -333,11 +335,11 @@ class ReaderActivity :
right = systemBars.right,
left = systemBars.left,
)
viewBinding.appbarBottom?.updatePadding(
bottom = systemBars.bottom,
right = systemBars.right,
left = systemBars.left,
)
viewBinding.appbarBottom?.updateLayoutParams<MarginLayoutParams> {
bottomMargin = systemBars.bottom + topMargin
rightMargin = systemBars.right + topMargin
leftMargin = systemBars.left + topMargin
}
return WindowInsetsCompat.Builder(insets)
.setInsets(WindowInsetsCompat.Type.systemBars(), Insets.NONE)
.build()
@@ -373,19 +375,15 @@ class ReaderActivity :
}
private fun onUiStateChanged(pair: Pair<ReaderUiState?, ReaderUiState?>) {
val (uiState: ReaderUiState?, previous: ReaderUiState?) = pair
title = uiState?.chapterName ?: uiState?.mangaName ?: getString(R.string.loading_)
val (previous: ReaderUiState?, uiState: ReaderUiState?) = pair
title = uiState?.resolveTitle(this) ?: getString(R.string.loading_)
viewBinding.infoBar.update(uiState)
if (uiState == null) {
supportActionBar?.subtitle = null
viewBinding.slider.isVisible = false
return
}
supportActionBar?.subtitle = if (uiState.chapterNumber in 1..uiState.chaptersTotal) {
getString(R.string.chapter_d_of_d, uiState.chapterNumber, uiState.chaptersTotal)
} else {
null
}
supportActionBar?.subtitle = uiState.chapterName
if (previous?.chapterName != null && uiState.chapterName != previous.chapterName) {
if (!uiState.chapterName.isNullOrEmpty()) {
viewBinding.toastView.showTemporary(uiState.chapterName, TOAST_DURATION)

View File

@@ -366,6 +366,7 @@ class ReaderViewModel @Inject constructor(
val chapter = state?.chapterId?.let { chaptersLoader.peekChapter(it) }
val newState = ReaderUiState(
mangaName = manga?.any?.title,
branch = chapter?.branch,
chapterName = chapter?.name,
chapterNumber = chapter?.number ?: 0,
chaptersTotal = manga?.any?.getChapters(chapter?.branch)?.size ?: 0,

View File

@@ -41,7 +41,8 @@ class ReaderConfigBottomSheet :
ActivityResultCallback<Uri?>,
View.OnClickListener,
MaterialButtonToggleGroup.OnButtonCheckedListener,
Slider.OnChangeListener, CompoundButton.OnCheckedChangeListener {
Slider.OnChangeListener,
CompoundButton.OnCheckedChangeListener {
private val viewModel by activityViewModels<ReaderViewModel>()
private val savePageRequest = registerForActivityResult(PageSaveContract(), this)

View File

@@ -1,7 +1,11 @@
package org.koitharu.kotatsu.reader.ui.pager
import android.content.Context
import org.koitharu.kotatsu.R
data class ReaderUiState(
val mangaName: String?,
val branch: String?,
val chapterName: String?,
val chapterNumber: Int,
val chaptersTotal: Int,
@@ -14,4 +18,10 @@ data class ReaderUiState(
fun isSliderAvailable(): Boolean {
return isSliderEnabled && totalPages > 1 && currentPage < totalPages
}
fun resolveTitle(context: Context): String? = when {
mangaName == null -> null
branch == null -> mangaName
else -> context.getString(R.string.manga_branch_title_template, mangaName, branch)
}
}

View File

@@ -124,6 +124,7 @@ class PagesThumbnailsSheet :
} else {
headerBar.subtitle = null
}
viewBinding?.recyclerView?.isFastScrollerEnabled = isExpanded
}
private inner class ScrollListener : BoundsScrollListener(3, 3) {

View File

@@ -1,10 +1,12 @@
package org.koitharu.kotatsu.reader.ui.thumbnails.adapter
import android.content.Context
import androidx.lifecycle.LifecycleOwner
import androidx.recyclerview.widget.DiffUtil
import coil.ImageLoader
import com.hannesdorfmann.adapterdelegates4.AsyncListDifferDelegationAdapter
import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener
import org.koitharu.kotatsu.core.ui.list.fastscroll.FastScroller
import org.koitharu.kotatsu.list.ui.adapter.listHeaderAD
import org.koitharu.kotatsu.list.ui.adapter.loadingFooterAD
import org.koitharu.kotatsu.list.ui.model.ListHeader
@@ -16,7 +18,7 @@ class PageThumbnailAdapter(
coil: ImageLoader,
lifecycleOwner: LifecycleOwner,
clickListener: OnListItemClickListener<PageThumbnail>,
) : AsyncListDifferDelegationAdapter<ListModel>(DiffCallback()) {
) : AsyncListDifferDelegationAdapter<ListModel>(DiffCallback()), FastScroller.SectionIndexer {
init {
delegatesManager.addDelegate(ITEM_TYPE_THUMBNAIL, pageThumbnailAD(coil, lifecycleOwner, clickListener))
@@ -24,6 +26,17 @@ class PageThumbnailAdapter(
.addDelegate(ITEM_LOADING, loadingFooterAD())
}
override fun getSectionText(context: Context, position: Int): CharSequence? {
val list = items
for (i in (0..position).reversed()) {
val item = list.getOrNull(i) ?: continue
if (item is ListHeader) {
return item.getText(context)
}
}
return null
}
private class DiffCallback : DiffUtil.ItemCallback<ListModel>() {
override fun areItemsTheSame(oldItem: ListModel, newItem: ListModel): Boolean {

View File

@@ -1,9 +1,11 @@
package org.koitharu.kotatsu.tracker.ui.feed.adapter
import android.content.Context
import androidx.lifecycle.LifecycleOwner
import androidx.recyclerview.widget.DiffUtil
import coil.ImageLoader
import com.hannesdorfmann.adapterdelegates4.AsyncListDifferDelegationAdapter
import org.koitharu.kotatsu.core.ui.list.fastscroll.FastScroller
import org.koitharu.kotatsu.core.ui.model.DateTimeAgo
import org.koitharu.kotatsu.list.ui.adapter.MangaListListener
import org.koitharu.kotatsu.list.ui.adapter.emptyStateListAD
@@ -21,7 +23,7 @@ class FeedAdapter(
coil: ImageLoader,
lifecycleOwner: LifecycleOwner,
listener: MangaListListener,
) : AsyncListDifferDelegationAdapter<ListModel>(DiffCallback()) {
) : AsyncListDifferDelegationAdapter<ListModel>(DiffCallback()), FastScroller.SectionIndexer {
init {
delegatesManager
@@ -34,6 +36,17 @@ class FeedAdapter(
.addDelegate(ITEM_TYPE_DATE_HEADER, relatedDateItemAD())
}
override fun getSectionText(context: Context, position: Int): CharSequence? {
val list = items
for (i in (0..position).reversed()) {
val item = list.getOrNull(i) ?: continue
if (item is DateTimeAgo) {
return item.format(context.resources)
}
}
return null
}
private class DiffCallback : DiffUtil.ItemCallback<ListModel>() {
override fun areItemsTheSame(oldItem: ListModel, newItem: ListModel) = when {

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
<androidx.coordinatorlayout.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
@@ -22,27 +22,13 @@
android:visibility="gone"
tools:visibility="visible" />
<org.koitharu.kotatsu.reader.ui.ReaderToastView
android:id="@+id/toastView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|center_horizontal"
android:layout_marginBottom="20dp"
android:background="@drawable/bg_reader_indicator"
android:drawablePadding="6dp"
android:singleLine="true"
android:textAppearance="?attr/textAppearanceBodySmall"
android:theme="@style/ThemeOverlay.Material3.Dark"
tools:text="@string/loading_" />
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/appbar_top"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/dim"
android:elevation="0dp"
android:theme="@style/ThemeOverlay.Material3.Dark"
app:elevation="0dp">
android:elevation="@dimen/m3_card_elevated_elevation"
app:elevation="@dimen/m3_card_elevated_elevation"
app:liftOnScroll="false">
<LinearLayout
android:layout_width="match_parent"
@@ -53,16 +39,14 @@
android:id="@id/toolbar"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
app:popupTheme="@style/ThemeOverlay.Kotatsu" />
android:layout_weight="1" />
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/toolbar_bottom"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
app:menu="@menu/opt_reader_bottom"
app:popupTheme="@style/ThemeOverlay.Kotatsu">
app:menu="@menu/opt_reader_bottom">
<com.google.android.material.slider.Slider
android:id="@+id/slider"
@@ -79,6 +63,20 @@
</com.google.android.material.appbar.AppBarLayout>
<org.koitharu.kotatsu.reader.ui.ReaderToastView
android:id="@+id/toastView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|center_horizontal"
android:layout_marginBottom="20dp"
android:background="@drawable/bg_reader_indicator"
android:drawablePadding="6dp"
android:singleLine="true"
android:textAppearance="?attr/textAppearanceBodySmall"
android:theme="@style/ThemeOverlay.Material3.Dark"
app:layout_dodgeInsetEdges="bottom"
tools:text="@string/loading_" />
<LinearLayout
android:id="@+id/layout_loading"
android:layout_width="wrap_content"
@@ -103,4 +101,4 @@
</LinearLayout>
</FrameLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@@ -206,6 +206,7 @@
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:showAnimationBehavior="inward"
app:trackCornerRadius="0dp"
tools:visibility="visible" />
<androidx.constraintlayout.widget.Group

View File

@@ -25,6 +25,7 @@
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/appbar"
app:trackCornerRadius="0dp"
tools:visibility="visible" />
<com.google.android.material.appbar.AppBarLayout
@@ -43,4 +44,4 @@
</com.google.android.material.appbar.AppBarLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
<androidx.coordinatorlayout.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
@@ -12,19 +12,6 @@
android:layout_width="match_parent"
android:layout_height="match_parent" />
<org.koitharu.kotatsu.reader.ui.ReaderToastView
android:id="@+id/toastView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|center_horizontal"
android:layout_marginBottom="20dp"
android:background="@drawable/bg_reader_indicator"
android:drawablePadding="6dp"
android:singleLine="true"
android:textAppearance="?attr/textAppearanceBodySmall"
android:theme="@style/ThemeOverlay.Material3.Dark"
tools:text="@string/loading_" />
<org.koitharu.kotatsu.reader.ui.ReaderInfoBarView
android:id="@+id/infoBar"
android:layout_width="match_parent"
@@ -38,36 +25,34 @@
android:id="@+id/appbar_top"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/dim"
android:elevation="0dp"
android:theme="@style/ThemeOverlay.Material3.Dark"
app:elevation="0dp">
android:elevation="@dimen/m3_card_elevated_elevation"
app:elevation="@dimen/m3_card_elevated_elevation"
app:liftOnScroll="false">
<com.google.android.material.appbar.MaterialToolbar
android:id="@id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:elevation="@dimen/m3_card_elevated_elevation"
app:elevation="@dimen/m3_card_elevated_elevation"
app:popupTheme="@style/ThemeOverlay.Kotatsu" />
</com.google.android.material.appbar.AppBarLayout>
<com.google.android.material.appbar.AppBarLayout
<com.google.android.material.card.MaterialCardView
android:id="@+id/appbar_bottom"
style="?materialCardViewElevatedStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:background="@color/dim"
android:elevation="0dp"
android:theme="@style/ThemeOverlay.Material3.Dark"
app:elevation="0dp"
tools:visibility="gone">
android:layout_margin="8dp"
app:layout_insetEdge="bottom">
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/toolbar_bottom"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:menu="@menu/opt_reader_bottom"
app:popupTheme="@style/ThemeOverlay.Kotatsu">
app:menu="@menu/opt_reader_bottom">
<com.google.android.material.slider.Slider
android:id="@+id/slider"
@@ -80,7 +65,21 @@
</com.google.android.material.appbar.MaterialToolbar>
</com.google.android.material.appbar.AppBarLayout>
</com.google.android.material.card.MaterialCardView>
<org.koitharu.kotatsu.reader.ui.ReaderToastView
android:id="@+id/toastView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|center_horizontal"
android:layout_marginBottom="20dp"
android:background="@drawable/bg_reader_indicator"
android:drawablePadding="6dp"
android:singleLine="true"
android:textAppearance="?attr/textAppearanceBodySmall"
android:theme="@style/ThemeOverlay.Material3.Dark"
app:layout_dodgeInsetEdges="bottom"
tools:text="@string/loading_" />
<LinearLayout
android:id="@+id/layout_loading"
@@ -94,7 +93,8 @@
android:id="@+id/progressBar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:indeterminate="true" />
android:indeterminate="true"
app:trackCornerRadius="@dimen/mtrl_progress_indicator_full_rounded_corner_radius" />
<TextView
android:id="@+id/textView_loading"
@@ -106,4 +106,4 @@
</LinearLayout>
</FrameLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@@ -218,6 +218,7 @@
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:showAnimationBehavior="inward"
app:trackCornerRadius="0dp"
tools:visibility="visible" />
<androidx.constraintlayout.widget.Group

View File

@@ -57,7 +57,6 @@
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/barrier_top"
app:trackColor="?colorPrimaryContainer"
app:trackCornerRadius="12dp"
tools:progress="25" />
<TextView

View File

@@ -12,16 +12,22 @@
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView"
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clipToPadding="false"
android:padding="@dimen/grid_spacing"
android:scrollbarStyle="outsideOverlay"
android:scrollbars="vertical"
app:layoutManager="androidx.recyclerview.widget.GridLayoutManager"
app:spanCount="3"
tools:listitem="@layout/item_page_thumb" />
android:layout_height="match_parent">
<org.koitharu.kotatsu.core.ui.list.fastscroll.FastScrollRecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clipToPadding="false"
android:padding="@dimen/grid_spacing"
app:bubbleSize="small"
app:layoutManager="androidx.recyclerview.widget.GridLayoutManager"
app:spanCount="3"
app:trackColor="?attr/colorOutline"
tools:listitem="@layout/item_page_thumb" />
</FrameLayout>
</LinearLayout>

View File

@@ -424,4 +424,5 @@
<string name="port">Port</string>
<string name="proxy">Proxy</string>
<string name="invalid_value_message">Invalid value</string>
<string name="manga_branch_title_template">%1$s (%2$s)</string>
</resources>

View File

@@ -76,6 +76,14 @@
<item name="android:textSize">18sp</item>
</style>
<style name="Widget.Kotatsu.CircularProgressIndicator" parent="Widget.Material3.CircularProgressIndicator">
<item name="trackCornerRadius">@dimen/mtrl_progress_indicator_full_rounded_corner_radius</item>
</style>
<style name="Widget.Kotatsu.LinearProgressIndicator" parent="Widget.Material3.LinearProgressIndicator">
<item name="trackCornerRadius">@dimen/mtrl_progress_indicator_full_rounded_corner_radius</item>
</style>
<style name="Widget.Kotatsu.Chip" parent="Widget.Material3.Chip.Suggestion">
<item name="chipSurfaceColor">?attr/colorSurface</item>
<item name="android:textColor">?attr/colorOnSurfaceVariant</item>

View File

@@ -74,6 +74,8 @@
<item name="materialSwitchStyle">@style/Widget.Material3.CompoundButton.MaterialSwitch</item>
<item name="switchPreferenceCompatStyle">@style/Preference.SwitchPreferenceCompat.M3</item>
<item name="collapsingToolbarLayoutStyle">@style/Widget.Material3.CollapsingToolbar.Medium</item>
<item name="circularProgressIndicatorStyle">@style/Widget.Kotatsu.CircularProgressIndicator</item>
<item name="linearProgressIndicatorStyle">@style/Widget.Kotatsu.LinearProgressIndicator</item>
<!-- Text appearance -->
<item name="actionMenuTextAppearance">@style/TextAppearance.Kotatsu.Menu</item>