mirror of
https://github.com/tachiyomiorg/tachiyomi.git
synced 2024-11-09 05:25:08 +01:00
UI Revamp of Recents
*Now Endless scrolling in ungrouped/history/updates *Removed going to history/updates controller in grouped (will later be removed entirely) *Always showing a header to switch modes, instead of using a filter button (which will later be replaced
This commit is contained in:
parent
2d10680fd9
commit
0c66d3b8b6
@ -283,7 +283,7 @@ class PreferencesHelper(val context: Context) {
|
||||
|
||||
fun extensionUpdatesCount() = rxPrefs.getInteger("ext_updates_count", 0)
|
||||
|
||||
fun recentsViewType() = rxPrefs.getInteger("recents_view_type", 0)
|
||||
fun recentsViewType() = flowPrefs.getInt("recents_view_type", 0)
|
||||
|
||||
fun lastExtCheck() = rxPrefs.getLong("last_ext_check", 0)
|
||||
|
||||
|
@ -52,9 +52,8 @@ import eu.kanade.tachiyomi.ui.base.controller.BaseController
|
||||
import eu.kanade.tachiyomi.ui.base.controller.DialogController
|
||||
import eu.kanade.tachiyomi.ui.library.LibraryController
|
||||
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.recents.RecentsController
|
||||
import eu.kanade.tachiyomi.ui.recents.RecentsPresenter
|
||||
import eu.kanade.tachiyomi.ui.security.SecureActivityDelegate
|
||||
import eu.kanade.tachiyomi.ui.setting.AboutController
|
||||
import eu.kanade.tachiyomi.ui.setting.SettingsController
|
||||
@ -473,11 +472,11 @@ open class MainActivity : BaseActivity<MainActivityBinding>(), DownloadServiceLi
|
||||
SHORTCUT_LIBRARY -> binding.bottomNav.selectedItemId = R.id.nav_library
|
||||
SHORTCUT_RECENTLY_UPDATED, SHORTCUT_RECENTLY_READ -> {
|
||||
binding.bottomNav.selectedItemId = R.id.nav_recents
|
||||
val controller: Controller = when (intent.action) {
|
||||
SHORTCUT_RECENTLY_UPDATED -> RecentChaptersController()
|
||||
else -> RecentlyReadController()
|
||||
val viewType = when (intent.action) {
|
||||
SHORTCUT_RECENTLY_UPDATED -> RecentsPresenter.VIEW_TYPE_ONLY_UPDATES
|
||||
else -> RecentsPresenter.VIEW_TYPE_ONLY_HISTORY
|
||||
}
|
||||
router.pushController(controller.withFadeTransaction())
|
||||
router.pushController(RecentsController(viewType).withFadeTransaction())
|
||||
}
|
||||
SHORTCUT_BROWSE -> binding.bottomNav.selectedItemId = R.id.nav_browse
|
||||
SHORTCUT_EXTENSIONS -> {
|
||||
|
@ -29,8 +29,8 @@ class RecentMangaAdapter(val delegate: RecentsInterface) :
|
||||
fun onCoverClick(position: Int)
|
||||
fun markAsRead(position: Int)
|
||||
fun isSearching(): Boolean
|
||||
fun showHistory()
|
||||
fun showUpdates()
|
||||
fun setViewType(viewType: Int)
|
||||
fun getViewType(): Int
|
||||
}
|
||||
|
||||
override fun onItemSwiped(position: Int, direction: Int) {
|
||||
|
@ -2,6 +2,7 @@ package eu.kanade.tachiyomi.ui.recents
|
||||
|
||||
import android.view.View
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.google.android.material.tabs.TabLayout
|
||||
import eu.davidea.flexibleadapter.FlexibleAdapter
|
||||
import eu.davidea.flexibleadapter.items.AbstractHeaderItem
|
||||
import eu.davidea.flexibleadapter.items.IFlexible
|
||||
@ -62,8 +63,19 @@ class RecentMangaHeaderItem(val recentsType: Int) :
|
||||
|
||||
private val binding = RecentsHeaderItemBinding.bind(view)
|
||||
init {
|
||||
binding.actionHistory.setOnClickListener { adapter.delegate.showHistory() }
|
||||
binding.actionUpdate.setOnClickListener { adapter.delegate.showUpdates() }
|
||||
listOf(R.string.grouped, R.string.all, R.string.history, R.string.updates).forEach { resId ->
|
||||
binding.recentsTabs.addTab(binding.recentsTabs.newTab().setText(resId))
|
||||
}
|
||||
val selectedTab = (this@Holder.bindingAdapter as? RecentMangaAdapter)?.delegate?.getViewType() ?: 0
|
||||
binding.recentsTabs.selectTab(binding.recentsTabs.getTabAt(selectedTab))
|
||||
binding.recentsTabs.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener {
|
||||
override fun onTabSelected(tab: TabLayout.Tab?) {
|
||||
(this@Holder.bindingAdapter as? RecentMangaAdapter)?.delegate?.setViewType(tab?.position ?: 0)
|
||||
}
|
||||
|
||||
override fun onTabUnselected(tab: TabLayout.Tab?) { }
|
||||
override fun onTabReselected(tab: TabLayout.Tab?) { }
|
||||
})
|
||||
}
|
||||
|
||||
fun bind(recentsType: Int) {
|
||||
@ -75,8 +87,9 @@ class RecentMangaHeaderItem(val recentsType: Int) :
|
||||
else -> R.string.continue_reading
|
||||
}
|
||||
)
|
||||
binding.actionHistory.visibleIf(recentsType == -1)
|
||||
binding.actionUpdate.visibleIf(recentsType == -1)
|
||||
binding.recentsTabs.visibleIf(recentsType == -1)
|
||||
val selectedTab = (this@Holder.bindingAdapter as? RecentMangaAdapter)?.delegate?.getViewType() ?: 0
|
||||
binding.recentsTabs.selectTab(binding.recentsTabs.getTabAt(selectedTab))
|
||||
binding.title.visibleIf(recentsType != -1)
|
||||
}
|
||||
}
|
||||
|
@ -14,7 +14,6 @@ import androidx.appcompat.widget.SearchView
|
||||
import androidx.recyclerview.widget.ItemTouchHelper
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.bluelinelabs.conductor.Controller
|
||||
import com.bluelinelabs.conductor.ControllerChangeHandler
|
||||
import com.bluelinelabs.conductor.ControllerChangeType
|
||||
import com.google.android.material.bottomsheet.BottomSheetBehavior
|
||||
@ -22,6 +21,7 @@ import com.google.android.material.snackbar.BaseTransientBottomBar
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import eu.davidea.flexibleadapter.FlexibleAdapter
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.backup.BackupRestoreService
|
||||
import eu.kanade.tachiyomi.data.database.models.History
|
||||
import eu.kanade.tachiyomi.data.database.models.Manga
|
||||
import eu.kanade.tachiyomi.data.download.DownloadService
|
||||
@ -34,9 +34,8 @@ import eu.kanade.tachiyomi.ui.main.MainActivity
|
||||
import eu.kanade.tachiyomi.ui.main.RootSearchInterface
|
||||
import eu.kanade.tachiyomi.ui.manga.MangaDetailsController
|
||||
import eu.kanade.tachiyomi.ui.reader.ReaderActivity
|
||||
import eu.kanade.tachiyomi.ui.recent_updates.RecentChaptersController
|
||||
import eu.kanade.tachiyomi.ui.recently_read.RecentlyReadController
|
||||
import eu.kanade.tachiyomi.ui.recently_read.RemoveHistoryDialog
|
||||
import eu.kanade.tachiyomi.ui.source.browse.ProgressItem
|
||||
import eu.kanade.tachiyomi.util.system.dpToPx
|
||||
import eu.kanade.tachiyomi.util.system.spToPx
|
||||
import eu.kanade.tachiyomi.util.system.toast
|
||||
@ -65,6 +64,7 @@ class RecentsController(bundle: Bundle? = null) :
|
||||
FlexibleAdapter.OnItemClickListener,
|
||||
FlexibleAdapter.OnItemLongClickListener,
|
||||
FlexibleAdapter.OnItemMoveListener,
|
||||
FlexibleAdapter.EndlessScrollListener,
|
||||
RootSearchInterface,
|
||||
BottomSheetController,
|
||||
RemoveHistoryDialog.Listener {
|
||||
@ -74,11 +74,16 @@ class RecentsController(bundle: Bundle? = null) :
|
||||
retainViewMode = RetainViewMode.RETAIN_DETACH
|
||||
}
|
||||
|
||||
constructor(viewType: Int) : this() {
|
||||
presenter.toggleGroupRecents(viewType, false)
|
||||
}
|
||||
|
||||
/**
|
||||
* Adapter containing the recent manga.
|
||||
*/
|
||||
private var adapter = RecentMangaAdapter(this)
|
||||
|
||||
private var progressItem: ProgressItem? = null
|
||||
private var presenter = RecentsPresenter(this)
|
||||
private var snack: Snackbar? = null
|
||||
private var lastChapterId: Long? = null
|
||||
@ -113,6 +118,7 @@ class RecentsController(bundle: Bundle? = null) :
|
||||
adapter.itemTouchHelperCallback.setSwipeFlags(
|
||||
ItemTouchHelper.LEFT
|
||||
)
|
||||
resetProgressItem()
|
||||
val attrsArray = intArrayOf(android.R.attr.actionBarSize)
|
||||
val array = view.context.obtainStyledAttributes(attrsArray)
|
||||
val appBarHeight = array.getDimensionPixelSize(0, 0)
|
||||
@ -257,6 +263,10 @@ class RecentsController(bundle: Bundle? = null) :
|
||||
binding.downloadBottomSheet.dlBottomSheet.dismiss()
|
||||
return true
|
||||
}
|
||||
if (presenter.preferences.recentsViewType().get() != presenter.viewType) {
|
||||
presenter.toggleGroupRecents(RecentsPresenter.VIEW_TYPE_GROUP_ALL, false)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
@ -284,14 +294,29 @@ class RecentsController(bundle: Bundle? = null) :
|
||||
|
||||
fun refresh() = presenter.getRecents()
|
||||
|
||||
fun showLists(recents: List<RecentMangaItem>) {
|
||||
fun showLists(recents: List<RecentMangaItem>, hasNewItems: Boolean, shouldMoveToTop: Boolean = false) {
|
||||
if (view == null) return
|
||||
binding.swipeRefresh.isRefreshing = LibraryUpdateService.isRunning()
|
||||
adapter.updateItems(recents)
|
||||
adapter.removeAllScrollableHeaders()
|
||||
if (presenter.viewType > 0) {
|
||||
adapter.headerItems.forEach {
|
||||
if (it != presenter.generalHeader) {
|
||||
adapter.removeScrollableHeader(it)
|
||||
}
|
||||
}
|
||||
if (!adapter.headerItems.any { it === presenter.generalHeader }) {
|
||||
adapter.addScrollableHeader(presenter.generalHeader)
|
||||
}
|
||||
adapter.onLoadMoreComplete(null)
|
||||
if (!hasNewItems || presenter.viewType == RecentsPresenter.VIEW_TYPE_GROUP_ALL || presenter.query.isNotEmpty() ||
|
||||
recents.isEmpty()
|
||||
) {
|
||||
onAddPageError()
|
||||
} else if (hasNewItems && presenter.viewType != RecentsPresenter.VIEW_TYPE_GROUP_ALL && presenter.query.isEmpty()) {
|
||||
resetProgressItem()
|
||||
}
|
||||
if (shouldMoveToTop) {
|
||||
binding.recycler.scrollToPosition(0)
|
||||
}
|
||||
if (lastChapterId != null) {
|
||||
refreshItem(lastChapterId ?: 0L)
|
||||
lastChapterId = null
|
||||
@ -339,20 +364,32 @@ class RecentsController(bundle: Bundle? = null) :
|
||||
router.pushController(MangaDetailsController(manga).withFadeTransaction())
|
||||
}
|
||||
|
||||
override fun showHistory() = router.pushController(RecentlyReadController().withFadeTransaction())
|
||||
override fun showUpdates() = router.pushController(RecentChaptersController().withFadeTransaction())
|
||||
fun showHistory() {
|
||||
presenter.toggleGroupRecents(RecentsPresenter.VIEW_TYPE_ONLY_HISTORY, false)
|
||||
}
|
||||
|
||||
fun showUpdates() {
|
||||
presenter.toggleGroupRecents(RecentsPresenter.VIEW_TYPE_ONLY_UPDATES, false)
|
||||
}
|
||||
|
||||
override fun setViewType(viewType: Int) {
|
||||
if (viewType != presenter.viewType) {
|
||||
presenter.toggleGroupRecents(viewType)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getViewType() = presenter.viewType
|
||||
|
||||
override fun onItemClick(view: View?, position: Int): Boolean {
|
||||
val item = adapter.getItem(position) ?: return false
|
||||
if (item is RecentMangaItem) {
|
||||
if (item.mch.manga.id == null) {
|
||||
val headerItem = adapter.getHeaderOf(item) as? RecentMangaHeaderItem
|
||||
val controller: Controller = when (headerItem?.recentsType) {
|
||||
RecentMangaHeaderItem.NEW_CHAPTERS -> RecentChaptersController()
|
||||
RecentMangaHeaderItem.CONTINUE_READING -> RecentlyReadController()
|
||||
when (headerItem?.recentsType) {
|
||||
RecentMangaHeaderItem.NEW_CHAPTERS -> showUpdates()
|
||||
RecentMangaHeaderItem.CONTINUE_READING -> showHistory()
|
||||
else -> return false
|
||||
}
|
||||
router.pushController(controller.withFadeTransaction())
|
||||
} else {
|
||||
val activity = activity ?: return false
|
||||
val intent = ReaderActivity.newIntent(activity, item.mch.manga, item.chapter)
|
||||
@ -440,6 +477,7 @@ class RecentsController(bundle: Bundle? = null) :
|
||||
setOnQueryTextChangeListener(searchView) {
|
||||
if (presenter.query != it) {
|
||||
presenter.query = it ?: return@setOnQueryTextChangeListener false
|
||||
resetProgressItem()
|
||||
refresh()
|
||||
}
|
||||
true
|
||||
@ -515,4 +553,31 @@ class RecentsController(bundle: Bundle? = null) :
|
||||
}
|
||||
return super.onOptionsItemSelected(item)
|
||||
}
|
||||
|
||||
override fun noMoreLoad(newItemsSize: Int) {}
|
||||
|
||||
override fun onLoadMore(lastPosition: Int, currentPage: Int) {
|
||||
val view = view ?: return
|
||||
if (presenter.finished || BackupRestoreService.isRunning(view.context.applicationContext)) {
|
||||
onAddPageError()
|
||||
return
|
||||
}
|
||||
presenter.requestNext()
|
||||
}
|
||||
|
||||
private fun onAddPageError() {
|
||||
adapter.onLoadMoreComplete(null)
|
||||
adapter.endlessTargetCount = 0
|
||||
adapter.setEndlessScrollListener(null, progressItem!!)
|
||||
adapter.setEndlessProgressItem(null)
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a new progress item and reenables the scroll listener.
|
||||
*/
|
||||
private fun resetProgressItem() {
|
||||
progressItem = ProgressItem()
|
||||
adapter.endlessTargetCount = 0
|
||||
adapter.setEndlessScrollListener(this, progressItem!!)
|
||||
}
|
||||
}
|
||||
|
@ -12,7 +12,6 @@ import eu.kanade.tachiyomi.data.download.model.DownloadQueue
|
||||
import eu.kanade.tachiyomi.data.library.LibraryServiceListener
|
||||
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.source.SourceManager
|
||||
import eu.kanade.tachiyomi.ui.recent_updates.DateItem
|
||||
import eu.kanade.tachiyomi.util.system.executeOnIO
|
||||
@ -42,6 +41,10 @@ class RecentsPresenter(
|
||||
var recentItems = listOf<RecentMangaItem>()
|
||||
private set
|
||||
var query = ""
|
||||
set(value) {
|
||||
field = value
|
||||
page = 0
|
||||
}
|
||||
private val newAdditionsHeader = RecentMangaHeaderItem(RecentMangaHeaderItem.NEWLY_ADDED)
|
||||
private val newChaptersHeader = RecentMangaHeaderItem(RecentMangaHeaderItem.NEW_CHAPTERS)
|
||||
val generalHeader = RecentMangaHeaderItem(-1)
|
||||
@ -49,7 +52,17 @@ class RecentsPresenter(
|
||||
RecentMangaHeaderItem
|
||||
.CONTINUE_READING
|
||||
)
|
||||
var viewType: Int = preferences.recentsViewType().getOrDefault()
|
||||
var finished = false
|
||||
var shouldMoveToTop = false
|
||||
var viewType: Int = preferences.recentsViewType().get()
|
||||
private var page = 0
|
||||
set(value) {
|
||||
field = value
|
||||
if (value == 0) {
|
||||
finished = false
|
||||
shouldMoveToTop = true
|
||||
}
|
||||
}
|
||||
|
||||
fun onCreate() {
|
||||
downloadManager.addListener(this)
|
||||
@ -63,25 +76,44 @@ class RecentsPresenter(
|
||||
getRecents()
|
||||
}
|
||||
|
||||
fun getRecents() {
|
||||
fun getRecents(updatePageCount: Boolean = false, retryCount: Int = 0, itemCount: Int = 0) {
|
||||
val oldQuery = query
|
||||
scope.launch {
|
||||
val isUngrouped = viewType > 0 && query.isEmpty()
|
||||
// groupRecents && query.isEmpty()
|
||||
if (retryCount > 20) {
|
||||
finished = true
|
||||
setDownloadedChapters(recentItems)
|
||||
withContext(Dispatchers.Main) { controller.showLists(recentItems, false) }
|
||||
}
|
||||
|
||||
if (updatePageCount) {
|
||||
page++
|
||||
}
|
||||
|
||||
val isUngrouped = viewType > VIEW_TYPE_GROUP_ALL && query.isEmpty()
|
||||
val cal = Calendar.getInstance().apply {
|
||||
time = Date()
|
||||
when {
|
||||
query.isNotEmpty() -> add(Calendar.YEAR, -50)
|
||||
isUngrouped -> add(Calendar.MONTH, -1)
|
||||
isUngrouped -> add(Calendar.MONTH, -(page + 1))
|
||||
else -> add(Calendar.MONTH, -1)
|
||||
}
|
||||
}
|
||||
|
||||
val startCal = Calendar.getInstance().apply {
|
||||
time = Date()
|
||||
when {
|
||||
query.isNotEmpty() -> {}
|
||||
isUngrouped && !updatePageCount -> {}
|
||||
isUngrouped -> add(Calendar.MONTH, -page)
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
|
||||
val calWeek = Calendar.getInstance().apply {
|
||||
time = Date()
|
||||
when {
|
||||
query.isNotEmpty() -> add(Calendar.YEAR, -50)
|
||||
isUngrouped -> add(Calendar.MONTH, -1)
|
||||
isUngrouped -> add(Calendar.MONTH, -(page + 1))
|
||||
else -> add(Calendar.WEEK_OF_YEAR, -1)
|
||||
}
|
||||
}
|
||||
@ -95,27 +127,29 @@ class RecentsPresenter(
|
||||
}
|
||||
}
|
||||
|
||||
val cReading = if (viewType != 3) {
|
||||
if (query.isEmpty() && viewType != 2) {
|
||||
db.getRecentsWithUnread(cal.time, query, isUngrouped).executeOnIO()
|
||||
val cReading = if (viewType != VIEW_TYPE_ONLY_UPDATES) {
|
||||
if (query.isEmpty() && viewType != VIEW_TYPE_ONLY_HISTORY) {
|
||||
db.getRecentsWithUnread(startCal.time, cal.time, query, isUngrouped)
|
||||
.executeOnIO()
|
||||
} else db.getRecentMangaLimit(
|
||||
startCal.time,
|
||||
cal.time,
|
||||
if (viewType == 2) 200 else 8,
|
||||
if (viewType == VIEW_TYPE_ONLY_HISTORY) 200 else 8,
|
||||
query
|
||||
).executeOnIO()
|
||||
} else emptyList()
|
||||
val rUpdates = when {
|
||||
viewType == 3 -> db.getRecentChapters(calWeek.time).executeOnIO().map {
|
||||
viewType == VIEW_TYPE_ONLY_UPDATES -> db.getRecentChapters(startCal.time, calWeek.time).executeOnIO().map {
|
||||
MangaChapterHistory(it.manga, it.chapter, HistoryImpl())
|
||||
}
|
||||
viewType != 2 -> db.getUpdatedManga(calWeek.time, query, isUngrouped).executeOnIO()
|
||||
viewType != VIEW_TYPE_ONLY_HISTORY -> db.getUpdatedManga(startCal.time, calWeek.time, query, isUngrouped).executeOnIO()
|
||||
else -> emptyList()
|
||||
}
|
||||
rUpdates.forEach {
|
||||
it.history.last_read = it.chapter.date_fetch
|
||||
}
|
||||
val nAdditions = if (viewType < 2) {
|
||||
db.getRecentlyAdded(calDay.time, query, isUngrouped).executeOnIO()
|
||||
val nAdditions = if (viewType < VIEW_TYPE_ONLY_HISTORY) {
|
||||
db.getRecentlyAdded(startCal.time, calDay.time, query, isUngrouped).executeOnIO()
|
||||
} else emptyList()
|
||||
nAdditions.forEach {
|
||||
it.history.last_read = it.manga.date_added
|
||||
@ -124,35 +158,33 @@ class RecentsPresenter(
|
||||
val mangaList = (cReading + rUpdates + nAdditions).sortedByDescending {
|
||||
it.history.last_read
|
||||
}.distinctBy {
|
||||
if (query.isEmpty() && viewType != 3) it.manga.id else it.chapter.id
|
||||
if (query.isEmpty() && viewType != VIEW_TYPE_ONLY_HISTORY) it.manga.id else it.chapter.id
|
||||
}
|
||||
val pairs = mangaList.mapNotNull {
|
||||
val chapter = when {
|
||||
viewType == 3 -> it.chapter
|
||||
viewType == VIEW_TYPE_ONLY_HISTORY -> it.chapter
|
||||
it.chapter.read || it.chapter.id == null -> getNextChapter(it.manga)
|
||||
it.history.id == null -> getFirstUpdatedChapter(it.manga, it.chapter)
|
||||
else -> it.chapter
|
||||
}
|
||||
if (chapter == null) if ((query.isNotEmpty() || viewType > 1) &&
|
||||
if (chapter == null) if ((query.isNotEmpty() || viewType > VIEW_TYPE_UNGROUP_ALL) &&
|
||||
it.chapter.id != null
|
||||
) Pair(it, it.chapter)
|
||||
else null
|
||||
else Pair(it, chapter)
|
||||
}
|
||||
if (query.isEmpty() && !isUngrouped) {
|
||||
val newItems = if (query.isEmpty() && !isUngrouped) {
|
||||
val nChaptersItems =
|
||||
pairs.filter { it.first.history.id == null && it.first.chapter.id != null }
|
||||
.sortedWith(
|
||||
Comparator<Pair<MangaChapterHistory, Chapter>> { f1, f2 ->
|
||||
if (abs(f1.second.date_fetch - f2.second.date_fetch) <=
|
||||
TimeUnit.HOURS.toMillis(12)
|
||||
) {
|
||||
f2.second.date_upload.compareTo(f1.second.date_upload)
|
||||
} else {
|
||||
f2.second.date_fetch.compareTo(f1.second.date_fetch)
|
||||
}
|
||||
.sortedWith { f1, f2 ->
|
||||
if (abs(f1.second.date_fetch - f2.second.date_fetch) <=
|
||||
TimeUnit.HOURS.toMillis(12)
|
||||
) {
|
||||
f2.second.date_upload.compareTo(f1.second.date_upload)
|
||||
} else {
|
||||
f2.second.date_fetch.compareTo(f1.second.date_fetch)
|
||||
}
|
||||
)
|
||||
}
|
||||
.take(4).map {
|
||||
RecentMangaItem(
|
||||
it.first,
|
||||
@ -171,36 +203,43 @@ class RecentsPresenter(
|
||||
} + RecentMangaItem(header = continueReadingHeader)
|
||||
val nAdditionsItems = pairs.filter { it.first.chapter.id == null }.take(4)
|
||||
.map { RecentMangaItem(it.first, it.second, newAdditionsHeader) }
|
||||
recentItems =
|
||||
listOf(nChaptersItems, cReadingItems, nAdditionsItems).sortedByDescending {
|
||||
it.firstOrNull()?.mch?.history?.last_read ?: 0L
|
||||
}.flatten()
|
||||
listOf(nChaptersItems, cReadingItems, nAdditionsItems).sortedByDescending {
|
||||
it.firstOrNull()?.mch?.history?.last_read ?: 0L
|
||||
}.flatten()
|
||||
} else {
|
||||
recentItems =
|
||||
if (viewType == 3) {
|
||||
val map = TreeMap<Date, MutableList<Pair<MangaChapterHistory, Chapter>>> {
|
||||
d1, d2 ->
|
||||
d2
|
||||
.compareTo(d1)
|
||||
if (viewType == VIEW_TYPE_ONLY_UPDATES) {
|
||||
val map = TreeMap<Date, MutableList<Pair<MangaChapterHistory, Chapter>>> {
|
||||
d1, d2 ->
|
||||
d2
|
||||
.compareTo(d1)
|
||||
}
|
||||
val byDay =
|
||||
pairs.groupByTo(map, { getMapKey(it.first.history.last_read) })
|
||||
byDay.flatMap {
|
||||
val dateItem = DateItem(it.key, true)
|
||||
it.value.map { item ->
|
||||
RecentMangaItem(item.first, item.second, dateItem)
|
||||
}
|
||||
val byDay =
|
||||
pairs.groupByTo(map, { getMapKey(it.first.history.last_read) })
|
||||
byDay.flatMap {
|
||||
val dateItem = DateItem(it.key, true)
|
||||
it.value.map { item ->
|
||||
RecentMangaItem(item.first, item.second, dateItem)
|
||||
}
|
||||
}
|
||||
} else pairs.map { RecentMangaItem(it.first, it.second, null) }
|
||||
if (isUngrouped && recentItems.isEmpty()) {
|
||||
recentItems = listOf(
|
||||
RecentMangaItem(header = newChaptersHeader),
|
||||
RecentMangaItem(header = continueReadingHeader)
|
||||
)
|
||||
}
|
||||
}
|
||||
} else pairs.map { RecentMangaItem(it.first, it.second, null) }
|
||||
}
|
||||
recentItems = if (page == 0) {
|
||||
newItems
|
||||
} else {
|
||||
recentItems + newItems
|
||||
}
|
||||
val newCount = itemCount + newItems.size
|
||||
val hasNewItems = newItems.isNotEmpty()
|
||||
if (newCount < 25 && viewType != VIEW_TYPE_GROUP_ALL && query.isEmpty()) {
|
||||
page++
|
||||
getRecents(true, retryCount + (if (hasNewItems) 0 else 1), newCount)
|
||||
return@launch
|
||||
}
|
||||
setDownloadedChapters(recentItems)
|
||||
withContext(Dispatchers.Main) { controller.showLists(recentItems) }
|
||||
withContext(Dispatchers.Main) {
|
||||
controller.showLists(recentItems, hasNewItems, shouldMoveToTop)
|
||||
shouldMoveToTop = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -226,9 +265,12 @@ class RecentsPresenter(
|
||||
scope.cancel()
|
||||
}
|
||||
|
||||
fun toggleGroupRecents(pref: Int) {
|
||||
preferences.recentsViewType().set(pref)
|
||||
fun toggleGroupRecents(pref: Int, updatePref: Boolean = true) {
|
||||
if (updatePref) {
|
||||
preferences.recentsViewType().set(pref)
|
||||
}
|
||||
viewType = pref
|
||||
page = 0
|
||||
getRecents()
|
||||
}
|
||||
|
||||
@ -259,7 +301,7 @@ class RecentsPresenter(
|
||||
scope.launch {
|
||||
setDownloadedChapters(recentItems)
|
||||
withContext(Dispatchers.Main) {
|
||||
controller.showLists(recentItems)
|
||||
controller.showLists(recentItems, true)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -289,7 +331,7 @@ class RecentsPresenter(
|
||||
download = null
|
||||
}
|
||||
|
||||
controller.showLists(recentItems)
|
||||
controller.showLists(recentItems, true)
|
||||
}
|
||||
}
|
||||
|
||||
@ -367,7 +409,16 @@ class RecentsPresenter(
|
||||
getRecents()
|
||||
}
|
||||
|
||||
private companion object {
|
||||
var lastRecents: List<RecentMangaItem>? = null
|
||||
fun requestNext() {
|
||||
getRecents(true)
|
||||
}
|
||||
|
||||
companion object {
|
||||
private var lastRecents: List<RecentMangaItem>? = null
|
||||
|
||||
const val VIEW_TYPE_GROUP_ALL = 0
|
||||
const val VIEW_TYPE_UNGROUP_ALL = 1
|
||||
const val VIEW_TYPE_ONLY_HISTORY = 2
|
||||
const val VIEW_TYPE_ONLY_UPDATES = 3
|
||||
}
|
||||
}
|
||||
|
4
app/src/main/res/color/accent_alpha.xml
Normal file
4
app/src/main/res/color/accent_alpha.xml
Normal file
@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:alpha="0.80" android:color="?attr/colorAccent" />
|
||||
</selector>
|
10
app/src/main/res/color/tabs_selector_alt.xml
Normal file
10
app/src/main/res/color/tabs_selector_alt.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Based on mtrl_tabs_icon_color_selector_colored.
|
||||
|
||||
Ensures visibility on top of the background color.
|
||||
-->
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:color="@color/md_white_1000" android:state_selected="true"/>
|
||||
<item android:alpha="0.60" android:color="?attr/colorOnBackground"/>
|
||||
</selector>
|
12
app/src/main/res/drawable/tab_highlight_indicator.xml
Normal file
12
app/src/main/res/drawable/tab_highlight_indicator.xml
Normal file
@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item
|
||||
android:end="2dp"
|
||||
android:start="2dp" >
|
||||
<shape>
|
||||
<corners android:radius="4dp" />
|
||||
<solid android:color="@color/accent_alpha" />
|
||||
<size android:height="32sp"/>
|
||||
</shape>
|
||||
</item>
|
||||
</layer-list>
|
@ -21,30 +21,17 @@
|
||||
app:layout_constraintHorizontal_bias="0.0"
|
||||
tools:text="@string/recent_updates" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/action_history"
|
||||
android:visibility="gone"
|
||||
android:layout_width="wrap_content"
|
||||
<com.google.android.material.tabs.TabLayout
|
||||
android:id="@+id/recents_tabs"
|
||||
style="@style/Theme.Widget.Tabs.Highlight"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:icon="@drawable/ic_history_24dp"
|
||||
android:layout_marginStart="12dp"
|
||||
android:layout_marginStart="6dp"
|
||||
android:layout_marginEnd="6dp"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
android:text="@string/history"
|
||||
style="@style/Theme.Widget.Button.RoundedOutline"/>
|
||||
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/action_update"
|
||||
android:layout_width="wrap_content"
|
||||
android:visibility="gone"
|
||||
android:layout_height="wrap_content"
|
||||
app:icon="@drawable/ic_update_24dp"
|
||||
android:layout_marginEnd="12dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
android:text="@string/updates"
|
||||
style="@style/Theme.Widget.Button.RoundedOutline"/>
|
||||
app:tabIndicatorColor="?attr/colorAccent"
|
||||
app:tabGravity="fill"/>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
@ -224,6 +224,7 @@
|
||||
<string name="no_recent_chapters">No recent chapters</string>
|
||||
<string name="no_recently_read_manga">No recently read manga</string>
|
||||
<string name="group_all">Group all</string>
|
||||
<string name="grouped">Grouped</string>
|
||||
<string name="ungroup_all">Ungroup all</string>
|
||||
<string name="only_history">Only history</string>
|
||||
<string name="only_updates">Only updates</string>
|
||||
|
@ -214,13 +214,22 @@
|
||||
<item name="tabTextColor">@color/tabs_selector</item>
|
||||
<item name="tabRippleColor">@color/rippleColor</item>
|
||||
<item name="tabIndicatorFullWidth">false</item>
|
||||
<item name="tabIndicatorHeight">3dp</item>
|
||||
<item name="tabInlineLabel">true</item>
|
||||
<item name="tabMinWidth">75dp</item>
|
||||
<item name="tabMode">scrollable</item>
|
||||
<item name="tabTextAppearance">@style/TextAppearance.Widget.Tab</item>
|
||||
</style>
|
||||
|
||||
<style name="Theme.Widget.Tabs.Highlight" parent="Theme.Widget.Tabs">
|
||||
<item name="android:background">@android:color/transparent</item>
|
||||
<item name="tabIndicatorGravity">center</item>
|
||||
<item name="tabTextColor">@color/tabs_selector_alt</item>
|
||||
<item name="tabIndicator">@drawable/tab_highlight_indicator</item>
|
||||
<item name="tabMaxWidth">0dp</item>
|
||||
<item name="tabMode">fixed</item>
|
||||
<item name="tabIndicatorFullWidth">true</item>
|
||||
</style>
|
||||
|
||||
<!--==============-->
|
||||
<!--Widgets.Button-->
|
||||
<!--==============-->
|
||||
|
Loading…
Reference in New Issue
Block a user