diff --git a/.config/ags/modules/bar/main.js b/.config/ags/modules/bar/main.js index 771306e86..c1f8dfce8 100644 --- a/.config/ags/modules/bar/main.js +++ b/.config/ags/modules/bar/main.js @@ -1,129 +1,142 @@ const { Gtk } = imports.gi; -import Widget from 'resource:///com/github/Aylur/ags/widget.js'; -import Battery from 'resource:///com/github/Aylur/ags/service/battery.js'; +import Widget from "resource:///com/github/Aylur/ags/widget.js"; +import Battery from "resource:///com/github/Aylur/ags/service/battery.js"; import WindowTitle from "./normal/spaceleft.js"; +import RecordingIndicator from "./normal/recording.js"; import Indicators from "./normal/spaceright.js"; import Music from "./normal/music.js"; import System from "./normal/system.js"; import { enableClickthrough } from "../.widgetutils/clickthrough.js"; import { RoundedCorner } from "../.commonwidgets/cairo_roundedcorner.js"; -import { currentShellMode } from '../../variables.js'; +import { currentShellMode } from "../../variables.js"; const NormalOptionalWorkspaces = async () => { + try { + return (await import("./normal/workspaces_hyprland.js")).default(); + } catch { try { - return (await import('./normal/workspaces_hyprland.js')).default(); + return (await import("./normal/workspaces_sway.js")).default(); } catch { - try { - return (await import('./normal/workspaces_sway.js')).default(); - } catch { - return null; - } + return null; } + } }; const FocusOptionalWorkspaces = async () => { + try { + return (await import("./focus/workspaces_hyprland.js")).default(); + } catch { try { - return (await import('./focus/workspaces_hyprland.js')).default(); + return (await import("./focus/workspaces_sway.js")).default(); } catch { - try { - return (await import('./focus/workspaces_sway.js')).default(); - } catch { - return null; - } + return null; } + } }; export const Bar = async (monitor = 0) => { - const SideModule = (children) => Widget.Box({ - className: 'bar-sidemodule', - children: children, + const SideModule = (children) => + Widget.Box({ + className: "bar-sidemodule", + children: children, }); - const normalBarContent = Widget.CenterBox({ - className: 'bar-bg', - setup: (self) => { - const styleContext = self.get_style_context(); - const minHeight = styleContext.get_property('min-height', Gtk.StateFlags.NORMAL); - // execAsync(['bash', '-c', `hyprctl keyword monitor ,addreserved,${minHeight},0,0,0`]).catch(print); - }, - startWidget: (await WindowTitle(monitor)), - centerWidget: Widget.Box({ - className: 'spacing-h-4', - children: [ - SideModule([Music()]), - Widget.Box({ - homogeneous: true, - children: [await NormalOptionalWorkspaces()], - }), - SideModule([System()]), - ] + const normalBarContent = Widget.CenterBox({ + className: "bar-bg", + setup: (self) => { + const styleContext = self.get_style_context(); + const minHeight = styleContext.get_property( + "min-height", + Gtk.StateFlags.NORMAL, + ); + // execAsync(['bash', '-c', `hyprctl keyword monitor ,addreserved,${minHeight},0,0,0`]).catch(print); + }, + startWidget: await WindowTitle(monitor), + centerWidget: Widget.Box({ + className: "spacing-h-4", + children: [ + SideModule([Music()]), + Widget.Box({ + homogeneous: true, + children: [await NormalOptionalWorkspaces()], }), - endWidget: Indicators(monitor), - }); - const focusedBarContent = Widget.CenterBox({ - className: 'bar-bg-focus', - startWidget: Widget.Box({}), - centerWidget: Widget.Box({ - className: 'spacing-h-4', - children: [ - SideModule([]), - Widget.Box({ - homogeneous: true, - children: [await FocusOptionalWorkspaces()], - }), - SideModule([]), - ] + SideModule([System()]), + ], + }), + endWidget: Widget.Box({ + children: [RecordingIndicator(), Indicators()], + }), + }); + const focusedBarContent = Widget.CenterBox({ + className: "bar-bg-focus", + startWidget: Widget.Box({}), + centerWidget: Widget.Box({ + className: "spacing-h-4", + children: [ + SideModule([]), + Widget.Box({ + homogeneous: true, + children: [await FocusOptionalWorkspaces()], }), - endWidget: Widget.Box({}), - setup: (self) => { - self.hook(Battery, (self) => { - if (!Battery.available) return; - self.toggleClassName('bar-bg-focus-batterylow', Battery.percent <= userOptions.battery.low); - }) - } - }); - const nothingContent = Widget.Box({ - className: 'bar-bg-nothing', - }) - return Widget.Window({ - monitor, - name: `bar${monitor}`, - anchor: ['top', 'left', 'right'], - exclusivity: 'exclusive', - visible: true, - child: Widget.Stack({ - homogeneous: false, - transition: 'slide_up_down', - transitionDuration: userOptions.animations.durationLarge, - children: { - 'normal': normalBarContent, - 'focus': focusedBarContent, - 'nothing': nothingContent, - }, - setup: (self) => self.hook(currentShellMode, (self) => { - self.shown = currentShellMode.value[monitor]; - }) + SideModule([]), + ], + }), + endWidget: Widget.Box({}), + setup: (self) => { + self.hook(Battery, (self) => { + if (!Battery.available) return; + self.toggleClassName( + "bar-bg-focus-batterylow", + Battery.percent <= userOptions.battery.low, + ); + }); + }, + }); + const nothingContent = Widget.Box({ + className: "bar-bg-nothing", + }); + return Widget.Window({ + monitor, + name: `bar${monitor}`, + anchor: ["top", "left", "right"], + exclusivity: "exclusive", + visible: true, + child: Widget.Stack({ + homogeneous: false, + transition: "slide_up_down", + transitionDuration: userOptions.animations.durationLarge, + children: { + normal: normalBarContent, + focus: focusedBarContent, + nothing: nothingContent, + }, + setup: (self) => + self.hook(currentShellMode, (self) => { + self.shown = currentShellMode.value[monitor]; }), - }); -} + }), + }); +}; -export const BarCornerTopleft = (monitor = 0) => Widget.Window({ +export const BarCornerTopleft = (monitor = 0) => + Widget.Window({ monitor, name: `barcornertl${monitor}`, - layer: 'top', - anchor: ['top', 'left'], - exclusivity: 'normal', + layer: "top", + anchor: ["top", "left"], + exclusivity: "normal", visible: true, - child: RoundedCorner('topleft', { className: 'corner', }), + child: RoundedCorner("topleft", { className: "corner" }), setup: enableClickthrough, -}); -export const BarCornerTopright = (monitor = 0) => Widget.Window({ + }); +export const BarCornerTopright = (monitor = 0) => + Widget.Window({ monitor, name: `barcornertr${monitor}`, - layer: 'top', - anchor: ['top', 'right'], - exclusivity: 'normal', + layer: "top", + anchor: ["top", "right"], + exclusivity: "normal", visible: true, - child: RoundedCorner('topright', { className: 'corner', }), + child: RoundedCorner("topright", { className: "corner" }), setup: enableClickthrough, -}); + }); diff --git a/.config/ags/modules/bar/normal/recording.js b/.config/ags/modules/bar/normal/recording.js new file mode 100644 index 000000000..a807b28ef --- /dev/null +++ b/.config/ags/modules/bar/normal/recording.js @@ -0,0 +1,46 @@ +import Widget from "resource:///com/github/Aylur/ags/widget.js"; +import RecordingService from "../../../services/recording.js"; + +const RecordingIndicator = () => { + return Widget.Label({ + className: "recording-indicator", + label: "●", + visible: false, + setup: (self) => { + self.setCss(` + font-size: 22px; + color: #c43737; + margin: 0 6px; + opacity: 0; + transition: opacity 300ms ease; + `); + + self.hook(RecordingService, () => { + if (RecordingService.recording) { + self.setCss(` + font-size: 22px; + color: #c43737; + margin: 0 6px; + opacity: 1; + transition: opacity 300ms ease; + `); + self.visible = true; + } else { + self.setCss(` + font-size: 22px; + color: #c43737; + margin: 0 6px; + opacity: 0; + transition: opacity 300ms ease; + `); + + Utils.timeout(300, () => { + self.visible = false; + }); + } + }); + }, + }); +}; + +export default RecordingIndicator; diff --git a/.config/ags/services/recording.js b/.config/ags/services/recording.js new file mode 100644 index 000000000..b3298ef9d --- /dev/null +++ b/.config/ags/services/recording.js @@ -0,0 +1,59 @@ +import Service from "resource:///com/github/Aylur/ags/service.js"; +import Utils from "resource:///com/github/Aylur/ags/utils.js"; + +class RecordingService extends Service { + static { + Service.register( + this, + { "recording-status": ["boolean"] }, + { recording: "boolean" }, + ); + } + + #recording = false; + #checkInterval = null; + + constructor() { + super(); + this.#initRecordingCheck(); + } + + #initRecordingCheck() { + if (this.#checkInterval) { + clearInterval(this.#checkInterval); + } + + this.#checkInterval = setInterval(() => { + this.#checkRecordingStatus(); + }, 2000); + } + + #checkRecordingStatus() { + try { + const processCheck = Utils.exec("pgrep -x wf-recorder"); + const newStatus = processCheck.length > 0; + + if (newStatus !== this.#recording) { + this.#recording = newStatus; + this.changed("recording"); + } + } catch { + if (this.#recording) { + this.#recording = false; + this.changed("recording"); + } + } + } + + get recording() { + return this.#recording; + } + + destroy() { + if (this.#checkInterval) { + clearInterval(this.#checkInterval); + } + } +} + +export default new RecordingService();