Skip to content

fixes #511 - #512

Open
Somil450 wants to merge 2 commits into
piyushdotcomm:mainfrom
Somil450:511-issue-solve
Open

fixes #511#512
Somil450 wants to merge 2 commits into
piyushdotcomm:mainfrom
Somil450:511-issue-solve

Conversation

@Somil450

@Somil450 Somil450 commented Jul 21, 2026

Copy link
Copy Markdown

fixes issue #511

Summary

  • what changed
  • why it changed

Type of change

  • Bug fix
  • New feature
  • Refactor
  • Documentation
  • Test or CI improvement
  • Starter template change

Related issue

Closes #

Validation

  • npm run lint
  • npm test
  • npm run build

List any additional manual verification you performed:

Screenshots or recordings

Add screenshots or short recordings for UI changes when relevant.

Checklist

  • I kept this PR focused on one primary change
  • I updated documentation if behavior changed
  • I did not commit secrets, local logs, or scratch files
  • I am requesting review on the correct scope

Summary by CodeRabbit

  • New Features

    • Added an Editor Preferences dialog for selecting the editor theme and enabling font ligatures.
    • Preferences are saved and restored automatically.
    • Added toolbar and menu access to Editor Preferences.
    • Separated AI Settings from editor preferences.
  • Improvements

    • Editor settings now apply consistently to the code editor.
    • Improved editor rendering performance.

@Somil450
Somil450 requested a review from piyushdotcomm as a code owner July 21, 2026 01:42
@github-actions

Copy link
Copy Markdown

👋 Thanks for opening a PR, @Somil450!

Your PR has entered the 🚦 PR Review Pipeline.

Standard PR detected — your PR will follow the standard review pipeline.


What happens next

Stage Reviewer Checks
Stage 1 — Automated Validation 🤖 Bot DCO · Format · AI/Slop · Duplicate
Stage 2 — Human Review 👥 Maintainer Code + Quality Review
Stage 3 — PA / Maintainer Review 🔑 Project Admin Final Merge Decision

A pipeline status comment will appear below and update automatically as your PR progresses.


While you wait

  • Sign all commits (git commit -s)
  • Link your issue (Closes #123)
  • Use a feature branch (not main)
  • Avoid unrelated changes

This comment is posted only once.

@coderabbitai

coderabbitai Bot commented Jul 21, 2026

Copy link
Copy Markdown

Review Change Stack

Walkthrough

The playground adds a dedicated preferences store and dialog for editor theme and font ligatures. Header controls open the dialog through new UI state, while Monaco reads the preferences and applies them to the editor.

Changes

Editor preferences

Layer / File(s) Summary
Preferences state and store migration
modules/playground/hooks/usePreferences.ts, modules/playground/hooks/useAI.ts, modules/playground/hooks/useAI.test.ts
Editor theme and font ligature settings use a new localStorage-backed Zustand store; theme state and actions are removed from useAI.
Preferences dialog and UI wiring
modules/playground/hooks/usePlaygroundUI.ts, modules/playground/components/preferences-dialog.tsx, modules/playground/components/playground-header.tsx, modules/playground/components/playground-modals.tsx
A controlled preferences dialog is opened from toolbar and menu controls through showPreferences UI state.
Monaco preference integration
modules/playground/components/playground-editor.tsx
Monaco consumes theme and font ligature preferences, retains inline suggestions, and the editor export is memoized.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Developer
  participant PlaygroundHeader
  participant PlaygroundUI
  participant PreferencesDialog
  participant PreferencesStore
  participant PlaygroundEditor
  Developer->>PlaygroundHeader: Select Preferences
  PlaygroundHeader->>PlaygroundUI: setShowPreferences(true)
  PlaygroundUI->>PreferencesDialog: Open dialog
  PreferencesDialog->>PreferencesStore: Read editorTheme and fontLigatures
  PreferencesDialog->>PreferencesStore: Persist preference changes
  PreferencesStore->>PlaygroundEditor: Provide updated preferences
  PlaygroundEditor->>PlaygroundEditor: Apply Monaco theme and options
Loading

Possibly related PRs

Suggested labels: enhancement, type:feature, level:intermediate

Suggested reviewers: piyushdotcomm

Poem

I’m a rabbit tuning themes in the night,
With ligatures curled just right.
A dialog blooms, preferences flow,
Monaco learns the hues we show—
Hop, hop, ship the editor bright! 🐇

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description mostly repeats the template and leaves the actual summary, type, issue, validation, and checklist fields unfilled. Fill in the template with a real summary, select the change type, link the issue, note validation, and add any relevant screenshots.
Title check ❓ Inconclusive The title only references issue closure and does not describe the actual changes in the pull request. Rename the PR to summarize the main change, such as adding a preferences dialog and moving editor settings into a new preferences store.
✅ Passed checks (3 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

Playground: add Editor Preferences dialog (theme + font ligatures)

✨ Enhancement 🧪 Tests 🕐 40+ Minutes

Grey Divider

AI Description

• Add Editor Preferences dialog for theme selection and font ligature toggle.
• Persist preferences via a new Zustand store backed by localStorage.
• Move editor theme state out of AI store; wire header/menu to open preferences.
Diagram

graph TD
  H["PlaygroundHeader"] --> UI["usePlaygroundUI"] --> M["PlaygroundModals"] --> D["PreferencesDialog"] --> P["usePreferences store"] --> LS[("localStorage")]
  P --> E["PlaygroundEditor (Monaco)"]
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Keep editor preferences inside useAI store
  • ➕ Fewer stores/hooks to reason about
  • ➕ Avoids migrating state and tests
  • ➖ Couples editor UX preferences to AI feature concerns
  • ➖ Makes future non-AI preferences (layout, keybindings) harder to organize
2. Use a dedicated Preferences context/provider scoped to Playground
  • ➕ Clear ownership and easy to add derived/memoized values
  • ➕ Can swap persistence mechanism without touching all consumers
  • ➖ More boilerplate and wiring than a small Zustand store
  • ➖ Still needs careful SSR/localStorage initialization logic

Recommendation: The PR’s approach (a dedicated usePreferences Zustand store) is the best fit: it cleanly decouples editor UX settings from AI state while keeping persistence logic centralized. If this area grows, consider standardizing all preference storage keys under STORAGE_KEYS to avoid ad-hoc string literals (e.g., ligatures key).

Files changed (8) +152 / -74

Enhancement (6) +151 / -47
playground-editor.tsxApply preferences-based theme + font ligatures to Monaco editor +12/-10

Apply preferences-based theme + font ligatures to Monaco editor

• Switches theme source from the AI store to the new preferences store and passes fontLigatures into Monaco options. Wraps the editor component in React.memo to reduce unnecessary re-renders.

modules/playground/components/playground-editor.tsx

playground-header.tsxAdd Preferences entry points in header UI +21/-4

Add Preferences entry points in header UI

• Removes the inline ThemeSelector and replaces it with a preferences button that opens the new preferences dialog. Adds a Preferences item to the dropdown menu and keeps AI Settings as a separate action.

modules/playground/components/playground-header.tsx

playground-modals.tsxRender PreferencesDialog from the shared modal host +7/-0

Render PreferencesDialog from the shared modal host

• Imports and mounts PreferencesDialog, driven by showPreferences state from the playground UI store.

modules/playground/components/playground-modals.tsx

preferences-dialog.tsxReplace ThemeSelector with a full Editor Preferences dialog +65/-33

Replace ThemeSelector with a full Editor Preferences dialog

• Refactors the former theme selector into a dialog that edits both editorTheme and fontLigatures. Uses the new usePreferences store and clarifies that settings are saved locally.

modules/playground/components/preferences-dialog.tsx

usePlaygroundUI.tsAdd preferences modal visibility state +5/-0

Add preferences modal visibility state

• Extends the playground UI store with showPreferences and setShowPreferences, and resets it in resetUI().

modules/playground/hooks/usePlaygroundUI.ts

usePreferences.tsIntroduce persisted editor preferences store +41/-0

Introduce persisted editor preferences store

• Adds a new Zustand store that initializes theme/ligature settings from localStorage and persists updates back to localStorage.

modules/playground/hooks/usePreferences.ts

Refactor (1) +1 / -12
useAI.tsDecouple editor theme from AI store +1/-12

Decouple editor theme from AI store

• Removes editorTheme state and setEditorTheme action from the AI Zustand store, leaving AI-specific state (inline suggestions, chat, API keys) intact.

modules/playground/hooks/useAI.ts

Tests (1) +0 / -15
useAI.test.tsRemove editor theme tests from AI store coverage +0/-15

Remove editor theme tests from AI store coverage

• Updates the useAI store tests to reflect removal of editorTheme state and its persistence behavior.

modules/playground/hooks/useAI.test.ts

@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.

🧹 Nitpick comments (2)
modules/playground/hooks/usePreferences.ts (1)

19-38: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Extract the magic string to STORAGE_KEYS.

For consistency with EDITOR_THEME and to prevent potential typos across the codebase, consider extracting "editron:preferences:ligatures" into the STORAGE_KEYS configuration constant.

♻️ Proposed refactor

Update your STORAGE_KEYS object in @/lib/constants/config.ts first:

export const STORAGE_KEYS = {
  // ...
  FONT_LIGATURES: "editron:preferences:ligatures",
};

Then apply this change:

-const getInitialLigatures = () => {
-  if (typeof window === "undefined") return true;
-  return localStorage.getItem("editron:preferences:ligatures") !== "false";
-};
+const getInitialLigatures = () => {
+  if (typeof window === "undefined") return true;
+  return localStorage.getItem(STORAGE_KEYS.FONT_LIGATURES) !== "false";
+};

 export const usePreferences = create<PreferencesState>((set) => ({
   editorTheme: getInitialTheme(),
   fontLigatures: getInitialLigatures(),

   setEditorTheme: (theme: string) => {
     try {
       localStorage.setItem(STORAGE_KEYS.EDITOR_THEME, theme);
     } catch {}
     set({ editorTheme: theme });
   },

   setFontLigatures: (enabled: boolean) => {
     try {
-      localStorage.setItem("editron:preferences:ligatures", String(enabled));
+      localStorage.setItem(STORAGE_KEYS.FONT_LIGATURES, String(enabled));
     } catch {}
     set({ fontLigatures: enabled });
   }
 }));
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@modules/playground/hooks/usePreferences.ts` around lines 19 - 38, Extract the
"editron:preferences:ligatures" value into a FONT_LIGATURES entry in the
STORAGE_KEYS constant, then update getInitialLigatures and setFontLigatures to
reference STORAGE_KEYS.FONT_LIGATURES instead of the literal string. Keep the
existing preference behavior unchanged.
modules/playground/components/playground-editor.tsx (1)

485-495: 🚀 Performance & Scalability | 🔵 Trivial | 💤 Low value

Memoize Monaco editor options and verify parent callbacks.

Passing a fresh object to the options prop on every render can cause the Monaco wrapper to diff and update options unnecessarily. Consider memoizing this object.
Additionally, since PlaygroundEditor is now exported with React.memo (line 495), ensure that the parent component passes stable references (e.g., via useCallback) for the onContentChange and onCursorChange props; otherwise, the memo wrapper will be ineffective.

♻️ Proposed refactor for memoizing options
+  const editorOptions = useMemo(() => ({
+    ...defaultEditorOptions,
+    fontLigatures,
+    inlineSuggest: { enabled: true },
+  }), [fontLigatures]);

   return (
     <div className="h-full relative">
       <Editor
         height={"100%"}
         defaultValue={content}
         onChange={(value) => onContentChange(value || "")}
         onMount={handleEditorDidMount}
         language={
           activeFile
             ? getEditorLanguage(activeFile.fileExtension || "")
             : "plaintext"
         }
-        options={{
-          ...defaultEditorOptions,
-          fontLigatures: fontLigatures,
-          inlineSuggest: { enabled: true },
-        }}
+        options={editorOptions}
       />
     </div>
   );
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@modules/playground/components/playground-editor.tsx` around lines 485 - 495,
Memoize the Monaco `options` object in `PlaygroundEditor` so it is recreated
only when `defaultEditorOptions` or `fontLigatures` changes. Also update the
parent component’s `onContentChange` and `onCursorChange` props to use stable
`useCallback` references, preserving their existing behavior so
`memo(PlaygroundEditor)` can prevent unnecessary renders.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@modules/playground/components/playground-editor.tsx`:
- Around line 485-495: Memoize the Monaco `options` object in `PlaygroundEditor`
so it is recreated only when `defaultEditorOptions` or `fontLigatures` changes.
Also update the parent component’s `onContentChange` and `onCursorChange` props
to use stable `useCallback` references, preserving their existing behavior so
`memo(PlaygroundEditor)` can prevent unnecessary renders.

In `@modules/playground/hooks/usePreferences.ts`:
- Around line 19-38: Extract the "editron:preferences:ligatures" value into a
FONT_LIGATURES entry in the STORAGE_KEYS constant, then update
getInitialLigatures and setFontLigatures to reference
STORAGE_KEYS.FONT_LIGATURES instead of the literal string. Keep the existing
preference behavior unchanged.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 6f839ae3-c6cd-4c53-ad50-32e1fd9d51ed

📥 Commits

Reviewing files that changed from the base of the PR and between 4ffe26f and f8b2701.

📒 Files selected for processing (8)
  • modules/playground/components/playground-editor.tsx
  • modules/playground/components/playground-header.tsx
  • modules/playground/components/playground-modals.tsx
  • modules/playground/components/preferences-dialog.tsx
  • modules/playground/hooks/useAI.test.ts
  • modules/playground/hooks/useAI.ts
  • modules/playground/hooks/usePlaygroundUI.ts
  • modules/playground/hooks/usePreferences.ts
💤 Files with no reviewable changes (1)
  • modules/playground/hooks/useAI.test.ts

@qodo-code-review

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (2) 📘 Rule violations (2) 📜 Skill insights (0)

Context used
✅ Compliance rules (platform): 22 rules

Grey Divider


Action required

1. Ligatures preference overridden 🐞 Bug ≡ Correctness
Description
PlaygroundEditor sets fontLigatures via the Editor options prop, but handleEditorDidMount
immediately calls editor.updateOptions({ ...defaultEditorOptions, ... }), which re-applies
defaultEditorOptions.fontLigatures (true) and can override a persisted false setting on initial
load. This causes the PreferencesDialog toggle and the actual editor rendering to disagree until the
user changes the setting again.
Code

modules/playground/components/playground-editor.tsx[R484-489]

        }
        options={{
          ...defaultEditorOptions,
+          fontLigatures: fontLigatures,
          inlineSuggest: { enabled: true },
        }}
Relevance

⭐⭐⭐ High

Team fixes Monaco/editor lifecycle correctness issues (see PlaygroundEditor race-condition fixes in
PR #184).

PR-#184

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The mount handler re-applies defaultEditorOptions (including fontLigatures: true), which can
override the new preferences-driven fontLigatures option passed to the Editor component.

modules/playground/components/playground-editor.tsx[54-63]
modules/playground/components/playground-editor.tsx[473-490]
modules/playground/lib/editor-config.ts[265-271]

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

### Issue description
`fontLigatures` is now user-configurable, but the editor mount handler re-applies `defaultEditorOptions` (which sets `fontLigatures: true`), overriding a saved `false` preference on initial mount.

### Issue Context
- The React wrapper receives `options.fontLigatures`, but `handleEditorDidMount` calls `editor.updateOptions({...defaultEditorOptions,...})` which can overwrite it.

### Fix Focus Areas
- modules/playground/components/playground-editor.tsx[54-63]
- modules/playground/components/playground-editor.tsx[484-489]

### Suggested fix
- Ensure the mount-time `editor.updateOptions(...)` does **not** force ligatures back to the default.
 - Option A (simplest): remove the redundant `editor.updateOptions({ ...defaultEditorOptions, ... })` call and only set the specific mount-only options you need (e.g., `inlineSuggest`).
 - Option B: include the current preference when calling `updateOptions`, e.g. `editor.updateOptions({ ...defaultEditorOptions, fontLigatures, inlineSuggest: { enabled: true } })` (requires moving `usePreferences()` above the callback so `fontLigatures` is in scope).
 - Option C: add a `useEffect` that calls `editorRef.current?.updateOptions({ fontLigatures })` when `fontLigatures` changes, to guarantee the preference always wins.

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



Remediation recommended

2. Unsafe localStorage reads 🐞 Bug ☼ Reliability
Description
usePreferences initializes Zustand state by calling localStorage.getItem(...) without a
try/catch, which can throw (e.g., blocked storage / restricted contexts) and prevent the preferences
store from initializing. This can break rendering for any component importing the store (notably
PlaygroundEditor and PreferencesDialog).
Code

modules/playground/hooks/usePreferences.ts[R14-22]

+const getInitialTheme = () => {
+  if (typeof window === "undefined") return DEFAULT_EDITOR_THEME;
+  return localStorage.getItem(STORAGE_KEYS.EDITOR_THEME) || DEFAULT_EDITOR_THEME;
+};
+
+const getInitialLigatures = () => {
+  if (typeof window === "undefined") return true;
+  return localStorage.getItem("editron:preferences:ligatures") !== "false";
+};
Relevance

⭐⭐⭐ High

LocalStorage-at-init fragility acknowledged (PR #232); repo often adds guards/try-catch for
runtime-safety (e.g., PR #73).

PR-#232
PR-#73

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The new preferences store performs unguarded localStorage reads, unlike the existing AI store which
already uses try/catch for localStorage access, demonstrating this repo expects storage access to
fail sometimes.

modules/playground/hooks/usePreferences.ts[14-22]
modules/playground/hooks/useAI.ts[44-55]

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

### Issue description
`getInitialTheme()` / `getInitialLigatures()` call `localStorage.getItem` without exception handling. In browsers where storage access throws, this can crash store creation.

### Issue Context
The codebase already treats localStorage as fallible in other stores (e.g., `useAI` wraps reads in try/catch).

### Fix Focus Areas
- modules/playground/hooks/usePreferences.ts[14-22]

### Suggested fix
Wrap both `localStorage.getItem(...)` calls in `try/catch` and return safe defaults when an exception occurs, e.g.:
- `try { return localStorage.getItem(...) ?? DEFAULT } catch { return DEFAULT }`
Also consider centralizing the ligatures key into `STORAGE_KEYS` for consistency (optional).

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


3. PreferencesDialog missing return type 📘 Rule violation ⚙ Maintainability
Description
The newly exported PreferencesDialog component relies on an inferred return type rather than
declaring an explicit return type annotation. This makes the module’s public API less explicit and
can weaken type-safety guarantees over time.
Code

modules/playground/components/preferences-dialog.tsx[R74-75]

+export default function PreferencesDialog({ open, onOpenChange }: PreferencesDialogProps) {
+  const { editorTheme, setEditorTheme, fontLigatures, setFontLigatures } = usePreferences();
Relevance

⭐⭐ Medium

Repo prefers strict typing (PR #191/#236), but no precedent found for explicit React return type
annotations.

PR-#191
PR-#236

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
PR Compliance ID 599991 requires explicit parameter and return typing for public APIs.
PreferencesDialog is exported but does not declare an explicit return type annotation on its
function signature.

Rule 599991: Public APIs must use typed interfaces for parameters and return types
modules/playground/components/preferences-dialog.tsx[69-76]

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

## Issue description
A newly exported (public) component is missing an explicit return type annotation.

## Issue Context
Compliance requires explicit typing for public API parameters and return values; exported components count as public APIs within the module boundary.

## Fix Focus Areas
- modules/playground/components/preferences-dialog.tsx[74-75]

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



Informational

4. useAI.test.ts outside /tests 📘 Rule violation ▣ Testability
Description
This PR modifies a test file located under modules/ instead of the required top-level /tests
directory. Keeping tests outside /tests makes test discovery and project structure enforcement
harder.
Code

modules/playground/hooks/useAI.test.ts[L411-423]

-  // --- editor theme -----------------------------------------------------------
-  describe("setEditorTheme", () => {
-    it("updates the editorTheme state", () => {
-      useAI.getState().setEditorTheme("github-dark");
-      expect(useAI.getState().editorTheme).toBe("github-dark");
-    });
-
-    it("persists the theme to localStorage", () => {
-      const spy = vi.spyOn(Storage.prototype, "setItem");
-      useAI.getState().setEditorTheme("monokai");
-      expect(spy).toHaveBeenCalledWith("editron_editor_theme", "monokai");
-    });
-  });
Relevance

⭐ Low

Tests exist under modules (e.g., modules/playground/hooks/useAI.test.ts added in PR #111), so
/tests-only rule not enforced.

PR-#111

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
PR Compliance ID 599997 requires automated tests to be placed under /tests. The modified test file
is modules/playground/hooks/useAI.test.ts, which is outside /tests.

Rule 599997: Place all automated tests under the /tests directory
modules/playground/hooks/useAI.test.ts[1-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
A modified test file is not located under the top-level `/tests` directory.

## Issue Context
The compliance checklist requires automated tests to live under `/tests` to keep structure consistent and predictable.

## Fix Focus Areas
- modules/playground/hooks/useAI.test.ts[1-22]

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


Grey Divider

Qodo Logo

</div>
);
} No newline at end of file
export default function PreferencesDialog({ open, onOpenChange }: PreferencesDialogProps) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Remediation recommended

1. preferencesdialog missing return type 📘 Rule violation ⚙ Maintainability

The newly exported PreferencesDialog component relies on an inferred return type rather than
declaring an explicit return type annotation. This makes the module’s public API less explicit and
can weaken type-safety guarantees over time.
Agent Prompt
## Issue description
A newly exported (public) component is missing an explicit return type annotation.

## Issue Context
Compliance requires explicit typing for public API parameters and return values; exported components count as public APIs within the module boundary.

## Fix Focus Areas
- modules/playground/components/preferences-dialog.tsx[74-75]

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

@@ -483,11 +484,12 @@ const PlaygroundEditor = ({
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Action required

3. Ligatures preference overridden 🐞 Bug ≡ Correctness

PlaygroundEditor sets fontLigatures via the Editor options prop, but handleEditorDidMount
immediately calls editor.updateOptions({ ...defaultEditorOptions, ... }), which re-applies
defaultEditorOptions.fontLigatures (true) and can override a persisted false setting on initial
load. This causes the PreferencesDialog toggle and the actual editor rendering to disagree until the
user changes the setting again.
Agent Prompt
### Issue description
`fontLigatures` is now user-configurable, but the editor mount handler re-applies `defaultEditorOptions` (which sets `fontLigatures: true`), overriding a saved `false` preference on initial mount.

### Issue Context
- The React wrapper receives `options.fontLigatures`, but `handleEditorDidMount` calls `editor.updateOptions({...defaultEditorOptions,...})` which can overwrite it.

### Fix Focus Areas
- modules/playground/components/playground-editor.tsx[54-63]
- modules/playground/components/playground-editor.tsx[484-489]

### Suggested fix
- Ensure the mount-time `editor.updateOptions(...)` does **not** force ligatures back to the default.
  - Option A (simplest): remove the redundant `editor.updateOptions({ ...defaultEditorOptions, ... })` call and only set the specific mount-only options you need (e.g., `inlineSuggest`).
  - Option B: include the current preference when calling `updateOptions`, e.g. `editor.updateOptions({ ...defaultEditorOptions, fontLigatures, inlineSuggest: { enabled: true } })` (requires moving `usePreferences()` above the callback so `fontLigatures` is in scope).
  - Option C: add a `useEffect` that calls `editorRef.current?.updateOptions({ fontLigatures })` when `fontLigatures` changes, to guarantee the preference always wins.

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

setFontLigatures: (enabled: boolean) => void;
}

const getInitialTheme = () => {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Remediation recommended

4. Unsafe localstorage reads 🐞 Bug ☼ Reliability

usePreferences initializes Zustand state by calling localStorage.getItem(...) without a
try/catch, which can throw (e.g., blocked storage / restricted contexts) and prevent the preferences
store from initializing. This can break rendering for any component importing the store (notably
PlaygroundEditor and PreferencesDialog).
Agent Prompt
### Issue description
`getInitialTheme()` / `getInitialLigatures()` call `localStorage.getItem` without exception handling. In browsers where storage access throws, this can crash store creation.

### Issue Context
The codebase already treats localStorage as fallible in other stores (e.g., `useAI` wraps reads in try/catch).

### Fix Focus Areas
- modules/playground/hooks/usePreferences.ts[14-22]

### Suggested fix
Wrap both `localStorage.getItem(...)` calls in `try/catch` and return safe defaults when an exception occurs, e.g.:
- `try { return localStorage.getItem(...) ?? DEFAULT } catch { return DEFAULT }`
Also consider centralizing the ligatures key into `STORAGE_KEYS` for consistency (optional).

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

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