Skip to content

fix(sonar): clear complexity findings and add locale screenshot drift checks#124

Merged
Mehdi-Bl merged 2 commits into
mainfrom
fix/sonar-complexity-locale-qa
Feb 14, 2026
Merged

fix(sonar): clear complexity findings and add locale screenshot drift checks#124
Mehdi-Bl merged 2 commits into
mainfrom
fix/sonar-complexity-locale-qa

Conversation

@Mehdi-Bl

@Mehdi-Bl Mehdi-Bl commented Feb 14, 2026

Copy link
Copy Markdown
Contributor

Summary

  • clear all open Sonar code-smell findings, including cognitive complexity in src/renderer/components/ConfigTab.tsx
  • add deterministic locale screenshot captures for en, es, fr, de in the QA screenshot flow
  • keep renderer/provider behavior intact while simplifying config loading and provider save path logic

Sonar

  • local scan (make sonar) completed successfully
  • project quality gate metric alert_status is OK
  • open issues: 0 (code smells 0, bugs 0, vulnerabilities 0)

Validation

  • npm run lint
  • npm test -- --runInBand
  • npm run qa:screenshot
  • npm run e2e:playwright
  • make sonar

Summary by Sourcery

Refactor config tab state handling and locale initialization for better robustness while extending QA UI screenshot coverage across locales.

Enhancements:

  • Simplify and centralize ConfigTab form state loading and saving, including provider configuration handling and YAML parsing.
  • Harden locale initialization and persistence logic by avoiding direct window access, improving compatibility with non-browser environments.
  • Tidy feature-flag dev-mode detection and i18n export to reduce cognitive complexity.

Tests:

  • Extend QA screenshot script to capture deterministic UI screenshots for en, es, fr, and de locales and document the new behavior in the test catalog.

Summary by CodeRabbit

  • Chores

    • Improved locale and environment detection for more reliable behavior.
    • Refactored configuration loading, validation, and save flow for greater reliability and clearer error feedback.
    • Enhanced UI screenshot tooling to capture app views across multiple locales (EN/ES/FR/DE) and reset state after capture.
  • Documentation

    • Updated test docs to note locale-specific screenshot capture and related signal details.

@sourcery-ai

sourcery-ai Bot commented Feb 14, 2026

Copy link
Copy Markdown

Reviewer's Guide

Refactors config tab state handling to reduce cognitive complexity, and extends the QA screenshot flow to deterministically capture locale-specific UI screenshots while keeping provider and locale behavior consistent and testable.

Sequence diagram for refactored config save flow in ConfigTab

sequenceDiagram
  actor User
  participant ConfigTab
  participant ConfigTabHelpers
  participant ProviderValidationHelpers
  participant onConfigChange

  User->>ConfigTab: trigger saveConfig(state)
  ConfigTab->>ConfigTabHelpers: parseConfigContent(configContent)
  ConfigTabHelpers-->>ConfigTab: ConfigObject config

  ConfigTab->>ConfigTabHelpers: applyBaseConfigState(config, state)
  ConfigTab->>ConfigTabHelpers: applyProviderConfigState(config, state, aiSurfacesEnabled, t)
  ConfigTabHelpers->>ProviderValidationHelpers: getProviderValidationErrors(providerFields, t)
  ProviderValidationHelpers-->>ConfigTabHelpers: validationErrors
  ConfigTabHelpers-->>ConfigTab: ProviderConfigSaveResult providerResult

  alt aiSurfacesEnabled and providerResult.hasValidationErrors
    ConfigTab->>ConfigTab: setProviderValidationErrors(validationErrors)
    ConfigTab->>ConfigTab: setProviderTestResult(failMessage)
    ConfigTab->>onConfigChange: onConfigChange(updatedConfig)
    ConfigTab->>ConfigTab: setIsSaved(false)
  else no provider validation errors
    ConfigTab->>ConfigTab: setProviderValidationErrors([])
    ConfigTab->>onConfigChange: onConfigChange(updatedConfig)
    ConfigTab->>ConfigTab: setIsSaved(true)
    ConfigTab->>ConfigTab: schedule reset of isSaved
  end
Loading

Sequence diagram for locale-specific QA screenshot capture flow

sequenceDiagram
  participant NodeScript as capture-ui-screenshot
  participant Browser as PlaywrightPage
  participant App as RendererApp
  participant LanguageSelector as languageSelector
  participant LocalStorage

  NodeScript->>Browser: setupMockElectronApi(page)
  Browser->>LocalStorage: setItem(app.locale, en)

  NodeScript->>Browser: captureAppStateScreenshots(page)
  Browser->>App: render app with initial locale en
  NodeScript->>Browser: capture configDefault screenshot

  NodeScript->>Browser: captureLocaleScreenshots(page)
  NodeScript->>Browser: waitForSelector(languageSelector)

  loop for each locale in SUPPORTED_LOCALES
    NodeScript->>Browser: setLocaleAndWait(page, locale)
    Browser->>LanguageSelector: selectOption(locale)
    Browser->>LocalStorage: setItem(app.locale, locale)
    Browser-->>NodeScript: locale selector and storage updated
    NodeScript->>Browser: page.screenshot(path for locale)
  end

  NodeScript->>Browser: setLocaleAndWait(page, DEFAULT_LOCALE)
  Browser->>LanguageSelector: selectOption(en)
  Browser->>LocalStorage: setItem(app.locale, en)

  NodeScript->>Browser: continue remaining screenshots
  NodeScript->>NodeScript: log deterministic screenshot paths
Loading

Class diagram for refactored ConfigTab helpers

classDiagram
  class ConfigFormState {
    string fileExtensions
    string excludePatterns
    boolean useCustomExcludes
    boolean useCustomIncludes
    boolean useGitignore
    boolean enableSecretScanning
    boolean excludeSuspiciousFiles
    boolean includeTreeView
    boolean showTokenCount
    string exportFormat
    string providerId
    string providerModel
    string providerApiKey
    string providerBaseUrl
  }

  class ConfigObject {
    boolean use_custom_excludes
    boolean use_custom_includes
    boolean use_gitignore
    boolean enable_secret_scanning
    boolean exclude_suspicious_files
    boolean include_tree_view
    boolean show_token_count
    string export_format
    string[] include_extensions
    string[] exclude_patterns
    ProviderConfig provider
  }

  class ProviderConfig {
    string id
    string model
    string api_key
    string base_url
  }

  class ConfigTabHelpers {
    +string toPlainTextList(value)
    +string[] toTrimmedLines(value)
    +ConfigFormState loadFormStateFromConfig(state, config, aiSurfacesEnabled)
    +ConfigObject parseConfigContent(configContent)
    +void applyBaseConfigState(config, state)
    +ProviderConfigSaveResult applyProviderConfigState(config, state, aiSurfacesEnabled, translate)
    +ProviderFormFields extractProviderFormFields(config, aiSurfacesEnabled)
  }

  class ProviderFormFields {
    string providerId
    string providerModel
    string providerApiKey
    string providerBaseUrl
  }

  class ProviderConfigSaveResult {
    boolean hasValidationErrors
    string[] validationErrors
  }

  class ProviderValidationHelpers {
    +string[] getProviderValidationErrors(providerFields, translate)
    +boolean hasProviderInput(providerFields)
    +string trimToUndefined(value)
  }

  ConfigTabHelpers --> ConfigFormState
  ConfigTabHelpers --> ConfigObject
  ConfigTabHelpers --> ProviderConfig
  ConfigTabHelpers --> ProviderFormFields
  ConfigTabHelpers --> ProviderConfigSaveResult
  ConfigTabHelpers ..> ProviderValidationHelpers
  ConfigObject o--> ProviderConfig
Loading

Class diagram for updated i18n and feature flag utilities

classDiagram
  class I18nSettings {
    +SupportedLocale getInitialLocale()
    +void persistLocale(locale)
    +boolean isSupportedLocale(value)
    +string normalizeLocale(value)
    +Window getBrowserWindow()
  }

  class FeatureFlags {
    +boolean isDevMode()
    +boolean isAiSurfacesEnabled()
  }

  class Window {
    LocalStorage localStorage
    Navigator navigator
    DevUtils devUtils
  }

  class LocalStorage {
    +void setItem(key, value)
    +string getItem(key)
  }

  class Navigator {
    string[] languages
    string language
  }

  class DevUtils {
    boolean isDev
  }

  I18nSettings ..> Window
  FeatureFlags ..> Window
  Window o--> LocalStorage
  Window o--> Navigator
  Window o--> DevUtils
Loading

File-Level Changes

Change Details Files
Refactor ConfigTab config-load and save logic into smaller helper functions to reduce cognitive complexity while preserving behavior.
  • Extract provider-related form field derivation into extractProviderFormFields and reuse via loadFormStateFromConfig in the reducer
  • Introduce loadFormStateFromConfig to handle LOAD_FROM_CONFIG, centralizing mapping from ConfigObject to ConfigFormState
  • Factor out YAML parsing into parseConfigContent with safe fallback on errors
  • Extract applyBaseConfigState to map base config form state into ConfigObject when saving
  • Extract applyProviderConfigState to encapsulate provider validation, config persistence/removal, and validation side-effects in saveConfig, simplifying the save flow
src/renderer/components/ConfigTab.tsx
Make locale handling more testable and robust and align feature-flag dev-mode detection with safer global access.
  • Introduce getBrowserWindow helper to safely access window in i18n settings and reuse in getInitialLocale/persistLocale
  • Update getInitialLocale and persistLocale to use getBrowserWindow, avoiding direct window access when unavailable
  • Change feature-flags isDevMode to use globalThis.window instead of typeof window checks, simplifying Sonar concerns
  • Export i18n instance via an intermediate constant to satisfy static analysis expectations
src/renderer/i18n/settings.ts
src/renderer/feature-flags.ts
src/renderer/i18n/index.ts
Extend QA screenshot capture script to produce deterministic locale-specific screenshots for supported languages and ensure stable locale state.
  • Define DEFAULT_LOCALE and SUPPORTED_LOCALES plus LOCALE_SCREENSHOT_KEYS for mapping locales to screenshot outputs
  • Add languageSelector selector and locale-specific screenshot paths to SCREENSHOTS and wire them into capture flow
  • Initialize app.locale in mocked Electron API setup to a known default
  • Implement setLocaleAndWait and captureLocaleScreenshots to switch locales via the UI, wait for persistence, and capture per-locale screenshots, resetting to default afterward
  • Restrict final logging to an explicit ordered list of screenshot paths for clarity and drift checks
scripts/capture-ui-screenshot.js
Document the extended QA screenshot coverage to include per-locale captures.
  • Update tests/catalog.md visual regression table entry for npm run qa:screenshot to mention EN/ES/FR/DE locale screenshot captures
tests/catalog.md

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@coderabbitai

coderabbitai Bot commented Feb 14, 2026

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

Adds locale-aware UI screenshot capture, refactors ConfigTab to modularize config parsing and provider validation, and replaces direct window usage with safer global/window access patterns in i18n and feature-flags modules.

Changes

Cohort / File(s) Summary
Locale-Aware Screenshot Capture
scripts/capture-ui-screenshot.js
Adds DEFAULT_LOCALE, SUPPORTED_LOCALES, LOCALE_SCREENSHOT_PATHS; adds UI_SELECTORS.languageSelector; implements setLocaleAndWait() and captureLocaleScreenshots(); integrates locale screenshots into capture flow and updates mock setup initial locale.
Config Handling Refactor
src/renderer/components/ConfigTab.tsx
Extracts helpers (parseConfigContent, applyBaseConfigState, applyProviderConfigState, etc.); centralizes config load/save and provider validation; replaces inline YAML manipulation with modular functions and returns structured provider validation results.
Safer Global Window Access
src/renderer/feature-flags.ts, src/renderer/i18n/settings.ts
Introduces getBrowserWindow()/getBrowserWindow usage and switches accesses from window to globalThis.window-backed getter; falls back to defaults when window is unavailable; updates localStorage and navigator access paths.
i18n Export Binding
src/renderer/i18n/index.ts
Exports new i18nInstance constant as the default export instead of exporting i18n directly (runtime value preserved).
Docs / Tests
tests/catalog.md
Updates Visual Regression Signal entry to note locale-specific screenshots (EN/ES/FR/DE) and minor formatting tweaks.

Sequence Diagram(s)

sequenceDiagram
participant Script as Capture Script
participant App as Renderer/UI
participant Storage as LocalStorage
participant FS as Screenshot FS

Script->>App: navigate to app, open language selector
Script->>App: run setLocaleAndWait(locale)
App->>Storage: write selected locale to localStorage
Storage-->>App: confirm persistence
App-->>Script: locale applied (UI updated)
Script->>App: take locale-specific screenshot
App->>FS: save screenshot to `LOCALE_SCREENSHOT_PATHS[locale]`
FS-->>Script: write complete
Script->>App: repeat for next locale, then reset to DEFAULT_LOCALE
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Poem

🐰 I hopped through locales, one by one,

en, es, fr, de — what fun!
I nudged the selector, stored the choice,
Saved each view with a jubilant voice,
Thump—config neat, screenshots done! 🥕📸

🚥 Pre-merge checks | ✅ 3 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ 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 specifically summarizes the main changes: fixing Sonar complexity findings and adding locale screenshot drift checks, which aligns with the PR's primary objectives of resolving code-smell findings and adding deterministic locale-specific QA captures.
Merge Conflict Detection ✅ Passed ✅ No merge conflicts detected when merging into main

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ 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 fix/sonar-complexity-locale-qa

No actionable comments were generated in the recent review. 🎉

🧹 Recent nitpick comments
scripts/capture-ui-screenshot.js (2)

14-15: Locale constants are duplicated from src/renderer/i18n/settings.ts.

These values mirror DEFAULT_LOCALE and SUPPORTED_LOCALES in src/renderer/i18n/settings.ts. If locales are added or removed in the source of truth, this file must be updated manually. Consider adding a comment referencing the canonical source, or generating/reading these values from a shared JSON file that both the TS module and this script can consume.


756-767: Consider verifying screenshot files exist before logging success.

The forEach loop logs each path but doesn't confirm the files were actually written. A quick fs.existsSync check would catch silent write failures (e.g., permission issues, disk full) and provide a clearer error signal during QA runs.

🛡️ Optional: add existence check
     screenshotPaths.forEach((screenshotPath) => {
+      if (!fs.existsSync(screenshotPath)) {
+        throw new Error(`Expected screenshot not found: ${screenshotPath}`);
+      }
       console.log(`UI screenshot captured: ${screenshotPath}`);
     });

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 OpenGrep (1.16.0)
scripts/capture-ui-screenshot.js

┌──────────────┐
│ Opengrep CLI │
└──────────────┘

�[32m✔�[39m �[1mOpengrep OSS�[0m
�[32m✔�[39m Basic security coverage for first-party code vulnerabilities.

�[1m Loading rules from local config...�[0m

src/renderer/feature-flags.ts

┌──────────────┐
│ Opengrep CLI │
└──────────────┘

�[32m✔�[39m �[1mOpengrep OSS�[0m
�[32m✔�[39m Basic security coverage for first-party code vulnerabilities.

�[1m Loading rules from local config...�[0m


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.

@qodo-free-for-open-source-projects

Copy link
Copy Markdown

Review Summary by Qodo

Reduce complexity and add locale screenshot QA validation

🐞 Bug fix ✨ Enhancement 🧪 Tests

Grey Divider

Walkthroughs

Description
• Refactor ConfigTab reducer to reduce cognitive complexity
  - Extract provider config logic into separate functions
  - Extract form state loading into dedicated helper
  - Simplify config parsing and application logic
• Replace typeof checks with globalThis for better SSR compatibility
  - Update feature-flags and i18n settings modules
  - Add getBrowserWindow helper for consistent window access
• Add deterministic locale screenshot captures for QA
  - Capture UI screenshots for en, es, fr, de locales
  - Add language selector automation and locale persistence
  - Update screenshot validation to include all locale variants
Diagram
flowchart LR
  A["ConfigTab Reducer<br/>High Complexity"] -->|Extract Functions| B["Helper Functions<br/>Reduced Complexity"]
  C["typeof window<br/>Checks"] -->|Replace| D["globalThis.window<br/>SSR Safe"]
  E["QA Screenshot<br/>Config Only"] -->|Extend| F["QA Screenshot<br/>+ 4 Locales"]
  B --> G["Sonar Quality Gate<br/>PASS"]
  D --> G
  F --> G
Loading

Grey Divider

File Changes

1. src/renderer/feature-flags.ts ✨ Enhancement +2/-2

Replace typeof checks with globalThis

• Replace typeof window === 'undefined' with globalThis.window === undefined
• Update window access to use globalThis.window for better SSR compatibility

src/renderer/feature-flags.ts


2. src/renderer/i18n/index.ts ✨ Enhancement +3/-1

Simplify i18n instance export

• Assign i18n instance to intermediate variable before export
• Improves code clarity and reduces Sonar complexity findings

src/renderer/i18n/index.ts


3. src/renderer/i18n/settings.ts ✨ Enhancement +16/-6

Add getBrowserWindow helper for SSR safety

• Add getBrowserWindow() helper function for consistent window access
• Replace all typeof window === 'undefined' checks with helper function
• Update localStorage and navigator access to use helper

src/renderer/i18n/settings.ts


View more (3)
4. scripts/capture-ui-screenshot.js 🧪 Tests +69/-1

Add deterministic locale screenshot captures

• Add locale constants and screenshot paths for en, es, fr, de
• Add language selector UI selector for locale switching
• Implement setLocaleAndWait() function to switch locales deterministically
• Implement captureLocaleScreenshots() to capture UI in all supported locales
• Integrate locale screenshot capture into main screenshot flow
• Update screenshot validation to include all locale variants

scripts/capture-ui-screenshot.js


5. src/renderer/components/ConfigTab.tsx 🐞 Bug fix +150/-111

Extract helpers to reduce ConfigTab complexity

• Extract toPlainTextList() and toTrimmedLines() helper functions
• Extract extractProviderFormFields() to isolate provider config logic
• Extract loadFormStateFromConfig() to simplify reducer complexity
• Extract parseConfigContent() for config parsing logic
• Extract applyBaseConfigState() for base config application
• Extract applyProviderConfigState() for provider config application with validation
• Refactor saveConfig() callback to use extracted helpers
• Reduce cognitive complexity from deeply nested conditionals

src/renderer/components/ConfigTab.tsx


6. tests/catalog.md 📝 Documentation +4/-4

Document locale screenshot QA validation

• Update npm run qa:screenshot description to include locale screenshot captures
• Document EN/ES/FR/DE locale screenshot validation as key use case

tests/catalog.md


Grey Divider

Qodo Logo

@gemini-code-assist

Copy link
Copy Markdown

Summary of Changes

Hello @Mehdi-Bl, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request focuses on improving code quality and enhancing the UI testing infrastructure. It resolves existing code-smell issues by refactoring complex configuration handling logic into more manageable functions. Additionally, it significantly upgrades the QA process by introducing automated, locale-specific UI screenshot captures, ensuring consistent user experience across multiple languages. These changes collectively contribute to a more maintainable codebase and a more reliable testing suite.

Highlights

  • Sonar Code-Smell Resolution: Addressed and cleared all open Sonar code-smell findings, specifically targeting cognitive complexity within the ConfigTab.tsx component by refactoring its logic.
  • Locale Screenshot Drift Checks: Implemented deterministic screenshot captures for English, Spanish, French, and German locales within the QA screenshot flow to prevent UI drift across different languages.
  • Config Logic Simplification: Simplified the configuration loading and provider save path logic in ConfigTab.tsx while maintaining existing renderer/provider behavior.
  • Global Window Access Refinement: Updated references to the global window object to use globalThis.window for improved compatibility and robustness across various JavaScript environments.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Changelog
  • scripts/capture-ui-screenshot.js
    • Introduced constants for default and supported locales (en, es, fr, de).
    • Defined new screenshot paths for each supported locale.
    • Added a UI selector for the language dropdown.
    • Implemented setLocaleAndWait and captureLocaleScreenshots functions to programmatically switch locales and capture screenshots.
    • Integrated the locale screenshot capture process into the main captureAppStateScreenshots flow.
    • Updated the console output to list all captured screenshot paths, including the new locale-specific ones.
  • src/renderer/components/ConfigTab.tsx
    • Refactored the configFormReducer to use a new loadFormStateFromConfig helper function for clearer config loading logic.
    • Extracted toPlainTextList, toTrimmedLines, extractProviderFormFields, parseConfigContent, applyBaseConfigState, and applyProviderConfigState into separate, modular utility functions.
    • Simplified the saveConfig callback by leveraging the newly extracted functions for parsing, applying base configuration, and handling provider-specific settings and validations.
    • Improved the handling and display of provider validation errors during configuration saving.
  • src/renderer/feature-flags.ts
    • Updated checks for the global window object to use globalThis.window for enhanced environment compatibility.
  • src/renderer/i18n/index.ts
    • Changed the default export of the i18n instance to a named constant i18nInstance.
  • src/renderer/i18n/settings.ts
    • Introduced a getBrowserWindow helper function to safely access the global window object.
    • Replaced direct window references with calls to getBrowserWindow() or globalThis.window for consistency and robustness.
  • tests/catalog.md
    • Updated the qa:screenshot command description to reflect the new functionality of capturing locale-specific screenshots.
Activity
  • No human activity (comments, reviews) was detected on this pull request yet.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

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 locale screenshot handling duplicates the supported locale list across SUPPORTED_LOCALES and LOCALE_SCREENSHOT_KEYS; consider deriving the screenshot key names from SUPPORTED_LOCALES to avoid drift when adding or removing locales.
  • Now that getBrowserWindow centralizes the window access pattern in i18n/settings.ts, it may be worth reusing a similar helper (or this one if feasible) in other modules like feature-flags.ts to keep environment checks consistent and reduce repetition.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The locale screenshot handling duplicates the supported locale list across `SUPPORTED_LOCALES` and `LOCALE_SCREENSHOT_KEYS`; consider deriving the screenshot key names from `SUPPORTED_LOCALES` to avoid drift when adding or removing locales.
- Now that `getBrowserWindow` centralizes the `window` access pattern in `i18n/settings.ts`, it may be worth reusing a similar helper (or this one if feasible) in other modules like `feature-flags.ts` to keep environment checks consistent and reduce repetition.

## Individual Comments

### Comment 1
<location> `scripts/capture-ui-screenshot.js:15-18` </location>
<code_context>
 const PORT = Number(process.env.UI_SCREENSHOT_PORT || 4173);
 const DEFAULT_SCREENSHOT_NAME = `ui-${process.platform}-${process.arch}.png`;
+const DEFAULT_LOCALE = 'en';
+const SUPPORTED_LOCALES = ['en', 'es', 'fr', 'de'];
 const FIXED_MTIME = 1700000000000;

</code_context>

<issue_to_address>
**issue (bug_risk):** Avoid duplicating the set of supported locales to keep screenshots in sync with locales

This introduces a second source of truth for locales (`SUPPORTED_LOCALES` vs `LOCALE_SCREENSHOT_KEYS`). If a locale is added to `SUPPORTED_LOCALES` without updating `LOCALE_SCREENSHOT_KEYS`, `captureLocaleScreenshots` will throw when `SCREENSHOTS[screenshotKey]` is undefined. Consider deriving `LOCALE_SCREENSHOT_KEYS` from `SUPPORTED_LOCALES` or adding a validation step to ensure every locale has a corresponding screenshot key.
</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 thread scripts/capture-ui-screenshot.js
@github-actions

github-actions Bot commented Feb 14, 2026

Copy link
Copy Markdown

Dependency Review

✅ No vulnerabilities or license issues found.

Scanned Files

None

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Caution

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

⚠️ Outside diff range comments (1)
src/renderer/components/ConfigTab.tsx (1)

330-371: ⚠️ Potential issue | 🟡 Minor

Save flow: config is persisted even when provider validation fails.

When providerResult.hasValidationErrors is true, onConfigChange(updatedConfig) still fires (line 354) — saving the base config with the provider section deleted — before the early return on line 358. This is likely intentional (base config changes shouldn't be lost due to provider errors), but it may confuse users who see the "fix before saving" message while their non-provider changes were actually saved. Consider whether the save feedback should differentiate between "provider not saved" and "base config saved."

🧹 Nitpick comments (5)
scripts/capture-ui-screenshot.js (2)

14-15: Locale constants are duplicated from src/renderer/i18n/settings.ts.

DEFAULT_LOCALE and SUPPORTED_LOCALES are defined here and in src/renderer/i18n/settings.ts. Since this is a CommonJS Node script that can't import the TS source directly, the duplication is understandable. Consider adding a comment referencing the canonical source so future changes stay in sync.

📝 Suggested comment
-const DEFAULT_LOCALE = 'en';
-const SUPPORTED_LOCALES = ['en', 'es', 'fr', 'de'];
+// Keep in sync with src/renderer/i18n/settings.ts
+const DEFAULT_LOCALE = 'en';
+const SUPPORTED_LOCALES = ['en', 'es', 'fr', 'de'];

762-776: Explicit screenshot path list is an improvement over dynamic iteration.

Using a hardcoded ordered list ensures deterministic log output and makes the expected set of screenshots visible at a glance. However, if new entries are added to the SCREENSHOTS object in the future, this list must be updated separately.

Consider deriving this list from SCREENSHOTS to keep them in sync automatically:

📝 Alternative approach
-    const screenshotPaths = [
-      SCREENSHOTS.configDefault,
-      SCREENSHOTS.localeEn,
-      SCREENSHOTS.localeEs,
-      SCREENSHOTS.localeFr,
-      SCREENSHOTS.localeDe,
-      SCREENSHOTS.sourceTab,
-      SCREENSHOTS.sourceSelected,
-      SCREENSHOTS.sourceSelectedResized,
-      SCREENSHOTS.processedTab,
-    ];
+    const screenshotPaths = Object.values(SCREENSHOTS);
src/renderer/components/ConfigTab.tsx (2)

317-325: Inconsistent YAML parsing: useEffect bypasses the new parseConfigContent helper.

The useEffect on mount/config-change uses yaml.parse(configContent) directly with its own try/catch, while saveConfig (line 332) uses the newly extracted parseConfigContent. Consider using parseConfigContent here as well for consistency and to centralize error handling.

♻️ Proposed fix
   useEffect(() => {
-    try {
-      const config = (yaml.parse(configContent) || {}) as ConfigObject;
-      dispatch({ type: 'LOAD_FROM_CONFIG', config, aiSurfacesEnabled });
-      setProviderValidationErrors([]);
-      setProviderTestResult(null);
-    } catch (error) {
-      console.error('Error parsing config:', error);
-    }
+    const config = parseConfigContent(configContent);
+    dispatch({ type: 'LOAD_FROM_CONFIG', config, aiSurfacesEnabled });
+    setProviderValidationErrors([]);
+    setProviderTestResult(null);
   }, [aiSurfacesEnabled, configContent]);

240-251: applyBaseConfigState mutates config in place — consider documenting intent.

The void return type hints at mutation, but in a React codebase where immutability is the norm, a brief JSDoc comment (e.g., /** Mutates config in place */) or renaming to applyBaseConfigStateTo(config, ...) would make the side-effect explicit to future readers.

src/renderer/i18n/index.ts (1)

33-35: Remove unnecessary alias for simpler code.

The pattern const i18nInstance = i18n followed by export default i18nInstance is functionally identical to export default i18n and serves no purpose. No ESLint rule in the project configuration (import plugin, sonarjs, or any other active plugin) requires this indirect export pattern. Simplify by directly exporting the imported binding.

@qodo-free-for-open-source-projects

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (2) 📘 Rule violations (1) 📎 Requirement gaps (0)

Grey Divider


Remediation recommended

1. parseConfigContent logs raw error 📘 Rule violation ⛨ Security
Description
parseConfigContent logs the full caught error object while parsing configContent, which may
include sensitive configuration details (e.g., provider API keys) in logs. This risks leaking
secrets or sensitive data through unredacted log output.
Code

src/renderer/components/ConfigTab.tsx[R234-236]

+  } catch (error) {
+    console.error('Error parsing config content, using empty config:', error);
+    return {};
Evidence
The checklist prohibits sensitive data in logs; the new code logs the entire parsing error object
when parsing configuration content, which can contain or reveal parts of the config and related
details.

Rule 5: Generic: Secure Logging Practices
src/renderer/components/ConfigTab.tsx[227-237]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`parseConfigContent` logs the full caught `error` object while parsing `configContent`. Since `configContent` may contain sensitive fields (e.g., provider API keys), parser errors can include details that risk leaking secrets into logs.

## Issue Context
Compliance requires that logs contain no sensitive data. Configuration parsing failures should be logged in a way that is useful for debugging but does not risk exposing config contents.

## Fix Focus Areas
- src/renderer/components/ConfigTab.tsx[227-237]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Config parse too permissive 🐞 Bug ✓ Correctness
Description
The new parseConfigContent helper intends to sanitize YAML input, but it still accepts arrays (valid
YAML sequences) as "object" and then mutates them as if they were ConfigObject maps. This can lead
to confusing/incorrect serialized YAML and lost settings if configContent is accidentally a
sequence.
Code

src/renderer/components/ConfigTab.tsx[R227-234]

+const parseConfigContent = (configContent: string): ConfigObject => {
+  try {
+    const parsedConfig = yaml.parse(configContent) as ConfigObject;
+    if (!parsedConfig || typeof parsedConfig !== 'object') {
+      return {};
+    }
+    return parsedConfig;
+  } catch (error) {
Evidence
ConfigObject is an interface for a key/value mapping (not a sequence). parseConfigContent only
guards non-objects via typeof, so YAML arrays pass through; applyBaseConfigState then assigns
mapping fields onto whatever was parsed, assuming a plain object.

src/renderer/components/ConfigTab.tsx[227-234]
src/renderer/components/ConfigTab.tsx[240-251]
src/types/ipc.ts[9-26]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`parseConfigContent` currently treats any YAML value with `typeof === &#x27;object&#x27;` as a valid `ConfigObject`. YAML sequences parse to JS arrays (also `typeof === &#x27;object&#x27;`), so the save path may mutate/serialize an array instead of a mapping.

### Issue Context
`ConfigObject` is a mapping-like interface. The save path (`applyBaseConfigState`/`applyProviderConfigState`) assumes it can safely set named properties.

### Fix Focus Areas
- src/renderer/components/ConfigTab.tsx[227-238]
- src/renderer/components/ConfigTab.tsx[316-326]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. Locale mapping lacks guards 🐞 Bug ⛯ Reliability
Description
The locale screenshot loop relies on three separate structures (SUPPORTED_LOCALES,
LOCALE_SCREENSHOT_KEYS, SCREENSHOTS) without asserting they stay in sync, and it hard-codes the
locale storage key/default in multiple places. If a future locale is added or a key changes,
screenshots may be missing or written to an unintended path without a clear error.
Code

scripts/capture-ui-screenshot.js[R524-537]

+async function captureLocaleScreenshots(page) {
+  await runStep('Wait for language selector', async () => {
+    await page.waitForSelector(UI_SELECTORS.languageSelector, { timeout: 10000 });
+  });
+
+  for (const locale of SUPPORTED_LOCALES) {
+    await runStep(`Switch locale to ${locale}`, async () => {
+      await setLocaleAndWait(page, locale);
+    });
+
+    await runStep(`Capture locale screenshot (${locale})`, async () => {
+      const screenshotKey = LOCALE_SCREENSHOT_KEYS[locale];
+      await page.screenshot({ path: SCREENSHOTS[screenshotKey], fullPage: true });
+    });
Evidence
The capture loop derives a screenshot path from LOCALE_SCREENSHOT_KEYS and SCREENSHOTS without
checking that the derived key/path exists. Additionally, the script hard-codes 'app.locale'/'en'
even though the renderer defines LOCALE_STORAGE_KEY/DEFAULT_LOCALE, increasing drift risk.

scripts/capture-ui-screenshot.js[14-16]
scripts/capture-ui-screenshot.js[371-376]
scripts/capture-ui-screenshot.js[381-386]
scripts/capture-ui-screenshot.js[529-537]
src/renderer/i18n/settings.ts[1-7]
src/renderer/components/LanguageSelector.tsx[18-22]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
The locale screenshot capture uses separate locale lists/mappings without validation and duplicates the locale storage key/default locale. If these drift, the script may capture fewer screenshots than expected or fail in confusing ways.

### Issue Context
The renderer uses `LOCALE_STORAGE_KEY = &#x27;app.locale&#x27;` and `DEFAULT_LOCALE = &#x27;en&#x27;`, while the capture script hard-codes these values in multiple places.

### Fix Focus Areas
- scripts/capture-ui-screenshot.js[14-16]
- scripts/capture-ui-screenshot.js[371-376]
- scripts/capture-ui-screenshot.js[378-503]
- scripts/capture-ui-screenshot.js[524-543]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

ⓘ The new review experience is currently in Beta. Learn more

Grey Divider

Qodo Logo

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

Copy link
Copy Markdown

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 is a solid step forward in improving the application's robustness and test coverage. The refactoring in ConfigTab.tsx significantly reduces cognitive complexity by breaking down large functions into smaller, more manageable pieces, which is a great improvement for maintainability. The addition of locale-based screenshot testing is also a valuable enhancement for quality assurance across different languages. My review includes a few suggestions to further improve maintainability by reducing code duplication in the test script. Overall, these are excellent changes.

Comment thread scripts/capture-ui-screenshot.js Outdated
Comment on lines +371 to +376
const LOCALE_SCREENSHOT_KEYS = {
en: 'localeEn',
es: 'localeEs',
fr: 'localeFr',
de: 'localeDe',
};

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

Similar to the SCREENSHOTS object, this mapping can be generated dynamically from SUPPORTED_LOCALES to avoid repetition and improve maintainability. This change, combined with the suggested change for SCREENSHOTS, would allow you to simply update the SUPPORTED_LOCALES array to add new languages to the screenshot test suite.

const LOCALE_SCREENSHOT_KEYS = SUPPORTED_LOCALES.reduce((acc, locale) => {
  acc[locale] = `locale${locale.charAt(0).toUpperCase() + locale.slice(1)}`;
  return acc;
}, {});

Comment on lines +762 to +772
const screenshotPaths = [
SCREENSHOTS.configDefault,
SCREENSHOTS.localeEn,
SCREENSHOTS.localeEs,
SCREENSHOTS.localeFr,
SCREENSHOTS.localeDe,
SCREENSHOTS.sourceTab,
SCREENSHOTS.sourceSelected,
SCREENSHOTS.sourceSelectedResized,
SCREENSHOTS.processedTab,
];

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

Instead of manually listing all screenshot paths, you can use Object.values(SCREENSHOTS) to get all paths from the SCREENSHOTS object. This simplifies the code and ensures that any new screenshots added to the SCREENSHOTS object are automatically included in the log output.

    const screenshotPaths = Object.values(SCREENSHOTS);

Comment thread src/renderer/feature-flags.ts Outdated
Comment on lines +6 to +10
if (globalThis.window === undefined) {
return false;
}

return window.devUtils?.isDev === true;
return globalThis.window.devUtils?.isDev === true;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

Using globalThis.window is a good step towards universal code. However, you can simplify this by using optional chaining (?.), which makes the code more concise and readable.

  return globalThis.window?.devUtils?.isDev === true;

Comment on lines +33 to +35
const i18nInstance = i18n;

export default i18nInstance;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

While creating an intermediate constant i18nInstance works, it's unnecessary. You can directly export the i18n object as the default export, which is a more common and direct pattern.

Suggested change
const i18nInstance = i18n;
export default i18nInstance;
export default i18n;

@sonarqubecloud

Copy link
Copy Markdown

@Mehdi-Bl Mehdi-Bl enabled auto-merge (squash) February 14, 2026 19:28
@Mehdi-Bl Mehdi-Bl merged commit cbc680f into main Feb 14, 2026
25 checks passed
@Mehdi-Bl Mehdi-Bl deleted the fix/sonar-complexity-locale-qa branch February 14, 2026 19:29
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.

1 participant