1+ /* eslint-disable no-unused-vars */
12// ---------------------------------------------------------------------------------------------------------------------
23// HELPERS
34// ---------------------------------------------------------------------------------------------------------------------
@@ -60,13 +61,25 @@ function addStyles (document, content) {
6061// FRAME
6162// ---------------------------------------------------------------------------------------------------------------------
6263
64+ /**
65+ * Frame class
66+ *
67+ * @property {Manager } manager
68+ * @property {number } index
69+ * @property {Window } window
70+ * @property {HTMLElement } element
71+ */
6372class Frame {
64- constructor ( parent , index ) {
65- this . parent = parent
73+ /**
74+ *
75+ * @param {Manager } manager
76+ * @param {number } index
77+ */
78+ constructor ( manager , index ) {
79+ this . manager = manager
6680 this . index = index
6781 this . window = null
6882 this . element = null
69- this . visible = true
7083 }
7184
7285 create ( src ) {
@@ -87,7 +100,7 @@ class Frame {
87100
88101 init ( ) {
89102 // variables
90- const parent = this . parent
103+ const manager = this . manager
91104 const frame = this . window
92105 const element = this . element
93106 const document = getDoc ( element )
@@ -104,7 +117,7 @@ class Frame {
104117 // duplicate frame handler
105118 document . querySelector ( '.breadcrumbs' ) . addEventListener ( 'click' , ( event ) => {
106119 if ( event . target . matches ( 'a:last-of-type' ) && isModifier ( event ) ) {
107- parent . loadNextFrame ( this , frame . location . href )
120+ manager . loadNextFrame ( this , frame . location . href )
108121 }
109122 } )
110123
@@ -116,7 +129,7 @@ class Frame {
116129 ? target
117130 : target . closest ( selector )
118131 if ( link && isModifier ( event ) ) {
119- parent . loadNextFrame ( this , WF_URL + link . getAttribute ( 'href' ) )
132+ manager . loadNextFrame ( this , WF_URL + link . getAttribute ( 'href' ) )
120133 stop ( event )
121134 }
122135 } , { capture : true } )
@@ -127,7 +140,7 @@ class Frame {
127140 if ( el . tagName === 'A' ) {
128141 const href = el . getAttribute ( 'href' )
129142 if ( href . startsWith ( WF_URL ) ) {
130- parent . load ( this , href , isModifier ( event ) )
143+ manager . load ( this , href , isModifier ( event ) )
131144 stop ( event )
132145 }
133146 }
@@ -142,8 +155,8 @@ class Frame {
142155 button . innerHTML = '<div class="iconButton _pn8v4l"><svg width="14" height="14" viewBox="0 0 20 20" fill="none" stroke-linecap="round" stroke="#b7bcbf" style="position: relative;"><line x1="1" y1="1" x2="19" y2="19"></line><line x1="19" y1="1" x2="1" y2="19"></line></svg></div>'
143156 button . addEventListener ( 'click' , ( event ) => {
144157 isModifier ( event )
145- ? parent . removeFrame ( this )
146- : parent . hideFrame ( this )
158+ ? manager . removeFrame ( this )
159+ : manager . hideFrame ( this )
147160 } )
148161 }
149162 }
@@ -185,6 +198,12 @@ class Frame {
185198// MANAGER
186199// ---------------------------------------------------------------------------------------------------------------------
187200
201+ /**
202+ * Manager class
203+ *
204+ * @property {Frame[] } frames
205+ * @property {HTMLElement } container
206+ */
188207class Manager {
189208 constructor ( ) {
190209 this . frames = [ ]
@@ -252,51 +271,86 @@ class Manager {
252271 if ( this . container ) {
253272 const layout = document . body . getAttribute ( 'data-layout' )
254273 this . container . style . width = layout === 'fit-content'
255- ? ( WF_WIDTH * manager . numVisible ) + 'px'
274+ ? ( WF_WIDTH * this . numVisible ) + 'px'
256275 : 'auto'
257276 }
277+
278+ // trigger save
279+ document . dispatchEvent ( new Event ( 'multiflow:update' ) )
258280 }
259281}
260282
261283// ---------------------------------------------------------------------------------------------------------------------
262284// DATA
263285// ---------------------------------------------------------------------------------------------------------------------
264286
287+ /**
288+ * Data class
289+ */
265290class Data {
291+ /**
292+ * Loads frame data
293+ * @returns {{urls: string[], titles: string[], layout: string} }
294+ */
266295 load ( ) {
267296 return JSON . parse ( localStorage . getItem ( 'multiflow' ) || '{}' )
268297 }
269298
270- save ( frames ) {
299+ /**
300+ * Save visible frames
301+ * @param {Frame[] } frames
302+ * @param {string } layout
303+ */
304+ save ( frames , layout ) {
271305 // input data
272- const input = manager . frames
306+ const input = frames
273307 . filter ( frame => frame . isVisible ( ) )
274308 . map ( frame => frame . getData ( ) )
275309
276310 // output data
277311 const urls = input . map ( d => d . url )
278312 const titles = input . map ( d => d . title )
279- const data = { urls, titles }
313+ const data = { urls, titles, layout }
280314
281- // check
282- const title = 'MultiFlow: ' + titles . join ( ' + ' )
283- if ( document . title !== title ) {
284- document . title = title
285- localStorage . setItem ( 'multiflow' , JSON . stringify ( data ) )
286- }
315+ // save
316+ document . title = 'MultiFlow: ' + titles . join ( ' + ' )
317+ localStorage . setItem ( 'multiflow' , JSON . stringify ( data ) )
318+
319+ // return
320+ return data
287321 }
288322}
289323
290324// ---------------------------------------------------------------------------------------------------------------------
291325// APP
292326// ---------------------------------------------------------------------------------------------------------------------
293327
328+ /**
329+ * Application class
330+ *
331+ * @property {boolean } loadState
332+ * @property {Manager } manager
333+ * @property {Data } data
334+ */
294335class App {
295- constructor ( ) {
336+ /**
337+ * Application class
338+ *
339+ * @param {Manager } manager
340+ * @param {Data } data
341+ */
342+ constructor ( manager , data ) {
296343 this . loadState = null
344+ this . manager = manager
345+ this . data = data
297346 }
298347
299348 start ( ) {
349+ // only load if top window
350+ if ( window !== window . top ) {
351+ return
352+ }
353+
300354 // initialize
301355 if ( ! this . loadState ) {
302356 this . loadState = 'initializing'
@@ -322,13 +376,15 @@ class App {
322376 this . loadState = 'loaded'
323377 location . replace ( WF_URL + '/#multiflow' )
324378
325- // save
326- setInterval ( this . save , 1000 )
379+ // saving
380+ const save = this . save . bind ( this )
381+ document . addEventListener ( 'multiflow:update' , save )
382+ setInterval ( save , 5000 )
327383 }
328384
329385 setup ( ) {
330386 document . write ( `
331- <html>
387+ <html lang="en" >
332388 <head>
333389 <title>MultiFlow</title>
334390 <style>
@@ -380,31 +436,39 @@ class App {
380436 }
381437 </style>
382438 </head>
383- <body class="multiflow">
439+ <body class="multiflow" data-layout="fit-screen" >
384440 <main/>
385441 </body>
386442 </html>` )
387- manager . container = document . querySelector ( 'main' )
443+ this . manager . container = document . querySelector ( 'main' )
388444 }
389445
390446 load ( ) {
391- const saved = data . load ( )
392- const current = location . href
393- const urls = saved . urls || [ current , current ]
394- urls . forEach ( url => manager . addFrame ( url ) )
447+ if ( ! this . loadState ) {
448+ const saved = this . data . load ( )
449+ const current = location . href
450+ const urls = saved . urls || [ current , current ]
451+ urls . forEach ( url => this . manager . addFrame ( url ) )
452+ this . setLayout ( saved . layout )
453+ }
454+ else {
455+ console . warn ( 'MultiFLow has already loaded data' )
456+ }
395457 }
396458
397459 save ( ) {
398- const frames = manager . frames
399- . filter ( frame => frame . isVisible ( ) )
400- . map ( frame => frame . getData ( ) )
401- data . save ( frames )
460+ return this . data . save ( this . manager . frames , this . getLayout ( ) )
402461 }
403462
404463 setLayout ( value ) {
405- document . body . setAttribute ( 'data-layout' , value )
406- manager . update ( )
407- return true
464+ if ( value ) {
465+ document . body . setAttribute ( 'data-layout' , value )
466+ this . manager . update ( )
467+ }
468+ }
469+
470+ getLayout ( ) {
471+ return document . body . getAttribute ( 'data-layout' )
408472 }
409473}
410474
@@ -419,20 +483,23 @@ const WF_WIDTH = 700
419483// instances
420484const manager = new Manager ( )
421485const data = new Data ( )
422- const app = new App ( )
486+ const app = new App ( manager , data )
423487
424488// debug
425489console . log ( 'MultiFlow is ready...' )
426490
427491// commands
428492chrome . runtime . onMessage . addListener ( function ( request = { } , _sender , callback ) {
429- switch ( request . type ) {
493+ switch ( request . command ) {
430494 case 'start' :
431495 return callback ( app . start ( ) )
432496
433- case 'layout ' :
497+ case 'setLayout ' :
434498 return callback ( app . setLayout ( request . value ) )
435499
500+ case 'getLayout' :
501+ return callback ( app . getLayout ( ) )
502+
436503 default :
437504 // eslint-disable-next-line node/no-callback-literal
438505 return callback ( 'Unknown request' )
0 commit comments