feat: 深色模式基础设施 (system theme + 跟随系统)
This commit is contained in:
@@ -1,9 +1,20 @@
|
|||||||
const themeMod = require('./utils/theme')
|
const themeMod = require('./utils/theme')
|
||||||
const cloud = require('./utils/cloud')
|
const cloud = require('./utils/cloud')
|
||||||
const storage = require('./utils/storage')
|
const storage = require('./utils/storage')
|
||||||
|
const darkMod = require('./utils/darkMode')
|
||||||
|
|
||||||
App({
|
App({
|
||||||
async onLaunch() {
|
async onLaunch() {
|
||||||
|
// Init dark mode listener (refreshes all open pages when system theme changes)
|
||||||
|
darkMod.watchDarkMode((isDark) => {
|
||||||
|
const pages = getCurrentPages()
|
||||||
|
pages.forEach(p => {
|
||||||
|
if (p && typeof p.applyThemeToPage === 'function') {
|
||||||
|
p.applyThemeToPage()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
// Init cloud storage (no-op if not configured)
|
// Init cloud storage (no-op if not configured)
|
||||||
cloud.init()
|
cloud.init()
|
||||||
|
|
||||||
|
|||||||
@@ -25,5 +25,7 @@
|
|||||||
{ "pagePath": "pages/settings/settings", "text": "设置" }
|
{ "pagePath": "pages/settings/settings", "text": "设置" }
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"darkmode": true,
|
||||||
|
"themeLocation": "theme.json",
|
||||||
"sitemapLocation": "sitemap.json"
|
"sitemapLocation": "sitemap.json"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ page {
|
|||||||
font-size: 28rpx;
|
font-size: 28rpx;
|
||||||
color: var(--text);
|
color: var(--text);
|
||||||
background-color: var(--bg) !important;
|
background-color: var(--bg) !important;
|
||||||
|
transition: background-color 0.3s ease, color 0.3s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
.container {
|
.container {
|
||||||
|
|||||||
+16
@@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
"light": {
|
||||||
|
"navigationBarBackgroundColor": "#FF6B35",
|
||||||
|
"navigationBarTextStyle": "white",
|
||||||
|
"backgroundColor": "#F5F5F5",
|
||||||
|
"backgroundColorTop": "#F5F5F5",
|
||||||
|
"backgroundColorBottom": "#F5F5F5"
|
||||||
|
},
|
||||||
|
"dark": {
|
||||||
|
"navigationBarBackgroundColor": "#FF6B35",
|
||||||
|
"navigationBarTextStyle": "white",
|
||||||
|
"backgroundColor": "#0F0F12",
|
||||||
|
"backgroundColorTop": "#0F0F12",
|
||||||
|
"backgroundColorBottom": "#0F0F12"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
/**
|
||||||
|
* 系统深色模式监听 — 提供初始值与变更回调
|
||||||
|
* 旧设备 wx.onThemeChange 失败时退化为只读一次
|
||||||
|
*/
|
||||||
|
|
||||||
|
const STORAGE_KEY = 'dark_mode_pref'
|
||||||
|
|
||||||
|
function _readSystemTheme() {
|
||||||
|
try {
|
||||||
|
const info = wx.getSystemInfoSync()
|
||||||
|
return info.theme === 'dark' ? true : false
|
||||||
|
} catch (e) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getInitialDarkMode() {
|
||||||
|
const pref = wx.getStorageSync(STORAGE_KEY) || 'system'
|
||||||
|
if (pref === 'system') return _readSystemTheme()
|
||||||
|
return pref === 'dark'
|
||||||
|
}
|
||||||
|
|
||||||
|
function getPref() {
|
||||||
|
return wx.getStorageSync(STORAGE_KEY) || 'system'
|
||||||
|
}
|
||||||
|
|
||||||
|
function setPref(value) {
|
||||||
|
if (!['system', 'light', 'dark'].includes(value)) return
|
||||||
|
wx.setStorageSync(STORAGE_KEY, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
function watchDarkMode(onChange) {
|
||||||
|
if (typeof wx.onThemeChange !== 'function') return
|
||||||
|
try {
|
||||||
|
wx.onThemeChange(({ theme }) => {
|
||||||
|
const pref = getPref()
|
||||||
|
if (pref === 'system') onChange(theme === 'dark')
|
||||||
|
})
|
||||||
|
} catch (e) {
|
||||||
|
// 旧设备不支持,忽略
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
getInitialDarkMode,
|
||||||
|
getPref,
|
||||||
|
setPref,
|
||||||
|
watchDarkMode
|
||||||
|
}
|
||||||
+9
-4
@@ -94,19 +94,24 @@ const setTheme = (id) => {
|
|||||||
return theme
|
return theme
|
||||||
}
|
}
|
||||||
|
|
||||||
const getThemeStyle = (theme) => {
|
const getThemeStyle = (theme, isDark = false) => {
|
||||||
const t = theme || getCurrentTheme()
|
const t = theme || getCurrentTheme()
|
||||||
return `${BASE_VARS}--primary:${t.primary};--primary-light:${t.primaryLight};--primary-bg:${t.primaryBg};--primary-rgb:${t.primaryRgb};`
|
const baseVars = isDark
|
||||||
|
? '--text:#E5E5E7;--text-secondary:#98989F;--bg:#0F0F12;--card-bg:#1C1C1E;--border:#2C2C2E;--success:#30D158;'
|
||||||
|
: '--text:#333333;--text-secondary:#999999;--bg:#F5F5F5;--card-bg:#FFFFFF;--border:#EEEEEE;--success:#4CAF50;'
|
||||||
|
return `${baseVars}--primary:${t.primary};--primary-light:${t.primaryLight};--primary-bg:${t.primaryBg};--primary-rgb:${t.primaryRgb};`
|
||||||
}
|
}
|
||||||
|
|
||||||
const applyThemeToPage = (self) => {
|
const applyThemeToPage = (self) => {
|
||||||
|
const darkMod = require('./darkMode')
|
||||||
const theme = getCurrentTheme()
|
const theme = getCurrentTheme()
|
||||||
const nextStyle = getThemeStyle(theme)
|
const isDark = darkMod.getInitialDarkMode()
|
||||||
|
const nextStyle = getThemeStyle(theme, isDark)
|
||||||
// Skip setData if nothing changed — avoid unnecessary re-renders on every onShow
|
// Skip setData if nothing changed — avoid unnecessary re-renders on every onShow
|
||||||
if (self.data && self.data.themeStyle === nextStyle) {
|
if (self.data && self.data.themeStyle === nextStyle) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
self.setData({ theme, themeStyle: nextStyle })
|
self.setData({ theme, themeStyle: nextStyle, isDark })
|
||||||
_setNavBarColor(theme.primary)
|
_setNavBarColor(theme.primary)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user