mirror of
https://github.com/tachiyomiorg/tachiyomi.git
synced 2024-12-23 21:01:51 +01:00
Updates & Fixes
Made manga header in details its own item Pressing the tab icon in library toggles the filters bottom sheet state, no longer just shows it Pressing the tab icon in browse toggles the extensions sheet Better logic in detecting which section of the list library you're in Fixing: • download cache with incorrect casing • "view chapters" from notifcation • Title bar centering • Filtering by tracker
This commit is contained in:
parent
1a9614b5de
commit
93cb8f649e
@ -24,19 +24,10 @@ interface Chapter : SChapter, Serializable {
|
||||
val isRecognizedNumber: Boolean
|
||||
get() = chapter_number >= 0f
|
||||
|
||||
val isHeader: Boolean
|
||||
get() = id == Long.MIN_VALUE
|
||||
|
||||
companion object {
|
||||
|
||||
fun create(): Chapter = ChapterImpl().apply {
|
||||
chapter_number = -1f
|
||||
}
|
||||
|
||||
fun createHeader(isExpanded: Boolean): Chapter = ChapterImpl().apply {
|
||||
id = Long.MIN_VALUE
|
||||
read = isExpanded
|
||||
manga_id = null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -78,7 +78,9 @@ class DownloadCache(
|
||||
checkRenew()
|
||||
|
||||
val files = mangaFiles[manga.id] ?: return false
|
||||
return files.any { it in provider.getValidChapterDirNames(chapter) }
|
||||
return files.any { file -> provider.getValidChapterDirNames(chapter).any {
|
||||
it.toLowerCase() == file.toLowerCase()
|
||||
} }
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -395,7 +395,7 @@ class NotificationReceiver : BroadcastReceiver() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns [PendingIntent] that opens the manga info controller.
|
||||
* Returns [PendingIntent] that opens the manga details controller.
|
||||
*
|
||||
* @param context context of application
|
||||
* @param manga manga of chapter
|
||||
@ -404,7 +404,7 @@ class NotificationReceiver : BroadcastReceiver() {
|
||||
PendingIntent {
|
||||
val newIntent =
|
||||
Intent(context, MainActivity::class.java).setAction(MainActivity.SHORTCUT_MANGA)
|
||||
.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
|
||||
.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_SINGLE_TOP)
|
||||
.putExtra(MangaDetailsController.MANGA_EXTRA, manga.id)
|
||||
.putExtra("notificationId", manga.id.hashCode())
|
||||
.putExtra("groupId", groupId)
|
||||
@ -422,7 +422,7 @@ class NotificationReceiver : BroadcastReceiver() {
|
||||
internal fun openExtensionsPendingActivity(context: Context): PendingIntent {
|
||||
val newIntent =
|
||||
Intent(context, MainActivity::class.java).setAction(MainActivity.SHORTCUT_EXTENSIONS)
|
||||
.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
|
||||
.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_SINGLE_TOP)
|
||||
return PendingIntent.getActivity(
|
||||
context, 0, newIntent, PendingIntent.FLAG_UPDATE_CURRENT
|
||||
)
|
||||
|
@ -21,9 +21,11 @@ class CenteredToolbar@JvmOverloads constructor(context: Context, attrs: Attribut
|
||||
else {
|
||||
toolbar_title.text = context.getString(resId)
|
||||
post {
|
||||
if (navigationIcon !is DrawerArrowDrawable) {
|
||||
toolbar_title.text = context.getString(resId)
|
||||
requestLayout()
|
||||
}
|
||||
}
|
||||
super.setTitle(null)
|
||||
}
|
||||
}
|
||||
@ -31,14 +33,16 @@ class CenteredToolbar@JvmOverloads constructor(context: Context, attrs: Attribut
|
||||
override fun setTitle(title: CharSequence?) {
|
||||
if (navigationIcon is DrawerArrowDrawable) {
|
||||
super.setTitle(title)
|
||||
toolbar_title.text = null
|
||||
toolbar_title.text = ""
|
||||
}
|
||||
else {
|
||||
toolbar_title.text = title
|
||||
post {
|
||||
if (navigationIcon !is DrawerArrowDrawable) {
|
||||
toolbar_title.text = title
|
||||
requestLayout()
|
||||
}
|
||||
}
|
||||
super.setTitle(null)
|
||||
}
|
||||
}
|
||||
|
@ -1,18 +1,15 @@
|
||||
package eu.kanade.tachiyomi.ui.base.controller
|
||||
|
||||
import android.os.Bundle
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import android.view.LayoutInflater
|
||||
import android.view.Menu
|
||||
import android.view.MenuInflater
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.bluelinelabs.conductor.Controller
|
||||
import com.bluelinelabs.conductor.ControllerChangeHandler
|
||||
import com.bluelinelabs.conductor.ControllerChangeType
|
||||
import com.bluelinelabs.conductor.RestoreViewOnCreateController
|
||||
import eu.kanade.tachiyomi.util.view.setOnQueryTextChangeListener
|
||||
import kotlinx.android.extensions.LayoutContainer
|
||||
import kotlinx.android.synthetic.*
|
||||
import timber.log.Timber
|
||||
@ -82,6 +79,7 @@ abstract class BaseController(bundle: Bundle? = null) : RestoreViewOnCreateContr
|
||||
parentController = parentController.parentController
|
||||
}
|
||||
|
||||
if (router.backstack.lastOrNull()?.controller() == this)
|
||||
(activity as? AppCompatActivity)?.supportActionBar?.title = getTitle()
|
||||
}
|
||||
|
||||
|
@ -164,6 +164,15 @@ class CatalogueController : NucleusController<CataloguePresenter>(),
|
||||
|
||||
}
|
||||
|
||||
fun toggleExtensions() {
|
||||
if (ext_bottom_sheet.sheetBehavior?.state != BottomSheetBehavior.STATE_COLLAPSED) {
|
||||
ext_bottom_sheet.sheetBehavior?.state = BottomSheetBehavior.STATE_COLLAPSED
|
||||
}
|
||||
else {
|
||||
ext_bottom_sheet.sheetBehavior?.state = BottomSheetBehavior.STATE_EXPANDED
|
||||
}
|
||||
}
|
||||
|
||||
override fun handleRootBack(): Boolean {
|
||||
if (ext_bottom_sheet.sheetBehavior?.state != BottomSheetBehavior.STATE_COLLAPSED) {
|
||||
ext_bottom_sheet.sheetBehavior?.state = BottomSheetBehavior.STATE_COLLAPSED
|
||||
|
@ -514,13 +514,7 @@ open class LibraryController(
|
||||
when (item.itemId) {
|
||||
R.id.action_search -> expandActionViewFromInteraction = true
|
||||
R.id.action_library_filter -> {
|
||||
if (bottom_sheet.sheetBehavior?.isHideable == true &&
|
||||
bottom_sheet.sheetBehavior?.state == BottomSheetBehavior.STATE_EXPANDED)
|
||||
bottom_sheet.sheetBehavior?.state = BottomSheetBehavior.STATE_HIDDEN
|
||||
else if (bottom_sheet.sheetBehavior?.state != BottomSheetBehavior.STATE_COLLAPSED
|
||||
&& bottom_sheet.sheetBehavior?.skipCollapsed == false)
|
||||
bottom_sheet.sheetBehavior?.state = BottomSheetBehavior.STATE_COLLAPSED
|
||||
else bottom_sheet.sheetBehavior?.state = BottomSheetBehavior.STATE_EXPANDED
|
||||
toggleFilters()
|
||||
}
|
||||
R.id.action_library_display -> {
|
||||
DisplayBottomSheet(this).show()
|
||||
@ -531,12 +525,14 @@ open class LibraryController(
|
||||
return true
|
||||
}
|
||||
|
||||
fun showFiltersBottomSheet() {
|
||||
if (bottom_sheet.sheetBehavior?.state == BottomSheetBehavior.STATE_HIDDEN)
|
||||
bottom_sheet.sheetBehavior?.state =
|
||||
if (bottom_sheet.sheetBehavior?.skipCollapsed == false)
|
||||
BottomSheetBehavior.STATE_COLLAPSED
|
||||
else BottomSheetBehavior.STATE_EXPANDED
|
||||
fun toggleFilters() {
|
||||
if (bottom_sheet.sheetBehavior?.isHideable == true &&
|
||||
bottom_sheet.sheetBehavior?.state == BottomSheetBehavior.STATE_EXPANDED)
|
||||
bottom_sheet.sheetBehavior?.state = BottomSheetBehavior.STATE_HIDDEN
|
||||
else if (bottom_sheet.sheetBehavior?.state != BottomSheetBehavior.STATE_COLLAPSED
|
||||
&& bottom_sheet.sheetBehavior?.skipCollapsed == false)
|
||||
bottom_sheet.sheetBehavior?.state = BottomSheetBehavior.STATE_COLLAPSED
|
||||
else bottom_sheet.sheetBehavior?.state = BottomSheetBehavior.STATE_EXPANDED
|
||||
}
|
||||
|
||||
|
||||
|
@ -246,6 +246,9 @@ class LibraryHeaderItem(private val categoryF: (Int) -> Category, val catId: Int
|
||||
checkboxImage.setImageDrawable(tintedDrawable)
|
||||
}
|
||||
|
||||
|
||||
override fun onLongClick(view: View?): Boolean {
|
||||
super.onLongClick(view)
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
@ -24,6 +24,7 @@ import com.afollestad.materialdialogs.checkbox.checkBoxPrompt
|
||||
import com.afollestad.materialdialogs.checkbox.isCheckPromptChecked
|
||||
import com.bluelinelabs.conductor.ControllerChangeHandler
|
||||
import com.bluelinelabs.conductor.ControllerChangeType
|
||||
import com.google.android.material.bottomsheet.BottomSheetBehavior
|
||||
import eu.davidea.flexibleadapter.FlexibleAdapter
|
||||
import eu.davidea.flexibleadapter.SelectableAdapter
|
||||
import eu.davidea.flexibleadapter.items.IFlexible
|
||||
@ -113,13 +114,7 @@ class LibraryListController(bundle: Bundle? = null) : LibraryController(bundle),
|
||||
private var scrollListener = 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
|
||||
}
|
||||
val order = getCategoryOrder()
|
||||
if (order != null && order != activeCategory) {
|
||||
preferences.lastUsedCategory().set(order)
|
||||
activeCategory = order
|
||||
@ -163,13 +158,9 @@ class LibraryListController(bundle: Bundle? = null) : LibraryController(bundle),
|
||||
if (startPosX == null) {
|
||||
startPosX = event.rawX
|
||||
startPosY = event.rawY
|
||||
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
|
||||
}
|
||||
val position = (recycler.layoutManager as LinearLayoutManager)
|
||||
.findFirstVisibleItemPosition()
|
||||
val order = getCategoryOrder()
|
||||
if (order != null) {
|
||||
ogCategory = order
|
||||
var newOffsetN = order + 1
|
||||
@ -255,6 +246,26 @@ class LibraryListController(bundle: Bundle? = null) : LibraryController(bundle),
|
||||
}
|
||||
}
|
||||
|
||||
private fun getCategoryOrder(): Int? {
|
||||
val position =
|
||||
(recycler.layoutManager as LinearLayoutManager).findFirstCompletelyVisibleItemPosition()
|
||||
var 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) {
|
||||
val fPosition =
|
||||
(recycler.layoutManager as LinearLayoutManager).findFirstVisibleItemPosition()
|
||||
order = when (val item = adapter.getItem(fPosition)) {
|
||||
is LibraryHeaderItem -> item.category.order
|
||||
is LibraryItem -> presenter.categories.find { it.id == item.manga.category }?.order
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
return order
|
||||
}
|
||||
|
||||
private fun resetScrollingValues() {
|
||||
startPosX = null
|
||||
startPosY = null
|
||||
@ -448,13 +459,11 @@ class LibraryListController(bundle: Bundle? = null) : LibraryController(bundle),
|
||||
headerPosition, (if (headerPosition == 0) 0 else (-28).dpToPx)
|
||||
+ appbarOffset
|
||||
)
|
||||
val isCurrentController = router?.backstack?.lastOrNull()?.controller() ==
|
||||
this
|
||||
|
||||
val headerItem = adapter.getItem(headerPosition) as? LibraryHeaderItem
|
||||
if (headerItem != null) {
|
||||
customTitleSpinner.category_title.text = headerItem.category.name
|
||||
if (isCurrentController) setTitle()
|
||||
setTitle()
|
||||
}
|
||||
recycler.suppressLayout(false)
|
||||
}
|
||||
@ -590,6 +599,7 @@ class LibraryListController(bundle: Bundle? = null) : LibraryController(bundle),
|
||||
*/
|
||||
override fun onItemLongClick(position: Int) {
|
||||
if (recyclerIsScrolling()) return
|
||||
if (adapter.getItem(position) is LibraryHeaderItem) return
|
||||
createActionModeIfNeeded()
|
||||
when {
|
||||
lastClickPosition == -1 -> setSelection(position)
|
||||
@ -778,8 +788,10 @@ class LibraryListController(bundle: Bundle? = null) : LibraryController(bundle),
|
||||
override fun onSwipeTop(x: Float, y: Float) {
|
||||
val sheetRect = Rect()
|
||||
activity!!.navigationView.getGlobalVisibleRect(sheetRect)
|
||||
if (sheetRect.contains(x.toInt(), y.toInt()))
|
||||
showFiltersBottomSheet()
|
||||
if (sheetRect.contains(x.toInt(), y.toInt())) {
|
||||
if (bottom_sheet.sheetBehavior?.state != BottomSheetBehavior.STATE_EXPANDED)
|
||||
toggleFilters()
|
||||
}
|
||||
}
|
||||
override fun onSwipeLeft(x: Float, y: Float) = goToNextCategory(x)
|
||||
override fun onSwipeRight(x: Float, y: Float) = goToNextCategory(x)
|
||||
|
@ -60,11 +60,9 @@ class FilterBottomSheet @JvmOverloads constructor(context: Context, attrs: Attri
|
||||
|
||||
private val filterItems:MutableList<FilterTagGroup> by lazy {
|
||||
val list = mutableListOf<FilterTagGroup>()
|
||||
list.add(downloaded)
|
||||
list.add(unread)
|
||||
list.add(downloaded)
|
||||
list.add(completed)
|
||||
//if (Injekt.get<DatabaseHelper>().getCategories().executeAsBlocking().isNotEmpty())
|
||||
// list.add(categories)
|
||||
if (Injekt.get<TrackManager>().hasLoggedServices())
|
||||
list.add(tracked)
|
||||
list
|
||||
@ -261,6 +259,8 @@ class FilterBottomSheet @JvmOverloads constructor(context: Context, attrs: Attri
|
||||
if (tracked.isActivated) {
|
||||
filter_layout.addView(trackers)
|
||||
filterItems.add(trackers!!)
|
||||
trackers?.setState(FILTER_TRACKER)
|
||||
reSortViews()
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -293,6 +293,8 @@ class FilterBottomSheet @JvmOverloads constructor(context: Context, attrs: Attri
|
||||
else if (preferences.filterTracked().getOrDefault() != 1 &&
|
||||
trackers?.parent != null) {
|
||||
filter_layout.removeView(trackers)
|
||||
trackers?.reset()
|
||||
FILTER_TRACKER = ""
|
||||
filterItems.remove(trackers!!)
|
||||
}
|
||||
val hasFilters = hasActiveFilters()
|
||||
|
@ -3,6 +3,7 @@ package eu.kanade.tachiyomi.ui.library.filter
|
||||
import android.content.Context
|
||||
import android.graphics.Color
|
||||
import android.util.AttributeSet
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.LinearLayout
|
||||
import com.f2prateek.rx.preferences.Preference
|
||||
@ -76,9 +77,10 @@ class FilterTagGroup@JvmOverloads constructor(context: Context, attrs: Attribute
|
||||
toggleButton(index, false)
|
||||
}
|
||||
|
||||
fun setState(enabled: Boolean) {
|
||||
if (enabled)
|
||||
toggleButton(0, false)
|
||||
fun setState(text: String) {
|
||||
val index = buttons.indexOfFirst { it.text == text && it.visibility == View.VISIBLE }
|
||||
if (index > -1)
|
||||
toggleButton(index, false)
|
||||
}
|
||||
|
||||
fun reset() {
|
||||
|
@ -36,7 +36,6 @@ import com.google.android.material.snackbar.Snackbar
|
||||
import eu.kanade.tachiyomi.BuildConfig
|
||||
import eu.kanade.tachiyomi.Migrations
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.download.DownloadManager
|
||||
import eu.kanade.tachiyomi.data.download.DownloadService
|
||||
import eu.kanade.tachiyomi.data.download.DownloadServiceListener
|
||||
import eu.kanade.tachiyomi.data.notification.NotificationReceiver
|
||||
@ -58,6 +57,7 @@ import eu.kanade.tachiyomi.ui.manga.MangaDetailsController
|
||||
import eu.kanade.tachiyomi.ui.recent_updates.RecentChaptersController
|
||||
import eu.kanade.tachiyomi.ui.recently_read.RecentlyReadController
|
||||
import eu.kanade.tachiyomi.ui.security.SecureActivityDelegate
|
||||
import eu.kanade.tachiyomi.ui.setting.SettingsController
|
||||
import eu.kanade.tachiyomi.ui.setting.SettingsMainController
|
||||
import eu.kanade.tachiyomi.util.system.getResourceColor
|
||||
import eu.kanade.tachiyomi.util.system.launchUI
|
||||
@ -71,8 +71,6 @@ import kotlinx.coroutines.GlobalScope
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
import timber.log.Timber
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
import uy.kohesive.injekt.injectLazy
|
||||
import java.util.Date
|
||||
import java.util.concurrent.TimeUnit
|
||||
@ -170,26 +168,26 @@ open class MainActivity : BaseActivity(), DownloadServiceListener {
|
||||
}
|
||||
}
|
||||
else if (currentRoot.tag()?.toIntOrNull() == id) {
|
||||
if (router.backstackSize == 1) {
|
||||
when (id) {
|
||||
R.id.nav_recents -> {
|
||||
if (router.backstack.size > 1) router.popToRoot()
|
||||
else {
|
||||
val showRecents = preferences.showRecentUpdates().getOrDefault()
|
||||
if (!showRecents) setRoot(RecentChaptersController(), id)
|
||||
else setRoot(RecentlyReadController(), id)
|
||||
preferences.showRecentUpdates().set(!showRecents)
|
||||
updateRecentsIcon()
|
||||
}
|
||||
}
|
||||
R.id.nav_library -> {
|
||||
if (router.backstack.size > 1) router.popToRoot()
|
||||
else {
|
||||
val controller = router.getControllerWithTag(id.toString()) as?
|
||||
LibraryController
|
||||
controller?.showFiltersBottomSheet()
|
||||
val controller =
|
||||
router.getControllerWithTag(id.toString()) as? LibraryController
|
||||
controller?.toggleFilters()
|
||||
}
|
||||
R.id.nav_catalogues -> {
|
||||
val controller =
|
||||
router.getControllerWithTag(id.toString()) as? CatalogueController
|
||||
controller?.toggleExtensions()
|
||||
}
|
||||
}
|
||||
R.id.nav_catalogues -> router.popToRoot()
|
||||
}
|
||||
}
|
||||
true
|
||||
@ -314,9 +312,6 @@ open class MainActivity : BaseActivity(), DownloadServiceListener {
|
||||
}
|
||||
}
|
||||
|
||||
toolbar.navigationIcon = if (router.backstackSize > 1) drawerArrow else searchDrawable
|
||||
(router.backstack.lastOrNull()?.controller() as? BaseController)?.setTitle()
|
||||
|
||||
toolbar.setNavigationOnClickListener {
|
||||
val rootSearchController = router.backstack.lastOrNull()?.controller()
|
||||
if (rootSearchController is RootSearchInterface) {
|
||||
@ -344,6 +339,10 @@ open class MainActivity : BaseActivity(), DownloadServiceListener {
|
||||
|
||||
syncActivityViewWithController(router.backstack.lastOrNull()?.controller())
|
||||
|
||||
toolbar.navigationIcon = if (router.backstackSize > 1) drawerArrow else searchDrawable
|
||||
(router.backstack.lastOrNull()?.controller() as? BaseController)?.setTitle()
|
||||
(router.backstack.lastOrNull()?.controller() as? SettingsController)?.setTitle()
|
||||
|
||||
if (savedInstanceState == null) {
|
||||
// Show changelog if needed
|
||||
if (Migrations.upgrade(preferences)) {
|
||||
|
@ -1,20 +0,0 @@
|
||||
package eu.kanade.tachiyomi.ui.manga
|
||||
|
||||
import android.view.View
|
||||
import eu.kanade.tachiyomi.data.database.models.Manga
|
||||
import eu.kanade.tachiyomi.ui.base.holder.BaseFlexibleViewHolder
|
||||
import eu.kanade.tachiyomi.ui.manga.chapter.ChapterItem
|
||||
import eu.kanade.tachiyomi.ui.manga.chapter.ChaptersAdapter
|
||||
|
||||
abstract class MangaChapterHolder(
|
||||
private val view: View,
|
||||
private val adapter: ChaptersAdapter
|
||||
) : BaseFlexibleViewHolder(view, adapter) {
|
||||
/**
|
||||
* Method called from [ChaptersAdapter.onBindViewHolder]. It updates the data for this
|
||||
* holder with the given manga.
|
||||
*
|
||||
* @param item the manga item to bind.
|
||||
*/
|
||||
abstract fun bind(item: ChapterItem, manga: Manga)
|
||||
}
|
@ -105,7 +105,7 @@ import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
import java.io.File
|
||||
|
||||
open class MangaDetailsController : BaseController,
|
||||
class MangaDetailsController : BaseController,
|
||||
FlexibleAdapter.OnItemClickListener,
|
||||
FlexibleAdapter.OnItemLongClickListener,
|
||||
ActionMode.Callback,
|
||||
@ -126,6 +126,7 @@ open class MangaDetailsController : BaseController,
|
||||
if (manga != null) {
|
||||
source = Injekt.get<SourceManager>().getOrStub(manga.source)
|
||||
}
|
||||
presenter = MangaDetailsPresenter(this, manga!!, source!!)
|
||||
}
|
||||
|
||||
constructor(mangaId: Long) : this(
|
||||
@ -142,15 +143,15 @@ open class MangaDetailsController : BaseController,
|
||||
private var manga: Manga? = null
|
||||
private var source: Source? = null
|
||||
var colorAnimator:ValueAnimator? = null
|
||||
lateinit var presenter:MangaDetailsPresenter
|
||||
val presenter:MangaDetailsPresenter
|
||||
var coverColor:Int? = null
|
||||
var toolbarIsColored = false
|
||||
private var snack: Snackbar? = null
|
||||
val fromCatalogue = args.getBoolean(FROM_CATALOGUE_EXTRA, false)
|
||||
var coverDrawable:Drawable? = null
|
||||
var trackingBottomSheet: TrackingBottomSheet? = null
|
||||
private var trackingBottomSheet: TrackingBottomSheet? = null
|
||||
private var startingDLChapterPos:Int? = null
|
||||
|
||||
var startingDLChapterPos:Int? = null
|
||||
/**
|
||||
* Adapter containing a list of chapters.
|
||||
*/
|
||||
@ -178,7 +179,6 @@ open class MangaDetailsController : BaseController,
|
||||
override fun onViewCreated(view: View) {
|
||||
super.onViewCreated(view)
|
||||
coverColor = null
|
||||
if (!::presenter.isInitialized) presenter = MangaDetailsPresenter(this, manga!!, source!!)
|
||||
|
||||
// Init RecyclerView and adapter
|
||||
adapter = ChaptersAdapter(this, view.context)
|
||||
@ -191,7 +191,7 @@ open class MangaDetailsController : BaseController,
|
||||
DividerItemDecoration.VERTICAL
|
||||
)
|
||||
)
|
||||
recycler.setHasFixedSize(false)
|
||||
recycler.setHasFixedSize(true)
|
||||
adapter?.fastScroller = fast_scroller
|
||||
val attrsArray = intArrayOf(android.R.attr.actionBarSize)
|
||||
val array = view.context.obtainStyledAttributes(attrsArray)
|
||||
@ -208,7 +208,6 @@ open class MangaDetailsController : BaseController,
|
||||
topMargin = appbarHeight + insets.systemWindowInsetTop
|
||||
bottomMargin = insets.systemWindowInsetBottom
|
||||
}
|
||||
// offset the recycler by the fab's inset + some inset on top
|
||||
v.updatePaddingRelative(bottom = insets.systemWindowInsetBottom)
|
||||
}
|
||||
|
||||
@ -306,6 +305,11 @@ open class MangaDetailsController : BaseController,
|
||||
presenter.isLockedFromSearch = SecureActivityDelegate.shouldBeLocked()
|
||||
presenter.headerItem.isLocked = presenter.isLockedFromSearch
|
||||
presenter.fetchChapters()
|
||||
val isCurrentController = router?.backstack?.lastOrNull()?.controller() ==
|
||||
this
|
||||
if (isCurrentController) {
|
||||
setStatusBarAndToolbar()
|
||||
}
|
||||
}
|
||||
|
||||
fun showError(message: String) {
|
||||
@ -325,10 +329,7 @@ open class MangaDetailsController : BaseController,
|
||||
override fun onChangeStarted(handler: ControllerChangeHandler, type: ControllerChangeType) {
|
||||
super.onChangeStarted(handler, type)
|
||||
if (type == ControllerChangeType.PUSH_ENTER || type == ControllerChangeType.POP_ENTER) {
|
||||
setStatusBar()
|
||||
(activity as MainActivity).appbar.setBackgroundColor(Color.TRANSPARENT)
|
||||
(activity as MainActivity).toolbar.setBackgroundColor(activity?.window?.statusBarColor
|
||||
?: Color.TRANSPARENT)
|
||||
setStatusBarAndToolbar()
|
||||
}
|
||||
else if (type == ControllerChangeType.PUSH_EXIT || type == ControllerChangeType.POP_EXIT) {
|
||||
if (router.backstack.lastOrNull()?.controller() is DialogController)
|
||||
@ -351,15 +352,9 @@ open class MangaDetailsController : BaseController,
|
||||
}
|
||||
|
||||
fun updateHeader() {
|
||||
if (presenter.chapters.isEmpty()) {
|
||||
adapter?.updateDataSet(listOf(presenter.headerItem))
|
||||
}
|
||||
else {
|
||||
swipe_refresh?.isRefreshing = presenter.isLoading
|
||||
adapter?.updateDataSet(
|
||||
listOf(ChapterItem(presenter.headerItem, presenter.manga)) + presenter.chapters
|
||||
)
|
||||
}
|
||||
adapter?.setChapters(presenter.chapters)
|
||||
addMangaHeader()
|
||||
activity?.invalidateOptionsMenu()
|
||||
}
|
||||
|
||||
@ -369,15 +364,15 @@ open class MangaDetailsController : BaseController,
|
||||
launchUI { swipe_refresh?.isRefreshing = true }
|
||||
presenter.fetchChaptersFromSource()
|
||||
}
|
||||
adapter?.updateDataSet(listOf(presenter.headerItem) + chapters)
|
||||
adapter?.setChapters(chapters)
|
||||
addMangaHeader()
|
||||
activity?.invalidateOptionsMenu()
|
||||
}
|
||||
|
||||
fun refreshAdapter() = adapter?.notifyDataSetChanged()
|
||||
|
||||
override fun onItemClick(view: View?, position: Int): Boolean {
|
||||
val chapter = adapter?.getItem(position)?.chapter ?: return false
|
||||
if (chapter.isHeader) return false
|
||||
val chapter = (adapter?.getItem(position) as? ChapterItem)?.chapter ?: return false
|
||||
if (actionMode != null) {
|
||||
if (startingDLChapterPos == null) {
|
||||
adapter?.addSelection(position)
|
||||
@ -410,7 +405,7 @@ open class MangaDetailsController : BaseController,
|
||||
|
||||
override fun onItemLongClick(position: Int) {
|
||||
val adapter = adapter ?: return
|
||||
val item = adapter.getItem(position) ?: return
|
||||
val item = (adapter.getItem(position) as? ChapterItem) ?: return
|
||||
val itemView = getHolder(item)?.itemView ?: return
|
||||
val popup = PopupMenu(itemView.context, itemView, Gravity.END)
|
||||
|
||||
@ -709,7 +704,7 @@ open class MangaDetailsController : BaseController,
|
||||
}
|
||||
|
||||
override fun startDownloadRange(position: Int) {
|
||||
createActionModeIfNeeded()
|
||||
if (actionMode == null) createActionModeIfNeeded()
|
||||
onItemClick(null, position)
|
||||
}
|
||||
|
||||
@ -743,8 +738,11 @@ open class MangaDetailsController : BaseController,
|
||||
|
||||
override fun downloadChapter(position: Int) {
|
||||
val view = view ?: return
|
||||
val chapter = adapter?.getItem(position) ?: return
|
||||
if (chapter.isHeader) return
|
||||
val chapter = (adapter?.getItem(position) as? ChapterItem) ?: return
|
||||
if (actionMode != null) {
|
||||
onItemClick(null, position)
|
||||
return
|
||||
}
|
||||
if (chapter.status != Download.NOT_DOWNLOADED && chapter.status != Download.ERROR) {
|
||||
presenter.deleteChapters(listOf(chapter))
|
||||
}
|
||||
@ -970,19 +968,30 @@ open class MangaDetailsController : BaseController,
|
||||
|
||||
override fun onDestroyActionMode(mode: ActionMode?) {
|
||||
actionMode = null
|
||||
setStatusBar()
|
||||
setStatusBarAndToolbar()
|
||||
startingDLChapterPos = null
|
||||
adapter?.mode = SelectableAdapter.Mode.IDLE
|
||||
adapter?.clearSelection()
|
||||
return
|
||||
}
|
||||
|
||||
private fun setStatusBar() {
|
||||
/**
|
||||
* Called to set the last used catalogue at the top of the view.
|
||||
*/
|
||||
private fun addMangaHeader() {
|
||||
adapter?.removeAllScrollableHeaders()
|
||||
adapter?.addScrollableHeader(presenter.headerItem)
|
||||
}
|
||||
|
||||
private fun setStatusBarAndToolbar() {
|
||||
activity?.window?.statusBarColor = if (toolbarIsColored) {
|
||||
val translucentColor = ColorUtils.setAlphaComponent(coverColor ?: Color.TRANSPARENT, 175)
|
||||
(activity as MainActivity).toolbar.setBackgroundColor(translucentColor)
|
||||
translucentColor
|
||||
} else Color.TRANSPARENT
|
||||
(activity as MainActivity).appbar.setBackgroundColor(Color.TRANSPARENT)
|
||||
(activity as MainActivity).toolbar.setBackgroundColor(activity?.window?.statusBarColor
|
||||
?: Color.TRANSPARENT)
|
||||
}
|
||||
|
||||
override fun onPrepareActionMode(mode: ActionMode?, menu: Menu?): Boolean {
|
||||
|
@ -69,7 +69,7 @@ class MangaDetailsPresenter(private val controller: MangaDetailsController,
|
||||
var chapters:List<ChapterItem> = emptyList()
|
||||
private set
|
||||
|
||||
var headerItem = ChapterItem(Chapter.createHeader(controller.fromCatalogue), manga)
|
||||
var headerItem = MangaHeaderItem(manga, controller.fromCatalogue)
|
||||
|
||||
fun onCreate() {
|
||||
isLockedFromSearch = SecureActivityDelegate.shouldBeLocked()
|
||||
|
@ -16,7 +16,7 @@ import eu.kanade.tachiyomi.data.database.models.Manga
|
||||
import eu.kanade.tachiyomi.data.database.models.MangaImpl
|
||||
import eu.kanade.tachiyomi.data.glide.GlideApp
|
||||
import eu.kanade.tachiyomi.source.model.SManga
|
||||
import eu.kanade.tachiyomi.ui.manga.chapter.ChapterItem
|
||||
import eu.kanade.tachiyomi.ui.base.holder.BaseFlexibleViewHolder
|
||||
import eu.kanade.tachiyomi.ui.manga.chapter.ChaptersAdapter
|
||||
import eu.kanade.tachiyomi.util.system.getResourceColor
|
||||
import eu.kanade.tachiyomi.util.view.gone
|
||||
@ -30,7 +30,7 @@ class MangaHeaderHolder(
|
||||
private val view: View,
|
||||
private val adapter: ChaptersAdapter,
|
||||
startExpanded: Boolean
|
||||
) : MangaChapterHolder(view, adapter) {
|
||||
) : BaseFlexibleViewHolder(view, adapter) {
|
||||
|
||||
init {
|
||||
start_reading_button.setOnClickListener { adapter.coverListener.readNextChapter() }
|
||||
@ -84,8 +84,8 @@ class MangaHeaderHolder(
|
||||
}
|
||||
|
||||
@SuppressLint("SetTextI18n")
|
||||
override fun bind(item: ChapterItem, manga: Manga) {
|
||||
val presenter = adapter.coverListener?.mangaPresenter() ?: return
|
||||
fun bind(item: MangaHeaderItem, manga: Manga) {
|
||||
val presenter = adapter.coverListener.mangaPresenter()
|
||||
manga_full_title.text = manga.currentTitle()
|
||||
|
||||
if (manga.currentGenres().isNullOrBlank().not())
|
||||
|
@ -0,0 +1,44 @@
|
||||
package eu.kanade.tachiyomi.ui.manga
|
||||
|
||||
import android.view.View
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import eu.davidea.flexibleadapter.FlexibleAdapter
|
||||
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.ui.manga.chapter.ChaptersAdapter
|
||||
|
||||
class MangaHeaderItem(val manga: Manga, private val startExpanded: Boolean):
|
||||
AbstractFlexibleItem<MangaHeaderHolder>(){
|
||||
|
||||
var isLocked = false
|
||||
|
||||
override fun getLayoutRes(): Int {
|
||||
return R.layout.manga_header_item
|
||||
}
|
||||
|
||||
override fun isSelectable(): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun createViewHolder(view: View, adapter: FlexibleAdapter<IFlexible<RecyclerView.ViewHolder>>): MangaHeaderHolder {
|
||||
return MangaHeaderHolder(view, adapter as ChaptersAdapter, startExpanded)
|
||||
}
|
||||
|
||||
override fun bindViewHolder(adapter: FlexibleAdapter<IFlexible<RecyclerView.ViewHolder>>,
|
||||
holder: MangaHeaderHolder,
|
||||
position: Int,
|
||||
payloads: MutableList<Any?>?) {
|
||||
holder.bind(this, manga)
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
return (this === other)
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
return manga.id!!.hashCode()
|
||||
}
|
||||
|
||||
}
|
@ -10,11 +10,9 @@ import eu.kanade.tachiyomi.data.database.models.Chapter
|
||||
import eu.kanade.tachiyomi.data.database.models.Manga
|
||||
import eu.kanade.tachiyomi.data.download.model.Download
|
||||
import eu.kanade.tachiyomi.source.model.Page
|
||||
import eu.kanade.tachiyomi.ui.manga.MangaChapterHolder
|
||||
import eu.kanade.tachiyomi.ui.manga.MangaHeaderHolder
|
||||
|
||||
class ChapterItem(val chapter: Chapter, val manga: Manga) :
|
||||
AbstractFlexibleItem<MangaChapterHolder>(),
|
||||
AbstractFlexibleItem<ChapterMatHolder>(),
|
||||
Chapter by chapter {
|
||||
|
||||
private var _status: Int = 0
|
||||
@ -36,22 +34,19 @@ class ChapterItem(val chapter: Chapter, val manga: Manga) :
|
||||
get() = status == Download.DOWNLOADED
|
||||
|
||||
override fun getLayoutRes(): Int {
|
||||
return if (chapter.isHeader) R.layout.manga_header_item
|
||||
else R.layout.chapters_mat_item
|
||||
return R.layout.chapters_mat_item
|
||||
}
|
||||
|
||||
override fun isSelectable(): Boolean {
|
||||
return !chapter.isHeader
|
||||
return true
|
||||
}
|
||||
|
||||
override fun createViewHolder(view: View, adapter: FlexibleAdapter<IFlexible<RecyclerView.ViewHolder>>): MangaChapterHolder {
|
||||
return if (chapter.isHeader) MangaHeaderHolder(view, adapter as ChaptersAdapter,
|
||||
startExpanded = chapter.read)
|
||||
else ChapterMatHolder(view, adapter as ChaptersAdapter)
|
||||
override fun createViewHolder(view: View, adapter: FlexibleAdapter<IFlexible<RecyclerView.ViewHolder>>): ChapterMatHolder {
|
||||
return ChapterMatHolder(view, adapter as ChaptersAdapter)
|
||||
}
|
||||
|
||||
override fun bindViewHolder(adapter: FlexibleAdapter<IFlexible<RecyclerView.ViewHolder>>,
|
||||
holder: MangaChapterHolder,
|
||||
holder: ChapterMatHolder,
|
||||
position: Int,
|
||||
payloads: MutableList<Any?>?) {
|
||||
holder.bind(this, manga)
|
||||
|
@ -6,10 +6,10 @@ import androidx.appcompat.widget.PopupMenu
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.database.models.Manga
|
||||
import eu.kanade.tachiyomi.data.download.model.Download
|
||||
import eu.kanade.tachiyomi.ui.manga.MangaChapterHolder
|
||||
import eu.kanade.tachiyomi.source.LocalSource
|
||||
import eu.kanade.tachiyomi.ui.base.holder.BaseFlexibleViewHolder
|
||||
import eu.kanade.tachiyomi.util.view.gone
|
||||
import eu.kanade.tachiyomi.util.view.invisible
|
||||
import eu.kanade.tachiyomi.util.view.visible
|
||||
import eu.kanade.tachiyomi.util.view.visibleIf
|
||||
import kotlinx.android.synthetic.main.chapters_mat_item.*
|
||||
import kotlinx.android.synthetic.main.download_button.*
|
||||
import java.util.Date
|
||||
@ -17,8 +17,9 @@ import java.util.Date
|
||||
class ChapterMatHolder(
|
||||
private val view: View,
|
||||
private val adapter: ChaptersAdapter
|
||||
) : MangaChapterHolder(view, adapter) {
|
||||
) : BaseFlexibleViewHolder(view, adapter) {
|
||||
|
||||
private var localSource = false
|
||||
init {
|
||||
download_button.setOnClickListener { downloadOrRemoveMenu() }
|
||||
download_button.setOnLongClickListener {
|
||||
@ -28,7 +29,7 @@ class ChapterMatHolder(
|
||||
}
|
||||
|
||||
private fun downloadOrRemoveMenu() {
|
||||
val chapter = adapter.getItem(adapterPosition) ?: return
|
||||
val chapter = adapter.getItem(adapterPosition) as? ChapterItem ?: return
|
||||
if (chapter.status == Download.NOT_DOWNLOADED || chapter.status == Download.ERROR) {
|
||||
adapter.coverListener.downloadChapter(adapterPosition)
|
||||
} else {
|
||||
@ -56,7 +57,7 @@ class ChapterMatHolder(
|
||||
}
|
||||
}
|
||||
|
||||
override fun bind(item: ChapterItem, manga: Manga) {
|
||||
fun bind(item: ChapterItem, manga: Manga) {
|
||||
val chapter = item.chapter
|
||||
val isLocked = item.isLocked
|
||||
chapter_title.text = when (manga.displayMode) {
|
||||
@ -67,12 +68,10 @@ class ChapterMatHolder(
|
||||
else -> chapter.name
|
||||
}
|
||||
|
||||
//chapter_menu.visible()
|
||||
// Set the correct drawable for dropdown and update the tint to match theme.
|
||||
//chapter_menu.setVectorCompat(R.drawable.ic_more_vert_black_24dp, view.context
|
||||
// .getResourceColor(R.attr.icon_color))
|
||||
localSource = manga.source == LocalSource.ID
|
||||
download_button.visibleIf(!localSource)
|
||||
|
||||
if (isLocked) download_button.invisible()
|
||||
if (isLocked) download_button.gone()
|
||||
|
||||
|
||||
// Set correct text color
|
||||
@ -110,7 +109,7 @@ class ChapterMatHolder(
|
||||
gone()
|
||||
return
|
||||
}
|
||||
visible()
|
||||
download_button.visibleIf(!localSource)
|
||||
setDownloadStatus(status, progress)
|
||||
}
|
||||
}
|
||||
|
@ -4,22 +4,21 @@ import android.content.Context
|
||||
import android.view.View
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import eu.davidea.flexibleadapter.FlexibleAdapter
|
||||
import eu.davidea.flexibleadapter.items.IFlexible
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||
import eu.kanade.tachiyomi.data.preference.getOrDefault
|
||||
import eu.kanade.tachiyomi.ui.manga.MangaDetailsController
|
||||
import eu.kanade.tachiyomi.ui.manga.MangaDetailsPresenter
|
||||
import eu.kanade.tachiyomi.ui.security.SecureActivityDelegate
|
||||
import eu.kanade.tachiyomi.util.system.getResourceColor
|
||||
import uy.kohesive.injekt.injectLazy
|
||||
import java.text.DateFormat
|
||||
import java.text.DecimalFormat
|
||||
import java.text.DecimalFormatSymbols
|
||||
|
||||
class ChaptersAdapter(
|
||||
val controller: MangaDetailsController,
|
||||
context: Context
|
||||
) : FlexibleAdapter<ChapterItem>(null, controller, true) {
|
||||
) : FlexibleAdapter<IFlexible<*>>(null, controller, true) {
|
||||
|
||||
val preferences: PreferencesHelper by injectLazy()
|
||||
|
||||
@ -36,9 +35,7 @@ class ChaptersAdapter(
|
||||
val decimalFormat = DecimalFormat("#.###", DecimalFormatSymbols()
|
||||
.apply { decimalSeparator = '.' })
|
||||
|
||||
val dateFormat: DateFormat = preferences.dateFormat().getOrDefault()
|
||||
|
||||
override fun updateDataSet(items: List<ChapterItem>?) {
|
||||
fun setChapters(items: List<ChapterItem>?) {
|
||||
this.items = items ?: emptyList()
|
||||
super.updateDataSet(items)
|
||||
}
|
||||
|
@ -156,6 +156,5 @@
|
||||
tools:text="Sample artist" />
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</FrameLayout>
|
@ -30,7 +30,7 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="2dp"
|
||||
android:clipToPadding="false"
|
||||
android:paddingStart="20dp"
|
||||
android:paddingStart="10dp"
|
||||
android:paddingTop="8dp"
|
||||
android:paddingEnd="20dp"
|
||||
android:paddingBottom="6dp"
|
||||
@ -63,7 +63,7 @@
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="23dp"
|
||||
android:layout_marginStart="10dp"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<com.google.android.material.checkbox.MaterialCheckBox
|
||||
|
@ -18,7 +18,7 @@
|
||||
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
android:id="@+id/download_text"
|
||||
style="@style/TextAppearance.Regular.Caption.Light"
|
||||
style="@style/TextAppearance.MaterialComponents.Caption"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@color/pale_red"
|
||||
@ -48,7 +48,7 @@
|
||||
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
android:id="@+id/unread_text"
|
||||
style="@style/TextAppearance.Regular.Caption.Light"
|
||||
style="@style/TextAppearance.MaterialComponents.Caption"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@color/colorAccent"
|
||||
|
@ -551,8 +551,8 @@
|
||||
<string name="manga_download">Download</string>
|
||||
<string name="custom_download">Download custom amount</string>
|
||||
<string name="download_1">Next chapter</string>
|
||||
<string name="download_first">First unread chapter</string>
|
||||
<string name="download_5">Next 5 chapters</string>
|
||||
<string name="download_first">Next unread chapter</string>
|
||||
<string name="download_5">Next 5 unread</string>
|
||||
<string name="download_10">Next 10 chapters</string>
|
||||
<string name="download_custom">Custom range</string>
|
||||
<string name="download_all">All chapters</string>
|
||||
|
Loading…
Reference in New Issue
Block a user