瀏覽代碼

[REF-2588]Clear color mode local storage for dev mode (#3548)

* Clear color mode local storage

* use the last compiled time logic to determine when to clear local storage

* precommit fix

* app harness fix

* run prettier on reflex/.templates/web/utils/helpers/color_mode.js

* make sure last_compiled_time is updated for stateless apps as well.

* set the chkara-ui-color-mode cookie instead of clearing it, so it is integrated in the app's useEffect cycle

* fix CI

* fix import formatting

---------

Co-authored-by: Masen Furer <m_github@0x26.net>
Elijah Ahianyo 10 月之前
父節點
當前提交
8f2cbb5ea1

+ 2 - 0
integration/test_client_storage.py

@@ -311,6 +311,7 @@ async def test_client_side_state(
     assert not driver.get_cookies()
     local_storage_items = local_storage.items()
     local_storage_items.pop("chakra-ui-color-mode", None)
+    local_storage_items.pop("last_compiled_time", None)
     assert not local_storage_items
 
     # set some cookies and local storage values
@@ -426,6 +427,7 @@ async def test_client_side_state(
 
     local_storage_items = local_storage.items()
     local_storage_items.pop("chakra-ui-color-mode", None)
+    local_storage_items.pop("last_compiled_time", None)
     assert (
         local_storage_items.pop("state.client_side_state.client_side_sub_state.l1")
         == "l1 value"

+ 0 - 1
reflex/.templates/jinja/web/pages/_app.js.jinja2

@@ -8,7 +8,6 @@ import '/styles/styles.css'
 import { EventLoopProvider, StateProvider, defaultColorMode } from "/utils/context.js";
 import { ThemeProvider } from 'next-themes'
 
-
 {% for custom_code in custom_codes %}
 {{custom_code}}
 {% endfor %}

+ 2 - 0
reflex/.templates/jinja/web/utils/context.js.jinja2

@@ -64,6 +64,8 @@ export const initialEvents = () => []
 
 export const isDevMode = {{ is_dev_mode|json_dumps }}
 
+export const lastCompiledTimeStamp = {{ last_compiled_time|json_dumps }}
+
 export function UploadFilesProvider({ children }) {
   const [filesById, setFilesById] = useState({})
   refs["__clear_selected_files"] = (id) => setFilesById(filesById => {

+ 20 - 2
reflex/.templates/web/components/reflex/radix_themes_color_mode_provider.js

@@ -1,6 +1,11 @@
 import { useTheme } from "next-themes";
 import { useEffect, useState } from "react";
-import { ColorModeContext, defaultColorMode } from "/utils/context.js";
+import {
+  ColorModeContext,
+  defaultColorMode,
+  isDevMode,
+  lastCompiledTimeStamp
+} from "/utils/context.js";
 
 export default function RadixThemesColorModeProvider({ children }) {
   const { theme, resolvedTheme, setTheme } = useTheme();
@@ -8,6 +13,19 @@ export default function RadixThemesColorModeProvider({ children }) {
   const [resolvedColorMode, setResolvedColorMode] = useState("dark");
 
   useEffect(() => {
+    if (isDevMode) {
+      const lastCompiledTimeInLocalStorage =
+        localStorage.getItem("last_compiled_time");
+      if (
+        lastCompiledTimeInLocalStorage &&
+        lastCompiledTimeInLocalStorage !== lastCompiledTimeStamp
+      ) {
+        // on app startup, make sure the application color mode is persisted correctly.
+        setTheme(defaultColorMode);
+        localStorage.setItem("last_compiled_time", lastCompiledTimeStamp);
+        return;
+      }
+    }
     setRawColorMode(theme);
     setResolvedColorMode(resolvedTheme);
   }, [theme, resolvedTheme]);
@@ -19,7 +37,7 @@ export default function RadixThemesColorModeProvider({ children }) {
     const allowedModes = ["light", "dark", "system"];
     if (!allowedModes.includes(mode)) {
       console.error(
-        `Invalid color mode "${mode}". Defaulting to "${defaultColorMode}".`
+        `Invalid color mode "${mode}". Defaulting to "${defaultColorMode}".`,
       );
       mode = defaultColorMode;
     }

+ 6 - 1
reflex/compiler/compiler.py

@@ -3,6 +3,7 @@
 from __future__ import annotations
 
 import os
+from datetime import datetime
 from pathlib import Path
 from typing import Dict, Iterable, Optional, Type, Union
 
@@ -79,20 +80,24 @@ def _compile_contexts(state: Optional[Type[BaseState]], theme: Component | None)
         The compiled context file.
     """
     appearance = getattr(theme, "appearance", None)
-    if appearance is None:
+    if appearance is None or Var.create_safe(appearance)._var_name == "inherit":
         appearance = SYSTEM_COLOR_MODE
+
+    last_compiled_time = str(datetime.now())
     return (
         templates.CONTEXT.render(
             initial_state=utils.compile_state(state),
             state_name=state.get_name(),
             client_storage=utils.compile_client_storage(state),
             is_dev_mode=not is_prod_mode(),
+            last_compiled_time=last_compiled_time,
             default_color_mode=appearance,
         )
         if state
         else templates.CONTEXT.render(
             is_dev_mode=not is_prod_mode(),
             default_color_mode=appearance,
+            last_compiled_time=last_compiled_time,
         )
     )