Attempting making library as one big list
This commit is contained in:
parent
fc0ab3e878
commit
83441a5ebd
@ -113,6 +113,8 @@ object PreferenceKeys {
|
||||
|
||||
const val libraryLayout = "pref_display_library_layout"
|
||||
|
||||
const val libraryUsingPager = "library_using_pager"
|
||||
|
||||
const val lang = "app_language"
|
||||
|
||||
const val dateFormat = "app_date_format"
|
||||
|
@ -11,9 +11,9 @@ import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.track.TrackService
|
||||
import eu.kanade.tachiyomi.source.Source
|
||||
import java.io.File
|
||||
import java.util.Locale
|
||||
import java.text.DateFormat
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Locale
|
||||
import eu.kanade.tachiyomi.data.preference.PreferenceKeys as Keys
|
||||
|
||||
fun <T> Preference<T>.getOrDefault(): T = get() ?: defaultValue()!!
|
||||
@ -173,6 +173,8 @@ class PreferencesHelper(val context: Context) {
|
||||
|
||||
fun libraryLayout() = rxPrefs.getInteger(Keys.libraryLayout, 1)
|
||||
|
||||
fun libraryUsingPager() = rxPrefs.getBoolean(Keys.libraryUsingPager, false)
|
||||
|
||||
fun downloadBadge() = rxPrefs.getBoolean(Keys.downloadBadge, false)
|
||||
|
||||
fun filterDownloaded() = rxPrefs.getInteger(Keys.filterDownloaded, 0)
|
||||
|
@ -6,11 +6,10 @@ import eu.kanade.tachiyomi.data.database.DatabaseHelper
|
||||
import eu.kanade.tachiyomi.data.database.models.Manga
|
||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||
import eu.kanade.tachiyomi.data.preference.getOrDefault
|
||||
import eu.kanade.tachiyomi.ui.category.CategoryAdapter
|
||||
import eu.kanade.tachiyomi.util.lang.chop
|
||||
import eu.kanade.tachiyomi.util.lang.removeArticles
|
||||
import eu.kanade.tachiyomi.util.system.launchUI
|
||||
import kotlinx.coroutines.delay
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
import uy.kohesive.injekt.injectLazy
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Calendar
|
||||
@ -22,19 +21,18 @@ import java.util.Locale
|
||||
*
|
||||
* @param view the fragment containing this adapter.
|
||||
*/
|
||||
class LibraryCategoryAdapter(val view: LibraryCategoryView) :
|
||||
FlexibleAdapter<LibraryItem>(null, view, true) {
|
||||
class LibraryCategoryAdapter(val libraryListener: LibraryListener) :
|
||||
FlexibleAdapter<IFlexible<*>>(null, libraryListener, true) {
|
||||
|
||||
init {
|
||||
setDisplayHeadersAtStartUp(!Injekt.get<PreferencesHelper>().libraryUsingPager()
|
||||
.getOrDefault())
|
||||
}
|
||||
/**
|
||||
* The list of manga in this category.
|
||||
*/
|
||||
private var mangas: List<LibraryItem> = emptyList()
|
||||
|
||||
/**
|
||||
* Listener called when an item of the list press start reading.
|
||||
*/
|
||||
val libraryListener: LibraryListener = view
|
||||
|
||||
/**
|
||||
* Sets a list of manga in the adapter.
|
||||
*
|
||||
@ -47,13 +45,26 @@ class LibraryCategoryAdapter(val view: LibraryCategoryView) :
|
||||
performFilter()
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the position in the adapter for the given manga.
|
||||
*
|
||||
* @param manga the manga to find.
|
||||
*/
|
||||
fun indexOf(categoryOrder: Int): Int {
|
||||
return currentItems.indexOfFirst {
|
||||
if (it is LibraryHeaderItem) it.category.order == categoryOrder
|
||||
else false }
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the position in the adapter for the given manga.
|
||||
*
|
||||
* @param manga the manga to find.
|
||||
*/
|
||||
fun indexOf(manga: Manga): Int {
|
||||
return currentItems.indexOfFirst { it.manga.id == manga.id }
|
||||
return currentItems.indexOfFirst {
|
||||
if (it is LibraryItem) it.manga.id == manga.id
|
||||
else false }
|
||||
}
|
||||
|
||||
fun performFilter() {
|
||||
@ -64,7 +75,7 @@ class LibraryCategoryAdapter(val view: LibraryCategoryView) :
|
||||
else {
|
||||
updateDataSet(mangas.filter { it.filter(s) })
|
||||
}
|
||||
isLongPressDragEnabled = view.canDrag() && s.isNullOrBlank()
|
||||
isLongPressDragEnabled = libraryListener.canDrag() && s.isNullOrBlank()
|
||||
}
|
||||
|
||||
override fun onCreateBubbleText(position: Int):String {
|
||||
@ -74,6 +85,13 @@ class LibraryCategoryAdapter(val view: LibraryCategoryView) :
|
||||
"Bottom"
|
||||
} else { // Get and show the first character
|
||||
val iFlexible: IFlexible<*>? = getItem(position)
|
||||
return if (iFlexible is LibraryHeaderItem) {
|
||||
iFlexible.category.name
|
||||
} else {
|
||||
val db:DatabaseHelper by injectLazy()
|
||||
val category = db.getCategoriesForManga((iFlexible as LibraryItem).manga).executeAsBlocking().firstOrNull()?.name
|
||||
category?.chop(10) ?: "Default"
|
||||
}
|
||||
val preferences:PreferencesHelper by injectLazy()
|
||||
when (preferences.librarySortingMode().getOrDefault()) {
|
||||
LibrarySort.DRAG_AND_DROP -> {
|
||||
@ -145,5 +163,6 @@ class LibraryCategoryAdapter(val view: LibraryCategoryView) :
|
||||
*/
|
||||
fun startReading(position: Int)
|
||||
fun onItemReleased(position: Int)
|
||||
fun canDrag(): Boolean
|
||||
}
|
||||
}
|
||||
|
@ -79,6 +79,7 @@ class LibraryCategoryView @JvmOverloads constructor(context: Context, attrs: Att
|
||||
fun onCreate(controller: LibraryController) {
|
||||
this.controller = controller
|
||||
|
||||
adapter = LibraryCategoryAdapter(this)
|
||||
recycler = if (preferences.libraryLayout().getOrDefault() == 0) {
|
||||
(swipe_refresh.inflate(R.layout.library_list_recycler) as RecyclerView).apply {
|
||||
layoutManager = LinearLayoutManager(context)
|
||||
@ -89,7 +90,6 @@ class LibraryCategoryView @JvmOverloads constructor(context: Context, attrs: Att
|
||||
}
|
||||
}
|
||||
|
||||
adapter = LibraryCategoryAdapter(this)
|
||||
|
||||
recycler.setHasFixedSize(true)
|
||||
recycler.adapter = adapter
|
||||
@ -155,7 +155,7 @@ class LibraryCategoryView @JvmOverloads constructor(context: Context, attrs: Att
|
||||
.subscribe {
|
||||
if (it == category.id) {
|
||||
adapter.currentItems.forEach { item ->
|
||||
controller.setSelection(item.manga, true)
|
||||
controller.setSelection((item as LibraryItem).manga, true)
|
||||
}
|
||||
controller.invalidateActionMode()
|
||||
}
|
||||
@ -167,11 +167,12 @@ class LibraryCategoryView @JvmOverloads constructor(context: Context, attrs: Att
|
||||
if (it.second in -2..-1) {
|
||||
val items = adapter.currentItems.toMutableList()
|
||||
val mangas = controller.selectedMangas
|
||||
val selectedManga = items.filter { item -> item.manga in mangas }
|
||||
val selectedManga = items.filter { item -> (item as LibraryItem).manga in
|
||||
mangas }
|
||||
items.removeAll(selectedManga)
|
||||
if (it.second == -1) items.addAll(0, selectedManga)
|
||||
else items.addAll(selectedManga)
|
||||
adapter.setItems(items)
|
||||
adapter.setItems(items.filterIsInstance<LibraryItem>())
|
||||
adapter.notifyDataSetChanged()
|
||||
saveDragSort()
|
||||
}
|
||||
@ -179,7 +180,7 @@ class LibraryCategoryView @JvmOverloads constructor(context: Context, attrs: Att
|
||||
}
|
||||
}
|
||||
|
||||
fun canDrag(): Boolean {
|
||||
override fun canDrag(): Boolean {
|
||||
val sortingMode = preferences.librarySortingMode().getOrDefault()
|
||||
val filterOff = preferences.filterCompleted().getOrDefault() +
|
||||
preferences.filterTracked().getOrDefault() +
|
||||
@ -212,6 +213,7 @@ class LibraryCategoryView @JvmOverloads constructor(context: Context, attrs: Att
|
||||
val mangaForCategory = event.getMangaForCategory(category).orEmpty()
|
||||
|
||||
adapter.setItems(mangaForCategory)
|
||||
adapter.hideAllHeaders()
|
||||
|
||||
swipe_refresh.isEnabled = !preferences.hideCategories().getOrDefault()
|
||||
|
||||
@ -283,7 +285,7 @@ class LibraryCategoryView @JvmOverloads constructor(context: Context, attrs: Att
|
||||
*/
|
||||
override fun onItemClick(view: View?, position: Int): Boolean {
|
||||
// If the action mode is created and the position is valid, toggle the selection.
|
||||
val item = adapter.getItem(position) ?: return false
|
||||
val item = adapter.getItem(position) as? LibraryItem ?: return false
|
||||
return if (adapter.mode == SelectableAdapter.Mode.MULTI) {
|
||||
lastClickPosition = position
|
||||
toggleSelection(position)
|
||||
@ -328,13 +330,13 @@ class LibraryCategoryView @JvmOverloads constructor(context: Context, attrs: Att
|
||||
}
|
||||
|
||||
override fun startReading(position: Int) {
|
||||
val manga = adapter.getItem(position)?.manga ?: return
|
||||
val manga = (adapter.getItem(position) as? LibraryItem)?.manga ?: return
|
||||
if (adapter.mode == SelectableAdapter.Mode.MULTI) toggleSelection(position)
|
||||
else controller.startReading(manga)
|
||||
}
|
||||
|
||||
private fun saveDragSort() {
|
||||
val mangaIds = adapter.currentItems.mapNotNull { it.manga.id }
|
||||
val mangaIds = adapter.currentItems.mapNotNull { (it as? LibraryItem)?.manga?.id }
|
||||
category.mangaSort = null
|
||||
category.mangaOrder = mangaIds
|
||||
if (category.id == 0)
|
||||
@ -373,7 +375,7 @@ class LibraryCategoryView @JvmOverloads constructor(context: Context, attrs: Att
|
||||
private fun toggleSelection(position: Int) {
|
||||
val item = adapter.getItem(position) ?: return
|
||||
|
||||
controller.setSelection(item.manga, !adapter.isSelected(position))
|
||||
controller.setSelection((item as LibraryItem).manga, !adapter.isSelected(position))
|
||||
controller.invalidateActionMode()
|
||||
}
|
||||
|
||||
@ -386,7 +388,7 @@ class LibraryCategoryView @JvmOverloads constructor(context: Context, attrs: Att
|
||||
private fun setSelection(position: Int) {
|
||||
val item = adapter.getItem(position) ?: return
|
||||
|
||||
controller.setSelection(item.manga, true)
|
||||
controller.setSelection((item as LibraryItem).manga, true)
|
||||
controller.invalidateActionMode()
|
||||
}
|
||||
|
||||
|
@ -2,7 +2,6 @@ package eu.kanade.tachiyomi.ui.library
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.res.Configuration
|
||||
import android.graphics.Color
|
||||
import android.os.Bundle
|
||||
@ -14,10 +13,18 @@ import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.WindowInsets
|
||||
import android.view.inputmethod.InputMethodManager
|
||||
import android.widget.ArrayAdapter
|
||||
import android.widget.Spinner
|
||||
import android.widget.TextView
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.appcompat.view.ActionMode
|
||||
import androidx.appcompat.widget.AppCompatSpinner
|
||||
import androidx.appcompat.widget.SearchView
|
||||
import androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||
import androidx.core.graphics.drawable.DrawableCompat
|
||||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import androidx.viewpager.widget.ViewPager
|
||||
import com.afollestad.materialdialogs.MaterialDialog
|
||||
import com.bluelinelabs.conductor.ControllerChangeHandler
|
||||
@ -26,9 +33,10 @@ import com.f2prateek.rx.preferences.Preference
|
||||
import com.google.android.material.bottomsheet.BottomSheetBehavior
|
||||
import com.google.android.material.snackbar.BaseTransientBottomBar
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import com.google.android.material.tabs.TabLayout
|
||||
import com.jakewharton.rxrelay.BehaviorRelay
|
||||
import com.jakewharton.rxrelay.PublishRelay
|
||||
import eu.davidea.flexibleadapter.FlexibleAdapter
|
||||
import eu.davidea.flexibleadapter.SelectableAdapter
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.database.models.Category
|
||||
import eu.kanade.tachiyomi.data.database.models.LibraryManga
|
||||
@ -40,7 +48,6 @@ import eu.kanade.tachiyomi.data.library.LibraryUpdateService
|
||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||
import eu.kanade.tachiyomi.data.preference.getOrDefault
|
||||
import eu.kanade.tachiyomi.ui.base.controller.BaseController
|
||||
import eu.kanade.tachiyomi.ui.base.controller.TabbedController
|
||||
import eu.kanade.tachiyomi.ui.base.controller.withFadeTransaction
|
||||
import eu.kanade.tachiyomi.ui.category.CategoryController
|
||||
import eu.kanade.tachiyomi.ui.download.DownloadController
|
||||
@ -53,14 +60,20 @@ import eu.kanade.tachiyomi.ui.migration.manga.design.PreMigrationController
|
||||
import eu.kanade.tachiyomi.ui.migration.manga.process.MigrationListController
|
||||
import eu.kanade.tachiyomi.ui.migration.manga.process.MigrationProcedureConfig
|
||||
import eu.kanade.tachiyomi.ui.reader.ReaderActivity
|
||||
import eu.kanade.tachiyomi.util.system.dpToPx
|
||||
import eu.kanade.tachiyomi.util.system.getResourceColor
|
||||
import eu.kanade.tachiyomi.util.system.launchUI
|
||||
import eu.kanade.tachiyomi.util.view.gone
|
||||
import eu.kanade.tachiyomi.util.view.inflate
|
||||
import eu.kanade.tachiyomi.util.view.setOnQueryTextChangeListener
|
||||
import eu.kanade.tachiyomi.util.view.snack
|
||||
import eu.kanade.tachiyomi.util.view.updateLayoutParams
|
||||
import eu.kanade.tachiyomi.util.view.updatePaddingRelative
|
||||
import eu.kanade.tachiyomi.util.view.visible
|
||||
import eu.kanade.tachiyomi.widget.AutofitRecyclerView
|
||||
import eu.kanade.tachiyomi.widget.IgnoreFirstSpinnerListener
|
||||
import kotlinx.android.synthetic.main.filter_bottom_sheet.*
|
||||
import kotlinx.android.synthetic.main.library_controller.*
|
||||
import kotlinx.android.synthetic.main.main_activity.*
|
||||
import rx.Subscription
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
|
||||
@ -68,12 +81,16 @@ class LibraryController(
|
||||
bundle: Bundle? = null,
|
||||
private val preferences: PreferencesHelper = Injekt.get()
|
||||
) : BaseController(bundle),
|
||||
TabbedController,
|
||||
//TabbedController,
|
||||
ActionMode.Callback,
|
||||
ChangeMangaCategoriesDialog.Listener,
|
||||
MigrationInterface,
|
||||
DownloadServiceListener,
|
||||
LibraryServiceListener {
|
||||
LibraryServiceListener,
|
||||
FlexibleAdapter.OnItemClickListener,
|
||||
FlexibleAdapter.OnItemLongClickListener,
|
||||
FlexibleAdapter.OnItemMoveListener,
|
||||
LibraryCategoryAdapter.LibraryListener{
|
||||
|
||||
/**
|
||||
* Position of the active category.
|
||||
@ -135,14 +152,19 @@ class LibraryController(
|
||||
/**
|
||||
* Adapter of the view pager.
|
||||
*/
|
||||
private var adapter: LibraryAdapter? = null
|
||||
private var pagerAdapter: LibraryAdapter? = null
|
||||
private lateinit var adapter: LibraryCategoryAdapter
|
||||
|
||||
private lateinit var spinner: Spinner
|
||||
|
||||
private var lastClickPosition = -1
|
||||
|
||||
/**
|
||||
* Drawer listener to allow swipe only for closing the drawer.
|
||||
*/
|
||||
private var tabsVisibilityRelay: BehaviorRelay<Boolean> = BehaviorRelay.create(false)
|
||||
// private var tabsVisibilityRelay: BehaviorRelay<Boolean> = BehaviorRelay.create(false)
|
||||
|
||||
private var tabsVisibilitySubscription: Subscription? = null
|
||||
// private var tabsVisibilitySubscription: Subscription? = null
|
||||
|
||||
private var observeLater:Boolean = false
|
||||
|
||||
@ -153,47 +175,131 @@ class LibraryController(
|
||||
|
||||
private var justStarted = true
|
||||
|
||||
private var updateScroll = true
|
||||
|
||||
private var spinnerAdapter: SpinnerAdapter? = null
|
||||
|
||||
var scrollLister = object : RecyclerView.OnScrollListener () {
|
||||
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
|
||||
super.onScrolled(recyclerView, dx, dy)
|
||||
val position =
|
||||
(recycler.layoutManager as LinearLayoutManager).findFirstVisibleItemPosition()
|
||||
val order = when (val item = adapter.getItem(position)) {
|
||||
is LibraryHeaderItem -> item.category.order
|
||||
is LibraryItem -> presenter.categories.find { it.id == item.manga.category }?.order
|
||||
else -> null
|
||||
}
|
||||
if (order != null && order != activeCategory) {
|
||||
preferences.lastUsedCategory().set(order)
|
||||
activeCategory = order
|
||||
val category = presenter.categories.find { it.order == order }
|
||||
|
||||
bottom_sheet.lastCategory = category
|
||||
if (preferences.librarySortingMode().getOrDefault() == LibrarySort.DRAG_AND_DROP)
|
||||
bottom_sheet.updateTitle()
|
||||
// spinner.onItemSelectedListener = null
|
||||
spinnerAdapter?.setCustomText(category?.name)
|
||||
//spinner.view
|
||||
//spinner.post { spinner.onItemSelectedListener = listener }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Recycler view of the list of manga.
|
||||
*/
|
||||
private lateinit var recycler: RecyclerView
|
||||
|
||||
var usePager = preferences.libraryUsingPager().getOrDefault()
|
||||
|
||||
init {
|
||||
setHasOptionsMenu(true)
|
||||
retainViewMode = RetainViewMode.RETAIN_DETACH
|
||||
}
|
||||
|
||||
override fun getTitle(): String? {
|
||||
return resources?.getString(R.string.label_library)
|
||||
return null//if (title != null) null else resources?.getString(R.string.label_library)
|
||||
}
|
||||
|
||||
private var title: String? = null
|
||||
set(value) {
|
||||
field = value
|
||||
setTitle()
|
||||
}
|
||||
|
||||
override fun inflateView(inflater: LayoutInflater, container: ViewGroup): View {
|
||||
return inflater.inflate(R.layout.library_controller, container, false)
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View) {
|
||||
super.onViewCreated(view)
|
||||
|
||||
adapter = LibraryAdapter(this)
|
||||
library_pager.adapter = adapter
|
||||
|
||||
library_pager.addOnPageChangeListener(object : ViewPager.OnPageChangeListener {
|
||||
override fun onPageSelected(position: Int) {
|
||||
preferences.lastUsedCategory().set(position)
|
||||
activeCategory = position
|
||||
bottom_sheet.lastCategory = adapter?.categories?.getOrNull(position)
|
||||
if (preferences.librarySortingMode().getOrDefault() == LibrarySort.DRAG_AND_DROP) bottom_sheet.updateTitle()
|
||||
}
|
||||
|
||||
override fun onPageScrolled(
|
||||
position: Int, positionOffset: Float, positionOffsetPixels: Int
|
||||
) {
|
||||
}
|
||||
|
||||
override fun onPageScrollStateChanged(state: Int) {}
|
||||
})
|
||||
|
||||
mangaPerRow = getColumnsPreferenceForCurrentOrientation().getOrDefault()
|
||||
|
||||
if (usePager) {
|
||||
pager_layout.visible()
|
||||
fast_scroller.gone()
|
||||
pagerAdapter = LibraryAdapter(this)
|
||||
library_pager.adapter = pagerAdapter
|
||||
library_pager.addOnPageChangeListener(object : ViewPager.OnPageChangeListener {
|
||||
override fun onPageSelected(position: Int) {
|
||||
preferences.lastUsedCategory().set(position)
|
||||
activeCategory = position
|
||||
bottom_sheet.lastCategory = pagerAdapter?.categories?.getOrNull(position)
|
||||
if (preferences.librarySortingMode().getOrDefault() == LibrarySort.DRAG_AND_DROP) bottom_sheet.updateTitle()
|
||||
}
|
||||
|
||||
override fun onPageScrolled(
|
||||
position: Int, positionOffset: Float, positionOffsetPixels: Int
|
||||
) {
|
||||
}
|
||||
|
||||
override fun onPageScrollStateChanged(state: Int) {}
|
||||
})
|
||||
}
|
||||
else {
|
||||
adapter = LibraryCategoryAdapter(this)
|
||||
recycler = if (preferences.libraryLayout().getOrDefault() == 0) {
|
||||
(swipe_refresh.inflate(R.layout.library_list_recycler) as RecyclerView).apply {
|
||||
layoutManager = LinearLayoutManager(context)
|
||||
}
|
||||
} else {
|
||||
(swipe_refresh.inflate(R.layout.library_grid_recycler) as AutofitRecyclerView).apply {
|
||||
spanCount = mangaPerRow
|
||||
manager.spanSizeLookup = (object : GridLayoutManager.SpanSizeLookup() {
|
||||
override fun getSpanSize(position: Int): Int {
|
||||
val item = this@LibraryController.adapter.getItem(position)
|
||||
return if (item is LibraryHeaderItem)
|
||||
manager.spanCount else 1
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
recycler.setHasFixedSize(true)
|
||||
recycler.adapter = adapter
|
||||
//adapter.setStickyHeaders(true)
|
||||
recycler_layout.addView(recycler)
|
||||
adapter.fastScroller = fast_scroller
|
||||
recycler.addOnScrollListener(scrollLister)
|
||||
|
||||
spinner = swipe_refresh.inflate(R.layout.library_spinner) as AppCompatSpinner
|
||||
(activity as MainActivity).supportActionBar?.setDisplayShowCustomEnabled(true)
|
||||
(activity as MainActivity).supportActionBar?.customView = spinner
|
||||
spinnerAdapter = SpinnerAdapter(view.context, R.layout.library_spinner_textview,
|
||||
arrayOf(resources!!.getString(R.string.label_library)))
|
||||
spinner.adapter = spinnerAdapter
|
||||
|
||||
spinnerAdapter?.setCustomText(resources?.getString(R.string.label_library))
|
||||
}
|
||||
|
||||
|
||||
if (selectedMangas.isNotEmpty()) {
|
||||
createActionModeIfNeeded()
|
||||
}
|
||||
|
||||
bottom_sheet.onCreate(pager_layout)
|
||||
|
||||
//bottom_sheet.onCreate(pager_layout)
|
||||
bottom_sheet.onCreate(if (usePager) pager_layout else swipe_refresh)
|
||||
|
||||
bottom_sheet.onGroupClicked = {
|
||||
when (it) {
|
||||
@ -211,6 +317,28 @@ class LibraryController(
|
||||
router.pushController(DownloadController().withFadeTransaction())
|
||||
}
|
||||
|
||||
|
||||
// spinner.onItemSelectedListener = listener
|
||||
/*spinner.onItemSelectedListener = IgnoreFirstSpinnerListener { position ->
|
||||
if (!updateScroll) return@IgnoreFirstSpinnerListener
|
||||
val headerPosition = adapter.indexOf(position) + 1
|
||||
if (headerPosition > -1) (recycler.layoutManager as LinearLayoutManager)
|
||||
.scrollToPositionWithOffset(position, 0)
|
||||
}*/
|
||||
|
||||
val config = resources?.configuration
|
||||
val phoneLandscape = (config?.orientation == Configuration.ORIENTATION_LANDSCAPE &&
|
||||
(config.screenLayout.and(Configuration.SCREENLAYOUT_SIZE_MASK)) <
|
||||
Configuration.SCREENLAYOUT_SIZE_LARGE)
|
||||
// pad the recycler if the filter bottom sheet is visible
|
||||
if (!usePager && !phoneLandscape) {
|
||||
val height = view.context.resources.getDimensionPixelSize(R.dimen.rounder_radius) + 5.dpToPx
|
||||
recycler.updatePaddingRelative(bottom = height)
|
||||
fast_scroller.updateLayoutParams<CoordinatorLayout.LayoutParams> {
|
||||
bottomMargin = height
|
||||
}
|
||||
}
|
||||
|
||||
if (presenter.isDownloading()) {
|
||||
fab.scaleY = 1f
|
||||
fab.scaleX = 1f
|
||||
@ -219,9 +347,10 @@ class LibraryController(
|
||||
}
|
||||
presenter.onRestore()
|
||||
val library = presenter.getAllManga()
|
||||
if (library != null) onNextLibraryUpdate(presenter.categories, library)
|
||||
if (library != null) presenter.updateViewBlocking() //onNextLibraryUpdate(presenter.categories, library)
|
||||
else {
|
||||
library_pager.alpha = 0f
|
||||
swipe_refresh.alpha = 0f
|
||||
presenter.getLibraryBlocking()
|
||||
}
|
||||
}
|
||||
@ -229,12 +358,17 @@ class LibraryController(
|
||||
override fun onChangeStarted(handler: ControllerChangeHandler, type: ControllerChangeType) {
|
||||
super.onChangeStarted(handler, type)
|
||||
if (type.isEnter) {
|
||||
activity?.tabs?.setupWithViewPager(library_pager)
|
||||
if (usePager)
|
||||
(activity as MainActivity).supportActionBar?.setDisplayShowCustomEnabled(true)
|
||||
//activity?.tabs?.setupWithViewPager(library_pager)
|
||||
presenter.getLibrary()
|
||||
DownloadService.addListener(this)
|
||||
DownloadService.callListeners()
|
||||
LibraryUpdateService.setListener(this)
|
||||
}
|
||||
else if (type == ControllerChangeType.PUSH_EXIT) {
|
||||
(activity as MainActivity).supportActionBar?.setDisplayShowCustomEnabled(false)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onActivityResumed(activity: Activity) {
|
||||
@ -251,18 +385,19 @@ class LibraryController(
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
(activity as MainActivity).supportActionBar?.setDisplayShowCustomEnabled(false)
|
||||
presenter.onDestroy()
|
||||
super.onDestroy()
|
||||
}
|
||||
|
||||
override fun onDestroyView(view: View) {
|
||||
adapter?.onDestroy()
|
||||
//adapter.onDestroy()
|
||||
DownloadService.removeListener(this)
|
||||
LibraryUpdateService.removeListener()
|
||||
adapter = null
|
||||
//adapter = null
|
||||
actionMode = null
|
||||
tabsVisibilitySubscription?.unsubscribe()
|
||||
tabsVisibilitySubscription = null
|
||||
//tabsVisibilitySubscription?.unsubscribe()
|
||||
//tabsVisibilitySubscription = null
|
||||
super.onDestroyView(view)
|
||||
}
|
||||
|
||||
@ -288,7 +423,7 @@ class LibraryController(
|
||||
super.onDetach(view)
|
||||
}
|
||||
|
||||
override fun configureTabs(tabs: TabLayout) {
|
||||
/*override fun configureTabs(tabs: TabLayout) {
|
||||
with(tabs) {
|
||||
tabGravity = TabLayout.GRAVITY_CENTER
|
||||
tabMode = TabLayout.MODE_SCROLLABLE
|
||||
@ -307,12 +442,53 @@ class LibraryController(
|
||||
override fun cleanupTabs(tabs: TabLayout) {
|
||||
tabsVisibilitySubscription?.unsubscribe()
|
||||
tabsVisibilitySubscription = null
|
||||
}*/
|
||||
|
||||
fun onNextLibraryUpdate(mangaMap: List<LibraryItem>, freshStart: Boolean = false) {
|
||||
if (mangaMap.isNotEmpty()) {
|
||||
empty_view.hide()
|
||||
} else {
|
||||
empty_view.show(R.drawable.ic_book_black_128dp, R.string.information_empty_library)
|
||||
}
|
||||
adapter.setItems(mangaMap)
|
||||
|
||||
val position = if (freshStart) adapter.indexOf(activeCategory) + 1 else null
|
||||
|
||||
spinner.onItemSelectedListener = null
|
||||
spinnerAdapter = SpinnerAdapter(view!!.context, R.layout.library_spinner_textview,
|
||||
presenter.categories.map { it.name }.toTypedArray())
|
||||
spinner.adapter = spinnerAdapter
|
||||
|
||||
|
||||
spinnerAdapter?.setCustomText(presenter.categories.find { it.order == activeCategory
|
||||
}?.name ?: resources?.getString(R.string.label_library))
|
||||
if (!freshStart) {
|
||||
spinnerAdapter?.setCustomText(presenter.categories.find { it.order == activeCategory
|
||||
}?.name ?: resources?.getString(R.string.label_library))
|
||||
justStarted = false
|
||||
if (swipe_refresh.alpha == 0f)
|
||||
swipe_refresh.animate().alpha(1f).setDuration(500).start()
|
||||
|
||||
|
||||
}else {
|
||||
if (position != null)
|
||||
(recycler.layoutManager as LinearLayoutManager)
|
||||
.scrollToPositionWithOffset(position, 0)
|
||||
}
|
||||
spinner.onItemSelectedListener = IgnoreFirstSpinnerListener { pos ->
|
||||
val headerPosition = adapter.indexOf(pos - 1) + 1
|
||||
if (headerPosition > -1) {
|
||||
(recycler.layoutManager as LinearLayoutManager).scrollToPositionWithOffset(
|
||||
headerPosition, 0
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun onNextLibraryUpdate(categories: List<Category>, mangaMap: Map<Int, List<LibraryItem>>,
|
||||
freshStart: Boolean = false) {
|
||||
val view = view ?: return
|
||||
val adapter = adapter ?: return
|
||||
val adapter = pagerAdapter ?: return
|
||||
|
||||
// Show empty view if needed
|
||||
if (mangaMap.isNotEmpty()) {
|
||||
@ -342,13 +518,13 @@ class LibraryController(
|
||||
bottom_sheet.lastCategory = adapter.categories.getOrNull(activeCat)
|
||||
bottom_sheet.updateTitle()
|
||||
|
||||
tabsVisibilityRelay.call(categories.size > 1)
|
||||
//tabsVisibilityRelay.call(categories.size > 1)
|
||||
|
||||
if (freshStart || !justStarted) {
|
||||
// Delay the scroll position to allow the view to be properly measured.
|
||||
view.post {
|
||||
if (isAttached) {
|
||||
activity?.tabs?.setScrollPosition(library_pager.currentItem, 0f, true)
|
||||
//activity?.tabs?.setScrollPosition(library_pager.currentItem, 0f, true)
|
||||
}
|
||||
}
|
||||
|
||||
@ -398,22 +574,50 @@ class LibraryController(
|
||||
}
|
||||
|
||||
fun onCatSortChanged(id: Int? = null) {
|
||||
val catId = id ?: adapter?.categories?.getOrNull(library_pager.currentItem)?.id ?: return
|
||||
presenter.requestCatSortUpdate(catId)
|
||||
val catId = id ?: presenter.categories.find { it.order == activeCategory }?.id ?: return
|
||||
presenter.requestCatSortUpdate(catId)
|
||||
//val catId = id ?: adapter?.categories?.getOrNull(library_pager.currentItem)?.id ?: return
|
||||
// presenter.requestCatSortUpdate(catId)
|
||||
}
|
||||
|
||||
/**
|
||||
* Reattaches the adapter to the view pager to recreate fragments
|
||||
*/
|
||||
private fun reattachAdapter() {
|
||||
val adapter = adapter ?: return
|
||||
val position = (recycler.layoutManager as LinearLayoutManager).findFirstVisibleItemPosition()
|
||||
if (recycler is AutofitRecyclerView && preferences.libraryLayout().getOrDefault() == 0 ||
|
||||
recycler !is AutofitRecyclerView && preferences.libraryLayout().getOrDefault() > 0) {
|
||||
recycler_layout.removeView(recycler)
|
||||
recycler = if (preferences.libraryLayout().getOrDefault() == 0) {
|
||||
(swipe_refresh.inflate(R.layout.library_list_recycler) as RecyclerView).apply {
|
||||
layoutManager = LinearLayoutManager(context)
|
||||
}
|
||||
} else {
|
||||
(swipe_refresh.inflate(R.layout.library_grid_recycler) as AutofitRecyclerView).apply {
|
||||
spanCount = mangaPerRow
|
||||
manager.spanSizeLookup = (object : GridLayoutManager.SpanSizeLookup() {
|
||||
override fun getSpanSize(position: Int): Int {
|
||||
val item = this@LibraryController.adapter.getItem(position)
|
||||
return if (item is LibraryHeaderItem)
|
||||
manager.spanCount else 1
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
recycler.setHasFixedSize(true)
|
||||
recycler.addOnScrollListener(scrollLister)
|
||||
recycler_layout.addView(recycler)
|
||||
}
|
||||
recycler.adapter = adapter
|
||||
(recycler.layoutManager as LinearLayoutManager).scrollToPositionWithOffset(position, 0)
|
||||
//val adapter = adapter ?: return
|
||||
|
||||
val position = library_pager.currentItem
|
||||
/*val position = library_pager.currentItem
|
||||
|
||||
adapter.recycle = false
|
||||
library_pager.adapter = adapter
|
||||
library_pager.currentItem = position
|
||||
adapter.recycle = true
|
||||
adapter.recycle = true*/
|
||||
}
|
||||
|
||||
/**
|
||||
@ -533,8 +737,8 @@ class LibraryController(
|
||||
mode.title = resources?.getString(R.string.label_selected, count)
|
||||
if (preferences.librarySortingMode().getOrDefault() == LibrarySort.DRAG_AND_DROP) {
|
||||
val catId = (selectedMangas.first() as? LibraryManga)?.category
|
||||
val sameCat = (adapter?.categories?.getOrNull(library_pager.currentItem)?.id
|
||||
== catId) && selectedMangas.all { (it as? LibraryManga)?.category == catId }
|
||||
val sameCat = /*(adapter?.categories?.getOrNull(library_pager.currentItem)?.id
|
||||
== catId) &&*/ selectedMangas.all { (it as? LibraryManga)?.category == catId }
|
||||
menu.findItem(R.id.action_move_manga).isVisible = sameCat
|
||||
}
|
||||
else menu.findItem(R.id.action_move_manga).isVisible = false
|
||||
@ -554,11 +758,11 @@ class LibraryController(
|
||||
.negativeButton(android.R.string.no)
|
||||
.show()
|
||||
}
|
||||
R.id.action_select_all -> {
|
||||
/*R.id.action_select_all -> {
|
||||
adapter?.categories?.getOrNull(library_pager.currentItem)?.id?.let {
|
||||
selectAllRelay.call(it)
|
||||
}
|
||||
}
|
||||
}*/
|
||||
R.id.action_migrate -> {
|
||||
router.pushController(
|
||||
if (preferences.skipPreMigration().getOrDefault()) {
|
||||
@ -573,12 +777,12 @@ class LibraryController(
|
||||
.withFadeTransaction())
|
||||
destroyActionModeIfNeeded()
|
||||
}
|
||||
R.id.action_to_top, R.id.action_to_bottom -> {
|
||||
/*R.id.action_to_top, R.id.action_to_bottom -> {
|
||||
adapter?.categories?.getOrNull(library_pager.currentItem)?.id?.let {
|
||||
reorganizeRelay.call(it to if (item.itemId == R.id.action_to_top) -1 else -2)
|
||||
}
|
||||
destroyActionModeIfNeeded()
|
||||
}
|
||||
}*/
|
||||
else -> return false
|
||||
}
|
||||
return true
|
||||
@ -669,6 +873,19 @@ class LibraryController(
|
||||
destroyActionModeIfNeeded()
|
||||
}
|
||||
|
||||
override fun startReading(position: Int) {
|
||||
val activity = activity ?: return
|
||||
val manga = (adapter.getItem(position) as? LibraryItem)?.manga ?: return
|
||||
val chapter = presenter.getFirstUnread(manga) ?: return
|
||||
val intent = ReaderActivity.newIntent(activity, manga, chapter)
|
||||
destroyActionModeIfNeeded()
|
||||
startActivity(intent)
|
||||
}
|
||||
|
||||
override fun onItemReleased(position: Int) {
|
||||
|
||||
}
|
||||
|
||||
fun startReading(manga: Manga) {
|
||||
val activity = activity ?: return
|
||||
val chapter = presenter.getFirstUnread(manga) ?: return
|
||||
@ -676,6 +893,94 @@ class LibraryController(
|
||||
destroyActionModeIfNeeded()
|
||||
startActivity(intent)
|
||||
}
|
||||
|
||||
override fun canDrag(): Boolean {
|
||||
val sortingMode = preferences.librarySortingMode().getOrDefault()
|
||||
val filterOff = preferences.filterCompleted().getOrDefault() +
|
||||
preferences.filterTracked().getOrDefault() +
|
||||
preferences.filterUnread().getOrDefault() +
|
||||
preferences.filterCompleted().getOrDefault() == 0 &&
|
||||
!preferences.hideCategories().getOrDefault()
|
||||
return sortingMode == LibrarySort.DRAG_AND_DROP && filterOff &&
|
||||
adapter.mode != SelectableAdapter.Mode.MULTI
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a manga is clicked.
|
||||
*
|
||||
* @param position the position of the element clicked.
|
||||
* @return true if the item should be selected, false otherwise.
|
||||
*/
|
||||
override fun onItemClick(view: View?, position: Int): Boolean {
|
||||
// If the action mode is created and the position is valid, toggle the selection.
|
||||
val item = adapter.getItem(position) as? LibraryItem ?: return false
|
||||
return if (adapter.mode == SelectableAdapter.Mode.MULTI) {
|
||||
lastClickPosition = position
|
||||
toggleSelection(position)
|
||||
true
|
||||
} else {
|
||||
openManga(item.manga, 0f)
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a manga is long clicked.
|
||||
*
|
||||
* @param position the position of the element clicked.
|
||||
*/
|
||||
override fun onItemLongClick(position: Int) {
|
||||
createActionModeIfNeeded()
|
||||
when {
|
||||
lastClickPosition == -1 -> setSelection(position)
|
||||
lastClickPosition > position -> for (i in position until lastClickPosition)
|
||||
setSelection(i)
|
||||
lastClickPosition < position -> for (i in lastClickPosition + 1..position)
|
||||
setSelection(i)
|
||||
else -> setSelection(position)
|
||||
}
|
||||
lastClickPosition = position
|
||||
}
|
||||
|
||||
override fun onActionStateChanged(viewHolder: RecyclerView.ViewHolder?, actionState: Int) {
|
||||
val position = viewHolder?.adapterPosition ?: return
|
||||
if (actionState == 2) onItemLongClick(position)
|
||||
}
|
||||
|
||||
/**
|
||||
* Tells the presenter to toggle the selection for the given position.
|
||||
*
|
||||
* @param position the position to toggle.
|
||||
*/
|
||||
private fun toggleSelection(position: Int) {
|
||||
val item = adapter.getItem(position) ?: return
|
||||
|
||||
setSelection((item as LibraryItem).manga, !adapter.isSelected(position))
|
||||
invalidateActionMode()
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Tells the presenter to set the selection for the given position.
|
||||
*
|
||||
* @param position the position to toggle.
|
||||
*/
|
||||
private fun setSelection(position: Int) {
|
||||
val item = adapter.getItem(position) ?: return
|
||||
|
||||
setSelection((item as LibraryItem).manga, true)
|
||||
invalidateActionMode()
|
||||
}
|
||||
|
||||
override fun onItemMove(fromPosition: Int, toPosition: Int) { }
|
||||
|
||||
override fun shouldMoveItem(fromPosition: Int, toPosition: Int): Boolean {
|
||||
if (adapter.selectedItemCount > 1)
|
||||
return false
|
||||
if (adapter.isSelected(fromPosition))
|
||||
toggleSelection(fromPosition)
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
object HeightTopWindowInsetsListener : View.OnApplyWindowInsetsListener {
|
||||
@ -688,4 +993,30 @@ object HeightTopWindowInsetsListener : View.OnApplyWindowInsetsListener {
|
||||
}
|
||||
return insets
|
||||
}
|
||||
}
|
||||
|
||||
class SpinnerAdapter(context: Context, layoutId: Int, val array: Array<String>) :
|
||||
ArrayAdapter<String>
|
||||
(context, layoutId, array) {
|
||||
private var mCustomText = ""
|
||||
|
||||
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
|
||||
val view = super.getView(position, convertView, parent)
|
||||
val tv: TextView = view as TextView
|
||||
tv.text = mCustomText
|
||||
return view
|
||||
}
|
||||
|
||||
fun setCustomText(customText: String?) {
|
||||
// Call to set the text that must be shown in the spinner for the custom option.
|
||||
val text = customText ?: return
|
||||
mCustomText = text
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
|
||||
override fun getDropDownView(position: Int, convertView: View?, parent: ViewGroup): View {
|
||||
val view = parent.inflate(R.layout.library_spinner_entry_text) as TextView
|
||||
view.text = array[position]
|
||||
return view
|
||||
}
|
||||
}
|
@ -7,13 +7,11 @@ import android.widget.FrameLayout
|
||||
import androidx.constraintlayout.widget.ConstraintLayout
|
||||
import com.bumptech.glide.load.engine.DiskCacheStrategy
|
||||
import com.bumptech.glide.signature.ObjectKey
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.database.models.MangaImpl
|
||||
import eu.kanade.tachiyomi.data.glide.GlideApp
|
||||
import eu.kanade.tachiyomi.source.LocalSource
|
||||
import eu.kanade.tachiyomi.util.system.dpToPx
|
||||
import eu.kanade.tachiyomi.util.view.gone
|
||||
import eu.kanade.tachiyomi.util.view.updatePaddingRelative
|
||||
import eu.kanade.tachiyomi.util.view.visible
|
||||
import kotlinx.android.synthetic.main.catalogue_grid_item.*
|
||||
import kotlinx.android.synthetic.main.unread_download_badge.*
|
||||
|
@ -0,0 +1,64 @@
|
||||
package eu.kanade.tachiyomi.ui.library
|
||||
|
||||
import android.view.View
|
||||
import android.widget.TextView
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import eu.davidea.flexibleadapter.FlexibleAdapter
|
||||
import eu.davidea.flexibleadapter.items.AbstractHeaderItem
|
||||
import eu.davidea.flexibleadapter.items.IFlexible
|
||||
import eu.davidea.viewholders.FlexibleViewHolder
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.database.models.Category
|
||||
|
||||
class LibraryHeaderItem(val category: Category) : AbstractHeaderItem<LibraryHeaderItem.Holder>() {
|
||||
|
||||
override fun getLayoutRes(): Int {
|
||||
return R.layout.library_category_header_item
|
||||
}
|
||||
|
||||
override fun createViewHolder(
|
||||
view: View,
|
||||
adapter: FlexibleAdapter<IFlexible<RecyclerView.ViewHolder>>
|
||||
): Holder {
|
||||
return Holder(view, adapter)
|
||||
}
|
||||
|
||||
override fun bindViewHolder(
|
||||
adapter: FlexibleAdapter<IFlexible<RecyclerView.ViewHolder>>,
|
||||
holder: Holder,
|
||||
position: Int,
|
||||
payloads: MutableList<Any?>?
|
||||
) {
|
||||
holder.bind(this)
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
if (other is LibraryHeaderItem) {
|
||||
return category.id == other.category.id
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
override fun isDraggable(): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun isSelectable(): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
return category.id!!
|
||||
}
|
||||
|
||||
class Holder(view: View, adapter: FlexibleAdapter<IFlexible<RecyclerView.ViewHolder>>) :
|
||||
FlexibleViewHolder(view, adapter, true) {
|
||||
|
||||
private val sectionText: TextView = view.findViewById(R.id.category_title)
|
||||
|
||||
fun bind(item: LibraryHeaderItem) {
|
||||
sectionText.text = item.category.name
|
||||
}
|
||||
}
|
||||
}
|
@ -37,8 +37,4 @@ abstract class LibraryHolder(
|
||||
super.onItemReleased(position)
|
||||
(adapter as? LibraryCategoryAdapter)?.libraryListener?.onItemReleased(position)
|
||||
}
|
||||
|
||||
protected fun convertColor(color: Int):String {
|
||||
return Integer.toHexString(color and 0x00ffffff)
|
||||
}
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ import androidx.core.content.ContextCompat
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.f2prateek.rx.preferences.Preference
|
||||
import eu.davidea.flexibleadapter.FlexibleAdapter
|
||||
import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
|
||||
import eu.davidea.flexibleadapter.items.AbstractSectionableItem
|
||||
import eu.davidea.flexibleadapter.items.IFilterable
|
||||
import eu.davidea.flexibleadapter.items.IFlexible
|
||||
import eu.kanade.tachiyomi.R
|
||||
@ -21,8 +21,10 @@ import eu.kanade.tachiyomi.widget.AutofitRecyclerView
|
||||
import kotlinx.android.synthetic.main.catalogue_grid_item.view.*
|
||||
import uy.kohesive.injekt.injectLazy
|
||||
|
||||
class LibraryItem(val manga: LibraryManga, private val libraryLayout: Preference<Int>) :
|
||||
AbstractFlexibleItem<LibraryHolder>(), IFilterable<String> {
|
||||
class LibraryItem(val manga: LibraryManga,
|
||||
private val libraryLayout: Preference<Int>,
|
||||
header: LibraryHeaderItem) :
|
||||
AbstractSectionableItem<LibraryHolder, LibraryHeaderItem>(header), IFilterable<String> {
|
||||
|
||||
var downloadCount = -1
|
||||
var unreadType = 1
|
||||
@ -51,7 +53,8 @@ class LibraryItem(val manga: LibraryManga, private val libraryLayout: Preference
|
||||
cover_thumbnail.maxHeight = Integer.MAX_VALUE
|
||||
constraint_layout.minHeight = 0
|
||||
cover_thumbnail.adjustViewBounds = false
|
||||
cover_thumbnail.layoutParams = FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, coverHeight)
|
||||
cover_thumbnail.layoutParams =
|
||||
FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, coverHeight)
|
||||
}
|
||||
else {
|
||||
constraint_layout.minHeight = coverHeight
|
||||
|
@ -17,7 +17,6 @@ import eu.kanade.tachiyomi.source.SourceManager
|
||||
import eu.kanade.tachiyomi.source.model.SChapter
|
||||
import eu.kanade.tachiyomi.source.model.SManga
|
||||
import eu.kanade.tachiyomi.source.online.HttpSource
|
||||
import eu.kanade.tachiyomi.ui.manga.chapter.ChapterItem
|
||||
import eu.kanade.tachiyomi.ui.migration.MigrationFlags
|
||||
import eu.kanade.tachiyomi.util.chapter.syncChaptersWithSource
|
||||
import eu.kanade.tachiyomi.util.lang.removeArticles
|
||||
@ -29,20 +28,16 @@ import eu.kanade.tachiyomi.widget.ExtendedNavigationView.Item.TriStateGroup.Comp
|
||||
import kotlinx.coroutines.CoroutineStart
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.GlobalScope
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import rx.Observable
|
||||
import rx.Subscription
|
||||
import rx.android.schedulers.AndroidSchedulers
|
||||
import rx.schedulers.Schedulers
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
import java.util.ArrayList
|
||||
import java.util.Calendar
|
||||
import java.util.Collections
|
||||
import java.util.Comparator
|
||||
import java.util.Date
|
||||
|
||||
/**
|
||||
* Class containing library information.
|
||||
@ -109,7 +104,7 @@ class LibraryPresenter(
|
||||
mangaMap
|
||||
}
|
||||
currentMangaMap = mangaMap
|
||||
view.onNextLibraryUpdate(categories, mangaMap)
|
||||
updateView(categories, mangaMap)
|
||||
}
|
||||
}
|
||||
|
||||
@ -124,7 +119,9 @@ class LibraryPresenter(
|
||||
mangaMap
|
||||
}()
|
||||
currentMangaMap = mangaMap
|
||||
view.onNextLibraryUpdate(categories, mangaMap, true)
|
||||
launchUI {
|
||||
updateView(categories, mangaMap, true)
|
||||
}
|
||||
}
|
||||
|
||||
fun getAllManga(): LibraryMap? {
|
||||
@ -314,7 +311,6 @@ class LibraryPresenter(
|
||||
}
|
||||
val catListing by lazy {
|
||||
val default = createDefaultCategory()
|
||||
default.order = -1
|
||||
listOf(default) + db.getCategories().executeAsBlocking()
|
||||
}
|
||||
|
||||
@ -423,11 +419,38 @@ class LibraryPresenter(
|
||||
var libraryManga = db.getLibraryMangas().executeAsBlocking()
|
||||
if (!showCategories)
|
||||
libraryManga = libraryManga.distinctBy { it.id }
|
||||
val libraryMap = libraryManga.map { manga ->
|
||||
/*val libraryMap = libraryManga.map { manga ->
|
||||
LibraryItem(manga, libraryLayout).apply { unreadType = unreadBadgeType }
|
||||
}.groupBy {
|
||||
if (showCategories) it.manga.category else 0
|
||||
}
|
||||
}*/
|
||||
val catItemMain = LibraryHeaderItem(categories.firstOrNull() ?: createDefaultCategory())
|
||||
val libraryMap =
|
||||
if (preferences.libraryUsingPager().getOrDefault()) {
|
||||
libraryManga.map { manga ->
|
||||
LibraryItem(manga, libraryLayout, catItemMain).apply { unreadType = unreadBadgeType }
|
||||
}.groupBy {
|
||||
if (showCategories) it.manga.category else 0
|
||||
}
|
||||
}
|
||||
else {
|
||||
libraryManga.groupBy { manga ->
|
||||
if (showCategories) manga.category else 0
|
||||
//LibraryItem(manga, libraryLayout).apply { unreadType = unreadBadgeType }
|
||||
}.map { entry ->
|
||||
val categoryItem = LibraryHeaderItem(categories.find { entry.key == it.id }
|
||||
?: createDefaultCategory())
|
||||
entry.value.map {
|
||||
LibraryItem(
|
||||
it, libraryLayout, categoryItem
|
||||
).apply { unreadType = unreadBadgeType }
|
||||
}
|
||||
}.map {
|
||||
val cat = if (showCategories) it.firstOrNull()?.manga?.category ?: 0 else 0
|
||||
cat to it
|
||||
//LibraryItem(manga, libraryLayout).apply { unreadType = unreadBadgeType }
|
||||
}.toMap()
|
||||
}
|
||||
if (libraryMap.containsKey(0))
|
||||
categories.add(0, createDefaultCategory())
|
||||
|
||||
@ -441,6 +464,7 @@ class LibraryPresenter(
|
||||
|
||||
private fun createDefaultCategory(): Category {
|
||||
val default = Category.createDefault(context)
|
||||
default.order = -1
|
||||
val defOrder = preferences.defaultMangaOrder().getOrDefault()
|
||||
if (defOrder.firstOrNull()?.isLetter() == true) default.mangaSort = defOrder.first()
|
||||
else default.mangaOrder = defOrder.split("/").mapNotNull { it.toLongOrNull() }
|
||||
@ -456,10 +480,61 @@ class LibraryPresenter(
|
||||
mangaMap = withContext(Dispatchers.IO) { applyFilters(mangaMap) }
|
||||
mangaMap = withContext(Dispatchers.IO) { applySort(mangaMap) }
|
||||
currentMangaMap = mangaMap
|
||||
view.onNextLibraryUpdate(categories, mangaMap)
|
||||
updateView(categories, mangaMap)
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun updateView(categories: List<Category>, mangaMap: LibraryMap, freshStart:Boolean
|
||||
= false) {
|
||||
/* val list = withContext(Dispatchers.IO) {
|
||||
val showCategories = !preferences.hideCategories().getOrDefault()
|
||||
val current = mangaMap.values.first()
|
||||
current.groupBy {
|
||||
if (showCategories) it.manga.category else 0
|
||||
}.flatMap { it.value }
|
||||
}*/
|
||||
if (preferences.libraryUsingPager().getOrDefault()) {
|
||||
view.onNextLibraryUpdate(categories, mangaMap, true)
|
||||
}
|
||||
else {
|
||||
val mangaList = withContext(Dispatchers.IO) {
|
||||
val list = mutableListOf<LibraryItem>()
|
||||
val many = categories.size > 1
|
||||
for (element in mangaMap.toSortedMap(compareBy { entry ->
|
||||
categories.find { it.id == entry }?.order ?: -1
|
||||
})) {
|
||||
list.addAll(element.value)
|
||||
}
|
||||
list
|
||||
}
|
||||
view.onNextLibraryUpdate(mangaList, freshStart)
|
||||
}
|
||||
}
|
||||
|
||||
fun updateViewBlocking() {
|
||||
/* val list = withContext(Dispatchers.IO) {
|
||||
val showCategories = !preferences.hideCategories().getOrDefault()
|
||||
val current = mangaMap.values.first()
|
||||
current.groupBy {
|
||||
if (showCategories) it.manga.category else 0
|
||||
}.flatMap { it.value }
|
||||
}*/
|
||||
val mangaMap = currentMangaMap ?: return
|
||||
if (preferences.libraryUsingPager().getOrDefault()) {
|
||||
view.onNextLibraryUpdate(categories, mangaMap, true)
|
||||
}
|
||||
else {
|
||||
val list = mutableListOf<LibraryItem>()
|
||||
for (element in mangaMap?.toSortedMap(compareBy { entry ->
|
||||
categories.find { it.id == entry }?.order ?: -1
|
||||
})) {
|
||||
list.addAll(element.value)
|
||||
}
|
||||
view.onNextLibraryUpdate(list, true)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Requests the library to have download badges added/removed.
|
||||
*/
|
||||
@ -471,7 +546,7 @@ class LibraryPresenter(
|
||||
val current = currentMangaMap ?: return@launchUI
|
||||
withContext(Dispatchers.IO) { setDownloadCount(current) }
|
||||
currentMangaMap = current
|
||||
view.onNextLibraryUpdate(categories, current)
|
||||
updateView(categories, current)
|
||||
}
|
||||
}
|
||||
|
||||
@ -487,7 +562,7 @@ class LibraryPresenter(
|
||||
val current = currentMangaMap ?: return@launchUI
|
||||
withContext(Dispatchers.IO) { setUnreadBadge(current) }
|
||||
currentMangaMap = current
|
||||
view.onNextLibraryUpdate(categories, current)
|
||||
updateView(categories, current)
|
||||
}
|
||||
}
|
||||
|
||||
@ -499,7 +574,7 @@ class LibraryPresenter(
|
||||
var mangaMap = currentMangaMap ?: return@launchUI
|
||||
mangaMap = withContext(Dispatchers.IO) { applySort(mangaMap) }
|
||||
currentMangaMap = mangaMap
|
||||
view.onNextLibraryUpdate(categories, mangaMap)
|
||||
updateView(categories, mangaMap)
|
||||
}
|
||||
}
|
||||
|
||||
@ -508,7 +583,7 @@ class LibraryPresenter(
|
||||
var mangaMap = currentMangaMap ?: return@launchUI
|
||||
mangaMap = withContext(Dispatchers.IO) { applyCatSort(mangaMap, catId) }
|
||||
currentMangaMap = mangaMap
|
||||
view.onNextLibraryUpdate(categories, mangaMap)
|
||||
updateView(categories, mangaMap)
|
||||
}
|
||||
}
|
||||
|
||||
@ -698,5 +773,6 @@ class LibraryPresenter(
|
||||
|
||||
private companion object {
|
||||
var currentLibrary:Library? = null
|
||||
var currentList:List<LibraryItem>? = null
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,6 @@
|
||||
package eu.kanade.tachiyomi.ui.main
|
||||
|
||||
import android.app.SearchManager
|
||||
import android.content.ComponentCallbacks2
|
||||
import android.content.Intent
|
||||
import android.content.res.Configuration
|
||||
import android.graphics.Color
|
||||
@ -48,7 +47,6 @@ import eu.kanade.tachiyomi.ui.catalogue.global_search.CatalogueSearchController
|
||||
import eu.kanade.tachiyomi.ui.download.DownloadController
|
||||
import eu.kanade.tachiyomi.ui.extension.ExtensionController
|
||||
import eu.kanade.tachiyomi.ui.library.LibraryController
|
||||
import eu.kanade.tachiyomi.ui.library.LibraryPresenter
|
||||
import eu.kanade.tachiyomi.ui.manga.MangaController
|
||||
import eu.kanade.tachiyomi.ui.recent_updates.RecentChaptersController
|
||||
import eu.kanade.tachiyomi.ui.recently_read.RecentlyReadController
|
||||
@ -58,7 +56,6 @@ import eu.kanade.tachiyomi.util.system.launchUI
|
||||
import eu.kanade.tachiyomi.util.view.gone
|
||||
import eu.kanade.tachiyomi.util.view.updateLayoutParams
|
||||
import eu.kanade.tachiyomi.util.view.updatePadding
|
||||
import eu.kanade.tachiyomi.util.view.updatePaddingRelative
|
||||
import eu.kanade.tachiyomi.util.view.visible
|
||||
import kotlinx.android.synthetic.main.main_activity.*
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
@ -186,6 +183,8 @@ open class MainActivity : BaseActivity(), DownloadServiceListener {
|
||||
}
|
||||
}
|
||||
|
||||
supportActionBar?.setDisplayShowCustomEnabled(true)
|
||||
|
||||
content.setOnApplyWindowInsetsListener { v, insets ->
|
||||
// if device doesn't support light nav bar
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
|
||||
@ -279,6 +278,10 @@ open class MainActivity : BaseActivity(), DownloadServiceListener {
|
||||
|
||||
})
|
||||
|
||||
if (router.backstackSize <= 1) {
|
||||
tabAnimator.hide()
|
||||
}
|
||||
|
||||
syncActivityViewWithController(router.backstack.lastOrNull()?.controller())
|
||||
|
||||
if (savedInstanceState == null) {
|
||||
|
@ -1,9 +1,9 @@
|
||||
package eu.kanade.tachiyomi.ui.main
|
||||
|
||||
import android.animation.ObjectAnimator
|
||||
import com.google.android.material.tabs.TabLayout
|
||||
import android.view.ViewTreeObserver
|
||||
import android.view.animation.DecelerateInterpolator
|
||||
import com.google.android.material.tabs.TabLayout
|
||||
|
||||
class TabsAnimator(val tabs: TabLayout) {
|
||||
|
||||
@ -97,6 +97,11 @@ class TabsAnimator(val tabs: TabLayout) {
|
||||
isLastStateShown = false
|
||||
}
|
||||
|
||||
fun hide() {
|
||||
setHeight(0)
|
||||
isLastStateShown = false
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the tab layout has a known height.
|
||||
*/
|
||||
|
@ -52,6 +52,13 @@ class SettingsLibraryController : SettingsController() {
|
||||
}
|
||||
}
|
||||
|
||||
switchPreference {
|
||||
key = Keys.libraryUsingPager
|
||||
titleRes = R.string.pref_remove_articles
|
||||
summaryRes = R.string.pref_remove_articles_summary
|
||||
defaultValue = false
|
||||
}
|
||||
|
||||
switchPreference {
|
||||
key = Keys.removeArticles
|
||||
titleRes = R.string.pref_remove_articles
|
||||
|
@ -3,13 +3,12 @@ package eu.kanade.tachiyomi.widget
|
||||
import android.content.Context
|
||||
import android.util.AttributeSet
|
||||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import kotlin.math.max
|
||||
|
||||
class AutofitRecyclerView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) :
|
||||
androidx.recyclerview.widget.RecyclerView(context, attrs) {
|
||||
|
||||
private val manager = GridLayoutManager(context, 1)
|
||||
val manager = GridLayoutManager(context, 1)
|
||||
|
||||
private var columnWidth = -1
|
||||
|
||||
|
@ -1,153 +1,154 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout 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:id="@+id/constraint_layout"
|
||||
<androidx.constraintlayout.widget.ConstraintLayout 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:id="@+id/constraint_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom"
|
||||
android:background="@drawable/library_compact_grid_selector"
|
||||
android:minHeight="200dp"
|
||||
android:orientation="vertical">
|
||||
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
android:id="@+id/card"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom"
|
||||
android:background="@drawable/library_compact_grid_selector"
|
||||
android:minHeight="200dp"
|
||||
android:orientation="vertical">
|
||||
android:layout_marginStart="8dp"
|
||||
android:layout_marginTop="10dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
app:layout_constraintBottom_toTopOf="@+id/title"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintVertical_bias="1.0">
|
||||
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
android:id="@+id/card"
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/cover_thumbnail"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom"
|
||||
android:layout_marginStart="8dp"
|
||||
android:layout_marginTop="10dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
app:layout_constraintBottom_toTopOf="@+id/title"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintVertical_bias="1.0">
|
||||
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/cover_thumbnail"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:adjustViewBounds="true"
|
||||
android:background="?android:attr/colorBackground"
|
||||
android:maxHeight="250dp"
|
||||
app:layout_constrainedHeight="true"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:background="?android:attr/colorBackground"
|
||||
tools:ignore="ContentDescription"
|
||||
tools:src="@mipmap/ic_launcher" />
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/play_layout"
|
||||
android:layout_width="50dp"
|
||||
android:layout_height="50dp"
|
||||
android:layout_gravity="end"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/play_button"
|
||||
android:layout_width="30dp"
|
||||
android:layout_height="30dp"
|
||||
android:layout_gravity="end"
|
||||
android:layout_marginTop="6dp"
|
||||
android:layout_marginBottom="6dp"
|
||||
android:layout_marginEnd="6dp"
|
||||
android:background="@drawable/round_play_background"
|
||||
android:contentDescription="@string/start_reading"
|
||||
android:padding="6dp"
|
||||
android:src="@drawable/ic_start_reading_white_24dp"
|
||||
android:tint="@android:color/white" />
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
<View
|
||||
android:id="@+id/gradient"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="150dp"
|
||||
android:layout_gravity="bottom"
|
||||
android:background="@drawable/gradient_shape" />
|
||||
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
android:id="@+id/compact_title"
|
||||
style="@style/TextAppearance.Regular.Body1.SemiBold"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom"
|
||||
android:layout_marginStart="4dp"
|
||||
android:layout_marginEnd="4dp"
|
||||
android:layout_marginBottom="4dp"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="2"
|
||||
android:textColor="@android:color/white"
|
||||
android:textSize="13sp"
|
||||
tools:text="Sample name" />
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/progress"
|
||||
style="?android:attr/progressBarStyleSmall"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
||||
<View
|
||||
android:id="@+id/badge_guide"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="10dp"
|
||||
app:layout_constraintTop_toTopOf="@+id/card"/>
|
||||
|
||||
<include layout="@layout/unread_download_badge"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="@id/badge_guide"/>
|
||||
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
android:id="@+id/title"
|
||||
style="@style/TextAppearance.Regular.Body1.Light"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="2"
|
||||
android:textColor="?android:attr/textColorPrimary"
|
||||
android:textSize="12sp"
|
||||
app:layout_constraintBottom_toTopOf="@+id/subtitle"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
tools:text="Sample name" />
|
||||
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
android:id="@+id/subtitle"
|
||||
style="@style/TextAppearance.Regular.Body1.Light"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:layout_marginTop="-1dp"
|
||||
android:ellipsize="end"
|
||||
android:singleLine="true"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
android:textSize="12sp"
|
||||
android:adjustViewBounds="true"
|
||||
android:background="?android:attr/colorBackground"
|
||||
android:maxHeight="250dp"
|
||||
app:layout_constrainedHeight="true"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
tools:text="Sample artist" />
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:background="?android:attr/colorBackground"
|
||||
tools:ignore="ContentDescription"
|
||||
tools:src="@mipmap/ic_launcher" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
<FrameLayout
|
||||
android:id="@+id/play_layout"
|
||||
android:layout_width="50dp"
|
||||
android:layout_height="50dp"
|
||||
android:layout_gravity="end"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/play_button"
|
||||
android:layout_width="30dp"
|
||||
android:layout_height="30dp"
|
||||
android:layout_gravity="end"
|
||||
android:layout_marginTop="6dp"
|
||||
android:layout_marginEnd="6dp"
|
||||
android:layout_marginBottom="6dp"
|
||||
android:background="@drawable/round_play_background"
|
||||
android:contentDescription="@string/start_reading"
|
||||
android:padding="6dp"
|
||||
android:src="@drawable/ic_start_reading_white_24dp"
|
||||
android:tint="@android:color/white" />
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
<View
|
||||
android:id="@+id/gradient"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="150dp"
|
||||
android:layout_gravity="bottom"
|
||||
android:background="@drawable/gradient_shape" />
|
||||
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
android:id="@+id/compact_title"
|
||||
style="@style/TextAppearance.Regular.Body1.SemiBold"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom"
|
||||
android:layout_marginStart="4dp"
|
||||
android:layout_marginEnd="4dp"
|
||||
android:layout_marginBottom="4dp"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="2"
|
||||
android:textColor="@android:color/white"
|
||||
android:textSize="13sp"
|
||||
tools:text="Sample name" />
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/progress"
|
||||
style="?android:attr/progressBarStyleSmall"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
||||
<View
|
||||
android:id="@+id/badge_guide"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="10dp"
|
||||
app:layout_constraintTop_toTopOf="@+id/card" />
|
||||
|
||||
<include
|
||||
layout="@layout/unread_download_badge"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintBottom_toBottomOf="@id/badge_guide"
|
||||
app:layout_constraintStart_toStartOf="parent" />
|
||||
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
android:id="@+id/title"
|
||||
style="@style/TextAppearance.Regular.Body1.Light"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="2"
|
||||
android:textColor="?android:attr/textColorPrimary"
|
||||
android:textSize="12sp"
|
||||
app:layout_constraintBottom_toTopOf="@+id/subtitle"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
tools:text="Sample name" />
|
||||
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
android:id="@+id/subtitle"
|
||||
style="@style/TextAppearance.Regular.Body1.Light"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:layout_marginTop="-1dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:ellipsize="end"
|
||||
android:singleLine="true"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
android:textSize="12sp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
tools:text="Sample artist" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
27
app/src/main/res/layout/library_category_header_item.xml
Normal file
27
app/src/main/res/layout/library_category_header_item.xml
Normal file
@ -0,0 +1,27 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingTop="15dp"
|
||||
android:paddingBottom="5dp"
|
||||
android:gravity="center_vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/category_title"
|
||||
style="@style/TextAppearance.MaterialComponents.Headline5"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center|start"
|
||||
android:inputType="none"
|
||||
android:layout_marginStart="10dp"
|
||||
android:maxLines="1"
|
||||
android:textColor="?attr/actionBarTintColor"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="Title" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
@ -2,11 +2,24 @@
|
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/library_layout"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
||||
android:id="@+id/swipe_refresh"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
<FrameLayout
|
||||
android:id="@+id/recycler_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
</FrameLayout>
|
||||
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
|
||||
|
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||
android:id="@+id/pager_layout"
|
||||
android:visibility="gone"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
@ -16,6 +29,14 @@
|
||||
android:layout_height="match_parent" />
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||
|
||||
<eu.davidea.fastscroller.FastScroller
|
||||
android:id="@+id/fast_scroller"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="end"
|
||||
app:fastScrollerBubbleEnabled="true"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||
android:id="@+id/snackbar_layout"
|
||||
android:layout_width="match_parent"
|
||||
|
5
app/src/main/res/layout/library_spinner.xml
Normal file
5
app/src/main/res/layout/library_spinner.xml
Normal file
@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.appcompat.widget.AppCompatSpinner xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:entries="@array/color_filter_modes" />
|
13
app/src/main/res/layout/library_spinner_entry_text.xml
Normal file
13
app/src/main/res/layout/library_spinner_entry_text.xml
Normal file
@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<TextView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
style="@style/TextAppearance.AppCompat.Widget.DropDownItem"
|
||||
android:textAllCaps="false"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="start"
|
||||
android:textSize="16sp"
|
||||
android:padding="10dip"
|
||||
tools:text="Title"
|
||||
tools:background="?attr/colorPrimary"/>
|
11
app/src/main/res/layout/library_spinner_textview.xml
Normal file
11
app/src/main/res/layout/library_spinner_textview.xml
Normal file
@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<TextView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
style="@style/TextAppearance.AppCompat.Widget.ActionBar.Title"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="start"
|
||||
android:textSize="20sp"
|
||||
tools:text="Title"
|
||||
tools:background="?attr/colorPrimary"/>
|
Loading…
Reference in New Issue
Block a user