66 PanelLeftOpenIcon ,
77 SearchIcon ,
88 SquarePenIcon ,
9+ WrenchIcon ,
910} from "lucide-react" ;
1011import {
1112 type CSSProperties ,
@@ -18,6 +19,10 @@ import {
1819 useState ,
1920} from "react" ;
2021
22+ import {
23+ commands as windowsCommands ,
24+ events as windowsEvents ,
25+ } from "@hypr/plugin-windows" ;
2126import {
2227 ResizableHandle ,
2328 ResizablePanel ,
@@ -38,6 +43,7 @@ import { useClassicMainTabsShortcuts } from "./useTabsShortcuts";
3843import { useShell } from "~/contexts/shell" ;
3944import { GlobalLiveTranscriptAccessory } from "~/session/components/bottom-accessory/global-live" ;
4045import { scrollElementByWheel } from "~/shared/dom/scroll-wheel" ;
46+ import { useMountEffect } from "~/shared/hooks/useMountEffect" ;
4147import { NOTE_SURFACE_MIN_WIDTH_PX } from "~/shared/main/layout-widths" ;
4248import { useOpenNoteDialog } from "~/shared/open-note-dialog" ;
4349import { useNewNote } from "~/shared/useNewNote" ;
@@ -54,6 +60,7 @@ const LEFT_SIDEBAR_DEFAULT_WIDTH_PX = 200;
5460const LEFT_SIDEBAR_MIN_WIDTH_PX = 200 ;
5561const LEFT_SIDEBAR_MAX_WIDTH_PX = 360 ;
5662const LEFT_SIDEBAR_FALLBACK_CONTAINER_WIDTH_PX = 1000 ;
63+ const showDevtoolsPanelButton = import . meta. env . DEV ;
5764
5865type MainAreaWindowDragStart = {
5966 pointerId : number ;
@@ -81,6 +88,36 @@ export function ClassicMainBody() {
8188 const leftSidebarResizeDraggingRef = useRef ( false ) ;
8289 const [ showIgnoredTimelineEvents , setShowIgnoredTimelineEvents ] =
8390 useState ( false ) ;
91+ const [ devtoolsPanelOpen , setDevtoolsPanelOpen ] = useState ( false ) ;
92+
93+ useMountEffect ( ( ) => {
94+ if ( ! showDevtoolsPanelButton ) {
95+ return ;
96+ }
97+
98+ let cancelled = false ;
99+ let unlistenDevtoolsAction : ( ( ) => void ) | undefined ;
100+
101+ windowsEvents . devtoolsPanelAction
102+ . listen ( ( { payload } ) => {
103+ if ( payload . action === "panel:closed" ) {
104+ setDevtoolsPanelOpen ( false ) ;
105+ }
106+ } )
107+ . then ( ( unlisten ) => {
108+ if ( cancelled ) {
109+ unlisten ( ) ;
110+ return ;
111+ }
112+
113+ unlistenDevtoolsAction = unlisten ;
114+ } ) ;
115+
116+ return ( ) => {
117+ cancelled = true ;
118+ unlistenDevtoolsAction ?.( ) ;
119+ } ;
120+ } ) ;
84121
85122 const isOnboarding = currentTab ?. type === "onboarding" ;
86123 const isChangelog = currentTab ?. type === "changelog" ;
@@ -117,6 +154,16 @@ export function ClassicMainBody() {
117154 const handleOpenNoteDialog = useCallback ( ( ) => {
118155 openNoteDialog . open ( ) ;
119156 } , [ openNoteDialog ] ) ;
157+ const handleOpenDevtoolsPanel = useCallback ( async ( ) => {
158+ const result = await windowsCommands . devtoolsPanelShow ( ) ;
159+
160+ if ( result . status === "ok" ) {
161+ setDevtoolsPanelOpen ( true ) ;
162+ return ;
163+ }
164+
165+ console . error ( "Failed to show devtools panel:" , result . error ) ;
166+ } , [ ] ) ;
120167 const applyLeftSidebarPanelSize = useCallback ( ( size : number ) => {
121168 const bodyRoot = bodyRootRef . current ;
122169 if ( ! bodyRoot ) {
@@ -241,8 +288,10 @@ export function ClassicMainBody() {
241288 >
242289 < SidebarTimelineChrome
243290 sidebarExpanded = { leftsidebar . expanded }
291+ devtoolsPanelOpen = { devtoolsPanelOpen }
244292 onNewNote = { createNewNote }
245293 onSearch = { handleOpenNoteDialog }
294+ onOpenDevtools = { handleOpenDevtoolsPanel }
246295 onToggleSidebar = { handleToggleLeftSidebar }
247296 hasUpcomingMeeting = { hasUpcomingMeetingBadge }
248297 update = { update }
@@ -542,15 +591,19 @@ function isMainAreaWindowDrag(
542591}
543592
544593function SidebarTimelineChrome ( {
594+ devtoolsPanelOpen,
545595 hasUpcomingMeeting,
546596 onNewNote,
597+ onOpenDevtools,
547598 onSearch,
548599 onToggleSidebar,
549600 sidebarExpanded,
550601 update,
551602} : {
603+ devtoolsPanelOpen : boolean ;
552604 hasUpcomingMeeting : boolean ;
553605 onNewNote : ( ) => void ;
606+ onOpenDevtools : ( ) => void ;
554607 onSearch : ( ) => void ;
555608 onToggleSidebar : ( ) => void ;
556609 sidebarExpanded : boolean ;
@@ -591,6 +644,14 @@ function SidebarTimelineChrome({
591644 < LeftSurfaceChromeButton ariaLabel = "New note" onClick = { onNewNote } >
592645 < SquarePenIcon size = { 15 } />
593646 </ LeftSurfaceChromeButton >
647+ { showDevtoolsPanelButton && ! devtoolsPanelOpen ? (
648+ < LeftSurfaceChromeButton
649+ ariaLabel = "Show devtools panel"
650+ onClick = { onOpenDevtools }
651+ >
652+ < WrenchIcon size = { 15 } />
653+ </ LeftSurfaceChromeButton >
654+ ) : null }
594655 </ >
595656 ) : null }
596657 </ div >
0 commit comments