|
@@ -3,6 +3,7 @@ package io.legado.app.ui.widget.dialog
|
|
|
import android.annotation.SuppressLint
|
|
import android.annotation.SuppressLint
|
|
|
import android.content.Context
|
|
import android.content.Context
|
|
|
import android.content.pm.ActivityInfo
|
|
import android.content.pm.ActivityInfo
|
|
|
|
|
+import android.content.res.Configuration
|
|
|
import android.graphics.Bitmap
|
|
import android.graphics.Bitmap
|
|
|
import android.net.Uri
|
|
import android.net.Uri
|
|
|
import android.net.http.SslError
|
|
import android.net.http.SslError
|
|
@@ -31,7 +32,9 @@ import androidx.appcompat.app.AppCompatActivity
|
|
|
import androidx.core.net.toUri
|
|
import androidx.core.net.toUri
|
|
|
import androidx.core.view.size
|
|
import androidx.core.view.size
|
|
|
import androidx.fragment.app.FragmentManager
|
|
import androidx.fragment.app.FragmentManager
|
|
|
|
|
+import androidx.lifecycle.Lifecycle
|
|
|
import androidx.lifecycle.lifecycleScope
|
|
import androidx.lifecycle.lifecycleScope
|
|
|
|
|
+import androidx.lifecycle.repeatOnLifecycle
|
|
|
import com.google.android.material.bottomsheet.BottomSheetBehavior
|
|
import com.google.android.material.bottomsheet.BottomSheetBehavior
|
|
|
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
|
|
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
|
|
|
import io.legado.app.R
|
|
import io.legado.app.R
|
|
@@ -41,6 +44,7 @@ import io.legado.app.constant.AppLog
|
|
|
import io.legado.app.data.appDb
|
|
import io.legado.app.data.appDb
|
|
|
import io.legado.app.data.entities.BaseSource
|
|
import io.legado.app.data.entities.BaseSource
|
|
|
import io.legado.app.databinding.DialogWebViewBinding
|
|
import io.legado.app.databinding.DialogWebViewBinding
|
|
|
|
|
+import io.legado.app.domain.gateway.AppUiConfigurationGateway
|
|
|
import io.legado.app.exception.NoStackTraceException
|
|
import io.legado.app.exception.NoStackTraceException
|
|
|
import io.legado.app.help.WebCacheManager
|
|
import io.legado.app.help.WebCacheManager
|
|
|
import io.legado.app.help.config.AppConfig
|
|
import io.legado.app.help.config.AppConfig
|
|
@@ -68,6 +72,7 @@ import io.legado.app.utils.invisible
|
|
|
import io.legado.app.utils.longSnackbar
|
|
import io.legado.app.utils.longSnackbar
|
|
|
import io.legado.app.utils.openUrl
|
|
import io.legado.app.utils.openUrl
|
|
|
import io.legado.app.utils.setLayout
|
|
import io.legado.app.utils.setLayout
|
|
|
|
|
+import io.legado.app.utils.setDarkeningAllowed
|
|
|
import io.legado.app.utils.startActivity
|
|
import io.legado.app.utils.startActivity
|
|
|
import io.legado.app.utils.toastOnUi
|
|
import io.legado.app.utils.toastOnUi
|
|
|
import io.legado.app.utils.viewbindingdelegate.viewBinding
|
|
import io.legado.app.utils.viewbindingdelegate.viewBinding
|
|
@@ -75,11 +80,14 @@ import io.legado.app.utils.visible
|
|
|
import io.legado.app.utils.writeBytes
|
|
import io.legado.app.utils.writeBytes
|
|
|
import kotlinx.coroutines.Dispatchers
|
|
import kotlinx.coroutines.Dispatchers
|
|
|
import kotlinx.coroutines.Dispatchers.IO
|
|
import kotlinx.coroutines.Dispatchers.IO
|
|
|
|
|
+import kotlinx.coroutines.flow.distinctUntilChanged
|
|
|
|
|
+import kotlinx.coroutines.flow.map
|
|
|
import kotlinx.coroutines.launch
|
|
import kotlinx.coroutines.launch
|
|
|
import kotlinx.coroutines.runBlocking
|
|
import kotlinx.coroutines.runBlocking
|
|
|
import java.io.ByteArrayInputStream
|
|
import java.io.ByteArrayInputStream
|
|
|
import java.lang.ref.WeakReference
|
|
import java.lang.ref.WeakReference
|
|
|
import java.util.Date
|
|
import java.util.Date
|
|
|
|
|
+import org.koin.android.ext.android.inject
|
|
|
|
|
|
|
|
class BottomWebViewDialog() : BottomSheetDialogFragment(R.layout.dialog_web_view),
|
|
class BottomWebViewDialog() : BottomSheetDialogFragment(R.layout.dialog_web_view),
|
|
|
WebJsExtensions.Callback {
|
|
WebJsExtensions.Callback {
|
|
@@ -116,6 +124,8 @@ class BottomWebViewDialog() : BottomSheetDialogFragment(R.layout.dialog_web_view
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
private val displayMetrics by lazy { resources.displayMetrics }
|
|
private val displayMetrics by lazy { resources.displayMetrics }
|
|
|
|
|
+ private val appUiConfigurationGateway by inject<AppUiConfigurationGateway>()
|
|
|
|
|
+ private var appliedDarkTheme: Boolean? = null
|
|
|
private val selectImageDir = registerForActivityResult(HandleFileContract()) {
|
|
private val selectImageDir = registerForActivityResult(HandleFileContract()) {
|
|
|
it.uri?.let { uri ->
|
|
it.uri?.let { uri ->
|
|
|
ACache.get().put(imagePathKey, uri.toString())
|
|
ACache.get().put(imagePathKey, uri.toString())
|
|
@@ -373,6 +383,7 @@ class BottomWebViewDialog() : BottomSheetDialogFragment(R.layout.dialog_web_view
|
|
|
super.onViewCreated(view, savedInstanceState)
|
|
super.onViewCreated(view, savedInstanceState)
|
|
|
view.setBackgroundColor(0)
|
|
view.setBackgroundColor(0)
|
|
|
binding.webViewContainer.addView(currentWebView)
|
|
binding.webViewContainer.addView(currentWebView)
|
|
|
|
|
+ observeAppTheme()
|
|
|
lifecycleScope.launch(IO) {
|
|
lifecycleScope.launch(IO) {
|
|
|
val args = arguments
|
|
val args = arguments
|
|
|
if (args == null) {
|
|
if (args == null) {
|
|
@@ -502,6 +513,43 @@ class BottomWebViewDialog() : BottomSheetDialogFragment(R.layout.dialog_web_view
|
|
|
currentWebView.loadDataWithBaseURL(url, html, "text/html", "utf-8", url)
|
|
currentWebView.loadDataWithBaseURL(url, html, "text/html", "utf-8", url)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ private fun observeAppTheme() {
|
|
|
|
|
+ viewLifecycleOwner.lifecycleScope.launch {
|
|
|
|
|
+ viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
|
|
|
|
|
+ appUiConfigurationGateway.configuration
|
|
|
|
|
+ .map { it.isDarkTheme }
|
|
|
|
|
+ .distinctUntilChanged()
|
|
|
|
|
+ .collect(::applyWebViewTheme)
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private fun applyWebViewTheme(isDark: Boolean, force: Boolean = false) {
|
|
|
|
|
+ if (!force && appliedDarkTheme == isDark) return
|
|
|
|
|
+ appliedDarkTheme = isDark
|
|
|
|
|
+ val configuration = Configuration(currentWebView.resources.configuration).apply {
|
|
|
|
|
+ uiMode = (uiMode and Configuration.UI_MODE_NIGHT_MASK.inv()) or if (isDark) {
|
|
|
|
|
+ Configuration.UI_MODE_NIGHT_YES
|
|
|
|
|
+ } else {
|
|
|
|
|
+ Configuration.UI_MODE_NIGHT_NO
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ currentWebView.dispatchConfigurationChanged(configuration)
|
|
|
|
|
+ currentWebView.settings.setDarkeningAllowed(isDark)
|
|
|
|
|
+ currentWebView.evaluateJavascript(
|
|
|
|
|
+ """
|
|
|
|
|
+ (() => {
|
|
|
|
|
+ const root = document.documentElement;
|
|
|
|
|
+ if (!root) return;
|
|
|
|
|
+ root.style.setProperty('color-scheme', '${if (isDark) "dark" else "light"}', 'important');
|
|
|
|
|
+ window.dispatchEvent(new CustomEvent('legado-theme-change', { detail: { dark: $isDark } }));
|
|
|
|
|
+ })();
|
|
|
|
|
+ """.trimIndent(),
|
|
|
|
|
+ null,
|
|
|
|
|
+ )
|
|
|
|
|
+ currentWebView.postInvalidate()
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
private fun buildSpliceHtml(originalHtml: String): String {
|
|
private fun buildSpliceHtml(originalHtml: String): String {
|
|
|
if (preloadJs.isNullOrEmpty()) return originalHtml
|
|
if (preloadJs.isNullOrEmpty()) return originalHtml
|
|
|
val headIndex = originalHtml.indexOf("<head", ignoreCase = true)
|
|
val headIndex = originalHtml.indexOf("<head", ignoreCase = true)
|
|
@@ -736,6 +784,11 @@ class BottomWebViewDialog() : BottomSheetDialogFragment(R.layout.dialog_web_view
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ override fun onPageFinished(view: WebView?, url: String?) {
|
|
|
|
|
+ super.onPageFinished(view, url)
|
|
|
|
|
+ appliedDarkTheme?.let { applyWebViewTheme(it, force = true) }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
private fun shouldOverrideUrlLoading(url: Uri): Boolean {
|
|
private fun shouldOverrideUrlLoading(url: Uri): Boolean {
|
|
|
return when (url.scheme) {
|
|
return when (url.scheme) {
|
|
|
"http", "https" -> {
|
|
"http", "https" -> {
|
|
@@ -816,4 +869,4 @@ class BottomWebViewDialog() : BottomSheetDialogFragment(R.layout.dialog_web_view
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
-}
|
|
|
|
|
|
|
+}
|