refactor(ags): improve typecheck and fix bugs
This commit is contained in:
parent
da30e6f05f
commit
a126d97bbf
12 changed files with 201 additions and 157 deletions
|
@ -1,15 +1,12 @@
|
|||
import { Label } from 'resource:///com/github/Aylur/ags/widget.js';
|
||||
|
||||
|
||||
export default () => Label({
|
||||
className: 'clock',
|
||||
|
||||
connections: [[1000, (self) => {
|
||||
export default () => Label({ className: 'clock' })
|
||||
.poll(1000, (self) => {
|
||||
const time = imports.gi.GLib
|
||||
.DateTime.new_now_local();
|
||||
.DateTime.new_now_local();
|
||||
|
||||
self.label = time.format('%a. ') +
|
||||
time.get_day_of_month() +
|
||||
time.format(' %b. %H:%M');
|
||||
}]],
|
||||
})
|
||||
});
|
||||
|
|
|
@ -9,7 +9,7 @@ export const NotifPopups = () => PopupWindow({
|
|||
anchor: ['bottom', 'left'],
|
||||
visible: true,
|
||||
transition: 'none',
|
||||
closeOnUnfocus: 'stay',
|
||||
close_on_unfocus: 'stay',
|
||||
monitor: 1,
|
||||
|
||||
child: PopUpsWidget(),
|
||||
|
|
|
@ -11,7 +11,7 @@ const SPACING = 4;
|
|||
/**
|
||||
* @param {Label} self
|
||||
* @param {string} layout
|
||||
* @param {void} _
|
||||
* @param {string} _
|
||||
*/
|
||||
const getKbdLayout = (self, _, layout) => {
|
||||
if (layout) {
|
||||
|
|
|
@ -9,12 +9,16 @@ export default () => CursorBox({
|
|||
|
||||
on_primary_click_release: () => Tablet.toggleOsk(),
|
||||
|
||||
setup: (self) => {
|
||||
self.hook(Tablet, () => {
|
||||
self.toggleClassName('toggle-on', Tablet.oskState);
|
||||
}, 'osk-toggled');
|
||||
},
|
||||
|
||||
child: Label({
|
||||
class_name: 'osk-toggle',
|
||||
xalign: 0.6,
|
||||
label: ' ',
|
||||
}),
|
||||
|
||||
}).hook(Tablet, (self) => {
|
||||
self.toggleClassName('toggle-on', Tablet.oskState);
|
||||
}, 'osk-toggled');
|
||||
});
|
||||
|
|
|
@ -38,39 +38,50 @@ const SysTray = () => MenuBar({
|
|||
},
|
||||
|
||||
setup: (self) => {
|
||||
/**
|
||||
* @param {import('types/widget').default} _
|
||||
* @param {string} id
|
||||
*/
|
||||
const addTray = (_, id) => {
|
||||
const item = SystemTray.getItem(id);
|
||||
|
||||
if (self.attribute.items.has(id) || !item) {
|
||||
return;
|
||||
}
|
||||
|
||||
const w = SysTrayItem(item);
|
||||
|
||||
// Early return if item is in blocklist
|
||||
if (!w) {
|
||||
return;
|
||||
}
|
||||
|
||||
self.attribute.items.set(id, w);
|
||||
self.child = w;
|
||||
self.show_all();
|
||||
// @ts-expect-error
|
||||
w.child.reveal_child = true;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {import('types/widget').default} _
|
||||
* @param {string} id
|
||||
*/
|
||||
const removeTray = (_, id) => {
|
||||
if (!self.attribute.items.has(id)) {
|
||||
return;
|
||||
}
|
||||
|
||||
self.attribute.items.get(id).child.reveal_child = false;
|
||||
timeout(REVEAL_DURATION, () => {
|
||||
self.attribute.items.get(id).destroy();
|
||||
self.attribute.items.delete(id);
|
||||
});
|
||||
};
|
||||
|
||||
self
|
||||
.hook(SystemTray, (_, id) => {
|
||||
const item = SystemTray.getItem(id);
|
||||
|
||||
if (self.attribute.items.has(id) || !item) {
|
||||
return;
|
||||
}
|
||||
|
||||
const w = SysTrayItem(item);
|
||||
|
||||
// Early return if item is in blocklist
|
||||
if (!w) {
|
||||
return;
|
||||
}
|
||||
|
||||
self.attribute.items.set(id, w);
|
||||
self.child = w;
|
||||
self.show_all();
|
||||
// @ts-expect-error
|
||||
w.child.reveal_child = true;
|
||||
}, 'added')
|
||||
|
||||
.hook(SystemTray, (_, id) => {
|
||||
if (!self.attribute.items.has(id)) {
|
||||
return;
|
||||
}
|
||||
|
||||
self.attribute.items.get(id).child.reveal_child = false;
|
||||
timeout(REVEAL_DURATION, () => {
|
||||
self.attribute.items.get(id).destroy();
|
||||
self.attribute.items.delete(id);
|
||||
});
|
||||
}, 'removed');
|
||||
.hook(SystemTray, addTray, 'added')
|
||||
.hook(SystemTray, removeTray, 'removed');
|
||||
},
|
||||
});
|
||||
|
||||
|
|
|
@ -9,12 +9,16 @@ export default () => CursorBox({
|
|||
|
||||
on_primary_click_release: () => Tablet.toggleMode(),
|
||||
|
||||
setup: (self) => {
|
||||
self.hook(Tablet, () => {
|
||||
self.toggleClassName('toggle-on', Tablet.tabletMode);
|
||||
}, 'mode-toggled');
|
||||
},
|
||||
|
||||
child: Box({
|
||||
class_name: 'tablet-toggle',
|
||||
vertical: false,
|
||||
children: [Label(' ')],
|
||||
}),
|
||||
|
||||
}).hook(Tablet, (self) => {
|
||||
self.toggleClassName('toggle-on', Tablet.tabletMode);
|
||||
}, 'mode-toggled');
|
||||
});
|
||||
|
|
|
@ -7,8 +7,6 @@ import CursorBox from '../../misc/cursorbox.js';
|
|||
|
||||
const URGENT_DURATION = 1000;
|
||||
|
||||
/** @typedef {import('types/widget.js').Widget} Widget */
|
||||
|
||||
|
||||
/** @property {number} id */
|
||||
const Workspace = ({ id }) => {
|
||||
|
@ -17,7 +15,7 @@ const Workspace = ({ id }) => {
|
|||
attribute: { id },
|
||||
|
||||
child: CursorBox({
|
||||
tooltipText: `${id}`,
|
||||
tooltip_text: `${id}`,
|
||||
|
||||
on_primary_click_release: () => {
|
||||
Hyprland.sendMessage(`dispatch workspace ${id}`);
|
||||
|
@ -29,7 +27,7 @@ const Workspace = ({ id }) => {
|
|||
|
||||
setup: (self) => {
|
||||
/**
|
||||
* @param {Widget} _
|
||||
* @param {import('types/widgets/box').default} _
|
||||
* @param {string|undefined} addr
|
||||
*/
|
||||
const update = (_, addr) => {
|
||||
|
@ -80,11 +78,11 @@ export default () => {
|
|||
const L_PADDING = 16;
|
||||
const WS_WIDTH = 30;
|
||||
|
||||
/** @param {Widget} self */
|
||||
/** @param {import('types/widgets/box').default} self */
|
||||
const updateHighlight = (self) => {
|
||||
const currentId = Hyprland.active.workspace.id;
|
||||
// @ts-expect-error
|
||||
const indicators = self.get_parent().get_children()[0].child.child.children;
|
||||
const indicators = self?.get_parent()?.child.child.child.children;
|
||||
const currentIndex = Array.from(indicators)
|
||||
.findIndex((w) => w.attribute.id === currentId);
|
||||
|
||||
|
@ -92,7 +90,6 @@ export default () => {
|
|||
return;
|
||||
}
|
||||
|
||||
// @ts-expect-error
|
||||
self.setCss(`margin-left: ${L_PADDING + (currentIndex * WS_WIDTH)}px`);
|
||||
};
|
||||
|
||||
|
@ -100,6 +97,7 @@ export default () => {
|
|||
vpack: 'center',
|
||||
hpack: 'start',
|
||||
class_name: 'button active',
|
||||
|
||||
}).hook(Hyprland.active.workspace, updateHighlight);
|
||||
|
||||
const widget = Overlay({
|
||||
|
@ -118,7 +116,7 @@ export default () => {
|
|||
rev.reveal_child = false;
|
||||
});
|
||||
Array.from(self.attribute.workspaces).forEach((ws) => {
|
||||
ws.revealChild = true;
|
||||
ws.reveal_child = true;
|
||||
});
|
||||
};
|
||||
|
||||
|
|
|
@ -35,20 +35,27 @@ export default (props) => {
|
|||
vertical: true,
|
||||
|
||||
setup: (self) => {
|
||||
const checkCurrentWsFsState = () => {
|
||||
const workspace = Hyprland.getWorkspace(
|
||||
Hyprland.active.workspace.id,
|
||||
);
|
||||
|
||||
if (workspace) {
|
||||
Revealed.value = !workspace['hasfullscreen'];
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {import('types/widgets/box').default} _
|
||||
* @param {boolean} fullscreen
|
||||
*/
|
||||
const checkGlobalFsState = (_, fullscreen) => {
|
||||
Revealed.value = !fullscreen;
|
||||
};
|
||||
|
||||
self
|
||||
.hook(Hyprland.active, () => {
|
||||
const workspace = Hyprland.getWorkspace(
|
||||
Hyprland.active.workspace.id,
|
||||
);
|
||||
|
||||
if (workspace) {
|
||||
Revealed.value = !workspace['hasfullscreen'];
|
||||
}
|
||||
})
|
||||
|
||||
.hook(Hyprland, (_, fullscreen) => {
|
||||
Revealed.value = !fullscreen;
|
||||
}, 'fullscreen');
|
||||
.hook(Hyprland.active, checkCurrentWsFsState)
|
||||
.hook(Hyprland, checkGlobalFsState, 'fullscreen');
|
||||
},
|
||||
|
||||
children: [
|
||||
|
|
|
@ -10,11 +10,17 @@ const TRANSITION = `transition: margin ${ANIM_DURATION}ms ease,
|
|||
opacity ${ANIM_DURATION}ms ease;`;
|
||||
|
||||
|
||||
/**
|
||||
* @typedef {import('types/widgets/overlay').OverlayProps} OverlayProps
|
||||
* @typedef {import('types/widgets/overlay').default} Overlay
|
||||
*
|
||||
* @param {OverlayProps & {
|
||||
* setup?: function(Overlay):void
|
||||
* }} o
|
||||
*/
|
||||
export default ({
|
||||
attribute = {},
|
||||
setup = (self) => {
|
||||
self;
|
||||
},
|
||||
setup = () => {/**/},
|
||||
...props
|
||||
}) => {
|
||||
const widget = EventBox();
|
||||
|
@ -36,6 +42,7 @@ export default ({
|
|||
// @ts-expect-error
|
||||
.filter((ch) => !ch.attribute?.empty),
|
||||
|
||||
/** @param {Overlay} playerW */
|
||||
includesWidget: (playerW) => {
|
||||
return Array.from(content.attribute.list())
|
||||
.find((w) => w === playerW);
|
||||
|
@ -46,6 +53,7 @@ export default ({
|
|||
over.visible = over === content.attribute.list().at(-1);
|
||||
}),
|
||||
|
||||
/** @param {import('types/widgets/centerbox').default} player */
|
||||
moveToTop: (player) => {
|
||||
player.visible = true;
|
||||
content.reorder_overlay(player, -1);
|
||||
|
@ -61,102 +69,113 @@ export default ({
|
|||
setup(self);
|
||||
|
||||
self
|
||||
.hook(gesture, (overlay, realGesture) => {
|
||||
if (realGesture) {
|
||||
Array.from(overlay.attribute.list()).forEach((over) => {
|
||||
over.visible = true;
|
||||
});
|
||||
}
|
||||
else {
|
||||
overlay.attribute.showTopOnly();
|
||||
}
|
||||
.hook(gesture,
|
||||
/**
|
||||
* @param {Overlay} overlay
|
||||
* @param {number} realGesture
|
||||
*/
|
||||
(overlay, realGesture) => {
|
||||
if (realGesture) {
|
||||
Array.from(overlay.attribute.list())
|
||||
.forEach((over) => {
|
||||
over.visible = true;
|
||||
});
|
||||
}
|
||||
else {
|
||||
overlay.attribute.showTopOnly();
|
||||
}
|
||||
|
||||
// Don't allow gesture when only one player
|
||||
if (overlay.attribute.list().length <= 1) {
|
||||
return;
|
||||
}
|
||||
// Don't allow gesture when only one player
|
||||
if (overlay.attribute.list().length <= 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
overlay.attribute.dragging = true;
|
||||
let offset = gesture.get_offset()[1];
|
||||
const playerBox = overlay.attribute.list().at(-1);
|
||||
overlay.attribute.dragging = true;
|
||||
let offset = gesture.get_offset()[1];
|
||||
const playerBox = overlay.attribute.list().at(-1);
|
||||
|
||||
if (!offset) {
|
||||
return;
|
||||
}
|
||||
if (!offset) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Slide right
|
||||
if (offset >= 0) {
|
||||
playerBox.setCss(`
|
||||
// Slide right
|
||||
if (offset >= 0) {
|
||||
playerBox.setCss(`
|
||||
margin-left: ${offset}px;
|
||||
margin-right: -${offset}px;
|
||||
${playerBox.attribute.bgStyle}
|
||||
`);
|
||||
}
|
||||
}
|
||||
|
||||
// Slide left
|
||||
else {
|
||||
offset = Math.abs(offset);
|
||||
playerBox.setCss(`
|
||||
// Slide left
|
||||
else {
|
||||
offset = Math.abs(offset);
|
||||
playerBox.setCss(`
|
||||
margin-left: -${offset}px;
|
||||
margin-right: ${offset}px;
|
||||
${playerBox.attribute.bgStyle}
|
||||
`);
|
||||
}
|
||||
}, 'drag-update')
|
||||
}
|
||||
},
|
||||
'drag-update')
|
||||
|
||||
.hook(gesture, (overlay) => {
|
||||
// Don't allow gesture when only one player
|
||||
if (overlay.attribute.list().length <= 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
overlay.attribute.dragging = false;
|
||||
const offset = gesture.get_offset()[1];
|
||||
.hook(gesture,
|
||||
/** @param {Overlay} overlay */
|
||||
(overlay) => {
|
||||
// Don't allow gesture when only one player
|
||||
if (overlay.attribute.list().length <= 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
const playerBox = overlay.attribute.list().at(-1);
|
||||
overlay.attribute.dragging = false;
|
||||
const offset = gesture.get_offset()[1];
|
||||
|
||||
// If crosses threshold after letting go, slide away
|
||||
if (offset && Math.abs(offset) > MAX_OFFSET) {
|
||||
// Disable inputs during animation
|
||||
widget.sensitive = false;
|
||||
const playerBox = overlay.attribute.list().at(-1);
|
||||
|
||||
// Slide away right
|
||||
if (offset >= 0) {
|
||||
playerBox.setCss(`
|
||||
// If crosses threshold after letting go, slide away
|
||||
if (offset && 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.attribute.bgStyle}
|
||||
`);
|
||||
}
|
||||
}
|
||||
|
||||
// Slide away left
|
||||
else {
|
||||
playerBox.setCss(`
|
||||
// Slide away left
|
||||
else {
|
||||
playerBox.setCss(`
|
||||
${TRANSITION}
|
||||
margin-left: -${OFFSCREEN}px;
|
||||
margin-right: ${OFFSCREEN}px;
|
||||
opacity: 0.7; ${playerBox.attribute.bgStyle}
|
||||
`);
|
||||
}
|
||||
|
||||
timeout(ANIM_DURATION, () => {
|
||||
// Put the player in the back after anim
|
||||
overlay.reorder_overlay(playerBox, 0);
|
||||
// Recenter player
|
||||
playerBox.setCss(playerBox.attribute.bgStyle);
|
||||
|
||||
widget.sensitive = true;
|
||||
|
||||
overlay.attribute.showTopOnly();
|
||||
});
|
||||
}
|
||||
|
||||
timeout(ANIM_DURATION, () => {
|
||||
// Put the player in the back after anim
|
||||
overlay.reorder_overlay(playerBox, 0);
|
||||
// Recenter player
|
||||
playerBox.setCss(playerBox.attribute.bgStyle);
|
||||
|
||||
widget.sensitive = true;
|
||||
|
||||
overlay.attribute.showTopOnly();
|
||||
});
|
||||
}
|
||||
else {
|
||||
// Recenter with transition for animation
|
||||
playerBox.setCss(`${TRANSITION}
|
||||
else {
|
||||
// Recenter with transition for animation
|
||||
playerBox.setCss(`${TRANSITION}
|
||||
${playerBox.attribute.bgStyle}`);
|
||||
}
|
||||
}, 'drag-end');
|
||||
}
|
||||
},
|
||||
'drag-end');
|
||||
},
|
||||
});
|
||||
|
||||
|
|
|
@ -5,11 +5,11 @@ import { EventBox } from 'resource:///com/github/Aylur/ags/widget.js';
|
|||
const { Gtk } = imports.gi;
|
||||
|
||||
|
||||
// TODO: wrap in another EventBox for disabled cursor
|
||||
/**
|
||||
* @typedef {import('types/widgets/eventbox').EventBoxProps} EventBox
|
||||
* @typedef {import('types/widgets/eventbox').EventBoxProps} EventBoxProps
|
||||
* @typedef {import('types/widgets/eventbox').default} EventBox
|
||||
*
|
||||
* @param {EventBox & {
|
||||
* @param {EventBoxProps & {
|
||||
* on_primary_click_release?: function(EventBox):void
|
||||
* }} o
|
||||
*/
|
||||
|
@ -23,22 +23,7 @@ export default ({
|
|||
const CanRun = Variable(true);
|
||||
const Disabled = Variable(false);
|
||||
|
||||
const widget = EventBox({
|
||||
...props,
|
||||
sensitive: Disabled.bind().transform((v) => !v),
|
||||
|
||||
on_primary_click_release: (self) => {
|
||||
// Every click, do a one shot connect to
|
||||
// CanRun to wait for location of click
|
||||
const id = CanRun.connect('changed', () => {
|
||||
if (CanRun.value) {
|
||||
on_primary_click_release(self);
|
||||
}
|
||||
|
||||
CanRun.disconnect(id);
|
||||
});
|
||||
},
|
||||
});
|
||||
let widget; // eslint-disable-line
|
||||
|
||||
const wrapper = EventBox({
|
||||
cursor: 'pointer',
|
||||
|
@ -55,14 +40,31 @@ export default ({
|
|||
},
|
||||
},
|
||||
|
||||
child: widget,
|
||||
|
||||
}).hook(Disabled, (self) => {
|
||||
self.cursor = Disabled.value ?
|
||||
'not-allowed' :
|
||||
'pointer';
|
||||
});
|
||||
|
||||
widget = EventBox({
|
||||
...props,
|
||||
sensitive: Disabled.bind().transform((v) => !v),
|
||||
|
||||
on_primary_click_release: () => {
|
||||
// Every click, do a one shot connect to
|
||||
// CanRun to wait for location of click
|
||||
const id = CanRun.connect('changed', () => {
|
||||
if (CanRun.value) {
|
||||
on_primary_click_release(wrapper);
|
||||
}
|
||||
|
||||
CanRun.disconnect(id);
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
wrapper.child = widget;
|
||||
|
||||
const gesture = Gtk.GestureLongPress.new(widget);
|
||||
|
||||
widget.hook(gesture, () => {
|
||||
|
|
|
@ -16,6 +16,7 @@ export const NotifPopups = () => PopupWindow({
|
|||
|
||||
const TOP_MARGIN = 6;
|
||||
|
||||
// FIXME: opens at wrong place
|
||||
export const NotifCenter = () => PopupWindow({
|
||||
name: 'notification-center',
|
||||
anchor: ['top', 'right'],
|
||||
|
|
|
@ -7,6 +7,7 @@ import PopupWindow from './misc/popup.js';
|
|||
import CursorBox from './misc/cursorbox.js';
|
||||
|
||||
|
||||
// FIXME: eventboxes are the wrong size
|
||||
const PowermenuWidget = () => CenterBox({
|
||||
class_name: 'powermenu',
|
||||
// @ts-expect-error
|
||||
|
|
Loading…
Reference in a new issue