Merge Latest and Browse into one screen (#7921)
* Merge Latest and Browse into one
* Add back Latest button
* Change context to IO instead of launching a job
* Use loading screen when loading initial page
(cherry picked from commit cc6aef693e)
# Conflicts:
# app/src/main/java/eu/kanade/data/source/SourceRepositoryImpl.kt
# app/src/main/java/eu/kanade/presentation/browse/BrowseLatestScreen.kt
# app/src/main/java/eu/kanade/presentation/browse/BrowseSourceScreen.kt
# app/src/main/java/eu/kanade/presentation/browse/SourceSearchScreen.kt
# app/src/main/java/eu/kanade/presentation/browse/SourcesScreen.kt
# app/src/main/java/eu/kanade/presentation/browse/components/BrowseLatestToolbar.kt
# app/src/main/java/eu/kanade/presentation/browse/components/BrowseSourceComfortableGrid.kt
# app/src/main/java/eu/kanade/presentation/browse/components/BrowseSourceToolbar.kt
# app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/search/SourceSearchController.kt
# app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/SourcesTab.kt
# app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/BrowsePagingSource.kt
# app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/BrowseSourceController.kt
# app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/BrowseSourcePresenter.kt
# app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/latest/LatestUpdatesController.kt
# app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/latest/LatestUpdatesPresenter.kt
This commit is contained in:
@@ -0,0 +1,63 @@
|
||||
package eu.kanade.data.source
|
||||
|
||||
import eu.kanade.tachiyomi.source.CatalogueSource
|
||||
import eu.kanade.tachiyomi.source.model.FilterList
|
||||
import eu.kanade.tachiyomi.source.model.MangasPage
|
||||
import eu.kanade.tachiyomi.source.model.MetadataMangasPage
|
||||
import eu.kanade.tachiyomi.util.lang.awaitSingle
|
||||
|
||||
abstract class EHentaiPagingSource(source: CatalogueSource) : SourcePagingSource(source) {
|
||||
|
||||
private var lastMangaLink: String? = null
|
||||
|
||||
abstract suspend fun fetchNextPage(currentPage: Int): MangasPage
|
||||
|
||||
override suspend fun requestNextPage(currentPage: Int): MangasPage {
|
||||
val lastMangaLink = lastMangaLink
|
||||
|
||||
val mangasPage = fetchNextPage(currentPage)
|
||||
|
||||
mangasPage.mangas.lastOrNull()?.let {
|
||||
this.lastMangaLink = it.url
|
||||
}
|
||||
return if (lastMangaLink != null) {
|
||||
val index = mangasPage.mangas.indexOfFirst { it.url == lastMangaLink }
|
||||
if (index != -1) {
|
||||
val lastIndex = mangasPage.mangas.size
|
||||
val startIndex = (index + 1).coerceAtMost(mangasPage.mangas.lastIndex)
|
||||
if (mangasPage is MetadataMangasPage) {
|
||||
mangasPage.copy(
|
||||
mangas = mangasPage.mangas.subList(startIndex, lastIndex),
|
||||
mangasMetadata = mangasPage.mangasMetadata.subList(startIndex, lastIndex),
|
||||
)
|
||||
} else {
|
||||
mangasPage.copy(
|
||||
mangas = mangasPage.mangas.subList(startIndex, lastIndex),
|
||||
)
|
||||
}
|
||||
} else {
|
||||
mangasPage
|
||||
}
|
||||
} else {
|
||||
mangasPage
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class EHentaiSearchPagingSource(source: CatalogueSource, val query: String, val filters: FilterList) : EHentaiPagingSource(source) {
|
||||
override suspend fun fetchNextPage(currentPage: Int): MangasPage {
|
||||
return source.fetchSearchManga(currentPage, query, filters).awaitSingle()
|
||||
}
|
||||
}
|
||||
|
||||
class EHentaiPopularPagingSource(source: CatalogueSource) : EHentaiPagingSource(source) {
|
||||
override suspend fun fetchNextPage(currentPage: Int): MangasPage {
|
||||
return source.fetchPopularManga(currentPage).awaitSingle()
|
||||
}
|
||||
}
|
||||
|
||||
class EHentaiLatestPagingSource(source: CatalogueSource) : EHentaiPagingSource(source) {
|
||||
override suspend fun fetchNextPage(currentPage: Int): MangasPage {
|
||||
return source.fetchLatestUpdates(currentPage).awaitSingle()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
package eu.kanade.data.source
|
||||
|
||||
class NoResultsException : Exception()
|
||||
@@ -0,0 +1,72 @@
|
||||
package eu.kanade.data.source
|
||||
|
||||
import androidx.paging.PagingState
|
||||
import eu.kanade.domain.source.model.SourcePagingSourceType
|
||||
import eu.kanade.tachiyomi.source.CatalogueSource
|
||||
import eu.kanade.tachiyomi.source.model.FilterList
|
||||
import eu.kanade.tachiyomi.source.model.MangasPage
|
||||
import eu.kanade.tachiyomi.source.model.MetadataMangasPage
|
||||
import eu.kanade.tachiyomi.source.model.SManga
|
||||
import eu.kanade.tachiyomi.util.lang.awaitSingle
|
||||
import eu.kanade.tachiyomi.util.lang.withIOContext
|
||||
import exh.metadata.metadata.base.RaisedSearchMetadata
|
||||
|
||||
abstract class SourcePagingSource(
|
||||
protected val source: CatalogueSource,
|
||||
) : SourcePagingSourceType() {
|
||||
|
||||
abstract suspend fun requestNextPage(currentPage: Int): MangasPage
|
||||
|
||||
override suspend fun load(params: LoadParams<Long>): LoadResult<Long, /*SY --> */ Pair<SManga, RaisedSearchMetadata?>/*SY <-- */> {
|
||||
val page = params.key ?: 1
|
||||
|
||||
val mangasPage = try {
|
||||
withIOContext {
|
||||
requestNextPage(page.toInt())
|
||||
.takeIf { it.mangas.isNotEmpty() }
|
||||
?: throw NoResultsException()
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
return LoadResult.Error(e)
|
||||
}
|
||||
// SY -->
|
||||
val metadata = if (mangasPage is MetadataMangasPage) {
|
||||
mangasPage.mangasMetadata
|
||||
} else emptyList()
|
||||
// SY <--
|
||||
|
||||
return LoadResult.Page(
|
||||
data = mangasPage.mangas
|
||||
// SY -->
|
||||
.mapIndexed { index, sManga -> sManga to metadata.getOrNull(index) },
|
||||
// SY <--
|
||||
prevKey = null,
|
||||
nextKey = if (mangasPage.hasNextPage) page + 1 else null,
|
||||
)
|
||||
}
|
||||
|
||||
override fun getRefreshKey(state: PagingState<Long, /*SY --> */ Pair<SManga, RaisedSearchMetadata?>/*SY <-- */>): Long? {
|
||||
return state.anchorPosition?.let { anchorPosition ->
|
||||
val anchorPage = state.closestPageToPosition(anchorPosition)
|
||||
anchorPage?.prevKey ?: anchorPage?.nextKey
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class SourceSearchPagingSource(source: CatalogueSource, val query: String, val filters: FilterList) : SourcePagingSource(source) {
|
||||
override suspend fun requestNextPage(currentPage: Int): MangasPage {
|
||||
return source.fetchSearchManga(currentPage, query, filters).awaitSingle()
|
||||
}
|
||||
}
|
||||
|
||||
class SourcePopularPagingSource(source: CatalogueSource) : SourcePagingSource(source) {
|
||||
override suspend fun requestNextPage(currentPage: Int): MangasPage {
|
||||
return source.fetchPopularManga(currentPage).awaitSingle()
|
||||
}
|
||||
}
|
||||
|
||||
class SourceLatestPagingSource(source: CatalogueSource) : SourcePagingSource(source) {
|
||||
override suspend fun requestNextPage(currentPage: Int): MangasPage {
|
||||
return source.fetchLatestUpdates(currentPage).awaitSingle()
|
||||
}
|
||||
}
|
||||
@@ -2,11 +2,15 @@ package eu.kanade.data.source
|
||||
|
||||
import eu.kanade.data.DatabaseHandler
|
||||
import eu.kanade.domain.source.model.Source
|
||||
import eu.kanade.domain.source.model.SourcePagingSourceType
|
||||
import eu.kanade.domain.source.model.SourceWithCount
|
||||
import eu.kanade.domain.source.repository.SourceRepository
|
||||
import eu.kanade.tachiyomi.source.CatalogueSource
|
||||
import eu.kanade.tachiyomi.source.LocalSource
|
||||
import eu.kanade.tachiyomi.source.SourceManager
|
||||
import eu.kanade.tachiyomi.source.model.FilterList
|
||||
import exh.source.MERGED_SOURCE_ID
|
||||
import exh.source.isEhBasedSource
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.map
|
||||
|
||||
@@ -50,4 +54,38 @@ class SourceRepositoryImpl(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun search(
|
||||
sourceId: Long,
|
||||
query: String,
|
||||
filterList: FilterList,
|
||||
): SourcePagingSourceType {
|
||||
val source = sourceManager.get(sourceId) as CatalogueSource
|
||||
// SY -->
|
||||
if (source.isEhBasedSource()) {
|
||||
return EHentaiSearchPagingSource(source, query, filterList)
|
||||
}
|
||||
// SY <--
|
||||
return SourceSearchPagingSource(source, query, filterList)
|
||||
}
|
||||
|
||||
override fun getPopular(sourceId: Long): SourcePagingSourceType {
|
||||
val source = sourceManager.get(sourceId) as CatalogueSource
|
||||
// SY -->
|
||||
if (source.isEhBasedSource()) {
|
||||
return EHentaiPopularPagingSource(source)
|
||||
}
|
||||
// SY <--
|
||||
return SourcePopularPagingSource(source)
|
||||
}
|
||||
|
||||
override fun getLatest(sourceId: Long): SourcePagingSourceType {
|
||||
val source = sourceManager.get(sourceId) as CatalogueSource
|
||||
// SY -->
|
||||
if (source.isEhBasedSource()) {
|
||||
return EHentaiLatestPagingSource(source)
|
||||
}
|
||||
// SY <--
|
||||
return SourceLatestPagingSource(source)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user