diff --git a/devices/wim/config/ags/js/applauncher/main.js b/devices/wim/config/ags/js/applauncher/main.js index a741286..500e71c 100644 --- a/devices/wim/config/ags/js/applauncher/main.js +++ b/devices/wim/config/ags/js/applauncher/main.js @@ -1,6 +1,5 @@ import App from 'resource:///com/github/Aylur/ags/app.js'; import Applications from 'resource:///com/github/Aylur/ags/service/applications.js'; -import Hyprland from 'resource:///com/github/Aylur/ags/service/hyprland.js'; // TODO: find cleaner way to import this import { Fzf } from '../../node_modules/fzf/dist/fzf.es.js'; diff --git a/devices/wim/config/ags/js/bar/buttons/bluetooth.js b/devices/wim/config/ags/js/bar/buttons/bluetooth.js index 4c29603..07bd92f 100644 --- a/devices/wim/config/ags/js/bar/buttons/bluetooth.js +++ b/devices/wim/config/ags/js/bar/buttons/bluetooth.js @@ -1,4 +1,3 @@ -// @ts-expect-error import Bluetooth from 'resource:///com/github/Aylur/ags/service/bluetooth.js'; import { Label, Box, EventBox, Icon, Revealer } from 'resource:///com/github/Aylur/ags/widget.js'; @@ -11,8 +10,8 @@ const SPACING = 5; export default () => { const icon = Icon().hook(Bluetooth, (self) => { if (Bluetooth.enabled) { - self.icon = Bluetooth.connectedDevices[0] ? - Bluetooth.connectedDevices[0].iconName : + self.icon = Bluetooth.connected_devices[0] ? + Bluetooth.connected_devices[0].icon_name : 'bluetooth-active-symbolic'; } else { @@ -29,8 +28,8 @@ export default () => { Separator(SPACING), Label().hook(Bluetooth, (self) => { - self.label = Bluetooth.connectedDevices[0] ? - `${Bluetooth.connectedDevices[0]}` : + self.label = Bluetooth.connected_devices[0] ? + `${Bluetooth.connected_devices[0]}` : 'Disconnected'; }, 'notify::connected-devices'), ], diff --git a/devices/wim/config/ags/js/media-player/gesture.js b/devices/wim/config/ags/js/media-player/gesture.js index f206d07..1fbf110 100644 --- a/devices/wim/config/ags/js/media-player/gesture.js +++ b/devices/wim/config/ags/js/media-player/gesture.js @@ -70,113 +70,104 @@ export default ({ setup(self); self - .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(); - } + .hook(gesture, (_, realGesture) => { + if (realGesture) { + Array.from(self.attribute.list()) + .forEach((over) => { + over.visible = true; + }); + } + else { + self.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 (self.attribute.list().length <= 1) { + return; + } - overlay.attribute.dragging = true; - let offset = gesture.get_offset()[1]; - const playerBox = overlay.attribute.list().at(-1); + self.attribute.dragging = true; + let offset = gesture.get_offset()[1]; + const playerBox = self.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, - /** @param {Overlay} overlay */ - (overlay) => { - // Don't allow gesture when only one player - if (overlay.attribute.list().length <= 1) { - return; - } + .hook(gesture, () => { + // Don't allow gesture when only one player + if (self.attribute.list().length <= 1) { + return; + } - overlay.attribute.dragging = false; - const offset = gesture.get_offset()[1]; + self.attribute.dragging = false; + const offset = gesture.get_offset()[1]; - const playerBox = overlay.attribute.list().at(-1); + const playerBox = self.attribute.list().at(-1); - // If crosses threshold after letting go, slide away - if (offset && Math.abs(offset) > MAX_OFFSET) { - // Disable inputs during animation - widget.sensitive = false; + // 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(` + // 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(); - }); } - else { - // Recenter with transition for animation - playerBox.setCss(`${TRANSITION} + + timeout(ANIM_DURATION, () => { + // Put the player in the back after anim + self.reorder_overlay(playerBox, 0); + // Recenter player + playerBox.setCss(playerBox.attribute.bgStyle); + + widget.sensitive = true; + + self.attribute.showTopOnly(); + }); + } + else { + // Recenter with transition for animation + playerBox.setCss(`${TRANSITION} ${playerBox.attribute.bgStyle}`); - } - }, - 'drag-end'); + } + }, 'drag-end'); }, }); diff --git a/devices/wim/config/ags/js/osd/main.js b/devices/wim/config/ags/js/osd/main.js index 42d8c26..d7a4738 100644 --- a/devices/wim/config/ags/js/osd/main.js +++ b/devices/wim/config/ags/js/osd/main.js @@ -26,6 +26,7 @@ const OSDs = () => { }, }); + // Send reference of stack to all items stack.items = OSDList.map((osd, i) => [`${i}`, osd(stack)]); // Delay popup method so it diff --git a/devices/wim/config/ags/js/overview/clients.js b/devices/wim/config/ags/js/overview/clients.js index ade8db8..e802b29 100644 --- a/devices/wim/config/ags/js/overview/clients.js +++ b/devices/wim/config/ags/js/overview/clients.js @@ -7,7 +7,16 @@ import { timeout } from 'resource:///com/github/Aylur/ags/utils.js'; import { WindowButton } from './dragndrop.js'; import * as VARS from './variables.js'; +/** + * @typedef {import('types/service/hyprland.js').Client} Client + * @typedef {import('types/widgets/revealer').default} Revealer + * @typedef {import('types/widgets/box').default} Box + */ + +/** @param {number} size */ const scale = (size) => (size * VARS.SCALE) - VARS.MARGIN; + +/** @param {Client} client */ const getFontSize = (client) => { const valX = scale(client.size[0]) * VARS.ICON_SCALE; const valY = scale(client.size[1]) * VARS.ICON_SCALE; @@ -17,6 +26,7 @@ const getFontSize = (client) => { return size <= 0 ? 0.1 : size; }; +/** @param {Client} client */ const IconStyle = (client) => ` min-width: ${scale(client.size[0])}px; min-height: ${scale(client.size[1])}px; @@ -24,6 +34,12 @@ const IconStyle = (client) => ` `; +/** + * @param {Client} client + * @param {boolean} active + * @param {Array} clients + * @param {Box} box + */ const Client = (client, active, clients, box) => { const wsName = String(client.workspace.name).replace('special:', ''); const wsId = client.workspace.id; @@ -31,42 +47,40 @@ const Client = (client, active, clients, box) => { return Revealer({ transition: 'crossfade', + reveal_child: true, - setup: (rev) => { - rev.revealChild = true; + attribute: { + address: client.address, + to_destroy: false, }, - properties: [ - ['address', client.address], - ['toDestroy', false], - ], - child: WindowButton({ mainBox: box, address: client.address, - onSecondaryClickRelease: () => { + on_secondary_click_release: () => { Hyprland.sendMessage(`dispatch closewindow ${addr}`); }, - onPrimaryClickRelease: () => { + on_primary_click_release: () => { if (wsId < 0) { if (client.workspace.name === 'special') { Hyprland.sendMessage('dispatch ' + `movetoworkspacesilent special:${wsId},${addr}`) - .then( + .then(() => { Hyprland.sendMessage('dispatch ' + `togglespecialworkspace ${wsId}`) - .then( - () => App.closeWindow('overview'), - ).catch(print), - ).catch(print); + .then(() => { + App.closeWindow('overview'); + }).catch(print); + }).catch(print); } else { Hyprland.sendMessage('dispatch ' + - `togglespecialworkspace ${wsName}`).then( - () => App.closeWindow('overview'), - ).catch(print); + `togglespecialworkspace ${wsName}`) + .then(() => { + App.closeWindow('overview'); + }).catch(print); } } else { @@ -86,14 +100,15 @@ const Client = (client, active, clients, box) => { .catch(print); } - Hyprland.sendMessage(`dispatch focuswindow ${addr}`).then( - () => App.closeWindow('overview'), - ).catch(print); + Hyprland.sendMessage(`dispatch focuswindow ${addr}`) + .then(() => { + App.closeWindow('overview'); + }).catch(print); } }, child: Icon({ - className: `window ${active}`, + class_name: `window ${active ? 'active' : ''}`, css: `${IconStyle(client)} font-size: 10px;`, icon: client.class, }), @@ -101,69 +116,79 @@ const Client = (client, active, clients, box) => { }); }; +/** @param {Box} box */ export const updateClients = (box) => { Hyprland.sendMessage('j/clients').then((out) => { - const clients = JSON.parse(out).filter((client) => client.class); + /** @type Array */ + let clients = JSON.parse(out); - box._workspaces.forEach((workspace) => { - const fixed = workspace.getFixed(); - const toRemove = fixed.get_children(); + clients = clients.filter((client) => client.class); - clients.filter((client) => client.workspace.id === workspace._id) - .forEach((client) => { - let active = ''; + box.attribute.workspaces.forEach( + /** @param {Revealer} workspace */ + (workspace) => { + const fixed = workspace.attribute.get_fixed(); + /** @type Array */ + const toRemove = fixed.get_children(); - if (client.address === Hyprland.active.client.address) { - active = 'active'; - } + clients.filter((client) => + client.workspace.id === workspace.attribute.id) + .forEach((client) => { + const active = + client.address === Hyprland.active.client.address; - // TODO: fix multi monitor issue. this is just a temp fix - client.at[1] -= 2920; + // TODO: fix multi monitor issue. this is just a temp fix + client.at[1] -= 2920; - // Special workspaces that haven't been opened yet - // return a size of 0. We need to set them to default - // values to show the workspace properly - if (client.size[0] === 0) { - client.size[0] = VARS.DEFAULT_SPECIAL.SIZE_X; - client.size[1] = VARS.DEFAULT_SPECIAL.SIZE_Y; - client.at[0] = VARS.DEFAULT_SPECIAL.POS_X; - client.at[1] = VARS.DEFAULT_SPECIAL.POS_Y; - } + // Special workspaces that haven't been opened yet + // return a size of 0. We need to set them to default + // values to show the workspace properly + if (client.size[0] === 0) { + client.size[0] = VARS.DEFAULT_SPECIAL.SIZE_X; + client.size[1] = VARS.DEFAULT_SPECIAL.SIZE_Y; + client.at[0] = VARS.DEFAULT_SPECIAL.POS_X; + client.at[1] = VARS.DEFAULT_SPECIAL.POS_Y; + } - const newClient = [ - fixed.get_children() - .find((ch) => ch._address === client.address), - client.at[0] * VARS.SCALE, - client.at[1] * VARS.SCALE, - ]; + const newClient = [ + fixed.get_children().find( + /** @param {typeof WindowButton} ch */ + // @ts-expect-error + (ch) => ch.attribute.address === client.address, + ), + client.at[0] * VARS.SCALE, + client.at[1] * VARS.SCALE, + ]; - // If it exists already - if (newClient[0]) { - toRemove.splice(toRemove.indexOf(newClient[0]), 1); - fixed.move(...newClient); + // If it exists already + if (newClient[0]) { + toRemove.splice(toRemove.indexOf(newClient[0]), 1); + fixed.move(...newClient); + } + else { + newClient[0] = Client(client, active, clients, box); + fixed.put(...newClient); + } + + // Set a timeout here to have an animation when the icon first appears + timeout(1, () => { + newClient[0].child.child.className = + `window ${active}`; + newClient[0].child.child.setCss(IconStyle(client)); + }); + }); + + fixed.show_all(); + toRemove.forEach((ch) => { + if (ch.attribute.to_destroy) { + ch.destroy(); } else { - newClient[0] = Client(client, active, clients, box); - fixed.put(...newClient); + ch.reveal_child = false; + ch.attribute.to_destroy = true; } - - // Set a timeout here to have an animation when the icon first appears - timeout(1, () => { - newClient[0].child.child.className = `window ${active}`; - newClient[0].child.child.setCss(IconStyle(client)); - }); }); - - fixed.show_all(); - toRemove.forEach((ch) => { - if (ch._toDestroy) { - ch.destroy(); - } - else { - ch.revealChild = false; - ch._toDestroy = true; - } - }); - }); + }, + ); }).catch(print); }; diff --git a/devices/wim/config/ags/js/overview/current-workspace.js b/devices/wim/config/ags/js/overview/current-workspace.js index c654d18..a6537fb 100644 --- a/devices/wim/config/ags/js/overview/current-workspace.js +++ b/devices/wim/config/ags/js/overview/current-workspace.js @@ -11,23 +11,39 @@ const DEFAULT_STYLE = ` border-radius: 10px; `; +/** + * @typedef {import('types/widgets/box').default} Box + * @typedef {import('types/widgets/revealer').default} Revealer + */ + export const Highlighter = () => Box({ vpack: 'start', hpack: 'start', - className: 'workspace active', + class_name: 'workspace active', css: DEFAULT_STYLE, }); +/** + * @param {Box} main + * @param {Box} highlighter + */ export const updateCurrentWorkspace = (main, highlighter) => { const currentId = Hyprland.active.workspace.id; const row = Math.floor((currentId - 1) / VARS.WORKSPACE_PER_ROW); + // @ts-expect-error const rowObject = main.children[0].children[row]; const workspaces = rowObject.child.centerWidget.child - .get_children().filter((w) => w.revealChild); + .get_children().filter( + /** @param {Revealer} w */ + (w) => w.reveal_child, + ); - const currentIndex = workspaces.findIndex((w) => w._id === currentId); + const currentIndex = workspaces.findIndex( + /** @param {Revealer} w */ + (w) => w.attribute.id === currentId, + ); const left = currentIndex * ((VARS.SCREEN.X * VARS.SCALE) + PADDING); const height = row * ((VARS.SCREEN.Y * VARS.SCALE) + (PADDING / 2)); diff --git a/devices/wim/config/ags/js/overview/dragndrop.js b/devices/wim/config/ags/js/overview/dragndrop.js index 73b0841..e841c6d 100644 --- a/devices/wim/config/ags/js/overview/dragndrop.js +++ b/devices/wim/config/ags/js/overview/dragndrop.js @@ -9,7 +9,15 @@ import { updateClients } from './clients.js'; const TARGET = [Gtk.TargetEntry.new('text/plain', Gtk.TargetFlags.SAME_APP, 0)]; +/** + * @typedef {import('types/widgets/button').default} Button + * @typedef {import('types/widgets/button').ButtonProps} ButtonProps + * @typedef {import('types/widgets/eventbox').EventBoxProps=} EventBoxProps + * @typedef {import('types/widgets/box').default} Box + */ + +/** @param {Button} widget */ const createSurfaceFromWidget = (widget) => { const alloc = widget.get_allocation(); const surface = new Cairo.ImageSurface( @@ -29,16 +37,19 @@ const createSurfaceFromWidget = (widget) => { let hidden = 0; -export const WorkspaceDrop = (props) => EventBox({ +/** @params {EventBoxProps} props */ +export const WorkspaceDrop = ({ ...props }) => EventBox({ ...props, 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; + // @ts-expect-error + let id = self.get_parent()?.attribute.id; if (id < -1) { - id = self.get_parent()._name; + // @ts-expect-error + id = self.get_parent()?.attribute.name; } else if (id === -1) { @@ -56,11 +67,17 @@ export const WorkspaceDrop = (props) => EventBox({ }, }); +/** + * @param {ButtonProps & { + * address: string + * mainBox: Box + * }} o + */ export const WindowButton = ({ address, mainBox, ...props -} = {}) => Button({ +}) => Button({ ...props, cursor: 'pointer', @@ -78,11 +95,12 @@ export const WindowButton = ({ self.on('drag-begin', (_, context) => { Gtk.drag_set_icon_surface(context, createSurfaceFromWidget(self)); - self.get_parent().revealChild = false; + // @ts-expect-error + self.get_parent()?.set_reveal_child(false); }); self.on('drag-end', () => { - self.get_parent().destroy(); + self.get_parent()?.destroy(); updateClients(mainBox); }); diff --git a/devices/wim/config/ags/js/overview/main.js b/devices/wim/config/ags/js/overview/main.js index 1047599..9c7ab39 100644 --- a/devices/wim/config/ags/js/overview/main.js +++ b/devices/wim/config/ags/js/overview/main.js @@ -9,21 +9,30 @@ import { Highlighter, updateCurrentWorkspace } from './current-workspace.js'; import { updateClients } from './clients.js'; - - // TODO: have a 'page' for each monitor, arrows on both sides to loop through export const Overview = () => { const highlighter = Highlighter(); const mainBox = Box({ // Do this for scss hierarchy - className: 'overview', + class_name: 'overview', css: 'all: unset', vertical: true, vpack: 'center', hpack: 'center', + attribute: { + workspaces: [], + + update: () => { + getWorkspaces(mainBox); + updateWorkspaces(mainBox); + updateClients(mainBox); + updateCurrentWorkspace(mainBox, highlighter); + }, + }, + children: [ Box({ vertical: true, @@ -42,31 +51,24 @@ export const Overview = () => { setup: (self) => { self.hook(Hyprland, () => { - if (!App.getWindow('overview').visible) { + if (!App.getWindow('overview')?.visible) { return; } - self.update(); + self?.attribute.update(); }); }, - - properties: [ - ['workspaces'], - ], }); - mainBox.update = () => { - getWorkspaces(mainBox); - updateWorkspaces(mainBox); - updateClients(mainBox); - updateCurrentWorkspace(mainBox, highlighter); - }; - const widget = Overlay({ overlays: [highlighter, mainBox], + attribute: { + get_child: () => mainBox, + }, + child: Box({ - className: 'overview', + class_name: 'overview', css: ` min-height: ${mainBox.get_allocated_height()}px; min-width: ${mainBox.get_allocated_width()}px; @@ -77,6 +79,7 @@ export const Overview = () => { setup: (self) => { self.on('get-child-position', (_, ch) => { if (ch === mainBox) { + // @ts-expect-error self.child.setCss(` transition: min-height 0.2s ease, min-width 0.2s ease; min-height: ${mainBox.get_allocated_height()}px; @@ -87,8 +90,6 @@ export const Overview = () => { }, }); - widget.getChild = () => mainBox; - return widget; }; @@ -99,7 +100,7 @@ export default () => { close_on_unfocus: 'none', onOpen: () => { win.attribute.set_child(Overview()); - win.attribute.get_child().getChild().update(); + win.attribute.get_child().attribute.get_child().attribute.update(); }, }); diff --git a/devices/wim/config/ags/js/overview/workspaces.js b/devices/wim/config/ags/js/overview/workspaces.js index e6e9349..24612b3 100644 --- a/devices/wim/config/ags/js/overview/workspaces.js +++ b/devices/wim/config/ags/js/overview/workspaces.js @@ -10,42 +10,69 @@ const DEFAULT_STYLE = ` min-height: ${VARS.SCREEN.Y * VARS.SCALE}px; `; +/** + * @typedef {import('types/widgets/box').default} Box + * @typedef {import('types/widgets/revealer').default} Revealer + */ + +/** @param {Box} box */ export const getWorkspaces = (box) => { const children = []; box.children.forEach((type) => { - type.children.forEach((row) => { - row.child.centerWidget.child.children.forEach((ch) => { - children.push(ch); - }); - }); + // @ts-expect-error + type.children.forEach( + /** @param {Revealer} row */ + (row) => { + // @ts-expect-error + row.child.centerWidget.child.children.forEach( + /** @param {Revealer} workspace */ + (workspace) => { + children.push(workspace); + }, + ); + }, + ); }); - box._workspaces = children.sort((a, b) => a._id - b._id); + box.attribute.workspaces = children.sort((a, b) => + a.attribute.id - b.attribute.id); }; +/** + * @param {number} id + * @param {string} name + * @param {boolean} normal + */ const Workspace = (id, name, normal = true) => { const fixed = Fixed(); const workspace = Revealer({ transition: 'slide_right', - transitionDuration: 500, + transition_duration: 500, + + attribute: { + id, + name, + get_fixed: () => fixed, + }, setup: (self) => { if (normal) { self.hook(Hyprland, () => { const activeId = Hyprland.active.workspace.id; - const active = activeId === self._id; + const active = activeId === self.attribute.id; + const ws = Hyprland.getWorkspace(self.attribute.id); - self.revealChild = Hyprland.getWorkspace(self._id) - ?.windows > 0 || active; + self.reveal_child = + (ws?.windows && ws.windows > 0) || active; }); } }, child: WorkspaceDrop({ child: Box({ - className: 'workspace', + class_name: 'workspace', css: normal ? DEFAULT_STYLE : @@ -70,23 +97,23 @@ const Workspace = (id, name, normal = true) => { }), }); - workspace._id = id; - workspace._name = name; - workspace.getFixed = () => fixed; - return workspace; }; -export const WorkspaceRow = (className, i) => { +/** + * @param {string} class_name + * @param {number} i + */ +export const WorkspaceRow = (class_name, i) => { const addWorkspace = Workspace( - className === 'special' ? -1 : 1000, - className === 'special' ? 'special' : '', + class_name === 'special' ? -1 : 1000, + class_name === 'special' ? 'special' : '', false, ); return Revealer({ transition: 'slide_down', - hpack: className === 'special' ? '' : 'start', + hpack: class_name === 'special' ? 'fill' : 'start', setup: (self) => { self.hook(Hyprland, (rev) => { @@ -101,18 +128,18 @@ export const WorkspaceRow = (className, i) => { return isInRow && (hasClients || isActive); }); - rev.revealChild = rowExists; + rev.reveal_child = rowExists; }); }, child: CenterBox({ - children: [null, EventBox({ + center_widget: EventBox({ setup: (self) => { self.hook(Hyprland, () => { const maxId = (i + 1) * VARS.WORKSPACE_PER_ROW; const activeId = Hyprland.active.workspace.id; - const isSpecial = className === 'special'; + const isSpecial = class_name === 'special'; const nextRowExists = Hyprland.workspaces.some((ws) => { const isInNextRow = ws.id > maxId; const hasClients = ws.windows > 0; @@ -121,22 +148,26 @@ export const WorkspaceRow = (className, i) => { return isInNextRow && (hasClients || isActive); }); - addWorkspace.revealChild = isSpecial || !nextRowExists; + addWorkspace.reveal_child = isSpecial || !nextRowExists; }); }, child: Box({ - className, + class_name, children: [addWorkspace], }), - }), null], + }), }), }); }; +/** @param {Box} box */ export const updateWorkspaces = (box) => { Hyprland.workspaces.forEach((ws) => { - const currentWs = box._workspaces.find((ch) => ch._id === ws.id); + const currentWs = box.attribute.workspaces.find( + /** @param {Revealer} ch */ + (ch) => ch.attribute.id === ws.id, + ); if (!currentWs) { let type = 0; @@ -148,16 +179,19 @@ export const updateWorkspaces = (box) => { } else { rowNo = Math.floor((ws.id - 1) / VARS.WORKSPACE_PER_ROW); + // @ts-expect-error const wsQty = box.children[type].children.length; if (rowNo >= wsQty) { for (let i = wsQty; i <= rowNo; ++i) { + // @ts-expect-error box.children[type].add(WorkspaceRow( type ? 'special' : 'normal', i, )); } } } + // @ts-expect-error const row = box.children[type].children[rowNo] .child.centerWidget.child; @@ -166,8 +200,15 @@ export const updateWorkspaces = (box) => { }); // Make sure the order is correct - box._workspaces.forEach((workspace, i) => { - workspace.get_parent().reorder_child(workspace, i); - }); + box.attribute.workspaces.forEach( + /** + * @param {Revealer} workspace + * @param {number} i + */ + (workspace, i) => { + // @ts-expect-error + workspace?.get_parent()?.reorder_child(workspace, i); + }, + ); box.show_all(); }; diff --git a/devices/wim/config/ags/js/powermenu.js b/devices/wim/config/ags/js/powermenu.js index 0ad9dff..4947a20 100644 --- a/devices/wim/config/ags/js/powermenu.js +++ b/devices/wim/config/ags/js/powermenu.js @@ -13,7 +13,7 @@ const PowermenuWidget = () => CenterBox({ // @ts-expect-error vertical: false, - startWidget: CursorBox({ + start_widget: CursorBox({ class_name: 'shutdown', on_primary_click_release: () => execAsync(['systemctl', 'poweroff']) .catch(print), @@ -23,7 +23,7 @@ const PowermenuWidget = () => CenterBox({ }), }), - centerWidget: CursorBox({ + center_widget: CursorBox({ class_name: 'reboot', on_primary_click_release: () => execAsync(['systemctl', 'reboot']) .catch(print), @@ -33,7 +33,7 @@ const PowermenuWidget = () => CenterBox({ }), }), - endWidget: CursorBox({ + end_widget: CursorBox({ class_name: 'logout', on_primary_click_release: () => Hyprland.sendMessage('dispatch exit') .catch(print), diff --git a/devices/wim/config/ags/js/quick-settings/bluetooth.js b/devices/wim/config/ags/js/quick-settings/bluetooth.js index 8785ef6..27cacd3 100644 --- a/devices/wim/config/ags/js/quick-settings/bluetooth.js +++ b/devices/wim/config/ags/js/quick-settings/bluetooth.js @@ -8,56 +8,62 @@ import CursorBox from '../misc/cursorbox.js'; const SCROLL_THRESH_H = 200; const SCROLL_THRESH_N = 7; +/** + * @typedef {import('types/widgets/box').default} Box + * @typedef {import('types/service/bluetooth').BluetoothDevice} BluetoothDevice + */ -const BluetoothDevice = (dev) => { - const widget = Box({ - className: 'menu-item', - }); +/** @param {BluetoothDevice} dev */ +const BluetoothDevice = (dev) => Box({ + class_name: 'menu-item', - const child = Box({ - hexpand: true, - children: [ - Icon({ - binds: [['icon', dev, 'icon-name']], - }), + attribute: { dev }, - Label({ - binds: [['label', dev, 'name']], - }), - - Icon({ - icon: 'object-select-symbolic', - hexpand: true, - hpack: 'end', - setup: (self) => { - self.hook(dev, () => { - self.setCss(`opacity: ${dev.paired ? '1' : '0'};`); - }); - }, - }), - ], - }); - - widget.dev = dev; - widget.add(Revealer({ - revealChild: true, + children: [Revealer({ + reveal_child: true, transition: 'slide_down', + child: CursorBox({ on_primary_click_release: () => dev.setConnection(true), - child, - }), - })); - return widget; -}; + child: Box({ + hexpand: true, + + children: [ + Icon({ + icon: dev.bind('icon_name'), + }), + + Label({ + label: dev.bind('name'), + }), + + Icon({ + icon: 'object-select-symbolic', + hexpand: true, + hpack: 'end', + + }).hook(dev, (self) => { + self.setCss(`opacity: ${dev.paired ? + '1' : + '0'}; + `); + }), + ], + }), + }), + })], +}); export const BluetoothMenu = () => { const DevList = new Map(); + const topArrow = Revealer({ transition: 'slide_down', + child: Icon({ icon: `${App.configDir }/icons/down-large.svg`, - className: 'scrolled-indicator', + class_name: 'scrolled-indicator', size: 16, css: '-gtk-icon-transform: rotate(180deg);', }), @@ -65,15 +71,17 @@ export const BluetoothMenu = () => { const bottomArrow = Revealer({ transition: 'slide_up', + child: Icon({ icon: `${App.configDir }/icons/down-large.svg`, - className: 'scrolled-indicator', + class_name: 'scrolled-indicator', size: 16, }), }); return Overlay({ pass_through: true, + overlays: [ Box({ vpack: 'start', @@ -91,7 +99,7 @@ export const BluetoothMenu = () => { ], child: Box({ - className: 'menu', + class_name: 'menu', child: Scrollable({ hscroll: 'never', @@ -101,28 +109,36 @@ export const BluetoothMenu = () => { self.on('edge-reached', (_, pos) => { // Manage scroll indicators if (pos === 2) { - topArrow.revealChild = false; - bottomArrow.revealChild = true; + topArrow.reveal_child = false; + bottomArrow.reveal_child = true; } else if (pos === 3) { - topArrow.revealChild = true; - bottomArrow.revealChild = false; + topArrow.reveal_child = true; + bottomArrow.reveal_child = false; } }); }, child: ListBox({ setup: (self) => { - self.set_sort_func((a, b) => { - return b.get_children()[0].dev.paired - - a.get_children()[0].dev.paired; - }); + // @ts-expect-error + self.set_sort_func( + /** + * @param {Box} a + * @param {Box} b + */ + (a, b) => { + // @ts-expect-error + return b.get_children()[0].attribute.dev.paired - // eslint-disable-line + // @ts-expect-error + a.get_children()[0].attribute.dev.paired; + }, + ); self.hook(Bluetooth, () => { // Get all devices - const Devices = [].concat( - Bluetooth.devices, - Bluetooth.connectedDevices, + const Devices = Bluetooth.devices.concat( + Bluetooth.connected_devices, ); // Add missing devices @@ -130,6 +146,7 @@ export const BluetoothMenu = () => { if (!DevList.has(dev) && dev.name) { DevList.set(dev, BluetoothDevice(dev)); + // @ts-expect-error self.add(DevList.get(dev)); self.show_all(); } @@ -151,7 +168,7 @@ export const BluetoothMenu = () => { } else { devWidget.children[0] - .revealChild = false; + .reveal_child = false; devWidget.toDestroy = true; } } @@ -160,34 +177,48 @@ export const BluetoothMenu = () => { // Start scrolling after a specified height // is reached by the children const height = Math.max( - self.get_parent().get_allocated_height(), + self.get_parent()?.get_allocated_height() || 0, SCROLL_THRESH_H, ); - const scroll = self.get_parent().get_parent(); + const scroll = self.get_parent()?.get_parent(); - if (self.get_children().length > SCROLL_THRESH_N) { - scroll.vscroll = 'always'; - scroll.setCss(`min-height: ${height}px;`); + if (scroll) { + // @ts-expect-error + const n_child = self.get_children().length; - // Make bottom scroll indicator appear only - // when first getting overflowing children - if (!(bottomArrow.revealChild === true || - topArrow.revealChild === true)) { - bottomArrow.revealChild = true; + if (n_child > SCROLL_THRESH_N) { + // @ts-expect-error + scroll.vscroll = 'always'; + // @ts-expect-error + scroll.setCss(`min-height: ${height}px;`); + + // Make bottom scroll indicator appear only + // when first getting overflowing children + if (!(bottomArrow.reveal_child === true || + topArrow.reveal_child === true)) { + bottomArrow.reveal_child = true; + } + } + else { + // @ts-expect-error + scroll.vscroll = 'never'; + // @ts-expect-error + scroll.setCss(''); + topArrow.reveal_child = false; + bottomArrow.reveal_child = false; } - } - else { - scroll.vscroll = 'never'; - scroll.setCss(''); - topArrow.revealChild = false; - bottomArrow.revealChild = false; } // Trigger sort_func - self.get_children().forEach((ch) => { - ch.changed(); - }); + // @ts-expect-error + self.get_children().forEach( + /** @param {Box} ListBoxRow */ + (ListBoxRow) => { + // @ts-expect-error + ListBoxRow.changed(); + }, + ); }); }, }), diff --git a/devices/wim/config/ags/js/quick-settings/button-grid.js b/devices/wim/config/ags/js/quick-settings/button-grid.js index 57e9137..70828ea 100644 --- a/devices/wim/config/ags/js/quick-settings/button-grid.js +++ b/devices/wim/config/ags/js/quick-settings/button-grid.js @@ -1,5 +1,4 @@ import App from 'resource:///com/github/Aylur/ags/app.js'; -// @ts-expect-error import Bluetooth from 'resource:///com/github/Aylur/ags/service/bluetooth.js'; import Network from 'resource:///com/github/Aylur/ags/service/network.js'; import Variable from 'resource:///com/github/Aylur/ags/variable.js'; @@ -17,16 +16,23 @@ import { BluetoothMenu } from './bluetooth.js'; const SPACING = 28; const ButtonStates = []; -/** @typedef {import('types/widgets/widget').default} Widget */ +/** + * @typedef {import('types/widgets/widget').default} Widget + * @typedef {import('types/widgets/box').default} Box + * @typedef {import('types/widgets/icon').default} Icon + * @typedef {import('types/widgets/label').default} Label + * @typedef {import('types/widgets/revealer').default} Revealer + * @typedef {[any, function, (string|undefined)?]} BindTuple + */ /** * @param {{ * command?: function * secondary_command?: function - * onOpen?: function(Widget):void - * icon: any - * indicator?: any + * onOpen?: function(Revealer):void + * icon: string|BindTuple + * indicator?: BindTuple * menu?: any * }} o */ @@ -41,10 +47,13 @@ const GridButton = ({ const Activated = Variable(false); ButtonStates.push(Activated); + let iconWidget; + /** @type Label */ + let indicatorWidget = Label(); // Allow setting icon dynamically or statically if (typeof icon === 'string') { - icon = Icon({ + iconWidget = Icon({ class_name: 'grid-label', icon, setup: (self) => { @@ -56,11 +65,12 @@ const GridButton = ({ }, }); } - else { - icon = Icon({ + else if (Array.isArray(icon)) { + iconWidget = Icon({ class_name: 'grid-label', setup: (self) => { self + // @ts-expect-error .hook(...icon) .hook(Activated, () => { self.setCss(`color: ${Activated.value ? @@ -72,12 +82,13 @@ const GridButton = ({ } if (indicator) { - indicator = Label({ + indicatorWidget = Label({ class_name: 'sub-label', justification: 'left', truncate: 'end', - maxWidthChars: 12, + max_width_chars: 12, setup: (self) => { + // @ts-expect-error self.hook(...indicator); }, }); @@ -87,7 +98,7 @@ const GridButton = ({ menu = Revealer({ transition: 'slide_down', child: menu, - binds: [['revealChild', Activated, 'value']], + reveal_child: Activated.bind(), }); } @@ -110,7 +121,7 @@ const GridButton = ({ } }, - child: icon, + child: iconWidget, }), CursorBox({ @@ -131,10 +142,13 @@ const GridButton = ({ self.get_parent() ?.get_parent()?.get_parent() ?.get_parent()?.get_parent() + // @ts-expect-error ?.children[1]; - const isSetup = rowMenu.get_children() - .find((ch) => ch === menu); + const isSetup = rowMenu.get_children().find( + /** @param {Box} ch */ + (ch) => ch === menu, + ); if (!isSetup) { rowMenu.add(menu); @@ -165,14 +179,14 @@ const GridButton = ({ ], }), - indicator, + indicatorWidget, ], }); return widget; }; -const Row = ({ buttons } = {}) => { +const Row = ({ buttons }) => { const widget = Box({ vertical: true, @@ -188,10 +202,13 @@ const Row = ({ buttons } = {}) => { for (let i = 0; i < buttons.length; ++i) { if (i === buttons.length - 1) { + // @ts-expect-error widget.children[0].add(buttons[i]); } else { + // @ts-expect-error widget.children[0].add(buttons[i]); + // @ts-expect-error widget.children[0].add(Separator(SPACING)); } } @@ -209,13 +226,17 @@ const FirstRow = () => Row({ // TODO: connection editor }, - icon: [Network, (icon) => { - icon.icon = Network.wifi?.iconName; - }], + icon: [Network, + /** @param {Icon} self */ + (self) => { + self.icon = Network.wifi?.icon_name; + }], - indicator: [Network, (self) => { - self.label = Network.wifi?.ssid || Network.wired?.internet; - }], + indicator: [Network, + /** @param {Label} self */ + (self) => { + self.label = Network.wifi?.ssid || Network.wired?.internet; + }], menu: NetworkMenu(), onOpen: () => Network.wifi.scan(), @@ -241,26 +262,30 @@ const FirstRow = () => Row({ // TODO: bluetooth connection editor }, - icon: [Bluetooth, (self) => { - if (Bluetooth.enabled) { - self.icon = Bluetooth.connectedDevices[0] ? - Bluetooth.connectedDevices[0].iconName : - 'bluetooth-active-symbolic'; - } - else { - self.icon = 'bluetooth-disabled-symbolic'; - } - }], + icon: [Bluetooth, + /** @param {Icon} self */ + (self) => { + if (Bluetooth.enabled) { + self.icon = Bluetooth.connected_devices[0] ? + Bluetooth.connected_devices[0].icon_name : + 'bluetooth-active-symbolic'; + } + else { + self.icon = 'bluetooth-disabled-symbolic'; + } + }], - indicator: [Bluetooth, (self) => { - self.label = Bluetooth.connectedDevices[0] ? - `${Bluetooth.connectedDevices[0]}` : - 'Disconnected'; - }, 'notify::connected-devices'], + indicator: [Bluetooth, + /** @param {Label} self */ + (self) => { + self.label = Bluetooth.connected_devices[0] ? + `${Bluetooth.connected_devices[0]}` : + 'Disconnected'; + }, 'notify::connected-devices'], menu: BluetoothMenu(), onOpen: (menu) => { - execAsync(`bluetoothctl scan ${menu.revealChild ? + execAsync(`bluetoothctl scan ${menu.reveal_child ? 'on' : 'off'}`).catch(print); }, @@ -282,9 +307,11 @@ const SecondRow = () => Row({ .catch(print); }, - icon: [SpeakerIcon, (self) => { - self.icon = SpeakerIcon.value; - }], + icon: [SpeakerIcon, + /** @param {Icon} self */ + (self) => { + self.icon = SpeakerIcon.value; + }], }), GridButton({ @@ -298,9 +325,11 @@ const SecondRow = () => Row({ .catch(print); }, - icon: [MicIcon, (self) => { - self.icon = MicIcon.value; - }], + icon: [MicIcon, + /** @param {Icon} self */ + (self) => { + self.icon = MicIcon.value; + }], }), GridButton({ diff --git a/devices/wim/config/ags/js/quick-settings/main.js b/devices/wim/config/ags/js/quick-settings/main.js index 7873dbb..1be90c5 100644 --- a/devices/wim/config/ags/js/quick-settings/main.js +++ b/devices/wim/config/ags/js/quick-settings/main.js @@ -14,18 +14,18 @@ const QuickSettingsWidget = () => { }); return Box({ - className: 'qs-container', + class_name: 'qs-container', vertical: true, children: [ Box({ - className: 'quick-settings', + class_name: 'quick-settings', vertical: true, children: [ Label({ label: 'Control Center', - className: 'title', + class_name: 'title', hpack: 'start', css: ` margin-left: 20px; diff --git a/devices/wim/config/ags/js/quick-settings/network.js b/devices/wim/config/ags/js/quick-settings/network.js index 2895420..89be5b3 100644 --- a/devices/wim/config/ags/js/quick-settings/network.js +++ b/devices/wim/config/ags/js/quick-settings/network.js @@ -10,42 +10,41 @@ import CursorBox from '../misc/cursorbox.js'; const SCROLL_THRESH_H = 200; const SCROLL_THRESH_N = 7; +/** @typedef {import('types/widgets/box').default} Box */ + +/** @param {any} ap */ const AccessPoint = (ap) => { const widget = Box({ - className: 'menu-item', + class_name: 'menu-item', + attribute: { + ap: Variable(ap), + }, }); - widget.ap = Variable(ap); const child = Box({ hexpand: true, children: [ - Icon({ - setup: (self) => { - self.hook(widget.ap, () => { - self.icon = widget.ap.value.iconName; - }); - }, + Icon().hook(widget.attribute.ap, (self) => { + self.icon = widget.attribute.ap.value.iconName; }), - Label({ - setup: (self) => { - self.hook(widget.ap, () => { - self.label = widget.ap.value.ssid || ''; - }); - }, + Label().hook(widget.attribute.ap, (self) => { + self.label = widget.attribute.ap.value.ssid || ''; }), Icon({ icon: 'object-select-symbolic', hexpand: true, hpack: 'end', + setup: (self) => { self.hook(Network, () => { self.setCss( `opacity: ${ - widget.ap.value.ssid === Network.wifi.ssid ? + widget.attribute.ap.value.ssid === + Network.wifi.ssid ? '1' : '0' }; @@ -58,12 +57,13 @@ const AccessPoint = (ap) => { }); widget.add(Revealer({ - revealChild: true, + reveal_child: true, transition: 'slide_down', + child: CursorBox({ on_primary_click_release: () => { execAsync(`nmcli device wifi connect - ${widget.ap.value.bssid}`).catch(print); + ${widget.attribute.ap.value.bssid}`).catch(print); }, child, }), @@ -74,11 +74,13 @@ const AccessPoint = (ap) => { export const NetworkMenu = () => { const APList = new Map(); + const topArrow = Revealer({ transition: 'slide_down', + child: Icon({ icon: `${App.configDir }/icons/down-large.svg`, - className: 'scrolled-indicator', + class_name: 'scrolled-indicator', size: 16, css: '-gtk-icon-transform: rotate(180deg);', }), @@ -86,15 +88,17 @@ export const NetworkMenu = () => { const bottomArrow = Revealer({ transition: 'slide_up', + child: Icon({ icon: `${App.configDir }/icons/down-large.svg`, - className: 'scrolled-indicator', + class_name: 'scrolled-indicator', size: 16, }), }); return Overlay({ pass_through: true, + overlays: [ Box({ vpack: 'start', @@ -112,7 +116,7 @@ export const NetworkMenu = () => { ], child: Box({ - className: 'menu', + class_name: 'menu', child: Scrollable({ hscroll: 'never', @@ -122,22 +126,32 @@ export const NetworkMenu = () => { self.on('edge-reached', (_, pos) => { // Manage scroll indicators if (pos === 2) { - topArrow.revealChild = false; - bottomArrow.revealChild = true; + topArrow.reveal_child = false; + bottomArrow.reveal_child = true; } else if (pos === 3) { - topArrow.revealChild = true; - bottomArrow.revealChild = false; + topArrow.reveal_child = true; + bottomArrow.reveal_child = false; } }); }, child: ListBox({ setup: (self) => { - self.set_sort_func((a, b) => { - return b.get_children()[0].ap.value.strength - - a.get_children()[0].ap.value.strength; - }); + // @ts-expect-error + self.set_sort_func( + /** + * @param {Box} a + * @param {Box} b + */ + (a, b) => { + return b.get_children()[0] + // @ts-expect-error + .attribute.ap.value.strength - + // @ts-expect-error + a.get_children()[0].attribute.ap.value.strength; + }, + ); self.hook(Network, () => { // Add missing APs @@ -145,15 +159,17 @@ export const NetworkMenu = () => { if (ap.ssid !== 'Unknown') { if (APList.has(ap.ssid)) { const accesPoint = APList.get(ap.ssid) - .ap.value; + .attribute.ap.value; if (accesPoint.strength < ap.strength) { - APList.get(ap.ssid).ap.value = ap; + APList.get(ap.ssid).attribute + .ap.value = ap; } } else { APList.set(ap.ssid, AccessPoint(ap)); + // @ts-expect-error self.add(APList.get(ap.ssid)); self.show_all(); } @@ -176,7 +192,7 @@ export const NetworkMenu = () => { } else { apWidget.children[0] - .revealChild = false; + .reveal_child = false; apWidget.toDestroy = true; } } @@ -185,34 +201,48 @@ export const NetworkMenu = () => { // Start scrolling after a specified height // is reached by the children const height = Math.max( - self.get_parent().get_allocated_height(), + self.get_parent()?.get_allocated_height() || 0, SCROLL_THRESH_H, ); - const scroll = self.get_parent().get_parent(); + const scroll = self.get_parent()?.get_parent(); - if (self.get_children().length > SCROLL_THRESH_N) { - scroll.vscroll = 'always'; - scroll.setCss(`min-height: ${height}px;`); + if (scroll) { + // @ts-expect-error + const n_child = self.get_children().length; - // Make bottom scroll indicator appear only - // when first getting overflowing children - if (!(bottomArrow.revealChild === true || - topArrow.revealChild === true)) { - bottomArrow.revealChild = true; + if (n_child > SCROLL_THRESH_N) { + // @ts-expect-error + scroll.vscroll = 'always'; + // @ts-expect-error + scroll.setCss(`min-height: ${height}px;`); + + // Make bottom scroll indicator appear only + // when first getting overflowing children + if (!(bottomArrow.reveal_child === true || + topArrow.reveal_child === true)) { + bottomArrow.reveal_child = true; + } + } + else { + // @ts-expect-error + scroll.vscroll = 'never'; + // @ts-expect-error + scroll.setCss(''); + topArrow.reveal_child = false; + bottomArrow.reveal_child = false; } - } - else { - scroll.vscroll = 'never'; - scroll.setCss(''); - topArrow.revealChild = false; - bottomArrow.revealChild = false; } // Trigger sort_func - self.get_children().forEach((ch) => { - ch.changed(); - }); + // @ts-expect-error + self.get_children().forEach( + /** @param {Box} ListBoxRow */ + (ListBoxRow) => { + // @ts-expect-error + ListBoxRow.changed(); + }, + ); }); }, }), diff --git a/devices/wim/config/ags/js/quick-settings/slider-box.js b/devices/wim/config/ags/js/quick-settings/slider-box.js index a1f55b9..770d103 100644 --- a/devices/wim/config/ags/js/quick-settings/slider-box.js +++ b/devices/wim/config/ags/js/quick-settings/slider-box.js @@ -7,20 +7,20 @@ import { SpeakerIcon } from '../misc/audio-icons.js'; export default () => Box({ - className: 'slider-box', + class_name: 'slider-box', vertical: true, hpack: 'center', children: [ Box({ - className: 'slider', + class_name: 'slider', vpack: 'start', hpack: 'center', children: [ Icon({ size: 26, - className: 'slider-label', + class_name: 'slider-label', binds: [['icon', SpeakerIcon, 'value']], }), @@ -30,14 +30,16 @@ export default () => Box({ max: 0.999, draw_value: false, - onChange: ({ value }) => { - Audio.speaker.volume = value; + on_change: ({ value }) => { + if (Audio.speaker) { + Audio.speaker.volume = value; + } }, setup: (self) => { self .hook(Audio, () => { - self.value = Audio.speaker?.volume; + self.value = Audio.speaker?.volume || 0; }, 'speaker-changed') .on('button-press-event', () => { @@ -53,13 +55,13 @@ export default () => Box({ }), Box({ - className: 'slider', + class_name: 'slider', vpack: 'start', hpack: 'center', children: [ Icon({ - className: 'slider-label', + class_name: 'slider-label', binds: [['icon', Brightness, 'screen-icon']], }), @@ -68,7 +70,7 @@ export default () => Box({ vpack: 'center', draw_value: false, - onChange: ({ value }) => { + on_change: ({ value }) => { Brightness.screen = value; }, diff --git a/devices/wim/config/ags/js/quick-settings/toggle-button.js b/devices/wim/config/ags/js/quick-settings/toggle-button.js index 0d1611d..341fa3c 100644 --- a/devices/wim/config/ags/js/quick-settings/toggle-button.js +++ b/devices/wim/config/ags/js/quick-settings/toggle-button.js @@ -4,6 +4,7 @@ import Mpris from 'resource:///com/github/Aylur/ags/service/mpris.js'; import { CenterBox, Icon, ToggleButton } from 'resource:///com/github/Aylur/ags/widget.js'; +/** @param {import('types/widgets/revealer').default} rev */ export default (rev) => CenterBox({ center_widget: ToggleButton({ cursor: 'pointer', @@ -11,30 +12,32 @@ export default (rev) => CenterBox({ setup: (self) => { // Open at startup if there are players const id = Mpris.connect('changed', () => { + // @ts-expect-error self.set_active(Mpris.players.length > 0); Mpris.disconnect(id); }); self.on('toggled', () => { + // @ts-expect-error if (self.get_active()) { - self.get_children()[0] - .setCss('-gtk-icon-transform: rotate(0deg);'); - rev.revealChild = true; + self.child + // @ts-expect-error + ?.setCss('-gtk-icon-transform: rotate(0deg);'); + rev.reveal_child = true; } else { - self.get_children()[0] - .setCss('-gtk-icon-transform: rotate(180deg);'); - rev.revealChild = false; + self.child + // @ts-expect-error + ?.setCss('-gtk-icon-transform: rotate(180deg);'); + rev.reveal_child = false; } }); }, child: Icon({ icon: `${App.configDir }/icons/down-large.svg`, - className: 'arrow', + class_name: 'arrow', css: '-gtk-icon-transform: rotate(180deg);', }), }), - start_widget: null, - end_widget: null, }); diff --git a/devices/wim/config/ags/services/brightness.js b/devices/wim/config/ags/services/brightness.js index 3a937d7..34d7a56 100644 --- a/devices/wim/config/ags/services/brightness.js +++ b/devices/wim/config/ags/services/brightness.js @@ -114,12 +114,18 @@ class Brightness extends Service { #monitorKbdState() { Variable(0, { - poll: [INTERVAL, `brightnessctl -d ${KBD} g`, (out) => { - if (out !== this.#kbd) { - this.#kbd = out; - this.emit('kbd', this.#kbd); - } - }], + poll: [ + INTERVAL, + `brightnessctl -d ${KBD} g`, + (out) => { + if (parseInt(out) !== this.#kbd) { + this.#kbd = parseInt(out); + this.emit('kbd', this.#kbd); + + return this.#kbd; + } + }, + ], }); } }