mirror of
				https://github.com/mihonapp/mihon.git
				synced 2025-11-04 08:08:55 +01:00 
			
		
		
		
	Introduce coroutines. Fix #1027. Lower notification channels' importance
This commit is contained in:
		@@ -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)
 | 
			
		||||
		Reference in New Issue
	
	Block a user