代码之家  ›  专栏  ›  技术社区  ›  LITzman

使用状态处理颜色主题更改

  •  0
  • LITzman  · 技术社区  · 1 年前

    我有一个使用Electron和React的桌面应用程序。

    我希望应用程序对Windows主题的更改做出响应(深色或浅色模式)。

    我在网上查看了其他实现,并提出了这个解决方案:

    主要反应部件:

    const App: React.FC = function () {
        const getTheme = (): Theme => (ipcRenderer.invoke('should-use-dark-colors') ? customDarkTheme : customLightTheme)
    
        const [theme, setTheme] = React.useState(getTheme)
    
        React.useEffect(function () {
            ipcRenderer.onNativeThemeChanged(() => {
                setTheme(getTheme())
            })
        })
    
        return (
            <FluentProvider theme={theme}>
                ...
            </FluentProvider>
        )
    }
    

    预加载.js

    const { contextBridge, ipcRenderer } = require('electron');
    
    window.ipcRenderer = require('electron').ipcRenderer
    
    contextBridge.exposeInMainWorld('ipcRenderer', {
        invoke: (channel) => ipcRenderer.invoke(channel),
        onNativeThemeChanged: (callback) => ipcRenderer.on("native-theme-changed", callback)
    });
    

    在Electron客户内部:

    ipcMain.handle('should-use-dark-colors', function (event, ...args) {
        tray.setImage(getIcon())
        return nativeTheme.shouldUseDarkColors
    })
    
    nativeTheme.addListener("updated", function () {
        mainWindow.webContents.send('native-theme-changed')
    }) 
    

    我已经调试了两个IPC例程,它们按预期工作。

    当我打开应用程序时,它最初使用正确的主题,但如果我在运行时更改系统主题,它不会相应地更改。

    我做错了什么?

    0 回复  |  直到 1 年前
        1
  •  0
  •   LITzman    1 年前

    终于想明白了。

    起初我试着 this 但无法使其发挥作用,所以我最终在 prefers-color-scheme 检测系统主题更改的CSS功能。

    结果如下:

    const useThemeChange = () => {
        const mediaQuery = () => window.matchMedia('(prefers-color-scheme: dark)')
    
        const [isDarkTheme, setDarkTheme] = useState(mediaQuery().matches)
    
        useEffect(() => {
            const mediaQueryResult = mediaQuery()
            mediaQueryResult.addEventListener("change", (event) => {
                setDarkTheme(event.matches)
            })
        }, [])
    
        return isDarkTheme
    }
    
    export const App: React.FC = () => {
    
       const isDarkTheme = useThemeChange()
        return (
            <FluentProvider theme={isDarkTheme ? customDarkTheme : customLightTheme}>
                ...
            </FluentProvider>
        )
    }