-
Notifications
You must be signed in to change notification settings - Fork 528
feat: add sheet panel persistency #3951
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
feat: add sheet panel persistency #3951
Conversation
|
Note Other AI code review bot(s) detectedCodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review. WalkthroughThe PR makes BottomSheet placement persistent and controlled: adds exported getStoredPlacement() to read/validate Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes
Files/areas needing extra attention:
Possibly related PRs
Suggested reviewers
Pre-merge checks and finishing touches✅ Passed checks (3 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (7)
app/src/features/apiClient/screens/apiClient/components/views/graphql/GraphQLClientView.tsx (1)
506-511: Use the localStorage wrapper and extract the storage key constant.The code directly accesses
window.localStorageinstead of using the existing wrapper atapp/src/utils/localStorage.ts. Additionally, the storage key"sheet_placement"is a magic string duplicated across multiple files.Consider these improvements:
- Use the localStorage wrapper for consistency with the codebase (it handles JSON serialization and key namespacing via
getStorageKey)- Extract the storage key to a shared constant (e.g., in
app/src/componentsV2/BottomSheet/constants.tsor the context file)- Add error handling since localStorage can throw in incognito mode or when quota is exceeded
+import { localStorage as localStorageWrapper } from "utils/localStorage"; + useLayoutEffect(() => { if (isDefaultPlacementRef.current) { return; } - const savedPlacement = localStorage.getItem("sheet_placement"); + try { + const savedPlacement = localStorageWrapper.getItem("sheet_placement"); - if (!savedPlacement) { + if (!savedPlacement) { isDefaultPlacementRef.current = true; const bottomSheetPlacement = window.innerWidth <= 1280 ? BottomSheetPlacement.BOTTOM : BottomSheetPlacement.RIGHT; toggleSheetPlacement(bottomSheetPlacement); + } + } catch (error) { + // Fallback to default behavior if localStorage is unavailable + isDefaultPlacementRef.current = true; + const bottomSheetPlacement = window.innerWidth <= 1280 ? BottomSheetPlacement.BOTTOM : BottomSheetPlacement.RIGHT; + toggleSheetPlacement(bottomSheetPlacement); } }, [toggleSheetPlacement]);app/src/features/apiClient/screens/apiClient/components/views/http/HttpClientView.tsx (1)
259-264: Use the localStorage wrapper and verify breakpoint consistency.Similar to GraphQLClientView, this code directly accesses
window.localStorageinstead of the wrapper, and uses a magic string for the storage key.Additionally, this view uses a 1440px breakpoint while GraphQLClientView uses 1280px. This inconsistency may be intentional (different layouts), but should be verified.
Apply similar improvements as suggested for GraphQLClientView:
+import { localStorage as localStorageWrapper } from "utils/localStorage"; + useLayoutEffect(() => { if (isDefaultPlacementRef.current) { return; } - const savedPlacement = localStorage.getItem("sheet_placement"); + try { + const savedPlacement = localStorageWrapper.getItem("sheet_placement"); - if (!savedPlacement) { + if (!savedPlacement) { isDefaultPlacementRef.current = true; const bottomSheetPlacement = window.innerWidth < 1440 ? BottomSheetPlacement.BOTTOM : BottomSheetPlacement.RIGHT; toggleSheetPlacement(bottomSheetPlacement); + } + } catch (error) { + isDefaultPlacementRef.current = true; + const bottomSheetPlacement = window.innerWidth < 1440 ? BottomSheetPlacement.BOTTOM : BottomSheetPlacement.RIGHT; + toggleSheetPlacement(bottomSheetPlacement); } }, [toggleSheetPlacement]);Verification needed: Confirm whether the different breakpoints (1440px here vs 1280px in GraphQL) are intentional or should be aligned.
app/src/componentsV2/BottomSheet/context/index.tsx (4)
9-14: Use the localStorage wrapper for consistency.The
getStoredPlacementhelper directly accesseswindow.localStorage, while the codebase has a centralized wrapper atapp/src/utils/localStorage.tsthat handles JSON serialization and key namespacing.+import { localStorage as localStorageWrapper } from "utils/localStorage"; + const SHEET_PLACEMENT_STORAGE_KEY = "sheet_placement"; const getStoredPlacement = (): BottomSheetPlacement | null => { - const storedValue = localStorage.getItem(SHEET_PLACEMENT_STORAGE_KEY); + try { + const storedValue = localStorageWrapper.getItem(SHEET_PLACEMENT_STORAGE_KEY) as string | null; - return storedValue === BottomSheetPlacement.BOTTOM || storedValue === BottomSheetPlacement.RIGHT ? storedValue : null; + return storedValue === BottomSheetPlacement.BOTTOM || storedValue === BottomSheetPlacement.RIGHT ? storedValue : null; + } catch (error) { + return null; + } };
41-44: Add error handling for localStorage operations.The
persistPlacementfunction could throw if localStorage is unavailable (incognito mode) or quota is exceeded. Consider adding error handling to gracefully degrade.+import { localStorage as localStorageWrapper } from "utils/localStorage"; + const persistPlacement = (placement: BottomSheetPlacement) => { setSheetPlacement(placement); - localStorage.setItem(SHEET_PLACEMENT_STORAGE_KEY, placement); + try { + localStorageWrapper.setItem(SHEET_PLACEMENT_STORAGE_KEY, placement); + } catch (error) { + // Silently fail if localStorage is unavailable + console.warn("Failed to persist sheet placement:", error); + } };
46-52: Consider removing the redundant synchronization effect.This effect syncs
sheetPlacementwith stored/default values on mount and when dependencies change. However, since the state is already initialized with the correct value (lines 36-39), this effect appears redundant.Additionally, including
sheetPlacementin the dependency array could cause unnecessary re-renders or logic conflicts when the user toggles placement.If the intent is to handle external changes to
defaultPlacement(e.g., from props), consider:
- Removing this effect entirely if
defaultPlacementis static- Or, if dynamic, remove
sheetPlacementfrom deps and only react todefaultPlacementchanges:useEffect(() => { const storedPlacement = getStoredPlacement(); - const nextPlacement = storedPlacement ?? defaultPlacement; - if (sheetPlacement !== nextPlacement) { - setSheetPlacement(nextPlacement); - } - }, [defaultPlacement, sheetPlacement]); + if (!storedPlacement) { + setSheetPlacement(defaultPlacement); + } +}, [defaultPlacement]);
68-87: Use the localStorage wrapper consistently.The toggle logic directly calls
localStorage.setItem(line 77) instead of using the wrapper or thepersistPlacementhelper defined above.const toggleSheetPlacement = useCallback((placement?: BottomSheetPlacement) => { if (placement) { persistPlacement(placement); return; } setSheetPlacement((prev) => { const nextPlacement = prev === BottomSheetPlacement.BOTTOM ? BottomSheetPlacement.RIGHT : BottomSheetPlacement.BOTTOM; - localStorage.setItem(SHEET_PLACEMENT_STORAGE_KEY, nextPlacement); + try { + localStorageWrapper.setItem(SHEET_PLACEMENT_STORAGE_KEY, nextPlacement); + } catch (error) { + console.warn("Failed to persist sheet placement:", error); + } if (nextPlacement === BottomSheetPlacement.RIGHT) { trackViewBottomSheetOnRightClicked(); } else { trackViewBottomSheetOnBottomClicked(); } return nextPlacement; }); }, []);Alternatively, refactor to use
persistPlacementconsistently:const toggleSheetPlacement = useCallback((placement?: BottomSheetPlacement) => { if (placement) { persistPlacement(placement); return; } - setSheetPlacement((prev) => { + + setSheetPlacement((prev) => { const nextPlacement = prev === BottomSheetPlacement.BOTTOM ? BottomSheetPlacement.RIGHT : BottomSheetPlacement.BOTTOM; - - localStorage.setItem(SHEET_PLACEMENT_STORAGE_KEY, nextPlacement); - + + // Track analytics if (nextPlacement === BottomSheetPlacement.RIGHT) { trackViewBottomSheetOnRightClicked(); } else { trackViewBottomSheetOnBottomClicked(); } - + + // Persist after tracking + try { + localStorageWrapper.setItem(SHEET_PLACEMENT_STORAGE_KEY, nextPlacement); + } catch (error) { + console.warn("Failed to persist sheet placement:", error); + } + return nextPlacement; }); }, []);app/src/features/sessionBook/components/SessionViewerBottomSheet/SessionViewerBottomSheet.tsx (1)
31-34: Use the localStorage wrapper and add error handling.Similar to the other files, this code directly accesses
window.localStoragewith a magic string and no error handling.+import { localStorage as localStorageWrapper } from "utils/localStorage"; + useEffect(() => { - const savedPlacement = localStorage.getItem("sheet_placement"); + try { + const savedPlacement = localStorageWrapper.getItem("sheet_placement"); - if (bottomSheetBottomBreakpoint && location.pathname.includes(PATHS.SESSIONS.INDEX) && !savedPlacement) { + if (bottomSheetBottomBreakpoint && location.pathname.includes(PATHS.SESSIONS.INDEX) && !savedPlacement) { toggleSheetPlacement(BottomSheetPlacement.BOTTOM); + } + } catch (error) { + // Fallback: apply default behavior if localStorage fails + if (bottomSheetBottomBreakpoint && location.pathname.includes(PATHS.SESSIONS.INDEX)) { + toggleSheetPlacement(BottomSheetPlacement.BOTTOM); } + } }, [bottomSheetBottomBreakpoint, toggleSheetPlacement, location.pathname]);Additionally, consider extracting
"sheet_placement"to the shared constant defined in the BottomSheet context file.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
app/src/componentsV2/BottomSheet/context/index.tsx(3 hunks)app/src/features/apiClient/screens/apiClient/components/views/graphql/GraphQLClientView.tsx(1 hunks)app/src/features/apiClient/screens/apiClient/components/views/http/HttpClientView.tsx(1 hunks)app/src/features/sessionBook/components/SessionViewerBottomSheet/SessionViewerBottomSheet.tsx(1 hunks)
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-10-10T11:08:23.369Z
Learnt from: nafees87n
Repo: requestly/requestly PR: 3655
File: app/src/features/apiClient/screens/apiClient/components/views/components/Collection/components/CollectionRunnerView/components/RunResultView/RunResultContainer/RunResultContainer.tsx:426-426
Timestamp: 2025-10-10T11:08:23.369Z
Learning: In the file `app/src/features/apiClient/screens/apiClient/components/views/components/Collection/components/CollectionRunnerView/components/RunResultView/RunResultContainer/RunResultContainer.tsx`, the `destroyInactiveTabPane={true}` setting is intentional. The loss of state (expandedKeys, scroll position) when switching tabs is acceptable for now and will be addressed in future work.
Applied to files:
app/src/features/apiClient/screens/apiClient/components/views/graphql/GraphQLClientView.tsxapp/src/features/apiClient/screens/apiClient/components/views/http/HttpClientView.tsx
📚 Learning: 2025-10-22T22:57:45.959Z
Learnt from: mustafa-sayyed
Repo: requestly/requestly PR: 3723
File: app/src/features/apiClient/screens/apiClient/components/views/http/components/HttpRequestTabs/HttpRequestTabs.tsx:146-151
Timestamp: 2025-10-22T22:57:45.959Z
Learning: In the API Client Scripts tab (app/src/features/apiClient/screens/apiClient/components/views/http/components/HttpRequestTabs/HttpRequestTabs.tsx), the dot indicator should only appear when scripts are present (count > 0). When no scripts exist, the dot should not be rendered. This is the intended behavior per issue #3731.
Applied to files:
app/src/features/apiClient/screens/apiClient/components/views/http/HttpClientView.tsx
🧬 Code graph analysis (4)
app/src/features/apiClient/screens/apiClient/components/views/graphql/GraphQLClientView.tsx (2)
app/src/utils/localStorage.ts (1)
localStorage(6-22)app/src/componentsV2/BottomSheet/index.ts (1)
BottomSheetPlacement(1-1)
app/src/componentsV2/BottomSheet/context/index.tsx (3)
app/src/componentsV2/BottomSheet/index.ts (1)
BottomSheetPlacement(1-1)app/src/utils/localStorage.ts (1)
localStorage(6-22)app/src/componentsV2/BottomSheet/analytics/index.ts (2)
trackViewBottomSheetOnRightClicked(8-10)trackViewBottomSheetOnBottomClicked(12-14)
app/src/features/sessionBook/components/SessionViewerBottomSheet/SessionViewerBottomSheet.tsx (2)
app/src/utils/localStorage.ts (1)
localStorage(6-22)app/src/config/constants/sub/paths.js (1)
PATHS(15-15)
app/src/features/apiClient/screens/apiClient/components/views/http/HttpClientView.tsx (2)
app/src/utils/localStorage.ts (1)
localStorage(6-22)app/src/componentsV2/BottomSheet/index.ts (1)
BottomSheetPlacement(1-1)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Agent
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR adds persistence for the bottom sheet placement using browser localStorage, allowing users' preferred sheet position (bottom or right) to be preserved across sessions.
- Implemented localStorage-based persistence in the BottomSheet context provider
- Updated HttpClientView and GraphQLClientView to respect saved placement preferences
- Modified SessionViewerBottomSheet to check for saved placement before applying default positioning
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 6 comments.
| File | Description |
|---|---|
| app/src/componentsV2/BottomSheet/context/index.tsx | Added storage key constant, getStoredPlacement helper, and persistence logic in state initialization and toggleSheetPlacement function |
| app/src/features/apiClient/screens/apiClient/components/views/http/HttpClientView.tsx | Modified default placement logic to skip if saved placement exists in localStorage |
| app/src/features/apiClient/screens/apiClient/components/views/graphql/GraphQLClientView.tsx | Modified default placement logic to skip if saved placement exists in localStorage |
| app/src/features/sessionBook/components/SessionViewerBottomSheet/SessionViewerBottomSheet.tsx | Added check for saved placement to prevent overriding user preference on session view |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
app/src/features/apiClient/screens/apiClient/components/views/http/HttpClientView.tsx
Show resolved
Hide resolved
app/src/features/apiClient/screens/apiClient/components/views/graphql/GraphQLClientView.tsx
Show resolved
Hide resolved
app/src/features/sessionBook/components/SessionViewerBottomSheet/SessionViewerBottomSheet.tsx
Show resolved
Hide resolved
app/src/features/apiClient/screens/apiClient/components/views/http/HttpClientView.tsx
Outdated
Show resolved
Hide resolved
app/src/features/apiClient/screens/apiClient/components/views/graphql/GraphQLClientView.tsx
Outdated
Show resolved
Hide resolved
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
…uestly into add-sheet-persistency
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🧹 Nitpick comments (2)
app/src/componentsV2/BottomSheet/context/index.tsx (2)
44-47: Consider wrappingpersistPlacementinuseCallback.While not causing issues currently (since it's only called from the already-memoized
toggleSheetPlacement), wrappingpersistPlacementinuseCallbackwould be more consistent and future-proof.Apply this diff:
- const persistPlacement = (placement: BottomSheetPlacement) => { + const persistPlacement = useCallback((placement: BottomSheetPlacement) => { setSheetPlacement(placement); localStorage.setItem("sheet_placement", placement); - }; + }, [setSheetPlacement]);
9-12: Optional: Consider a custom hook to reduce duplication.The pattern of initializing placement state from storage is repeated across 6+ components:
const [sheetPlacement, setSheetPlacement] = useState(() => { const savedPlacement = getStoredPlacement(); return savedPlacement ?? BottomSheetPlacement.RIGHT; });You could extract this into a custom hook:
export const usePersistedSheetPlacement = (defaultPlacement: BottomSheetPlacement) => { return useState(() => getStoredPlacement() ?? defaultPlacement); };Then consumers would use:
const [sheetPlacement, setSheetPlacement] = usePersistedSheetPlacement(BottomSheetPlacement.RIGHT);Also applies to: 26-32, 36-41, 44-47, 63-82
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (7)
app/src/components/features/mocksV2/MockEditorIndex/Editor/index.tsx(3 hunks)app/src/componentsV2/BottomSheet/context/index.tsx(3 hunks)app/src/features/apiClient/components/common/APIClient/APIClient.tsx(4 hunks)app/src/features/apiClient/screens/apiClient/clientView/ApiClientViewManager.tsx(4 hunks)app/src/features/apiClient/screens/apiClient/clientView/GenericApiClient.tsx(2 hunks)app/src/features/sessionBook/screens/DraftSessionScreen/components/DraftSessionDetailsPanel/DraftSessionDetailsPanel.tsx(3 hunks)app/src/features/sessionBook/screens/SavedSessionScreen/components/SavedSessionViewer/SavedSessionViewer.tsx(2 hunks)
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-10-10T11:08:23.369Z
Learnt from: nafees87n
Repo: requestly/requestly PR: 3655
File: app/src/features/apiClient/screens/apiClient/components/views/components/Collection/components/CollectionRunnerView/components/RunResultView/RunResultContainer/RunResultContainer.tsx:426-426
Timestamp: 2025-10-10T11:08:23.369Z
Learning: In the file `app/src/features/apiClient/screens/apiClient/components/views/components/Collection/components/CollectionRunnerView/components/RunResultView/RunResultContainer/RunResultContainer.tsx`, the `destroyInactiveTabPane={true}` setting is intentional. The loss of state (expandedKeys, scroll position) when switching tabs is acceptable for now and will be addressed in future work.
Applied to files:
app/src/features/apiClient/screens/apiClient/clientView/ApiClientViewManager.tsx
📚 Learning: 2025-08-20T11:23:01.896Z
Learnt from: nafees87n
Repo: requestly/requestly PR: 3417
File: app/src/hooks/workspaceFetcher/useWorkspaceFetcher.ts:4-7
Timestamp: 2025-08-20T11:23:01.896Z
Learning: In useFetchTeamWorkspaces hook, activeWorkspaceId should not be included in the effect dependency array to avoid re-subscription on every workspace change, as per user's preference.
Applied to files:
app/src/componentsV2/BottomSheet/context/index.tsx
🧬 Code graph analysis (5)
app/src/features/apiClient/screens/apiClient/clientView/GenericApiClient.tsx (2)
app/src/componentsV2/BottomSheet/context/index.tsx (2)
getStoredPlacement(9-12)BottomSheetProvider(36-96)app/src/componentsV2/BottomSheet/index.ts (1)
BottomSheetPlacement(1-1)
app/src/features/apiClient/screens/apiClient/clientView/ApiClientViewManager.tsx (1)
app/src/componentsV2/BottomSheet/context/index.tsx (2)
getStoredPlacement(9-12)BottomSheetProvider(36-96)
app/src/components/features/mocksV2/MockEditorIndex/Editor/index.tsx (1)
app/src/componentsV2/BottomSheet/context/index.tsx (2)
getStoredPlacement(9-12)BottomSheetProvider(36-96)
app/src/features/apiClient/components/common/APIClient/APIClient.tsx (1)
app/src/componentsV2/BottomSheet/context/index.tsx (2)
getStoredPlacement(9-12)BottomSheetProvider(36-96)
app/src/componentsV2/BottomSheet/context/index.tsx (2)
app/src/utils/localStorage.ts (1)
localStorage(6-22)app/src/componentsV2/BottomSheet/analytics/index.ts (2)
trackViewBottomSheetOnRightClicked(8-10)trackViewBottomSheetOnBottomClicked(12-14)
🔇 Additional comments (8)
app/src/components/features/mocksV2/MockEditorIndex/Editor/index.tsx (1)
35-35: LGTM! Sheet placement persistence implemented correctly.The implementation properly initializes placement from storage with a lazy initializer and passes controlled state to the provider.
Also applies to: 95-98, 460-460
app/src/features/apiClient/screens/apiClient/clientView/GenericApiClient.tsx (1)
1-1: LGTM! Consistent implementation.The pattern matches other consumer components correctly.
Also applies to: 3-3, 19-22, 24-28
app/src/features/apiClient/screens/apiClient/clientView/ApiClientViewManager.tsx (1)
1-1: LGTM! Consistent implementation.The pattern is correctly applied.
Also applies to: 10-10, 33-36, 56-60
app/src/features/apiClient/components/common/APIClient/APIClient.tsx (1)
2-2: LGTM! Correct implementation with context-appropriate default.The use of
BottomSheetPlacement.BOTTOMas the default for the modal context appears intentional and appropriate.Also applies to: 22-22, 123-126, 144-144
app/src/features/sessionBook/screens/SavedSessionScreen/components/SavedSessionViewer/SavedSessionViewer.tsx (1)
32-32: LGTM! Consistent implementation.The persistence pattern is correctly applied.
Also applies to: 110-113, 117-117
app/src/features/sessionBook/screens/DraftSessionScreen/components/DraftSessionDetailsPanel/DraftSessionDetailsPanel.tsx (1)
1-1: LGTM! Correct implementation with appropriate default.The use of
BottomSheetPlacement.BOTTOMas the default appears appropriate for this context.Also applies to: 14-14, 47-50, 53-53
app/src/componentsV2/BottomSheet/context/index.tsx (2)
9-12: LGTM! Clean helper function.The validation logic correctly ensures only valid placements are returned from storage.
63-82: LGTM! Correct functional state update with persistence.The refactored
toggleSheetPlacementcorrectly:
- Uses functional state updates to compute the next placement
- Persists to localStorage
- Triggers analytics after computing the new value
- Returns the new placement to update state
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🧹 Nitpick comments (1)
app/src/componentsV2/BottomSheet/context/index.tsx (1)
9-12: Consider using the shared localStorage helper and guarding for non-DOM environments.
getStoredPlacementandpersistPlacementaccess the globallocalStoragedirectly; this is fine in the browser, but it bypasses the existingapp/src/utils/localStoragehelper (which centralizes key prefixing/JSON handling) and will throw if this code ever runs wherewindow.localStorageis unavailable (SSR, some tests). If you expect this context to ever be used outside a pure browser runtime, consider either:
- Switching to the shared
localStoragehelper, or- Adding a small guard (e.g.
if (typeof window === "undefined" || !window.localStorage) return null;) insidegetStoredPlacement/persistPlacement.Also applies to: 43-46
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
app/src/componentsV2/BottomSheet/context/index.tsx(3 hunks)app/src/features/apiClient/screens/apiClient/clientView/GenericApiClient.tsx(2 hunks)app/src/features/apiClient/screens/apiClient/components/views/http/HttpClientView.tsx(1 hunks)app/src/views/features/rules/RuleEditor/RuleEditorView.js(2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- app/src/features/apiClient/screens/apiClient/clientView/GenericApiClient.tsx
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-08-20T11:23:01.896Z
Learnt from: nafees87n
Repo: requestly/requestly PR: 3417
File: app/src/hooks/workspaceFetcher/useWorkspaceFetcher.ts:4-7
Timestamp: 2025-08-20T11:23:01.896Z
Learning: In useFetchTeamWorkspaces hook, activeWorkspaceId should not be included in the effect dependency array to avoid re-subscription on every workspace change, as per user's preference.
Applied to files:
app/src/componentsV2/BottomSheet/context/index.tsx
🧬 Code graph analysis (3)
app/src/views/features/rules/RuleEditor/RuleEditorView.js (2)
app/src/componentsV2/BottomSheet/context/index.tsx (2)
getStoredPlacement(9-12)BottomSheetProvider(35-95)app/src/componentsV2/BottomSheet/index.ts (2)
BottomSheetPlacement(1-1)BottomSheetProvider(3-3)
app/src/features/apiClient/screens/apiClient/components/views/http/HttpClientView.tsx (2)
app/src/utils/localStorage.ts (1)
localStorage(6-22)app/src/componentsV2/BottomSheet/index.ts (1)
BottomSheetPlacement(1-1)
app/src/componentsV2/BottomSheet/context/index.tsx (3)
app/src/componentsV2/BottomSheet/index.ts (2)
BottomSheetPlacement(1-1)BottomSheetProvider(3-3)app/src/utils/localStorage.ts (1)
localStorage(6-22)app/src/componentsV2/BottomSheet/analytics/index.ts (2)
trackViewBottomSheetOnRightClicked(8-10)trackViewBottomSheetOnBottomClicked(12-14)
🔇 Additional comments (2)
app/src/views/features/rules/RuleEditor/RuleEditorView.js (1)
9-17: LGTM on controlled placement + persistence wiring.Using a lazy
useStateinitializer withgetStoredPlacement()and falling back toBottomSheetPlacement.BOTTOM, then passingsheetPlacement/setSheetPlacementintoBottomSheetProvider, cleanly aligns this view with the new controlled + persistent bottom sheet API.Also applies to: 29-31
app/src/componentsV2/BottomSheet/context/index.tsx (1)
62-81: Clarify analytics behavior for explicit placement and tightenuseCallbackdependencies.Two small points here:
When
toggleSheetPlacementis called with an explicitplacement, it persists state but does not fire any analytics, whereas the no-arg toggle path does. If any user-facing UI calls this with an explicit placement (e.g., "always show on right"), you may want to track those interactions as well, or clearly reserve the param form for non-analytic flows (programmatic sync/initialization).The
useCallbackcurrently has an empty dependency array but closes oversetSheetPlacement(from props) andpersistPlacement. This is likely to tripreact-hooks/exhaustive-depsand could capture a stale setter if a non-useStateimplementation is ever passed in. Verify the actual dependency sources and add appropriate dependencies if needed.
app/src/features/apiClient/screens/apiClient/components/views/http/HttpClientView.tsx
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (2)
app/src/componentsV2/BottomSheet/context/index.tsx (2)
9-12: Consider using the shared localStorage wrapper for consistency
getStoredPlacementandpersistPlacementcurrently call the globallocalStoragedirectly with the raw"sheet_placement"key and plain string values. Given you already have a namespaced, JSON-aware storage helper inapp/src/utils/localStorage.ts, it may be worth routing these reads/writes through that utility for consistency (and to avoid key collisions), updating both the setter andgetStoredPlacementaccordingly. If this helper is also used in non-DOM contexts, wrapping access in a small try/catch or environment check would makegetStoredPlacementsafer to reuse elsewhere.Also applies to: 42-45
62-81: TightenuseCallbackdependencies or simplify toggle logic
toggleSheetPlacementis wrapped inuseCallbackwith an empty dependency array while closing overpersistPlacementandsetSheetPlacement. Because the setter is stable and the logic is side‑effectful but simple, you could either:
- Add the appropriate dependencies (e.g.,
persistPlacement) to satisfy hook expectations, or- Drop
useCallbackentirely and let React recreate this function per render, which is usually fine for a small context like this.Functionality is correct as written; this is just about hook hygiene and future‑proofing.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (5)
app/src/componentsV2/BottomSheet/context/index.tsx(3 hunks)app/src/features/apiClient/components/common/APIClient/APIClient.tsx(4 hunks)app/src/features/apiClient/screens/apiClient/components/views/graphql/GraphQLClientView.tsx(2 hunks)app/src/features/apiClient/screens/apiClient/components/views/http/HttpClientView.tsx(2 hunks)app/src/features/sessionBook/screens/SavedSessionScreen/components/SavedSessionViewer/SavedSessionViewer.tsx(2 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
- app/src/features/apiClient/screens/apiClient/components/views/http/HttpClientView.tsx
- app/src/features/sessionBook/screens/SavedSessionScreen/components/SavedSessionViewer/SavedSessionViewer.tsx
- app/src/features/apiClient/screens/apiClient/components/views/graphql/GraphQLClientView.tsx
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-08-20T11:23:01.896Z
Learnt from: nafees87n
Repo: requestly/requestly PR: 3417
File: app/src/hooks/workspaceFetcher/useWorkspaceFetcher.ts:4-7
Timestamp: 2025-08-20T11:23:01.896Z
Learning: In useFetchTeamWorkspaces hook, activeWorkspaceId should not be included in the effect dependency array to avoid re-subscription on every workspace change, as per user's preference.
Applied to files:
app/src/componentsV2/BottomSheet/context/index.tsx
📚 Learning: 2025-12-11T06:43:01.328Z
Learnt from: rohanmathur91
Repo: requestly/requestly PR: 4000
File: app/src/features/apiClient/slices/multiWorkspaceView/helpers/ApiClientContextRegistry/hooks.ts:6-14
Timestamp: 2025-12-11T06:43:01.328Z
Learning: In app/src/features/apiClient/slices/multiWorkspaceView/helpers/ApiClientContextRegistry/hooks.ts, the useApiClientFeatureContext hook uses useMemo without reactivity intentionally. Contexts are expected to be registered before component mount, and reactivity to registry updates is not needed.
Applied to files:
app/src/features/apiClient/components/common/APIClient/APIClient.tsx
🧬 Code graph analysis (2)
app/src/componentsV2/BottomSheet/context/index.tsx (3)
app/src/componentsV2/BottomSheet/index.ts (1)
BottomSheetPlacement(1-1)app/src/utils/localStorage.ts (1)
localStorage(6-22)app/src/componentsV2/BottomSheet/analytics/index.ts (2)
trackViewBottomSheetOnRightClicked(8-10)trackViewBottomSheetOnBottomClicked(12-14)
app/src/features/apiClient/components/common/APIClient/APIClient.tsx (3)
app/src/views/features/rules/RuleEditor/RuleEditorView.js (1)
sheetPlacement(14-17)app/src/componentsV2/BottomSheet/context/index.tsx (2)
getStoredPlacement(9-12)BottomSheetProvider(34-95)app/src/componentsV2/BottomSheet/index.ts (1)
BottomSheetPlacement(1-1)
🔇 Additional comments (1)
app/src/features/apiClient/components/common/APIClient/APIClient.tsx (1)
2-2: Controlled sheet placement wiring in APIClientModal looks correctUsing a lazy
useStateinitializer withgetStoredPlacement()and passing[sheetPlacement, setSheetPlacement]through toBottomSheetProvidermatches the new controlled BottomSheet API and persistence model. The initialization fallback toBottomSheetPlacement.BOTTOMis consistent with other call sites, and the provider props are correctly updated.Also applies to: 22-22, 123-127, 144-156
Closes issue: #3859
📜 Summary of changes:
🎥 Demo Video:
Screen.Recording.2025-12-03.170318.mp4
✅ Checklist:
🧪 Test instructions:
Summary by CodeRabbit
Bug Fixes
New Features
Chores / Public API
✏️ Tip: You can customize this high-level summary in your review settings.