pull/2637/head
arkon 5 years ago
parent 58ab06b4f8
commit 043e3784e8

@ -90,5 +90,4 @@ open class App : Application(), LifecycleObserver {
protected open fun setupNotificationChannels() {
Notifications.createChannels(this)
}
}

@ -52,7 +52,5 @@ class AppModule(val app: Application) : InjektModule {
GlobalScope.launch { get<DatabaseHelper>() }
GlobalScope.launch { get<DownloadManager>() }
}
}

@ -59,5 +59,4 @@ object Migrations {
}
return false
}
}

@ -2,7 +2,6 @@ package eu.kanade.tachiyomi.data.backup
import eu.kanade.tachiyomi.BuildConfig.APPLICATION_ID as ID
object BackupConst {
const val INTENT_FILTER = "SettingsBackupFragment"

@ -5,8 +5,8 @@ import android.content.Context
import android.content.Intent
import android.net.Uri
import com.google.gson.JsonArray
import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.BuildConfig.APPLICATION_ID as ID
import eu.kanade.tachiyomi.data.database.models.Manga
/**
* [IntentService] used to backup [Manga] information to [JsonArray]
@ -45,7 +45,6 @@ class BackupCreateService : IntentService(NAME) {
}
context.startService(intent)
}
}
private val backupManager by lazy { BackupManager(this) }
@ -59,5 +58,4 @@ class BackupCreateService : IntentService(NAME) {
// Create backup
backupManager.createBackup(uri, flags, false)
}
}

@ -32,10 +32,10 @@ import eu.kanade.tachiyomi.source.Source
import eu.kanade.tachiyomi.source.SourceManager
import eu.kanade.tachiyomi.util.chapter.syncChaptersWithSource
import eu.kanade.tachiyomi.util.system.sendLocalBroadcast
import kotlin.math.max
import rx.Observable
import timber.log.Timber
import uy.kohesive.injekt.injectLazy
import kotlin.math.max
class BackupManager(val context: Context, version: Int = CURRENT_VERSION) {

@ -26,17 +26,17 @@ import eu.kanade.tachiyomi.source.Source
import eu.kanade.tachiyomi.util.lang.chop
import eu.kanade.tachiyomi.util.system.isServiceRunning
import eu.kanade.tachiyomi.util.system.sendLocalBroadcast
import rx.Observable
import rx.Subscription
import rx.schedulers.Schedulers
import timber.log.Timber
import uy.kohesive.injekt.injectLazy
import java.io.File
import java.text.SimpleDateFormat
import java.util.Date
import java.util.Locale
import java.util.concurrent.ExecutorService
import java.util.concurrent.Executors
import rx.Observable
import rx.Subscription
import rx.schedulers.Schedulers
import timber.log.Timber
import uy.kohesive.injekt.injectLazy
/**
* Restores backup from json file
@ -119,7 +119,6 @@ class BackupRestoreService : Service() {
*/
internal val trackManager: TrackManager by injectLazy()
private lateinit var executor: ExecutorService
/**
@ -250,7 +249,6 @@ class BackupRestoreService : Service() {
putExtra(BackupConst.ACTION, BackupConst.ACTION_RESTORE_COMPLETED_DIALOG)
}
sendLocalBroadcast(completeIntent)
}
.doOnError { error ->
Timber.e(error)
@ -296,9 +294,13 @@ class BackupRestoreService : Service() {
* @param tracks tracking data from json
* @return [Observable] containing manga restore information
*/
private fun getMangaRestoreObservable(manga: Manga, chapters: List<Chapter>,
categories: List<String>, history: List<DHistory>,
tracks: List<Track>): Observable<Manga>? {
private fun getMangaRestoreObservable(
manga: Manga,
chapters: List<Chapter>,
categories: List<String>,
history: List<DHistory>,
tracks: List<Track>
): Observable<Manga>? {
// Get source
val source = backupManager.sourceManager.getOrStub(manga.source)
val dbManga = backupManager.getMangaFromDatabase(manga)
@ -321,9 +323,14 @@ class BackupRestoreService : Service() {
* @param chapters chapters of manga that needs updating
* @param categories categories that need updating
*/
private fun mangaFetchObservable(source: Source, manga: Manga, chapters: List<Chapter>,
categories: List<String>, history: List<DHistory>,
tracks: List<Track>): Observable<Manga> {
private fun mangaFetchObservable(
source: Source,
manga: Manga,
chapters: List<Chapter>,
categories: List<String>,
history: List<DHistory>,
tracks: List<Track>
): Observable<Manga> {
return backupManager.restoreMangaFetchObservable(source, manga)
.onErrorReturn {
errors.add(Date() to "${manga.title} - ${it.message}")
@ -349,9 +356,14 @@ class BackupRestoreService : Service() {
}
}
private fun mangaNoFetchObservable(source: Source, backupManga: Manga, chapters: List<Chapter>,
categories: List<String>, history: List<DHistory>,
tracks: List<Track>): Observable<Manga> {
private fun mangaNoFetchObservable(
source: Source,
backupManga: Manga,
chapters: List<Chapter>,
categories: List<String>,
history: List<DHistory>,
tracks: List<Track>
): Observable<Manga> {
return Observable.just(backupManga)
.flatMap { manga ->
@ -434,8 +446,13 @@ class BackupRestoreService : Service() {
* @param amount total restoreAmount of manga
* @param title title of restored manga
*/
private fun showRestoreProgress(progress: Int, amount: Int, title: String, errors: Int,
content: String = getString(R.string.dialog_restoring_backup, title.chop(15))) {
private fun showRestoreProgress(
progress: Int,
amount: Int,
title: String,
errors: Int,
content: String = getString(R.string.dialog_restoring_backup, title.chop(15))
) {
val intent = Intent(BackupConst.INTENT_FILTER).apply {
putExtra(BackupConst.EXTRA_PROGRESS, progress)
putExtra(BackupConst.EXTRA_AMOUNT, amount)
@ -445,5 +462,4 @@ class BackupRestoreService : Service() {
}
sendLocalBroadcast(intent)
}
}

@ -9,13 +9,13 @@ import eu.kanade.tachiyomi.data.database.models.Chapter
import eu.kanade.tachiyomi.source.model.Page
import eu.kanade.tachiyomi.util.storage.DiskUtil
import eu.kanade.tachiyomi.util.storage.saveTo
import java.io.File
import java.io.IOException
import okhttp3.Response
import okio.buffer
import okio.sink
import rx.Observable
import uy.kohesive.injekt.injectLazy
import java.io.File
import java.io.IOException
/**
* Class used to create chapter cache
@ -135,7 +135,6 @@ class ChapterCache(private val context: Context) {
diskCache.flush()
editor.commit()
editor.abortUnlessCommitted()
} catch (e: Exception) {
// Ignore.
} finally {
@ -201,4 +200,3 @@ class ChapterCache(private val context: Context) {
return "${chapter.manga_id}${chapter.url}"
}
}

@ -63,5 +63,4 @@ class CoverCache(private val context: Context) {
val file = getCoverFile(thumbnailUrl)
return file.exists() && file.delete()
}
}

@ -11,8 +11,8 @@ import io.requery.android.database.sqlite.RequerySQLiteOpenHelperFactory
/**
* This class provides operations to manage the database through its interfaces.
*/
open class DatabaseHelper(context: Context)
: MangaQueries, ChapterQueries, TrackQueries, CategoryQueries, MangaCategoryQueries, HistoryQueries {
open class DatabaseHelper(context: Context) :
MangaQueries, ChapterQueries, TrackQueries, CategoryQueries, MangaCategoryQueries, HistoryQueries {
private val configuration = SupportSQLiteOpenHelper.Configuration.builder(context)
.name(DbOpenCallback.DATABASE_NAME)
@ -32,5 +32,4 @@ open class DatabaseHelper(context: Context)
inline fun inTransaction(block: () -> Unit) = db.inTransaction(block)
fun lowLevel() = db.lowLevel()
}

@ -22,4 +22,3 @@ inline fun <T> StorIOSQLite.inTransactionReturn(block: () -> T): T {
lowLevel().endTransaction()
}
}

@ -69,5 +69,4 @@ class DbOpenCallback : SupportSQLiteOpenHelper.Callback(DATABASE_VERSION) {
override fun onConfigure(db: SupportSQLiteDatabase) {
db.setForeignKeyConstraintsEnabled(true)
}
}

@ -5,5 +5,4 @@ import com.pushtorefresh.storio.sqlite.impl.DefaultStorIOSQLite
interface DbProvider {
val db: DefaultStorIOSQLite
}

@ -85,4 +85,3 @@ class ChapterDeleteResolver : DefaultDeleteResolver<Chapter>() {
.whereArgs(obj.id)
.build()
}

@ -54,7 +54,6 @@ class TrackPutResolver : DefaultPutResolver<Track>() {
put(COL_STATUS, obj.status)
put(COL_TRACKING_URL, obj.tracking_url)
put(COL_SCORE, obj.score)
}
}

@ -23,5 +23,4 @@ interface Category : Serializable {
fun createDefault(): Category = create("Default").apply { id = 0 }
}
}

@ -22,5 +22,4 @@ class CategoryImpl : Category {
override fun hashCode(): Int {
return name.hashCode()
}
}

@ -37,5 +37,4 @@ class ChapterImpl : Chapter {
override fun hashCode(): Int {
return url.hashCode()
}
}

@ -5,5 +5,4 @@ class LibraryManga : MangaImpl() {
var unread: Int = 0
var category: Int = 0
}

@ -88,5 +88,4 @@ interface Manga : SManga {
this.source = source
}
}
}

@ -39,11 +39,9 @@ open class MangaImpl : Manga {
val manga = other as Manga
return url == manga.url
}
override fun hashCode(): Int {
return url.hashCode()
}
}

@ -37,5 +37,4 @@ interface Track : Serializable {
sync_id = serviceId
}
}
}

@ -41,5 +41,4 @@ class TrackImpl : Track {
result = 31 * result + media_id
return result
}
}

@ -32,5 +32,4 @@ interface CategoryQueries : DbProvider {
fun deleteCategory(category: Category) = db.delete().`object`(category).prepare()
fun deleteCategories(categories: List<Category>) = db.delete().objects(categories).prepare()
}

@ -88,5 +88,4 @@ interface ChapterQueries : DbProvider {
.objects(chapters)
.withPutResolver(ChapterSourceOrderPutResolver())
.prepare()
}

@ -28,5 +28,4 @@ interface MangaCategoryQueries : DbProvider {
insertMangasCategories(mangasCategories).executeAsBlocking()
}
}
}

@ -30,5 +30,4 @@ interface TrackQueries : DbProvider {
.whereArgs(manga.id, sync.id)
.build())
.prepare()
}

@ -30,6 +30,4 @@ class ChapterBackupPutResolver : PutResolver<Chapter>() {
put(ChapterTable.COL_BOOKMARK, chapter.bookmark)
put(ChapterTable.COL_LAST_PAGE_READ, chapter.last_page_read)
}
}

@ -30,6 +30,4 @@ class ChapterProgressPutResolver : PutResolver<Chapter>() {
put(ChapterTable.COL_BOOKMARK, chapter.bookmark)
put(ChapterTable.COL_LAST_PAGE_READ, chapter.last_page_read)
}
}

@ -28,5 +28,4 @@ class ChapterSourceOrderPutResolver : PutResolver<Chapter>() {
fun mapToContentValues(chapter: Chapter) = ContentValues(1).apply {
put(ChapterTable.COL_SOURCE_ORDER, chapter.source_order)
}
}

@ -60,5 +60,4 @@ class HistoryLastReadPutResolver : HistoryPutResolver() {
fun mapToUpdateContentValues(history: History) = ContentValues(1).apply {
put(HistoryTable.COL_LAST_READ, history.last_read)
}
}

@ -21,5 +21,4 @@ class LibraryMangaGetResolver : DefaultGetResolver<LibraryManga>(), BaseMangaGet
return manga
}
}

@ -24,5 +24,4 @@ class MangaChapterGetResolver : DefaultGetResolver<MangaChapter>() {
return MangaChapter(manga, chapter)
}
}

@ -28,6 +28,4 @@ class MangaFavoritePutResolver : PutResolver<Manga>() {
fun mapToContentValues(manga: Manga) = ContentValues(1).apply {
put(MangaTable.COL_FAVORITE, manga.favorite)
}
}

@ -28,6 +28,4 @@ class MangaFlagsPutResolver : PutResolver<Manga>() {
fun mapToContentValues(manga: Manga) = ContentValues(1).apply {
put(MangaTable.COL_CHAPTER_FLAGS, manga.chapter_flags)
}
}

@ -28,6 +28,4 @@ class MangaLastUpdatedPutResolver : PutResolver<Manga>() {
fun mapToContentValues(manga: Manga) = ContentValues(1).apply {
put(MangaTable.COL_LAST_UPDATE, manga.last_update)
}
}

@ -28,5 +28,4 @@ class MangaTitlePutResolver : PutResolver<Manga>() {
fun mapToContentValues(manga: Manga) = ContentValues(1).apply {
put(MangaTable.COL_TITLE, manga.title)
}
}

@ -28,5 +28,4 @@ class MangaViewerPutResolver : PutResolver<Manga>() {
fun mapToContentValues(manga: Manga) = ContentValues(1).apply {
put(MangaTable.COL_VIEWER, manga.viewer)
}
}

@ -19,5 +19,4 @@ object CategoryTable {
$COL_ORDER INTEGER NOT NULL,
$COL_FLAGS INTEGER NOT NULL
)"""
}

@ -61,5 +61,4 @@ object ChapterTable {
val addScanlator: String
get() = "ALTER TABLE $TABLE ADD COLUMN $COL_SCANLATOR TEXT DEFAULT NULL"
}

@ -20,5 +20,4 @@ object MangaCategoryTable {
FOREIGN KEY($COL_MANGA_ID) REFERENCES ${MangaTable.TABLE} (${MangaTable.COL_ID})
ON DELETE CASCADE
)"""
}

@ -8,9 +8,9 @@ import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.data.preference.getOrDefault
import eu.kanade.tachiyomi.source.SourceManager
import java.util.concurrent.TimeUnit
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import java.util.concurrent.TimeUnit
/**
* Cache where we dump the downloads directory from the filesystem. This class is needed because
@ -233,20 +233,26 @@ class DownloadCache(
/**
* Class to store the files under the root downloads directory.
*/
private class RootDirectory(val dir: UniFile,
var files: Map<Long, SourceDirectory> = hashMapOf())
private class RootDirectory(
val dir: UniFile,
var files: Map<Long, SourceDirectory> = hashMapOf()
)
/**
* Class to store the files under a source directory.
*/
private class SourceDirectory(val dir: UniFile,
var files: Map<String, MangaDirectory> = hashMapOf())
private class SourceDirectory(
val dir: UniFile,
var files: Map<String, MangaDirectory> = hashMapOf()
)
/**
* Class to store the files under a manga directory.
*/
private class MangaDirectory(val dir: UniFile,
var files: Set<String> = hashSetOf())
private class MangaDirectory(
val dir: UniFile,
var files: Set<String> = hashSetOf()
)
/**
* Returns a new map containing only the key entries of [transform] that are not null.
@ -270,5 +276,4 @@ class DownloadCache(
}
return destination
}
}

@ -206,5 +206,4 @@ class DownloadManager(context: Context) {
deleteChapters(chapters, manga, source)
}
}
}

@ -176,5 +176,4 @@ class DownloadPendingDeleter(context: Context) {
it.name = name
}
}
}

@ -126,5 +126,4 @@ class DownloadProvider(private val context: Context) {
fun getChapterDirName(chapter: Chapter): String {
return DiskUtil.buildValidFilename(chapter.name)
}
}

@ -194,5 +194,4 @@ class DownloadService : Service() {
setContentTitle(getString(R.string.download_notifier_downloader_title))
}
}
}

@ -133,5 +133,4 @@ class DownloadStore(
* @param order the order of the download in the queue.
*/
data class DownloadObject(val mangaId: Long, val chapterId: Long, val order: Int)
}

@ -291,7 +291,6 @@ class Downloader(
notifier.onError(error.message, download.chapter.name)
download
}
}
/**
@ -394,8 +393,12 @@ class Downloader(
* @param tmpDir the directory where the download is currently stored.
* @param dirname the real (non temporary) directory name of the download.
*/
private fun ensureSuccessfulDownload(download: Download, mangaDir: UniFile,
tmpDir: UniFile, dirname: String) {
private fun ensureSuccessfulDownload(
download: Download,
mangaDir: UniFile,
tmpDir: UniFile,
dirname: String
) {
// Ensure that the chapter folder has all the images.
val downloadedImages = tmpDir.listFiles().orEmpty().filterNot { it.name!!.endsWith(".tmp") }
@ -439,5 +442,4 @@ class Downloader(
companion object {
const val TMP_DIR_SUFFIX = "_tmp"
}
}

@ -5,14 +5,15 @@ import eu.kanade.tachiyomi.data.database.models.Chapter
import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.data.download.DownloadStore
import eu.kanade.tachiyomi.source.model.Page
import java.util.concurrent.CopyOnWriteArrayList
import rx.Observable
import rx.subjects.PublishSubject
import java.util.concurrent.CopyOnWriteArrayList
class DownloadQueue(
private val store: DownloadStore,
private val queue: MutableList<Download> = CopyOnWriteArrayList<Download>())
: List<Download> by queue {
private val queue: MutableList<Download> = CopyOnWriteArrayList<Download>()
) :
List<Download> by queue {
private val statusSubject = PublishSubject.create<Download>()
@ -80,7 +81,6 @@ class DownloadQueue(
.onBackpressureBuffer()
.filter { it == Page.READY }
.map { download }
} else if (download.status == Download.DOWNLOADED || download.status == Download.ERROR) {
setPagesSubject(download.pages, null)
}
@ -96,5 +96,4 @@ class DownloadQueue(
}
}
}
}

@ -16,10 +16,12 @@ import java.io.InputStream
* @param manga the manga of the cover to load.
* @param file the file where this cover should be. It may exists or not.
*/
class LibraryMangaUrlFetcher(private val networkFetcher: DataFetcher<InputStream>,
class LibraryMangaUrlFetcher(
private val networkFetcher: DataFetcher<InputStream>,
private val manga: Manga,
private val file: File)
: FileFetcher(file) {
private val file: File
) :
FileFetcher(file) {
override fun loadData(priority: Priority, callback: DataFetcher.DataCallback<in InputStream>) {
if (!file.exists()) {
@ -52,7 +54,6 @@ class LibraryMangaUrlFetcher(private val networkFetcher: DataFetcher<InputStream
override fun onLoadFailed(e: Exception) {
callback.onLoadFailed(e)
}
})
} else {
loadFromFile(callback)
@ -68,5 +69,4 @@ class LibraryMangaUrlFetcher(private val networkFetcher: DataFetcher<InputStream
super.cancel()
networkFetcher.cancel()
}
}

@ -9,12 +9,11 @@ import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.network.NetworkHelper
import eu.kanade.tachiyomi.source.SourceManager
import eu.kanade.tachiyomi.source.online.HttpSource
import java.io.File
import java.io.InputStream
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import uy.kohesive.injekt.injectLazy
import java.io.File
import java.io.InputStream
/**
* A class for loading a cover associated with a [Manga] that can be present in our own cache.
@ -78,8 +77,12 @@ class MangaModelLoader : ModelLoader<Manga, InputStream> {
* @param width the width of the view where the resource will be loaded.
* @param height the height of the view where the resource will be loaded.
*/
override fun buildLoadData(manga: Manga, width: Int, height: Int,
options: Options): ModelLoader.LoadData<InputStream>? {
override fun buildLoadData(
manga: Manga,
width: Int,
height: Int,
options: Options
): ModelLoader.LoadData<InputStream>? {
// Check thumbnail is not null or empty
val url = manga.thumbnail_url
if (url == null || url.isEmpty()) {
@ -142,5 +145,4 @@ class MangaModelLoader : ModelLoader<Manga, InputStream> {
value
}
}
}

@ -54,7 +54,6 @@ class PassthroughModelLoader : ModelLoader<InputStream, InputStream> {
) {
callback.onDataReady(stream)
}
}
/**
@ -70,5 +69,4 @@ class PassthroughModelLoader : ModelLoader<InputStream, InputStream> {
override fun teardown() {}
}
}

@ -15,9 +15,9 @@ import com.bumptech.glide.module.AppGlideModule
import com.bumptech.glide.request.RequestOptions
import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.network.NetworkHelper
import java.io.InputStream
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import java.io.InputStream
/**
* Class used to update Glide module settings

@ -39,5 +39,4 @@ object LibraryUpdateRanker {
compareValues(mangaFirst.title, mangaSecond.title)
}
}
}

@ -39,16 +39,16 @@ import eu.kanade.tachiyomi.util.system.isServiceRunning
import eu.kanade.tachiyomi.util.system.notification
import eu.kanade.tachiyomi.util.system.notificationBuilder
import eu.kanade.tachiyomi.util.system.notificationManager
import java.text.DecimalFormat
import java.text.DecimalFormatSymbols
import java.util.ArrayList
import java.util.concurrent.atomic.AtomicInteger
import rx.Observable
import rx.Subscription
import rx.schedulers.Schedulers
import timber.log.Timber
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import java.text.DecimalFormat
import java.text.DecimalFormatSymbols
import java.util.ArrayList
import java.util.concurrent.atomic.AtomicInteger
/**
* This class will take care of updating the chapters of the manga from the library. It can be
@ -169,7 +169,6 @@ class LibraryUpdateService(
fun stop(context: Context) {
context.stopService(Intent(context, LibraryUpdateService::class.java))
}
}
/**
@ -589,5 +588,4 @@ class LibraryUpdateService(
}
return PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)
}
}

@ -6,6 +6,7 @@ import android.content.Context
import android.content.Intent
import android.os.Build
import android.os.Handler
import eu.kanade.tachiyomi.BuildConfig.APPLICATION_ID as ID
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.database.DatabaseHelper
import eu.kanade.tachiyomi.data.database.models.Chapter
@ -23,11 +24,10 @@ import eu.kanade.tachiyomi.util.storage.DiskUtil
import eu.kanade.tachiyomi.util.storage.getUriCompat
import eu.kanade.tachiyomi.util.system.notificationManager
import eu.kanade.tachiyomi.util.system.toast
import java.io.File
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import uy.kohesive.injekt.injectLazy
import java.io.File
import eu.kanade.tachiyomi.BuildConfig.APPLICATION_ID as ID
/**
* Global [BroadcastReceiver] that runs on UI thread
@ -407,8 +407,13 @@ class NotificationReceiver : BroadcastReceiver() {
* @param context context of application
* @param manga manga of chapter
*/
internal fun markAsReadPendingBroadcast(context: Context, manga: Manga, chapters:
Array<Chapter>, groupId: Int):
internal fun markAsReadPendingBroadcast(
context: Context,
manga: Manga,
chapters:
Array<Chapter>,
groupId: Int
):
PendingIntent {
val newIntent = Intent(context, NotificationReceiver::class.java).apply {
action = ACTION_MARK_AS_READ

@ -144,5 +144,4 @@ object PreferenceKeys {
fun trackPassword(syncId: Int) = "pref_mangasync_password_$syncId"
fun trackToken(syncId: Int) = "track_token_$syncId"
}

@ -12,5 +12,4 @@ object PreferenceValues {
const val THEME_DARK_DEFAULT = "default"
const val THEME_DARK_BLUE = "blue"
const val THEME_DARK_AMOLED = "amoled"
}

@ -8,14 +8,14 @@ import android.preference.PreferenceManager
import com.f2prateek.rx.preferences.Preference
import com.f2prateek.rx.preferences.RxSharedPreferences
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.preference.PreferenceKeys as Keys
import eu.kanade.tachiyomi.data.preference.PreferenceValues as Values
import eu.kanade.tachiyomi.data.track.TrackService
import eu.kanade.tachiyomi.source.Source
import java.io.File
import java.text.DateFormat
import java.text.SimpleDateFormat
import java.util.Locale
import eu.kanade.tachiyomi.data.preference.PreferenceKeys as Keys
import eu.kanade.tachiyomi.data.preference.PreferenceValues as Values
fun <T> Preference<T>.getOrDefault(): T = get() ?: defaultValue()!!

@ -32,5 +32,4 @@ class TrackManager(private val context: Context) {
fun getService(id: Int) = services.find { it.id == id }
fun hasLoggedServices() = services.any { it.isLogged }
}

@ -209,6 +209,4 @@ class Anilist(private val context: Context, id: Int) : TrackService(id) {
null
}
}
}

@ -7,13 +7,12 @@ import com.google.gson.JsonParser
import eu.kanade.tachiyomi.data.database.models.Track
import eu.kanade.tachiyomi.data.track.model.TrackSearch
import eu.kanade.tachiyomi.network.asObservableSuccess
import java.util.Calendar
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.RequestBody.Companion.toRequestBody
import rx.Observable
import java.util.Calendar
class AnilistApi(val client: OkHttpClient, interceptor: AnilistInterceptor) {
@ -143,7 +142,6 @@ class AnilistApi(val client: OkHttpClient, interceptor: AnilistInterceptor) {
}
}
fun findLibManga(track: Track, userid: Int): Observable<Track?> {
val query = """
|query (${'$'}id: Int!, ${'$'}manga_id: Int!) {
@ -201,7 +199,6 @@ class AnilistApi(val client: OkHttpClient, interceptor: AnilistInterceptor) {
val media = page["mediaList"].array
val entries = media.map { jsonToALUserManga(it.obj) }
entries.firstOrNull()?.toTrack()
}
}
@ -283,5 +280,4 @@ class AnilistApi(val client: OkHttpClient, interceptor: AnilistInterceptor) {
.appendQueryParameter("response_type", "token")
.build()
}
}

@ -3,7 +3,6 @@ package eu.kanade.tachiyomi.data.track.anilist
import okhttp3.Interceptor
import okhttp3.Response
class AnilistInterceptor(val anilist: Anilist, private var token: String?) : Interceptor {
/**
@ -54,5 +53,4 @@ class AnilistInterceptor(val anilist: Anilist, private var token: String?) : Int
this.oauth = oauth
anilist.saveOAuth(oauth)
}
}

@ -5,9 +5,9 @@ import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.data.preference.getOrDefault
import eu.kanade.tachiyomi.data.track.TrackManager
import eu.kanade.tachiyomi.data.track.model.TrackSearch
import uy.kohesive.injekt.injectLazy
import java.text.SimpleDateFormat
import java.util.Locale
import uy.kohesive.injekt.injectLazy
data class ALManga(
val media_id: Int,
@ -17,7 +17,8 @@ data class ALManga(
val type: String,
val publishing_status: String,
val start_date_fuzzy: Long,
val total_chapters: Int) {
val total_chapters: Int
) {
fun toTrack() = TrackSearch.create(TrackManager.ANILIST).apply {
media_id = this@ALManga.media_id
@ -44,7 +45,8 @@ data class ALUserManga(
val list_status: String,
val score_raw: Int,
val chapters_read: Int,
val manga: ALManga) {
val manga: ALManga
) {
fun toTrack() = Track.create(TrackManager.ANILIST).apply {
media_id = manga.media_id

@ -4,7 +4,8 @@ data class OAuth(
val access_token: String,
val token_type: String,
val expires: Long,
val expires_in: Long) {
val expires_in: Long
) {
fun isExpired() = System.currentTimeMillis() > expires
}

@ -11,13 +11,13 @@ import eu.kanade.tachiyomi.data.track.TrackManager
import eu.kanade.tachiyomi.data.track.model.TrackSearch
import eu.kanade.tachiyomi.network.POST
import eu.kanade.tachiyomi.network.asObservableSuccess
import java.net.URLEncoder
import okhttp3.CacheControl
import okhttp3.FormBody
import okhttp3.OkHttpClient
import okhttp3.Request
import rx.Observable
import uy.kohesive.injekt.injectLazy
import java.net.URLEncoder
class BangumiApi(private val client: OkHttpClient, interceptor: BangumiInterceptor) {
@ -94,7 +94,6 @@ class BangumiApi(private val client: OkHttpClient, interceptor: BangumiIntercept
val response = parser.parse(responseBody).obj["list"]?.array
response?.filter { it.obj["type"].asInt == 1 }?.map { jsonToSearch(it.obj) }
}
}
private fun jsonToSearch(obj: JsonObject): TrackSearch {
@ -207,5 +206,4 @@ class BangumiApi(private val client: OkHttpClient, interceptor: BangumiIntercept
.add("redirect_uri", redirectUrl)
.build())
}
}

@ -11,6 +11,4 @@ data class OAuth(
// Access token refresh before expired
fun isExpired() = (System.currentTimeMillis() / 1000) > (created_at + expires_in - 3600)
}

@ -7,10 +7,10 @@ import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.database.models.Track
import eu.kanade.tachiyomi.data.track.TrackService
import eu.kanade.tachiyomi.data.track.model.TrackSearch
import java.text.DecimalFormat
import rx.Completable
import rx.Observable
import uy.kohesive.injekt.injectLazy
import java.text.DecimalFormat
class Kitsu(private val context: Context, id: Int) : TrackService(id) {
@ -140,5 +140,4 @@ class Kitsu(private val context: Context, id: Int) : TrackService(id) {
null
}
}
}

@ -94,7 +94,6 @@ class KitsuApi(private val client: OkHttpClient, interceptor: KitsuInterceptor)
}
}
fun search(query: String): Observable<List<TrackSearch>> {
return searchRest
.getKey().map { json ->
@ -104,7 +103,6 @@ class KitsuApi(private val client: OkHttpClient, interceptor: KitsuInterceptor)
}
}
private fun algoliaSearch(key: String, query: String): Observable<List<TrackSearch>> {
val jsonObject = jsonObject("params" to "query=$query$algoliaFilter")
return algoliaRest
@ -173,7 +171,6 @@ class KitsuApi(private val client: OkHttpClient, interceptor: KitsuInterceptor)
@Body data: JsonObject
): Observable<JsonObject>
@GET("library-entries")
fun findLibManga(
@Query("filter[manga_id]", encoded = true) remoteId: Int,
@ -191,7 +188,6 @@ class KitsuApi(private val client: OkHttpClient, interceptor: KitsuInterceptor)
fun getCurrentUser(
@Query("filter[self]", encoded = true) self: Boolean = true
): Observable<JsonObject>
}
private interface SearchKeyRest {
@ -215,7 +211,6 @@ class KitsuApi(private val client: OkHttpClient, interceptor: KitsuInterceptor)
@Field("client_id") client_id: String = clientId,
@Field("client_secret") client_secret: String = clientSecret
): Observable<OAuth>
}
companion object {
@ -229,12 +224,10 @@ class KitsuApi(private val client: OkHttpClient, interceptor: KitsuInterceptor)
private const val algoliaAppId = "AWQO5J657S"
private const val algoliaFilter = "&facetFilters=%5B%22kind%3Amanga%22%5D&attributesToRetrieve=%5B%22synopsis%22%2C%22canonicalTitle%22%2C%22chapterCount%22%2C%22posterImage%22%2C%22startDate%22%2C%22subtype%22%2C%22endDate%22%2C%20%22id%22%5D"
fun mangaUrl(remoteId: Int): String {
return baseMangaUrl + remoteId
}
fun refreshTokenRequest(token: String) = POST("${loginUrl}oauth/token",
body = FormBody.Builder()
.add("grant_type", "refresh_token")
@ -242,7 +235,5 @@ class KitsuApi(private val client: OkHttpClient, interceptor: KitsuInterceptor)
.add("client_secret", clientSecret)
.add("refresh_token", token)
.build())
}
}

@ -42,5 +42,4 @@ class KitsuInterceptor(val kitsu: Kitsu, val gson: Gson) : Interceptor {
this.oauth = oauth
kitsu.saveToken(oauth)
}
}

@ -41,7 +41,6 @@ class KitsuSearchManga(obj: JsonObject) {
}
}
class KitsuLibManga(obj: JsonObject, manga: JsonObject) {
val id by manga.byInt
private val canonicalTitle by manga["attributes"].byString
@ -78,7 +77,6 @@ class KitsuLibManga(obj: JsonObject, manga: JsonObject) {
"planned" -> Kitsu.PLAN_TO_READ
else -> throw Exception("Unknown status")
}
}
fun Track.toKitsuStatus() = when (status) {

@ -5,7 +5,8 @@ data class OAuth(
val token_type: String,
val created_at: Long,
val expires_in: Long,
val refresh_token: String?) {
val refresh_token: String?
) {
fun isExpired() = (System.currentTimeMillis() / 1000) > (created_at + expires_in - 3600)
}

@ -59,5 +59,4 @@ class TrackSearch : Track {
sync_id = serviceId
}
}
}

@ -159,5 +159,4 @@ class Myanimelist(private val context: Context, id: Int) : TrackService(id) {
return ckCount == 2
}
}

@ -10,6 +10,9 @@ import eu.kanade.tachiyomi.network.asObservable
import eu.kanade.tachiyomi.network.asObservableSuccess
import eu.kanade.tachiyomi.util.selectInt
import eu.kanade.tachiyomi.util.selectText
import java.io.BufferedReader
import java.io.InputStreamReader
import java.util.zip.GZIPInputStream
import okhttp3.FormBody
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.OkHttpClient
@ -22,10 +25,6 @@ import org.jsoup.nodes.Document
import org.jsoup.nodes.Element
import org.jsoup.parser.Parser
import rx.Observable
import java.io.BufferedReader
import java.io.InputStreamReader
import java.util.zip.GZIPInputStream
class MyAnimeListApi(private val client: OkHttpClient, interceptor: MyAnimeListInterceptor) {

@ -5,9 +5,9 @@ data class OAuth(
val token_type: String,
val created_at: Long,
val expires_in: Long,
val refresh_token: String?) {
val refresh_token: String?
) {
// Access token lives 1 day
fun isExpired() = (System.currentTimeMillis() / 1000) > (created_at + expires_in - 3600)
}

@ -74,7 +74,6 @@ class ShikimoriApi(private val client: OkHttpClient, interceptor: ShikimoriInter
val response = parser.parse(responseBody).array
response.map { jsonToSearch(it.obj) }
}
}
private fun jsonToSearch(obj: JsonObject): TrackSearch {
@ -171,7 +170,6 @@ class ShikimoriApi(private val client: OkHttpClient, interceptor: ShikimoriInter
.build()
)
companion object {
private const val clientId = "1aaf4cf232372708e98b5abc813d795b539c5a916dbbfe9ac61bf02a360832cc"
private const val clientSecret = "229942c742dd4cde803125d17d64501d91c0b12e14cb1e5120184d77d67024c0"
@ -195,7 +193,6 @@ class ShikimoriApi(private val client: OkHttpClient, interceptor: ShikimoriInter
.appendQueryParameter("response_type", "code")
.build()
fun refreshTokenRequest(token: String) = POST(oauthUrl,
body = FormBody.Builder()
.add("grant_type", "refresh_token")
@ -203,7 +200,5 @@ class ShikimoriApi(private val client: OkHttpClient, interceptor: ShikimoriInter
.add("client_secret", clientSecret)
.add("refresh_token", token)
.build())
}
}

@ -9,5 +9,4 @@ interface Release {
* @return download link of latest release.
*/
val downloadLink: String
}

@ -20,5 +20,4 @@ abstract class UpdateChecker {
* Returns observable containing release information
*/
abstract suspend fun checkForUpdate(): UpdateResult
}

@ -4,5 +4,4 @@ abstract class UpdateResult {
open class NewUpdate<T : Release>(val release: T) : UpdateResult()
open class NoNewUpdate : UpdateResult()
}

@ -64,5 +64,4 @@ class UpdaterJob : Job() {
JobManager.instance().cancelAllForTag(TAG)
}
}
}

@ -12,9 +12,9 @@ import eu.kanade.tachiyomi.network.ProgressListener
import eu.kanade.tachiyomi.network.newCallWithProgress
import eu.kanade.tachiyomi.util.storage.getUriCompat
import eu.kanade.tachiyomi.util.storage.saveTo
import java.io.File
import timber.log.Timber
import uy.kohesive.injekt.injectLazy
import java.io.File
class UpdaterService : IntentService(UpdaterService::class.java.name) {
@ -119,5 +119,3 @@ class UpdaterService : IntentService(UpdaterService::class.java.name) {
}
}
}

@ -10,5 +10,4 @@ class DevRepoRelease(override val info: String) : Release {
companion object {
const val LATEST_URL = "https://tachiyomi.kanade.eu/latest"
}
}

@ -38,5 +38,4 @@ class DevRepoUpdateChecker : UpdateChecker() {
DevRepoUpdateResult.NoNewUpdate()
}
}
}

@ -6,5 +6,4 @@ sealed class DevRepoUpdateResult : UpdateResult() {
class NewUpdate(release: DevRepoRelease) : UpdateResult.NewUpdate<DevRepoRelease>(release)
class NoNewUpdate : UpdateResult.NoNewUpdate()
}

@ -11,9 +11,11 @@ import eu.kanade.tachiyomi.data.updater.Release
* @param info log of latest release.
* @param assets assets of latest release.
*/
class GithubRelease(@SerializedName("tag_name") val version: String,
class GithubRelease(
@SerializedName("tag_name") val version: String,
@SerializedName("body") override val info: String,
@SerializedName("assets") private val assets: List<Assets>) : Release {
@SerializedName("assets") private val assets: List<Assets>
) : Release {
/**
* Get download link of latest release from the assets.
@ -28,4 +30,3 @@ class GithubRelease(@SerializedName("tag_name") val version: String,
*/
inner class Assets(@SerializedName("browser_download_url") val downloadLink: String)
}

@ -26,5 +26,4 @@ interface GithubService {
@GET("/repos/inorichi/tachiyomi/releases/latest")
suspend fun getLatestVersion(): GithubRelease
}

@ -20,5 +20,4 @@ class GithubUpdateChecker : UpdateChecker() {
GithubUpdateResult.NoNewUpdate()
}
}
}

@ -6,5 +6,4 @@ sealed class GithubUpdateResult : UpdateResult() {
class NewUpdate(release: GithubRelease) : UpdateResult.NewUpdate<GithubRelease>(release)
class NoNewUpdate : UpdateResult.NoNewUpdate()
}

@ -341,5 +341,4 @@ class ExtensionManager(
}
return this
}
}

@ -10,28 +10,33 @@ sealed class Extension {
abstract val versionCode: Int
abstract val lang: String?
data class Installed(override val name: String,
data class Installed(
override val name: String,
override val pkgName: String,
override val versionName: String,
override val versionCode: Int,
val sources: List<Source>,
override val lang: String,
val hasUpdate: Boolean = false,
val isObsolete: Boolean = false) : Extension()
val isObsolete: Boolean = false
) : Extension()
data class Available(override val name: String,
data class Available(
override val name: String,
override val pkgName: String,
override val versionName: String,
override val versionCode: Int,
override val lang: String,
val apkName: String,
val iconUrl: String) : Extension()
val iconUrl: String
) : Extension()
data class Untrusted(override val name: String,
data class Untrusted(
override val name: String,
override val pkgName: String,
override val versionName: String,
override val versionCode: Int,
val signatureHash: String,
override val lang: String? = null) : Extension()
override val lang: String? = null
) : Extension()
}

@ -115,5 +115,4 @@ internal class ExtensionInstallReceiver(private val listener: Listener) :
fun onExtensionUntrusted(extension: Extension.Untrusted)
fun onPackageUninstalled(pkgName: String)
}
}

@ -11,11 +11,11 @@ import com.jakewharton.rxrelay.PublishRelay
import eu.kanade.tachiyomi.extension.model.Extension
import eu.kanade.tachiyomi.extension.model.InstallStep
import eu.kanade.tachiyomi.util.storage.getUriCompat
import java.io.File
import java.util.concurrent.TimeUnit
import rx.Observable
import rx.android.schedulers.AndroidSchedulers
import timber.log.Timber
import java.io.File
import java.util.concurrent.TimeUnit
/**
* The installer which installs, updates and uninstalls the extensions.
@ -243,5 +243,4 @@ internal class ExtensionInstaller(private val context: Context) {
const val APK_MIME = "application/vnd.android.package-archive"
const val EXTRA_DOWNLOAD_ID = "ExtensionInstaller.extra.DOWNLOAD_ID"
}
}

@ -185,5 +185,4 @@ internal object ExtensionLoader {
null
}
}
}

@ -12,15 +12,15 @@ import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.util.system.WebViewClientCompat
import eu.kanade.tachiyomi.util.system.isOutdated
import eu.kanade.tachiyomi.util.system.toast
import java.io.IOException
import java.util.concurrent.CountDownLatch
import java.util.concurrent.TimeUnit
import okhttp3.Cookie
import okhttp3.HttpUrl.Companion.toHttpUrl
import okhttp3.Interceptor
import okhttp3.Request
import okhttp3.Response
import uy.kohesive.injekt.injectLazy
import java.io.IOException
import java.util.concurrent.CountDownLatch
import java.util.concurrent.TimeUnit
class CloudflareInterceptor(private val context: Context) : Interceptor {
@ -157,5 +157,4 @@ class CloudflareInterceptor(private val context: Context) : Interceptor {
private val SERVER_CHECK = arrayOf("cloudflare-nginx", "cloudflare")
private val COOKIE_NAMES = listOf("__cfduid", "cf_clearance")
}
}

@ -1,9 +1,9 @@
package eu.kanade.tachiyomi.network
import android.content.Context
import java.io.File
import okhttp3.Cache
import okhttp3.OkHttpClient
import java.io.File
class NetworkHelper(context: Context) {
@ -21,5 +21,4 @@ class NetworkHelper(context: Context) {
val cloudflareClient = client.newBuilder()
.addInterceptor(CloudflareInterceptor(context))
.build()
}

@ -1,14 +1,14 @@
package eu.kanade.tachiyomi.network
import java.io.IOException
import java.util.concurrent.atomic.AtomicBoolean
import kotlin.coroutines.resume
import kotlin.coroutines.resumeWithException
import kotlinx.coroutines.suspendCancellableCoroutine
import okhttp3.*
import rx.Observable
import rx.Producer
import rx.Subscription
import java.io.IOException
import java.util.concurrent.atomic.AtomicBoolean
import kotlin.coroutines.resume
import kotlin.coroutines.resumeWithException
fun Call.asObservable(): Observable<Response> {
return Observable.unsafeCreate { subscriber ->

@ -1,9 +1,9 @@
package eu.kanade.tachiyomi.network
import java.io.IOException
import okhttp3.MediaType
import okhttp3.ResponseBody
import okio.*
import java.io.IOException
class ProgressResponseBody(private val responseBody: ResponseBody, private val progressListener: ProgressListener) : ResponseBody() {

@ -1,15 +1,17 @@
package eu.kanade.tachiyomi.network
import okhttp3.*
import java.util.concurrent.TimeUnit.MINUTES
import okhttp3.*
private val DEFAULT_CACHE_CONTROL = CacheControl.Builder().maxAge(10, MINUTES).build()
private val DEFAULT_HEADERS = Headers.Builder().build()
private val DEFAULT_BODY: RequestBody = FormBody.Builder().build()
fun GET(url: String,
fun GET(
url: String,
headers: Headers = DEFAULT_HEADERS,
cache: CacheControl = DEFAULT_CACHE_CONTROL): Request {
cache: CacheControl = DEFAULT_CACHE_CONTROL
): Request {
return Request.Builder()
.url(url)
@ -18,10 +20,12 @@ fun GET(url: String,
.build()
}
fun POST(url: String,
fun POST(
url: String,
headers: Headers = DEFAULT_HEADERS,
body: RequestBody = DEFAULT_BODY,
cache: CacheControl = DEFAULT_CACHE_CONTROL): Request {
cache: CacheControl = DEFAULT_CACHE_CONTROL
): Request {
return Request.Builder()
.url(url)

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

Loading…
Cancel
Save