Refactor downloading-related classes

This commit is contained in:
Koitharu
2023-05-08 16:49:58 +03:00
parent 42df607f52
commit ac9680b5c0
11 changed files with 75 additions and 40 deletions

View File

@@ -102,6 +102,12 @@ dependencies {
implementation 'com.google.android.material:material:1.9.0'
//noinspection LifecycleAnnotationProcessorWithJava8
kapt 'androidx.lifecycle:lifecycle-compiler:2.6.1'
/**
* TODO: check
* https://issuetracker.google.com/issues/270245927
* https://issuetracker.google.com/issues/280504155
*/
implementation 'androidx.work:work-runtime-ktx:2.8.1'
//noinspection GradleDependency
implementation('com.google.guava:guava:31.1-android') {

View File

@@ -6,7 +6,7 @@ import org.koitharu.kotatsu.local.data.LocalManga
import org.koitharu.kotatsu.parsers.model.Manga
import java.util.Date
data class DownloadState2(
data class DownloadState(
val manga: Manga,
val isIndeterminate: Boolean,
val isPaused: Boolean = false,
@@ -46,6 +46,50 @@ data class DownloadState2(
.putBoolean(DATA_PAUSED, isPaused)
.build()
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false
other as DownloadState
if (manga != other.manga) return false
if (isIndeterminate != other.isIndeterminate) return false
if (isPaused != other.isPaused) return false
if (isStopped != other.isStopped) return false
if (error != other.error) return false
if (totalChapters != other.totalChapters) return false
if (currentChapter != other.currentChapter) return false
if (totalPages != other.totalPages) return false
if (currentPage != other.currentPage) return false
if (eta != other.eta) return false
if (localManga != other.localManga) return false
if (!downloadedChapters.contentEquals(other.downloadedChapters)) return false
if (timestamp != other.timestamp) return false
if (max != other.max) return false
if (progress != other.progress) return false
return percent == other.percent
}
override fun hashCode(): Int {
var result = manga.hashCode()
result = 31 * result + isIndeterminate.hashCode()
result = 31 * result + isPaused.hashCode()
result = 31 * result + isStopped.hashCode()
result = 31 * result + (error?.hashCode() ?: 0)
result = 31 * result + totalChapters
result = 31 * result + currentChapter
result = 31 * result + totalPages
result = 31 * result + currentPage
result = 31 * result + eta.hashCode()
result = 31 * result + (localManga?.hashCode() ?: 0)
result = 31 * result + downloadedChapters.contentHashCode()
result = 31 * result + timestamp.hashCode()
result = 31 * result + max
result = 31 * result + progress
result = 31 * result + percent.hashCode()
return result
}
companion object {
private const val DATA_MANGA_ID = "manga_id"

View File

@@ -19,7 +19,7 @@ import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.base.domain.MangaDataRepository
import org.koitharu.kotatsu.base.ui.BaseViewModel
import org.koitharu.kotatsu.core.ui.DateTimeAgo
import org.koitharu.kotatsu.download.domain.DownloadState2
import org.koitharu.kotatsu.download.domain.DownloadState
import org.koitharu.kotatsu.download.ui.worker.DownloadWorker
import org.koitharu.kotatsu.list.ui.model.EmptyState
import org.koitharu.kotatsu.list.ui.model.ListModel
@@ -173,21 +173,21 @@ class DownloadsViewModel @Inject constructor(
private suspend fun WorkInfo.toUiModel(): DownloadItemModel? {
val workData = if (outputData == Data.EMPTY) progress else outputData
val mangaId = DownloadState2.getMangaId(workData)
val mangaId = DownloadState.getMangaId(workData)
if (mangaId == 0L) return null
val manga = getManga(mangaId) ?: return null
return DownloadItemModel(
id = id,
workState = state,
manga = manga,
error = DownloadState2.getError(workData),
isIndeterminate = DownloadState2.isIndeterminate(workData),
isPaused = DownloadState2.isPaused(workData),
max = DownloadState2.getMax(workData),
progress = DownloadState2.getProgress(workData),
eta = DownloadState2.getEta(workData),
timestamp = DownloadState2.getTimestamp(workData),
totalChapters = DownloadState2.getDownloadedChapters(workData).size,
error = DownloadState.getError(workData),
isIndeterminate = DownloadState.isIndeterminate(workData),
isPaused = DownloadState.isPaused(workData),
max = DownloadState.getMax(workData),
progress = DownloadState.getProgress(workData),
eta = DownloadState.getEta(workData),
timestamp = DownloadState.getTimestamp(workData),
totalChapters = DownloadState.getDownloadedChapters(workData).size,
)
}

View File

@@ -25,7 +25,7 @@ import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.details.ui.DetailsActivity
import org.koitharu.kotatsu.download.domain.DownloadState2
import org.koitharu.kotatsu.download.domain.DownloadState
import org.koitharu.kotatsu.download.ui.list.DownloadsActivity
import org.koitharu.kotatsu.parsers.model.Manga
import org.koitharu.kotatsu.parsers.model.MangaSource
@@ -100,7 +100,7 @@ class DownloadNotificationFactory @AssistedInject constructor(
builder.priority = NotificationCompat.PRIORITY_DEFAULT
}
suspend fun create(state: DownloadState2?): Notification = mutex.withLock {
suspend fun create(state: DownloadState?): Notification = mutex.withLock {
builder.setContentTitle(state?.manga?.title ?: context.getString(R.string.preparing_))
builder.setContentText(context.getString(R.string.manga_downloading_))
builder.setProgress(1, 0, true)

View File

@@ -39,8 +39,7 @@ import org.koitharu.kotatsu.base.domain.MangaDataRepository
import org.koitharu.kotatsu.core.network.CommonHeaders
import org.koitharu.kotatsu.core.parser.MangaRepository
import org.koitharu.kotatsu.core.prefs.AppSettings
import org.koitharu.kotatsu.download.domain.DownloadState2
import org.koitharu.kotatsu.download.ui.service.PausingHandle
import org.koitharu.kotatsu.download.domain.DownloadState
import org.koitharu.kotatsu.local.data.LocalManga
import org.koitharu.kotatsu.local.data.LocalStorageChanges
import org.koitharu.kotatsu.local.data.PagesCache
@@ -52,6 +51,7 @@ import org.koitharu.kotatsu.parsers.model.MangaChapter
import org.koitharu.kotatsu.parsers.model.MangaSource
import org.koitharu.kotatsu.parsers.util.await
import org.koitharu.kotatsu.parsers.util.mapToSet
import org.koitharu.kotatsu.utils.Throttler
import org.koitharu.kotatsu.utils.WorkManagerHelper
import org.koitharu.kotatsu.utils.ext.deleteAwait
import org.koitharu.kotatsu.utils.ext.getDisplayMessage
@@ -83,8 +83,8 @@ class DownloadWorker @AssistedInject constructor(
private val notificationManager = appContext.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
@Volatile
private var lastPublishedState: DownloadState2? = null
private val currentState: DownloadState2
private var lastPublishedState: DownloadState? = null
private val currentState: DownloadState
get() = checkNotNull(lastPublishedState)
private val pausingHandle = PausingHandle()
@@ -98,7 +98,7 @@ class DownloadWorker @AssistedInject constructor(
val manga = mangaDataRepository.findMangaById(mangaId) ?: return Result.failure()
val chaptersIds = inputData.getLongArray(CHAPTERS_IDS)?.takeUnless { it.isEmpty() }
val downloadedIds = getDoneChapters()
lastPublishedState = DownloadState2(manga, isIndeterminate = true)
lastPublishedState = DownloadState(manga, isIndeterminate = true)
return try {
downloadMangaImpl(chaptersIds, downloadedIds)
Result.success(currentState.toWorkData())
@@ -291,7 +291,7 @@ class DownloadWorker @AssistedInject constructor(
return file
}
private suspend fun publishState(state: DownloadState2) {
private suspend fun publishState(state: DownloadState) {
val previousState = currentState
lastPublishedState = state
if (previousState.isParticularProgress && state.isParticularProgress) {
@@ -314,7 +314,7 @@ class DownloadWorker @AssistedInject constructor(
private suspend fun getDoneChapters(): LongArray {
val work = WorkManagerHelper(WorkManager.getInstance(applicationContext)).getWorkInfoById(id)
?: return LongArray(0)
return DownloadState2.getDownloadedChapters(work.progress)
return DownloadState.getDownloadedChapters(work.progress)
}
private fun getChapters(

View File

@@ -1,4 +1,4 @@
package org.koitharu.kotatsu.download.ui.service
package org.koitharu.kotatsu.download.ui.worker
import androidx.annotation.AnyThread
import kotlinx.coroutines.flow.MutableStateFlow

View File

@@ -7,7 +7,6 @@ import android.content.IntentFilter
import android.net.Uri
import android.os.PatternMatcher
import androidx.core.app.PendingIntentCompat
import org.koitharu.kotatsu.download.ui.service.PausingHandle
import org.koitharu.kotatsu.utils.ext.toUUIDOrNull
import java.util.UUID

View File

@@ -26,7 +26,7 @@ import org.koitharu.kotatsu.parsers.util.json.mapJSONTo
import org.koitharu.kotatsu.sync.data.SyncAuthApi
import org.koitharu.kotatsu.sync.data.SyncAuthenticator
import org.koitharu.kotatsu.sync.data.SyncInterceptor
import org.koitharu.kotatsu.utils.GZipInterceptor
import org.koitharu.kotatsu.core.network.GZipInterceptor
import org.koitharu.kotatsu.utils.ext.parseJsonOrNull
import org.koitharu.kotatsu.utils.ext.toContentValues
import org.koitharu.kotatsu.utils.ext.toJson

View File

@@ -1,14 +0,0 @@
package org.koitharu.kotatsu.utils
import okhttp3.Interceptor
import okhttp3.Response
import org.koitharu.kotatsu.core.network.CommonHeaders.CONTENT_ENCODING
class GZipInterceptor : Interceptor {
override fun intercept(chain: Interceptor.Chain): Response {
val newRequest = chain.request().newBuilder()
newRequest.addHeader(CONTENT_ENCODING, "gzip")
return chain.proceed(newRequest.build())
}
}

View File

@@ -1,4 +1,4 @@
package org.koitharu.kotatsu.download.ui.worker
package org.koitharu.kotatsu.utils
import android.os.SystemClock

View File

@@ -3,7 +3,7 @@ package org.koitharu.kotatsu.utils.progress
import androidx.annotation.AnyThread
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.StateFlow
import org.koitharu.kotatsu.download.ui.service.PausingHandle
import org.koitharu.kotatsu.download.ui.worker.PausingHandle
class PausingProgressJob<P>(
job: Job,
@@ -23,4 +23,4 @@ class PausingProgressJob<P>(
@AnyThread
fun resume() = pausingHandle.resume()
}
}