diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaController.kt index 06cc793b1..ff3d90d9d 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaController.kt @@ -109,7 +109,6 @@ import exh.metadata.metadata.base.FlatMetadata import exh.recs.RecommendsController import exh.source.MERGED_SOURCE_ID import exh.source.getMainSource -import exh.source.isEhBasedSource import exh.source.isMdBasedSource import kotlinx.coroutines.CancellationException import kotlinx.coroutines.Dispatchers @@ -281,11 +280,17 @@ class MangaController : override fun onViewCreated(view: View) { super.onViewCreated(view) - binding.recycler.applyInsetter { - type(navigationBars = true) { - padding() + listOfNotNull(binding.fullRecycler, binding.infoRecycler, binding.chaptersRecycler) + .forEach { + it.applyInsetter { + type(navigationBars = true) { + padding() + } + } + + it.layoutManager = LinearLayoutManager(view.context) + it.setHasFixedSize(true) } - } binding.actionToolbar.applyInsetter { type(navigationBars = true) { margin(bottom = true) @@ -293,59 +298,70 @@ class MangaController : } if (manga == null || source == null) return - val adapters: MutableList<RecyclerView.Adapter<out RecyclerView.ViewHolder>?> = mutableListOf() // Init RecyclerView and adapter + mangaInfoAdapter = MangaInfoHeaderAdapter(this, binding.infoRecycler != null) + chaptersHeaderAdapter = MangaChaptersHeaderAdapter(this) + chaptersAdapter = ChaptersAdapter(this, view.context) // SY --> - mangaInfoAdapter = MangaInfoHeaderAdapter(this) - - adapters += mangaInfoAdapter - val mainSource = presenter.source.getMainSource() if (mainSource is MetadataSource<*, *>) { mangaMetaInfoAdapter = mainSource.getDescriptionAdapter(this) - mangaMetaInfoAdapter?.let { adapters += it } } - mangaInfoItemAdapter = MangaInfoItemAdapter(this, fromSource) - adapters += mangaInfoItemAdapter - if (!preferences.recommendsInOverflow().get() || smartSearchConfig != null) { mangaInfoButtonsAdapter = MangaInfoButtonsAdapter(this) - adapters += mangaInfoButtonsAdapter + } + mangaInfoItemAdapter = MangaInfoItemAdapter(this, fromSource, binding.infoRecycler != null) + // SY <-- + + // Phone layout + binding.fullRecycler?.let { + it.adapter = ConcatAdapter( + listOfNotNull( + mangaInfoAdapter, + mangaMetaInfoAdapter, + mangaInfoItemAdapter, + mangaInfoButtonsAdapter, + chaptersHeaderAdapter, + chaptersAdapter + ) + ) + + it.scrollEvents() + .onEach { updateToolbarTitleAlpha() } + .launchIn(viewScope) + } + // Tablet layout + binding.infoRecycler?.let { + it.adapter = ConcatAdapter( + listOfNotNull( + mangaInfoAdapter, + mangaMetaInfoAdapter, + mangaInfoItemAdapter, + mangaInfoButtonsAdapter + ) + ) + } + binding.chaptersRecycler?.let { + it.adapter = ConcatAdapter(chaptersHeaderAdapter, chaptersAdapter) } - chaptersHeaderAdapter = MangaChaptersHeaderAdapter(this) - - adapters += chaptersHeaderAdapter - - chaptersAdapter = ChaptersAdapter(this, view.context) - - adapters += chaptersAdapter - - binding.recycler.adapter = ConcatAdapter(adapters) - // SY <-- - binding.recycler.layoutManager = LinearLayoutManager(view.context) - binding.recycler.setHasFixedSize(true) chaptersAdapter?.fastScroller = binding.fastScroller - actionFabScrollListener = actionFab?.shrinkOnScroll(binding.recycler) + actionFabScrollListener = actionFab?.shrinkOnScroll(chaptersRecycler) // Skips directly to chapters list if navigated to from the library - binding.recycler.post { + chaptersRecycler.post { if (!fromSource && preferences.jumpToChapters()) { - (binding.recycler.layoutManager as LinearLayoutManager).scrollToPositionWithOffset(1, 0) + (chaptersRecycler.layoutManager as LinearLayoutManager).scrollToPositionWithOffset(1, 0) } // Delayed in case we need to jump to chapters - binding.recycler.post { + binding.fullRecycler?.post { updateToolbarTitleAlpha() } } - binding.recycler.scrollEvents() - .onEach { updateToolbarTitleAlpha() } - .launchIn(viewScope) - binding.swipeRefresh.refreshes() .onEach { fetchMangaInfoFromSource(manualFetch = true) @@ -376,15 +392,19 @@ class MangaController : } private fun updateToolbarTitleAlpha(alpha: Int? = null) { + if (binding.fullRecycler == null) { + return + } + val calculatedAlpha = when { // Specific alpha provided alpha != null -> alpha // First item isn't in view, full opacity - ((binding.recycler.layoutManager as LinearLayoutManager).findFirstVisibleItemPosition() > 0) -> 255 + ((binding.fullRecycler!!.layoutManager as LinearLayoutManager).findFirstVisibleItemPosition() > 0) -> 255 // Based on scroll amount when first item is in view - else -> min(binding.recycler.computeVerticalScrollOffset(), 255) + else -> min(binding.fullRecycler!!.computeVerticalScrollOffset(), 255) } (activity as? MainActivity)?.binding?.toolbar?.setTitleTextColor( @@ -428,7 +448,7 @@ class MangaController : override fun cleanupFab(fab: ExtendedFloatingActionButton) { fab.setOnClickListener(null) - actionFabScrollListener?.let { binding.recycler.removeOnScrollListener(it) } + actionFabScrollListener?.let { binding.fullRecycler?.removeOnScrollListener(it) } actionFab = null } @@ -1497,6 +1517,9 @@ class MangaController : // Tracker sheet - end + private val chaptersRecycler: RecyclerView + get() = binding.fullRecycler ?: binding.chaptersRecycler!! + companion object { const val FROM_SOURCE_EXTRA = "from_source" const val MANGA_EXTRA = "manga" diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/info/MangaInfoHeaderAdapter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/info/MangaInfoHeaderAdapter.kt index 8377f2630..8748d0dd7 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/info/MangaInfoHeaderAdapter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/info/MangaInfoHeaderAdapter.kt @@ -30,7 +30,8 @@ import uy.kohesive.injekt.api.get import uy.kohesive.injekt.injectLazy class MangaInfoHeaderAdapter( - private val controller: MangaController + private val controller: MangaController, + private val isTablet: Boolean ) : RecyclerView.Adapter<MangaInfoHeaderAdapter.HeaderViewHolder>() { @@ -223,10 +224,16 @@ class MangaInfoHeaderAdapter( */ private fun setMangaInfo(manga: Manga, source: Source?) { // Update full title TextView. - binding.mangaFullTitle.text = if (manga.title.isBlank()) { - view.context.getString(R.string.unknown) - } else { - manga.title + with(binding.mangaFullTitle) { + if (isTablet) { + isVisible = false + } else { + text = if (manga.title.isBlank()) { + view.context.getString(R.string.unknown) + } else { + manga.title + } + } } // Update author TextView. diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/info/MangaInfoItemAdapter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/info/MangaInfoItemAdapter.kt index a714cf421..47ba13e11 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/info/MangaInfoItemAdapter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/info/MangaInfoItemAdapter.kt @@ -33,7 +33,8 @@ import reactivecircus.flowbinding.android.view.longClicks class MangaInfoItemAdapter( private val controller: MangaController, - private val fromSource: Boolean + private val fromSource: Boolean, + private val isTablet: Boolean ) : RecyclerView.Adapter<MangaInfoItemAdapter.HeaderViewHolder>() { @@ -191,7 +192,7 @@ class MangaInfoItemAdapter( .launchIn(controller.viewScope) // Expand manga info if navigated from source listing - if (initialLoad && fromSource) { + if (initialLoad && (fromSource || isTablet)) { toggleMangaInfo() initialLoad = false } diff --git a/app/src/main/res/layout-sw600dp/manga_controller.xml b/app/src/main/res/layout-sw600dp/manga_controller.xml new file mode 100644 index 000000000..dd3bd0696 --- /dev/null +++ b/app/src/main/res/layout-sw600dp/manga_controller.xml @@ -0,0 +1,84 @@ +<?xml version="1.0" encoding="utf-8"?> +<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" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="vertical"> + + <eu.kanade.tachiyomi.widget.RevealAnimationView + android:id="@+id/reveal_view" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:background="?attr/colorAccent" + android:elevation="5dp" + android:visibility="invisible" /> + + <eu.kanade.tachiyomi.widget.ThemedSwipeRefreshLayout + android:id="@+id/swipe_refresh" + android:layout_width="match_parent" + android:layout_height="match_parent"> + + <androidx.constraintlayout.widget.ConstraintLayout + android:id="@+id/linear_recycler_layout" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="horizontal"> + + <androidx.recyclerview.widget.RecyclerView + android:id="@+id/info_recycler" + android:layout_width="0dp" + android:layout_height="match_parent" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintEnd_toStartOf="@id/chapters_recycler" + app:layout_constraintWidth_percent="0.4" + tools:itemCount="1" + tools:listitem="@layout/manga_info_header" /> + + <androidx.recyclerview.widget.RecyclerView + android:id="@+id/chapters_recycler" + android:layout_width="0dp" + android:layout_height="match_parent" + android:clipToPadding="false" + android:paddingBottom="@dimen/fab_list_padding" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toEndOf="@id/info_recycler" + tools:listitem="@layout/chapters_item" /> + + <eu.kanade.tachiyomi.widget.MaterialFastScroll + android:id="@+id/fast_scroller" + android:layout_width="wrap_content" + android:layout_height="match_parent" + android:layout_centerHorizontal="true" + android:layout_gravity="end" + app:fastScrollerBubbleEnabled="false" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintEnd_toEndOf="parent" + tools:visibility="visible" /> + + <eu.kanade.tachiyomi.widget.ActionToolbar + android:id="@+id/action_toolbar" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_gravity="bottom" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintStart_toStartOf="@+id/chapters_recycler" + app:layout_constraintEnd_toEndOf="@+id/chapters_recycler" + app:layout_dodgeInsetEdges="bottom" /> + + </androidx.constraintlayout.widget.ConstraintLayout> + + </eu.kanade.tachiyomi.widget.ThemedSwipeRefreshLayout> + + <ImageView + android:id="@+id/expanded_image" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:visibility="invisible" /> + +</androidx.coordinatorlayout.widget.CoordinatorLayout> diff --git a/app/src/main/res/layout/manga_controller.xml b/app/src/main/res/layout/manga_controller.xml index 0338f736d..0b7bead52 100755 --- a/app/src/main/res/layout/manga_controller.xml +++ b/app/src/main/res/layout/manga_controller.xml @@ -18,11 +18,10 @@ android:id="@+id/swipe_refresh" android:layout_width="match_parent" android:layout_height="match_parent" - android:layout_above="@+id/toolbar_bottom" android:orientation="vertical"> <androidx.recyclerview.widget.RecyclerView - android:id="@+id/recycler" + android:id="@+id/full_recycler" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_marginStart="16dp"