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"
|
testCompile "org.robolectric:shadows-play-services:$robolectric_version"
|
||||||
|
|
||||||
compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_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 {
|
buildscript {
|
||||||
ext.kotlin_version = '1.1.50'
|
ext.kotlin_version = '1.1.51'
|
||||||
repositories {
|
repositories {
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
}
|
}
|
||||||
@ -234,6 +238,12 @@ repositories {
|
|||||||
mavenCentral()
|
mavenCentral()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
kotlin {
|
||||||
|
experimental {
|
||||||
|
coroutines 'enable'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// add support for placeholders in resource files
|
// add support for placeholders in resource files
|
||||||
//https://code.google.com/p/android/issues/detail?id=69224
|
//https://code.google.com/p/android/issues/detail?id=69224
|
||||||
def replacePlaceholdersInFile(basePath, fileName, placeholders) {
|
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.HttpSource
|
||||||
import eu.kanade.tachiyomi.source.online.fetchAllImageUrlsFromPageList
|
import eu.kanade.tachiyomi.source.online.fetchAllImageUrlsFromPageList
|
||||||
import eu.kanade.tachiyomi.util.*
|
import eu.kanade.tachiyomi.util.*
|
||||||
|
import kotlinx.coroutines.experimental.async
|
||||||
import okhttp3.Response
|
import okhttp3.Response
|
||||||
import rx.Observable
|
import rx.Observable
|
||||||
import rx.android.schedulers.AndroidSchedulers
|
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
|
@Volatile private var isRunning: Boolean = false
|
||||||
|
|
||||||
init {
|
init {
|
||||||
Observable.fromCallable { store.restore() }
|
launchNow {
|
||||||
.subscribeOn(Schedulers.io())
|
val chapters = async { store.restore() }
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
queue.addAll(chapters.await())
|
||||||
.subscribe({ downloads -> queue.addAll(downloads)
|
}
|
||||||
}, { error -> Timber.e(error) })
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -217,51 +217,49 @@ class Downloader(private val context: Context, private val provider: DownloadPro
|
|||||||
* @param manga the manga of the chapters to download.
|
* @param manga the manga of the chapters to download.
|
||||||
* @param chapters the list of chapters to download.
|
* @param chapters the list of chapters to download.
|
||||||
*/
|
*/
|
||||||
fun queueChapters(manga: Manga, chapters: List<Chapter>) {
|
fun queueChapters(manga: Manga, chapters: List<Chapter>) = launchUI {
|
||||||
val source = sourceManager.get(manga.source) as? HttpSource ?: return
|
val source = sourceManager.get(manga.source) as? HttpSource ?: return@launchUI
|
||||||
|
|
||||||
Observable
|
// Called in background thread, the operation can be slow with SAF.
|
||||||
// Background, long running checks
|
val chaptersWithoutDir = async {
|
||||||
.fromCallable {
|
val mangaDir = provider.findMangaDir(source, manga)
|
||||||
val mangaDir = provider.findMangaDir(source, manga)
|
|
||||||
|
|
||||||
chapters
|
chapters
|
||||||
// Avoid downloading chapters with the same name.
|
// Avoid downloading chapters with the same name.
|
||||||
.distinctBy { it.name }
|
.distinctBy { it.name }
|
||||||
// Filter out those already downloaded.
|
// Filter out those already downloaded.
|
||||||
.filter { mangaDir?.findFile(provider.getChapterDirName(it)) == null }
|
.filter { mangaDir?.findFile(provider.getChapterDirName(it)) == null }
|
||||||
// Add chapters to queue from the start.
|
// Add chapters to queue from the start.
|
||||||
.sortedByDescending { it.source_order }
|
.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)
|
|
||||||
|
|
||||||
// Initialize queue size.
|
// Runs in main thread (synchronization needed).
|
||||||
notifier.initialQueueSize = queue.size
|
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
|
if (chaptersToQueue.isNotEmpty()) {
|
||||||
notifier.multipleDownloadThreads = preferences.downloadThreads().getOrDefault() > 1
|
queue.addAll(chaptersToQueue)
|
||||||
|
|
||||||
if (isRunning) {
|
// Initialize queue size.
|
||||||
// Send the list of downloads to the downloader.
|
notifier.initialQueueSize = queue.size
|
||||||
downloadsRelay.call(chaptersToQueue)
|
|
||||||
} else {
|
// Initial multi-thread
|
||||||
// Show initial notification.
|
notifier.multipleDownloadThreads = preferences.downloadThreads().getOrDefault() > 1
|
||||||
notifier.onProgressChange(queue)
|
|
||||||
}
|
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(
|
val channels = listOf(
|
||||||
NotificationChannel(CHANNEL_COMMON, context.getString(R.string.channel_common),
|
NotificationChannel(CHANNEL_COMMON, context.getString(R.string.channel_common),
|
||||||
NotificationManager.IMPORTANCE_DEFAULT),
|
NotificationManager.IMPORTANCE_LOW),
|
||||||
NotificationChannel(CHANNEL_LIBRARY, context.getString(R.string.channel_library),
|
NotificationChannel(CHANNEL_LIBRARY, context.getString(R.string.channel_library),
|
||||||
NotificationManager.IMPORTANCE_DEFAULT),
|
NotificationManager.IMPORTANCE_LOW),
|
||||||
NotificationChannel(CHANNEL_DOWNLOADER, context.getString(R.string.channel_downloader),
|
NotificationChannel(CHANNEL_DOWNLOADER, context.getString(R.string.channel_downloader),
|
||||||
NotificationManager.IMPORTANCE_DEFAULT)
|
NotificationManager.IMPORTANCE_LOW)
|
||||||
)
|
)
|
||||||
context.notificationManager.createNotificationChannels(channels)
|
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.Chapter
|
||||||
import eu.kanade.tachiyomi.data.database.models.Manga
|
import eu.kanade.tachiyomi.data.database.models.Manga
|
||||||
import eu.kanade.tachiyomi.data.download.DownloadManager
|
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.download.model.Download
|
||||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||||
import eu.kanade.tachiyomi.source.Source
|
import eu.kanade.tachiyomi.source.Source
|
||||||
@ -35,8 +34,6 @@ class ChaptersPresenter(
|
|||||||
private val downloadManager: DownloadManager = Injekt.get()
|
private val downloadManager: DownloadManager = Injekt.get()
|
||||||
) : BasePresenter<ChaptersController>() {
|
) : BasePresenter<ChaptersController>() {
|
||||||
|
|
||||||
private val context = preferences.context
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* List of chapters of the manga. It's always unfiltered and unsorted.
|
* 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.
|
* @param chapters the list of chapters to download.
|
||||||
*/
|
*/
|
||||||
fun downloadChapters(chapters: List<ChapterItem>) {
|
fun downloadChapters(chapters: List<ChapterItem>) {
|
||||||
DownloadService.start(context)
|
|
||||||
downloadManager.downloadChapters(manga, chapters)
|
downloadManager.downloadChapters(manga, chapters)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,8 +25,6 @@ class RecentChaptersPresenter(
|
|||||||
private val sourceManager: SourceManager = Injekt.get()
|
private val sourceManager: SourceManager = Injekt.get()
|
||||||
) : BasePresenter<RecentChaptersController>() {
|
) : BasePresenter<RecentChaptersController>() {
|
||||||
|
|
||||||
private val context = preferences.context
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* List containing chapter and manga information
|
* List containing chapter and manga information
|
||||||
*/
|
*/
|
||||||
@ -207,7 +205,6 @@ class RecentChaptersPresenter(
|
|||||||
*/
|
*/
|
||||||
fun downloadChapters(items: List<RecentChapterItem>) {
|
fun downloadChapters(items: List<RecentChapterItem>) {
|
||||||
items.forEach { downloadManager.downloadChapters(it.manga, listOf(it.chapter)) }
|
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