chore: update ags and start fixing breaking changes
This commit is contained in:
parent
4f349dae0f
commit
4412d13997
39 changed files with 1064 additions and 966 deletions
|
@ -21,6 +21,7 @@ exec(`sassc ${scss} ${css}`);
|
|||
Setup();
|
||||
|
||||
|
||||
// TODO: get rid of 'properties' and 'binds' prop
|
||||
export default {
|
||||
style: css,
|
||||
notificationPopupTimeout: 5000,
|
||||
|
|
|
@ -101,6 +101,23 @@ const Applauncher = ({ window_name = 'applauncher' } = {}) => {
|
|||
className: 'applauncher',
|
||||
vertical: true,
|
||||
|
||||
setup: (self) => {
|
||||
self.hook(App, (_, name, visible) => {
|
||||
if (name !== window_name) {
|
||||
return;
|
||||
}
|
||||
|
||||
entry.text = '';
|
||||
|
||||
if (visible) {
|
||||
entry.grab_focus();
|
||||
}
|
||||
else {
|
||||
makeNewChildren();
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
children: [
|
||||
Box({
|
||||
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();
|
||||
}
|
||||
}]],
|
||||
});
|
||||
};
|
||||
|
||||
|
|
|
@ -13,11 +13,13 @@ const SpeakerIndicator = (props) => Icon({
|
|||
|
||||
const SpeakerPercentLabel = (props) => Label({
|
||||
...props,
|
||||
connections: [[Audio, (label) => {
|
||||
if (Audio.speaker) {
|
||||
label.label = `${Math.round(Audio.speaker.volume * 100)}%`;
|
||||
}
|
||||
}, 'speaker-changed']],
|
||||
setup: (self) => {
|
||||
self.hook(Audio, (label) => {
|
||||
if (Audio.speaker) {
|
||||
label.label = `${Math.round(Audio.speaker.volume * 100)}%`;
|
||||
}
|
||||
}, 'speaker-changed');
|
||||
},
|
||||
});
|
||||
|
||||
const SPACING = 5;
|
||||
|
|
|
@ -12,20 +12,24 @@ const Indicator = () => Icon({
|
|||
|
||||
binds: [['icon', Battery, 'icon-name']],
|
||||
|
||||
connections: [[Battery, (self) => {
|
||||
self.toggleClassName('charging', Battery.charging);
|
||||
self.toggleClassName('charged', Battery.charged);
|
||||
self.toggleClassName('low', Battery.percent < LOW_BATT);
|
||||
}]],
|
||||
setup: (self) => {
|
||||
self.hook(Battery, () => {
|
||||
self.toggleClassName('charging', Battery.charging);
|
||||
self.toggleClassName('charged', Battery.charged);
|
||||
self.toggleClassName('low', Battery.percent < LOW_BATT);
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
const LevelLabel = (props) => Label({
|
||||
...props,
|
||||
className: 'label',
|
||||
|
||||
connections: [[Battery, (self) => {
|
||||
self.label = `${Battery.percent}%`;
|
||||
}]],
|
||||
setup: (self) => {
|
||||
self.hook(Battery, () => {
|
||||
self.label = `${Battery.percent}%`;
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
const SPACING = 5;
|
||||
|
|
|
@ -7,25 +7,29 @@ import Separator from '../../misc/separator.js';
|
|||
|
||||
const Indicator = (props) => Icon({
|
||||
...props,
|
||||
connections: [[Bluetooth, (self) => {
|
||||
if (Bluetooth.enabled) {
|
||||
self.icon = Bluetooth.connectedDevices[0] ?
|
||||
Bluetooth.connectedDevices[0].iconName :
|
||||
'bluetooth-active-symbolic';
|
||||
}
|
||||
else {
|
||||
self.icon = 'bluetooth-disabled-symbolic';
|
||||
}
|
||||
}]],
|
||||
setup: (self) => {
|
||||
self.hook(Bluetooth, () => {
|
||||
if (Bluetooth.enabled) {
|
||||
self.icon = Bluetooth.connectedDevices[0] ?
|
||||
Bluetooth.connectedDevices[0].iconName :
|
||||
'bluetooth-active-symbolic';
|
||||
}
|
||||
else {
|
||||
self.icon = 'bluetooth-disabled-symbolic';
|
||||
}
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
const ConnectedLabel = (props) => Label({
|
||||
...props,
|
||||
connections: [[Bluetooth, (self) => {
|
||||
self.label = Bluetooth.connectedDevices[0] ?
|
||||
`${Bluetooth.connectedDevices[0]}` :
|
||||
'Disconnected';
|
||||
}, 'notify::connected-devices']],
|
||||
setup: (self) => {
|
||||
self.hook(Bluetooth, () => {
|
||||
self.label = Bluetooth.connectedDevices[0] ?
|
||||
`${Bluetooth.connectedDevices[0]}` :
|
||||
'Disconnected';
|
||||
}, 'notify::connected-devices');
|
||||
},
|
||||
});
|
||||
|
||||
const SPACING = 5;
|
||||
|
|
|
@ -13,9 +13,11 @@ const Indicator = (props) => Icon({
|
|||
|
||||
const BrightnessPercentLabel = (props) => Label({
|
||||
...props,
|
||||
connections: [[Brightness, (self) => {
|
||||
self.label = `${Math.round(Brightness.screen * 100)}%`;
|
||||
}, 'screen']],
|
||||
setup: (self) => {
|
||||
self.hook(Brightness, () => {
|
||||
self.label = `${Math.round(Brightness.screen * 100)}%`;
|
||||
}, 'screen');
|
||||
},
|
||||
});
|
||||
|
||||
export default () => {
|
||||
|
|
|
@ -8,36 +8,32 @@ const { DateTime } = GLib;
|
|||
import EventBox from '../../misc/cursorbox.js';
|
||||
|
||||
|
||||
const ClockModule = ({
|
||||
interval = 1000,
|
||||
...props
|
||||
} = {}) => {
|
||||
return Label({
|
||||
...props,
|
||||
className: 'clock',
|
||||
const ClockModule = () => Label({
|
||||
className: 'clock',
|
||||
|
||||
connections: [[interval, (self) => {
|
||||
setup: (self) => {
|
||||
self.poll(1000, () => {
|
||||
const time = DateTime.new_now_local();
|
||||
|
||||
self.label = time.format('%a. ') +
|
||||
time.get_day_of_month() +
|
||||
time.format(' %b. %H:%M');
|
||||
}]],
|
||||
});
|
||||
};
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
export default () => EventBox({
|
||||
className: 'toggle-off',
|
||||
|
||||
onPrimaryClickRelease: () => App.toggleWindow('calendar'),
|
||||
|
||||
connections: [
|
||||
[App, (self, windowName, visible) => {
|
||||
setup: (self) => {
|
||||
self.hook(App, (_, windowName, visible) => {
|
||||
if (windowName === 'calendar') {
|
||||
self.toggleClassName('toggle-on', visible);
|
||||
}
|
||||
}],
|
||||
],
|
||||
});
|
||||
},
|
||||
|
||||
child: ClockModule(),
|
||||
});
|
||||
|
|
|
@ -13,14 +13,17 @@ export default () => Box({
|
|||
|
||||
Icon({
|
||||
size: 30,
|
||||
connections: [[Hyprland.active.client, (self) => {
|
||||
const app = Applications.query(Hyprland.active.client.class)[0];
|
||||
setup: (self) => {
|
||||
self.hook(Hyprland.active.client, () => {
|
||||
const app = Applications
|
||||
.query(Hyprland.active.client.class)[0];
|
||||
|
||||
if (app) {
|
||||
self.icon = app.iconName;
|
||||
self.visible = Hyprland.active.client.title !== '';
|
||||
}
|
||||
}]],
|
||||
if (app) {
|
||||
self.icon = app.iconName;
|
||||
self.visible = Hyprland.active.client.title !== '';
|
||||
}
|
||||
});
|
||||
},
|
||||
}),
|
||||
|
||||
Separator(SPACING),
|
||||
|
|
|
@ -8,40 +8,44 @@ const DEFAULT_KB = 'at-translated-set-2-keyboard';
|
|||
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 () => {
|
||||
const rev = Revealer({
|
||||
transition: 'slide_right',
|
||||
child: Box({
|
||||
children: [
|
||||
Separator(SPACING),
|
||||
Label({
|
||||
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']],
|
||||
}),
|
||||
Indicator(),
|
||||
],
|
||||
}),
|
||||
});
|
||||
|
|
|
@ -7,36 +7,40 @@ import Separator from '../../misc/separator.js';
|
|||
|
||||
const Indicator = (props) => Icon({
|
||||
...props,
|
||||
connections: [[Network, (self) => {
|
||||
if (Network.wifi.internet === 'connected' ||
|
||||
Network.wifi.internet === 'connecting') {
|
||||
self.icon = Network.wifi.iconName;
|
||||
}
|
||||
else if (Network.wired.internet === 'connected' ||
|
||||
Network.wired.internet === 'connecting') {
|
||||
self.icon = Network.wired.iconName;
|
||||
}
|
||||
else {
|
||||
self.icon = Network.wifi.iconName;
|
||||
}
|
||||
}]],
|
||||
setup: (self) => {
|
||||
self.hook(Network, () => {
|
||||
if (Network.wifi.internet === 'connected' ||
|
||||
Network.wifi.internet === 'connecting') {
|
||||
self.icon = Network.wifi.iconName;
|
||||
}
|
||||
else if (Network.wired.internet === 'connected' ||
|
||||
Network.wired.internet === 'connecting') {
|
||||
self.icon = Network.wired.iconName;
|
||||
}
|
||||
else {
|
||||
self.icon = Network.wifi.iconName;
|
||||
}
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
const APLabel = (props) => Label({
|
||||
...props,
|
||||
connections: [[Network, (self) => {
|
||||
if (Network.wifi.internet === 'connected' ||
|
||||
Network.wifi.internet === 'connecting') {
|
||||
self.label = Network.wifi.ssid;
|
||||
}
|
||||
else if (Network.wired.internet === 'connected' ||
|
||||
Network.wired.internet === 'connecting') {
|
||||
self.label = 'Connected';
|
||||
}
|
||||
else {
|
||||
self.label = 'Disconnected';
|
||||
}
|
||||
}]],
|
||||
setup: (self) => {
|
||||
self.hook(Network, () => {
|
||||
if (Network.wifi.internet === 'connected' ||
|
||||
Network.wifi.internet === 'connecting') {
|
||||
self.label = Network.wifi.ssid;
|
||||
}
|
||||
else if (Network.wired.internet === 'connected' ||
|
||||
Network.wired.internet === 'connecting') {
|
||||
self.label = 'Connected';
|
||||
}
|
||||
else {
|
||||
self.label = 'Disconnected';
|
||||
}
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
const SPACING = 5;
|
||||
|
|
|
@ -19,11 +19,13 @@ export default () => EventBox({
|
|||
App.toggleWindow('notification-center');
|
||||
},
|
||||
|
||||
connections: [[App, (self, windowName, visible) => {
|
||||
if (windowName === 'notification-center') {
|
||||
self.toggleClassName('toggle-on', visible);
|
||||
}
|
||||
}]],
|
||||
setup: (self) => {
|
||||
self.hook(App, (_, windowName, visible) => {
|
||||
if (windowName === 'notification-center') {
|
||||
self.toggleClassName('toggle-on', visible);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
child: CenterBox({
|
||||
className: 'notif-panel',
|
||||
|
@ -31,17 +33,19 @@ export default () => EventBox({
|
|||
center_widget: Box({
|
||||
children: [
|
||||
Icon({
|
||||
connections: [[Notifications, (self) => {
|
||||
if (Notifications.dnd) {
|
||||
self.icon = 'notification-disabled-symbolic';
|
||||
}
|
||||
else if (Notifications.notifications.length > 0) {
|
||||
self.icon = 'notification-new-symbolic';
|
||||
}
|
||||
else {
|
||||
self.icon = 'notification-symbolic';
|
||||
}
|
||||
}]],
|
||||
setup: (self) => {
|
||||
self.hook(Notifications, () => {
|
||||
if (Notifications.dnd) {
|
||||
self.icon = 'notification-disabled-symbolic';
|
||||
}
|
||||
else if (Notifications.notifications.length > 0) {
|
||||
self.icon = 'notification-new-symbolic';
|
||||
}
|
||||
else {
|
||||
self.icon = 'notification-symbolic';
|
||||
}
|
||||
});
|
||||
},
|
||||
}),
|
||||
|
||||
Separator(SPACING),
|
||||
|
|
|
@ -9,9 +9,11 @@ export default () => EventBox({
|
|||
|
||||
onPrimaryClickRelease: () => Tablet.toggleOsk(),
|
||||
|
||||
connections: [[Tablet, (self) => {
|
||||
self.toggleClassName('toggle-on', Tablet.oskState);
|
||||
}, 'osk-toggled']],
|
||||
setup: (self) => {
|
||||
self.hook(Tablet, () => {
|
||||
self.toggleClassName('toggle-on', Tablet.oskState);
|
||||
}, 'osk-toggled');
|
||||
},
|
||||
|
||||
child: Box({
|
||||
className: 'osk-toggle',
|
||||
|
|
|
@ -26,11 +26,13 @@ export default () => EventBox({
|
|||
App.toggleWindow('quick-settings');
|
||||
},
|
||||
|
||||
connections: [[App, (self, windowName, visible) => {
|
||||
if (windowName === 'quick-settings') {
|
||||
self.toggleClassName('toggle-on', visible);
|
||||
}
|
||||
}]],
|
||||
setup: (self) => {
|
||||
self.hook(App, (_, windowName, visible) => {
|
||||
if (windowName === 'quick-settings') {
|
||||
self.toggleClassName('toggle-on', visible);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
child: Box({
|
||||
className: 'quick-settings-toggle',
|
||||
|
|
|
@ -33,42 +33,39 @@ const SysTray = () => MenuBar({
|
|||
setup: (self) => {
|
||||
self.items = new Map();
|
||||
|
||||
self.onAdded = (id) => {
|
||||
const item = SystemTray.getItem(id);
|
||||
self
|
||||
.hook(SystemTray, (_, id) => {
|
||||
const item = SystemTray.getItem(id);
|
||||
|
||||
if (self.items.has(id) || !item) {
|
||||
return;
|
||||
}
|
||||
if (self.items.has(id) || !item) {
|
||||
return;
|
||||
}
|
||||
|
||||
const w = SysTrayItem(item);
|
||||
const w = SysTrayItem(item);
|
||||
|
||||
// Early return if item is in blocklist
|
||||
if (!w) {
|
||||
return;
|
||||
}
|
||||
// Early return if item is in blocklist
|
||||
if (!w) {
|
||||
return;
|
||||
}
|
||||
|
||||
self.items.set(id, w);
|
||||
self.add(w);
|
||||
self.show_all();
|
||||
w.child.revealChild = true;
|
||||
};
|
||||
self.items.set(id, w);
|
||||
self.add(w);
|
||||
self.show_all();
|
||||
w.child.revealChild = true;
|
||||
}, 'added')
|
||||
|
||||
self.onRemoved = (id) => {
|
||||
if (!self.items.has(id)) {
|
||||
return;
|
||||
}
|
||||
.hook(SystemTray, (_, id) => {
|
||||
if (!self.items.has(id)) {
|
||||
return;
|
||||
}
|
||||
|
||||
self.items.get(id).child.revealChild = false;
|
||||
timeout(REVEAL_DURATION, () => {
|
||||
self.items.get(id).destroy();
|
||||
self.items.delete(id);
|
||||
});
|
||||
};
|
||||
self.items.get(id).child.revealChild = false;
|
||||
timeout(REVEAL_DURATION, () => {
|
||||
self.items.get(id).destroy();
|
||||
self.items.delete(id);
|
||||
});
|
||||
}, 'removed');
|
||||
},
|
||||
connections: [
|
||||
[SystemTray, (self, id) => self.onAdded(id), 'added'],
|
||||
[SystemTray, (self, id) => self.onRemoved(id), 'removed'],
|
||||
],
|
||||
});
|
||||
|
||||
export default () => {
|
||||
|
@ -77,9 +74,11 @@ export default () => {
|
|||
return Revealer({
|
||||
transition: 'slide_right',
|
||||
|
||||
connections: [[SystemTray, (rev) => {
|
||||
rev.revealChild = systray.get_children().length > 0;
|
||||
}]],
|
||||
setup: (self) => {
|
||||
self.hook(SystemTray, () => {
|
||||
self.revealChild = systray.get_children().length > 0;
|
||||
});
|
||||
},
|
||||
|
||||
child: Box({
|
||||
children: [
|
||||
|
|
|
@ -9,9 +9,11 @@ export default () => EventBox({
|
|||
|
||||
onPrimaryClickRelease: () => Tablet.toggleMode(),
|
||||
|
||||
connections: [[Tablet, (self) => {
|
||||
self.toggleClassName('toggle-on', Tablet.tabletMode);
|
||||
}, 'mode-toggled']],
|
||||
setup: (self) => {
|
||||
self.hook(Tablet, () => {
|
||||
self.toggleClassName('toggle-on', Tablet.tabletMode);
|
||||
}, 'mode-toggled');
|
||||
},
|
||||
|
||||
child: Box({
|
||||
className: 'tablet-toggle',
|
||||
|
|
|
@ -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',
|
||||
hpack: 'start',
|
||||
className: 'button active',
|
||||
connections: [[Hyprland.active.workspace, updateHighlight]],
|
||||
setup: (self) => {
|
||||
self.hook(Hyprland.active.workspace, updateHighlight);
|
||||
},
|
||||
});
|
||||
|
||||
const widget = Overlay({
|
||||
|
@ -122,21 +124,23 @@ export default () => {
|
|||
}],
|
||||
],
|
||||
|
||||
connections: [[Hyprland, (self) => {
|
||||
self._workspaces = self.children.filter((ch) => {
|
||||
return Hyprland.workspaces.find((ws) => {
|
||||
return ws.id === ch._id;
|
||||
});
|
||||
}).sort((a, b) => a._id - b._id);
|
||||
setup: (self) => {
|
||||
self.hook(Hyprland, () => {
|
||||
self._workspaces = self.children.filter((ch) => {
|
||||
return Hyprland.workspaces.find((ws) => {
|
||||
return ws.id === ch._id;
|
||||
});
|
||||
}).sort((a, b) => a._id - b._id);
|
||||
|
||||
self._updateWorkspaces(self);
|
||||
self._refresh(self);
|
||||
self._updateWorkspaces(self);
|
||||
self._refresh(self);
|
||||
|
||||
// Make sure the highlight doesn't go too far
|
||||
const TEMP_TIMEOUT = 10;
|
||||
// Make sure the highlight doesn't go too far
|
||||
const TEMP_TIMEOUT = 10;
|
||||
|
||||
timeout(TEMP_TIMEOUT, () => updateHighlight(highlight));
|
||||
}]],
|
||||
timeout(TEMP_TIMEOUT, () => updateHighlight(highlight));
|
||||
});
|
||||
},
|
||||
}),
|
||||
}),
|
||||
});
|
||||
|
|
|
@ -31,19 +31,20 @@ export default (props) => {
|
|||
hexpand: true,
|
||||
vertical: true,
|
||||
|
||||
connections: [
|
||||
[Hyprland.active, () => {
|
||||
const workspace = Hyprland.getWorkspace(
|
||||
Hyprland.active.workspace.id,
|
||||
);
|
||||
setup: (self) => {
|
||||
self
|
||||
.hook(Hyprland.active, () => {
|
||||
const workspace = Hyprland.getWorkspace(
|
||||
Hyprland.active.workspace.id,
|
||||
);
|
||||
|
||||
Revealed.value = !workspace?.hasfullscreen;
|
||||
}],
|
||||
Revealed.value = !workspace?.hasfullscreen;
|
||||
})
|
||||
|
||||
[Hyprland, (_, fullscreen) => {
|
||||
Revealed.value = !fullscreen;
|
||||
}, 'fullscreen'],
|
||||
],
|
||||
.hook(Hyprland, (_, fullscreen) => {
|
||||
Revealed.value = !fullscreen;
|
||||
}, 'fullscreen');
|
||||
},
|
||||
|
||||
children: [
|
||||
Revealer({
|
||||
|
|
|
@ -25,9 +25,11 @@ const Time = () => Box({
|
|||
Label({
|
||||
className: 'content',
|
||||
label: 'hour',
|
||||
connections: [[1000, (self) => {
|
||||
self.label = DateTime.new_now_local().format('%H');
|
||||
}]],
|
||||
setup: (self) => {
|
||||
self.poll(1000, () => {
|
||||
self.label = DateTime.new_now_local().format('%H');
|
||||
});
|
||||
},
|
||||
}),
|
||||
|
||||
Divider(),
|
||||
|
@ -35,9 +37,11 @@ const Time = () => Box({
|
|||
Label({
|
||||
className: 'content',
|
||||
label: 'minute',
|
||||
connections: [[1000, (self) => {
|
||||
self.label = DateTime.new_now_local().format('%M');
|
||||
}]],
|
||||
setup: (self) => {
|
||||
self.poll(1000, () => {
|
||||
self.label = DateTime.new_now_local().format('%M');
|
||||
});
|
||||
},
|
||||
}),
|
||||
|
||||
],
|
||||
|
@ -49,13 +53,15 @@ const Time = () => Box({
|
|||
child: Label({
|
||||
css: 'font-size: 20px',
|
||||
label: 'complete date',
|
||||
connections: [[1000, (self) => {
|
||||
const time = DateTime.new_now_local();
|
||||
setup: (self) => {
|
||||
self.poll(1000, () => {
|
||||
const time = DateTime.new_now_local();
|
||||
|
||||
self.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');
|
||||
});
|
||||
},
|
||||
}),
|
||||
}),
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ const TRANSITION = `transition: margin ${ANIM_DURATION}ms ease,
|
|||
|
||||
export default ({
|
||||
properties,
|
||||
connections,
|
||||
setup = () => {/**/},
|
||||
props,
|
||||
} = {}) => {
|
||||
const widget = EventBox();
|
||||
|
@ -33,101 +33,103 @@ export default ({
|
|||
|
||||
child: emptyPlayer,
|
||||
|
||||
connections: [
|
||||
...connections,
|
||||
setup: (self) => {
|
||||
setup(self);
|
||||
|
||||
[gesture, (overlay, realGesture) => {
|
||||
if (realGesture) {
|
||||
overlay.list().forEach((over) => {
|
||||
over.visible = true;
|
||||
});
|
||||
}
|
||||
else {
|
||||
overlay.showTopOnly();
|
||||
}
|
||||
self
|
||||
.hook(gesture, (overlay, realGesture) => {
|
||||
if (realGesture) {
|
||||
overlay.list().forEach((over) => {
|
||||
over.visible = true;
|
||||
});
|
||||
}
|
||||
else {
|
||||
overlay.showTopOnly();
|
||||
}
|
||||
|
||||
// Don't allow gesture when only one player
|
||||
if (overlay.list().length <= 1) {
|
||||
return;
|
||||
}
|
||||
// Don't allow gesture when only one player
|
||||
if (overlay.list().length <= 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
overlay._dragging = true;
|
||||
let offset = gesture.get_offset()[1];
|
||||
overlay._dragging = true;
|
||||
let offset = gesture.get_offset()[1];
|
||||
|
||||
const playerBox = overlay.list().at(-1);
|
||||
const playerBox = overlay.list().at(-1);
|
||||
|
||||
// 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
|
||||
// Slide right
|
||||
if (offset >= 0) {
|
||||
playerBox.setCss(`
|
||||
${TRANSITION}
|
||||
margin-left: ${OFFSCREEN}px;
|
||||
margin-right: -${OFFSCREEN}px;
|
||||
opacity: 0.7; ${playerBox._bgStyle}
|
||||
margin-left: ${offset}px;
|
||||
margin-right: -${offset}px;
|
||||
${playerBox._bgStyle}
|
||||
`);
|
||||
}
|
||||
|
||||
// Slide away left
|
||||
// Slide left
|
||||
else {
|
||||
offset = Math.abs(offset);
|
||||
playerBox.setCss(`
|
||||
${TRANSITION}
|
||||
margin-left: -${OFFSCREEN}px;
|
||||
margin-right: ${OFFSCREEN}px;
|
||||
opacity: 0.7; ${playerBox._bgStyle}`);
|
||||
margin-left: -${offset}px;
|
||||
margin-right: ${offset}px;
|
||||
${playerBox._bgStyle}
|
||||
`);
|
||||
}
|
||||
}, 'drag-update')
|
||||
|
||||
.hook(gesture, (overlay) => {
|
||||
// Don't allow gesture when only one player
|
||||
if (overlay.list().length <= 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
timeout(ANIM_DURATION, () => {
|
||||
// Put the player in the back after anim
|
||||
overlay.reorder_overlay(playerBox, 0);
|
||||
// Recenter player
|
||||
playerBox.setCss(playerBox._bgStyle);
|
||||
overlay._dragging = false;
|
||||
const offset = gesture.get_offset()[1];
|
||||
|
||||
widget.sensitive = true;
|
||||
const playerBox = overlay.list().at(-1);
|
||||
|
||||
overlay.showTopOnly();
|
||||
});
|
||||
}
|
||||
else {
|
||||
// Recenter with transition for animation
|
||||
playerBox.setCss(`${TRANSITION} ${playerBox._bgStyle}`);
|
||||
}
|
||||
}, 'drag-end'],
|
||||
],
|
||||
// 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) {
|
||||
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);
|
||||
|
|
|
@ -60,19 +60,18 @@ export const CoverArt = (player, props) => CenterBox({
|
|||
self.setCss(self._bgStyle);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
connections: [[player, (self) => {
|
||||
execAsync(['bash', '-c', `[[ -f "${player.coverPath}" ]] &&
|
||||
self.hook(player, () => {
|
||||
execAsync(['bash', '-c', `[[ -f "${player.coverPath}" ]] &&
|
||||
coloryou "${player.coverPath}" | grep -v Warning`])
|
||||
.then((out) => {
|
||||
if (!Mpris.players.find((p) => player === p)) {
|
||||
return;
|
||||
}
|
||||
.then((out) => {
|
||||
if (!Mpris.players.find((p) => player === p)) {
|
||||
return;
|
||||
}
|
||||
|
||||
player.colors.value = JSON.parse(out);
|
||||
player.colors.value = JSON.parse(out);
|
||||
|
||||
self._bgStyle = `
|
||||
self._bgStyle = `
|
||||
background: radial-gradient(circle,
|
||||
rgba(0, 0, 0, 0.4) 30%,
|
||||
${player.colors.value.imageAccent}),
|
||||
|
@ -81,15 +80,16 @@ export const CoverArt = (player, props) => CenterBox({
|
|||
background-position: center;
|
||||
`;
|
||||
|
||||
if (!self.get_parent()._dragging) {
|
||||
self.setCss(self._bgStyle);
|
||||
}
|
||||
}).catch((err) => {
|
||||
if (err !== '') {
|
||||
print(err);
|
||||
}
|
||||
});
|
||||
}]],
|
||||
if (!self.get_parent()._dragging) {
|
||||
self.setCss(self._bgStyle);
|
||||
}
|
||||
}).catch((err) => {
|
||||
if (err !== '') {
|
||||
print(err);
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
export const TitleLabel = (player, props) => Label({
|
||||
|
@ -127,27 +127,31 @@ export const PlayerIcon = (player, overlay, props) => {
|
|||
className: widget ? 'position-indicator' : 'player-icon',
|
||||
size: widget ? '' : ICON_SIZE,
|
||||
|
||||
connections: [[p, (self) => {
|
||||
self.icon = lookUpIcon(p.entry) ?
|
||||
p.entry :
|
||||
icons.mpris.fallback;
|
||||
}]],
|
||||
setup: (self) => {
|
||||
self.hook(p, () => {
|
||||
self.icon = lookUpIcon(p.entry) ?
|
||||
p.entry :
|
||||
icons.mpris.fallback;
|
||||
});
|
||||
},
|
||||
}),
|
||||
});
|
||||
|
||||
return Box({
|
||||
connections: [[Mpris, (self) => {
|
||||
const thisIndex = overlay.list()
|
||||
.indexOf(self.get_parent().get_parent());
|
||||
setup: (self) => {
|
||||
self.hook(Mpris, () => {
|
||||
const thisIndex = overlay.list()
|
||||
.indexOf(self.get_parent().get_parent());
|
||||
|
||||
self.children = overlay.list().map((over, i) => {
|
||||
self.children.push(Separator(2));
|
||||
self.children = overlay.list().map((over, i) => {
|
||||
self.children.push(Separator(2));
|
||||
|
||||
return i === thisIndex ?
|
||||
playerIcon(player) :
|
||||
playerIcon(over._player, overlay, over);
|
||||
}).reverse();
|
||||
}]],
|
||||
return i === thisIndex ?
|
||||
playerIcon(player) :
|
||||
playerIcon(over._player, overlay, over);
|
||||
}).reverse();
|
||||
});
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -163,38 +167,38 @@ export const PositionSlider = (player, props) => Slider({
|
|||
player.position = player.length * value;
|
||||
},
|
||||
|
||||
properties: [['update', (slider) => {
|
||||
if (!slider.dragging) {
|
||||
slider.visible = player.length > 0;
|
||||
if (player.length > 0) {
|
||||
slider.value = player.position / player.length;
|
||||
setup: (self) => {
|
||||
const update = () => {
|
||||
if (!self.dragging) {
|
||||
self.visible = player.length > 0;
|
||||
if (player.length > 0) {
|
||||
self.value = player.position / player.length;
|
||||
}
|
||||
}
|
||||
}
|
||||
}]],
|
||||
};
|
||||
|
||||
connections: [
|
||||
[1000, (s) => s._update(s)],
|
||||
[player, (s) => s._update(s), 'position'],
|
||||
[player.colors, (s) => {
|
||||
if (player.colors.value) {
|
||||
const c = player.colors.value;
|
||||
self
|
||||
.poll(1000, () => update())
|
||||
.hook(player, () => update(), 'position')
|
||||
.hook(player.colors, () => {
|
||||
if (player.colors.value) {
|
||||
const c = player.colors.value;
|
||||
|
||||
s.setCss(`
|
||||
highlight { background-color: ${c.buttonAccent}; }
|
||||
slider { background-color: ${c.buttonAccent}; }
|
||||
slider:hover { background-color: ${c.hoverAccent}; }
|
||||
trough { background-color: ${c.buttonText}; }
|
||||
`);
|
||||
}
|
||||
}],
|
||||
|
||||
['button-press-event', (s) => {
|
||||
s.cursor = 'grabbing';
|
||||
}],
|
||||
['button-release-event', (s) => {
|
||||
s.cursor = 'pointer';
|
||||
}],
|
||||
],
|
||||
self.setCss(`
|
||||
highlight { background-color: ${c.buttonAccent}; }
|
||||
slider { background-color: ${c.buttonAccent}; }
|
||||
slider:hover { background-color: ${c.hoverAccent}; }
|
||||
trough { background-color: ${c.buttonText}; }
|
||||
`);
|
||||
}
|
||||
})
|
||||
.on('button-press-event', (s) => {
|
||||
s.cursor = 'grabbing';
|
||||
})
|
||||
.on('button-release-event', (s) => {
|
||||
s.cursor = 'pointer';
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
const PlayerButton = ({ player, items, onClick, prop }) => EventBox({
|
||||
|
@ -212,13 +216,13 @@ const PlayerButton = ({ player, items, onClick, prop }) => EventBox({
|
|||
|
||||
items.forEach((item) => {
|
||||
item[1].setCss(`
|
||||
background-color: ${c.hoverAccent};
|
||||
color: ${c.buttonText};
|
||||
min-height: 40px;
|
||||
min-width: 36px;
|
||||
margin-bottom: 1px;
|
||||
margin-right: 1px;
|
||||
`);
|
||||
background-color: ${c.hoverAccent};
|
||||
color: ${c.buttonText};
|
||||
min-height: 40px;
|
||||
min-width: 36px;
|
||||
margin-bottom: 1px;
|
||||
margin-right: 1px;
|
||||
`);
|
||||
});
|
||||
}
|
||||
},
|
||||
|
@ -230,60 +234,61 @@ const PlayerButton = ({ player, items, onClick, prop }) => EventBox({
|
|||
|
||||
items.forEach((item) => {
|
||||
item[1].setCss(`
|
||||
background-color: ${c.buttonAccent};
|
||||
color: ${c.buttonText};
|
||||
min-height: 42px;
|
||||
min-width: 38px;
|
||||
`);
|
||||
background-color: ${c.buttonAccent};
|
||||
color: ${c.buttonText};
|
||||
min-height: 42px;
|
||||
min-width: 38px;
|
||||
`);
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
connections: [
|
||||
[player, (button) => {
|
||||
button.child.shown = `${player[prop]}`;
|
||||
}],
|
||||
setup: (self) => {
|
||||
self
|
||||
.hook(player, () => {
|
||||
self.child.shown = `${player[prop]}`;
|
||||
})
|
||||
.hook(player.colors, () => {
|
||||
if (!Mpris.players.find((p) => player === p)) {
|
||||
return;
|
||||
}
|
||||
|
||||
[player.colors, (button) => {
|
||||
if (!Mpris.players.find((p) => player === p)) {
|
||||
return;
|
||||
}
|
||||
if (player.colors.value) {
|
||||
const c = player.colors.value;
|
||||
|
||||
if (player.colors.value) {
|
||||
const c = player.colors.value;
|
||||
|
||||
if (prop === 'playBackStatus') {
|
||||
if (button._hovered) {
|
||||
items.forEach((item) => {
|
||||
item[1].setCss(`
|
||||
background-color: ${c.hoverAccent};
|
||||
color: ${c.buttonText};
|
||||
min-height: 40px;
|
||||
min-width: 36px;
|
||||
margin-bottom: 1px;
|
||||
margin-right: 1px;
|
||||
`);
|
||||
});
|
||||
if (prop === 'playBackStatus') {
|
||||
if (self._hovered) {
|
||||
items.forEach((item) => {
|
||||
item[1].setCss(`
|
||||
background-color: ${c.hoverAccent};
|
||||
color: ${c.buttonText};
|
||||
min-height: 40px;
|
||||
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 {
|
||||
items.forEach((item) => {
|
||||
item[1].setCss(`
|
||||
background-color: ${c.buttonAccent};
|
||||
color: ${c.buttonText};
|
||||
min-height: 42px;
|
||||
min-width: 38px;`);
|
||||
});
|
||||
self.setCss(`
|
||||
* { color: ${c.buttonAccent}; }
|
||||
*:hover { color: ${c.hoverAccent}; }
|
||||
`);
|
||||
}
|
||||
}
|
||||
else {
|
||||
button.setCss(`
|
||||
* { color: ${c.buttonAccent}; }
|
||||
*:hover { color: ${c.hoverAccent}; }
|
||||
`);
|
||||
}
|
||||
}
|
||||
}],
|
||||
],
|
||||
});
|
||||
},
|
||||
}),
|
||||
});
|
||||
|
||||
|
|
|
@ -107,72 +107,72 @@ export default () => {
|
|||
['setup', false],
|
||||
],
|
||||
|
||||
connections: [
|
||||
[Mpris, (overlay, busName) => {
|
||||
if (overlay._players.has(busName)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 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 {
|
||||
setup: (self) => {
|
||||
self
|
||||
.hook(Mpris, (overlay, busName) => {
|
||||
if (overlay._players.has(busName)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Get the one on top so we can move it up later
|
||||
const previousFirst = overlay.list().at(-1);
|
||||
// Sometimes the signal doesn't give the busName
|
||||
if (!busName) {
|
||||
const player = Mpris.players.find((p) => {
|
||||
return !overlay._players.has(p.busName);
|
||||
});
|
||||
|
||||
// Make the new player
|
||||
const player = Mpris.getPlayer(busName);
|
||||
if (player) {
|
||||
busName = player.busName;
|
||||
}
|
||||
else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
player.colors = Variable();
|
||||
overlay._players.set(
|
||||
busName,
|
||||
PlayerBox(player, content.getOverlay()),
|
||||
);
|
||||
overlay.overlays = Array.from(overlay._players.values())
|
||||
.map((widget) => widget);
|
||||
// Get the one on top so we can move it up later
|
||||
const previousFirst = overlay.list().at(-1);
|
||||
|
||||
// Select favorite player at startup
|
||||
if (!overlay._setup && overlay._players.has(FAVE_PLAYER)) {
|
||||
overlay.moveToTop(overlay._players.get(FAVE_PLAYER));
|
||||
overlay._setup = true;
|
||||
}
|
||||
// Make the new player
|
||||
const player = Mpris.getPlayer(busName);
|
||||
|
||||
// Move previousFirst on top again
|
||||
else if (overlay.includesWidget(previousFirst)) {
|
||||
overlay.moveToTop(previousFirst);
|
||||
}
|
||||
}, 'player-added'],
|
||||
player.colors = Variable();
|
||||
overlay._players.set(
|
||||
busName,
|
||||
PlayerBox(player, content.getOverlay()),
|
||||
);
|
||||
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) => {
|
||||
if (!busName || !overlay._players.has(busName)) {
|
||||
return;
|
||||
}
|
||||
// Move previousFirst on top again
|
||||
else if (overlay.includesWidget(previousFirst)) {
|
||||
overlay.moveToTop(previousFirst);
|
||||
}
|
||||
}, 'player-added')
|
||||
|
||||
// Get the one on top so we can move it up later
|
||||
const previousFirst = overlay.list().at(-1);
|
||||
.hook(Mpris, (overlay, busName) => {
|
||||
if (!busName || !overlay._players.has(busName)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Remake overlays without deleted one
|
||||
overlay._players.delete(busName);
|
||||
overlay.overlays = Array.from(overlay._players.values())
|
||||
.map((widget) => widget);
|
||||
// Get the one on top so we can move it up later
|
||||
const previousFirst = overlay.list().at(-1);
|
||||
|
||||
// Move previousFirst on top again
|
||||
if (overlay.includesWidget(previousFirst)) {
|
||||
overlay.moveToTop(previousFirst);
|
||||
}
|
||||
}, 'player-closed'],
|
||||
],
|
||||
// Remake overlays without deleted one
|
||||
overlay._players.delete(busName);
|
||||
overlay.overlays = Array.from(overlay._players.values())
|
||||
.map((widget) => widget);
|
||||
|
||||
// Move previousFirst on top again
|
||||
if (overlay.includesWidget(previousFirst)) {
|
||||
overlay.moveToTop(previousFirst);
|
||||
}
|
||||
}, 'player-closed');
|
||||
},
|
||||
});
|
||||
|
||||
return Box({
|
||||
|
|
|
@ -42,7 +42,7 @@ export default ({
|
|||
|
||||
const gesture = Gtk.GestureLongPress.new(widget);
|
||||
|
||||
widget.connectTo(gesture, () => {
|
||||
widget.hook(gesture, () => {
|
||||
const pointer = gesture.get_point(null);
|
||||
const x = pointer[1];
|
||||
const y = pointer[2];
|
||||
|
|
|
@ -58,20 +58,22 @@ export default ({
|
|||
transition,
|
||||
transitionDuration,
|
||||
|
||||
connections: [[App, (rev, currentName, isOpen) => {
|
||||
if (currentName === name) {
|
||||
rev.revealChild = isOpen;
|
||||
setup: (self) => {
|
||||
self.hook(App, (_, currentName, isOpen) => {
|
||||
if (currentName === name) {
|
||||
self.revealChild = isOpen;
|
||||
|
||||
if (isOpen) {
|
||||
onOpen(window);
|
||||
if (isOpen) {
|
||||
onOpen(window);
|
||||
}
|
||||
else {
|
||||
timeout(transitionDuration, () => {
|
||||
onClose(window);
|
||||
});
|
||||
}
|
||||
}
|
||||
else {
|
||||
timeout(transitionDuration, () => {
|
||||
onClose(window);
|
||||
});
|
||||
}
|
||||
}
|
||||
}]],
|
||||
});
|
||||
},
|
||||
|
||||
child: child || Box(),
|
||||
}),
|
||||
|
|
|
@ -28,28 +28,30 @@ const NotificationList = () => Box({
|
|||
vexpand: true,
|
||||
vpack: 'start',
|
||||
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) {
|
||||
addNotif(box, Notifications.getNotification(id));
|
||||
}
|
||||
}, 'notified'],
|
||||
setup: (self) => {
|
||||
self
|
||||
.hook(Notifications, (box, id) => {
|
||||
// Handle cached notifs
|
||||
if (box.children.length === 0) {
|
||||
Notifications.notifications.forEach((n) => {
|
||||
addNotif(box, n);
|
||||
});
|
||||
}
|
||||
|
||||
[Notifications, (box, id) => {
|
||||
const notif = box.children.find((ch) => ch._id === id);
|
||||
else if (id) {
|
||||
addNotif(box, Notifications.getNotification(id));
|
||||
}
|
||||
}, 'notified')
|
||||
|
||||
if (notif?.sensitive) {
|
||||
notif.slideAway('Right');
|
||||
}
|
||||
}, 'closed'],
|
||||
],
|
||||
.hook(Notifications, (box, id) => {
|
||||
const notif = box.children.find((ch) => ch._id === id);
|
||||
|
||||
if (notif?.sensitive) {
|
||||
notif.slideAway('Right');
|
||||
}
|
||||
}, 'closed');
|
||||
},
|
||||
});
|
||||
|
||||
// Needs to be wrapped to still have onHover when disabled
|
||||
|
@ -64,11 +66,13 @@ const ClearButton = () => EventBox({
|
|||
children: [
|
||||
Label('Clear '),
|
||||
Icon({
|
||||
connections: [[Notifications, (self) => {
|
||||
self.icon = Notifications.notifications.length > 0 ?
|
||||
'user-trash-full-symbolic' :
|
||||
'user-trash-symbolic';
|
||||
}]],
|
||||
setup: (self) => {
|
||||
self.hook(Notifications, () => {
|
||||
self.icon = Notifications.notifications.length > 0 ?
|
||||
'user-trash-full-symbolic' :
|
||||
'user-trash-symbolic';
|
||||
});
|
||||
},
|
||||
}),
|
||||
],
|
||||
}),
|
||||
|
|
|
@ -91,80 +91,80 @@ export default ({
|
|||
|
||||
widget.add(Box({
|
||||
css: squeezeLeft,
|
||||
connections: [
|
||||
setup: (self) => {
|
||||
self
|
||||
// When dragging
|
||||
.hook(gesture, () => {
|
||||
let offset = gesture.get_offset()[1];
|
||||
|
||||
// When dragging
|
||||
[gesture, (self) => {
|
||||
let offset = gesture.get_offset()[1];
|
||||
if (offset === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (offset === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Slide right
|
||||
if (offset > 0) {
|
||||
self.setCss(`
|
||||
// Slide right
|
||||
if (offset > 0) {
|
||||
self.setCss(`
|
||||
margin-top: 0px; margin-bottom: 0px;
|
||||
opacity: 1; transition: none;
|
||||
margin-left: ${offset}px;
|
||||
margin-right: -${offset}px;
|
||||
`);
|
||||
}
|
||||
}
|
||||
|
||||
// Slide left
|
||||
else {
|
||||
offset = Math.abs(offset);
|
||||
self.setCss(`
|
||||
// Slide left
|
||||
else {
|
||||
offset = Math.abs(offset);
|
||||
self.setCss(`
|
||||
margin-top: 0px; margin-bottom: 0px;
|
||||
opacity: 1; transition: none;
|
||||
margin-right: ${offset}px;
|
||||
margin-left: -${offset}px;
|
||||
`);
|
||||
}
|
||||
}
|
||||
|
||||
// Put a threshold on if a click is actually dragging
|
||||
widget._dragging = Math.abs(offset) > SLIDE_MIN_THRESHOLD;
|
||||
widget.cursor = 'grabbing';
|
||||
}, 'drag-update'],
|
||||
// Put a threshold on if a click is actually dragging
|
||||
widget._dragging = Math.abs(offset) > SLIDE_MIN_THRESHOLD;
|
||||
widget.cursor = 'grabbing';
|
||||
}, '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, () => {
|
||||
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 (Math.abs(offset) > MAX_OFFSET) {
|
||||
if (offset > 0) {
|
||||
widget.slideAway('Right');
|
||||
// If crosses threshold after letting go, slide away
|
||||
if (Math.abs(offset) > MAX_OFFSET) {
|
||||
if (offset > 0) {
|
||||
widget.slideAway('Right');
|
||||
}
|
||||
else {
|
||||
widget.slideAway('Left');
|
||||
}
|
||||
}
|
||||
else {
|
||||
widget.slideAway('Left');
|
||||
self.setCss(defaultStyle);
|
||||
widget.cursor = 'grab';
|
||||
widget._dragging = false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
self.setCss(defaultStyle);
|
||||
widget.cursor = 'grab';
|
||||
widget._dragging = false;
|
||||
}
|
||||
}, 'drag-end'],
|
||||
|
||||
],
|
||||
}, 'drag-end');
|
||||
},
|
||||
}));
|
||||
|
||||
return widget;
|
||||
|
|
|
@ -10,56 +10,57 @@ import { Notification } from './base.js';
|
|||
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({
|
||||
vertical: true,
|
||||
|
||||
connections: [
|
||||
[Notifications, (s, id) => addPopup(s, id), 'notified'],
|
||||
[Notifications, (s, id) => handleDismiss(s, id), 'dismissed'],
|
||||
[Notifications, (s, id) => handleDismiss(s, id, true), 'closed'],
|
||||
],
|
||||
setup: (self) => {
|
||||
const addPopup = (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
|
||||
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');
|
||||
},
|
||||
});
|
||||
|
|
|
@ -37,15 +37,17 @@ export default (window) => Box({
|
|||
active: true,
|
||||
vpack: 'center',
|
||||
|
||||
connections: [['toggled', (self) => {
|
||||
self.toggleClassName(
|
||||
'toggled',
|
||||
self.get_active(),
|
||||
);
|
||||
window.exclusivity = self.get_active() ?
|
||||
'exclusive' :
|
||||
'normal';
|
||||
}]],
|
||||
setup: (self) => {
|
||||
self.on('toggled', () => {
|
||||
self.toggleClassName(
|
||||
'toggled',
|
||||
self.get_active(),
|
||||
);
|
||||
window.exclusivity = self.get_active() ?
|
||||
'exclusive' :
|
||||
'normal';
|
||||
});
|
||||
},
|
||||
|
||||
child: Label('Exclusive'),
|
||||
}),
|
||||
|
|
|
@ -86,11 +86,13 @@ const ModKey = (key) => {
|
|||
self.child.toggleClassName('active', !Mod.value);
|
||||
Mod.value = !Mod.value;
|
||||
},
|
||||
connections: [[NormalClick, (self) => {
|
||||
Mod.value = false;
|
||||
self.child.toggleClassName('active', false);
|
||||
execAsync(`ydotool key ${key.keycode}:0`);
|
||||
}]],
|
||||
setup: (self) => {
|
||||
self.hook(NormalClick, () => {
|
||||
Mod.value = false;
|
||||
self.child.toggleClassName('active', false);
|
||||
execAsync(`ydotool key ${key.keycode}:0`);
|
||||
});
|
||||
},
|
||||
child: Label({
|
||||
class_name: `mod ${key.label}`,
|
||||
label: key.label,
|
||||
|
@ -114,40 +116,41 @@ const RegularKey = (key) => {
|
|||
class_name: `normal ${key.label}`,
|
||||
label: key.label,
|
||||
|
||||
connections: [
|
||||
[Shift, (self) => {
|
||||
if (!key.labelShift) {
|
||||
return;
|
||||
}
|
||||
setup: (self) => {
|
||||
self
|
||||
.hook(Shift, () => {
|
||||
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) => {
|
||||
if (key.label === 'Caps') {
|
||||
self.toggleClassName('active', Caps.value);
|
||||
return;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
if (!key.labelShift) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!key.labelShift) {
|
||||
return;
|
||||
}
|
||||
if (key.label.match(/[A-Za-z]/)) {
|
||||
self.label = Caps.value ?
|
||||
key.labelShift :
|
||||
key.label;
|
||||
}
|
||||
})
|
||||
.hook(AltGr, () => {
|
||||
if (!key.labelAltGr) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (key.label.match(/[A-Za-z]/)) {
|
||||
self.label = Caps.value ? key.labelShift : key.label;
|
||||
}
|
||||
}],
|
||||
|
||||
[AltGr, (self) => {
|
||||
if (!key.labelAltGr) {
|
||||
return;
|
||||
}
|
||||
|
||||
self.toggleClassName('altgr', AltGr.value);
|
||||
self.label = AltGr.value ? key.labelAltGr : key.label;
|
||||
}],
|
||||
],
|
||||
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;
|
||||
|
||||
// Long press
|
||||
widget.connectTo(gesture, () => {
|
||||
widget.hook(gesture, () => {
|
||||
const pointer = gesture.get_point(null);
|
||||
const x = pointer[1];
|
||||
const y = pointer[2];
|
||||
|
@ -171,7 +174,7 @@ const RegularKey = (key) => {
|
|||
}, 'pressed');
|
||||
|
||||
// OnPrimaryClickRelease
|
||||
widget.connectTo(gesture, () => {
|
||||
widget.hook(gesture, () => {
|
||||
const pointer = gesture.get_point(null);
|
||||
const x = pointer[1];
|
||||
const y = pointer[2];
|
||||
|
|
|
@ -16,17 +16,18 @@ export default () => {
|
|||
visible: false,
|
||||
anchor: ['left', 'bottom', 'right'],
|
||||
|
||||
connections: [
|
||||
[Tablet, (self, state) => {
|
||||
self.setVisible(state);
|
||||
}, 'osk-toggled'],
|
||||
setup: (self) => {
|
||||
self
|
||||
.hook(Tablet, (_, state) => {
|
||||
self.setVisible(state);
|
||||
}, 'osk-toggled')
|
||||
|
||||
[Tablet, () => {
|
||||
if (!Tablet.tabletMode && !Tablet.oskState) {
|
||||
window.visible = false;
|
||||
}
|
||||
}, 'mode-toggled'],
|
||||
],
|
||||
.hook(Tablet, () => {
|
||||
if (!Tablet.tabletMode && !Tablet.oskState) {
|
||||
window.visible = false;
|
||||
}
|
||||
}, 'mode-toggled');
|
||||
},
|
||||
});
|
||||
|
||||
window.child = Keyboard(window);
|
||||
|
|
|
@ -36,7 +36,7 @@ export default ({ stack, icon, info } = {}) => {
|
|||
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;
|
||||
};
|
||||
|
|
|
@ -33,28 +33,28 @@ let hidden = 0;
|
|||
|
||||
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 = 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) => {
|
||||
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,
|
||||
);
|
||||
|
||||
self.connect('drag-data-get', (_w, _c, data) => {
|
||||
self.on('drag-data-get', (_w, _c, data) => {
|
||||
data.set_text(address, address.length);
|
||||
});
|
||||
|
||||
self.connect('drag-begin', (_, context) => {
|
||||
self.on('drag-begin', (_, context) => {
|
||||
Gtk.drag_set_icon_surface(context, createSurfaceFromWidget(self));
|
||||
self.get_parent().revealChild = false;
|
||||
});
|
||||
|
||||
self.connect('drag-end', () => {
|
||||
self.on('drag-end', () => {
|
||||
self.get_parent().destroy();
|
||||
|
||||
updateClients(mainBox);
|
||||
|
|
|
@ -40,13 +40,15 @@ export const Overview = () => {
|
|||
}),
|
||||
],
|
||||
|
||||
connections: [[Hyprland, (self) => {
|
||||
if (!App.getWindow('overview').visible) {
|
||||
return;
|
||||
}
|
||||
setup: (self) => {
|
||||
self.hook(Hyprland, () => {
|
||||
if (!App.getWindow('overview').visible) {
|
||||
return;
|
||||
}
|
||||
|
||||
self.update();
|
||||
}]],
|
||||
self.update();
|
||||
});
|
||||
},
|
||||
|
||||
properties: [
|
||||
['workspaces'],
|
||||
|
@ -72,15 +74,17 @@ export const Overview = () => {
|
|||
}),
|
||||
|
||||
// TODO: throttle his?
|
||||
connections: [['get-child-position', (self, ch) => {
|
||||
if (ch === mainBox) {
|
||||
self.child.setCss(`
|
||||
transition: min-height 0.2s ease, min-width 0.2s ease;
|
||||
min-height: ${mainBox.get_allocated_height()}px;
|
||||
min-width: ${mainBox.get_allocated_width()}px;
|
||||
`);
|
||||
}
|
||||
}]],
|
||||
setup: (self) => {
|
||||
self.on('get-child-position', (_, ch) => {
|
||||
if (ch === mainBox) {
|
||||
self.child.setCss(`
|
||||
transition: min-height 0.2s ease, min-width 0.2s ease;
|
||||
min-height: ${mainBox.get_allocated_height()}px;
|
||||
min-width: ${mainBox.get_allocated_width()}px;
|
||||
`);
|
||||
}
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
widget.getChild = () => mainBox;
|
||||
|
|
|
@ -31,17 +31,17 @@ const Workspace = (id, name, normal = true) => {
|
|||
transition: 'slide_right',
|
||||
transitionDuration: 500,
|
||||
|
||||
connections: normal ?
|
||||
setup: (self) => {
|
||||
if (normal) {
|
||||
self.hook(Hyprland, () => {
|
||||
const activeId = Hyprland.active.workspace.id;
|
||||
const active = activeId === self._id;
|
||||
|
||||
[[Hyprland, (box) => {
|
||||
const activeId = Hyprland.active.workspace.id;
|
||||
const active = activeId === box._id;
|
||||
|
||||
box.revealChild = Hyprland.getWorkspace(box._id)
|
||||
?.windows > 0 || active;
|
||||
}]] :
|
||||
|
||||
[],
|
||||
self.revealChild = Hyprland.getWorkspace(self._id)
|
||||
?.windows > 0 || active;
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
child: WorkspaceDrop({
|
||||
child: Box({
|
||||
|
@ -88,38 +88,42 @@ export const WorkspaceRow = (className, i) => {
|
|||
transition: 'slide_down',
|
||||
hpack: className === 'special' ? '' : 'start',
|
||||
|
||||
connections: [[Hyprland, (rev) => {
|
||||
const minId = i * VARS.WORKSPACE_PER_ROW;
|
||||
const activeId = Hyprland.active.workspace.id;
|
||||
setup: (self) => {
|
||||
self.hook(Hyprland, (rev) => {
|
||||
const minId = i * VARS.WORKSPACE_PER_ROW;
|
||||
const activeId = Hyprland.active.workspace.id;
|
||||
|
||||
const rowExists = Hyprland.workspaces.some((ws) => {
|
||||
const isInRow = ws.id > minId;
|
||||
const hasClients = ws.windows > 0;
|
||||
const isActive = ws.id === activeId;
|
||||
const rowExists = Hyprland.workspaces.some((ws) => {
|
||||
const isInRow = ws.id > minId;
|
||||
const hasClients = ws.windows > 0;
|
||||
const isActive = ws.id === activeId;
|
||||
|
||||
return isInRow && (hasClients || isActive);
|
||||
return isInRow && (hasClients || isActive);
|
||||
});
|
||||
|
||||
rev.revealChild = rowExists;
|
||||
});
|
||||
|
||||
rev.revealChild = rowExists;
|
||||
}]],
|
||||
},
|
||||
|
||||
child: CenterBox({
|
||||
children: [null, EventBox({
|
||||
connections: [[Hyprland, () => {
|
||||
const maxId = (i + 1) * VARS.WORKSPACE_PER_ROW;
|
||||
const activeId = Hyprland.active.workspace.id;
|
||||
setup: (self) => {
|
||||
self.hook(Hyprland, () => {
|
||||
const maxId = (i + 1) * VARS.WORKSPACE_PER_ROW;
|
||||
const activeId = Hyprland.active.workspace.id;
|
||||
|
||||
const isSpecial = className === 'special';
|
||||
const nextRowExists = Hyprland.workspaces.some((ws) => {
|
||||
const isInNextRow = ws.id > maxId;
|
||||
const hasClients = ws.windows > 0;
|
||||
const isActive = ws.id === activeId;
|
||||
const isSpecial = className === 'special';
|
||||
const nextRowExists = Hyprland.workspaces.some((ws) => {
|
||||
const isInNextRow = ws.id > maxId;
|
||||
const hasClients = ws.windows > 0;
|
||||
const isActive = ws.id === activeId;
|
||||
|
||||
return isInNextRow && (hasClients || isActive);
|
||||
return isInNextRow && (hasClients || isActive);
|
||||
});
|
||||
|
||||
addWorkspace.revealChild = isSpecial || !nextRowExists;
|
||||
});
|
||||
|
||||
addWorkspace.revealChild = isSpecial || !nextRowExists;
|
||||
}]],
|
||||
},
|
||||
|
||||
child: Box({
|
||||
className,
|
||||
|
|
|
@ -5,8 +5,8 @@ import { Box, Icon, Label, ListBox, Overlay, Revealer, Scrollable } from 'resour
|
|||
|
||||
import EventBox from '../misc/cursorbox.js';
|
||||
|
||||
const SCROLL_THRESHOLD_H = 200;
|
||||
const SCROLL_THRESHOLD_N = 7;
|
||||
const SCROLL_THRESH_H = 200;
|
||||
const SCROLL_THRESH_N = 7;
|
||||
|
||||
|
||||
const BluetoothDevice = (dev) => {
|
||||
|
@ -29,9 +29,11 @@ const BluetoothDevice = (dev) => {
|
|||
icon: 'object-select-symbolic',
|
||||
hexpand: true,
|
||||
hpack: 'end',
|
||||
connections: [[dev, (self) => {
|
||||
self.setCss(`opacity: ${dev.paired ? '1' : '0'};`);
|
||||
}]],
|
||||
setup: (self) => {
|
||||
self.hook(dev, () => {
|
||||
self.setCss(`opacity: ${dev.paired ? '1' : '0'};`);
|
||||
});
|
||||
},
|
||||
}),
|
||||
],
|
||||
});
|
||||
|
@ -95,17 +97,19 @@ export const BluetoothMenu = () => {
|
|||
hscroll: 'never',
|
||||
vscroll: 'never',
|
||||
|
||||
connections: [['edge-reached', (_, pos) => {
|
||||
// Manage scroll indicators
|
||||
if (pos === 2) {
|
||||
topArrow.revealChild = false;
|
||||
bottomArrow.revealChild = true;
|
||||
}
|
||||
else if (pos === 3) {
|
||||
topArrow.revealChild = true;
|
||||
bottomArrow.revealChild = false;
|
||||
}
|
||||
}]],
|
||||
setup: (self) => {
|
||||
self.on('edge-reached', (_, pos) => {
|
||||
// Manage scroll indicators
|
||||
if (pos === 2) {
|
||||
topArrow.revealChild = false;
|
||||
bottomArrow.revealChild = true;
|
||||
}
|
||||
else if (pos === 3) {
|
||||
topArrow.revealChild = true;
|
||||
bottomArrow.revealChild = false;
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
child: ListBox({
|
||||
setup: (self) => {
|
||||
|
@ -113,78 +117,79 @@ export const BluetoothMenu = () => {
|
|||
return b.get_children()[0].dev.paired -
|
||||
a.get_children()[0].dev.paired;
|
||||
});
|
||||
},
|
||||
|
||||
connections: [[Bluetooth, (box) => {
|
||||
// Get all devices
|
||||
const Devices = [].concat(
|
||||
Bluetooth.devices,
|
||||
Bluetooth.connectedDevices,
|
||||
);
|
||||
self.hook(Bluetooth, () => {
|
||||
// Get all devices
|
||||
const Devices = [].concat(
|
||||
Bluetooth.devices,
|
||||
Bluetooth.connectedDevices,
|
||||
);
|
||||
|
||||
// Add missing devices
|
||||
Devices.forEach((dev) => {
|
||||
if (!DevList.has(dev) && dev.name) {
|
||||
DevList.set(dev, BluetoothDevice(dev));
|
||||
// Add missing devices
|
||||
Devices.forEach((dev) => {
|
||||
if (!DevList.has(dev) && dev.name) {
|
||||
DevList.set(dev, BluetoothDevice(dev));
|
||||
|
||||
box.add(DevList.get(dev));
|
||||
box.show_all();
|
||||
}
|
||||
});
|
||||
self.add(DevList.get(dev));
|
||||
self.show_all();
|
||||
}
|
||||
});
|
||||
|
||||
// Delete ones that don't exist anymore
|
||||
const difference = Array.from(DevList.keys())
|
||||
.filter((dev) => !Devices
|
||||
.find((d) => dev === d) &&
|
||||
// Delete ones that don't exist anymore
|
||||
const difference = Array.from(DevList.keys())
|
||||
.filter((dev) => !Devices
|
||||
.find((d) => dev === d) &&
|
||||
dev.name);
|
||||
|
||||
difference.forEach((dev) => {
|
||||
const devWidget = DevList.get(dev);
|
||||
difference.forEach((dev) => {
|
||||
const devWidget = DevList.get(dev);
|
||||
|
||||
if (devWidget) {
|
||||
if (devWidget.toDestroy) {
|
||||
devWidget.get_parent().destroy();
|
||||
DevList.delete(dev);
|
||||
if (devWidget) {
|
||||
if (devWidget.toDestroy) {
|
||||
devWidget.get_parent().destroy();
|
||||
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;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
else {
|
||||
scroll.vscroll = 'never';
|
||||
scroll.setCss('');
|
||||
topArrow.revealChild = false;
|
||||
bottomArrow.revealChild = false;
|
||||
}
|
||||
|
||||
// Trigger sort_func
|
||||
box.get_children().forEach((ch) => {
|
||||
ch.changed();
|
||||
// Trigger sort_func
|
||||
self.get_children().forEach((ch) => {
|
||||
ch.changed();
|
||||
});
|
||||
});
|
||||
}]],
|
||||
},
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
|
|
|
@ -34,24 +34,27 @@ const GridButton = ({
|
|||
icon = Icon({
|
||||
className: 'grid-label',
|
||||
icon,
|
||||
connections: [[Activated, (self) => {
|
||||
self.setCss(`color: ${Activated.value ?
|
||||
'rgba(189, 147, 249, 0.8)' :
|
||||
'unset'};`);
|
||||
}]],
|
||||
setup: (self) => {
|
||||
self.hook(Activated, () => {
|
||||
self.setCss(`color: ${Activated.value ?
|
||||
'rgba(189, 147, 249, 0.8)' :
|
||||
'unset'};`);
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
else {
|
||||
icon = Icon({
|
||||
className: 'grid-label',
|
||||
connections: [
|
||||
icon,
|
||||
[Activated, (self) => {
|
||||
self.setCss(`color: ${Activated.value ?
|
||||
'rgba(189, 147, 249, 0.8)' :
|
||||
'unset'};`);
|
||||
}],
|
||||
],
|
||||
setup: (self) => {
|
||||
self
|
||||
.hook(...icon)
|
||||
.hook(Activated, () => {
|
||||
self.setCss(`color: ${Activated.value ?
|
||||
'rgba(189, 147, 249, 0.8)' :
|
||||
'unset'};`);
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -61,7 +64,9 @@ const GridButton = ({
|
|||
justification: 'left',
|
||||
truncate: 'end',
|
||||
maxWidthChars: 12,
|
||||
connections: [indicator],
|
||||
setup: (self) => {
|
||||
self.hook(...indicator);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -126,17 +131,19 @@ const GridButton = ({
|
|||
icon: `${App.configDir }/icons/down-large.svg`,
|
||||
className: 'grid-chev',
|
||||
|
||||
connections: [[Activated, (self) => {
|
||||
let deg = 270;
|
||||
setup: (self) => {
|
||||
self.hook(Activated, () => {
|
||||
let deg = 270;
|
||||
|
||||
if (Activated.value) {
|
||||
deg = menu ? 360 : 450;
|
||||
onOpen(menu);
|
||||
}
|
||||
self.setCss(`
|
||||
-gtk-icon-transform: rotate(${deg}deg);
|
||||
`);
|
||||
}]],
|
||||
if (Activated.value) {
|
||||
deg = menu ? 360 : 450;
|
||||
onOpen(menu);
|
||||
}
|
||||
self.setCss(`
|
||||
-gtk-icon-transform: rotate(${deg}deg);
|
||||
`);
|
||||
});
|
||||
},
|
||||
}),
|
||||
}),
|
||||
|
||||
|
|
|
@ -7,8 +7,8 @@ import { execAsync } from 'resource:///com/github/Aylur/ags/utils.js';
|
|||
|
||||
import EventBox from '../misc/cursorbox.js';
|
||||
|
||||
const SCROLL_THRESHOLD_H = 200;
|
||||
const SCROLL_THRESHOLD_N = 7;
|
||||
const SCROLL_THRESH_H = 200;
|
||||
const SCROLL_THRESH_N = 7;
|
||||
|
||||
|
||||
const AccessPoint = (ap) => {
|
||||
|
@ -22,28 +22,37 @@ const AccessPoint = (ap) => {
|
|||
hexpand: true,
|
||||
children: [
|
||||
Icon({
|
||||
connections: [[widget.ap, (self) => {
|
||||
self.icon = widget.ap.value.iconName;
|
||||
}]],
|
||||
setup: (self) => {
|
||||
self.hook(widget.ap, () => {
|
||||
self.icon = widget.ap.value.iconName;
|
||||
});
|
||||
},
|
||||
}),
|
||||
|
||||
Label({
|
||||
connections: [[widget.ap, (self) => {
|
||||
self.label = widget.ap.value.ssid || '';
|
||||
}]],
|
||||
setup: (self) => {
|
||||
self.hook(widget.ap, () => {
|
||||
self.label = widget.ap.value.ssid || '';
|
||||
});
|
||||
},
|
||||
}),
|
||||
|
||||
Icon({
|
||||
icon: 'object-select-symbolic',
|
||||
hexpand: true,
|
||||
hpack: 'end',
|
||||
connections: [[Network, (self) => {
|
||||
self.setCss(`opacity: ${
|
||||
widget.ap.value.ssid === Network.wifi.ssid ?
|
||||
'1' :
|
||||
'0'
|
||||
};`);
|
||||
}]],
|
||||
setup: (self) => {
|
||||
self.hook(Network, () => {
|
||||
self.setCss(
|
||||
`opacity: ${
|
||||
widget.ap.value.ssid === Network.wifi.ssid ?
|
||||
'1' :
|
||||
'0'
|
||||
};
|
||||
`,
|
||||
);
|
||||
});
|
||||
},
|
||||
}),
|
||||
],
|
||||
});
|
||||
|
@ -109,17 +118,19 @@ export const NetworkMenu = () => {
|
|||
hscroll: 'never',
|
||||
vscroll: 'never',
|
||||
|
||||
connections: [['edge-reached', (_, pos) => {
|
||||
// Manage scroll indicators
|
||||
if (pos === 2) {
|
||||
topArrow.revealChild = false;
|
||||
bottomArrow.revealChild = true;
|
||||
}
|
||||
else if (pos === 3) {
|
||||
topArrow.revealChild = true;
|
||||
bottomArrow.revealChild = false;
|
||||
}
|
||||
}]],
|
||||
setup: (self) => {
|
||||
self.on('edge-reached', (_, pos) => {
|
||||
// Manage scroll indicators
|
||||
if (pos === 2) {
|
||||
topArrow.revealChild = false;
|
||||
bottomArrow.revealChild = true;
|
||||
}
|
||||
else if (pos === 3) {
|
||||
topArrow.revealChild = true;
|
||||
bottomArrow.revealChild = false;
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
child: ListBox({
|
||||
setup: (self) => {
|
||||
|
@ -127,82 +138,83 @@ export const NetworkMenu = () => {
|
|||
return b.get_children()[0].ap.value.strength -
|
||||
a.get_children()[0].ap.value.strength;
|
||||
});
|
||||
},
|
||||
|
||||
connections: [[Network, (box) => {
|
||||
// Add missing APs
|
||||
Network.wifi?.access_points.forEach((ap) => {
|
||||
if (ap.ssid !== 'Unknown') {
|
||||
if (APList.has(ap.ssid)) {
|
||||
const accesPoint = APList.get(ap.ssid)
|
||||
.ap.value;
|
||||
self.hook(Network, () => {
|
||||
// Add missing APs
|
||||
Network.wifi?.access_points.forEach((ap) => {
|
||||
if (ap.ssid !== 'Unknown') {
|
||||
if (APList.has(ap.ssid)) {
|
||||
const accesPoint = APList.get(ap.ssid)
|
||||
.ap.value;
|
||||
|
||||
if (accesPoint.strength < ap.strength) {
|
||||
APList.get(ap.ssid).ap.value = ap;
|
||||
if (accesPoint.strength < ap.strength) {
|
||||
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));
|
||||
box.show_all();
|
||||
// Delete ones that don't exist anymore
|
||||
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;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Delete ones that don't exist anymore
|
||||
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;
|
||||
}
|
||||
else {
|
||||
scroll.vscroll = 'never';
|
||||
scroll.setCss('');
|
||||
topArrow.revealChild = false;
|
||||
bottomArrow.revealChild = false;
|
||||
}
|
||||
|
||||
// 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();
|
||||
});
|
||||
}]],
|
||||
},
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
|
|
|
@ -34,18 +34,20 @@ export default () => Box({
|
|||
Audio.speaker.volume = value;
|
||||
},
|
||||
|
||||
connections: [
|
||||
[Audio, (slider) => {
|
||||
slider.value = Audio.speaker?.volume;
|
||||
}, 'speaker-changed'],
|
||||
setup: (self) => {
|
||||
self
|
||||
.hook(Audio, () => {
|
||||
self.value = Audio.speaker?.volume;
|
||||
}, 'speaker-changed')
|
||||
|
||||
['button-press-event', (s) => {
|
||||
s.cursor = 'grabbing';
|
||||
}],
|
||||
['button-release-event', (s) => {
|
||||
s.cursor = 'pointer';
|
||||
}],
|
||||
],
|
||||
.on('button-press-event', () => {
|
||||
self.cursor = 'grabbing';
|
||||
})
|
||||
|
||||
.on('button-release-event', () => {
|
||||
self.cursor = 'pointer';
|
||||
});
|
||||
},
|
||||
}),
|
||||
],
|
||||
}),
|
||||
|
@ -70,18 +72,20 @@ export default () => Box({
|
|||
Brightness.screen = value;
|
||||
},
|
||||
|
||||
connections: [
|
||||
[Brightness, (slider) => {
|
||||
slider.value = Brightness.screen;
|
||||
}, 'screen'],
|
||||
setup: (self) => {
|
||||
self
|
||||
.hook(Brightness, () => {
|
||||
self.value = Brightness.screen;
|
||||
}, 'screen')
|
||||
|
||||
['button-press-event', (s) => {
|
||||
s.cursor = 'grabbing';
|
||||
}],
|
||||
['button-release-event', (s) => {
|
||||
s.cursor = 'pointer';
|
||||
}],
|
||||
],
|
||||
.on('button-press-event', () => {
|
||||
self.cursor = 'grabbing';
|
||||
})
|
||||
|
||||
.on('button-release-event', () => {
|
||||
self.cursor = 'pointer';
|
||||
});
|
||||
},
|
||||
}),
|
||||
],
|
||||
}),
|
||||
|
|
|
@ -14,20 +14,20 @@ export default (rev) => CenterBox({
|
|||
self.set_active(Mpris.players.length > 0);
|
||||
Mpris.disconnect(id);
|
||||
});
|
||||
},
|
||||
|
||||
connections: [['toggled', (self) => {
|
||||
if (self.get_active()) {
|
||||
self.get_children()[0]
|
||||
.setCss('-gtk-icon-transform: rotate(0deg);');
|
||||
rev.revealChild = true;
|
||||
}
|
||||
else {
|
||||
self.get_children()[0]
|
||||
.setCss('-gtk-icon-transform: rotate(180deg);');
|
||||
rev.revealChild = false;
|
||||
}
|
||||
}]],
|
||||
self.on('toggled', () => {
|
||||
if (self.get_active()) {
|
||||
self.get_children()[0]
|
||||
.setCss('-gtk-icon-transform: rotate(0deg);');
|
||||
rev.revealChild = true;
|
||||
}
|
||||
else {
|
||||
self.get_children()[0]
|
||||
.setCss('-gtk-icon-transform: rotate(180deg);');
|
||||
rev.revealChild = false;
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
child: Icon({
|
||||
icon: `${App.configDir }/icons/down-large.svg`,
|
||||
|
|
BIN
flake.lock
BIN
flake.lock
Binary file not shown.
Loading…
Reference in a new issue