[Astal] Finish modes, move tray into quickactions menu

This commit is contained in:
2025-10-17 10:43:50 +02:00
parent 00d4f101fc
commit 539ec34b4c
6 changed files with 175 additions and 108 deletions

View File

@@ -1,44 +1,58 @@
import { Gtk } from "astal/gtk4";
import Power from "./modules/Power";
import Audio from "./modules/Audio/Audio";
import Bluetooth from "./modules/Bluetooth/Bluetooth";
import Brightness from "./modules/Brightness/Brightness";
import Player from "./modules/Player/Player";
import { BatteryBox } from "./modules/Battery";
import { exec } from "astal";
import Network from "./modules/Networking/Network";
import Audio from './modules/Audio/Audio';
import {
BatteryBox
} from './modules/Battery';
import Bluetooth from './modules/Bluetooth/Bluetooth';
import Brightness from './modules/Brightness/Brightness';
import {
Gtk
} from 'astal/gtk4';
import Network from './modules/Networking/Network';
import Player from './modules/Player/Player';
import Power from './modules/Power';
import SysTray from './modules/SysTray';
import {
exec
} from 'astal';
const QuickActions = () => {
const popover = new Gtk.Popover({ cssClasses: ["quick-actions-wrapper"] });
popover.set_child(renderQuickActions());
const popover = new Gtk.Popover( {
'cssClasses': [ 'quick-actions-wrapper' ]
} );
popover.set_child( renderQuickActions() );
return popover;
};
const renderQuickActions = () => {
const user = exec("/bin/sh -c whoami");
const profile = exec("/bin/fish -c get-profile-picture");
const cwd = exec("pwd");
const user = exec( '/bin/sh -c whoami' );
const profile = exec( '/bin/fish -c get-profile-picture' );
const cwd = exec( 'pwd' );
const um = Power.UserMenu();
return (
<box visible cssClasses={["quick-actions", "popover-box"]} vertical>
<box visible cssClasses={[
'quick-actions',
'popover-box'
]} vertical>
<centerbox
startWidget={
<button
onClicked={() => um.popup()}
cssClasses={["stealthy-button"]}
cssClasses={[ 'stealthy-button' ]}
child={
<box>
{um}
<Gtk.Frame
cssClasses={["avatar-icon"]}
cssClasses={[ 'avatar-icon' ]}
child={
<image
file={
profile !== ""
profile !== ''
? profile
: cwd +
"/no-avatar-icon.jpg"
: cwd
+ '/no-avatar-icon.jpg'
}
></image>
}
@@ -53,6 +67,7 @@ const renderQuickActions = () => {
hexpand={false}
>
<BatteryBox></BatteryBox>
<SysTray.SystemTray></SysTray.SystemTray>
<Power.Power></Power.Power>
</box>
}

View File

@@ -1,48 +1,56 @@
import { exec } from "astal";
import { Gtk } from "astal/gtk4";
import {
exec
} from 'astal';
import {
Gtk
} from 'astal/gtk4';
const PowerMenu = (): Gtk.Popover => {
const popover = new Gtk.Popover({ cssClasses: ["PowerMenu"] });
const popover = new Gtk.Popover( {
'cssClasses': [ 'PowerMenu' ]
} );
const powerMenuBox = () => {
return (
<box>
<button
cssClasses={["power-button"]}
cssClasses={[ 'power-button' ]}
child={
<image iconName={"system-shutdown-symbolic"}></image>
<image iconName={'system-shutdown-symbolic'}></image>
}
onClicked={() => exec("/bin/sh -c 'shutdown now'")}
onClicked={() => exec( '/bin/sh -c \'shutdown now\'' )}
></button>
<button
cssClasses={["power-button"]}
child={<image iconName={"system-reboot-symbolic"}></image>}
onClicked={() => exec("/bin/sh -c 'reboot'")}
cssClasses={[ 'power-button' ]}
child={<image iconName={'system-reboot-symbolic'}></image>}
onClicked={() => exec( '/bin/sh -c \'reboot\'' )}
></button>
<button
cssClasses={["power-button"]}
child={<image iconName={"system-suspend-symbolic"}></image>}
onClicked={() => exec("/bin/sh -c 'systemctl suspend'")}
cssClasses={[ 'power-button' ]}
child={<image iconName={'system-suspend-symbolic'}></image>}
onClicked={() => exec( '/bin/sh -c \'systemctl suspend\'' )}
></button>
</box>
);
};
popover.set_child(powerMenuBox());
popover.set_child( powerMenuBox() );
return popover;
};
const Power = () => {
const pm = PowerMenu();
return (
<button
widthRequest={0}
hexpand={false}
vexpand={false}
cssClasses={["power-menu-button"]}
cssClasses={[ 'power-menu-button' ]}
child={
<box>
<image iconName={"system-shutdown-symbolic"}></image>
<image iconName={'system-shutdown-symbolic'}></image>
{pm}
</box>
}
@@ -58,24 +66,24 @@ const UserMenu = (): Gtk.Popover => {
return (
<box>
<button
cssClasses={["power-button"]}
cssClasses={[ 'power-button' ]}
child={
<image iconName={"system-lock-screen-symbolic"}></image>
<image iconName={'system-lock-screen-symbolic'}></image>
}
onClicked={() => exec("/bin/sh -c 'hyprlock'")}
onClicked={() => exec( '/bin/sh -c \'hyprlock\'' )}
></button>
<button
cssClasses={["power-button"]}
child={<image iconName={"system-log-out-symbolic"}></image>}
onClicked={() =>
exec("/bin/sh -c 'hyprctl dispatch exit 0'")
cssClasses={[ 'power-button' ]}
child={<image iconName={'system-log-out-symbolic'}></image>}
onClicked={() => exec( '/bin/sh -c \'hyprctl dispatch exit 0\'' )
}
></button>
</box>
);
};
popover.set_child(powerMenuBox());
popover.set_child( powerMenuBox() );
return popover;
};

View File

@@ -0,0 +1,88 @@
import AstalTray from 'gi://AstalTray';
import {
GObject
} from 'astal';
import {
Gtk
} from 'astal/gtk4';
const SYNC = GObject.BindingFlags.SYNC_CREATE;
const SysTray = () => {
const trayBox = new Gtk.Box( {
'cssClasses': [ '' ]
} );
const tray = AstalTray.get_default();
const trayItems = new Map<string, Gtk.MenuButton>();
const trayAddedHandler = tray.connect( 'item-added', ( _, id ) => {
const item = tray.get_item( id );
const popover = Gtk.PopoverMenu.new_from_model( item.menu_model );
const icon = new Gtk.Image();
const button = new Gtk.MenuButton( {
popover,
'child': icon,
'cssClasses': [ 'tray-item' ],
} );
item.bind_property(
'gicon', icon, 'gicon', SYNC
);
popover.insert_action_group( 'dbusmenu', item.action_group );
item.connect( 'notify::action-group', () => {
popover.insert_action_group( 'dbusmenu', item.action_group );
} );
trayItems.set( id, button );
trayBox.append( button );
} );
const trayRemovedHandler = tray.connect( 'item-removed', ( _, id ) => {
const button = trayItems.get( id );
if ( button ) {
trayBox.remove( button );
button.run_dispose();
trayItems.delete( id );
}
} );
trayBox.connect( 'destroy', () => {
tray.disconnect( trayAddedHandler );
tray.disconnect( trayRemovedHandler );
} );
return trayBox;
};
const TrayPopover = () => {
const popover = new Gtk.Popover( {
'cssClasses': [ 'TrayPopover' ]
} );
popover.set_child( SysTray() );
return popover;
};
const SystemTray = () => {
const systray = TrayPopover();
return (
<button
widthRequest={0}
hexpand={false}
vexpand={false}
cssClasses={[ 'power-menu-button' ]}
child={
<box>
<image iconName={'systemtray'}></image>
{systray}
</box>
}
onClicked={() => systray.popup()}
/>
);
};
export default {
SystemTray
};

View File

@@ -39,7 +39,6 @@ const Bar = ( {
>
<Hyprland.ModeStatus />
<Calendar.Time />
<SystemInfo.SystemInfo />
<Hyprland.Workspace />
</box>
}
@@ -50,7 +49,7 @@ const Bar = ( {
halign={Gtk.Align.END}
cssClasses={[ 'BarRight' ]}
>
<Hyprland.SysTray />
<SystemInfo.SystemInfo />
<QuickView.QuickView />
</box>
}

View File

@@ -20,6 +20,11 @@ window.Bar {
border-radius: 20px;
font-family: $monospace-font;
&.command-mode {
background-color: darkslategray;
color: white;
}
&.windowing-mode {
background-color: darkslategray;
color: white;

View File

@@ -1,62 +1,15 @@
import {
GObject, bind,
bind,
exec,
readFile
} from 'astal';
import AstalHyprland from 'gi://AstalHyprland';
import AstalTray from 'gi://AstalTray';
import {
Gtk
} from 'astal/gtk4';
import Pango from 'gi://Pango?version=1.0';
const hypr = AstalHyprland.get_default();
const SYNC = GObject.BindingFlags.SYNC_CREATE;
const SysTray = () => {
const trayBox = new Gtk.Box( {
'cssClasses': [ 'bar-button' ]
} );
const tray = AstalTray.get_default();
const trayItems = new Map<string, Gtk.MenuButton>();
const trayAddedHandler = tray.connect( 'item-added', ( _, id ) => {
const item = tray.get_item( id );
const popover = Gtk.PopoverMenu.new_from_model( item.menu_model );
const icon = new Gtk.Image();
const button = new Gtk.MenuButton( {
popover,
'child': icon,
'cssClasses': [ 'tray-item' ],
} );
item.bind_property(
'gicon', icon, 'gicon', SYNC
);
popover.insert_action_group( 'dbusmenu', item.action_group );
item.connect( 'notify::action-group', () => {
popover.insert_action_group( 'dbusmenu', item.action_group );
} );
trayItems.set( id, button );
trayBox.append( button );
} );
const trayRemovedHandler = tray.connect( 'item-removed', ( _, id ) => {
const button = trayItems.get( id );
if ( button ) {
trayBox.remove( button );
button.run_dispose();
trayItems.delete( id );
}
} );
trayBox.connect( 'destroy', () => {
tray.disconnect( trayAddedHandler );
tray.disconnect( trayRemovedHandler );
} );
return trayBox;
};
const Workspace = () => {
return (
@@ -123,33 +76,33 @@ const ActiveWindow = () => {
type submaps = 'device' | 'launch' | 'workspace' | 'windowing' | 'screenshotting' | 'notifications' | '';
const ModeStatus = () => {
let isUsingHyprmode = false;
let isUsingHyprvim = false;
try {
const path = exec( 'bash -c "cd ~ && pwd"' ) + '/.config/hyprmode';
const path = exec( 'bash -c "cd ~ && pwd"' ) + '/.config/hyprvim';
isUsingHyprmode = readFile( path ).trim() === 'y';
isUsingHyprvim = readFile( path ).trim() === 'y';
} catch ( e ) {
printerr( 'Failed to read hyprmode config', e );
printerr( 'Failed to read hyprvim config', e );
}
const label = new Gtk.Label();
if ( !isUsingHyprmode ) return label;
if ( !isUsingHyprvim ) return label;
print( '==> Using hyprmode config' );
print( '==> Using hyprvim config' );
const map = {
'device': 'D',
'launch': 'L',
'workspace': 'W',
'windowing': 'M',
'screenshotting': 'S',
'notifications': 'N',
'': 'N'
'device': 'DEV',
'launch': 'LNC',
'workspace': 'WSP',
'windowing': 'WIN',
'screenshotting': 'SCS',
'notifications': 'NOT',
'': 'NRM'
};
label.label = 'N';
label.label = map[''];
label.cssClasses = [ 'mode-status' ];
// TODO: Possibly add popover to it that lists binds
@@ -189,6 +142,5 @@ const WindowPopoverBox = () => {
export default {
Workspace,
ActiveWindow,
SysTray,
ModeStatus
};