mirror of
https://github.com/tachiyomiorg/tachiyomi.git
synced 2024-11-10 19:55:06 +01:00
Turned on kt lint
This commit is contained in:
parent
cc28ff7a77
commit
da786bbc40
@ -8,7 +8,7 @@ plugins {
|
|||||||
kotlin("android")
|
kotlin("android")
|
||||||
kotlin("android.extensions")
|
kotlin("android.extensions")
|
||||||
kotlin("kapt")
|
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.github.zellius.shortcut-helper")
|
||||||
id("com.google.gms.google-services") apply false
|
id("com.google.gms.google-services") apply false
|
||||||
}
|
}
|
||||||
@ -114,9 +114,9 @@ dependencies {
|
|||||||
|
|
||||||
implementation("com.google.firebase:firebase-core:17.2.3")
|
implementation("com.google.firebase:firebase-core:17.2.3")
|
||||||
|
|
||||||
val lifecycle_version = "2.1.0"
|
val lifecycleVersion = "2.1.0"
|
||||||
implementation("androidx.lifecycle:lifecycle-extensions:$lifecycle_version")
|
implementation("androidx.lifecycle:lifecycle-extensions:$lifecycleVersion")
|
||||||
implementation("androidx.lifecycle:lifecycle-common-java8:$lifecycle_version")
|
implementation("androidx.lifecycle:lifecycle-common-java8:$lifecycleVersion")
|
||||||
|
|
||||||
// ReactiveX
|
// ReactiveX
|
||||||
implementation("io.reactivex:rxandroid:1.2.1")
|
implementation("io.reactivex:rxandroid:1.2.1")
|
||||||
@ -126,15 +126,15 @@ dependencies {
|
|||||||
implementation("com.github.pwittchen:reactivenetwork:0.13.0")
|
implementation("com.github.pwittchen:reactivenetwork:0.13.0")
|
||||||
|
|
||||||
// Network client
|
// Network client
|
||||||
val okhttp_version = "4.3.1"
|
val okhttpVersion = "4.3.1"
|
||||||
implementation("com.squareup.okhttp3:okhttp:$okhttp_version")
|
implementation("com.squareup.okhttp3:okhttp:$okhttpVersion")
|
||||||
implementation("com.squareup.okhttp3:logging-interceptor:$okhttp_version")
|
implementation("com.squareup.okhttp3:logging-interceptor:$okhttpVersion")
|
||||||
implementation("com.squareup.okio:okio:2.4.3")
|
implementation("com.squareup.okio:okio:2.4.3")
|
||||||
|
|
||||||
// REST
|
// REST
|
||||||
val retrofit_version = "2.7.1"
|
val retrofitVersion = "2.7.1"
|
||||||
implementation("com.squareup.retrofit2:retrofit:$retrofit_version")
|
implementation("com.squareup.retrofit2:retrofit:$retrofitVersion")
|
||||||
implementation("com.squareup.retrofit2:converter-gson:$retrofit_version")
|
implementation("com.squareup.retrofit2:converter-gson:$retrofitVersion")
|
||||||
|
|
||||||
// JSON
|
// JSON
|
||||||
implementation("com.google.code.gson:gson:2.8.6")
|
implementation("com.google.code.gson:gson:2.8.6")
|
||||||
@ -164,18 +164,18 @@ dependencies {
|
|||||||
implementation("io.requery:sqlite-android:3.31.0")
|
implementation("io.requery:sqlite-android:3.31.0")
|
||||||
|
|
||||||
// Model View Presenter
|
// Model View Presenter
|
||||||
val nucleus_version = "3.0.0"
|
val nucleusVersion = "3.0.0"
|
||||||
implementation("info.android15.nucleus:nucleus:$nucleus_version")
|
implementation("info.android15.nucleus:nucleus:$nucleusVersion")
|
||||||
implementation("info.android15.nucleus:nucleus-support-v7:$nucleus_version")
|
implementation("info.android15.nucleus:nucleus-support-v7:$nucleusVersion")
|
||||||
|
|
||||||
// Dependency injection
|
// Dependency injection
|
||||||
implementation("com.github.inorichi.injekt:injekt-core:65b0440")
|
implementation("com.github.inorichi.injekt:injekt-core:65b0440")
|
||||||
|
|
||||||
// Image library
|
// Image library
|
||||||
val glide_version = "4.11.0"
|
val glideVersion = "4.11.0"
|
||||||
implementation("com.github.bumptech.glide:glide:$glide_version")
|
implementation("com.github.bumptech.glide:glide:$glideVersion")
|
||||||
implementation("com.github.bumptech.glide:okhttp3-integration:$glide_version")
|
implementation("com.github.bumptech.glide:okhttp3-integration:$glideVersion")
|
||||||
kapt("com.github.bumptech.glide:compiler:$glide_version")
|
kapt("com.github.bumptech.glide:compiler:$glideVersion")
|
||||||
|
|
||||||
// Transformations
|
// Transformations
|
||||||
implementation("jp.wasabeef:glide-transformations:4.1.0")
|
implementation("jp.wasabeef:glide-transformations:4.1.0")
|
||||||
@ -208,28 +208,28 @@ dependencies {
|
|||||||
implementation("com.github.inorichi:conductor-support-preference:a32c357")
|
implementation("com.github.inorichi:conductor-support-preference:a32c357")
|
||||||
|
|
||||||
// RxBindings
|
// RxBindings
|
||||||
val rxbindings_version = "1.0.1"
|
val rxbindingsVersion = "1.0.1"
|
||||||
implementation("com.jakewharton.rxbinding:rxbinding-kotlin:$rxbindings_version")
|
implementation("com.jakewharton.rxbinding:rxbinding-kotlin:$rxbindingsVersion")
|
||||||
implementation("com.jakewharton.rxbinding:rxbinding-appcompat-v7-kotlin:$rxbindings_version")
|
implementation("com.jakewharton.rxbinding:rxbinding-appcompat-v7-kotlin:$rxbindingsVersion")
|
||||||
implementation("com.jakewharton.rxbinding:rxbinding-support-v4-kotlin:$rxbindings_version")
|
implementation("com.jakewharton.rxbinding:rxbinding-support-v4-kotlin:$rxbindingsVersion")
|
||||||
implementation("com.jakewharton.rxbinding:rxbinding-recyclerview-v7-kotlin:$rxbindings_version")
|
implementation("com.jakewharton.rxbinding:rxbinding-recyclerview-v7-kotlin:$rxbindingsVersion")
|
||||||
|
|
||||||
// Tests
|
// Tests
|
||||||
testImplementation("junit:junit:4.13")
|
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")
|
testImplementation("org.mockito:mockito-core:1.10.19")
|
||||||
|
|
||||||
val robolectric_version = "3.1.4"
|
val robolectricVersion = "3.1.4"
|
||||||
testImplementation("org.robolectric:robolectric:$robolectric_version")
|
testImplementation("org.robolectric:robolectric:$robolectricVersion")
|
||||||
testImplementation("org.robolectric:shadows-multidex:$robolectric_version")
|
testImplementation("org.robolectric:shadows-multidex:$robolectricVersion")
|
||||||
testImplementation("org.robolectric:shadows-play-services:$robolectric_version")
|
testImplementation("org.robolectric:shadows-play-services:$robolectricVersion")
|
||||||
|
|
||||||
|
|
||||||
implementation(kotlin("stdlib", org.jetbrains.kotlin.config.KotlinCompilerVersion.VERSION))
|
implementation(kotlin("stdlib", org.jetbrains.kotlin.config.KotlinCompilerVersion.VERSION))
|
||||||
|
|
||||||
val coroutines_version = "1.3.3"
|
val coroutinesVersion = "1.3.3"
|
||||||
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines_version")
|
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutinesVersion")
|
||||||
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines_version")
|
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutinesVersion")
|
||||||
|
|
||||||
//Crash reports
|
//Crash reports
|
||||||
val acraVersion = "4.9.2"
|
val acraVersion = "4.9.2"
|
||||||
@ -239,13 +239,13 @@ dependencies {
|
|||||||
implementation("info.debatty:java-string-similarity:1.2.1")
|
implementation("info.debatty:java-string-similarity:1.2.1")
|
||||||
}
|
}
|
||||||
|
|
||||||
/*tasks.preBuild {
|
tasks.preBuild {
|
||||||
dependsOn(tasks.lintKotlin)
|
dependsOn(tasks.lintKotlin)
|
||||||
}
|
}
|
||||||
tasks.lintKotlin {
|
tasks.lintKotlin {
|
||||||
dependsOn(tasks.formatKotlin)
|
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"))
|
apply(mapOf("plugin" to "com.google.gms.google-services"))
|
||||||
}
|
}
|
@ -52,7 +52,7 @@ open class App : Application(), LifecycleObserver {
|
|||||||
|
|
||||||
@OnLifecycleEvent(Lifecycle.Event.ON_STOP)
|
@OnLifecycleEvent(Lifecycle.Event.ON_STOP)
|
||||||
fun onAppBackgrounded() {
|
fun onAppBackgrounded() {
|
||||||
//App in background
|
// App in background
|
||||||
val preferences: PreferencesHelper by injectLazy()
|
val preferences: PreferencesHelper by injectLazy()
|
||||||
if (preferences.lockAfter().getOrDefault() >= 0) {
|
if (preferences.lockAfter().getOrDefault() >= 0) {
|
||||||
SecureActivityDelegate.locked = true
|
SecureActivityDelegate.locked = true
|
||||||
@ -92,5 +92,4 @@ open class App : Application(), LifecycleObserver {
|
|||||||
protected open fun setupNotificationChannels() {
|
protected open fun setupNotificationChannels() {
|
||||||
Notifications.createChannels(this)
|
Notifications.createChannels(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,11 @@ import eu.kanade.tachiyomi.network.NetworkHelper
|
|||||||
import eu.kanade.tachiyomi.source.SourceManager
|
import eu.kanade.tachiyomi.source.SourceManager
|
||||||
import kotlinx.coroutines.GlobalScope
|
import kotlinx.coroutines.GlobalScope
|
||||||
import kotlinx.coroutines.launch
|
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 {
|
class AppModule(val app: Application) : InjektModule {
|
||||||
|
|
||||||
@ -52,7 +56,5 @@ class AppModule(val app: Application) : InjektModule {
|
|||||||
GlobalScope.launch { get<DatabaseHelper>() }
|
GlobalScope.launch { get<DatabaseHelper>() }
|
||||||
|
|
||||||
GlobalScope.launch { get<DownloadManager>() }
|
GlobalScope.launch { get<DownloadManager>() }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -67,5 +67,4 @@ object Migrations {
|
|||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package eu.kanade.tachiyomi.data.backup
|
package eu.kanade.tachiyomi.data.backup
|
||||||
import eu.kanade.tachiyomi.BuildConfig.APPLICATION_ID as ID
|
import eu.kanade.tachiyomi.BuildConfig.APPLICATION_ID as ID
|
||||||
|
|
||||||
|
|
||||||
object BackupConst {
|
object BackupConst {
|
||||||
|
|
||||||
const val INTENT_FILTER = "SettingsBackupFragment"
|
const val INTENT_FILTER = "SettingsBackupFragment"
|
||||||
@ -18,5 +17,5 @@ object BackupConst {
|
|||||||
const val EXTRA_TIME = "$ID.$INTENT_FILTER.EXTRA_TIME"
|
const val EXTRA_TIME = "$ID.$INTENT_FILTER.EXTRA_TIME"
|
||||||
const val EXTRA_ERROR_FILE_PATH = "$ID.$INTENT_FILTER.EXTRA_ERROR_FILE_PATH"
|
const val EXTRA_ERROR_FILE_PATH = "$ID.$INTENT_FILTER.EXTRA_ERROR_FILE_PATH"
|
||||||
const val EXTRA_ERROR_FILE = "$ID.$INTENT_FILTER.EXTRA_ERROR_FILE"
|
const val EXTRA_ERROR_FILE = "$ID.$INTENT_FILTER.EXTRA_ERROR_FILE"
|
||||||
const val EXTRA_MINI_ERROR= "$ID.$INTENT_FILTER.EXTRA_MINI_ERROR"
|
const val EXTRA_MINI_ERROR = "$ID.$INTENT_FILTER.EXTRA_MINI_ERROR"
|
||||||
}
|
}
|
||||||
|
@ -5,8 +5,8 @@ import android.content.Context
|
|||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import com.google.gson.JsonArray
|
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.BuildConfig.APPLICATION_ID as ID
|
||||||
|
import eu.kanade.tachiyomi.data.database.models.Manga
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* [IntentService] used to backup [Manga] information to [JsonArray]
|
* [IntentService] used to backup [Manga] information to [JsonArray]
|
||||||
@ -45,7 +45,6 @@ class BackupCreateService : IntentService(NAME) {
|
|||||||
}
|
}
|
||||||
context.startService(intent)
|
context.startService(intent)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private val backupManager by lazy { BackupManager(this) }
|
private val backupManager by lazy { BackupManager(this) }
|
||||||
@ -60,5 +59,4 @@ class BackupCreateService : IntentService(NAME) {
|
|||||||
if (uri != null)
|
if (uri != null)
|
||||||
backupManager.createBackup(uri, flags, false)
|
backupManager.createBackup(uri, flags, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -6,9 +6,9 @@ import com.evernote.android.job.JobManager
|
|||||||
import com.evernote.android.job.JobRequest
|
import com.evernote.android.job.JobRequest
|
||||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||||
import eu.kanade.tachiyomi.data.preference.getOrDefault
|
import eu.kanade.tachiyomi.data.preference.getOrDefault
|
||||||
|
import java.util.concurrent.TimeUnit
|
||||||
import uy.kohesive.injekt.Injekt
|
import uy.kohesive.injekt.Injekt
|
||||||
import uy.kohesive.injekt.api.get
|
import uy.kohesive.injekt.api.get
|
||||||
import java.util.concurrent.TimeUnit
|
|
||||||
|
|
||||||
class BackupCreatorJob : Job() {
|
class BackupCreatorJob : Job() {
|
||||||
|
|
||||||
|
@ -3,8 +3,15 @@ package eu.kanade.tachiyomi.data.backup
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import com.github.salomonbrys.kotson.*
|
import com.github.salomonbrys.kotson.fromJson
|
||||||
import com.google.gson.*
|
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 com.hippo.unifile.UniFile
|
||||||
import eu.kanade.tachiyomi.data.backup.BackupCreateService.Companion.BACKUP_CATEGORY
|
import eu.kanade.tachiyomi.data.backup.BackupCreateService.Companion.BACKUP_CATEGORY
|
||||||
import eu.kanade.tachiyomi.data.backup.BackupCreateService.Companion.BACKUP_CATEGORY_MASK
|
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.MANGA
|
||||||
import eu.kanade.tachiyomi.data.backup.models.Backup.TRACK
|
import eu.kanade.tachiyomi.data.backup.models.Backup.TRACK
|
||||||
import eu.kanade.tachiyomi.data.backup.models.DHistory
|
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.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.PreferencesHelper
|
||||||
import eu.kanade.tachiyomi.data.preference.getOrDefault
|
import eu.kanade.tachiyomi.data.preference.getOrDefault
|
||||||
import eu.kanade.tachiyomi.data.track.TrackManager
|
import eu.kanade.tachiyomi.data.track.TrackManager
|
||||||
import eu.kanade.tachiyomi.source.Source
|
import eu.kanade.tachiyomi.source.Source
|
||||||
import eu.kanade.tachiyomi.source.SourceManager
|
import eu.kanade.tachiyomi.source.SourceManager
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.withContext
|
|
||||||
import eu.kanade.tachiyomi.util.chapter.syncChaptersWithSource
|
import eu.kanade.tachiyomi.util.chapter.syncChaptersWithSource
|
||||||
import eu.kanade.tachiyomi.util.system.sendLocalBroadcast
|
import eu.kanade.tachiyomi.util.system.sendLocalBroadcast
|
||||||
|
import kotlin.math.max
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
import rx.Observable
|
import rx.Observable
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import uy.kohesive.injekt.injectLazy
|
import uy.kohesive.injekt.injectLazy
|
||||||
import kotlin.math.max
|
|
||||||
|
|
||||||
class BackupManager(val context: Context, version: Int = CURRENT_VERSION) {
|
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.storage.getUriCompat
|
||||||
import eu.kanade.tachiyomi.util.system.isServiceRunning
|
import eu.kanade.tachiyomi.util.system.isServiceRunning
|
||||||
import eu.kanade.tachiyomi.util.system.notificationManager
|
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.CoroutineExceptionHandler
|
||||||
import kotlinx.coroutines.GlobalScope
|
import kotlinx.coroutines.GlobalScope
|
||||||
import kotlinx.coroutines.Job
|
import kotlinx.coroutines.Job
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import uy.kohesive.injekt.injectLazy
|
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
|
* Restores backup from json file
|
||||||
*/
|
*/
|
||||||
class BackupRestoreService : Service() {
|
class BackupRestoreService : Service() {
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wake lock that will be held until the service is destroyed.
|
* Wake lock that will be held until the service is destroyed.
|
||||||
*/
|
*/
|
||||||
@ -87,7 +86,6 @@ class BackupRestoreService : Service() {
|
|||||||
*/
|
*/
|
||||||
private val trackingErrors = mutableListOf<String>()
|
private val trackingErrors = mutableListOf<String>()
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* List containing missing sources
|
* List containing missing sources
|
||||||
*/
|
*/
|
||||||
@ -113,7 +111,6 @@ class BackupRestoreService : Service() {
|
|||||||
*/
|
*/
|
||||||
internal val trackManager: TrackManager by injectLazy()
|
internal val trackManager: TrackManager by injectLazy()
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method called when the service is created. It injects dependencies and acquire the wake lock.
|
* 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)
|
showResultNotification(logFile.parent, logFile.name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**Restore categories if they were backed up
|
/**Restore categories if they were backed up
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
@ -246,8 +242,7 @@ class BackupRestoreService : Service() {
|
|||||||
if (job?.isCancelled == false) {
|
if (job?.isCancelled == false) {
|
||||||
showProgressNotification(restoreProgress, totalAmount, manga.title)
|
showProgressNotification(restoreProgress, totalAmount, manga.title)
|
||||||
restoreProgress += 1
|
restoreProgress += 1
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
throw java.lang.Exception("Job was cancelled")
|
throw java.lang.Exception("Job was cancelled")
|
||||||
}
|
}
|
||||||
val dbManga = backupManager.getMangaFromDatabase(manga)
|
val dbManga = backupManager.getMangaFromDatabase(manga)
|
||||||
@ -262,7 +257,7 @@ class BackupRestoreService : Service() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!dbMangaExists || !backupManager.restoreChaptersForManga(manga, chapters)) {
|
if (!dbMangaExists || !backupManager.restoreChaptersForManga(manga, chapters)) {
|
||||||
//manga gets chapters added
|
// manga gets chapters added
|
||||||
backupManager.restoreChapterFetch(source, manga, chapters)
|
backupManager.restoreChapterFetch(source, manga, chapters)
|
||||||
}
|
}
|
||||||
// Restore categories
|
// Restore categories
|
||||||
@ -280,8 +275,7 @@ class BackupRestoreService : Service() {
|
|||||||
val cause = e.cause
|
val cause = e.cause
|
||||||
if (cause is SourceNotFoundException) {
|
if (cause is SourceNotFoundException) {
|
||||||
sourcesMissing.add(cause.id)
|
sourcesMissing.add(cause.id)
|
||||||
}
|
} else if (e.message?.contains("licensed", true) == true) {
|
||||||
else if (e.message?.contains("licensed", true) == true) {
|
|
||||||
lincensedManga++
|
lincensedManga++
|
||||||
}
|
}
|
||||||
errors.add("${manga.title} - ${cause?.message ?: e.message}")
|
errors.add("${manga.title} - ${cause?.message ?: e.message}")
|
||||||
@ -303,7 +297,7 @@ class BackupRestoreService : Service() {
|
|||||||
try {
|
try {
|
||||||
service.refresh(track)
|
service.refresh(track)
|
||||||
db.insertTrack(track).executeAsBlocking()
|
db.insertTrack(track).executeAsBlocking()
|
||||||
}catch (e : Exception){
|
} catch (e: Exception) {
|
||||||
errors.add("${manga.title} - ${e.message}")
|
errors.add("${manga.title} - ${e.message}")
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -357,7 +351,6 @@ class BackupRestoreService : Service() {
|
|||||||
NotificationReceiver.cancelRestorePendingBroadcast(this)
|
NotificationReceiver.cancelRestorePendingBroadcast(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Shows the notification containing the currently updating manga and the progress.
|
* Shows the notification containing the currently updating manga and the progress.
|
||||||
*
|
*
|
||||||
@ -473,4 +466,4 @@ class BackupRestoreService : Service() {
|
|||||||
context.stopService(Intent(context, BackupRestoreService::class.java))
|
context.stopService(Intent(context, BackupRestoreService::class.java))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
package eu.kanade.tachiyomi.data.backup.models
|
package eu.kanade.tachiyomi.data.backup.models
|
||||||
|
|
||||||
import java.text.SimpleDateFormat
|
import java.text.SimpleDateFormat
|
||||||
import java.util.*
|
import java.util.Date
|
||||||
|
import java.util.Locale
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Json values
|
* Json values
|
||||||
@ -20,4 +21,4 @@ object Backup {
|
|||||||
val date = SimpleDateFormat("yyyy-MM-dd_HH-mm", Locale.getDefault()).format(Date())
|
val date = SimpleDateFormat("yyyy-MM-dd_HH-mm", Locale.getDefault()).format(Date())
|
||||||
return "tachiyomi_$date.json"
|
return "tachiyomi_$date.json"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
package eu.kanade.tachiyomi.data.backup.models
|
package eu.kanade.tachiyomi.data.backup.models
|
||||||
|
|
||||||
data class DHistory(val url: String,val lastRead: Long)
|
data class DHistory(val url: String, val lastRead: Long)
|
||||||
|
@ -28,4 +28,4 @@ object CategoryTypeAdapter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -29,4 +29,4 @@ object HistoryTypeAdapter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -35,4 +35,4 @@ object MangaTypeAdapter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
package eu.kanade.tachiyomi.data.backup.serializer
|
package eu.kanade.tachiyomi.data.backup.serializer
|
||||||
|
|
||||||
import android.telecom.DisconnectCause.REMOTE
|
|
||||||
import com.github.salomonbrys.kotson.typeAdapter
|
import com.github.salomonbrys.kotson.typeAdapter
|
||||||
import com.google.gson.TypeAdapter
|
import com.google.gson.TypeAdapter
|
||||||
import com.google.gson.stream.JsonToken
|
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.source.model.Page
|
||||||
import eu.kanade.tachiyomi.util.storage.DiskUtil
|
import eu.kanade.tachiyomi.util.storage.DiskUtil
|
||||||
import eu.kanade.tachiyomi.util.storage.saveTo
|
import eu.kanade.tachiyomi.util.storage.saveTo
|
||||||
|
import java.io.File
|
||||||
|
import java.io.IOException
|
||||||
import okhttp3.Response
|
import okhttp3.Response
|
||||||
import okio.Okio
|
|
||||||
import okio.buffer
|
import okio.buffer
|
||||||
import okio.sink
|
import okio.sink
|
||||||
import rx.Observable
|
import rx.Observable
|
||||||
import uy.kohesive.injekt.injectLazy
|
import uy.kohesive.injekt.injectLazy
|
||||||
import java.io.File
|
|
||||||
import java.io.IOException
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class used to create chapter cache
|
* Class used to create chapter cache
|
||||||
@ -136,7 +135,6 @@ class ChapterCache(private val context: Context) {
|
|||||||
diskCache.flush()
|
diskCache.flush()
|
||||||
editor.commit()
|
editor.commit()
|
||||||
editor.abortUnlessCommitted()
|
editor.abortUnlessCommitted()
|
||||||
|
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
// Ignore.
|
// Ignore.
|
||||||
} finally {
|
} finally {
|
||||||
@ -202,4 +200,3 @@ class ChapterCache(private val context: Context) {
|
|||||||
return "${chapter.manga_id}${chapter.url}"
|
return "${chapter.manga_id}${chapter.url}"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,8 +20,8 @@ class CoverCache(private val context: Context) {
|
|||||||
/**
|
/**
|
||||||
* Cache directory used for cache management.
|
* Cache directory used for cache management.
|
||||||
*/
|
*/
|
||||||
private val cacheDir = context.getExternalFilesDir("covers") ?:
|
private val cacheDir = context.getExternalFilesDir("covers")
|
||||||
File(context.filesDir, "covers").also { it.mkdirs() }
|
?: File(context.filesDir, "covers").also { it.mkdirs() }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the cover from cache.
|
* Returns the cover from cache.
|
||||||
@ -37,7 +37,7 @@ class CoverCache(private val context: Context) {
|
|||||||
* Copy the given stream to this cache.
|
* Copy the given stream to this cache.
|
||||||
*
|
*
|
||||||
* @param thumbnailUrl url of the thumbnail.
|
* @param thumbnailUrl url of the thumbnail.
|
||||||
* @param inputStream the stream to copy.
|
* @param inputStream the stream to copy.
|
||||||
* @throws IOException if there's any error.
|
* @throws IOException if there's any error.
|
||||||
*/
|
*/
|
||||||
@Throws(IOException::class)
|
@Throws(IOException::class)
|
||||||
|
@ -29,8 +29,8 @@ import io.requery.android.database.sqlite.RequerySQLiteOpenHelperFactory
|
|||||||
/**
|
/**
|
||||||
* This class provides operations to manage the database through its interfaces.
|
* This class provides operations to manage the database through its interfaces.
|
||||||
*/
|
*/
|
||||||
open class DatabaseHelper(context: Context)
|
open class DatabaseHelper(context: Context) :
|
||||||
: MangaQueries, ChapterQueries, TrackQueries, CategoryQueries, MangaCategoryQueries,
|
MangaQueries, ChapterQueries, TrackQueries, CategoryQueries, MangaCategoryQueries,
|
||||||
HistoryQueries, SearchMetadataQueries {
|
HistoryQueries, SearchMetadataQueries {
|
||||||
|
|
||||||
private val configuration = SupportSQLiteOpenHelper.Configuration.builder(context)
|
private val configuration = SupportSQLiteOpenHelper.Configuration.builder(context)
|
||||||
@ -52,5 +52,4 @@ open class DatabaseHelper(context: Context)
|
|||||||
inline fun inTransaction(block: () -> Unit) = db.inTransaction(block)
|
inline fun inTransaction(block: () -> Unit) = db.inTransaction(block)
|
||||||
|
|
||||||
fun lowLevel() = db.lowLevel()
|
fun lowLevel() = db.lowLevel()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -22,4 +22,3 @@ inline fun <T> StorIOSQLite.inTransactionReturn(block: () -> T): T {
|
|||||||
lowLevel().endTransaction()
|
lowLevel().endTransaction()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,10 +2,12 @@ package eu.kanade.tachiyomi.data.database
|
|||||||
|
|
||||||
import androidx.sqlite.db.SupportSQLiteDatabase
|
import androidx.sqlite.db.SupportSQLiteDatabase
|
||||||
import androidx.sqlite.db.SupportSQLiteOpenHelper
|
import androidx.sqlite.db.SupportSQLiteOpenHelper
|
||||||
import android.content.Context
|
import eu.kanade.tachiyomi.data.database.tables.CategoryTable
|
||||||
import android.database.sqlite.SQLiteDatabase
|
import eu.kanade.tachiyomi.data.database.tables.ChapterTable
|
||||||
import android.database.sqlite.SQLiteOpenHelper
|
import eu.kanade.tachiyomi.data.database.tables.HistoryTable
|
||||||
import eu.kanade.tachiyomi.data.database.tables.*
|
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) {
|
class DbOpenCallback : SupportSQLiteOpenHelper.Callback(DATABASE_VERSION) {
|
||||||
|
|
||||||
@ -81,5 +83,4 @@ class DbOpenCallback : SupportSQLiteOpenHelper.Callback(DATABASE_VERSION) {
|
|||||||
override fun onConfigure(db: SupportSQLiteDatabase) {
|
override fun onConfigure(db: SupportSQLiteDatabase) {
|
||||||
db.setForeignKeyConstraintsEnabled(true)
|
db.setForeignKeyConstraintsEnabled(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -5,5 +5,4 @@ import com.pushtorefresh.storio.sqlite.impl.DefaultStorIOSQLite
|
|||||||
interface DbProvider {
|
interface DbProvider {
|
||||||
|
|
||||||
val db: DefaultStorIOSQLite
|
val db: DefaultStorIOSQLite
|
||||||
|
}
|
||||||
}
|
|
||||||
|
@ -47,7 +47,6 @@ class CategoryPutResolver : DefaultPutResolver<Category>() {
|
|||||||
val orderString = obj.mangaOrder.joinToString("/")
|
val orderString = obj.mangaOrder.joinToString("/")
|
||||||
put(COL_MANGA_ORDER, orderString)
|
put(COL_MANGA_ORDER, orderString)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,4 +88,3 @@ class ChapterDeleteResolver : DefaultDeleteResolver<Chapter>() {
|
|||||||
.whereArgs(obj.id)
|
.whereArgs(obj.id)
|
||||||
.build()
|
.build()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
package eu.kanade.tachiyomi.data.database.mappers
|
package eu.kanade.tachiyomi.data.database.mappers
|
||||||
|
|
||||||
|
|
||||||
import android.content.ContentValues
|
import android.content.ContentValues
|
||||||
import android.database.Cursor
|
import android.database.Cursor
|
||||||
import com.pushtorefresh.storio.sqlite.SQLiteTypeMapping
|
import com.pushtorefresh.storio.sqlite.SQLiteTypeMapping
|
||||||
@ -63,4 +62,4 @@ class SearchMetadataDeleteResolver : DefaultDeleteResolver<SearchMetadata>() {
|
|||||||
.where("$COL_MANGA_ID = ?")
|
.where("$COL_MANGA_ID = ?")
|
||||||
.whereArgs(obj.mangaId)
|
.whereArgs(obj.mangaId)
|
||||||
.build()
|
.build()
|
||||||
}
|
}
|
||||||
|
@ -54,7 +54,6 @@ class TrackPutResolver : DefaultPutResolver<Track>() {
|
|||||||
put(COL_STATUS, obj.status)
|
put(COL_STATUS, obj.status)
|
||||||
put(COL_TRACKING_URL, obj.tracking_url)
|
put(COL_TRACKING_URL, obj.tracking_url)
|
||||||
put(COL_SCORE, obj.score)
|
put(COL_SCORE, obj.score)
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,18 +15,18 @@ interface Category : Serializable {
|
|||||||
|
|
||||||
var flags: Int
|
var flags: Int
|
||||||
|
|
||||||
var mangaOrder:List<Long>
|
var mangaOrder: List<Long>
|
||||||
|
|
||||||
var mangaSort:Char?
|
var mangaSort: Char?
|
||||||
|
|
||||||
var isFirst:Boolean?
|
var isFirst: Boolean?
|
||||||
var isLast:Boolean?
|
var isLast: Boolean?
|
||||||
|
|
||||||
val nameLower: String
|
val nameLower: String
|
||||||
get() = name.toLowerCase()
|
get() = name.toLowerCase()
|
||||||
|
|
||||||
fun isAscending(): Boolean {
|
fun isAscending(): Boolean {
|
||||||
return ((mangaSort?.minus('a') ?: 0) % 2) != 1
|
return ((mangaSort?.minus('a') ?: 0) % 2) != 1
|
||||||
}
|
}
|
||||||
|
|
||||||
fun sortingMode(): Int? = when (mangaSort) {
|
fun sortingMode(): Int? = when (mangaSort) {
|
||||||
@ -42,9 +42,9 @@ interface Category : Serializable {
|
|||||||
fun sortRes(): Int = when (mangaSort) {
|
fun sortRes(): Int = when (mangaSort) {
|
||||||
ALPHA_ASC, ALPHA_DSC -> R.string.title
|
ALPHA_ASC, ALPHA_DSC -> R.string.title
|
||||||
UPDATED_ASC, UPDATED_DSC -> R.string.action_sort_latest_chapter
|
UPDATED_ASC, UPDATED_DSC -> R.string.action_sort_latest_chapter
|
||||||
UNREAD_ASC, UNREAD_DSC -> R.string.action_filter_unread
|
UNREAD_ASC, UNREAD_DSC -> R.string.action_filter_unread
|
||||||
LAST_READ_ASC, LAST_READ_DSC -> R.string.action_sort_last_read
|
LAST_READ_ASC, LAST_READ_DSC -> R.string.action_sort_last_read
|
||||||
TOTAL_ASC, TOTAL_DSC -> R.string.action_sort_total
|
TOTAL_ASC, TOTAL_DSC -> R.string.action_sort_total
|
||||||
else -> R.string.action_sort_drag_and_drop
|
else -> R.string.action_sort_drag_and_drop
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -111,5 +111,4 @@ interface Category : Serializable {
|
|||||||
isLast = true
|
isLast = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
|
@ -30,5 +30,4 @@ class CategoryImpl : Category {
|
|||||||
override fun hashCode(): Int {
|
override fun hashCode(): Int {
|
||||||
return name.hashCode()
|
return name.hashCode()
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -39,5 +39,4 @@ class ChapterImpl : Chapter {
|
|||||||
override fun hashCode(): Int {
|
override fun hashCode(): Int {
|
||||||
return url.hashCode()
|
return url.hashCode()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
|
@ -35,7 +35,7 @@ interface History : Serializable {
|
|||||||
* @param chapter chapter object
|
* @param chapter chapter object
|
||||||
* @return history object
|
* @return history object
|
||||||
*/
|
*/
|
||||||
fun create(chapter: Chapter): History = HistoryImpl().apply {
|
fun create(chapter: Chapter): History = HistoryImpl().apply {
|
||||||
this.chapter_id = chapter.id!!
|
this.chapter_id = chapter.id!!
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,5 +5,4 @@ class LibraryManga : MangaImpl() {
|
|||||||
var unread: Int = 0
|
var unread: Int = 0
|
||||||
|
|
||||||
var category: 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.SourceManager
|
||||||
import eu.kanade.tachiyomi.source.model.SManga
|
import eu.kanade.tachiyomi.source.model.SManga
|
||||||
import eu.kanade.tachiyomi.ui.reader.ReaderActivity
|
import eu.kanade.tachiyomi.ui.reader.ReaderActivity
|
||||||
|
import java.util.Locale
|
||||||
import uy.kohesive.injekt.Injekt
|
import uy.kohesive.injekt.Injekt
|
||||||
import uy.kohesive.injekt.api.get
|
import uy.kohesive.injekt.api.get
|
||||||
import java.util.Locale
|
|
||||||
|
|
||||||
interface Manga : SManga {
|
interface Manga : SManga {
|
||||||
|
|
||||||
@ -82,7 +82,7 @@ interface Manga : SManga {
|
|||||||
tag.startsWith("chinese") || tag == "manhua" ||
|
tag.startsWith("chinese") || tag == "manhua" ||
|
||||||
tag.startsWith("english") || tag == "comic"
|
tag.startsWith("english") || tag == "comic"
|
||||||
} == true || isComicSource(sourceName) ||
|
} == true || isComicSource(sourceName) ||
|
||||||
sourceName.contains("manhua", true) )
|
sourceName.contains("manhua", true))
|
||||||
ReaderActivity.LEFT_TO_RIGHT
|
ReaderActivity.LEFT_TO_RIGHT
|
||||||
else 0
|
else 0
|
||||||
}
|
}
|
||||||
@ -168,5 +168,4 @@ interface Manga : SManga {
|
|||||||
this.source = source
|
this.source = source
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
|
@ -17,5 +17,4 @@ class MangaCategory {
|
|||||||
return mc
|
return mc
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,6 @@ package eu.kanade.tachiyomi.data.database.models
|
|||||||
*
|
*
|
||||||
* @param manga object containing manga
|
* @param manga object containing manga
|
||||||
* @param chapter object containing chater
|
* @param chapter object containing chater
|
||||||
* @param history object containing history
|
* @param history object containing history
|
||||||
*/
|
*/
|
||||||
data class MangaChapterHistory(val manga: Manga, val chapter: Chapter, val history: History)
|
data class MangaChapterHistory(val manga: Manga, val chapter: Chapter, val history: History)
|
||||||
|
@ -3,8 +3,8 @@ package eu.kanade.tachiyomi.data.database.models
|
|||||||
import eu.kanade.tachiyomi.data.download.DownloadManager
|
import eu.kanade.tachiyomi.data.download.DownloadManager
|
||||||
import eu.kanade.tachiyomi.data.download.DownloadProvider
|
import eu.kanade.tachiyomi.data.download.DownloadProvider
|
||||||
import eu.kanade.tachiyomi.source.model.SManga
|
import eu.kanade.tachiyomi.source.model.SManga
|
||||||
import uy.kohesive.injekt.injectLazy
|
|
||||||
import kotlin.collections.set
|
import kotlin.collections.set
|
||||||
|
import uy.kohesive.injekt.injectLazy
|
||||||
|
|
||||||
open class MangaImpl : Manga {
|
open class MangaImpl : Manga {
|
||||||
|
|
||||||
@ -47,9 +47,9 @@ open class MangaImpl : Manga {
|
|||||||
title = if (currentTitle() != originalTitle()) {
|
title = if (currentTitle() != originalTitle()) {
|
||||||
val customTitle = currentTitle()
|
val customTitle = currentTitle()
|
||||||
val trueTitle = other.title
|
val trueTitle = other.title
|
||||||
"${customTitle}${SManga.splitter}${trueTitle}"
|
"${customTitle}${SManga.splitter}$trueTitle"
|
||||||
} else other.title
|
} else other.title
|
||||||
val db:DownloadManager by injectLazy()
|
val db: DownloadManager by injectLazy()
|
||||||
val provider = DownloadProvider(db.context)
|
val provider = DownloadProvider(db.context)
|
||||||
provider.renameMangaFolder(oldTitle, title, source)
|
provider.renameMangaFolder(oldTitle, title, source)
|
||||||
}
|
}
|
||||||
@ -63,7 +63,6 @@ open class MangaImpl : Manga {
|
|||||||
val manga = other as Manga
|
val manga = other as Manga
|
||||||
|
|
||||||
return url == manga.url
|
return url == manga.url
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun hashCode(): Int {
|
override fun hashCode(): Int {
|
||||||
@ -71,7 +70,7 @@ open class MangaImpl : Manga {
|
|||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private var lastCoverFetch:HashMap<Long, Long> = hashMapOf()
|
private var lastCoverFetch: HashMap<Long, Long> = hashMapOf()
|
||||||
|
|
||||||
fun setLastCoverFetch(id: Long, time: Long) {
|
fun setLastCoverFetch(id: Long, time: Long) {
|
||||||
lastCoverFetch[id] = time
|
lastCoverFetch[id] = time
|
||||||
@ -79,5 +78,4 @@ open class MangaImpl : Manga {
|
|||||||
|
|
||||||
fun getLastCoverFetch(id: Long) = lastCoverFetch[id] ?: 0
|
fun getLastCoverFetch(id: Long) = lastCoverFetch[id] ?: 0
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -18,4 +18,4 @@ data class SearchMetadata(
|
|||||||
) {
|
) {
|
||||||
// Transient information attached to this piece of metadata, useful for caching
|
// Transient information attached to this piece of metadata, useful for caching
|
||||||
var transientCache: Map<String, Any>? = null
|
var transientCache: Map<String, Any>? = null
|
||||||
}
|
}
|
||||||
|
@ -37,5 +37,4 @@ interface Track : Serializable {
|
|||||||
sync_id = serviceId
|
sync_id = serviceId
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -41,5 +41,4 @@ class TrackImpl : Track {
|
|||||||
result = 31 * result + media_id
|
result = 31 * result + media_id
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -32,5 +32,4 @@ interface CategoryQueries : DbProvider {
|
|||||||
fun deleteCategory(category: Category) = db.delete().`object`(category).prepare()
|
fun deleteCategory(category: Category) = db.delete().`object`(category).prepare()
|
||||||
|
|
||||||
fun deleteCategories(categories: List<Category>) = db.delete().objects(categories).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.ChapterSourceOrderPutResolver
|
||||||
import eu.kanade.tachiyomi.data.database.resolvers.MangaChapterGetResolver
|
import eu.kanade.tachiyomi.data.database.resolvers.MangaChapterGetResolver
|
||||||
import eu.kanade.tachiyomi.data.database.tables.ChapterTable
|
import eu.kanade.tachiyomi.data.database.tables.ChapterTable
|
||||||
import java.util.*
|
import java.util.Date
|
||||||
|
|
||||||
interface ChapterQueries : DbProvider {
|
interface ChapterQueries : DbProvider {
|
||||||
|
|
||||||
@ -88,5 +88,4 @@ interface ChapterQueries : DbProvider {
|
|||||||
.objects(chapters)
|
.objects(chapters)
|
||||||
.withPutResolver(ChapterSourceOrderPutResolver())
|
.withPutResolver(ChapterSourceOrderPutResolver())
|
||||||
.prepare()
|
.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.HistoryLastReadPutResolver
|
||||||
import eu.kanade.tachiyomi.data.database.resolvers.MangaChapterHistoryGetResolver
|
import eu.kanade.tachiyomi.data.database.resolvers.MangaChapterHistoryGetResolver
|
||||||
import eu.kanade.tachiyomi.data.database.tables.HistoryTable
|
import eu.kanade.tachiyomi.data.database.tables.HistoryTable
|
||||||
import java.util.*
|
import java.util.Date
|
||||||
|
|
||||||
interface HistoryQueries : DbProvider {
|
interface HistoryQueries : DbProvider {
|
||||||
|
|
||||||
|
@ -28,5 +28,4 @@ interface MangaCategoryQueries : DbProvider {
|
|||||||
insertMangasCategories(mangasCategories).executeAsBlocking()
|
insertMangasCategories(mangasCategories).executeAsBlocking()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
|
@ -145,5 +145,5 @@ interface MangaQueries : DbProvider {
|
|||||||
.prepare()
|
.prepare()
|
||||||
|
|
||||||
fun getTotalChapterManga() = db.get().listOfObjects(Manga::class.java)
|
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}
|
ON ${Chapter.TABLE}.${Chapter.COL_MANGA_ID} = max_last_read.${Chapter.COL_MANGA_ID}
|
||||||
WHERE ${History.TABLE}.${History.COL_LAST_READ} > ?
|
WHERE ${History.TABLE}.${History.COL_LAST_READ} > ?
|
||||||
AND max_last_read.${History.COL_CHAPTER_ID} = ${History.TABLE}.${History.COL_CHAPTER_ID}
|
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
|
ORDER BY max_last_read.${History.COL_LAST_READ} DESC
|
||||||
LIMIT 25 OFFSET $offset
|
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}
|
ON ${Chapter.TABLE}.${Chapter.COL_MANGA_ID} = max_last_read.${Chapter.COL_MANGA_ID}
|
||||||
WHERE ${History.TABLE}.${History.COL_LAST_READ} > ?
|
WHERE ${History.TABLE}.${History.COL_LAST_READ} > ?
|
||||||
AND max_last_read.${History.COL_CHAPTER_ID} = ${History.TABLE}.${History.COL_CHAPTER_ID}
|
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
|
ORDER BY max_last_read.${History.COL_LAST_READ} DESC
|
||||||
LIMIT $limit
|
LIMIT $limit
|
||||||
"""
|
"""
|
||||||
@ -142,7 +142,7 @@ fun getLastReadMangaQuery() = """
|
|||||||
ORDER BY max DESC
|
ORDER BY max DESC
|
||||||
"""
|
"""
|
||||||
|
|
||||||
fun getTotalChapterMangaQuery()= """
|
fun getTotalChapterMangaQuery() = """
|
||||||
SELECT ${Manga.TABLE}.*
|
SELECT ${Manga.TABLE}.*
|
||||||
FROM ${Manga.TABLE}
|
FROM ${Manga.TABLE}
|
||||||
JOIN ${Chapter.TABLE}
|
JOIN ${Chapter.TABLE}
|
||||||
@ -159,4 +159,4 @@ fun getCategoriesForMangaQuery() = """
|
|||||||
JOIN ${MangaCategory.TABLE} ON ${Category.TABLE}.${Category.COL_ID} =
|
JOIN ${MangaCategory.TABLE} ON ${Category.TABLE}.${Category.COL_ID} =
|
||||||
${MangaCategory.TABLE}.${MangaCategory.COL_CATEGORY_ID}
|
${MangaCategory.TABLE}.${MangaCategory.COL_CATEGORY_ID}
|
||||||
WHERE ${MangaCategory.COL_MANGA_ID} = ?
|
WHERE ${MangaCategory.COL_MANGA_ID} = ?
|
||||||
"""
|
"""
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
package eu.kanade.tachiyomi.data.database.queries
|
package eu.kanade.tachiyomi.data.database.queries
|
||||||
|
|
||||||
|
|
||||||
import com.pushtorefresh.storio.sqlite.queries.DeleteQuery
|
import com.pushtorefresh.storio.sqlite.queries.DeleteQuery
|
||||||
import com.pushtorefresh.storio.sqlite.queries.Query
|
import com.pushtorefresh.storio.sqlite.queries.Query
|
||||||
import eu.kanade.tachiyomi.data.database.DbProvider
|
import eu.kanade.tachiyomi.data.database.DbProvider
|
||||||
@ -42,4 +41,4 @@ interface SearchMetadataQueries : DbProvider {
|
|||||||
.table(SearchMetadataTable.TABLE)
|
.table(SearchMetadataTable.TABLE)
|
||||||
.build())
|
.build())
|
||||||
.prepare()
|
.prepare()
|
||||||
}
|
}
|
||||||
|
@ -30,5 +30,4 @@ interface TrackQueries : DbProvider {
|
|||||||
.whereArgs(manga.id, sync.id)
|
.whereArgs(manga.id, sync.id)
|
||||||
.build())
|
.build())
|
||||||
.prepare()
|
.prepare()
|
||||||
|
}
|
||||||
}
|
|
||||||
|
@ -30,6 +30,4 @@ class ChapterBackupPutResolver : PutResolver<Chapter>() {
|
|||||||
put(ChapterTable.COL_BOOKMARK, chapter.bookmark)
|
put(ChapterTable.COL_BOOKMARK, chapter.bookmark)
|
||||||
put(ChapterTable.COL_LAST_PAGE_READ, chapter.last_page_read)
|
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_LAST_PAGE_READ, chapter.last_page_read)
|
||||||
put(ChapterTable.COL_PAGES_LEFT, chapter.pages_left)
|
put(ChapterTable.COL_PAGES_LEFT, chapter.pages_left)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,5 +28,4 @@ class ChapterSourceOrderPutResolver : PutResolver<Chapter>() {
|
|||||||
fun mapToContentValues(chapter: Chapter) = ContentValues(1).apply {
|
fun mapToContentValues(chapter: Chapter) = ContentValues(1).apply {
|
||||||
put(ChapterTable.COL_SOURCE_ORDER, chapter.source_order)
|
put(ChapterTable.COL_SOURCE_ORDER, chapter.source_order)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
|
@ -60,5 +60,4 @@ class HistoryLastReadPutResolver : HistoryPutResolver() {
|
|||||||
fun mapToUpdateContentValues(history: History) = ContentValues(1).apply {
|
fun mapToUpdateContentValues(history: History) = ContentValues(1).apply {
|
||||||
put(HistoryTable.COL_LAST_READ, history.last_read)
|
put(HistoryTable.COL_LAST_READ, history.last_read)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -21,5 +21,4 @@ class LibraryMangaGetResolver : DefaultGetResolver<LibraryManga>(), BaseMangaGet
|
|||||||
|
|
||||||
return manga
|
return manga
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -24,5 +24,4 @@ class MangaChapterGetResolver : DefaultGetResolver<MangaChapter>() {
|
|||||||
|
|
||||||
return MangaChapter(manga, chapter)
|
return MangaChapter(manga, chapter)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -28,6 +28,4 @@ class MangaFavoritePutResolver : PutResolver<Manga>() {
|
|||||||
fun mapToContentValues(manga: Manga) = ContentValues(1).apply {
|
fun mapToContentValues(manga: Manga) = ContentValues(1).apply {
|
||||||
put(MangaTable.COL_FAVORITE, manga.favorite)
|
put(MangaTable.COL_FAVORITE, manga.favorite)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,6 +28,4 @@ class MangaFlagsPutResolver : PutResolver<Manga>() {
|
|||||||
fun mapToContentValues(manga: Manga) = ContentValues(1).apply {
|
fun mapToContentValues(manga: Manga) = ContentValues(1).apply {
|
||||||
put(MangaTable.COL_CHAPTER_FLAGS, manga.chapter_flags)
|
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.operations.put.PutResult
|
||||||
import com.pushtorefresh.storio.sqlite.queries.UpdateQuery
|
import com.pushtorefresh.storio.sqlite.queries.UpdateQuery
|
||||||
import eu.kanade.tachiyomi.data.database.inTransactionReturn
|
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.models.Manga
|
||||||
import eu.kanade.tachiyomi.data.database.tables.MangaTable
|
import eu.kanade.tachiyomi.data.database.tables.MangaTable
|
||||||
|
|
||||||
@ -29,5 +28,4 @@ class MangaHideTitlePutResolver : PutResolver<Manga>() {
|
|||||||
fun mapToContentValues(manga: Manga) = ContentValues(1).apply {
|
fun mapToContentValues(manga: Manga) = ContentValues(1).apply {
|
||||||
put(MangaTable.COL_HIDE_TITLE, manga.hide_title)
|
put(MangaTable.COL_HIDE_TITLE, manga.hide_title)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,7 @@ import eu.kanade.tachiyomi.data.database.inTransactionReturn
|
|||||||
import eu.kanade.tachiyomi.data.database.models.Manga
|
import eu.kanade.tachiyomi.data.database.models.Manga
|
||||||
import eu.kanade.tachiyomi.data.database.tables.MangaTable
|
import eu.kanade.tachiyomi.data.database.tables.MangaTable
|
||||||
|
|
||||||
class MangaInfoPutResolver(val reset:Boolean = false): PutResolver<Manga>() {
|
class MangaInfoPutResolver(val reset: Boolean = false) : PutResolver<Manga>() {
|
||||||
|
|
||||||
override fun performPut(db: StorIOSQLite, manga: Manga) = db.inTransactionReturn {
|
override fun performPut(db: StorIOSQLite, manga: Manga) = db.inTransactionReturn {
|
||||||
val updateQuery = mapToUpdateQuery(manga)
|
val updateQuery = mapToUpdateQuery(manga)
|
||||||
@ -40,6 +40,4 @@ class MangaInfoPutResolver(val reset:Boolean = false): PutResolver<Manga>() {
|
|||||||
put(MangaTable.COL_ARTIST, manga.originalArtist())
|
put(MangaTable.COL_ARTIST, manga.originalArtist())
|
||||||
put(MangaTable.COL_DESCRIPTION, manga.originalDesc())
|
put(MangaTable.COL_DESCRIPTION, manga.originalDesc())
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
|
||||||
|
@ -28,6 +28,4 @@ class MangaLastUpdatedPutResolver : PutResolver<Manga>() {
|
|||||||
fun mapToContentValues(manga: Manga) = ContentValues(1).apply {
|
fun mapToContentValues(manga: Manga) = ContentValues(1).apply {
|
||||||
put(MangaTable.COL_LAST_UPDATE, manga.last_update)
|
put(MangaTable.COL_LAST_UPDATE, manga.last_update)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,5 +28,4 @@ class MangaTitlePutResolver : PutResolver<Manga>() {
|
|||||||
fun mapToContentValues(manga: Manga) = ContentValues(1).apply {
|
fun mapToContentValues(manga: Manga) = ContentValues(1).apply {
|
||||||
put(MangaTable.COL_TITLE, manga.title)
|
put(MangaTable.COL_TITLE, manga.title)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -28,5 +28,4 @@ class MangaViewerPutResolver : PutResolver<Manga>() {
|
|||||||
fun mapToContentValues(manga: Manga) = ContentValues(1).apply {
|
fun mapToContentValues(manga: Manga) = ContentValues(1).apply {
|
||||||
put(MangaTable.COL_VIEWER, manga.viewer)
|
put(MangaTable.COL_VIEWER, manga.viewer)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,6 @@ object CategoryTable {
|
|||||||
$COL_MANGA_ORDER TEXT NOT NULL
|
$COL_MANGA_ORDER TEXT NOT NULL
|
||||||
)"""
|
)"""
|
||||||
|
|
||||||
|
|
||||||
val addMangaOrder: String
|
val addMangaOrder: String
|
||||||
get() = "ALTER TABLE $TABLE ADD COLUMN $COL_MANGA_ORDER TEXT"
|
get() = "ALTER TABLE $TABLE ADD COLUMN $COL_MANGA_ORDER TEXT"
|
||||||
}
|
}
|
||||||
|
@ -67,5 +67,4 @@ object ChapterTable {
|
|||||||
|
|
||||||
val pagesLeftQuery: String
|
val pagesLeftQuery: String
|
||||||
get() = "ALTER TABLE $TABLE ADD COLUMN $COL_PAGES_LEFT INTEGER DEFAULT 0"
|
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})
|
FOREIGN KEY($COL_MANGA_ID) REFERENCES ${MangaTable.TABLE} (${MangaTable.COL_ID})
|
||||||
ON DELETE CASCADE
|
ON DELETE CASCADE
|
||||||
)"""
|
)"""
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
package eu.kanade.tachiyomi.data.database.tables
|
package eu.kanade.tachiyomi.data.database.tables
|
||||||
|
|
||||||
|
|
||||||
object SearchMetadataTable {
|
object SearchMetadataTable {
|
||||||
const val TABLE = "search_metadata"
|
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.data.preference.getOrDefault
|
||||||
import eu.kanade.tachiyomi.source.SourceManager
|
import eu.kanade.tachiyomi.source.SourceManager
|
||||||
import eu.kanade.tachiyomi.util.storage.DiskUtil
|
import eu.kanade.tachiyomi.util.storage.DiskUtil
|
||||||
|
import java.util.concurrent.TimeUnit
|
||||||
import uy.kohesive.injekt.Injekt
|
import uy.kohesive.injekt.Injekt
|
||||||
import uy.kohesive.injekt.api.get
|
import uy.kohesive.injekt.api.get
|
||||||
import uy.kohesive.injekt.injectLazy
|
import uy.kohesive.injekt.injectLazy
|
||||||
import java.util.concurrent.TimeUnit
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cache where we dump the downloads directory from the filesystem. This class is needed because
|
* Cache where we dump the downloads directory from the filesystem. This class is needed because
|
||||||
@ -27,10 +27,10 @@ import java.util.concurrent.TimeUnit
|
|||||||
* @param preferences the preferences of the app.
|
* @param preferences the preferences of the app.
|
||||||
*/
|
*/
|
||||||
class DownloadCache(
|
class DownloadCache(
|
||||||
private val context: Context,
|
private val context: Context,
|
||||||
private val provider: DownloadProvider,
|
private val provider: DownloadProvider,
|
||||||
private val sourceManager: SourceManager,
|
private val sourceManager: SourceManager,
|
||||||
private val preferences: PreferencesHelper = Injekt.get()
|
private val preferences: PreferencesHelper = Injekt.get()
|
||||||
) {
|
) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -119,7 +119,7 @@ class DownloadCache(
|
|||||||
onlineSources.find { provider.getSourceDirName(it) == entry.key }?.id
|
onlineSources.find { provider.getSourceDirName(it) == entry.key }?.id
|
||||||
}
|
}
|
||||||
|
|
||||||
val db:DatabaseHelper by injectLazy()
|
val db: DatabaseHelper by injectLazy()
|
||||||
val mangas = db.getMangas().executeAsBlocking().groupBy { it.source }
|
val mangas = db.getMangas().executeAsBlocking().groupBy { it.source }
|
||||||
|
|
||||||
sourceDirs.forEach { sourceValue ->
|
sourceDirs.forEach { sourceValue ->
|
||||||
@ -143,8 +143,8 @@ class DownloadCache(
|
|||||||
val trueMangaDirs = mangaDirs.mapNotNull { mangaDir ->
|
val trueMangaDirs = mangaDirs.mapNotNull { mangaDir ->
|
||||||
val manga = sourceMangas.firstOrNull()?.find { DiskUtil.buildValidFilename(
|
val manga = sourceMangas.firstOrNull()?.find { DiskUtil.buildValidFilename(
|
||||||
it.originalTitle()).toLowerCase() == mangaDir.key
|
it.originalTitle()).toLowerCase() == mangaDir.key
|
||||||
.toLowerCase() && it.source == sourceValue.key } ?:
|
.toLowerCase() && it.source == sourceValue.key }
|
||||||
sourceMangas.lastOrNull()?.find { DiskUtil.buildValidFilename(
|
?: sourceMangas.lastOrNull()?.find { DiskUtil.buildValidFilename(
|
||||||
it.originalTitle()).toLowerCase() == mangaDir.key
|
it.originalTitle()).toLowerCase() == mangaDir.key
|
||||||
.toLowerCase() && it.source == sourceValue.key }
|
.toLowerCase() && it.source == sourceValue.key }
|
||||||
val id = manga?.id ?: return@mapNotNull null
|
val id = manga?.id ?: return@mapNotNull null
|
||||||
@ -169,8 +169,7 @@ class DownloadCache(
|
|||||||
val files = mangaFiles[id]
|
val files = mangaFiles[id]
|
||||||
if (files == null) {
|
if (files == null) {
|
||||||
mangaFiles[id] = mutableSetOf(chapterDirName)
|
mangaFiles[id] = mutableSetOf(chapterDirName)
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
mangaFiles[id]?.add(chapterDirName)
|
mangaFiles[id]?.add(chapterDirName)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -216,7 +215,6 @@ class DownloadCache(
|
|||||||
sourceDir.files = list
|
sourceDir.files = list
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes a manga that has been deleted from this cache.
|
* 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.
|
* Class to store the files under the root downloads directory.
|
||||||
*/
|
*/
|
||||||
private class RootDirectory(val dir: UniFile,
|
private class RootDirectory(
|
||||||
var files: Map<Long, SourceDirectory> = hashMapOf())
|
val dir: UniFile,
|
||||||
|
var files: Map<Long, SourceDirectory> = hashMapOf()
|
||||||
|
)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class to store the files under a source directory.
|
* Class to store the files under a source directory.
|
||||||
*/
|
*/
|
||||||
private class SourceDirectory(val dir: UniFile,
|
private class SourceDirectory(
|
||||||
var files: Map<Long, MutableSet<String>> = hashMapOf())
|
val dir: UniFile,
|
||||||
|
var files: Map<Long, MutableSet<String>> = hashMapOf()
|
||||||
|
)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class to store the files under a manga directory.
|
* Class to store the files under a manga directory.
|
||||||
*/
|
*/
|
||||||
private class MangaDirectory(val dir: UniFile,
|
private class MangaDirectory(
|
||||||
var files: MutableSet<String> = hashSetOf())
|
val dir: UniFile,
|
||||||
|
var files: MutableSet<String> = hashSetOf()
|
||||||
|
)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a new map containing only the key entries of [transform] that are not null.
|
* Returns a new map containing only the key entries of [transform] that are not null.
|
||||||
@ -267,5 +271,4 @@ class DownloadCache(
|
|||||||
}
|
}
|
||||||
return destination
|
return destination
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -114,7 +114,7 @@ class DownloadManager(val context: Context) {
|
|||||||
downloader.pause()
|
downloader.pause()
|
||||||
downloader.queue.clear()
|
downloader.queue.clear()
|
||||||
downloader.queue.addAll(downloads)
|
downloader.queue.addAll(downloads)
|
||||||
if(!wasPaused){
|
if (!wasPaused) {
|
||||||
downloader.start()
|
downloader.start()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -221,10 +221,9 @@ class DownloadManager(val context: Context) {
|
|||||||
}
|
}
|
||||||
downloader.pause()
|
downloader.pause()
|
||||||
downloader.queue.remove(chapters)
|
downloader.queue.remove(chapters)
|
||||||
if(!wasPaused && downloader.queue.isNotEmpty()){
|
if (!wasPaused && downloader.queue.isNotEmpty()) {
|
||||||
downloader.start()
|
downloader.start()
|
||||||
}
|
} else if (downloader.queue.isEmpty() && DownloadService.isRunning(context)) {
|
||||||
else if (downloader.queue.isEmpty() && DownloadService.isRunning(context)) {
|
|
||||||
DownloadService.stop(context)
|
DownloadService.stop(context)
|
||||||
}
|
}
|
||||||
queue.remove(chapters)
|
queue.remove(chapters)
|
||||||
@ -255,7 +254,7 @@ class DownloadManager(val context: Context) {
|
|||||||
cleaned += readChapterDirs.size
|
cleaned += readChapterDirs.size
|
||||||
cache.removeChapters(readChapters, manga)
|
cache.removeChapters(readChapters, manga)
|
||||||
if (cache.getDownloadCount(manga) == 0) {
|
if (cache.getDownloadCount(manga) == 0) {
|
||||||
provider.findChapterDirs(allChapters, manga, source).firstOrNull()?.parentFile?.delete()// Delete manga directory if empty
|
provider.findChapterDirs(allChapters, manga, source).firstOrNull()?.parentFile?.delete() // Delete manga directory if empty
|
||||||
}
|
}
|
||||||
return cleaned
|
return cleaned
|
||||||
}
|
}
|
||||||
@ -295,5 +294,5 @@ class DownloadManager(val context: Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun addListener(listener: DownloadQueue.DownloadListener) = queue.addListener(listener)
|
fun addListener(listener: DownloadQueue.DownloadListener) = queue.addListener(listener)
|
||||||
fun removeListener(listener: DownloadQueue.DownloadListener) = queue.removeListener(listener)
|
fun removeListener(listener: DownloadQueue.DownloadListener) = queue.removeListener(listener)
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,6 @@ import androidx.core.app.NotificationCompat
|
|||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
import eu.kanade.tachiyomi.data.download.model.Download
|
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.NotificationHandler
|
||||||
import eu.kanade.tachiyomi.data.notification.NotificationReceiver
|
import eu.kanade.tachiyomi.data.notification.NotificationReceiver
|
||||||
import eu.kanade.tachiyomi.data.notification.Notifications
|
import eu.kanade.tachiyomi.data.notification.Notifications
|
||||||
@ -93,8 +92,7 @@ internal class DownloadNotifier(private val context: Context) {
|
|||||||
setContentText(
|
setContentText(
|
||||||
context.getString(R.string.chapter_downloading)
|
context.getString(R.string.chapter_downloading)
|
||||||
)
|
)
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
setContentTitle(
|
setContentTitle(
|
||||||
context.getString(
|
context.getString(
|
||||||
R.string.chapter_downloading
|
R.string.chapter_downloading
|
||||||
@ -102,12 +100,11 @@ internal class DownloadNotifier(private val context: Context) {
|
|||||||
)
|
)
|
||||||
setContentText(null)
|
setContentText(null)
|
||||||
}
|
}
|
||||||
setProgress(0,0, true)
|
setProgress(0, 0, true)
|
||||||
setStyle(null)
|
setStyle(null)
|
||||||
}
|
}
|
||||||
// Displays the progress bar on notification
|
// Displays the progress bar on notification
|
||||||
notification.show()
|
notification.show()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -164,7 +161,7 @@ internal class DownloadNotifier(private val context: Context) {
|
|||||||
context.getString(R.string.action_resume),
|
context.getString(R.string.action_resume),
|
||||||
NotificationReceiver.resumeDownloadsPendingBroadcast(context)
|
NotificationReceiver.resumeDownloadsPendingBroadcast(context)
|
||||||
)
|
)
|
||||||
//Clear action
|
// Clear action
|
||||||
addAction(
|
addAction(
|
||||||
R.drawable.ic_clear_grey_24dp_img,
|
R.drawable.ic_clear_grey_24dp_img,
|
||||||
context.getString(R.string.action_cancel_all),
|
context.getString(R.string.action_cancel_all),
|
||||||
|
@ -136,28 +136,28 @@ class DownloadPendingDeleter(context: Context) {
|
|||||||
* Class used to save an entry of chapters with their manga into preferences.
|
* Class used to save an entry of chapters with their manga into preferences.
|
||||||
*/
|
*/
|
||||||
private data class Entry(
|
private data class Entry(
|
||||||
val chapters: List<ChapterEntry>,
|
val chapters: List<ChapterEntry>,
|
||||||
val manga: MangaEntry
|
val manga: MangaEntry
|
||||||
)
|
)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class used to save an entry for a chapter into preferences.
|
* Class used to save an entry for a chapter into preferences.
|
||||||
*/
|
*/
|
||||||
private data class ChapterEntry(
|
private data class ChapterEntry(
|
||||||
val id: Long,
|
val id: Long,
|
||||||
val url: String,
|
val url: String,
|
||||||
val name: String,
|
val name: String,
|
||||||
val scanlator: String?
|
val scanlator: String?
|
||||||
)
|
)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class used to save an entry for a manga into preferences.
|
* Class used to save an entry for a manga into preferences.
|
||||||
*/
|
*/
|
||||||
private data class MangaEntry(
|
private data class MangaEntry(
|
||||||
val id: Long,
|
val id: Long,
|
||||||
val url: String,
|
val url: String,
|
||||||
val title: String,
|
val title: String,
|
||||||
val source: Long
|
val source: Long
|
||||||
)
|
)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -194,5 +194,4 @@ class DownloadPendingDeleter(context: Context) {
|
|||||||
it.name = name
|
it.name = name
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -37,9 +37,8 @@ class DownloadProvider(private val context: Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
init {
|
init {
|
||||||
preferences.downloadsDirectory().asObservable()
|
preferences.downloadsDirectory().asObservable().skip(1)
|
||||||
.skip(1)
|
.subscribe { downloadsDir = UniFile.fromUri(context, Uri.parse(it)) }
|
||||||
.subscribe { downloadsDir = UniFile.fromUri(context, Uri.parse(it)) }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -50,9 +49,8 @@ class DownloadProvider(private val context: Context) {
|
|||||||
*/
|
*/
|
||||||
internal fun getMangaDir(manga: Manga, source: Source): UniFile {
|
internal fun getMangaDir(manga: Manga, source: Source): UniFile {
|
||||||
try {
|
try {
|
||||||
return downloadsDir
|
return downloadsDir.createDirectory(getSourceDirName(source))
|
||||||
.createDirectory(getSourceDirName(source))
|
.createDirectory(getMangaDirName(manga))
|
||||||
.createDirectory(getMangaDirName(manga))
|
|
||||||
} catch (e: NullPointerException) {
|
} catch (e: NullPointerException) {
|
||||||
throw Exception(context.getString(R.string.invalid_download_dir))
|
throw Exception(context.getString(R.string.invalid_download_dir))
|
||||||
}
|
}
|
||||||
@ -136,8 +134,6 @@ class DownloadProvider(private val context: Context) {
|
|||||||
val sourceDir = findSourceDir(source)
|
val sourceDir = findSourceDir(source)
|
||||||
val mangaDir = sourceDir?.findFile(DiskUtil.buildValidFilename(from))
|
val mangaDir = sourceDir?.findFile(DiskUtil.buildValidFilename(from))
|
||||||
mangaDir?.renameTo(to)
|
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 manga the manga of the chapter.
|
||||||
* @param source the source 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()
|
val mangaDir = findMangaDir(manga, source) ?: return emptyList()
|
||||||
return mangaDir.listFiles()!!.asList().filter {
|
return mangaDir.listFiles()!!.asList().filter {
|
||||||
(chapters.find { chp ->
|
(chapters.find { chp ->
|
||||||
@ -170,7 +170,6 @@ class DownloadProvider(private val context: Context) {
|
|||||||
return chapters.mapNotNull { mangaDir.findFile("${getChapterDirName(it)}_tmp") }
|
return chapters.mapNotNull { mangaDir.findFile("${getChapterDirName(it)}_tmp") }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the download directory name for a source.
|
* Returns the download directory name for a source.
|
||||||
*
|
*
|
||||||
@ -213,5 +212,4 @@ class DownloadProvider(private val context: Context) {
|
|||||||
DiskUtil.buildValidFilename(chapter.name)
|
DiskUtil.buildValidFilename(chapter.name)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -221,7 +221,6 @@ class DownloadService : Service() {
|
|||||||
.setContentTitle(getString(R.string.download_notifier_downloader_title))
|
.setContentTitle(getString(R.string.download_notifier_downloader_title))
|
||||||
.build()
|
.build()
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
interface DownloadServiceListener {
|
interface DownloadServiceListener {
|
||||||
|
@ -15,8 +15,8 @@ import uy.kohesive.injekt.injectLazy
|
|||||||
* @param context the application context.
|
* @param context the application context.
|
||||||
*/
|
*/
|
||||||
class DownloadStore(
|
class DownloadStore(
|
||||||
context: Context,
|
context: Context,
|
||||||
private val sourceManager: SourceManager
|
private val sourceManager: SourceManager
|
||||||
) {
|
) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -133,5 +133,4 @@ class DownloadStore(
|
|||||||
* @param order the order of the download in the queue.
|
* @param order the order of the download in the queue.
|
||||||
*/
|
*/
|
||||||
data class DownloadObject(val mangaId: Long, val chapterId: Long, val order: Int)
|
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.ImageUtil
|
||||||
import eu.kanade.tachiyomi.util.system.launchNow
|
import eu.kanade.tachiyomi.util.system.launchNow
|
||||||
import eu.kanade.tachiyomi.util.system.launchUI
|
import eu.kanade.tachiyomi.util.system.launchUI
|
||||||
|
import java.io.File
|
||||||
import kotlinx.coroutines.async
|
import kotlinx.coroutines.async
|
||||||
import okhttp3.Response
|
import okhttp3.Response
|
||||||
import rx.Observable
|
import rx.Observable
|
||||||
@ -28,7 +29,6 @@ import rx.android.schedulers.AndroidSchedulers
|
|||||||
import rx.schedulers.Schedulers
|
import rx.schedulers.Schedulers
|
||||||
import rx.subscriptions.CompositeSubscription
|
import rx.subscriptions.CompositeSubscription
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import java.io.File
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class is the one in charge of downloading chapters.
|
* This class is the one in charge of downloading chapters.
|
||||||
@ -45,10 +45,10 @@ import java.io.File
|
|||||||
* @param sourceManager the source manager.
|
* @param sourceManager the source manager.
|
||||||
*/
|
*/
|
||||||
class Downloader(
|
class Downloader(
|
||||||
private val context: Context,
|
private val context: Context,
|
||||||
private val provider: DownloadProvider,
|
private val provider: DownloadProvider,
|
||||||
private val cache: DownloadCache,
|
private val cache: DownloadCache,
|
||||||
private val sourceManager: SourceManager
|
private val sourceManager: SourceManager
|
||||||
) {
|
) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -129,12 +129,11 @@ class Downloader(
|
|||||||
if (notifier.paused) {
|
if (notifier.paused) {
|
||||||
if (queue.isEmpty()) {
|
if (queue.isEmpty()) {
|
||||||
notifier.dismiss()
|
notifier.dismiss()
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
notifier.paused = false
|
notifier.paused = false
|
||||||
notifier.onDownloadPaused()
|
notifier.onDownloadPaused()
|
||||||
}
|
}
|
||||||
}else {
|
} else {
|
||||||
notifier.dismiss()
|
notifier.dismiss()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -164,7 +163,7 @@ class Downloader(
|
|||||||
fun clearQueue(isNotification: Boolean = false) {
|
fun clearQueue(isNotification: Boolean = false) {
|
||||||
destroySubscriptions()
|
destroySubscriptions()
|
||||||
|
|
||||||
//Needed to update the chapter view
|
// Needed to update the chapter view
|
||||||
if (isNotification) {
|
if (isNotification) {
|
||||||
queue
|
queue
|
||||||
.filter { it.status == Download.QUEUE }
|
.filter { it.status == Download.QUEUE }
|
||||||
@ -180,7 +179,7 @@ class Downloader(
|
|||||||
* @param isNotification value that determines if status is set (needed for view updates)
|
* @param isNotification value that determines if status is set (needed for view updates)
|
||||||
*/
|
*/
|
||||||
fun clearQueue(manga: Manga, isNotification: Boolean = false) {
|
fun clearQueue(manga: Manga, isNotification: Boolean = false) {
|
||||||
//Needed to update the chapter view
|
// Needed to update the chapter view
|
||||||
if (isNotification) {
|
if (isNotification) {
|
||||||
queue
|
queue
|
||||||
.filter { it.status == Download.QUEUE && it.manga.id == manga.id }
|
.filter { it.status == Download.QUEUE && it.manga.id == manga.id }
|
||||||
@ -318,7 +317,6 @@ class Downloader(
|
|||||||
notifier.onError(error.message, download.chapter.name)
|
notifier.onError(error.message, download.chapter.name)
|
||||||
download
|
download
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -448,8 +446,12 @@ class Downloader(
|
|||||||
* @param tmpDir the directory where the download is currently stored.
|
* @param tmpDir the directory where the download is currently stored.
|
||||||
* @param dirname the real (non temporary) directory name of the download.
|
* @param dirname the real (non temporary) directory name of the download.
|
||||||
*/
|
*/
|
||||||
private fun ensureSuccessfulDownload(download: Download, mangaDir: UniFile,
|
private fun ensureSuccessfulDownload(
|
||||||
tmpDir: UniFile, dirname: String) {
|
download: Download,
|
||||||
|
mangaDir: UniFile,
|
||||||
|
tmpDir: UniFile,
|
||||||
|
dirname: String
|
||||||
|
) {
|
||||||
|
|
||||||
// Ensure that the chapter folder has all the images.
|
// Ensure that the chapter folder has all the images.
|
||||||
val downloadedImages = tmpDir.listFiles().orEmpty().filterNot { it.name!!.endsWith(".tmp") }
|
val downloadedImages = tmpDir.listFiles().orEmpty().filterNot { it.name!!.endsWith(".tmp") }
|
||||||
@ -497,5 +499,4 @@ class Downloader(
|
|||||||
companion object {
|
companion object {
|
||||||
const val TMP_DIR_SUFFIX = "_tmp"
|
const val TMP_DIR_SUFFIX = "_tmp"
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -47,4 +47,4 @@ class Download(val source: HttpSource, val manga: Manga, val chapter: Chapter) {
|
|||||||
const val DOWNLOADED = 3
|
const val DOWNLOADED = 3
|
||||||
const val ERROR = 4
|
const val ERROR = 4
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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.database.models.Manga
|
||||||
import eu.kanade.tachiyomi.data.download.DownloadStore
|
import eu.kanade.tachiyomi.data.download.DownloadStore
|
||||||
import eu.kanade.tachiyomi.source.model.Page
|
import eu.kanade.tachiyomi.source.model.Page
|
||||||
|
import java.util.concurrent.CopyOnWriteArrayList
|
||||||
import rx.Observable
|
import rx.Observable
|
||||||
import rx.subjects.PublishSubject
|
import rx.subjects.PublishSubject
|
||||||
import java.util.concurrent.CopyOnWriteArrayList
|
|
||||||
|
|
||||||
class DownloadQueue(
|
class DownloadQueue(
|
||||||
private val store: DownloadStore,
|
private val store: DownloadStore,
|
||||||
private val queue: MutableList<Download> = CopyOnWriteArrayList<Download>())
|
private val queue: MutableList<Download> = CopyOnWriteArrayList<Download>()
|
||||||
: List<Download> by queue {
|
) :
|
||||||
|
List<Download> by queue {
|
||||||
|
|
||||||
private val statusSubject = PublishSubject.create<Download>()
|
private val statusSubject = PublishSubject.create<Download>()
|
||||||
|
|
||||||
@ -89,8 +90,7 @@ class DownloadQueue(
|
|||||||
} else if (download.status == Download.DOWNLOADED || download.status == Download.ERROR) {
|
} else if (download.status == Download.DOWNLOADED || download.status == Download.ERROR) {
|
||||||
setPagesSubject(download.pages, null)
|
setPagesSubject(download.pages, null)
|
||||||
downloadListeners.forEach { it.updateDownload(download) }
|
downloadListeners.forEach { it.updateDownload(download) }
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
downloadListeners.forEach { it.updateDownload(download) }
|
downloadListeners.forEach { it.updateDownload(download) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -111,7 +111,6 @@ class DownloadQueue(
|
|||||||
.onBackpressureBuffer()
|
.onBackpressureBuffer()
|
||||||
.filter { it == Page.READY }
|
.filter { it == Page.READY }
|
||||||
.map { download }
|
.map { download }
|
||||||
|
|
||||||
} else if (download.status == Download.DOWNLOADED || download.status == Download.ERROR) {
|
} else if (download.status == Download.DOWNLOADED || download.status == Download.ERROR) {
|
||||||
setPagesSubject(download.pages, null)
|
setPagesSubject(download.pages, null)
|
||||||
downloadListeners.forEach { it.updateDownload(download) }
|
downloadListeners.forEach { it.updateDownload(download) }
|
||||||
@ -140,5 +139,4 @@ class DownloadQueue(
|
|||||||
interface DownloadListener {
|
interface DownloadListener {
|
||||||
fun updateDownload(download: Download)
|
fun updateDownload(download: Download)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
|
@ -5,7 +5,11 @@ import android.util.Log
|
|||||||
import com.bumptech.glide.Priority
|
import com.bumptech.glide.Priority
|
||||||
import com.bumptech.glide.load.DataSource
|
import com.bumptech.glide.load.DataSource
|
||||||
import com.bumptech.glide.load.data.DataFetcher
|
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> {
|
open class FileFetcher(private val file: File) : DataFetcher<InputStream> {
|
||||||
|
|
||||||
@ -48,4 +52,4 @@ open class FileFetcher(private val file: File) : DataFetcher<InputStream> {
|
|||||||
override fun getDataSource(): DataSource {
|
override fun getDataSource(): DataSource {
|
||||||
return DataSource.LOCAL
|
return DataSource.LOCAL
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,10 +16,12 @@ import java.io.InputStream
|
|||||||
* @param manga the manga of the cover to load.
|
* @param manga the manga of the cover to load.
|
||||||
* @param file the file where this cover should be. It may exists or not.
|
* @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 manga: Manga,
|
private val networkFetcher: DataFetcher<InputStream>,
|
||||||
private val file: File)
|
private val manga: Manga,
|
||||||
: FileFetcher(file) {
|
private val file: File
|
||||||
|
) :
|
||||||
|
FileFetcher(file) {
|
||||||
|
|
||||||
override fun loadData(priority: Priority, callback: DataFetcher.DataCallback<in InputStream>) {
|
override fun loadData(priority: Priority, callback: DataFetcher.DataCallback<in InputStream>) {
|
||||||
if (!file.exists()) {
|
if (!file.exists()) {
|
||||||
@ -52,7 +54,6 @@ class LibraryMangaUrlFetcher(private val networkFetcher: DataFetcher<InputStream
|
|||||||
override fun onLoadFailed(e: Exception) {
|
override fun onLoadFailed(e: Exception) {
|
||||||
callback.onLoadFailed(e)
|
callback.onLoadFailed(e)
|
||||||
}
|
}
|
||||||
|
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
loadFromFile(callback)
|
loadFromFile(callback)
|
||||||
@ -68,5 +69,4 @@ class LibraryMangaUrlFetcher(private val networkFetcher: DataFetcher<InputStream
|
|||||||
super.cancel()
|
super.cancel()
|
||||||
networkFetcher.cancel()
|
networkFetcher.cancel()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
|
@ -3,18 +3,22 @@ package eu.kanade.tachiyomi.data.glide
|
|||||||
import android.util.LruCache
|
import android.util.LruCache
|
||||||
import com.bumptech.glide.integration.okhttp3.OkHttpStreamFetcher
|
import com.bumptech.glide.integration.okhttp3.OkHttpStreamFetcher
|
||||||
import com.bumptech.glide.load.Options
|
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.cache.CoverCache
|
||||||
import eu.kanade.tachiyomi.data.database.models.Manga
|
import eu.kanade.tachiyomi.data.database.models.Manga
|
||||||
import eu.kanade.tachiyomi.network.NetworkHelper
|
import eu.kanade.tachiyomi.network.NetworkHelper
|
||||||
import eu.kanade.tachiyomi.source.SourceManager
|
import eu.kanade.tachiyomi.source.SourceManager
|
||||||
import eu.kanade.tachiyomi.source.online.HttpSource
|
import eu.kanade.tachiyomi.source.online.HttpSource
|
||||||
|
import java.io.File
|
||||||
|
import java.io.InputStream
|
||||||
import uy.kohesive.injekt.Injekt
|
import uy.kohesive.injekt.Injekt
|
||||||
import uy.kohesive.injekt.api.get
|
import uy.kohesive.injekt.api.get
|
||||||
import uy.kohesive.injekt.injectLazy
|
import uy.kohesive.injekt.injectLazy
|
||||||
import java.io.File
|
|
||||||
import java.io.InputStream
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A class for loading a cover associated with a [Manga] that can be present in our own cache.
|
* 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 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.
|
* @param height the height of the view where the resource will be loaded.
|
||||||
*/
|
*/
|
||||||
override fun buildLoadData(manga: Manga, width: Int, height: Int,
|
override fun buildLoadData(
|
||||||
options: Options): ModelLoader.LoadData<InputStream>? {
|
manga: Manga,
|
||||||
|
width: Int,
|
||||||
|
height: Int,
|
||||||
|
options: Options
|
||||||
|
): ModelLoader.LoadData<InputStream>? {
|
||||||
// Check thumbnail is not null or empty
|
// Check thumbnail is not null or empty
|
||||||
val url = manga.thumbnail_url
|
val url = manga.thumbnail_url
|
||||||
if (url == null || url.isEmpty()) {
|
if (url == null || url.isEmpty()) {
|
||||||
@ -142,5 +150,4 @@ class MangaModelLoader : ModelLoader<Manga, InputStream> {
|
|||||||
value
|
value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -24,4 +24,4 @@ class MangaSignature(manga: Manga, file: File) : Key {
|
|||||||
override fun updateDiskCacheKey(md: MessageDigest) {
|
override fun updateDiskCacheKey(md: MessageDigest) {
|
||||||
md.update(key.toByteArray(Key.CHARSET))
|
md.update(key.toByteArray(Key.CHARSET))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,10 +14,10 @@ import java.io.InputStream
|
|||||||
class PassthroughModelLoader : ModelLoader<InputStream, InputStream> {
|
class PassthroughModelLoader : ModelLoader<InputStream, InputStream> {
|
||||||
|
|
||||||
override fun buildLoadData(
|
override fun buildLoadData(
|
||||||
model: InputStream,
|
model: InputStream,
|
||||||
width: Int,
|
width: Int,
|
||||||
height: Int,
|
height: Int,
|
||||||
options: Options
|
options: Options
|
||||||
): ModelLoader.LoadData<InputStream>? {
|
): ModelLoader.LoadData<InputStream>? {
|
||||||
return ModelLoader.LoadData(ObjectKey(model), Fetcher(model))
|
return ModelLoader.LoadData(ObjectKey(model), Fetcher(model))
|
||||||
}
|
}
|
||||||
@ -49,12 +49,11 @@ class PassthroughModelLoader : ModelLoader<InputStream, InputStream> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun loadData(
|
override fun loadData(
|
||||||
priority: Priority,
|
priority: Priority,
|
||||||
callback: DataFetcher.DataCallback<in InputStream>
|
callback: DataFetcher.DataCallback<in InputStream>
|
||||||
) {
|
) {
|
||||||
callback.onDataReady(stream)
|
callback.onDataReady(stream)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -63,12 +62,11 @@ class PassthroughModelLoader : ModelLoader<InputStream, InputStream> {
|
|||||||
class Factory : ModelLoaderFactory<InputStream, InputStream> {
|
class Factory : ModelLoaderFactory<InputStream, InputStream> {
|
||||||
|
|
||||||
override fun build(
|
override fun build(
|
||||||
multiFactory: MultiModelLoaderFactory
|
multiFactory: MultiModelLoaderFactory
|
||||||
): ModelLoader<InputStream, InputStream> {
|
): ModelLoader<InputStream, InputStream> {
|
||||||
return PassthroughModelLoader()
|
return PassthroughModelLoader()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun teardown() {}
|
override fun teardown() {}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -13,9 +13,9 @@ import com.bumptech.glide.module.AppGlideModule
|
|||||||
import com.bumptech.glide.request.RequestOptions
|
import com.bumptech.glide.request.RequestOptions
|
||||||
import eu.kanade.tachiyomi.data.database.models.Manga
|
import eu.kanade.tachiyomi.data.database.models.Manga
|
||||||
import eu.kanade.tachiyomi.network.NetworkHelper
|
import eu.kanade.tachiyomi.network.NetworkHelper
|
||||||
|
import java.io.InputStream
|
||||||
import uy.kohesive.injekt.Injekt
|
import uy.kohesive.injekt.Injekt
|
||||||
import uy.kohesive.injekt.api.get
|
import uy.kohesive.injekt.api.get
|
||||||
import java.io.InputStream
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class used to update Glide module settings
|
* Class used to update Glide module settings
|
||||||
@ -26,8 +26,8 @@ class TachiGlideModule : AppGlideModule() {
|
|||||||
override fun applyOptions(context: Context, builder: GlideBuilder) {
|
override fun applyOptions(context: Context, builder: GlideBuilder) {
|
||||||
builder.setDiskCache(InternalCacheDiskCacheFactory(context, 50 * 1024 * 1024))
|
builder.setDiskCache(InternalCacheDiskCacheFactory(context, 50 * 1024 * 1024))
|
||||||
builder.setDefaultRequestOptions(RequestOptions().format(DecodeFormat.PREFER_RGB_565))
|
builder.setDefaultRequestOptions(RequestOptions().format(DecodeFormat.PREFER_RGB_565))
|
||||||
//val memoryCacheSizeBytes = 1024 * 1024 * 100 // 100mb
|
// val memoryCacheSizeBytes = 1024 * 1024 * 100 // 100mb
|
||||||
//builder.setMemoryCache(LruResourceCache(memoryCacheSizeBytes.toLong()))
|
// builder.setMemoryCache(LruResourceCache(memoryCacheSizeBytes.toLong()))
|
||||||
|
|
||||||
/* builder.setDefaultTransitionOptions(
|
/* builder.setDefaultTransitionOptions(
|
||||||
Drawable::class.java,
|
Drawable::class.java,
|
||||||
|
@ -5,9 +5,9 @@ import com.evernote.android.job.JobManager
|
|||||||
import com.evernote.android.job.JobRequest
|
import com.evernote.android.job.JobRequest
|
||||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||||
import eu.kanade.tachiyomi.data.preference.getOrDefault
|
import eu.kanade.tachiyomi.data.preference.getOrDefault
|
||||||
|
import java.util.concurrent.TimeUnit
|
||||||
import uy.kohesive.injekt.Injekt
|
import uy.kohesive.injekt.Injekt
|
||||||
import uy.kohesive.injekt.api.get
|
import uy.kohesive.injekt.api.get
|
||||||
import java.util.concurrent.TimeUnit
|
|
||||||
|
|
||||||
class LibraryUpdateJob : Job() {
|
class LibraryUpdateJob : Job() {
|
||||||
|
|
||||||
|
@ -39,5 +39,4 @@ object LibraryUpdateRanker {
|
|||||||
compareValues(mangaFirst.currentTitle(), mangaSecond.currentTitle())
|
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.lang.chop
|
||||||
import eu.kanade.tachiyomi.util.system.notification
|
import eu.kanade.tachiyomi.util.system.notification
|
||||||
import eu.kanade.tachiyomi.util.system.notificationManager
|
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.CoroutineExceptionHandler
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.GlobalScope
|
import kotlinx.coroutines.GlobalScope
|
||||||
@ -50,10 +54,6 @@ import rx.schedulers.Schedulers
|
|||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import uy.kohesive.injekt.Injekt
|
import uy.kohesive.injekt.Injekt
|
||||||
import uy.kohesive.injekt.api.get
|
import uy.kohesive.injekt.api.get
|
||||||
import java.util.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
|
* This class will take care of updating the chapters of the manga from the library. It can be
|
||||||
@ -127,8 +127,8 @@ class LibraryUpdateService(
|
|||||||
*/
|
*/
|
||||||
enum class Target {
|
enum class Target {
|
||||||
CHAPTERS, // Manga chapters
|
CHAPTERS, // Manga chapters
|
||||||
DETAILS, // Manga metadata
|
DETAILS, // Manga metadata
|
||||||
TRACKING // Tracking metadata
|
TRACKING // Tracking metadata
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
@ -10,6 +10,7 @@ import android.content.Intent
|
|||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.Handler
|
import android.os.Handler
|
||||||
|
import eu.kanade.tachiyomi.BuildConfig.APPLICATION_ID as ID
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
import eu.kanade.tachiyomi.data.backup.BackupRestoreService
|
import eu.kanade.tachiyomi.data.backup.BackupRestoreService
|
||||||
import eu.kanade.tachiyomi.data.database.DatabaseHelper
|
import eu.kanade.tachiyomi.data.database.DatabaseHelper
|
||||||
@ -27,12 +28,10 @@ import eu.kanade.tachiyomi.util.storage.DiskUtil
|
|||||||
import eu.kanade.tachiyomi.util.storage.getUriCompat
|
import eu.kanade.tachiyomi.util.storage.getUriCompat
|
||||||
import eu.kanade.tachiyomi.util.system.notificationManager
|
import eu.kanade.tachiyomi.util.system.notificationManager
|
||||||
import eu.kanade.tachiyomi.util.system.toast
|
import eu.kanade.tachiyomi.util.system.toast
|
||||||
|
import java.io.File
|
||||||
import uy.kohesive.injekt.Injekt
|
import uy.kohesive.injekt.Injekt
|
||||||
import uy.kohesive.injekt.api.get
|
import uy.kohesive.injekt.api.get
|
||||||
import uy.kohesive.injekt.injectLazy
|
import uy.kohesive.injekt.injectLazy
|
||||||
import java.io.File
|
|
||||||
import eu.kanade.tachiyomi.BuildConfig.APPLICATION_ID as ID
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Global [BroadcastReceiver] that runs on UI thread
|
* Global [BroadcastReceiver] that runs on UI thread
|
||||||
@ -113,7 +112,6 @@ class NotificationReceiver : BroadcastReceiver() {
|
|||||||
type = "image/*"
|
type = "image/*"
|
||||||
}
|
}
|
||||||
// Close Navigation Shade
|
// Close Navigation Shade
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -217,7 +215,6 @@ class NotificationReceiver : BroadcastReceiver() {
|
|||||||
// Called to cancel restore
|
// Called to cancel restore
|
||||||
private const val ACTION_CANCEL_RESTORE = "$ID.$NAME.CANCEL_RESTORE"
|
private const val ACTION_CANCEL_RESTORE = "$ID.$NAME.CANCEL_RESTORE"
|
||||||
|
|
||||||
|
|
||||||
// Called to open chapter
|
// Called to open chapter
|
||||||
private const val ACTION_OPEN_CHAPTER = "$ID.$NAME.ACTION_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
|
* @param notificationId id of notification
|
||||||
* @return [PendingIntent]
|
* @return [PendingIntent]
|
||||||
*/
|
*/
|
||||||
internal fun dismissNotification(context: Context, notificationId: Int, groupId: Int? =
|
internal fun dismissNotification(
|
||||||
null) {
|
context: Context,
|
||||||
|
notificationId: Int,
|
||||||
|
groupId: Int? =
|
||||||
|
null
|
||||||
|
) {
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||||
val groupKey = context.notificationManager.activeNotifications.find {
|
val groupKey = context.notificationManager.activeNotifications.find {
|
||||||
it.id == notificationId
|
it.id == notificationId
|
||||||
@ -350,7 +351,7 @@ class NotificationReceiver : BroadcastReceiver() {
|
|||||||
* @return [PendingIntent]
|
* @return [PendingIntent]
|
||||||
*/
|
*/
|
||||||
internal fun shareImagePendingBroadcast(context: Context, path: String, notificationId: Int): PendingIntent {
|
internal fun shareImagePendingBroadcast(context: Context, path: String, notificationId: Int): PendingIntent {
|
||||||
//val shareIntent = ShareStartingActivity.newIntent(context, path)
|
// val shareIntent = ShareStartingActivity.newIntent(context, path)
|
||||||
val shareIntent = Intent(Intent.ACTION_SEND).apply {
|
val shareIntent = Intent(Intent.ACTION_SEND).apply {
|
||||||
val uri = File(path).getUriCompat(context)
|
val uri = File(path).getUriCompat(context)
|
||||||
putExtra(Intent.EXTRA_STREAM, uri)
|
putExtra(Intent.EXTRA_STREAM, uri)
|
||||||
@ -358,7 +359,7 @@ class NotificationReceiver : BroadcastReceiver() {
|
|||||||
clipData = ClipData.newRawUri(null, uri)
|
clipData = ClipData.newRawUri(null, uri)
|
||||||
type = "image/*"
|
type = "image/*"
|
||||||
}
|
}
|
||||||
//val shareIntent2 = Intent.createChooser(shareIntent, context.getString(R.string.action_share))
|
// val shareIntent2 = Intent.createChooser(shareIntent, context.getString(R.string.action_share))
|
||||||
return PendingIntent.getActivity(context, 0, shareIntent, PendingIntent
|
return PendingIntent.getActivity(context, 0, shareIntent, PendingIntent
|
||||||
.FLAG_CANCEL_CURRENT)
|
.FLAG_CANCEL_CURRENT)
|
||||||
}
|
}
|
||||||
@ -387,8 +388,12 @@ class NotificationReceiver : BroadcastReceiver() {
|
|||||||
* @param manga manga of chapter
|
* @param manga manga of chapter
|
||||||
* @param chapter chapter that needs to be opened
|
* @param chapter chapter that needs to be opened
|
||||||
*/
|
*/
|
||||||
internal fun openChapterPendingActivity(context: Context, manga: Manga, chapter:
|
internal fun openChapterPendingActivity(
|
||||||
Chapter): PendingIntent {
|
context: Context,
|
||||||
|
manga: Manga,
|
||||||
|
chapter:
|
||||||
|
Chapter
|
||||||
|
): PendingIntent {
|
||||||
val newIntent = ReaderActivity.newIntent(context, manga, chapter)
|
val newIntent = ReaderActivity.newIntent(context, manga, chapter)
|
||||||
return PendingIntent.getActivity(context, manga.id.hashCode(), newIntent, PendingIntent
|
return PendingIntent.getActivity(context, manga.id.hashCode(), newIntent, PendingIntent
|
||||||
.FLAG_UPDATE_CURRENT)
|
.FLAG_UPDATE_CURRENT)
|
||||||
@ -440,15 +445,19 @@ class NotificationReceiver : BroadcastReceiver() {
|
|||||||
return PendingIntent.getActivity(context, 0, toLaunch, 0)
|
return PendingIntent.getActivity(context, 0, toLaunch, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns [PendingIntent] that marks a chapter as read and deletes it if preferred
|
* Returns [PendingIntent] that marks a chapter as read and deletes it if preferred
|
||||||
*
|
*
|
||||||
* @param context context of application
|
* @param context context of application
|
||||||
* @param manga manga of chapter
|
* @param manga manga of chapter
|
||||||
*/
|
*/
|
||||||
internal fun markAsReadPendingBroadcast(context: Context, manga: Manga, chapters:
|
internal fun markAsReadPendingBroadcast(
|
||||||
Array<Chapter>, groupId: Int):
|
context: Context,
|
||||||
|
manga: Manga,
|
||||||
|
chapters:
|
||||||
|
Array<Chapter>,
|
||||||
|
groupId: Int
|
||||||
|
):
|
||||||
PendingIntent {
|
PendingIntent {
|
||||||
val newIntent = Intent(context, NotificationReceiver::class.java).apply {
|
val newIntent = Intent(context, NotificationReceiver::class.java).apply {
|
||||||
action = ACTION_MARK_AS_READ
|
action = ACTION_MARK_AS_READ
|
||||||
@ -486,4 +495,4 @@ class NotificationReceiver : BroadcastReceiver() {
|
|||||||
return PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)
|
return PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -38,6 +38,7 @@ object Notifications {
|
|||||||
const val CHANNEL_NEW_CHAPTERS = "new_chapters_channel"
|
const val CHANNEL_NEW_CHAPTERS = "new_chapters_channel"
|
||||||
const val ID_NEW_CHAPTERS = -301
|
const val ID_NEW_CHAPTERS = -301
|
||||||
const val GROUP_NEW_CHAPTERS = "eu.kanade.tachiyomi.NEW_CHAPTERS"
|
const val GROUP_NEW_CHAPTERS = "eu.kanade.tachiyomi.NEW_CHAPTERS"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Notification channel and ids used by the library updater.
|
* 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_COMPLETE = -502
|
||||||
const val ID_RESTORE_ERROR = -503
|
const val ID_RESTORE_ERROR = -503
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates the notification channels introduced in Android Oreo.
|
* Creates the notification channels introduced in Android Oreo.
|
||||||
*
|
*
|
||||||
@ -58,36 +58,37 @@ object Notifications {
|
|||||||
fun createChannels(context: Context) {
|
fun createChannels(context: Context) {
|
||||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) return
|
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) return
|
||||||
|
|
||||||
val channels = listOf(
|
val channels = listOf(NotificationChannel(
|
||||||
NotificationChannel(
|
CHANNEL_COMMON,
|
||||||
CHANNEL_COMMON,
|
context.getString(R.string.channel_common),
|
||||||
context.getString(R.string.channel_common),
|
NotificationManager.IMPORTANCE_LOW
|
||||||
NotificationManager.IMPORTANCE_LOW
|
), NotificationChannel(
|
||||||
), NotificationChannel(
|
CHANNEL_LIBRARY,
|
||||||
CHANNEL_LIBRARY,
|
context.getString(R.string.channel_library_updates),
|
||||||
context.getString(R.string.channel_library_updates),
|
NotificationManager.IMPORTANCE_LOW
|
||||||
NotificationManager.IMPORTANCE_LOW
|
).apply {
|
||||||
).apply {
|
setShowBadge(false)
|
||||||
setShowBadge(false)
|
}, NotificationChannel(
|
||||||
}, NotificationChannel(
|
CHANNEL_DOWNLOADER,
|
||||||
CHANNEL_DOWNLOADER,
|
context.getString(R.string.channel_downloader),
|
||||||
context.getString(R.string.channel_downloader),
|
NotificationManager.IMPORTANCE_LOW
|
||||||
NotificationManager.IMPORTANCE_LOW
|
).apply {
|
||||||
).apply {
|
setShowBadge(false)
|
||||||
setShowBadge(false)
|
}, NotificationChannel(
|
||||||
}, NotificationChannel(
|
CHANNEL_UPDATES_TO_EXTS,
|
||||||
CHANNEL_UPDATES_TO_EXTS,
|
context.getString(R.string.channel_ext_updates),
|
||||||
context.getString(R.string.channel_ext_updates),
|
NotificationManager.IMPORTANCE_DEFAULT
|
||||||
NotificationManager.IMPORTANCE_DEFAULT
|
), NotificationChannel(
|
||||||
), NotificationChannel(
|
CHANNEL_NEW_CHAPTERS,
|
||||||
CHANNEL_NEW_CHAPTERS,
|
context.getString(R.string.channel_new_chapters),
|
||||||
context.getString(R.string.channel_new_chapters),
|
NotificationManager.IMPORTANCE_DEFAULT
|
||||||
NotificationManager.IMPORTANCE_DEFAULT
|
), NotificationChannel(
|
||||||
), NotificationChannel(CHANNEL_RESTORE, context.getString(R.string.channel_backup_restore),
|
CHANNEL_RESTORE,
|
||||||
NotificationManager.IMPORTANCE_LOW).apply {
|
context.getString(R.string.channel_backup_restore),
|
||||||
setShowBadge(false)
|
NotificationManager.IMPORTANCE_LOW
|
||||||
}
|
).apply {
|
||||||
)
|
setShowBadge(false)
|
||||||
|
})
|
||||||
context.notificationManager.createNotificationChannels(channels)
|
context.notificationManager.createNotificationChannels(channels)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -155,11 +155,9 @@ object PreferenceKeys {
|
|||||||
|
|
||||||
fun sourceSharedPref(sourceId: Long) = "source_$sourceId"
|
fun sourceSharedPref(sourceId: Long) = "source_$sourceId"
|
||||||
|
|
||||||
|
|
||||||
fun trackUsername(syncId: Int) = "pref_mangasync_username_$syncId"
|
fun trackUsername(syncId: Int) = "pref_mangasync_username_$syncId"
|
||||||
|
|
||||||
fun trackPassword(syncId: Int) = "pref_mangasync_password_$syncId"
|
fun trackPassword(syncId: Int) = "pref_mangasync_password_$syncId"
|
||||||
|
|
||||||
fun trackToken(syncId: Int) = "track_token_$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.Preference
|
||||||
import com.f2prateek.rx.preferences.RxSharedPreferences
|
import com.f2prateek.rx.preferences.RxSharedPreferences
|
||||||
import eu.kanade.tachiyomi.R
|
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.data.track.TrackService
|
||||||
import eu.kanade.tachiyomi.source.Source
|
import eu.kanade.tachiyomi.source.Source
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.text.DateFormat
|
import java.text.DateFormat
|
||||||
import java.text.SimpleDateFormat
|
import java.text.SimpleDateFormat
|
||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
import eu.kanade.tachiyomi.data.preference.PreferenceKeys as Keys
|
|
||||||
|
|
||||||
fun <T> Preference<T>.getOrDefault(): T = get() ?: defaultValue()!!
|
fun <T> Preference<T>.getOrDefault(): T = get() ?: defaultValue()!!
|
||||||
|
|
||||||
|
@ -2,10 +2,10 @@ package eu.kanade.tachiyomi.data.track
|
|||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import eu.kanade.tachiyomi.data.track.anilist.Anilist
|
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.kitsu.Kitsu
|
||||||
import eu.kanade.tachiyomi.data.track.myanimelist.MyAnimeList
|
import eu.kanade.tachiyomi.data.track.myanimelist.MyAnimeList
|
||||||
import eu.kanade.tachiyomi.data.track.shikimori.Shikimori
|
import eu.kanade.tachiyomi.data.track.shikimori.Shikimori
|
||||||
import eu.kanade.tachiyomi.data.track.bangumi.Bangumi
|
|
||||||
|
|
||||||
class TrackManager(context: Context) {
|
class TrackManager(context: Context) {
|
||||||
|
|
||||||
@ -32,5 +32,4 @@ class TrackManager(context: Context) {
|
|||||||
fun getService(id: Int) = services.find { it.id == id }
|
fun getService(id: Int) = services.find { it.id == id }
|
||||||
|
|
||||||
fun hasLoggedServices() = services.any { it.isLogged }
|
fun hasLoggedServices() = services.any { it.isLogged }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -3,8 +3,8 @@ package eu.kanade.tachiyomi.data.track
|
|||||||
import androidx.annotation.CallSuper
|
import androidx.annotation.CallSuper
|
||||||
import androidx.annotation.DrawableRes
|
import androidx.annotation.DrawableRes
|
||||||
import eu.kanade.tachiyomi.data.database.models.Track
|
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.preference.PreferencesHelper
|
||||||
|
import eu.kanade.tachiyomi.data.track.model.TrackSearch
|
||||||
import eu.kanade.tachiyomi.network.NetworkHelper
|
import eu.kanade.tachiyomi.network.NetworkHelper
|
||||||
import okhttp3.OkHttpClient
|
import okhttp3.OkHttpClient
|
||||||
import uy.kohesive.injekt.injectLazy
|
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.database.models.Track
|
||||||
import eu.kanade.tachiyomi.data.preference.getOrDefault
|
import eu.kanade.tachiyomi.data.preference.getOrDefault
|
||||||
import eu.kanade.tachiyomi.data.track.TrackService
|
import eu.kanade.tachiyomi.data.track.TrackService
|
||||||
import eu.kanade.tachiyomi.data.track.model.TrackSearch
|
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import uy.kohesive.injekt.injectLazy
|
import uy.kohesive.injekt.injectLazy
|
||||||
|
|
||||||
@ -144,25 +143,24 @@ class Anilist(private val context: Context, id: Int) : TrackService(id) {
|
|||||||
track.copyPersonalFrom(remoteTrack)
|
track.copyPersonalFrom(remoteTrack)
|
||||||
track.total_chapters = remoteTrack.total_chapters
|
track.total_chapters = remoteTrack.total_chapters
|
||||||
return track
|
return track
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun login(username: String, password: String) = login(password)
|
override suspend fun login(username: String, password: String) = login(password)
|
||||||
|
|
||||||
suspend fun login(token: String): Boolean {
|
suspend fun login(token: String): Boolean {
|
||||||
val oauth = api.createOAuth(token)
|
val oauth = api.createOAuth(token)
|
||||||
interceptor.setAuth(oauth)
|
interceptor.setAuth(oauth)
|
||||||
|
|
||||||
return try {
|
return try {
|
||||||
val currentUser = api.getCurrentUser()
|
val currentUser = api.getCurrentUser()
|
||||||
scorePreference.set(currentUser.second)
|
scorePreference.set(currentUser.second)
|
||||||
saveCredentials(currentUser.first.toString(), oauth.access_token)
|
saveCredentials(currentUser.first.toString(), oauth.access_token)
|
||||||
true
|
true
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Timber.e(e)
|
Timber.e(e)
|
||||||
logout()
|
logout()
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun logout() {
|
override fun logout() {
|
||||||
@ -184,7 +182,6 @@ class Anilist(private val context: Context, id: Int) : TrackService(id) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val READING = 1
|
const val READING = 1
|
||||||
const val COMPLETED = 2
|
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_5 = "POINT_5"
|
||||||
const val POINT_3 = "POINT_3"
|
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.database.models.Track
|
||||||
import eu.kanade.tachiyomi.data.track.model.TrackSearch
|
import eu.kanade.tachiyomi.data.track.model.TrackSearch
|
||||||
import eu.kanade.tachiyomi.network.jsonType
|
import eu.kanade.tachiyomi.network.jsonType
|
||||||
|
import java.util.Calendar
|
||||||
|
import java.util.concurrent.TimeUnit
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import okhttp3.MediaType
|
import okhttp3.MediaType
|
||||||
@ -19,8 +21,6 @@ import okhttp3.OkHttpClient
|
|||||||
import okhttp3.Request
|
import okhttp3.Request
|
||||||
import okhttp3.RequestBody.Companion.toRequestBody
|
import okhttp3.RequestBody.Companion.toRequestBody
|
||||||
import okhttp3.Response
|
import okhttp3.Response
|
||||||
import java.util.Calendar
|
|
||||||
import java.util.concurrent.TimeUnit
|
|
||||||
|
|
||||||
class AnilistApi(val client: OkHttpClient, interceptor: AnilistInterceptor) {
|
class AnilistApi(val client: OkHttpClient, interceptor: AnilistInterceptor) {
|
||||||
|
|
||||||
|
@ -3,7 +3,6 @@ package eu.kanade.tachiyomi.data.track.anilist
|
|||||||
import okhttp3.Interceptor
|
import okhttp3.Interceptor
|
||||||
import okhttp3.Response
|
import okhttp3.Response
|
||||||
|
|
||||||
|
|
||||||
class AnilistInterceptor(private val anilist: Anilist, private var token: String?) : Interceptor {
|
class AnilistInterceptor(private val anilist: Anilist, private var token: String?) : Interceptor {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -23,7 +22,7 @@ class AnilistInterceptor(private val anilist: Anilist, private var token: String
|
|||||||
if (token.isNullOrEmpty()) {
|
if (token.isNullOrEmpty()) {
|
||||||
throw Exception("Not authenticated with Anilist")
|
throw Exception("Not authenticated with Anilist")
|
||||||
}
|
}
|
||||||
if (oauth == null){
|
if (oauth == null) {
|
||||||
oauth = anilist.loadOAuth()
|
oauth = anilist.loadOAuth()
|
||||||
}
|
}
|
||||||
// Refresh access token if null or expired.
|
// Refresh access token if null or expired.
|
||||||
@ -54,5 +53,4 @@ class AnilistInterceptor(private val anilist: Anilist, private var token: String
|
|||||||
this.oauth = oauth
|
this.oauth = oauth
|
||||||
anilist.saveOAuth(oauth)
|
anilist.saveOAuth(oauth)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
|
@ -5,28 +5,30 @@ import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
|||||||
import eu.kanade.tachiyomi.data.preference.getOrDefault
|
import eu.kanade.tachiyomi.data.preference.getOrDefault
|
||||||
import eu.kanade.tachiyomi.data.track.TrackManager
|
import eu.kanade.tachiyomi.data.track.TrackManager
|
||||||
import eu.kanade.tachiyomi.data.track.model.TrackSearch
|
import eu.kanade.tachiyomi.data.track.model.TrackSearch
|
||||||
import uy.kohesive.injekt.injectLazy
|
|
||||||
import java.text.SimpleDateFormat
|
import java.text.SimpleDateFormat
|
||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
|
import uy.kohesive.injekt.injectLazy
|
||||||
|
|
||||||
data class OAuth(
|
data class OAuth(
|
||||||
val access_token: String,
|
val access_token: String,
|
||||||
val token_type: String,
|
val token_type: String,
|
||||||
val expires: Long,
|
val expires: Long,
|
||||||
val expires_in: Long) {
|
val expires_in: Long
|
||||||
|
) {
|
||||||
|
|
||||||
fun isExpired() = System.currentTimeMillis() > expires
|
fun isExpired() = System.currentTimeMillis() > expires
|
||||||
}
|
}
|
||||||
|
|
||||||
data class ALManga(
|
data class ALManga(
|
||||||
val media_id: Int,
|
val media_id: Int,
|
||||||
val title_romaji: String,
|
val title_romaji: String,
|
||||||
val image_url_lge: String,
|
val image_url_lge: String,
|
||||||
val description: String?,
|
val description: String?,
|
||||||
val type: String,
|
val type: String,
|
||||||
val publishing_status: String,
|
val publishing_status: String,
|
||||||
val start_date_fuzzy: Long,
|
val start_date_fuzzy: Long,
|
||||||
val total_chapters: Int) {
|
val total_chapters: Int
|
||||||
|
) {
|
||||||
|
|
||||||
fun toTrack() = TrackSearch.create(TrackManager.ANILIST).apply {
|
fun toTrack() = TrackSearch.create(TrackManager.ANILIST).apply {
|
||||||
media_id = this@ALManga.media_id
|
media_id = this@ALManga.media_id
|
||||||
|
@ -60,12 +60,12 @@ class Bangumi(private val context: Context, id: Int) : TrackService(id) {
|
|||||||
override suspend fun refresh(track: Track): Track {
|
override suspend fun refresh(track: Track): Track {
|
||||||
val statusTrack = api.statusLibManga(track)
|
val statusTrack = api.statusLibManga(track)
|
||||||
track.copyPersonalFrom(statusTrack!!)
|
track.copyPersonalFrom(statusTrack!!)
|
||||||
val remoteTrack = api.findLibManga(track)
|
val remoteTrack = api.findLibManga(track)
|
||||||
if(remoteTrack != null){
|
if (remoteTrack != null) {
|
||||||
track.total_chapters = remoteTrack.total_chapters
|
track.total_chapters = remoteTrack.total_chapters
|
||||||
track.status = remoteTrack.status
|
track.status = remoteTrack.status
|
||||||
}
|
}
|
||||||
return track
|
return track
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getLogo() = R.drawable.tracker_bangumi
|
override fun getLogo() = R.drawable.tracker_bangumi
|
||||||
|
@ -11,6 +11,7 @@ import eu.kanade.tachiyomi.data.track.TrackManager
|
|||||||
import eu.kanade.tachiyomi.data.track.model.TrackSearch
|
import eu.kanade.tachiyomi.data.track.model.TrackSearch
|
||||||
import eu.kanade.tachiyomi.network.POST
|
import eu.kanade.tachiyomi.network.POST
|
||||||
import eu.kanade.tachiyomi.network.await
|
import eu.kanade.tachiyomi.network.await
|
||||||
|
import java.net.URLEncoder
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import okhttp3.CacheControl
|
import okhttp3.CacheControl
|
||||||
@ -18,7 +19,6 @@ import okhttp3.FormBody
|
|||||||
import okhttp3.OkHttpClient
|
import okhttp3.OkHttpClient
|
||||||
import okhttp3.Request
|
import okhttp3.Request
|
||||||
import uy.kohesive.injekt.injectLazy
|
import uy.kohesive.injekt.injectLazy
|
||||||
import java.net.URLEncoder
|
|
||||||
|
|
||||||
class BangumiApi(private val client: OkHttpClient, interceptor: BangumiInterceptor) {
|
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()
|
private val authClient = client.newBuilder().addInterceptor(interceptor).build()
|
||||||
|
|
||||||
suspend fun addLibManga(track: Track): Track {
|
suspend fun addLibManga(track: Track): Track {
|
||||||
val body = FormBody.Builder()
|
val body = FormBody.Builder().add("rating", track.score.toInt().toString())
|
||||||
.add("rating", track.score.toInt().toString())
|
.add("status", track.toBangumiStatus()).build()
|
||||||
.add("status", track.toBangumiStatus())
|
val request =
|
||||||
.build()
|
Request.Builder().url("$apiUrl/collection/${track.media_id}/update").post(body).build()
|
||||||
val request = Request.Builder()
|
|
||||||
.url("$apiUrl/collection/${track.media_id}/update")
|
|
||||||
.post(body)
|
|
||||||
.build()
|
|
||||||
val response = authClient.newCall(request).await()
|
val response = authClient.newCall(request).await()
|
||||||
return track
|
return track
|
||||||
}
|
}
|
||||||
@ -41,22 +37,17 @@ class BangumiApi(private val client: OkHttpClient, interceptor: BangumiIntercept
|
|||||||
suspend fun updateLibManga(track: Track): Track {
|
suspend fun updateLibManga(track: Track): Track {
|
||||||
// chapter update
|
// chapter update
|
||||||
return withContext(Dispatchers.IO) {
|
return withContext(Dispatchers.IO) {
|
||||||
val body = FormBody.Builder()
|
val body =
|
||||||
.add("watched_eps", track.last_chapter_read.toString())
|
FormBody.Builder().add("watched_eps", track.last_chapter_read.toString()).build()
|
||||||
.build()
|
val request =
|
||||||
val request = Request.Builder()
|
Request.Builder().url("$apiUrl/subject/${track.media_id}/update/watched_eps")
|
||||||
.url("$apiUrl/subject/${track.media_id}/update/watched_eps")
|
.post(body).build()
|
||||||
.post(body)
|
|
||||||
.build()
|
|
||||||
|
|
||||||
// read status update
|
// read status update
|
||||||
val sbody = FormBody.Builder()
|
val sbody = FormBody.Builder().add("status", track.toBangumiStatus()).build()
|
||||||
.add("status", track.toBangumiStatus())
|
val srequest =
|
||||||
.build()
|
Request.Builder().url("$apiUrl/collection/${track.media_id}/update").post(sbody)
|
||||||
val srequest = Request.Builder()
|
.build()
|
||||||
.url("$apiUrl/collection/${track.media_id}/update")
|
|
||||||
.post(sbody)
|
|
||||||
.build()
|
|
||||||
authClient.newCall(srequest).execute()
|
authClient.newCall(srequest).execute()
|
||||||
authClient.newCall(request).execute()
|
authClient.newCall(request).execute()
|
||||||
track
|
track
|
||||||
@ -67,13 +58,8 @@ class BangumiApi(private val client: OkHttpClient, interceptor: BangumiIntercept
|
|||||||
return withContext(Dispatchers.IO) {
|
return withContext(Dispatchers.IO) {
|
||||||
val url = Uri.parse(
|
val url = Uri.parse(
|
||||||
"$apiUrl/search/subject/${URLEncoder.encode(search, Charsets.UTF_8.name())}"
|
"$apiUrl/search/subject/${URLEncoder.encode(search, Charsets.UTF_8.name())}"
|
||||||
).buildUpon()
|
).buildUpon().appendQueryParameter("max_results", "20").build()
|
||||||
.appendQueryParameter("max_results", "20")
|
val request = Request.Builder().url(url.toString()).get().build()
|
||||||
.build()
|
|
||||||
val request = Request.Builder()
|
|
||||||
.url(url.toString())
|
|
||||||
.get()
|
|
||||||
.build()
|
|
||||||
|
|
||||||
val netResponse = authClient.newCall(request).await()
|
val netResponse = authClient.newCall(request).await()
|
||||||
var responseBody = netResponse.body?.string().orEmpty()
|
var responseBody = netResponse.body?.string().orEmpty()
|
||||||
@ -106,9 +92,9 @@ class BangumiApi(private val client: OkHttpClient, interceptor: BangumiIntercept
|
|||||||
return Track.create(TrackManager.BANGUMI).apply {
|
return Track.create(TrackManager.BANGUMI).apply {
|
||||||
title = mangas["name"].asString
|
title = mangas["name"].asString
|
||||||
media_id = mangas["id"].asInt
|
media_id = mangas["id"].asInt
|
||||||
score = if (mangas["rating"] != null)
|
score =
|
||||||
(if (mangas["rating"].isJsonObject) mangas["rating"].obj["score"].asFloat else 0f)
|
if (mangas["rating"] != null) (if (mangas["rating"].isJsonObject) mangas["rating"].obj["score"].asFloat else 0f)
|
||||||
else 0f
|
else 0f
|
||||||
status = Bangumi.DEFAULT_STATUS
|
status = Bangumi.DEFAULT_STATUS
|
||||||
tracking_url = mangas["url"].asString
|
tracking_url = mangas["url"].asString
|
||||||
}
|
}
|
||||||
@ -117,10 +103,7 @@ class BangumiApi(private val client: OkHttpClient, interceptor: BangumiIntercept
|
|||||||
suspend fun findLibManga(track: Track): Track? {
|
suspend fun findLibManga(track: Track): Track? {
|
||||||
return withContext(Dispatchers.IO) {
|
return withContext(Dispatchers.IO) {
|
||||||
val urlMangas = "$apiUrl/subject/${track.media_id}"
|
val urlMangas = "$apiUrl/subject/${track.media_id}"
|
||||||
val requestMangas = Request.Builder()
|
val requestMangas = Request.Builder().url(urlMangas).get().build()
|
||||||
.url(urlMangas)
|
|
||||||
.get()
|
|
||||||
.build()
|
|
||||||
val netResponse = authClient.newCall(requestMangas).execute()
|
val netResponse = authClient.newCall(requestMangas).execute()
|
||||||
val responseBody = netResponse.body?.string().orEmpty()
|
val responseBody = netResponse.body?.string().orEmpty()
|
||||||
jsonToTrack(JsonParser.parseString(responseBody).obj)
|
jsonToTrack(JsonParser.parseString(responseBody).obj)
|
||||||
@ -129,11 +112,9 @@ class BangumiApi(private val client: OkHttpClient, interceptor: BangumiIntercept
|
|||||||
|
|
||||||
suspend fun statusLibManga(track: Track): Track? {
|
suspend fun statusLibManga(track: Track): Track? {
|
||||||
val urlUserRead = "$apiUrl/collection/${track.media_id}"
|
val urlUserRead = "$apiUrl/collection/${track.media_id}"
|
||||||
val requestUserRead = Request.Builder()
|
val requestUserRead =
|
||||||
.url(urlUserRead)
|
Request.Builder().url(urlUserRead).cacheControl(CacheControl.FORCE_NETWORK).get()
|
||||||
.cacheControl(CacheControl.FORCE_NETWORK)
|
.build()
|
||||||
.get()
|
|
||||||
.build()
|
|
||||||
|
|
||||||
// todo get user readed chapter here
|
// todo get user readed chapter here
|
||||||
val response = authClient.newCall(requestUserRead).await()
|
val response = authClient.newCall(requestUserRead).await()
|
||||||
@ -145,10 +126,10 @@ class BangumiApi(private val client: OkHttpClient, interceptor: BangumiIntercept
|
|||||||
}
|
}
|
||||||
|
|
||||||
suspend fun accessToken(code: String): OAuth {
|
suspend fun accessToken(code: String): OAuth {
|
||||||
return withContext(Dispatchers.IO){
|
return withContext(Dispatchers.IO) {
|
||||||
val netResponse = client.newCall(accessTokenRequest(code)).execute()
|
val netResponse = client.newCall(accessTokenRequest(code)).execute()
|
||||||
val responseBody = netResponse.body?.string().orEmpty()
|
val responseBody = netResponse.body?.string().orEmpty()
|
||||||
if(responseBody.isEmpty()){
|
if (responseBody.isEmpty()) {
|
||||||
throw Exception("Null Response")
|
throw Exception("Null Response")
|
||||||
}
|
}
|
||||||
gson.fromJson(responseBody, OAuth::class.java)
|
gson.fromJson(responseBody, OAuth::class.java)
|
||||||
@ -157,12 +138,8 @@ class BangumiApi(private val client: OkHttpClient, interceptor: BangumiIntercept
|
|||||||
|
|
||||||
private fun accessTokenRequest(code: String) = POST(
|
private fun accessTokenRequest(code: String) = POST(
|
||||||
oauthUrl,
|
oauthUrl,
|
||||||
body = FormBody.Builder()
|
body = FormBody.Builder().add("grant_type", "authorization_code").add("client_id", clientId)
|
||||||
.add("grant_type", "authorization_code")
|
.add("client_secret", clientSecret).add("code", code).add("redirect_uri", redirectUrl)
|
||||||
.add("client_id", clientId)
|
|
||||||
.add("client_secret", clientSecret)
|
|
||||||
.add("code", code)
|
|
||||||
.add("redirect_uri", redirectUrl)
|
|
||||||
.build()
|
.build()
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -182,22 +159,15 @@ class BangumiApi(private val client: OkHttpClient, interceptor: BangumiIntercept
|
|||||||
return "$baseMangaUrl/$remoteId"
|
return "$baseMangaUrl/$remoteId"
|
||||||
}
|
}
|
||||||
|
|
||||||
fun authUrl() =
|
fun authUrl() = Uri.parse(loginUrl).buildUpon().appendQueryParameter("client_id", clientId)
|
||||||
Uri.parse(loginUrl).buildUpon()
|
.appendQueryParameter("response_type", "code")
|
||||||
.appendQueryParameter("client_id", clientId)
|
.appendQueryParameter("redirect_uri", redirectUrl).build()
|
||||||
.appendQueryParameter("response_type", "code")
|
|
||||||
.appendQueryParameter("redirect_uri", redirectUrl)
|
|
||||||
.build()
|
|
||||||
|
|
||||||
fun refreshTokenRequest(token: String) = POST(
|
fun refreshTokenRequest(token: String) = POST(
|
||||||
oauthUrl,
|
oauthUrl,
|
||||||
body = FormBody.Builder()
|
body = FormBody.Builder().add("grant_type", "refresh_token").add("client_id", clientId)
|
||||||
.add("grant_type", "refresh_token")
|
.add("client_secret", clientSecret).add("refresh_token", token)
|
||||||
.add("client_id", clientId)
|
.add("redirect_uri", redirectUrl).build()
|
||||||
.add("client_secret", clientSecret)
|
|
||||||
.add("refresh_token", token)
|
|
||||||
.add("redirect_uri", redirectUrl)
|
|
||||||
.build()
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -59,7 +59,7 @@ class BangumiInterceptor(val bangumi: Bangumi, val gson: Gson) : Interceptor {
|
|||||||
bangumi.saveToken(oauth)
|
bangumi.saveToken(oauth)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun clearOauth(){
|
fun clearOauth() {
|
||||||
bangumi.saveToken(null)
|
bangumi.saveToken(null)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,49 +1,47 @@
|
|||||||
package eu.kanade.tachiyomi.data.track.bangumi
|
package eu.kanade.tachiyomi.data.track.bangumi
|
||||||
|
|
||||||
data class Collection(
|
data class Collection(
|
||||||
val `private`: Int? = 0,
|
val `private`: Int? = 0,
|
||||||
val comment: String? = "",
|
val comment: String? = "",
|
||||||
val ep_status: Int? = 0,
|
val ep_status: Int? = 0,
|
||||||
val lasttouch: Int? = 0,
|
val lasttouch: Int? = 0,
|
||||||
val rating: Int? = 0,
|
val rating: Int? = 0,
|
||||||
val status: Status? = Status(),
|
val status: Status? = Status(),
|
||||||
val tag: List<String?>? = listOf(),
|
val tag: List<String?>? = listOf(),
|
||||||
val user: User? = User(),
|
val user: User? = User(),
|
||||||
val vol_status: Int? = 0
|
val vol_status: Int? = 0
|
||||||
)
|
)
|
||||||
|
|
||||||
data class OAuth(
|
data class OAuth(
|
||||||
val access_token: String,
|
val access_token: String,
|
||||||
val token_type: String,
|
val token_type: String,
|
||||||
val created_at: Long,
|
val created_at: Long,
|
||||||
val expires_in: Long,
|
val expires_in: Long,
|
||||||
val refresh_token: String?,
|
val refresh_token: String?,
|
||||||
val user_id: Long?
|
val user_id: Long?
|
||||||
) {
|
) {
|
||||||
// Access token refresh before expired
|
// Access token refresh before expired
|
||||||
fun isExpired() = (System.currentTimeMillis() / 1000) > (created_at + expires_in - 3600)
|
fun isExpired() = (System.currentTimeMillis() / 1000) > (created_at + expires_in - 3600)
|
||||||
}
|
}
|
||||||
|
|
||||||
data class Status(
|
data class Status(
|
||||||
val id: Int? = 0,
|
val id: Int? = 0,
|
||||||
val name: String? = "",
|
val name: String? = "",
|
||||||
val type: String? = ""
|
val type: String? = ""
|
||||||
)
|
)
|
||||||
|
|
||||||
data class User(
|
data class User(
|
||||||
val avatar: Avatar? = Avatar(),
|
val avatar: Avatar? = Avatar(),
|
||||||
val id: Int? = 0,
|
val id: Int? = 0,
|
||||||
val nickname: String? = "",
|
val nickname: String? = "",
|
||||||
val sign: String? = "",
|
val sign: String? = "",
|
||||||
val url: String? = "",
|
val url: String? = "",
|
||||||
val usergroup: Int? = 0,
|
val usergroup: Int? = 0,
|
||||||
val username: String? = ""
|
val username: String? = ""
|
||||||
)
|
)
|
||||||
|
|
||||||
data class Avatar(
|
data class Avatar(
|
||||||
val large: String? = "",
|
val large: String? = "",
|
||||||
val medium: String? = "",
|
val medium: String? = "",
|
||||||
val small: 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.database.models.Track
|
||||||
import eu.kanade.tachiyomi.data.track.TrackService
|
import eu.kanade.tachiyomi.data.track.TrackService
|
||||||
import eu.kanade.tachiyomi.data.track.model.TrackSearch
|
import eu.kanade.tachiyomi.data.track.model.TrackSearch
|
||||||
|
import java.text.DecimalFormat
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import uy.kohesive.injekt.injectLazy
|
import uy.kohesive.injekt.injectLazy
|
||||||
import java.text.DecimalFormat
|
|
||||||
|
|
||||||
class Kitsu(private val context: Context, id: Int) : TrackService(id) {
|
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
|
this.oauth = oauth
|
||||||
kitsu.saveToken(oauth)
|
kitsu.saveToken(oauth)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,13 +1,19 @@
|
|||||||
package eu.kanade.tachiyomi.data.track.kitsu
|
package eu.kanade.tachiyomi.data.track.kitsu
|
||||||
|
|
||||||
import androidx.annotation.CallSuper
|
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 com.google.gson.JsonObject
|
||||||
import eu.kanade.tachiyomi.data.database.models.Track
|
import eu.kanade.tachiyomi.data.database.models.Track
|
||||||
import eu.kanade.tachiyomi.data.track.TrackManager
|
import eu.kanade.tachiyomi.data.track.TrackManager
|
||||||
import eu.kanade.tachiyomi.data.track.model.TrackSearch
|
import eu.kanade.tachiyomi.data.track.model.TrackSearch
|
||||||
import java.text.SimpleDateFormat
|
import java.text.SimpleDateFormat
|
||||||
import java.util.*
|
import java.util.Date
|
||||||
|
import java.util.Locale
|
||||||
|
|
||||||
class KitsuSearchManga(obj: JsonObject) {
|
class KitsuSearchManga(obj: JsonObject) {
|
||||||
val id by obj.byInt
|
val id by obj.byInt
|
||||||
@ -40,7 +46,6 @@ class KitsuSearchManga(obj: JsonObject) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class KitsuLibManga(obj: JsonObject, manga: JsonObject) {
|
class KitsuLibManga(obj: JsonObject, manga: JsonObject) {
|
||||||
val id by manga.byInt
|
val id by manga.byInt
|
||||||
private val canonicalTitle by manga["attributes"].byString
|
private val canonicalTitle by manga["attributes"].byString
|
||||||
@ -77,7 +82,6 @@ class KitsuLibManga(obj: JsonObject, manga: JsonObject) {
|
|||||||
"planned" -> Kitsu.PLAN_TO_READ
|
"planned" -> Kitsu.PLAN_TO_READ
|
||||||
else -> throw Exception("Unknown status")
|
else -> throw Exception("Unknown status")
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Track.toKitsuStatus() = when (status) {
|
fun Track.toKitsuStatus() = when (status) {
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
package eu.kanade.tachiyomi.data.track.kitsu
|
package eu.kanade.tachiyomi.data.track.kitsu
|
||||||
|
|
||||||
data class OAuth(
|
data class OAuth(
|
||||||
val access_token: String,
|
val access_token: String,
|
||||||
val token_type: String,
|
val token_type: String,
|
||||||
val created_at: Long,
|
val created_at: Long,
|
||||||
val expires_in: Long,
|
val expires_in: Long,
|
||||||
val refresh_token: String?) {
|
val refresh_token: String?
|
||||||
|
) {
|
||||||
|
|
||||||
fun isExpired() = (System.currentTimeMillis() / 1000) > (created_at + expires_in - 3600)
|
fun isExpired() = (System.currentTimeMillis() / 1000) > (created_at + expires_in - 3600)
|
||||||
}
|
}
|
||||||
|
@ -58,7 +58,5 @@ class TrackSearch : Track {
|
|||||||
fun create(serviceId: Int): TrackSearch = TrackSearch().apply {
|
fun create(serviceId: Int): TrackSearch = TrackSearch().apply {
|
||||||
sync_id = serviceId
|
sync_id = serviceId
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user