chore: update ags and start fixing breaking changes

This commit is contained in:
matt1432 2023-12-17 00:01:58 -05:00
parent 4f349dae0f
commit 4412d13997
39 changed files with 1064 additions and 966 deletions

View file

@ -21,6 +21,7 @@ exec(`sassc ${scss} ${css}`);
Setup(); Setup();
// TODO: get rid of 'properties' and 'binds' prop
export default { export default {
style: css, style: css,
notificationPopupTimeout: 5000, notificationPopupTimeout: 5000,

View file

@ -101,6 +101,23 @@ const Applauncher = ({ window_name = 'applauncher' } = {}) => {
className: 'applauncher', className: 'applauncher',
vertical: true, vertical: true,
setup: (self) => {
self.hook(App, (_, name, visible) => {
if (name !== window_name) {
return;
}
entry.text = '';
if (visible) {
entry.grab_focus();
}
else {
makeNewChildren();
}
});
},
children: [ children: [
Box({ Box({
className: 'header', className: 'header',
@ -119,21 +136,6 @@ const Applauncher = ({ window_name = 'applauncher' } = {}) => {
}), }),
}), }),
], ],
connections: [[App, (_, name, visible) => {
if (name !== window_name) {
return;
}
entry.text = '';
if (visible) {
entry.grab_focus();
}
else {
makeNewChildren();
}
}]],
}); });
}; };

View file

@ -13,11 +13,13 @@ const SpeakerIndicator = (props) => Icon({
const SpeakerPercentLabel = (props) => Label({ const SpeakerPercentLabel = (props) => Label({
...props, ...props,
connections: [[Audio, (label) => { setup: (self) => {
if (Audio.speaker) { self.hook(Audio, (label) => {
label.label = `${Math.round(Audio.speaker.volume * 100)}%`; if (Audio.speaker) {
} label.label = `${Math.round(Audio.speaker.volume * 100)}%`;
}, 'speaker-changed']], }
}, 'speaker-changed');
},
}); });
const SPACING = 5; const SPACING = 5;

View file

@ -12,20 +12,24 @@ const Indicator = () => Icon({
binds: [['icon', Battery, 'icon-name']], binds: [['icon', Battery, 'icon-name']],
connections: [[Battery, (self) => { setup: (self) => {
self.toggleClassName('charging', Battery.charging); self.hook(Battery, () => {
self.toggleClassName('charged', Battery.charged); self.toggleClassName('charging', Battery.charging);
self.toggleClassName('low', Battery.percent < LOW_BATT); self.toggleClassName('charged', Battery.charged);
}]], self.toggleClassName('low', Battery.percent < LOW_BATT);
});
},
}); });
const LevelLabel = (props) => Label({ const LevelLabel = (props) => Label({
...props, ...props,
className: 'label', className: 'label',
connections: [[Battery, (self) => { setup: (self) => {
self.label = `${Battery.percent}%`; self.hook(Battery, () => {
}]], self.label = `${Battery.percent}%`;
});
},
}); });
const SPACING = 5; const SPACING = 5;

View file

@ -7,25 +7,29 @@ import Separator from '../../misc/separator.js';
const Indicator = (props) => Icon({ const Indicator = (props) => Icon({
...props, ...props,
connections: [[Bluetooth, (self) => { setup: (self) => {
if (Bluetooth.enabled) { self.hook(Bluetooth, () => {
self.icon = Bluetooth.connectedDevices[0] ? if (Bluetooth.enabled) {
Bluetooth.connectedDevices[0].iconName : self.icon = Bluetooth.connectedDevices[0] ?
'bluetooth-active-symbolic'; Bluetooth.connectedDevices[0].iconName :
} 'bluetooth-active-symbolic';
else { }
self.icon = 'bluetooth-disabled-symbolic'; else {
} self.icon = 'bluetooth-disabled-symbolic';
}]], }
});
},
}); });
const ConnectedLabel = (props) => Label({ const ConnectedLabel = (props) => Label({
...props, ...props,
connections: [[Bluetooth, (self) => { setup: (self) => {
self.label = Bluetooth.connectedDevices[0] ? self.hook(Bluetooth, () => {
`${Bluetooth.connectedDevices[0]}` : self.label = Bluetooth.connectedDevices[0] ?
'Disconnected'; `${Bluetooth.connectedDevices[0]}` :
}, 'notify::connected-devices']], 'Disconnected';
}, 'notify::connected-devices');
},
}); });
const SPACING = 5; const SPACING = 5;

View file

@ -13,9 +13,11 @@ const Indicator = (props) => Icon({
const BrightnessPercentLabel = (props) => Label({ const BrightnessPercentLabel = (props) => Label({
...props, ...props,
connections: [[Brightness, (self) => { setup: (self) => {
self.label = `${Math.round(Brightness.screen * 100)}%`; self.hook(Brightness, () => {
}, 'screen']], self.label = `${Math.round(Brightness.screen * 100)}%`;
}, 'screen');
},
}); });
export default () => { export default () => {

View file

@ -8,36 +8,32 @@ const { DateTime } = GLib;
import EventBox from '../../misc/cursorbox.js'; import EventBox from '../../misc/cursorbox.js';
const ClockModule = ({ const ClockModule = () => Label({
interval = 1000, className: 'clock',
...props
} = {}) => {
return Label({
...props,
className: 'clock',
connections: [[interval, (self) => { setup: (self) => {
self.poll(1000, () => {
const time = DateTime.new_now_local(); const time = DateTime.new_now_local();
self.label = time.format('%a. ') + self.label = time.format('%a. ') +
time.get_day_of_month() + time.get_day_of_month() +
time.format(' %b. %H:%M'); time.format(' %b. %H:%M');
}]], });
}); },
}; });
export default () => EventBox({ export default () => EventBox({
className: 'toggle-off', className: 'toggle-off',
onPrimaryClickRelease: () => App.toggleWindow('calendar'), onPrimaryClickRelease: () => App.toggleWindow('calendar'),
connections: [ setup: (self) => {
[App, (self, windowName, visible) => { self.hook(App, (_, windowName, visible) => {
if (windowName === 'calendar') { if (windowName === 'calendar') {
self.toggleClassName('toggle-on', visible); self.toggleClassName('toggle-on', visible);
} }
}], });
], },
child: ClockModule(), child: ClockModule(),
}); });

View file

@ -13,14 +13,17 @@ export default () => Box({
Icon({ Icon({
size: 30, size: 30,
connections: [[Hyprland.active.client, (self) => { setup: (self) => {
const app = Applications.query(Hyprland.active.client.class)[0]; self.hook(Hyprland.active.client, () => {
const app = Applications
.query(Hyprland.active.client.class)[0];
if (app) { if (app) {
self.icon = app.iconName; self.icon = app.iconName;
self.visible = Hyprland.active.client.title !== ''; self.visible = Hyprland.active.client.title !== '';
} }
}]], });
},
}), }),
Separator(SPACING), Separator(SPACING),

View file

@ -8,40 +8,44 @@ const DEFAULT_KB = 'at-translated-set-2-keyboard';
const SPACING = 4; const SPACING = 4;
const Indicator = () => Label({
css: 'font-size: 20px;',
setup: (self) => {
self.hook(Hyprland, (_, _n, layout) => {
if (layout) {
if (layout === 'error') {
return;
}
const shortName = layout.match(/\(([A-Za-z]+)\)/);
self.label = shortName ? shortName[1] : layout;
}
else {
// At launch, kb layout is undefined
Hyprland.sendMessage('j/devices').then((obj) => {
const kb = JSON.parse(obj).keyboards
.find((val) => val.name === DEFAULT_KB);
layout = kb['active_keymap'];
const shortName = layout
.match(/\(([A-Za-z]+)\)/);
self.label = shortName ? shortName[1] : layout;
}).catch(print);
}
}, 'keyboard-layout');
},
});
export default () => { export default () => {
const rev = Revealer({ const rev = Revealer({
transition: 'slide_right', transition: 'slide_right',
child: Box({ child: Box({
children: [ children: [
Separator(SPACING), Separator(SPACING),
Label({ Indicator(),
css: 'font-size: 20px;',
connections: [[Hyprland, (self, _n, layout) => {
if (layout) {
if (layout === 'error') {
return;
}
const shortName = layout.match(/\(([A-Za-z]+)\)/);
self.label = shortName ? shortName[1] : layout;
}
else {
// At launch, kb layout is undefined
Hyprland.sendMessage('j/devices').then((obj) => {
const kb = JSON.parse(obj).keyboards
.find((val) => val.name === DEFAULT_KB);
layout = kb['active_keymap'];
const shortName = layout
.match(/\(([A-Za-z]+)\)/);
self.label = shortName ? shortName[1] : layout;
}).catch(print);
}
}, 'keyboard-layout']],
}),
], ],
}), }),
}); });

View file

@ -7,36 +7,40 @@ import Separator from '../../misc/separator.js';
const Indicator = (props) => Icon({ const Indicator = (props) => Icon({
...props, ...props,
connections: [[Network, (self) => { setup: (self) => {
if (Network.wifi.internet === 'connected' || self.hook(Network, () => {
Network.wifi.internet === 'connecting') { if (Network.wifi.internet === 'connected' ||
self.icon = Network.wifi.iconName; Network.wifi.internet === 'connecting') {
} self.icon = Network.wifi.iconName;
else if (Network.wired.internet === 'connected' || }
Network.wired.internet === 'connecting') { else if (Network.wired.internet === 'connected' ||
self.icon = Network.wired.iconName; Network.wired.internet === 'connecting') {
} self.icon = Network.wired.iconName;
else { }
self.icon = Network.wifi.iconName; else {
} self.icon = Network.wifi.iconName;
}]], }
});
},
}); });
const APLabel = (props) => Label({ const APLabel = (props) => Label({
...props, ...props,
connections: [[Network, (self) => { setup: (self) => {
if (Network.wifi.internet === 'connected' || self.hook(Network, () => {
Network.wifi.internet === 'connecting') { if (Network.wifi.internet === 'connected' ||
self.label = Network.wifi.ssid; Network.wifi.internet === 'connecting') {
} self.label = Network.wifi.ssid;
else if (Network.wired.internet === 'connected' || }
Network.wired.internet === 'connecting') { else if (Network.wired.internet === 'connected' ||
self.label = 'Connected'; Network.wired.internet === 'connecting') {
} self.label = 'Connected';
else { }
self.label = 'Disconnected'; else {
} self.label = 'Disconnected';
}]], }
});
},
}); });
const SPACING = 5; const SPACING = 5;

View file

@ -19,11 +19,13 @@ export default () => EventBox({
App.toggleWindow('notification-center'); App.toggleWindow('notification-center');
}, },
connections: [[App, (self, windowName, visible) => { setup: (self) => {
if (windowName === 'notification-center') { self.hook(App, (_, windowName, visible) => {
self.toggleClassName('toggle-on', visible); if (windowName === 'notification-center') {
} self.toggleClassName('toggle-on', visible);
}]], }
});
},
child: CenterBox({ child: CenterBox({
className: 'notif-panel', className: 'notif-panel',
@ -31,17 +33,19 @@ export default () => EventBox({
center_widget: Box({ center_widget: Box({
children: [ children: [
Icon({ Icon({
connections: [[Notifications, (self) => { setup: (self) => {
if (Notifications.dnd) { self.hook(Notifications, () => {
self.icon = 'notification-disabled-symbolic'; 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) {
} self.icon = 'notification-new-symbolic';
else { }
self.icon = 'notification-symbolic'; else {
} self.icon = 'notification-symbolic';
}]], }
});
},
}), }),
Separator(SPACING), Separator(SPACING),

View file

@ -9,9 +9,11 @@ export default () => EventBox({
onPrimaryClickRelease: () => Tablet.toggleOsk(), onPrimaryClickRelease: () => Tablet.toggleOsk(),
connections: [[Tablet, (self) => { setup: (self) => {
self.toggleClassName('toggle-on', Tablet.oskState); self.hook(Tablet, () => {
}, 'osk-toggled']], self.toggleClassName('toggle-on', Tablet.oskState);
}, 'osk-toggled');
},
child: Box({ child: Box({
className: 'osk-toggle', className: 'osk-toggle',

View file

@ -26,11 +26,13 @@ export default () => EventBox({
App.toggleWindow('quick-settings'); App.toggleWindow('quick-settings');
}, },
connections: [[App, (self, windowName, visible) => { setup: (self) => {
if (windowName === 'quick-settings') { self.hook(App, (_, windowName, visible) => {
self.toggleClassName('toggle-on', visible); if (windowName === 'quick-settings') {
} self.toggleClassName('toggle-on', visible);
}]], }
});
},
child: Box({ child: Box({
className: 'quick-settings-toggle', className: 'quick-settings-toggle',

View file

@ -33,42 +33,39 @@ const SysTray = () => MenuBar({
setup: (self) => { setup: (self) => {
self.items = new Map(); self.items = new Map();
self.onAdded = (id) => { self
const item = SystemTray.getItem(id); .hook(SystemTray, (_, id) => {
const item = SystemTray.getItem(id);
if (self.items.has(id) || !item) { if (self.items.has(id) || !item) {
return; return;
} }
const w = SysTrayItem(item); const w = SysTrayItem(item);
// Early return if item is in blocklist // Early return if item is in blocklist
if (!w) { if (!w) {
return; return;
} }
self.items.set(id, w); self.items.set(id, w);
self.add(w); self.add(w);
self.show_all(); self.show_all();
w.child.revealChild = true; w.child.revealChild = true;
}; }, 'added')
self.onRemoved = (id) => { .hook(SystemTray, (_, id) => {
if (!self.items.has(id)) { if (!self.items.has(id)) {
return; return;
} }
self.items.get(id).child.revealChild = false; self.items.get(id).child.revealChild = false;
timeout(REVEAL_DURATION, () => { timeout(REVEAL_DURATION, () => {
self.items.get(id).destroy(); self.items.get(id).destroy();
self.items.delete(id); self.items.delete(id);
}); });
}; }, 'removed');
}, },
connections: [
[SystemTray, (self, id) => self.onAdded(id), 'added'],
[SystemTray, (self, id) => self.onRemoved(id), 'removed'],
],
}); });
export default () => { export default () => {
@ -77,9 +74,11 @@ export default () => {
return Revealer({ return Revealer({
transition: 'slide_right', transition: 'slide_right',
connections: [[SystemTray, (rev) => { setup: (self) => {
rev.revealChild = systray.get_children().length > 0; self.hook(SystemTray, () => {
}]], self.revealChild = systray.get_children().length > 0;
});
},
child: Box({ child: Box({
children: [ children: [

View file

@ -9,9 +9,11 @@ export default () => EventBox({
onPrimaryClickRelease: () => Tablet.toggleMode(), onPrimaryClickRelease: () => Tablet.toggleMode(),
connections: [[Tablet, (self) => { setup: (self) => {
self.toggleClassName('toggle-on', Tablet.tabletMode); self.hook(Tablet, () => {
}, 'mode-toggled']], self.toggleClassName('toggle-on', Tablet.tabletMode);
}, 'mode-toggled');
},
child: Box({ child: Box({
className: 'tablet-toggle', className: 'tablet-toggle',

View file

@ -43,19 +43,19 @@ const Workspace = ({ i } = {}) => {
} }
} }
}; };
self
.hook(Hyprland, () => self.update())
// Deal with urgent windows
.hook(Hyprland, (_, a) => {
self.update(a);
}, 'urgent-window')
.hook(Hyprland.active.workspace, () => {
if (Hyprland.active.workspace.id === i) {
self.toggleClassName('urgent', false);
}
});
}, },
connections: [
[Hyprland, (self) => self.update()],
// Deal with urgent windows
[Hyprland, (self, a) => self.update(a), 'urgent-window'],
[Hyprland.active.workspace, (self) => {
if (Hyprland.active.workspace.id === i) {
self.toggleClassName('urgent', false);
}
}],
],
}), }),
}), }),
}); });
@ -81,7 +81,9 @@ export default () => {
vpack: 'center', vpack: 'center',
hpack: 'start', hpack: 'start',
className: 'button active', className: 'button active',
connections: [[Hyprland.active.workspace, updateHighlight]], setup: (self) => {
self.hook(Hyprland.active.workspace, updateHighlight);
},
}); });
const widget = Overlay({ const widget = Overlay({
@ -122,21 +124,23 @@ export default () => {
}], }],
], ],
connections: [[Hyprland, (self) => { setup: (self) => {
self._workspaces = self.children.filter((ch) => { self.hook(Hyprland, () => {
return Hyprland.workspaces.find((ws) => { self._workspaces = self.children.filter((ch) => {
return ws.id === ch._id; return Hyprland.workspaces.find((ws) => {
}); return ws.id === ch._id;
}).sort((a, b) => a._id - b._id); });
}).sort((a, b) => a._id - b._id);
self._updateWorkspaces(self); self._updateWorkspaces(self);
self._refresh(self); self._refresh(self);
// Make sure the highlight doesn't go too far // Make sure the highlight doesn't go too far
const TEMP_TIMEOUT = 10; const TEMP_TIMEOUT = 10;
timeout(TEMP_TIMEOUT, () => updateHighlight(highlight)); timeout(TEMP_TIMEOUT, () => updateHighlight(highlight));
}]], });
},
}), }),
}), }),
}); });

View file

@ -31,19 +31,20 @@ export default (props) => {
hexpand: true, hexpand: true,
vertical: true, vertical: true,
connections: [ setup: (self) => {
[Hyprland.active, () => { self
const workspace = Hyprland.getWorkspace( .hook(Hyprland.active, () => {
Hyprland.active.workspace.id, const workspace = Hyprland.getWorkspace(
); Hyprland.active.workspace.id,
);
Revealed.value = !workspace?.hasfullscreen; Revealed.value = !workspace?.hasfullscreen;
}], })
[Hyprland, (_, fullscreen) => { .hook(Hyprland, (_, fullscreen) => {
Revealed.value = !fullscreen; Revealed.value = !fullscreen;
}, 'fullscreen'], }, 'fullscreen');
], },
children: [ children: [
Revealer({ Revealer({

View file

@ -25,9 +25,11 @@ const Time = () => Box({
Label({ Label({
className: 'content', className: 'content',
label: 'hour', label: 'hour',
connections: [[1000, (self) => { setup: (self) => {
self.label = DateTime.new_now_local().format('%H'); self.poll(1000, () => {
}]], self.label = DateTime.new_now_local().format('%H');
});
},
}), }),
Divider(), Divider(),
@ -35,9 +37,11 @@ const Time = () => Box({
Label({ Label({
className: 'content', className: 'content',
label: 'minute', label: 'minute',
connections: [[1000, (self) => { setup: (self) => {
self.label = DateTime.new_now_local().format('%M'); self.poll(1000, () => {
}]], self.label = DateTime.new_now_local().format('%M');
});
},
}), }),
], ],
@ -49,13 +53,15 @@ const Time = () => Box({
child: Label({ child: Label({
css: 'font-size: 20px', css: 'font-size: 20px',
label: 'complete date', label: 'complete date',
connections: [[1000, (self) => { setup: (self) => {
const time = DateTime.new_now_local(); self.poll(1000, () => {
const time = DateTime.new_now_local();
self.label = time.format('%A, %B ') + self.label = time.format('%A, %B ') +
time.get_day_of_month() + time.get_day_of_month() +
time.format(', %Y'); time.format(', %Y');
}]], });
},
}), }),
}), }),

View file

@ -12,7 +12,7 @@ const TRANSITION = `transition: margin ${ANIM_DURATION}ms ease,
export default ({ export default ({
properties, properties,
connections, setup = () => {/**/},
props, props,
} = {}) => { } = {}) => {
const widget = EventBox(); const widget = EventBox();
@ -33,101 +33,103 @@ export default ({
child: emptyPlayer, child: emptyPlayer,
connections: [ setup: (self) => {
...connections, setup(self);
[gesture, (overlay, realGesture) => { self
if (realGesture) { .hook(gesture, (overlay, realGesture) => {
overlay.list().forEach((over) => { if (realGesture) {
over.visible = true; overlay.list().forEach((over) => {
}); over.visible = true;
} });
else { }
overlay.showTopOnly(); else {
} overlay.showTopOnly();
}
// Don't allow gesture when only one player // Don't allow gesture when only one player
if (overlay.list().length <= 1) { if (overlay.list().length <= 1) {
return; return;
} }
overlay._dragging = true; overlay._dragging = true;
let offset = gesture.get_offset()[1]; let offset = gesture.get_offset()[1];
const playerBox = overlay.list().at(-1); const playerBox = overlay.list().at(-1);
// Slide right // Slide right
if (offset >= 0) {
playerBox.setCss(`
margin-left: ${offset}px;
margin-right: -${offset}px;
${playerBox._bgStyle}
`);
}
// Slide left
else {
offset = Math.abs(offset);
playerBox.setCss(`
margin-left: -${offset}px;
margin-right: ${offset}px;
${playerBox._bgStyle}
`);
}
}, 'drag-update'],
[gesture, (overlay) => {
// Don't allow gesture when only one player
if (overlay.list().length <= 1) {
return;
}
overlay._dragging = false;
const offset = gesture.get_offset()[1];
const playerBox = overlay.list().at(-1);
// If crosses threshold after letting go, slide away
if (Math.abs(offset) > MAX_OFFSET) {
// Disable inputs during animation
widget.sensitive = false;
// Slide away right
if (offset >= 0) { if (offset >= 0) {
playerBox.setCss(` playerBox.setCss(`
${TRANSITION} margin-left: ${offset}px;
margin-left: ${OFFSCREEN}px; margin-right: -${offset}px;
margin-right: -${OFFSCREEN}px; ${playerBox._bgStyle}
opacity: 0.7; ${playerBox._bgStyle}
`); `);
} }
// Slide away left // Slide left
else { else {
offset = Math.abs(offset);
playerBox.setCss(` playerBox.setCss(`
${TRANSITION} margin-left: -${offset}px;
margin-left: -${OFFSCREEN}px; margin-right: ${offset}px;
margin-right: ${OFFSCREEN}px; ${playerBox._bgStyle}
opacity: 0.7; ${playerBox._bgStyle}`); `);
}
}, 'drag-update')
.hook(gesture, (overlay) => {
// Don't allow gesture when only one player
if (overlay.list().length <= 1) {
return;
} }
timeout(ANIM_DURATION, () => { overlay._dragging = false;
// Put the player in the back after anim const offset = gesture.get_offset()[1];
overlay.reorder_overlay(playerBox, 0);
// Recenter player
playerBox.setCss(playerBox._bgStyle);
widget.sensitive = true; const playerBox = overlay.list().at(-1);
overlay.showTopOnly(); // If crosses threshold after letting go, slide away
}); if (Math.abs(offset) > MAX_OFFSET) {
} // Disable inputs during animation
else { widget.sensitive = false;
// Recenter with transition for animation
playerBox.setCss(`${TRANSITION} ${playerBox._bgStyle}`); // Slide away right
} if (offset >= 0) {
}, 'drag-end'], playerBox.setCss(`
], ${TRANSITION}
margin-left: ${OFFSCREEN}px;
margin-right: -${OFFSCREEN}px;
opacity: 0.7; ${playerBox._bgStyle}
`);
}
// Slide away left
else {
playerBox.setCss(`
${TRANSITION}
margin-left: -${OFFSCREEN}px;
margin-right: ${OFFSCREEN}px;
opacity: 0.7; ${playerBox._bgStyle}
`);
}
timeout(ANIM_DURATION, () => {
// Put the player in the back after anim
overlay.reorder_overlay(playerBox, 0);
// Recenter player
playerBox.setCss(playerBox._bgStyle);
widget.sensitive = true;
overlay.showTopOnly();
});
}
else {
// Recenter with transition for animation
playerBox.setCss(`${TRANSITION} ${playerBox._bgStyle}`);
}
}, 'drag-end');
},
}); });
widget.add(content); widget.add(content);

View file

@ -60,19 +60,18 @@ export const CoverArt = (player, props) => CenterBox({
self.setCss(self._bgStyle); self.setCss(self._bgStyle);
} }
}); });
},
connections: [[player, (self) => { self.hook(player, () => {
execAsync(['bash', '-c', `[[ -f "${player.coverPath}" ]] && execAsync(['bash', '-c', `[[ -f "${player.coverPath}" ]] &&
coloryou "${player.coverPath}" | grep -v Warning`]) coloryou "${player.coverPath}" | grep -v Warning`])
.then((out) => { .then((out) => {
if (!Mpris.players.find((p) => player === p)) { if (!Mpris.players.find((p) => player === p)) {
return; return;
} }
player.colors.value = JSON.parse(out); player.colors.value = JSON.parse(out);
self._bgStyle = ` self._bgStyle = `
background: radial-gradient(circle, background: radial-gradient(circle,
rgba(0, 0, 0, 0.4) 30%, rgba(0, 0, 0, 0.4) 30%,
${player.colors.value.imageAccent}), ${player.colors.value.imageAccent}),
@ -81,15 +80,16 @@ export const CoverArt = (player, props) => CenterBox({
background-position: center; background-position: center;
`; `;
if (!self.get_parent()._dragging) { if (!self.get_parent()._dragging) {
self.setCss(self._bgStyle); self.setCss(self._bgStyle);
} }
}).catch((err) => { }).catch((err) => {
if (err !== '') { if (err !== '') {
print(err); print(err);
} }
}); });
}]], });
},
}); });
export const TitleLabel = (player, props) => Label({ export const TitleLabel = (player, props) => Label({
@ -127,27 +127,31 @@ export const PlayerIcon = (player, overlay, props) => {
className: widget ? 'position-indicator' : 'player-icon', className: widget ? 'position-indicator' : 'player-icon',
size: widget ? '' : ICON_SIZE, size: widget ? '' : ICON_SIZE,
connections: [[p, (self) => { setup: (self) => {
self.icon = lookUpIcon(p.entry) ? self.hook(p, () => {
p.entry : self.icon = lookUpIcon(p.entry) ?
icons.mpris.fallback; p.entry :
}]], icons.mpris.fallback;
});
},
}), }),
}); });
return Box({ return Box({
connections: [[Mpris, (self) => { setup: (self) => {
const thisIndex = overlay.list() self.hook(Mpris, () => {
.indexOf(self.get_parent().get_parent()); const thisIndex = overlay.list()
.indexOf(self.get_parent().get_parent());
self.children = overlay.list().map((over, i) => { self.children = overlay.list().map((over, i) => {
self.children.push(Separator(2)); self.children.push(Separator(2));
return i === thisIndex ? return i === thisIndex ?
playerIcon(player) : playerIcon(player) :
playerIcon(over._player, overlay, over); playerIcon(over._player, overlay, over);
}).reverse(); }).reverse();
}]], });
},
}); });
}; };
@ -163,38 +167,38 @@ export const PositionSlider = (player, props) => Slider({
player.position = player.length * value; player.position = player.length * value;
}, },
properties: [['update', (slider) => { setup: (self) => {
if (!slider.dragging) { const update = () => {
slider.visible = player.length > 0; if (!self.dragging) {
if (player.length > 0) { self.visible = player.length > 0;
slider.value = player.position / player.length; if (player.length > 0) {
self.value = player.position / player.length;
}
} }
} };
}]],
connections: [ self
[1000, (s) => s._update(s)], .poll(1000, () => update())
[player, (s) => s._update(s), 'position'], .hook(player, () => update(), 'position')
[player.colors, (s) => { .hook(player.colors, () => {
if (player.colors.value) { if (player.colors.value) {
const c = player.colors.value; const c = player.colors.value;
s.setCss(` self.setCss(`
highlight { background-color: ${c.buttonAccent}; } highlight { background-color: ${c.buttonAccent}; }
slider { background-color: ${c.buttonAccent}; } slider { background-color: ${c.buttonAccent}; }
slider:hover { background-color: ${c.hoverAccent}; } slider:hover { background-color: ${c.hoverAccent}; }
trough { background-color: ${c.buttonText}; } trough { background-color: ${c.buttonText}; }
`); `);
} }
}], })
.on('button-press-event', (s) => {
['button-press-event', (s) => { s.cursor = 'grabbing';
s.cursor = 'grabbing'; })
}], .on('button-release-event', (s) => {
['button-release-event', (s) => { s.cursor = 'pointer';
s.cursor = 'pointer'; });
}], },
],
}); });
const PlayerButton = ({ player, items, onClick, prop }) => EventBox({ const PlayerButton = ({ player, items, onClick, prop }) => EventBox({
@ -212,13 +216,13 @@ const PlayerButton = ({ player, items, onClick, prop }) => EventBox({
items.forEach((item) => { items.forEach((item) => {
item[1].setCss(` item[1].setCss(`
background-color: ${c.hoverAccent}; background-color: ${c.hoverAccent};
color: ${c.buttonText}; color: ${c.buttonText};
min-height: 40px; min-height: 40px;
min-width: 36px; min-width: 36px;
margin-bottom: 1px; margin-bottom: 1px;
margin-right: 1px; margin-right: 1px;
`); `);
}); });
} }
}, },
@ -230,60 +234,61 @@ const PlayerButton = ({ player, items, onClick, prop }) => EventBox({
items.forEach((item) => { items.forEach((item) => {
item[1].setCss(` item[1].setCss(`
background-color: ${c.buttonAccent}; background-color: ${c.buttonAccent};
color: ${c.buttonText}; color: ${c.buttonText};
min-height: 42px; min-height: 42px;
min-width: 38px; min-width: 38px;
`); `);
}); });
} }
}, },
connections: [ setup: (self) => {
[player, (button) => { self
button.child.shown = `${player[prop]}`; .hook(player, () => {
}], self.child.shown = `${player[prop]}`;
})
.hook(player.colors, () => {
if (!Mpris.players.find((p) => player === p)) {
return;
}
[player.colors, (button) => { if (player.colors.value) {
if (!Mpris.players.find((p) => player === p)) { const c = player.colors.value;
return;
}
if (player.colors.value) { if (prop === 'playBackStatus') {
const c = player.colors.value; if (self._hovered) {
items.forEach((item) => {
if (prop === 'playBackStatus') { item[1].setCss(`
if (button._hovered) { background-color: ${c.hoverAccent};
items.forEach((item) => { color: ${c.buttonText};
item[1].setCss(` min-height: 40px;
background-color: ${c.hoverAccent}; min-width: 36px;
color: ${c.buttonText}; margin-bottom: 1px;
min-height: 40px; margin-right: 1px;
min-width: 36px; `);
margin-bottom: 1px; });
margin-right: 1px; }
`); else {
}); items.forEach((item) => {
item[1].setCss(`
background-color: ${c.buttonAccent};
color: ${c.buttonText};
min-height: 42px;
min-width: 38px;
`);
});
}
} }
else { else {
items.forEach((item) => { self.setCss(`
item[1].setCss(` * { color: ${c.buttonAccent}; }
background-color: ${c.buttonAccent}; *:hover { color: ${c.hoverAccent}; }
color: ${c.buttonText}; `);
min-height: 42px;
min-width: 38px;`);
});
} }
} }
else { });
button.setCss(` },
* { color: ${c.buttonAccent}; }
*:hover { color: ${c.hoverAccent}; }
`);
}
}
}],
],
}), }),
}); });

View file

@ -107,72 +107,72 @@ export default () => {
['setup', false], ['setup', false],
], ],
connections: [ setup: (self) => {
[Mpris, (overlay, busName) => { self
if (overlay._players.has(busName)) { .hook(Mpris, (overlay, busName) => {
return; if (overlay._players.has(busName)) {
}
// Sometimes the signal doesn't give the busName
if (!busName) {
const player = Mpris.players.find((p) => {
return !overlay._players.has(p.busName);
});
if (player) {
busName = player.busName;
}
else {
return; return;
} }
}
// Get the one on top so we can move it up later // Sometimes the signal doesn't give the busName
const previousFirst = overlay.list().at(-1); if (!busName) {
const player = Mpris.players.find((p) => {
return !overlay._players.has(p.busName);
});
// Make the new player if (player) {
const player = Mpris.getPlayer(busName); busName = player.busName;
}
else {
return;
}
}
player.colors = Variable(); // Get the one on top so we can move it up later
overlay._players.set( const previousFirst = overlay.list().at(-1);
busName,
PlayerBox(player, content.getOverlay()),
);
overlay.overlays = Array.from(overlay._players.values())
.map((widget) => widget);
// Select favorite player at startup // Make the new player
if (!overlay._setup && overlay._players.has(FAVE_PLAYER)) { const player = Mpris.getPlayer(busName);
overlay.moveToTop(overlay._players.get(FAVE_PLAYER));
overlay._setup = true;
}
// Move previousFirst on top again player.colors = Variable();
else if (overlay.includesWidget(previousFirst)) { overlay._players.set(
overlay.moveToTop(previousFirst); busName,
} PlayerBox(player, content.getOverlay()),
}, 'player-added'], );
overlay.overlays = Array.from(overlay._players.values())
.map((widget) => widget);
// Select favorite player at startup
if (!overlay._setup && overlay._players.has(FAVE_PLAYER)) {
overlay.moveToTop(overlay._players.get(FAVE_PLAYER));
overlay._setup = true;
}
[Mpris, (overlay, busName) => { // Move previousFirst on top again
if (!busName || !overlay._players.has(busName)) { else if (overlay.includesWidget(previousFirst)) {
return; overlay.moveToTop(previousFirst);
} }
}, 'player-added')
// Get the one on top so we can move it up later .hook(Mpris, (overlay, busName) => {
const previousFirst = overlay.list().at(-1); if (!busName || !overlay._players.has(busName)) {
return;
}
// Remake overlays without deleted one // Get the one on top so we can move it up later
overlay._players.delete(busName); const previousFirst = overlay.list().at(-1);
overlay.overlays = Array.from(overlay._players.values())
.map((widget) => widget);
// Move previousFirst on top again // Remake overlays without deleted one
if (overlay.includesWidget(previousFirst)) { overlay._players.delete(busName);
overlay.moveToTop(previousFirst); overlay.overlays = Array.from(overlay._players.values())
} .map((widget) => widget);
}, 'player-closed'],
], // Move previousFirst on top again
if (overlay.includesWidget(previousFirst)) {
overlay.moveToTop(previousFirst);
}
}, 'player-closed');
},
}); });
return Box({ return Box({

View file

@ -42,7 +42,7 @@ export default ({
const gesture = Gtk.GestureLongPress.new(widget); const gesture = Gtk.GestureLongPress.new(widget);
widget.connectTo(gesture, () => { widget.hook(gesture, () => {
const pointer = gesture.get_point(null); const pointer = gesture.get_point(null);
const x = pointer[1]; const x = pointer[1];
const y = pointer[2]; const y = pointer[2];

View file

@ -58,20 +58,22 @@ export default ({
transition, transition,
transitionDuration, transitionDuration,
connections: [[App, (rev, currentName, isOpen) => { setup: (self) => {
if (currentName === name) { self.hook(App, (_, currentName, isOpen) => {
rev.revealChild = isOpen; if (currentName === name) {
self.revealChild = isOpen;
if (isOpen) { if (isOpen) {
onOpen(window); onOpen(window);
}
else {
timeout(transitionDuration, () => {
onClose(window);
});
}
} }
else { });
timeout(transitionDuration, () => { },
onClose(window);
});
}
}
}]],
child: child || Box(), child: child || Box(),
}), }),

View file

@ -28,28 +28,30 @@ const NotificationList = () => Box({
vexpand: true, vexpand: true,
vpack: 'start', vpack: 'start',
binds: [['visible', HasNotifs]], binds: [['visible', HasNotifs]],
connections: [
[Notifications, (box, id) => {
// Handle cached notifs
if (box.children.length === 0) {
Notifications.notifications.forEach((n) => {
addNotif(box, n);
});
}
else if (id) { setup: (self) => {
addNotif(box, Notifications.getNotification(id)); self
} .hook(Notifications, (box, id) => {
}, 'notified'], // Handle cached notifs
if (box.children.length === 0) {
Notifications.notifications.forEach((n) => {
addNotif(box, n);
});
}
[Notifications, (box, id) => { else if (id) {
const notif = box.children.find((ch) => ch._id === id); addNotif(box, Notifications.getNotification(id));
}
}, 'notified')
if (notif?.sensitive) { .hook(Notifications, (box, id) => {
notif.slideAway('Right'); const notif = box.children.find((ch) => ch._id === id);
}
}, 'closed'], if (notif?.sensitive) {
], notif.slideAway('Right');
}
}, 'closed');
},
}); });
// Needs to be wrapped to still have onHover when disabled // Needs to be wrapped to still have onHover when disabled
@ -64,11 +66,13 @@ const ClearButton = () => EventBox({
children: [ children: [
Label('Clear '), Label('Clear '),
Icon({ Icon({
connections: [[Notifications, (self) => { setup: (self) => {
self.icon = Notifications.notifications.length > 0 ? self.hook(Notifications, () => {
'user-trash-full-symbolic' : self.icon = Notifications.notifications.length > 0 ?
'user-trash-symbolic'; 'user-trash-full-symbolic' :
}]], 'user-trash-symbolic';
});
},
}), }),
], ],
}), }),

View file

@ -91,80 +91,80 @@ export default ({
widget.add(Box({ widget.add(Box({
css: squeezeLeft, css: squeezeLeft,
connections: [ setup: (self) => {
self
// When dragging
.hook(gesture, () => {
let offset = gesture.get_offset()[1];
// When dragging if (offset === 0) {
[gesture, (self) => { return;
let offset = gesture.get_offset()[1]; }
if (offset === 0) { // Slide right
return; if (offset > 0) {
} self.setCss(`
// Slide right
if (offset > 0) {
self.setCss(`
margin-top: 0px; margin-bottom: 0px; margin-top: 0px; margin-bottom: 0px;
opacity: 1; transition: none; opacity: 1; transition: none;
margin-left: ${offset}px; margin-left: ${offset}px;
margin-right: -${offset}px; margin-right: -${offset}px;
`); `);
} }
// Slide left // Slide left
else { else {
offset = Math.abs(offset); offset = Math.abs(offset);
self.setCss(` self.setCss(`
margin-top: 0px; margin-bottom: 0px; margin-top: 0px; margin-bottom: 0px;
opacity: 1; transition: none; opacity: 1; transition: none;
margin-right: ${offset}px; margin-right: ${offset}px;
margin-left: -${offset}px; margin-left: -${offset}px;
`); `);
} }
// Put a threshold on if a click is actually dragging // Put a threshold on if a click is actually dragging
widget._dragging = Math.abs(offset) > SLIDE_MIN_THRESHOLD; widget._dragging = Math.abs(offset) > SLIDE_MIN_THRESHOLD;
widget.cursor = 'grabbing'; widget.cursor = 'grabbing';
}, 'drag-update'], }, 'drag-update')
// On drag end
.hook(gesture, () => {
// Make it slide in on init
if (!widget.ready) {
// Reverse of slideAway, so it started at squeeze, then we go to slide
self.setCss(slideIn === 'Left' ?
slideLeft :
slideRight);
// On drag end
[gesture, (self) => {
// Make it slide in on init
if (!widget.ready) {
// Reverse of slideAway, so it started at squeeze, then we go to slide
self.setCss(slideIn === 'Left' ? slideLeft : slideRight);
timeout(ANIM_DURATION, () => {
// Then we go to center
self.setCss(defaultStyle);
timeout(ANIM_DURATION, () => { timeout(ANIM_DURATION, () => {
widget.ready = true; // Then we go to center
self.setCss(defaultStyle);
timeout(ANIM_DURATION, () => {
widget.ready = true;
});
}); });
});
return; return;
} }
const offset = gesture.get_offset()[1]; const offset = gesture.get_offset()[1];
// If crosses threshold after letting go, slide away // If crosses threshold after letting go, slide away
if (Math.abs(offset) > MAX_OFFSET) { if (Math.abs(offset) > MAX_OFFSET) {
if (offset > 0) { if (offset > 0) {
widget.slideAway('Right'); widget.slideAway('Right');
}
else {
widget.slideAway('Left');
}
} }
else { else {
widget.slideAway('Left'); self.setCss(defaultStyle);
widget.cursor = 'grab';
widget._dragging = false;
} }
} }, 'drag-end');
else { },
self.setCss(defaultStyle);
widget.cursor = 'grab';
widget._dragging = false;
}
}, 'drag-end'],
],
})); }));
return widget; return widget;

View file

@ -10,56 +10,57 @@ import { Notification } from './base.js';
const DELAY = 2000; const DELAY = 2000;
const addPopup = (box, id) => {
if (!id) {
return;
}
const notif = Notifications.getNotification(id);
const NewNotif = Notification({
notif,
command: () => notif.dismiss(),
});
if (NewNotif) {
// Use this instead of add to put it at the top
box.pack_end(NewNotif, false, false, 0);
box.show_all();
}
};
const handleDismiss = (box, id, force = false) => {
const notif = box.children.find((ch) => ch._id === id);
if (!notif) {
return;
}
// If notif isn't hovered or was closed, slide away
if (!notif._hovered || force) {
notif.slideAway('Left');
}
// If notif is hovered, delay close
else if (notif._hovered) {
notif.interval = interval(DELAY, () => {
if (!notif._hovered && notif.interval) {
notif.slideAway('Left');
GLib.source_remove(notif.interval);
notif.interval = null;
}
});
}
};
export default () => Box({ export default () => Box({
vertical: true, vertical: true,
connections: [ setup: (self) => {
[Notifications, (s, id) => addPopup(s, id), 'notified'], const addPopup = (id) => {
[Notifications, (s, id) => handleDismiss(s, id), 'dismissed'], if (!id) {
[Notifications, (s, id) => handleDismiss(s, id, true), 'closed'], return;
], }
const notif = Notifications.getNotification(id);
const NewNotif = Notification({
notif,
command: () => notif.dismiss(),
});
if (NewNotif) {
// Use this instead of add to put it at the top
self.pack_end(NewNotif, false, false, 0);
self.show_all();
}
};
const handleDismiss = (id, force = false) => {
const notif = self.children.find((ch) => ch._id === id);
if (!notif) {
return;
}
// If notif isn't hovered or was closed, slide away
if (!notif._hovered || force) {
notif.slideAway('Left');
}
// If notif is hovered, delay close
else if (notif._hovered) {
notif.interval = interval(DELAY, () => {
if (!notif._hovered && notif.interval) {
notif.slideAway('Left');
GLib.source_remove(notif.interval);
notif.interval = null;
}
});
}
};
self
.hook(Notifications, (_, id) => addPopup(id), 'notified')
.hook(Notifications, (_, id) => handleDismiss(id), 'dismissed')
.hook(Notifications, (_, id) => handleDismiss(id, true), 'closed');
},
}); });

View file

@ -37,15 +37,17 @@ export default (window) => Box({
active: true, active: true,
vpack: 'center', vpack: 'center',
connections: [['toggled', (self) => { setup: (self) => {
self.toggleClassName( self.on('toggled', () => {
'toggled', self.toggleClassName(
self.get_active(), 'toggled',
); self.get_active(),
window.exclusivity = self.get_active() ? );
'exclusive' : window.exclusivity = self.get_active() ?
'normal'; 'exclusive' :
}]], 'normal';
});
},
child: Label('Exclusive'), child: Label('Exclusive'),
}), }),

View file

@ -86,11 +86,13 @@ const ModKey = (key) => {
self.child.toggleClassName('active', !Mod.value); self.child.toggleClassName('active', !Mod.value);
Mod.value = !Mod.value; Mod.value = !Mod.value;
}, },
connections: [[NormalClick, (self) => { setup: (self) => {
Mod.value = false; self.hook(NormalClick, () => {
self.child.toggleClassName('active', false); Mod.value = false;
execAsync(`ydotool key ${key.keycode}:0`); self.child.toggleClassName('active', false);
}]], execAsync(`ydotool key ${key.keycode}:0`);
});
},
child: Label({ child: Label({
class_name: `mod ${key.label}`, class_name: `mod ${key.label}`,
label: key.label, label: key.label,
@ -114,40 +116,41 @@ const RegularKey = (key) => {
class_name: `normal ${key.label}`, class_name: `normal ${key.label}`,
label: key.label, label: key.label,
connections: [ setup: (self) => {
[Shift, (self) => { self
if (!key.labelShift) { .hook(Shift, () => {
return; if (!key.labelShift) {
} return;
}
self.label = Shift.value ? key.labelShift : key.label; self.label = Shift.value ? key.labelShift : key.label;
}], })
.hook(Caps, () => {
if (key.label === 'Caps') {
self.toggleClassName('active', Caps.value);
[Caps, (self) => { return;
if (key.label === 'Caps') { }
self.toggleClassName('active', Caps.value);
return; if (!key.labelShift) {
} return;
}
if (!key.labelShift) { if (key.label.match(/[A-Za-z]/)) {
return; self.label = Caps.value ?
} key.labelShift :
key.label;
}
})
.hook(AltGr, () => {
if (!key.labelAltGr) {
return;
}
if (key.label.match(/[A-Za-z]/)) { self.toggleClassName('altgr', AltGr.value);
self.label = Caps.value ? key.labelShift : key.label; self.label = AltGr.value ? key.labelAltGr : key.label;
} });
}], },
[AltGr, (self) => {
if (!key.labelAltGr) {
return;
}
self.toggleClassName('altgr', AltGr.value);
self.label = AltGr.value ? key.labelAltGr : key.label;
}],
],
}), }),
}); });
@ -156,7 +159,7 @@ const RegularKey = (key) => {
gesture.delay_factor = 1.0; gesture.delay_factor = 1.0;
// Long press // Long press
widget.connectTo(gesture, () => { widget.hook(gesture, () => {
const pointer = gesture.get_point(null); const pointer = gesture.get_point(null);
const x = pointer[1]; const x = pointer[1];
const y = pointer[2]; const y = pointer[2];
@ -171,7 +174,7 @@ const RegularKey = (key) => {
}, 'pressed'); }, 'pressed');
// OnPrimaryClickRelease // OnPrimaryClickRelease
widget.connectTo(gesture, () => { widget.hook(gesture, () => {
const pointer = gesture.get_point(null); const pointer = gesture.get_point(null);
const x = pointer[1]; const x = pointer[1];
const y = pointer[2]; const y = pointer[2];

View file

@ -16,17 +16,18 @@ export default () => {
visible: false, visible: false,
anchor: ['left', 'bottom', 'right'], anchor: ['left', 'bottom', 'right'],
connections: [ setup: (self) => {
[Tablet, (self, state) => { self
self.setVisible(state); .hook(Tablet, (_, state) => {
}, 'osk-toggled'], self.setVisible(state);
}, 'osk-toggled')
[Tablet, () => { .hook(Tablet, () => {
if (!Tablet.tabletMode && !Tablet.oskState) { if (!Tablet.tabletMode && !Tablet.oskState) {
window.visible = false; window.visible = false;
} }
}, 'mode-toggled'], }, 'mode-toggled');
], },
}); });
window.child = Keyboard(window); window.child = Keyboard(window);

View file

@ -36,7 +36,7 @@ export default ({ stack, icon, info } = {}) => {
connectFunc = () => stack.popup(osd); connectFunc = () => stack.popup(osd);
} }
osd.children[0].children[1].connectTo(info.mod, connectFunc, info.signal); osd.children[0].children[1].hook(info.mod, connectFunc, info.signal);
return osd; return osd;
}; };

View file

@ -33,28 +33,28 @@ let hidden = 0;
export const WorkspaceDrop = (props) => EventBox({ export const WorkspaceDrop = (props) => EventBox({
...props, ...props,
connections: [['drag-data-received', (self, _c, _x, _y, data) => {
let id = self.get_parent()._id;
if (id < -1) {
id = self.get_parent()._name;
}
else if (id === -1) {
id = `special:${++hidden}`;
}
else if (id === 1000) {
id = 'empty';
}
Hyprland.sendMessage('dispatch ' +
`movetoworkspacesilent ${id},address:${data.get_text()}`)
.catch(print);
}]],
setup: (self) => { setup: (self) => {
self.drag_dest_set(Gtk.DestDefaults.ALL, TARGET, Gdk.DragAction.COPY); self.drag_dest_set(Gtk.DestDefaults.ALL, TARGET, Gdk.DragAction.COPY);
self.on('drag-data-received', (_, _c, _x, _y, data) => {
let id = self.get_parent()._id;
if (id < -1) {
id = self.get_parent()._name;
}
else if (id === -1) {
id = `special:${++hidden}`;
}
else if (id === 1000) {
id = 'empty';
}
Hyprland.sendMessage('dispatch ' +
`movetoworkspacesilent ${id},address:${data.get_text()}`)
.catch(print);
});
}, },
}); });
@ -69,16 +69,16 @@ export const WindowButton = ({ address, mainBox, ...props } = {}) => Button({
Gdk.DragAction.COPY, Gdk.DragAction.COPY,
); );
self.connect('drag-data-get', (_w, _c, data) => { self.on('drag-data-get', (_w, _c, data) => {
data.set_text(address, address.length); data.set_text(address, address.length);
}); });
self.connect('drag-begin', (_, context) => { self.on('drag-begin', (_, context) => {
Gtk.drag_set_icon_surface(context, createSurfaceFromWidget(self)); Gtk.drag_set_icon_surface(context, createSurfaceFromWidget(self));
self.get_parent().revealChild = false; self.get_parent().revealChild = false;
}); });
self.connect('drag-end', () => { self.on('drag-end', () => {
self.get_parent().destroy(); self.get_parent().destroy();
updateClients(mainBox); updateClients(mainBox);

View file

@ -40,13 +40,15 @@ export const Overview = () => {
}), }),
], ],
connections: [[Hyprland, (self) => { setup: (self) => {
if (!App.getWindow('overview').visible) { self.hook(Hyprland, () => {
return; if (!App.getWindow('overview').visible) {
} return;
}
self.update(); self.update();
}]], });
},
properties: [ properties: [
['workspaces'], ['workspaces'],
@ -72,15 +74,17 @@ export const Overview = () => {
}), }),
// TODO: throttle his? // TODO: throttle his?
connections: [['get-child-position', (self, ch) => { setup: (self) => {
if (ch === mainBox) { self.on('get-child-position', (_, ch) => {
self.child.setCss(` if (ch === mainBox) {
transition: min-height 0.2s ease, min-width 0.2s ease; self.child.setCss(`
min-height: ${mainBox.get_allocated_height()}px; transition: min-height 0.2s ease, min-width 0.2s ease;
min-width: ${mainBox.get_allocated_width()}px; min-height: ${mainBox.get_allocated_height()}px;
`); min-width: ${mainBox.get_allocated_width()}px;
} `);
}]], }
});
},
}); });
widget.getChild = () => mainBox; widget.getChild = () => mainBox;

View file

@ -31,17 +31,17 @@ const Workspace = (id, name, normal = true) => {
transition: 'slide_right', transition: 'slide_right',
transitionDuration: 500, transitionDuration: 500,
connections: normal ? setup: (self) => {
if (normal) {
self.hook(Hyprland, () => {
const activeId = Hyprland.active.workspace.id;
const active = activeId === self._id;
[[Hyprland, (box) => { self.revealChild = Hyprland.getWorkspace(self._id)
const activeId = Hyprland.active.workspace.id; ?.windows > 0 || active;
const active = activeId === box._id; });
}
box.revealChild = Hyprland.getWorkspace(box._id) },
?.windows > 0 || active;
}]] :
[],
child: WorkspaceDrop({ child: WorkspaceDrop({
child: Box({ child: Box({
@ -88,38 +88,42 @@ export const WorkspaceRow = (className, i) => {
transition: 'slide_down', transition: 'slide_down',
hpack: className === 'special' ? '' : 'start', hpack: className === 'special' ? '' : 'start',
connections: [[Hyprland, (rev) => { setup: (self) => {
const minId = i * VARS.WORKSPACE_PER_ROW; self.hook(Hyprland, (rev) => {
const activeId = Hyprland.active.workspace.id; const minId = i * VARS.WORKSPACE_PER_ROW;
const activeId = Hyprland.active.workspace.id;
const rowExists = Hyprland.workspaces.some((ws) => { const rowExists = Hyprland.workspaces.some((ws) => {
const isInRow = ws.id > minId; const isInRow = ws.id > minId;
const hasClients = ws.windows > 0; const hasClients = ws.windows > 0;
const isActive = ws.id === activeId; const isActive = ws.id === activeId;
return isInRow && (hasClients || isActive); return isInRow && (hasClients || isActive);
});
rev.revealChild = rowExists;
}); });
},
rev.revealChild = rowExists;
}]],
child: CenterBox({ child: CenterBox({
children: [null, EventBox({ children: [null, EventBox({
connections: [[Hyprland, () => { setup: (self) => {
const maxId = (i + 1) * VARS.WORKSPACE_PER_ROW; self.hook(Hyprland, () => {
const activeId = Hyprland.active.workspace.id; const maxId = (i + 1) * VARS.WORKSPACE_PER_ROW;
const activeId = Hyprland.active.workspace.id;
const isSpecial = className === 'special'; const isSpecial = className === 'special';
const nextRowExists = Hyprland.workspaces.some((ws) => { const nextRowExists = Hyprland.workspaces.some((ws) => {
const isInNextRow = ws.id > maxId; const isInNextRow = ws.id > maxId;
const hasClients = ws.windows > 0; const hasClients = ws.windows > 0;
const isActive = ws.id === activeId; const isActive = ws.id === activeId;
return isInNextRow && (hasClients || isActive); return isInNextRow && (hasClients || isActive);
});
addWorkspace.revealChild = isSpecial || !nextRowExists;
}); });
},
addWorkspace.revealChild = isSpecial || !nextRowExists;
}]],
child: Box({ child: Box({
className, className,

View file

@ -5,8 +5,8 @@ import { Box, Icon, Label, ListBox, Overlay, Revealer, Scrollable } from 'resour
import EventBox from '../misc/cursorbox.js'; import EventBox from '../misc/cursorbox.js';
const SCROLL_THRESHOLD_H = 200; const SCROLL_THRESH_H = 200;
const SCROLL_THRESHOLD_N = 7; const SCROLL_THRESH_N = 7;
const BluetoothDevice = (dev) => { const BluetoothDevice = (dev) => {
@ -29,9 +29,11 @@ const BluetoothDevice = (dev) => {
icon: 'object-select-symbolic', icon: 'object-select-symbolic',
hexpand: true, hexpand: true,
hpack: 'end', hpack: 'end',
connections: [[dev, (self) => { setup: (self) => {
self.setCss(`opacity: ${dev.paired ? '1' : '0'};`); self.hook(dev, () => {
}]], self.setCss(`opacity: ${dev.paired ? '1' : '0'};`);
});
},
}), }),
], ],
}); });
@ -95,17 +97,19 @@ export const BluetoothMenu = () => {
hscroll: 'never', hscroll: 'never',
vscroll: 'never', vscroll: 'never',
connections: [['edge-reached', (_, pos) => { setup: (self) => {
// Manage scroll indicators self.on('edge-reached', (_, pos) => {
if (pos === 2) { // Manage scroll indicators
topArrow.revealChild = false; if (pos === 2) {
bottomArrow.revealChild = true; topArrow.revealChild = false;
} bottomArrow.revealChild = true;
else if (pos === 3) { }
topArrow.revealChild = true; else if (pos === 3) {
bottomArrow.revealChild = false; topArrow.revealChild = true;
} bottomArrow.revealChild = false;
}]], }
});
},
child: ListBox({ child: ListBox({
setup: (self) => { setup: (self) => {
@ -113,78 +117,79 @@ export const BluetoothMenu = () => {
return b.get_children()[0].dev.paired - return b.get_children()[0].dev.paired -
a.get_children()[0].dev.paired; a.get_children()[0].dev.paired;
}); });
},
connections: [[Bluetooth, (box) => { self.hook(Bluetooth, () => {
// Get all devices // Get all devices
const Devices = [].concat( const Devices = [].concat(
Bluetooth.devices, Bluetooth.devices,
Bluetooth.connectedDevices, Bluetooth.connectedDevices,
); );
// Add missing devices // Add missing devices
Devices.forEach((dev) => { Devices.forEach((dev) => {
if (!DevList.has(dev) && dev.name) { if (!DevList.has(dev) && dev.name) {
DevList.set(dev, BluetoothDevice(dev)); DevList.set(dev, BluetoothDevice(dev));
box.add(DevList.get(dev)); self.add(DevList.get(dev));
box.show_all(); self.show_all();
} }
}); });
// Delete ones that don't exist anymore // Delete ones that don't exist anymore
const difference = Array.from(DevList.keys()) const difference = Array.from(DevList.keys())
.filter((dev) => !Devices .filter((dev) => !Devices
.find((d) => dev === d) && .find((d) => dev === d) &&
dev.name); dev.name);
difference.forEach((dev) => { difference.forEach((dev) => {
const devWidget = DevList.get(dev); const devWidget = DevList.get(dev);
if (devWidget) { if (devWidget) {
if (devWidget.toDestroy) { if (devWidget.toDestroy) {
devWidget.get_parent().destroy(); devWidget.get_parent().destroy();
DevList.delete(dev); DevList.delete(dev);
}
else {
devWidget.children[0]
.revealChild = false;
devWidget.toDestroy = true;
}
} }
else { });
devWidget.children[0].revealChild = false;
devWidget.toDestroy = true; // Start scrolling after a specified height
// is reached by the children
const height = Math.max(
self.get_parent().get_allocated_height(),
SCROLL_THRESH_H,
);
const scroll = self.get_parent().get_parent();
if (self.get_children().length > SCROLL_THRESH_N) {
scroll.vscroll = 'always';
scroll.setCss(`min-height: ${height}px;`);
// Make bottom scroll indicator appear only
// when first getting overflowing children
if (!(bottomArrow.revealChild === true ||
topArrow.revealChild === true)) {
bottomArrow.revealChild = true;
} }
} }
}); else {
scroll.vscroll = 'never';
// Start scrolling after a specified height scroll.setCss('');
// is reached by the children topArrow.revealChild = false;
const height = Math.max( bottomArrow.revealChild = false;
box.get_parent().get_allocated_height(),
SCROLL_THRESHOLD_H,
);
const scroll = box.get_parent().get_parent();
if (box.get_children().length > SCROLL_THRESHOLD_N) {
scroll.vscroll = 'always';
scroll.setCss(`min-height: ${height}px;`);
// Make bottom scroll indicator appear only
// when first getting overflowing children
if (!(bottomArrow.revealChild === true ||
topArrow.revealChild === true)) {
bottomArrow.revealChild = true;
} }
}
else {
scroll.vscroll = 'never';
scroll.setCss('');
topArrow.revealChild = false;
bottomArrow.revealChild = false;
}
// Trigger sort_func // Trigger sort_func
box.get_children().forEach((ch) => { self.get_children().forEach((ch) => {
ch.changed(); ch.changed();
});
}); });
}]], },
}), }),
}), }),
}), }),

View file

@ -34,24 +34,27 @@ const GridButton = ({
icon = Icon({ icon = Icon({
className: 'grid-label', className: 'grid-label',
icon, icon,
connections: [[Activated, (self) => { setup: (self) => {
self.setCss(`color: ${Activated.value ? self.hook(Activated, () => {
'rgba(189, 147, 249, 0.8)' : self.setCss(`color: ${Activated.value ?
'unset'};`); 'rgba(189, 147, 249, 0.8)' :
}]], 'unset'};`);
});
},
}); });
} }
else { else {
icon = Icon({ icon = Icon({
className: 'grid-label', className: 'grid-label',
connections: [ setup: (self) => {
icon, self
[Activated, (self) => { .hook(...icon)
self.setCss(`color: ${Activated.value ? .hook(Activated, () => {
'rgba(189, 147, 249, 0.8)' : self.setCss(`color: ${Activated.value ?
'unset'};`); 'rgba(189, 147, 249, 0.8)' :
}], 'unset'};`);
], });
},
}); });
} }
@ -61,7 +64,9 @@ const GridButton = ({
justification: 'left', justification: 'left',
truncate: 'end', truncate: 'end',
maxWidthChars: 12, maxWidthChars: 12,
connections: [indicator], setup: (self) => {
self.hook(...indicator);
},
}); });
} }
@ -126,17 +131,19 @@ const GridButton = ({
icon: `${App.configDir }/icons/down-large.svg`, icon: `${App.configDir }/icons/down-large.svg`,
className: 'grid-chev', className: 'grid-chev',
connections: [[Activated, (self) => { setup: (self) => {
let deg = 270; self.hook(Activated, () => {
let deg = 270;
if (Activated.value) { if (Activated.value) {
deg = menu ? 360 : 450; deg = menu ? 360 : 450;
onOpen(menu); onOpen(menu);
} }
self.setCss(` self.setCss(`
-gtk-icon-transform: rotate(${deg}deg); -gtk-icon-transform: rotate(${deg}deg);
`); `);
}]], });
},
}), }),
}), }),

View file

@ -7,8 +7,8 @@ import { execAsync } from 'resource:///com/github/Aylur/ags/utils.js';
import EventBox from '../misc/cursorbox.js'; import EventBox from '../misc/cursorbox.js';
const SCROLL_THRESHOLD_H = 200; const SCROLL_THRESH_H = 200;
const SCROLL_THRESHOLD_N = 7; const SCROLL_THRESH_N = 7;
const AccessPoint = (ap) => { const AccessPoint = (ap) => {
@ -22,28 +22,37 @@ const AccessPoint = (ap) => {
hexpand: true, hexpand: true,
children: [ children: [
Icon({ Icon({
connections: [[widget.ap, (self) => { setup: (self) => {
self.icon = widget.ap.value.iconName; self.hook(widget.ap, () => {
}]], self.icon = widget.ap.value.iconName;
});
},
}), }),
Label({ Label({
connections: [[widget.ap, (self) => { setup: (self) => {
self.label = widget.ap.value.ssid || ''; self.hook(widget.ap, () => {
}]], self.label = widget.ap.value.ssid || '';
});
},
}), }),
Icon({ Icon({
icon: 'object-select-symbolic', icon: 'object-select-symbolic',
hexpand: true, hexpand: true,
hpack: 'end', hpack: 'end',
connections: [[Network, (self) => { setup: (self) => {
self.setCss(`opacity: ${ self.hook(Network, () => {
widget.ap.value.ssid === Network.wifi.ssid ? self.setCss(
'1' : `opacity: ${
'0' widget.ap.value.ssid === Network.wifi.ssid ?
};`); '1' :
}]], '0'
};
`,
);
});
},
}), }),
], ],
}); });
@ -109,17 +118,19 @@ export const NetworkMenu = () => {
hscroll: 'never', hscroll: 'never',
vscroll: 'never', vscroll: 'never',
connections: [['edge-reached', (_, pos) => { setup: (self) => {
// Manage scroll indicators self.on('edge-reached', (_, pos) => {
if (pos === 2) { // Manage scroll indicators
topArrow.revealChild = false; if (pos === 2) {
bottomArrow.revealChild = true; topArrow.revealChild = false;
} bottomArrow.revealChild = true;
else if (pos === 3) { }
topArrow.revealChild = true; else if (pos === 3) {
bottomArrow.revealChild = false; topArrow.revealChild = true;
} bottomArrow.revealChild = false;
}]], }
});
},
child: ListBox({ child: ListBox({
setup: (self) => { setup: (self) => {
@ -127,82 +138,83 @@ export const NetworkMenu = () => {
return b.get_children()[0].ap.value.strength - return b.get_children()[0].ap.value.strength -
a.get_children()[0].ap.value.strength; a.get_children()[0].ap.value.strength;
}); });
},
connections: [[Network, (box) => { self.hook(Network, () => {
// Add missing APs // Add missing APs
Network.wifi?.access_points.forEach((ap) => { Network.wifi?.access_points.forEach((ap) => {
if (ap.ssid !== 'Unknown') { if (ap.ssid !== 'Unknown') {
if (APList.has(ap.ssid)) { if (APList.has(ap.ssid)) {
const accesPoint = APList.get(ap.ssid) const accesPoint = APList.get(ap.ssid)
.ap.value; .ap.value;
if (accesPoint.strength < ap.strength) { if (accesPoint.strength < ap.strength) {
APList.get(ap.ssid).ap.value = ap; APList.get(ap.ssid).ap.value = ap;
}
}
else {
APList.set(ap.ssid, AccessPoint(ap));
self.add(APList.get(ap.ssid));
self.show_all();
} }
} }
else { });
APList.set(ap.ssid, AccessPoint(ap));
box.add(APList.get(ap.ssid)); // Delete ones that don't exist anymore
box.show_all(); const difference = Array.from(APList.keys())
.filter((ssid) => !Network.wifi.access_points
.find((ap) => ap.ssid === ssid) &&
ssid !== 'Unknown');
difference.forEach((ssid) => {
const apWidget = APList.get(ssid);
if (apWidget) {
if (apWidget.toDestroy) {
apWidget.get_parent().destroy();
APList.delete(ssid);
}
else {
apWidget.children[0]
.revealChild = false;
apWidget.toDestroy = true;
}
}
});
// Start scrolling after a specified height
// is reached by the children
const height = Math.max(
self.get_parent().get_allocated_height(),
SCROLL_THRESH_H,
);
const scroll = self.get_parent().get_parent();
if (self.get_children().length > SCROLL_THRESH_N) {
scroll.vscroll = 'always';
scroll.setCss(`min-height: ${height}px;`);
// Make bottom scroll indicator appear only
// when first getting overflowing children
if (!(bottomArrow.revealChild === true ||
topArrow.revealChild === true)) {
bottomArrow.revealChild = true;
} }
} }
}); else {
scroll.vscroll = 'never';
// Delete ones that don't exist anymore scroll.setCss('');
const difference = Array.from(APList.keys()) topArrow.revealChild = false;
.filter((ssid) => !Network.wifi.access_points bottomArrow.revealChild = false;
.find((ap) => ap.ssid === ssid) &&
ssid !== 'Unknown');
difference.forEach((ssid) => {
const apWidget = APList.get(ssid);
if (apWidget) {
if (apWidget.toDestroy) {
apWidget.get_parent().destroy();
APList.delete(ssid);
}
else {
apWidget.children[0].revealChild = false;
apWidget.toDestroy = true;
}
} }
// Trigger sort_func
self.get_children().forEach((ch) => {
ch.changed();
});
}); });
},
// Start scrolling after a specified height
// is reached by the children
const height = Math.max(
box.get_parent().get_allocated_height(),
SCROLL_THRESHOLD_H,
);
const scroll = box.get_parent().get_parent();
if (box.get_children().length > SCROLL_THRESHOLD_N) {
scroll.vscroll = 'always';
scroll.setCss(`min-height: ${height}px;`);
// Make bottom scroll indicator appear only
// when first getting overflowing children
if (!(bottomArrow.revealChild === true ||
topArrow.revealChild === true)) {
bottomArrow.revealChild = true;
}
}
else {
scroll.vscroll = 'never';
scroll.setCss('');
topArrow.revealChild = false;
bottomArrow.revealChild = false;
}
// Trigger sort_func
box.get_children().forEach((ch) => {
ch.changed();
});
}]],
}), }),
}), }),
}), }),

View file

@ -34,18 +34,20 @@ export default () => Box({
Audio.speaker.volume = value; Audio.speaker.volume = value;
}, },
connections: [ setup: (self) => {
[Audio, (slider) => { self
slider.value = Audio.speaker?.volume; .hook(Audio, () => {
}, 'speaker-changed'], self.value = Audio.speaker?.volume;
}, 'speaker-changed')
['button-press-event', (s) => { .on('button-press-event', () => {
s.cursor = 'grabbing'; self.cursor = 'grabbing';
}], })
['button-release-event', (s) => {
s.cursor = 'pointer'; .on('button-release-event', () => {
}], self.cursor = 'pointer';
], });
},
}), }),
], ],
}), }),
@ -70,18 +72,20 @@ export default () => Box({
Brightness.screen = value; Brightness.screen = value;
}, },
connections: [ setup: (self) => {
[Brightness, (slider) => { self
slider.value = Brightness.screen; .hook(Brightness, () => {
}, 'screen'], self.value = Brightness.screen;
}, 'screen')
['button-press-event', (s) => { .on('button-press-event', () => {
s.cursor = 'grabbing'; self.cursor = 'grabbing';
}], })
['button-release-event', (s) => {
s.cursor = 'pointer'; .on('button-release-event', () => {
}], self.cursor = 'pointer';
], });
},
}), }),
], ],
}), }),

View file

@ -14,20 +14,20 @@ export default (rev) => CenterBox({
self.set_active(Mpris.players.length > 0); self.set_active(Mpris.players.length > 0);
Mpris.disconnect(id); Mpris.disconnect(id);
}); });
},
connections: [['toggled', (self) => { self.on('toggled', () => {
if (self.get_active()) { if (self.get_active()) {
self.get_children()[0] self.get_children()[0]
.setCss('-gtk-icon-transform: rotate(0deg);'); .setCss('-gtk-icon-transform: rotate(0deg);');
rev.revealChild = true; rev.revealChild = true;
} }
else { else {
self.get_children()[0] self.get_children()[0]
.setCss('-gtk-icon-transform: rotate(180deg);'); .setCss('-gtk-icon-transform: rotate(180deg);');
rev.revealChild = false; rev.revealChild = false;
} }
}]], });
},
child: Icon({ child: Icon({
icon: `${App.configDir }/icons/down-large.svg`, icon: `${App.configDir }/icons/down-large.svg`,

Binary file not shown.