Turned on kt lint

pull/3117/head
Jay 5 years ago
parent cc28ff7a77
commit da786bbc40

@ -8,7 +8,7 @@ plugins {
kotlin("android")
kotlin("android.extensions")
kotlin("kapt")
//id("org.jmailen.kotlinter") version "2.3.1"
id("org.jmailen.kotlinter") version "2.3.1"
id("com.github.zellius.shortcut-helper")
id("com.google.gms.google-services") apply false
}
@ -114,9 +114,9 @@ dependencies {
implementation("com.google.firebase:firebase-core:17.2.3")
val lifecycle_version = "2.1.0"
implementation("androidx.lifecycle:lifecycle-extensions:$lifecycle_version")
implementation("androidx.lifecycle:lifecycle-common-java8:$lifecycle_version")
val lifecycleVersion = "2.1.0"
implementation("androidx.lifecycle:lifecycle-extensions:$lifecycleVersion")
implementation("androidx.lifecycle:lifecycle-common-java8:$lifecycleVersion")
// ReactiveX
implementation("io.reactivex:rxandroid:1.2.1")
@ -126,15 +126,15 @@ dependencies {
implementation("com.github.pwittchen:reactivenetwork:0.13.0")
// Network client
val okhttp_version = "4.3.1"
implementation("com.squareup.okhttp3:okhttp:$okhttp_version")
implementation("com.squareup.okhttp3:logging-interceptor:$okhttp_version")
val okhttpVersion = "4.3.1"
implementation("com.squareup.okhttp3:okhttp:$okhttpVersion")
implementation("com.squareup.okhttp3:logging-interceptor:$okhttpVersion")
implementation("com.squareup.okio:okio:2.4.3")
// REST
val retrofit_version = "2.7.1"
implementation("com.squareup.retrofit2:retrofit:$retrofit_version")
implementation("com.squareup.retrofit2:converter-gson:$retrofit_version")
val retrofitVersion = "2.7.1"
implementation("com.squareup.retrofit2:retrofit:$retrofitVersion")
implementation("com.squareup.retrofit2:converter-gson:$retrofitVersion")
// JSON
implementation("com.google.code.gson:gson:2.8.6")
@ -164,18 +164,18 @@ dependencies {
implementation("io.requery:sqlite-android:3.31.0")
// Model View Presenter
val nucleus_version = "3.0.0"
implementation("info.android15.nucleus:nucleus:$nucleus_version")
implementation("info.android15.nucleus:nucleus-support-v7:$nucleus_version")
val nucleusVersion = "3.0.0"
implementation("info.android15.nucleus:nucleus:$nucleusVersion")
implementation("info.android15.nucleus:nucleus-support-v7:$nucleusVersion")
// Dependency injection
implementation("com.github.inorichi.injekt:injekt-core:65b0440")
// Image library
val glide_version = "4.11.0"
implementation("com.github.bumptech.glide:glide:$glide_version")
implementation("com.github.bumptech.glide:okhttp3-integration:$glide_version")
kapt("com.github.bumptech.glide:compiler:$glide_version")
val glideVersion = "4.11.0"
implementation("com.github.bumptech.glide:glide:$glideVersion")
implementation("com.github.bumptech.glide:okhttp3-integration:$glideVersion")
kapt("com.github.bumptech.glide:compiler:$glideVersion")
// Transformations
implementation("jp.wasabeef:glide-transformations:4.1.0")
@ -208,28 +208,28 @@ dependencies {
implementation("com.github.inorichi:conductor-support-preference:a32c357")
// RxBindings
val rxbindings_version = "1.0.1"
implementation("com.jakewharton.rxbinding:rxbinding-kotlin:$rxbindings_version")
implementation("com.jakewharton.rxbinding:rxbinding-appcompat-v7-kotlin:$rxbindings_version")
implementation("com.jakewharton.rxbinding:rxbinding-support-v4-kotlin:$rxbindings_version")
implementation("com.jakewharton.rxbinding:rxbinding-recyclerview-v7-kotlin:$rxbindings_version")
val rxbindingsVersion = "1.0.1"
implementation("com.jakewharton.rxbinding:rxbinding-kotlin:$rxbindingsVersion")
implementation("com.jakewharton.rxbinding:rxbinding-appcompat-v7-kotlin:$rxbindingsVersion")
implementation("com.jakewharton.rxbinding:rxbinding-support-v4-kotlin:$rxbindingsVersion")
implementation("com.jakewharton.rxbinding:rxbinding-recyclerview-v7-kotlin:$rxbindingsVersion")
// Tests
testImplementation("junit:junit:4.13")
testImplementation("org.assertj:assertj-core:1.7.1")
testImplementation("org.assertj:assertj-core:3.12.2")
testImplementation("org.mockito:mockito-core:1.10.19")
val robolectric_version = "3.1.4"
testImplementation("org.robolectric:robolectric:$robolectric_version")
testImplementation("org.robolectric:shadows-multidex:$robolectric_version")
testImplementation("org.robolectric:shadows-play-services:$robolectric_version")
val robolectricVersion = "3.1.4"
testImplementation("org.robolectric:robolectric:$robolectricVersion")
testImplementation("org.robolectric:shadows-multidex:$robolectricVersion")
testImplementation("org.robolectric:shadows-play-services:$robolectricVersion")
implementation(kotlin("stdlib", org.jetbrains.kotlin.config.KotlinCompilerVersion.VERSION))
val coroutines_version = "1.3.3"
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines_version")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines_version")
val coroutinesVersion = "1.3.3"
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutinesVersion")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutinesVersion")
//Crash reports
val acraVersion = "4.9.2"
@ -239,13 +239,13 @@ dependencies {
implementation("info.debatty:java-string-similarity:1.2.1")
}
/*tasks.preBuild {
tasks.preBuild {
dependsOn(tasks.lintKotlin)
}
tasks.lintKotlin {
dependsOn(tasks.formatKotlin)
}*/
}
if (getGradle().getStartParameter().getTaskRequests().toString().contains("Standard")) {
if (gradle.startParameter.taskRequests.toString().contains("Standard")) {
apply(mapOf("plugin" to "com.google.gms.google-services"))
}

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

@ -13,7 +13,11 @@ import eu.kanade.tachiyomi.network.NetworkHelper
import eu.kanade.tachiyomi.source.SourceManager
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import uy.kohesive.injekt.api.*
import uy.kohesive.injekt.api.InjektModule
import uy.kohesive.injekt.api.InjektRegistrar
import uy.kohesive.injekt.api.addSingleton
import uy.kohesive.injekt.api.addSingletonFactory
import uy.kohesive.injekt.api.get
class AppModule(val app: Application) : InjektModule {
@ -52,7 +56,5 @@ class AppModule(val app: Application) : InjektModule {
GlobalScope.launch { get<DatabaseHelper>() }
GlobalScope.launch { get<DownloadManager>() }
}
}

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

@ -1,7 +1,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) }
@ -60,5 +59,4 @@ class BackupCreateService : IntentService(NAME) {
if (uri != null)
backupManager.createBackup(uri, flags, false)
}
}

@ -6,9 +6,9 @@ import com.evernote.android.job.JobManager
import com.evernote.android.job.JobRequest
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.data.preference.getOrDefault
import java.util.concurrent.TimeUnit
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import java.util.concurrent.TimeUnit
class BackupCreatorJob : Job() {

@ -3,8 +3,15 @@ package eu.kanade.tachiyomi.data.backup
import android.content.Context
import android.content.Intent
import android.net.Uri
import com.github.salomonbrys.kotson.*
import com.google.gson.*
import com.github.salomonbrys.kotson.fromJson
import com.github.salomonbrys.kotson.registerTypeAdapter
import com.github.salomonbrys.kotson.registerTypeHierarchyAdapter
import com.github.salomonbrys.kotson.set
import com.google.gson.Gson
import com.google.gson.GsonBuilder
import com.google.gson.JsonArray
import com.google.gson.JsonElement
import com.google.gson.JsonObject
import com.hippo.unifile.UniFile
import eu.kanade.tachiyomi.data.backup.BackupCreateService.Companion.BACKUP_CATEGORY
import eu.kanade.tachiyomi.data.backup.BackupCreateService.Companion.BACKUP_CATEGORY_MASK
@ -22,22 +29,34 @@ import eu.kanade.tachiyomi.data.backup.models.Backup.HISTORY
import eu.kanade.tachiyomi.data.backup.models.Backup.MANGA
import eu.kanade.tachiyomi.data.backup.models.Backup.TRACK
import eu.kanade.tachiyomi.data.backup.models.DHistory
import eu.kanade.tachiyomi.data.backup.serializer.*
import eu.kanade.tachiyomi.data.backup.serializer.CategoryTypeAdapter
import eu.kanade.tachiyomi.data.backup.serializer.ChapterTypeAdapter
import eu.kanade.tachiyomi.data.backup.serializer.HistoryTypeAdapter
import eu.kanade.tachiyomi.data.backup.serializer.MangaTypeAdapter
import eu.kanade.tachiyomi.data.backup.serializer.TrackTypeAdapter
import eu.kanade.tachiyomi.data.database.DatabaseHelper
import eu.kanade.tachiyomi.data.database.models.*
import eu.kanade.tachiyomi.data.database.models.CategoryImpl
import eu.kanade.tachiyomi.data.database.models.Chapter
import eu.kanade.tachiyomi.data.database.models.ChapterImpl
import eu.kanade.tachiyomi.data.database.models.History
import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.data.database.models.MangaCategory
import eu.kanade.tachiyomi.data.database.models.MangaImpl
import eu.kanade.tachiyomi.data.database.models.Track
import eu.kanade.tachiyomi.data.database.models.TrackImpl
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.source.Source
import eu.kanade.tachiyomi.source.SourceManager
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import eu.kanade.tachiyomi.util.chapter.syncChaptersWithSource
import eu.kanade.tachiyomi.util.system.sendLocalBroadcast
import kotlin.math.max
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
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) {

@ -38,23 +38,22 @@ import eu.kanade.tachiyomi.util.lang.chop
import eu.kanade.tachiyomi.util.storage.getUriCompat
import eu.kanade.tachiyomi.util.system.isServiceRunning
import eu.kanade.tachiyomi.util.system.notificationManager
import java.io.File
import java.text.SimpleDateFormat
import java.util.Locale
import java.util.concurrent.TimeUnit
import kotlinx.coroutines.CoroutineExceptionHandler
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
import timber.log.Timber
import uy.kohesive.injekt.injectLazy
import java.io.File
import java.text.SimpleDateFormat
import java.util.Locale
import java.util.concurrent.TimeUnit
/**
* Restores backup from json file
*/
class BackupRestoreService : Service() {
/**
* Wake lock that will be held until the service is destroyed.
*/
@ -87,7 +86,6 @@ class BackupRestoreService : Service() {
*/
private val trackingErrors = mutableListOf<String>()
/**
* List containing missing sources
*/
@ -113,7 +111,6 @@ class BackupRestoreService : Service() {
*/
internal val trackManager: TrackManager by injectLazy()
/**
* Method called when the service is created. It injects dependencies and acquire the wake lock.
*/
@ -216,7 +213,6 @@ class BackupRestoreService : Service() {
showResultNotification(logFile.parent, logFile.name)
}
/**Restore categories if they were backed up
*
*/
@ -246,8 +242,7 @@ class BackupRestoreService : Service() {
if (job?.isCancelled == false) {
showProgressNotification(restoreProgress, totalAmount, manga.title)
restoreProgress += 1
}
else {
} else {
throw java.lang.Exception("Job was cancelled")
}
val dbManga = backupManager.getMangaFromDatabase(manga)
@ -280,8 +275,7 @@ class BackupRestoreService : Service() {
val cause = e.cause
if (cause is SourceNotFoundException) {
sourcesMissing.add(cause.id)
}
else if (e.message?.contains("licensed", true) == true) {
} else if (e.message?.contains("licensed", true) == true) {
lincensedManga++
}
errors.add("${manga.title} - ${cause?.message ?: e.message}")
@ -357,7 +351,6 @@ class BackupRestoreService : Service() {
NotificationReceiver.cancelRestorePendingBroadcast(this)
}
/**
* Shows the notification containing the currently updating manga and the progress.
*

@ -1,7 +1,8 @@
package eu.kanade.tachiyomi.data.backup.models
import java.text.SimpleDateFormat
import java.util.*
import java.util.Date
import java.util.Locale
/**
* Json values

@ -1,6 +1,5 @@
package eu.kanade.tachiyomi.data.backup.serializer
import android.telecom.DisconnectCause.REMOTE
import com.github.salomonbrys.kotson.typeAdapter
import com.google.gson.TypeAdapter
import com.google.gson.stream.JsonToken

@ -9,14 +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.Okio
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
@ -136,7 +135,6 @@ class ChapterCache(private val context: Context) {
diskCache.flush()
editor.commit()
editor.abortUnlessCommitted()
} catch (e: Exception) {
// Ignore.
} finally {
@ -202,4 +200,3 @@ class ChapterCache(private val context: Context) {
return "${chapter.manga_id}${chapter.url}"
}
}

@ -20,8 +20,8 @@ class CoverCache(private val context: Context) {
/**
* Cache directory used for cache management.
*/
private val cacheDir = context.getExternalFilesDir("covers") ?:
File(context.filesDir, "covers").also { it.mkdirs() }
private val cacheDir = context.getExternalFilesDir("covers")
?: File(context.filesDir, "covers").also { it.mkdirs() }
/**
* Returns the cover from cache.

@ -29,8 +29,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,
open class DatabaseHelper(context: Context) :
MangaQueries, ChapterQueries, TrackQueries, CategoryQueries, MangaCategoryQueries,
HistoryQueries, SearchMetadataQueries {
private val configuration = SupportSQLiteOpenHelper.Configuration.builder(context)
@ -52,5 +52,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()
}
}

@ -2,10 +2,12 @@ package eu.kanade.tachiyomi.data.database
import androidx.sqlite.db.SupportSQLiteDatabase
import androidx.sqlite.db.SupportSQLiteOpenHelper
import android.content.Context
import android.database.sqlite.SQLiteDatabase
import android.database.sqlite.SQLiteOpenHelper
import eu.kanade.tachiyomi.data.database.tables.*
import eu.kanade.tachiyomi.data.database.tables.CategoryTable
import eu.kanade.tachiyomi.data.database.tables.ChapterTable
import eu.kanade.tachiyomi.data.database.tables.HistoryTable
import eu.kanade.tachiyomi.data.database.tables.MangaCategoryTable
import eu.kanade.tachiyomi.data.database.tables.MangaTable
import eu.kanade.tachiyomi.data.database.tables.TrackTable
class DbOpenCallback : SupportSQLiteOpenHelper.Callback(DATABASE_VERSION) {
@ -81,5 +83,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
}

@ -47,7 +47,6 @@ class CategoryPutResolver : DefaultPutResolver<Category>() {
val orderString = obj.mangaOrder.joinToString("/")
put(COL_MANGA_ORDER, orderString)
}
}
}

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

@ -1,6 +1,5 @@
package eu.kanade.tachiyomi.data.database.mappers
import android.content.ContentValues
import android.database.Cursor
import com.pushtorefresh.storio.sqlite.SQLiteTypeMapping

@ -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)
}
}

@ -111,5 +111,4 @@ interface Category : Serializable {
isLast = true
}
}
}

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

@ -39,5 +39,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
}

@ -3,9 +3,9 @@ package eu.kanade.tachiyomi.data.database.models
import eu.kanade.tachiyomi.source.SourceManager
import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.ui.reader.ReaderActivity
import java.util.Locale
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import java.util.Locale
interface Manga : SManga {
@ -168,5 +168,4 @@ interface Manga : SManga {
this.source = source
}
}
}

@ -3,8 +3,8 @@ package eu.kanade.tachiyomi.data.database.models
import eu.kanade.tachiyomi.data.download.DownloadManager
import eu.kanade.tachiyomi.data.download.DownloadProvider
import eu.kanade.tachiyomi.source.model.SManga
import uy.kohesive.injekt.injectLazy
import kotlin.collections.set
import uy.kohesive.injekt.injectLazy
open class MangaImpl : Manga {
@ -47,7 +47,7 @@ open class MangaImpl : Manga {
title = if (currentTitle() != originalTitle()) {
val customTitle = currentTitle()
val trueTitle = other.title
"${customTitle}${SManga.splitter}${trueTitle}"
"${customTitle}${SManga.splitter}$trueTitle"
} else other.title
val db: DownloadManager by injectLazy()
val provider = DownloadProvider(db.context)
@ -63,7 +63,6 @@ open class MangaImpl : Manga {
val manga = other as Manga
return url == manga.url
}
override fun hashCode(): Int {
@ -79,5 +78,4 @@ open class MangaImpl : Manga {
fun getLastCoverFetch(id: Long) = lastCoverFetch[id] ?: 0
}
}

@ -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()
}

@ -11,7 +11,7 @@ import eu.kanade.tachiyomi.data.database.resolvers.ChapterProgressPutResolver
import eu.kanade.tachiyomi.data.database.resolvers.ChapterSourceOrderPutResolver
import eu.kanade.tachiyomi.data.database.resolvers.MangaChapterGetResolver
import eu.kanade.tachiyomi.data.database.tables.ChapterTable
import java.util.*
import java.util.Date
interface ChapterQueries : DbProvider {
@ -88,5 +88,4 @@ interface ChapterQueries : DbProvider {
.objects(chapters)
.withPutResolver(ChapterSourceOrderPutResolver())
.prepare()
}

@ -8,7 +8,7 @@ import eu.kanade.tachiyomi.data.database.models.MangaChapterHistory
import eu.kanade.tachiyomi.data.database.resolvers.HistoryLastReadPutResolver
import eu.kanade.tachiyomi.data.database.resolvers.MangaChapterHistoryGetResolver
import eu.kanade.tachiyomi.data.database.tables.HistoryTable
import java.util.*
import java.util.Date
interface HistoryQueries : DbProvider {

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

@ -145,5 +145,5 @@ interface MangaQueries : DbProvider {
.prepare()
fun getTotalChapterManga() = db.get().listOfObjects(Manga::class.java)
.withQuery(RawQuery.builder().query(getTotalChapterMangaQuery()).observesTables(MangaTable.TABLE).build()).prepare();
.withQuery(RawQuery.builder().query(getTotalChapterMangaQuery()).observesTables(MangaTable.TABLE).build()).prepare()
}

@ -83,7 +83,7 @@ fun getRecentMangasQuery(offset: Int = 0, search: String = "") = """
ON ${Chapter.TABLE}.${Chapter.COL_MANGA_ID} = max_last_read.${Chapter.COL_MANGA_ID}
WHERE ${History.TABLE}.${History.COL_LAST_READ} > ?
AND max_last_read.${History.COL_CHAPTER_ID} = ${History.TABLE}.${History.COL_CHAPTER_ID}
AND lower(${Manga.TABLE}.${Manga.COL_TITLE}) LIKE '%${search}%'
AND lower(${Manga.TABLE}.${Manga.COL_TITLE}) LIKE '%$search%'
ORDER BY max_last_read.${History.COL_LAST_READ} DESC
LIMIT 25 OFFSET $offset
"""
@ -109,7 +109,7 @@ fun getRecentMangasLimitQuery(limit: Int = 25, search: String = "") = """
ON ${Chapter.TABLE}.${Chapter.COL_MANGA_ID} = max_last_read.${Chapter.COL_MANGA_ID}
WHERE ${History.TABLE}.${History.COL_LAST_READ} > ?
AND max_last_read.${History.COL_CHAPTER_ID} = ${History.TABLE}.${History.COL_CHAPTER_ID}
AND lower(${Manga.TABLE}.${Manga.COL_TITLE}) LIKE '%${search}%'
AND lower(${Manga.TABLE}.${Manga.COL_TITLE}) LIKE '%$search%'
ORDER BY max_last_read.${History.COL_LAST_READ} DESC
LIMIT $limit
"""

@ -1,6 +1,5 @@
package eu.kanade.tachiyomi.data.database.queries
import com.pushtorefresh.storio.sqlite.queries.DeleteQuery
import com.pushtorefresh.storio.sqlite.queries.Query
import eu.kanade.tachiyomi.data.database.DbProvider

@ -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)
}
}

@ -31,6 +31,4 @@ class ChapterProgressPutResolver : PutResolver<Chapter>() {
put(ChapterTable.COL_LAST_PAGE_READ, chapter.last_page_read)
put(ChapterTable.COL_PAGES_LEFT, chapter.pages_left)
}
}

@ -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)
}
}

@ -6,7 +6,6 @@ import com.pushtorefresh.storio.sqlite.operations.put.PutResolver
import com.pushtorefresh.storio.sqlite.operations.put.PutResult
import com.pushtorefresh.storio.sqlite.queries.UpdateQuery
import eu.kanade.tachiyomi.data.database.inTransactionReturn
import eu.kanade.tachiyomi.data.database.models.LibraryManga
import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.data.database.tables.MangaTable
@ -29,5 +28,4 @@ class MangaHideTitlePutResolver : PutResolver<Manga>() {
fun mapToContentValues(manga: Manga) = ContentValues(1).apply {
put(MangaTable.COL_HIDE_TITLE, manga.hide_title)
}
}

@ -40,6 +40,4 @@ class MangaInfoPutResolver(val reset:Boolean = false): PutResolver<Manga>() {
put(MangaTable.COL_ARTIST, manga.originalArtist())
put(MangaTable.COL_DESCRIPTION, manga.originalDesc())
}
}

@ -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)
}
}

@ -23,7 +23,6 @@ object CategoryTable {
$COL_MANGA_ORDER TEXT NOT NULL
)"""
val addMangaOrder: String
get() = "ALTER TABLE $TABLE ADD COLUMN $COL_MANGA_ORDER TEXT"
}

@ -67,5 +67,4 @@ object ChapterTable {
val pagesLeftQuery: String
get() = "ALTER TABLE $TABLE ADD COLUMN $COL_PAGES_LEFT INTEGER DEFAULT 0"
}

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

@ -1,6 +1,5 @@
package eu.kanade.tachiyomi.data.database.tables
object SearchMetadataTable {
const val TABLE = "search_metadata"

@ -10,10 +10,10 @@ import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.data.preference.getOrDefault
import eu.kanade.tachiyomi.source.SourceManager
import eu.kanade.tachiyomi.util.storage.DiskUtil
import java.util.concurrent.TimeUnit
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import uy.kohesive.injekt.injectLazy
import java.util.concurrent.TimeUnit
/**
* Cache where we dump the downloads directory from the filesystem. This class is needed because
@ -143,8 +143,8 @@ class DownloadCache(
val trueMangaDirs = mangaDirs.mapNotNull { mangaDir ->
val manga = sourceMangas.firstOrNull()?.find { DiskUtil.buildValidFilename(
it.originalTitle()).toLowerCase() == mangaDir.key
.toLowerCase() && it.source == sourceValue.key } ?:
sourceMangas.lastOrNull()?.find { DiskUtil.buildValidFilename(
.toLowerCase() && it.source == sourceValue.key }
?: sourceMangas.lastOrNull()?.find { DiskUtil.buildValidFilename(
it.originalTitle()).toLowerCase() == mangaDir.key
.toLowerCase() && it.source == sourceValue.key }
val id = manga?.id ?: return@mapNotNull null
@ -169,8 +169,7 @@ class DownloadCache(
val files = mangaFiles[id]
if (files == null) {
mangaFiles[id] = mutableSetOf(chapterDirName)
}
else {
} else {
mangaFiles[id]?.add(chapterDirName)
}
}
@ -216,7 +215,6 @@ class DownloadCache(
sourceDir.files = list
}*/
/**
* Removes a manga that has been deleted from this cache.
*
@ -230,20 +228,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<Long, MutableSet<String>> = hashMapOf())
private class SourceDirectory(
val dir: UniFile,
var files: Map<Long, MutableSet<String>> = hashMapOf()
)
/**
* Class to store the files under a manga directory.
*/
private class MangaDirectory(val dir: UniFile,
var files: MutableSet<String> = hashSetOf())
private class MangaDirectory(
val dir: UniFile,
var files: MutableSet<String> = hashSetOf()
)
/**
* Returns a new map containing only the key entries of [transform] that are not null.
@ -267,5 +271,4 @@ class DownloadCache(
}
return destination
}
}

@ -223,8 +223,7 @@ class DownloadManager(val context: Context) {
downloader.queue.remove(chapters)
if (!wasPaused && downloader.queue.isNotEmpty()) {
downloader.start()
}
else if (downloader.queue.isEmpty() && DownloadService.isRunning(context)) {
} else if (downloader.queue.isEmpty() && DownloadService.isRunning(context)) {
DownloadService.stop(context)
}
queue.remove(chapters)

@ -6,7 +6,6 @@ import androidx.core.app.NotificationCompat
import androidx.core.content.ContextCompat
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.download.model.Download
import eu.kanade.tachiyomi.data.download.model.DownloadQueue
import eu.kanade.tachiyomi.data.notification.NotificationHandler
import eu.kanade.tachiyomi.data.notification.NotificationReceiver
import eu.kanade.tachiyomi.data.notification.Notifications
@ -93,8 +92,7 @@ internal class DownloadNotifier(private val context: Context) {
setContentText(
context.getString(R.string.chapter_downloading)
)
}
else {
} else {
setContentTitle(
context.getString(
R.string.chapter_downloading
@ -107,7 +105,6 @@ internal class DownloadNotifier(private val context: Context) {
}
// Displays the progress bar on notification
notification.show()
}
/**

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

@ -37,8 +37,7 @@ class DownloadProvider(private val context: Context) {
}
init {
preferences.downloadsDirectory().asObservable()
.skip(1)
preferences.downloadsDirectory().asObservable().skip(1)
.subscribe { downloadsDir = UniFile.fromUri(context, Uri.parse(it)) }
}
@ -50,8 +49,7 @@ class DownloadProvider(private val context: Context) {
*/
internal fun getMangaDir(manga: Manga, source: Source): UniFile {
try {
return downloadsDir
.createDirectory(getSourceDirName(source))
return downloadsDir.createDirectory(getSourceDirName(source))
.createDirectory(getMangaDirName(manga))
} catch (e: NullPointerException) {
throw Exception(context.getString(R.string.invalid_download_dir))
@ -136,8 +134,6 @@ class DownloadProvider(private val context: Context) {
val sourceDir = findSourceDir(source)
val mangaDir = sourceDir?.findFile(DiskUtil.buildValidFilename(from))
mangaDir?.renameTo(to)
// val downloadManager:DownloadManager by injectLazy()
// downloadManager.renameCache(from, to, sourceId)
}
/**
@ -147,7 +143,11 @@ class DownloadProvider(private val context: Context) {
* @param manga the manga of the chapter.
* @param source the source of the chapter.
*/
fun findUnmatchedChapterDirs(chapters: List<Chapter>, manga: Manga, source: Source): List<UniFile> {
fun findUnmatchedChapterDirs(
chapters: List<Chapter>,
manga: Manga,
source: Source
): List<UniFile> {
val mangaDir = findMangaDir(manga, source) ?: return emptyList()
return mangaDir.listFiles()!!.asList().filter {
(chapters.find { chp ->
@ -170,7 +170,6 @@ class DownloadProvider(private val context: Context) {
return chapters.mapNotNull { mangaDir.findFile("${getChapterDirName(it)}_tmp") }
}
/**
* Returns the download directory name for a source.
*
@ -213,5 +212,4 @@ class DownloadProvider(private val context: Context) {
DiskUtil.buildValidFilename(chapter.name)
)
}
}

@ -221,7 +221,6 @@ class DownloadService : Service() {
.setContentTitle(getString(R.string.download_notifier_downloader_title))
.build()
}
}
interface DownloadServiceListener {

@ -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)
}

@ -21,6 +21,7 @@ import eu.kanade.tachiyomi.util.storage.saveTo
import eu.kanade.tachiyomi.util.system.ImageUtil
import eu.kanade.tachiyomi.util.system.launchNow
import eu.kanade.tachiyomi.util.system.launchUI
import java.io.File
import kotlinx.coroutines.async
import okhttp3.Response
import rx.Observable
@ -28,7 +29,6 @@ import rx.android.schedulers.AndroidSchedulers
import rx.schedulers.Schedulers
import rx.subscriptions.CompositeSubscription
import timber.log.Timber
import java.io.File
/**
* This class is the one in charge of downloading chapters.
@ -129,8 +129,7 @@ class Downloader(
if (notifier.paused) {
if (queue.isEmpty()) {
notifier.dismiss()
}
else {
} else {
notifier.paused = false
notifier.onDownloadPaused()
}
@ -318,7 +317,6 @@ class Downloader(
notifier.onError(error.message, download.chapter.name)
download
}
}
/**
@ -448,8 +446,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") }
@ -497,5 +499,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>()
@ -89,8 +90,7 @@ class DownloadQueue(
} else if (download.status == Download.DOWNLOADED || download.status == Download.ERROR) {
setPagesSubject(download.pages, null)
downloadListeners.forEach { it.updateDownload(download) }
}
else {
} else {
downloadListeners.forEach { it.updateDownload(download) }
}
}
@ -111,7 +111,6 @@ class DownloadQueue(
.onBackpressureBuffer()
.filter { it == Page.READY }
.map { download }
} else if (download.status == Download.DOWNLOADED || download.status == Download.ERROR) {
setPagesSubject(download.pages, null)
downloadListeners.forEach { it.updateDownload(download) }
@ -140,5 +139,4 @@ class DownloadQueue(
interface DownloadListener {
fun updateDownload(download: Download)
}
}

@ -5,7 +5,11 @@ import android.util.Log
import com.bumptech.glide.Priority
import com.bumptech.glide.load.DataSource
import com.bumptech.glide.load.data.DataFetcher
import java.io.*
import java.io.File
import java.io.FileInputStream
import java.io.FileNotFoundException
import java.io.IOException
import java.io.InputStream
open class FileFetcher(private val file: File) : DataFetcher<InputStream> {

@ -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()
}
}

@ -3,18 +3,22 @@ package eu.kanade.tachiyomi.data.glide
import android.util.LruCache
import com.bumptech.glide.integration.okhttp3.OkHttpStreamFetcher
import com.bumptech.glide.load.Options
import com.bumptech.glide.load.model.*
import com.bumptech.glide.load.model.GlideUrl
import com.bumptech.glide.load.model.Headers
import com.bumptech.glide.load.model.LazyHeaders
import com.bumptech.glide.load.model.ModelLoader
import com.bumptech.glide.load.model.ModelLoaderFactory
import com.bumptech.glide.load.model.MultiModelLoaderFactory
import eu.kanade.tachiyomi.data.cache.CoverCache
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 +82,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 +150,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() {}
}
}

@ -13,9 +13,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

@ -5,9 +5,9 @@ import com.evernote.android.job.JobManager
import com.evernote.android.job.JobRequest
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.data.preference.getOrDefault
import java.util.concurrent.TimeUnit
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import java.util.concurrent.TimeUnit
class LibraryUpdateJob : Job() {

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

@ -38,6 +38,10 @@ import eu.kanade.tachiyomi.util.chapter.syncChaptersWithSource
import eu.kanade.tachiyomi.util.lang.chop
import eu.kanade.tachiyomi.util.system.notification
import eu.kanade.tachiyomi.util.system.notificationManager
import java.util.ArrayList
import java.util.Date
import java.util.concurrent.TimeUnit
import java.util.concurrent.atomic.AtomicInteger
import kotlinx.coroutines.CoroutineExceptionHandler
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
@ -50,10 +54,6 @@ import rx.schedulers.Schedulers
import timber.log.Timber
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import java.util.ArrayList
import java.util.Date
import java.util.concurrent.TimeUnit
import java.util.concurrent.atomic.AtomicInteger
/**
* This class will take care of updating the chapters of the manga from the library. It can be

@ -10,6 +10,7 @@ import android.content.Intent
import android.net.Uri
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.backup.BackupRestoreService
import eu.kanade.tachiyomi.data.database.DatabaseHelper
@ -27,12 +28,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
@ -113,7 +112,6 @@ class NotificationReceiver : BroadcastReceiver() {
type = "image/*"
}
// Close Navigation Shade
}
/**
@ -217,7 +215,6 @@ class NotificationReceiver : BroadcastReceiver() {
// Called to cancel restore
private const val ACTION_CANCEL_RESTORE = "$ID.$NAME.CANCEL_RESTORE"
// Called to open chapter
private const val ACTION_OPEN_CHAPTER = "$ID.$NAME.ACTION_OPEN_CHAPTER"
@ -322,8 +319,12 @@ class NotificationReceiver : BroadcastReceiver() {
* @param notificationId id of notification
* @return [PendingIntent]
*/
internal fun dismissNotification(context: Context, notificationId: Int, groupId: Int? =
null) {
internal fun dismissNotification(
context: Context,
notificationId: Int,
groupId: Int? =
null
) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
val groupKey = context.notificationManager.activeNotifications.find {
it.id == notificationId
@ -387,8 +388,12 @@ class NotificationReceiver : BroadcastReceiver() {
* @param manga manga of chapter
* @param chapter chapter that needs to be opened
*/
internal fun openChapterPendingActivity(context: Context, manga: Manga, chapter:
Chapter): PendingIntent {
internal fun openChapterPendingActivity(
context: Context,
manga: Manga,
chapter:
Chapter
): PendingIntent {
val newIntent = ReaderActivity.newIntent(context, manga, chapter)
return PendingIntent.getActivity(context, manga.id.hashCode(), newIntent, PendingIntent
.FLAG_UPDATE_CURRENT)
@ -440,15 +445,19 @@ class NotificationReceiver : BroadcastReceiver() {
return PendingIntent.getActivity(context, 0, toLaunch, 0)
}
/**
* Returns [PendingIntent] that marks a chapter as read and deletes it if preferred
*
* @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

@ -38,6 +38,7 @@ object Notifications {
const val CHANNEL_NEW_CHAPTERS = "new_chapters_channel"
const val ID_NEW_CHAPTERS = -301
const val GROUP_NEW_CHAPTERS = "eu.kanade.tachiyomi.NEW_CHAPTERS"
/**
* Notification channel and ids used by the library updater.
*/
@ -49,7 +50,6 @@ object Notifications {
const val ID_RESTORE_COMPLETE = -502
const val ID_RESTORE_ERROR = -503
/**
* Creates the notification channels introduced in Android Oreo.
*
@ -58,8 +58,7 @@ object Notifications {
fun createChannels(context: Context) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) return
val channels = listOf(
NotificationChannel(
val channels = listOf(NotificationChannel(
CHANNEL_COMMON,
context.getString(R.string.channel_common),
NotificationManager.IMPORTANCE_LOW
@ -83,11 +82,13 @@ object Notifications {
CHANNEL_NEW_CHAPTERS,
context.getString(R.string.channel_new_chapters),
NotificationManager.IMPORTANCE_DEFAULT
), NotificationChannel(CHANNEL_RESTORE, context.getString(R.string.channel_backup_restore),
NotificationManager.IMPORTANCE_LOW).apply {
), NotificationChannel(
CHANNEL_RESTORE,
context.getString(R.string.channel_backup_restore),
NotificationManager.IMPORTANCE_LOW
).apply {
setShowBadge(false)
}
)
})
context.notificationManager.createNotificationChannels(channels)
}
}

@ -155,11 +155,9 @@ object PreferenceKeys {
fun sourceSharedPref(sourceId: Long) = "source_$sourceId"
fun trackUsername(syncId: Int) = "pref_mangasync_username_$syncId"
fun trackPassword(syncId: Int) = "pref_mangasync_password_$syncId"
fun trackToken(syncId: Int) = "track_token_$syncId"
}

@ -8,13 +8,13 @@ import androidx.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.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
fun <T> Preference<T>.getOrDefault(): T = get() ?: defaultValue()!!

@ -2,10 +2,10 @@ package eu.kanade.tachiyomi.data.track
import android.content.Context
import eu.kanade.tachiyomi.data.track.anilist.Anilist
import eu.kanade.tachiyomi.data.track.bangumi.Bangumi
import eu.kanade.tachiyomi.data.track.kitsu.Kitsu
import eu.kanade.tachiyomi.data.track.myanimelist.MyAnimeList
import eu.kanade.tachiyomi.data.track.shikimori.Shikimori
import eu.kanade.tachiyomi.data.track.bangumi.Bangumi
class TrackManager(context: Context) {
@ -32,5 +32,4 @@ class TrackManager(context: Context) {
fun getService(id: Int) = services.find { it.id == id }
fun hasLoggedServices() = services.any { it.isLogged }
}

@ -3,8 +3,8 @@ package eu.kanade.tachiyomi.data.track
import androidx.annotation.CallSuper
import androidx.annotation.DrawableRes
import eu.kanade.tachiyomi.data.database.models.Track
import eu.kanade.tachiyomi.data.track.model.TrackSearch
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.data.track.model.TrackSearch
import eu.kanade.tachiyomi.network.NetworkHelper
import okhttp3.OkHttpClient
import uy.kohesive.injekt.injectLazy

@ -7,7 +7,6 @@ import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.database.models.Track
import eu.kanade.tachiyomi.data.preference.getOrDefault
import eu.kanade.tachiyomi.data.track.TrackService
import eu.kanade.tachiyomi.data.track.model.TrackSearch
import timber.log.Timber
import uy.kohesive.injekt.injectLazy
@ -144,7 +143,6 @@ class Anilist(private val context: Context, id: Int) : TrackService(id) {
track.copyPersonalFrom(remoteTrack)
track.total_chapters = remoteTrack.total_chapters
return track
}
override suspend fun login(username: String, password: String) = login(password)
@ -184,7 +182,6 @@ class Anilist(private val context: Context, id: Int) : TrackService(id) {
}
}
companion object {
const val READING = 1
const val COMPLETED = 2
@ -202,6 +199,4 @@ class Anilist(private val context: Context, id: Int) : TrackService(id) {
const val POINT_5 = "POINT_5"
const val POINT_3 = "POINT_3"
}
}

@ -12,6 +12,8 @@ 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.jsonType
import java.util.Calendar
import java.util.concurrent.TimeUnit
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import okhttp3.MediaType
@ -19,8 +21,6 @@ import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.RequestBody.Companion.toRequestBody
import okhttp3.Response
import java.util.Calendar
import java.util.concurrent.TimeUnit
class AnilistApi(val client: OkHttpClient, interceptor: AnilistInterceptor) {

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

@ -5,15 +5,16 @@ 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 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
}
@ -26,7 +27,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

@ -11,6 +11,7 @@ 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.await
import java.net.URLEncoder
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import okhttp3.CacheControl
@ -18,7 +19,6 @@ import okhttp3.FormBody
import okhttp3.OkHttpClient
import okhttp3.Request
import uy.kohesive.injekt.injectLazy
import java.net.URLEncoder
class BangumiApi(private val client: OkHttpClient, interceptor: BangumiInterceptor) {
@ -26,14 +26,10 @@ class BangumiApi(private val client: OkHttpClient, interceptor: BangumiIntercept
private val authClient = client.newBuilder().addInterceptor(interceptor).build()
suspend fun addLibManga(track: Track): Track {
val body = FormBody.Builder()
.add("rating", track.score.toInt().toString())
.add("status", track.toBangumiStatus())
.build()
val request = Request.Builder()
.url("$apiUrl/collection/${track.media_id}/update")
.post(body)
.build()
val body = FormBody.Builder().add("rating", track.score.toInt().toString())
.add("status", track.toBangumiStatus()).build()
val request =
Request.Builder().url("$apiUrl/collection/${track.media_id}/update").post(body).build()
val response = authClient.newCall(request).await()
return track
}
@ -41,21 +37,16 @@ class BangumiApi(private val client: OkHttpClient, interceptor: BangumiIntercept
suspend fun updateLibManga(track: Track): Track {
// chapter update
return withContext(Dispatchers.IO) {
val body = FormBody.Builder()
.add("watched_eps", track.last_chapter_read.toString())
.build()
val request = Request.Builder()
.url("$apiUrl/subject/${track.media_id}/update/watched_eps")
.post(body)
.build()
val body =
FormBody.Builder().add("watched_eps", track.last_chapter_read.toString()).build()
val request =
Request.Builder().url("$apiUrl/subject/${track.media_id}/update/watched_eps")
.post(body).build()
// read status update
val sbody = FormBody.Builder()
.add("status", track.toBangumiStatus())
.build()
val srequest = Request.Builder()
.url("$apiUrl/collection/${track.media_id}/update")
.post(sbody)
val sbody = FormBody.Builder().add("status", track.toBangumiStatus()).build()
val srequest =
Request.Builder().url("$apiUrl/collection/${track.media_id}/update").post(sbody)
.build()
authClient.newCall(srequest).execute()
authClient.newCall(request).execute()
@ -67,13 +58,8 @@ class BangumiApi(private val client: OkHttpClient, interceptor: BangumiIntercept
return withContext(Dispatchers.IO) {
val url = Uri.parse(
"$apiUrl/search/subject/${URLEncoder.encode(search, Charsets.UTF_8.name())}"
).buildUpon()
.appendQueryParameter("max_results", "20")
.build()
val request = Request.Builder()
.url(url.toString())
.get()
.build()
).buildUpon().appendQueryParameter("max_results", "20").build()
val request = Request.Builder().url(url.toString()).get().build()
val netResponse = authClient.newCall(request).await()
var responseBody = netResponse.body?.string().orEmpty()
@ -106,8 +92,8 @@ class BangumiApi(private val client: OkHttpClient, interceptor: BangumiIntercept
return Track.create(TrackManager.BANGUMI).apply {
title = mangas["name"].asString
media_id = mangas["id"].asInt
score = if (mangas["rating"] != null)
(if (mangas["rating"].isJsonObject) mangas["rating"].obj["score"].asFloat else 0f)
score =
if (mangas["rating"] != null) (if (mangas["rating"].isJsonObject) mangas["rating"].obj["score"].asFloat else 0f)
else 0f
status = Bangumi.DEFAULT_STATUS
tracking_url = mangas["url"].asString
@ -117,10 +103,7 @@ class BangumiApi(private val client: OkHttpClient, interceptor: BangumiIntercept
suspend fun findLibManga(track: Track): Track? {
return withContext(Dispatchers.IO) {
val urlMangas = "$apiUrl/subject/${track.media_id}"
val requestMangas = Request.Builder()
.url(urlMangas)
.get()
.build()
val requestMangas = Request.Builder().url(urlMangas).get().build()
val netResponse = authClient.newCall(requestMangas).execute()
val responseBody = netResponse.body?.string().orEmpty()
jsonToTrack(JsonParser.parseString(responseBody).obj)
@ -129,10 +112,8 @@ class BangumiApi(private val client: OkHttpClient, interceptor: BangumiIntercept
suspend fun statusLibManga(track: Track): Track? {
val urlUserRead = "$apiUrl/collection/${track.media_id}"
val requestUserRead = Request.Builder()
.url(urlUserRead)
.cacheControl(CacheControl.FORCE_NETWORK)
.get()
val requestUserRead =
Request.Builder().url(urlUserRead).cacheControl(CacheControl.FORCE_NETWORK).get()
.build()
// todo get user readed chapter here
@ -157,12 +138,8 @@ class BangumiApi(private val client: OkHttpClient, interceptor: BangumiIntercept
private fun accessTokenRequest(code: String) = POST(
oauthUrl,
body = FormBody.Builder()
.add("grant_type", "authorization_code")
.add("client_id", clientId)
.add("client_secret", clientSecret)
.add("code", code)
.add("redirect_uri", redirectUrl)
body = FormBody.Builder().add("grant_type", "authorization_code").add("client_id", clientId)
.add("client_secret", clientSecret).add("code", code).add("redirect_uri", redirectUrl)
.build()
)
@ -182,22 +159,15 @@ class BangumiApi(private val client: OkHttpClient, interceptor: BangumiIntercept
return "$baseMangaUrl/$remoteId"
}
fun authUrl() =
Uri.parse(loginUrl).buildUpon()
.appendQueryParameter("client_id", clientId)
fun authUrl() = Uri.parse(loginUrl).buildUpon().appendQueryParameter("client_id", clientId)
.appendQueryParameter("response_type", "code")
.appendQueryParameter("redirect_uri", redirectUrl)
.build()
.appendQueryParameter("redirect_uri", redirectUrl).build()
fun refreshTokenRequest(token: String) = POST(
oauthUrl,
body = FormBody.Builder()
.add("grant_type", "refresh_token")
.add("client_id", clientId)
.add("client_secret", clientSecret)
.add("refresh_token", token)
.add("redirect_uri", redirectUrl)
.build()
body = FormBody.Builder().add("grant_type", "refresh_token").add("client_id", clientId)
.add("client_secret", clientSecret).add("refresh_token", token)
.add("redirect_uri", redirectUrl).build()
)
}
}

@ -45,5 +45,3 @@ data class Avatar(
val medium: String? = "",
val small: String? = ""
)

@ -7,9 +7,9 @@ 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 timber.log.Timber
import uy.kohesive.injekt.injectLazy
import java.text.DecimalFormat
class Kitsu(private val context: Context, id: Int) : TrackService(id) {

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

@ -1,13 +1,19 @@
package eu.kanade.tachiyomi.data.track.kitsu
import androidx.annotation.CallSuper
import com.github.salomonbrys.kotson.*
import com.github.salomonbrys.kotson.byInt
import com.github.salomonbrys.kotson.byString
import com.github.salomonbrys.kotson.nullInt
import com.github.salomonbrys.kotson.nullObj
import com.github.salomonbrys.kotson.nullString
import com.github.salomonbrys.kotson.obj
import com.google.gson.JsonObject
import eu.kanade.tachiyomi.data.database.models.Track
import eu.kanade.tachiyomi.data.track.TrackManager
import eu.kanade.tachiyomi.data.track.model.TrackSearch
import java.text.SimpleDateFormat
import java.util.*
import java.util.Date
import java.util.Locale
class KitsuSearchManga(obj: JsonObject) {
val id by obj.byInt
@ -40,7 +46,6 @@ class KitsuSearchManga(obj: JsonObject) {
}
}
class KitsuLibManga(obj: JsonObject, manga: JsonObject) {
val id by manga.byInt
private val canonicalTitle by manga["attributes"].byString
@ -77,7 +82,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)
}

@ -58,7 +58,5 @@ class TrackSearch : Track {
fun create(serviceId: Int): TrackSearch = TrackSearch().apply {
sync_id = serviceId
}
}
}

@ -131,8 +131,7 @@ class MyAnimeList(private val context: Context, id: Int) : TrackService(id) {
var ckCount = 0
val url = BASE_URL.toHttpUrlOrNull()!!
for (ck in networkService.cookieManager.get(url)) {
if (ck.name == USER_SESSION_COOKIE || ck.name == LOGGED_IN_COOKIE)
ckCount++
if (ck.name == USER_SESSION_COOKIE || ck.name == LOGGED_IN_COOKIE) ckCount++
}
return ckCount == 2

@ -36,12 +36,10 @@ class MyAnimeListApi(private val client: OkHttpClient, interceptor: MyAnimeListI
val realQuery = query.take(100)
val response = client.newCall(GET(searchUrl(realQuery))).await()
val matches = Jsoup.parse(response.consumeBody())
.select("div.js-categories-seasonal.js-block-list.list")
.select("table").select("tbody")
.select("tr").drop(1)
.select("div.js-categories-seasonal.js-block-list.list").select("table")
.select("tbody").select("tr").drop(1)
matches.filter { row -> row.select(TD)[2].text() != "Novel" }
.map { row ->
matches.filter { row -> row.select(TD)[2].text() != "Novel" }.map { row ->
TrackSearch.create(TrackManager.MYANIMELIST).apply {
title = row.searchTitle()
media_id = row.searchMediaId()
@ -53,8 +51,7 @@ class MyAnimeListApi(private val client: OkHttpClient, interceptor: MyAnimeListI
publishing_type = row.searchPublishingType()
start_date = row.searchStartDate()
}
}
.toList()
}.toList()
}
}
}
@ -117,9 +114,7 @@ class MyAnimeListApi(private val client: OkHttpClient, interceptor: MyAnimeListI
private suspend fun getSessionInfo(): String {
val response = client.newCall(GET(loginUrl())).execute()
return Jsoup.parse(response.consumeBody())
.select("meta[name=csrf_token]")
.attr("content")
return Jsoup.parse(response.consumeBody()).select("meta[name=csrf_token]").attr("content")
}
private suspend fun login(username: String, password: String, csrf: String) {
@ -147,8 +142,7 @@ class MyAnimeListApi(private val client: OkHttpClient, interceptor: MyAnimeListI
total_chapters = it.selectInt("manga_chapters")
tracking_url = mangaUrl(media_id)
}
}
.toList()
}.toList()
}
private suspend fun getListUrl(): String {
@ -156,9 +150,7 @@ class MyAnimeListApi(private val client: OkHttpClient, interceptor: MyAnimeListI
val response =
authClient.newCall(POST(url = exportListUrl(), body = exportPostBody())).execute()
baseUrl + Jsoup.parse(response.consumeBody())
.select("div.goodresult")
.select("a")
baseUrl + Jsoup.parse(response.consumeBody()).select("div.goodresult").select("a")
.attr("href")
}
}
@ -179,66 +171,43 @@ class MyAnimeListApi(private val client: OkHttpClient, interceptor: MyAnimeListI
private fun mangaUrl(remoteId: Int) = baseMangaUrl + remoteId
private fun loginUrl() = Uri.parse(baseUrl).buildUpon()
.appendPath("login.php")
.toString()
private fun loginUrl() = Uri.parse(baseUrl).buildUpon().appendPath("login.php").toString()
private fun searchUrl(query: String): String {
val col = "c[]"
return Uri.parse(baseUrl).buildUpon()
.appendPath("manga.php")
.appendQueryParameter("q", query)
.appendQueryParameter(col, "a")
.appendQueryParameter(col, "b")
.appendQueryParameter(col, "c")
.appendQueryParameter(col, "d")
.appendQueryParameter(col, "e")
.appendQueryParameter(col, "g")
.toString()
}
private fun exportListUrl() = Uri.parse(baseUrl).buildUpon()
.appendPath("panel.php")
.appendQueryParameter("go", "export")
.toString()
private fun updateUrl() = Uri.parse(baseModifyListUrl).buildUpon()
.appendPath("edit.json")
.toString()
private fun addUrl() = Uri.parse(baseModifyListUrl).buildUpon()
.appendPath("add.json")
.toString()
private fun listEntryUrl(mediaId: Int) = Uri.parse(baseModifyListUrl).buildUpon()
.appendPath(mediaId.toString())
.appendPath("edit")
.toString()
return Uri.parse(baseUrl).buildUpon().appendPath("manga.php")
.appendQueryParameter("q", query).appendQueryParameter(col, "a")
.appendQueryParameter(col, "b").appendQueryParameter(col, "c")
.appendQueryParameter(col, "d").appendQueryParameter(col, "e")
.appendQueryParameter(col, "g").toString()
}
private fun exportListUrl() = Uri.parse(baseUrl).buildUpon().appendPath("panel.php")
.appendQueryParameter("go", "export").toString()
private fun updateUrl() =
Uri.parse(baseModifyListUrl).buildUpon().appendPath("edit.json").toString()
private fun addUrl() =
Uri.parse(baseModifyListUrl).buildUpon().appendPath("add.json").toString()
private fun listEntryUrl(mediaId: Int) =
Uri.parse(baseModifyListUrl).buildUpon().appendPath(mediaId.toString())
.appendPath("edit").toString()
private fun loginPostBody(username: String, password: String, csrf: String): RequestBody {
return FormBody.Builder()
.add("user_name", username)
.add("password", password)
.add("cookie", "1")
.add("sublogin", "Login")
.add("submit", "1")
.add(CSRF, csrf)
return FormBody.Builder().add("user_name", username).add("password", password)
.add("cookie", "1").add("sublogin", "Login").add("submit", "1").add(CSRF, csrf)
.build()
}
private fun exportPostBody(): RequestBody {
return FormBody.Builder()
.add("type", "2")
.add("subexport", "Export My List")
.build()
return FormBody.Builder().add("type", "2").add("subexport", "Export My List").build()
}
private fun mangaPostPayload(track: Track): RequestBody {
val body = JSONObject()
.put("manga_id", track.media_id)
.put("status", track.status)
.put("score", track.score)
.put("num_read_chapters", track.last_chapter_read)
val body = JSONObject().put("manga_id", track.media_id).put("status", track.status)
.put("score", track.score).put("num_read_chapters", track.last_chapter_read)
return body.toString()
.toRequestBody("application/json; charset=utf-8".toMediaTypeOrNull())
@ -249,19 +218,13 @@ class MyAnimeListApi(private val client: OkHttpClient, interceptor: MyAnimeListI
private fun Element.searchTotalChapters() =
if (select(TD)[4].text() == "-") 0 else select(TD)[4].text().toInt()
private fun Element.searchCoverUrl() = select("img")
.attr("data-src")
.split("\\?")[0]
.replace("/r/50x70/", "/")
private fun Element.searchCoverUrl() =
select("img").attr("data-src").split("\\?")[0].replace("/r/50x70/", "/")
private fun Element.searchMediaId() = select("div.picSurround")
.select("a").attr("id")
.replace("sarea", "")
.toInt()
private fun Element.searchMediaId() =
select("div.picSurround").select("a").attr("id").replace("sarea", "").toInt()
private fun Element.searchSummary() = select("div.pt4")
.first()
.ownText()!!
private fun Element.searchSummary() = select("div.pt4").first().ownText()!!
private fun Element.searchPublishingStatus() =
if (select(TD).last().text() == "-") "Publishing" else "Finished"

@ -22,7 +22,6 @@ class MyAnimeListInterceptor(private val myanimelist: MyAnimeList) : Interceptor
}
val request = chain.request()
return chain.proceed(updateRequest(request))
}
private fun updateRequest(request: Request): Request {

@ -6,7 +6,6 @@ import com.google.gson.Gson
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 timber.log.Timber
import uy.kohesive.injekt.injectLazy

@ -13,7 +13,6 @@ import eu.kanade.tachiyomi.data.track.TrackManager
import eu.kanade.tachiyomi.data.track.model.TrackSearch
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.network.POST
import eu.kanade.tachiyomi.network.asObservableSuccess
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import okhttp3.FormBody
@ -44,10 +43,7 @@ class ShikimoriApi(private val client: OkHttpClient, interceptor: ShikimoriInter
)
)
val body = payload.toString().toRequestBody(jsonime)
val request = Request.Builder()
.url("$apiUrl/v2/user_rates")
.post(body)
.build()
val request = Request.Builder().url("$apiUrl/v2/user_rates").post(body).build()
authClient.newCall(request).execute()
track
}
@ -55,15 +51,11 @@ class ShikimoriApi(private val client: OkHttpClient, interceptor: ShikimoriInter
suspend fun search(search: String): List<TrackSearch> {
return withContext(Dispatchers.IO) {
val url = Uri.parse("$apiUrl/mangas").buildUpon()
.appendQueryParameter("order", "popularity")
.appendQueryParameter("search", search)
.appendQueryParameter("limit", "20")
.build()
val request = Request.Builder()
.url(url.toString())
.get()
val url =
Uri.parse("$apiUrl/mangas").buildUpon().appendQueryParameter("order", "popularity")
.appendQueryParameter("search", search).appendQueryParameter("limit", "20")
.build()
val request = Request.Builder().url(url.toString()).get().build()
val netResponse = authClient.newCall(request).execute()
val responseBody = netResponse.body?.string().orEmpty()
@ -73,7 +65,6 @@ class ShikimoriApi(private val client: OkHttpClient, interceptor: ShikimoriInter
val response = JsonParser.parseString(responseBody).array
response.map { jsonToSearch(it.obj) }
}
}
@ -108,20 +99,13 @@ class ShikimoriApi(private val client: OkHttpClient, interceptor: ShikimoriInter
val url = Uri.parse("$apiUrl/v2/user_rates").buildUpon()
.appendQueryParameter("user_id", user_id)
.appendQueryParameter("target_id", track.media_id.toString())
.appendQueryParameter("target_type", "Manga")
.build()
val request = Request.Builder()
.url(url.toString())
.get()
.build()
.appendQueryParameter("target_type", "Manga").build()
val request = Request.Builder().url(url.toString()).get().build()
val urlMangas = Uri.parse("$apiUrl/mangas").buildUpon()
.appendPath(track.media_id.toString())
.build()
val requestMangas = Request.Builder()
.url(urlMangas.toString())
.get()
val urlMangas =
Uri.parse("$apiUrl/mangas").buildUpon().appendPath(track.media_id.toString())
.build()
val requestMangas = Request.Builder().url(urlMangas.toString()).get().build()
val requestMangasResponse = authClient.newCall(requestMangas).execute()
val requestMangasBody = requestMangasResponse.body?.string().orEmpty()
@ -162,12 +146,8 @@ class ShikimoriApi(private val client: OkHttpClient, interceptor: ShikimoriInter
private fun accessTokenRequest(code: String) = POST(
oauthUrl,
body = FormBody.Builder()
.add("grant_type", "authorization_code")
.add("client_id", clientId)
.add("client_secret", clientSecret)
.add("code", code)
.add("redirect_uri", redirectUrl)
body = FormBody.Builder().add("grant_type", "authorization_code").add("client_id", clientId)
.add("client_secret", clientSecret).add("code", code).add("redirect_uri", redirectUrl)
.build()
)
@ -189,21 +169,14 @@ class ShikimoriApi(private val client: OkHttpClient, interceptor: ShikimoriInter
return "$baseMangaUrl/$remoteId"
}
fun authUrl() =
Uri.parse(loginUrl).buildUpon()
.appendQueryParameter("client_id", clientId)
fun authUrl() = Uri.parse(loginUrl).buildUpon().appendQueryParameter("client_id", clientId)
.appendQueryParameter("redirect_uri", redirectUrl)
.appendQueryParameter("response_type", "code")
.build()
.appendQueryParameter("response_type", "code").build()
fun refreshTokenRequest(token: String) = POST(
oauthUrl,
body = FormBody.Builder()
.add("grant_type", "refresh_token")
.add("client_id", clientId)
.add("client_secret", clientSecret)
.add("refresh_token", token)
.build()
body = FormBody.Builder().add("grant_type", "refresh_token").add("client_id", clientId)
.add("client_secret", clientSecret).add("refresh_token", token).build()
)
}
}

@ -28,9 +28,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)
}

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

@ -12,5 +12,4 @@ abstract class UpdateChecker {
* Returns suspended result 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()
}

@ -10,17 +10,16 @@ import com.evernote.android.job.JobRequest
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.notification.Notifications
import eu.kanade.tachiyomi.util.system.notificationManager
import java.util.concurrent.TimeUnit
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import java.util.concurrent.TimeUnit
class UpdaterJob : Job() {
override fun onRunJob(params: Params): Result {
GlobalScope.launch(Dispatchers.IO) {
val result = try { UpdateChecker.getUpdateChecker().checkForUpdate() }
catch (e: Exception) { return@launch }
val result = try { UpdateChecker.getUpdateChecker().checkForUpdate() } catch (e: Exception) { return@launch }
if (result is UpdateResult.NewUpdate<*>) {
val url = result.release.downloadLink
@ -73,5 +72,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) {
}
}
}

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

Loading…
Cancel
Save