Linting fixes

This commit is contained in:
arkon
2020-04-25 14:24:45 -04:00
parent 4da760d614
commit 3f63b320c4
272 changed files with 4167 additions and 3602 deletions
@@ -100,8 +100,8 @@ class DownloadCache(
val mangaDir = sourceDir.files[provider.getMangaDirName(manga)]
if (mangaDir != null) {
return mangaDir.files
.filter { !it.endsWith(Downloader.TMP_DIR_SUFFIX) }
.size
.filter { !it.endsWith(Downloader.TMP_DIR_SUFFIX) }
.size
}
}
return 0
@@ -125,26 +125,26 @@ class DownloadCache(
val onlineSources = sourceManager.getOnlineSources()
val sourceDirs = rootDir.dir.listFiles()
.orEmpty()
.associate { it.name to SourceDirectory(it) }
.mapNotNullKeys { entry ->
onlineSources.find { provider.getSourceDirName(it) == entry.key }?.id
}
.orEmpty()
.associate { it.name to SourceDirectory(it) }
.mapNotNullKeys { entry ->
onlineSources.find { provider.getSourceDirName(it) == entry.key }?.id
}
rootDir.files = sourceDirs
sourceDirs.values.forEach { sourceDir ->
val mangaDirs = sourceDir.dir.listFiles()
.orEmpty()
.associateNotNullKeys { it.name to MangaDirectory(it) }
.orEmpty()
.associateNotNullKeys { it.name to MangaDirectory(it) }
sourceDir.files = mangaDirs
mangaDirs.values.forEach { mangaDir ->
val chapterDirs = mangaDir.dir.listFiles()
.orEmpty()
.mapNotNull { it.name }
.toHashSet()
.orEmpty()
.mapNotNull { it.name }
.toHashSet()
mangaDir.files = chapterDirs
}
@@ -148,16 +148,16 @@ class DownloadManager(private val context: Context) {
private fun buildPageList(chapterDir: UniFile?): Observable<List<Page>> {
return Observable.fromCallable {
val files = chapterDir?.listFiles().orEmpty()
.filter { "image" in it.type.orEmpty() }
.filter { "image" in it.type.orEmpty() }
if (files.isEmpty()) {
throw Exception("Page list is empty")
}
files.sortedBy { it.name }
.mapIndexed { i, file ->
Page(i, uri = file.uri).apply { status = Page.READY }
}
.mapIndexed { i, file ->
Page(i, uri = file.uri).apply { status = Page.READY }
}
}
}
@@ -87,13 +87,15 @@ internal class DownloadNotifier(private val context: Context) {
setContentIntent(NotificationHandler.openDownloadManagerPendingActivity(context))
isDownloading = true
// Pause action
addAction(R.drawable.ic_pause_24dp,
context.getString(R.string.action_pause),
NotificationReceiver.pauseDownloadsPendingBroadcast(context))
addAction(
R.drawable.ic_pause_24dp,
context.getString(R.string.action_pause),
NotificationReceiver.pauseDownloadsPendingBroadcast(context)
)
}
val downloadingProgressText = context.getString(R.string.chapter_downloading_progress)
.format(download.downloadedImages, download.pages!!.size)
.format(download.downloadedImages, download.pages!!.size)
if (preferences.hideNotificationContent()) {
setContentTitle(downloadingProgressText)
@@ -126,13 +128,17 @@ internal class DownloadNotifier(private val context: Context) {
// Open download manager when clicked
setContentIntent(NotificationHandler.openDownloadManagerPendingActivity(context))
// Resume action
addAction(R.drawable.ic_play_arrow_24dp,
context.getString(R.string.action_resume),
NotificationReceiver.resumeDownloadsPendingBroadcast(context))
addAction(
R.drawable.ic_play_arrow_24dp,
context.getString(R.string.action_resume),
NotificationReceiver.resumeDownloadsPendingBroadcast(context)
)
// Clear action
addAction(R.drawable.ic_close_24dp,
context.getString(R.string.action_cancel_all),
NotificationReceiver.clearDownloadsPendingBroadcast(context))
addAction(
R.drawable.ic_close_24dp,
context.getString(R.string.action_cancel_all),
NotificationReceiver.clearDownloadsPendingBroadcast(context)
)
}
// Show notification.
@@ -173,8 +179,10 @@ internal class DownloadNotifier(private val context: Context) {
fun onError(error: String? = null, chapter: String? = null) {
// Create notification
with(notificationBuilder) {
setContentTitle(chapter
?: context.getString(R.string.download_notifier_downloader_title))
setContentTitle(
chapter
?: context.getString(R.string.download_notifier_downloader_title)
)
setContentText(error ?: context.getString(R.string.download_notifier_unknown_error))
setSmallIcon(android.R.drawable.stat_sys_warning)
clearActions()
@@ -52,8 +52,8 @@ class DownloadProvider(private val context: Context) {
internal fun getMangaDir(manga: Manga, source: Source): UniFile {
try {
return downloadsDir
.createDirectory(getSourceDirName(source))
.createDirectory(getMangaDirName(manga))
.createDirectory(getSourceDirName(source))
.createDirectory(getMangaDirName(manga))
} catch (e: NullPointerException) {
throw Exception(context.getString(R.string.invalid_download_dir))
}
@@ -123,14 +123,17 @@ class DownloadService : Service() {
*/
private fun listenNetworkChanges() {
subscriptions += ReactiveNetwork.observeNetworkConnectivity(applicationContext)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe({ state ->
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
{ state ->
onNetworkStateChanged(state)
}, {
},
{
toast(R.string.download_queue_error)
stopSelf()
})
}
)
}
/**
@@ -162,10 +165,11 @@ class DownloadService : Service() {
*/
private fun listenDownloaderState() {
subscriptions += downloadManager.runningRelay.subscribe { running ->
if (running)
if (running) {
wakeLock.acquireIfNeeded()
else
} else {
wakeLock.releaseIfNeeded()
}
}
}
@@ -77,9 +77,9 @@ class DownloadStore(
*/
fun restore(): List<Download> {
val objs = preferences.all
.mapNotNull { it.value as? String }
.mapNotNull { deserialize(it) }
.sortedBy { it.order }
.mapNotNull { it.value as? String }
.mapNotNull { deserialize(it) }
.sortedBy { it.order }
val downloads = mutableListOf<Download>()
if (objs.isNotEmpty()) {
@@ -100,11 +100,13 @@ class Downloader(
* @return true if the downloader is started, false otherwise.
*/
fun start(): Boolean {
if (isRunning || queue.isEmpty())
if (isRunning || queue.isEmpty()) {
return false
}
if (!subscriptions.hasSubscriptions())
if (!subscriptions.hasSubscriptions()) {
initializeSubscriptions()
}
val pending = queue.filter { it.status != Download.DOWNLOADED }
pending.forEach { if (it.status != Download.QUEUE) it.status = Download.QUEUE }
@@ -119,8 +121,8 @@ class Downloader(
fun stop(reason: String? = null) {
destroySubscriptions()
queue
.filter { it.status == Download.DOWNLOADING }
.forEach { it.status = Download.ERROR }
.filter { it.status == Download.DOWNLOADING }
.forEach { it.status = Download.ERROR }
if (reason != null) {
notifier.onWarning(reason)
@@ -140,8 +142,8 @@ class Downloader(
fun pause() {
destroySubscriptions()
queue
.filter { it.status == Download.DOWNLOADING }
.forEach { it.status = Download.QUEUE }
.filter { it.status == Download.DOWNLOADING }
.forEach { it.status = Download.QUEUE }
notifier.paused = true
}
@@ -156,8 +158,8 @@ class Downloader(
// Needed to update the chapter view
if (isNotification) {
queue
.filter { it.status == Download.QUEUE }
.forEach { it.status = Download.NOT_DOWNLOADED }
.filter { it.status == Download.QUEUE }
.forEach { it.status = Download.NOT_DOWNLOADED }
}
queue.clear()
notifier.dismiss()
@@ -174,16 +176,19 @@ class Downloader(
subscriptions.clear()
subscriptions += downloadsRelay.concatMapIterable { it }
.concatMap { downloadChapter(it).subscribeOn(Schedulers.io()) }
.onBackpressureBuffer()
.observeOn(AndroidSchedulers.mainThread())
.subscribe({
.concatMap { downloadChapter(it).subscribeOn(Schedulers.io()) }
.onBackpressureBuffer()
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
{
completeDownload(it)
}, { error ->
},
{ error ->
DownloadService.stop(context)
Timber.e(error)
notifier.onError(error.message)
})
}
)
}
/**
@@ -212,20 +217,20 @@ class Downloader(
val mangaDir = provider.findMangaDir(manga, source)
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 }
// 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 }
}
// 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) }
// 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) }
if (chaptersToQueue.isNotEmpty()) {
queue.addAll(chaptersToQueue)
@@ -255,43 +260,43 @@ class Downloader(
val pageListObservable = if (download.pages == null) {
// Pull page list from network and add them to download object
download.source.fetchPageList(download.chapter)
.doOnNext { pages ->
if (pages.isEmpty()) {
throw Exception("Page list is empty")
}
download.pages = pages
.doOnNext { pages ->
if (pages.isEmpty()) {
throw Exception("Page list is empty")
}
download.pages = pages
}
} else {
// Or if the page list already exists, start from the file
Observable.just(download.pages!!)
}
pageListObservable
.doOnNext { _ ->
// Delete all temporary (unfinished) files
tmpDir.listFiles()
?.filter { it.name!!.endsWith(".tmp") }
?.forEach { it.delete() }
.doOnNext { _ ->
// Delete all temporary (unfinished) files
tmpDir.listFiles()
?.filter { it.name!!.endsWith(".tmp") }
?.forEach { it.delete() }
download.downloadedImages = 0
download.status = Download.DOWNLOADING
}
// Get all the URLs to the source images, fetch pages if necessary
.flatMap { download.source.fetchAllImageUrlsFromPageList(it) }
// Start downloading images, consider we can have downloaded images already
.concatMap { page -> getOrDownloadImage(page, download, tmpDir) }
// Do when page is downloaded.
.doOnNext { notifier.onProgressChange(download) }
.toList()
.map { download }
// Do after download completes
.doOnNext { ensureSuccessfulDownload(download, mangaDir, tmpDir, chapterDirname) }
// If the page list threw, it will resume here
.onErrorReturn { error ->
download.status = Download.ERROR
notifier.onError(error.message, download.chapter.name)
download
}
download.downloadedImages = 0
download.status = Download.DOWNLOADING
}
// Get all the URLs to the source images, fetch pages if necessary
.flatMap { download.source.fetchAllImageUrlsFromPageList(it) }
// Start downloading images, consider we can have downloaded images already
.concatMap { page -> getOrDownloadImage(page, download, tmpDir) }
// Do when page is downloaded.
.doOnNext { notifier.onProgressChange(download) }
.toList()
.map { download }
// Do after download completes
.doOnNext { ensureSuccessfulDownload(download, mangaDir, tmpDir, chapterDirname) }
// If the page list threw, it will resume here
.onErrorReturn { error ->
download.status = Download.ERROR
notifier.onError(error.message, download.chapter.name)
download
}
}
/**
@@ -304,8 +309,9 @@ class Downloader(
*/
private fun getOrDownloadImage(page: Page, download: Download, tmpDir: UniFile): Observable<Page> {
// If the image URL is empty, do nothing
if (page.imageUrl == null)
if (page.imageUrl == null) {
return Observable.just(page)
}
val filename = String.format("%03d", page.number)
val tmpFile = tmpDir.findFile("$filename.tmp")
@@ -317,26 +323,27 @@ class Downloader(
val imageFile = tmpDir.listFiles()!!.find { it.name!!.startsWith("$filename.") }
// If the image is already downloaded, do nothing. Otherwise download from network
val pageObservable = if (imageFile != null)
val pageObservable = if (imageFile != null) {
Observable.just(imageFile)
else
} else {
downloadImage(page, download.source, tmpDir, filename)
}
return pageObservable
// When the image is ready, set image path, progress (just in case) and status
.doOnNext { file ->
page.uri = file.uri
page.progress = 100
download.downloadedImages++
page.status = Page.READY
}
.map { page }
// Mark this page as error and allow to download the remaining
.onErrorReturn {
page.progress = 0
page.status = Page.ERROR
page
}
// When the image is ready, set image path, progress (just in case) and status
.doOnNext { file ->
page.uri = file.uri
page.progress = 100
download.downloadedImages++
page.status = Page.READY
}
.map { page }
// Mark this page as error and allow to download the remaining
.onErrorReturn {
page.progress = 0
page.status = Page.ERROR
page
}
}
/**
@@ -351,21 +358,21 @@ class Downloader(
page.status = Page.DOWNLOAD_IMAGE
page.progress = 0
return source.fetchImage(page)
.map { response ->
val file = tmpDir.createFile("$filename.tmp")
try {
response.body!!.source().saveTo(file.openOutputStream())
val extension = getImageExtension(response, file)
file.renameTo("$filename.$extension")
} catch (e: Exception) {
response.close()
file.delete()
throw e
}
file
.map { response ->
val file = tmpDir.createFile("$filename.tmp")
try {
response.body!!.source().saveTo(file.openOutputStream())
val extension = getImageExtension(response, file)
file.renameTo("$filename.$extension")
} catch (e: Exception) {
response.close()
file.delete()
throw e
}
// Retry 3 times, waiting 2, 4 and 8 seconds between attempts.
.retryWhen(RetryWithDelay(3, { (2 shl it - 1) * 1000 }, Schedulers.trampoline()))
file
}
// Retry 3 times, waiting 2, 4 and 8 seconds between attempts.
.retryWhen(RetryWithDelay(3, { (2 shl it - 1) * 1000 }, Schedulers.trampoline()))
}
/**
@@ -378,10 +385,10 @@ class Downloader(
private fun getImageExtension(response: Response, file: UniFile): String {
// Read content type if available.
val mime = response.body?.contentType()?.let { ct -> "${ct.type}/${ct.subtype}" }
// Else guess from the uri.
?: context.contentResolver.getType(file.uri)
// Else read magic numbers.
?: ImageUtil.findImageType { file.openInputStream() }?.mime
// Else guess from the uri.
?: context.contentResolver.getType(file.uri)
// Else read magic numbers.
?: ImageUtil.findImageType { file.openInputStream() }?.mime
return MimeTypeMap.getSingleton().getExtensionFromMimeType(mime) ?: "jpg"
}
@@ -400,7 +407,6 @@ class Downloader(
tmpDir: UniFile,
dirname: String
) {
// Ensure that the chapter folder has all the images.
val downloadedImages = tmpDir.listFiles().orEmpty().filterNot { it.name!!.endsWith(".tmp") }
@@ -70,13 +70,13 @@ class DownloadQueue(
}
fun getActiveDownloads(): Observable<Download> =
Observable.from(this).filter { download -> download.status == Download.DOWNLOADING }
Observable.from(this).filter { download -> download.status == Download.DOWNLOADING }
fun getStatusObservable(): Observable<Download> = statusSubject.onBackpressureBuffer()
fun getUpdatedObservable(): Observable<List<Download>> = updatedRelay.onBackpressureBuffer()
.startWith(Unit)
.map { this }
.startWith(Unit)
.map { this }
private fun setPagesFor(download: Download) {
if (download.status == Download.DOWNLOADED || download.status == Download.ERROR) {
@@ -86,21 +86,21 @@ class DownloadQueue(
fun getProgressObservable(): Observable<Download> {
return statusSubject.onBackpressureBuffer()
.startWith(getActiveDownloads())
.flatMap { download ->
if (download.status == Download.DOWNLOADING) {
val pageStatusSubject = PublishSubject.create<Int>()
setPagesSubject(download.pages, pageStatusSubject)
return@flatMap pageStatusSubject
.onBackpressureBuffer()
.filter { it == Page.READY }
.map { download }
} else if (download.status == Download.DOWNLOADED || download.status == Download.ERROR) {
setPagesSubject(download.pages, null)
}
Observable.just(download)
.startWith(getActiveDownloads())
.flatMap { download ->
if (download.status == Download.DOWNLOADING) {
val pageStatusSubject = PublishSubject.create<Int>()
setPagesSubject(download.pages, pageStatusSubject)
return@flatMap pageStatusSubject
.onBackpressureBuffer()
.filter { it == Page.READY }
.map { download }
} else if (download.status == Download.DOWNLOADED || download.status == Download.ERROR) {
setPagesSubject(download.pages, null)
}
.filter { it.status == Download.DOWNLOADING }
Observable.just(download)
}
.filter { it.status == Download.DOWNLOADING }
}
private fun setPagesSubject(pages: List<Page>?, subject: PublishSubject<Int>?) {