22
33const CONFIG_URL = "config.json" ;
44const THEME_STORAGE_KEY = "xrobot_onboarding_theme" ;
5+ const DARK_MODE_MEDIA_QUERY = "(prefers-color-scheme: dark)" ;
56
67let treeConfig = null ;
78let state = null ;
9+ let themeMediaQuery = null ;
810
911const mdTextCache = { } ;
1012
@@ -16,7 +18,7 @@ function md(text) {
1618 return String ( text ) ;
1719}
1820
19- function getPreferredTheme ( ) {
21+ function getStoredThemePreference ( ) {
2022 try {
2123 const savedTheme = localStorage . getItem ( THEME_STORAGE_KEY ) ;
2224 if ( savedTheme === "light" || savedTheme === "dark" ) {
@@ -26,38 +28,81 @@ function getPreferredTheme() {
2628 console . warn ( "读取主题偏好失败" , e ) ;
2729 }
2830
29- if ( window . matchMedia && window . matchMedia ( "(prefers-color-scheme: dark)" ) . matches ) {
31+ return null ;
32+ }
33+
34+ function getSystemTheme ( ) {
35+ if ( window . matchMedia && window . matchMedia ( DARK_MODE_MEDIA_QUERY ) . matches ) {
3036 return "dark" ;
3137 }
3238
3339 return "light" ;
3440}
3541
36- function syncThemeToggleButtons ( theme ) {
37- document . querySelectorAll ( "[data-theme-option]" ) . forEach ( btn => {
38- btn . classList . toggle ( "active" , btn . dataset . themeOption === theme ) ;
39- } ) ;
42+ function getPreferredTheme ( ) {
43+ return getStoredThemePreference ( ) || getSystemTheme ( ) ;
4044}
4145
42- function applyTheme ( theme ) {
46+ function updateThemeToggleLabel ( theme ) {
47+ const nextTheme = theme === "dark" ? "light" : "dark" ;
48+ const nextLabel = nextTheme === "dark" ? "切换到深色模式" : "切换到浅色模式" ;
49+ const toggleButton = document . getElementById ( "theme-toggle-button" ) ;
50+ const toggleText = document . getElementById ( "theme-toggle-text" ) ;
51+
52+ if ( toggleButton ) {
53+ toggleButton . setAttribute ( "aria-label" , nextLabel ) ;
54+ toggleButton . setAttribute ( "title" , nextLabel ) ;
55+ }
56+
57+ if ( toggleText ) {
58+ toggleText . textContent = nextLabel ;
59+ }
60+ }
61+
62+ function applyTheme ( theme , options = { } ) {
4363 const nextTheme = theme === "dark" ? "dark" : "light" ;
64+ const { persist = true } = options ;
4465 document . documentElement . setAttribute ( "data-theme" , nextTheme ) ;
45- syncThemeToggleButtons ( nextTheme ) ;
66+ updateThemeToggleLabel ( nextTheme ) ;
4667
47- try {
48- localStorage . setItem ( THEME_STORAGE_KEY , nextTheme ) ;
49- } catch ( e ) {
50- console . warn ( "保存主题偏好失败" , e ) ;
68+ if ( persist ) {
69+ try {
70+ localStorage . setItem ( THEME_STORAGE_KEY , nextTheme ) ;
71+ } catch ( e ) {
72+ console . warn ( "保存主题偏好失败" , e ) ;
73+ }
74+ }
75+ }
76+
77+ function handleSystemThemeChange ( event ) {
78+ if ( getStoredThemePreference ( ) ) {
79+ return ;
5180 }
81+
82+ applyTheme ( event . matches ? "dark" : "light" , { persist : false } ) ;
5283}
5384
5485function initThemeToggle ( ) {
55- const theme = getPreferredTheme ( ) ;
56- syncThemeToggleButtons ( theme ) ;
57- document . querySelectorAll ( "[data-theme-option]" ) . forEach ( btn => {
58- btn . addEventListener ( "click" , ( ) => applyTheme ( btn . dataset . themeOption ) ) ;
59- } ) ;
60- applyTheme ( theme ) ;
86+ const toggleButton = document . getElementById ( "theme-toggle-button" ) ;
87+ const storedTheme = getStoredThemePreference ( ) ;
88+ applyTheme ( storedTheme || getSystemTheme ( ) , { persist : ! ! storedTheme } ) ;
89+
90+ if ( toggleButton ) {
91+ toggleButton . addEventListener ( "click" , ( ) => {
92+ const currentTheme = document . documentElement . getAttribute ( "data-theme" ) === "dark" ? "dark" : "light" ;
93+ const nextTheme = currentTheme === "dark" ? "light" : "dark" ;
94+ applyTheme ( nextTheme , { persist : true } ) ;
95+ } ) ;
96+ }
97+
98+ if ( window . matchMedia ) {
99+ themeMediaQuery = window . matchMedia ( DARK_MODE_MEDIA_QUERY ) ;
100+ if ( typeof themeMediaQuery . addEventListener === "function" ) {
101+ themeMediaQuery . addEventListener ( "change" , handleSystemThemeChange ) ;
102+ } else if ( typeof themeMediaQuery . addListener === "function" ) {
103+ themeMediaQuery . addListener ( handleSystemThemeChange ) ;
104+ }
105+ }
61106}
62107
63108function loadMdIntoElement ( path , el ) {
0 commit comments