@@ -27,6 +27,7 @@ import UIWindowColorPicker from './UI/UIWindowColorPicker.js';
2727import UIPrompt from './UI/UIPrompt.js' ;
2828import download from './helpers/download.js' ;
2929import path from "./lib/path.js" ;
30+ import UIContextMenu from './UI/UIContextMenu.js' ;
3031
3132/**
3233 * In Puter, apps are loaded in iframes and communicate with the graphical user interface (GUI) aand each other using the postMessage API.
@@ -352,6 +353,119 @@ window.addEventListener('message', async (event) => {
352353 } , '*' ) ;
353354 }
354355 //--------------------------------------------------------
356+ // setMenubar
357+ //--------------------------------------------------------
358+ else if ( event . data . msg === 'setMenubar' ) {
359+ const el_window = window_for_app_instance ( event . data . appInstanceID ) ;
360+
361+ console . error ( `EXPERIMENTAL: setMenubar is a work-in-progress` ) ;
362+ const hydrator = puter . util . rpc . getHydrator ( {
363+ target : target_iframe . contentWindow ,
364+ } ) ;
365+ const value = hydrator . hydrate ( event . data . value ) ;
366+ console . log ( 'hydrated value' , value ) ;
367+
368+ // Show menubar
369+ const $menubar = $ ( el_window ) . find ( '.window-menubar' )
370+ $menubar . show ( ) ;
371+
372+ const sanitize_items = items => {
373+ return items . map ( item => {
374+ return {
375+ html : item . label ,
376+ action : item . action ,
377+ items : item . items && sanitize_items ( item . items ) ,
378+ } ;
379+ } ) ;
380+ } ;
381+
382+ // This array will store the menubar button elements
383+ const menubar_buttons = [ ] ;
384+
385+ // Add menubar items
386+ let current = null ;
387+ let current_i = null ;
388+ let state_open = false ;
389+ const open_menu = ( { i, pos, parent_element, items } ) => {
390+ let delay = true ;
391+ if ( state_open ) {
392+ if ( current_i === i ) return ;
393+
394+ delay = false ;
395+ current && current . cancel ( { meta : 'menubar' , fade : false } ) ;
396+ }
397+
398+ // Set this menubar button as active
399+ menubar_buttons . forEach ( el => el . removeClass ( 'active' ) ) ;
400+ menubar_buttons [ i ] . addClass ( 'active' ) ;
401+
402+ // Open the context menu
403+ const ctxMenu = UIContextMenu ( {
404+ delay,
405+ parent_element,
406+ position : { top : pos . top + 28 , left : pos . left } ,
407+ items : sanitize_items ( items ) ,
408+ } ) ;
409+
410+ state_open = true ;
411+ current = ctxMenu ;
412+ current_i = i ;
413+
414+ ctxMenu . onClose = ( cancel_options ) => {
415+ if ( cancel_options ?. meta === 'menubar' ) return ;
416+ menubar_buttons . forEach ( el => el . removeClass ( 'active' ) ) ;
417+ ctxMenu . onClose = null ;
418+ current_i = null ;
419+ current = null ;
420+ state_open = false ;
421+ }
422+ } ;
423+ const add_items = ( parent , items ) => {
424+ for ( let i = 0 ; i < items . length ; i ++ ) {
425+ const I = i ;
426+ const item = items [ i ] ;
427+ const label = html_encode ( item . label ) ;
428+ const el_item = $ ( `<div class="window-menubar-item"><span>${ label } </span></div>` ) ;
429+ const parent_element = el_item . parent ( ) [ 0 ] ;
430+ el_item . on ( 'click' , ( ) => {
431+ if ( state_open ) {
432+ state_open = false ;
433+ current && current . cancel ( { meta : 'menubar' } ) ;
434+ current_i = null ;
435+ current = null ;
436+ return ;
437+ }
438+ if ( item . action ) {
439+ item . action ( ) ;
440+ } else if ( item . items ) {
441+ const pos = el_item [ 0 ] . getBoundingClientRect ( ) ;
442+ open_menu ( {
443+ i,
444+ pos,
445+ parent_element,
446+ items : item . items ,
447+ } ) ;
448+ }
449+ } ) ;
450+ el_item . on ( 'mouseover' , ( ) => {
451+ if ( ! state_open ) return ;
452+ if ( ! item . items ) return ;
453+
454+ const pos = el_item [ 0 ] . getBoundingClientRect ( ) ;
455+ open_menu ( {
456+ i,
457+ pos,
458+ parent_element,
459+ items : item . items ,
460+ } ) ;
461+ } ) ;
462+ $menubar . append ( el_item ) ;
463+ menubar_buttons . push ( el_item ) ;
464+ }
465+ } ;
466+ add_items ( $menubar , value . items ) ;
467+ }
468+ //--------------------------------------------------------
355469 // setWindowWidth
356470 //--------------------------------------------------------
357471 else if ( event . data . msg === 'setWindowWidth' && event . data . width !== undefined ) {
0 commit comments