[AGS] Remove old modules
This commit is contained in:
		
							
								
								
									
										2
									
								
								config/ags/bar/.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								config/ags/bar/.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -1,2 +0,0 @@ | ||||
| node_modules/ | ||||
| @girs/ | ||||
| @@ -1,10 +0,0 @@ | ||||
| import { App } from "astal/gtk4" | ||||
| import style from "./style.scss" | ||||
| import Bar from "./ui/Bar" | ||||
|  | ||||
| App.start({ | ||||
|     css: style, | ||||
|     main() { | ||||
|         App.get_monitors().map(Bar) | ||||
|     }, | ||||
| }) | ||||
| @@ -1,886 +0,0 @@ | ||||
|  | ||||
| import GLib from "gi://GLib"; | ||||
| import Astal from "gi://Astal"; | ||||
| import AstalHyprland from "gi://AstalHyprland"; | ||||
| import Gio from "gi://Gio"; | ||||
| import Gtk from "gi://Gtk"; | ||||
| import Gdk from "gi://Gdk"; | ||||
| import { exec } from "gi://GLib"; | ||||
|  | ||||
| function getSystemStats() { | ||||
|     const cpu = exec("sh -c 'top -bn1 | grep \"Cpu(s)\" | sed \"s/.*, *\\([0-9.]*\\)%* id.*/\\1/\" | awk \"{print 100 - $1}\"'"); | ||||
|     const memory = exec("free | grep Mem | awk '{print $3/$2 * 100.0}'"); | ||||
|     const brightness = exec("brightnessctl g"); | ||||
|     const battery = exec("cat /sys/class/power_supply/BAT0/capacity"); | ||||
|     return { cpu, memory, brightness, battery }; | ||||
| } | ||||
|  | ||||
| function getWorkspaceNumber() { | ||||
|     return AstalHyprland.get_default().get_active_workspace().get_id(); | ||||
| } | ||||
|  | ||||
| function getWindowTitle() { | ||||
|     return exec("xdotool getactivewindow getwindowname"); | ||||
| } | ||||
|  | ||||
| function getDateTime() { | ||||
|     return GLib.DateTime.new_now_local().format("%a %b %d, %Y %H:%M:%S"); | ||||
| } | ||||
|  | ||||
| function createQuickActionMenu() { | ||||
|     const menu = new Gtk.Menu(); | ||||
|     const volumeItem = new Gtk.MenuItem({ label: "🔊 Volume" }); | ||||
|     const micItem = new Gtk.MenuItem({ label: "🎙️ Microphone" }); | ||||
|     const wifiItem = new Gtk.MenuItem({ label: "📶 WiFi" }); | ||||
|     const powerItem = new Gtk.MenuItem({ label: "🔌 Power" }); | ||||
|  | ||||
|     menu.append(volumeItem); | ||||
|     menu.append(micItem); | ||||
|     menu.append(wifiItem); | ||||
|     menu.append(powerItem); | ||||
|  | ||||
|     volumeItem.show(); | ||||
|     micItem.show(); | ||||
|     wifiItem.show(); | ||||
|     powerItem.show(); | ||||
|  | ||||
|     return menu; | ||||
| } | ||||
|  | ||||
| function Bar(gdkmonitor) { | ||||
|     const { cpu, memory, brightness, battery } = getSystemStats(); | ||||
|     const workspaceNumber = getWorkspaceNumber(); | ||||
|     const windowTitle = getWindowTitle(); | ||||
|     const dateTime = getDateTime(); | ||||
|     const quickActionMenu = createQuickActionMenu(); | ||||
|  | ||||
|     return ( | ||||
|         <window gdkmonitor={gdkmonitor}> | ||||
|             <box orientation="horizontal" spacing={10}> | ||||
|                 <box> | ||||
|                     <label>{dateTime}</label> | ||||
|                     <label>{`CPU: ${cpu}%`}</label> | ||||
|                     <label>{`Mem: ${memory}%`}</label> | ||||
|                     <label>{`Brightness: ${brightness}%`}</label> | ||||
|                     <label>{`Battery: ${battery}%`}</label> | ||||
|                     <label>{`Workspace: ${workspaceNumber}`}</label> | ||||
|                 </box> | ||||
|                 <label>{windowTitle}</label> | ||||
|                 <box> | ||||
|                     <tray /> | ||||
|                     <button icon="quickaction" menu={quickActionMenu} /> | ||||
|                 </box> | ||||
|             </box> | ||||
|         </window> | ||||
|     ); | ||||
| } | ||||
|  | ||||
| function main() { | ||||
|     for (const m of AstalHyprland.get_default().get_monitors()) { | ||||
|         Bar(m.gdk_monitor); | ||||
|     } | ||||
| } | ||||
|  | ||||
| App.start({ main }); | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| import GLib from "gi://GLib"; | ||||
| import Astal from "gi://Astal"; | ||||
| import AstalHyprland from "gi://AstalHyprland"; | ||||
| import Gtk from "gi://Gtk"; | ||||
| import { exec } from "gi://GLib"; | ||||
| import { createQuickActionsMenu } from "./quickactions.js"; | ||||
|  | ||||
| function getSystemStats() { | ||||
|     const cpu = exec("sh -c 'top -bn1 | grep \"Cpu(s)\" | sed \"s/.*, *\\([0-9.]*\\)%* id.*/\\1/\" | awk \"{print 100 - $1}\"'"); | ||||
|     const memory = exec("free | grep Mem | awk '{print $3/$2 * 100.0}'"); | ||||
|     const brightness = exec("brightnessctl g"); | ||||
|     const battery = exec("cat /sys/class/power_supply/BAT0/capacity"); | ||||
|     return { cpu, memory, brightness, battery }; | ||||
| } | ||||
|  | ||||
| function getWorkspaceNumber() { | ||||
|     return AstalHyprland.get_default().get_active_workspace().get_id(); | ||||
| } | ||||
|  | ||||
| function getWindowTitle() { | ||||
|     return exec("xdotool getactivewindow getwindowname"); | ||||
| } | ||||
|  | ||||
| function getDateTime() { | ||||
|     return GLib.DateTime.new_now_local().format("%a %b %d, %Y %H:%M:%S"); | ||||
| } | ||||
|  | ||||
| function Bar(gdkmonitor) { | ||||
|     const { cpu, memory, brightness, battery } = getSystemStats(); | ||||
|     const workspaceNumber = getWorkspaceNumber(); | ||||
|     const windowTitle = getWindowTitle(); | ||||
|     const dateTime = getDateTime(); | ||||
|     const quickActionMenu = createQuickActionsMenu(); | ||||
|  | ||||
|     return ( | ||||
|         <window gdkmonitor={gdkmonitor}> | ||||
|             <box orientation="horizontal" spacing={10}> | ||||
|                 <box> | ||||
|                     <label>{dateTime}</label> | ||||
|                     <label>{`CPU: ${cpu}%`}</label> | ||||
|                     <label>{`Mem: ${memory}%`}</label> | ||||
|                     <label>{`Brightness: ${brightness}%`}</label> | ||||
|                     <label>{`Battery: ${battery}%`}</label> | ||||
|                     <label>{`Workspace: ${workspaceNumber}`}</label> | ||||
|                 </box> | ||||
|                 <label>{windowTitle}</label> | ||||
|                 <box> | ||||
|                     <tray /> | ||||
|                     <button icon="quickaction" menu={quickActionMenu} /> | ||||
|                 </box> | ||||
|             </box> | ||||
|         </window> | ||||
|     ); | ||||
| } | ||||
|  | ||||
| function main() { | ||||
|     for (const m of AstalHyprland.get_default().get_monitors()) { | ||||
|         Bar(m.gdk_monitor); | ||||
|     } | ||||
| } | ||||
|  | ||||
| App.start({ main }); | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| import AstalNetwork from "gi://AstalNetwork"; | ||||
| import AstalBluetooth from "gi://AstalBluetooth"; | ||||
| import Gtk from "gi://Gtk"; | ||||
|  | ||||
| function createQuickActionsMenu() { | ||||
|     const menu = new Gtk.Menu(); | ||||
|  | ||||
|     const wifiItem = new Gtk.MenuItem({ label: "📶 WiFi" }); | ||||
|     const bluetoothItem = new Gtk.MenuItem({ label: "🔵 Bluetooth" }); | ||||
|     const volumeItem = new Gtk.MenuItem({ label: "🔊 Volume" }); | ||||
|     const micItem = new Gtk.MenuItem({ label: "🎙️ Microphone" }); | ||||
|     const powerItem = new Gtk.MenuItem({ label: "🔌 Power" }); | ||||
|  | ||||
|     menu.append(wifiItem); | ||||
|     menu.append(bluetoothItem); | ||||
|     menu.append(volumeItem); | ||||
|     menu.append(micItem); | ||||
|     menu.append(powerItem); | ||||
|  | ||||
|     wifiItem.connect("activate", () => toggleWiFi()); | ||||
|     bluetoothItem.connect("activate", () => toggleBluetooth()); | ||||
|     volumeItem.connect("activate", () => adjustVolume()); | ||||
|     micItem.connect("activate", () => adjustMic()); | ||||
|     powerItem.connect("activate", () => showPowerMenu()); | ||||
|  | ||||
|     wifiItem.show(); | ||||
|     bluetoothItem.show(); | ||||
|     volumeItem.show(); | ||||
|     micItem.show(); | ||||
|     powerItem.show(); | ||||
|  | ||||
|     return menu; | ||||
| } | ||||
|  | ||||
| function toggleWiFi() { | ||||
|     const network = AstalNetwork.get_default(); | ||||
|     const wifi = network.get_wifi(); | ||||
|     const state = wifi.get_state(); | ||||
|  | ||||
|     if (state === AstalNetwork.WifiState.DISCONNECTED) { | ||||
|         wifi.connect(); | ||||
|     } else { | ||||
|         wifi.disconnect(); | ||||
|     } | ||||
| } | ||||
|  | ||||
| function toggleBluetooth() { | ||||
|     const bluetooth = AstalBluetooth.get_default(); | ||||
|     const adapter = bluetooth.get_adapter(); | ||||
|     const powered = adapter.get_powered(); | ||||
|  | ||||
|     adapter.set_powered(!powered); | ||||
| } | ||||
|  | ||||
| function adjustVolume() { | ||||
|     exec("pavucontrol"); | ||||
| } | ||||
|  | ||||
| function adjustMic() { | ||||
|     exec("pavucontrol"); | ||||
| } | ||||
|  | ||||
| function showPowerMenu() { | ||||
|     exec("power-menu"); | ||||
| } | ||||
|  | ||||
| export { createQuickActionsMenu }; | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| // colors.scss | ||||
| $accent: #4a90e2;            // Primary accent color (change this) | ||||
| $bg: #1e1e2e;                // Background | ||||
| $fg: #f8f8f2;                // Foreground/text | ||||
| $hover: lighten($accent, 10%); | ||||
| $border: rgba(255, 255, 255, 0.1); | ||||
|  | ||||
|  | ||||
|  | ||||
| @import "colors"; | ||||
|  | ||||
| * { | ||||
|   all: unset; | ||||
|   font-family: "JetBrainsMono Nerd Font", monospace; | ||||
|   font-size: 14px; | ||||
|   color: $fg; | ||||
| } | ||||
|  | ||||
| window { | ||||
|   background-color: transparent; | ||||
| } | ||||
|  | ||||
| box { | ||||
|   background-color: $bg; | ||||
|   border-radius: 16px; | ||||
|   padding: 6px 12px; | ||||
|   border: 1px solid $border; | ||||
|   margin: 8px; | ||||
|   box-shadow: 0px 4px 12px rgba(0, 0, 0, 0.3); | ||||
| } | ||||
|  | ||||
| label { | ||||
|   padding: 0 8px; | ||||
| } | ||||
|  | ||||
| // Clickable buttons/icons (e.g. QuickAction, tray items) | ||||
| button { | ||||
|   background-color: transparent; | ||||
|   border-radius: 12px; | ||||
|   padding: 6px; | ||||
|   transition: background-color 0.2s ease-in-out; | ||||
|  | ||||
|   &:hover { | ||||
|     background-color: $hover; | ||||
|   } | ||||
| } | ||||
|  | ||||
| // System Tray area | ||||
| tray { | ||||
|   padding: 0 8px; | ||||
| } | ||||
|  | ||||
| // Layout specifics | ||||
| .left-section, | ||||
| .center-section, | ||||
| .right-section { | ||||
|   padding: 0 12px; | ||||
| } | ||||
|  | ||||
| .left-section { | ||||
|   border-right: 1px solid $border; | ||||
| } | ||||
|  | ||||
| .right-section { | ||||
|   border-left: 1px solid $border; | ||||
| } | ||||
|  | ||||
| // Icons (you'll replace them with fluentui icons) | ||||
| .icon { | ||||
|   font-family: "FluentUI System Icons"; // Ensure this font is loaded | ||||
|   font-size: 16px; | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| import Gtk from "gi://Gtk"; | ||||
| import AstalNetwork from "gi://AstalNetwork"; | ||||
| import AstalBluetooth from "gi://AstalBluetooth"; | ||||
| import { exec } from "gi://GLib"; | ||||
|  | ||||
| let quickActionsMenu; | ||||
|  | ||||
| // Toggle WiFi connection | ||||
| function toggleWiFi() { | ||||
|     const network = AstalNetwork.get_default(); | ||||
|     const wifi = network.get_wifi(); | ||||
|     const state = wifi.get_state(); | ||||
|  | ||||
|     if (state === AstalNetwork.WifiState.DISCONNECTED) { | ||||
|         wifi.connect(); | ||||
|     } else { | ||||
|         wifi.disconnect(); | ||||
|     } | ||||
| } | ||||
|  | ||||
| // Toggle Bluetooth power state | ||||
| function toggleBluetooth() { | ||||
|     const bluetooth = AstalBluetooth.get_default(); | ||||
|     const adapter = bluetooth.get_adapter(); | ||||
|     const powered = adapter.get_powered(); | ||||
|  | ||||
|     adapter.set_powered(!powered); | ||||
| } | ||||
|  | ||||
| // Adjust volume or microphone (opens pavucontrol) | ||||
| function adjustVolume() { | ||||
|     exec("pavucontrol"); | ||||
| } | ||||
|  | ||||
| function adjustMic() { | ||||
|     exec("pavucontrol"); | ||||
| } | ||||
|  | ||||
| // Power menu | ||||
| function showPowerMenu() { | ||||
|     exec("power-menu"); | ||||
| } | ||||
|  | ||||
| // Show WiFi network picker | ||||
| function pickWiFi() { | ||||
|     const wifi = AstalNetwork.get_default().get_wifi(); | ||||
|     wifi.show_picker(); | ||||
| } | ||||
|  | ||||
| // Show Bluetooth device picker | ||||
| function pickBluetooth() { | ||||
|     const bluetooth = AstalBluetooth.get_default(); | ||||
|     bluetooth.show_picker(); | ||||
| } | ||||
|  | ||||
| // Create menu using JSX | ||||
| function createQuickActionsMenu() { | ||||
|     quickActionsMenu = ( | ||||
|         <menu> | ||||
|             <item label="📶 WiFi" onActivate={toggleWiFi} /> | ||||
|             <item label="→ Pick Network" onActivate={pickWiFi} /> | ||||
|  | ||||
|             <item label="🔵 Bluetooth" onActivate={toggleBluetooth} /> | ||||
|             <item label="→ Pick Device" onActivate={pickBluetooth} /> | ||||
|  | ||||
|             <item label="🔊 Volume" onActivate={adjustVolume} /> | ||||
|             <item label="🎙️ Microphone" onActivate={adjustMic} /> | ||||
|             <item label="🔌 Power" onActivate={showPowerMenu} /> | ||||
|         </menu> | ||||
|     ); | ||||
|  | ||||
|     return quickActionsMenu; | ||||
| } | ||||
|  | ||||
| // Export the function | ||||
| export { createQuickActionsMenu }; | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| import Gtk from "gi://Gtk"; | ||||
| import AstalNetwork from "gi://AstalNetwork"; | ||||
| import AstalBluetooth from "gi://AstalBluetooth"; | ||||
| import { exec } from "gi://GLib"; | ||||
|  | ||||
| function toggleWiFi() { | ||||
|     const network = AstalNetwork.get_default(); | ||||
|     const wifi = network.get_wifi(); | ||||
|     wifi.get_state() === AstalNetwork.WifiState.DISCONNECTED | ||||
|         ? wifi.connect() | ||||
|         : wifi.disconnect(); | ||||
| } | ||||
|  | ||||
| function toggleBluetooth() { | ||||
|     const adapter = AstalBluetooth.get_default().get_adapter(); | ||||
|     adapter.set_powered(!adapter.get_powered()); | ||||
| } | ||||
|  | ||||
| function adjustVolume() { | ||||
|     exec("pavucontrol"); | ||||
| } | ||||
|  | ||||
| function adjustMic() { | ||||
|     exec("pavucontrol"); | ||||
| } | ||||
|  | ||||
| function showPowerMenu() { | ||||
|     exec("power-menu"); | ||||
| } | ||||
|  | ||||
| // Build submenu for WiFi networks | ||||
| function buildWifiMenu() { | ||||
|     const wifi = AstalNetwork.get_default().get_wifi(); | ||||
|     const menu = new Gtk.Menu(); | ||||
|  | ||||
|     for (const ap of wifi.get_access_points()) { | ||||
|         const ssid = ap.get_ssid(); | ||||
|         const strength = ap.get_strength(); | ||||
|         const item = new Gtk.MenuItem({ label: `${ssid} (${strength}%)` }); | ||||
|  | ||||
|         item.connect("activate", () => { | ||||
|             wifi.connect_access_point(ap); | ||||
|         }); | ||||
|  | ||||
|         item.show(); | ||||
|         menu.append(item); | ||||
|     } | ||||
|  | ||||
|     return menu; | ||||
| } | ||||
|  | ||||
| // Build submenu for Bluetooth devices | ||||
| function buildBluetoothMenu() { | ||||
|     const bluetooth = AstalBluetooth.get_default(); | ||||
|     const menu = new Gtk.Menu(); | ||||
|  | ||||
|     for (const device of bluetooth.get_devices()) { | ||||
|         const name = device.get_name(); | ||||
|         const connected = device.get_connected(); | ||||
|         const label = connected ? `✔ ${name}` : name; | ||||
|  | ||||
|         const item = new Gtk.MenuItem({ label }); | ||||
|  | ||||
|         item.connect("activate", () => { | ||||
|             if (!connected) { | ||||
|                 device.connect_device(); | ||||
|             } else { | ||||
|                 device.disconnect_device(); | ||||
|             } | ||||
|         }); | ||||
|  | ||||
|         item.show(); | ||||
|         menu.append(item); | ||||
|     } | ||||
|  | ||||
|     return menu; | ||||
| } | ||||
|  | ||||
| function createQuickActionsMenu() { | ||||
|     const wifiPicker = new Gtk.MenuItem({ label: "→ Pick Network ▸" }); | ||||
|     const btPicker = new Gtk.MenuItem({ label: "→ Pick Device ▸" }); | ||||
|  | ||||
|     const wifiSubMenu = new Gtk.Menu(); | ||||
|     const btSubMenu = new Gtk.Menu(); | ||||
|  | ||||
|     // Populate submenus on open | ||||
|     wifiPicker.connect("activate", () => { | ||||
|         wifiSubMenu.foreach(child => wifiSubMenu.remove(child)); | ||||
|         const newMenu = buildWifiMenu(); | ||||
|         newMenu.foreach(child => wifiSubMenu.append(child)); | ||||
|         wifiSubMenu.show_all(); | ||||
|     }); | ||||
|  | ||||
|     btPicker.connect("activate", () => { | ||||
|         btSubMenu.foreach(child => btSubMenu.remove(child)); | ||||
|         const newMenu = buildBluetoothMenu(); | ||||
|         newMenu.foreach(child => btSubMenu.append(child)); | ||||
|         btSubMenu.show_all(); | ||||
|     }); | ||||
|  | ||||
|     wifiPicker.set_submenu(wifiSubMenu); | ||||
|     btPicker.set_submenu(btSubMenu); | ||||
|  | ||||
|     return ( | ||||
|         <menu> | ||||
|             <item label="📶 WiFi" onActivate={toggleWiFi} /> | ||||
|             {wifiPicker} | ||||
|  | ||||
|             <item label="🔵 Bluetooth" onActivate={toggleBluetooth} /> | ||||
|             {btPicker} | ||||
|  | ||||
|             <item label="🔊 Volume" onActivate={adjustVolume} /> | ||||
|             <item label="🎙️ Microphone" onActivate={adjustMic} /> | ||||
|             <item label="🔌 Power" onActivate={showPowerMenu} /> | ||||
|         </menu> | ||||
|     ); | ||||
| } | ||||
|  | ||||
| export { createQuickActionsMenu }; | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| import Gtk from "gi://Gtk"; | ||||
| import AstalNetwork from "gi://AstalNetwork"; | ||||
| import AstalBluetooth from "gi://AstalBluetooth"; | ||||
| import { exec } from "gi://GLib"; | ||||
|  | ||||
| function createToggleRow({ label, active, onToggle, onExpand }) { | ||||
|     return ( | ||||
|         <box className="toggle-row" orientation="horizontal"> | ||||
|             <button className={active ? "toggle active" : "toggle"} onClicked={onToggle}> | ||||
|                 {label} | ||||
|             </button> | ||||
|             <button className="arrow" onClicked={onExpand}> | ||||
|                 > | ||||
|             </button> | ||||
|         </box> | ||||
|     ); | ||||
| } | ||||
|  | ||||
| function createQuickActionsMenu() { | ||||
|     const wifi = AstalNetwork.get_default().get_wifi(); | ||||
|     const bt = AstalBluetooth.get_default().get_adapter(); | ||||
|  | ||||
|     const wifiSub = new Gtk.Menu(); | ||||
|     const btSub = new Gtk.Menu(); | ||||
|  | ||||
|     function refreshWifiMenu() { | ||||
|         wifiSub.foreach(c => wifiSub.remove(c)); | ||||
|         for (const ap of wifi.get_access_points()) { | ||||
|             const item = new Gtk.MenuItem({ label: `${ap.get_ssid()} (${ap.get_strength()}%)` }); | ||||
|             item.connect("activate", () => wifi.connect_access_point(ap)); | ||||
|             item.show(); | ||||
|             wifiSub.append(item); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     function refreshBtMenu() { | ||||
|         btSub.foreach(c => btSub.remove(c)); | ||||
|         for (const dev of AstalBluetooth.get_default().get_devices()) { | ||||
|             const name = dev.get_name(); | ||||
|             const label = dev.get_connected() ? `✔ ${name}` : name; | ||||
|             const item = new Gtk.MenuItem({ label }); | ||||
|             item.connect("activate", () => { | ||||
|                 dev.get_connected() ? dev.disconnect_device() : dev.connect_device(); | ||||
|             }); | ||||
|             item.show(); | ||||
|             btSub.append(item); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     return ( | ||||
|         <menu className="quickactions-menu"> | ||||
|  | ||||
|             <submenu label=""> | ||||
|                 {createToggleRow({ | ||||
|                     label: "📶 WiFi", | ||||
|                     active: wifi.get_state() !== AstalNetwork.WifiState.DISCONNECTED, | ||||
|                     onToggle: () => { | ||||
|                         wifi.get_state() === AstalNetwork.WifiState.DISCONNECTED ? wifi.connect() : wifi.disconnect(); | ||||
|                     }, | ||||
|                     onExpand: () => { | ||||
|                         refreshWifiMenu(); | ||||
|                         wifiSub.popup(); | ||||
|                     } | ||||
|                 })} | ||||
|             </submenu> | ||||
|  | ||||
|             <submenu label=""> | ||||
|                 {createToggleRow({ | ||||
|                     label: "🔵 Bluetooth", | ||||
|                     active: bt.get_powered(), | ||||
|                     onToggle: () => bt.set_powered(!bt.get_powered()), | ||||
|                     onExpand: () => { | ||||
|                         refreshBtMenu(); | ||||
|                         btSub.popup(); | ||||
|                     } | ||||
|                 })} | ||||
|             </submenu> | ||||
|  | ||||
|             <item label="🔊 Volume" onActivate={() => exec("pavucontrol")} /> | ||||
|             <item label="🎙️ Microphone" onActivate={() => exec("pavucontrol")} /> | ||||
|             <item label="🔌 Power" onActivate={() => exec("power-menu")} /> | ||||
|         </menu> | ||||
|     ); | ||||
| } | ||||
|  | ||||
| export { createQuickActionsMenu }; | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| @import "colors"; | ||||
|  | ||||
| .toggle-row { | ||||
|   background-color: $bg; | ||||
|   border-radius: 12px; | ||||
|   margin: 6px 0; | ||||
|   overflow: hidden; | ||||
|   border: 1px solid $border; | ||||
|  | ||||
|   button { | ||||
|     padding: 10px 16px; | ||||
|     font-size: 14px; | ||||
|     transition: background 0.2s ease; | ||||
|     border: none; | ||||
|     background: transparent; | ||||
|  | ||||
|     &:hover { | ||||
|       background-color: $hover; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   .toggle { | ||||
|     flex: 1; | ||||
|     background-color: transparent; | ||||
|     text-align: left; | ||||
|     &.active { | ||||
|       background-color: $accent; | ||||
|       color: white; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   .arrow { | ||||
|     width: 40px; | ||||
|     background-color: transparent; | ||||
|     text-align: center; | ||||
|   } | ||||
| } | ||||
|  | ||||
|  | ||||
| .audio-control { | ||||
|   display: flex; | ||||
|   align-items: center; | ||||
|   padding: 8px 12px; | ||||
|   gap: 8px; | ||||
|  | ||||
|   label { | ||||
|     min-width: 60px; | ||||
|     color: $fg; | ||||
|   } | ||||
|  | ||||
|   scale { | ||||
|     flex: 1; | ||||
|   } | ||||
|  | ||||
|   button { | ||||
|     background-color: transparent; | ||||
|     padding: 6px; | ||||
|     border-radius: 6px; | ||||
|  | ||||
|     &:hover { | ||||
|       background-color: $hover; | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | ||||
| .media-control { | ||||
|   padding: 12px; | ||||
|   text-align: center; | ||||
|  | ||||
|   label { | ||||
|     display: block; | ||||
|     margin-bottom: 6px; | ||||
|   } | ||||
|  | ||||
|   button { | ||||
|     margin: 0 4px; | ||||
|     padding: 6px 10px; | ||||
|     border-radius: 6px; | ||||
|  | ||||
|     &:hover { | ||||
|       background-color: $hover; | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| import Gtk from "gi://Gtk"; | ||||
| import AstalNetwork from "gi://AstalNetwork"; | ||||
| import AstalBluetooth from "gi://AstalBluetooth"; | ||||
| import AstalAudio from "gi://AstalAudio"; | ||||
| import AstalMedia from "gi://AstalMedia"; | ||||
| import { exec } from "gi://GLib"; | ||||
|  | ||||
| // Helpers | ||||
| function createToggleRow({ label, active, onToggle, onExpand }) { | ||||
|     return ( | ||||
|         <box className="toggle-row" orientation="horizontal"> | ||||
|             <button className={active ? "toggle active" : "toggle"} onClicked={onToggle}> | ||||
|                 {label} | ||||
|             </button> | ||||
|             <button className="arrow" onClicked={onExpand}> | ||||
|                 > | ||||
|             </button> | ||||
|         </box> | ||||
|     ); | ||||
| } | ||||
|  | ||||
| function createPowerRow({ onExpand }) { | ||||
|     return ( | ||||
|         <box className="toggle-row" orientation="horizontal"> | ||||
|             <button className="toggle" onClicked={() => exec("systemctl suspend")}> | ||||
|                 🔋 Power | ||||
|             </button> | ||||
|             <button className="arrow" onClicked={onExpand}> | ||||
|                 > | ||||
|             </button> | ||||
|         </box> | ||||
|     ); | ||||
| } | ||||
|  | ||||
| function createQuickActionsMenu() { | ||||
|     const wifi = AstalNetwork.get_default().get_wifi(); | ||||
|     const bt = AstalBluetooth.get_default().get_adapter(); | ||||
|     const audio = AstalAudio.get_default(); | ||||
|     const media = AstalMedia.get_default(); | ||||
|  | ||||
|     // Submenus | ||||
|     const wifiSub = new Gtk.Menu(); | ||||
|     const btSub = new Gtk.Menu(); | ||||
|     const powerSub = new Gtk.Menu(); | ||||
|     const outputSub = new Gtk.Menu(); | ||||
|     const inputSub = new Gtk.Menu(); | ||||
|  | ||||
|     function refreshWifiMenu() { | ||||
|         wifiSub.foreach(c => wifiSub.remove(c)); | ||||
|         for (const ap of wifi.get_access_points()) { | ||||
|             const item = new Gtk.MenuItem({ label: `${ap.get_ssid()} (${ap.get_strength()}%)` }); | ||||
|             item.connect("activate", () => wifi.connect_access_point(ap)); | ||||
|             item.show(); | ||||
|             wifiSub.append(item); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     function refreshBtMenu() { | ||||
|         btSub.foreach(c => btSub.remove(c)); | ||||
|         for (const dev of AstalBluetooth.get_default().get_devices()) { | ||||
|             const label = dev.get_connected() ? `✔ ${dev.get_name()}` : dev.get_name(); | ||||
|             const item = new Gtk.MenuItem({ label }); | ||||
|             item.connect("activate", () => | ||||
|                 dev.get_connected() ? dev.disconnect_device() : dev.connect_device() | ||||
|             ); | ||||
|             item.show(); | ||||
|             btSub.append(item); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     function refreshPowerMenu() { | ||||
|         const entries = [ | ||||
|             { label: "⏻ Shutdown", cmd: "systemctl poweroff" }, | ||||
|             { label: "🔁 Reboot", cmd: "systemctl reboot" }, | ||||
|             { label: "🔒 Lock", cmd: "loginctl lock-session" }, | ||||
|             { label: "🚪 Logout", cmd: "hyprctl dispatch exit" }, | ||||
|         ]; | ||||
|         powerSub.foreach(c => powerSub.remove(c)); | ||||
|         for (const entry of entries) { | ||||
|             const item = new Gtk.MenuItem({ label: entry.label }); | ||||
|             item.connect("activate", () => exec(entry.cmd)); | ||||
|             item.show(); | ||||
|             powerSub.append(item); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     function refreshOutputDevices() { | ||||
|         outputSub.foreach(c => outputSub.remove(c)); | ||||
|         for (const device of audio.get_outputs()) { | ||||
|             const label = device.is_default() ? `✔ ${device.get_description()}` : device.get_description(); | ||||
|             const item = new Gtk.MenuItem({ label }); | ||||
|             item.connect("activate", () => audio.set_default_output(device)); | ||||
|             item.show(); | ||||
|             outputSub.append(item); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     function refreshInputDevices() { | ||||
|         inputSub.foreach(c => inputSub.remove(c)); | ||||
|         for (const device of audio.get_inputs()) { | ||||
|             const label = device.is_default() ? `✔ ${device.get_description()}` : device.get_description(); | ||||
|             const item = new Gtk.MenuItem({ label }); | ||||
|             item.connect("activate", () => audio.set_default_input(device)); | ||||
|             item.show(); | ||||
|             inputSub.append(item); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     return ( | ||||
|         <menu className="quickactions-menu"> | ||||
|  | ||||
|             {/* WiFi */} | ||||
|             <submenu label=""> | ||||
|                 {createToggleRow({ | ||||
|                     label: "📶 WiFi", | ||||
|                     active: wifi.get_state() !== AstalNetwork.WifiState.DISCONNECTED, | ||||
|                     onToggle: () => | ||||
|                         wifi.get_state() === AstalNetwork.WifiState.DISCONNECTED | ||||
|                             ? wifi.connect() | ||||
|                             : wifi.disconnect(), | ||||
|                     onExpand: () => { | ||||
|                         refreshWifiMenu(); | ||||
|                         wifiSub.popup(); | ||||
|                     }, | ||||
|                 })} | ||||
|             </submenu> | ||||
|  | ||||
|             {/* Bluetooth */} | ||||
|             <submenu label=""> | ||||
|                 {createToggleRow({ | ||||
|                     label: "🔵 Bluetooth", | ||||
|                     active: bt.get_powered(), | ||||
|                     onToggle: () => bt.set_powered(!bt.get_powered()), | ||||
|                     onExpand: () => { | ||||
|                         refreshBtMenu(); | ||||
|                         btSub.popup(); | ||||
|                     }, | ||||
|                 })} | ||||
|             </submenu> | ||||
|  | ||||
|             {/* Output Volume */} | ||||
|             <box className="audio-control"> | ||||
|                 <label>🔊 Output</label> | ||||
|                 <scale | ||||
|                     value={audio.get_output_volume()} | ||||
|                     onChange={v => audio.set_output_volume(v)} | ||||
|                     drawValue={false} | ||||
|                     min={0} | ||||
|                     max={100} | ||||
|                 /> | ||||
|                 <button onClicked={() => { | ||||
|                     refreshOutputDevices(); | ||||
|                     outputSub.popup(); | ||||
|                 }}>⋯</button> | ||||
|             </box> | ||||
|  | ||||
|             {/* Input Volume */} | ||||
|             <box className="audio-control"> | ||||
|                 <label>🎙️ Mic</label> | ||||
|                 <scale | ||||
|                     value={audio.get_input_volume()} | ||||
|                     onChange={v => audio.set_input_volume(v)} | ||||
|                     drawValue={false} | ||||
|                     min={0} | ||||
|                     max={100} | ||||
|                 /> | ||||
|                 <button onClicked={() => { | ||||
|                     refreshInputDevices(); | ||||
|                     inputSub.popup(); | ||||
|                 }}>⋯</button> | ||||
|             </box> | ||||
|  | ||||
|             {/* Media Controls */} | ||||
|             {media && ( | ||||
|                 <box className="media-control"> | ||||
|                     <label>{media.get_artist()} – {media.get_title()}</label> | ||||
|                     <box> | ||||
|                         <button onClicked={() => media.prev()}>⏮</button> | ||||
|                         <button onClicked={() => media.play_pause()}>⏯</button> | ||||
|                         <button onClicked={() => media.next()}>⏭</button> | ||||
|                     </box> | ||||
|                 </box> | ||||
|             )} | ||||
|  | ||||
|             {/* Power */} | ||||
|             <submenu label=""> | ||||
|                 {createPowerRow({ | ||||
|                     onExpand: () => { | ||||
|                         refreshPowerMenu(); | ||||
|                         powerSub.popup(); | ||||
|                     }, | ||||
|                 })} | ||||
|             </submenu> | ||||
|         </menu> | ||||
|     ); | ||||
| } | ||||
|  | ||||
| export { createQuickActionsMenu }; | ||||
							
								
								
									
										21
									
								
								config/ags/bar/env.d.ts
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										21
									
								
								config/ags/bar/env.d.ts
									
									
									
									
										vendored
									
									
								
							| @@ -1,21 +0,0 @@ | ||||
| declare const SRC: string | ||||
|  | ||||
| declare module "inline:*" { | ||||
|     const content: string | ||||
|     export default content | ||||
| } | ||||
|  | ||||
| declare module "*.scss" { | ||||
|     const content: string | ||||
|     export default content | ||||
| } | ||||
|  | ||||
| declare module "*.blp" { | ||||
|     const content: string | ||||
|     export default content | ||||
| } | ||||
|  | ||||
| declare module "*.css" { | ||||
|     const content: string | ||||
|     export default content | ||||
| } | ||||
| @@ -1,6 +0,0 @@ | ||||
| { | ||||
|     "name": "astal-shell", | ||||
|     "dependencies": { | ||||
|         "astal": "/usr/share/astal/gjs" | ||||
|     } | ||||
| } | ||||
| @@ -1,20 +0,0 @@ | ||||
| // https://gitlab.gnome.org/GNOME/gtk/-/blob/gtk-3-24/gtk/theme/Adwaita/_colors-public.scss | ||||
| $fg-color: #{"@theme_fg_color"}; | ||||
| $bg-color: #{"@theme_bg_color"}; | ||||
|  | ||||
| window.Bar { | ||||
|     background: transparent; | ||||
|     color: $fg-color; | ||||
|     font-weight: bold; | ||||
|  | ||||
|     >centerbox { | ||||
|         background: $bg-color; | ||||
|         border-radius: 10px; | ||||
|         margin: 8px; | ||||
|     } | ||||
|  | ||||
|     button { | ||||
|         border-radius: 8px; | ||||
|         margin: 2px; | ||||
|     } | ||||
| } | ||||
| @@ -1,14 +0,0 @@ | ||||
| { | ||||
|     "$schema": "https://json.schemastore.org/tsconfig", | ||||
|     "compilerOptions": { | ||||
|         "experimentalDecorators": true, | ||||
|         "strict": true, | ||||
|         "target": "ES2022", | ||||
|         "module": "ES2022", | ||||
|         "moduleResolution": "Bundler", | ||||
|         // "checkJs": true, | ||||
|         // "allowJs": true, | ||||
|         "jsx": "react-jsx", | ||||
|         "jsxImportSource": "astal/gtk3", | ||||
|     } | ||||
| } | ||||
| @@ -1,23 +0,0 @@ | ||||
| import { createQuickActionsMenu } from "./QuickActions"; | ||||
| import { GLib } from "astal"; | ||||
| import { Astal, Gdk, Gtk } from "astal/gtk3"; | ||||
|  | ||||
| const Bar = (gdkmonitor: Gdk.Monitor) => { | ||||
|  | ||||
|     return ( | ||||
|         <window gdkmonitor={gdkmonitor} | ||||
|             cssClasses={["Bar"]}> | ||||
|             <box orientation={Gtk.Orientation.HORIZONTAL} spacing={10}> | ||||
|                 <box> | ||||
|                 </box> | ||||
|                 <label>{windowTitle}</label> | ||||
|                 <box> | ||||
|                     <tray /> | ||||
|                     <button icon="quickaction" menu={quickActionMenu} /> | ||||
|                 </box> | ||||
|             </box> | ||||
|         </window> | ||||
|     ); | ||||
| } | ||||
|  | ||||
| export default Bar; | ||||
| @@ -1,76 +0,0 @@ | ||||
| import Gtk from "gi://Gtk"; | ||||
| import AstalNetwork from "gi://AstalNetwork"; | ||||
| import AstalBluetooth from "gi://AstalBluetooth"; | ||||
| import { exec } from "gi://GLib"; | ||||
|  | ||||
| let quickActionsMenu; | ||||
|  | ||||
| // Toggle WiFi connection | ||||
| function toggleWiFi() { | ||||
|     const network = AstalNetwork.get_default(); | ||||
|     const wifi = network.get_wifi()!; | ||||
|     const state = wifi.get_state(); | ||||
|  | ||||
|     if (state === AstalNetwork.WifiState.DISCONNECTED) { | ||||
|         wifi.connect(); | ||||
|     } else { | ||||
|         wifi.disconnect(); | ||||
|     } | ||||
| } | ||||
|  | ||||
| // Toggle Bluetooth power state | ||||
| function toggleBluetooth() { | ||||
|     const bluetooth = AstalBluetooth.get_default(); | ||||
|     const adapter = bluetooth.get_adapter(); | ||||
|     const powered = adapter?.get_powered(); | ||||
|  | ||||
|     adapter?.set_powered(!powered); | ||||
| } | ||||
|  | ||||
| // Adjust volume or microphone (opens pavucontrol) | ||||
| function adjustVolume() { | ||||
|     exec("pavucontrol"); | ||||
| } | ||||
|  | ||||
| function adjustMic() { | ||||
|     exec("pavucontrol"); | ||||
| } | ||||
|  | ||||
| // Power menu | ||||
| function showPowerMenu() { | ||||
|     exec("power-menu"); | ||||
| } | ||||
|  | ||||
| // Show WiFi network picker | ||||
| function pickWiFi() { | ||||
|     const wifi = AstalNetwork.get_default().get_wifi(); | ||||
|     wifi.show_picker(); | ||||
| } | ||||
|  | ||||
| // Show Bluetooth device picker | ||||
| function pickBluetooth() { | ||||
|     const bluetooth = AstalBluetooth.get_default(); | ||||
|     bluetooth.show_picker(); | ||||
| } | ||||
|  | ||||
| // Create menu using JSX | ||||
| function createQuickActionsMenu() { | ||||
|     quickActionsMenu = ( | ||||
|         <menu> | ||||
|             <item label="📶 WiFi" onActivate={toggleWiFi} /> | ||||
|             <item label="→ Pick Network" onActivate={pickWiFi} /> | ||||
|  | ||||
|             <item label="🔵 Bluetooth" onActivate={toggleBluetooth} /> | ||||
|             <item label="→ Pick Device" onActivate={pickBluetooth} /> | ||||
|  | ||||
|             <item label="🔊 Volume" onActivate={adjustVolume} /> | ||||
|             <item label="🎙️ Microphone" onActivate={adjustMic} /> | ||||
|             <item label="🔌 Power" onActivate={showPowerMenu} /> | ||||
|         </menu> | ||||
|     ); | ||||
|  | ||||
|     return quickActionsMenu; | ||||
| } | ||||
|  | ||||
| // Export the function | ||||
| export { createQuickActionsMenu }; | ||||
| @@ -1,57 +0,0 @@ | ||||
| import AstalTray from "gi://AstalTray"; | ||||
| import { bind } from "astal"; | ||||
| import AstalHyprland from "gi://AstalHyprland"; | ||||
|  | ||||
| const SysTray = () => { | ||||
|     const tray = AstalTray.get_default(); | ||||
|  | ||||
|     return <box className="SysTray"> | ||||
|         {bind(tray, "items").as( items => items.map( item => ( | ||||
|             <button | ||||
|                 tooltipMarkup={bind(item, "tooltipMarkup")} | ||||
|                 usePopover={false} | ||||
|                 actionGroup={bind(item, "actionGroup").as(ag => ["dbusmenu", ag])} | ||||
|                 menuModel={bind(item, "menuModel")}> | ||||
|                 <icon gicon={bind(item, "gicon")} /> | ||||
|             </button> | ||||
|         ) ) ) } | ||||
|     </box> | ||||
| } | ||||
|  | ||||
|  | ||||
| const HyprlandWorkspace = () => { | ||||
|     const hypr = AstalHyprland.get_default() | ||||
|  | ||||
|     return <box className={"HyprlandWorkspaces"}> | ||||
|         {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 | ||||
|                     className={bind(hypr, "focusedWorkspace").as(fw => | ||||
|                         ws === fw ? "HyprlandFocusedWorkspace" : "")} | ||||
|                     onClicked={() => ws.focus()}> | ||||
|                     {ws.id} | ||||
|                 </button> | ||||
|             )) | ||||
|         )} | ||||
|     </box> | ||||
| } | ||||
|  | ||||
|  | ||||
| const HyprlandActiveWindow = () => { | ||||
|     const hypr = AstalHyprland.get_default(); | ||||
|     const focused = bind( hypr, "focusedClient" ); | ||||
|  | ||||
|     return <box className={"HyprlandFocusedClients"} visible={focused.as(Boolean)}> | ||||
|         {focused.as( client => ( | ||||
|             client && <label label={bind( client, "title" ).as( String )} /> | ||||
|         ))} | ||||
|     </box> | ||||
| } | ||||
|  | ||||
| export default { | ||||
|     HyprlandWorkspace,  | ||||
|     HyprlandActiveWindow, | ||||
|     SysTray | ||||
| } | ||||
| @@ -1,37 +0,0 @@ | ||||
| @import "colors"; | ||||
|  | ||||
| .toggle-row { | ||||
|   background-color: $bg; | ||||
|   border-radius: 12px; | ||||
|   margin: 6px 0; | ||||
|   overflow: hidden; | ||||
|   border: 1px solid $border; | ||||
|  | ||||
|   button { | ||||
|     padding: 10px 16px; | ||||
|     font-size: 14px; | ||||
|     transition: background 0.2s ease; | ||||
|     border: none; | ||||
|     background: transparent; | ||||
|  | ||||
|     &:hover { | ||||
|       background-color: $hover; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   .toggle { | ||||
|     flex: 1; | ||||
|     background-color: transparent; | ||||
|     text-align: left; | ||||
|     &.active { | ||||
|       background-color: $accent; | ||||
|       color: white; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   .arrow { | ||||
|     width: 40px; | ||||
|     background-color: transparent; | ||||
|     text-align: center; | ||||
|   } | ||||
| } | ||||
| @@ -1,68 +0,0 @@ | ||||
| import AstalHyprland from "gi://AstalHyprland"; | ||||
|  | ||||
| const getAvailableWorkspaces = (): number[] => { | ||||
|     const workspaces: number[] = []; | ||||
|     AstalHyprland.get_default().get_workspaces().forEach( val => { | ||||
|         workspaces.push( val.get_id() ); | ||||
|     } ) | ||||
|     return workspaces; | ||||
| } | ||||
|  | ||||
| const getCurrentWorkspaceID = (): number => { | ||||
|     return AstalHyprland.get_default().get_focused_workspace().get_id(); | ||||
| } | ||||
|  | ||||
| const getCurrentWindowTitle = (): string => { | ||||
|     return AstalHyprland.get_default().get_focused_client().get_title(); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Get the workspace ID of a window by its address | ||||
|  * @param address - The address of the window | ||||
|  * @returns The workspace ID | ||||
|  */ | ||||
| const getWorkspaceIDOfWindowByAddress = ( address: string ): number => { | ||||
|     AstalHyprland.get_default().get_clients().forEach( client => { | ||||
|         if ( client.get_address() === address ) { | ||||
|             return client.get_workspace().get_id(); | ||||
|         } | ||||
|     } ); | ||||
|  | ||||
|     return -1; | ||||
| } | ||||
|  | ||||
|  | ||||
| interface HyprlandSubscriptions { | ||||
|     [key: string]: ( data: string ) => void; | ||||
| } | ||||
| const hooks: HyprlandSubscriptions = {}; | ||||
|  | ||||
| /** | ||||
|  * Add an event listener for Hyprland events. | ||||
|  * @param event - A hyprland IPC event. See https://wiki.hyprland.org/IPC/. Useful events include: urgent, windowtitlev2, workspace, createworkspacev2, destroyworkspacev2, activewindowv2 | ||||
|  * @param cb - The callback function | ||||
|  */ | ||||
| const subscribeToUpdates = ( event: string, cb: ( data: string ) => void ): void => { | ||||
|     hooks[ event ] = cb; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Listen to events. Must be called at some point if events are to be listened for | ||||
|  */ | ||||
| const listen = () => { | ||||
|     AstalHyprland.get_default().connect( "event", ( name: string, data: string ) => { | ||||
|         if ( hooks[ name ] ) { | ||||
|             hooks[ name ]( data ); | ||||
|         } | ||||
|     } ); | ||||
| } | ||||
|  | ||||
|  | ||||
| export default { | ||||
|     getAvailableWorkspaces, | ||||
|     getCurrentWorkspaceID, | ||||
|     getCurrentWindowTitle, | ||||
|     getWorkspaceIDOfWindowByAddress, | ||||
|     subscribeToUpdates, | ||||
|     listen | ||||
| } | ||||
		Reference in New Issue
	
	Block a user