fix(ui): 初始背景跟随外观 + 修复跟随系统
- app.config 移除写死的浅色背景,交给 theme.json 按系统外观选择首帧底色 - 跟随系统模式增加 setInterval 轮询兜底,onThemeChange 不回调时也能跟上切换
This commit is contained in:
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
@@ -1 +1 @@
|
|||||||
{"darkmode":true,"themeLocation":"theme.json","pages":["pages/index/index","pages/shop/index","pages/shop/detail/index","pages/product/index","pages/diy/index","pages/diy/stickerEdit/index","pages/checkout/index","pages/designList/index","pages/orders/index","pages/profile/index","pages/service/index","pages/wordcloud/index","pages/orderDetail/index","pages/address/index","pages/settings/index","pages/agreement/index","pages/userDatabase/index"],"window":{"backgroundTextStyle":"dark","navigationStyle":"custom","navigationBarBackgroundColor":"#faf7f2","backgroundColor":"#faf7f2","backgroundColorTop":"#faf7f2","backgroundColorBottom":"#faf7f2","navigationBarTextStyle":"black"},"tabBar":{"custom":true,"list":[{"pagePath":"pages/index/index","text":"首页"},{"pagePath":"pages/shop/index","text":"商品"},{"pagePath":"pages/designList/index","text":"设计清单"},{"pagePath":"pages/orders/index","text":"订单"},{"pagePath":"pages/profile/index","text":"我的"}]}}
|
{"darkmode":true,"themeLocation":"theme.json","pages":["pages/index/index","pages/shop/index","pages/shop/detail/index","pages/product/index","pages/diy/index","pages/diy/stickerEdit/index","pages/checkout/index","pages/designList/index","pages/orders/index","pages/profile/index","pages/service/index","pages/wordcloud/index","pages/orderDetail/index","pages/address/index","pages/settings/index","pages/agreement/index","pages/userDatabase/index"],"window":{"navigationStyle":"custom"},"tabBar":{"custom":true,"list":[{"pagePath":"pages/index/index","text":"首页"},{"pagePath":"pages/shop/index","text":"商品"},{"pagePath":"pages/designList/index","text":"设计清单"},{"pagePath":"pages/orders/index","text":"订单"},{"pagePath":"pages/profile/index","text":"我的"}]}}
|
||||||
Vendored
+1
-1
File diff suppressed because one or more lines are too long
+2
-9
@@ -23,16 +23,9 @@ export default defineAppConfig({
|
|||||||
'pages/userDatabase/index'
|
'pages/userDatabase/index'
|
||||||
],
|
],
|
||||||
window: {
|
window: {
|
||||||
backgroundTextStyle: 'dark',
|
// 初始窗口/导航背景交给 theme.json 按系统外观自动选择,
|
||||||
|
// 避免首帧先固定成浅色再被 JS 切到深色而闪烁。
|
||||||
navigationStyle: 'custom',
|
navigationStyle: 'custom',
|
||||||
// 顶部/窗口颜色先显式固定为小程序浅色主题,避免 iOS 顶部区域跟随系统深色;
|
|
||||||
// 应用启动后页面 Hook 会按小程序内主题实时覆盖上面的值。
|
|
||||||
navigationBarBackgroundColor: '#faf7f2',
|
|
||||||
backgroundColor: '#faf7f2',
|
|
||||||
backgroundColorTop: '#faf7f2',
|
|
||||||
backgroundColorBottom: '#faf7f2',
|
|
||||||
// 状态栏文字默认黑字;各页面 useStatusBar 会按小程序主题覆盖它。
|
|
||||||
navigationBarTextStyle: 'black',
|
|
||||||
},
|
},
|
||||||
tabBar: {
|
tabBar: {
|
||||||
custom: true,
|
custom: true,
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { createContext, useContext, useState, useCallback, useEffect } from 'react'
|
import { createContext, useContext, useState, useCallback, useEffect, useRef } from 'react'
|
||||||
import Taro, { useDidShow } from '@tarojs/taro'
|
import Taro, { useDidShow } from '@tarojs/taro'
|
||||||
import { View } from '@tarojs/components'
|
import { View } from '@tarojs/components'
|
||||||
import { getTheme, setTheme as saveTheme, resolveTheme, setDetectedSystemTheme, type ThemeMode } from '../utils/store'
|
import { getTheme, setTheme as saveTheme, resolveTheme, setDetectedSystemTheme, type ThemeMode } from '../utils/store'
|
||||||
@@ -31,6 +31,7 @@ type ThemeChangeApi = {
|
|||||||
export function ThemeProvider({ children }: { children: React.ReactNode }) {
|
export function ThemeProvider({ children }: { children: React.ReactNode }) {
|
||||||
const [theme, set] = useState<ThemeMode>(getTheme())
|
const [theme, set] = useState<ThemeMode>(getTheme())
|
||||||
const [resolvedTheme, setResolved] = useState<'light' | 'dark'>(resolveTheme(getTheme()))
|
const [resolvedTheme, setResolved] = useState<'light' | 'dark'>(resolveTheme(getTheme()))
|
||||||
|
const systemThemeRef = useRef<'light' | 'dark' | null>(null)
|
||||||
|
|
||||||
const updateResolved = useCallback((mode: ThemeMode) => {
|
const updateResolved = useCallback((mode: ThemeMode) => {
|
||||||
setResolved(resolveTheme(mode))
|
setResolved(resolveTheme(mode))
|
||||||
@@ -42,6 +43,7 @@ export function ThemeProvider({ children }: { children: React.ReactNode }) {
|
|||||||
*/
|
*/
|
||||||
const updateFromSystem = useCallback((t: 'light' | 'dark') => {
|
const updateFromSystem = useCallback((t: 'light' | 'dark') => {
|
||||||
setDetectedSystemTheme(t)
|
setDetectedSystemTheme(t)
|
||||||
|
systemThemeRef.current = t
|
||||||
if (getTheme() === 'auto') {
|
if (getTheme() === 'auto') {
|
||||||
setResolved(t)
|
setResolved(t)
|
||||||
}
|
}
|
||||||
@@ -102,6 +104,23 @@ export function ThemeProvider({ children }: { children: React.ReactNode }) {
|
|||||||
}
|
}
|
||||||
}, [updateFromSystem])
|
}, [updateFromSystem])
|
||||||
|
|
||||||
|
// 部分机型/工具上 onThemeChange 不回调,自动模式再轮询兜底,保证系统切换能跟上
|
||||||
|
useEffect(() => {
|
||||||
|
if (theme !== 'auto') return
|
||||||
|
const timer = setInterval(() => {
|
||||||
|
try {
|
||||||
|
const info = Taro.getAppBaseInfo()
|
||||||
|
const next = info.theme === 'dark' ? 'dark' : 'light'
|
||||||
|
if (next !== systemThemeRef.current) {
|
||||||
|
updateFromSystem(next)
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
/* ignore */
|
||||||
|
}
|
||||||
|
}, 2000)
|
||||||
|
return () => clearInterval(timer)
|
||||||
|
}, [theme, updateFromSystem])
|
||||||
|
|
||||||
// 广播实际生效主题,供 custom-tab-bar 等独立组件订阅
|
// 广播实际生效主题,供 custom-tab-bar 等独立组件订阅
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
Taro.eventCenter.trigger(THEME_CHANGE_EVENT, resolvedTheme)
|
Taro.eventCenter.trigger(THEME_CHANGE_EVENT, resolvedTheme)
|
||||||
|
|||||||
@@ -42,3 +42,16 @@ test('app sets page background before first render without a blinking full fade'
|
|||||||
assert.match(appSource, /componentWillMount/)
|
assert.match(appSource, /componentWillMount/)
|
||||||
assert.doesNotMatch(appCss, /animation:\s*page-fade-in/)
|
assert.doesNotMatch(appCss, /animation:\s*page-fade-in/)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test('delegates initial background to themeLocation instead of hardcoding light', () => {
|
||||||
|
const config = read('src/app.config.ts')
|
||||||
|
assert.match(config, /themeLocation:\s*'theme\.json'/)
|
||||||
|
assert.doesNotMatch(config, /navigationBarBackgroundColor:\s*'#faf7f2'/)
|
||||||
|
assert.doesNotMatch(config, /backgroundColorTop:\s*'#faf7f2'/)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('polls the system theme while following the system', () => {
|
||||||
|
const ctx = read('src/context/ThemeContext.tsx')
|
||||||
|
assert.match(ctx, /setInterval/)
|
||||||
|
assert.match(ctx, /getAppBaseInfo\(\)/)
|
||||||
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user