electrobun-window-management

安装量: 35
排名: #19514

安装

npx skills add https://github.com/rajavijayach/electrobun-skills --skill electrobun-window-management

Electrobun Window Management Advanced patterns for managing windows and views in Electrobun applications. Multi-Window Applications Basic Window Manager import { BrowserWindow } from "electrobun/bun" ; class WindowManager { private windows = new Map < string , BrowserWindow

( ) ; createWindow ( id : string , options : any ) { const win = new BrowserWindow ( options ) ; this . windows . set ( id , win ) ; win . on ( "close" , ( ) => { this . windows . delete ( id ) ; } ) ; return win ; } getWindow ( id : string ) { return this . windows . get ( id ) ; } getAllWindows ( ) { return Array . from ( this . windows . values ( ) ) ; } closeWindow ( id : string ) { const win = this . windows . get ( id ) ; if ( win ) { win . close ( ) ; } } closeAllWindows ( ) { this . windows . forEach ( win => win . close ( ) ) ; this . windows . clear ( ) ; } } const windowManager = new WindowManager ( ) ; Window Factory Pattern type WindowType = "main" | "settings" | "editor" | "preview" ; interface WindowConfig { type : WindowType ; url : string ; width : number ; height : number ; frame ? : boolean ; parent ? : BrowserWindow ; } class WindowFactory { private configs : Record < WindowType , Partial < WindowConfig

= { main : { url : "views://main/index.html" , width : 1200 , height : 800 , frame : true , } , settings : { url : "views://settings/index.html" , width : 600 , height : 500 , frame : true , } , editor : { url : "views://editor/index.html" , width : 1000 , height : 700 , } , preview : { url : "views://preview/index.html" , width : 800 , height : 600 , frame : false , } } ; create ( type : WindowType , overrides ? : Partial < WindowConfig

) { const config = { ... this . configs [ type ] , ... overrides } ; return new BrowserWindow ( config ) ; } } const factory = new WindowFactory ( ) ; const mainWindow = factory . create ( "main" ) ; const settingsWindow = factory . create ( "settings" , { width : 700 } ) ; BrowserView BrowserView allows embedding webviews within a window without creating a separate window. Basic BrowserView import { BrowserWindow , BrowserView } from "electrobun/bun" ; const win = new BrowserWindow ( { title : "Browser App" , width : 1200 , height : 800 , } ) ; const view = new BrowserView ( { bounds : { x : 0 , y : 60 , width : 1200 , height : 740 } } ) ; win . addBrowserView ( view ) ; view . loadURL ( "https://example.com" ) ; // Update bounds on window resize win . on ( "resize" , ( { width , height } ) => { view . setBounds ( { x : 0 , y : 60 , width , height : height - 60 } ) ; } ) ; Tab System with BrowserView class TabManager { private tabs : Map < string , BrowserView

= new Map ( ) ; private activeTab : string | null = null ; private window : BrowserWindow ; constructor ( window : BrowserWindow ) { this . window = window ; } createTab ( id : string , url : string ) { const view = new BrowserView ( { bounds : this . getViewBounds ( ) } ) ; view . loadURL ( url ) ; this . tabs . set ( id , view ) ; if ( ! this . activeTab ) { this . activateTab ( id ) ; } return view ; } activateTab ( id : string ) { const view = this . tabs . get ( id ) ; if ( ! view ) return ; // Hide current tab if ( this . activeTab ) { const currentView = this . tabs . get ( this . activeTab ) ; if ( currentView ) { this . window . removeBrowserView ( currentView ) ; } } // Show new tab this . window . addBrowserView ( view ) ; this . activeTab = id ; } closeTab ( id : string ) { const view = this . tabs . get ( id ) ; if ( ! view ) return ; if ( this . activeTab === id ) { this . window . removeBrowserView ( view ) ; this . activeTab = null ; // Activate another tab const otherTab = Array . from ( this . tabs . keys ( ) ) . find ( k => k !== id ) ; if ( otherTab ) { this . activateTab ( otherTab ) ; } } this . tabs . delete ( id ) ; } private getViewBounds ( ) { const { width , height } = this . window . getBounds ( ) ; return { x : 0 , y : 60 , width , height : height - 60 } ; } updateBounds ( ) { const bounds = this . getViewBounds ( ) ; this . tabs . forEach ( view => { view . setBounds ( bounds ) ; } ) ; } } // Usage const tabManager = new TabManager ( mainWindow ) ; tabManager . createTab ( "tab1" , "https://example.com" ) ; tabManager . createTab ( "tab2" , "https://github.com" ) ; tabManager . activateTab ( "tab2" ) ; mainWindow . on ( "resize" , ( ) => { tabManager . updateBounds ( ) ; } ) ; Window Lifecycle Management Window State Persistence import { paths } from "electrobun/bun" ; import { join } from "path" ; interface WindowState { x : number ; y : number ; width : number ; height : number ; maximized : boolean ; } class WindowStateManager { private stateFile : string ; constructor ( windowId : string ) { this . stateFile = join ( paths . userData , window-state- ${ windowId } .json ) ; } async save ( state : WindowState ) { await Bun . write ( this . stateFile , JSON . stringify ( state , null , 2 ) ) ; } async load ( ) : Promise < WindowState | null

{ try { const content = await Bun . file ( this . stateFile ) . text ( ) ; return JSON . parse ( content ) ; } catch { return null ; } } async restore ( window : BrowserWindow ) { const state = await this . load ( ) ; if ( ! state ) return false ; window . move ( { x : state . x , y : state . y } ) ; window . resize ( { width : state . width , height : state . height } ) ; if ( state . maximized ) { window . maximize ( ) ; } return true ; } startTracking ( window : BrowserWindow ) { let saveTimeout : Timer ; const saveState = ( ) => { clearTimeout ( saveTimeout ) ; saveTimeout = setTimeout ( async ( ) => { const bounds = window . getBounds ( ) ; await this . save ( { x : bounds . x , y : bounds . y , width : bounds . width , height : bounds . height , maximized : window . isMaximized ( ) , } ) ; } , 500 ) ; } ; window . on ( "move" , saveState ) ; window . on ( "resize" , saveState ) ; } } // Usage const stateManager = new WindowStateManager ( "main" ) ; const win = new BrowserWindow ( { width : 1200 , height : 800 } ) ; await stateManager . restore ( win ) ; stateManager . startTracking ( win ) ; Window Groups & Parent-Child class WindowGroup { private parent : BrowserWindow ; private children : BrowserWindow [ ] = [ ] ; constructor ( parent : BrowserWindow ) { this . parent = parent ; // Close children when parent closes parent . on ( "close" , ( ) => { this . closeAllChildren ( ) ; } ) ; } addChild ( options : any ) { const child = new BrowserWindow ( { ... options , parent : this . parent , } ) ; this . children . push ( child ) ; child . on ( "close" , ( ) => { const index = this . children . indexOf ( child ) ; if ( index

- 1 ) { this . children . splice ( index , 1 ) ; } } ) ; return child ; } closeAllChildren ( ) { this . children . forEach ( child => child . close ( ) ) ; this . children = [ ] ; } showAll ( ) { this . parent . show ( ) ; this . children . forEach ( child => child . show ( ) ) ; } hideAll ( ) { this . parent . hide ( ) ; this . children . forEach ( child => child . hide ( ) ) ; } } // Usage const mainWindow = new BrowserWindow ( { width : 1200 , height : 800 } ) ; const group = new WindowGroup ( mainWindow ) ; const palette = group . addChild ( { url : "views://palette/index.html" , width : 250 , height : 600 , frame : false , } ) ; const inspector = group . addChild ( { url : "views://inspector/index.html" , width : 300 , height : 400 , } ) ; Window Orchestration Broadcasting to All Windows class WindowBroadcaster { private windows : Set < BrowserWindow

= new Set ( ) ; register ( window : BrowserWindow ) { this . windows . add ( window ) ; window . on ( "close" , ( ) => { this . windows . delete ( window ) ; } ) ; } async broadcast ( method : string , ... args : any [ ] ) { const promises = Array . from ( this . windows ) . map ( win => win . rpc [ method ] ( ... args ) . catch ( err => { console . error ( Broadcast to window failed: , err ) ; } ) ) ; await Promise . allSettled ( promises ) ; } } const broadcaster = new WindowBroadcaster ( ) ; // Register windows broadcaster . register ( mainWindow ) ; broadcaster . register ( settingsWindow ) ; // Broadcast to all await broadcaster . broadcast ( "updateTheme" , { theme : "dark" } ) ; Window Communication Hub class WindowHub { private windows = new Map < string , BrowserWindow

( ) ; register ( id : string , window : BrowserWindow ) { this . windows . set ( id , window ) ; // Setup RPC handler for messaging window . defineRpc ( { handlers : { sendToWindow : async ( targetId : string , method : string , ... args : any [ ] ) => { return this . send ( targetId , method , ... args ) ; } } } ) ; } async send ( targetId : string , method : string , ... args : any [ ] ) { const target = this . windows . get ( targetId ) ; if ( ! target ) { throw new Error ( Window ${ targetId } not found ) ; } return await target . rpc [ method ] ( ... args ) ; } async broadcast ( method : string , ... args : any [ ] ) { const results = new Map ( ) ; for ( const [ id , window ] of this . windows ) { try { const result = await window . rpc [ method ] ( ... args ) ; results . set ( id , result ) ; } catch ( err ) { results . set ( id , { error : err . message } ) ; } } return results ; } } const hub = new WindowHub ( ) ; hub . register ( "main" , mainWindow ) ; hub . register ( "editor" , editorWindow ) ; // Send from main to editor await hub . send ( "editor" , "updateContent" , { text : "Hello" } ) ; // Broadcast to all await hub . broadcast ( "refreshData" ) ; Floating Windows & Overlays Always-on-Top Window const floatingWindow = new BrowserWindow ( { url : "views://floating/index.html" , width : 300 , height : 200 , frame : false , alwaysOnTop : true , skipTaskbar : true , } ) ; // Toggle always-on-top floatingWindow . setAlwaysOnTop ( ! floatingWindow . isAlwaysOnTop ( ) ) ; Picture-in-Picture Mode class PictureInPicture { private pipWindow : BrowserWindow | null = null ; private sourceWindow : BrowserWindow ; constructor ( sourceWindow : BrowserWindow ) { this . sourceWindow = sourceWindow ; } enter ( url : string ) { if ( this . pipWindow ) return ; this . pipWindow = new BrowserWindow ( { url , width : 400 , height : 300 , frame : false , alwaysOnTop : true , resizable : true , } ) ; this . pipWindow . on ( "close" , ( ) => { this . pipWindow = null ; } ) ; } exit ( ) { if ( this . pipWindow ) { this . pipWindow . close ( ) ; this . pipWindow = null ; } } toggle ( url : string ) { if ( this . pipWindow ) { this . exit ( ) ; } else { this . enter ( url ) ; } } } const pip = new PictureInPicture ( mainWindow ) ; pip . enter ( "views://video-player/index.html" ) ; Advanced Patterns Modal Dialogs function showModal ( parent : BrowserWindow , options : any ) { const modal = new BrowserWindow ( { ... options , parent , modal : true , frame : false , } ) ; // Disable parent interaction parent . setEnabled ( false ) ; modal . on ( "close" , ( ) => { parent . setEnabled ( true ) ; parent . focus ( ) ; } ) ; return modal ; } // Usage const confirmDialog = showModal ( mainWindow , { url : "views://confirm/index.html" , width : 400 , height : 200 , } ) ; Window Positioning function centerWindow ( window : BrowserWindow ) { const { screen } = require ( "electrobun/bun" ) ; const display = screen . getPrimaryDisplay ( ) ; const { width : screenWidth , height : screenHeight } = display . workArea ; const { width , height } = window . getBounds ( ) ; const x = Math . floor ( ( screenWidth - width ) / 2 ) ; const y = Math . floor ( ( screenHeight - height ) / 2 ) ; window . move ( { x , y } ) ; } function cascadeWindows ( windows : BrowserWindow [ ] ) { const offset = 30 ; windows . forEach ( ( win , index ) => { win . move ( { x : 100 + ( index * offset ) , y : 100 + ( index * offset ) } ) ; } ) ; } Resources For more on Electrobun: Core skill : electrobun - Basic window creation and APIs RPC patterns : electrobun-rpc-patterns - Window-to-window RPC Native UI : electrobun-native-ui - Menus and tray integration

返回排行榜