Performance fixes#98
Conversation
- Updated useEffect to refetch selection and connected-nodes data when returning to the Index page, ensuring changes made elsewhere are reflected. - Modified queryClient.invalidateQueries in useSetNodesDataMutation to mark connected-nodes data as stale without immediate refetch, preventing UI freezes during typing.
- Changed connectNodes and handleConnectOnly functions to use async/await for better handling of asynchronous operations. - Ensured local Figma node data is updated before navigating away from the Push view to prevent stale data issues.
…eval - Simplified visibility checks in shouldIncludeNode function to enhance performance. - Updated findTextNodes to skip hidden subtrees early, reducing unnecessary parent checks. - Adjusted handleConnect to utilize new key translation fetching logic, improving data handling during connection.
…ndling - Registered clearPrefilledKeysEndpoint in main.ts to manage prefilled key states. - Updated usePrefilledKey hook to allow dynamic enabling of queries based on the new parameter. - Enhanced StringsSection to clear prefilled keys when the prefill toggle is disabled, ensuring data consistency.
- Implemented a test to ensure screenshot entries are deduplicated when multiple nodes share the same key in the Push component. - Added a regression test to verify no changes are shown when re-opening Push immediately after a successful push. - Created tests to confirm that prefilled keys are cleared for unconnected nodes when the prefill toggle is disabled, while preserving keys for connected nodes.
WalkthroughThis PR adds an endpoint to clear non-connected prefilled keys, refactors text-node discovery, deduplicates screenshots per (key,namespace) in push payloads, fetches per-key metadata during connect, converts push/connect flows to async mutations, updates settings UI to clear persisted prefilled keys, and adds E2E tests plus updated web mocks. ChangesPrefilled Key Lifecycle & Connect Flow Redesign
Sequence DiagramsequenceDiagram
participant User
participant UI as Connect UI
participant API as API Layer
participant DB as Node Data
participant Mutation as setNodesDataMutation
User->>UI: Select key to connect
UI->>API: Fetch per-key translation metadata
API-->>UI: Return isPlural, pluralParamValue, translation
UI->>UI: Resolve translation (metadata > provided > default)
User->>UI: Confirm connect
UI->>Mutation: Mutate with translation, isPlural, pluralParamValue
Mutation->>DB: Update node plugin data
DB-->>Mutation: Success
Mutation->>API: Invalidate getConnectedNodes query
API-->>UI: Query refreshed
UI->>UI: Navigate to Index
sequenceDiagram
participant User
participant Settings as Settings UI
participant QueryClient as React Query
participant Endpoint as clearPrefilledKeysEndpoint
participant PluginData as Plugin Data Store
User->>Settings: Toggle prefill OFF
Settings->>Endpoint: Call clearPrefilledKeysEndpoint
Endpoint->>PluginData: Walk all nodes in document
PluginData->>Endpoint: Read TOLGEE_NODE_INFO for each node
Endpoint->>Endpoint: Filter non-connected nodes
Endpoint->>PluginData: Clear key field for unconnected nodes
Endpoint-->>Settings: Complete
Settings->>QueryClient: Invalidate getConnectedNodes & selection
QueryClient-->>Settings: Queries refetched
Settings->>UI: UI reflects cleared prefilled keys
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Suggested reviewers
🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Tip 💬 Introducing Slack Agent: The best way for teams to turn conversations into code.Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.
Built for teams:
One agent for your entire SDLC. Right inside Slack. 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. Comment |
There was a problem hiding this comment.
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/ui/hooks/usePrefilledKey.ts (1)
15-27:⚠️ Potential issue | 🟠 Major | ⚡ Quick winPrevent stale prefill values from persisting after prefill is disabled.
In react-query v3,
enabled: falsestops fetching but still exposes cacheddata. When users disable prefill, this hook continues returning the previously computed key, allowingListItemto re-seed itskeyNamestate (line 52–54) and immediately persist that stale value back to plugin data via mutation (lines 71–74), defeating the "disable and clear" flow.Fix by returning
undefinedforkeywhen the query is disabled:Suggested fix
export function usePrefilledKey( nodeId: string, keyFormat: string, variableCasing: TolgeeConfig["variableCasing"], enabled: boolean = true, nodeKey?: string, ) { + const queryEnabled = enabled && !!nodeId && !!keyFormat && !nodeKey; const result = useQuery<string, undefined, string>( [preformatKeyEndpoint.name, nodeId, keyFormat], async () => { if (!nodeId || !keyFormat) return ""; return preformatKeyEndpoint.call({ keyFormat, nodeId, variableCasing }); }, { - enabled: enabled && !!nodeId && !!keyFormat && !nodeKey, + enabled: queryEnabled, structuralSharing: false, }, ); - return { key: result.data, isLoading: result.isLoading }; + return { + key: queryEnabled ? result.data : undefined, + isLoading: queryEnabled && result.isLoading, + }; }🤖 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 `@src/ui/hooks/usePrefilledKey.ts` around lines 15 - 27, The hook usePrefilledKey returns cached result.data even when the react-query is disabled; change the return so that key is undefined whenever prefill is disabled (i.e., when enabled is false or the query conditions are unmet) instead of returning result.data. Locate usePrefilledKey and the query using preformatKeyEndpoint.call(...) and update the final return to only expose result.data when the query is actually enabled/successful (e.g., check enabled && result.isSuccess or similar) otherwise return key: undefined so stale prefill values cannot persist.
🧹 Nitpick comments (1)
src/ui/views/Settings/StringsSection.tsx (1)
169-169: 💤 Low valueType the event parameter consistently with the other handlers.
The other change handlers in this file use
TargetedEvent<HTMLInputElement, Event>; aligning here keeps the surface uniform and avoids theanyescape hatch.♻️ Proposed change
- const handlePrefillChange = async (e: any) => { - const checked = e.currentTarget.checked; + const handlePrefillChange = async ( + e: TargetedEvent<HTMLInputElement, Event>, + ) => { + const checked = e.currentTarget.checked;🤖 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 `@src/ui/views/Settings/StringsSection.tsx` at line 169, The event parameter of the handler handlePrefillChange is typed as any; update its signature to use the same type as other handlers (TargetedEvent<HTMLInputElement, Event>) to make the typing consistent and avoid the any escape hatch, and adjust any internal refs to e.target.value accordingly so the function compiles with the stricter type.
🤖 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.
Inline comments:
In `@src/ui/views/Connect/Connect.tsx`:
- Around line 162-167: The multi-line call to handleConnect (the invocation with
key.id, key.name, key.namespace, key.translation in Connect.tsx) is failing
Prettier/ESLint; reformat this call to match the project's Prettier rules
(collapse the arguments onto a single line or otherwise run the project's
formatter) so the prettier/prettier lint error is resolved—run the project's
formatter or IDE formatting on the handleConnect(...) call to produce the
expected single-line argument list.
In `@src/ui/views/Index/Index.tsx`:
- Around line 93-103: The useEffect currently triggers
selectionLoadable.refetch() and allNodes.refetch() on the initial mount when
route[0] === "index", causing a double-expensive fetch; fix by tracking initial
mount with a ref (import useRef from "preact/hooks") and only call
selectionLoadable.refetch() and allNodes.refetch() inside the useEffect when the
ref indicates this is not the first render (i.e., set a mounted ref after the
first render and skip the refetch when mountedRef.current is false).
---
Outside diff comments:
In `@src/ui/hooks/usePrefilledKey.ts`:
- Around line 15-27: The hook usePrefilledKey returns cached result.data even
when the react-query is disabled; change the return so that key is undefined
whenever prefill is disabled (i.e., when enabled is false or the query
conditions are unmet) instead of returning result.data. Locate usePrefilledKey
and the query using preformatKeyEndpoint.call(...) and update the final return
to only expose result.data when the query is actually enabled/successful (e.g.,
check enabled && result.isSuccess or similar) otherwise return key: undefined so
stale prefill values cannot persist.
---
Nitpick comments:
In `@src/ui/views/Settings/StringsSection.tsx`:
- Line 169: The event parameter of the handler handlePrefillChange is typed as
any; update its signature to use the same type as other handlers
(TargetedEvent<HTMLInputElement, Event>) to make the typing consistent and avoid
the any escape hatch, and adjust any internal refs to e.target.value accordingly
so the function compiles with the stricter type.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: c179c84a-117e-4c26-a23f-12e4d1828bae
📒 Files selected for processing (14)
cypress/e2e/push.cy.tscypress/e2e/settings.cy.tssrc/main/endpoints/clearPrefilledKeys.tssrc/main/main.tssrc/main/utils/nodeTools.tssrc/tools/getPushChanges.tssrc/ui/hooks/usePrefilledKey.tssrc/ui/hooks/useSetNodesDataMutation.tssrc/ui/views/Connect/Connect.tsxsrc/ui/views/Index/Index.tsxsrc/ui/views/Index/ListItem.tsxsrc/ui/views/Push/Push.tsxsrc/ui/views/Settings/StringsSection.tsxsrc/web/main.ts
- Removed unnecessary line breaks in Cypress tests for better readability. - Simplified the handleConnect function call in the Connect component. - Optimized the useMemo hook in ProjectSettings for branch names. - Added a mountedRef to prevent unnecessary effect execution in the Index component.
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 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.
Inline comments:
In `@src/ui/views/Connect/Connect.tsx`:
- Line 97: The assignment to the translation property currently uses a logical
OR which will replace intentionally empty strings; change the fallback to a
nullish coalescing so translation: resolvedTranslation ?? node.characters
(replace the OR usage where translation: resolvedTranslation || node.characters
is set) to preserve empty-string translations while still falling back when
resolvedTranslation is null or undefined.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 17e23db3-04e3-4b38-8548-77682e0f8269
📒 Files selected for processing (4)
cypress/e2e/settings.cy.tssrc/ui/views/Connect/Connect.tsxsrc/ui/views/Index/Index.tsxsrc/ui/views/Settings/ProjectSettings.tsx
🚧 Files skipped from review as they are similar to previous changes (2)
- cypress/e2e/settings.cy.ts
- src/ui/views/Index/Index.tsx
| { | ||
| ...node, | ||
| translation: translation || node.characters, | ||
| translation: resolvedTranslation || node.characters, |
There was a problem hiding this comment.
Use nullish fallback for translation to avoid overwriting valid empty strings.
At Line 97, resolvedTranslation || node.characters will replace "" with node.characters. If an empty translation is intentional, this silently changes user data. Use ?? instead.
Suggested fix
- translation: resolvedTranslation || node.characters,
+ translation: resolvedTranslation ?? node.characters,📝 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.
| translation: resolvedTranslation || node.characters, | |
| translation: resolvedTranslation ?? node.characters, |
🤖 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 `@src/ui/views/Connect/Connect.tsx` at line 97, The assignment to the
translation property currently uses a logical OR which will replace
intentionally empty strings; change the fallback to a nullish coalescing so
translation: resolvedTranslation ?? node.characters (replace the OR usage where
translation: resolvedTranslation || node.characters is set) to preserve
empty-string translations while still falling back when resolvedTranslation is
null or undefined.
Summary by CodeRabbit
New Features
Bug Fixes
Improvements
Tests