extension settings
This commit is contained in:
parent
9c0ef7a788
commit
3368a1bc8d
76 changed files with 2320 additions and 131 deletions
22
app/src/main/java/tachiyomi/domain/entries/TriStateFilter.kt
Normal file
22
app/src/main/java/tachiyomi/domain/entries/TriStateFilter.kt
Normal file
|
@ -0,0 +1,22 @@
|
|||
package tachiyomi.domain.entries
|
||||
|
||||
enum class TriStateFilter {
|
||||
DISABLED, // Disable filter
|
||||
ENABLED_IS, // Enabled with "is" filter
|
||||
ENABLED_NOT, // Enabled with "not" filter
|
||||
;
|
||||
|
||||
fun next(): TriStateFilter {
|
||||
return when (this) {
|
||||
DISABLED -> ENABLED_IS
|
||||
ENABLED_IS -> ENABLED_NOT
|
||||
ENABLED_NOT -> DISABLED
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline fun applyFilter(filter: TriStateFilter, predicate: () -> Boolean): Boolean = when (filter) {
|
||||
TriStateFilter.DISABLED -> true
|
||||
TriStateFilter.ENABLED_IS -> predicate()
|
||||
TriStateFilter.ENABLED_NOT -> !predicate()
|
||||
}
|
134
app/src/main/java/tachiyomi/domain/entries/anime/model/Anime.kt
Normal file
134
app/src/main/java/tachiyomi/domain/entries/anime/model/Anime.kt
Normal file
|
@ -0,0 +1,134 @@
|
|||
package tachiyomi.domain.entries.anime.model
|
||||
|
||||
import eu.kanade.tachiyomi.source.model.UpdateStrategy
|
||||
import tachiyomi.domain.entries.TriStateFilter
|
||||
import java.io.Serializable
|
||||
import kotlin.math.pow
|
||||
|
||||
data class Anime(
|
||||
val id: Long,
|
||||
val source: Long,
|
||||
val favorite: Boolean,
|
||||
val lastUpdate: Long,
|
||||
val nextUpdate: Long,
|
||||
val calculateInterval: Int,
|
||||
val dateAdded: Long,
|
||||
val viewerFlags: Long,
|
||||
val episodeFlags: Long,
|
||||
val coverLastModified: Long,
|
||||
val url: String,
|
||||
val title: String,
|
||||
val artist: String?,
|
||||
val author: String?,
|
||||
val description: String?,
|
||||
val genre: List<String>?,
|
||||
val status: Long,
|
||||
val thumbnailUrl: String?,
|
||||
val updateStrategy: UpdateStrategy,
|
||||
val initialized: Boolean,
|
||||
) : Serializable {
|
||||
|
||||
val sorting: Long
|
||||
get() = episodeFlags and EPISODE_SORTING_MASK
|
||||
|
||||
val displayMode: Long
|
||||
get() = episodeFlags and EPISODE_DISPLAY_MASK
|
||||
|
||||
val unseenFilterRaw: Long
|
||||
get() = episodeFlags and EPISODE_UNSEEN_MASK
|
||||
|
||||
val downloadedFilterRaw: Long
|
||||
get() = episodeFlags and EPISODE_DOWNLOADED_MASK
|
||||
|
||||
val bookmarkedFilterRaw: Long
|
||||
get() = episodeFlags and EPISODE_BOOKMARKED_MASK
|
||||
|
||||
val skipIntroLength: Int
|
||||
get() = (viewerFlags and ANIME_INTRO_MASK).toInt()
|
||||
|
||||
val nextEpisodeToAir: Int
|
||||
get() = (viewerFlags and ANIME_AIRING_EPISODE_MASK).removeHexZeros(zeros = 2).toInt()
|
||||
|
||||
val nextEpisodeAiringAt: Long
|
||||
get() = (viewerFlags and ANIME_AIRING_TIME_MASK).removeHexZeros(zeros = 6)
|
||||
|
||||
val unseenFilter: TriStateFilter
|
||||
get() = when (unseenFilterRaw) {
|
||||
EPISODE_SHOW_UNSEEN -> TriStateFilter.ENABLED_IS
|
||||
EPISODE_SHOW_SEEN -> TriStateFilter.ENABLED_NOT
|
||||
else -> TriStateFilter.DISABLED
|
||||
}
|
||||
|
||||
val bookmarkedFilter: TriStateFilter
|
||||
get() = when (bookmarkedFilterRaw) {
|
||||
EPISODE_SHOW_BOOKMARKED -> TriStateFilter.ENABLED_IS
|
||||
EPISODE_SHOW_NOT_BOOKMARKED -> TriStateFilter.ENABLED_NOT
|
||||
else -> TriStateFilter.DISABLED
|
||||
}
|
||||
|
||||
fun sortDescending(): Boolean {
|
||||
return episodeFlags and EPISODE_SORT_DIR_MASK == EPISODE_SORT_DESC
|
||||
}
|
||||
|
||||
private fun Long.removeHexZeros(zeros: Int): Long {
|
||||
val hex = 16.0
|
||||
return this.div(hex.pow(zeros)).toLong()
|
||||
}
|
||||
|
||||
companion object {
|
||||
// Generic filter that does not filter anything
|
||||
const val SHOW_ALL = 0x00000000L
|
||||
|
||||
const val EPISODE_SORT_DESC = 0x00000000L
|
||||
const val EPISODE_SORT_ASC = 0x00000001L
|
||||
const val EPISODE_SORT_DIR_MASK = 0x00000001L
|
||||
|
||||
const val EPISODE_SHOW_UNSEEN = 0x00000002L
|
||||
const val EPISODE_SHOW_SEEN = 0x00000004L
|
||||
const val EPISODE_UNSEEN_MASK = 0x00000006L
|
||||
|
||||
const val EPISODE_SHOW_DOWNLOADED = 0x00000008L
|
||||
const val EPISODE_SHOW_NOT_DOWNLOADED = 0x00000010L
|
||||
const val EPISODE_DOWNLOADED_MASK = 0x00000018L
|
||||
|
||||
const val EPISODE_SHOW_BOOKMARKED = 0x00000020L
|
||||
const val EPISODE_SHOW_NOT_BOOKMARKED = 0x00000040L
|
||||
const val EPISODE_BOOKMARKED_MASK = 0x00000060L
|
||||
|
||||
const val EPISODE_SORTING_SOURCE = 0x00000000L
|
||||
const val EPISODE_SORTING_NUMBER = 0x00000100L
|
||||
const val EPISODE_SORTING_UPLOAD_DATE = 0x00000200L
|
||||
const val EPISODE_SORTING_MASK = 0x00000300L
|
||||
|
||||
const val EPISODE_DISPLAY_NAME = 0x00000000L
|
||||
const val EPISODE_DISPLAY_NUMBER = 0x00100000L
|
||||
const val EPISODE_DISPLAY_MASK = 0x00100000L
|
||||
|
||||
const val ANIME_INTRO_MASK = 0x000000000000FFL
|
||||
const val ANIME_AIRING_EPISODE_MASK = 0x00000000FFFF00L
|
||||
const val ANIME_AIRING_TIME_MASK = 0xFFFFFFFF000000L
|
||||
|
||||
fun create() = Anime(
|
||||
id = -1L,
|
||||
url = "",
|
||||
title = "",
|
||||
source = -1L,
|
||||
favorite = false,
|
||||
lastUpdate = 0L,
|
||||
nextUpdate = 0L,
|
||||
calculateInterval = 0,
|
||||
dateAdded = 0L,
|
||||
viewerFlags = 0L,
|
||||
episodeFlags = 0L,
|
||||
coverLastModified = 0L,
|
||||
artist = null,
|
||||
author = null,
|
||||
description = null,
|
||||
genre = null,
|
||||
status = 0L,
|
||||
thumbnailUrl = null,
|
||||
updateStrategy = UpdateStrategy.ALWAYS_UPDATE,
|
||||
initialized = false,
|
||||
)
|
||||
}
|
||||
}
|
115
app/src/main/java/tachiyomi/domain/entries/manga/model/Manga.kt
Normal file
115
app/src/main/java/tachiyomi/domain/entries/manga/model/Manga.kt
Normal file
|
@ -0,0 +1,115 @@
|
|||
package tachiyomi.domain.entries.manga.model
|
||||
|
||||
import eu.kanade.tachiyomi.source.model.UpdateStrategy
|
||||
import tachiyomi.domain.entries.TriStateFilter
|
||||
import java.io.Serializable
|
||||
|
||||
data class Manga(
|
||||
val id: Long,
|
||||
val source: Long,
|
||||
val favorite: Boolean,
|
||||
val lastUpdate: Long,
|
||||
val nextUpdate: Long,
|
||||
val calculateInterval: Int,
|
||||
val dateAdded: Long,
|
||||
val viewerFlags: Long,
|
||||
val chapterFlags: Long,
|
||||
val coverLastModified: Long,
|
||||
val url: String,
|
||||
val title: String,
|
||||
val artist: String?,
|
||||
val author: String?,
|
||||
val description: String?,
|
||||
val genre: List<String>?,
|
||||
val status: Long,
|
||||
val thumbnailUrl: String?,
|
||||
val updateStrategy: UpdateStrategy,
|
||||
val initialized: Boolean,
|
||||
) : Serializable {
|
||||
|
||||
val sorting: Long
|
||||
get() = chapterFlags and CHAPTER_SORTING_MASK
|
||||
|
||||
val displayMode: Long
|
||||
get() = chapterFlags and CHAPTER_DISPLAY_MASK
|
||||
|
||||
val unreadFilterRaw: Long
|
||||
get() = chapterFlags and CHAPTER_UNREAD_MASK
|
||||
|
||||
val downloadedFilterRaw: Long
|
||||
get() = chapterFlags and CHAPTER_DOWNLOADED_MASK
|
||||
|
||||
val bookmarkedFilterRaw: Long
|
||||
get() = chapterFlags and CHAPTER_BOOKMARKED_MASK
|
||||
|
||||
val unreadFilter: TriStateFilter
|
||||
get() = when (unreadFilterRaw) {
|
||||
CHAPTER_SHOW_UNREAD -> TriStateFilter.ENABLED_IS
|
||||
CHAPTER_SHOW_READ -> TriStateFilter.ENABLED_NOT
|
||||
else -> TriStateFilter.DISABLED
|
||||
}
|
||||
|
||||
val bookmarkedFilter: TriStateFilter
|
||||
get() = when (bookmarkedFilterRaw) {
|
||||
CHAPTER_SHOW_BOOKMARKED -> TriStateFilter.ENABLED_IS
|
||||
CHAPTER_SHOW_NOT_BOOKMARKED -> TriStateFilter.ENABLED_NOT
|
||||
else -> TriStateFilter.DISABLED
|
||||
}
|
||||
|
||||
fun sortDescending(): Boolean {
|
||||
return chapterFlags and CHAPTER_SORT_DIR_MASK == CHAPTER_SORT_DESC
|
||||
}
|
||||
|
||||
companion object {
|
||||
// Generic filter that does not filter anything
|
||||
const val SHOW_ALL = 0x00000000L
|
||||
|
||||
const val CHAPTER_SORT_DESC = 0x00000000L
|
||||
const val CHAPTER_SORT_ASC = 0x00000001L
|
||||
const val CHAPTER_SORT_DIR_MASK = 0x00000001L
|
||||
|
||||
const val CHAPTER_SHOW_UNREAD = 0x00000002L
|
||||
const val CHAPTER_SHOW_READ = 0x00000004L
|
||||
const val CHAPTER_UNREAD_MASK = 0x00000006L
|
||||
|
||||
const val CHAPTER_SHOW_DOWNLOADED = 0x00000008L
|
||||
const val CHAPTER_SHOW_NOT_DOWNLOADED = 0x00000010L
|
||||
const val CHAPTER_DOWNLOADED_MASK = 0x00000018L
|
||||
|
||||
const val CHAPTER_SHOW_BOOKMARKED = 0x00000020L
|
||||
const val CHAPTER_SHOW_NOT_BOOKMARKED = 0x00000040L
|
||||
const val CHAPTER_BOOKMARKED_MASK = 0x00000060L
|
||||
|
||||
const val CHAPTER_SORTING_SOURCE = 0x00000000L
|
||||
const val CHAPTER_SORTING_NUMBER = 0x00000100L
|
||||
const val CHAPTER_SORTING_UPLOAD_DATE = 0x00000200L
|
||||
const val CHAPTER_SORTING_MASK = 0x00000300L
|
||||
|
||||
const val CHAPTER_DISPLAY_NAME = 0x00000000L
|
||||
const val CHAPTER_DISPLAY_NUMBER = 0x00100000L
|
||||
const val CHAPTER_DISPLAY_MASK = 0x00100000L
|
||||
|
||||
fun create() = Manga(
|
||||
id = -1L,
|
||||
url = "",
|
||||
title = "",
|
||||
source = -1L,
|
||||
favorite = false,
|
||||
lastUpdate = 0L,
|
||||
nextUpdate = 0L,
|
||||
calculateInterval = 0,
|
||||
dateAdded = 0L,
|
||||
viewerFlags = 0L,
|
||||
chapterFlags = 0L,
|
||||
coverLastModified = 0L,
|
||||
artist = null,
|
||||
author = null,
|
||||
description = null,
|
||||
genre = null,
|
||||
status = 0L,
|
||||
thumbnailUrl = null,
|
||||
updateStrategy = UpdateStrategy.ALWAYS_UPDATE,
|
||||
initialized = false,
|
||||
)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,119 @@
|
|||
package tachiyomi.domain.items.episode.service
|
||||
|
||||
/**
|
||||
* -R> = regex conversion.
|
||||
*/
|
||||
object EpisodeRecognition {
|
||||
|
||||
private const val NUMBER_PATTERN = """([0-9]+)(\.[0-9]+)?(\.?[a-z]+)?"""
|
||||
|
||||
/**
|
||||
* All cases with Ch.xx
|
||||
* Mokushiroku Alice Vol.1 Ch. 4: Misrepresentation -R> 4
|
||||
*/
|
||||
private val basic = Regex("""(?<=ep\.) *$NUMBER_PATTERN""")
|
||||
|
||||
/**
|
||||
* Example: Bleach 567: Down With Snowwhite -R> 567
|
||||
*/
|
||||
private val number = Regex(NUMBER_PATTERN)
|
||||
|
||||
/**
|
||||
* Regex used to remove unwanted tags
|
||||
* Example Prison School 12 v.1 vol004 version1243 volume64 -R> Prison School 12
|
||||
*/
|
||||
private val unwanted = Regex("""\b(?:v|ver|vol|version|volume|season|s)[^a-z]?[0-9]+""")
|
||||
|
||||
/**
|
||||
* Regex used to remove unwanted whitespace
|
||||
* Example One Piece 12 special -R> One Piece 12special
|
||||
*/
|
||||
private val unwantedWhiteSpace = Regex("""\s(?=extra|special|omake)""")
|
||||
|
||||
fun parseEpisodeNumber(animeTitle: String, episodeName: String, episodeNumber: Float? = null): Float {
|
||||
// If episode number is known return.
|
||||
if (episodeNumber != null && (episodeNumber == -2f || episodeNumber > -1f)) {
|
||||
return episodeNumber
|
||||
}
|
||||
|
||||
// Get chapter title with lower case
|
||||
var name = episodeName.lowercase()
|
||||
|
||||
// Remove anime title from episode title.
|
||||
name = name.replace(animeTitle.lowercase(), "").trim()
|
||||
|
||||
// Remove comma's or hyphens.
|
||||
name = name.replace(',', '.').replace('-', '.')
|
||||
|
||||
// Remove unwanted white spaces.
|
||||
name = unwantedWhiteSpace.replace(name, "")
|
||||
|
||||
// Remove unwanted tags.
|
||||
name = unwanted.replace(name, "")
|
||||
|
||||
// Check base case ch.xx
|
||||
basic.find(name)?.let { return getEpisodeNumberFromMatch(it) }
|
||||
|
||||
// Take the first number encountered.
|
||||
number.find(name)?.let { return getEpisodeNumberFromMatch(it) }
|
||||
|
||||
return episodeNumber ?: -1f
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if episode number is found and return it
|
||||
* @param match result of regex
|
||||
* @return chapter number if found else null
|
||||
*/
|
||||
private fun getEpisodeNumberFromMatch(match: MatchResult): Float {
|
||||
return match.let {
|
||||
val initial = it.groups[1]?.value?.toFloat()!!
|
||||
val subChapterDecimal = it.groups[2]?.value
|
||||
val subChapterAlpha = it.groups[3]?.value
|
||||
val addition = checkForDecimal(subChapterDecimal, subChapterAlpha)
|
||||
initial.plus(addition)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check for decimal in received strings
|
||||
* @param decimal decimal value of regex
|
||||
* @param alpha alpha value of regex
|
||||
* @return decimal/alpha float value
|
||||
*/
|
||||
private fun checkForDecimal(decimal: String?, alpha: String?): Float {
|
||||
if (!decimal.isNullOrEmpty()) {
|
||||
return decimal.toFloat()
|
||||
}
|
||||
|
||||
if (!alpha.isNullOrEmpty()) {
|
||||
if (alpha.contains("extra")) {
|
||||
return .99f
|
||||
}
|
||||
|
||||
if (alpha.contains("omake")) {
|
||||
return .98f
|
||||
}
|
||||
|
||||
if (alpha.contains("special")) {
|
||||
return .97f
|
||||
}
|
||||
|
||||
val trimmedAlpha = alpha.trimStart('.')
|
||||
if (trimmedAlpha.length == 1) {
|
||||
return parseAlphaPostFix(trimmedAlpha[0])
|
||||
}
|
||||
}
|
||||
|
||||
return .0f
|
||||
}
|
||||
|
||||
/**
|
||||
* x.a -> x.1, x.b -> x.2, etc
|
||||
*/
|
||||
private fun parseAlphaPostFix(alpha: Char): Float {
|
||||
val number = alpha.code - ('a'.code - 1)
|
||||
if (number >= 10) return 0f
|
||||
return number / 10f
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
package tachiyomi.domain.source.anime.model
|
||||
|
||||
data class AnimeSource(
|
||||
val id: Long,
|
||||
val lang: String,
|
||||
val name: String,
|
||||
val supportsLatest: Boolean,
|
||||
val isStub: Boolean,
|
||||
val pin: Pins = Pins.unpinned,
|
||||
val isUsedLast: Boolean = false,
|
||||
) {
|
||||
|
||||
val visualName: String
|
||||
get() = when {
|
||||
lang.isEmpty() -> name
|
||||
else -> "$name (${lang.uppercase()})"
|
||||
}
|
||||
|
||||
val key: () -> String = {
|
||||
when {
|
||||
isUsedLast -> "$id-lastused"
|
||||
else -> "$id"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
package tachiyomi.domain.source.anime.model
|
||||
|
||||
data class AnimeSourceWithCount(
|
||||
val source: AnimeSource,
|
||||
val count: Long,
|
||||
) {
|
||||
|
||||
val id: Long
|
||||
get() = source.id
|
||||
|
||||
val name: String
|
||||
get() = source.name
|
||||
}
|
42
app/src/main/java/tachiyomi/domain/source/anime/model/Pin.kt
Normal file
42
app/src/main/java/tachiyomi/domain/source/anime/model/Pin.kt
Normal file
|
@ -0,0 +1,42 @@
|
|||
package tachiyomi.domain.source.anime.model
|
||||
|
||||
sealed class Pin(val code: Int) {
|
||||
object Unpinned : Pin(0b00)
|
||||
object Pinned : Pin(0b01)
|
||||
object Actual : Pin(0b10)
|
||||
}
|
||||
|
||||
inline fun Pins(builder: Pins.PinsBuilder.() -> Unit = {}): Pins {
|
||||
return Pins.PinsBuilder().apply(builder).flags()
|
||||
}
|
||||
|
||||
fun Pins(vararg pins: Pin) = Pins {
|
||||
pins.forEach { +it }
|
||||
}
|
||||
|
||||
data class Pins(val code: Int = Pin.Unpinned.code) {
|
||||
|
||||
operator fun contains(pin: Pin): Boolean = pin.code and code == pin.code
|
||||
|
||||
operator fun plus(pin: Pin): Pins = Pins(code or pin.code)
|
||||
|
||||
operator fun minus(pin: Pin): Pins = Pins(code xor pin.code)
|
||||
|
||||
companion object {
|
||||
val unpinned = Pins(Pin.Unpinned)
|
||||
|
||||
val pinned = Pins(Pin.Pinned, Pin.Actual)
|
||||
}
|
||||
|
||||
class PinsBuilder(var code: Int = 0) {
|
||||
operator fun Pin.unaryPlus() {
|
||||
this@PinsBuilder.code = code or this@PinsBuilder.code
|
||||
}
|
||||
|
||||
operator fun Pin.unaryMinus() {
|
||||
this@PinsBuilder.code = code or this@PinsBuilder.code
|
||||
}
|
||||
|
||||
fun flags(): Pins = Pins(code)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
package tachiyomi.domain.source.anime.model
|
||||
|
||||
import eu.kanade.tachiyomi.animesource.AnimeSource
|
||||
import eu.kanade.tachiyomi.animesource.model.SAnime
|
||||
import eu.kanade.tachiyomi.animesource.model.SEpisode
|
||||
import eu.kanade.tachiyomi.animesource.model.Video
|
||||
|
||||
@Suppress("OverridingDeprecatedMember")
|
||||
class StubAnimeSource(private val sourceData: AnimeSourceData) : AnimeSource {
|
||||
|
||||
override val id: Long = sourceData.id
|
||||
|
||||
override val name: String = sourceData.name.ifBlank { id.toString() }
|
||||
|
||||
override val lang: String = sourceData.lang
|
||||
|
||||
override suspend fun getAnimeDetails(anime: SAnime): SAnime {
|
||||
throw AnimeSourceNotInstalledException()
|
||||
}
|
||||
|
||||
override suspend fun getEpisodeList(anime: SAnime): List<SEpisode> {
|
||||
throw AnimeSourceNotInstalledException()
|
||||
}
|
||||
|
||||
override suspend fun getVideoList(episode: SEpisode): List<Video> {
|
||||
throw AnimeSourceNotInstalledException()
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
return if (sourceData.isMissingInfo.not()) "$name (${lang.uppercase()})" else id.toString()
|
||||
}
|
||||
}
|
||||
class AnimeSourceNotInstalledException : Exception()
|
|
@ -0,0 +1,27 @@
|
|||
package tachiyomi.domain.source.anime.repository
|
||||
|
||||
import androidx.paging.PagingSource
|
||||
import eu.kanade.tachiyomi.animesource.model.AnimeFilterList
|
||||
import eu.kanade.tachiyomi.animesource.model.SAnime
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import tachiyomi.domain.source.anime.model.AnimeSource
|
||||
import tachiyomi.domain.source.anime.model.AnimeSourceWithCount
|
||||
|
||||
typealias AnimeSourcePagingSourceType = PagingSource<Long, SAnime>
|
||||
|
||||
interface AnimeSourceRepository {
|
||||
|
||||
fun getAnimeSources(): Flow<List<AnimeSource>>
|
||||
|
||||
fun getOnlineAnimeSources(): Flow<List<AnimeSource>>
|
||||
|
||||
fun getAnimeSourcesWithFavoriteCount(): Flow<List<Pair<AnimeSource, Long>>>
|
||||
|
||||
fun getSourcesWithNonLibraryAnime(): Flow<List<AnimeSourceWithCount>>
|
||||
|
||||
fun searchAnime(sourceId: Long, query: String, filterList: AnimeFilterList): AnimeSourcePagingSourceType
|
||||
|
||||
fun getPopularAnime(sourceId: Long): AnimeSourcePagingSourceType
|
||||
|
||||
fun getLatestAnime(sourceId: Long): AnimeSourcePagingSourceType
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
package tachiyomi.domain.source.anime.service
|
||||
|
||||
import eu.kanade.tachiyomi.animesource.AnimeCatalogueSource
|
||||
import eu.kanade.tachiyomi.animesource.AnimeSource
|
||||
import eu.kanade.tachiyomi.animesource.online.AnimeHttpSource
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import tachiyomi.domain.source.anime.model.StubAnimeSource
|
||||
|
||||
interface AnimeSourceManager {
|
||||
|
||||
val catalogueSources: Flow<List<AnimeCatalogueSource>>
|
||||
|
||||
fun get(sourceKey: Long): AnimeSource?
|
||||
|
||||
fun getOrStub(sourceKey: Long): AnimeSource
|
||||
|
||||
fun getOnlineSources(): List<AnimeHttpSource>
|
||||
|
||||
fun getCatalogueSources(): List<AnimeCatalogueSource>
|
||||
|
||||
fun getStubSources(): List<StubAnimeSource>
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
package tachiyomi.domain.source.manga.model
|
||||
|
||||
import eu.kanade.tachiyomi.source.MangaSource
|
||||
import eu.kanade.tachiyomi.source.model.Page
|
||||
import eu.kanade.tachiyomi.source.model.SChapter
|
||||
import eu.kanade.tachiyomi.source.model.SManga
|
||||
import rx.Observable
|
||||
|
||||
@Suppress("OverridingDeprecatedMember")
|
||||
class StubMangaSource(private val sourceData: MangaSourceData) : MangaSource {
|
||||
|
||||
override val id: Long = sourceData.id
|
||||
|
||||
override val name: String = sourceData.name.ifBlank { id.toString() }
|
||||
|
||||
override val lang: String = sourceData.lang
|
||||
|
||||
override suspend fun getMangaDetails(manga: SManga): SManga {
|
||||
throw SourceNotInstalledException()
|
||||
}
|
||||
|
||||
@Deprecated("Use the 1.x API instead", replaceWith = ReplaceWith("getMangaDetails"))
|
||||
override fun fetchMangaDetails(manga: SManga): Observable<SManga> {
|
||||
return Observable.error(SourceNotInstalledException())
|
||||
}
|
||||
|
||||
override suspend fun getChapterList(manga: SManga): List<SChapter> {
|
||||
throw SourceNotInstalledException()
|
||||
}
|
||||
|
||||
@Deprecated("Use the 1.x API instead", replaceWith = ReplaceWith("getChapterList"))
|
||||
override fun fetchChapterList(manga: SManga): Observable<List<SChapter>> {
|
||||
return Observable.error(SourceNotInstalledException())
|
||||
}
|
||||
|
||||
override suspend fun getPageList(chapter: SChapter): List<Page> {
|
||||
throw SourceNotInstalledException()
|
||||
}
|
||||
|
||||
@Deprecated("Use the 1.x API instead", replaceWith = ReplaceWith("getPageList"))
|
||||
override fun fetchPageList(chapter: SChapter): Observable<List<Page>> {
|
||||
return Observable.error(SourceNotInstalledException())
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
return if (sourceData.isMissingInfo.not()) "$name (${lang.uppercase()})" else id.toString()
|
||||
}
|
||||
}
|
||||
|
||||
class SourceNotInstalledException : Exception()
|
|
@ -0,0 +1,22 @@
|
|||
package tachiyomi.domain.source.manga.service
|
||||
|
||||
import eu.kanade.tachiyomi.source.CatalogueSource
|
||||
import eu.kanade.tachiyomi.source.MangaSource
|
||||
import eu.kanade.tachiyomi.source.online.HttpSource
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import tachiyomi.domain.source.manga.model.StubMangaSource
|
||||
|
||||
interface MangaSourceManager {
|
||||
|
||||
val catalogueSources: Flow<List<CatalogueSource>>
|
||||
|
||||
fun get(sourceKey: Long): MangaSource?
|
||||
|
||||
fun getOrStub(sourceKey: Long): MangaSource
|
||||
|
||||
fun getOnlineSources(): List<HttpSource>
|
||||
|
||||
fun getCatalogueSources(): List<CatalogueSource>
|
||||
|
||||
fun getStubSources(): List<StubMangaSource>
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue