Skip to content

Allow hiding Orca Mobile sidebar button once a device is paired#5785

Merged
AmethystLiang merged 3 commits into
mainfrom
hide-mobile-sidebar-once-connected
Jul 19, 2026
Merged

Allow hiding Orca Mobile sidebar button once a device is paired#5785
AmethystLiang merged 3 commits into
mainfrom
hide-mobile-sidebar-once-connected

Conversation

@AmethystLiang

@AmethystLiang AmethystLiang commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

Summary

Allows hiding the Orca Mobile sidebar button once a device has been paired.

  • Adds a shared state/cache manager for paired mobile devices (paired-mobile-devices.ts) to avoid duplicate IPC calls when the Sidebar, Settings pane, and Mobile page mount concurrently.
  • Introduces a "Hide from sidebar" option (an inline EyeOff button with a tooltip) next to the "Orca Mobile" sidebar link when at least one paired device is present.
  • Extracts MobilePage's pairing stage/revoke/polling state logic into a custom hook useMobilePagePairedDevices.
  • Integrates the new shared paired devices state/hook into MobilePane (Settings) and SidebarNav.

Screenshots

  • Added an inline "Hide from sidebar" button next to the "Orca Mobile" sidebar item once a device is paired.

Testing

  • pnpm lint
  • pnpm typecheck
  • pnpm test
  • pnpm build
  • Added or updated high-quality tests that would catch regressions, or explained why tests were not needed

Added unit tests in paired-mobile-devices.test.ts to cover caching and coalescing logic, added integration/rendering tests in MobilePane.test.tsx to verify refresh/unmount flows, and updated SidebarNav.test.tsx to verify the inline sidebar hide control.

AI Review Report

The code review with the AI coding agent focused on:

  1. Concurrency and Caching: Checked that concurrent listDevices calls coalesce correctly to a single IPC call and that stale/superseded requests are ignored properly, preventing race conditions or flashing UI state.
  2. Component Lifecycle & Memory Leaks: Verified that if a component (like MobilePane) unmounts while an IPC call is in flight, state updates (e.g., toast notifications) do not execute on unmounted components.
  3. Cross-Platform Compatibility: Confirmed that the UI components rely on global Electron API channels (such as window.api.mobile and window.api.ui.writeClipboardText) and platform-agnostic layout structures. No hardcoded or platform-specific file paths or shortcuts were introduced or modified.

Security Audit

  1. IPC & Input Handling: Reviewed the revocation call (window.api.mobile.revokeDevice({ deviceId })). It passes an existing deviceId sourced from paired devices list, mitigating injection risks.
  2. Clipboard Access: Verified that clipboard writes use the established window.api.ui.writeClipboardText utility.
  3. Information Disclosure: The local caching mechanism only stores basic device info in-memory on the renderer side and does not leak or persist any authentication secrets.

Notes

No platform-specific regressions are expected; behavior is uniform across macOS, Windows, and Linux.


Open in Stage

@stage-review

stage-review Bot commented Jun 19, 2026

Copy link
Copy Markdown

Ready to review this PR? Stage has broken it down into 4 individual chapters for you:

Title
1 Create shared paired mobile devices cache
2 Extract mobile page logic into custom hook
3 Integrate shared cache into Settings pane
4 Add inline sidebar hide control
Open in Stage

Chapters generated by Stage for commit 404cf23 on Jun 19, 2026 8:15am UTC.

@coderabbitai

coderabbitai Bot commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

A new paired-mobile-devices.ts module introduces a shared, cross-surface cache for paired mobile devices, backed by window.api.mobile.listDevices() with request coalescing via refreshPairedMobileDevices, an immediate-write path via replacePairedMobileDevices, and a usePairedMobileDevices hook using useSyncExternalStore. Existing components—MobilePage, MobilePane, and the sidebar onboarding badge—are migrated from local state/direct IPC calls to this shared cache. Pairing state-machine logic is extracted from MobilePage into a new useMobilePagePairedDevices hook. The PairedDevice types in consumer components become aliases of PairedMobileDevice. SidebarNav gains a conditional "Hide from sidebar" icon button shown when a device is paired, using hasPairedDevice newly exposed by useMobileSidebarOnboardingBadge. Tests are added or rewritten for all changed modules.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 4.76% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately and clearly summarizes the main user-visible feature: allowing users to hide the Orca Mobile sidebar button once a device is paired.
Description check ✅ Passed The description is comprehensive and well-structured, covering all required template sections: summary, screenshots, testing checklist with verification, AI review report with concurrency/lifecycle/compatibility findings, security audit with IPC/input handling analysis, and platform-specific notes.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (1)
src/renderer/src/components/settings/MobilePane.test.tsx (1)

142-145: ⚡ Quick win

Add a mounted success-toast assertion.

The unmount test below is a negative assertion; without a positive control here, deleting toast.success from revokeDevice would still leave this suite green.

Proposed test assertion
     await vi.waitFor(() =>
       expect(mocks.latestPairedDevicesProps?.devices.map((d) => d.deviceId)).toEqual(['phone-2'])
     )
+    await vi.waitFor(() => expect(mocks.toastSuccess).toHaveBeenCalledTimes(1))
   })

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 02095453-171f-454c-9f51-344891c7ee8d

📥 Commits

Reviewing files that changed from the base of the PR and between b5b018c and 404cf23.

📒 Files selected for processing (12)
  • src/renderer/src/components/mobile/MobileHeroPairedDevices.tsx
  • src/renderer/src/components/mobile/MobilePage.tsx
  • src/renderer/src/components/mobile/paired-mobile-devices.test.ts
  • src/renderer/src/components/mobile/paired-mobile-devices.ts
  • src/renderer/src/components/mobile/use-mobile-page-paired-devices.ts
  • src/renderer/src/components/settings/MobilePairedDevicesSection.tsx
  • src/renderer/src/components/settings/MobilePane.test.tsx
  • src/renderer/src/components/settings/MobilePane.tsx
  • src/renderer/src/components/sidebar/SidebarNav.test.tsx
  • src/renderer/src/components/sidebar/SidebarNav.tsx
  • src/renderer/src/components/sidebar/mobile-sidebar-onboarding-badge.test.ts
  • src/renderer/src/components/sidebar/mobile-sidebar-onboarding-badge.ts

Introduce a shared external store (`paired-mobile-devices.ts`) to cache
and synchronize the paired mobile device list across the sidebar,
Settings pane, and Mobile page. This prevents redundant backend IPC
requests when multiple surfaces mount simultaneously.

Using this shared pairing status, display an inline "Hide from sidebar"
control next to "Orca Mobile" in the navigation sidebar once a device
has been paired. This allows users to easily declutter their sidebar
after completing setup.
@AmethystLiang
AmethystLiang force-pushed the hide-mobile-sidebar-once-connected branch from 404cf23 to 5422437 Compare July 19, 2026 05:02
- Add error flag to distinguish failed device loads from empty device lists
- Recover from transient startup IPC failures by retrying on window focus or online
- Validate revoke device success before routing or showing success toast
- Only show hide control after first device is actually paired
- Use snapshot getter to avoid manual device ref tracking in MobilePane
- Shared module-level listeners for failed load recovery reduce IPC spam
  compared to per-consumer event listeners on every focus/online event.
- Optimistically remove revoked devices if post-revoke reload fails,
  keeping success toast and intro routing correct.
- Prevent repo/branch label overflow with CSS text truncation.
- Fix HTML entity rendering: use plain spaces instead of   in
  translations so React text nodes render them correctly.
- Add comprehensive tests for the paired devices hook covering load,
  navigation, revoke, and error recovery paths.
@AmethystLiang
AmethystLiang merged commit e885cec into main Jul 19, 2026
1 check 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.

1 participant