|
|
@@ -16,7 +16,6 @@ import androidx.appcompat.app.AppCompatActivity
|
|
|
import androidx.core.view.isVisible
|
|
|
import androidx.lifecycle.lifecycleScope
|
|
|
import com.codex.webviewgrammar.databinding.ActivityMainBinding
|
|
|
-import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
|
|
import kotlinx.coroutines.Dispatchers
|
|
|
import kotlinx.coroutines.launch
|
|
|
import kotlinx.coroutines.suspendCancellableCoroutine
|
|
|
@@ -154,8 +153,13 @@ class MainActivity : AppCompatActivity() {
|
|
|
val result = runCatching { requestHighlight(pageText) }
|
|
|
setActionButtonsEnabled(true)
|
|
|
result.onSuccess { html ->
|
|
|
- binding.statusText.text = getString(R.string.status_ready)
|
|
|
- showHighlightDialog(html)
|
|
|
+ val applied = runCatching { applyHighlightToPage(html) }
|
|
|
+ if (applied.getOrDefault(false)) {
|
|
|
+ binding.statusText.text = getString(R.string.status_ready)
|
|
|
+ } else {
|
|
|
+ val reason = applied.exceptionOrNull()?.message ?: "无法更新页面内容"
|
|
|
+ binding.statusText.text = getString(R.string.error_highlight_failed, reason)
|
|
|
+ }
|
|
|
}.onFailure { err ->
|
|
|
binding.statusText.text = getString(R.string.error_highlight_failed, err.message ?: "")
|
|
|
}
|
|
|
@@ -337,17 +341,28 @@ class MainActivity : AppCompatActivity() {
|
|
|
binding.ttsButton.isEnabled = enabled
|
|
|
}
|
|
|
|
|
|
- private fun showHighlightDialog(html: String) {
|
|
|
- val dialogWebView = WebView(this).apply {
|
|
|
- settings.javaScriptEnabled = false
|
|
|
- settings.defaultTextEncodingName = "utf-8"
|
|
|
- loadDataWithBaseURL(null, html, "text/html", "utf-8", null)
|
|
|
- }
|
|
|
- MaterialAlertDialogBuilder(this)
|
|
|
- .setTitle(R.string.dialog_highlight_title)
|
|
|
- .setView(dialogWebView)
|
|
|
- .setPositiveButton(R.string.action_close, null)
|
|
|
- .show()
|
|
|
+ private suspend fun applyHighlightToPage(html: String): Boolean {
|
|
|
+ val encoded = Base64.encodeToString(html.toByteArray(Charsets.UTF_8), Base64.NO_WRAP)
|
|
|
+ val script = """
|
|
|
+ (function() {
|
|
|
+ try {
|
|
|
+ var raw = window.atob("$encoded");
|
|
|
+ var parser = new DOMParser();
|
|
|
+ var parsed = parser.parseFromString(raw, 'text/html');
|
|
|
+ if (parsed && parsed.documentElement) {
|
|
|
+ document.documentElement.innerHTML = parsed.documentElement.innerHTML;
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ document.body.innerHTML = raw;
|
|
|
+ return true;
|
|
|
+ } catch (e) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ })();
|
|
|
+ """.trimIndent()
|
|
|
+ val rawResult = evaluateJavascript(script)
|
|
|
+ val normalized = decodeJsResult(rawResult)
|
|
|
+ return normalized.equals("true", ignoreCase = true)
|
|
|
}
|
|
|
|
|
|
private class ByteArrayMediaDataSource(private val data: ByteArray) : MediaDataSource() {
|