Comfortable Grid (#3238)
* Comfortable Grid * Add requested changes * Add more requested changes
This commit is contained in:
+21
-16
@@ -22,6 +22,9 @@ import eu.davidea.flexibleadapter.items.IFlexible
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.database.models.Category
|
||||
import eu.kanade.tachiyomi.data.database.models.Manga
|
||||
import eu.kanade.tachiyomi.data.preference.PreferenceValues.DISPLAY_COMFORTABLE_GRID
|
||||
import eu.kanade.tachiyomi.data.preference.PreferenceValues.DISPLAY_COMPACT_GRID
|
||||
import eu.kanade.tachiyomi.data.preference.PreferenceValues.DISPLAY_LIST
|
||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||
import eu.kanade.tachiyomi.data.preference.asImmediateFlow
|
||||
import eu.kanade.tachiyomi.databinding.SourceControllerBinding
|
||||
@@ -187,7 +190,7 @@ open class BrowseSourceController(bundle: Bundle) :
|
||||
binding.catalogueView.removeView(oldRecycler)
|
||||
}
|
||||
|
||||
val recycler = if (presenter.isListMode) {
|
||||
val recycler = if (preferences.catalogueDisplayMode().get() == DISPLAY_LIST) {
|
||||
RecyclerView(view.context).apply {
|
||||
id = R.id.recycler
|
||||
layoutManager = LinearLayoutManager(context)
|
||||
@@ -205,7 +208,7 @@ open class BrowseSourceController(bundle: Bundle) :
|
||||
(layoutManager as GridLayoutManager).spanSizeLookup = object : GridLayoutManager.SpanSizeLookup() {
|
||||
override fun getSpanSize(position: Int): Int {
|
||||
return when (adapter?.getItemViewType(position)) {
|
||||
R.layout.source_grid_item, null -> 1
|
||||
R.layout.source_grid_item, R.layout.source_comfortable_grid_item, null -> 1
|
||||
else -> spanCount
|
||||
}
|
||||
}
|
||||
@@ -266,15 +269,13 @@ open class BrowseSourceController(bundle: Bundle) :
|
||||
}
|
||||
)
|
||||
|
||||
// Show next display mode
|
||||
menu.findItem(R.id.action_display_mode).apply {
|
||||
val icon = if (presenter.isListMode) {
|
||||
R.drawable.ic_view_module_24dp
|
||||
} else {
|
||||
R.drawable.ic_view_list_24dp
|
||||
}
|
||||
setIcon(icon)
|
||||
val displayItem = when (preferences.catalogueDisplayMode().get()) {
|
||||
DISPLAY_COMPACT_GRID -> R.id.action_compact_grid
|
||||
DISPLAY_LIST -> R.id.action_list
|
||||
DISPLAY_COMFORTABLE_GRID -> R.id.action_comfortable_grid
|
||||
else -> throw NotImplementedError("Unimplemented display")
|
||||
}
|
||||
menu.findItem(displayItem).isChecked = true
|
||||
}
|
||||
|
||||
override fun onPrepareOptionsMenu(menu: Menu) {
|
||||
@@ -290,7 +291,9 @@ open class BrowseSourceController(bundle: Bundle) :
|
||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||
when (item.itemId) {
|
||||
R.id.action_search -> expandActionViewFromInteraction = true
|
||||
R.id.action_display_mode -> swapDisplayMode()
|
||||
R.id.action_compact_grid -> setDisplayMode(DISPLAY_COMPACT_GRID)
|
||||
R.id.action_list -> setDisplayMode(DISPLAY_LIST)
|
||||
R.id.action_comfortable_grid -> setDisplayMode(DISPLAY_COMFORTABLE_GRID)
|
||||
R.id.action_open_in_web_view -> openInWebView()
|
||||
R.id.action_local_source_help -> openLocalSourceHelpGuide()
|
||||
}
|
||||
@@ -433,17 +436,19 @@ open class BrowseSourceController(bundle: Bundle) :
|
||||
}
|
||||
|
||||
/**
|
||||
* Swaps the current display mode.
|
||||
* Sets the current display mode.
|
||||
*
|
||||
* @param mode the mode to change to
|
||||
*/
|
||||
private fun swapDisplayMode() {
|
||||
private fun setDisplayMode(mode: Int) {
|
||||
val view = view ?: return
|
||||
val adapter = adapter ?: return
|
||||
|
||||
presenter.swapDisplayMode()
|
||||
val isListMode = presenter.isListMode
|
||||
preferences.catalogueDisplayMode().set(mode)
|
||||
presenter.refreshDisplayMode()
|
||||
activity?.invalidateOptionsMenu()
|
||||
setupRecycler(view)
|
||||
if (!isListMode || !view.context.connectivityManager.isActiveNetworkMetered) {
|
||||
if (mode == DISPLAY_LIST || !view.context.connectivityManager.isActiveNetworkMetered) {
|
||||
// Initialize mangas if going to grid view or if over wifi when going to list view
|
||||
val mangas = (0 until adapter.itemCount).mapNotNull {
|
||||
(adapter.getItem(it) as? SourceItem)?.manga
|
||||
|
||||
+4
-14
@@ -87,12 +87,6 @@ open class BrowseSourcePresenter(
|
||||
*/
|
||||
private val mangaDetailSubject = PublishSubject.create<List<Manga>>()
|
||||
|
||||
/**
|
||||
* Whether the view is in list mode or not.
|
||||
*/
|
||||
var isListMode: Boolean = false
|
||||
private set
|
||||
|
||||
/**
|
||||
* Subscription for the pager.
|
||||
*/
|
||||
@@ -119,7 +113,6 @@ open class BrowseSourcePresenter(
|
||||
query = savedState.getString(::query.name, "")
|
||||
}
|
||||
|
||||
isListMode = prefs.catalogueAsList().get()
|
||||
restartPager()
|
||||
}
|
||||
|
||||
@@ -145,7 +138,7 @@ open class BrowseSourcePresenter(
|
||||
|
||||
val sourceId = source.id
|
||||
|
||||
val catalogueAsList = prefs.catalogueAsList()
|
||||
val catalogueDisplayMode = prefs.catalogueDisplayMode()
|
||||
|
||||
// Prepare the pager.
|
||||
pagerSubscription?.let { remove(it) }
|
||||
@@ -153,7 +146,7 @@ open class BrowseSourcePresenter(
|
||||
.observeOn(Schedulers.io())
|
||||
.map { pair -> pair.first to pair.second.map { networkToLocalManga(it, sourceId) } }
|
||||
.doOnNext { initializeMangas(it.second) }
|
||||
.map { pair -> pair.first to pair.second.map { SourceItem(it, catalogueAsList) } }
|
||||
.map { pair -> pair.first to pair.second.map { SourceItem(it, catalogueDisplayMode) } }
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribeReplay(
|
||||
{ view, (page, mangas) ->
|
||||
@@ -273,12 +266,9 @@ open class BrowseSourcePresenter(
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the active display mode.
|
||||
* Refreshes the active display mode.
|
||||
*/
|
||||
fun swapDisplayMode() {
|
||||
val mode = !isListMode
|
||||
prefs.catalogueAsList().set(mode)
|
||||
isListMode = mode
|
||||
fun refreshDisplayMode() {
|
||||
subscribeToMangaInitializer()
|
||||
}
|
||||
|
||||
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
package eu.kanade.tachiyomi.ui.browse.source.browse
|
||||
|
||||
import android.view.View
|
||||
import com.bumptech.glide.load.engine.DiskCacheStrategy
|
||||
import eu.davidea.flexibleadapter.FlexibleAdapter
|
||||
import eu.kanade.tachiyomi.data.database.models.Manga
|
||||
import eu.kanade.tachiyomi.data.glide.GlideApp
|
||||
import eu.kanade.tachiyomi.data.glide.toMangaThumbnail
|
||||
import eu.kanade.tachiyomi.widget.StateImageViewTarget
|
||||
import kotlinx.android.synthetic.main.source_comfortable_grid_item.card
|
||||
import kotlinx.android.synthetic.main.source_comfortable_grid_item.progress
|
||||
import kotlinx.android.synthetic.main.source_comfortable_grid_item.thumbnail
|
||||
import kotlinx.android.synthetic.main.source_comfortable_grid_item.title
|
||||
|
||||
/**
|
||||
* Class used to hold the displayed data of a manga in the catalogue, like the cover or the title.
|
||||
* All the elements from the layout file "item_source_grid" are available in this class.
|
||||
*
|
||||
* @param view the inflated view for this holder.
|
||||
* @param adapter the adapter handling this holder.
|
||||
* @constructor creates a new catalogue holder.
|
||||
*/
|
||||
class SourceComfortableGridHolder(private val view: View, private val adapter: FlexibleAdapter<*>) :
|
||||
SourceGridHolder(view, adapter) {
|
||||
|
||||
/**
|
||||
* Method called from [CatalogueAdapter.onBindViewHolder]. It updates the data for this
|
||||
* holder with the given manga.
|
||||
*
|
||||
* @param manga the manga to bind.
|
||||
*/
|
||||
override fun onSetValues(manga: Manga) {
|
||||
// Set manga title
|
||||
title.text = manga.title
|
||||
|
||||
// Set alpha of thumbnail.
|
||||
thumbnail.alpha = if (manga.favorite) 0.3f else 1.0f
|
||||
|
||||
setImage(manga)
|
||||
}
|
||||
|
||||
override fun setImage(manga: Manga) {
|
||||
// Setting this via XML doesn't work
|
||||
card.clipToOutline = true
|
||||
|
||||
GlideApp.with(view.context).clear(thumbnail)
|
||||
if (!manga.thumbnail_url.isNullOrEmpty()) {
|
||||
GlideApp.with(view.context)
|
||||
.load(manga.toMangaThumbnail())
|
||||
.diskCacheStrategy(DiskCacheStrategy.DATA)
|
||||
.centerCrop()
|
||||
.placeholder(android.R.color.transparent)
|
||||
.into(StateImageViewTarget(thumbnail, progress))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -20,7 +20,7 @@ import kotlinx.android.synthetic.main.source_grid_item.title
|
||||
* @param adapter the adapter handling this holder.
|
||||
* @constructor creates a new catalogue holder.
|
||||
*/
|
||||
class SourceGridHolder(private val view: View, private val adapter: FlexibleAdapter<*>) :
|
||||
open class SourceGridHolder(private val view: View, private val adapter: FlexibleAdapter<*>) :
|
||||
SourceHolder(view, adapter) {
|
||||
|
||||
/**
|
||||
|
||||
@@ -4,6 +4,7 @@ import android.view.Gravity
|
||||
import android.view.View
|
||||
import android.view.ViewGroup.LayoutParams.MATCH_PARENT
|
||||
import android.widget.FrameLayout
|
||||
import androidx.constraintlayout.widget.ConstraintLayout
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.tfcporciuncula.flow.Preference
|
||||
import eu.davidea.flexibleadapter.FlexibleAdapter
|
||||
@@ -11,18 +12,20 @@ import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
|
||||
import eu.davidea.flexibleadapter.items.IFlexible
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.database.models.Manga
|
||||
import eu.kanade.tachiyomi.data.preference.PreferenceValues.DISPLAY_COMPACT_GRID
|
||||
import eu.kanade.tachiyomi.data.preference.PreferenceValues.DISPLAY_LIST
|
||||
import eu.kanade.tachiyomi.widget.AutofitRecyclerView
|
||||
import kotlinx.android.synthetic.main.source_grid_item.view.card
|
||||
import kotlinx.android.synthetic.main.source_grid_item.view.gradient
|
||||
|
||||
class SourceItem(val manga: Manga, private val catalogueAsList: Preference<Boolean>) :
|
||||
class SourceItem(val manga: Manga, private val catalogueDisplayMode: Preference<Int>) :
|
||||
AbstractFlexibleItem<SourceHolder>() {
|
||||
|
||||
override fun getLayoutRes(): Int {
|
||||
return if (catalogueAsList.get()) {
|
||||
R.layout.source_list_item
|
||||
} else {
|
||||
R.layout.source_grid_item
|
||||
return when (catalogueDisplayMode.get()) {
|
||||
DISPLAY_COMPACT_GRID -> R.layout.source_grid_item
|
||||
DISPLAY_LIST -> R.layout.source_list_item
|
||||
else -> R.layout.source_comfortable_grid_item
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,15 +35,28 @@ class SourceItem(val manga: Manga, private val catalogueAsList: Preference<Boole
|
||||
): SourceHolder {
|
||||
val parent = adapter.recyclerView
|
||||
return if (parent is AutofitRecyclerView) {
|
||||
view.apply {
|
||||
card.layoutParams = FrameLayout.LayoutParams(
|
||||
MATCH_PARENT, parent.itemWidth / 3 * 4
|
||||
)
|
||||
gradient.layoutParams = FrameLayout.LayoutParams(
|
||||
MATCH_PARENT, parent.itemWidth / 3 * 4 / 2, Gravity.BOTTOM
|
||||
)
|
||||
val coverHeight = parent.itemWidth / 3 * 4
|
||||
if (catalogueDisplayMode.get() == DISPLAY_COMPACT_GRID) {
|
||||
view.apply {
|
||||
card.layoutParams = FrameLayout.LayoutParams(
|
||||
MATCH_PARENT, coverHeight
|
||||
)
|
||||
gradient.layoutParams = FrameLayout.LayoutParams(
|
||||
MATCH_PARENT, coverHeight / 2, Gravity.BOTTOM
|
||||
)
|
||||
}
|
||||
SourceGridHolder(view, adapter)
|
||||
} else {
|
||||
view.apply {
|
||||
card.layoutParams = ConstraintLayout.LayoutParams(
|
||||
MATCH_PARENT, coverHeight
|
||||
)
|
||||
gradient.layoutParams = FrameLayout.LayoutParams(
|
||||
MATCH_PARENT, coverHeight / 2, Gravity.BOTTOM
|
||||
)
|
||||
}
|
||||
SourceComfortableGridHolder(view, adapter)
|
||||
}
|
||||
SourceGridHolder(view, adapter)
|
||||
} else {
|
||||
SourceListHolder(view, adapter)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user