147 lines
		
	
	
		
			4.6 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			147 lines
		
	
	
		
			4.6 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
| import {
 | |
|     bind,
 | |
|     exec,
 | |
|     readFile
 | |
| } from 'astal';
 | |
| import AstalHyprland from 'gi://AstalHyprland';
 | |
| import {
 | |
|     Gtk
 | |
| } from 'astal/gtk4';
 | |
| import Pango from 'gi://Pango?version=1.0';
 | |
| 
 | |
| const hypr = AstalHyprland.get_default();
 | |
| 
 | |
| const Workspace = () => {
 | |
|     return (
 | |
|         <box>
 | |
|             {bind( hypr, 'workspaces' ).as( wss => wss
 | |
|                 .filter( ws => !( ws.id >= -99 && ws.id <= -2 ) ) // filter out special workspaces
 | |
|                 .sort( ( a, b ) => a.id - b.id )
 | |
|                 .map( ws => (
 | |
|                     <button
 | |
|                         cssClasses={bind( hypr, 'focusedWorkspace' ).as( fw => ws === fw
 | |
|                             ? [
 | |
|                                 'focused-workspace-button',
 | |
|                                 'workspace-button',
 | |
|                             ]
 | |
|                             : [ 'workspace-button' ], )}
 | |
|                         onButtonPressed={() => ws.focus()}
 | |
|                         child={<label label={String( ws.id )}></label>}
 | |
|                     ></button>
 | |
|                 ) ), )}
 | |
|         </box>
 | |
|     );
 | |
| };
 | |
| 
 | |
| /**
 | |
|  * Displays the name of the currently active window and provides a popover for
 | |
|  * displaying all available clients
 | |
|  */
 | |
| const ActiveWindow = () => {
 | |
|     const focused = bind( hypr, 'focusedClient' );
 | |
| 
 | |
|     const WindowPopover = (): Gtk.Popover => {
 | |
|         // Set up boxes + Popover
 | |
|         const popover = new Gtk.Popover();
 | |
|         const popoverBox = WindowPopoverBox();
 | |
| 
 | |
|         popover.set_child( popoverBox );
 | |
| 
 | |
|         return popover;
 | |
|     };
 | |
| 
 | |
|     const windowPopover = WindowPopover();
 | |
| 
 | |
|     // ───────────────────────────────────────────────────────────────────
 | |
|     // Return fully assembled HyprlandFocusedClient box
 | |
|     // ───────────────────────────────────────────────────────────────────
 | |
|     return (
 | |
|         <box visible={focused.as( Boolean )}>
 | |
|             <button
 | |
|                 onClicked={() => windowPopover.popup()}
 | |
|                 cssClasses={[ 'bar-button' ]}
 | |
|                 child={
 | |
|                     focused.as( client => client && (
 | |
|                         <label
 | |
|                             maxWidthChars={70}
 | |
|                             ellipsize={Pango.EllipsizeMode.END}
 | |
|                             label={bind( client, 'title' ).as( String )} />
 | |
|                     ), )
 | |
|                 }></button>
 | |
|             {windowPopover}
 | |
|         </box >
 | |
|     );
 | |
| };
 | |
| 
 | |
| type submaps = 'device' | 'launch' | 'workspace' | 'windowing' | 'screenshotting' | 'notifications' | '';
 | |
| 
 | |
| const ModeStatus = () => {
 | |
|     let isUsingHyprvim = false;
 | |
| 
 | |
|     try {
 | |
|         const path = exec( 'bash -c "cd ~ && pwd"' ) + '/.config/hyprvim';
 | |
| 
 | |
|         isUsingHyprvim = readFile( path ).trim() === 'y';
 | |
|     } catch ( e ) {
 | |
|         printerr( 'Failed to read hyprvim config', e );
 | |
|     }
 | |
| 
 | |
|     const label = new Gtk.Label();
 | |
| 
 | |
|     if ( !isUsingHyprvim ) return label;
 | |
| 
 | |
|     print( '==> Using hyprvim config' );
 | |
| 
 | |
|     const map = {
 | |
|         'device': 'DEV',
 | |
|         'launch': 'LNC',
 | |
|         'workspace': 'WSP',
 | |
|         'windowing': 'WIN',
 | |
|         'screenshotting': 'SCS',
 | |
|         'notifications': 'NOT',
 | |
|         '': 'NRM'
 | |
|     };
 | |
| 
 | |
|     label.label = map[''];
 | |
|     label.cssClasses = [ 'mode-status' ];
 | |
| 
 | |
|     // TODO: Possibly add popover to it that lists binds
 | |
|     hypr.connect( 'submap', ( _, name: submaps ) => {
 | |
|         label.label = map[name];
 | |
|         label.cssClasses = [
 | |
|             'mode-status',
 | |
|             name + '-mode'
 | |
|         ];
 | |
|     } );
 | |
| 
 | |
|     return label;
 | |
| };
 | |
| 
 | |
| const WindowPopoverBox = () => {
 | |
|     return <box vertical>
 | |
|         <label label={'Available Windows'} cssClasses={[ 'title-2' ]}></label>
 | |
|         <Gtk.Separator marginTop={5} marginBottom={5}></Gtk.Separator>
 | |
|         <box vertical>
 | |
|             {bind( hypr, 'clients' ).as( clients => {
 | |
|                 return clients.map( client => {
 | |
|                     return <button child={
 | |
|                         <box>
 | |
|                             <label label={bind( client, 'workspace' ).as( w => `(WS ${ w.name })` )}></label>
 | |
|                             <label label={bind( client, 'initialClass' ).as( c => `[${ c }]` )}></label>
 | |
|                             <label label={bind( client, 'title' )}></label>
 | |
|                         </box>
 | |
|                     }
 | |
|                     onClicked={() => client.focus()}
 | |
|                     ></button>;
 | |
|                 } );
 | |
|             } )}
 | |
|         </box>
 | |
|     </box>;
 | |
| };
 | |
| 
 | |
| export default {
 | |
|     Workspace,
 | |
|     ActiveWindow,
 | |
|     ModeStatus
 | |
| };
 |