1717export default class TabPreviewPanel {
1818 #panel;
1919 #root;
20- #windowId;
20+ #windowId; // for SIDEBAR case
21+ #lastTimestamp = 0 ;
2122
2223 // https://searchfox.org/mozilla-central/rev/dfaf02d68a7cb018b6cad7e189f450352e2cde04/browser/themes/shared/tabbrowser/tab-hover-preview.css#5
2324 BASE_PANEL_WIDTH = 280 ;
@@ -292,14 +293,10 @@ export default class TabPreviewPanel {
292293 }
293294
294295 constructor ( givenRoot ) {
295- this . #panel = null ;
296- this . #root = null ;
297- this . onMessage = null ;
298- this . #windowId = null ; // for SIDEBAR case
299-
300- this . destroy = this . destroy . bind ( this ) ;
301-
302296 try {
297+ this . destroy = this . #destroy. bind ( this ) ;
298+ this . onMessage = this . #onMessage. bind ( this ) ;
299+
303300 this . #root = givenRoot || document . documentElement ;
304301 this . #root. classList . add ( 'tab-preview-root' ) ;
305302
@@ -308,78 +305,6 @@ export default class TabPreviewPanel {
308305 style . textContent = this . styleRules ;
309306 this . #root. appendChild ( style ) ;
310307
311- let lastTimestamp = 0 ;
312- this . onMessage = ( message , _sender ) => {
313- if ( ( this . #windowId &&
314- message ?. windowId != this . #windowId) )
315- return ;
316-
317- if ( message ?. logging )
318- console . log ( 'on message: ' , message ) ;
319-
320- switch ( message ?. type ) {
321- case 'treestyletab:show-tab-preview' :
322- return ( async ( ) => {
323- // Simulate the behavior: show tab preview panel with delay
324- // only when the panel is not shown yet.
325- if ( typeof message . waitInitialShowUntil == 'number' &&
326- ( ! this . #panel ||
327- ! this . #panel. classList . contains ( 'open' ) ) ) {
328- const delay = Math . max ( 0 , message . waitInitialShowUntil - Date . now ( ) ) ;
329- if ( delay > 0 ) {
330- await new Promise ( ( resolve , _reject ) => {
331- setTimeout ( resolve , delay ) ;
332- } ) ;
333- }
334- }
335- if ( message . timestamp < lastTimestamp ) {
336- if ( message ?. logging )
337- console . log ( `show tab preview(${ message . previewTabId } ): expired, give up to show/update preview ` , message . timestamp ) ;
338- return true ;
339- }
340- if ( message ?. logging )
341- console . log ( `show tab preview(${ message . previewTabId } ): invoked, let's show/update preview ` , message . timestamp ) ;
342- lastTimestamp = message . timestamp ;
343- this . prepareUI ( ) ;
344- this . updateUI ( message ) ;
345- this . #panel. classList . add ( 'open' ) ;
346- return true ;
347- } ) ( ) ;
348-
349- case 'treestyletab:hide-tab-preview' :
350- return ( async ( ) => {
351- // Ensure the order of messages: "show" for newly hovered tab =>
352- // "hide" for previously hovered tab.
353- await new Promise ( requestAnimationFrame ) ;
354- if ( ! this . #panel ||
355- ( message . previewTabId &&
356- this . #panel. dataset . tabId != message . previewTabId ) ) {
357- if ( message ?. logging )
358- console . log ( `hide tab preview(${ message . previewTabId } ): already hidden, nothing to do ` , message . timestamp ) ;
359- if ( ! this . #panel && ! message . previewTabId ) // on initial case
360- lastTimestamp = message . timestamp ;
361- return ;
362- }
363- if ( message . timestamp < lastTimestamp ) {
364- if ( message ?. logging )
365- console . log ( `hide tab preview(${ message . previewTabId } ): expired, give up to hide preview ` , message . timestamp ) ;
366- return true ;
367- }
368- if ( message ?. logging )
369- console . log ( `hide tab preview(${ message . previewTabId } ): invoked, let's hide preview ` , message . timestamp ) ;
370- lastTimestamp = message . timestamp ;
371- this . #panel. classList . remove ( 'open' ) ;
372- return true ;
373- } ) ( ) ;
374-
375- case 'treestyletab:notify-sidebar-closed' :
376- if ( this . #panel) {
377- this . #panel. classList . remove ( 'open' ) ;
378- }
379- break ;
380- }
381- } ;
382- this . onMessage = this . onMessage . bind ( this ) ;
383308 browser . runtime . onMessage . addListener ( this . onMessage ) ;
384309 window . addEventListener ( 'unload' , this . destroy , { once : true } ) ;
385310 window . addEventListener ( 'pagehide' , this . destroy , { once : true } ) ;
@@ -390,10 +315,82 @@ export default class TabPreviewPanel {
390315 }
391316 catch ( error ) {
392317 console . log ( 'TST Tab Preview Frame fatal error: ' , error ) ;
318+ this . #root = this . onMessage = this . destroy = null ;
319+ }
320+ }
321+
322+ #onMessage( message , _sender ) {
323+ if ( ( this . #windowId &&
324+ message ?. windowId != this . #windowId) )
325+ return ;
326+
327+ if ( message ?. logging )
328+ console . log ( 'on message: ' , message ) ;
329+
330+ switch ( message ?. type ) {
331+ case 'treestyletab:show-tab-preview' :
332+ return ( async ( ) => {
333+ // Simulate the behavior: show tab preview panel with delay
334+ // only when the panel is not shown yet.
335+ if ( typeof message . waitInitialShowUntil == 'number' &&
336+ ( ! this . #panel ||
337+ ! this . #panel. classList . contains ( 'open' ) ) ) {
338+ const delay = Math . max ( 0 , message . waitInitialShowUntil - Date . now ( ) ) ;
339+ if ( delay > 0 ) {
340+ await new Promise ( ( resolve , _reject ) => {
341+ setTimeout ( resolve , delay ) ;
342+ } ) ;
343+ }
344+ }
345+ if ( message . timestamp < this . #lastTimestamp) {
346+ if ( message ?. logging )
347+ console . log ( `show tab preview(${ message . previewTabId } ): expired, give up to show/update preview ` , message . timestamp ) ;
348+ return true ;
349+ }
350+ if ( message ?. logging )
351+ console . log ( `show tab preview(${ message . previewTabId } ): invoked, let's show/update preview ` , message . timestamp ) ;
352+ this . #lastTimestamp = message . timestamp ;
353+ this . prepareUI ( ) ;
354+ this . updateUI ( message ) ;
355+ this . #panel. classList . add ( 'open' ) ;
356+ return true ;
357+ } ) ( ) ;
358+
359+ case 'treestyletab:hide-tab-preview' :
360+ return ( async ( ) => {
361+ // Ensure the order of messages: "show" for newly hovered tab =>
362+ // "hide" for previously hovered tab.
363+ await new Promise ( requestAnimationFrame ) ;
364+ if ( ! this . #panel ||
365+ ( message . previewTabId &&
366+ this . #panel. dataset . tabId != message . previewTabId ) ) {
367+ if ( message ?. logging )
368+ console . log ( `hide tab preview(${ message . previewTabId } ): already hidden, nothing to do ` , message . timestamp ) ;
369+ if ( ! this . #panel && ! message . previewTabId ) // on initial case
370+ this . #lastTimestamp = message . timestamp ;
371+ return ;
372+ }
373+ if ( message . timestamp < this . #lastTimestamp) {
374+ if ( message ?. logging )
375+ console . log ( `hide tab preview(${ message . previewTabId } ): expired, give up to hide preview ` , message . timestamp ) ;
376+ return true ;
377+ }
378+ if ( message ?. logging )
379+ console . log ( `hide tab preview(${ message . previewTabId } ): invoked, let's hide preview ` , message . timestamp ) ;
380+ this . #lastTimestamp = message . timestamp ;
381+ this . #panel. classList . remove ( 'open' ) ;
382+ return true ;
383+ } ) ( ) ;
384+
385+ case 'treestyletab:notify-sidebar-closed' :
386+ if ( this . #panel) {
387+ this . #panel. classList . remove ( 'open' ) ;
388+ }
389+ break ;
393390 }
394391 }
395392
396- destroy ( ) {
393+ # destroy( ) {
397394 if ( ! this . onMessage )
398395 return ;
399396
@@ -406,7 +403,7 @@ export default class TabPreviewPanel {
406403 window . removeEventListener ( 'unload' , this . destroy ) ;
407404 window . removeEventListener ( 'pagehide' , this . destroy ) ;
408405
409- this . #root = this . onMessage = null ;
406+ this . #root = this . onMessage = this . destroy = null ;
410407 }
411408
412409 prepareUI ( ) {
0 commit comments