Autodetect webtoon

This commit is contained in:
Koitharu
2020-02-25 21:14:13 +02:00
parent 6cf9e69f99
commit 331ebfabb4
4 changed files with 76 additions and 3 deletions

View File

@@ -19,8 +19,7 @@ class MangaPreferencesRepository : KoinComponent {
)
}
suspend fun getReaderMode(mangaId: Long): ReaderMode {
suspend fun getReaderMode(mangaId: Long): ReaderMode? {
return db.preferencesDao().find(mangaId)?.let { ReaderMode.valueOf(it.mode) }
?: ReaderMode.UNKNOWN
}
}

View File

@@ -0,0 +1,57 @@
package org.koitharu.kotatsu.domain
import android.graphics.BitmapFactory
import android.util.Size
import okhttp3.OkHttpClient
import okhttp3.Request
import org.koin.core.KoinComponent
import org.koin.core.get
import org.koitharu.kotatsu.BuildConfig
import org.koitharu.kotatsu.core.model.MangaPage
import org.koitharu.kotatsu.core.prefs.ReaderMode
import org.koitharu.kotatsu.utils.ext.await
import org.koitharu.kotatsu.utils.ext.medianOrNull
import java.io.InputStream
object MangaUtils : KoinComponent {
/**
* Automatic determine type of manga by page size
* @return ReaderMode.WEBTOON if page is wide
*/
suspend fun determineReaderMode(pages: List<MangaPage>): ReaderMode? {
try {
val page = pages.medianOrNull() ?: return null
val url = MangaProviderFactory.create(page.source).getPageFullUrl(page)
val client = get<OkHttpClient>()
val request = Request.Builder()
.url(url)
.get()
.build()
val size = client.newCall(request).await().use {
getBitmapSize(it.body?.byteStream())
}
return when {
size.width * 2 < size.height -> ReaderMode.WEBTOON
else -> ReaderMode.STANDARD
}
} catch (e: Exception) {
if (BuildConfig.DEBUG) {
e.printStackTrace()
}
return null
}
}
@JvmStatic
private fun getBitmapSize(input: InputStream?): Size {
val options = BitmapFactory.Options().apply {
inJustDecodeBounds = true
}
BitmapFactory.decodeStream(input, null, options)
val imageHeight: Int = options.outHeight
val imageWidth: Int = options.outWidth
check(imageHeight > 0 && imageWidth > 0)
return Size(imageWidth, imageHeight)
}
}

View File

@@ -15,6 +15,7 @@ import org.koitharu.kotatsu.core.model.MangaPage
import org.koitharu.kotatsu.core.prefs.ReaderMode
import org.koitharu.kotatsu.domain.MangaPreferencesRepository
import org.koitharu.kotatsu.domain.MangaProviderFactory
import org.koitharu.kotatsu.domain.MangaUtils
import org.koitharu.kotatsu.domain.history.HistoryRepository
import org.koitharu.kotatsu.ui.common.BasePresenter
import org.koitharu.kotatsu.utils.MediaStoreCompat
@@ -34,7 +35,18 @@ class ReaderPresenter : BasePresenter<ReaderView>() {
val chapter = state.chapter ?: repo.getDetails(state.manga).chapters
?.first { it.id == state.chapterId }
?: throw RuntimeException("Chapter ${state.chapterId} not found")
repo.getPages(chapter) to MangaPreferencesRepository().getReaderMode(state.manga.id)
var mode = MangaPreferencesRepository().getReaderMode(state.manga.id)
val pages = repo.getPages(chapter)
if (mode == null) {
mode = MangaUtils.determineReaderMode(pages)
if (mode != null) {
MangaPreferencesRepository().saveData(
mangaId = state.manga.id,
mode = mode
)
}
}
pages to (mode ?: ReaderMode.UNKNOWN)
}
viewState.onInitReader(pages, mode, state)
} catch (e: Exception) {

View File

@@ -19,4 +19,9 @@ inline fun <T> Iterable<T>.sumByLong(selector: (T) -> Long): Long {
sum += selector(element)
}
return sum
}
fun <T> List<T>.medianOrNull(): T? = when {
isEmpty() -> null
else -> get((size / 2).coerceIn(indices))
}