Skip to content

Conversation

junhaoliao
Copy link
Member

@junhaoliao junhaoliao commented Sep 3, 2025

Description

  1. Refactor isPrettify toggle handling into a helper function, which updates the UI visuals, URL parameters and triggers a page load.
  2. Let both the toggle button and the editor "Toggle Prettify" action handler call the same helper.

Checklist

  • The PR satisfies the contribution guidelines.
  • This is a breaking change and that has been indicated in the PR title, OR this isn't a
    breaking change.
  • Necessary docs have been updated, OR no docs need to be updated.

Validation performed

Launched development server and tested the monaco editor action toggle as instructed by the reproduction steps in #379 :

  1. Added &isPrettified=true to the URL in the address bar and observed the logs became formatted with spaces in between numbers.
  2. Observed the "Pretty" button in the lower right corner became active as well.
  3. Toggled the "Pretty" button so that it became inactive. Observed that the special formatting was removed from the logs in the editor.
  4. Pressed F1 to bring up the monaco editor's action menu. Typed View: Toggle Prettify and hit Enter. Observed the "Pretty" button became active and the URL parameter isPrettified=true was added, and the "Prettify" toggle button became active, and the log content in the monaco editor change format as expected.
  5. Toggled the monaco action again as done in Step 4 and observed the URL parameter isPrettified=true was removed from the address bar, and the "Prettify" toggle button became inactive, and the log content in the monaco editor removed the special format as expected.

Summary by CodeRabbit

  • Refactor

    • Unified the “Prettify” toggle into a single shared action used by the Editor and Status Bar to avoid duplicated logic.
  • Bug Fixes

    • Improved reliability and sync of the “Prettify” toggle between the UI and URL/state handling.
  • Documentation

    • Updated contributor/dev-guide testing notes to reflect three ways to toggle Prettify: status bar, address bar, and editor command.

@junhaoliao junhaoliao requested a review from a team as a code owner September 3, 2025 08:38
@junhaoliao junhaoliao requested a review from Henry8192 September 3, 2025 08:38
Copy link

coderabbitai bot commented Sep 3, 2025

Caution

Review failed

An error occurred during the review process. Please try again later.

✨ Finishing Touches
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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

@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: 5

Caution

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

⚠️ Outside diff range comments (1)
src/components/StatusBar/index.tsx (1)

80-93: Optional: disable the button while toggling to prevent double clicks.

If you adopt the in-flight guard in the slice, surface an isPrettifyUpdating flag to the UI and wire it here to disabled or a loading state.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between a6aee18 and a55a00e.

📒 Files selected for processing (3)
  • src/components/Editor/index.tsx (2 hunks)
  • src/components/StatusBar/index.tsx (4 hunks)
  • src/stores/viewStore/createViewFormattingSlice.ts (3 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{cpp,hpp,java,js,jsx,tpp,ts,tsx}

⚙️ CodeRabbit configuration file

  • Prefer false == <expression> rather than !<expression>.

Files:

  • src/stores/viewStore/createViewFormattingSlice.ts
  • src/components/StatusBar/index.tsx
  • src/components/Editor/index.tsx
🧠 Learnings (2)
📚 Learning: 2025-04-28T08:21:28.568Z
Learnt from: junhaoliao
PR: y-scope/yscope-log-viewer#224
File: src/contexts/states/logFileStore/loadSlice.ts:1-1
Timestamp: 2025-04-28T08:21:28.568Z
Learning: When importing from npm packages, use the public API entrypoint (e.g., `import {StateCreator} from "zustand"`) rather than deep-linking into package internals (e.g., `import {StateCreator} from "zustand/index"`), as internal file structures may change between package versions.

Applied to files:

  • src/stores/viewStore/createViewFormattingSlice.ts
📚 Learning: 2025-06-01T13:40:12.222Z
Learnt from: zzxthehappiest
PR: y-scope/yscope-log-viewer#286
File: src/components/Editor/index.tsx:138-139
Timestamp: 2025-06-01T13:40:12.222Z
Learning: In the yscope-log-viewer codebase, when using Zustand stores in React components, the preferred pattern is to use `getState()` for static setters that never change (like `setLogEventNum`) to avoid unnecessary subscriptions, while using hooks for actions that do more than just setting values. All store state variables should be declared at the beginning of the component for consistency and clear dependency overview.

Applied to files:

  • src/stores/viewStore/createViewFormattingSlice.ts
🧬 Code graph analysis (1)
src/stores/viewStore/createViewFormattingSlice.ts (6)
src/utils/url/index.ts (1)
  • updateWindowUrlHashParams (385-385)
src/typings/url.ts (1)
  • HASH_PARAM_NAMES (39-39)
src/services/LogFileManager/index.ts (1)
  • setIsPrettified (199-201)
src/typings/worker.ts (1)
  • CURSOR_CODE (101-101)
src/utils/url/urlHash.ts (1)
  • updateViewHashParams (138-138)
src/stores/notificationStore.ts (1)
  • handleErrorWithNotification (76-76)
🔇 Additional comments (5)
src/stores/viewStore/createViewFormattingSlice.ts (3)

7-7: Import path verified: The useLogFileManagerProxyStore module resides at src/stores/logFileManagerProxyStore.ts, so the import import useLogFileManagerProxyStore from "../logFileManagerProxyStore.ts"; in createViewFormattingSlice.ts is correct.


35-35: Remove unnecessary await on the setIsPrettified call in createViewFormattingSlice.ts:35—it returns void, so use a direct call.

⛔ Skipped due to learnings
Learnt from: Henry8192
PR: y-scope/yscope-log-viewer#367
File: src/utils/url/urlHash.ts:39-51
Timestamp: 2025-08-14T15:27:32.421Z
Learning: The logFileManagerProxy methods (including setIsPrettified) are asynchronous and return Promises, requiring await when called and proper async handling.

36-39: Remove null/undefined guard—logEventNum is always a non-null number
logEventNum’s type is number (defaulting to 0) and cannot be null or undefined. If you need to guard against the initial “no-event” state, check for the sentinel value 0 instead.

Likely an incorrect or invalid review comment.

src/components/Editor/index.tsx (1)

13-17: Centralizing toggle + error handling looks good.

Importing togglePrettify and handleErrorWithNotification removes URL/hash manipulation from the Editor and unifies behaviour.

src/components/StatusBar/index.tsx (1)

47-49: Good switch to a shared toggle with centralized error handling.

The useCallback wrapper and unified store action simplify the click path.

Comment on lines 24 to 44
const togglePrettify = async () => {
const {logEventNum, loadPageByCursor, isPrettified, setIsPrettified} = useViewStore.getState();
const newIsPrettified = !isPrettified;

// Update the URL and store state.
updateWindowUrlHashParams({[HASH_PARAM_NAMES.IS_PRETTIFIED]: newIsPrettified});
setIsPrettified(newIsPrettified);

// Update the log file manager and reload the page.
try {
const {logFileManagerProxy} = useLogFileManagerProxyStore.getState();
await logFileManagerProxy.setIsPrettified(newIsPrettified);
await loadPageByCursor({
code: CURSOR_CODE.EVENT_NUM,
args: {eventNum: logEventNum},
});
updateViewHashParams();
} catch (error) {
handleErrorWithNotification(error);
}
};
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Make toggle operation atomic; add re-entrancy guard and rollback on failure.

Current flow optimistically updates URL/store before I/O and doesn’t rollback on errors; it’s also re-entrant if clicked rapidly, causing racey flips and duplicate reloads.

@@
-const togglePrettify = async () => {
-    const {logEventNum, loadPageByCursor, isPrettified, setIsPrettified} = useViewStore.getState();
-    const newIsPrettified = !isPrettified;
-
-    // Update the URL and store state.
-    updateWindowUrlHashParams({[HASH_PARAM_NAMES.IS_PRETTIFIED]: newIsPrettified});
-    setIsPrettified(newIsPrettified);
-
-    // Update the log file manager and reload the page.
-    try {
-        const {logFileManagerProxy} = useLogFileManagerProxyStore.getState();
-        await logFileManagerProxy.setIsPrettified(newIsPrettified);
-        await loadPageByCursor({
-            code: CURSOR_CODE.EVENT_NUM,
-            args: {eventNum: logEventNum},
-        });
-        updateViewHashParams();
-    } catch (error) {
-        handleErrorWithNotification(error);
-    }
-};
+let isTogglingPrettify = false;
+
+const togglePrettify = async (): Promise<void> => {
+    if (true === isTogglingPrettify) {
+        return;
+    }
+    isTogglingPrettify = true;
+    const {logEventNum, loadPageByCursor, isPrettified, setIsPrettified} = useViewStore.getState();
+    const prevIsPrettified = isPrettified;
+    const newIsPrettified = false === isPrettified;
+    try {
+        // Optimistically update URL + store, then commit to services.
+        updateWindowUrlHashParams({[HASH_PARAM_NAMES.IS_PRETTIFIED]: newIsPrettified});
+        setIsPrettified(newIsPrettified);
+
+        const {logFileManagerProxy} = useLogFileManagerProxyStore.getState();
+        await logFileManagerProxy.setIsPrettified(newIsPrettified);
+        if (null !== logEventNum) {
+            await loadPageByCursor({
+                code: CURSOR_CODE.EVENT_NUM,
+                args: {eventNum: logEventNum},
+            });
+        }
+        updateViewHashParams();
+    } catch (error) {
+        // Roll back URL + store to consistent previous state.
+        updateWindowUrlHashParams({[HASH_PARAM_NAMES.IS_PRETTIFIED]: prevIsPrettified});
+        setIsPrettified(prevIsPrettified);
+        updateViewHashParams();
+        handleErrorWithNotification(error);
+    } finally {
+        isTogglingPrettify = false;
+    }
+};
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const togglePrettify = async () => {
const {logEventNum, loadPageByCursor, isPrettified, setIsPrettified} = useViewStore.getState();
const newIsPrettified = !isPrettified;
// Update the URL and store state.
updateWindowUrlHashParams({[HASH_PARAM_NAMES.IS_PRETTIFIED]: newIsPrettified});
setIsPrettified(newIsPrettified);
// Update the log file manager and reload the page.
try {
const {logFileManagerProxy} = useLogFileManagerProxyStore.getState();
await logFileManagerProxy.setIsPrettified(newIsPrettified);
await loadPageByCursor({
code: CURSOR_CODE.EVENT_NUM,
args: {eventNum: logEventNum},
});
updateViewHashParams();
} catch (error) {
handleErrorWithNotification(error);
}
};
let isTogglingPrettify = false;
const togglePrettify = async (): Promise<void> => {
if (true === isTogglingPrettify) {
return;
}
isTogglingPrettify = true;
const {logEventNum, loadPageByCursor, isPrettified, setIsPrettified} = useViewStore.getState();
const prevIsPrettified = isPrettified;
const newIsPrettified = false === isPrettified;
try {
// Optimistically update URL + store, then commit to services.
updateWindowUrlHashParams({[HASH_PARAM_NAMES.IS_PRETTIFIED]: newIsPrettified});
setIsPrettified(newIsPrettified);
const {logFileManagerProxy} = useLogFileManagerProxyStore.getState();
await logFileManagerProxy.setIsPrettified(newIsPrettified);
if (null !== logEventNum) {
await loadPageByCursor({
code: CURSOR_CODE.EVENT_NUM,
args: {eventNum: logEventNum},
});
}
updateViewHashParams();
} catch (error) {
// Roll back URL + store to consistent previous state.
updateWindowUrlHashParams({[HASH_PARAM_NAMES.IS_PRETTIFIED]: prevIsPrettified});
setIsPrettified(prevIsPrettified);
updateViewHashParams();
handleErrorWithNotification(error);
} finally {
isTogglingPrettify = false;
}
};
🤖 Prompt for AI Agents
In src/stores/viewStore/createViewFormattingSlice.ts around lines 24-44, the
togglePrettify function is optimistic and re-entrant: add a re-entrancy guard
(e.g., an in-flight flag in the view slice or a module-scoped boolean) to return
early if a toggle is already running, perform the I/O (call
logFileManagerProxy.setIsPrettified and reload) first, and only update the store
and URL after the I/O succeeds; if you must update optimistically keep the
original state and URL so you can rollback them in the catch block (call
setIsPrettified(original) and restore the previous hash param) before
re-throwing or notifying the user, and ensure the in-flight flag is cleared in
both success and error paths.

Comment on lines 28 to 31
// Update the URL and store state.
updateWindowUrlHashParams({[HASH_PARAM_NAMES.IS_PRETTIFIED]: newIsPrettified});
setIsPrettified(newIsPrettified);

Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

Avoid duplicative hash updates unless required.

Calling both updateWindowUrlHashParams({IS_PRETTIFIED}) and updateViewHashParams() may be redundant if the latter already covers IS_PRETTIFIED. Consider relying on a single source of truth to reduce drift.

Also applies to: 40-40

🤖 Prompt for AI Agents
In src/stores/viewStore/createViewFormattingSlice.ts around lines 28-31 (and
also line 40), there are duplicate hash updates:
updateWindowUrlHashParams({IS_PRETTIFIED}) is called in addition to
updateViewHashParams(), which risks drift; remove the redundant direct call and
rely on the single canonical updater (preferably updateViewHashParams) to write
IS_PRETTIFIED to the URL after state is set, or conversely consolidate logic so
updateWindowUrlHashParams is the single writer and updateViewHashParams no
longer writes the same key; update the surrounding code to set state first, call
only the chosen hash updater, and adjust any callers/tests expecting the
previous double-update behavior.

@Henry8192
Copy link
Contributor

@junhaoliao I noticed that toggle prettify keyboard shortcut "Alt+Shift+F" never worked. Can you confirm this?

@junhaoliao
Copy link
Member Author

junhaoliao commented Sep 5, 2025

@junhaoliao I noticed that toggle prettify keyboard shortcut "Alt+Shift+F" never worked. Can you confirm this?

On my end the shortcut is Alt + F and it seems to work for me in c404aa6 . On which platform (e.g. OS, browser) were you launching the log viewer?
image

/**
* Toggles the prettify state for formatted log viewing.
*/
const togglePrettify = () => {
Copy link
Member Author

Choose a reason for hiding this comment

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

@Henry8192 do you think there's a better place to move this into?

Copy link
Member Author

Choose a reason for hiding this comment

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

since now this does not directly touch the Zustand handling of isPretified

Copy link
Member Author

Choose a reason for hiding this comment

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

for now, i have moved it to the urlHash utils

Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah, I guess either leave it inside the urlHash utils, or we need to create a new file for this function, as it doesn't really belong to any of the utility functions.

Copy link

@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: 2

Caution

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

⚠️ Outside diff range comments (1)
src/components/Editor/index.tsx (1)

103-104: Off-by-one: last line is excluded from the selection.

Monaco ranges are end-inclusive; using getLineCount() - 1 drops the final line.

Apply:

-        endLineNumber = model.getLineCount() - 1;
+        endLineNumber = model.getLineCount();
♻️ Duplicate comments (2)
src/components/Editor/index.tsx (1)

167-169: Keep the async IIFE here.

This handler is sync; the IIFE correctly awaits and funnels errors to the notifier. Note: once togglePrettify rethrows on failure (see store review), this catch will work as intended.

src/stores/viewStore/createViewFormattingSlice.ts (1)

24-44: Make toggle atomic; add re-entrancy guard, rollback on failure, and rethrow.

Current flow: (1) optimistic URL/store update, (2) service calls, (3) catch+notify but no rollback, and (4) the Promise resolves, so callers’ .catch() never runs. This can leave UI/URL inconsistent if the proxy or reload fails and can double-execute on rapid clicks.

  • Add an in-flight guard to prevent concurrent toggles from Editor/StatusBar.
  • Roll back URL and store on failure.
  • Re-throw after rollback so callers’ .catch(handleErrorWithNotification) remains effective.
  • Guard loadPageByCursor when logEventNum is null.

Apply:

+let isTogglingPrettify = false;
+
-const togglePrettify = async () => {
+const togglePrettify = async (): Promise<void> => {
-    const {logEventNum, loadPageByCursor, isPrettified, setIsPrettified} = useViewStore.getState();
-    const newIsPrettified = !isPrettified;
-
-    // Update the URL and store state.
-    updateWindowUrlHashParams({[HASH_PARAM_NAMES.IS_PRETTIFIED]: newIsPrettified});
-    setIsPrettified(newIsPrettified);
-
-    // Update the log file manager and reload the page.
-    try {
-        const {logFileManagerProxy} = useLogFileManagerProxyStore.getState();
-        await logFileManagerProxy.setIsPrettified(newIsPrettified);
-        await loadPageByCursor({
-            code: CURSOR_CODE.EVENT_NUM,
-            args: {eventNum: logEventNum},
-        });
-        updateViewHashParams();
-    } catch (error) {
-        handleErrorWithNotification(error);
-    }
-};
+    if (true === isTogglingPrettify) {
+        return;
+    }
+    isTogglingPrettify = true;
+    const {logEventNum, loadPageByCursor, isPrettified, setIsPrettified} = useViewStore.getState();
+    const prevIsPrettified = isPrettified;
+    const newIsPrettified = !isPrettified;
+    // Optimistically update URL + store.
+    updateWindowUrlHashParams({[HASH_PARAM_NAMES.IS_PRETTIFIED]: newIsPrettified});
+    setIsPrettified(newIsPrettified);
+    try {
+        const {logFileManagerProxy} = useLogFileManagerProxyStore.getState();
+        logFileManagerProxy.setIsPrettified(newIsPrettified);
+        if (null !== logEventNum) {
+            await loadPageByCursor({
+                code: CURSOR_CODE.EVENT_NUM,
+                args: {eventNum: logEventNum},
+            });
+        }
+        updateViewHashParams();
+    } catch (error) {
+        // Roll back to previous consistent state.
+        updateWindowUrlHashParams({[HASH_PARAM_NAMES.IS_PRETTIFIED]: prevIsPrettified});
+        setIsPrettified(prevIsPrettified);
+        updateViewHashParams();
+        throw error;
+    } finally {
+        isTogglingPrettify = false;
+    }
+};

Optional: if updateViewHashParams() already writes IS_PRETTIFIED, you can remove the direct updateWindowUrlHashParams call to avoid double writes. See prior note.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between a55a00e and 5c6f3a1.

📒 Files selected for processing (3)
  • src/components/Editor/index.tsx (2 hunks)
  • src/components/StatusBar/index.tsx (4 hunks)
  • src/stores/viewStore/createViewFormattingSlice.ts (3 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{cpp,hpp,java,js,jsx,tpp,ts,tsx}

⚙️ CodeRabbit configuration file

  • Prefer false == <expression> rather than !<expression>.

Files:

  • src/components/Editor/index.tsx
  • src/stores/viewStore/createViewFormattingSlice.ts
  • src/components/StatusBar/index.tsx
🧠 Learnings (7)
📚 Learning: 2025-09-03T18:22:30.594Z
Learnt from: junhaoliao
PR: y-scope/yscope-log-viewer#371
File: src/components/MenuBar/index.tsx:42-46
Timestamp: 2025-09-03T18:22:30.594Z
Learning: The development team has discussed that fire-and-forget async IIFE patterns (like `(async () => { ... })().catch(handleErrorWithNotification)`) don't cause synchronization issues in the yscope-log-viewer codebase due to serialized service worker communications, but they acknowledge it's still an error-prone pattern that should be refactored for better code clarity and maintainability.

Applied to files:

  • src/components/Editor/index.tsx
📚 Learning: 2025-09-05T15:00:08.221Z
Learnt from: Henry8192
PR: y-scope/yscope-log-viewer#380
File: src/components/Editor/index.tsx:167-170
Timestamp: 2025-09-05T15:00:08.221Z
Learning: In the yscope-log-viewer codebase, when calling async functions from synchronous contexts (like handleEditorCustomAction), async IIFE patterns like (async () => { await asyncFunction(); })().catch(errorHandler) are the appropriate approach to properly handle the Promise without making the parent function async.

Applied to files:

  • src/components/Editor/index.tsx
📚 Learning: 2025-03-03T18:10:02.451Z
Learnt from: Henry8192
PR: y-scope/yscope-log-viewer#196
File: src/components/CentralContainer/Sidebar/SidebarTabs/SearchTabPanel/QueryInputBox.tsx:55-58
Timestamp: 2025-03-03T18:10:02.451Z
Learning: In the y-scope/yscope-log-viewer repository, the team prefers using the `!` operator to flip boolean values (e.g., `!isRegex`) rather than the pattern `false == <expression>` that's mentioned in the coding guidelines.

Applied to files:

  • src/stores/viewStore/createViewFormattingSlice.ts
📚 Learning: 2025-06-01T13:41:12.938Z
Learnt from: zzxthehappiest
PR: y-scope/yscope-log-viewer#286
File: src/components/CentralContainer/Sidebar/SidebarTabs/SearchTabPanel/QueryInputBox.tsx:37-40
Timestamp: 2025-06-01T13:41:12.938Z
Learning: The `updateWindowUrlHashParams` function in `src/utils/url.ts` doesn't throw errors, so error handling is not needed when calling this function.

Applied to files:

  • src/stores/viewStore/createViewFormattingSlice.ts
📚 Learning: 2025-07-15T16:29:02.609Z
Learnt from: Henry8192
PR: y-scope/yscope-log-viewer#152
File: src/components/AppController.tsx:42-42
Timestamp: 2025-07-15T16:29:02.609Z
Learning: In the y-scope/yscope-log-viewer repository, the team never uses `==` for comparisons, preferring strict equality (`===`) instead. This overrides the coding guidelines that suggest using `false == <expression>` rather than `!<expression>`.

Applied to files:

  • src/stores/viewStore/createViewFormattingSlice.ts
📚 Learning: 2025-04-28T08:21:28.568Z
Learnt from: junhaoliao
PR: y-scope/yscope-log-viewer#224
File: src/contexts/states/logFileStore/loadSlice.ts:1-1
Timestamp: 2025-04-28T08:21:28.568Z
Learning: When importing from npm packages, use the public API entrypoint (e.g., `import {StateCreator} from "zustand"`) rather than deep-linking into package internals (e.g., `import {StateCreator} from "zustand/index"`), as internal file structures may change between package versions.

Applied to files:

  • src/stores/viewStore/createViewFormattingSlice.ts
📚 Learning: 2025-06-01T13:40:12.222Z
Learnt from: zzxthehappiest
PR: y-scope/yscope-log-viewer#286
File: src/components/Editor/index.tsx:138-139
Timestamp: 2025-06-01T13:40:12.222Z
Learning: In the yscope-log-viewer codebase, when using Zustand stores in React components, the preferred pattern is to use `getState()` for static setters that never change (like `setLogEventNum`) to avoid unnecessary subscriptions, while using hooks for actions that do more than just setting values. All store state variables should be declared at the beginning of the component for consistency and clear dependency overview.

Applied to files:

  • src/stores/viewStore/createViewFormattingSlice.ts
🧬 Code graph analysis (3)
src/components/Editor/index.tsx (2)
src/stores/viewStore/createViewFormattingSlice.ts (1)
  • togglePrettify (61-61)
src/stores/notificationStore.ts (1)
  • handleErrorWithNotification (76-76)
src/stores/viewStore/createViewFormattingSlice.ts (6)
src/utils/url/index.ts (1)
  • updateWindowUrlHashParams (389-389)
src/typings/url.ts (1)
  • HASH_PARAM_NAMES (41-41)
src/services/LogFileManager/index.ts (1)
  • setIsPrettified (200-202)
src/typings/worker.ts (1)
  • CURSOR_CODE (101-101)
src/utils/url/urlHash.ts (1)
  • updateViewHashParams (158-158)
src/stores/notificationStore.ts (1)
  • handleErrorWithNotification (76-76)
src/components/StatusBar/index.tsx (2)
src/stores/viewStore/createViewFormattingSlice.ts (1)
  • togglePrettify (61-61)
src/stores/notificationStore.ts (1)
  • handleErrorWithNotification (76-76)
🔇 Additional comments (4)
src/components/Editor/index.tsx (1)

13-16: Imports wired correctly.

Centralizing error handling and prettify toggle via store is the right direction.

src/components/StatusBar/index.tsx (2)

1-1: Imports look good and are minimally scoped.

Nice cleanup.

Also applies to: 15-15, 18-18, 22-22


92-92: Hook-up is correct.

onClick now routes through the shared helper with unified error handling.

src/stores/viewStore/createViewFormattingSlice.ts (1)

3-9: New deps are appropriate.

Public entrypoints and typings are used correctly.

@Henry8192
Copy link
Contributor

Henry8192 commented Sep 7, 2025

On my end the shortcut is Alt + F and it seems to work for me

I just saw the key bindings of toggle isPrettified in utils/actions.ts is [monaco.KeyMod.Alt | monaco.KeyCode.Shift | monaco.KeyCode.KeyF] and that doesn't work

@junhaoliao
Copy link
Member Author

junhaoliao commented Sep 7, 2025

On my end the shortcut is Shift + F and it seems to work for me

I just saw the key bindings of toggle isPrettified in utils/actions.ts is [monaco.KeyMod.Alt | monaco.KeyCode.Shift | monaco.KeyCode.KeyF] and that doesn't work

i guess we can file a separate issue. it should be KeyMod.Shift instead of KeyCode.Shift i believe

@coderabbitai file the issue

Copy link

coderabbitai bot commented Sep 7, 2025

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

I'll help you file an issue for the keyboard shortcut bug. Let me first examine the current implementation and then create the issue.

@junhaoliao I've created a GitHub issue for the keyboard shortcut bug. The issue documents the problem with using monaco.KeyCode.Shift instead of monaco.KeyMod.Shift in the key binding configuration, and includes the technical details and context from your discussion with @Henry8192.

The issue has been assigned to you and includes references to this PR and the specific comment thread where the bug was discovered.


🏁 Script executed:

#!/bin/bash
# Find and examine the actions.ts file to understand the current keyboard shortcut implementation
fd -n "actions.ts" --type f

Length of output: 230


🏁 Script executed:

#!/bin/bash
# Examine the keyboard shortcut implementation in utils/actions.ts
cat src/utils/actions.ts

Length of output: 3193


🏁 Script executed:

#!/bin/bash
# Create a GitHub issue for the keyboard shortcut bug
gh issue create \
  --title "fix: Toggle prettify keyboard shortcut (Alt+Shift+F) doesn't work due to incorrect Monaco key binding" \
  --body "## Description

The keyboard shortcut for toggling prettify (Alt+Shift+F) is not working due to incorrect Monaco Editor key binding configuration.

## Current Implementation

In \`src/utils/actions.ts\`, the key binding is currently defined as:
\`\`\`typescript
keybindings: [monaco.KeyMod.Alt | monaco.KeyCode.Shift | monaco.KeyCode.KeyF]
\`\`\`

## Issue

The problem is using \`monaco.KeyCode.Shift\` instead of \`monaco.KeyMod.Shift\`. According to Monaco Editor's API, modifier keys should use \`KeyMod\` while regular keys should use \`KeyCode\`.

## Expected Fix

The key binding should be:
\`\`\`typescript
keybindings: [monaco.KeyMod.Alt | monaco.KeyMod.Shift | monaco.KeyCode.KeyF]
\`\`\`

## Context

This issue was discovered during testing of PR #380 which fixes the prettify toggle functionality. The UI toggle and F1 command palette action work correctly, but the direct keyboard shortcut does not.

## References

- Related PR: https://github.com/y-scope/yscope-log-viewer/pull/380
- Original discussion: https://github.com/y-scope/yscope-log-viewer/pull/380#issuecomment-2328916234

Reported by: @Henry8192
Analysis by: @junhaoliao" \
  --assignee junhaoliao

Length of output: 55


@junhaoliao Perfect! I've successfully created GitHub issue #386 for the keyboard shortcut bug.

Issue Details:

The issue documents the problem where monaco.KeyCode.Shift should be monaco.KeyMod.Shift in the key binding configuration for the TOGGLE_PRETTIFY action. I've included the current implementation, the expected fix, and references to this PR discussion for context.

The issue is now ready for you to address in a future PR, separate from the current prettify toggle functionality fix in PR #380.

Copy link

@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

♻️ Duplicate comments (1)
src/components/StatusBar/index.tsx (1)

73-86: Guard against rapid re-clicks; disable while in-flight

Double taps from StatusBar + Editor can race. Ensure the store’s togglePrettify is re-entrancy guarded and, if an in-flight flag exists, OR it into disabled here.

Run to verify a guard exists:

#!/bin/bash
rg -nC2 -g 'src/**' -P '(togglePrettify|in[Ff]light|toggling).*' src/stores/viewStore
📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 363f081 and 71c0456.

📒 Files selected for processing (1)
  • src/components/StatusBar/index.tsx (2 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{cpp,hpp,java,js,jsx,tpp,ts,tsx}

⚙️ CodeRabbit configuration file

  • Prefer false == <expression> rather than !<expression>.

Files:

  • src/components/StatusBar/index.tsx
🧬 Code graph analysis (1)
src/components/StatusBar/index.tsx (1)
src/stores/viewStore/createViewFormattingSlice.ts (1)
  • togglePrettify (42-42)
🔇 Additional comments (2)
src/components/StatusBar/index.tsx (2)

15-15: Centralized toggle import — LGTM

Correct import path for the shared store action; aligns with the PR objective to centralize the prettify toggle.


19-19: Permalink helper import — LGTM

Import remains correct and matches the usage below.

Copy link

@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

📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3603252 and e5c6b42.

📒 Files selected for processing (1)
  • docs/src/dev-guide/contributing-validation.md (1 hunks)

@Henry8192 Henry8192 self-requested a review September 10, 2025 18:13
Copy link
Contributor

@Henry8192 Henry8192 left a comment

Choose a reason for hiding this comment

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

LGTM.

@junhaoliao junhaoliao merged commit 04ef695 into y-scope:main Sep 16, 2025
5 checks passed
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