Refactor repository creation

This commit is contained in:
Koitharu
2021-01-20 20:27:47 +02:00
parent bb1dd74277
commit 9054f5720f
7 changed files with 77 additions and 39 deletions

View File

@@ -93,7 +93,7 @@ class DownloadService : BaseService() {
checkNotNull(destination) { getString(R.string.cannot_find_available_storage) }
var output: MangaZip? = null
try {
val repo = manga.source.repository
val repo = mangaRepositoryOf(manga.source)
val cover = runCatching {
imageLoader.execute(
ImageRequest.Builder(this@DownloadService)

View File

@@ -3,16 +3,20 @@ package org.koitharu.kotatsu.reader.domain
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.net.Uri
import android.util.ArrayMap
import androidx.collection.LongSparseArray
import androidx.collection.set
import kotlinx.coroutines.*
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
import okhttp3.OkHttpClient
import org.koitharu.kotatsu.core.model.RequestDraft
import org.koin.core.component.KoinComponent
import org.koitharu.kotatsu.core.model.MangaPage
import org.koitharu.kotatsu.core.network.CommonHeaders
import org.koitharu.kotatsu.core.parser.MangaRepository
import org.koitharu.kotatsu.local.data.PagesCache
import org.koitharu.kotatsu.utils.CacheUtils
import org.koitharu.kotatsu.utils.ext.await
import org.koitharu.kotatsu.utils.ext.mangaRepositoryOf
import java.io.File
import java.util.zip.ZipFile
@@ -20,45 +24,61 @@ class PageLoader(
scope: CoroutineScope,
private val okHttp: OkHttpClient,
private val cache: PagesCache
) : CoroutineScope by scope {
) : CoroutineScope by scope, KoinComponent {
private val tasks = ArrayMap<String, Deferred<File>>()
private var repository: MangaRepository? = null
private val tasks = LongSparseArray<Deferred<File>>()
private val convertLock = Mutex()
suspend fun loadFile(requestDraft: RequestDraft, force: Boolean): File {
suspend fun loadPage(page: MangaPage, force: Boolean): File {
if (!force) {
cache[requestDraft.url]?.let {
cache[page.url]?.let {
return it
}
}
val task =
tasks[requestDraft.url]?.takeUnless { it.isCancelled || (force && it.isCompleted) }
return (task ?: loadAsync(requestDraft).also { tasks[requestDraft.url] = it }).await()
var task = tasks[page.id]
if (force) {
task?.cancel()
} else if (task?.isCancelled == false) {
return task.await()
}
task = loadAsync(page)
tasks[page.id] = task
return task.await()
}
private fun loadAsync(requestDraft: RequestDraft) = async(Dispatchers.IO) {
val uri = Uri.parse(requestDraft.url)
if (uri.scheme == "cbz") {
val zip = ZipFile(uri.schemeSpecificPart)
val entry = zip.getEntry(uri.fragment)
zip.getInputStream(entry).use {
cache.put(requestDraft.url, it)
}
} else {
val request = requestDraft.newBuilder()
.header(CommonHeaders.ACCEPT, "image/webp,image/png;q=0.9,image/jpeg,*/*;q=0.8")
.cacheControl(CacheUtils.CONTROL_DISABLED)
.build()
okHttp.newCall(request).await().use { response ->
check(response.isSuccessful) {
"Invalid response: ${response.code} ${response.message}"
}
val body = checkNotNull(response.body) {
"Null response"
}
body.byteStream().use {
private fun loadAsync(page: MangaPage): Deferred<File> {
var repo = repository
if (repo?.javaClass != page.source.cls) {
repo = mangaRepositoryOf(page.source)
repository = repo
}
return async(Dispatchers.IO) {
val requestDraft = repo.getPageRequest(page)
check(requestDraft.isValid) { "Cannot obtain full image url" }
val uri = Uri.parse(requestDraft.url)
if (uri.scheme == "cbz") {
val zip = ZipFile(uri.schemeSpecificPart)
val entry = zip.getEntry(uri.fragment)
zip.getInputStream(entry).use {
cache.put(requestDraft.url, it)
}
} else {
val request = requestDraft.newBuilder()
.header(CommonHeaders.ACCEPT, "image/webp,image/png;q=0.9,image/jpeg,*/*;q=0.8")
.cacheControl(CacheUtils.CONTROL_DISABLED)
.build()
okHttp.newCall(request).await().use { response ->
check(response.isSuccessful) {
"Invalid response: ${response.code} ${response.message}"
}
val body = checkNotNull(response.body) {
"Null response"
}
body.byteStream().use {
cache.put(requestDraft.url, it)
}
}
}
}
}

View File

@@ -88,11 +88,7 @@ class PageHolderDelegate(
error = null
callback.onLoadingStarted()
try {
val file = withContext(Dispatchers.IO) {
val pageRequest = data.source.repository.getPageRequest(data)
check(pageRequest.isValid) { "Cannot obtain full image url" }
loader.loadFile(pageRequest, force)
}
val file = loader.loadPage(data, force)
this@PageHolderDelegate.file = file
state = State.LOADED
callback.onImageReady(file.toUri())

View File

@@ -18,6 +18,7 @@ import org.koitharu.kotatsu.core.prefs.AppSettings
import org.koitharu.kotatsu.databinding.SheetPagesBinding
import org.koitharu.kotatsu.list.ui.MangaListSpanResolver
import org.koitharu.kotatsu.reader.ui.thumbnails.adapter.PageThumbnailAdapter
import org.koitharu.kotatsu.utils.ext.mangaRepositoryOf
import org.koitharu.kotatsu.utils.ext.resolveDp
import org.koitharu.kotatsu.utils.ext.viewLifecycleScope
import org.koitharu.kotatsu.utils.ext.withArgs
@@ -36,7 +37,7 @@ class PagesThumbnailsSheet : BaseBottomSheet<SheetPagesBinding>(),
return
}
val current = arguments?.getInt(ARG_CURRENT, -1) ?: -1
val repository = pages.first().source.repository
val repository = mangaRepositoryOf(pages.first().source)
thumbnails = pages.mapIndexed { i, x ->
PageThumbnail(
number = i + 1,

View File

@@ -9,6 +9,7 @@ import org.koitharu.kotatsu.core.model.MangaSource
import org.koitharu.kotatsu.core.parser.RemoteMangaRepository
import org.koitharu.kotatsu.core.prefs.SourceSettings
import org.koitharu.kotatsu.settings.utils.EditTextSummaryProvider
import org.koitharu.kotatsu.utils.ext.mangaRepositoryOf
import org.koitharu.kotatsu.utils.ext.withArgs
class SourceSettingsFragment : PreferenceFragmentCompat() {
@@ -24,7 +25,7 @@ class SourceSettingsFragment : PreferenceFragmentCompat() {
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
preferenceManager.sharedPreferencesName = source.name
val repo = source.repository as? RemoteMangaRepository ?: return
val repo = mangaRepositoryOf(source) as? RemoteMangaRepository ?: return
val keys = repo.onCreatePreferences()
addPreferencesFromResource(R.xml.pref_source)
for (i in 0 until preferenceScreen.preferenceCount) {

View File

@@ -21,6 +21,7 @@ import org.koitharu.kotatsu.core.model.MangaChapter
import org.koitharu.kotatsu.core.prefs.AppSettings
import org.koitharu.kotatsu.details.ui.DetailsActivity
import org.koitharu.kotatsu.tracker.domain.TrackingRepository
import org.koitharu.kotatsu.utils.ext.mangaRepositoryOf
import org.koitharu.kotatsu.utils.ext.toBitmapOrNull
import org.koitharu.kotatsu.utils.ext.toUriOrNull
import java.util.concurrent.TimeUnit
@@ -51,7 +52,7 @@ class TrackWorker(context: Context, workerParams: WorkerParameters) :
var success = 0
for (track in tracks) {
val details = runCatching {
track.manga.source.repository.getDetails(track.manga)
mangaRepositoryOf(track.manga.source).getDetails(track.manga)
}.getOrNull()
val chapters = details?.chapters ?: continue
when {

View File

@@ -0,0 +1,19 @@
package org.koitharu.kotatsu.utils.ext
import android.content.ComponentCallbacks
import org.koin.android.ext.android.get
import org.koin.core.component.KoinComponent
import org.koin.core.component.get
import org.koin.core.qualifier.named
import org.koitharu.kotatsu.core.model.MangaSource
import org.koitharu.kotatsu.core.parser.MangaRepository
@Suppress("NOTHING_TO_INLINE")
inline fun ComponentCallbacks.mangaRepositoryOf(source: MangaSource): MangaRepository {
return get(named(source))
}
@Suppress("NOTHING_TO_INLINE")
inline fun KoinComponent.mangaRepositoryOf(source: MangaSource): MangaRepository {
return get(named(source))
}