Skip to content

fix(dashboard): scope console ANSI colors to dark mode only#8062

Open
piexian wants to merge 2 commits intoAstrBotDevs:masterfrom
piexian:fix/console-ansi-theme-aware
Open

fix(dashboard): scope console ANSI colors to dark mode only#8062
piexian wants to merge 2 commits intoAstrBotDevs:masterfrom
piexian:fix/console-ansi-theme-aware

Conversation

@piexian
Copy link
Copy Markdown
Contributor

@piexian piexian commented May 7, 2026

Summary / 概述

修复我在 #7173ConsoleDisplayer.vue 的 ANSI 终端颜色被全局应用的问题。#7173 将 ANSI 颜色从高饱和度改为低饱和度以适配深色模式,但这些颜色是硬编码的 inline style,在浅色模式下同样生效,导致浅色模式下终端文字对比度不足(尤其是默认文字从 #FFFFFF 变为 #c8c8c8)。

Modifications / 改动点

  • ConsoleDisplayer.vue:将 logColorAnsiMapdata() 中的静态对象重构为 computed 属性,根据 useCustomizerStore().uiTheme 动态切换浅色/深色调色板
  • 新增 logColorAnsiMap 的 watcher,主题切换时自动调用 refreshDisplay() 重绘已显示的日志行,确保无需刷新页面即可生效
  • This is NOT a breaking change. / 这不是一个破坏性变更。

Screenshots or Test Results / 运行截图或测试结果

Screenshot_2026-05-07-23-37-34-317_com microsoft emmx Screenshot_2026-05-07-23-37-00-803_com microsoft emmx

关联

Checklist / 检查清单

  • 😊 If there are new features added in the PR, I have discussed it with the authors through issues/emails, etc.
    / 如果 PR 中有新加入的功能,已经通过 Issue / 邮件等方式和作者讨论过。

  • 👀 My changes have been well-tested, and "Verification Steps" and "Screenshots" have been provided above.
    / 我的更改经过了良好的测试,并已在上方提供了“验证步骤”和“运行截图”

  • 🤓 I have ensured that no new dependencies are introduced, OR if new dependencies are introduced, they have been added to the appropriate locations in requirements.txt and pyproject.toml.
    / 我确保没有引入新依赖库,或者引入了新依赖库的同时将其添加到 requirements.txtpyproject.toml 文件相应位置。

  • 😮 My changes do not introduce malicious code.
    / 我的更改没有引入恶意代码。 code.

Summary by Sourcery

Scope console ANSI color styles to dark mode and make them update dynamically when the UI theme changes.

Bug Fixes:

  • Restrict console ANSI color styling to the dark theme to restore contrast in light mode.

Enhancements:

  • Make console ANSI color mappings reactive to theme changes and refresh displayed logs on theme switch.

Switch logColorAnsiMap from static data to a computed property that picks
light or dark palette based on uiTheme, and watch it to re-render
already-displayed logs on theme change.
Copilot AI review requested due to automatic review settings May 7, 2026 15:32
@auto-assign auto-assign Bot requested review from LIghtJUNction and Raven95676 May 7, 2026 15:32
@dosubot dosubot Bot added the size:M This PR changes 30-99 lines, ignoring generated files. label May 7, 2026
Copy link
Copy Markdown
Contributor

@sourcery-ai sourcery-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've found 1 issue, and left some high level feedback:

  • The logColorAnsiMap computed property hardcodes customizerStore.uiTheme === 'PurpleThemeDark' to detect dark mode; consider basing this on a more generic dark/light flag or a shared enum so additional dark themes automatically pick up the dark palette.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The `logColorAnsiMap` computed property hardcodes `customizerStore.uiTheme === 'PurpleThemeDark'` to detect dark mode; consider basing this on a more generic dark/light flag or a shared enum so additional dark themes automatically pick up the dark palette.

## Individual Comments

### Comment 1
<location path="dashboard/src/components/shared/ConsoleDisplayer.vue" line_range="84-85" />
<code_context>
     commonStore() {
       return useCommonStore();
     },
+    logColorAnsiMap() {
+      const customizerStore = useCustomizerStore();
+      return customizerStore.uiTheme === 'PurpleThemeDark' ? darkColorAnsiMap : lightColorAnsiMap;
+    },
</code_context>
<issue_to_address>
**suggestion:** Consider using a more generic theme signal than a hard-coded 'PurpleThemeDark' check.

Right now this mapping depends on `customizerStore.uiTheme === 'PurpleThemeDark'`, so any rename or addition of dark themes could make it wrong without failing loudly. If the store can expose a semantic flag (e.g. `isDarkTheme`) or theme type, prefer branching on that, or at least centralize this string comparison in the store rather than repeating it in components.

Suggested implementation:

```
    commonStore() {
      return useCommonStore();
    },
    logColorAnsiMap() {
      const customizerStore = useCustomizerStore();
      return customizerStore.isDarkTheme ? darkColorAnsiMap : lightColorAnsiMap;
    },

```

To fully implement this change you should:
1. Update `useCustomizerStore` (likely in `dashboard/src/stores/customizer.ts` or similar) to expose a semantic boolean like `isDarkTheme`, derived from `uiTheme` (e.g., `isDarkTheme = uiTheme.endsWith('Dark')` or a switch on known dark themes).
2. Ensure all components that need to distinguish dark/light themes rely on this semantic flag (`isDarkTheme`) instead of comparing `uiTheme` strings directly, to centralize theme-typing logic.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment on lines +84 to +85
logColorAnsiMap() {
const customizerStore = useCustomizerStore();
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion: Consider using a more generic theme signal than a hard-coded 'PurpleThemeDark' check.

Right now this mapping depends on customizerStore.uiTheme === 'PurpleThemeDark', so any rename or addition of dark themes could make it wrong without failing loudly. If the store can expose a semantic flag (e.g. isDarkTheme) or theme type, prefer branching on that, or at least centralize this string comparison in the store rather than repeating it in components.

Suggested implementation:

    commonStore() {
      return useCommonStore();
    },
    logColorAnsiMap() {
      const customizerStore = useCustomizerStore();
      return customizerStore.isDarkTheme ? darkColorAnsiMap : lightColorAnsiMap;
    },

To fully implement this change you should:

  1. Update useCustomizerStore (likely in dashboard/src/stores/customizer.ts or similar) to expose a semantic boolean like isDarkTheme, derived from uiTheme (e.g., isDarkTheme = uiTheme.endsWith('Dark') or a switch on known dark themes).
  2. Ensure all components that need to distinguish dark/light themes rely on this semantic flag (isDarkTheme) instead of comparing uiTheme strings directly, to centralize theme-typing logic.

@dosubot dosubot Bot added the area:webui The bug / feature is about webui(dashboard) of astrbot. label May 7, 2026
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adjusts the dashboard log console’s ANSI color styling so it adapts to the active UI theme, preventing dark-mode-optimized colors from reducing readability when the user is not in dark mode.

Changes:

  • Refactors logColorAnsiMap into a theme-dependent computed property that switches between light/dark palettes based on useCustomizerStore().uiTheme.
  • Adds a watcher to re-render existing log lines on theme changes via refreshDisplay().

Comment on lines +34 to +52
const lightColorAnsiMap = {
'': 'color: #39C5BB; font-weight: bold;',
'': 'color: #00FFFF; font-weight: bold;',
'': 'color: #FFFF00; font-weight: bold;',
'': 'color: #FF0000;',
'': 'color: #FF0000; font-weight: bold;',
'': 'color: inherit; font-weight: normal;',
'': 'color: #00FF00;',
'default': 'color: #FFFFFF;'
};

const darkColorAnsiMap = {
'': 'color: #6cb6d9; font-weight: bold;',
'': 'color: #72c4cc; font-weight: bold;',
'': 'color: #d4b95e; font-weight: bold;',
'': 'color: #d46a6a;',
'': 'color: #e06060; font-weight: bold;',
'': 'color: inherit; font-weight: normal;',
'': 'color: #6cc070;',
Comment on lines 340 to 346
let style = this.logColorAnsiMap['default']
for (let key in this.logColorAnsiMap) {
if (log.startsWith(key)) {
style = this.logColorAnsiMap[key]
log = log.replace(key, '').replace('\u001b[0m', '')
log = log.replace(key, '').replace('', '')
break
}
Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces theme-aware ANSI color mapping for the console displayer. It refactors the color maps into external constants and implements a computed property that selects the appropriate map based on the current UI theme from the customizer store. A watcher has also been added to refresh the display when the theme changes. The review feedback suggests reverting the use of literal ESC characters in the ANSI maps and replacement logic back to '\u001b' escape sequences to improve maintainability and prevent potential encoding issues.

Comment on lines +34 to +54
const lightColorAnsiMap = {
'': 'color: #39C5BB; font-weight: bold;',
'': 'color: #00FFFF; font-weight: bold;',
'': 'color: #FFFF00; font-weight: bold;',
'': 'color: #FF0000;',
'': 'color: #FF0000; font-weight: bold;',
'': 'color: inherit; font-weight: normal;',
'': 'color: #00FF00;',
'default': 'color: #FFFFFF;'
};

const darkColorAnsiMap = {
'': 'color: #6cb6d9; font-weight: bold;',
'': 'color: #72c4cc; font-weight: bold;',
'': 'color: #d4b95e; font-weight: bold;',
'': 'color: #d46a6a;',
'': 'color: #e06060; font-weight: bold;',
'': 'color: inherit; font-weight: normal;',
'': 'color: #6cc070;',
'default': 'color: #c8c8c8;'
};
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

建议使用 \u001b 转义序列代替字面量 ESC 字符。字面量不可见字符在编辑器中难以阅读,且在某些环境或 Git 操作中可能会被错误处理或损坏。原代码中使用了 \u001b,此处应保持一致以提高代码的可维护性。

const lightColorAnsiMap = {
  '\u001b[1;34m': 'color: #39C5BB; font-weight: bold;',
  '\u001b[1;36m': 'color: #00FFFF; font-weight: bold;',
  '\u001b[1;33m': 'color: #FFFF00; font-weight: bold;',
  '\u001b[31m': 'color: #FF0000;',
  '\u001b[1;31m': 'color: #FF0000; font-weight: bold;',
  '\u001b[0m': 'color: inherit; font-weight: normal;',
  '\u001b[32m': 'color: #00FF00;',
  'default': 'color: #FFFFFF;'
};

const darkColorAnsiMap = {
  '\u001b[1;34m': 'color: #6cb6d9; font-weight: bold;',
  '\u001b[1;36m': 'color: #72c4cc; font-weight: bold;',
  '\u001b[1;33m': 'color: #d4b95e; font-weight: bold;',
  '\u001b[31m': 'color: #d46a6a;',
  '\u001b[1;31m': 'color: #e06060; font-weight: bold;',
  '\u001b[0m': 'color: inherit; font-weight: normal;',
  '\u001b[32m': 'color: #6cc070;',
  'default': 'color: #c8c8c8;'
};

if (log.startsWith(key)) {
style = this.logColorAnsiMap[key]
log = log.replace(key, '').replace('\u001b[0m', '')
log = log.replace(key, '').replace('', '')
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

同样建议在这里使用 \u001b 转义序列代替字面量 ESC 字符,以保持代码风格的一致性并避免潜在的编码问题。

          log = log.replace(key, '').replace('\u001b[0m', '')

Replace literal ESC control characters with � Unicode escape
sequences for editor readability and tooling safety.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:webui The bug / feature is about webui(dashboard) of astrbot. size:M This PR changes 30-99 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants