diff --git a/src/textual/app.py b/src/textual/app.py index 5fb81038cc..d028d5f413 100644 --- a/src/textual/app.py +++ b/src/textual/app.py @@ -786,6 +786,9 @@ def __init__( self._hover_effects_timer: Timer | None = None + self._css_update_count: int = -1 + """Incremented when CSS is invalidated.""" + if self.ENABLE_COMMAND_PALETTE: for _key, binding in self._bindings: if binding.action in {"command_palette", "app.command_palette"}: @@ -1189,6 +1192,10 @@ def get_css_variables(self) -> dict[str, str]: variables = design.generate() return variables + def _invalidate_css(self) -> None: + """Invalidate CSS, so it will be refreshed.""" + self._css_update_count += 1 + def watch_dark(self, dark: bool) -> None: """Watches the dark bool. @@ -1198,16 +1205,19 @@ def watch_dark(self, dark: bool) -> None: self.set_class(dark, "-dark-mode", update=False) self.set_class(not dark, "-light-mode", update=False) self._refresh_truecolor_filter(self.ansi_theme) + self._invalidate_css() self.call_next(self.refresh_css) def watch_ansi_theme_dark(self, theme: TerminalTheme) -> None: if self.dark: self._refresh_truecolor_filter(theme) + self._invalidate_css() self.call_next(self.refresh_css) def watch_ansi_theme_light(self, theme: TerminalTheme) -> None: if not self.dark: self._refresh_truecolor_filter(theme) + self._invalidate_css() self.call_next(self.refresh_css) @property @@ -2203,7 +2213,7 @@ def _init_mode(self, mode: str) -> AwaitMount: screen, await_mount = self._get_screen(new_screen) stack.append(screen) self._load_screen_css(screen) - self.refresh_css() + screen.post_message(events.ScreenResume()) else: # Mode is not defined @@ -2213,6 +2223,8 @@ def _init_mode(self, mode: str) -> AwaitMount: screen.post_message(events.ScreenResume()) await_mount = AwaitMount(stack[0], []) + if screen._css_update_count != self._css_update_count: + self.refresh_css() screen._screen_resized(self.size) self._screen_stacks[mode] = stack @@ -2248,7 +2260,8 @@ def switch_mode(self, mode: str) -> AwaitMount: await_mount = AwaitMount(self.screen, []) self._current_mode = mode - self.refresh_css() + if self.screen._css_update_count != self._css_update_count: + self.refresh_css() self.screen._screen_resized(self.size) self.screen.post_message(events.ScreenResume()) @@ -3365,6 +3378,7 @@ def refresh_css(self, animate: bool = True) -> None: stylesheet.update(self.app, animate=animate) try: self.screen._refresh_layout(self.size) + self.screen._css_update_count = self._css_update_count except ScreenError: pass # The other screens in the stack will need to know about some style @@ -3373,6 +3387,7 @@ def refresh_css(self, animate: bool = True) -> None: for screen in self.screen_stack: if screen != self.screen: stylesheet.update(screen, animate=animate) + screen._css_update_count = self._css_update_count def _display(self, screen: Screen, renderable: RenderableType | None) -> None: """Display a renderable within a sync. diff --git a/src/textual/screen.py b/src/textual/screen.py index 3e7d21f1ce..026bebb434 100644 --- a/src/textual/screen.py +++ b/src/textual/screen.py @@ -267,6 +267,9 @@ def __init__( self.bindings_updated_signal: Signal[Screen] = Signal(self, "bindings_updated") """A signal published when the bindings have been updated""" + self._css_update_count = 0 + """Track updates to CSS.""" + @property def is_modal(self) -> bool: """Is the screen modal?"""