Refactor downloading-related classes
This commit is contained in:
@@ -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') {
|
||||
|
||||
@@ -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"
|
||||
@@ -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,
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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())
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package org.koitharu.kotatsu.download.ui.worker
|
||||
package org.koitharu.kotatsu.utils
|
||||
|
||||
import android.os.SystemClock
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user