breaking changes!!!

-moved a bunch of classes to the package called animesource
-implemented a downloader that (barely) works
This commit is contained in:
jmir1 2021-05-27 22:13:27 +02:00
parent 58c954e1c3
commit 6461ea42dc
101 changed files with 583 additions and 471 deletions

View file

@ -2,6 +2,7 @@ package eu.kanade.tachiyomi
import android.app.Application
import android.os.Handler
import eu.kanade.tachiyomi.animesource.AnimeSourceManager
import eu.kanade.tachiyomi.data.cache.AnimeCoverCache
import eu.kanade.tachiyomi.data.cache.ChapterCache
import eu.kanade.tachiyomi.data.cache.CoverCache
@ -15,7 +16,6 @@ import eu.kanade.tachiyomi.data.track.TrackManager
import eu.kanade.tachiyomi.extension.AnimeExtensionManager
import eu.kanade.tachiyomi.extension.ExtensionManager
import eu.kanade.tachiyomi.network.NetworkHelper
import eu.kanade.tachiyomi.source.AnimeSourceManager
import eu.kanade.tachiyomi.source.SourceManager
import kotlinx.serialization.json.Json
import uy.kohesive.injekt.api.InjektModule

View file

@ -1,7 +1,7 @@
package eu.kanade.tachiyomi.source
package eu.kanade.tachiyomi.animesource
import eu.kanade.tachiyomi.source.model.AnimesPage
import eu.kanade.tachiyomi.source.model.FilterList
import eu.kanade.tachiyomi.animesource.model.AnimesPage
import eu.kanade.tachiyomi.animesource.model.FilterList
import rx.Observable
interface AnimeCatalogueSource : AnimeSource {

View file

@ -0,0 +1,30 @@
package eu.kanade.tachiyomi.animesource
import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.animesource.online.AnimeHttpSource
import rx.Observable
import timber.log.Timber
fun AnimeHttpSource.getImageUrl(video: Video): Observable<Video> {
Timber.w("getImageUrl")
video.status = Video.LOAD_VIDEO
return fetchVideoLink(video)
.doOnError { video.status = Video.ERROR }
.onErrorReturn { null }
.doOnNext { video.videoUrl = it }
.map { video }
}
fun AnimeHttpSource.fetchUrlFromVideo(video: Video): Observable<Video> {
Timber.w("fetchUrlFromVideo")
return Observable.just(video)
.filter { !it.url.isEmpty() }
.mergeWith(fetchRemainingImageUrlsFromPageList(video))
}
fun AnimeHttpSource.fetchRemainingImageUrlsFromPageList(video: Video): Observable<Video> {
Timber.w("fetchRemainingImageUrlsFromPageList")
return Observable.just(video)
.filter { it.url.isEmpty() }
.concatMap { getImageUrl(it) }
}

View file

@ -1,24 +1,24 @@
package eu.kanade.tachiyomi.source
package eu.kanade.tachiyomi.animesource
import android.graphics.drawable.Drawable
import eu.kanade.tachiyomi.animesource.model.SAnime
import eu.kanade.tachiyomi.animesource.model.SEpisode
import eu.kanade.tachiyomi.animesource.model.toAnimeInfo
import eu.kanade.tachiyomi.animesource.model.toEpisodeInfo
import eu.kanade.tachiyomi.animesource.model.toSAnime
import eu.kanade.tachiyomi.animesource.model.toSEpisode
import eu.kanade.tachiyomi.extension.AnimeExtensionManager
import eu.kanade.tachiyomi.source.model.SAnime
import eu.kanade.tachiyomi.source.model.SEpisode
import eu.kanade.tachiyomi.source.model.toAnimeInfo
import eu.kanade.tachiyomi.source.model.toEpisodeInfo
import eu.kanade.tachiyomi.source.model.toSAnime
import eu.kanade.tachiyomi.source.model.toSEpisode
import eu.kanade.tachiyomi.util.lang.awaitSingle
import rx.Observable
import tachiyomi.source.model.AnimeInfo
import tachiyomi.source.model.EpisodeInfo
import tachiyomi.animesource.model.AnimeInfo
import tachiyomi.animesource.model.EpisodeInfo
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
/**
* A basic interface for creating a source. It could be an online source, a local source, etc...
*/
interface AnimeSource : tachiyomi.source.AnimeSource {
interface AnimeSource : tachiyomi.animesource.AnimeSource {
/**
* Id for the source. Must be unique.

View file

@ -1,4 +1,4 @@
package eu.kanade.tachiyomi.source
package eu.kanade.tachiyomi.animesource
/**
* A factory for creating sources at runtime.

View file

@ -1,10 +1,10 @@
package eu.kanade.tachiyomi.source
package eu.kanade.tachiyomi.animesource
import android.content.Context
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.source.model.SAnime
import eu.kanade.tachiyomi.source.model.SEpisode
import eu.kanade.tachiyomi.source.online.AnimeHttpSource
import eu.kanade.tachiyomi.animesource.model.SAnime
import eu.kanade.tachiyomi.animesource.model.SEpisode
import eu.kanade.tachiyomi.animesource.online.AnimeHttpSource
import rx.Observable
open class AnimeSourceManager(private val context: Context) {

View file

@ -1,4 +1,4 @@
package eu.kanade.tachiyomi.source
package eu.kanade.tachiyomi.animesource
import androidx.preference.PreferenceScreen

View file

@ -1,14 +1,14 @@
package eu.kanade.tachiyomi.source
package eu.kanade.tachiyomi.animesource
import android.content.Context
import com.github.junrar.Archive
import com.google.gson.JsonParser
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.source.model.AnimesPage
import eu.kanade.tachiyomi.source.model.Filter
import eu.kanade.tachiyomi.source.model.FilterList
import eu.kanade.tachiyomi.source.model.SAnime
import eu.kanade.tachiyomi.source.model.SEpisode
import eu.kanade.tachiyomi.animesource.model.AnimesPage
import eu.kanade.tachiyomi.animesource.model.Filter
import eu.kanade.tachiyomi.animesource.model.FilterList
import eu.kanade.tachiyomi.animesource.model.SAnime
import eu.kanade.tachiyomi.animesource.model.SEpisode
import eu.kanade.tachiyomi.util.episode.EpisodeRecognition
import eu.kanade.tachiyomi.util.lang.compareToCaseInsensitiveNaturalOrder
import eu.kanade.tachiyomi.util.storage.AnimeFile

View file

@ -1,3 +1,3 @@
package eu.kanade.tachiyomi.source.model
package eu.kanade.tachiyomi.animesource.model
data class AnimesPage(val animes: List<SAnime>, val hasNextPage: Boolean)

View file

@ -0,0 +1,40 @@
package eu.kanade.tachiyomi.animesource.model
sealed class Filter<T>(val name: String, var state: T) {
open class Header(name: String) : Filter<Any>(name, 0)
open class Separator(name: String = "") : Filter<Any>(name, 0)
abstract class Select<V>(name: String, val values: Array<V>, state: Int = 0) : Filter<Int>(name, state)
abstract class Text(name: String, state: String = "") : Filter<String>(name, state)
abstract class CheckBox(name: String, state: Boolean = false) : Filter<Boolean>(name, state)
abstract class TriState(name: String, state: Int = STATE_IGNORE) : Filter<Int>(name, state) {
fun isIgnored() = state == STATE_IGNORE
fun isIncluded() = state == STATE_INCLUDE
fun isExcluded() = state == STATE_EXCLUDE
companion object {
const val STATE_IGNORE = 0
const val STATE_INCLUDE = 1
const val STATE_EXCLUDE = 2
}
}
abstract class Group<V>(name: String, state: List<V>) : Filter<List<V>>(name, state)
abstract class Sort(name: String, val values: Array<String>, state: Selection? = null) :
Filter<Sort.Selection?>(name, state) {
data class Selection(val index: Int, val ascending: Boolean)
}
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other !is Filter<*>) return false
return name == other.name && state == other.state
}
override fun hashCode(): Int {
var result = name.hashCode()
result = 31 * result + (state?.hashCode() ?: 0)
return result
}
}

View file

@ -0,0 +1,6 @@
package eu.kanade.tachiyomi.animesource.model
data class FilterList(val list: List<Filter<*>>) : List<Filter<*>> by list {
constructor(vararg fs: Filter<*>) : this(if (fs.isNotEmpty()) fs.asList() else emptyList())
}

View file

@ -1,6 +1,6 @@
package eu.kanade.tachiyomi.source.model
package eu.kanade.tachiyomi.animesource.model
import tachiyomi.source.model.AnimeInfo
import tachiyomi.animesource.model.AnimeInfo
import java.io.Serializable
interface SAnime : Serializable {

View file

@ -1,4 +1,4 @@
package eu.kanade.tachiyomi.source.model
package eu.kanade.tachiyomi.animesource.model
class SAnimeImpl : SAnime {

View file

@ -1,6 +1,6 @@
package eu.kanade.tachiyomi.source.model
package eu.kanade.tachiyomi.animesource.model
import tachiyomi.source.model.EpisodeInfo
import tachiyomi.animesource.model.EpisodeInfo
import java.io.Serializable
interface SEpisode : Serializable {

View file

@ -1,4 +1,4 @@
package eu.kanade.tachiyomi.source.model
package eu.kanade.tachiyomi.animesource.model
class SEpisodeImpl : SEpisode {

View file

@ -0,0 +1,72 @@
package eu.kanade.tachiyomi.animesource.model
import android.net.Uri
import eu.kanade.tachiyomi.network.ProgressListener
import rx.subjects.Subject
import tachiyomi.animesource.model.VideoUrl
open class Video(
val url: String = "",
var videoUrl: String? = null,
@Transient var uri: Uri? = null // Deprecated but can't be deleted due to extensions
) : ProgressListener {
@Transient
@Volatile
var status: Int = 0
set(value) {
field = value
statusSubject?.onNext(value)
statusCallback?.invoke(this)
}
@Transient
@Volatile
var progress: Int = 0
set(value) {
field = value
statusCallback?.invoke(this)
}
@Transient
private var statusSubject: Subject<Int, Int>? = null
@Transient
private var statusCallback: ((Video) -> Unit)? = null
override fun update(bytesRead: Long, contentLength: Long, done: Boolean) {
progress = if (contentLength > 0) {
(100 * bytesRead / contentLength).toInt()
} else {
-1
}
}
fun setStatusSubject(subject: Subject<Int, Int>?) {
this.statusSubject = subject
}
fun setStatusCallback(f: ((Video) -> Unit)?) {
statusCallback = f
}
companion object {
const val QUEUE = 0
const val LOAD_VIDEO = 1
const val DOWNLOAD_IMAGE = 2
const val READY = 3
const val ERROR = 4
}
}
fun Video.toVideoUrl(): VideoUrl {
return VideoUrl(
url = this.videoUrl ?: this.url
)
}
fun VideoUrl.toVideo(index: Int): Video {
return Video(
videoUrl = this.url
)
}

View file

@ -1,20 +1,19 @@
package eu.kanade.tachiyomi.source.online
package eu.kanade.tachiyomi.animesource.online
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.network.NetworkHelper
import eu.kanade.tachiyomi.network.asObservableSuccess
import eu.kanade.tachiyomi.network.newCallWithProgress
import eu.kanade.tachiyomi.source.AnimeCatalogueSource
import eu.kanade.tachiyomi.source.model.AnimesPage
import eu.kanade.tachiyomi.source.model.FilterList
import eu.kanade.tachiyomi.source.model.Page
import eu.kanade.tachiyomi.source.model.SAnime
import eu.kanade.tachiyomi.source.model.SEpisode
import android.net.Uri
import eu.kanade.tachiyomi.animesource.AnimeCatalogueSource
import eu.kanade.tachiyomi.animesource.model.AnimesPage
import eu.kanade.tachiyomi.animesource.model.FilterList
import eu.kanade.tachiyomi.animesource.model.SAnime
import eu.kanade.tachiyomi.animesource.model.SEpisode
import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.network.*
import okhttp3.Headers
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.Response
import rx.Observable
import timber.log.Timber
import uy.kohesive.injekt.injectLazy
import java.net.URI
import java.net.URISyntaxException
@ -226,6 +225,67 @@ abstract class AnimeHttpSource : AnimeCatalogueSource {
}
}
/**
* Returns an observable with the page containing the source url of the image. If there's any
* error, it will return null instead of throwing an exception.
*
* @param page the page whose source image has to be fetched.
*/
open fun fetchVideoLink(video: Video): Observable<String> {
Timber.w("fetchVideoLink")
return client.newCall(videoUrlRequest(video))
.asObservableSuccess()
.map { videoUrlParse(it) }
}
/**
* Returns the request for getting the url to the source image. Override only if it's needed to
* override the url, send different headers or request method like POST.
*
* @param video the episode whose page list has to be fetched
*/
protected open fun videoUrlRequest(video: Video): Request {
return GET(video.url, headers)
}
/**
* Parses the response from the site and returns the absolute url to the source image.
*
* @param response the response from the site.
*/
protected abstract fun videoUrlParse(response: Response): String
/**
* Returns an observable with the response of the source image.
*
* @param page the page whose source image has to be downloaded.
*/
fun fetchVideo(page: Video): Observable<Response> {
return client.newCallWithProgress(videoRequest(page), page)
.asObservableSuccess()
}
/**
* Returns the request for getting the source image. Override only if it's needed to override
* the url, send different headers or request method like POST.
*
* @param video the episode whose page list has to be fetched
*/
protected open fun videoRequest(video: Video): Request {
return GET(video.videoUrl!!, headers)
}
/**
* Returns an observable with the page list for a chapter.
*
* @param chapter the chapter whose page list has to be fetched.
*/
fun fetchVideoList(episode: SEpisode): Observable<Video> {
return client.newCall(episodeLinkRequest(episode))
.asObservableSuccess()
.map { response -> val link = episodeLinkParse(response); Video(link, link, Uri.parse(link)) }
}
/**
* Returns the request for updating the episode list. Override only if it's needed to override
* the url, send different headers or request method like POST.
@ -260,72 +320,6 @@ abstract class AnimeHttpSource : AnimeCatalogueSource {
*/
protected abstract fun episodeLinkParse(response: Response): String
/**
* Returns the request for getting the page list. Override only if it's needed to override the
* url, send different headers or request method like POST.
*
* @param episode the episode whose page list has to be fetched.
*/
protected open fun pageListRequest(episode: SEpisode): Request {
return GET(baseUrl + episode.url, headers)
}
/**
* Parses the response from the site and returns a list of pages.
*
* @param response the response from the site.
*/
protected abstract fun pageListParse(response: Response): List<Page>
/**
* Returns an observable with the page containing the source url of the image. If there's any
* error, it will return null instead of throwing an exception.
*
* @param page the page whose source image has to be fetched.
*/
open fun fetchImageUrl(page: Page): Observable<String> {
return client.newCall(imageUrlRequest(page))
.asObservableSuccess()
.map { imageUrlParse(it) }
}
/**
* Returns the request for getting the url to the source image. Override only if it's needed to
* override the url, send different headers or request method like POST.
*
* @param page the episode whose page list has to be fetched
*/
protected open fun imageUrlRequest(page: Page): Request {
return GET(page.url, headers)
}
/**
* Parses the response from the site and returns the absolute url to the source image.
*
* @param response the response from the site.
*/
protected abstract fun imageUrlParse(response: Response): String
/**
* Returns an observable with the response of the source image.
*
* @param page the page whose source image has to be downloaded.
*/
fun fetchImage(page: Page): Observable<Response> {
return client.newCallWithProgress(imageRequest(page), page)
.asObservableSuccess()
}
/**
* Returns the request for getting the source image. Override only if it's needed to override
* the url, send different headers or request method like POST.
*
* @param page the episode whose page list has to be fetched
*/
protected open fun imageRequest(page: Page): Request {
return GET(page.imageUrl!!, headers)
}
/**
* Assigns the url of the episode without the scheme and domain. It saves some redundancy from
* database and the urls could still work after a domain change.

View file

@ -1,9 +1,8 @@
package eu.kanade.tachiyomi.source.online
package eu.kanade.tachiyomi.animesource.online
import eu.kanade.tachiyomi.source.model.AnimesPage
import eu.kanade.tachiyomi.source.model.Page
import eu.kanade.tachiyomi.source.model.SAnime
import eu.kanade.tachiyomi.source.model.SEpisode
import eu.kanade.tachiyomi.animesource.model.AnimesPage
import eu.kanade.tachiyomi.animesource.model.SAnime
import eu.kanade.tachiyomi.animesource.model.SEpisode
import eu.kanade.tachiyomi.util.asJsoup
import okhttp3.Response
import org.jsoup.nodes.Document
@ -187,36 +186,4 @@ abstract class ParsedAnimeHttpSource : AnimeHttpSource() {
* @param element an element obtained from [episodeListSelector].
*/
protected abstract fun linkFromElement(element: Element): String
/**
* Parses the response from the site and returns the page list.
*
* @param response the response from the site.
*/
override fun pageListParse(response: Response): List<Page> {
return pageListParse(response.asJsoup())
}
/**
* Returns a page list from the given document.
*
* @param document the parsed document.
*/
protected abstract fun pageListParse(document: Document): List<Page>
/**
* Parse the response from the site and returns the absolute url to the source image.
*
* @param response the response from the site.
*/
override fun imageUrlParse(response: Response): String {
return imageUrlParse(response.asJsoup())
}
/**
* Returns the absolute url to the source image from the document.
*
* @param document the parsed document.
*/
protected abstract fun imageUrlParse(document: Document): String
}

View file

@ -7,6 +7,10 @@ import android.os.IBinder
import android.os.PowerManager
import androidx.core.content.ContextCompat
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.animesource.AnimeSourceManager
import eu.kanade.tachiyomi.animesource.model.SAnime
import eu.kanade.tachiyomi.animesource.model.toSAnime
import eu.kanade.tachiyomi.animesource.model.toSEpisode
import eu.kanade.tachiyomi.data.animelib.AnimelibUpdateRanker.rankingScheme
import eu.kanade.tachiyomi.data.animelib.AnimelibUpdateService.Companion.start
import eu.kanade.tachiyomi.data.cache.AnimeCoverCache
@ -23,10 +27,6 @@ import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.data.track.TrackManager
import eu.kanade.tachiyomi.data.track.TrackService
import eu.kanade.tachiyomi.data.track.UnattendedTrackService
import eu.kanade.tachiyomi.source.AnimeSourceManager
import eu.kanade.tachiyomi.source.model.SAnime
import eu.kanade.tachiyomi.source.model.toSAnime
import eu.kanade.tachiyomi.source.model.toSEpisode
import eu.kanade.tachiyomi.util.episode.NoEpisodesException
import eu.kanade.tachiyomi.util.episode.syncEpisodesWithSource
import eu.kanade.tachiyomi.util.episode.syncEpisodesWithTrackServiceTwoWay

View file

@ -2,6 +2,8 @@ package eu.kanade.tachiyomi.data.backup
import android.content.Context
import android.net.Uri
import eu.kanade.tachiyomi.animesource.AnimeSource
import eu.kanade.tachiyomi.animesource.model.toSEpisode
import eu.kanade.tachiyomi.data.database.AnimeDatabaseHelper
import eu.kanade.tachiyomi.data.database.DatabaseHelper
import eu.kanade.tachiyomi.data.database.models.Anime
@ -12,11 +14,9 @@ import eu.kanade.tachiyomi.data.database.models.toAnimeInfo
import eu.kanade.tachiyomi.data.database.models.toMangaInfo
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.data.track.TrackManager
import eu.kanade.tachiyomi.source.AnimeSource
import eu.kanade.tachiyomi.source.Source
import eu.kanade.tachiyomi.source.SourceManager
import eu.kanade.tachiyomi.source.model.toSChapter
import eu.kanade.tachiyomi.source.model.toSEpisode
import eu.kanade.tachiyomi.util.chapter.syncChaptersWithSource
import eu.kanade.tachiyomi.util.episode.syncEpisodesWithSource
import uy.kohesive.injekt.injectLazy

View file

@ -8,6 +8,8 @@ import com.github.salomonbrys.kotson.registerTypeHierarchyAdapter
import com.google.gson.Gson
import com.google.gson.GsonBuilder
import com.google.gson.JsonArray
import eu.kanade.tachiyomi.animesource.AnimeSource
import eu.kanade.tachiyomi.animesource.model.toSAnime
import eu.kanade.tachiyomi.data.backup.AbstractBackupManager
import eu.kanade.tachiyomi.data.backup.legacy.models.Backup.CURRENT_VERSION
import eu.kanade.tachiyomi.data.backup.legacy.models.DHistory
@ -28,9 +30,7 @@ import eu.kanade.tachiyomi.data.database.models.Track
import eu.kanade.tachiyomi.data.database.models.TrackImpl
import eu.kanade.tachiyomi.data.database.models.toAnimeInfo
import eu.kanade.tachiyomi.data.database.models.toMangaInfo
import eu.kanade.tachiyomi.source.AnimeSource
import eu.kanade.tachiyomi.source.Source
import eu.kanade.tachiyomi.source.model.toSAnime
import eu.kanade.tachiyomi.source.model.toSManga
import kotlin.math.max

View file

@ -4,8 +4,8 @@ import android.content.Context
import android.text.format.Formatter
import com.google.gson.Gson
import com.jakewharton.disklrucache.DiskLruCache
import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.data.database.models.Episode
import eu.kanade.tachiyomi.source.model.Page
import eu.kanade.tachiyomi.util.storage.DiskUtil
import eu.kanade.tachiyomi.util.storage.saveTo
import okhttp3.Response
@ -97,9 +97,9 @@ class EpisodeCache(private val context: Context) {
* @param episode the episode.
* @param pages list of pages.
*/
fun putPageListToCache(episode: Episode, pages: List<Page>) {
fun putPageListToCache(episode: Episode, video: Video) {
// Convert list of pages to json string.
val cachedValue = gson.toJson(pages)
val cachedValue = gson.toJson(video)
// Initialize the editor (edits the values for an entry).
var editor: DiskLruCache.Editor? = null
@ -145,7 +145,7 @@ class EpisodeCache(private val context: Context) {
* @param imageUrl url of image.
* @return path of image.
*/
fun getImageFile(imageUrl: String): File {
fun getVideoFile(imageUrl: String): File {
// Get file from md5 key.
val imageName = DiskUtil.hashKeyForDisk(imageUrl) + ".0"
return File(diskCache.directory, imageName)

View file

@ -9,12 +9,12 @@ import coil.fetch.SourceResult
import coil.network.HttpException
import coil.request.get
import coil.size.Size
import eu.kanade.tachiyomi.animesource.AnimeSourceManager
import eu.kanade.tachiyomi.animesource.online.AnimeHttpSource
import eu.kanade.tachiyomi.data.cache.AnimeCoverCache
import eu.kanade.tachiyomi.data.database.models.Anime
import eu.kanade.tachiyomi.network.NetworkHelper
import eu.kanade.tachiyomi.network.await
import eu.kanade.tachiyomi.source.AnimeSourceManager
import eu.kanade.tachiyomi.source.online.AnimeHttpSource
import okhttp3.CacheControl
import okhttp3.Call
import okhttp3.Request

View file

@ -1,7 +1,7 @@
package eu.kanade.tachiyomi.data.database.models
import eu.kanade.tachiyomi.source.model.SAnime
import tachiyomi.source.model.AnimeInfo
import eu.kanade.tachiyomi.animesource.model.SAnime
import tachiyomi.animesource.model.AnimeInfo
interface Anime : SAnime {

View file

@ -1,6 +1,6 @@
package eu.kanade.tachiyomi.data.database.models
import eu.kanade.tachiyomi.source.model.SEpisode
import eu.kanade.tachiyomi.animesource.model.SEpisode
import java.io.Serializable
interface Episode : SEpisode, Serializable {

View file

@ -3,10 +3,10 @@ package eu.kanade.tachiyomi.data.download
import android.content.Context
import androidx.core.net.toUri
import com.hippo.unifile.UniFile
import eu.kanade.tachiyomi.animesource.AnimeSourceManager
import eu.kanade.tachiyomi.data.database.models.Anime
import eu.kanade.tachiyomi.data.database.models.Episode
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.source.AnimeSourceManager
import kotlinx.coroutines.flow.onEach
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get

View file

@ -4,14 +4,14 @@ import android.content.Context
import com.hippo.unifile.UniFile
import com.jakewharton.rxrelay.BehaviorRelay
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.animesource.AnimeSource
import eu.kanade.tachiyomi.animesource.AnimeSourceManager
import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.data.database.models.Anime
import eu.kanade.tachiyomi.data.database.models.Episode
import eu.kanade.tachiyomi.data.download.model.AnimeDownload
import eu.kanade.tachiyomi.data.download.model.AnimeDownloadQueue
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.source.AnimeSource
import eu.kanade.tachiyomi.source.AnimeSourceManager
import eu.kanade.tachiyomi.source.model.Page
import eu.kanade.tachiyomi.util.lang.launchIO
import rx.Observable
import timber.log.Timber
@ -137,8 +137,8 @@ class AnimeDownloadManager(private val context: Context) {
* @param episode the downloaded episode.
* @return an observable containing the list of pages from the episode.
*/
fun buildPageList(source: AnimeSource, anime: Anime, episode: Episode): Observable<List<Page>> {
return buildPageList(provider.findEpisodeDir(episode, anime, source))
fun buildVideo(source: AnimeSource, anime: Anime, episode: Episode): Observable<Video> {
return buildVideo(provider.findEpisodeDir(episode, anime, source))
}
/**
@ -147,19 +147,17 @@ class AnimeDownloadManager(private val context: Context) {
* @param episodeDir the file where the episode is downloaded.
* @return an observable containing the list of pages from the episode.
*/
private fun buildPageList(episodeDir: UniFile?): Observable<List<Page>> {
private fun buildVideo(episodeDir: UniFile?): Observable<Video> {
return Observable.fromCallable {
val files = episodeDir?.listFiles().orEmpty()
.filter { "image" in it.type.orEmpty() }
.filter { "video" in it.type.orEmpty() }
if (files.isEmpty()) {
throw Exception(context.getString(R.string.page_list_empty_error))
}
files.sortedBy { it.name }
.mapIndexed { i, file ->
Page(i, uri = file.uri).apply { status = Page.READY }
}
val file = files[0]
Video(uri = file.uri).apply { status = Video.READY }
}
}

View file

@ -100,7 +100,7 @@ internal class AnimeDownloadNotifier(private val context: Context) {
val downloadingProgressText = context.getString(
R.string.chapter_downloading_progress,
download.downloadedImages,
download.pages!!.size
1
)
if (preferences.hideNotificationContent()) {
@ -113,7 +113,7 @@ internal class AnimeDownloadNotifier(private val context: Context) {
setContentText(downloadingProgressText)
}
setProgress(download.pages!!.size, download.downloadedImages, false)
setProgress(1, download.downloadedImages, false)
setOngoing(true)
show(Notifications.ID_DOWNLOAD_CHAPTER_PROGRESS)

View file

@ -4,10 +4,10 @@ import android.content.Context
import androidx.core.net.toUri
import com.hippo.unifile.UniFile
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.animesource.AnimeSource
import eu.kanade.tachiyomi.data.database.models.Anime
import eu.kanade.tachiyomi.data.database.models.Episode
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.source.AnimeSource
import eu.kanade.tachiyomi.util.storage.DiskUtil
import kotlinx.coroutines.MainScope
import kotlinx.coroutines.flow.launchIn

View file

@ -2,11 +2,11 @@ package eu.kanade.tachiyomi.data.download
import android.content.Context
import androidx.core.content.edit
import eu.kanade.tachiyomi.animesource.AnimeSourceManager
import eu.kanade.tachiyomi.animesource.online.AnimeHttpSource
import eu.kanade.tachiyomi.data.database.AnimeDatabaseHelper
import eu.kanade.tachiyomi.data.database.models.Anime
import eu.kanade.tachiyomi.data.download.model.AnimeDownload
import eu.kanade.tachiyomi.source.AnimeSourceManager
import eu.kanade.tachiyomi.source.online.AnimeHttpSource
import kotlinx.serialization.Serializable
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.encodeToString

View file

@ -1,20 +1,21 @@
package eu.kanade.tachiyomi.data.download
import android.content.Context
import android.util.Log
import android.webkit.MimeTypeMap
import com.hippo.unifile.UniFile
import com.jakewharton.rxrelay.BehaviorRelay
import com.jakewharton.rxrelay.PublishRelay
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.animesource.AnimeSourceManager
import eu.kanade.tachiyomi.animesource.fetchUrlFromVideo
import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.animesource.online.AnimeHttpSource
import eu.kanade.tachiyomi.data.cache.EpisodeCache
import eu.kanade.tachiyomi.data.database.models.Anime
import eu.kanade.tachiyomi.data.database.models.Episode
import eu.kanade.tachiyomi.data.download.model.AnimeDownload
import eu.kanade.tachiyomi.data.download.model.AnimeDownloadQueue
import eu.kanade.tachiyomi.source.AnimeSourceManager
import eu.kanade.tachiyomi.source.model.Page
import eu.kanade.tachiyomi.source.online.AnimeHttpSource
import eu.kanade.tachiyomi.source.online.fetchAllImageUrlsFromPageList
import eu.kanade.tachiyomi.util.lang.RetryWithDelay
import eu.kanade.tachiyomi.util.lang.launchIO
import eu.kanade.tachiyomi.util.lang.launchNow
@ -257,7 +258,8 @@ class AnimeDownloader(
// Start downloader if needed
if (autoStart && wasEmpty) {
DownloadService.start(this@AnimeDownloader.context)
Log.w("start", "started")
AnimeDownloadService.start(this@AnimeDownloader.context)
}
}
}
@ -280,17 +282,25 @@ class AnimeDownloader(
val episodeDirname = provider.getEpisodeDirName(download.episode)
val tmpDir = animeDir.createDirectory(episodeDirname + TMP_DIR_SUFFIX)
val pageListObservable = if (download.pages == null) {
// Pull page list from network and add them to download object
Observable.just(emptyList())
val videoObservable = if (download.video == null) {
// Pull video from network and add them to download object
download.source.fetchVideoList(download.episode)
.doOnNext { video ->
if (video == null) {
Timber.w("mah m9")
throw Exception(context.getString(R.string.page_list_empty_error))
}
download.video = video
}
} else {
// Or if the page list already exists, start from the file
Observable.just(download.pages!!)
// Or if the video already exists, start from the file
Observable.just(download.video!!)
}
pageListObservable
videoObservable
.doOnNext { _ ->
// Delete all temporary (unfinished) files
Timber.w("delfiles")
tmpDir.listFiles()
?.filter { it.name!!.endsWith(".tmp") }
?.forEach { it.delete() }
@ -299,10 +309,10 @@ class AnimeDownloader(
download.status = AnimeDownload.State.DOWNLOADING
}
// Get all the URLs to the source images, fetch pages if necessary
.flatMap { download.source.fetchAllImageUrlsFromPageList(it) }
.flatMap { download.source.fetchUrlFromVideo(it) }
// Start downloading images, consider we can have downloaded images already
// Concurrently do 5 pages at a time
.flatMap({ page -> getOrAnimeDownloadImage(page, download, tmpDir) }, 5)
.flatMap({ video -> getOrAnimeDownloadImage(video, download, tmpDir) }, 5)
.onBackpressureLatest()
// Do when page is downloaded.
.doOnNext { notifier.onProgressChange(download) }
@ -322,61 +332,63 @@ class AnimeDownloader(
* Returns the observable which gets the image from the filesystem if it exists or downloads it
* otherwise.
*
* @param page the page to download.
* @param video the page to download.
* @param download the download of the page.
* @param tmpDir the temporary directory of the download.
*/
private fun getOrAnimeDownloadImage(page: Page, download: AnimeDownload, tmpDir: UniFile): Observable<Page> {
private fun getOrAnimeDownloadImage(video: Video, download: AnimeDownload, tmpDir: UniFile): Observable<Video> {
// If the image URL is empty, do nothing
if (page.imageUrl == null) {
return Observable.just(page)
if (video.videoUrl == null) {
Timber.w("nourl")
return Observable.just(video)
}
val filename = String.format("%03d", page.number)
val filename = download.episode.name
Timber.w(filename)
val tmpFile = tmpDir.findFile("$filename.tmp")
// Delete temp file if it exists.
tmpFile?.delete()
// Try to find the image file.
val imageFile = tmpDir.listFiles()!!.find { it.name!!.startsWith("$filename.") }
val videoFile = tmpDir.listFiles()!!.find { it.name!!.startsWith("$filename.") }
// If the image is already downloaded, do nothing. Otherwise download from network
// If the video is already downloaded, do nothing. Otherwise download from network
val pageObservable = when {
imageFile != null -> Observable.just(imageFile)
episodeCache.isImageInCache(page.imageUrl!!) -> copyImageFromCache(episodeCache.getImageFile(page.imageUrl!!), tmpDir, filename)
else -> downloadImage(page, download.source, tmpDir, filename)
videoFile != null -> Observable.just(videoFile)
episodeCache.isImageInCache(video.videoUrl!!) -> copyVideoFromCache(episodeCache.getVideoFile(video.videoUrl!!), tmpDir, filename)
else -> downloadVideo(video, download.source, tmpDir, filename)
}
return pageObservable
// When the image is ready, set image path, progress (just in case) and status
.doOnNext { file ->
page.uri = file.uri
page.progress = 100
video.uri = file.uri
video.progress = 100
download.downloadedImages++
page.status = Page.READY
video.status = Video.READY
}
.map { page }
.map { video }
// Mark this page as error and allow to download the remaining
.onErrorReturn {
page.progress = 0
page.status = Page.ERROR
page
video.progress = 0
video.status = Video.ERROR
video
}
}
/**
* Returns the observable which downloads the image from network.
*
* @param page the page to download.
* @param video the page to download.
* @param source the source of the page.
* @param tmpDir the temporary directory of the download.
* @param filename the filename of the image.
*/
private fun downloadImage(page: Page, source: AnimeHttpSource, tmpDir: UniFile, filename: String): Observable<UniFile> {
page.status = Page.DOWNLOAD_IMAGE
page.progress = 0
return source.fetchImage(page)
private fun downloadVideo(video: Video, source: AnimeHttpSource, tmpDir: UniFile, filename: String): Observable<UniFile> {
video.status = Video.DOWNLOAD_IMAGE
video.progress = 0
return source.fetchVideo(video)
.map { response ->
val file = tmpDir.createFile("$filename.tmp")
try {
@ -401,7 +413,7 @@ class AnimeDownloader(
* @param tmpDir the temporary directory of the download.
* @param filename the filename of the image.
*/
private fun copyImageFromCache(cacheFile: File, tmpDir: UniFile, filename: String): Observable<UniFile> {
private fun copyVideoFromCache(cacheFile: File, tmpDir: UniFile, filename: String): Observable<UniFile> {
return Observable.just(cacheFile).map {
val tmpFile = tmpDir.createFile("$filename.tmp")
cacheFile.inputStream().use { input ->
@ -451,7 +463,7 @@ class AnimeDownloader(
// Ensure that the episode folder has all the images.
val downloadedImages = tmpDir.listFiles().orEmpty().filterNot { it.name!!.endsWith(".tmp") }
download.status = if (downloadedImages.size == download.pages!!.size) {
download.status = if (downloadedImages.size == 1) {
AnimeDownload.State.DOWNLOADED
} else {
AnimeDownload.State.ERROR

View file

@ -1,14 +1,14 @@
package eu.kanade.tachiyomi.data.download.model
import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.animesource.online.AnimeHttpSource
import eu.kanade.tachiyomi.data.database.models.Anime
import eu.kanade.tachiyomi.data.database.models.Episode
import eu.kanade.tachiyomi.source.model.Page
import eu.kanade.tachiyomi.source.online.AnimeHttpSource
import rx.subjects.PublishSubject
class AnimeDownload(val source: AnimeHttpSource, val anime: Anime, val episode: Episode) {
var pages: List<Page>? = null
var video: Video? = null
@Volatile
@Transient
@ -35,8 +35,8 @@ class AnimeDownload(val source: AnimeHttpSource, val anime: Anime, val episode:
val progress: Int
get() {
val pages = pages ?: return 0
return pages.map(Page::progress).average().toInt()
val video = video ?: return 0
return video.progress
}
fun setStatusSubject(subject: PublishSubject<AnimeDownload>?) {

View file

@ -1,10 +1,10 @@
package eu.kanade.tachiyomi.data.download.model
import com.jakewharton.rxrelay.PublishRelay
import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.data.database.models.Anime
import eu.kanade.tachiyomi.data.database.models.Episode
import eu.kanade.tachiyomi.data.download.AnimeDownloadStore
import eu.kanade.tachiyomi.source.model.Page
import rx.Observable
import rx.subjects.PublishSubject
import java.util.concurrent.CopyOnWriteArrayList
@ -80,7 +80,7 @@ class AnimeDownloadQueue(
private fun setPagesFor(download: AnimeDownload) {
if (download.status == AnimeDownload.State.DOWNLOADED || download.status == AnimeDownload.State.ERROR) {
setPagesSubject(download.pages, null)
setPagesSubject(download.video, null)
}
}
@ -90,20 +90,20 @@ class AnimeDownloadQueue(
.flatMap { download ->
if (download.status == AnimeDownload.State.DOWNLOADING) {
val pageStatusSubject = PublishSubject.create<Int>()
setPagesSubject(download.pages, pageStatusSubject)
setPagesSubject(download.video, pageStatusSubject)
return@flatMap pageStatusSubject
.onBackpressureBuffer()
.filter { it == Page.READY }
.filter { it == Video.READY }
.map { download }
} else if (download.status == AnimeDownload.State.DOWNLOADED || download.status == AnimeDownload.State.ERROR) {
setPagesSubject(download.pages, null)
setPagesSubject(download.video, null)
}
Observable.just(download)
}
.filter { it.status == AnimeDownload.State.DOWNLOADING }
}
private fun setPagesSubject(pages: List<Page>?, subject: PublishSubject<Int>?) {
pages?.forEach { it.setStatusSubject(subject) }
private fun setPagesSubject(video: Video?, subject: PublishSubject<Int>?) {
video?.setStatusSubject(subject)
}
}

View file

@ -9,6 +9,7 @@ import android.net.Uri
import android.os.Build
import android.os.Handler
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.animesource.AnimeSourceManager
import eu.kanade.tachiyomi.data.animelib.AnimelibUpdateService
import eu.kanade.tachiyomi.data.backup.BackupRestoreService
import eu.kanade.tachiyomi.data.database.DatabaseHelper
@ -20,29 +21,24 @@ import eu.kanade.tachiyomi.data.download.DownloadManager
import eu.kanade.tachiyomi.data.download.DownloadService
import eu.kanade.tachiyomi.data.library.LibraryUpdateService
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.source.AnimeSourceManager
import eu.kanade.tachiyomi.source.SourceManager
import eu.kanade.tachiyomi.source.model.toEpisodeInfo
import eu.kanade.tachiyomi.ui.anime.AnimeController
import eu.kanade.tachiyomi.ui.anime.episode.EpisodeItem
import eu.kanade.tachiyomi.ui.main.MainActivity
import eu.kanade.tachiyomi.ui.manga.MangaController
import eu.kanade.tachiyomi.ui.reader.ReaderActivity
import eu.kanade.tachiyomi.ui.watcher.EpisodeLoader
import eu.kanade.tachiyomi.ui.watcher.WatcherActivity
import eu.kanade.tachiyomi.util.lang.launchIO
import eu.kanade.tachiyomi.util.lang.withUIContext
import eu.kanade.tachiyomi.util.storage.DiskUtil
import eu.kanade.tachiyomi.util.storage.getUriCompat
import eu.kanade.tachiyomi.util.system.notificationManager
import eu.kanade.tachiyomi.util.system.toast
import kotlinx.coroutines.runBlocking
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import uy.kohesive.injekt.injectLazy
import java.io.File
import java.util.Collections.emptyList
import kotlin.coroutines.resume
import kotlin.coroutines.suspendCoroutine
import eu.kanade.tachiyomi.BuildConfig.APPLICATION_ID as ID
/**
@ -441,19 +437,7 @@ class NotificationReceiver : BroadcastReceiver() {
*/
internal fun openEpisodePendingActivity(context: Context, anime: Anime, episode: Episode): PendingIntent {
val source = Injekt.get<AnimeSourceManager>().getOrStub(anime.source)
val link = runBlocking {
return@runBlocking suspendCoroutine<String> { continuation ->
var link: String
launchIO {
try {
link = source.getEpisodeLink(episode.toEpisodeInfo())
continuation.resume(link)
} catch (e: Throwable) {
withUIContext { throw e }
}
}
}
}
val link = EpisodeLoader.getUri(episode, anime, source)
val episodeList: List<EpisodeItem> = emptyList()
val newIntent = WatcherActivity.newIntent(context, anime, episode, episodeList, link)
return PendingIntent.getActivity(context, AnimeController.REQUEST_INTERNAL, newIntent, PendingIntent.FLAG_UPDATE_CURRENT)

View file

@ -1,10 +1,10 @@
package eu.kanade.tachiyomi.data.track
import eu.kanade.tachiyomi.animesource.AnimeSource
import eu.kanade.tachiyomi.data.database.models.Anime
import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.data.track.model.AnimeTrackSearch
import eu.kanade.tachiyomi.data.track.model.TrackSearch
import eu.kanade.tachiyomi.source.AnimeSource
import eu.kanade.tachiyomi.source.Source
/**

View file

@ -4,6 +4,7 @@ import android.content.Context
import android.graphics.Color
import androidx.annotation.StringRes
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.animesource.AnimeSource
import eu.kanade.tachiyomi.data.database.models.Anime
import eu.kanade.tachiyomi.data.database.models.AnimeTrack
import eu.kanade.tachiyomi.data.database.models.Manga
@ -13,7 +14,6 @@ import eu.kanade.tachiyomi.data.track.TrackService
import eu.kanade.tachiyomi.data.track.UnattendedTrackService
import eu.kanade.tachiyomi.data.track.model.AnimeTrackSearch
import eu.kanade.tachiyomi.data.track.model.TrackSearch
import eu.kanade.tachiyomi.source.AnimeSource
import eu.kanade.tachiyomi.source.Source
import okhttp3.Dns
import okhttp3.OkHttpClient

View file

@ -3,6 +3,8 @@ package eu.kanade.tachiyomi.extension
import android.content.Context
import android.graphics.drawable.Drawable
import com.jakewharton.rxrelay.BehaviorRelay
import eu.kanade.tachiyomi.animesource.AnimeSource
import eu.kanade.tachiyomi.animesource.AnimeSourceManager
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.data.preference.plusAssign
import eu.kanade.tachiyomi.extension.api.AnimeExtensionGithubApi
@ -12,8 +14,6 @@ import eu.kanade.tachiyomi.extension.model.InstallStep
import eu.kanade.tachiyomi.extension.util.AnimeExtensionInstallReceiver
import eu.kanade.tachiyomi.extension.util.AnimeExtensionInstaller
import eu.kanade.tachiyomi.extension.util.AnimeExtensionLoader
import eu.kanade.tachiyomi.source.AnimeSource
import eu.kanade.tachiyomi.source.AnimeSourceManager
import eu.kanade.tachiyomi.util.lang.launchNow
import eu.kanade.tachiyomi.util.system.toast
import kotlinx.coroutines.async

View file

@ -1,6 +1,6 @@
package eu.kanade.tachiyomi.extension.model
import eu.kanade.tachiyomi.source.AnimeSource
import eu.kanade.tachiyomi.animesource.AnimeSource
sealed class AnimeExtension {

View file

@ -5,13 +5,13 @@ import android.content.Context
import android.content.pm.PackageInfo
import android.content.pm.PackageManager
import dalvik.system.PathClassLoader
import eu.kanade.tachiyomi.animesource.AnimeCatalogueSource
import eu.kanade.tachiyomi.animesource.AnimeSource
import eu.kanade.tachiyomi.animesource.AnimeSourceFactory
import eu.kanade.tachiyomi.annotations.Nsfw
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.extension.model.AnimeExtension
import eu.kanade.tachiyomi.extension.model.AnimeLoadResult
import eu.kanade.tachiyomi.source.AnimeCatalogueSource
import eu.kanade.tachiyomi.source.AnimeSource
import eu.kanade.tachiyomi.source.AnimeSourceFactory
import eu.kanade.tachiyomi.util.lang.Hash
import kotlinx.coroutines.async
import kotlinx.coroutines.runBlocking

View file

@ -1,25 +0,0 @@
package eu.kanade.tachiyomi.source.online
import eu.kanade.tachiyomi.source.model.Page
import rx.Observable
fun AnimeHttpSource.getImageUrl(page: Page): Observable<Page> {
page.status = Page.LOAD_PAGE
return fetchImageUrl(page)
.doOnError { page.status = Page.ERROR }
.onErrorReturn { null }
.doOnNext { page.imageUrl = it }
.map { page }
}
fun AnimeHttpSource.fetchAllImageUrlsFromPageList(pages: List<Page>): Observable<Page> {
return Observable.from(pages)
.filter { !it.imageUrl.isNullOrEmpty() }
.mergeWith(fetchRemainingImageUrlsFromPageList(pages))
}
fun AnimeHttpSource.fetchRemainingImageUrlsFromPageList(pages: List<Page>): Observable<Page> {
return Observable.from(pages)
.filter { it.imageUrl.isNullOrEmpty() }
.concatMap { getImageUrl(it) }
}

View file

@ -26,6 +26,10 @@ import dev.chrisbanes.insetter.applyInsetter
import eu.davidea.flexibleadapter.FlexibleAdapter
import eu.davidea.flexibleadapter.SelectableAdapter
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.animesource.AnimeSource
import eu.kanade.tachiyomi.animesource.AnimeSourceManager
import eu.kanade.tachiyomi.animesource.LocalAnimeSource
import eu.kanade.tachiyomi.animesource.online.AnimeHttpSource
import eu.kanade.tachiyomi.data.cache.AnimeCoverCache
import eu.kanade.tachiyomi.data.database.AnimeDatabaseHelper
import eu.kanade.tachiyomi.data.database.models.Anime
@ -41,10 +45,6 @@ import eu.kanade.tachiyomi.data.track.TrackService
import eu.kanade.tachiyomi.data.track.UnattendedTrackService
import eu.kanade.tachiyomi.data.track.model.AnimeTrackSearch
import eu.kanade.tachiyomi.databinding.AnimeControllerBinding
import eu.kanade.tachiyomi.source.AnimeSource
import eu.kanade.tachiyomi.source.AnimeSourceManager
import eu.kanade.tachiyomi.source.LocalSource
import eu.kanade.tachiyomi.source.online.AnimeHttpSource
import eu.kanade.tachiyomi.ui.anime.episode.*
import eu.kanade.tachiyomi.ui.anime.episode.base.BaseEpisodesAdapter
import eu.kanade.tachiyomi.ui.anime.info.AnimeInfoHeaderAdapter
@ -65,6 +65,7 @@ import eu.kanade.tachiyomi.ui.browse.migration.search.AnimeSearchController
import eu.kanade.tachiyomi.ui.main.MainActivity
import eu.kanade.tachiyomi.ui.recent.history.HistoryController
import eu.kanade.tachiyomi.ui.recent.updates.UpdatesController
import eu.kanade.tachiyomi.ui.watcher.EpisodeLoader
import eu.kanade.tachiyomi.ui.watcher.WatcherActivity
import eu.kanade.tachiyomi.ui.webview.WebViewActivity
import eu.kanade.tachiyomi.util.episode.NoEpisodesException
@ -80,8 +81,6 @@ import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import reactivecircus.flowbinding.recyclerview.scrollEvents
import reactivecircus.flowbinding.swiperefreshlayout.refreshes
import rx.schedulers.Schedulers
@ -163,7 +162,7 @@ class AnimeController :
*/
private val selectedEpisodes = mutableSetOf<EpisodeItem>()
private val isLocalSource by lazy { presenter.source.id == LocalSource.ID }
private val isLocalSource by lazy { presenter.source.id == LocalAnimeSource.ID }
private var lastClickPositionStack = ArrayDeque(listOf(-1))
@ -337,7 +336,7 @@ class AnimeController :
// Create animation listener
val revealAnimationListener: Animator.AnimatorListener = object : AnimatorListenerAdapter() {
override fun onAnimationStart(animation: Animator?) {
openEpisode(item.episode, true)
openEpisode(item.episode)
}
}
@ -348,7 +347,7 @@ class AnimeController :
coordinates.y,
object : AnimatorListenerAdapter() {
override fun onAnimationStart(animation: Animator?) {
openEpisode(item.episode, true)
openEpisode(item.episode)
}
}
)
@ -901,23 +900,18 @@ class AnimeController :
}
}
fun openEpisode(episode: Episode, hasAnimation: Boolean = false) {
fun openEpisode(episode: Episode) {
val activity = activity ?: return
runBlocking {
launch {
val url = fetchEpisodeLinksFromSource(false, episode)
launchIO {
val url = EpisodeLoader.getUri(episode, anime!!, source!!)
val episodeList = presenter.filteredAndSortedEpisodes
val intent = WatcherActivity.newIntent(activity, presenter.anime, episode, episodeList, url)
if (hasAnimation) {
intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION)
}
if (!preferences.alwaysUseExternalPlayer()) {
startActivityForResult(intent, REQUEST_INTERNAL)
} else {
currentExtEpisode = episode
val uri = Uri.parse(url)
val extIntent = Intent(Intent.ACTION_VIEW)
extIntent.setDataAndTypeAndNormalize(uri, "video/*")
extIntent.setDataAndTypeAndNormalize(Uri.parse(url), "video/*")
extIntent.putExtra("title", episode.name)
extIntent.putExtra("position", episode.last_second_seen.toInt())
extIntent.putExtra("return_result", true)
@ -925,7 +919,6 @@ class AnimeController :
}
}
}
}
override fun onItemClick(view: View?, position: Int): Boolean {
val adapter = episodesAdapter ?: return false

View file

@ -4,6 +4,11 @@ import android.content.Context
import android.net.Uri
import android.os.Bundle
import com.jakewharton.rxrelay.PublishRelay
import eu.kanade.tachiyomi.animesource.AnimeSource
import eu.kanade.tachiyomi.animesource.LocalAnimeSource
import eu.kanade.tachiyomi.animesource.model.toEpisodeInfo
import eu.kanade.tachiyomi.animesource.model.toSAnime
import eu.kanade.tachiyomi.animesource.model.toSEpisode
import eu.kanade.tachiyomi.data.cache.AnimeCoverCache
import eu.kanade.tachiyomi.data.database.AnimeDatabaseHelper
import eu.kanade.tachiyomi.data.database.models.Anime
@ -18,11 +23,6 @@ import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.data.track.TrackManager
import eu.kanade.tachiyomi.data.track.TrackService
import eu.kanade.tachiyomi.data.track.UnattendedTrackService
import eu.kanade.tachiyomi.source.AnimeSource
import eu.kanade.tachiyomi.source.LocalAnimeSource
import eu.kanade.tachiyomi.source.model.toEpisodeInfo
import eu.kanade.tachiyomi.source.model.toSAnime
import eu.kanade.tachiyomi.source.model.toSEpisode
import eu.kanade.tachiyomi.ui.anime.episode.EpisodeItem
import eu.kanade.tachiyomi.ui.anime.track.TrackItem
import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter

View file

@ -6,9 +6,9 @@ import androidx.core.text.buildSpannedString
import androidx.core.text.color
import androidx.core.view.isVisible
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.animesource.LocalAnimeSource
import eu.kanade.tachiyomi.data.database.models.Anime
import eu.kanade.tachiyomi.databinding.EpisodesItemBinding
import eu.kanade.tachiyomi.source.LocalSource
import eu.kanade.tachiyomi.ui.anime.episode.base.BaseEpisodeHolder
import java.util.Date
import java.util.concurrent.TimeUnit
@ -93,7 +93,7 @@ class EpisodeHolder(
binding.episodeDescription.text = ""
}
binding.animedownload.isVisible = item.anime.source != LocalSource.ID
binding.animedownload.isVisible = item.anime.source != LocalAnimeSource.ID
binding.animedownload.setState(item.status, item.progress)
}
}

View file

@ -4,7 +4,6 @@ import eu.davidea.flexibleadapter.items.AbstractHeaderItem
import eu.davidea.flexibleadapter.items.AbstractSectionableItem
import eu.kanade.tachiyomi.data.database.models.Episode
import eu.kanade.tachiyomi.data.download.model.AnimeDownload
import eu.kanade.tachiyomi.source.model.Page
abstract class BaseEpisodeItem<T : BaseEpisodeHolder, H : AbstractHeaderItem<*>>(
val episode: Episode,
@ -23,8 +22,8 @@ abstract class BaseEpisodeItem<T : BaseEpisodeHolder, H : AbstractHeaderItem<*>>
val progress: Int
get() {
val pages = download?.pages ?: return 0
return pages.map(Page::progress).average().toInt()
val video = download?.video ?: return 0
return video.progress
}
@Transient

View file

@ -7,13 +7,13 @@ import androidx.core.view.isVisible
import androidx.recyclerview.widget.RecyclerView
import coil.loadAny
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.animesource.AnimeSource
import eu.kanade.tachiyomi.animesource.AnimeSourceManager
import eu.kanade.tachiyomi.animesource.model.SAnime
import eu.kanade.tachiyomi.animesource.online.AnimeHttpSource
import eu.kanade.tachiyomi.data.database.models.Anime
import eu.kanade.tachiyomi.data.track.TrackManager
import eu.kanade.tachiyomi.databinding.AnimeInfoHeaderBinding
import eu.kanade.tachiyomi.source.AnimeSource
import eu.kanade.tachiyomi.source.AnimeSourceManager
import eu.kanade.tachiyomi.source.model.SAnime
import eu.kanade.tachiyomi.source.online.HttpSource
import eu.kanade.tachiyomi.ui.anime.AnimeController
import eu.kanade.tachiyomi.util.system.copyToClipboard
import eu.kanade.tachiyomi.util.view.setChips
@ -114,7 +114,7 @@ class AnimeInfoHeaderAdapter(
}
}
if (controller.presenter.source is HttpSource) {
if (controller.presenter.source is AnimeHttpSource) {
binding.btnWebview.isVisible = true
binding.btnWebview.clicks()
.onEach { controller.openAnimeInWebView() }

View file

@ -6,10 +6,10 @@ import android.view.View
import androidx.recyclerview.widget.LinearLayoutManager
import com.google.android.material.bottomsheet.BottomSheetBehavior
import eu.kanade.tachiyomi.R.string
import eu.kanade.tachiyomi.animesource.AnimeSourceManager
import eu.kanade.tachiyomi.data.database.models.Anime
import eu.kanade.tachiyomi.data.track.UnattendedTrackService
import eu.kanade.tachiyomi.databinding.TrackControllerBinding
import eu.kanade.tachiyomi.source.AnimeSourceManager
import eu.kanade.tachiyomi.ui.anime.AnimeController
import eu.kanade.tachiyomi.ui.base.controller.openInBrowser
import eu.kanade.tachiyomi.util.lang.launchIO

View file

@ -19,13 +19,13 @@ import com.jakewharton.rxrelay.PublishRelay
import com.tfcporciuncula.flow.Preference
import dev.chrisbanes.insetter.applyInsetter
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.animesource.LocalAnimeSource
import eu.kanade.tachiyomi.data.animelib.AnimelibUpdateService
import eu.kanade.tachiyomi.data.database.models.Anime
import eu.kanade.tachiyomi.data.database.models.Category
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.data.preference.asImmediateFlow
import eu.kanade.tachiyomi.databinding.AnimelibControllerBinding
import eu.kanade.tachiyomi.source.LocalSource
import eu.kanade.tachiyomi.ui.anime.AnimeController
import eu.kanade.tachiyomi.ui.base.controller.RootController
import eu.kanade.tachiyomi.ui.base.controller.SearchableNucleusController
@ -447,7 +447,7 @@ class AnimelibController(
} else {
mode.title = count.toString()
binding.actionToolbar.findItem(R.id.action_download_unread)?.isVisible = selectedAnimes.any { it.source != LocalSource.ID }
binding.actionToolbar.findItem(R.id.action_download_unread)?.isVisible = selectedAnimes.any { it.source != LocalAnimeSource.ID }
}
return false
}

View file

@ -12,11 +12,11 @@ import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
import eu.davidea.flexibleadapter.items.IFilterable
import eu.davidea.flexibleadapter.items.IFlexible
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.animesource.AnimeSourceManager
import eu.kanade.tachiyomi.data.database.models.AnimelibAnime
import eu.kanade.tachiyomi.data.preference.PreferenceValues.DisplayMode
import eu.kanade.tachiyomi.databinding.SourceComfortableGridItemBinding
import eu.kanade.tachiyomi.databinding.SourceCompactGridItemBinding
import eu.kanade.tachiyomi.source.SourceManager
import eu.kanade.tachiyomi.widget.AutofitRecyclerView
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
@ -24,7 +24,7 @@ import uy.kohesive.injekt.api.get
class AnimelibItem(val anime: AnimelibAnime, private val animelibDisplayMode: Preference<DisplayMode>) :
AbstractFlexibleItem<AnimelibHolder<*>>(), IFilterable<String> {
private val sourceManager: SourceManager = Injekt.get()
private val sourceManager: AnimeSourceManager = Injekt.get()
var downloadCount = -1
var unreadCount = -1

View file

@ -2,6 +2,9 @@ package eu.kanade.tachiyomi.ui.animelib
import android.os.Bundle
import com.jakewharton.rxrelay.BehaviorRelay
import eu.kanade.tachiyomi.animesource.AnimeSourceManager
import eu.kanade.tachiyomi.animesource.model.SAnime
import eu.kanade.tachiyomi.animesource.online.AnimeHttpSource
import eu.kanade.tachiyomi.data.cache.AnimeCoverCache
import eu.kanade.tachiyomi.data.database.AnimeDatabaseHelper
import eu.kanade.tachiyomi.data.database.models.Anime
@ -11,9 +14,6 @@ import eu.kanade.tachiyomi.data.database.models.Episode
import eu.kanade.tachiyomi.data.download.AnimeDownloadManager
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.data.track.TrackManager
import eu.kanade.tachiyomi.source.AnimeSourceManager
import eu.kanade.tachiyomi.source.model.SAnime
import eu.kanade.tachiyomi.source.online.AnimeHttpSource
import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
import eu.kanade.tachiyomi.util.isLocal
import eu.kanade.tachiyomi.util.lang.combineLatest

View file

@ -6,9 +6,9 @@ import eu.davidea.flexibleadapter.FlexibleAdapter
import eu.davidea.flexibleadapter.items.AbstractSectionableItem
import eu.davidea.flexibleadapter.items.IFlexible
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.animesource.AnimeCatalogueSource
import eu.kanade.tachiyomi.extension.model.AnimeExtension
import eu.kanade.tachiyomi.extension.model.InstallStep
import eu.kanade.tachiyomi.source.AnimeCatalogueSource
/**
* Item that contains source information.

View file

@ -23,16 +23,16 @@ import androidx.recyclerview.widget.ConcatAdapter
import androidx.recyclerview.widget.LinearLayoutManager
import dev.chrisbanes.insetter.applyInsetter
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.animesource.AnimeCatalogueSource
import eu.kanade.tachiyomi.animesource.AnimeSource
import eu.kanade.tachiyomi.animesource.ConfigurableAnimeSource
import eu.kanade.tachiyomi.animesource.getPreferenceKey
import eu.kanade.tachiyomi.data.preference.EmptyPreferenceDataStore
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.data.preference.minusAssign
import eu.kanade.tachiyomi.data.preference.plusAssign
import eu.kanade.tachiyomi.databinding.AnimeExtensionDetailControllerBinding
import eu.kanade.tachiyomi.extension.model.AnimeExtension
import eu.kanade.tachiyomi.source.AnimeCatalogueSource
import eu.kanade.tachiyomi.source.AnimeSource
import eu.kanade.tachiyomi.source.ConfigurableAnimeSource
import eu.kanade.tachiyomi.source.getPreferenceKey
import eu.kanade.tachiyomi.ui.base.controller.NucleusController
import eu.kanade.tachiyomi.ui.base.controller.ToolbarLiftOnScrollController
import eu.kanade.tachiyomi.ui.base.controller.openInBrowser

View file

@ -21,12 +21,12 @@ import androidx.preference.PreferenceManager
import androidx.preference.PreferenceScreen
import androidx.recyclerview.widget.LinearLayoutManager
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.animesource.AnimeSource
import eu.kanade.tachiyomi.animesource.ConfigurableAnimeSource
import eu.kanade.tachiyomi.animesource.getPreferenceKey
import eu.kanade.tachiyomi.data.preference.EmptyPreferenceDataStore
import eu.kanade.tachiyomi.data.preference.SharedPreferencesDataStore
import eu.kanade.tachiyomi.databinding.AnimeSourcePreferencesControllerBinding
import eu.kanade.tachiyomi.source.AnimeSource
import eu.kanade.tachiyomi.source.ConfigurableAnimeSource
import eu.kanade.tachiyomi.source.getPreferenceKey
import eu.kanade.tachiyomi.ui.base.controller.NucleusController
import timber.log.Timber

View file

@ -1,6 +1,6 @@
package eu.kanade.tachiyomi.ui.browse.animeextension.details
import eu.kanade.tachiyomi.source.AnimeSourceManager
import eu.kanade.tachiyomi.animesource.AnimeSourceManager
import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get

View file

@ -17,13 +17,13 @@ import dev.chrisbanes.insetter.applyInsetter
import eu.davidea.flexibleadapter.FlexibleAdapter
import eu.davidea.flexibleadapter.items.IFlexible
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.animesource.AnimeCatalogueSource
import eu.kanade.tachiyomi.animesource.AnimeSource
import eu.kanade.tachiyomi.animesource.LocalAnimeSource
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.data.preference.minusAssign
import eu.kanade.tachiyomi.data.preference.plusAssign
import eu.kanade.tachiyomi.databinding.AnimeSourceMainControllerBinding
import eu.kanade.tachiyomi.source.AnimeCatalogueSource
import eu.kanade.tachiyomi.source.AnimeSource
import eu.kanade.tachiyomi.source.LocalAnimeSource
import eu.kanade.tachiyomi.ui.base.controller.DialogController
import eu.kanade.tachiyomi.ui.base.controller.SearchableNucleusController
import eu.kanade.tachiyomi.ui.base.controller.requestPermissionsSafe

View file

@ -5,12 +5,12 @@ import androidx.preference.CheckBoxPreference
import androidx.preference.PreferenceGroup
import androidx.preference.PreferenceScreen
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.animesource.AnimeSourceManager
import eu.kanade.tachiyomi.animesource.getPreferenceKey
import eu.kanade.tachiyomi.animesource.icon
import eu.kanade.tachiyomi.animesource.online.AnimeHttpSource
import eu.kanade.tachiyomi.data.preference.minusAssign
import eu.kanade.tachiyomi.data.preference.plusAssign
import eu.kanade.tachiyomi.source.SourceManager
import eu.kanade.tachiyomi.source.getPreferenceKey
import eu.kanade.tachiyomi.source.icon
import eu.kanade.tachiyomi.source.online.HttpSource
import eu.kanade.tachiyomi.ui.setting.SettingsController
import eu.kanade.tachiyomi.util.preference.onChange
import eu.kanade.tachiyomi.util.preference.switchPreferenceCategory
@ -22,7 +22,7 @@ import java.util.TreeMap
class AnimeSourceFilterController : SettingsController() {
private val onlineSources by lazy { Injekt.get<SourceManager>().getOnlineSources() }
private val onlineSources by lazy { Injekt.get<AnimeSourceManager>().getOnlineSources() }
override fun setupPreferenceScreen(screen: PreferenceScreen) = screen.apply {
titleRes = R.string.label_sources
@ -78,7 +78,7 @@ class AnimeSourceFilterController : SettingsController() {
*
* @param group the language category.
*/
private fun addLanguageSources(group: PreferenceGroup, sources: List<HttpSource>) {
private fun addLanguageSources(group: PreferenceGroup, sources: List<AnimeHttpSource>) {
val disabledSourceIds = preferences.disabledAnimeSources().get()
sources

View file

@ -4,10 +4,9 @@ import android.view.View
import androidx.core.view.isVisible
import eu.davidea.viewholders.FlexibleViewHolder
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.animesource.LocalAnimeSource
import eu.kanade.tachiyomi.animesource.icon
import eu.kanade.tachiyomi.databinding.SourceMainControllerCardItemBinding
import eu.kanade.tachiyomi.source.LocalAnimeSource
import eu.kanade.tachiyomi.source.LocalSource
import eu.kanade.tachiyomi.source.icon
import eu.kanade.tachiyomi.util.system.LocaleHelper
import eu.kanade.tachiyomi.util.view.setVectorCompat
@ -38,7 +37,7 @@ class AnimeSourceHolder(private val view: View, val adapter: AnimeSourceAdapter)
val icon = source.icon()
when {
icon != null -> binding.image.setImageDrawable(icon)
item.source.id == LocalSource.ID -> binding.image.setImageResource(R.mipmap.ic_local_source)
item.source.id == LocalAnimeSource.ID -> binding.image.setImageResource(R.mipmap.ic_local_source)
}
}

View file

@ -6,7 +6,7 @@ import eu.davidea.flexibleadapter.FlexibleAdapter
import eu.davidea.flexibleadapter.items.AbstractSectionableItem
import eu.davidea.flexibleadapter.items.IFlexible
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.source.AnimeCatalogueSource
import eu.kanade.tachiyomi.animesource.AnimeCatalogueSource
/**
* Item that contains source information.

View file

@ -1,10 +1,10 @@
package eu.kanade.tachiyomi.ui.browse.animesource
import android.os.Bundle
import eu.kanade.tachiyomi.animesource.AnimeCatalogueSource
import eu.kanade.tachiyomi.animesource.AnimeSourceManager
import eu.kanade.tachiyomi.animesource.LocalAnimeSource
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.source.AnimeCatalogueSource
import eu.kanade.tachiyomi.source.AnimeSourceManager
import eu.kanade.tachiyomi.source.LocalAnimeSource
import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.distinctUntilChanged

View file

@ -1,8 +1,8 @@
package eu.kanade.tachiyomi.ui.browse.animesource.browse
import com.jakewharton.rxrelay.PublishRelay
import eu.kanade.tachiyomi.source.model.AnimesPage
import eu.kanade.tachiyomi.source.model.SAnime
import eu.kanade.tachiyomi.animesource.model.AnimesPage
import eu.kanade.tachiyomi.animesource.model.SAnime
import rx.Observable
/**

View file

@ -1,8 +1,8 @@
package eu.kanade.tachiyomi.ui.browse.animesource.browse
import eu.kanade.tachiyomi.source.AnimeCatalogueSource
import eu.kanade.tachiyomi.source.model.AnimesPage
import eu.kanade.tachiyomi.source.model.FilterList
import eu.kanade.tachiyomi.animesource.AnimeCatalogueSource
import eu.kanade.tachiyomi.animesource.model.AnimesPage
import eu.kanade.tachiyomi.animesource.model.FilterList
import rx.Observable
import rx.android.schedulers.AndroidSchedulers
import rx.schedulers.Schedulers

View file

@ -22,16 +22,16 @@ import dev.chrisbanes.insetter.applyInsetter
import eu.davidea.flexibleadapter.FlexibleAdapter
import eu.davidea.flexibleadapter.items.IFlexible
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.animesource.AnimeCatalogueSource
import eu.kanade.tachiyomi.animesource.LocalAnimeSource
import eu.kanade.tachiyomi.animesource.model.FilterList
import eu.kanade.tachiyomi.animesource.online.AnimeHttpSource
import eu.kanade.tachiyomi.data.database.models.Anime
import eu.kanade.tachiyomi.data.database.models.Category
import eu.kanade.tachiyomi.data.preference.PreferenceValues.DisplayMode
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.data.preference.asImmediateFlow
import eu.kanade.tachiyomi.databinding.AnimeSourceControllerBinding
import eu.kanade.tachiyomi.source.AnimeCatalogueSource
import eu.kanade.tachiyomi.source.LocalAnimeSource
import eu.kanade.tachiyomi.source.model.FilterList
import eu.kanade.tachiyomi.source.online.AnimeHttpSource
import eu.kanade.tachiyomi.ui.anime.AnimeController
import eu.kanade.tachiyomi.ui.animelib.ChangeAnimeCategoriesDialog
import eu.kanade.tachiyomi.ui.base.controller.FabController

View file

@ -2,6 +2,12 @@ package eu.kanade.tachiyomi.ui.browse.animesource.browse
import android.os.Bundle
import eu.davidea.flexibleadapter.items.IFlexible
import eu.kanade.tachiyomi.animesource.AnimeCatalogueSource
import eu.kanade.tachiyomi.animesource.AnimeSourceManager
import eu.kanade.tachiyomi.animesource.model.Filter
import eu.kanade.tachiyomi.animesource.model.FilterList
import eu.kanade.tachiyomi.animesource.model.SAnime
import eu.kanade.tachiyomi.animesource.model.toSAnime
import eu.kanade.tachiyomi.data.cache.AnimeCoverCache
import eu.kanade.tachiyomi.data.database.AnimeDatabaseHelper
import eu.kanade.tachiyomi.data.database.models.Anime
@ -12,12 +18,6 @@ import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.data.track.TrackManager
import eu.kanade.tachiyomi.data.track.TrackService
import eu.kanade.tachiyomi.data.track.UnattendedTrackService
import eu.kanade.tachiyomi.source.AnimeCatalogueSource
import eu.kanade.tachiyomi.source.AnimeSourceManager
import eu.kanade.tachiyomi.source.model.Filter
import eu.kanade.tachiyomi.source.model.FilterList
import eu.kanade.tachiyomi.source.model.SAnime
import eu.kanade.tachiyomi.source.model.toSAnime
import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
import eu.kanade.tachiyomi.ui.browse.animesource.filter.CheckboxItem
import eu.kanade.tachiyomi.ui.browse.animesource.filter.CheckboxSectionItem

View file

@ -8,7 +8,7 @@ import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
import eu.davidea.flexibleadapter.items.IFlexible
import eu.davidea.viewholders.FlexibleViewHolder
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.source.model.Filter
import eu.kanade.tachiyomi.animesource.model.Filter
open class CheckboxItem(val filter: Filter.CheckBox) : AbstractFlexibleItem<CheckboxItem.Holder>() {

View file

@ -10,7 +10,7 @@ import eu.davidea.flexibleadapter.items.IFlexible
import eu.davidea.flexibleadapter.items.ISectionable
import eu.davidea.viewholders.ExpandableViewHolder
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.source.model.Filter
import eu.kanade.tachiyomi.animesource.model.Filter
import eu.kanade.tachiyomi.util.view.setVectorCompat
class GroupItem(val filter: Filter.Group<*>) : AbstractExpandableHeaderItem<GroupItem.Holder, ISectionable<*, *>>() {

View file

@ -9,7 +9,7 @@ import eu.davidea.flexibleadapter.FlexibleAdapter
import eu.davidea.flexibleadapter.items.AbstractHeaderItem
import eu.davidea.flexibleadapter.items.IFlexible
import eu.davidea.viewholders.FlexibleViewHolder
import eu.kanade.tachiyomi.source.model.Filter
import eu.kanade.tachiyomi.animesource.model.Filter
class HeaderItem(val filter: Filter.Header) : AbstractHeaderItem<HeaderItem.Holder>() {

View file

@ -1,7 +1,7 @@
package eu.kanade.tachiyomi.ui.browse.animesource.filter
import eu.davidea.flexibleadapter.items.ISectionable
import eu.kanade.tachiyomi.source.model.Filter
import eu.kanade.tachiyomi.animesource.model.Filter
class TriStateSectionItem(filter: Filter.TriState) : TriStateItem(filter), ISectionable<TriStateItem.Holder, GroupItem> {

View file

@ -10,7 +10,7 @@ import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
import eu.davidea.flexibleadapter.items.IFlexible
import eu.davidea.viewholders.FlexibleViewHolder
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.source.model.Filter
import eu.kanade.tachiyomi.animesource.model.Filter
import eu.kanade.tachiyomi.widget.listener.IgnoreFirstSpinnerListener
open class SelectItem(val filter: Filter.Select<*>) : AbstractFlexibleItem<SelectItem.Holder>() {

View file

@ -8,7 +8,7 @@ import eu.davidea.flexibleadapter.FlexibleAdapter
import eu.davidea.flexibleadapter.items.AbstractHeaderItem
import eu.davidea.flexibleadapter.items.IFlexible
import eu.davidea.viewholders.FlexibleViewHolder
import eu.kanade.tachiyomi.source.model.Filter
import eu.kanade.tachiyomi.animesource.model.Filter
class SeparatorItem(val filter: Filter.Separator) : AbstractHeaderItem<SeparatorItem.Holder>() {

View file

@ -7,7 +7,7 @@ import eu.davidea.flexibleadapter.items.AbstractExpandableHeaderItem
import eu.davidea.flexibleadapter.items.IFlexible
import eu.davidea.flexibleadapter.items.ISectionable
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.source.model.Filter
import eu.kanade.tachiyomi.animesource.model.Filter
import eu.kanade.tachiyomi.util.view.setVectorCompat
class SortGroup(val filter: Filter.Sort) : AbstractExpandableHeaderItem<SortGroup.Holder, ISectionable<*, *>>() {

View file

@ -9,7 +9,7 @@ import eu.davidea.flexibleadapter.items.AbstractSectionableItem
import eu.davidea.flexibleadapter.items.IFlexible
import eu.davidea.viewholders.FlexibleViewHolder
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.source.model.Filter
import eu.kanade.tachiyomi.animesource.model.Filter
import eu.kanade.tachiyomi.util.system.getResourceColor
class SortItem(val name: String, val group: SortGroup) : AbstractSectionableItem<SortItem.Holder, SortGroup>(group) {

View file

@ -10,7 +10,7 @@ import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
import eu.davidea.flexibleadapter.items.IFlexible
import eu.davidea.viewholders.FlexibleViewHolder
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.source.model.Filter
import eu.kanade.tachiyomi.animesource.model.Filter
open class TextItem(val filter: Filter.Text) : AbstractFlexibleItem<TextItem.Holder>() {

View file

@ -9,7 +9,7 @@ import eu.davidea.flexibleadapter.FlexibleAdapter
import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
import eu.davidea.flexibleadapter.items.IFlexible
import eu.davidea.viewholders.FlexibleViewHolder
import eu.kanade.tachiyomi.source.model.Filter
import eu.kanade.tachiyomi.animesource.model.Filter
import eu.kanade.tachiyomi.util.system.dpToPx
import eu.kanade.tachiyomi.util.system.getResourceColor
import eu.kanade.tachiyomi.R as TR

View file

@ -5,7 +5,7 @@ import android.os.Parcelable
import android.util.SparseArray
import androidx.recyclerview.widget.RecyclerView
import eu.davidea.flexibleadapter.FlexibleAdapter
import eu.kanade.tachiyomi.source.AnimeCatalogueSource
import eu.kanade.tachiyomi.animesource.AnimeCatalogueSource
/**
* Adapter that holds the search cards.

View file

@ -10,10 +10,10 @@ import androidx.appcompat.widget.SearchView
import androidx.core.view.isVisible
import androidx.recyclerview.widget.LinearLayoutManager
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.animesource.AnimeCatalogueSource
import eu.kanade.tachiyomi.data.database.models.Anime
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.databinding.GlobalAnimeSearchControllerBinding
import eu.kanade.tachiyomi.source.AnimeCatalogueSource
import eu.kanade.tachiyomi.ui.anime.AnimeController
import eu.kanade.tachiyomi.ui.base.controller.SearchableNucleusController
import eu.kanade.tachiyomi.ui.base.controller.withFadeTransaction

View file

@ -4,9 +4,9 @@ import android.view.View
import androidx.core.view.isVisible
import androidx.recyclerview.widget.LinearLayoutManager
import eu.davidea.viewholders.FlexibleViewHolder
import eu.kanade.tachiyomi.animesource.LocalAnimeSource
import eu.kanade.tachiyomi.data.database.models.Anime
import eu.kanade.tachiyomi.databinding.GlobalSearchControllerCardBinding
import eu.kanade.tachiyomi.source.LocalAnimeSource
import eu.kanade.tachiyomi.util.system.LocaleHelper
/**

View file

@ -6,7 +6,7 @@ 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.source.AnimeCatalogueSource
import eu.kanade.tachiyomi.animesource.AnimeCatalogueSource
/**
* Item that contains search result information.

View file

@ -1,18 +1,18 @@
package eu.kanade.tachiyomi.ui.browse.animesource.globalsearch
import android.os.Bundle
import eu.kanade.tachiyomi.animesource.AnimeCatalogueSource
import eu.kanade.tachiyomi.animesource.AnimeSource
import eu.kanade.tachiyomi.animesource.AnimeSourceManager
import eu.kanade.tachiyomi.animesource.model.AnimesPage
import eu.kanade.tachiyomi.animesource.model.FilterList
import eu.kanade.tachiyomi.animesource.model.SAnime
import eu.kanade.tachiyomi.animesource.model.toSAnime
import eu.kanade.tachiyomi.data.database.AnimeDatabaseHelper
import eu.kanade.tachiyomi.data.database.models.Anime
import eu.kanade.tachiyomi.data.database.models.toAnimeInfo
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.extension.AnimeExtensionManager
import eu.kanade.tachiyomi.source.AnimeCatalogueSource
import eu.kanade.tachiyomi.source.AnimeSource
import eu.kanade.tachiyomi.source.AnimeSourceManager
import eu.kanade.tachiyomi.source.model.AnimesPage
import eu.kanade.tachiyomi.source.model.FilterList
import eu.kanade.tachiyomi.source.model.SAnime
import eu.kanade.tachiyomi.source.model.toSAnime
import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
import eu.kanade.tachiyomi.ui.browse.animesource.browse.BrowseAnimeSourcePresenter
import eu.kanade.tachiyomi.util.lang.runAsObservable

View file

@ -4,7 +4,7 @@ import android.os.Bundle
import android.view.Menu
import androidx.core.os.bundleOf
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.source.AnimeCatalogueSource
import eu.kanade.tachiyomi.animesource.AnimeCatalogueSource
import eu.kanade.tachiyomi.ui.browse.animesource.browse.BrowseAnimeSourceController
import eu.kanade.tachiyomi.ui.browse.animesource.browse.BrowseAnimeSourcePresenter

View file

@ -1,7 +1,7 @@
package eu.kanade.tachiyomi.ui.browse.animesource.latest
import eu.kanade.tachiyomi.source.AnimeCatalogueSource
import eu.kanade.tachiyomi.source.model.AnimesPage
import eu.kanade.tachiyomi.animesource.AnimeCatalogueSource
import eu.kanade.tachiyomi.animesource.model.AnimesPage
import eu.kanade.tachiyomi.ui.browse.animesource.browse.AnimePager
import rx.Observable
import rx.android.schedulers.AndroidSchedulers

View file

@ -1,6 +1,6 @@
package eu.kanade.tachiyomi.ui.browse.animesource.latest
import eu.kanade.tachiyomi.source.model.FilterList
import eu.kanade.tachiyomi.animesource.model.FilterList
import eu.kanade.tachiyomi.ui.browse.animesource.browse.AnimePager
import eu.kanade.tachiyomi.ui.browse.animesource.browse.BrowseAnimeSourcePresenter

View file

@ -7,9 +7,9 @@ import com.afollestad.materialdialogs.MaterialDialog
import com.afollestad.materialdialogs.list.listItemsMultiChoice
import com.bluelinelabs.conductor.Controller
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.animesource.AnimeCatalogueSource
import eu.kanade.tachiyomi.data.database.models.Anime
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.source.AnimeCatalogueSource
import eu.kanade.tachiyomi.ui.base.controller.DialogController
import eu.kanade.tachiyomi.ui.base.controller.withFadeTransaction
import eu.kanade.tachiyomi.ui.browse.animesource.globalsearch.GlobalAnimeSearchController

View file

@ -2,14 +2,14 @@ package eu.kanade.tachiyomi.ui.browse.migration.search
import android.os.Bundle
import com.jakewharton.rxrelay.BehaviorRelay
import eu.kanade.tachiyomi.animesource.AnimeCatalogueSource
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.toSEpisode
import eu.kanade.tachiyomi.data.database.models.Anime
import eu.kanade.tachiyomi.data.database.models.AnimeCategory
import eu.kanade.tachiyomi.data.database.models.toAnimeInfo
import eu.kanade.tachiyomi.source.AnimeCatalogueSource
import eu.kanade.tachiyomi.source.AnimeSource
import eu.kanade.tachiyomi.source.model.SAnime
import eu.kanade.tachiyomi.source.model.SEpisode
import eu.kanade.tachiyomi.source.model.toSEpisode
import eu.kanade.tachiyomi.ui.browse.animesource.globalsearch.GlobalAnimeSearchCardItem
import eu.kanade.tachiyomi.ui.browse.animesource.globalsearch.GlobalAnimeSearchItem
import eu.kanade.tachiyomi.ui.browse.animesource.globalsearch.GlobalAnimeSearchPresenter

View file

@ -2,8 +2,8 @@ package eu.kanade.tachiyomi.ui.browse.migration.search
import android.os.Bundle
import android.view.View
import eu.kanade.tachiyomi.animesource.AnimeCatalogueSource
import eu.kanade.tachiyomi.data.database.models.Anime
import eu.kanade.tachiyomi.source.AnimeCatalogueSource
import eu.kanade.tachiyomi.ui.browse.animesource.browse.AnimeSourceItem
import eu.kanade.tachiyomi.ui.browse.animesource.browse.BrowseAnimeSourceController

View file

@ -6,7 +6,7 @@ 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.source.AnimeSource
import eu.kanade.tachiyomi.animesource.AnimeSource
/**
* Item that contains source information.

View file

@ -1,11 +1,14 @@
package eu.kanade.tachiyomi.ui.browse.migration.sources
import android.os.Bundle
import eu.kanade.tachiyomi.animesource.AnimeSourceManager
import eu.kanade.tachiyomi.animesource.LocalAnimeSource
import eu.kanade.tachiyomi.data.database.AnimeDatabaseHelper
import eu.kanade.tachiyomi.data.database.DatabaseHelper
import eu.kanade.tachiyomi.data.database.models.Anime
import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.source.*
import eu.kanade.tachiyomi.source.LocalSource
import eu.kanade.tachiyomi.source.SourceManager
import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
import rx.android.schedulers.AndroidSchedulers
import uy.kohesive.injekt.Injekt
@ -49,7 +52,7 @@ class MigrationSourcesPresenter(
private fun findSourcesWithAnime(library: List<Anime>): List<AnimeSourceItem> {
return library
.groupBy { it.source }
.filterKeys { it != LocalSource.ID }
.filterKeys { it != LocalAnimeSource.ID }
.map {
val source = animesourceManager.getOrStub(it.key)
AnimeSourceItem(source, it.value.size)

View file

@ -3,6 +3,7 @@ package eu.kanade.tachiyomi.ui.browse.migration.sources
import android.view.View
import androidx.core.view.isVisible
import eu.davidea.viewholders.FlexibleViewHolder
import eu.kanade.tachiyomi.animesource.icon
import eu.kanade.tachiyomi.databinding.SourceMainControllerCardItemBinding
import eu.kanade.tachiyomi.source.icon
import eu.kanade.tachiyomi.util.system.LocaleHelper

View file

@ -2,7 +2,7 @@ package eu.kanade.tachiyomi.ui.recent.animehistory
import eu.davidea.flexibleadapter.FlexibleAdapter
import eu.davidea.flexibleadapter.items.IFlexible
import eu.kanade.tachiyomi.source.AnimeSourceManager
import eu.kanade.tachiyomi.animesource.AnimeSourceManager
import uy.kohesive.injekt.injectLazy
import java.text.DecimalFormat
import java.text.DecimalFormatSymbols

View file

@ -13,13 +13,12 @@ import com.afollestad.materialdialogs.MaterialDialog
import dev.chrisbanes.insetter.applyInsetter
import eu.davidea.flexibleadapter.FlexibleAdapter
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.animesource.AnimeSourceManager
import eu.kanade.tachiyomi.data.backup.BackupRestoreService
import eu.kanade.tachiyomi.data.database.AnimeDatabaseHelper
import eu.kanade.tachiyomi.data.database.models.Anime
import eu.kanade.tachiyomi.data.database.models.AnimeHistory
import eu.kanade.tachiyomi.databinding.AnimeHistoryControllerBinding
import eu.kanade.tachiyomi.source.AnimeSourceManager
import eu.kanade.tachiyomi.source.model.toEpisodeInfo
import eu.kanade.tachiyomi.ui.anime.AnimeController
import eu.kanade.tachiyomi.ui.anime.episode.EpisodeItem
import eu.kanade.tachiyomi.ui.base.controller.DialogController
@ -27,21 +26,17 @@ import eu.kanade.tachiyomi.ui.base.controller.NucleusController
import eu.kanade.tachiyomi.ui.base.controller.RootController
import eu.kanade.tachiyomi.ui.base.controller.withFadeTransaction
import eu.kanade.tachiyomi.ui.browse.source.browse.ProgressItem
import eu.kanade.tachiyomi.ui.watcher.EpisodeLoader
import eu.kanade.tachiyomi.ui.watcher.WatcherActivity
import eu.kanade.tachiyomi.util.lang.launchIO
import eu.kanade.tachiyomi.util.lang.withUIContext
import eu.kanade.tachiyomi.util.system.toast
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.runBlocking
import reactivecircus.flowbinding.appcompat.queryTextChanges
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import uy.kohesive.injekt.injectLazy
import java.util.Collections
import kotlin.coroutines.resume
import kotlin.coroutines.suspendCoroutine
/**
* Fragment that shows recently read anime.
@ -166,19 +161,7 @@ class AnimeHistoryController :
val nextEpisode = presenter.getNextEpisode(chapter, anime)
if (nextEpisode != null) {
val source = Injekt.get<AnimeSourceManager>().getOrStub(anime.source)
val link = runBlocking {
return@runBlocking suspendCoroutine<String> { continuation ->
var link: String
launchIO {
try {
link = source.getEpisodeLink(nextEpisode.toEpisodeInfo())
continuation.resume(link)
} catch (e: Throwable) {
withUIContext { throw e }
}
}
}
}
val link = EpisodeLoader.getUri(nextEpisode, anime, source)
val episodeList: List<EpisodeItem> = Collections.emptyList()
val newIntent = WatcherActivity.newIntent(activity, anime, nextEpisode, episodeList, link)
startActivity(newIntent)

View file

@ -13,13 +13,12 @@ import eu.davidea.flexibleadapter.FlexibleAdapter
import eu.davidea.flexibleadapter.SelectableAdapter
import eu.davidea.flexibleadapter.items.IFlexible
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.animesource.AnimeSourceManager
import eu.kanade.tachiyomi.data.animelib.AnimelibUpdateService
import eu.kanade.tachiyomi.data.download.AnimeDownloadService
import eu.kanade.tachiyomi.data.download.model.AnimeDownload
import eu.kanade.tachiyomi.data.notification.Notifications
import eu.kanade.tachiyomi.databinding.AnimeUpdatesControllerBinding
import eu.kanade.tachiyomi.source.AnimeSourceManager
import eu.kanade.tachiyomi.source.model.toEpisodeInfo
import eu.kanade.tachiyomi.ui.anime.AnimeController
import eu.kanade.tachiyomi.ui.anime.episode.EpisodeItem
import eu.kanade.tachiyomi.ui.anime.episode.base.BaseEpisodesAdapter
@ -27,22 +26,18 @@ import eu.kanade.tachiyomi.ui.base.controller.NucleusController
import eu.kanade.tachiyomi.ui.base.controller.RootController
import eu.kanade.tachiyomi.ui.base.controller.withFadeTransaction
import eu.kanade.tachiyomi.ui.main.MainActivity
import eu.kanade.tachiyomi.ui.watcher.EpisodeLoader
import eu.kanade.tachiyomi.ui.watcher.WatcherActivity
import eu.kanade.tachiyomi.util.lang.launchIO
import eu.kanade.tachiyomi.util.lang.withUIContext
import eu.kanade.tachiyomi.util.system.notificationManager
import eu.kanade.tachiyomi.util.system.toast
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.runBlocking
import reactivecircus.flowbinding.recyclerview.scrollStateChanges
import reactivecircus.flowbinding.swiperefreshlayout.refreshes
import timber.log.Timber
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import java.util.*
import kotlin.coroutines.resume
import kotlin.coroutines.suspendCoroutine
/**
* Fragment that shows recent episodes.
@ -216,19 +211,7 @@ class AnimeUpdatesController :
private fun openEpisode(item: AnimeUpdatesItem) {
val activity = activity ?: return
val source = Injekt.get<AnimeSourceManager>().getOrStub(item.anime.source)
val link = runBlocking {
return@runBlocking suspendCoroutine<String> { continuation ->
var link: String
launchIO {
try {
link = source.getEpisodeLink(item.episode.toEpisodeInfo())
continuation.resume(link)
} catch (e: Throwable) {
withUIContext { throw e }
}
}
}
}
val link = EpisodeLoader.getUri(item.episode, item.anime, source)
val episodeList: List<EpisodeItem> = Collections.emptyList()
val intent = WatcherActivity.newIntent(activity, item.anime, item.episode, episodeList, link)
startActivity(intent)

View file

@ -6,8 +6,8 @@ import coil.clear
import coil.loadAny
import coil.transform.RoundedCornersTransformation
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.animesource.LocalAnimeSource
import eu.kanade.tachiyomi.databinding.AnimeUpdatesItemBinding
import eu.kanade.tachiyomi.source.LocalSource
import eu.kanade.tachiyomi.ui.anime.episode.base.BaseEpisodeHolder
/**
@ -51,7 +51,7 @@ class AnimeUpdatesHolder(private val view: View, private val adapter: AnimeUpdat
}
// Set episode status
binding.download.isVisible = item.anime.source != LocalSource.ID
binding.download.isVisible = item.anime.source != LocalAnimeSource.ID
binding.download.setState(item.status, item.progress)
// Set cover

View file

@ -1,12 +1,12 @@
package eu.kanade.tachiyomi.ui.recent.animeupdates
import android.os.Bundle
import eu.kanade.tachiyomi.animesource.AnimeSourceManager
import eu.kanade.tachiyomi.data.database.AnimeDatabaseHelper
import eu.kanade.tachiyomi.data.database.models.AnimeEpisode
import eu.kanade.tachiyomi.data.download.AnimeDownloadManager
import eu.kanade.tachiyomi.data.download.model.AnimeDownload
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.source.AnimeSourceManager
import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
import eu.kanade.tachiyomi.ui.recent.DateSectionItem
import eu.kanade.tachiyomi.util.lang.toDateKey

View file

@ -0,0 +1,68 @@
package eu.kanade.tachiyomi.ui.watcher
import android.net.Uri
import eu.kanade.tachiyomi.animesource.AnimeSource
import eu.kanade.tachiyomi.animesource.LocalAnimeSource
import eu.kanade.tachiyomi.animesource.model.toEpisodeInfo
import eu.kanade.tachiyomi.animesource.online.AnimeHttpSource
import eu.kanade.tachiyomi.data.database.models.Anime
import eu.kanade.tachiyomi.data.database.models.Episode
import eu.kanade.tachiyomi.data.download.AnimeDownloadManager
import eu.kanade.tachiyomi.util.lang.awaitSingle
import eu.kanade.tachiyomi.util.lang.launchIO
import eu.kanade.tachiyomi.util.lang.withUIContext
import kotlinx.coroutines.runBlocking
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import kotlin.coroutines.resume
import kotlin.coroutines.suspendCoroutine
class EpisodeLoader {
companion object {
fun getUri(episode: Episode, anime: Anime, source: AnimeSource): String {
val downloadManager: AnimeDownloadManager = Injekt.get()
val isDownloaded = downloadManager.isEpisodeDownloaded(episode, anime, true)
return when {
isDownloaded -> downloaded(episode, anime, source, downloadManager).toString()
source is AnimeHttpSource -> notDownloaded(episode, anime, source)
source is LocalAnimeSource -> "path"
else -> error("no worky")
}
}
fun notDownloaded(episode: Episode, anime: Anime, source: AnimeSource): String {
val link = runBlocking {
return@runBlocking suspendCoroutine<String> { continuation ->
var link: String
launchIO {
try {
link = source.getEpisodeLink(episode.toEpisodeInfo())
continuation.resume(link)
} catch (e: Throwable) {
withUIContext { throw e }
}
}
}
}
return link
}
fun downloaded(
episode: Episode,
anime: Anime,
source: AnimeSource,
downloadManager: AnimeDownloadManager
): Uri {
val path = runBlocking {
return@runBlocking suspendCoroutine<Uri> { continuation ->
launchIO {
val link =
downloadManager.buildVideo(source, anime, episode).awaitSingle().uri!!
continuation.resume(link)
}
}
}
return path
}
}
}

View file

@ -21,6 +21,8 @@ import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory
import com.google.android.exoplayer2.util.MimeTypes
import com.google.android.exoplayer2.util.Util
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.animesource.AnimeSource
import eu.kanade.tachiyomi.animesource.AnimeSourceManager
import eu.kanade.tachiyomi.data.database.AnimeDatabaseHelper
import eu.kanade.tachiyomi.data.database.models.Anime
import eu.kanade.tachiyomi.data.database.models.AnimeHistory
@ -29,8 +31,6 @@ import eu.kanade.tachiyomi.data.download.AnimeDownloadManager
import eu.kanade.tachiyomi.data.download.model.AnimeDownload
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.data.track.TrackManager
import eu.kanade.tachiyomi.source.AnimeSource
import eu.kanade.tachiyomi.source.AnimeSourceManager
import eu.kanade.tachiyomi.ui.anime.episode.EpisodeItem
import eu.kanade.tachiyomi.util.lang.launchIO
import eu.kanade.tachiyomi.util.view.hideBar

View file

@ -1,11 +1,11 @@
package eu.kanade.tachiyomi.util
import eu.kanade.tachiyomi.animesource.LocalAnimeSource
import eu.kanade.tachiyomi.animesource.model.SAnime
import eu.kanade.tachiyomi.data.cache.AnimeCoverCache
import eu.kanade.tachiyomi.data.database.AnimeDatabaseHelper
import eu.kanade.tachiyomi.data.database.models.Anime
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.source.LocalAnimeSource
import eu.kanade.tachiyomi.source.model.SAnime
import java.util.Date
fun Anime.isLocal() = source == LocalAnimeSource.ID

View file

@ -1,7 +1,7 @@
package eu.kanade.tachiyomi.util.episode
import eu.kanade.tachiyomi.source.model.SAnime
import eu.kanade.tachiyomi.source.model.SEpisode
import eu.kanade.tachiyomi.animesource.model.SAnime
import eu.kanade.tachiyomi.animesource.model.SEpisode
/**
* -R> = regex conversion.

View file

@ -1,12 +1,12 @@
package eu.kanade.tachiyomi.util.episode
import eu.kanade.tachiyomi.animesource.AnimeSource
import eu.kanade.tachiyomi.animesource.model.SEpisode
import eu.kanade.tachiyomi.animesource.online.AnimeHttpSource
import eu.kanade.tachiyomi.data.database.AnimeDatabaseHelper
import eu.kanade.tachiyomi.data.database.models.Anime
import eu.kanade.tachiyomi.data.database.models.Episode
import eu.kanade.tachiyomi.data.download.AnimeDownloadManager
import eu.kanade.tachiyomi.source.AnimeSource
import eu.kanade.tachiyomi.source.model.SEpisode
import eu.kanade.tachiyomi.source.online.AnimeHttpSource
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import java.util.Date

View file

@ -1,7 +1,7 @@
package eu.kanade.tachiyomi.util.storage
import eu.kanade.tachiyomi.source.model.SAnime
import eu.kanade.tachiyomi.source.model.SEpisode
import eu.kanade.tachiyomi.animesource.model.SAnime
import eu.kanade.tachiyomi.animesource.model.SEpisode
import org.jsoup.Jsoup
import org.jsoup.nodes.Document
import java.io.Closeable

View file

@ -1,7 +1,7 @@
package tachiyomi.source
package tachiyomi.animesource
import tachiyomi.source.model.AnimeInfo
import tachiyomi.source.model.EpisodeInfo
import tachiyomi.animesource.model.AnimeInfo
import tachiyomi.animesource.model.EpisodeInfo
/**
* A basic interface for creating a source. It could be an online source, a local source, etc...

View file

@ -1,4 +1,4 @@
package tachiyomi.source.model
package tachiyomi.animesource.model
/**
* Model for a anime given by a source

View file

@ -1,4 +1,4 @@
package tachiyomi.source.model
package tachiyomi.animesource.model
data class EpisodeInfo(
var key: String,

Some files were not shown because too many files have changed in this diff Show more