Introduce coroutines. Fix #1027. Lower notification channels' importance
This commit is contained in:
parent
d97aff85b3
commit
4abd2d709f
@ -218,10 +218,14 @@ dependencies {
|
||||
testCompile "org.robolectric:shadows-play-services:$robolectric_version"
|
||||
|
||||
compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
||||
|
||||
final coroutines_version = '0.19.1'
|
||||
compile "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines_version"
|
||||
compile "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines_version"
|
||||
}
|
||||
|
||||
buildscript {
|
||||
ext.kotlin_version = '1.1.50'
|
||||
ext.kotlin_version = '1.1.51'
|
||||
repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
@ -234,6 +238,12 @@ repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
kotlin {
|
||||
experimental {
|
||||
coroutines 'enable'
|
||||
}
|
||||
}
|
||||
|
||||
// add support for placeholders in resource files
|
||||
//https://code.google.com/p/android/issues/detail?id=69224
|
||||
def replacePlaceholdersInFile(basePath, fileName, placeholders) {
|
||||
|
@ -16,6 +16,7 @@ import eu.kanade.tachiyomi.source.model.Page
|
||||
import eu.kanade.tachiyomi.source.online.HttpSource
|
||||
import eu.kanade.tachiyomi.source.online.fetchAllImageUrlsFromPageList
|
||||
import eu.kanade.tachiyomi.util.*
|
||||
import kotlinx.coroutines.experimental.async
|
||||
import okhttp3.Response
|
||||
import rx.Observable
|
||||
import rx.android.schedulers.AndroidSchedulers
|
||||
@ -90,11 +91,10 @@ class Downloader(private val context: Context, private val provider: DownloadPro
|
||||
@Volatile private var isRunning: Boolean = false
|
||||
|
||||
init {
|
||||
Observable.fromCallable { store.restore() }
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe({ downloads -> queue.addAll(downloads)
|
||||
}, { error -> Timber.e(error) })
|
||||
launchNow {
|
||||
val chapters = async { store.restore() }
|
||||
queue.addAll(chapters.await())
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -217,51 +217,49 @@ class Downloader(private val context: Context, private val provider: DownloadPro
|
||||
* @param manga the manga of the chapters to download.
|
||||
* @param chapters the list of chapters to download.
|
||||
*/
|
||||
fun queueChapters(manga: Manga, chapters: List<Chapter>) {
|
||||
val source = sourceManager.get(manga.source) as? HttpSource ?: return
|
||||
fun queueChapters(manga: Manga, chapters: List<Chapter>) = launchUI {
|
||||
val source = sourceManager.get(manga.source) as? HttpSource ?: return@launchUI
|
||||
|
||||
Observable
|
||||
// Background, long running checks
|
||||
.fromCallable {
|
||||
val mangaDir = provider.findMangaDir(source, manga)
|
||||
// Called in background thread, the operation can be slow with SAF.
|
||||
val chaptersWithoutDir = async {
|
||||
val mangaDir = provider.findMangaDir(source, manga)
|
||||
|
||||
chapters
|
||||
// Avoid downloading chapters with the same name.
|
||||
.distinctBy { it.name }
|
||||
// Filter out those already downloaded.
|
||||
.filter { mangaDir?.findFile(provider.getChapterDirName(it)) == null }
|
||||
// Add chapters to queue from the start.
|
||||
.sortedByDescending { it.source_order }
|
||||
}
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
// Main thread, quick checks
|
||||
.map { chaptersToQueue ->
|
||||
chaptersToQueue
|
||||
// Filter out those already enqueued.
|
||||
.filter { chapter -> queue.none { it.chapter.id == chapter.id } }
|
||||
// Create a download for each one.
|
||||
.map { Download(source, manga, it) }
|
||||
}
|
||||
.subscribe { chaptersToQueue ->
|
||||
if (chaptersToQueue.isNotEmpty()) {
|
||||
queue.addAll(chaptersToQueue)
|
||||
chapters
|
||||
// Avoid downloading chapters with the same name.
|
||||
.distinctBy { it.name }
|
||||
// Filter out those already downloaded.
|
||||
.filter { mangaDir?.findFile(provider.getChapterDirName(it)) == null }
|
||||
// Add chapters to queue from the start.
|
||||
.sortedByDescending { it.source_order }
|
||||
}
|
||||
|
||||
// Initialize queue size.
|
||||
notifier.initialQueueSize = queue.size
|
||||
// Runs in main thread (synchronization needed).
|
||||
val chaptersToQueue = chaptersWithoutDir.await()
|
||||
// Filter out those already enqueued.
|
||||
.filter { chapter -> queue.none { it.chapter.id == chapter.id } }
|
||||
// Create a download for each one.
|
||||
.map { Download(source, manga, it) }
|
||||
|
||||
// Initial multi-thread
|
||||
notifier.multipleDownloadThreads = preferences.downloadThreads().getOrDefault() > 1
|
||||
if (chaptersToQueue.isNotEmpty()) {
|
||||
queue.addAll(chaptersToQueue)
|
||||
|
||||
if (isRunning) {
|
||||
// Send the list of downloads to the downloader.
|
||||
downloadsRelay.call(chaptersToQueue)
|
||||
} else {
|
||||
// Show initial notification.
|
||||
notifier.onProgressChange(queue)
|
||||
}
|
||||
}
|
||||
}
|
||||
// Initialize queue size.
|
||||
notifier.initialQueueSize = queue.size
|
||||
|
||||
// Initial multi-thread
|
||||
notifier.multipleDownloadThreads = preferences.downloadThreads().getOrDefault() > 1
|
||||
|
||||
if (isRunning) {
|
||||
// Send the list of downloads to the downloader.
|
||||
downloadsRelay.call(chaptersToQueue)
|
||||
} else {
|
||||
// Show initial notification.
|
||||
notifier.onProgressChange(queue)
|
||||
}
|
||||
|
||||
// Start downloader if needed
|
||||
DownloadService.start(this@Downloader.context)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -43,11 +43,11 @@ object Notifications {
|
||||
|
||||
val channels = listOf(
|
||||
NotificationChannel(CHANNEL_COMMON, context.getString(R.string.channel_common),
|
||||
NotificationManager.IMPORTANCE_DEFAULT),
|
||||
NotificationManager.IMPORTANCE_LOW),
|
||||
NotificationChannel(CHANNEL_LIBRARY, context.getString(R.string.channel_library),
|
||||
NotificationManager.IMPORTANCE_DEFAULT),
|
||||
NotificationManager.IMPORTANCE_LOW),
|
||||
NotificationChannel(CHANNEL_DOWNLOADER, context.getString(R.string.channel_downloader),
|
||||
NotificationManager.IMPORTANCE_DEFAULT)
|
||||
NotificationManager.IMPORTANCE_LOW)
|
||||
)
|
||||
context.notificationManager.createNotificationChannels(channels)
|
||||
}
|
||||
|
@ -7,7 +7,6 @@ import eu.kanade.tachiyomi.data.database.DatabaseHelper
|
||||
import eu.kanade.tachiyomi.data.database.models.Chapter
|
||||
import eu.kanade.tachiyomi.data.database.models.Manga
|
||||
import eu.kanade.tachiyomi.data.download.DownloadManager
|
||||
import eu.kanade.tachiyomi.data.download.DownloadService
|
||||
import eu.kanade.tachiyomi.data.download.model.Download
|
||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||
import eu.kanade.tachiyomi.source.Source
|
||||
@ -35,8 +34,6 @@ class ChaptersPresenter(
|
||||
private val downloadManager: DownloadManager = Injekt.get()
|
||||
) : BasePresenter<ChaptersController>() {
|
||||
|
||||
private val context = preferences.context
|
||||
|
||||
/**
|
||||
* List of chapters of the manga. It's always unfiltered and unsorted.
|
||||
*/
|
||||
@ -246,7 +243,6 @@ class ChaptersPresenter(
|
||||
* @param chapters the list of chapters to download.
|
||||
*/
|
||||
fun downloadChapters(chapters: List<ChapterItem>) {
|
||||
DownloadService.start(context)
|
||||
downloadManager.downloadChapters(manga, chapters)
|
||||
}
|
||||
|
||||
|
@ -25,8 +25,6 @@ class RecentChaptersPresenter(
|
||||
private val sourceManager: SourceManager = Injekt.get()
|
||||
) : BasePresenter<RecentChaptersController>() {
|
||||
|
||||
private val context = preferences.context
|
||||
|
||||
/**
|
||||
* List containing chapter and manga information
|
||||
*/
|
||||
@ -207,7 +205,6 @@ class RecentChaptersPresenter(
|
||||
*/
|
||||
fun downloadChapters(items: List<RecentChapterItem>) {
|
||||
items.forEach { downloadManager.downloadChapters(it.manga, listOf(it.chapter)) }
|
||||
DownloadService.start(context)
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -0,0 +1,13 @@
|
||||
package eu.kanade.tachiyomi.util
|
||||
|
||||
import kotlinx.coroutines.experimental.CoroutineScope
|
||||
import kotlinx.coroutines.experimental.CoroutineStart
|
||||
import kotlinx.coroutines.experimental.Job
|
||||
import kotlinx.coroutines.experimental.android.UI
|
||||
import kotlinx.coroutines.experimental.launch
|
||||
|
||||
fun launchUI(block: suspend CoroutineScope.() -> Unit): Job =
|
||||
launch(UI, CoroutineStart.DEFAULT, block)
|
||||
|
||||
fun launchNow(block: suspend CoroutineScope.() -> Unit): Job =
|
||||
launch(UI, CoroutineStart.UNDISPATCHED, block)
|
Loading…
Reference in New Issue
Block a user