@@ -14,6 +14,8 @@ import {
1414 updateSettings ,
1515 upsertTabSnapshot
1616} from "../shared/db.js" ;
17+ import { executeActionClick } from "./action-click.js" ;
18+ import { configureOpenOnActionClick } from "./side-panel-behavior.js" ;
1719import { createSessionEngine } from "./session-engine.js" ;
1820import { extractDomain , isExcludedDomain , isTrackableUrl , readableTitle } from "../shared/url.js" ;
1921
@@ -28,7 +30,10 @@ const state = {
2830 paused : false ,
2931 excludedDomains : [ ] ,
3032 retentionDays : 30 ,
31- theme : "dark"
33+ theme : "dark" ,
34+ openPanelOnActionClick : null ,
35+ lastActionClickResult : null ,
36+ lastOpenSidePanelResult : null
3237} ;
3338
3439const sessionEngine = createSessionEngine ( {
@@ -326,19 +331,22 @@ async function openPanelForAllWindows() {
326331 }
327332
328333 const windows = await chrome . windows . getAll ( { populate : false } ) ;
334+ let openedCount = 0 ;
335+
329336 await Promise . all (
330337 windows
331338 . filter ( ( windowEntry ) => typeof windowEntry . id === "number" )
332339 . map ( async ( windowEntry ) => {
333340 try {
334341 await chrome . sidePanel . open ( { windowId : windowEntry . id } ) ;
342+ openedCount += 1 ;
335343 } catch {
336344 // Ignore non-supported window types or gesture mismatches.
337345 }
338346 } )
339347 ) ;
340348
341- return true ;
349+ return openedCount > 0 ;
342350}
343351
344352async function openPanelForWindow ( windowId ) {
@@ -355,17 +363,14 @@ async function openPanelForWindow(windowId) {
355363}
356364
357365async function initializeSidePanelBehavior ( ) {
358- if ( ! chrome . sidePanel ?. setPanelBehavior ) {
366+ const result = await configureOpenOnActionClick ( chrome . sidePanel ?. setPanelBehavior ?. bind ( chrome . sidePanel ) ) ;
367+ state . openPanelOnActionClick = result . ok ;
368+
369+ if ( result . ok || result . reason === "not_supported" ) {
359370 return ;
360371 }
361372
362- try {
363- await chrome . sidePanel . setPanelBehavior ( {
364- openPanelOnActionClick : false
365- } ) ;
366- } catch ( error ) {
367- console . warn ( "Unable to configure side panel behavior" , error ) ;
368- }
373+ console . warn ( "Unable to configure side panel behavior" , result . error || result . reason ) ;
369374}
370375
371376async function initializeExtension ( reason ) {
@@ -396,32 +401,30 @@ chrome.runtime.onStartup.addListener(() => {
396401} ) ;
397402
398403chrome . action . onClicked . addListener ( ( ) => {
399- // Keep icon-click predictable: open current window panel first, then best-effort global open.
400- chrome . windows
401- . getLastFocused ( )
402- . then ( async ( windowEntry ) => {
403- const focusedWindowId = typeof windowEntry ?. id === "number" ? windowEntry . id : null ;
404- let opened = false ;
405-
406- if ( focusedWindowId !== null ) {
407- opened = await openPanelForWindow ( focusedWindowId ) ;
408- }
409-
410- if ( ! opened ) {
411- opened = await openPanelForAllWindows ( ) ;
412- }
413-
414- if ( ! opened ) {
415- await chrome . tabs . create ( { url : getDashboardUrl ( ) } ) ;
416- return ;
417- }
418-
419- openPanelForAllWindows ( ) . catch ( ( ) => {
420- // Ignore follow-up global open failures.
421- } ) ;
404+ executeActionClick ( {
405+ getFocusedWindowId : async ( ) => {
406+ const windowEntry = await chrome . windows . getLastFocused ( ) ;
407+ return typeof windowEntry ?. id === "number" ? windowEntry . id : null ;
408+ } ,
409+ openPanelForWindow,
410+ openPanelForAllWindows,
411+ openDashboardTab : async ( ) => chrome . tabs . create ( { url : getDashboardUrl ( ) } )
412+ } )
413+ . then ( ( result ) => {
414+ state . lastActionClickResult = {
415+ ...result ,
416+ source : "action-click" ,
417+ at : Date . now ( )
418+ } ;
422419 } )
423- . catch ( async ( ) => {
424- await chrome . tabs . create ( { url : getDashboardUrl ( ) } ) ;
420+ . catch ( ( error ) => {
421+ state . lastActionClickResult = {
422+ ok : false ,
423+ source : "action-click" ,
424+ at : Date . now ( ) ,
425+ error : String ( error )
426+ } ;
427+ console . error ( "Failed to handle action click" , error ) ;
425428 } ) ;
426429} ) ;
427430
@@ -548,11 +551,48 @@ chrome.runtime.onMessage.addListener((message, _sender, sendResponse) => {
548551
549552 if ( message ?. type === "open-side-panel" ) {
550553 openPanelForAllWindows ( )
551- . then ( ( ) => sendResponse ( { ok : true } ) )
554+ . then ( ( opened ) => {
555+ state . lastOpenSidePanelResult = {
556+ ok : opened ,
557+ opened,
558+ at : Date . now ( )
559+ } ;
560+ sendResponse ( { ok : opened , opened } ) ;
561+ } )
552562 . catch ( ( error ) => sendResponse ( { ok : false , error : String ( error ) } ) ) ;
553563 return true ;
554564 }
555565
566+ if ( message ?. type === "debug-trigger-action-click" ) {
567+ executeActionClick ( {
568+ getFocusedWindowId : async ( ) => {
569+ const windowEntry = await chrome . windows . getLastFocused ( ) ;
570+ return typeof windowEntry ?. id === "number" ? windowEntry . id : null ;
571+ } ,
572+ openPanelForWindow,
573+ openPanelForAllWindows,
574+ openDashboardTab : async ( ) => chrome . tabs . create ( { url : getDashboardUrl ( ) } )
575+ } )
576+ . then ( ( result ) => {
577+ state . lastActionClickResult = {
578+ ...result ,
579+ source : "debug-trigger-action-click" ,
580+ at : Date . now ( )
581+ } ;
582+ sendResponse ( result ) ;
583+ } )
584+ . catch ( ( error ) => {
585+ state . lastActionClickResult = {
586+ ok : false ,
587+ source : "debug-trigger-action-click" ,
588+ at : Date . now ( ) ,
589+ error : String ( error )
590+ } ;
591+ sendResponse ( { ok : false , error : String ( error ) } ) ;
592+ } ) ;
593+ return true ;
594+ }
595+
556596 if ( message ?. type === "get-runtime-status" ) {
557597 const runtimeState = sessionEngine . readState ( ) ;
558598 sendResponse ( {
@@ -562,7 +602,11 @@ chrome.runtime.onMessage.addListener((message, _sender, sendResponse) => {
562602 retentionDays : state . retentionDays ,
563603 idleState : state . idleState ,
564604 theme : state . theme ,
565- meaningfulThresholdSec : FOCUS_MEANINGFUL_THRESHOLD_SEC
605+ meaningfulThresholdSec : FOCUS_MEANINGFUL_THRESHOLD_SEC ,
606+ sidePanelApiAvailable : Boolean ( chrome . sidePanel ?. open ) ,
607+ openPanelOnActionClick : state . openPanelOnActionClick ,
608+ lastActionClickResult : state . lastActionClickResult ,
609+ lastOpenSidePanelResult : state . lastOpenSidePanelResult
566610 } ) ;
567611 return false ;
568612 }
0 commit comments