mirror of
https://github.com/aniyomiorg/aniyomi.git
synced 2024-11-25 06:11:04 +03:00
breaking changes!!!
-moved a bunch of classes to the package called animesource -implemented a downloader that (barely) works
This commit is contained in:
parent
58c954e1c3
commit
6461ea42dc
101 changed files with 583 additions and 471 deletions
|
@ -2,6 +2,7 @@ package eu.kanade.tachiyomi
|
||||||
|
|
||||||
import android.app.Application
|
import android.app.Application
|
||||||
import android.os.Handler
|
import android.os.Handler
|
||||||
|
import eu.kanade.tachiyomi.animesource.AnimeSourceManager
|
||||||
import eu.kanade.tachiyomi.data.cache.AnimeCoverCache
|
import eu.kanade.tachiyomi.data.cache.AnimeCoverCache
|
||||||
import eu.kanade.tachiyomi.data.cache.ChapterCache
|
import eu.kanade.tachiyomi.data.cache.ChapterCache
|
||||||
import eu.kanade.tachiyomi.data.cache.CoverCache
|
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.AnimeExtensionManager
|
||||||
import eu.kanade.tachiyomi.extension.ExtensionManager
|
import eu.kanade.tachiyomi.extension.ExtensionManager
|
||||||
import eu.kanade.tachiyomi.network.NetworkHelper
|
import eu.kanade.tachiyomi.network.NetworkHelper
|
||||||
import eu.kanade.tachiyomi.source.AnimeSourceManager
|
|
||||||
import eu.kanade.tachiyomi.source.SourceManager
|
import eu.kanade.tachiyomi.source.SourceManager
|
||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
import uy.kohesive.injekt.api.InjektModule
|
import uy.kohesive.injekt.api.InjektModule
|
||||||
|
|
|
@ -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.animesource.model.AnimesPage
|
||||||
import eu.kanade.tachiyomi.source.model.FilterList
|
import eu.kanade.tachiyomi.animesource.model.FilterList
|
||||||
import rx.Observable
|
import rx.Observable
|
||||||
|
|
||||||
interface AnimeCatalogueSource : AnimeSource {
|
interface AnimeCatalogueSource : AnimeSource {
|
|
@ -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) }
|
||||||
|
}
|
|
@ -1,24 +1,24 @@
|
||||||
package eu.kanade.tachiyomi.source
|
package eu.kanade.tachiyomi.animesource
|
||||||
|
|
||||||
import android.graphics.drawable.Drawable
|
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.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 eu.kanade.tachiyomi.util.lang.awaitSingle
|
||||||
import rx.Observable
|
import rx.Observable
|
||||||
import tachiyomi.source.model.AnimeInfo
|
import tachiyomi.animesource.model.AnimeInfo
|
||||||
import tachiyomi.source.model.EpisodeInfo
|
import tachiyomi.animesource.model.EpisodeInfo
|
||||||
import uy.kohesive.injekt.Injekt
|
import uy.kohesive.injekt.Injekt
|
||||||
import uy.kohesive.injekt.api.get
|
import uy.kohesive.injekt.api.get
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A basic interface for creating a source. It could be an online source, a local source, etc...
|
* 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.
|
* Id for the source. Must be unique.
|
|
@ -1,4 +1,4 @@
|
||||||
package eu.kanade.tachiyomi.source
|
package eu.kanade.tachiyomi.animesource
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A factory for creating sources at runtime.
|
* A factory for creating sources at runtime.
|
|
@ -1,10 +1,10 @@
|
||||||
package eu.kanade.tachiyomi.source
|
package eu.kanade.tachiyomi.animesource
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
import eu.kanade.tachiyomi.source.model.SAnime
|
import eu.kanade.tachiyomi.animesource.model.SAnime
|
||||||
import eu.kanade.tachiyomi.source.model.SEpisode
|
import eu.kanade.tachiyomi.animesource.model.SEpisode
|
||||||
import eu.kanade.tachiyomi.source.online.AnimeHttpSource
|
import eu.kanade.tachiyomi.animesource.online.AnimeHttpSource
|
||||||
import rx.Observable
|
import rx.Observable
|
||||||
|
|
||||||
open class AnimeSourceManager(private val context: Context) {
|
open class AnimeSourceManager(private val context: Context) {
|
|
@ -1,4 +1,4 @@
|
||||||
package eu.kanade.tachiyomi.source
|
package eu.kanade.tachiyomi.animesource
|
||||||
|
|
||||||
import androidx.preference.PreferenceScreen
|
import androidx.preference.PreferenceScreen
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
package eu.kanade.tachiyomi.source
|
package eu.kanade.tachiyomi.animesource
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import com.github.junrar.Archive
|
import com.github.junrar.Archive
|
||||||
import com.google.gson.JsonParser
|
import com.google.gson.JsonParser
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
import eu.kanade.tachiyomi.source.model.AnimesPage
|
import eu.kanade.tachiyomi.animesource.model.AnimesPage
|
||||||
import eu.kanade.tachiyomi.source.model.Filter
|
import eu.kanade.tachiyomi.animesource.model.Filter
|
||||||
import eu.kanade.tachiyomi.source.model.FilterList
|
import eu.kanade.tachiyomi.animesource.model.FilterList
|
||||||
import eu.kanade.tachiyomi.source.model.SAnime
|
import eu.kanade.tachiyomi.animesource.model.SAnime
|
||||||
import eu.kanade.tachiyomi.source.model.SEpisode
|
import eu.kanade.tachiyomi.animesource.model.SEpisode
|
||||||
import eu.kanade.tachiyomi.util.episode.EpisodeRecognition
|
import eu.kanade.tachiyomi.util.episode.EpisodeRecognition
|
||||||
import eu.kanade.tachiyomi.util.lang.compareToCaseInsensitiveNaturalOrder
|
import eu.kanade.tachiyomi.util.lang.compareToCaseInsensitiveNaturalOrder
|
||||||
import eu.kanade.tachiyomi.util.storage.AnimeFile
|
import eu.kanade.tachiyomi.util.storage.AnimeFile
|
|
@ -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)
|
data class AnimesPage(val animes: List<SAnime>, val hasNextPage: Boolean)
|
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
|
@ -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())
|
||||||
|
}
|
|
@ -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
|
import java.io.Serializable
|
||||||
|
|
||||||
interface SAnime : Serializable {
|
interface SAnime : Serializable {
|
|
@ -1,4 +1,4 @@
|
||||||
package eu.kanade.tachiyomi.source.model
|
package eu.kanade.tachiyomi.animesource.model
|
||||||
|
|
||||||
class SAnimeImpl : SAnime {
|
class SAnimeImpl : SAnime {
|
||||||
|
|
|
@ -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
|
import java.io.Serializable
|
||||||
|
|
||||||
interface SEpisode : Serializable {
|
interface SEpisode : Serializable {
|
|
@ -1,4 +1,4 @@
|
||||||
package eu.kanade.tachiyomi.source.model
|
package eu.kanade.tachiyomi.animesource.model
|
||||||
|
|
||||||
class SEpisodeImpl : SEpisode {
|
class SEpisodeImpl : SEpisode {
|
||||||
|
|
|
@ -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
|
||||||
|
)
|
||||||
|
}
|
|
@ -1,20 +1,19 @@
|
||||||
package eu.kanade.tachiyomi.source.online
|
package eu.kanade.tachiyomi.animesource.online
|
||||||
|
|
||||||
import eu.kanade.tachiyomi.network.GET
|
import android.net.Uri
|
||||||
import eu.kanade.tachiyomi.network.NetworkHelper
|
import eu.kanade.tachiyomi.animesource.AnimeCatalogueSource
|
||||||
import eu.kanade.tachiyomi.network.asObservableSuccess
|
import eu.kanade.tachiyomi.animesource.model.AnimesPage
|
||||||
import eu.kanade.tachiyomi.network.newCallWithProgress
|
import eu.kanade.tachiyomi.animesource.model.FilterList
|
||||||
import eu.kanade.tachiyomi.source.AnimeCatalogueSource
|
import eu.kanade.tachiyomi.animesource.model.SAnime
|
||||||
import eu.kanade.tachiyomi.source.model.AnimesPage
|
import eu.kanade.tachiyomi.animesource.model.SEpisode
|
||||||
import eu.kanade.tachiyomi.source.model.FilterList
|
import eu.kanade.tachiyomi.animesource.model.Video
|
||||||
import eu.kanade.tachiyomi.source.model.Page
|
import eu.kanade.tachiyomi.network.*
|
||||||
import eu.kanade.tachiyomi.source.model.SAnime
|
|
||||||
import eu.kanade.tachiyomi.source.model.SEpisode
|
|
||||||
import okhttp3.Headers
|
import okhttp3.Headers
|
||||||
import okhttp3.OkHttpClient
|
import okhttp3.OkHttpClient
|
||||||
import okhttp3.Request
|
import okhttp3.Request
|
||||||
import okhttp3.Response
|
import okhttp3.Response
|
||||||
import rx.Observable
|
import rx.Observable
|
||||||
|
import timber.log.Timber
|
||||||
import uy.kohesive.injekt.injectLazy
|
import uy.kohesive.injekt.injectLazy
|
||||||
import java.net.URI
|
import java.net.URI
|
||||||
import java.net.URISyntaxException
|
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
|
* 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.
|
* 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
|
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
|
* 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.
|
* database and the urls could still work after a domain change.
|
|
@ -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.animesource.model.AnimesPage
|
||||||
import eu.kanade.tachiyomi.source.model.Page
|
import eu.kanade.tachiyomi.animesource.model.SAnime
|
||||||
import eu.kanade.tachiyomi.source.model.SAnime
|
import eu.kanade.tachiyomi.animesource.model.SEpisode
|
||||||
import eu.kanade.tachiyomi.source.model.SEpisode
|
|
||||||
import eu.kanade.tachiyomi.util.asJsoup
|
import eu.kanade.tachiyomi.util.asJsoup
|
||||||
import okhttp3.Response
|
import okhttp3.Response
|
||||||
import org.jsoup.nodes.Document
|
import org.jsoup.nodes.Document
|
||||||
|
@ -187,36 +186,4 @@ abstract class ParsedAnimeHttpSource : AnimeHttpSource() {
|
||||||
* @param element an element obtained from [episodeListSelector].
|
* @param element an element obtained from [episodeListSelector].
|
||||||
*/
|
*/
|
||||||
protected abstract fun linkFromElement(element: Element): String
|
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
|
|
||||||
}
|
}
|
|
@ -7,6 +7,10 @@ import android.os.IBinder
|
||||||
import android.os.PowerManager
|
import android.os.PowerManager
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import eu.kanade.tachiyomi.R
|
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.AnimelibUpdateRanker.rankingScheme
|
||||||
import eu.kanade.tachiyomi.data.animelib.AnimelibUpdateService.Companion.start
|
import eu.kanade.tachiyomi.data.animelib.AnimelibUpdateService.Companion.start
|
||||||
import eu.kanade.tachiyomi.data.cache.AnimeCoverCache
|
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.TrackManager
|
||||||
import eu.kanade.tachiyomi.data.track.TrackService
|
import eu.kanade.tachiyomi.data.track.TrackService
|
||||||
import eu.kanade.tachiyomi.data.track.UnattendedTrackService
|
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.NoEpisodesException
|
||||||
import eu.kanade.tachiyomi.util.episode.syncEpisodesWithSource
|
import eu.kanade.tachiyomi.util.episode.syncEpisodesWithSource
|
||||||
import eu.kanade.tachiyomi.util.episode.syncEpisodesWithTrackServiceTwoWay
|
import eu.kanade.tachiyomi.util.episode.syncEpisodesWithTrackServiceTwoWay
|
||||||
|
|
|
@ -2,6 +2,8 @@ package eu.kanade.tachiyomi.data.backup
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.net.Uri
|
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.AnimeDatabaseHelper
|
||||||
import eu.kanade.tachiyomi.data.database.DatabaseHelper
|
import eu.kanade.tachiyomi.data.database.DatabaseHelper
|
||||||
import eu.kanade.tachiyomi.data.database.models.Anime
|
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.database.models.toMangaInfo
|
||||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||||
import eu.kanade.tachiyomi.data.track.TrackManager
|
import eu.kanade.tachiyomi.data.track.TrackManager
|
||||||
import eu.kanade.tachiyomi.source.AnimeSource
|
|
||||||
import eu.kanade.tachiyomi.source.Source
|
import eu.kanade.tachiyomi.source.Source
|
||||||
import eu.kanade.tachiyomi.source.SourceManager
|
import eu.kanade.tachiyomi.source.SourceManager
|
||||||
import eu.kanade.tachiyomi.source.model.toSChapter
|
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.chapter.syncChaptersWithSource
|
||||||
import eu.kanade.tachiyomi.util.episode.syncEpisodesWithSource
|
import eu.kanade.tachiyomi.util.episode.syncEpisodesWithSource
|
||||||
import uy.kohesive.injekt.injectLazy
|
import uy.kohesive.injekt.injectLazy
|
||||||
|
|
|
@ -8,6 +8,8 @@ import com.github.salomonbrys.kotson.registerTypeHierarchyAdapter
|
||||||
import com.google.gson.Gson
|
import com.google.gson.Gson
|
||||||
import com.google.gson.GsonBuilder
|
import com.google.gson.GsonBuilder
|
||||||
import com.google.gson.JsonArray
|
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.AbstractBackupManager
|
||||||
import eu.kanade.tachiyomi.data.backup.legacy.models.Backup.CURRENT_VERSION
|
import eu.kanade.tachiyomi.data.backup.legacy.models.Backup.CURRENT_VERSION
|
||||||
import eu.kanade.tachiyomi.data.backup.legacy.models.DHistory
|
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.TrackImpl
|
||||||
import eu.kanade.tachiyomi.data.database.models.toAnimeInfo
|
import eu.kanade.tachiyomi.data.database.models.toAnimeInfo
|
||||||
import eu.kanade.tachiyomi.data.database.models.toMangaInfo
|
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.Source
|
||||||
import eu.kanade.tachiyomi.source.model.toSAnime
|
|
||||||
import eu.kanade.tachiyomi.source.model.toSManga
|
import eu.kanade.tachiyomi.source.model.toSManga
|
||||||
import kotlin.math.max
|
import kotlin.math.max
|
||||||
|
|
||||||
|
|
|
@ -4,8 +4,8 @@ import android.content.Context
|
||||||
import android.text.format.Formatter
|
import android.text.format.Formatter
|
||||||
import com.google.gson.Gson
|
import com.google.gson.Gson
|
||||||
import com.jakewharton.disklrucache.DiskLruCache
|
import com.jakewharton.disklrucache.DiskLruCache
|
||||||
|
import eu.kanade.tachiyomi.animesource.model.Video
|
||||||
import eu.kanade.tachiyomi.data.database.models.Episode
|
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.DiskUtil
|
||||||
import eu.kanade.tachiyomi.util.storage.saveTo
|
import eu.kanade.tachiyomi.util.storage.saveTo
|
||||||
import okhttp3.Response
|
import okhttp3.Response
|
||||||
|
@ -97,9 +97,9 @@ class EpisodeCache(private val context: Context) {
|
||||||
* @param episode the episode.
|
* @param episode the episode.
|
||||||
* @param pages list of pages.
|
* @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.
|
// 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).
|
// Initialize the editor (edits the values for an entry).
|
||||||
var editor: DiskLruCache.Editor? = null
|
var editor: DiskLruCache.Editor? = null
|
||||||
|
@ -145,7 +145,7 @@ class EpisodeCache(private val context: Context) {
|
||||||
* @param imageUrl url of image.
|
* @param imageUrl url of image.
|
||||||
* @return path of image.
|
* @return path of image.
|
||||||
*/
|
*/
|
||||||
fun getImageFile(imageUrl: String): File {
|
fun getVideoFile(imageUrl: String): File {
|
||||||
// Get file from md5 key.
|
// Get file from md5 key.
|
||||||
val imageName = DiskUtil.hashKeyForDisk(imageUrl) + ".0"
|
val imageName = DiskUtil.hashKeyForDisk(imageUrl) + ".0"
|
||||||
return File(diskCache.directory, imageName)
|
return File(diskCache.directory, imageName)
|
||||||
|
|
|
@ -9,12 +9,12 @@ import coil.fetch.SourceResult
|
||||||
import coil.network.HttpException
|
import coil.network.HttpException
|
||||||
import coil.request.get
|
import coil.request.get
|
||||||
import coil.size.Size
|
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.cache.AnimeCoverCache
|
||||||
import eu.kanade.tachiyomi.data.database.models.Anime
|
import eu.kanade.tachiyomi.data.database.models.Anime
|
||||||
import eu.kanade.tachiyomi.network.NetworkHelper
|
import eu.kanade.tachiyomi.network.NetworkHelper
|
||||||
import eu.kanade.tachiyomi.network.await
|
import eu.kanade.tachiyomi.network.await
|
||||||
import eu.kanade.tachiyomi.source.AnimeSourceManager
|
|
||||||
import eu.kanade.tachiyomi.source.online.AnimeHttpSource
|
|
||||||
import okhttp3.CacheControl
|
import okhttp3.CacheControl
|
||||||
import okhttp3.Call
|
import okhttp3.Call
|
||||||
import okhttp3.Request
|
import okhttp3.Request
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package eu.kanade.tachiyomi.data.database.models
|
package eu.kanade.tachiyomi.data.database.models
|
||||||
|
|
||||||
import eu.kanade.tachiyomi.source.model.SAnime
|
import eu.kanade.tachiyomi.animesource.model.SAnime
|
||||||
import tachiyomi.source.model.AnimeInfo
|
import tachiyomi.animesource.model.AnimeInfo
|
||||||
|
|
||||||
interface Anime : SAnime {
|
interface Anime : SAnime {
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
package eu.kanade.tachiyomi.data.database.models
|
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
|
import java.io.Serializable
|
||||||
|
|
||||||
interface Episode : SEpisode, Serializable {
|
interface Episode : SEpisode, Serializable {
|
||||||
|
|
|
@ -3,10 +3,10 @@ package eu.kanade.tachiyomi.data.download
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import androidx.core.net.toUri
|
import androidx.core.net.toUri
|
||||||
import com.hippo.unifile.UniFile
|
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.Anime
|
||||||
import eu.kanade.tachiyomi.data.database.models.Episode
|
import eu.kanade.tachiyomi.data.database.models.Episode
|
||||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||||
import eu.kanade.tachiyomi.source.AnimeSourceManager
|
|
||||||
import kotlinx.coroutines.flow.onEach
|
import kotlinx.coroutines.flow.onEach
|
||||||
import uy.kohesive.injekt.Injekt
|
import uy.kohesive.injekt.Injekt
|
||||||
import uy.kohesive.injekt.api.get
|
import uy.kohesive.injekt.api.get
|
||||||
|
|
|
@ -4,14 +4,14 @@ import android.content.Context
|
||||||
import com.hippo.unifile.UniFile
|
import com.hippo.unifile.UniFile
|
||||||
import com.jakewharton.rxrelay.BehaviorRelay
|
import com.jakewharton.rxrelay.BehaviorRelay
|
||||||
import eu.kanade.tachiyomi.R
|
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.Anime
|
||||||
import eu.kanade.tachiyomi.data.database.models.Episode
|
import eu.kanade.tachiyomi.data.database.models.Episode
|
||||||
import eu.kanade.tachiyomi.data.download.model.AnimeDownload
|
import eu.kanade.tachiyomi.data.download.model.AnimeDownload
|
||||||
import eu.kanade.tachiyomi.data.download.model.AnimeDownloadQueue
|
import eu.kanade.tachiyomi.data.download.model.AnimeDownloadQueue
|
||||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
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 eu.kanade.tachiyomi.util.lang.launchIO
|
||||||
import rx.Observable
|
import rx.Observable
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
|
@ -137,8 +137,8 @@ class AnimeDownloadManager(private val context: Context) {
|
||||||
* @param episode the downloaded episode.
|
* @param episode the downloaded episode.
|
||||||
* @return an observable containing the list of pages from the episode.
|
* @return an observable containing the list of pages from the episode.
|
||||||
*/
|
*/
|
||||||
fun buildPageList(source: AnimeSource, anime: Anime, episode: Episode): Observable<List<Page>> {
|
fun buildVideo(source: AnimeSource, anime: Anime, episode: Episode): Observable<Video> {
|
||||||
return buildPageList(provider.findEpisodeDir(episode, anime, source))
|
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.
|
* @param episodeDir the file where the episode is downloaded.
|
||||||
* @return an observable containing the list of pages from the episode.
|
* @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 {
|
return Observable.fromCallable {
|
||||||
val files = episodeDir?.listFiles().orEmpty()
|
val files = episodeDir?.listFiles().orEmpty()
|
||||||
.filter { "image" in it.type.orEmpty() }
|
.filter { "video" in it.type.orEmpty() }
|
||||||
|
|
||||||
if (files.isEmpty()) {
|
if (files.isEmpty()) {
|
||||||
throw Exception(context.getString(R.string.page_list_empty_error))
|
throw Exception(context.getString(R.string.page_list_empty_error))
|
||||||
}
|
}
|
||||||
|
|
||||||
files.sortedBy { it.name }
|
val file = files[0]
|
||||||
.mapIndexed { i, file ->
|
Video(uri = file.uri).apply { status = Video.READY }
|
||||||
Page(i, uri = file.uri).apply { status = Page.READY }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -100,7 +100,7 @@ internal class AnimeDownloadNotifier(private val context: Context) {
|
||||||
val downloadingProgressText = context.getString(
|
val downloadingProgressText = context.getString(
|
||||||
R.string.chapter_downloading_progress,
|
R.string.chapter_downloading_progress,
|
||||||
download.downloadedImages,
|
download.downloadedImages,
|
||||||
download.pages!!.size
|
1
|
||||||
)
|
)
|
||||||
|
|
||||||
if (preferences.hideNotificationContent()) {
|
if (preferences.hideNotificationContent()) {
|
||||||
|
@ -113,7 +113,7 @@ internal class AnimeDownloadNotifier(private val context: Context) {
|
||||||
setContentText(downloadingProgressText)
|
setContentText(downloadingProgressText)
|
||||||
}
|
}
|
||||||
|
|
||||||
setProgress(download.pages!!.size, download.downloadedImages, false)
|
setProgress(1, download.downloadedImages, false)
|
||||||
setOngoing(true)
|
setOngoing(true)
|
||||||
|
|
||||||
show(Notifications.ID_DOWNLOAD_CHAPTER_PROGRESS)
|
show(Notifications.ID_DOWNLOAD_CHAPTER_PROGRESS)
|
||||||
|
|
|
@ -4,10 +4,10 @@ import android.content.Context
|
||||||
import androidx.core.net.toUri
|
import androidx.core.net.toUri
|
||||||
import com.hippo.unifile.UniFile
|
import com.hippo.unifile.UniFile
|
||||||
import eu.kanade.tachiyomi.R
|
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.Anime
|
||||||
import eu.kanade.tachiyomi.data.database.models.Episode
|
import eu.kanade.tachiyomi.data.database.models.Episode
|
||||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||||
import eu.kanade.tachiyomi.source.AnimeSource
|
|
||||||
import eu.kanade.tachiyomi.util.storage.DiskUtil
|
import eu.kanade.tachiyomi.util.storage.DiskUtil
|
||||||
import kotlinx.coroutines.MainScope
|
import kotlinx.coroutines.MainScope
|
||||||
import kotlinx.coroutines.flow.launchIn
|
import kotlinx.coroutines.flow.launchIn
|
||||||
|
|
|
@ -2,11 +2,11 @@ package eu.kanade.tachiyomi.data.download
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import androidx.core.content.edit
|
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.AnimeDatabaseHelper
|
||||||
import eu.kanade.tachiyomi.data.database.models.Anime
|
import eu.kanade.tachiyomi.data.database.models.Anime
|
||||||
import eu.kanade.tachiyomi.data.download.model.AnimeDownload
|
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.Serializable
|
||||||
import kotlinx.serialization.decodeFromString
|
import kotlinx.serialization.decodeFromString
|
||||||
import kotlinx.serialization.encodeToString
|
import kotlinx.serialization.encodeToString
|
||||||
|
|
|
@ -1,20 +1,21 @@
|
||||||
package eu.kanade.tachiyomi.data.download
|
package eu.kanade.tachiyomi.data.download
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import android.util.Log
|
||||||
import android.webkit.MimeTypeMap
|
import android.webkit.MimeTypeMap
|
||||||
import com.hippo.unifile.UniFile
|
import com.hippo.unifile.UniFile
|
||||||
import com.jakewharton.rxrelay.BehaviorRelay
|
import com.jakewharton.rxrelay.BehaviorRelay
|
||||||
import com.jakewharton.rxrelay.PublishRelay
|
import com.jakewharton.rxrelay.PublishRelay
|
||||||
import eu.kanade.tachiyomi.R
|
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.cache.EpisodeCache
|
||||||
import eu.kanade.tachiyomi.data.database.models.Anime
|
import eu.kanade.tachiyomi.data.database.models.Anime
|
||||||
import eu.kanade.tachiyomi.data.database.models.Episode
|
import eu.kanade.tachiyomi.data.database.models.Episode
|
||||||
import eu.kanade.tachiyomi.data.download.model.AnimeDownload
|
import eu.kanade.tachiyomi.data.download.model.AnimeDownload
|
||||||
import eu.kanade.tachiyomi.data.download.model.AnimeDownloadQueue
|
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.RetryWithDelay
|
||||||
import eu.kanade.tachiyomi.util.lang.launchIO
|
import eu.kanade.tachiyomi.util.lang.launchIO
|
||||||
import eu.kanade.tachiyomi.util.lang.launchNow
|
import eu.kanade.tachiyomi.util.lang.launchNow
|
||||||
|
@ -257,7 +258,8 @@ class AnimeDownloader(
|
||||||
|
|
||||||
// Start downloader if needed
|
// Start downloader if needed
|
||||||
if (autoStart && wasEmpty) {
|
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 episodeDirname = provider.getEpisodeDirName(download.episode)
|
||||||
val tmpDir = animeDir.createDirectory(episodeDirname + TMP_DIR_SUFFIX)
|
val tmpDir = animeDir.createDirectory(episodeDirname + TMP_DIR_SUFFIX)
|
||||||
|
|
||||||
val pageListObservable = if (download.pages == null) {
|
val videoObservable = if (download.video == null) {
|
||||||
// Pull page list from network and add them to download object
|
// Pull video from network and add them to download object
|
||||||
Observable.just(emptyList())
|
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 {
|
} else {
|
||||||
// Or if the page list already exists, start from the file
|
// Or if the video already exists, start from the file
|
||||||
Observable.just(download.pages!!)
|
Observable.just(download.video!!)
|
||||||
}
|
}
|
||||||
|
|
||||||
pageListObservable
|
videoObservable
|
||||||
.doOnNext { _ ->
|
.doOnNext { _ ->
|
||||||
// Delete all temporary (unfinished) files
|
// Delete all temporary (unfinished) files
|
||||||
|
Timber.w("delfiles")
|
||||||
tmpDir.listFiles()
|
tmpDir.listFiles()
|
||||||
?.filter { it.name!!.endsWith(".tmp") }
|
?.filter { it.name!!.endsWith(".tmp") }
|
||||||
?.forEach { it.delete() }
|
?.forEach { it.delete() }
|
||||||
|
@ -299,10 +309,10 @@ class AnimeDownloader(
|
||||||
download.status = AnimeDownload.State.DOWNLOADING
|
download.status = AnimeDownload.State.DOWNLOADING
|
||||||
}
|
}
|
||||||
// Get all the URLs to the source images, fetch pages if necessary
|
// 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
|
// Start downloading images, consider we can have downloaded images already
|
||||||
// Concurrently do 5 pages at a time
|
// Concurrently do 5 pages at a time
|
||||||
.flatMap({ page -> getOrAnimeDownloadImage(page, download, tmpDir) }, 5)
|
.flatMap({ video -> getOrAnimeDownloadImage(video, download, tmpDir) }, 5)
|
||||||
.onBackpressureLatest()
|
.onBackpressureLatest()
|
||||||
// Do when page is downloaded.
|
// Do when page is downloaded.
|
||||||
.doOnNext { notifier.onProgressChange(download) }
|
.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
|
* Returns the observable which gets the image from the filesystem if it exists or downloads it
|
||||||
* otherwise.
|
* otherwise.
|
||||||
*
|
*
|
||||||
* @param page the page to download.
|
* @param video the page to download.
|
||||||
* @param download the download of the page.
|
* @param download the download of the page.
|
||||||
* @param tmpDir the temporary directory of the download.
|
* @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 the image URL is empty, do nothing
|
||||||
if (page.imageUrl == null) {
|
if (video.videoUrl == null) {
|
||||||
return Observable.just(page)
|
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")
|
val tmpFile = tmpDir.findFile("$filename.tmp")
|
||||||
|
|
||||||
// Delete temp file if it exists.
|
// Delete temp file if it exists.
|
||||||
tmpFile?.delete()
|
tmpFile?.delete()
|
||||||
|
|
||||||
// Try to find the image file.
|
// 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 {
|
val pageObservable = when {
|
||||||
imageFile != null -> Observable.just(imageFile)
|
videoFile != null -> Observable.just(videoFile)
|
||||||
episodeCache.isImageInCache(page.imageUrl!!) -> copyImageFromCache(episodeCache.getImageFile(page.imageUrl!!), tmpDir, filename)
|
episodeCache.isImageInCache(video.videoUrl!!) -> copyVideoFromCache(episodeCache.getVideoFile(video.videoUrl!!), tmpDir, filename)
|
||||||
else -> downloadImage(page, download.source, tmpDir, filename)
|
else -> downloadVideo(video, download.source, tmpDir, filename)
|
||||||
}
|
}
|
||||||
|
|
||||||
return pageObservable
|
return pageObservable
|
||||||
// When the image is ready, set image path, progress (just in case) and status
|
// When the image is ready, set image path, progress (just in case) and status
|
||||||
.doOnNext { file ->
|
.doOnNext { file ->
|
||||||
page.uri = file.uri
|
video.uri = file.uri
|
||||||
page.progress = 100
|
video.progress = 100
|
||||||
download.downloadedImages++
|
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
|
// Mark this page as error and allow to download the remaining
|
||||||
.onErrorReturn {
|
.onErrorReturn {
|
||||||
page.progress = 0
|
video.progress = 0
|
||||||
page.status = Page.ERROR
|
video.status = Video.ERROR
|
||||||
page
|
video
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the observable which downloads the image from network.
|
* 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 source the source of the page.
|
||||||
* @param tmpDir the temporary directory of the download.
|
* @param tmpDir the temporary directory of the download.
|
||||||
* @param filename the filename of the image.
|
* @param filename the filename of the image.
|
||||||
*/
|
*/
|
||||||
private fun downloadImage(page: Page, source: AnimeHttpSource, tmpDir: UniFile, filename: String): Observable<UniFile> {
|
private fun downloadVideo(video: Video, source: AnimeHttpSource, tmpDir: UniFile, filename: String): Observable<UniFile> {
|
||||||
page.status = Page.DOWNLOAD_IMAGE
|
video.status = Video.DOWNLOAD_IMAGE
|
||||||
page.progress = 0
|
video.progress = 0
|
||||||
return source.fetchImage(page)
|
return source.fetchVideo(video)
|
||||||
.map { response ->
|
.map { response ->
|
||||||
val file = tmpDir.createFile("$filename.tmp")
|
val file = tmpDir.createFile("$filename.tmp")
|
||||||
try {
|
try {
|
||||||
|
@ -401,7 +413,7 @@ class AnimeDownloader(
|
||||||
* @param tmpDir the temporary directory of the download.
|
* @param tmpDir the temporary directory of the download.
|
||||||
* @param filename the filename of the image.
|
* @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 {
|
return Observable.just(cacheFile).map {
|
||||||
val tmpFile = tmpDir.createFile("$filename.tmp")
|
val tmpFile = tmpDir.createFile("$filename.tmp")
|
||||||
cacheFile.inputStream().use { input ->
|
cacheFile.inputStream().use { input ->
|
||||||
|
@ -451,7 +463,7 @@ class AnimeDownloader(
|
||||||
// Ensure that the episode folder has all the images.
|
// Ensure that the episode folder has all the images.
|
||||||
val downloadedImages = tmpDir.listFiles().orEmpty().filterNot { it.name!!.endsWith(".tmp") }
|
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
|
AnimeDownload.State.DOWNLOADED
|
||||||
} else {
|
} else {
|
||||||
AnimeDownload.State.ERROR
|
AnimeDownload.State.ERROR
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
package eu.kanade.tachiyomi.data.download.model
|
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.Anime
|
||||||
import eu.kanade.tachiyomi.data.database.models.Episode
|
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
|
import rx.subjects.PublishSubject
|
||||||
|
|
||||||
class AnimeDownload(val source: AnimeHttpSource, val anime: Anime, val episode: Episode) {
|
class AnimeDownload(val source: AnimeHttpSource, val anime: Anime, val episode: Episode) {
|
||||||
|
|
||||||
var pages: List<Page>? = null
|
var video: Video? = null
|
||||||
|
|
||||||
@Volatile
|
@Volatile
|
||||||
@Transient
|
@Transient
|
||||||
|
@ -35,8 +35,8 @@ class AnimeDownload(val source: AnimeHttpSource, val anime: Anime, val episode:
|
||||||
|
|
||||||
val progress: Int
|
val progress: Int
|
||||||
get() {
|
get() {
|
||||||
val pages = pages ?: return 0
|
val video = video ?: return 0
|
||||||
return pages.map(Page::progress).average().toInt()
|
return video.progress
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setStatusSubject(subject: PublishSubject<AnimeDownload>?) {
|
fun setStatusSubject(subject: PublishSubject<AnimeDownload>?) {
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
package eu.kanade.tachiyomi.data.download.model
|
package eu.kanade.tachiyomi.data.download.model
|
||||||
|
|
||||||
import com.jakewharton.rxrelay.PublishRelay
|
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.Anime
|
||||||
import eu.kanade.tachiyomi.data.database.models.Episode
|
import eu.kanade.tachiyomi.data.database.models.Episode
|
||||||
import eu.kanade.tachiyomi.data.download.AnimeDownloadStore
|
import eu.kanade.tachiyomi.data.download.AnimeDownloadStore
|
||||||
import eu.kanade.tachiyomi.source.model.Page
|
|
||||||
import rx.Observable
|
import rx.Observable
|
||||||
import rx.subjects.PublishSubject
|
import rx.subjects.PublishSubject
|
||||||
import java.util.concurrent.CopyOnWriteArrayList
|
import java.util.concurrent.CopyOnWriteArrayList
|
||||||
|
@ -80,7 +80,7 @@ class AnimeDownloadQueue(
|
||||||
|
|
||||||
private fun setPagesFor(download: AnimeDownload) {
|
private fun setPagesFor(download: AnimeDownload) {
|
||||||
if (download.status == AnimeDownload.State.DOWNLOADED || download.status == AnimeDownload.State.ERROR) {
|
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 ->
|
.flatMap { download ->
|
||||||
if (download.status == AnimeDownload.State.DOWNLOADING) {
|
if (download.status == AnimeDownload.State.DOWNLOADING) {
|
||||||
val pageStatusSubject = PublishSubject.create<Int>()
|
val pageStatusSubject = PublishSubject.create<Int>()
|
||||||
setPagesSubject(download.pages, pageStatusSubject)
|
setPagesSubject(download.video, pageStatusSubject)
|
||||||
return@flatMap pageStatusSubject
|
return@flatMap pageStatusSubject
|
||||||
.onBackpressureBuffer()
|
.onBackpressureBuffer()
|
||||||
.filter { it == Page.READY }
|
.filter { it == Video.READY }
|
||||||
.map { download }
|
.map { download }
|
||||||
} else if (download.status == AnimeDownload.State.DOWNLOADED || download.status == AnimeDownload.State.ERROR) {
|
} else if (download.status == AnimeDownload.State.DOWNLOADED || download.status == AnimeDownload.State.ERROR) {
|
||||||
setPagesSubject(download.pages, null)
|
setPagesSubject(download.video, null)
|
||||||
}
|
}
|
||||||
Observable.just(download)
|
Observable.just(download)
|
||||||
}
|
}
|
||||||
.filter { it.status == AnimeDownload.State.DOWNLOADING }
|
.filter { it.status == AnimeDownload.State.DOWNLOADING }
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setPagesSubject(pages: List<Page>?, subject: PublishSubject<Int>?) {
|
private fun setPagesSubject(video: Video?, subject: PublishSubject<Int>?) {
|
||||||
pages?.forEach { it.setStatusSubject(subject) }
|
video?.setStatusSubject(subject)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@ import android.net.Uri
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.Handler
|
import android.os.Handler
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
|
import eu.kanade.tachiyomi.animesource.AnimeSourceManager
|
||||||
import eu.kanade.tachiyomi.data.animelib.AnimelibUpdateService
|
import eu.kanade.tachiyomi.data.animelib.AnimelibUpdateService
|
||||||
import eu.kanade.tachiyomi.data.backup.BackupRestoreService
|
import eu.kanade.tachiyomi.data.backup.BackupRestoreService
|
||||||
import eu.kanade.tachiyomi.data.database.DatabaseHelper
|
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.download.DownloadService
|
||||||
import eu.kanade.tachiyomi.data.library.LibraryUpdateService
|
import eu.kanade.tachiyomi.data.library.LibraryUpdateService
|
||||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||||
import eu.kanade.tachiyomi.source.AnimeSourceManager
|
|
||||||
import eu.kanade.tachiyomi.source.SourceManager
|
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.AnimeController
|
||||||
import eu.kanade.tachiyomi.ui.anime.episode.EpisodeItem
|
import eu.kanade.tachiyomi.ui.anime.episode.EpisodeItem
|
||||||
import eu.kanade.tachiyomi.ui.main.MainActivity
|
import eu.kanade.tachiyomi.ui.main.MainActivity
|
||||||
import eu.kanade.tachiyomi.ui.manga.MangaController
|
import eu.kanade.tachiyomi.ui.manga.MangaController
|
||||||
import eu.kanade.tachiyomi.ui.reader.ReaderActivity
|
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.ui.watcher.WatcherActivity
|
||||||
import eu.kanade.tachiyomi.util.lang.launchIO
|
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.DiskUtil
|
||||||
import eu.kanade.tachiyomi.util.storage.getUriCompat
|
import eu.kanade.tachiyomi.util.storage.getUriCompat
|
||||||
import eu.kanade.tachiyomi.util.system.notificationManager
|
import eu.kanade.tachiyomi.util.system.notificationManager
|
||||||
import eu.kanade.tachiyomi.util.system.toast
|
import eu.kanade.tachiyomi.util.system.toast
|
||||||
import kotlinx.coroutines.runBlocking
|
|
||||||
import uy.kohesive.injekt.Injekt
|
import uy.kohesive.injekt.Injekt
|
||||||
import uy.kohesive.injekt.api.get
|
import uy.kohesive.injekt.api.get
|
||||||
import uy.kohesive.injekt.injectLazy
|
import uy.kohesive.injekt.injectLazy
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.util.Collections.emptyList
|
import java.util.Collections.emptyList
|
||||||
import kotlin.coroutines.resume
|
|
||||||
import kotlin.coroutines.suspendCoroutine
|
|
||||||
import eu.kanade.tachiyomi.BuildConfig.APPLICATION_ID as ID
|
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 {
|
internal fun openEpisodePendingActivity(context: Context, anime: Anime, episode: Episode): PendingIntent {
|
||||||
val source = Injekt.get<AnimeSourceManager>().getOrStub(anime.source)
|
val source = Injekt.get<AnimeSourceManager>().getOrStub(anime.source)
|
||||||
val link = runBlocking {
|
val link = EpisodeLoader.getUri(episode, anime, source)
|
||||||
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 episodeList: List<EpisodeItem> = emptyList()
|
val episodeList: List<EpisodeItem> = emptyList()
|
||||||
val newIntent = WatcherActivity.newIntent(context, anime, episode, episodeList, link)
|
val newIntent = WatcherActivity.newIntent(context, anime, episode, episodeList, link)
|
||||||
return PendingIntent.getActivity(context, AnimeController.REQUEST_INTERNAL, newIntent, PendingIntent.FLAG_UPDATE_CURRENT)
|
return PendingIntent.getActivity(context, AnimeController.REQUEST_INTERNAL, newIntent, PendingIntent.FLAG_UPDATE_CURRENT)
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
package eu.kanade.tachiyomi.data.track
|
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.Anime
|
||||||
import eu.kanade.tachiyomi.data.database.models.Manga
|
import eu.kanade.tachiyomi.data.database.models.Manga
|
||||||
import eu.kanade.tachiyomi.data.track.model.AnimeTrackSearch
|
import eu.kanade.tachiyomi.data.track.model.AnimeTrackSearch
|
||||||
import eu.kanade.tachiyomi.data.track.model.TrackSearch
|
import eu.kanade.tachiyomi.data.track.model.TrackSearch
|
||||||
import eu.kanade.tachiyomi.source.AnimeSource
|
|
||||||
import eu.kanade.tachiyomi.source.Source
|
import eu.kanade.tachiyomi.source.Source
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -4,6 +4,7 @@ import android.content.Context
|
||||||
import android.graphics.Color
|
import android.graphics.Color
|
||||||
import androidx.annotation.StringRes
|
import androidx.annotation.StringRes
|
||||||
import eu.kanade.tachiyomi.R
|
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.Anime
|
||||||
import eu.kanade.tachiyomi.data.database.models.AnimeTrack
|
import eu.kanade.tachiyomi.data.database.models.AnimeTrack
|
||||||
import eu.kanade.tachiyomi.data.database.models.Manga
|
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.UnattendedTrackService
|
||||||
import eu.kanade.tachiyomi.data.track.model.AnimeTrackSearch
|
import eu.kanade.tachiyomi.data.track.model.AnimeTrackSearch
|
||||||
import eu.kanade.tachiyomi.data.track.model.TrackSearch
|
import eu.kanade.tachiyomi.data.track.model.TrackSearch
|
||||||
import eu.kanade.tachiyomi.source.AnimeSource
|
|
||||||
import eu.kanade.tachiyomi.source.Source
|
import eu.kanade.tachiyomi.source.Source
|
||||||
import okhttp3.Dns
|
import okhttp3.Dns
|
||||||
import okhttp3.OkHttpClient
|
import okhttp3.OkHttpClient
|
||||||
|
|
|
@ -3,6 +3,8 @@ package eu.kanade.tachiyomi.extension
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.graphics.drawable.Drawable
|
import android.graphics.drawable.Drawable
|
||||||
import com.jakewharton.rxrelay.BehaviorRelay
|
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.PreferencesHelper
|
||||||
import eu.kanade.tachiyomi.data.preference.plusAssign
|
import eu.kanade.tachiyomi.data.preference.plusAssign
|
||||||
import eu.kanade.tachiyomi.extension.api.AnimeExtensionGithubApi
|
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.AnimeExtensionInstallReceiver
|
||||||
import eu.kanade.tachiyomi.extension.util.AnimeExtensionInstaller
|
import eu.kanade.tachiyomi.extension.util.AnimeExtensionInstaller
|
||||||
import eu.kanade.tachiyomi.extension.util.AnimeExtensionLoader
|
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.lang.launchNow
|
||||||
import eu.kanade.tachiyomi.util.system.toast
|
import eu.kanade.tachiyomi.util.system.toast
|
||||||
import kotlinx.coroutines.async
|
import kotlinx.coroutines.async
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
package eu.kanade.tachiyomi.extension.model
|
package eu.kanade.tachiyomi.extension.model
|
||||||
|
|
||||||
import eu.kanade.tachiyomi.source.AnimeSource
|
import eu.kanade.tachiyomi.animesource.AnimeSource
|
||||||
|
|
||||||
sealed class AnimeExtension {
|
sealed class AnimeExtension {
|
||||||
|
|
||||||
|
|
|
@ -5,13 +5,13 @@ import android.content.Context
|
||||||
import android.content.pm.PackageInfo
|
import android.content.pm.PackageInfo
|
||||||
import android.content.pm.PackageManager
|
import android.content.pm.PackageManager
|
||||||
import dalvik.system.PathClassLoader
|
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.annotations.Nsfw
|
||||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||||
import eu.kanade.tachiyomi.extension.model.AnimeExtension
|
import eu.kanade.tachiyomi.extension.model.AnimeExtension
|
||||||
import eu.kanade.tachiyomi.extension.model.AnimeLoadResult
|
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 eu.kanade.tachiyomi.util.lang.Hash
|
||||||
import kotlinx.coroutines.async
|
import kotlinx.coroutines.async
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
|
|
|
@ -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) }
|
|
||||||
}
|
|
|
@ -26,6 +26,10 @@ import dev.chrisbanes.insetter.applyInsetter
|
||||||
import eu.davidea.flexibleadapter.FlexibleAdapter
|
import eu.davidea.flexibleadapter.FlexibleAdapter
|
||||||
import eu.davidea.flexibleadapter.SelectableAdapter
|
import eu.davidea.flexibleadapter.SelectableAdapter
|
||||||
import eu.kanade.tachiyomi.R
|
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.cache.AnimeCoverCache
|
||||||
import eu.kanade.tachiyomi.data.database.AnimeDatabaseHelper
|
import eu.kanade.tachiyomi.data.database.AnimeDatabaseHelper
|
||||||
import eu.kanade.tachiyomi.data.database.models.Anime
|
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.UnattendedTrackService
|
||||||
import eu.kanade.tachiyomi.data.track.model.AnimeTrackSearch
|
import eu.kanade.tachiyomi.data.track.model.AnimeTrackSearch
|
||||||
import eu.kanade.tachiyomi.databinding.AnimeControllerBinding
|
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.*
|
||||||
import eu.kanade.tachiyomi.ui.anime.episode.base.BaseEpisodesAdapter
|
import eu.kanade.tachiyomi.ui.anime.episode.base.BaseEpisodesAdapter
|
||||||
import eu.kanade.tachiyomi.ui.anime.info.AnimeInfoHeaderAdapter
|
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.main.MainActivity
|
||||||
import eu.kanade.tachiyomi.ui.recent.history.HistoryController
|
import eu.kanade.tachiyomi.ui.recent.history.HistoryController
|
||||||
import eu.kanade.tachiyomi.ui.recent.updates.UpdatesController
|
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.watcher.WatcherActivity
|
||||||
import eu.kanade.tachiyomi.ui.webview.WebViewActivity
|
import eu.kanade.tachiyomi.ui.webview.WebViewActivity
|
||||||
import eu.kanade.tachiyomi.util.episode.NoEpisodesException
|
import eu.kanade.tachiyomi.util.episode.NoEpisodesException
|
||||||
|
@ -80,8 +81,6 @@ import kotlinx.coroutines.async
|
||||||
import kotlinx.coroutines.awaitAll
|
import kotlinx.coroutines.awaitAll
|
||||||
import kotlinx.coroutines.flow.launchIn
|
import kotlinx.coroutines.flow.launchIn
|
||||||
import kotlinx.coroutines.flow.onEach
|
import kotlinx.coroutines.flow.onEach
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
import kotlinx.coroutines.runBlocking
|
|
||||||
import reactivecircus.flowbinding.recyclerview.scrollEvents
|
import reactivecircus.flowbinding.recyclerview.scrollEvents
|
||||||
import reactivecircus.flowbinding.swiperefreshlayout.refreshes
|
import reactivecircus.flowbinding.swiperefreshlayout.refreshes
|
||||||
import rx.schedulers.Schedulers
|
import rx.schedulers.Schedulers
|
||||||
|
@ -163,7 +162,7 @@ class AnimeController :
|
||||||
*/
|
*/
|
||||||
private val selectedEpisodes = mutableSetOf<EpisodeItem>()
|
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))
|
private var lastClickPositionStack = ArrayDeque(listOf(-1))
|
||||||
|
|
||||||
|
@ -337,7 +336,7 @@ class AnimeController :
|
||||||
// Create animation listener
|
// Create animation listener
|
||||||
val revealAnimationListener: Animator.AnimatorListener = object : AnimatorListenerAdapter() {
|
val revealAnimationListener: Animator.AnimatorListener = object : AnimatorListenerAdapter() {
|
||||||
override fun onAnimationStart(animation: Animator?) {
|
override fun onAnimationStart(animation: Animator?) {
|
||||||
openEpisode(item.episode, true)
|
openEpisode(item.episode)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -348,7 +347,7 @@ class AnimeController :
|
||||||
coordinates.y,
|
coordinates.y,
|
||||||
object : AnimatorListenerAdapter() {
|
object : AnimatorListenerAdapter() {
|
||||||
override fun onAnimationStart(animation: Animator?) {
|
override fun onAnimationStart(animation: Animator?) {
|
||||||
openEpisode(item.episode, true)
|
openEpisode(item.episode)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -901,28 +900,22 @@ class AnimeController :
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun openEpisode(episode: Episode, hasAnimation: Boolean = false) {
|
fun openEpisode(episode: Episode) {
|
||||||
val activity = activity ?: return
|
val activity = activity ?: return
|
||||||
runBlocking {
|
launchIO {
|
||||||
launch {
|
val url = EpisodeLoader.getUri(episode, anime!!, source!!)
|
||||||
val url = fetchEpisodeLinksFromSource(false, episode)
|
val episodeList = presenter.filteredAndSortedEpisodes
|
||||||
val episodeList = presenter.filteredAndSortedEpisodes
|
val intent = WatcherActivity.newIntent(activity, presenter.anime, episode, episodeList, url)
|
||||||
val intent = WatcherActivity.newIntent(activity, presenter.anime, episode, episodeList, url)
|
if (!preferences.alwaysUseExternalPlayer()) {
|
||||||
if (hasAnimation) {
|
startActivityForResult(intent, REQUEST_INTERNAL)
|
||||||
intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION)
|
} else {
|
||||||
}
|
currentExtEpisode = episode
|
||||||
if (!preferences.alwaysUseExternalPlayer()) {
|
val extIntent = Intent(Intent.ACTION_VIEW)
|
||||||
startActivityForResult(intent, REQUEST_INTERNAL)
|
extIntent.setDataAndTypeAndNormalize(Uri.parse(url), "video/*")
|
||||||
} else {
|
extIntent.putExtra("title", episode.name)
|
||||||
currentExtEpisode = episode
|
extIntent.putExtra("position", episode.last_second_seen.toInt())
|
||||||
val uri = Uri.parse(url)
|
extIntent.putExtra("return_result", true)
|
||||||
val extIntent = Intent(Intent.ACTION_VIEW)
|
startActivityForResult(extIntent, REQUEST_EXTERNAL)
|
||||||
extIntent.setDataAndTypeAndNormalize(uri, "video/*")
|
|
||||||
extIntent.putExtra("title", episode.name)
|
|
||||||
extIntent.putExtra("position", episode.last_second_seen.toInt())
|
|
||||||
extIntent.putExtra("return_result", true)
|
|
||||||
startActivityForResult(extIntent, REQUEST_EXTERNAL)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,11 @@ import android.content.Context
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import com.jakewharton.rxrelay.PublishRelay
|
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.cache.AnimeCoverCache
|
||||||
import eu.kanade.tachiyomi.data.database.AnimeDatabaseHelper
|
import eu.kanade.tachiyomi.data.database.AnimeDatabaseHelper
|
||||||
import eu.kanade.tachiyomi.data.database.models.Anime
|
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.TrackManager
|
||||||
import eu.kanade.tachiyomi.data.track.TrackService
|
import eu.kanade.tachiyomi.data.track.TrackService
|
||||||
import eu.kanade.tachiyomi.data.track.UnattendedTrackService
|
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.episode.EpisodeItem
|
||||||
import eu.kanade.tachiyomi.ui.anime.track.TrackItem
|
import eu.kanade.tachiyomi.ui.anime.track.TrackItem
|
||||||
import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
|
import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
|
||||||
|
|
|
@ -6,9 +6,9 @@ import androidx.core.text.buildSpannedString
|
||||||
import androidx.core.text.color
|
import androidx.core.text.color
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
|
import eu.kanade.tachiyomi.animesource.LocalAnimeSource
|
||||||
import eu.kanade.tachiyomi.data.database.models.Anime
|
import eu.kanade.tachiyomi.data.database.models.Anime
|
||||||
import eu.kanade.tachiyomi.databinding.EpisodesItemBinding
|
import eu.kanade.tachiyomi.databinding.EpisodesItemBinding
|
||||||
import eu.kanade.tachiyomi.source.LocalSource
|
|
||||||
import eu.kanade.tachiyomi.ui.anime.episode.base.BaseEpisodeHolder
|
import eu.kanade.tachiyomi.ui.anime.episode.base.BaseEpisodeHolder
|
||||||
import java.util.Date
|
import java.util.Date
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
|
@ -93,7 +93,7 @@ class EpisodeHolder(
|
||||||
binding.episodeDescription.text = ""
|
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)
|
binding.animedownload.setState(item.status, item.progress)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,6 @@ import eu.davidea.flexibleadapter.items.AbstractHeaderItem
|
||||||
import eu.davidea.flexibleadapter.items.AbstractSectionableItem
|
import eu.davidea.flexibleadapter.items.AbstractSectionableItem
|
||||||
import eu.kanade.tachiyomi.data.database.models.Episode
|
import eu.kanade.tachiyomi.data.database.models.Episode
|
||||||
import eu.kanade.tachiyomi.data.download.model.AnimeDownload
|
import eu.kanade.tachiyomi.data.download.model.AnimeDownload
|
||||||
import eu.kanade.tachiyomi.source.model.Page
|
|
||||||
|
|
||||||
abstract class BaseEpisodeItem<T : BaseEpisodeHolder, H : AbstractHeaderItem<*>>(
|
abstract class BaseEpisodeItem<T : BaseEpisodeHolder, H : AbstractHeaderItem<*>>(
|
||||||
val episode: Episode,
|
val episode: Episode,
|
||||||
|
@ -23,8 +22,8 @@ abstract class BaseEpisodeItem<T : BaseEpisodeHolder, H : AbstractHeaderItem<*>>
|
||||||
|
|
||||||
val progress: Int
|
val progress: Int
|
||||||
get() {
|
get() {
|
||||||
val pages = download?.pages ?: return 0
|
val video = download?.video ?: return 0
|
||||||
return pages.map(Page::progress).average().toInt()
|
return video.progress
|
||||||
}
|
}
|
||||||
|
|
||||||
@Transient
|
@Transient
|
||||||
|
|
|
@ -7,13 +7,13 @@ import androidx.core.view.isVisible
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import coil.loadAny
|
import coil.loadAny
|
||||||
import eu.kanade.tachiyomi.R
|
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.database.models.Anime
|
||||||
import eu.kanade.tachiyomi.data.track.TrackManager
|
import eu.kanade.tachiyomi.data.track.TrackManager
|
||||||
import eu.kanade.tachiyomi.databinding.AnimeInfoHeaderBinding
|
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.ui.anime.AnimeController
|
||||||
import eu.kanade.tachiyomi.util.system.copyToClipboard
|
import eu.kanade.tachiyomi.util.system.copyToClipboard
|
||||||
import eu.kanade.tachiyomi.util.view.setChips
|
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.isVisible = true
|
||||||
binding.btnWebview.clicks()
|
binding.btnWebview.clicks()
|
||||||
.onEach { controller.openAnimeInWebView() }
|
.onEach { controller.openAnimeInWebView() }
|
||||||
|
|
|
@ -6,10 +6,10 @@ import android.view.View
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import com.google.android.material.bottomsheet.BottomSheetBehavior
|
import com.google.android.material.bottomsheet.BottomSheetBehavior
|
||||||
import eu.kanade.tachiyomi.R.string
|
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.database.models.Anime
|
||||||
import eu.kanade.tachiyomi.data.track.UnattendedTrackService
|
import eu.kanade.tachiyomi.data.track.UnattendedTrackService
|
||||||
import eu.kanade.tachiyomi.databinding.TrackControllerBinding
|
import eu.kanade.tachiyomi.databinding.TrackControllerBinding
|
||||||
import eu.kanade.tachiyomi.source.AnimeSourceManager
|
|
||||||
import eu.kanade.tachiyomi.ui.anime.AnimeController
|
import eu.kanade.tachiyomi.ui.anime.AnimeController
|
||||||
import eu.kanade.tachiyomi.ui.base.controller.openInBrowser
|
import eu.kanade.tachiyomi.ui.base.controller.openInBrowser
|
||||||
import eu.kanade.tachiyomi.util.lang.launchIO
|
import eu.kanade.tachiyomi.util.lang.launchIO
|
||||||
|
|
|
@ -19,13 +19,13 @@ import com.jakewharton.rxrelay.PublishRelay
|
||||||
import com.tfcporciuncula.flow.Preference
|
import com.tfcporciuncula.flow.Preference
|
||||||
import dev.chrisbanes.insetter.applyInsetter
|
import dev.chrisbanes.insetter.applyInsetter
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
|
import eu.kanade.tachiyomi.animesource.LocalAnimeSource
|
||||||
import eu.kanade.tachiyomi.data.animelib.AnimelibUpdateService
|
import eu.kanade.tachiyomi.data.animelib.AnimelibUpdateService
|
||||||
import eu.kanade.tachiyomi.data.database.models.Anime
|
import eu.kanade.tachiyomi.data.database.models.Anime
|
||||||
import eu.kanade.tachiyomi.data.database.models.Category
|
import eu.kanade.tachiyomi.data.database.models.Category
|
||||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||||
import eu.kanade.tachiyomi.data.preference.asImmediateFlow
|
import eu.kanade.tachiyomi.data.preference.asImmediateFlow
|
||||||
import eu.kanade.tachiyomi.databinding.AnimelibControllerBinding
|
import eu.kanade.tachiyomi.databinding.AnimelibControllerBinding
|
||||||
import eu.kanade.tachiyomi.source.LocalSource
|
|
||||||
import eu.kanade.tachiyomi.ui.anime.AnimeController
|
import eu.kanade.tachiyomi.ui.anime.AnimeController
|
||||||
import eu.kanade.tachiyomi.ui.base.controller.RootController
|
import eu.kanade.tachiyomi.ui.base.controller.RootController
|
||||||
import eu.kanade.tachiyomi.ui.base.controller.SearchableNucleusController
|
import eu.kanade.tachiyomi.ui.base.controller.SearchableNucleusController
|
||||||
|
@ -447,7 +447,7 @@ class AnimelibController(
|
||||||
} else {
|
} else {
|
||||||
mode.title = count.toString()
|
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
|
return false
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,11 +12,11 @@ import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
|
||||||
import eu.davidea.flexibleadapter.items.IFilterable
|
import eu.davidea.flexibleadapter.items.IFilterable
|
||||||
import eu.davidea.flexibleadapter.items.IFlexible
|
import eu.davidea.flexibleadapter.items.IFlexible
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
|
import eu.kanade.tachiyomi.animesource.AnimeSourceManager
|
||||||
import eu.kanade.tachiyomi.data.database.models.AnimelibAnime
|
import eu.kanade.tachiyomi.data.database.models.AnimelibAnime
|
||||||
import eu.kanade.tachiyomi.data.preference.PreferenceValues.DisplayMode
|
import eu.kanade.tachiyomi.data.preference.PreferenceValues.DisplayMode
|
||||||
import eu.kanade.tachiyomi.databinding.SourceComfortableGridItemBinding
|
import eu.kanade.tachiyomi.databinding.SourceComfortableGridItemBinding
|
||||||
import eu.kanade.tachiyomi.databinding.SourceCompactGridItemBinding
|
import eu.kanade.tachiyomi.databinding.SourceCompactGridItemBinding
|
||||||
import eu.kanade.tachiyomi.source.SourceManager
|
|
||||||
import eu.kanade.tachiyomi.widget.AutofitRecyclerView
|
import eu.kanade.tachiyomi.widget.AutofitRecyclerView
|
||||||
import uy.kohesive.injekt.Injekt
|
import uy.kohesive.injekt.Injekt
|
||||||
import uy.kohesive.injekt.api.get
|
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>) :
|
class AnimelibItem(val anime: AnimelibAnime, private val animelibDisplayMode: Preference<DisplayMode>) :
|
||||||
AbstractFlexibleItem<AnimelibHolder<*>>(), IFilterable<String> {
|
AbstractFlexibleItem<AnimelibHolder<*>>(), IFilterable<String> {
|
||||||
|
|
||||||
private val sourceManager: SourceManager = Injekt.get()
|
private val sourceManager: AnimeSourceManager = Injekt.get()
|
||||||
|
|
||||||
var downloadCount = -1
|
var downloadCount = -1
|
||||||
var unreadCount = -1
|
var unreadCount = -1
|
||||||
|
|
|
@ -2,6 +2,9 @@ package eu.kanade.tachiyomi.ui.animelib
|
||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import com.jakewharton.rxrelay.BehaviorRelay
|
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.cache.AnimeCoverCache
|
||||||
import eu.kanade.tachiyomi.data.database.AnimeDatabaseHelper
|
import eu.kanade.tachiyomi.data.database.AnimeDatabaseHelper
|
||||||
import eu.kanade.tachiyomi.data.database.models.Anime
|
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.download.AnimeDownloadManager
|
||||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||||
import eu.kanade.tachiyomi.data.track.TrackManager
|
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.ui.base.presenter.BasePresenter
|
||||||
import eu.kanade.tachiyomi.util.isLocal
|
import eu.kanade.tachiyomi.util.isLocal
|
||||||
import eu.kanade.tachiyomi.util.lang.combineLatest
|
import eu.kanade.tachiyomi.util.lang.combineLatest
|
||||||
|
|
|
@ -6,9 +6,9 @@ import eu.davidea.flexibleadapter.FlexibleAdapter
|
||||||
import eu.davidea.flexibleadapter.items.AbstractSectionableItem
|
import eu.davidea.flexibleadapter.items.AbstractSectionableItem
|
||||||
import eu.davidea.flexibleadapter.items.IFlexible
|
import eu.davidea.flexibleadapter.items.IFlexible
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
|
import eu.kanade.tachiyomi.animesource.AnimeCatalogueSource
|
||||||
import eu.kanade.tachiyomi.extension.model.AnimeExtension
|
import eu.kanade.tachiyomi.extension.model.AnimeExtension
|
||||||
import eu.kanade.tachiyomi.extension.model.InstallStep
|
import eu.kanade.tachiyomi.extension.model.InstallStep
|
||||||
import eu.kanade.tachiyomi.source.AnimeCatalogueSource
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Item that contains source information.
|
* Item that contains source information.
|
||||||
|
|
|
@ -23,16 +23,16 @@ import androidx.recyclerview.widget.ConcatAdapter
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import dev.chrisbanes.insetter.applyInsetter
|
import dev.chrisbanes.insetter.applyInsetter
|
||||||
import eu.kanade.tachiyomi.R
|
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.EmptyPreferenceDataStore
|
||||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||||
import eu.kanade.tachiyomi.data.preference.minusAssign
|
import eu.kanade.tachiyomi.data.preference.minusAssign
|
||||||
import eu.kanade.tachiyomi.data.preference.plusAssign
|
import eu.kanade.tachiyomi.data.preference.plusAssign
|
||||||
import eu.kanade.tachiyomi.databinding.AnimeExtensionDetailControllerBinding
|
import eu.kanade.tachiyomi.databinding.AnimeExtensionDetailControllerBinding
|
||||||
import eu.kanade.tachiyomi.extension.model.AnimeExtension
|
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.NucleusController
|
||||||
import eu.kanade.tachiyomi.ui.base.controller.ToolbarLiftOnScrollController
|
import eu.kanade.tachiyomi.ui.base.controller.ToolbarLiftOnScrollController
|
||||||
import eu.kanade.tachiyomi.ui.base.controller.openInBrowser
|
import eu.kanade.tachiyomi.ui.base.controller.openInBrowser
|
||||||
|
|
|
@ -21,12 +21,12 @@ import androidx.preference.PreferenceManager
|
||||||
import androidx.preference.PreferenceScreen
|
import androidx.preference.PreferenceScreen
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import eu.kanade.tachiyomi.R
|
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.EmptyPreferenceDataStore
|
||||||
import eu.kanade.tachiyomi.data.preference.SharedPreferencesDataStore
|
import eu.kanade.tachiyomi.data.preference.SharedPreferencesDataStore
|
||||||
import eu.kanade.tachiyomi.databinding.AnimeSourcePreferencesControllerBinding
|
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 eu.kanade.tachiyomi.ui.base.controller.NucleusController
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
package eu.kanade.tachiyomi.ui.browse.animeextension.details
|
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 eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
|
||||||
import uy.kohesive.injekt.Injekt
|
import uy.kohesive.injekt.Injekt
|
||||||
import uy.kohesive.injekt.api.get
|
import uy.kohesive.injekt.api.get
|
||||||
|
|
|
@ -17,13 +17,13 @@ import dev.chrisbanes.insetter.applyInsetter
|
||||||
import eu.davidea.flexibleadapter.FlexibleAdapter
|
import eu.davidea.flexibleadapter.FlexibleAdapter
|
||||||
import eu.davidea.flexibleadapter.items.IFlexible
|
import eu.davidea.flexibleadapter.items.IFlexible
|
||||||
import eu.kanade.tachiyomi.R
|
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.PreferencesHelper
|
||||||
import eu.kanade.tachiyomi.data.preference.minusAssign
|
import eu.kanade.tachiyomi.data.preference.minusAssign
|
||||||
import eu.kanade.tachiyomi.data.preference.plusAssign
|
import eu.kanade.tachiyomi.data.preference.plusAssign
|
||||||
import eu.kanade.tachiyomi.databinding.AnimeSourceMainControllerBinding
|
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.DialogController
|
||||||
import eu.kanade.tachiyomi.ui.base.controller.SearchableNucleusController
|
import eu.kanade.tachiyomi.ui.base.controller.SearchableNucleusController
|
||||||
import eu.kanade.tachiyomi.ui.base.controller.requestPermissionsSafe
|
import eu.kanade.tachiyomi.ui.base.controller.requestPermissionsSafe
|
||||||
|
|
|
@ -5,12 +5,12 @@ import androidx.preference.CheckBoxPreference
|
||||||
import androidx.preference.PreferenceGroup
|
import androidx.preference.PreferenceGroup
|
||||||
import androidx.preference.PreferenceScreen
|
import androidx.preference.PreferenceScreen
|
||||||
import eu.kanade.tachiyomi.R
|
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.minusAssign
|
||||||
import eu.kanade.tachiyomi.data.preference.plusAssign
|
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.ui.setting.SettingsController
|
||||||
import eu.kanade.tachiyomi.util.preference.onChange
|
import eu.kanade.tachiyomi.util.preference.onChange
|
||||||
import eu.kanade.tachiyomi.util.preference.switchPreferenceCategory
|
import eu.kanade.tachiyomi.util.preference.switchPreferenceCategory
|
||||||
|
@ -22,7 +22,7 @@ import java.util.TreeMap
|
||||||
|
|
||||||
class AnimeSourceFilterController : SettingsController() {
|
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 {
|
override fun setupPreferenceScreen(screen: PreferenceScreen) = screen.apply {
|
||||||
titleRes = R.string.label_sources
|
titleRes = R.string.label_sources
|
||||||
|
@ -78,7 +78,7 @@ class AnimeSourceFilterController : SettingsController() {
|
||||||
*
|
*
|
||||||
* @param group the language category.
|
* @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()
|
val disabledSourceIds = preferences.disabledAnimeSources().get()
|
||||||
|
|
||||||
sources
|
sources
|
||||||
|
|
|
@ -4,10 +4,9 @@ import android.view.View
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
import eu.davidea.viewholders.FlexibleViewHolder
|
import eu.davidea.viewholders.FlexibleViewHolder
|
||||||
import eu.kanade.tachiyomi.R
|
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.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.system.LocaleHelper
|
||||||
import eu.kanade.tachiyomi.util.view.setVectorCompat
|
import eu.kanade.tachiyomi.util.view.setVectorCompat
|
||||||
|
|
||||||
|
@ -38,7 +37,7 @@ class AnimeSourceHolder(private val view: View, val adapter: AnimeSourceAdapter)
|
||||||
val icon = source.icon()
|
val icon = source.icon()
|
||||||
when {
|
when {
|
||||||
icon != null -> binding.image.setImageDrawable(icon)
|
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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ import eu.davidea.flexibleadapter.FlexibleAdapter
|
||||||
import eu.davidea.flexibleadapter.items.AbstractSectionableItem
|
import eu.davidea.flexibleadapter.items.AbstractSectionableItem
|
||||||
import eu.davidea.flexibleadapter.items.IFlexible
|
import eu.davidea.flexibleadapter.items.IFlexible
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
import eu.kanade.tachiyomi.source.AnimeCatalogueSource
|
import eu.kanade.tachiyomi.animesource.AnimeCatalogueSource
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Item that contains source information.
|
* Item that contains source information.
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
package eu.kanade.tachiyomi.ui.browse.animesource
|
package eu.kanade.tachiyomi.ui.browse.animesource
|
||||||
|
|
||||||
import android.os.Bundle
|
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.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 eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
package eu.kanade.tachiyomi.ui.browse.animesource.browse
|
package eu.kanade.tachiyomi.ui.browse.animesource.browse
|
||||||
|
|
||||||
import com.jakewharton.rxrelay.PublishRelay
|
import com.jakewharton.rxrelay.PublishRelay
|
||||||
import eu.kanade.tachiyomi.source.model.AnimesPage
|
import eu.kanade.tachiyomi.animesource.model.AnimesPage
|
||||||
import eu.kanade.tachiyomi.source.model.SAnime
|
import eu.kanade.tachiyomi.animesource.model.SAnime
|
||||||
import rx.Observable
|
import rx.Observable
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
package eu.kanade.tachiyomi.ui.browse.animesource.browse
|
package eu.kanade.tachiyomi.ui.browse.animesource.browse
|
||||||
|
|
||||||
import eu.kanade.tachiyomi.source.AnimeCatalogueSource
|
import eu.kanade.tachiyomi.animesource.AnimeCatalogueSource
|
||||||
import eu.kanade.tachiyomi.source.model.AnimesPage
|
import eu.kanade.tachiyomi.animesource.model.AnimesPage
|
||||||
import eu.kanade.tachiyomi.source.model.FilterList
|
import eu.kanade.tachiyomi.animesource.model.FilterList
|
||||||
import rx.Observable
|
import rx.Observable
|
||||||
import rx.android.schedulers.AndroidSchedulers
|
import rx.android.schedulers.AndroidSchedulers
|
||||||
import rx.schedulers.Schedulers
|
import rx.schedulers.Schedulers
|
||||||
|
|
|
@ -22,16 +22,16 @@ import dev.chrisbanes.insetter.applyInsetter
|
||||||
import eu.davidea.flexibleadapter.FlexibleAdapter
|
import eu.davidea.flexibleadapter.FlexibleAdapter
|
||||||
import eu.davidea.flexibleadapter.items.IFlexible
|
import eu.davidea.flexibleadapter.items.IFlexible
|
||||||
import eu.kanade.tachiyomi.R
|
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.Anime
|
||||||
import eu.kanade.tachiyomi.data.database.models.Category
|
import eu.kanade.tachiyomi.data.database.models.Category
|
||||||
import eu.kanade.tachiyomi.data.preference.PreferenceValues.DisplayMode
|
import eu.kanade.tachiyomi.data.preference.PreferenceValues.DisplayMode
|
||||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||||
import eu.kanade.tachiyomi.data.preference.asImmediateFlow
|
import eu.kanade.tachiyomi.data.preference.asImmediateFlow
|
||||||
import eu.kanade.tachiyomi.databinding.AnimeSourceControllerBinding
|
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.anime.AnimeController
|
||||||
import eu.kanade.tachiyomi.ui.animelib.ChangeAnimeCategoriesDialog
|
import eu.kanade.tachiyomi.ui.animelib.ChangeAnimeCategoriesDialog
|
||||||
import eu.kanade.tachiyomi.ui.base.controller.FabController
|
import eu.kanade.tachiyomi.ui.base.controller.FabController
|
||||||
|
|
|
@ -2,6 +2,12 @@ package eu.kanade.tachiyomi.ui.browse.animesource.browse
|
||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import eu.davidea.flexibleadapter.items.IFlexible
|
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.cache.AnimeCoverCache
|
||||||
import eu.kanade.tachiyomi.data.database.AnimeDatabaseHelper
|
import eu.kanade.tachiyomi.data.database.AnimeDatabaseHelper
|
||||||
import eu.kanade.tachiyomi.data.database.models.Anime
|
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.TrackManager
|
||||||
import eu.kanade.tachiyomi.data.track.TrackService
|
import eu.kanade.tachiyomi.data.track.TrackService
|
||||||
import eu.kanade.tachiyomi.data.track.UnattendedTrackService
|
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.base.presenter.BasePresenter
|
||||||
import eu.kanade.tachiyomi.ui.browse.animesource.filter.CheckboxItem
|
import eu.kanade.tachiyomi.ui.browse.animesource.filter.CheckboxItem
|
||||||
import eu.kanade.tachiyomi.ui.browse.animesource.filter.CheckboxSectionItem
|
import eu.kanade.tachiyomi.ui.browse.animesource.filter.CheckboxSectionItem
|
||||||
|
|
|
@ -8,7 +8,7 @@ import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
|
||||||
import eu.davidea.flexibleadapter.items.IFlexible
|
import eu.davidea.flexibleadapter.items.IFlexible
|
||||||
import eu.davidea.viewholders.FlexibleViewHolder
|
import eu.davidea.viewholders.FlexibleViewHolder
|
||||||
import eu.kanade.tachiyomi.R
|
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>() {
|
open class CheckboxItem(val filter: Filter.CheckBox) : AbstractFlexibleItem<CheckboxItem.Holder>() {
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ import eu.davidea.flexibleadapter.items.IFlexible
|
||||||
import eu.davidea.flexibleadapter.items.ISectionable
|
import eu.davidea.flexibleadapter.items.ISectionable
|
||||||
import eu.davidea.viewholders.ExpandableViewHolder
|
import eu.davidea.viewholders.ExpandableViewHolder
|
||||||
import eu.kanade.tachiyomi.R
|
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
|
import eu.kanade.tachiyomi.util.view.setVectorCompat
|
||||||
|
|
||||||
class GroupItem(val filter: Filter.Group<*>) : AbstractExpandableHeaderItem<GroupItem.Holder, ISectionable<*, *>>() {
|
class GroupItem(val filter: Filter.Group<*>) : AbstractExpandableHeaderItem<GroupItem.Holder, ISectionable<*, *>>() {
|
||||||
|
|
|
@ -9,7 +9,7 @@ import eu.davidea.flexibleadapter.FlexibleAdapter
|
||||||
import eu.davidea.flexibleadapter.items.AbstractHeaderItem
|
import eu.davidea.flexibleadapter.items.AbstractHeaderItem
|
||||||
import eu.davidea.flexibleadapter.items.IFlexible
|
import eu.davidea.flexibleadapter.items.IFlexible
|
||||||
import eu.davidea.viewholders.FlexibleViewHolder
|
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>() {
|
class HeaderItem(val filter: Filter.Header) : AbstractHeaderItem<HeaderItem.Holder>() {
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package eu.kanade.tachiyomi.ui.browse.animesource.filter
|
package eu.kanade.tachiyomi.ui.browse.animesource.filter
|
||||||
|
|
||||||
import eu.davidea.flexibleadapter.items.ISectionable
|
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> {
|
class TriStateSectionItem(filter: Filter.TriState) : TriStateItem(filter), ISectionable<TriStateItem.Holder, GroupItem> {
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
|
||||||
import eu.davidea.flexibleadapter.items.IFlexible
|
import eu.davidea.flexibleadapter.items.IFlexible
|
||||||
import eu.davidea.viewholders.FlexibleViewHolder
|
import eu.davidea.viewholders.FlexibleViewHolder
|
||||||
import eu.kanade.tachiyomi.R
|
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
|
import eu.kanade.tachiyomi.widget.listener.IgnoreFirstSpinnerListener
|
||||||
|
|
||||||
open class SelectItem(val filter: Filter.Select<*>) : AbstractFlexibleItem<SelectItem.Holder>() {
|
open class SelectItem(val filter: Filter.Select<*>) : AbstractFlexibleItem<SelectItem.Holder>() {
|
||||||
|
|
|
@ -8,7 +8,7 @@ import eu.davidea.flexibleadapter.FlexibleAdapter
|
||||||
import eu.davidea.flexibleadapter.items.AbstractHeaderItem
|
import eu.davidea.flexibleadapter.items.AbstractHeaderItem
|
||||||
import eu.davidea.flexibleadapter.items.IFlexible
|
import eu.davidea.flexibleadapter.items.IFlexible
|
||||||
import eu.davidea.viewholders.FlexibleViewHolder
|
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>() {
|
class SeparatorItem(val filter: Filter.Separator) : AbstractHeaderItem<SeparatorItem.Holder>() {
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ import eu.davidea.flexibleadapter.items.AbstractExpandableHeaderItem
|
||||||
import eu.davidea.flexibleadapter.items.IFlexible
|
import eu.davidea.flexibleadapter.items.IFlexible
|
||||||
import eu.davidea.flexibleadapter.items.ISectionable
|
import eu.davidea.flexibleadapter.items.ISectionable
|
||||||
import eu.kanade.tachiyomi.R
|
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
|
import eu.kanade.tachiyomi.util.view.setVectorCompat
|
||||||
|
|
||||||
class SortGroup(val filter: Filter.Sort) : AbstractExpandableHeaderItem<SortGroup.Holder, ISectionable<*, *>>() {
|
class SortGroup(val filter: Filter.Sort) : AbstractExpandableHeaderItem<SortGroup.Holder, ISectionable<*, *>>() {
|
||||||
|
|
|
@ -9,7 +9,7 @@ import eu.davidea.flexibleadapter.items.AbstractSectionableItem
|
||||||
import eu.davidea.flexibleadapter.items.IFlexible
|
import eu.davidea.flexibleadapter.items.IFlexible
|
||||||
import eu.davidea.viewholders.FlexibleViewHolder
|
import eu.davidea.viewholders.FlexibleViewHolder
|
||||||
import eu.kanade.tachiyomi.R
|
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
|
import eu.kanade.tachiyomi.util.system.getResourceColor
|
||||||
|
|
||||||
class SortItem(val name: String, val group: SortGroup) : AbstractSectionableItem<SortItem.Holder, SortGroup>(group) {
|
class SortItem(val name: String, val group: SortGroup) : AbstractSectionableItem<SortItem.Holder, SortGroup>(group) {
|
||||||
|
|
|
@ -10,7 +10,7 @@ import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
|
||||||
import eu.davidea.flexibleadapter.items.IFlexible
|
import eu.davidea.flexibleadapter.items.IFlexible
|
||||||
import eu.davidea.viewholders.FlexibleViewHolder
|
import eu.davidea.viewholders.FlexibleViewHolder
|
||||||
import eu.kanade.tachiyomi.R
|
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>() {
|
open class TextItem(val filter: Filter.Text) : AbstractFlexibleItem<TextItem.Holder>() {
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@ import eu.davidea.flexibleadapter.FlexibleAdapter
|
||||||
import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
|
import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
|
||||||
import eu.davidea.flexibleadapter.items.IFlexible
|
import eu.davidea.flexibleadapter.items.IFlexible
|
||||||
import eu.davidea.viewholders.FlexibleViewHolder
|
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.dpToPx
|
||||||
import eu.kanade.tachiyomi.util.system.getResourceColor
|
import eu.kanade.tachiyomi.util.system.getResourceColor
|
||||||
import eu.kanade.tachiyomi.R as TR
|
import eu.kanade.tachiyomi.R as TR
|
||||||
|
|
|
@ -5,7 +5,7 @@ import android.os.Parcelable
|
||||||
import android.util.SparseArray
|
import android.util.SparseArray
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import eu.davidea.flexibleadapter.FlexibleAdapter
|
import eu.davidea.flexibleadapter.FlexibleAdapter
|
||||||
import eu.kanade.tachiyomi.source.AnimeCatalogueSource
|
import eu.kanade.tachiyomi.animesource.AnimeCatalogueSource
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adapter that holds the search cards.
|
* Adapter that holds the search cards.
|
||||||
|
|
|
@ -10,10 +10,10 @@ import androidx.appcompat.widget.SearchView
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
|
import eu.kanade.tachiyomi.animesource.AnimeCatalogueSource
|
||||||
import eu.kanade.tachiyomi.data.database.models.Anime
|
import eu.kanade.tachiyomi.data.database.models.Anime
|
||||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||||
import eu.kanade.tachiyomi.databinding.GlobalAnimeSearchControllerBinding
|
import eu.kanade.tachiyomi.databinding.GlobalAnimeSearchControllerBinding
|
||||||
import eu.kanade.tachiyomi.source.AnimeCatalogueSource
|
|
||||||
import eu.kanade.tachiyomi.ui.anime.AnimeController
|
import eu.kanade.tachiyomi.ui.anime.AnimeController
|
||||||
import eu.kanade.tachiyomi.ui.base.controller.SearchableNucleusController
|
import eu.kanade.tachiyomi.ui.base.controller.SearchableNucleusController
|
||||||
import eu.kanade.tachiyomi.ui.base.controller.withFadeTransaction
|
import eu.kanade.tachiyomi.ui.base.controller.withFadeTransaction
|
||||||
|
|
|
@ -4,9 +4,9 @@ import android.view.View
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import eu.davidea.viewholders.FlexibleViewHolder
|
import eu.davidea.viewholders.FlexibleViewHolder
|
||||||
|
import eu.kanade.tachiyomi.animesource.LocalAnimeSource
|
||||||
import eu.kanade.tachiyomi.data.database.models.Anime
|
import eu.kanade.tachiyomi.data.database.models.Anime
|
||||||
import eu.kanade.tachiyomi.databinding.GlobalSearchControllerCardBinding
|
import eu.kanade.tachiyomi.databinding.GlobalSearchControllerCardBinding
|
||||||
import eu.kanade.tachiyomi.source.LocalAnimeSource
|
|
||||||
import eu.kanade.tachiyomi.util.system.LocaleHelper
|
import eu.kanade.tachiyomi.util.system.LocaleHelper
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -6,7 +6,7 @@ import eu.davidea.flexibleadapter.FlexibleAdapter
|
||||||
import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
|
import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
|
||||||
import eu.davidea.flexibleadapter.items.IFlexible
|
import eu.davidea.flexibleadapter.items.IFlexible
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
import eu.kanade.tachiyomi.source.AnimeCatalogueSource
|
import eu.kanade.tachiyomi.animesource.AnimeCatalogueSource
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Item that contains search result information.
|
* Item that contains search result information.
|
||||||
|
|
|
@ -1,18 +1,18 @@
|
||||||
package eu.kanade.tachiyomi.ui.browse.animesource.globalsearch
|
package eu.kanade.tachiyomi.ui.browse.animesource.globalsearch
|
||||||
|
|
||||||
import android.os.Bundle
|
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.AnimeDatabaseHelper
|
||||||
import eu.kanade.tachiyomi.data.database.models.Anime
|
import eu.kanade.tachiyomi.data.database.models.Anime
|
||||||
import eu.kanade.tachiyomi.data.database.models.toAnimeInfo
|
import eu.kanade.tachiyomi.data.database.models.toAnimeInfo
|
||||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||||
import eu.kanade.tachiyomi.extension.AnimeExtensionManager
|
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.base.presenter.BasePresenter
|
||||||
import eu.kanade.tachiyomi.ui.browse.animesource.browse.BrowseAnimeSourcePresenter
|
import eu.kanade.tachiyomi.ui.browse.animesource.browse.BrowseAnimeSourcePresenter
|
||||||
import eu.kanade.tachiyomi.util.lang.runAsObservable
|
import eu.kanade.tachiyomi.util.lang.runAsObservable
|
||||||
|
|
|
@ -4,7 +4,7 @@ import android.os.Bundle
|
||||||
import android.view.Menu
|
import android.view.Menu
|
||||||
import androidx.core.os.bundleOf
|
import androidx.core.os.bundleOf
|
||||||
import eu.kanade.tachiyomi.R
|
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.BrowseAnimeSourceController
|
||||||
import eu.kanade.tachiyomi.ui.browse.animesource.browse.BrowseAnimeSourcePresenter
|
import eu.kanade.tachiyomi.ui.browse.animesource.browse.BrowseAnimeSourcePresenter
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package eu.kanade.tachiyomi.ui.browse.animesource.latest
|
package eu.kanade.tachiyomi.ui.browse.animesource.latest
|
||||||
|
|
||||||
import eu.kanade.tachiyomi.source.AnimeCatalogueSource
|
import eu.kanade.tachiyomi.animesource.AnimeCatalogueSource
|
||||||
import eu.kanade.tachiyomi.source.model.AnimesPage
|
import eu.kanade.tachiyomi.animesource.model.AnimesPage
|
||||||
import eu.kanade.tachiyomi.ui.browse.animesource.browse.AnimePager
|
import eu.kanade.tachiyomi.ui.browse.animesource.browse.AnimePager
|
||||||
import rx.Observable
|
import rx.Observable
|
||||||
import rx.android.schedulers.AndroidSchedulers
|
import rx.android.schedulers.AndroidSchedulers
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
package eu.kanade.tachiyomi.ui.browse.animesource.latest
|
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.AnimePager
|
||||||
import eu.kanade.tachiyomi.ui.browse.animesource.browse.BrowseAnimeSourcePresenter
|
import eu.kanade.tachiyomi.ui.browse.animesource.browse.BrowseAnimeSourcePresenter
|
||||||
|
|
||||||
|
|
|
@ -7,9 +7,9 @@ import com.afollestad.materialdialogs.MaterialDialog
|
||||||
import com.afollestad.materialdialogs.list.listItemsMultiChoice
|
import com.afollestad.materialdialogs.list.listItemsMultiChoice
|
||||||
import com.bluelinelabs.conductor.Controller
|
import com.bluelinelabs.conductor.Controller
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
|
import eu.kanade.tachiyomi.animesource.AnimeCatalogueSource
|
||||||
import eu.kanade.tachiyomi.data.database.models.Anime
|
import eu.kanade.tachiyomi.data.database.models.Anime
|
||||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
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.DialogController
|
||||||
import eu.kanade.tachiyomi.ui.base.controller.withFadeTransaction
|
import eu.kanade.tachiyomi.ui.base.controller.withFadeTransaction
|
||||||
import eu.kanade.tachiyomi.ui.browse.animesource.globalsearch.GlobalAnimeSearchController
|
import eu.kanade.tachiyomi.ui.browse.animesource.globalsearch.GlobalAnimeSearchController
|
||||||
|
|
|
@ -2,14 +2,14 @@ package eu.kanade.tachiyomi.ui.browse.migration.search
|
||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import com.jakewharton.rxrelay.BehaviorRelay
|
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.Anime
|
||||||
import eu.kanade.tachiyomi.data.database.models.AnimeCategory
|
import eu.kanade.tachiyomi.data.database.models.AnimeCategory
|
||||||
import eu.kanade.tachiyomi.data.database.models.toAnimeInfo
|
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.GlobalAnimeSearchCardItem
|
||||||
import eu.kanade.tachiyomi.ui.browse.animesource.globalsearch.GlobalAnimeSearchItem
|
import eu.kanade.tachiyomi.ui.browse.animesource.globalsearch.GlobalAnimeSearchItem
|
||||||
import eu.kanade.tachiyomi.ui.browse.animesource.globalsearch.GlobalAnimeSearchPresenter
|
import eu.kanade.tachiyomi.ui.browse.animesource.globalsearch.GlobalAnimeSearchPresenter
|
||||||
|
|
|
@ -2,8 +2,8 @@ package eu.kanade.tachiyomi.ui.browse.migration.search
|
||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.View
|
import android.view.View
|
||||||
|
import eu.kanade.tachiyomi.animesource.AnimeCatalogueSource
|
||||||
import eu.kanade.tachiyomi.data.database.models.Anime
|
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.AnimeSourceItem
|
||||||
import eu.kanade.tachiyomi.ui.browse.animesource.browse.BrowseAnimeSourceController
|
import eu.kanade.tachiyomi.ui.browse.animesource.browse.BrowseAnimeSourceController
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ import eu.davidea.flexibleadapter.FlexibleAdapter
|
||||||
import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
|
import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
|
||||||
import eu.davidea.flexibleadapter.items.IFlexible
|
import eu.davidea.flexibleadapter.items.IFlexible
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
import eu.kanade.tachiyomi.source.AnimeSource
|
import eu.kanade.tachiyomi.animesource.AnimeSource
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Item that contains source information.
|
* Item that contains source information.
|
||||||
|
|
|
@ -1,11 +1,14 @@
|
||||||
package eu.kanade.tachiyomi.ui.browse.migration.sources
|
package eu.kanade.tachiyomi.ui.browse.migration.sources
|
||||||
|
|
||||||
import android.os.Bundle
|
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.AnimeDatabaseHelper
|
||||||
import eu.kanade.tachiyomi.data.database.DatabaseHelper
|
import eu.kanade.tachiyomi.data.database.DatabaseHelper
|
||||||
import eu.kanade.tachiyomi.data.database.models.Anime
|
import eu.kanade.tachiyomi.data.database.models.Anime
|
||||||
import eu.kanade.tachiyomi.data.database.models.Manga
|
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 eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
|
||||||
import rx.android.schedulers.AndroidSchedulers
|
import rx.android.schedulers.AndroidSchedulers
|
||||||
import uy.kohesive.injekt.Injekt
|
import uy.kohesive.injekt.Injekt
|
||||||
|
@ -49,7 +52,7 @@ class MigrationSourcesPresenter(
|
||||||
private fun findSourcesWithAnime(library: List<Anime>): List<AnimeSourceItem> {
|
private fun findSourcesWithAnime(library: List<Anime>): List<AnimeSourceItem> {
|
||||||
return library
|
return library
|
||||||
.groupBy { it.source }
|
.groupBy { it.source }
|
||||||
.filterKeys { it != LocalSource.ID }
|
.filterKeys { it != LocalAnimeSource.ID }
|
||||||
.map {
|
.map {
|
||||||
val source = animesourceManager.getOrStub(it.key)
|
val source = animesourceManager.getOrStub(it.key)
|
||||||
AnimeSourceItem(source, it.value.size)
|
AnimeSourceItem(source, it.value.size)
|
||||||
|
|
|
@ -3,6 +3,7 @@ package eu.kanade.tachiyomi.ui.browse.migration.sources
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
import eu.davidea.viewholders.FlexibleViewHolder
|
import eu.davidea.viewholders.FlexibleViewHolder
|
||||||
|
import eu.kanade.tachiyomi.animesource.icon
|
||||||
import eu.kanade.tachiyomi.databinding.SourceMainControllerCardItemBinding
|
import eu.kanade.tachiyomi.databinding.SourceMainControllerCardItemBinding
|
||||||
import eu.kanade.tachiyomi.source.icon
|
import eu.kanade.tachiyomi.source.icon
|
||||||
import eu.kanade.tachiyomi.util.system.LocaleHelper
|
import eu.kanade.tachiyomi.util.system.LocaleHelper
|
||||||
|
|
|
@ -2,7 +2,7 @@ package eu.kanade.tachiyomi.ui.recent.animehistory
|
||||||
|
|
||||||
import eu.davidea.flexibleadapter.FlexibleAdapter
|
import eu.davidea.flexibleadapter.FlexibleAdapter
|
||||||
import eu.davidea.flexibleadapter.items.IFlexible
|
import eu.davidea.flexibleadapter.items.IFlexible
|
||||||
import eu.kanade.tachiyomi.source.AnimeSourceManager
|
import eu.kanade.tachiyomi.animesource.AnimeSourceManager
|
||||||
import uy.kohesive.injekt.injectLazy
|
import uy.kohesive.injekt.injectLazy
|
||||||
import java.text.DecimalFormat
|
import java.text.DecimalFormat
|
||||||
import java.text.DecimalFormatSymbols
|
import java.text.DecimalFormatSymbols
|
||||||
|
|
|
@ -13,13 +13,12 @@ import com.afollestad.materialdialogs.MaterialDialog
|
||||||
import dev.chrisbanes.insetter.applyInsetter
|
import dev.chrisbanes.insetter.applyInsetter
|
||||||
import eu.davidea.flexibleadapter.FlexibleAdapter
|
import eu.davidea.flexibleadapter.FlexibleAdapter
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
|
import eu.kanade.tachiyomi.animesource.AnimeSourceManager
|
||||||
import eu.kanade.tachiyomi.data.backup.BackupRestoreService
|
import eu.kanade.tachiyomi.data.backup.BackupRestoreService
|
||||||
import eu.kanade.tachiyomi.data.database.AnimeDatabaseHelper
|
import eu.kanade.tachiyomi.data.database.AnimeDatabaseHelper
|
||||||
import eu.kanade.tachiyomi.data.database.models.Anime
|
import eu.kanade.tachiyomi.data.database.models.Anime
|
||||||
import eu.kanade.tachiyomi.data.database.models.AnimeHistory
|
import eu.kanade.tachiyomi.data.database.models.AnimeHistory
|
||||||
import eu.kanade.tachiyomi.databinding.AnimeHistoryControllerBinding
|
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.AnimeController
|
||||||
import eu.kanade.tachiyomi.ui.anime.episode.EpisodeItem
|
import eu.kanade.tachiyomi.ui.anime.episode.EpisodeItem
|
||||||
import eu.kanade.tachiyomi.ui.base.controller.DialogController
|
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.RootController
|
||||||
import eu.kanade.tachiyomi.ui.base.controller.withFadeTransaction
|
import eu.kanade.tachiyomi.ui.base.controller.withFadeTransaction
|
||||||
import eu.kanade.tachiyomi.ui.browse.source.browse.ProgressItem
|
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.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 eu.kanade.tachiyomi.util.system.toast
|
||||||
import kotlinx.coroutines.flow.filter
|
import kotlinx.coroutines.flow.filter
|
||||||
import kotlinx.coroutines.flow.launchIn
|
import kotlinx.coroutines.flow.launchIn
|
||||||
import kotlinx.coroutines.flow.onEach
|
import kotlinx.coroutines.flow.onEach
|
||||||
import kotlinx.coroutines.runBlocking
|
|
||||||
import reactivecircus.flowbinding.appcompat.queryTextChanges
|
import reactivecircus.flowbinding.appcompat.queryTextChanges
|
||||||
import uy.kohesive.injekt.Injekt
|
import uy.kohesive.injekt.Injekt
|
||||||
import uy.kohesive.injekt.api.get
|
import uy.kohesive.injekt.api.get
|
||||||
import uy.kohesive.injekt.injectLazy
|
import uy.kohesive.injekt.injectLazy
|
||||||
import java.util.Collections
|
import java.util.Collections
|
||||||
import kotlin.coroutines.resume
|
|
||||||
import kotlin.coroutines.suspendCoroutine
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fragment that shows recently read anime.
|
* Fragment that shows recently read anime.
|
||||||
|
@ -166,19 +161,7 @@ class AnimeHistoryController :
|
||||||
val nextEpisode = presenter.getNextEpisode(chapter, anime)
|
val nextEpisode = presenter.getNextEpisode(chapter, anime)
|
||||||
if (nextEpisode != null) {
|
if (nextEpisode != null) {
|
||||||
val source = Injekt.get<AnimeSourceManager>().getOrStub(anime.source)
|
val source = Injekt.get<AnimeSourceManager>().getOrStub(anime.source)
|
||||||
val link = runBlocking {
|
val link = EpisodeLoader.getUri(nextEpisode, anime, source)
|
||||||
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 episodeList: List<EpisodeItem> = Collections.emptyList()
|
val episodeList: List<EpisodeItem> = Collections.emptyList()
|
||||||
val newIntent = WatcherActivity.newIntent(activity, anime, nextEpisode, episodeList, link)
|
val newIntent = WatcherActivity.newIntent(activity, anime, nextEpisode, episodeList, link)
|
||||||
startActivity(newIntent)
|
startActivity(newIntent)
|
||||||
|
|
|
@ -13,13 +13,12 @@ import eu.davidea.flexibleadapter.FlexibleAdapter
|
||||||
import eu.davidea.flexibleadapter.SelectableAdapter
|
import eu.davidea.flexibleadapter.SelectableAdapter
|
||||||
import eu.davidea.flexibleadapter.items.IFlexible
|
import eu.davidea.flexibleadapter.items.IFlexible
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
|
import eu.kanade.tachiyomi.animesource.AnimeSourceManager
|
||||||
import eu.kanade.tachiyomi.data.animelib.AnimelibUpdateService
|
import eu.kanade.tachiyomi.data.animelib.AnimelibUpdateService
|
||||||
import eu.kanade.tachiyomi.data.download.AnimeDownloadService
|
import eu.kanade.tachiyomi.data.download.AnimeDownloadService
|
||||||
import eu.kanade.tachiyomi.data.download.model.AnimeDownload
|
import eu.kanade.tachiyomi.data.download.model.AnimeDownload
|
||||||
import eu.kanade.tachiyomi.data.notification.Notifications
|
import eu.kanade.tachiyomi.data.notification.Notifications
|
||||||
import eu.kanade.tachiyomi.databinding.AnimeUpdatesControllerBinding
|
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.AnimeController
|
||||||
import eu.kanade.tachiyomi.ui.anime.episode.EpisodeItem
|
import eu.kanade.tachiyomi.ui.anime.episode.EpisodeItem
|
||||||
import eu.kanade.tachiyomi.ui.anime.episode.base.BaseEpisodesAdapter
|
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.RootController
|
||||||
import eu.kanade.tachiyomi.ui.base.controller.withFadeTransaction
|
import eu.kanade.tachiyomi.ui.base.controller.withFadeTransaction
|
||||||
import eu.kanade.tachiyomi.ui.main.MainActivity
|
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.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.notificationManager
|
||||||
import eu.kanade.tachiyomi.util.system.toast
|
import eu.kanade.tachiyomi.util.system.toast
|
||||||
import kotlinx.coroutines.flow.launchIn
|
import kotlinx.coroutines.flow.launchIn
|
||||||
import kotlinx.coroutines.flow.onEach
|
import kotlinx.coroutines.flow.onEach
|
||||||
import kotlinx.coroutines.runBlocking
|
|
||||||
import reactivecircus.flowbinding.recyclerview.scrollStateChanges
|
import reactivecircus.flowbinding.recyclerview.scrollStateChanges
|
||||||
import reactivecircus.flowbinding.swiperefreshlayout.refreshes
|
import reactivecircus.flowbinding.swiperefreshlayout.refreshes
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import uy.kohesive.injekt.Injekt
|
import uy.kohesive.injekt.Injekt
|
||||||
import uy.kohesive.injekt.api.get
|
import uy.kohesive.injekt.api.get
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import kotlin.coroutines.resume
|
|
||||||
import kotlin.coroutines.suspendCoroutine
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fragment that shows recent episodes.
|
* Fragment that shows recent episodes.
|
||||||
|
@ -216,19 +211,7 @@ class AnimeUpdatesController :
|
||||||
private fun openEpisode(item: AnimeUpdatesItem) {
|
private fun openEpisode(item: AnimeUpdatesItem) {
|
||||||
val activity = activity ?: return
|
val activity = activity ?: return
|
||||||
val source = Injekt.get<AnimeSourceManager>().getOrStub(item.anime.source)
|
val source = Injekt.get<AnimeSourceManager>().getOrStub(item.anime.source)
|
||||||
val link = runBlocking {
|
val link = EpisodeLoader.getUri(item.episode, item.anime, source)
|
||||||
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 episodeList: List<EpisodeItem> = Collections.emptyList()
|
val episodeList: List<EpisodeItem> = Collections.emptyList()
|
||||||
val intent = WatcherActivity.newIntent(activity, item.anime, item.episode, episodeList, link)
|
val intent = WatcherActivity.newIntent(activity, item.anime, item.episode, episodeList, link)
|
||||||
startActivity(intent)
|
startActivity(intent)
|
||||||
|
|
|
@ -6,8 +6,8 @@ import coil.clear
|
||||||
import coil.loadAny
|
import coil.loadAny
|
||||||
import coil.transform.RoundedCornersTransformation
|
import coil.transform.RoundedCornersTransformation
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
|
import eu.kanade.tachiyomi.animesource.LocalAnimeSource
|
||||||
import eu.kanade.tachiyomi.databinding.AnimeUpdatesItemBinding
|
import eu.kanade.tachiyomi.databinding.AnimeUpdatesItemBinding
|
||||||
import eu.kanade.tachiyomi.source.LocalSource
|
|
||||||
import eu.kanade.tachiyomi.ui.anime.episode.base.BaseEpisodeHolder
|
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
|
// 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)
|
binding.download.setState(item.status, item.progress)
|
||||||
|
|
||||||
// Set cover
|
// Set cover
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
package eu.kanade.tachiyomi.ui.recent.animeupdates
|
package eu.kanade.tachiyomi.ui.recent.animeupdates
|
||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
import eu.kanade.tachiyomi.animesource.AnimeSourceManager
|
||||||
import eu.kanade.tachiyomi.data.database.AnimeDatabaseHelper
|
import eu.kanade.tachiyomi.data.database.AnimeDatabaseHelper
|
||||||
import eu.kanade.tachiyomi.data.database.models.AnimeEpisode
|
import eu.kanade.tachiyomi.data.database.models.AnimeEpisode
|
||||||
import eu.kanade.tachiyomi.data.download.AnimeDownloadManager
|
import eu.kanade.tachiyomi.data.download.AnimeDownloadManager
|
||||||
import eu.kanade.tachiyomi.data.download.model.AnimeDownload
|
import eu.kanade.tachiyomi.data.download.model.AnimeDownload
|
||||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
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.base.presenter.BasePresenter
|
||||||
import eu.kanade.tachiyomi.ui.recent.DateSectionItem
|
import eu.kanade.tachiyomi.ui.recent.DateSectionItem
|
||||||
import eu.kanade.tachiyomi.util.lang.toDateKey
|
import eu.kanade.tachiyomi.util.lang.toDateKey
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -21,6 +21,8 @@ import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory
|
||||||
import com.google.android.exoplayer2.util.MimeTypes
|
import com.google.android.exoplayer2.util.MimeTypes
|
||||||
import com.google.android.exoplayer2.util.Util
|
import com.google.android.exoplayer2.util.Util
|
||||||
import eu.kanade.tachiyomi.R
|
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.AnimeDatabaseHelper
|
||||||
import eu.kanade.tachiyomi.data.database.models.Anime
|
import eu.kanade.tachiyomi.data.database.models.Anime
|
||||||
import eu.kanade.tachiyomi.data.database.models.AnimeHistory
|
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.download.model.AnimeDownload
|
||||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||||
import eu.kanade.tachiyomi.data.track.TrackManager
|
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.ui.anime.episode.EpisodeItem
|
||||||
import eu.kanade.tachiyomi.util.lang.launchIO
|
import eu.kanade.tachiyomi.util.lang.launchIO
|
||||||
import eu.kanade.tachiyomi.util.view.hideBar
|
import eu.kanade.tachiyomi.util.view.hideBar
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
package eu.kanade.tachiyomi.util
|
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.cache.AnimeCoverCache
|
||||||
import eu.kanade.tachiyomi.data.database.AnimeDatabaseHelper
|
import eu.kanade.tachiyomi.data.database.AnimeDatabaseHelper
|
||||||
import eu.kanade.tachiyomi.data.database.models.Anime
|
import eu.kanade.tachiyomi.data.database.models.Anime
|
||||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||||
import eu.kanade.tachiyomi.source.LocalAnimeSource
|
|
||||||
import eu.kanade.tachiyomi.source.model.SAnime
|
|
||||||
import java.util.Date
|
import java.util.Date
|
||||||
|
|
||||||
fun Anime.isLocal() = source == LocalAnimeSource.ID
|
fun Anime.isLocal() = source == LocalAnimeSource.ID
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package eu.kanade.tachiyomi.util.episode
|
package eu.kanade.tachiyomi.util.episode
|
||||||
|
|
||||||
import eu.kanade.tachiyomi.source.model.SAnime
|
import eu.kanade.tachiyomi.animesource.model.SAnime
|
||||||
import eu.kanade.tachiyomi.source.model.SEpisode
|
import eu.kanade.tachiyomi.animesource.model.SEpisode
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* -R> = regex conversion.
|
* -R> = regex conversion.
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
package eu.kanade.tachiyomi.util.episode
|
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.AnimeDatabaseHelper
|
||||||
import eu.kanade.tachiyomi.data.database.models.Anime
|
import eu.kanade.tachiyomi.data.database.models.Anime
|
||||||
import eu.kanade.tachiyomi.data.database.models.Episode
|
import eu.kanade.tachiyomi.data.database.models.Episode
|
||||||
import eu.kanade.tachiyomi.data.download.AnimeDownloadManager
|
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.Injekt
|
||||||
import uy.kohesive.injekt.api.get
|
import uy.kohesive.injekt.api.get
|
||||||
import java.util.Date
|
import java.util.Date
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package eu.kanade.tachiyomi.util.storage
|
package eu.kanade.tachiyomi.util.storage
|
||||||
|
|
||||||
import eu.kanade.tachiyomi.source.model.SAnime
|
import eu.kanade.tachiyomi.animesource.model.SAnime
|
||||||
import eu.kanade.tachiyomi.source.model.SEpisode
|
import eu.kanade.tachiyomi.animesource.model.SEpisode
|
||||||
import org.jsoup.Jsoup
|
import org.jsoup.Jsoup
|
||||||
import org.jsoup.nodes.Document
|
import org.jsoup.nodes.Document
|
||||||
import java.io.Closeable
|
import java.io.Closeable
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package tachiyomi.source
|
package tachiyomi.animesource
|
||||||
|
|
||||||
import tachiyomi.source.model.AnimeInfo
|
import tachiyomi.animesource.model.AnimeInfo
|
||||||
import tachiyomi.source.model.EpisodeInfo
|
import tachiyomi.animesource.model.EpisodeInfo
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A basic interface for creating a source. It could be an online source, a local source, etc...
|
* A basic interface for creating a source. It could be an online source, a local source, etc...
|
|
@ -1,4 +1,4 @@
|
||||||
package tachiyomi.source.model
|
package tachiyomi.animesource.model
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Model for a anime given by a source
|
* Model for a anime given by a source
|
|
@ -1,4 +1,4 @@
|
||||||
package tachiyomi.source.model
|
package tachiyomi.animesource.model
|
||||||
|
|
||||||
data class EpisodeInfo(
|
data class EpisodeInfo(
|
||||||
var key: String,
|
var key: String,
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue