Restore download after network error
This commit is contained in:
1
.idea/dictionaries/admin.xml
generated
1
.idea/dictionaries/admin.xml
generated
@@ -3,6 +3,7 @@
|
||||
<words>
|
||||
<w>chucker</w>
|
||||
<w>desu</w>
|
||||
<w>failsafe</w>
|
||||
<w>koin</w>
|
||||
<w>kotatsu</w>
|
||||
<w>manga</w>
|
||||
|
||||
@@ -62,7 +62,6 @@ dependencies {
|
||||
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.6'
|
||||
|
||||
implementation 'androidx.core:core-ktx:1.5.0-alpha01'
|
||||
implementation 'androidx.appcompat:appcompat:1.3.0-alpha01'
|
||||
implementation 'androidx.activity:activity-ktx:1.2.0-alpha06'
|
||||
implementation 'androidx.fragment:fragment-ktx:1.3.0-alpha06'
|
||||
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.3.0-alpha05'
|
||||
|
||||
@@ -72,7 +72,6 @@ class LocalMangaRepository : MangaRepository, KoinComponent {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun delete(manga: Manga): Boolean {
|
||||
val file = Uri.parse(manga.url).toFile()
|
||||
return file.delete()
|
||||
|
||||
@@ -13,7 +13,8 @@ import java.util.*
|
||||
object MangaProviderFactory : KoinComponent {
|
||||
|
||||
private val loaderContext by inject<MangaLoaderContext>()
|
||||
private val cache = EnumMap<MangaSource, WeakReference<MangaRepository>>(MangaSource::class.java)
|
||||
private val cache =
|
||||
EnumMap<MangaSource, WeakReference<MangaRepository>>(MangaSource::class.java)
|
||||
|
||||
fun getSources(includeHidden: Boolean): List<MangaSource> {
|
||||
val settings = get<AppSettings>()
|
||||
@@ -33,24 +34,37 @@ object MangaProviderFactory : KoinComponent {
|
||||
}
|
||||
}
|
||||
|
||||
fun createLocal(): LocalMangaRepository =
|
||||
(cache[MangaSource.LOCAL]?.get() as? LocalMangaRepository)
|
||||
?: LocalMangaRepository().also {
|
||||
cache[MangaSource.LOCAL] = WeakReference<MangaRepository>(it)
|
||||
fun createLocal(): LocalMangaRepository {
|
||||
var instance = cache[MangaSource.LOCAL]?.get()
|
||||
if (instance == null) {
|
||||
synchronized(cache) {
|
||||
instance = cache[MangaSource.LOCAL]?.get()
|
||||
if (instance == null) {
|
||||
instance = LocalMangaRepository()
|
||||
cache[MangaSource.LOCAL] = WeakReference<MangaRepository>(instance)
|
||||
}
|
||||
}
|
||||
}
|
||||
return instance as LocalMangaRepository
|
||||
}
|
||||
|
||||
@Throws(Throwable::class)
|
||||
fun create(source: MangaSource): MangaRepository {
|
||||
cache[source]?.get()?.let {
|
||||
return it
|
||||
var instance = cache[source]?.get()
|
||||
if (instance == null) {
|
||||
synchronized(cache) {
|
||||
instance = cache[source]?.get()
|
||||
if (instance == null) {
|
||||
instance = try {
|
||||
source.cls.getDeclaredConstructor(MangaLoaderContext::class.java)
|
||||
.newInstance(loaderContext)
|
||||
} catch (e: NoSuchMethodException) {
|
||||
source.cls.newInstance()
|
||||
}
|
||||
cache[source] = WeakReference(instance!!)
|
||||
}
|
||||
}
|
||||
}
|
||||
val instance = try {
|
||||
source.cls.getDeclaredConstructor(MangaLoaderContext::class.java)
|
||||
.newInstance(loaderContext)
|
||||
} catch (e: NoSuchMethodException) {
|
||||
source.cls.newInstance()
|
||||
}
|
||||
cache[source] = WeakReference<MangaRepository>(instance)
|
||||
return instance
|
||||
return instance!!
|
||||
}
|
||||
}
|
||||
@@ -92,6 +92,11 @@ class DownloadNotification(private val context: Context) {
|
||||
builder.setCategory(NotificationCompat.CATEGORY_PROGRESS)
|
||||
}
|
||||
|
||||
fun setWaitingForNetwork() {
|
||||
builder.setProgress(0, 0, false)
|
||||
builder.setContentText(context.getString(R.string.waiting_for_network))
|
||||
}
|
||||
|
||||
fun setPostProcessing() {
|
||||
builder.setProgress(1, 0, true)
|
||||
builder.setContentText(context.getString(R.string.processing_))
|
||||
|
||||
@@ -13,6 +13,7 @@ import kotlinx.coroutines.*
|
||||
import kotlinx.coroutines.sync.Mutex
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.Request
|
||||
import okio.IOException
|
||||
import org.koin.android.ext.android.inject
|
||||
import org.koitharu.kotatsu.BuildConfig
|
||||
import org.koitharu.kotatsu.R
|
||||
@@ -24,10 +25,7 @@ import org.koitharu.kotatsu.domain.local.MangaZip
|
||||
import org.koitharu.kotatsu.ui.common.BaseService
|
||||
import org.koitharu.kotatsu.ui.common.dialog.CheckBoxAlertDialog
|
||||
import org.koitharu.kotatsu.utils.CacheUtils
|
||||
import org.koitharu.kotatsu.utils.ext.await
|
||||
import org.koitharu.kotatsu.utils.ext.retryUntilSuccess
|
||||
import org.koitharu.kotatsu.utils.ext.safe
|
||||
import org.koitharu.kotatsu.utils.ext.sub
|
||||
import org.koitharu.kotatsu.utils.ext.*
|
||||
import java.io.File
|
||||
import java.util.concurrent.TimeUnit
|
||||
import kotlin.collections.set
|
||||
@@ -37,6 +35,7 @@ class DownloadService : BaseService() {
|
||||
|
||||
private lateinit var notification: DownloadNotification
|
||||
private lateinit var wakeLock: PowerManager.WakeLock
|
||||
private lateinit var connectivityManager: ConnectivityManager
|
||||
|
||||
private val okHttp by inject<OkHttpClient>()
|
||||
private val cache by inject<PagesCache>()
|
||||
@@ -47,6 +46,7 @@ class DownloadService : BaseService() {
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
notification = DownloadNotification(this)
|
||||
connectivityManager = getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
|
||||
wakeLock = (getSystemService(Context.POWER_SERVICE) as PowerManager)
|
||||
.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "kotatsu:downloading")
|
||||
}
|
||||
@@ -88,9 +88,11 @@ class DownloadService : BaseService() {
|
||||
try {
|
||||
val repo = MangaProviderFactory.create(manga.source)
|
||||
val cover = safe {
|
||||
Coil.execute(GetRequestBuilder(this@DownloadService)
|
||||
.data(manga.coverUrl)
|
||||
.build()).drawable
|
||||
Coil.execute(
|
||||
GetRequestBuilder(this@DownloadService)
|
||||
.data(manga.coverUrl)
|
||||
.build()
|
||||
).drawable
|
||||
}
|
||||
withContext(Dispatchers.Main) {
|
||||
notification.setLargeIcon(cover)
|
||||
@@ -112,23 +114,30 @@ class DownloadService : BaseService() {
|
||||
if (chaptersIds == null || chapter.id in chaptersIds) {
|
||||
val pages = repo.getPages(chapter)
|
||||
for ((pageIndex, page) in pages.withIndex()) {
|
||||
val url = repo.getPageFullUrl(page)
|
||||
val file = cache[url] ?: downloadPage(url, destination)
|
||||
output.addPage(
|
||||
chapter,
|
||||
file,
|
||||
pageIndex,
|
||||
MimeTypeMap.getFileExtensionFromUrl(url)
|
||||
failsafe@ do {
|
||||
try {
|
||||
val url = repo.getPageFullUrl(page)
|
||||
val file = cache[url] ?: downloadPage(url, destination)
|
||||
output.addPage(
|
||||
chapter,
|
||||
file,
|
||||
pageIndex,
|
||||
MimeTypeMap.getFileExtensionFromUrl(url)
|
||||
)
|
||||
} catch (e: IOException) {
|
||||
notification.setWaitingForNetwork()
|
||||
notification.update()
|
||||
connectivityManager.waitForNetwork()
|
||||
continue@failsafe
|
||||
}
|
||||
} while (false)
|
||||
notification.setProgress(
|
||||
chapters.size,
|
||||
pages.size,
|
||||
chapterIndex,
|
||||
pageIndex
|
||||
)
|
||||
withContext(Dispatchers.Main) {
|
||||
notification.setProgress(
|
||||
chapters.size,
|
||||
pages.size,
|
||||
chapterIndex,
|
||||
pageIndex
|
||||
)
|
||||
notification.update()
|
||||
}
|
||||
notification.update()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,6 @@ import org.koin.core.get
|
||||
import org.koitharu.kotatsu.BuildConfig
|
||||
import org.koitharu.kotatsu.core.exceptions.UnsupportedFileException
|
||||
import org.koitharu.kotatsu.core.model.Manga
|
||||
import org.koitharu.kotatsu.core.model.MangaSource
|
||||
import org.koitharu.kotatsu.core.parser.LocalMangaRepository
|
||||
import org.koitharu.kotatsu.core.prefs.AppSettings
|
||||
import org.koitharu.kotatsu.domain.MangaProviderFactory
|
||||
@@ -33,7 +32,8 @@ class LocalListPresenter : BasePresenter<MangaListView<File>>() {
|
||||
private lateinit var repository: LocalMangaRepository
|
||||
|
||||
override fun onFirstViewAttach() {
|
||||
repository = MangaProviderFactory.create(MangaSource.LOCAL) as LocalMangaRepository
|
||||
repository = MangaProviderFactory.createLocal()
|
||||
|
||||
super.onFirstViewAttach()
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
package org.koitharu.kotatsu.utils.ext
|
||||
|
||||
import android.net.ConnectivityManager
|
||||
import android.net.Network
|
||||
import android.net.NetworkRequest
|
||||
import kotlinx.coroutines.suspendCancellableCoroutine
|
||||
import kotlin.coroutines.resume
|
||||
|
||||
suspend fun ConnectivityManager.waitForNetwork(): Network {
|
||||
val request = NetworkRequest.Builder().build()
|
||||
return suspendCancellableCoroutine<Network> { cont ->
|
||||
val callback = object : ConnectivityManager.NetworkCallback() {
|
||||
override fun onAvailable(network: Network) {
|
||||
cont.resume(network)
|
||||
}
|
||||
}
|
||||
registerNetworkCallback(request, callback)
|
||||
cont.invokeOnCancellation {
|
||||
unregisterNetworkCallback(callback)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -139,4 +139,5 @@
|
||||
<string name="related">Похожие</string>
|
||||
<string name="new_version_s">Новая версия: %s</string>
|
||||
<string name="size_s">Размер: %s</string>
|
||||
<string name="waiting_for_network">Ожидание подключения…</string>
|
||||
</resources>
|
||||
@@ -140,4 +140,5 @@
|
||||
<string name="related">Related</string>
|
||||
<string name="new_version_s">New version: %s</string>
|
||||
<string name="size_s">Size: %s</string>
|
||||
<string name="waiting_for_network">Waiting for network…</string>
|
||||
</resources>
|
||||
Reference in New Issue
Block a user