Autodetect webtoon
This commit is contained in:
@@ -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) }
|
return db.preferencesDao().find(mangaId)?.let { ReaderMode.valueOf(it.mode) }
|
||||||
?: ReaderMode.UNKNOWN
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
57
app/src/main/java/org/koitharu/kotatsu/domain/MangaUtils.kt
Normal file
57
app/src/main/java/org/koitharu/kotatsu/domain/MangaUtils.kt
Normal 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)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -15,6 +15,7 @@ import org.koitharu.kotatsu.core.model.MangaPage
|
|||||||
import org.koitharu.kotatsu.core.prefs.ReaderMode
|
import org.koitharu.kotatsu.core.prefs.ReaderMode
|
||||||
import org.koitharu.kotatsu.domain.MangaPreferencesRepository
|
import org.koitharu.kotatsu.domain.MangaPreferencesRepository
|
||||||
import org.koitharu.kotatsu.domain.MangaProviderFactory
|
import org.koitharu.kotatsu.domain.MangaProviderFactory
|
||||||
|
import org.koitharu.kotatsu.domain.MangaUtils
|
||||||
import org.koitharu.kotatsu.domain.history.HistoryRepository
|
import org.koitharu.kotatsu.domain.history.HistoryRepository
|
||||||
import org.koitharu.kotatsu.ui.common.BasePresenter
|
import org.koitharu.kotatsu.ui.common.BasePresenter
|
||||||
import org.koitharu.kotatsu.utils.MediaStoreCompat
|
import org.koitharu.kotatsu.utils.MediaStoreCompat
|
||||||
@@ -34,7 +35,18 @@ class ReaderPresenter : BasePresenter<ReaderView>() {
|
|||||||
val chapter = state.chapter ?: repo.getDetails(state.manga).chapters
|
val chapter = state.chapter ?: repo.getDetails(state.manga).chapters
|
||||||
?.first { it.id == state.chapterId }
|
?.first { it.id == state.chapterId }
|
||||||
?: throw RuntimeException("Chapter ${state.chapterId} not found")
|
?: 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)
|
viewState.onInitReader(pages, mode, state)
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
|
|||||||
@@ -19,4 +19,9 @@ inline fun <T> Iterable<T>.sumByLong(selector: (T) -> Long): Long {
|
|||||||
sum += selector(element)
|
sum += selector(element)
|
||||||
}
|
}
|
||||||
return sum
|
return sum
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T> List<T>.medianOrNull(): T? = when {
|
||||||
|
isEmpty() -> null
|
||||||
|
else -> get((size / 2).coerceIn(indices))
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user