From 9b4e7fac4476c7fba7e7447c50bcd040a88dd9bb Mon Sep 17 00:00:00 2001 From: matt1432 Date: Tue, 17 Oct 2023 13:47:02 -0400 Subject: [PATCH] refactor(ags): make all widgets functions, use export default and some formatting --- hosts/wim/config/ags/js/applauncher/main.js | 4 +- hosts/wim/config/ags/js/bar/audio.js | 42 ++-- hosts/wim/config/ags/js/bar/battery.js | 14 +- hosts/wim/config/ags/js/bar/brightness.js | 18 +- hosts/wim/config/ags/js/bar/clock.js | 18 +- hosts/wim/config/ags/js/bar/current-window.js | 8 +- hosts/wim/config/ags/js/bar/fullscreen.js | 56 +++-- hosts/wim/config/ags/js/bar/gesture.js | 31 ++- hosts/wim/config/ags/js/bar/heart.js | 18 +- .../wim/config/ags/js/bar/keyboard-layout.js | 2 +- hosts/wim/config/ags/js/bar/main.js | 52 ++--- hosts/wim/config/ags/js/bar/notif-button.js | 45 ++-- hosts/wim/config/ags/js/bar/osk-toggle.js | 34 ++- hosts/wim/config/ags/js/bar/quick-settings.js | 15 +- hosts/wim/config/ags/js/bar/systray.js | 4 +- hosts/wim/config/ags/js/bar/tablet-toggle.js | 15 +- hosts/wim/config/ags/js/bar/workspaces.js | 54 ++--- hosts/wim/config/ags/js/date.js | 17 +- .../wim/config/ags/js/media-player/gesture.js | 4 +- hosts/wim/config/ags/js/media-player/mpris.js | 176 ++++++++------- .../wim/config/ags/js/media-player/player.js | 27 ++- hosts/wim/config/ags/js/misc/closer.js | 2 +- hosts/wim/config/ags/js/misc/cursorbox.js | 71 +++--- hosts/wim/config/ags/js/misc/popup.js | 52 +++-- hosts/wim/config/ags/js/misc/separator.js | 15 +- hosts/wim/config/ags/js/notifications/base.js | 39 ++-- .../wim/config/ags/js/notifications/center.js | 61 +++-- .../config/ags/js/notifications/gesture.js | 90 ++++---- .../wim/config/ags/js/notifications/popup.js | 13 +- hosts/wim/config/ags/js/overview/clients.js | 30 ++- hosts/wim/config/ags/js/overview/dragndrop.js | 39 ++-- hosts/wim/config/ags/js/overview/main.js | 19 +- .../wim/config/ags/js/overview/workspaces.js | 212 ++++++++++-------- hosts/wim/config/ags/js/powermenu.js | 11 +- .../ags/js/quick-settings/button-grid.js | 123 ++++++---- .../wim/config/ags/js/quick-settings/main.js | 24 +- .../ags/js/quick-settings/slider-box.js | 9 +- hosts/wim/config/ags/js/screen-corners.js | 25 ++- hosts/wim/config/hypr/main.conf | 2 +- 39 files changed, 797 insertions(+), 694 deletions(-) diff --git a/hosts/wim/config/ags/js/applauncher/main.js b/hosts/wim/config/ags/js/applauncher/main.js index cac6a644..5039bc3b 100644 --- a/hosts/wim/config/ags/js/applauncher/main.js +++ b/hosts/wim/config/ags/js/applauncher/main.js @@ -1,8 +1,8 @@ import { App, Applications, Utils, Widget } from '../../imports.js'; const { Label, Box, Icon, Button, Scrollable, Entry } = Widget; -import { Separator } from '../misc/separator.js'; -import { PopupWindow } from '../misc/popup.js'; +import Separator from '../misc/separator.js'; +import PopupWindow from '../misc/popup.js'; const icons = { apps: { diff --git a/hosts/wim/config/ags/js/bar/audio.js b/hosts/wim/config/ags/js/bar/audio.js index a0d4cb5f..70db20df 100644 --- a/hosts/wim/config/ags/js/bar/audio.js +++ b/hosts/wim/config/ags/js/bar/audio.js @@ -1,8 +1,8 @@ import { Audio, Widget } from '../../imports.js'; const { Label, Box, Icon } = Widget; -import { Separator } from '../misc/separator.js'; -import { EventBox } from '../misc/cursorbox.js'; +import Separator from '../misc/separator.js'; +import EventBox from '../misc/cursorbox.js'; const items = { 101: 'audio-volume-overamplified-symbolic', @@ -13,36 +13,36 @@ const items = { }; -const SpeakerIndicator = params => Icon({ - ...params, +const SpeakerIndicator = props => Icon({ + ...props, icon: '', - connections: [[Audio, icon => { - if (Audio.speaker) { - if (Audio.speaker.stream.isMuted) { - icon.icon = items[0]; - } - else { - const vol = Audio.speaker.volume * 100; - for (const threshold of [-1, 0, 33, 66, 100]) { - if (vol > threshold + 1) { - icon.icon = items[threshold + 1]; - } - } + connections: [[Audio, self => { + if (!Audio.speaker) + return; + + if (Audio.speaker.stream.isMuted) { + self.icon = items[0]; + } + else { + const vol = Audio.speaker.volume * 100; + + for (const threshold of [-1, 0, 33, 66, 100]) { + if (vol > threshold + 1) + self.icon = items[threshold + 1]; } } }, 'speaker-changed']], }); -const SpeakerPercentLabel = params => Label({ - ...params, +const SpeakerPercentLabel = props => Label({ + ...props, connections: [[Audio, label => { - if (Audio.speaker) { + if (Audio.speaker) label.label = Math.round(Audio.speaker.volume * 100) + '%'; - } }, 'speaker-changed']], }); -export const AudioIndicator = EventBox({ +export default () => EventBox({ onPrimaryClickRelease: 'pavucontrol', className: 'toggle-off', child: Box({ diff --git a/hosts/wim/config/ags/js/bar/battery.js b/hosts/wim/config/ags/js/bar/battery.js index 9b0bcdff..ef510c18 100644 --- a/hosts/wim/config/ags/js/bar/battery.js +++ b/hosts/wim/config/ags/js/bar/battery.js @@ -1,7 +1,7 @@ import { Battery, Widget } from '../../imports.js'; const { Label, Icon, Stack, Box } = Widget; -import { Separator } from '../misc/separator.js'; +import Separator from '../misc/separator.js'; const icons = charging => ([ ...Array.from({ length: 10 }, (_, i) => i * 10).map(i => ([ @@ -27,9 +27,9 @@ const Indicators = charging => Stack({ const Indicator = ({ charging = Indicators(true), discharging = Indicators(false), - ...params + ...props } = {}) => Stack({ - ...params, + ...props, className: 'battery-indicator', items: [ ['true', charging], @@ -43,13 +43,13 @@ const Indicator = ({ }]], }); -const LevelLabel = params => Label({ - ...params, +const LevelLabel = props => Label({ + ...props, className: 'label', - connections: [[Battery, label => label.label = `${Battery.percent}%`]], + connections: [[Battery, self => self.label = `${Battery.percent}%`]], }); -export const BatteryIndicator = Box({ +export default () => Box({ className: 'toggle-off battery', children: [ Indicator(), diff --git a/hosts/wim/config/ags/js/bar/brightness.js b/hosts/wim/config/ags/js/bar/brightness.js index 3c92e472..01859b28 100644 --- a/hosts/wim/config/ags/js/bar/brightness.js +++ b/hosts/wim/config/ags/js/bar/brightness.js @@ -1,25 +1,23 @@ import { Utils, Widget } from '../../imports.js'; const { ProgressBar, Overlay, Box } = Widget; -import { Separator } from '../misc/separator.js'; -import { Heart } from './heart.js'; +import Separator from '../misc/separator.js'; +import Heart from './heart.js'; -export const Brightness = Overlay({ - setup: widget => { - widget.set_tooltip_text('Brightness'); - }, +export default () => Overlay({ + tooltipText: 'Brightness', child: ProgressBar({ className: 'toggle-off brightness', connections: [ - [200, progress => { + [200, self => { Utils.execAsync('brightnessctl get').then(out => { let br = out / 255; if (br > 0.33) { - progress.value = br; + self.value = br; } else { - progress.value = 0.33; + self.value = 0.33; } }).catch(print); }], @@ -30,7 +28,7 @@ export const Brightness = Overlay({ style: 'color: #CBA6F7;', children: [ Separator(25), - Heart, + Heart(), ], }), ], diff --git a/hosts/wim/config/ags/js/bar/clock.js b/hosts/wim/config/ags/js/bar/clock.js index 6fdcf236..4f0cdfad 100644 --- a/hosts/wim/config/ags/js/bar/clock.js +++ b/hosts/wim/config/ags/js/bar/clock.js @@ -4,30 +4,32 @@ const { Box, Label } = Widget; import GLib from 'gi://GLib'; const { DateTime } = GLib; -import { EventBox } from '../misc/cursorbox.js'; +import EventBox from '../misc/cursorbox.js'; const ClockModule = ({ interval = 1000, - ...params + ...props }) => Label({ - ...params, + ...props, className: 'clock', connections: [ - [interval, label => { + [interval, self => { var time = DateTime.new_now_local(); - label.label = time.format('%a. ') + time.get_day_of_month() + time.format(' %b. %H:%M'); + self.label = time.format('%a. ') + + time.get_day_of_month() + + time.format(' %b. %H:%M'); }], ], }); -export const Clock = EventBox({ +export default () => EventBox({ className: 'toggle-off', onPrimaryClickRelease: () => App.toggleWindow('calendar'), connections: [ - [App, (box, windowName, visible) => { + [App, (self, windowName, visible) => { if (windowName == 'calendar') { - box.toggleClassName('toggle-on', visible); + self.toggleClassName('toggle-on', visible); } }], ], diff --git a/hosts/wim/config/ags/js/bar/current-window.js b/hosts/wim/config/ags/js/bar/current-window.js index faa27482..8548eef9 100644 --- a/hosts/wim/config/ags/js/bar/current-window.js +++ b/hosts/wim/config/ags/js/bar/current-window.js @@ -2,12 +2,8 @@ import { Widget, Hyprland } from '../../imports.js'; const { Label } = Widget; -export const CurrentWindow = Label({ +export default () => Label({ style: 'color: #CBA6F7; font-size: 18px', truncate: 'end', - connections: [ - [Hyprland, label => { - label.label = Hyprland.active.client.title; - }, 'changed'], - ], + binds: [['label', Hyprland.active.client, 'title']], }); diff --git a/hosts/wim/config/ags/js/bar/fullscreen.js b/hosts/wim/config/ags/js/bar/fullscreen.js index 479a324e..528546ae 100644 --- a/hosts/wim/config/ags/js/bar/fullscreen.js +++ b/hosts/wim/config/ags/js/bar/fullscreen.js @@ -4,19 +4,14 @@ const { Box, EventBox, Overlay } = Widget; const Revealed = Variable(true); const Hovering = Variable(false); -import { Gesture } from './gesture.js'; -import { RoundedCorner } from '../screen-corners.js'; +import { RoundedCorner } from '../screen-corners.js'; +import Gesture from './gesture.js'; -export const Revealer = params => Overlay({ +export default (props) => Overlay({ overlays: [ - RoundedCorner('topleft', { - className: 'corner', - }), - - RoundedCorner('topright', { - className: 'corner', - }), + RoundedCorner('topleft', { className: 'corner' }), + RoundedCorner('topright', { className: 'corner' }), ], child: Box({ @@ -27,27 +22,26 @@ export const Revealer = params => Overlay({ Widget.Revealer({ transition: 'slide_down', setup: self => self.revealChild = true, - properties: [ - ['timeouts', []], - ], - connections: [[Hyprland, self => { - Utils.execAsync('hyprctl activewindow -j') - .then(result => { - let client = JSON.parse(result); - if (client.fullscreen !== Revealed.value) { - Revealed.value = client.fullscreen; - if (Revealed.value) { - setTimeout(() => { - if (Revealed.value) - self.revealChild = false - }, 2000); - } - else { - self.revealChild = true; - } - } - }).catch(print); + properties: [['timeouts', []]], + connections: [[Hyprland, self => { + Utils.execAsync('hyprctl activewindow -j').then(out => { + let client = JSON.parse(out); + if (client.fullscreen === Revealed.value) + return; + + Revealed.value = client.fullscreen; + + if (Revealed.value) { + setTimeout(() => { + if (Revealed.value) + self.revealChild = false + }, 2000); + } + else { + self.revealChild = true; + } + }).catch(print); }]], child: Gesture({ @@ -63,7 +57,7 @@ export const Revealer = params => Overlay({ }, 2000); } }, - ...params, + ...props, }), }), diff --git a/hosts/wim/config/ags/js/bar/gesture.js b/hosts/wim/config/ags/js/bar/gesture.js index ea6f060e..474e6d75 100644 --- a/hosts/wim/config/ags/js/bar/gesture.js +++ b/hosts/wim/config/ags/js/bar/gesture.js @@ -4,30 +4,25 @@ const { CenterBox, EventBox } = Widget; import Gtk from 'gi://Gtk'; -export const Gesture = ({ +export default ({ child, - ...params + ...props }) => { - let w = EventBox({ - ...params, + let widget = EventBox({ + ...props, }); - let gesture = Gtk.GestureSwipe.new(w); + let gesture = Gtk.GestureSwipe.new(widget); - w.child = CenterBox({ - children: [ - child, - ], - connections: [ + widget.child = CenterBox({ + children: [ child ], + connections: [[gesture, () => { + const velocity = gesture.get_velocity()[1]; + if (velocity < -100) + App.openWindow('quick-settings'); - [gesture, _ => { - const velocity = gesture.get_velocity()[1]; - if (velocity < -100) - App.openWindow('quick-settings'); - }, 'update'], - - ], + }, 'update']], }); - return w; + return widget; }; diff --git a/hosts/wim/config/ags/js/bar/heart.js b/hosts/wim/config/ags/js/bar/heart.js index 3ca86a64..1bc3ec6a 100644 --- a/hosts/wim/config/ags/js/bar/heart.js +++ b/hosts/wim/config/ags/js/bar/heart.js @@ -2,26 +2,28 @@ import { Utils, Widget } from '../../imports.js'; const { Box, Label } = Widget; const { subprocess, execAsync } = Utils; -import { EventBox } from '../misc/cursorbox.js'; +import EventBox from '../misc/cursorbox.js'; -subprocess( - ['bash', '-c', 'tail -f /home/matt/.config/.heart'], - (output) => { - Heart.child.children[0].label = ' ' + output; - }, -); -export const Heart = EventBox({ +export default () => EventBox({ halign: 'center', + onPrimaryClickRelease: () => { execAsync(['bash', '-c', '$AGS_PATH/heart.sh toggle']).catch(print); }, + child: Box({ className: 'heart-toggle', vertical: false, child: Label({ label: '', + setup: self => { + subprocess( + ['bash', '-c', 'tail -f /home/matt/.config/.heart'], + (output) => self.label = ' ' + output, + ); + }, }), }), }); diff --git a/hosts/wim/config/ags/js/bar/keyboard-layout.js b/hosts/wim/config/ags/js/bar/keyboard-layout.js index 6122fbf5..ecb736c4 100644 --- a/hosts/wim/config/ags/js/bar/keyboard-layout.js +++ b/hosts/wim/config/ags/js/bar/keyboard-layout.js @@ -3,7 +3,7 @@ const { Label, Box, Icon } = Widget; const DEFAULT_KB = "at-translated-set-2-keyboard"; -export default Box({ +export default () => Box({ className: 'toggle-off', children: [ Icon({ diff --git a/hosts/wim/config/ags/js/bar/main.js b/hosts/wim/config/ags/js/bar/main.js index fe251b6c..182edb7f 100644 --- a/hosts/wim/config/ags/js/bar/main.js +++ b/hosts/wim/config/ags/js/bar/main.js @@ -1,20 +1,20 @@ import { Widget } from '../../imports.js'; const { Window, CenterBox, Box } = Widget; -import { Separator } from '../misc/separator.js'; -import { CurrentWindow } from './current-window.js'; -import { Workspaces } from './workspaces.js'; -import { OskToggle } from './osk-toggle.js'; -import { TabletToggle } from './tablet-toggle.js'; -import { QsToggle } from './quick-settings.js'; -import { NotifButton } from './notif-button.js'; -import { Clock } from './clock.js'; -import { SysTray } from './systray.js'; -import { BatteryIndicator } from './battery.js'; -import { Brightness } from './brightness.js'; -import { AudioIndicator } from './audio.js'; -import { Revealer } from './fullscreen.js'; -//import KeyboardLayout from './keyboard-layout.js'; +import Separator from '../misc/separator.js'; +import CurrentWindow from './current-window.js'; +import Workspaces from './workspaces.js'; +import OskToggle from './osk-toggle.js'; +import TabletToggle from './tablet-toggle.js'; +import QsToggle from './quick-settings.js'; +import NotifButton from './notif-button.js'; +import Clock from './clock.js'; +import SysTray from './systray.js'; +import Battery from './battery.js'; +import Brightness from './brightness.js'; +import Audio from './audio.js'; +import Revealer from './fullscreen.js'; +//import KeyboardLayout from './keyboard-layout.js'; export const Bar = () => Window({ @@ -31,55 +31,55 @@ export const Bar = () => Window({ halign: 'start', children: [ - OskToggle, + OskToggle(), Separator(12), - TabletToggle, + TabletToggle(), Separator(12), - SysTray, + SysTray(), - AudioIndicator, + Audio(), Separator(12), - Brightness, + Brightness(), Separator(12), - Workspaces, + Workspaces(), ], }), centerWidget: Box({ children: [ - CurrentWindow, + CurrentWindow(), ], }), endWidget: Box({ halign: 'end', children: [ - BatteryIndicator, + Battery(), Separator(12), - //KeyboardLayout, + //KeyboardLayout(), //Separator(12), - Clock, + Clock(), Separator(12), - NotifButton, + NotifButton(), Separator(12), - QsToggle, + QsToggle(), ], }), }), diff --git a/hosts/wim/config/ags/js/bar/notif-button.js b/hosts/wim/config/ags/js/bar/notif-button.js index 1bd5b912..bc834b9d 100644 --- a/hosts/wim/config/ags/js/bar/notif-button.js +++ b/hosts/wim/config/ags/js/bar/notif-button.js @@ -1,20 +1,17 @@ import { App, Notifications, Widget } from '../../imports.js'; const { Box, Label, Icon } = Widget; -import { Separator } from '../misc/separator.js'; -import { EventBox } from '../misc/cursorbox.js'; +import Separator from '../misc/separator.js'; +import EventBox from '../misc/cursorbox.js'; -export const NotifButton = EventBox({ +export default () => EventBox({ className: 'toggle-off', onPrimaryClickRelease: () => App.toggleWindow('notification-center'), - connections: [ - [App, (box, windowName, visible) => { - if (windowName == 'notification-center') { - box.toggleClassName('toggle-on', visible); - } - }], - ], + connections: [[App, (self, windowName, visible) => { + if (windowName == 'notification-center') + self.toggleClassName('toggle-on', visible); + }]], child: Box({ className: 'notif-panel', vertical: false, @@ -22,30 +19,26 @@ export const NotifButton = EventBox({ Separator(28), Icon({ - connections: [ - [Notifications, icon => { - if (Notifications.dnd) { - icon.icon = 'notification-disabled-symbolic' + connections: [[Notifications, self => { + if (Notifications.dnd) { + self.icon = 'notification-disabled-symbolic' + } + else { + if (Notifications.notifications.length > 0) { + self.icon = 'notification-new-symbolic' } else { - if (Notifications.notifications.length > 0) { - icon.icon = 'notification-new-symbolic' - } - else { - icon.icon = 'notification-symbolic' - } + self.icon = 'notification-symbolic' } - }], - ], + } + }]], }), Separator(8), Label({ - connections: [ - [Notifications, label => { - label.label = String(Notifications.notifications.length); - }], + binds: [ + ['label', Notifications, 'notifications', n => String(n.length)], ], }), diff --git a/hosts/wim/config/ags/js/bar/osk-toggle.js b/hosts/wim/config/ags/js/bar/osk-toggle.js index c53ea848..0d02d455 100644 --- a/hosts/wim/config/ags/js/bar/osk-toggle.js +++ b/hosts/wim/config/ags/js/bar/osk-toggle.js @@ -2,33 +2,25 @@ import { Utils, Widget } from '../../imports.js'; const { Box, Label } = Widget; const { subprocess } = Utils; -import { EventBox } from '../misc/cursorbox.js'; +import EventBox from '../misc/cursorbox.js'; -subprocess( - ['bash', '-c', '$AGS_PATH/osk-toggle.sh getState'], - (output) => { - if (output == 'Running') { - OskToggle.toggleClassName('toggle-on', true); - } else { - OskToggle.toggleClassName('toggle-on', false); - } - }, -); -export const OskToggle = EventBox({ +export default () => EventBox({ className: 'toggle-off', - onPrimaryClickRelease: function() { + setup: self => { subprocess( - ['bash', '-c', '$AGS_PATH/osk-toggle.sh toggle'], - (output) => { - if (output == 'Running') { - OskToggle.toggleClassName('toggle-on', false); - } else { - OskToggle.toggleClassName('toggle-on', true); - } - }, + ['bash', '-c', '$AGS_PATH/osk-toggle.sh getState'], + (output) => self.toggleClassName('toggle-on', output === 'Running'), ); }, + + onPrimaryClickRelease: self => { + subprocess( + ['bash', '-c', '$AGS_PATH/osk-toggle.sh toggle'], + (output) => self.toggleClassName('toggle-on', output !== 'Running'), + ); + }, + child: Box({ className: 'osk-toggle', vertical: false, diff --git a/hosts/wim/config/ags/js/bar/quick-settings.js b/hosts/wim/config/ags/js/bar/quick-settings.js index e039be06..d03d024c 100644 --- a/hosts/wim/config/ags/js/bar/quick-settings.js +++ b/hosts/wim/config/ags/js/bar/quick-settings.js @@ -1,19 +1,16 @@ import { Widget, App } from '../../imports.js'; const { Box, Label } = Widget; -import { EventBox } from '../misc/cursorbox.js'; +import EventBox from '../misc/cursorbox.js'; -export const QsToggle = EventBox({ +export default () => EventBox({ className: 'toggle-off', onPrimaryClickRelease: () => App.toggleWindow('quick-settings'), - connections: [ - [App, (box, windowName, visible) => { - if (windowName == 'quick-settings') { - box.toggleClassName('toggle-on', visible); - } - }], - ], + connections: [[App, (self, windowName, visible) => { + if (windowName == 'quick-settings') + self.toggleClassName('toggle-on', visible); + }]], child: Box({ className: 'quick-settings-toggle', vertical: false, diff --git a/hosts/wim/config/ags/js/bar/systray.js b/hosts/wim/config/ags/js/bar/systray.js index b31c3dbb..423376ee 100644 --- a/hosts/wim/config/ags/js/bar/systray.js +++ b/hosts/wim/config/ags/js/bar/systray.js @@ -3,7 +3,7 @@ const { Box, Revealer, Icon, MenuItem } = Widget; import Gtk from 'gi://Gtk'; -import { Separator } from '../misc/separator.js'; +import Separator from '../misc/separator.js'; const SysTrayItem = item => MenuItem({ @@ -21,7 +21,7 @@ const SysTrayItem = item => MenuItem({ }]] }); -export const SysTray = Revealer({ +export default () => Revealer({ transition: 'slide_right', connections: [[SystemTray, rev => { rev.revealChild = rev.child.children[0].get_children().length > 0; diff --git a/hosts/wim/config/ags/js/bar/tablet-toggle.js b/hosts/wim/config/ags/js/bar/tablet-toggle.js index 8b319925..e2319b68 100644 --- a/hosts/wim/config/ags/js/bar/tablet-toggle.js +++ b/hosts/wim/config/ags/js/bar/tablet-toggle.js @@ -2,22 +2,15 @@ import { Utils, Widget } from '../../imports.js'; const { Box, Label } = Widget; const { subprocess } = Utils; -import { EventBox } from '../misc/cursorbox.js'; +import EventBox from '../misc/cursorbox.js'; -export const TabletToggle = EventBox({ +export default () => EventBox({ className: 'toggle-off', - onPrimaryClickRelease: function() { + onPrimaryClickRelease: self => { subprocess( ['bash', '-c', '$AGS_PATH/tablet-toggle.sh toggle'], - (output) => { - print(output) - if (output == 'Tablet') { - TabletToggle.toggleClassName('toggle-on', true); - } else { - TabletToggle.toggleClassName('toggle-on', false); - } - }, + (output) => self.toggleClassName('toggle-on', output == 'Tablet'), ); }, child: Box({ diff --git a/hosts/wim/config/ags/js/bar/workspaces.js b/hosts/wim/config/ags/js/bar/workspaces.js index e806e8a2..898b8aac 100644 --- a/hosts/wim/config/ags/js/bar/workspaces.js +++ b/hosts/wim/config/ags/js/bar/workspaces.js @@ -1,69 +1,69 @@ import { Hyprland, Utils, Widget } from '../../imports.js'; -const { Box, Label, Revealer } = Widget; +const { Box, Revealer } = Widget; const { execAsync } = Utils; -import { EventBox } from '../misc/cursorbox.js'; +import EventBox from '../misc/cursorbox.js'; const Workspace = ({ i } = {}) => Revealer({ transition: "slide_right", - properties: [ - ['id', i], - ], + properties: [['id', i]], + child: EventBox({ tooltipText: `${i}`, - onPrimaryClickRelease: () => execAsync(`hyprctl dispatch workspace ${i}`).catch(print), + onPrimaryClickRelease: () => { + execAsync(`hyprctl dispatch workspace ${i}`) + .catch(print); + }, child: Box({ className: 'button', - connections: [ - [Hyprland, btn => { - const occupied = Hyprland.getWorkspace(i)?.windows > 0; - btn.toggleClassName('active', Hyprland.active.workspace.id === i); - btn.toggleClassName('occupied', occupied); - btn.toggleClassName('empty', !occupied); - }] - ], + connections: [[Hyprland, self => { + const occupied = Hyprland.getWorkspace(i)?.windows > 0; + self.toggleClassName('active', Hyprland.active.workspace.id === i); + self.toggleClassName('occupied', occupied); + self.toggleClassName('empty', !occupied); + }]], }), }), }); -export const Workspaces = Box({ +export default () => Box({ className: 'workspaces', children: [EventBox({ child: Box({ properties: [ ['workspaces'], - ['refresh', box => { - box.children.forEach(rev => rev.reveal_child = false); - box._workspaces.forEach(ws => { + ['refresh', self => { + self.children.forEach(rev => rev.reveal_child = false); + self._workspaces.forEach(ws => { ws.revealChild = true; }); }], - ['updateWs', box => { + ['updateWs', self => { Hyprland.workspaces.forEach(ws => { - let currentWs = box.children.find(ch => ch._id == ws.id); + let currentWs = self.children.find(ch => ch._id == ws.id); if (!currentWs && ws.id > 0) { - box.add(Workspace({ i: ws.id})); + self.add(Workspace({ i: ws.id})); } }); - box.show_all(); + self.show_all(); // Make sure the order is correct - box._workspaces.forEach((workspace, i) => { + self._workspaces.forEach((workspace, i) => { workspace.get_parent().reorder_child(workspace, i); }); }], ], - connections: [[Hyprland, box => { - box._workspaces = box.children.filter(ch => { + connections: [[Hyprland, self => { + self._workspaces = self.children.filter(ch => { return Hyprland.workspaces.find(ws => ws.id == ch._id) }).sort((a, b) => a._id - b._id); - box._updateWs(box); - box._refresh(box); + self._updateWs(self); + self._refresh(self); }]], }), })], diff --git a/hosts/wim/config/ags/js/date.js b/hosts/wim/config/ags/js/date.js index af907674..3ac8fc2b 100644 --- a/hosts/wim/config/ags/js/date.js +++ b/hosts/wim/config/ags/js/date.js @@ -5,7 +5,7 @@ import Gtk from 'gi://Gtk'; import GLib from 'gi://GLib'; const { DateTime } = GLib; -import { PopupWindow } from './misc/popup.js'; +import PopupWindow from './misc/popup.js'; const Divider = () => Box({ @@ -27,8 +27,8 @@ const Time = () => Box({ Label({ className: 'content', label: 'hour', - connections: [[1000, label => { - label.label = DateTime.new_now_local().format('%H'); + connections: [[1000, self => { + self.label = DateTime.new_now_local().format('%H'); }]], }), @@ -37,8 +37,8 @@ const Time = () => Box({ Label({ className: 'content', label: 'minute', - connections: [[1000, label => { - label.label = DateTime.new_now_local().format('%M'); + connections: [[1000, self => { + self.label = DateTime.new_now_local().format('%M'); }]], }), @@ -51,9 +51,11 @@ const Time = () => Box({ child: Label({ style: 'font-size: 20px', label: 'complete date', - connections: [[1000, label => { + connections: [[1000, self => { var time = DateTime.new_now_local(); - label.label = time.format("%A, %B ") + time.get_day_of_month() + time.format(", %Y"); + self.label = time.format("%A, %B ") + + time.get_day_of_month() + + time.format(", %Y"); }]], }), }), @@ -68,7 +70,6 @@ const CalendarWidget = () => Box({ showDayNames: true, showHeading: true, className: 'cal', - connections: [/* */] }), }); diff --git a/hosts/wim/config/ags/js/media-player/gesture.js b/hosts/wim/config/ags/js/media-player/gesture.js index 59d038ae..8cdc344a 100644 --- a/hosts/wim/config/ags/js/media-player/gesture.js +++ b/hosts/wim/config/ags/js/media-player/gesture.js @@ -8,12 +8,12 @@ const OFFSCREEN = 500; const TRANSITION = 'transition: margin 0.5s ease, opacity 3s ease;'; -export default ({ properties, connections, params } = {}) => { +export default ({ properties, connections, props } = {}) => { let widget = EventBox(); let gesture = Gtk.GestureDrag.new(widget) widget.child = Overlay({ - ...params, + ...props, properties: [ ...properties, ['dragging', false], diff --git a/hosts/wim/config/ags/js/media-player/mpris.js b/hosts/wim/config/ags/js/media-player/mpris.js index d5ee61b8..4943cbf7 100644 --- a/hosts/wim/config/ags/js/media-player/mpris.js +++ b/hosts/wim/config/ags/js/media-player/mpris.js @@ -5,8 +5,8 @@ const { execAsync, lookUpIcon } = Utils; import Gdk from 'gi://Gdk'; const display = Gdk.Display.get_default(); -import { EventBox } from '../misc/cursorbox.js'; -import { Separator } from '../misc/separator.js'; +import Separator from '../misc/separator.js'; +import EventBox from '../misc/cursorbox.js'; const icons = { mpris: { @@ -29,34 +29,35 @@ const icons = { } -export const CoverArt = (player, params) => CenterBox({ - ...params, +export const CoverArt = (player, props) => CenterBox({ + ...props, vertical: true, properties: [['bgStyle', '']], - connections: [ - [player, box => { - execAsync(['bash', '-c', `[[ -f "${player.coverPath}" ]] && coloryou "${player.coverPath}" | grep -v Warning`]) + connections: [[player, self => { + execAsync(['bash', '-c', `[[ -f "${player.coverPath}" ]] && + coloryou "${player.coverPath}" | grep -v Warning`]) .then(out => { if (!Mpris.players.find(p => player === p)) return; player.colors.value = JSON.parse(out); - box._bgStyle = `background: radial-gradient(circle, - rgba(0, 0, 0, 0.4) 30%, - ${player.colors.value.imageAccent}), - url("${player.coverPath}"); - background-size: cover; - background-position: center;`; - if (!box.get_parent()._dragging) - box.setStyle(box._bgStyle); - }).catch(err => { if (err !== "") print(err) }); - }], - ], + self._bgStyle = `background: radial-gradient(circle, + rgba(0, 0, 0, 0.4) 30%, + ${player.colors.value.imageAccent}), + url("${player.coverPath}"); + background-size: cover; + background-position: center;`; + + if (!self.get_parent()._dragging) + self.setStyle(self._bgStyle); + + }).catch(err => {if (err !== "") print(err)}); + }]], }); -export const TitleLabel = (player, params) => Label({ - ...params, +export const TitleLabel = (player, props) => Label({ + ...props, xalign: 0, maxWidthChars: 40, truncate: 'end', @@ -65,8 +66,8 @@ export const TitleLabel = (player, params) => Label({ binds: [['label', player, 'track-title']], }); -export const ArtistLabel = (player, params) => Label({ - ...params, +export const ArtistLabel = (player, props) => Label({ + ...props, xalign: 0, maxWidthChars: 40, truncate: 'end', @@ -75,80 +76,83 @@ export const ArtistLabel = (player, params) => Label({ binds: [['label', player, 'track-artists', a => a.join(', ') || '']], }); -export const PlayerIcon = (player, { symbolic = true, ...params } = {}) => { +export const PlayerIcon = (player, { symbolic = true, ...props } = {}) => { let MainIcon = Icon({ - ...params, + ...props, className: 'player-icon', size: 32, tooltipText: player.identity || '', - connections: [ - [player, icon => { - const name = `${player.entry}${symbolic ? '-symbolic' : ''}`; - lookUpIcon(name) ? icon.icon = name - : icon.icon = icons.mpris.fallback; - }], - ], + connections: [[player, self => { + const name = `${player.entry}${symbolic ? '-symbolic' : ''}`; + lookUpIcon(name) ? self.icon = name + : self.icon = icons.mpris.fallback; + }]], }); return Box({ - connections: [ - [Mpris, box => { - let overlays = box.get_parent().get_parent().get_parent().list(); - let player = overlays.find(overlay => overlay === box.get_parent().get_parent()); - let index = overlays.indexOf(player) + connections: [[Mpris, self => { + let overlays = self.get_parent().get_parent() + .get_parent().list(); - let children = []; - for (let i = 0; i < overlays.length; ++i) { - if (i === index) { - children.push(MainIcon); - children.push(Separator(2)); - } - else { - children.push(Box({ className: 'position-indicator' })); - children.push(Separator(2)); - } + let player = overlays.find(overlay => { + overlay === self.get_parent().get_parent(); + }); + + let index = overlays.indexOf(player); + + let children = []; + for (let i = 0; i < overlays.length; ++i) { + if (i === index) { + children.push(MainIcon); + children.push(Separator(2)); } - box.children = children; - }], - ], + else { + children.push(Box({className: 'position-indicator'})); + children.push(Separator(2)); + } + } + self.children = children; + }]], }); } -export const PositionSlider = (player, params) => EventBox({ +// FIXME: get the cursors right or just don't display when disabled +export const PositionSlider = (player, props) => EventBox({ child: Slider({ - ...params, + ...props, className: 'position-slider', hexpand: true, drawValue: false, onChange: ({ value }) => { player.position = player.length * value; }, - properties: [ - ['update', slider => { - if (slider.dragging) { - slider.get_parent().window.set_cursor(Gdk.Cursor.new_from_name(display, 'grabbing')); + properties: [['update', slider => { + if (slider.dragging) { + slider.get_parent().window.set_cursor(Gdk.Cursor + .new_from_name(display, 'grabbing')); + } + else { + if (slider.get_parent() && slider.get_parent().window) { + slider.get_parent().window.set_cursor(Gdk.Cursor + .new_from_name(display, 'pointer')); } - else { - if (slider.get_parent() && slider.get_parent().window) { - slider.get_parent().window.set_cursor(Gdk.Cursor.new_from_name(display, 'pointer')); - } - slider.sensitive = player.length > 0; - if (player.length > 0) { - slider.value = player.position / player.length; - } + slider.sensitive = player.length > 0; + if (player.length > 0) { + slider.value = player.position / player.length; } - }], - ], + } + }]], connections: [ [player, s => s._update(s), 'position'], [1000, s => s._update(s)], [player.colors, s => { - if (player.colors.value) - s.setCss(`highlight { background-color: ${player.colors.value.buttonAccent}; } - slider { background-color: ${player.colors.value.buttonAccent}; } - slider:hover { background-color: ${player.colors.value.hoverAccent}; } - trough { background-color: ${player.colors.value.buttonText}; }`); + let c = player.colors.value; + if (c) + s.setCss(`highlight { background-color: ${c.buttonAccent}; } + slider { background-color: ${c.buttonAccent}; } + slider:hover { background-color: ${c.hoverAccent}; } + trough { background-color: ${c.buttonText}; }`); }], ], }), @@ -162,9 +166,9 @@ function lengthStr(length) { } export const PositionLabel = player => Label({ - properties: [['update', label => { - player.length > 0 ? label.label = lengthStr(player.position) - : label.visible = !!player; + properties: [['update', self => { + player.length > 0 ? self.label = lengthStr(player.position) + : self.visible = !!player; }]], connections: [ [player, l => l._update(l), 'position'], @@ -173,16 +177,16 @@ export const PositionLabel = player => Label({ }); export const LengthLabel = player => Label({ - connections: [[player, label => { - player.length > 0 ? label.label = lengthStr(player.length) - : label.visible = !!player; + connections: [[player, self => { + player.length > 0 ? self.label = lengthStr(player.length) + : self.visible = !!player; }]], }); export const Slash = player => Label({ label: '/', - connections: [[player, label => { - label.visible = player.length > 0; + connections: [[player, self => { + self.visible = player.length > 0; }]], }); @@ -191,13 +195,13 @@ const PlayerButton = ({ player, items, onClick, prop }) => Button({ child: Stack({ items }), onPrimaryClickRelease: () => player[onClick](), properties: [['hovered', false]], - onHover: box => { - box._hovered = true; - if (! box.child.sensitive || ! box.sensitive) { - box.window.set_cursor(Gdk.Cursor.new_from_name(display, 'not-allowed')); + onHover: self => { + self._hovered = true; + if (! self.child.sensitive || ! self.sensitive) { + self.window.set_cursor(Gdk.Cursor.new_from_name(display, 'not-allowed')); } else { - box.window.set_cursor(Gdk.Cursor.new_from_name(display, 'pointer')); + self.window.set_cursor(Gdk.Cursor.new_from_name(display, 'pointer')); } if (prop == 'playBackStatus') { @@ -209,9 +213,9 @@ const PlayerButton = ({ player, items, onClick, prop }) => Button({ }); } }, - onHoverLost: box => { - box._hovered = false; - box.window.set_cursor(null); + onHoverLost: self => { + self._hovered = false; + self.window.set_cursor(null); if (prop == 'playBackStatus') { items.forEach(item => { item[1].setStyle(`background-color: ${player.colors.value.buttonAccent}; diff --git a/hosts/wim/config/ags/js/media-player/player.js b/hosts/wim/config/ags/js/media-player/player.js index 8ad8d8b2..c78e7153 100644 --- a/hosts/wim/config/ags/js/media-player/player.js +++ b/hosts/wim/config/ags/js/media-player/player.js @@ -1,9 +1,11 @@ import { Mpris, Variable, Widget } from '../../imports.js'; const { Box, CenterBox, Label } = Widget; -import * as mpris from './mpris.js'; +import * as mpris from './mpris.js'; import PlayerGesture from './gesture.js'; -import { Separator } from '../misc/separator.js'; +import Separator from '../misc/separator.js'; + +const FAVE_PLAYER = 'org.mpris.MediaPlayer2.spotify'; const Top = player => Box({ @@ -56,20 +58,22 @@ const Center = player => Box({ const Bottom = player => Box({ className: 'bottom', children: [ - mpris.PreviousButton(player, { valign: 'end', halign: 'start', }), Separator(8), + mpris.PositionSlider(player), Separator(8), + mpris.NextButton(player), Separator(8), + mpris.ShuffleButton(player), Separator(8), - mpris.LoopButton(player), + mpris.LoopButton(player), ], }); @@ -98,10 +102,12 @@ export default () => Box({ if (!busName) { let player = Mpris.players.find(p => !overlay._players.has(p.busName)); - if (player) + if (player) { busName = player.busName; - else + } + else { return; + } } const player = Mpris.getPlayer(busName); @@ -115,18 +121,20 @@ export default () => Box({ overlay.overlays = result; - // Favor spotify + // Select favorite player at startup if (!overlay._setup) { - if (overlay._players.has('org.mpris.MediaPlayer2.spotify')) { - overlay._selected = overlay._players.get('org.mpris.MediaPlayer2.spotify'); + if (overlay._players.has(FAVE_PLAYER)) { + overlay._selected = overlay._players.get(FAVE_PLAYER); } overlay._setup = true; } if (overlay._selected) overlay.reorder_overlay(overlay._selected, -1); + }, 'player-added'], + [Mpris, (overlay, busName) => { if (!busName || !overlay._players.has(busName)) return; @@ -141,6 +149,7 @@ export default () => Box({ overlay.overlays = result; if (overlay._selected) overlay.reorder_overlay(overlay._selected, -1); + }, 'player-closed'], ], }), diff --git a/hosts/wim/config/ags/js/misc/closer.js b/hosts/wim/config/ags/js/misc/closer.js index 3a913963..4db50d3e 100644 --- a/hosts/wim/config/ags/js/misc/closer.js +++ b/hosts/wim/config/ags/js/misc/closer.js @@ -21,7 +21,7 @@ const closeAll = () => { }); App.closeWindow('closer'); }; -globalThis.closeAll = () => closeAll(); +globalThis.closeAll = closeAll; Pointers.connect('new-line', (_, out) => { if (out) { diff --git a/hosts/wim/config/ags/js/misc/cursorbox.js b/hosts/wim/config/ags/js/misc/cursorbox.js index 540da80b..50129be2 100644 --- a/hosts/wim/config/ags/js/misc/cursorbox.js +++ b/hosts/wim/config/ags/js/misc/cursorbox.js @@ -4,34 +4,43 @@ import Gdk from 'gi://Gdk'; const display = Gdk.Display.get_default(); -export const EventBox = ({ reset = true, ...params }) => Widget.EventBox({ - ...params, - onHover: box => { - if (! box.child.sensitive || ! box.sensitive) { - box.window.set_cursor(Gdk.Cursor.new_from_name(display, 'not-allowed')); - } - else { - box.window.set_cursor(Gdk.Cursor.new_from_name(display, 'pointer')); - } - }, - onHoverLost: box => { - if (reset) - box.window.set_cursor(null); - }, -}); - -export const Button = ({ reset = true, ...params }) => Widget.Button({ - ...params, - onHover: box => { - if (! box.child.sensitive || ! box.sensitive) { - box.window.set_cursor(Gdk.Cursor.new_from_name(display, 'not-allowed')); - } - else { - box.window.set_cursor(Gdk.Cursor.new_from_name(display, 'pointer')); - } - }, - onHoverLost: box => { - if (reset) - box.window.set_cursor(null); - }, -}); +export default ({ + type = "EventBox", + reset = true, + ...props +}) => { + if (type === "EventBox") { + return Widget.EventBox({ + ...props, + onHover: self => { + if (!self.child.sensitive || !self.sensitive) { + self.window.set_cursor(Gdk.Cursor.new_from_name(display, 'not-allowed')); + } + else { + self.window.set_cursor(Gdk.Cursor.new_from_name(display, 'pointer')); + } + }, + onHoverLost: self => { + if (reset) + self.window.set_cursor(null); + }, + }); + } + else { + return Widget.Button({ + ...props, + onHover: self => { + if (!self.child.sensitive || !self.sensitive) { + self.window.set_cursor(Gdk.Cursor.new_from_name(display, 'not-allowed')); + } + else { + self.window.set_cursor(Gdk.Cursor.new_from_name(display, 'pointer')); + } + }, + onHoverLost: self => { + if (reset) + self.window.set_cursor(null); + }, + }); + } +} diff --git a/hosts/wim/config/ags/js/misc/popup.js b/hosts/wim/config/ags/js/misc/popup.js index 2cda285c..72b5ca23 100644 --- a/hosts/wim/config/ags/js/misc/popup.js +++ b/hosts/wim/config/ags/js/misc/popup.js @@ -2,32 +2,38 @@ import { App, Widget } from '../../imports.js'; const { Revealer, Box, Window } = Widget; -export const PopupWindow = ({ +export default ({ name, child, transition = 'slide_down', - ...params -}) => Window({ - name, - popup: true, - visible: false, - layer: 'overlay', - ...params, + onOpen = rev => {}, + ...props +}) => { + let window = Window({ + name, + popup: true, + visible: false, + layer: 'overlay', + ...props, - child: Box({ - style: 'min-height:1px; min-width:1px', - child: Revealer({ - transition, - transitionDuration: 500, - connections: [[App, (revealer, currentName, visible) => { - if (currentName === name) { - revealer.reveal_child = visible; + child: Box({ + style: 'min-height:1px; min-width:1px', + child: Revealer({ + transition, + transitionDuration: 500, + connections: [[App, (rev, currentName, visible) => { + if (currentName === name) { + rev.reveal_child = visible; + onOpen(child); - if (visible && name !== 'overview') - App.openWindow('closer'); - } - }]], - child: child, + if (visible && name !== 'overview') + App.openWindow('closer'); + } + }]], + child: child, + }), }), - }), -}); + }); + window.getChild = () => child; + return window; +} diff --git a/hosts/wim/config/ags/js/misc/separator.js b/hosts/wim/config/ags/js/misc/separator.js index f8484d6d..5e9e1479 100644 --- a/hosts/wim/config/ags/js/misc/separator.js +++ b/hosts/wim/config/ags/js/misc/separator.js @@ -2,6 +2,15 @@ import { Widget } from '../../imports.js'; const { Box } = Widget; -export const Separator = width => Box({ - style: `min-width: ${width}px;`, -}); +export default (size, { vertical = false } = {}) => { + if (vertical) { + return Box({ + style: `min-height: ${size}px;`, + }); + } + else { + return Box({ + style: `min-width: ${size}px;`, + }); + } +} diff --git a/hosts/wim/config/ags/js/notifications/base.js b/hosts/wim/config/ags/js/notifications/base.js index 3a1bebbb..8f00a5f4 100644 --- a/hosts/wim/config/ags/js/notifications/base.js +++ b/hosts/wim/config/ags/js/notifications/base.js @@ -4,8 +4,17 @@ const { Box, Icon, Label, Button } = Widget; import GLib from 'gi://GLib'; +const setTime = time => { + return GLib.DateTime + .new_from_unix_local(time) + .format('%H:%M'); +}; + +const getDragState = box => box.get_parent().get_parent() + .get_parent().get_parent().get_parent()._dragging; + import Gesture from './gesture.js'; -import { EventBox } from '../misc/cursorbox.js' +import EventBox from '../misc/cursorbox.js' const NotificationIcon = notif => { @@ -14,19 +23,19 @@ const NotificationIcon = notif => { if (Applications.query(notif.appEntry).length > 0) { let app = Applications.query(notif.appEntry)[0]; - if (app.app.get_string('StartupWMClass') != null) { + let wmClass = app.app.get_string('StartupWMClass'); + if (app.app.get_filename().includes('discord')) + wmClass = 'discord'; + + if (wmClass != null) { iconCmd = box => { - if (!box.get_parent().get_parent().get_parent().get_parent().get_parent()._dragging) { - execAsync(['bash', '-c', `$AGS_PATH/launch-app.sh ${app.app.get_string('StartupWMClass')} ${app.app.get_string('Exec')}`]).catch(print); - globalThis.closeAll(); - } - } - } - else if (app.app.get_filename().includes('discord')) { - iconCmd = box => { - if (!box.get_parent().get_parent().get_parent().get_parent().get_parent()._dragging) { - execAsync(['bash', '-c', `$AGS_PATH/launch-app.sh discord ${app.app.get_string('Exec')}`]) - .catch(print); + if (!getDragState(box)) { + execAsync(['bash', '-c', + `$AGS_PATH/launch-app.sh + ${wmClass} + ${app.app.get_string('Exec')}` + ]).catch(print); + globalThis.closeAll(); } } @@ -82,7 +91,7 @@ const NotificationIcon = notif => { }); }; -export default ({ notif, command = () => {}} = {}) => { +export default ({ notif, command = () => {}, } = {}) => { const BlockedApps = [ 'Spotify', ]; @@ -142,7 +151,7 @@ export default ({ notif, command = () => {}} = {}) => { Label({ className: 'time', valign: 'start', - label: GLib.DateTime.new_from_unix_local(notif.time).format('%H:%M'), + label: setTime(notif.time), }), EventBox({ reset: false, diff --git a/hosts/wim/config/ags/js/notifications/center.js b/hosts/wim/config/ags/js/notifications/center.js index c513c5a4..95df553a 100644 --- a/hosts/wim/config/ags/js/notifications/center.js +++ b/hosts/wim/config/ags/js/notifications/center.js @@ -3,23 +3,30 @@ const { Button, Label, Box, Icon, Scrollable, Revealer } = Widget; const { timeout } = Utils; import Notification from './base.js'; -import { EventBox } from '../misc/cursorbox.js'; -import { PopupWindow } from '../misc/popup.js'; +import PopupWindow from '../misc/popup.js'; +import EventBox from '../misc/cursorbox.js'; const ClearButton = () => EventBox({ child: Button({ onPrimaryClickRelease: button => { - button._popups.children.forEach(ch => ch.child.setStyle(ch.child._leftAnim1)); + button._popups.children.forEach(ch => { + ch.child.setStyle(ch.child._leftAnim1); + }); + button._notifList.children.forEach(ch => { - ch.child.setStyle(ch.child._rightAnim1); + if (ch.child) + ch.child.setStyle(ch.child._rightAnim1); timeout(500, () => { button._notifList.remove(ch); - Notifications.notifications.forEach(n => n.close()); + Notifications.clear(); }); }); }, - properties: [['notifList'], ['popups']], + properties: [ + ['notifList'], + ['popups'], + ], connections: [[Notifications, button => { if (!button._notifList) button._notifList = NotificationList; @@ -33,8 +40,8 @@ const ClearButton = () => EventBox({ children: [ Label('Clear '), Icon({ - connections: [[Notifications, icon => { - icon.icon = Notifications.notifications.length > 0 + connections: [[Notifications, self => { + self.icon = Notifications.notifications.length > 0 ? 'user-trash-full-symbolic' : 'user-trash-symbolic'; }]], }), @@ -46,7 +53,11 @@ const ClearButton = () => EventBox({ const Header = () => Box({ className: 'header', children: [ - Label({ label: 'Notifications', hexpand: true, xalign: 0 }), + Label({ + label: 'Notifications', + hexpand: true, + xalign: 0, + }), ClearButton(), ], }); @@ -110,26 +121,28 @@ const Placeholder = () => Revealer({ }), }); -const NotificationCenterWidget = Box({ +const NotificationCenterWidget = () => Box({ className: 'notification-center', vertical: true, children: [ Header(), Box({ className: 'notification-wallpaper-box', - children: [Scrollable({ - className: 'notification-list-box', - hscroll: 'never', - vscroll: 'automatic', - child: Box({ - className: 'notification-list', - vertical: true, - children: [ - NotificationList, - Placeholder(), - ], - }), - })], + children: [ + Scrollable({ + className: 'notification-list-box', + hscroll: 'never', + vscroll: 'automatic', + child: Box({ + className: 'notification-list', + vertical: true, + children: [ + NotificationList, + Placeholder(), + ], + }), + }) + ], }), ], }); @@ -138,5 +151,5 @@ export default () => PopupWindow({ name: 'notification-center', anchor: [ 'top', 'right' ], margin: [ 8, 60, 0, 0 ], - child: NotificationCenterWidget, + child: NotificationCenterWidget(), }); diff --git a/hosts/wim/config/ags/js/notifications/gesture.js b/hosts/wim/config/ags/js/notifications/gesture.js index 2f9f035f..45b957be 100644 --- a/hosts/wim/config/ags/js/notifications/gesture.js +++ b/hosts/wim/config/ags/js/notifications/gesture.js @@ -16,25 +16,25 @@ export default ({ child = '', children = [], properties = [[]], - ...params + ...props }) => { - let w = EventBox({ - ...params, + let widget = EventBox({ + ...props, properties: [ ['dragging', false], ...properties, ], - onHover: box => { - box.window.set_cursor(Gdk.Cursor.new_from_name(display, 'grab')); - onHover(box); + onHover: self => { + self.window.set_cursor(Gdk.Cursor.new_from_name(display, 'grab')); + onHover(self); }, - onHoverLost: box => { - box.window.set_cursor(null); - onHoverLost(box); + onHoverLost: self => { + self.window.set_cursor(null); + onHoverLost(self); }, }); - let gesture = Gtk.GestureDrag.new(w); + let gesture = Gtk.GestureDrag.new(widget); let leftAnim1 = `transition: margin 0.5s ease, opacity 0.5s ease; margin-left: -${Number(maxOffset + endMargin)}px; @@ -56,10 +56,10 @@ export default ({ margin-right: -${Number(maxOffset + endMargin)}px; margin-bottom: -70px; margin-top: -70px; opacity: 0;`; - w.child = Box({ + widget.child = Box({ properties: [ - ['leftAnim1', leftAnim1], - ['leftAnim2', leftAnim2], + ['leftAnim1', leftAnim1], + ['leftAnim2', leftAnim2], ['rightAnim1', rightAnim1], ['rightAnim2', rightAnim2], ['ready', false] @@ -71,39 +71,39 @@ export default ({ style: leftAnim2, connections: [ - [gesture, box => { + [gesture, self => { var offset = gesture.get_offset()[1]; if (offset >= 0) { - box.setStyle('margin-left: ' + Number(offset + startMargin) + 'px; ' + - 'margin-right: -' + Number(offset + startMargin) + 'px;'); + self.setStyle(`margin-left: ${Number(offset + startMargin)}px; + margin-right: -${Number(offset + startMargin)}px;`); } else { offset = Math.abs(offset); - box.setStyle('margin-right: ' + Number(offset + startMargin) + 'px; ' + - 'margin-left: -' + Number(offset + startMargin) + 'px;'); + self.setStyle(`margin-right: ${Number(offset + startMargin)}px; + margin-left: -${Number(offset + startMargin)}px;`); } - box.get_parent()._dragging = Math.abs(offset) > 10; + self.get_parent()._dragging = Math.abs(offset) > 10; - if (w.window) - w.window.set_cursor(Gdk.Cursor.new_from_name(display, 'grabbing')); + if (widget.window) + widget.window.set_cursor(Gdk.Cursor.new_from_name(display, 'grabbing')); }, 'drag-update'], - [gesture, box => { - if (!box._ready) { - box.setStyle(`transition: margin 0.5s ease, opacity 0.5s ease; - margin-left: -${Number(maxOffset + endMargin)}px; - margin-right: ${Number(maxOffset + endMargin)}px; - margin-bottom: 0px; margin-top: 0px; opacity: 0;`); + [gesture, self => { + if (!self._ready) { + self.setStyle(`transition: margin 0.5s ease, opacity 0.5s ease; + margin-left: -${Number(maxOffset + endMargin)}px; + margin-right: ${Number(maxOffset + endMargin)}px; + margin-bottom: 0px; margin-top: 0px; opacity: 0;`); setTimeout(() => { - box.setStyle('transition: margin 0.5s ease, opacity 0.5s ease; ' + - 'margin-left: ' + startMargin + 'px; ' + - 'margin-right: ' + startMargin + 'px; ' + - 'margin-bottom: unset; margin-top: unset; opacity: 1;'); + self.setStyle(`transition: margin 0.5s ease, opacity 0.5s ease; + margin-left: ${startMargin}px; + margin-right: ${startMargin}px; + margin-bottom: unset; margin-top: unset; opacity: 1;`); }, 500); - setTimeout(() => box._ready = true, 1000); + setTimeout(() => self._ready = true, 1000); return; } @@ -111,32 +111,32 @@ export default ({ if (Math.abs(offset) > maxOffset) { if (offset > 0) { - box.setStyle(rightAnim1); - setTimeout(() => box.setStyle(rightAnim2), 500); + self.setStyle(rightAnim1); + setTimeout(() => self.setStyle(rightAnim2), 500); } else { - box.setStyle(leftAnim1); - setTimeout(() => box.setStyle(leftAnim2), 500); + self.setStyle(leftAnim1); + setTimeout(() => self.setStyle(leftAnim2), 500); } setTimeout(() => { command(); - box.destroy(); + self.destroy(); }, 1000); } else { - box.setStyle('transition: margin 0.5s ease, opacity 0.5s ease; ' + - 'margin-left: ' + startMargin + 'px; ' + - 'margin-right: ' + startMargin + 'px; ' + - 'margin-bottom: unset; margin-top: unset; opacity: 1;'); - if (w.window) - w.window.set_cursor(Gdk.Cursor.new_from_name(display, 'grab')); + self.setStyle(`transition: margin 0.5s ease, opacity 0.5s ease; + margin-left: ${startMargin}px; + margin-right: ${startMargin}px; + margin-bottom: unset; margin-top: unset; opacity: 1;`); + if (widget.window) + widget.window.set_cursor(Gdk.Cursor.new_from_name(display, 'grab')); - box.get_parent()._dragging = false; + self.get_parent()._dragging = false; } }, 'drag-end'], ], }); - return w; + return widget; }; diff --git a/hosts/wim/config/ags/js/notifications/popup.js b/hosts/wim/config/ags/js/notifications/popup.js index 0abe15ed..3588ee18 100644 --- a/hosts/wim/config/ags/js/notifications/popup.js +++ b/hosts/wim/config/ags/js/notifications/popup.js @@ -8,12 +8,13 @@ const Popups = () => Box({ vertical: true, properties: [ ['map', new Map()], - ['dismiss', (box, id, force = false) => { - if (!id || !box._map.has(id)) - return; - if (box._map.get(id)._hovered && !force) + ['dismiss', (box, id, force = false) => { + if (!id || !box._map.has(id) || + box._map.get(id)._hovered && !force) { + return; + } if (box._map.size - 1 === 0) box.get_parent().reveal_child = false; @@ -27,6 +28,7 @@ const Popups = () => Box({ box._map.delete(id); }, 200); }], + ['notify', (box, id) => { if (!id || Notifications.dnd) return; @@ -43,11 +45,12 @@ const Popups = () => Box({ })); box.children = Array.from(box._map.values()).reverse(); + setTimeout(() => { box.get_parent().revealChild = true; }, 10); + box._map.get(id).interval = setInterval(() => { - print('interval') if (!box._map.get(id)._hovered) { box._map.get(id).child.setStyle(box._map.get(id).child._leftAnim1); diff --git a/hosts/wim/config/ags/js/overview/clients.js b/hosts/wim/config/ags/js/overview/clients.js index 9a5efff2..3da2cfc4 100644 --- a/hosts/wim/config/ags/js/overview/clients.js +++ b/hosts/wim/config/ags/js/overview/clients.js @@ -5,10 +5,12 @@ const { execAsync } = Utils; import { WindowButton } from './dragndrop.js'; import * as VARS from './variables.js'; +// Has to be a traditional function for 'this' scope Array.prototype.remove = function (el) { this.splice(this.indexOf(el), 1) }; const scale = size => size * VARS.SCALE - VARS.MARGIN; -const getFontSize = client => Math.min(scale(client.size[0]), scale(client.size[1])) * VARS.ICON_SCALE; +const getFontSize = client => Math.min(scale(client.size[0]), + scale(client.size[1])) * VARS.ICON_SCALE; const IconStyle = client => `transition: font-size 0.2s linear; min-width: ${scale(client.size[0])}px; @@ -31,14 +33,22 @@ const Client = (client, active, clients) => { ], child: WindowButton({ address: client.address, - onSecondaryClickRelease: () => execAsync(`hyprctl dispatch closewindow ${addr}`).catch(print), + onSecondaryClickRelease: () => { + execAsync(`hyprctl dispatch closewindow ${addr}`) + .catch(print); + }, + onPrimaryClickRelease: () => { if (wsId < 0) { if (client.workspace.name === 'special') { - execAsync(`hyprctl dispatch movetoworkspacesilent special:${wsId},${addr}`).then( + execAsync(`hyprctl dispatch + movetoworkspacesilent special:${wsId},${addr}`) + .then( + execAsync(`hyprctl dispatch togglespecialworkspace ${wsId}`).then( () => App.closeWindow('overview') ).catch(print) + ).catch(print); } else { @@ -53,13 +63,15 @@ const Client = (client, active, clients) => { let currentActive = clients.find(c => c.address === activeAddress) if (currentActive && currentActive.workspace.id < 0) { - execAsync(`hyprctl dispatch togglespecialworkspace ${wsName}`).catch(print); + execAsync(`hyprctl dispatch togglespecialworkspace ${wsName}`) + .catch(print); } execAsync(`hyprctl dispatch focuswindow ${addr}`).then( () => App.closeWindow('overview') ).catch(print); } }, + child: Icon({ className: `window ${active}`, style: IconStyle(client) + 'font-size: 10px;', @@ -70,15 +82,15 @@ const Client = (client, active, clients) => { }; export function updateClients(box) { - execAsync('hyprctl clients -j').then( - result => { - let clients = JSON.parse(result).filter(client => client.class) + execAsync('hyprctl clients -j').then(out => { + let clients = JSON.parse(out).filter(client => client.class) box._workspaces.forEach(workspace => { - let fixed = workspace.child.child.get_children()[2].children[0]; + let fixed = workspace.getFixed(); let toRemove = fixed.get_children(); - clients.filter(client => client.workspace.id == workspace._id).forEach(client => { + clients.filter(client => client.workspace.id == workspace._id) + .forEach(client => { let active = ''; if (client.address == Hyprland.active.client.address) { active = 'active'; diff --git a/hosts/wim/config/ags/js/overview/dragndrop.js b/hosts/wim/config/ags/js/overview/dragndrop.js index 47f37b92..5f89e6ae 100644 --- a/hosts/wim/config/ags/js/overview/dragndrop.js +++ b/hosts/wim/config/ags/js/overview/dragndrop.js @@ -6,7 +6,7 @@ import Gtk from 'gi://Gtk'; import Gdk from 'gi://Gdk'; import Cairo from 'cairo'; -import { Button } from '../misc/cursorbox.js'; +import Button from '../misc/cursorbox.js'; import { updateClients } from './clients.js'; const TARGET = [Gtk.TargetEntry.new('text/plain', Gtk.TargetFlags.SAME_APP, 0)]; @@ -29,13 +29,13 @@ function createSurfaceFromWidget(widget) { }; let hidden = 0; -export const WorkspaceDrop = params => EventBox({ - ...params, - connections: [['drag-data-received', (eventbox, _c, _x, _y, data) => { - let id = eventbox.get_parent()._id; +export const WorkspaceDrop = props => EventBox({ + ...props, + connections: [['drag-data-received', (self, _c, _x, _y, data) => { + let id = self.get_parent()._id; if (id < -1) { - id = eventbox.get_parent()._name; + id = self.get_parent()._name; } else if (id === -1) { id = `special:${++hidden}`; @@ -46,26 +46,27 @@ export const WorkspaceDrop = params => EventBox({ execAsync(`hyprctl dispatch movetoworkspacesilent ${id},address:${data.get_text()}`) .catch(print); }]], - setup: eventbox => { - eventbox.drag_dest_set(Gtk.DestDefaults.ALL, TARGET, Gdk.DragAction.COPY); + setup: self => { + self.drag_dest_set(Gtk.DestDefaults.ALL, TARGET, Gdk.DragAction.COPY); }, }); -export const WindowButton = ({address, ...params} = {}) => Button({ - ...params, - setup: button => { - button.drag_source_set(Gdk.ModifierType.BUTTON1_MASK, TARGET, Gdk.DragAction.COPY); - button.connect('drag-data-get', (_w, _c, data) => { +export const WindowButton = ({address, ...props} = {}) => Button({ + type: "Button", + ...props, + setup: self => { + self.drag_source_set(Gdk.ModifierType.BUTTON1_MASK, TARGET, Gdk.DragAction.COPY); + self.connect('drag-data-get', (_w, _c, data) => { data.set_text(address, address.length); }); - button.connect('drag-begin', (_, context) => { - Gtk.drag_set_icon_surface(context, createSurfaceFromWidget(button)); - button.get_parent().revealChild = false; + self.connect('drag-begin', (_, context) => { + Gtk.drag_set_icon_surface(context, createSurfaceFromWidget(self)); + self.get_parent().revealChild = false; }); - button.connect('drag-end', () => { - button.get_parent().destroy(); + self.connect('drag-end', () => { + self.get_parent().destroy(); - let mainBox = App.getWindow('overview').child.children[0].child; + let mainBox = App.getWindow('overview').getChild(); updateClients(mainBox); }); }, diff --git a/hosts/wim/config/ags/js/overview/main.js b/hosts/wim/config/ags/js/overview/main.js index a2bb2ba3..7402a9b4 100644 --- a/hosts/wim/config/ags/js/overview/main.js +++ b/hosts/wim/config/ags/js/overview/main.js @@ -1,10 +1,11 @@ import { App, Hyprland, Widget } from '../../imports.js'; const { Box } = Widget; -import { PopupWindow } from '../misc/popup.js'; +import PopupWindow from '../misc/popup.js'; import { WorkspaceRow, getWorkspaces, updateWorkspaces } from './workspaces.js'; import { updateClients } from './clients.js'; + function update(box) { getWorkspaces(box); updateWorkspaces(box); @@ -14,6 +15,7 @@ function update(box) { export default () => PopupWindow({ name: 'overview', transition: 'crossfade', + onOpen: child => update(child), child: Box({ className: 'overview', @@ -32,17 +34,12 @@ export default () => PopupWindow({ ], }), ], - // The timeout is because the list of clients is async - setup: box => setTimeout(() => update(box), 100), - connections: [ - [Hyprland, box => { - if (!App.getWindow('overview').visible) - return; + connections: [[Hyprland, self => { + if (!App.getWindow('overview').visible) + return; - print('running overview'); - update(box); - }], - ], + update(self); + }]], properties: [ ['workspaces'], ], diff --git a/hosts/wim/config/ags/js/overview/workspaces.js b/hosts/wim/config/ags/js/overview/workspaces.js index bf85c530..3adde232 100644 --- a/hosts/wim/config/ags/js/overview/workspaces.js +++ b/hosts/wim/config/ags/js/overview/workspaces.js @@ -6,7 +6,7 @@ import Gtk from 'gi://Gtk'; import { WorkspaceDrop } from './dragndrop.js'; import * as VARS from './variables.js'; -const DEFAULT_STYLE = `min-width: ${VARS.SCREEN.X * VARS.SCALE}px; +const DEFAULT_STYLE = `min-width: ${VARS.SCREEN.X * VARS.SCALE}px; min-height: ${VARS.SCREEN.Y * VARS.SCALE}px;`; @@ -48,126 +48,140 @@ export const WorkspaceRow = (className, i) => Revealer({ child: Box({ className: className, children: [ - Revealer({ - transition: 'slide_right', - properties: [ - ['id', className === 'special' ? -1 : 1000], - ['name', className === 'special' ? 'special' : ''], - ], - child: WorkspaceDrop({ - child: Overlay({ - child: Box({ - className: 'workspace', - style: DEFAULT_STYLE, - }), - overlays: [ - Box({ - className: 'workspace active', - style: `${DEFAULT_STYLE} opacity: 0;`, - }), - Box({ - style: DEFAULT_STYLE, - children: [ - Widget({ - type: Gtk.Fixed, - }), - Label({ - label: ' +', - style: 'font-size: 40px;', - }), - ], - }) - ], - }), - }), - }), + Workspace(className === 'special' ? -1 : 1000, + className === 'special' ? 'special' : '', + true), ], }), }), null], }), }); -const Workspace = (id, name) => Revealer({ - transition: 'slide_right', - transitionDuration: 500, - properties: [ - ['id', id], - ['name', name], - ['timeouts', []], - ['wasActive', false], - ], - connections: [[Hyprland, box => { - box._timeouts.forEach(timer => timer.destroy()); +// TODO: please make this readable for the love of god +const Workspace = (id, name, extra = false) => { + let workspace; + let fixed = Widget({ + type: Gtk.Fixed, + }); - let activeId = Hyprland.active.workspace.id; - let active = activeId === box._id; + if (!extra) { + workspace = Revealer({ + transition: 'slide_right', + transitionDuration: 500, + properties: [ + ['id', id], + ['name', name], + ['timeouts', []], + ['wasActive', false], + ], + connections: [[Hyprland, box => { + box._timeouts.forEach(timer => timer.destroy()); - let rev = box.child.child.get_children()[1]; - let n = activeId > box._id; + let activeId = Hyprland.active.workspace.id; + let active = activeId === box._id; - if (Hyprland.getWorkspace(box._id)?.windows > 0 || active) { - rev.setStyle(DEFAULT_STYLE); - box._timeouts.push(setTimeout(() => { - box.revealChild = true; - }, 100)); + let rev = box.child.child.get_children()[1]; + let n = activeId > box._id; - } - else if (!Hyprland.getWorkspace(box._id)?.windows > 0) { - rev.setStyle(DEFAULT_STYLE); - box._timeouts.push(setTimeout(() => { - box.revealChild = false; - }, 100)); - return; - } + if (Hyprland.getWorkspace(box._id)?.windows > 0 || active) { + rev.setStyle(DEFAULT_STYLE); + box._timeouts.push(setTimeout(() => { + box.revealChild = true; + }, 100)); - if (active) { - rev.setStyle(`${DEFAULT_STYLE} + } + else if (!Hyprland.getWorkspace(box._id)?.windows > 0) { + rev.setStyle(DEFAULT_STYLE); + box._timeouts.push(setTimeout(() => { + box.revealChild = false; + }, 100)); + return; + } + + if (active) { + rev.setStyle(`${DEFAULT_STYLE} transition: margin 0.5s ease-in-out; opacity: 1;`); - box._wasActive = true; - } - else if (box._wasActive) { - box._timeouts.push(setTimeout(() => { - rev.setStyle(`${DEFAULT_STYLE} + box._wasActive = true; + } + else if (box._wasActive) { + box._timeouts.push(setTimeout(() => { + rev.setStyle(`${DEFAULT_STYLE} transition: margin 0.5s ease-in-out; opacity: 1; margin-left: ${n ? '' : '-'}300px; margin-right: ${n ? '-' : ''}300px;`); - box._wasActive = false; - }, 120)); - box._timeouts.push(setTimeout(() => { - rev.setStyle(`${DEFAULT_STYLE} opacity: 0; + box._wasActive = false; + }, 120)); + box._timeouts.push(setTimeout(() => { + rev.setStyle(`${DEFAULT_STYLE} opacity: 0; margin-left: ${n ? '' : '-'}300px; margin-right: ${n ? '-' : ''}300px;`); - }, 500)); - } - else { - rev.setStyle(`${DEFAULT_STYLE} opacity: 0; + }, 500)); + } + else { + rev.setStyle(`${DEFAULT_STYLE} opacity: 0; margin-left: ${n ? '' : '-'}300px; margin-right: ${n ? '-' : ''}300px;`); - } - }]], - child: WorkspaceDrop({ - child: Overlay({ - child: Box({ - className: 'workspace active', - style: `${DEFAULT_STYLE} opacity: 0;`, - }), - overlays: [ - Box({ - className: 'workspace active', - style: `${DEFAULT_STYLE} opacity: 0;`, - }), - Box({ - className: 'workspace', - style: DEFAULT_STYLE, - child: Widget({ - type: Gtk.Fixed, + } + }]], + child: WorkspaceDrop({ + child: Overlay({ + child: Box({ + className: 'workspace active', + style: `${DEFAULT_STYLE} opacity: 0;`, }), - }) + overlays: [ + Box({ + className: 'workspace active', + style: `${DEFAULT_STYLE} opacity: 0;`, + }), + Box({ + className: 'workspace', + style: DEFAULT_STYLE, + child: fixed, + }) + ], + }), + }), + }); + } + else { + workspace = Revealer({ + transition: 'slide_right', + properties: [ + ['id', id], + ['name', name], ], - }), - }), -}); + child: WorkspaceDrop({ + child: Overlay({ + child: Box({ + className: 'workspace', + style: DEFAULT_STYLE, + }), + overlays: [ + Box({ + className: 'workspace active', + style: `${DEFAULT_STYLE} opacity: 0;`, + }), + Box({ + style: DEFAULT_STYLE, + children: [ + fixed, + Label({ + label: ' +', + style: 'font-size: 40px;', + }), + ], + }) + ], + }), + }), + }); + } + + workspace.getFixed = () => fixed; + return workspace; +}; export function updateWorkspaces(box) { Hyprland.workspaces.forEach(ws => { diff --git a/hosts/wim/config/ags/js/powermenu.js b/hosts/wim/config/ags/js/powermenu.js index 48c66ab2..5381e904 100644 --- a/hosts/wim/config/ags/js/powermenu.js +++ b/hosts/wim/config/ags/js/powermenu.js @@ -1,15 +1,16 @@ import { Widget } from '../imports.js'; const { CenterBox, Label } = Widget; -import { PopupWindow } from './misc/popup.js'; -import { Button } from './misc/cursorbox.js' +import PopupWindow from './misc/popup.js'; +import Button from './misc/cursorbox.js' -const PowermenuWidget = CenterBox({ +const PowermenuWidget = () => CenterBox({ className: 'powermenu', vertical: false, startWidget: Button({ + type: "Button", className: 'shutdown', onPrimaryClickRelease: 'systemctl poweroff', @@ -19,6 +20,7 @@ const PowermenuWidget = CenterBox({ }), centerWidget: Button({ + type: "Button", className: 'reboot', onPrimaryClickRelease: 'systemctl reboot', @@ -28,6 +30,7 @@ const PowermenuWidget = CenterBox({ }), endWidget: Button({ + type: "Button", className: 'logout', onPrimaryClickRelease: 'hyprctl dispatch exit', @@ -40,5 +43,5 @@ const PowermenuWidget = CenterBox({ export default () => PopupWindow({ name: 'powermenu', transition: 'crossfade', - child: PowermenuWidget, + child: PowermenuWidget(), }); diff --git a/hosts/wim/config/ags/js/quick-settings/button-grid.js b/hosts/wim/config/ags/js/quick-settings/button-grid.js index 402e8468..75de300b 100644 --- a/hosts/wim/config/ags/js/quick-settings/button-grid.js +++ b/hosts/wim/config/ags/js/quick-settings/button-grid.js @@ -2,10 +2,14 @@ import { Network, Bluetooth, Audio, App, Utils, Widget } from '../../imports.js' const { Box, CenterBox, Label, Icon } = Widget; const { execAsync } = Utils; -import { EventBox } from '../misc/cursorbox.js'; +import EventBox from '../misc/cursorbox.js'; -const GridButton = ({ command = () => {}, secondaryCommand = () => {}, icon } = {}) => Box({ +const GridButton = ({ + command = () => {}, + secondaryCommand = () => {}, + icon +} = {}) => Box({ className: 'grid-button', children: [ @@ -27,7 +31,7 @@ const GridButton = ({ command = () => {}, secondaryCommand = () => {}, icon } = ], }); -const FirstRow = Box({ +const FirstRow = () => Box({ className: 'button-row', halign: 'center', style: 'margin-top: 15px; margin-bottom: 7px;', @@ -35,7 +39,10 @@ const FirstRow = Box({ GridButton({ command: () => Network.toggleWifi(), - secondaryCommand: () => execAsync(['bash', '-c', 'nm-connection-editor']).catch(print), + secondaryCommand: () => { + execAsync(['bash', '-c', 'nm-connection-editor']) + .catch(print); + }, icon: Icon({ className: 'grid-label', connections: [[Network, icon => { @@ -50,35 +57,47 @@ const FirstRow = Box({ }), GridButton({ - command: () => execAsync(['bash', '-c', '$AGS_PATH/qs-toggles.sh blue-toggle']).catch(print), - secondaryCommand: () => execAsync(['bash', '-c', 'blueberry']).catch(print), + command: () => { + execAsync(['bash', '-c', '$AGS_PATH/qs-toggles.sh blue-toggle']) + .catch(print); + }, + secondaryCommand: () => { + execAsync(['bash', '-c', 'blueberry']) + .catch(print) + }, icon: Icon({ className: 'grid-label', - connections: [[Bluetooth, icon => { + connections: [[Bluetooth, self => { if (Bluetooth.enabled) { - icon.icon = 'bluetooth-active-symbolic'; - execAsync(['bash', '-c', 'echo 󰂯 > $HOME/.config/.bluetooth']).catch(print); + self.icon = 'bluetooth-active-symbolic'; + execAsync(['bash', '-c', 'echo 󰂯 > $HOME/.config/.bluetooth']) + .catch(print); } else { - icon.icon = 'bluetooth-disabled-symbolic'; - execAsync(['bash', '-c', 'echo 󰂲 > $HOME/.config/.bluetooth']).catch(print); + self.icon = 'bluetooth-disabled-symbolic'; + execAsync(['bash', '-c', 'echo 󰂲 > $HOME/.config/.bluetooth']) + .catch(print); } }, 'changed']], }) }), GridButton({ - command: () => execAsync(['bash', '-c', '$AGS_PATH/qs-toggles.sh toggle-radio']).catch(print), - secondaryCommand: () => execAsync(['notify-send', 'set this up moron']).catch(print), + command: () => { + execAsync(['bash', '-c', '$AGS_PATH/qs-toggles.sh toggle-radio']) + .catch(print); + }, + secondaryCommand: () => { + execAsync(['notify-send', 'set this up moron']) + .catch(print); + }, icon: Icon({ className: 'grid-label', - connections: [[Network, icon => { - if (Network.wifi.enabled) { - icon.icon = 'airplane-mode-disabled-symbolic'; - } - else { - icon.icon = 'airplane-mode-symbolic'; - } + connections: [[Network, self => { + if (Network.wifi.enabled) + self.icon = 'airplane-mode-disabled-symbolic'; + else + self.icon = 'airplane-mode-symbolic'; }, 'changed']], }), }), @@ -86,7 +105,7 @@ const FirstRow = Box({ ], }); -const SubRow = CenterBox({ +const SubRow = () => CenterBox({ halign: 'start', children: [ @@ -94,8 +113,9 @@ const SubRow = CenterBox({ className: 'sub-label', truncate: 'end', maxWidthChars: 12, - connections: [[Network, label => { - label.label = Network.wifi.ssid; + connections: [[Network, self => { + // TODO: handle ethernet too + self.label = Network.wifi.ssid; }, 'changed']], }), @@ -103,20 +123,15 @@ const SubRow = CenterBox({ className: 'sub-label', truncate: 'end', maxWidthChars: 12, - connections: [[Bluetooth, label => { - label.label = Bluetooth.connectedDevices[0] ? String(Bluetooth.connectedDevices[0]) : - 'Disconnected'; + connections: [[Bluetooth, self => { + if (Bluetooth.connectedDevices[0]) + self.label = String(Bluetooth.connectedDevices[0]) + else + self.label = 'Disconnected'; }, 'changed']], }), - Label({ - className: '', - truncate: 'end', - maxWidthChars: 12, - /*connections: [[Network, label => { - label.label = Network.wifi.ssid; - }, 'changed']],*/ - }), + null, ], }); @@ -135,15 +150,23 @@ const itemsMic = { 0: 'audio-input-microphone-muted-symbolic', }; -const SecondRow = Box({ +const SecondRow = () => Box({ className: 'button-row', halign: 'center', style: 'margin-top: 7px; margin-bottom: 15px;', children: [ GridButton({ - command: () => execAsync(['swayosd-client', '--output-volume', 'mute-toggle']).catch(print), - secondaryCommand: () => execAsync(['bash', '-c', 'pavucontrol']).catch(print), + command: () => { + execAsync(['swayosd-client', '--output-volume', 'mute-toggle']) + .catch(print); + }, + + secondaryCommand: () => { + execAsync(['bash', '-c', 'pavucontrol']) + .catch(print); + }, + icon: Icon({ className: 'grid-label', connections: [[Audio, icon => { @@ -165,8 +188,16 @@ const SecondRow = Box({ }), GridButton({ - command: () => execAsync(['swayosd-client', '--input-volume', 'mute-toggle']).catch(print), - secondaryCommand: () => execAsync(['bash', '-c', 'pavucontrol']).catch(print), + command: () => { + execAsync(['swayosd-client', '--input-volume', 'mute-toggle']) + .catch(print); + }, + + secondaryCommand: () => { + execAsync(['bash', '-c', 'pavucontrol']) + .catch(print); + }, + icon: Icon({ className: 'grid-label', connections: [[Audio, icon => { @@ -188,7 +219,10 @@ const SecondRow = Box({ }), GridButton({ - command: () => execAsync(['bash', '-c', '$LOCK_PATH/lock.sh']).catch(print), + command: () => { + execAsync(['bash', '-c', '$LOCK_PATH/lock.sh']) + .catch(print); + }, secondaryCommand: () => App.openWindow('powermenu'), icon: Label({ className: 'grid-label', @@ -199,14 +233,13 @@ const SecondRow = Box({ ], }); - -export const ButtonGrid = Box({ +export default () => Box({ className: 'button-grid', vertical: true, halign: 'center', children: [ - FirstRow, - SubRow, - SecondRow, + FirstRow(), + SubRow(), + SecondRow(), ], }); diff --git a/hosts/wim/config/ags/js/quick-settings/main.js b/hosts/wim/config/ags/js/quick-settings/main.js index 834980d0..fad89013 100644 --- a/hosts/wim/config/ags/js/quick-settings/main.js +++ b/hosts/wim/config/ags/js/quick-settings/main.js @@ -3,14 +3,14 @@ const { Box, Label, Revealer, Icon } = Widget; import Gtk from 'gi://Gtk'; -import { ButtonGrid } from './button-grid.js'; -import { SliderBox } from './slider-box.js'; -import Player from '../media-player/player.js'; -import { EventBox } from '../misc/cursorbox.js'; -import { PopupWindow } from '../misc/popup.js'; +import ButtonGrid from './button-grid.js'; +import SliderBox from './slider-box.js'; +import Player from '../media-player/player.js'; +import EventBox from '../misc/cursorbox.js'; +import PopupWindow from '../misc/popup.js'; -const QuickSettingsWidget = Box({ +const QuickSettingsWidget = () => Box({ className: 'qs-container', vertical: true, children: [ @@ -27,9 +27,9 @@ const QuickSettingsWidget = Box({ style: 'margin-left: 20px' }), - ButtonGrid, + ButtonGrid(), - SliderBox, + SliderBox(), EventBox({ child: Widget({ @@ -41,13 +41,15 @@ const QuickSettingsWidget = Box({ }); }, connections: [['toggled', button => { + let rev = button.get_parent().get_parent().get_parent().children[1]; + if (button.get_active()) { button.child.setStyle("-gtk-icon-transform: rotate(0deg);"); - button.get_parent().get_parent().get_parent().children[1].revealChild = true; + rev.revealChild = true; } else { button.child.setStyle('-gtk-icon-transform: rotate(180deg);'); - button.get_parent().get_parent().get_parent().children[1].revealChild = false; + rev.revealChild = false; } }]], child: Icon({ @@ -73,5 +75,5 @@ export default () => PopupWindow({ name: 'quick-settings', anchor: [ 'top', 'right' ], margin: [ 8, 5, 0, ], - child: QuickSettingsWidget, + child: QuickSettingsWidget(), }); diff --git a/hosts/wim/config/ags/js/quick-settings/slider-box.js b/hosts/wim/config/ags/js/quick-settings/slider-box.js index be3c419e..3aaecfff 100644 --- a/hosts/wim/config/ags/js/quick-settings/slider-box.js +++ b/hosts/wim/config/ags/js/quick-settings/slider-box.js @@ -11,7 +11,7 @@ const items = { }; -export const SliderBox = Box({ +export default () => Box({ className: 'slider-box', vertical: true, halign: 'center', @@ -73,11 +73,14 @@ export const SliderBox = Box({ ['canChange', true], ], onChange: ({ value }) => { - execAsync(`brightnessctl set ${value}`).catch(print); + execAsync(`brightnessctl set ${value}`) + .catch(print); }, connections: [[1000, slider => { if (slider._canChange) { - execAsync('brightnessctl get').then(out => slider.value = out).catch(print); + execAsync('brightnessctl get') + .then(out => slider.value = out) + .catch(print); } }]], min: 0, diff --git a/hosts/wim/config/ags/js/screen-corners.js b/hosts/wim/config/ags/js/screen-corners.js index 5a519be9..7e91c6d1 100644 --- a/hosts/wim/config/ags/js/screen-corners.js +++ b/hosts/wim/config/ags/js/screen-corners.js @@ -8,13 +8,23 @@ export const RoundedCorner = (place, props) => Widget({ halign: place.includes('left') ? 'start' : 'end', valign: place.includes('top') ? 'start' : 'end', setup: widget => { - const r = widget.get_style_context().get_property('border-radius', Gtk.StateFlags.NORMAL); + const r = widget.get_style_context() + .get_property('border-radius', Gtk.StateFlags.NORMAL); + widget.set_size_request(r, r); widget.connect('draw', Lang.bind(widget, (widget, cr) => { - const c = widget.get_style_context().get_property('background-color', Gtk.StateFlags.NORMAL); - const r = widget.get_style_context().get_property('border-radius', Gtk.StateFlags.NORMAL); - const borderColor = widget.get_style_context().get_property('color', Gtk.StateFlags.NORMAL); - const borderWidth = widget.get_style_context().get_border(Gtk.StateFlags.NORMAL).left; // ur going to write border-width: something anyway + const c = widget.get_style_context() + .get_property('background-color', Gtk.StateFlags.NORMAL); + + const r = widget.get_style_context() + .get_property('border-radius', Gtk.StateFlags.NORMAL); + + const borderColor = widget.get_style_context() + .get_property('color', Gtk.StateFlags.NORMAL); + + // ur going to write border-width: something anyway + const borderWidth = widget.get_style_context() + .get_border(Gtk.StateFlags.NORMAL).left; widget.set_size_request(r, r); switch (place) { @@ -43,7 +53,10 @@ export const RoundedCorner = (place, props) => Widget({ cr.setSourceRGBA(c.red, c.green, c.blue, c.alpha); cr.fill(); cr.setLineWidth(borderWidth); - cr.setSourceRGBA(borderColor.red, borderColor.green, borderColor.blue, borderColor.alpha); + cr.setSourceRGBA(borderColor.red, + borderColor.green, + borderColor.blue, + borderColor.alpha); cr.stroke(); })); }, diff --git a/hosts/wim/config/hypr/main.conf b/hosts/wim/config/hypr/main.conf index 73b73e35..c07b8072 100644 --- a/hosts/wim/config/hypr/main.conf +++ b/hosts/wim/config/hypr/main.conf @@ -28,7 +28,7 @@ exec-once = ags exec-once = gnome-keyring-daemon --start --components=secrets exec-once = squeekboard -exec-once = bash -c "sleep 1; ags -t applauncher" +exec-once = bash -c "sleep 3; ags -t applauncher" exec-once = hyprpaper exec-once = wl-paste --watch cliphist store