@@ -9,6 +9,7 @@ import android.os.Handler
99import android.os.Looper
1010import android.os.SystemClock
1111import android.util.Base64
12+ import android.view.ContextThemeWrapper
1213import android.view.MotionEvent
1314import android.view.View
1415import android.view.ViewGroup
@@ -24,6 +25,7 @@ import android.webkit.WebViewClient
2425import android.widget.FrameLayout
2526import androidx.webkit.WebSettingsCompat
2627import androidx.webkit.WebViewFeature
28+ import com.aicode.R
2729import com.aicode.core.util.FileLogger
2830import com.aicode.feature.agent.domain.model.AgentImage
2931import com.aicode.feature.workspace.domain.FileAccessProvider
@@ -119,16 +121,16 @@ class BrowserManager @Inject constructor(
119121 private const val NIGHT_STYLE_ID = " __bicode_night_css__"
120122 private val NIGHT_BG_COLOR = 0xFF121212 .toInt()
121123
122- /* * 反色夜间样式:整页 invert + hue-rotate,图片/视频二次反色还原原始观感 。 */
124+ /* * 夜间压暗样式:页面顶层盖一层半透明黑色蒙版,保留原色、只降低亮度(不改色相、不影响 fixed 布局) 。 */
123125 private const val NIGHT_CSS =
124- " html{filter:invert(1) hue-rotate(180deg);background:#fff}" +
125- " img,video,picture,canvas,svg image,[style*=\" background-image\" ]" +
126- " {filter:invert(1) hue-rotate(180deg)}"
126+ " html::after{content:'';position:fixed;top:0;left:0;right:0;bottom:0;" +
127+ " pointer-events:none;z-index:2147483647;background:rgba(0,0,0,0.2)}"
127128 }
128129
129130 private class TabHolder (
130131 val id : String ,
131132 val webView : WebView ,
133+ val themedContext : ContextThemeWrapper ,
132134 var url : String = " " ,
133135 var title : String = " " ,
134136 var loading : Boolean = false ,
@@ -399,9 +401,11 @@ class BrowserManager @Inject constructor(
399401 }
400402
401403 private fun createTabInternal (id : String , initialUrl : String? ): TabHolder {
402- val wv = WebView (appContext)
404+ // WebView 依据其上下文主题的 isLightTheme 向网页报告 prefers-color-scheme,必须用专用主题构建
405+ val themedContext = ContextThemeWrapper (appContext, webViewThemeRes(nightMode))
406+ val wv = WebView (themedContext)
403407 configureWebView(wv, id)
404- val tab = TabHolder (id = id, webView = wv)
408+ val tab = TabHolder (id = id, webView = wv, themedContext = themedContext )
405409 tabs.add(tab)
406410 activeTabId = id
407411
@@ -449,37 +453,39 @@ class BrowserManager @Inject constructor(
449453 private fun applyNightMode () {
450454 val night = nightMode
451455 tabs.forEach { tab ->
456+ // 先更新主题,让随后的 settings 变更触发 WebView 重读 prefers-color-scheme
457+ tab.themedContext.setTheme(webViewThemeRes(night))
452458 tab.webView.setBackgroundColor(if (night) NIGHT_BG_COLOR else Color .WHITE )
453459 applyDarkThemeToSettings(tab.webView)
454460 applyNightModeTo(tab.webView)
455461 }
456462 publishState()
457463 }
458464
459- /* * 适配内核级暗色模式(开启 prefers-color-scheme: dark 支持)。 */
465+ /* * WebView 主题:isLightTheme 决定网页看到的 prefers-color-scheme(见 values/styles.xml)。 */
466+ private fun webViewThemeRes (night : Boolean ): Int =
467+ if (night) R .style.Theme_AICode_WebView_Dark else R .style.Theme_AICode_WebView
468+
469+ /* *
470+ * 内核级暗色设置。prefers-color-scheme 实际由 WebView 主题的 isLightTheme 决定(见 [webViewThemeRes]),
471+ * 这里设置算法调暗并借此触发 WebView 重读偏好——夜间模式切换后需要一次 settings 变更才会下发新偏好。
472+ */
460473 private fun applyDarkThemeToSettings (wv : WebView ) {
461- val night = nightMode
462474 try {
463475 if (WebViewFeature .isFeatureSupported(WebViewFeature .ALGORITHMIC_DARKENING )) {
464- WebSettingsCompat .setAlgorithmicDarkeningAllowed(wv.settings, night)
476+ // 保持原色,不做内核算法调暗;此处借该开关的值变化触发 WebView 重读偏好——
477+ // 夜间模式切换后必须有一次 settings 变更,新的 prefers-color-scheme 才会下发到渲染进程。
478+ WebSettingsCompat .setAlgorithmicDarkeningAllowed(wv.settings, true )
479+ WebSettingsCompat .setAlgorithmicDarkeningAllowed(wv.settings, false )
465480 } else if (WebViewFeature .isFeatureSupported(WebViewFeature .FORCE_DARK )) {
466- WebSettingsCompat .setForceDark(
467- wv.settings,
468- if (night) WebSettingsCompat .FORCE_DARK_ON else WebSettingsCompat .FORCE_DARK_OFF
469- )
470- if (WebViewFeature .isFeatureSupported(WebViewFeature .FORCE_DARK_STRATEGY )) {
471- WebSettingsCompat .setForceDarkStrategy(
472- wv.settings,
473- WebSettingsCompat .DARK_STRATEGY_PREFER_WEB_THEME_OVER_USER_AGENT_DARKENING
474- )
475- }
481+ WebSettingsCompat .setForceDark(wv.settings, WebSettingsCompat .FORCE_DARK_OFF )
476482 }
477483 } catch (e: Throwable ) {
478484 FileLogger .w(TAG , " Failed to apply dark theme to WebSettings" , e)
479485 }
480486 }
481487
482- /* * 注入或移除夜间样式。带原生深色主题保护(对已支持深色的 GitHub 等网站避免反相破坏) 。 */
488+ /* * 注入或移除夜间压暗蒙版。对已支持原生深色的页面(背景为深色)不压暗 。 */
483489 private fun applyNightModeTo (wv : WebView ) {
484490 val js = if (nightMode) {
485491 """
0 commit comments