diff --git a/README.md b/README.md index a2a6ba3f..249a8589 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ *Pupil, Hitomi.la viewer for Android* ![](https://img.shields.io/github/downloads/tom5079/Pupil/total) -[![](https://img.shields.io/github/downloads/tom5079/Pupil/5.2.7/Pupil-v5.2.7.apk?color=%234fc3f7&label=DOWNLOAD%20APP&style=for-the-badge)](https://github.com/tom5079/Pupil/releases/download/5.2.7/Pupil-v5.2.7.apk) +[![](https://img.shields.io/github/downloads/tom5079/Pupil/5.2.8/Pupil-v5.2.8.apk?color=%234fc3f7&label=DOWNLOAD%20APP&style=for-the-badge)](https://github.com/tom5079/Pupil/releases/download/5.2.8/Pupil-v5.2.8.apk) [![](https://discordapp.com/api/guilds/610452916612104194/embed.png?style=banner2)](https://discord.gg/Stj4b5v) # Features diff --git a/app/build.gradle b/app/build.gradle index 3f2ac10c..4f7dcf3f 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -38,7 +38,7 @@ android { minSdkVersion 16 targetSdkVersion 31 versionCode 69 - versionName "5.2.8-BETA01" + versionName "5.2.8" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" vectorDrawables.useSupportLibrary = true } diff --git a/app/release/output-metadata.json b/app/release/output-metadata.json index 966545ef..5543bf8b 100644 --- a/app/release/output-metadata.json +++ b/app/release/output-metadata.json @@ -12,7 +12,7 @@ "filters": [], "attributes": [], "versionCode": 69, - "versionName": "5.2.8-BETA01", + "versionName": "5.2.8", "outputFile": "app-release.apk" } ], diff --git a/app/src/main/java/xyz/quaver/pupil/Pupil.kt b/app/src/main/java/xyz/quaver/pupil/Pupil.kt index 66762a51..c7173cde 100644 --- a/app/src/main/java/xyz/quaver/pupil/Pupil.kt +++ b/app/src/main/java/xyz/quaver/pupil/Pupil.kt @@ -39,7 +39,6 @@ import com.github.piasy.biv.loader.fresco.FrescoImageLoader import com.google.android.gms.common.GooglePlayServicesNotAvailableException import com.google.android.gms.common.GooglePlayServicesRepairableException import com.google.android.gms.security.ProviderInstaller -import com.google.android.material.snackbar.Snackbar import com.google.firebase.crashlytics.FirebaseCrashlytics import kotlinx.coroutines.* import kotlinx.coroutines.channels.BufferOverflow @@ -47,13 +46,12 @@ import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.asSharedFlow import okhttp3.* import xyz.quaver.io.FileX -import xyz.quaver.pupil.hitomi.evaluations +import xyz.quaver.pupil.hitomi.evaluationContext import xyz.quaver.pupil.types.Tag import xyz.quaver.pupil.util.* import java.io.File import java.net.URL import java.util.* -import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.Executors import java.util.concurrent.TimeUnit import kotlin.reflect.KClass @@ -96,31 +94,29 @@ fun reloadWebView() { if (reloadJob?.isActive == true) return reloadJob = CoroutineScope(Dispatchers.IO).launch { - if (evaluations.isEmpty()) { - webViewReady = false - webViewFailed = false + webViewReady = false + webViewFailed = false - while (evaluations.isNotEmpty()) yield() + evaluationContext.cancelChildren() - runCatching { - URL( - if (isDebugBuild) - "https://tom5079.github.io/Pupil/hitomi-dev.html" - else - "https://tom5079.github.io/Pupil/hitomi.html" - ).readText() - }.onFailure { - webViewFailed = true - }.getOrNull()?.let { html -> - launch(Dispatchers.Main) { - webView.loadDataWithBaseURL( - "https://hitomi.la/", - html, - "text/html", - null, - null - ) - } + runCatching { + URL( + if (isDebugBuild) + "https://tom5079.github.io/Pupil/hitomi-dev.html" + else + "https://tom5079.github.io/Pupil/hitomi.html" + ).readText() + }.onFailure { + webViewFailed = true + }.getOrNull()?.let { html -> + launch(Dispatchers.Main) { + webView.loadDataWithBaseURL( + "https://hitomi.la/", + html, + "text/html", + null, + null + ) } } } @@ -191,7 +187,6 @@ class Pupil : Application() { "onReceivedError: ${error?.description}" ) } - webViewFailed = true } } diff --git a/app/src/main/java/xyz/quaver/pupil/hitomi/common.kt b/app/src/main/java/xyz/quaver/pupil/hitomi/common.kt index 0c53f4e7..5e338d86 100644 --- a/app/src/main/java/xyz/quaver/pupil/hitomi/common.kt +++ b/app/src/main/java/xyz/quaver/pupil/hitomi/common.kt @@ -16,6 +16,7 @@ package xyz.quaver.pupil.hitomi +import android.util.Log import android.webkit.WebView import android.widget.Toast import com.google.common.collect.ConcurrentHashMultiset @@ -37,21 +38,25 @@ import kotlin.coroutines.suspendCoroutine const val protocol = "https:" -val evaluations = Collections.newSetFromMap(ConcurrentHashMap()) +val evaluationContext = Dispatchers.Main + Job() -suspend fun WebView.evaluate(script: String): String = withContext(Dispatchers.Main) { - val result: String = withTimeout(10000) { - while (webViewFailed || !webViewReady) yield() +suspend fun WebView.evaluate(script: String): String = coroutineScope { + var result: String? = null - val uid = UUID.randomUUID().toString() + while (result == null) { + try { + result = withContext(evaluationContext) { + while (webViewFailed || !webViewReady) yield() - evaluations.add(uid) + suspendCoroutine { continuation -> + evaluateJavascript(script) { + continuation.resume(it) + } + } - suspendCoroutine { continuation -> - evaluateJavascript(script) { - evaluations.remove(uid) - continuation.resume(it) } + } catch (e: CancellationException) { + continue } } @@ -59,26 +64,36 @@ suspend fun WebView.evaluate(script: String): String = withContext(Dispatchers.M } @OptIn(ExperimentalCoroutinesApi::class) -suspend fun WebView.evaluatePromise(script: String, then: String = ".then(result => Callback.onResult(%uid, JSON.stringify(result))).catch(err => Callback.onError(%uid, JSON.stringify(error)))"): String? = withContext(Dispatchers.Main) { - val flow: Flow> = withTimeout(10000) { - while (webViewFailed || !webViewReady) yield() +suspend fun WebView.evaluatePromise( + script: String, + then: String = ".then(result => Callback.onResult(%uid, JSON.stringify(result))).catch(err => Callback.onError(%uid, JSON.stringify(error)))" +): String? = coroutineScope { + var result: String? = null - val uid = UUID.randomUUID().toString() + while (result == null) { + try { + result = withContext(evaluationContext) { + while (webViewFailed || !webViewReady) yield() - evaluations.add(uid) + val uid = UUID.randomUUID().toString() - evaluateJavascript((script+then).replace("%uid", "'$uid'"), null) + evaluateJavascript((script + then).replace("%uid", "'$uid'"), null) - webViewFlow.transformWhile { (currentUid, result) -> - if (currentUid == uid) { - evaluations.remove(uid) - emit(currentUid to result) + val flow: Flow> = webViewFlow.transformWhile { (currentUid, result) -> + if (currentUid == uid) { + emit(currentUid to result) + } + currentUid != uid + } + + flow.first().second } - currentUid != uid + } catch (e: CancellationException) { + continue } } - flow.first().second + result } @Suppress("EXPERIMENTAL_API_USAGE") @@ -108,16 +123,6 @@ suspend fun urlFromUrlFromHash(galleryID: Int, image: GalleryFiles, dir: String? """.trimIndent() ) - - FirebaseCrashlytics.getInstance().log( - """ - url_from_url_from_hash( - ${galleryID.toString().js}, - ${Json.encodeToString(image)}, - ${dir.js}, ${ext.js}, ${base.js} - ) - """.trimIndent() - ) return Json.decodeFromString(result) }