Skip to content

Conversation

@zerob13
Copy link
Collaborator

@zerob13 zerob13 commented Dec 8, 2025

finish #563

Summary by CodeRabbit

  • New Features

    • Customizable UI and code fonts in Display settings with live search, previews, reset and persistence; selections apply globally (UI, previews, code editor).
    • Browse and load system fonts with lazy loading and live updates.
  • Documentation

    • Added Hebrew (he / he-IL) translations for the new font UI and related strings.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 8, 2025

Walkthrough

Adds UI and store support for configurable UI and code fonts: system font discovery, persistence, IPC events, renderer CSS variables and Monaco integration, settings UI and i18n entries, plus small dependency updates and related tests.

Changes

Cohort / File(s) Summary
Build config
electron-builder-macx64.yml, electron-builder.yml
Added he-IL and he to electronLanguages.
Dependencies
package.json
Added font-list; bumped markstream-vue 0.0.2-beta.80.0.2; bumped stream-monaco ^0.0.7^0.0.8.
IPC / Events
src/main/events.ts, src/renderer/src/events.ts
Added FONT_FAMILY_CHANGED and CODE_FONT_FAMILY_CHANGED event constants.
Presenter & types
src/main/presenter/configPresenter/index.ts, src/shared/types/presenters/legacy.presenters.d.ts
Added font-related presenter API: get/set/reset fontFamily & codeFontFamily, getSystemFonts; added defaults to app settings.
System font helper
src/main/presenter/configPresenter/uiSettingsHelper.ts
Implemented system font discovery, normalization, caching, parsing, and error handling (uses font-list).
Renderer store
src/renderer/src/stores/uiSettingsStore.ts
Added state for fontFamily, codeFontFamily, systemFonts, isLoadingFonts; formatted font stacks, persistence, fetch/reset methods, IPC listeners.
Settings UI
src/renderer/settings/components/DisplaySettings.vue, src/renderer/settings/components/display/FontSettingsSection.vue
Injected new FontSettingsSection component; refactored language block; new font picker UI with search, preview, select, and reset.
App styles & root
src/renderer/src/App.vue, src/renderer/src/assets/style.css
Introduced CSS variables --dc-font-family, --dc-code-font-family; added watcher to apply variables at runtime.
Artifacts & renderers
src/renderer/src/components/artifacts/CodeArtifact.vue, .../HTMLArtifact.vue, .../MarkdownArtifact.vue, .../ReactTemplate.ts, .../McpJsonViewer.vue, .../MessageBlockToolCall.vue
Replaced hard-coded font stacks with CSS variables; wired renderer/iframe styles to use --dc-font-family / --dc-code-font-family.
Monaco/editor integration
src/renderer/src/components/trace/TraceDialog.vue, src/renderer/src/composables/useArtifactCodeEditor.ts, src/renderer/src/components/artifacts/CodeArtifact.vue, src/renderer/src/components/markdown/MarkdownRenderer.vue
Passed configured code font into Monaco options; added runtime update path (getEditorView) and watchers to reapply font changes.
Markdown plumbing
src/renderer/src/components/markdown/MarkdownRenderer.vue
Added computed codeBlockMonacoOption to forward code font to NodeRenderer/Monaco code blocks.
I18n
src/renderer/src/i18n/.../settings.json (many locales incl. en-US, he-IL, ja-JP, fr-FR, ko-KR, pt-BR, ru-RU, zh-*, fa-IR, da-DK)
Added font-related localization keys (fontTitle, fontFamily, fontFamilyDesc, codeFontFamily, codeFontFamilyDesc, fontDefaultLabel, fontSearchPlaceholder, fontSearchEmpty, fontReset, fontSystemLoading, fontUsageHint).
Tests
test/main/presenter/configPresenter/uiSettingsHelper.test.ts
Added unit tests for system font discovery/normalization and failure handling.

Sequence Diagram(s)

sequenceDiagram
    autonumber
    participant UI as Renderer (UI)
    participant Store as uiSettingsStore
    participant IPC as Electron IPC
    participant Main as Main (ConfigPresenter)
    participant Helper as UiSettingsHelper
    participant Editor as Monaco Editor

    UI->>Store: open font settings / request fonts
    Store->>IPC: fetchSystemFonts()
    IPC->>Main: invoke getSystemFonts()
    Main->>Helper: discover system fonts
    Helper-->>Main: return fonts (normalized)
    Main-->>IPC: reply with fonts
    IPC-->>Store: deliver system fonts
    Store-->>UI: update systemFonts, formatted font stacks
    UI->>UI: set CSS vars (--dc-font-family / --dc-code-font-family)
    UI->>Editor: on create or setting change -> updateOptions({ fontFamily })
    Editor-->>UI: render updated font
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Areas to focus:

  • System font discovery and parsing in uiSettingsHelper.ts (platform commands, normalization, error paths).
  • IPC/presenter persistence logic in configPresenter/index.ts and uiSettingsStore.ts.
  • Monaco runtime updates (getEditorView) and lifecycle across components (CodeArtifact.vue, TraceDialog.vue, composables).
  • New UI component FontSettingsSection.vue for performance/accessibility and preview rendering.
  • i18n JSON changes for correctness across locales.

Possibly related PRs

Suggested labels

codex

Poem

🐰 I hopped through fonts both big and small,

I fetched the system list and found them all.
Monaco whispers in a new typeface,
CSS vars set a gentler space.
A rabbit's tweak — the UI finds its grace.

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main feature being added: custom font settings. It is specific enough to convey the primary change without being overly verbose.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/add-font-settings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
package.json (1)

8-11: Update Node.js engine requirement to match coding guidelines.

The engines field specifies Node.js >=20.19.0, but the coding guidelines require Node.js >= 22. Update the constraint to align with the project requirements.

 "engines": {
-  "node": ">=20.19.0",
+  "node": ">=22.0.0",
   "pnpm": ">=10.11.0"
 },

As per coding guidelines, Node.js >= 22 is required.

src/renderer/src/i18n/he-IL/settings.json (1)

1-975: Add Hebrew locale to supportedLocales array for consistent context menu and error message translations.

The Hebrew locale (he-IL) is properly registered in the i18n configuration at src/renderer/src/i18n/index.ts and is accessible in the language selector UI. However, it should also be added to the supportedLocales array in src/shared/i18n.ts to ensure consistent context menu and error message translations. Currently, context menus and error messages will fall back to English for Hebrew users.

Add 'he-IL' to the supportedLocales array and provide corresponding entries in contextMenuTranslations and errorMessageTranslations objects in src/shared/i18n.ts.

🧹 Nitpick comments (6)
src/renderer/src/components/message/MessageBlockToolCall.vue (1)

268-271: Consider adding a fallback to the CSS variable.

The change to use var(--dc-code-font-family) aligns with the centralized font system. However, other components in this PR use fallback fonts (e.g., ReactTemplate.ts uses var(--dc-font-family, Arial, sans-serif)). Consider adding a fallback for consistency:

-  font-family: var(--dc-code-font-family);
+  font-family: var(--dc-code-font-family, 'Menlo', 'Monaco', 'Courier New', monospace);

This ensures graceful degradation if the CSS variable isn't set.

src/renderer/src/components/trace/TraceDialog.vue (1)

197-202: Consider extracting shared applyFontFamily helper.

This helper function is duplicated in useArtifactCodeEditor.ts with identical implementation. For maintainability, consider extracting it to a shared utility.

Example shared helper location:

// src/renderer/src/composables/useMonacoFontHelper.ts
export const applyFontFamily = (
  getEditorView: () => monaco.editor.IStandaloneCodeEditor | null,
  fontFamily: string
) => {
  const editor = getEditorView()
  if (editor) {
    editor.updateOptions({ fontFamily })
  }
}
src/renderer/src/components/artifacts/CodeArtifact.vue (1)

266-270: Potentially redundant font application on mount.

The font family is already passed to createEditor via the useMonaco options (line 71), so calling applyFontFamily immediately after createEditor on mount may be redundant. Consider whether this extra call is necessary.

If the initial fontFamily option in useMonaco is sufficient, you could simplify:

 onMounted(() => {
   if (!codeEditor.value) return
   createEditor(codeEditor.value, props.block.content, codeLanguage.value)
-  applyFontFamily(uiSettingsStore.formattedCodeFontFamily)
 })
src/renderer/settings/components/display/FontSettingsSection.vue (1)

285-306: Consider adding error handling to font selection.

The handleReset function has proper try/finally handling, but selectTextFont and selectCodeFont don't handle potential errors. If the store methods fail, users won't receive feedback.

 const selectTextFont = async (font: string) => {
+  try {
     await uiSettingsStore.setFontFamily(font)
     textPopoverOpen.value = false
+  } catch (error) {
+    console.error('Failed to set text font:', error)
+  }
 }
src/main/presenter/configPresenter/uiSettingsHelper.ts (1)

9-22: System font detection design is solid; consider central logging instead of console

The lazy getSystemFonts() + systemFontsCache flow, platform‑specific detection, and directory fallbacks are all reasonable and limited to one-time work on first use. Error handling via try/catch in loadSystemFonts(), readFontsFromDirectories(), and runCommand() also prevents crashes if OS tools or folders are missing.

To align with the repository’s logging guidelines, it would be better to route the new console.warn calls through the shared logging utility (e.g., logger.warn(...)) so font‑detection failures are structured and easier to filter in logs, instead of going directly to the console.

As per coding guidelines, new TypeScript code should use structured logger.* calls instead of raw console.*.

Also applies to: 43-44, 156-167, 256-275, 277-289

src/renderer/src/stores/uiSettingsStore.ts (1)

52-54: Font settings persistence and IPC sync are fine; consider slightly stronger error/log handling

The new actions and IPC listeners behave consistently with the rest of the store:

  • loadSettings() pulls initial font values from configPresenter.
  • setFontFamily / setCodeFontFamily trim input and persist through the presenter.
  • resetFontSettings() clears local state and delegates reset to the main process helper.
  • fetchSystemFonts() is idempotent per session and avoids concurrent loads.
  • FONT_FAMILY_CHANGED / CODE_FONT_FAMILY_CHANGED listeners keep the store in sync with main‑process events, and are cleaned up on unmount.

Two small improvement ideas (optional):

  • In fetchSystemFonts(), instead of only logging with console.warn, consider exposing an error flag or message in state so the FontSettings UI can show a user‑friendly failure indicator, and route the log through the shared logger instead of console.
  • For setFontFamily / setCodeFontFamily / resetFontSettings, you might eventually wrap the presenter calls in try/catch and revert local changes or surface an error toast on failure, to avoid the (rare) case where UI shows a new font while the underlying config write failed.

These are refinements and not blockers; the current behavior is consistent with existing setters in this store.

As per coding guidelines, new TypeScript code should favor structured logging and user‑visible error feedback where feasible.

Also applies to: 70-85, 86-97, 154-159, 175-176, 179-199

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (2)
test/main/presenter/configPresenter/uiSettingsHelper.test.ts (1)

1-30: LGTM! Well-structured tests for Linux font parsing.

The test cases comprehensively cover the key scenarios for parseLinuxFontFamilies: extracting family names from fc-list output, deduplication of comma-separated families, and handling invalid entries. The tests follow Vitest conventions as specified in the coding guidelines.

Consider adding tests for the other platform-specific parsing methods (getMacFonts, getWindowsFonts) and the main UiSettingsHelper methods (getFontFamily, setFontFamily, getSystemFonts) to improve overall coverage.

src/main/presenter/configPresenter/uiSettingsHelper.ts (1)

169-177: Consider cache invalidation for dynamic font updates.

The systemFontsCache is populated once and never invalidated. While this is acceptable for most scenarios, fonts installed or uninstalled during the app's lifetime won't be detected until restart.

If dynamic font updates are needed, consider adding a cache invalidation method:

clearSystemFontsCache(): void {
  this.systemFontsCache = null
}
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8bbfa47 and bf1efcf.

📒 Files selected for processing (2)
  • src/main/presenter/configPresenter/uiSettingsHelper.ts (3 hunks)
  • test/main/presenter/configPresenter/uiSettingsHelper.test.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (16)
**/*.{ts,tsx,js,jsx,vue}

📄 CodeRabbit inference engine (CLAUDE.md)

Use English for logs and comments (Chinese text exists in legacy code, but new code should use English)

Files:

  • test/main/presenter/configPresenter/uiSettingsHelper.test.ts
  • src/main/presenter/configPresenter/uiSettingsHelper.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Enable and maintain strict TypeScript type checking for all files

**/*.{ts,tsx}: Always use try-catch to handle possible errors in TypeScript code
Provide meaningful error messages when catching errors
Log detailed error logs including error details, context, and stack traces
Distinguish and handle different error types (UserError, NetworkError, SystemError, BusinessError) with appropriate handlers in TypeScript
Use structured logging with logger.error(), logger.warn(), logger.info(), logger.debug() methods from logging utilities
Do not suppress errors (avoid empty catch blocks or silently ignoring errors)
Provide user-friendly error messages for user-facing errors in TypeScript components
Implement error retry mechanisms for transient failures in TypeScript
Avoid logging sensitive information (passwords, tokens, PII) in logs

Files:

  • test/main/presenter/configPresenter/uiSettingsHelper.test.ts
  • src/main/presenter/configPresenter/uiSettingsHelper.ts
test/**/*.{test,spec}.{ts,tsx,js}

📄 CodeRabbit inference engine (CLAUDE.md)

Use Vitest framework for unit and integration tests

Files:

  • test/main/presenter/configPresenter/uiSettingsHelper.test.ts
**/*.ts

📄 CodeRabbit inference engine (CLAUDE.md)

Do not include AI co-authoring information (e.g., 'Co-Authored-By: Claude') in git commits

Files:

  • test/main/presenter/configPresenter/uiSettingsHelper.test.ts
  • src/main/presenter/configPresenter/uiSettingsHelper.ts
**/*.{js,ts,jsx,tsx,mjs,cjs}

📄 CodeRabbit inference engine (.cursor/rules/development-setup.mdc)

Write logs and comments in English

Files:

  • test/main/presenter/configPresenter/uiSettingsHelper.test.ts
  • src/main/presenter/configPresenter/uiSettingsHelper.ts
test/**/*.{test,spec}.ts

📄 CodeRabbit inference engine (AGENTS.md)

test/**/*.{test,spec}.ts: Test files should follow the same directory structure as source code under test/main and test/renderer directories
Use Vitest and Vue Test Utils for testing with jsdom configuration
Test files must be named with .test.ts or .spec.ts extension

Files:

  • test/main/presenter/configPresenter/uiSettingsHelper.test.ts
src/main/presenter/**/*.ts

📄 CodeRabbit inference engine (CLAUDE.md)

Organize core business logic into dedicated Presenter classes, with one presenter per functional domain

Files:

  • src/main/presenter/configPresenter/uiSettingsHelper.ts
src/main/**/*.ts

📄 CodeRabbit inference engine (CLAUDE.md)

Use EventBus from src/main/eventbus.ts for main-to-renderer communication, broadcasting events via mainWindow.webContents.send()

src/main/**/*.ts: Use EventBus pattern for inter-process communication within the main process to decouple modules
Use Electron's built-in APIs for file system and native dialogs instead of Node.js or custom implementations

src/main/**/*.ts: Electron main process code belongs in src/main/ with presenters in presenter/ (Window/Tab/Thread/Mcp/Config/LLMProvider) and eventbus.ts for app events
Use the Presenter pattern in the main process for UI coordination

Files:

  • src/main/presenter/configPresenter/uiSettingsHelper.ts
src/main/presenter/configPresenter/**/*.ts

📄 CodeRabbit inference engine (CLAUDE.md)

Store and retrieve custom prompts via configPresenter.getCustomPrompts() for config-based data source management

Files:

  • src/main/presenter/configPresenter/uiSettingsHelper.ts
{src/main/presenter/**/*.ts,src/renderer/**/*.ts}

📄 CodeRabbit inference engine (.cursor/rules/electron-best-practices.mdc)

Implement proper inter-process communication (IPC) patterns using Electron's ipcRenderer and ipcMain APIs

Files:

  • src/main/presenter/configPresenter/uiSettingsHelper.ts
src/**/*

📄 CodeRabbit inference engine (.cursor/rules/project-structure.mdc)

New features should be developed in the src directory

Files:

  • src/main/presenter/configPresenter/uiSettingsHelper.ts
src/main/**/*.{js,ts}

📄 CodeRabbit inference engine (.cursor/rules/project-structure.mdc)

Main process code for Electron should be placed in src/main

Files:

  • src/main/presenter/configPresenter/uiSettingsHelper.ts
src/**/*.{ts,tsx,vue,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use Prettier with single quotes, no semicolons, and 100 character width

Files:

  • src/main/presenter/configPresenter/uiSettingsHelper.ts
src/**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use OxLint for linting JavaScript and TypeScript files

Files:

  • src/main/presenter/configPresenter/uiSettingsHelper.ts
src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

src/**/*.{ts,tsx}: Use camelCase for variable and function names in TypeScript files
Use PascalCase for type and class names in TypeScript
Use SCREAMING_SNAKE_CASE for constant names

Files:

  • src/main/presenter/configPresenter/uiSettingsHelper.ts
src/**/*.ts

📄 CodeRabbit inference engine (AGENTS.md)

Use EventBus for inter-process communication events

Files:

  • src/main/presenter/configPresenter/uiSettingsHelper.ts
🧠 Learnings (6)
📚 Learning: 2025-11-25T05:28:20.513Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-25T05:28:20.513Z
Learning: Applies to test/**/*.{test,spec}.ts : Test files should follow the same directory structure as source code under `test/main` and `test/renderer` directories

Applied to files:

  • test/main/presenter/configPresenter/uiSettingsHelper.test.ts
📚 Learning: 2025-11-25T05:28:20.513Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-25T05:28:20.513Z
Learning: Applies to test/**/*.{test,spec}.ts : Test files must be named with `.test.ts` or `.spec.ts` extension

Applied to files:

  • test/main/presenter/configPresenter/uiSettingsHelper.test.ts
📚 Learning: 2025-11-25T05:28:20.513Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-25T05:28:20.513Z
Learning: Applies to test/**/*.{test,spec}.ts : Use Vitest and Vue Test Utils for testing with jsdom configuration

Applied to files:

  • test/main/presenter/configPresenter/uiSettingsHelper.test.ts
📚 Learning: 2025-11-25T05:26:11.312Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T05:26:11.312Z
Learning: Applies to test/**/*.{test,spec}.{ts,tsx,js} : Use Vitest framework for unit and integration tests

Applied to files:

  • test/main/presenter/configPresenter/uiSettingsHelper.test.ts
📚 Learning: 2025-11-25T05:28:20.513Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-25T05:28:20.513Z
Learning: Applies to src/**/*.ts : Use EventBus for inter-process communication events

Applied to files:

  • src/main/presenter/configPresenter/uiSettingsHelper.ts
📚 Learning: 2025-11-25T05:26:24.867Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/electron-best-practices.mdc:0-0
Timestamp: 2025-11-25T05:26:24.867Z
Learning: Applies to src/main/**/*.ts : Use EventBus pattern for inter-process communication within the main process to decouple modules

Applied to files:

  • src/main/presenter/configPresenter/uiSettingsHelper.ts
🧬 Code graph analysis (2)
test/main/presenter/configPresenter/uiSettingsHelper.test.ts (1)
src/main/presenter/configPresenter/uiSettingsHelper.ts (1)
  • parseLinuxFontFamilies (50-75)
src/main/presenter/configPresenter/uiSettingsHelper.ts (2)
src/main/eventbus.ts (1)
  • eventBus (151-151)
src/renderer/src/events.ts (1)
  • CONFIG_EVENTS (11-35)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build-check (x64)
🔇 Additional comments (6)
src/main/presenter/configPresenter/uiSettingsHelper.ts (6)

50-75: Excellent fix for Linux font parsing.

The dedicated parseLinuxFontFamilies function correctly addresses the past review concern by explicitly extracting the family name before the colon (line 57), rather than stripping it. This ensures Linux fc-list output like "DejaVu Sans:style=Book" is properly parsed. The deduplication logic (lines 67-70) and normalization (line 64) are also well-implemented.


179-199: Good security filtering for font values.

The normalizeStoredFont method appropriately sanitizes stored font values by stripping potentially dangerous characters (lines 182-185) and limiting length (line 188). The cache validation (lines 191-196) ensures legitimate font names are preserved when available.


308-320: Good security practices for shell command execution.

The runCommand method follows security best practices:

  • Uses hardcoded commands (no user input injection risk)
  • Sets windowsHide: true to prevent window flashing (line 312)
  • Limits output with maxBuffer (line 313)
  • Applies timeout to prevent hanging (line 311)

228-272: Platform-specific font discovery is well-implemented.

The platform-specific font discovery methods correctly handle each OS:

  • Linux: Uses fc-list : family with dedicated parsing (lines 239-242)
  • macOS: Uses system_profiler with filesystem fallback (lines 244-259)
  • Windows: Uses PowerShell registry query with filesystem fallback (lines 261-272)

The fallback to directory scanning ensures fonts are discovered even if system commands fail.


274-281: parseFontOutput correctly handles macOS and Windows formats.

This method is now appropriately scoped to macOS and Windows font output, where the regex pattern /^[^:]*:\s*/ correctly handles "Family: Name" format. Linux font parsing has been moved to the dedicated parseLinuxFontFamilies function, resolving the past review concern.


144-167: Clean API with proper EventBus integration.

The font family getters and setters are well-implemented:

  • Proper use of EventBus for IPC (as per coding guidelines)
  • Correct event names from CONFIG_EVENTS (lines 151, 161)
  • Security through normalizeStoredFont (lines 145, 149, 155, 159)
  • Consistent patterns across text and code fonts

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
package.json (1)

9-9: Update Node.js version requirement to >= 22.

The engines field specifies Node.js >= 20.19.0, but the coding guidelines require Node.js >= 22.

As per coding guidelines for package.json: Node.js >= 22 required.

Apply this diff:

-    "node": ">=20.19.0",
+    "node": ">=22.0.0",
♻️ Duplicate comments (1)
src/main/presenter/configPresenter/uiSettingsHelper.ts (1)

147-158: Use structured logging instead of console.warn.

The error handling doesn't follow the coding guidelines. Line 155 uses console.warn, but the guidelines require structured logging with detailed error context and stack traces.

As per coding guidelines:

  • "Use structured logging with logger.error(), logger.warn(), logger.info(), logger.debug() methods from logging utilities"
  • "Log detailed error logs including error details, context, and stack traces"

Apply this pattern (ensure logger is imported):

+import logger from '@/logger' // or wherever the logger utility is located
+
 // ... rest of file ...

   private async loadSystemFonts(): Promise<string[]> {
     try {
       const detected = await fontList.getFonts()
       const normalized = detected
         .map((font) => this.normalizeFontName(font))
         .filter((font): font is string => Boolean(font))
       return this.uniqueFonts(normalized)
     } catch (error) {
-      console.warn('Failed to detect system fonts with font-list:', error)
+      logger.warn('Failed to detect system fonts with font-list', {
+        error,
+        stack: error instanceof Error ? error.stack : undefined,
+        platform: process.platform
+      })
       return []
     }
   }
🧹 Nitpick comments (1)
src/main/presenter/configPresenter/uiSettingsHelper.ts (1)

5-21: Consider making normalizeFontNameValue a private class method.

The normalizeFontNameValue function is only used internally by UiSettingsHelper. Moving it into the class as a private method would improve encapsulation and make the module structure clearer.

-const normalizeFontNameValue = (name: string): string => {
-  const trimmed = name
-    .replace(/\(.*?\)/g, '')
-    .replace(/\s+/g, ' ')
-    .trim()
-  if (!trimmed) return ''
-
-  const stripped = trimmed
-    .replace(
-      /\b(Regular|Italic|Oblique|Bold|Light|Medium|Semi\s*Bold|Black|Narrow|Condensed|Extended|Book|Roman)\b/gi,
-      ''
-    )
-    .replace(/\s+/g, ' ')
-    .trim()
-
-  return stripped || trimmed
-}
-
 type SetSetting = <T>(key: string, value: T) => void
 type GetSetting = <T>(key: string) => T | undefined
 
 interface UiSettingsHelperOptions {
   getSetting: GetSetting
   setSetting: SetSetting
 }
 
 export class UiSettingsHelper {
   private readonly getSetting: GetSetting
   private readonly setSetting: SetSetting
   private systemFontsCache: string[] | null = null
 
   constructor(options: UiSettingsHelperOptions) {
     this.getSetting = options.getSetting
     this.setSetting = options.setSetting
   }
+
+  private normalizeFontNameValue(name: string): string {
+    const trimmed = name
+      .replace(/\(.*?\)/g, '')
+      .replace(/\s+/g, ' ')
+      .trim()
+    if (!trimmed) return ''
+
+    const stripped = trimmed
+      .replace(
+        /\b(Regular|Italic|Oblique|Bold|Light|Medium|Semi\s*Bold|Black|Narrow|Condensed|Extended|Book|Roman)\b/gi,
+        ''
+      )
+      .replace(/\s+/g, ' ')
+      .trim()
+
+    return stripped || trimmed
+  }

Then update line 175:

   private normalizeFontName(name: string): string {
-    return normalizeFontNameValue(name)
+    return this.normalizeFontNameValue(name)
   }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between bf1efcf and dbf8838.

📒 Files selected for processing (3)
  • package.json (3 hunks)
  • src/main/presenter/configPresenter/uiSettingsHelper.ts (3 hunks)
  • test/main/presenter/configPresenter/uiSettingsHelper.test.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • test/main/presenter/configPresenter/uiSettingsHelper.test.ts
🧰 Additional context used
📓 Path-based instructions (15)
package.json

📄 CodeRabbit inference engine (.cursor/rules/development-setup.mdc)

package.json: Node.js >= 22 required
pnpm >= 9 required

Files:

  • package.json
**/*.{ts,tsx,js,jsx,vue}

📄 CodeRabbit inference engine (CLAUDE.md)

Use English for logs and comments (Chinese text exists in legacy code, but new code should use English)

Files:

  • src/main/presenter/configPresenter/uiSettingsHelper.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Enable and maintain strict TypeScript type checking for all files

**/*.{ts,tsx}: Always use try-catch to handle possible errors in TypeScript code
Provide meaningful error messages when catching errors
Log detailed error logs including error details, context, and stack traces
Distinguish and handle different error types (UserError, NetworkError, SystemError, BusinessError) with appropriate handlers in TypeScript
Use structured logging with logger.error(), logger.warn(), logger.info(), logger.debug() methods from logging utilities
Do not suppress errors (avoid empty catch blocks or silently ignoring errors)
Provide user-friendly error messages for user-facing errors in TypeScript components
Implement error retry mechanisms for transient failures in TypeScript
Avoid logging sensitive information (passwords, tokens, PII) in logs

Files:

  • src/main/presenter/configPresenter/uiSettingsHelper.ts
src/main/presenter/**/*.ts

📄 CodeRabbit inference engine (CLAUDE.md)

Organize core business logic into dedicated Presenter classes, with one presenter per functional domain

Files:

  • src/main/presenter/configPresenter/uiSettingsHelper.ts
src/main/**/*.ts

📄 CodeRabbit inference engine (CLAUDE.md)

Use EventBus from src/main/eventbus.ts for main-to-renderer communication, broadcasting events via mainWindow.webContents.send()

src/main/**/*.ts: Use EventBus pattern for inter-process communication within the main process to decouple modules
Use Electron's built-in APIs for file system and native dialogs instead of Node.js or custom implementations

src/main/**/*.ts: Electron main process code belongs in src/main/ with presenters in presenter/ (Window/Tab/Thread/Mcp/Config/LLMProvider) and eventbus.ts for app events
Use the Presenter pattern in the main process for UI coordination

Files:

  • src/main/presenter/configPresenter/uiSettingsHelper.ts
src/main/presenter/configPresenter/**/*.ts

📄 CodeRabbit inference engine (CLAUDE.md)

Store and retrieve custom prompts via configPresenter.getCustomPrompts() for config-based data source management

Files:

  • src/main/presenter/configPresenter/uiSettingsHelper.ts
**/*.ts

📄 CodeRabbit inference engine (CLAUDE.md)

Do not include AI co-authoring information (e.g., 'Co-Authored-By: Claude') in git commits

Files:

  • src/main/presenter/configPresenter/uiSettingsHelper.ts
**/*.{js,ts,jsx,tsx,mjs,cjs}

📄 CodeRabbit inference engine (.cursor/rules/development-setup.mdc)

Write logs and comments in English

Files:

  • src/main/presenter/configPresenter/uiSettingsHelper.ts
{src/main/presenter/**/*.ts,src/renderer/**/*.ts}

📄 CodeRabbit inference engine (.cursor/rules/electron-best-practices.mdc)

Implement proper inter-process communication (IPC) patterns using Electron's ipcRenderer and ipcMain APIs

Files:

  • src/main/presenter/configPresenter/uiSettingsHelper.ts
src/**/*

📄 CodeRabbit inference engine (.cursor/rules/project-structure.mdc)

New features should be developed in the src directory

Files:

  • src/main/presenter/configPresenter/uiSettingsHelper.ts
src/main/**/*.{js,ts}

📄 CodeRabbit inference engine (.cursor/rules/project-structure.mdc)

Main process code for Electron should be placed in src/main

Files:

  • src/main/presenter/configPresenter/uiSettingsHelper.ts
src/**/*.{ts,tsx,vue,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use Prettier with single quotes, no semicolons, and 100 character width

Files:

  • src/main/presenter/configPresenter/uiSettingsHelper.ts
src/**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use OxLint for linting JavaScript and TypeScript files

Files:

  • src/main/presenter/configPresenter/uiSettingsHelper.ts
src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

src/**/*.{ts,tsx}: Use camelCase for variable and function names in TypeScript files
Use PascalCase for type and class names in TypeScript
Use SCREAMING_SNAKE_CASE for constant names

Files:

  • src/main/presenter/configPresenter/uiSettingsHelper.ts
src/**/*.ts

📄 CodeRabbit inference engine (AGENTS.md)

Use EventBus for inter-process communication events

Files:

  • src/main/presenter/configPresenter/uiSettingsHelper.ts
🧠 Learnings (13)
📚 Learning: 2025-11-25T05:26:15.929Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/development-setup.mdc:0-0
Timestamp: 2025-11-25T05:26:15.929Z
Learning: Applies to package.json : Node.js >= 22 required

Applied to files:

  • package.json
📚 Learning: 2025-11-25T05:26:15.929Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/development-setup.mdc:0-0
Timestamp: 2025-11-25T05:26:15.929Z
Learning: Applies to package.json : pnpm >= 9 required

Applied to files:

  • package.json
📚 Learning: 2025-11-25T05:26:35.317Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/error-logging.mdc:0-0
Timestamp: 2025-11-25T05:26:35.317Z
Learning: Applies to **/*.{ts,tsx} : Use structured logging with logger.error(), logger.warn(), logger.info(), logger.debug() methods from logging utilities

Applied to files:

  • src/main/presenter/configPresenter/uiSettingsHelper.ts
📚 Learning: 2025-11-25T05:26:35.317Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/error-logging.mdc:0-0
Timestamp: 2025-11-25T05:26:35.317Z
Learning: Applies to **/*.{ts,tsx} : Do not suppress errors (avoid empty catch blocks or silently ignoring errors)

Applied to files:

  • src/main/presenter/configPresenter/uiSettingsHelper.ts
📚 Learning: 2025-11-25T05:26:11.312Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T05:26:11.312Z
Learning: Applies to **/*.{ts,tsx,js,jsx,vue} : Use English for logs and comments (Chinese text exists in legacy code, but new code should use English)

Applied to files:

  • src/main/presenter/configPresenter/uiSettingsHelper.ts
📚 Learning: 2025-11-25T05:26:35.317Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/error-logging.mdc:0-0
Timestamp: 2025-11-25T05:26:35.317Z
Learning: Applies to **/*.{ts,tsx} : Avoid logging sensitive information (passwords, tokens, PII) in logs

Applied to files:

  • src/main/presenter/configPresenter/uiSettingsHelper.ts
📚 Learning: 2025-11-25T05:27:39.200Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/provider-guidelines.mdc:0-0
Timestamp: 2025-11-25T05:27:39.200Z
Learning: Applies to **/*Provider**/index.ts : Error handling: use `error` event uniformly to carry error messages, avoid mixing errors into other event fields

Applied to files:

  • src/main/presenter/configPresenter/uiSettingsHelper.ts
📚 Learning: 2025-11-25T05:26:35.317Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/error-logging.mdc:0-0
Timestamp: 2025-11-25T05:26:35.317Z
Learning: Applies to **/*.{ts,tsx} : Provide meaningful error messages when catching errors

Applied to files:

  • src/main/presenter/configPresenter/uiSettingsHelper.ts
📚 Learning: 2025-11-25T05:26:35.317Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/error-logging.mdc:0-0
Timestamp: 2025-11-25T05:26:35.317Z
Learning: Applies to **/*.{ts,tsx} : Provide user-friendly error messages for user-facing errors in TypeScript components

Applied to files:

  • src/main/presenter/configPresenter/uiSettingsHelper.ts
📚 Learning: 2025-11-25T05:26:35.317Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/error-logging.mdc:0-0
Timestamp: 2025-11-25T05:26:35.317Z
Learning: Applies to **/*.{ts,tsx} : Log detailed error logs including error details, context, and stack traces

Applied to files:

  • src/main/presenter/configPresenter/uiSettingsHelper.ts
📚 Learning: 2025-11-25T05:26:15.929Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/development-setup.mdc:0-0
Timestamp: 2025-11-25T05:26:15.929Z
Learning: Applies to **/*.{js,ts,jsx,tsx,mjs,cjs} : Write logs and comments in English

Applied to files:

  • src/main/presenter/configPresenter/uiSettingsHelper.ts
📚 Learning: 2025-11-25T05:26:35.317Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/error-logging.mdc:0-0
Timestamp: 2025-11-25T05:26:35.317Z
Learning: Applies to **/*.{ts,tsx} : Always use try-catch to handle possible errors in TypeScript code

Applied to files:

  • src/main/presenter/configPresenter/uiSettingsHelper.ts
📚 Learning: 2025-11-25T05:26:11.312Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T05:26:11.312Z
Learning: Applies to src/main/**/*.ts : Use EventBus from `src/main/eventbus.ts` for main-to-renderer communication, broadcasting events via `mainWindow.webContents.send()`

Applied to files:

  • src/main/presenter/configPresenter/uiSettingsHelper.ts
🧬 Code graph analysis (1)
src/main/presenter/configPresenter/uiSettingsHelper.ts (3)
src/main/eventbus.ts (1)
  • eventBus (151-151)
src/main/events.ts (1)
  • CONFIG_EVENTS (12-46)
src/renderer/src/events.ts (1)
  • CONFIG_EVENTS (11-35)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build-check (x64)
🔇 Additional comments (6)
src/main/presenter/configPresenter/uiSettingsHelper.ts (5)

90-108: LGTM: Font family management implementation is solid.

The font family getters and setters correctly:

  • Normalize font values to prevent injection or malformed data
  • Persist settings via the provided storage interface
  • Emit appropriate events via EventBus for UI synchronization
  • Follow the established patterns for config management

110-113: LGTM: Reset function properly reuses setters.

The resetFontSettings method correctly delegates to the individual setters, ensuring events are emitted and normalization occurs consistently.


115-123: LGTM: Good caching pattern for system fonts.

The caching strategy prevents repeated expensive system calls to enumerate fonts, improving performance when the settings UI is opened multiple times.


125-145: LGTM: Robust font name sanitization.

The normalizeStoredFont method properly:

  • Removes potentially dangerous characters (brackets, quotes, etc.)
  • Limits length to prevent excessive storage
  • Performs case-insensitive matching against detected system fonts
  • Falls back to the sanitized input if no exact match is found

This prevents CSS injection and ensures valid font-family values.


160-172: LGTM: Efficient font deduplication.

The uniqueFonts method correctly deduplicates fonts using case-insensitive comparison, preventing "Arial" and "arial" from appearing as separate entries in the UI font picker.

package.json (1)

84-84: Verify new and updated dependencies.

Three dependencies have been added or updated to support the custom font feature:

  • font-list@^2.0.1 (new) - for system font discovery - stable, v2.0.1
  • [email protected] (updated) - markdown streaming - pre-release version (0.0.2)
  • stream-monaco@^0.0.8 (updated) - Monaco editor streaming - pre-release version (0.0.8)

All three versions exist on npm with no known security vulnerabilities. However, note that markstream-vue and stream-monaco are pre-release versions (0.0.x), which indicate experimental status rather than stable releases. Only [email protected] represents a traditional stable release.

@zerob13 zerob13 merged commit a00109a into dev Dec 8, 2025
2 checks passed
zerob13 added a commit that referenced this pull request Dec 12, 2025
* fix: Multiple Issues Affecting Conversation Flow and Model Settings (#1166)

* fix: #1164 support maxtoken 2

* fix: mcp tool panel close btn #1163

* fix: #1162 file content in converation

* fix(search-assistant): exclude acp models

* fix: #1072 thinkcontent respects the global font size set

* feat: Hebrew (he-IL) Translation (#1157)

* feat: Hebrew (he-IL) Translation

* feat: add workspace view to acp agents (#1158)

* feat: add workspaceview for acp agent

* feat: support workspace dirs

* fix: workspace file refresh

* fix: tool call status

* fix: review refactor

* chore: update readme

* fix: add file context actions (#1160)

* fix: keep last file list

* feat(acp-workspace): add file context actions

* fix(acp-workspace): move path helpers to preload

* fix(preload): allow empty relative path

* fix(preload): escape quotes when formatting paths

* chore: update docs

* fix: Multiple Issues Affecting Conversation Flow and Model Settings (#1166)

* fix: #1164 support maxtoken 2

* fix: mcp tool panel close btn #1163

* fix: #1162 file content in converation

* fix(search-assistant): exclude acp models

* fix: #1072 thinkcontent respects the global font size set

* feat: add new i18n translation

* feat: add custom font setting (#1167)

* feat(settings): add font customization controls

* feat: change font with monaco

* chore: remove log and remove unuse key

* fix: linux font parse

* feat: use font-list to get font

* fix: font setting not work on settings page (#1169)

* style: unify scroll bar style (#1173)

* feat: acp init and process manage (#1171)

* feat: init acp process on select

* feat: warm up acp process on new thread

* fix: reuse warmup process

* fix: vue warning

* chore: add plan for acp debug panel

* feat: add debugview for acp

* feat: add i18n for debug

* fix: code review

* fix: ai review

* fix: Shutdown may skip releasing warmup‑only processes due to using warmupKey instead of agentId.

* chore: update markdown renderer

* chore: update mermaid node

* Merge commit from fork

* chore: update markstream-vue to version 0.0.3-beta.3
fix link renderer
feat html_inline render

* fix: increase button size for web content limit adjustment

* fix: close app kill all acp processes (#1175)

* fix: close app kill all acp processes

* fix: disable tool call merge

* fix: handle uncatch error

* fix: remove redundant type

* feat: add  shell to powerpack (#1178)

* chore(powerpack): randomize shell workdir

* feat: exclusive inmem server in terminal display

* fix: add sandbox in shell script

---------

Co-authored-by: xiaomo <[email protected]>
Co-authored-by: Simon He <[email protected]>
Co-authored-by: Simon He <[email protected]>
@zerob13 zerob13 deleted the feat/add-font-settings branch December 13, 2025 06:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants