Improved search speed

This commit is contained in:
tom5079
2022-01-09 00:34:29 +09:00
parent 0fd2cf4fd7
commit 0902fdf981
9 changed files with 76 additions and 43 deletions

View File

@@ -38,7 +38,7 @@ android {
minSdkVersion 16
targetSdkVersion 31
versionCode 69
versionName "5.2.9"
versionName "5.2.10"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
vectorDrawables.useSupportLibrary = true
}
@@ -111,6 +111,7 @@ dependencies {
implementation 'com.github.piasy:BigImageViewer:1.8.1'
implementation 'com.github.piasy:FrescoImageLoader:1.8.1'
implementation 'com.github.piasy:FrescoImageViewFactory:1.8.1'
implementation 'com.facebook.fresco:imagepipeline-okhttp3:2.6.0'
//noinspection GradleDependency
implementation "com.squareup.okhttp3:okhttp:$okhttp_version"

View File

@@ -12,7 +12,7 @@
"filters": [],
"attributes": [],
"versionCode": 69,
"versionName": "5.2.9",
"versionName": "5.2.10",
"outputFile": "app-release.apk"
}
],

View File

@@ -20,10 +20,13 @@
package xyz.quaver.pupil
import android.os.Build
import android.util.Log
import android.webkit.*
import android.widget.Toast
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.platform.app.InstrumentationRegistry
import com.google.firebase.crashlytics.FirebaseCrashlytics
import kotlinx.coroutines.*
import org.junit.Before
import org.junit.Test
@@ -43,30 +46,48 @@ class ExampleInstrumentedTest {
runBlocking {
withContext(Dispatchers.Main) {
WebView.setWebContentsDebuggingEnabled(true)
webView = WebView(appContext).apply {
settings.javaScriptEnabled = true
with (settings) {
javaScriptEnabled = true
domStorageEnabled = true
}
userAgent = settings.userAgentString
webViewClient = object: WebViewClient() {
override fun onPageFinished(view: WebView?, url: String?) {
webViewReady = true
}
override fun onReceivedError(
view: WebView?,
request: WebResourceRequest?,
error: WebResourceError?
) {
}
}
webChromeClient = object: WebChromeClient() {
override fun onConsoleMessage(consoleMessage: ConsoleMessage?): Boolean {
return super.onConsoleMessage(consoleMessage)
}
}
addJavascriptInterface(object {
@JavascriptInterface
fun onResult(uid: String, result: String) {
_webViewFlow.tryEmit(uid to result)
}
@JavascriptInterface
fun onError(uid: String, message: String) {
_webViewFlow.tryEmit(uid to null)
}
}, "Callback")
loadDataWithBaseURL(
"https://hitomi.la/",
"""
<script src="https://ltn.hitomi.la/jquery.min.js"></script>
<script src="https://ltn.hitomi.la/common.js"></script>
<script src="https://ltn.hitomi.la/search.js"></script>
<script src="https://ltn.hitomi.la/searchlib.js"></script>
<script src="https://ltn.hitomi.la/results.js></script>
""".trimIndent(),
"text/html",
null,
null
)
}
reloadWhenFailedOrUpdate()
}
}
}
@@ -74,7 +95,7 @@ class ExampleInstrumentedTest {
@Test
fun test_getGalleryIDsFromNozomi() {
runBlocking {
val result = getGalleryIDsFromNozomi(null, "index", "all")
val result = getGalleryIDsFromNozomi(null, "boten", "all")
Log.d("PUPILD", "getGalleryIDsFromNozomi: ${result.size}")
}

View File

@@ -34,6 +34,7 @@ import android.widget.Toast
import androidx.appcompat.app.AppCompatDelegate
import androidx.core.content.ContextCompat
import androidx.preference.PreferenceManager
import com.facebook.imagepipeline.backends.okhttp3.OkHttpImagePipelineConfigFactory
import com.github.piasy.biv.BigImageViewer
import com.github.piasy.biv.loader.fresco.FrescoImageLoader
import com.google.android.gms.common.GooglePlayServicesNotAvailableException
@@ -79,15 +80,10 @@ val client: OkHttpClient
@SuppressLint("StaticFieldLeak")
lateinit var webView: WebView
val _webViewFlow = MutableSharedFlow<Pair<String, String?>>(
extraBufferCapacity = 2,
onBufferOverflow = BufferOverflow.DROP_OLDEST
)
val _webViewFlow = MutableSharedFlow<Pair<String, String?>>()
val webViewFlow = _webViewFlow.asSharedFlow()
var webViewReady = false
private set
var webViewFailed = false
private set
private var reloadJob: Job? = null
fun reloadWebView() {
@@ -203,11 +199,15 @@ class Pupil : Application() {
addJavascriptInterface(object {
@JavascriptInterface
fun onResult(uid: String, result: String) {
_webViewFlow.tryEmit(uid to result)
CoroutineScope(Dispatchers.Unconfined).launch {
_webViewFlow.emit(uid to result)
}
}
@JavascriptInterface
fun onError(uid: String, message: String) {
_webViewFlow.tryEmit(uid to null)
CoroutineScope(Dispatchers.Unconfined).launch {
_webViewFlow.emit(uid to null)
}
Toast.makeText(this@Pupil, message, Toast.LENGTH_LONG).show()
FirebaseCrashlytics.getInstance().recordException(
Exception(message)
@@ -238,6 +238,7 @@ class Pupil : Application() {
.addInterceptor { chain ->
val request = chain.request().newBuilder()
.header("User-Agent", userAgent)
.header("Referer", "https://hitomi.la/")
.build()
val tag = request.tag() ?: return@addInterceptor chain.proceed(request)
@@ -291,7 +292,14 @@ class Pupil : Application() {
e.printStackTrace()
}
BigImageViewer.initialize(FrescoImageLoader.with(this))
BigImageViewer.initialize(
FrescoImageLoader.with(
this,
OkHttpImagePipelineConfigFactory
.newBuilder(this, client)
.build()
)
)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val manager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager

View File

@@ -77,8 +77,6 @@ suspend fun WebView.evaluatePromise(
val uid = UUID.randomUUID().toString()
evaluateJavascript((script + then).replace("%uid", "'$uid'"), null)
val flow: Flow<Pair<String, String?>> = webViewFlow.transformWhile { (currentUid, result) ->
if (currentUid == uid) {
emit(currentUid to result)
@@ -86,6 +84,10 @@ suspend fun WebView.evaluatePromise(
currentUid != uid
}
launch {
evaluateJavascript((script + then).replace("%uid", "'$uid'"), null)
}
flow.first().second
}
} catch (e: CancellationException) {
@@ -100,7 +102,7 @@ suspend fun WebView.evaluatePromise(
suspend fun getGalleryInfo(galleryID: Int): GalleryInfo {
val result = webView.evaluatePromise("get_gallery_info($galleryID)")
return json.decodeFromString(result!!)
return json.decodeFromString(result)
}
//common.js

View File

@@ -52,7 +52,7 @@ suspend fun getGalleryBlock(galleryID: Int) : GalleryBlock {
});
""".trimIndent(),
then = ""
)!!
)
val doc = Jsoup.parse(html)

View File

@@ -16,6 +16,7 @@
package xyz.quaver.pupil.hitomi
import android.util.Log
import kotlinx.coroutines.*
import java.util.*
@@ -47,7 +48,7 @@ suspend fun doSearch(query: String, sortByPopularity: Boolean = false) : Set<Int
}
}
val negativeResults = negativeTerms.map {
val negativeResults = negativeTerms.mapIndexed { index, it ->
async {
runCatching {
getGalleryIDsForQuery(it)
@@ -55,21 +56,21 @@ suspend fun doSearch(query: String, sortByPopularity: Boolean = false) : Set<Int
}
}
var results = when {
val results = when {
sortByPopularity -> getGalleryIDsFromNozomi(null, "popular", "all")
positiveTerms.isEmpty() -> getGalleryIDsFromNozomi(null, "index", "all")
else -> emptySet()
}
}.toMutableSet()
fun filterPositive(newResults: Set<Int>) {
results = when {
results.isEmpty() -> newResults
else -> results intersect newResults
when {
results.isEmpty() -> results.addAll(newResults)
else -> results.retainAll(newResults)
}
}
fun filterNegative(newResults: Set<Int>) {
results = results subtract newResults
results.removeAll(newResults)
}
//positive results
@@ -78,7 +79,7 @@ suspend fun doSearch(query: String, sortByPopularity: Boolean = false) : Set<Int
}
//negative results
negativeResults.forEach {
negativeResults.forEachIndexed { index, it ->
filterNegative(it.await())
}

View File

@@ -27,7 +27,7 @@ const val extension = ".html"
@OptIn(ExperimentalSerializationApi::class)
suspend fun getGalleryIDsForQuery(query: String) : Set<Int> {
val result = webView.evaluatePromise("get_galleryids_for_query('$query')") ?: return emptySet()
val result = webView.evaluatePromise("get_galleryids_for_query('$query')")
return Json.decodeFromString(result)
}
@@ -37,7 +37,7 @@ data class Suggestion(val s: String, val t: Int, val u: String, val n: String)
@OptIn(ExperimentalSerializationApi::class)
suspend fun getSuggestionsForQuery(query: String) : List<Suggestion> {
val result = webView.evaluatePromise("get_suggestions_for_query('$query')") ?: return emptyList()
val result = webView.evaluatePromise("get_suggestions_for_query('$query')")
return Json.decodeFromString<List<List<Suggestion>?>>(result)[0] ?: return emptyList()
}