Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Conversation

@mustafa-sayyed
Copy link
Contributor

@mustafa-sayyed mustafa-sayyed commented Dec 3, 2025

Closes issue: #3859

📜 Summary of changes:

  • Added Sheet Panel Persistence using local storage
  • I have moved the setSheetPlacement state to the top components which makes it very easy to keep track and manage it

🎥 Demo Video:

Screen.Recording.2025-12-03.170318.mp4

✅ Checklist:

  • Make sure linting and unit tests pass.
  • No install/build warnings introduced.
  • Verified UI in browser.
  • For UI changes, added/updated analytics events (if applicable).
  • For changes in extension's code, manually tested in Chrome and Firefox.
  • Added/updated unit tests for this change.
  • Raised pull request to update corresponding documentation (if already exists).
  • Added demo video showing the changes in action (if applicable).

🧪 Test instructions:

  • Open API client
  • Toggle the Sheet Placement

Summary by CodeRabbit

  • Bug Fixes

    • Placement preference is now persisted and respected across screens; defaults apply only when no saved preference exists.
    • Analytics for placement changes now records the actual new placement after it’s computed.
  • New Features

    • Bottom sheet placement can be externally controlled, persisted, and restored to honor user preference across views.
  • Chores / Public API

    • One panel component’s public props were updated (an additional prop added).

✏️ Tip: You can customize this high-level summary in your review settings.

Copilot AI review requested due to automatic review settings December 3, 2025 11:38
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 3, 2025

Note

Other AI code review bot(s) detected

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

Walkthrough

The PR makes BottomSheet placement persistent and controlled: adds exported getStoredPlacement() to read/validate sheet_placement from localStorage, converts BottomSheetProvider to accept controlled props sheetPlacement and setSheetPlacement (dropping internal defaultPlacement usage), and adds an internal persistPlacement helper. toggleSheetPlacement now computes the next placement, persists it to localStorage, and fires analytics after determination. Multiple consumers were updated to initialize placement from storage and pass sheetPlacement/setSheetPlacement into the provider.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • Review BottomSheet context changes: getStoredPlacement, provider prop signature, persistPlacement, updated toggleSheetPlacement, and analytics ordering.
  • Verify consumer updates consistently replace defaultPlacement with controlled sheetPlacement/setSheetPlacement.
  • Check localStorage key handling and validation for sheet_placement.
  • Confirm call sites impacted by the DraftSessionDetailsPanel prop change were updated.

Files/areas needing extra attention:

  • app/src/componentsV2/BottomSheet/context/index.tsx
  • app/src/features/sessionBook/screens/DraftSessionScreen/components/DraftSessionDetailsPanel/DraftSessionDetailsPanel.tsx (signature change)
  • Representative consumer files updated to controlled provider usage (e.g., APIClient, GraphQLClientView, HttpClientView, MockEditorIndex, SessionViewerBottomSheet, RuleEditorView)

Possibly related PRs

Suggested reviewers

  • wrongsahil
  • rohanmathur91

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The PR title 'feat: add sheet panel persistency' clearly and concisely describes the main feature being added - persistence of the bottom sheet placement state using localStorage.
Description check ✅ Passed The PR description includes an issue reference, summary of changes with specifics, a demo video, completed checklist items, and test instructions. All main template sections are addressed with meaningful content.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • 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
Contributor

@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: 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.localStorage instead of using the existing wrapper at app/src/utils/localStorage.ts. Additionally, the storage key "sheet_placement" is a magic string duplicated across multiple files.

Consider these improvements:

  1. Use the localStorage wrapper for consistency with the codebase (it handles JSON serialization and key namespacing via getStorageKey)
  2. Extract the storage key to a shared constant (e.g., in app/src/componentsV2/BottomSheet/constants.ts or the context file)
  3. 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.localStorage instead 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 getStoredPlacement helper directly accesses window.localStorage, while the codebase has a centralized wrapper at app/src/utils/localStorage.ts that 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 persistPlacement function 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 sheetPlacement with 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 sheetPlacement in 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:

  1. Removing this effect entirely if defaultPlacement is static
  2. Or, if dynamic, remove sheetPlacement from deps and only react to defaultPlacement changes:
 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 the persistPlacement helper 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 persistPlacement consistently:

 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.localStorage with 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

📥 Commits

Reviewing files that changed from the base of the PR and between 244a2cf and 02bab99.

📒 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.tsx
  • app/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

Copy link
Contributor

Copilot AI left a 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/componentsV2/BottomSheet/context/index.tsx Outdated Show resolved Hide resolved
Copy link
Contributor

@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

🧹 Nitpick comments (2)
app/src/componentsV2/BottomSheet/context/index.tsx (2)

44-47: Consider wrapping persistPlacement in useCallback.

While not causing issues currently (since it's only called from the already-memoized toggleSheetPlacement), wrapping persistPlacement in useCallback would 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

📥 Commits

Reviewing files that changed from the base of the PR and between 716f685 and 1a14042.

📒 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.BOTTOM as 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.BOTTOM as 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 toggleSheetPlacement correctly:

  • 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

@RuntimeTerror10 RuntimeTerror10 self-requested a review December 5, 2025 05:24
@mustafa-sayyed mustafa-sayyed changed the title feat: add sheet persistency feat: add sheet panel persistency Dec 8, 2025
Copy link
Contributor

@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

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

getStoredPlacement and persistPlacement access the global localStorage directly; this is fine in the browser, but it bypasses the existing app/src/utils/localStorage helper (which centralizes key prefixing/JSON handling) and will throw if this code ever runs where window.localStorage is unavailable (SSR, some tests). If you expect this context to ever be used outside a pure browser runtime, consider either:

  • Switching to the shared localStorage helper, or
  • Adding a small guard (e.g. if (typeof window === "undefined" || !window.localStorage) return null;) inside getStoredPlacement / persistPlacement.

Also applies to: 43-46

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1a14042 and 997a0b4.

📒 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 useState initializer with getStoredPlacement() and falling back to BottomSheetPlacement.BOTTOM, then passing sheetPlacement/setSheetPlacement into BottomSheetProvider, 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 tighten useCallback dependencies.

Two small points here:

  1. When toggleSheetPlacement is called with an explicit placement, 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).

  2. The useCallback currently has an empty dependency array but closes over setSheetPlacement (from props) and persistPlacement. This is likely to trip react-hooks/exhaustive-deps and could capture a stale setter if a non-useState implementation is ever passed in. Verify the actual dependency sources and add appropriate dependencies if needed.

Copy link
Contributor

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

🧹 Nitpick comments (2)
app/src/componentsV2/BottomSheet/context/index.tsx (2)

9-12: Consider using the shared localStorage wrapper for consistency

getStoredPlacement and persistPlacement currently call the global localStorage directly with the raw "sheet_placement" key and plain string values. Given you already have a namespaced, JSON-aware storage helper in app/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 and getStoredPlacement accordingly. If this helper is also used in non-DOM contexts, wrapping access in a small try/catch or environment check would make getStoredPlacement safer to reuse elsewhere.

Also applies to: 42-45


62-81: Tighten useCallback dependencies or simplify toggle logic

toggleSheetPlacement is wrapped in useCallback with an empty dependency array while closing over persistPlacement and setSheetPlacement. 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 useCallback entirely 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

📥 Commits

Reviewing files that changed from the base of the PR and between 928f129 and 5413bd9.

📒 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 correct

Using a lazy useState initializer with getStoredPlacement() and passing [sheetPlacement, setSheetPlacement] through to BottomSheetProvider matches the new controlled BottomSheet API and persistence model. The initialization fallback to BottomSheetPlacement.BOTTOM is consistent with other call sites, and the provider props are correctly updated.

Also applies to: 22-22, 123-127, 144-156

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.

bug: api response panel isnt persistent for all responses throughout workspace when toggled

1 participant

Morty Proxy This is a proxified and sanitized view of the page, visit original site.