From 85704218e3cb488438e215f491b64936d69735ce Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Thu, 11 Jan 2024 16:50:12 +0700 Subject: [PATCH] ags: update to new syntax --- .config/ags/config.js | 7 +- .config/ags/imports.js | 2 +- .config/ags/lib/actioncenter.js | 245 ------ .config/ags/lib/advancedwidgets.js | 52 +- .config/ags/lib/animatedcircularprogress.js | 8 +- .config/ags/lib/calendarlayout.js | 2 - .config/ags/lib/configwidgets.js | 16 +- .config/ags/lib/cursorhover.js | 4 +- .config/ags/lib/materialicon.js | 4 +- .config/ags/lib/navigationindicator.js | 5 +- .config/ags/lib/notification.js | 33 +- .config/ags/lib/popupwindow.js | 3 +- .config/ags/lib/roundedcorner.js | 2 +- .config/ags/lib/separator.js | 2 +- .config/ags/lib/statusicons.js | 40 +- .../scripts/color_generation/applycolor.sh | 1 - .../scripts/color_generation/switchcolor.sh | 5 - .../scripts/color_generation/switchwall.sh | 2 +- .../scripts/templates/gradience/preset.json | 30 +- .config/ags/scss/_common.scss | 41 +- .config/ags/scss/_material.scss | 46 +- .config/ags/services/brightness.js | 5 +- .config/ags/services/chatgpt.js | 3 +- .config/ags/services/indicator.js | 3 +- .config/ags/services/messages.js | 3 +- .config/ags/services/sway.js | 417 +++++++++++ .config/ags/services/todo.js | 5 +- .config/ags/services/waifus.js | 4 +- .config/ags/style.css | 696 +++++++++--------- .config/ags/widgets/bar/leftspace.js | 92 +-- .config/ags/widgets/bar/main.js | 17 +- .config/ags/widgets/bar/music.js | 24 +- .config/ags/widgets/bar/rightspace.js | 27 +- .config/ags/widgets/bar/system.js | 26 +- .config/ags/widgets/bar/tray.js | 58 +- .../{workspaces.js => workspaces_hyprland.js} | 53 +- .config/ags/widgets/bar/workspaces_sway.js | 58 ++ .config/ags/widgets/cheatsheet/keybinds.js | 2 +- .config/ags/widgets/cheatsheet/main.js | 3 +- .config/ags/widgets/desktopbackground/main.js | 3 +- .../ags/widgets/desktopbackground/system.js | 21 +- .../desktopbackground/timeandlaunches.js | 8 +- .config/ags/widgets/dock/dock.js | 90 +-- .config/ags/widgets/dock/main.js | 2 +- .config/ags/widgets/indicators/colorscheme.js | 7 +- .../ags/widgets/indicators/indicatorvalues.js | 58 +- .config/ags/widgets/indicators/main.js | 2 +- .../ags/widgets/indicators/musiccontrols.js | 87 +-- .../widgets/indicators/notificationpopups.js | 44 +- .../onscreenkeyboard/onscreenkeyboard.js | 8 +- .config/ags/widgets/overview/actions.js | 4 +- .config/ags/widgets/overview/main.js | 4 +- .config/ags/widgets/overview/miscfunctions.js | 3 +- .config/ags/widgets/overview/overview.js | 552 -------------- .../ags/widgets/overview/overview_hyprland.js | 308 ++++++++ .config/ags/widgets/overview/searchbuttons.js | 30 +- .config/ags/widgets/overview/searchitem.js | 18 +- .config/ags/widgets/overview/windowcontent.js | 244 ++++++ .config/ags/widgets/screencorners/main.js | 2 +- .config/ags/widgets/session/main.js | 3 +- .config/ags/widgets/session/sessionscreen.js | 26 +- .config/ags/widgets/sideleft/apis/chatgpt.js | 41 +- .../sideleft/apis/chatgpt_chatmessage.js | 50 +- .config/ags/widgets/sideleft/apis/waifu.js | 91 +-- .config/ags/widgets/sideleft/apiwidgets.js | 23 +- .config/ags/widgets/sideleft/module.js | 6 +- .config/ags/widgets/sideleft/quickscripts.js | 4 +- .config/ags/widgets/sideleft/sideleft.js | 66 +- .config/ags/widgets/sideleft/toolbox.js | 4 +- .config/ags/widgets/sideright/calendar.js | 7 +- .../ags/widgets/sideright/notificationlist.js | 27 +- .config/ags/widgets/sideright/quicktoggles.js | 66 +- .config/ags/widgets/sideright/sideright.js | 43 +- .config/ags/widgets/sideright/todolist.js | 55 +- 74 files changed, 2155 insertions(+), 1898 deletions(-) delete mode 100644 .config/ags/lib/actioncenter.js create mode 100644 .config/ags/services/sway.js rename .config/ags/widgets/bar/{workspaces.js => workspaces_hyprland.js} (84%) create mode 100644 .config/ags/widgets/bar/workspaces_sway.js delete mode 100644 .config/ags/widgets/overview/overview.js create mode 100644 .config/ags/widgets/overview/overview_hyprland.js create mode 100644 .config/ags/widgets/overview/windowcontent.js diff --git a/.config/ags/config.js b/.config/ags/config.js index 65093724f..6a008a9f9 100644 --- a/.config/ags/config.js +++ b/.config/ags/config.js @@ -1,11 +1,12 @@ "use strict"; // Import const { GLib } = imports.gi; -import { App, Utils } from './imports.js'; +import App from 'resource:///com/github/Aylur/ags/app.js' +import * as Utils from 'resource:///com/github/Aylur/ags/utils.js' // Widgets import Bar from './widgets/bar/main.js'; import Cheatsheet from './widgets/cheatsheet/main.js'; -// import DesktopBackground from './widgets/desktopbackground/main.js'; +import DesktopBackground from './widgets/desktopbackground/main.js'; // import Dock from './widgets/dock/main.js'; import { CornerTopleft, CornerTopright, CornerBottomleft, CornerBottomright } from './widgets/screencorners/main.js'; import Indicator from './widgets/indicators/main.js'; @@ -42,7 +43,7 @@ export default { CornerTopright(), CornerBottomleft(), CornerBottomright(), - // DesktopBackground(), // If you're going to uncomment these, + DesktopBackground(), // If you're going to uncomment these, // Dock(), // Buggy // uncomment the import statement too. Overview(), Indicator(), diff --git a/.config/ags/imports.js b/.config/ags/imports.js index 91abda6be..d6b6fc6cc 100644 --- a/.config/ags/imports.js +++ b/.config/ags/imports.js @@ -29,7 +29,7 @@ globalThis['Utils'] = Utils; /////////////////////////// // globalThis['Bluetooth'] = Bluetooth; // globalThis['Hyprland'] = Hyprland; globalThis['Mpris'] = Mpris; -// globalThis['Network'] = Network; +globalThis['Network'] = Network; globalThis['Notifications'] = Notifications; // globalThis['SystemTray'] = SystemTray; diff --git a/.config/ags/lib/actioncenter.js b/.config/ags/lib/actioncenter.js deleted file mode 100644 index 9b8fb60f8..000000000 --- a/.config/ags/lib/actioncenter.js +++ /dev/null @@ -1,245 +0,0 @@ -// Not yet used. For cool drag and drop stuff. Thanks DevAlien - -const Toggles = {}; -Toggles.Wifi = NetworkToggle; -Toggles.Bluetooth = BluetoothToggle; -Toggles.DND = DNDToggle; -Toggles.ThemeToggle = ThemeToggle; -Toggles.ProfileToggle = ProfileToggle; -// Toggles.Record = RecordToggle; -// Toggles.Airplane = AirplaneToggle; -// Toggles.DoNotDisturb = DoNotDisturbToggle; -const TARGET = [Gtk.TargetEntry.new("text/plain", Gtk.TargetFlags.SAME_APP, 0)]; - -export class ActionCenter extends Gtk.Box { - static { - GObject.registerClass({ - GTypeName: 'ActionCenter', - Properties: { - - }, - }, this); - } - - constructor({ className = "ActionCenter", toggles, ...rest }) { - super(rest); - this.toggles = Toggles - this.currentToggles = Settings.getSetting("toggles", []); - this.mainFlowBox = this._setupFlowBox(className + QSView.editing && className + "Editing"); - this.mainFlowBox.connect("drag_motion", this._dragMotionMain); - this.mainFlowBox.connect("drag_drop", this._dragDropMain); - this._dragged = {}; - this._draggedExtra = {}; - - this._dragged; - this._currentPosition = 0; - this._orderedState; - this._draggedName; - - this.updateList(toggles, this.mainFlowBox) - - this.set_orientation(Gtk.Orientation.VERTICAL); - this.add(this.mainFlowBox) - this.mainFlowBox.set_size_request(1, 30) - if (QSView.editing) { - this.extraFlowBox = this._setupFlowBox(className); - this.extraFlowBox.connect("drag_motion", this._dragMotionExtra); - this.extraFlowBox.connect("drag_drop", this._dragDropExtra); - this.updateList(this._getExtraToggles(), this.extraFlowBox) - this.add(Box({ - vertical: true, - children: [ - Label("Extra widgets"), - Label("Drop here to remove or drag from here to add"), - this.extraFlowBox - ] - })) - } - } - - _getExtraToggles() { - let toggles = { ...this.toggles } - this.currentToggles.map(t => { - if (toggles[t]) { - delete toggles[t]; - } - }); - return Object.keys(toggles); - } - - _setupFlowBox(className) { - const flowBox = new Gtk.FlowBox(); - flowBox.set_valign(Gtk.Align.FILL); - flowBox.set_min_children_per_line(2); - flowBox.set_max_children_per_line(2); - flowBox.set_selection_mode(Gtk.SelectionMode.NONE); - flowBox.get_style_context().add_class(className); - flowBox.set_homogeneous(true); - flowBox.drag_dest_set(Gtk.DestDefaults.ALL, TARGET, Gdk.DragAction.COPY); - - return flowBox; - } - - createWidget = (name, index, type) => { - const editSetup = (widget) => { - widget.drag_source_set( - Gdk.ModifierType.BUTTON1_MASK, - TARGET, - Gdk.DragAction.COPY - ); - - widget.connect("drag-begin", (w, context) => { - const widgetContainer = widget.get_parent(); - - Gtk.drag_set_icon_surface(context, createSurfaceFromWidget(widgetContainer)); - this._dragged = { - widget: widgetContainer.get_parent().get_parent(), - container: widgetContainer, - name: name, - currentPosition: type === "Main" ? index : null, - currentPositionExtra: type === "Extra" ? index : null, - from: type, - } - widgetContainer.get_style_context().add_class("hidden"); - if (type !== "Main") { - this.extraFlowBox.remove(this._dragged.widget); - } - - - return true; - }); - widget.connect("drag-failed", () => { - this.updateList(Settings.getSetting("toggles"), this.mainFlowBox) - this.updateList(this._getExtraToggles(), this.extraFlowBox) - }); - } - - let row = new Gtk.FlowBoxChild({ visible: true }); - row.add(Toggles[name]({ setup: QSView.editing && editSetup, QSView: QSView })); - row._index = index; - row._name = name; - return row; - } - - updateList(toggles, flowBox) { - let type = flowBox === this.mainFlowBox ? "Main" : "Extra" - var childrenBox = flowBox.get_children(); - childrenBox.forEach((element) => { - flowBox.remove(element); - element.destroy(); - }); - - if (!toggles) return; - - toggles.forEach((name, i) => { - if (Toggles[name]) - flowBox.add(this.createWidget(name, i, type)); - }); - flowBox.show_all(); - } - - - _dragMotionMain = (widget, context, x, y, time) => { - if (this._dragged.currentPositionExtra !== null) { - this._dragged.currentPositionExtra = null; - if (this._isChild(this.extraFlowBox, this._dragged.widget)) { - this.extraFlowBox.remove(this._dragged.widget); - } - } - const children = this.mainFlowBox.get_children(); - const sampleItem = children[0]; - const sampleWidth = sampleItem.get_allocation().width; - const sampleHeight = sampleItem.get_allocated_height(); - const perLine = Math.floor(this.mainFlowBox.get_allocation().width / sampleWidth); - const pos = Math.floor(y / sampleHeight) * perLine + Math.floor(x / sampleWidth); - if (pos >= children.length && pos !== 0) return false; - - if (this._dragged.currentPosition === null) { - this.mainFlowBox.insert(this._dragged.widget, pos); - - this._dragged.currentPosition = pos; - } else if (this._dragged.currentPosition !== pos) { - if (this._isChild(this.mainFlowBox, this._dragged.widget)) { - this.mainFlowBox.remove(this._dragged.widget); - } - - this.mainFlowBox.insert(this._dragged.widget, pos); - - this._dragged.currentPosition = pos; - } - - return true; - } - - _dragDropMain = () => { - if (this._dragged.from !== "Main") { - this.currentToggles.splice(this._dragged.currentPosition, 0, this._dragged.name); - } else { - const indexCurrentToggle = this.currentToggles.indexOf(this._dragged.name); - this.currentToggles.splice(indexCurrentToggle, 1); - this.currentToggles.splice(this._dragged.currentPosition, 0, this._dragged.name); - } - - Settings.setSetting("toggles", this.currentToggles); - this._dragged.container.get_style_context().remove_class("hidden"); - return true; - } - - _dragDropExtra = () => { - if (this._dragged.from === "Main") { - const indexCurrentToggle = this.currentToggles.indexOf(this._dragged.name); - this.currentToggles.splice(indexCurrentToggle, 1); - } - - Settings.setSetting("toggles", this.currentToggles); - this._dragged.container.get_style_context().remove_class("hidden"); - return true; - } - - _dragMotionExtra = (widget, context, x, y, time) => { - if (this._dragged.currentPosition !== null) { - this._dragged.currentPosition = null; - if (this._isChild(this.mainFlowBox, this._dragged.widget)) { - this.mainFlowBox.remove(this._dragged.widget); - } - } - - const children = this.extraFlowBox.get_children(); - const sampleItem = children[0]; - let pos = 0; - if (sampleItem) { - const sampleWidth = sampleItem.get_allocation().width; - const sampleHeight = sampleItem.get_allocated_height(); - const perLine = Math.floor(this.extraFlowBox.get_allocation().width / sampleWidth); - pos = Math.floor(y / sampleHeight) * perLine + Math.floor(x / sampleWidth); - } - - if (pos >= children.length && pos !== 0) return false; - - if (this._dragged.currentPositionExtra === null) { - this.extraFlowBox.insert(this._dragged.widget, pos); - - this._dragged.currentPositionExtra = pos; - } - - if (this._dragged.currentPositionExtra !== pos) { - if (this._isChild(this.extraFlowBox, this._dragged.widget)) { - this.extraFlowBox.remove(this._dragged.widget); - } - - this.extraFlowBox.insert(this._dragged.widget, pos); - - this._dragged.currentPositionExtra = pos; - } - - return true; - } - - _isChild(container, widget) { - let found = false; - container.get_children().forEach((c) => { - if (c === widget) found = true; - }) - return found; - } -} \ No newline at end of file diff --git a/.config/ags/lib/advancedwidgets.js b/.config/ags/lib/advancedwidgets.js index aab474664..096c55fde 100644 --- a/.config/ags/lib/advancedwidgets.js +++ b/.config/ags/lib/advancedwidgets.js @@ -1,6 +1,6 @@ -const { Gdk, Gtk } = imports.gi; -import { App, SCREEN_WIDTH, SCREEN_HEIGHT, Service, Utils, Variable, Widget } from '../imports.js'; -const { Box, Button, EventBox, Label, Overlay, Revealer, Scrollable, Stack } = Widget; +import Widget from 'resource:///com/github/Aylur/ags/widget.js'; + +const { Revealer, Scrollable } = Widget; export const MarginRevealer = ({ transition = 'slide_down', @@ -8,47 +8,49 @@ export const MarginRevealer = ({ revealChild, showClass = 'element-show', // These are for animation curve, they don't really hide hideClass = 'element-hide', // Don't put margins in these classes! - extraProperties = [], + extraSetup = () => { }, ...rest }) => { const widget = Scrollable({ ...rest, - properties: [ - ['revealChild', true], // It'll be set to false after init if it's supposed to hide - ['transition', transition], - ['show', () => { - if (widget._revealChild) return; + attribute: { + 'revealChild': true, // It'll be set to false after init if it's supposed to hide + 'transition': transition, + 'show': () => { + if (widget.attribute.revealChild) return; widget.hscroll = 'never'; widget.vscroll = 'never'; child.toggleClassName(hideClass, false); child.toggleClassName(showClass, true); - widget._revealChild = true; + widget.attribute.revealChild = true; child.css = 'margin: 0px;'; - }], - ['hide', () => { - if (!widget._revealChild) return; + }, + 'hide': () => { + if (!widget.attribute.revealChild) return; child.toggleClassName(hideClass, true); child.toggleClassName(showClass, false); - widget._revealChild = false; - if (widget._transition == 'slide_left') + widget.attribute.revealChild = false; + if (widget.attribute.transition == 'slide_left') child.css = `margin-right: -${child.get_allocated_width()}px;`; - else if (widget._transition == 'slide_right') + else if (widget.attribute.transition == 'slide_right') child.css = `margin-left: -${child.get_allocated_width()}px;`; - else if (widget._transition == 'slide_up') + else if (widget.attribute.transition == 'slide_up') child.css = `margin-bottom: -${child.get_allocated_height()}px;`; - else if (widget._transition == 'slide_down') + else if (widget.attribute.transition == 'slide_down') child.css = `margin-top: -${child.get_allocated_height()}px;`; - }], - ['toggle', () => { + }, + 'toggle': () => { console.log('toggle'); - if (widget._revealChild) widget._hide(); - else widget._show(); - }], - ...extraProperties, - ], + if (widget.attribute.revealChild) widget.attribute.hide(); + else widget.attribute.show(); + }, + }, child: child, hscroll: `${revealChild ? 'never' : 'always'}`, vscroll: `${revealChild ? 'never' : 'always'}`, + setup: (self) => { + extraSetup(self); + } }); child.toggleClassName(`${revealChild ? showClass : hideClass}`, true); return widget; diff --git a/.config/ags/lib/animatedcircularprogress.js b/.config/ags/lib/animatedcircularprogress.js index f108aa545..3101ab48b 100644 --- a/.config/ags/lib/animatedcircularprogress.js +++ b/.config/ags/lib/animatedcircularprogress.js @@ -1,7 +1,7 @@ -const { Gdk, Gtk } = imports.gi; -const GObject = imports.gi.GObject; +const { Gtk } = imports.gi; const Lang = imports.lang; -import { Utils, Widget } from '../imports.js'; +import Widget from 'resource:///com/github/Aylur/ags/widget.js' +import * as Utils from 'resource:///com/github/Aylur/ags/utils.js' // -- Styling -- // min-height for diameter @@ -17,6 +17,7 @@ export const AnimatedCircProg = ({ initTo = 0, initAnimTime = 2900, initAnimPoints = 1, + extraSetup = () => { }, ...rest }) => Widget.DrawingArea({ ...rest, @@ -100,5 +101,6 @@ export const AnimatedCircProg = ({ // } } else area.css = 'font-size: 0px;'; + extraSetup(area); }, }) \ No newline at end of file diff --git a/.config/ags/lib/calendarlayout.js b/.config/ags/lib/calendarlayout.js index 0f1cf7514..35b481d6d 100644 --- a/.config/ags/lib/calendarlayout.js +++ b/.config/ags/lib/calendarlayout.js @@ -1,5 +1,3 @@ -const { GLib, Gio } = imports.gi; - function checkLeapYear(year) { return ( year % 400 == 0 || diff --git a/.config/ags/lib/configwidgets.js b/.config/ags/lib/configwidgets.js index 0c845859f..fa129345a 100644 --- a/.config/ags/lib/configwidgets.js +++ b/.config/ags/lib/configwidgets.js @@ -1,8 +1,8 @@ -const { Gdk, Gtk } = imports.gi; -import { App, Service, Utils, Variable, Widget } from '../imports.js'; +import Widget from 'resource:///com/github/Aylur/ags/widget.js'; +import * as Utils from 'resource:///com/github/Aylur/ags/utils.js'; import { MaterialIcon } from './materialicon.js'; import { setupCursorHover } from './cursorhover.js'; -const { Box, Button, Entry, EventBox, Icon, Label, Revealer, Scrollable, Stack } = Widget; +const { Box, Button, Label, Revealer } = Widget; export const ConfigToggle = ({ icon, name, desc = '', initValue, onChange, ...rest }) => { let value = initValue; @@ -37,8 +37,8 @@ export const ConfigToggle = ({ icon, name, desc = '', initValue, onChange, ...re ] }); const interactionWrapper = Button({ - properties: [ - ['toggle', (newValue) => { + attribute: { + toggle: (newValue) => { value = !value; toggleIcon.toggleClassName('switch-fg-toggling-false', false); if (!value) { @@ -52,10 +52,10 @@ export const ConfigToggle = ({ icon, name, desc = '', initValue, onChange, ...re toggleIcon.toggleClassName('txt-poof', false); }) onChange(interactionWrapper, value); - }] - ], + } + }, child: widgetContent, - onClicked: (self) => self._toggle(self), + onClicked: (self) => self.attribute.toggle(self), setup: (button) => { setupCursorHover(button), button.connect('pressed', () => { // mouse down diff --git a/.config/ags/lib/cursorhover.js b/.config/ags/lib/cursorhover.js index 58801c7d5..c8c436b6c 100644 --- a/.config/ags/lib/cursorhover.js +++ b/.config/ags/lib/cursorhover.js @@ -1,6 +1,4 @@ -const { Gdk, Gtk } = imports.gi; - -const CLICK_BRIGHTEN_AMOUNT = 0.13; +const { Gdk } = imports.gi; export function setupCursorHover(button) { const display = Gdk.Display.get_default(); diff --git a/.config/ags/lib/materialicon.js b/.config/ags/lib/materialicon.js index a06530f0e..029f0ede6 100644 --- a/.config/ags/lib/materialicon.js +++ b/.config/ags/lib/materialicon.js @@ -1,7 +1,7 @@ -import { Widget } from '../imports.js'; +import Widget from 'resource:///com/github/Aylur/ags/widget.js'; export const MaterialIcon = (icon, size, props = {}) => Widget.Label({ className: `icon-material txt-${size}`, label: icon, ...props, -}) \ No newline at end of file +}) diff --git a/.config/ags/lib/navigationindicator.js b/.config/ags/lib/navigationindicator.js index 26e9b83a7..173c13b51 100644 --- a/.config/ags/lib/navigationindicator.js +++ b/.config/ags/lib/navigationindicator.js @@ -1,7 +1,6 @@ -const { Gdk, Gtk } = imports.gi; -const GObject = imports.gi.GObject; +const { Gtk } = imports.gi; const Lang = imports.lang; -import { Utils, Widget } from '../imports.js'; +import Widget from 'resource:///com/github/Aylur/ags/widget.js'; // min-height/min-width for height/width // background-color/color for background/indicator color diff --git a/.config/ags/lib/notification.js b/.config/ags/lib/notification.js index 4c50fb785..10eee4a86 100644 --- a/.config/ags/lib/notification.js +++ b/.config/ags/lib/notification.js @@ -1,7 +1,8 @@ // This file is for the actual widget for each single notification const { GLib, Gdk, Gtk } = imports.gi; -import { Utils, Widget } from '../imports.js'; +import Widget from 'resource:///com/github/Aylur/ags/widget.js' +import * as Utils from 'resource:///com/github/Aylur/ags/utils.js' const { lookUpIcon, timeout } = Utils; const { Box, EventBox, Icon, Overlay, Label, Button, Revealer } = Widget; import { MaterialIcon } from "./materialicon.js"; @@ -92,13 +93,13 @@ export default ({ const widget = EventBox({ onHover: (self) => { self.window.set_cursor(Gdk.Cursor.new_from_name(display, 'grab')); - if (!wholeThing._hovered) - wholeThing._hovered = true; + if (!wholeThing.attribute.hovered) + wholeThing.attribute.hovered = true; }, onHoverLost: (self) => { self.window.set_cursor(null); - if (wholeThing._hovered) - wholeThing._hovered = false; + if (wholeThing.attribute.hovered) + wholeThing.attribute.hovered = false; if (isPopup) { command(); } @@ -108,13 +109,13 @@ export default ({ } }); const wholeThing = Revealer({ - properties: [ - ['id', notifObject.id], - ['close', undefined], - ['hovered', false], - ['dragging', false], - ['destroyWithAnims', () => destroyWithAnims] - ], + attribute: { + 'id': notifObject.id, + 'close': undefined, + 'hovered': false, + 'dragging': false, + 'destroyWithAnims': () => destroyWithAnims, + }, revealChild: false, transition: 'slide_down', transitionDuration: 200, @@ -343,7 +344,7 @@ export default ({ } } - wholeThing._dragging = Math.abs(offset_x) > 10; + wholeThing.attribute.dragging = Math.abs(offset_x) > 10; if (widget.window) widget.window.set_cursor(Gdk.Cursor.new_from_name(display, 'grabbing')); @@ -363,9 +364,9 @@ export default ({ }, 'drag-update') .hook(gesture, self => { - if (!self._ready) { + if (!self.attribute.ready) { wholeThing.revealChild = true; - self._ready = true; + self.attribute.ready = true; return; } const offset_h = gesture.get_offset()[1]; @@ -396,7 +397,7 @@ export default ({ if (widget.window) widget.window.set_cursor(Gdk.Cursor.new_from_name(display, 'grab')); - wholeThing._dragging = false; + wholeThing.attribute.dragging = false; } initDirX = 0; initDirVertical = -1; diff --git a/.config/ags/lib/popupwindow.js b/.config/ags/lib/popupwindow.js index 4f7e63d2e..2b85ca7cf 100644 --- a/.config/ags/lib/popupwindow.js +++ b/.config/ags/lib/popupwindow.js @@ -1,4 +1,5 @@ -import { App, Widget } from '../imports.js'; +import App from 'resource:///com/github/Aylur/ags/app.js'; +import Widget from 'resource:///com/github/Aylur/ags/widget.js'; const { Box, Window } = Widget; diff --git a/.config/ags/lib/roundedcorner.js b/.config/ags/lib/roundedcorner.js index e8c64ab4f..90c1cf07b 100644 --- a/.config/ags/lib/roundedcorner.js +++ b/.config/ags/lib/roundedcorner.js @@ -1,4 +1,4 @@ -import { Widget } from '../imports.js'; +import Widget from 'resource:///com/github/Aylur/ags/widget.js'; const { Gtk } = imports.gi; const Lang = imports.lang; diff --git a/.config/ags/lib/separator.js b/.config/ags/lib/separator.js index 3e39ca7a9..3098c7e60 100644 --- a/.config/ags/lib/separator.js +++ b/.config/ags/lib/separator.js @@ -1,4 +1,4 @@ -import { App, Service, Utils, Widget } from '../imports.js'; +import Widget from 'resource:///com/github/Aylur/ags/widget.js'; export const separatorLine = Widget.Box({ className: 'separator-line', diff --git a/.config/ags/lib/statusicons.js b/.config/ags/lib/statusicons.js index 600e88117..cec2843f3 100644 --- a/.config/ags/lib/statusicons.js +++ b/.config/ags/lib/statusicons.js @@ -1,4 +1,7 @@ -import { App, Service, Utils, Widget } from '../imports.js'; +import App from 'resource:///com/github/Aylur/ags/app.js'; +import Widget from 'resource:///com/github/Aylur/ags/widget.js'; +import * as Utils from 'resource:///com/github/Aylur/ags/utils.js'; + import { MaterialIcon } from './materialicon.js'; import Bluetooth from 'resource:///com/github/Aylur/ags/service/bluetooth.js'; import Network from 'resource:///com/github/Aylur/ags/service/network.js'; @@ -44,23 +47,21 @@ export const NotificationIndicator = (notifCenterName = 'sideright') => { MaterialIcon('notifications', 'norm'), Widget.Label({ className: 'txt-small titlefont', - properties: [ - ['increment', (self) => self._unreadCount++], - ['markread', (self) => self._unreadCount = 0], - ['update', (self) => self.label = `${self._unreadCount}`], - ['unreadCount', 0], - ], + attribute: { + unreadCount: 0, + update: (self) => self.label = `${self.attribute.unreadCount}`, + }, setup: (self) => self .hook(Notifications, (self, id) => { if (!id || Notifications.dnd) return; if (!Notifications.getNotification(id)) return; - self._increment(self); - self._update(self); + self.attribute.unreadCount++; + self.attribute.update(self); }, 'notified') .hook(App, (self, currentName, visible) => { if (visible && currentName === notifCenterName) { - self._markread(self); - self._update(self); + self.attribute.unreadCount = 0; + self.attribute.update(self); } }) , @@ -74,8 +75,8 @@ export const NotificationIndicator = (notifCenterName = 'sideright') => { export const BluetoothIndicator = () => Widget.Stack({ transition: 'slide_up_down', items: [ - ['true', Widget.Label({ className: 'txt-norm icon-material', label: 'bluetooth' })], ['false', Widget.Label({ className: 'txt-norm icon-material', label: 'bluetooth_disabled' })], + ['true', Widget.Label({ className: 'txt-norm icon-material', label: 'bluetooth' })], ], setup: (self) => self .hook(Bluetooth, stack => { @@ -161,7 +162,7 @@ export const NetworkIndicator = () => Widget.Stack({ }), }); -const KeyboardLayout = ({ useFlag } = {}) => { +const HyprlandXkbKeyboardLayout = async ({ useFlag } = {}) => { var initLangs = []; var languageStackArray = []; var currentKeyboard; @@ -215,15 +216,24 @@ const KeyboardLayout = ({ useFlag } = {}) => { return widgetRevealer; } +const OptionalKeyboardLayout = async () => { + try { + return await HyprlandXkbKeyboardLayout({ useFlag: false }); + } catch { + return null; + } +}; +const optionalKeyboardLayoutInstance = await OptionalKeyboardLayout(); + export const StatusIcons = (props = {}) => Widget.Box({ ...props, child: Widget.Box({ className: 'spacing-h-15', children: [ - KeyboardLayout({ useFlag: false }), + optionalKeyboardLayoutInstance, NotificationIndicator(), - BluetoothIndicator(), NetworkIndicator(), + BluetoothIndicator(), ] }) }); diff --git a/.config/ags/scripts/color_generation/applycolor.sh b/.config/ags/scripts/color_generation/applycolor.sh index 18284d16e..e0af2d75b 100755 --- a/.config/ags/scripts/color_generation/applycolor.sh +++ b/.config/ags/scripts/color_generation/applycolor.sh @@ -147,7 +147,6 @@ apply_ags() { ags run-js "App.resetCss(); App.applyCss('${HOME}/.config/ags/style.css');" } -# apply_svgs apply_ags & apply_hyprland & apply_gtk & diff --git a/.config/ags/scripts/color_generation/switchcolor.sh b/.config/ags/scripts/color_generation/switchcolor.sh index 75bcb2c3a..de59f04cc 100755 --- a/.config/ags/scripts/color_generation/switchcolor.sh +++ b/.config/ags/scripts/color_generation/switchcolor.sh @@ -1,11 +1,6 @@ #!/usr/bin/bash -# Switches sww wallpaper -# Requires: coreutils, xrandr, hyprland color=$(hyprpicker --no-fancy) # Generate colors for ags n stuff "$HOME"/.config/ags/scripts/color_generation/colorgen.sh "${color}" --apply -sassc "$HOME"/.config/ags/scss/main.scss "$HOME"/.config/ags/style.css -ags run-js "App.resetCss(); App.applyCss('${HOME}/.config/ags/style.css');" - diff --git a/.config/ags/scripts/color_generation/switchwall.sh b/.config/ags/scripts/color_generation/switchwall.sh index 3b5c2870a..d91674eca 100755 --- a/.config/ags/scripts/color_generation/switchwall.sh +++ b/.config/ags/scripts/color_generation/switchwall.sh @@ -1,5 +1,5 @@ #!/usr/bin/bash -# Switches sww wallpaper +# Switches swww wallpaper # Requires: coreutils, xrandr, hyprland if [ "$1" == "--noswitch" ]; then diff --git a/.config/ags/scripts/templates/gradience/preset.json b/.config/ags/scripts/templates/gradience/preset.json index d5b3171da..326615b1e 100644 --- a/.config/ags/scripts/templates/gradience/preset.json +++ b/.config/ags/scripts/templates/gradience/preset.json @@ -87,9 +87,9 @@ "BLACK_500": "#393634", "BLACK_700": "#33302F", "BLACK_900": "#2B2928", - "accent_bg_color": "#ffabf1", - "accent_fg_color": "#551251", - "accent_color": "#ffabf1", + "accent_bg_color": "#51d7ef", + "accent_fg_color": "#00363f", + "accent_color": "#51d7ef", "destructive_bg_color": "#ffb4a9", "destructive_fg_color": "#680003", "destructive_color": "#ffb4a9", @@ -99,22 +99,22 @@ "warning_fg_color": "rgba(0, 0, 0, 0.87)", "error_bg_color": "#ffb4a9", "error_fg_color": "#680003", - "window_bg_color": "#120F11", - "window_fg_color": "#eae0e4", - "view_bg_color": "#1f1a1d", - "view_fg_color": "#eae0e4", + "window_bg_color": "#0F1011", + "window_fg_color": "#e1e3e4", + "view_bg_color": "#191c1d", + "view_fg_color": "#e1e3e4", "headerbar_bg_color": "mix(@dialog_bg_color, @window_bg_color, 0.5)", - "headerbar_fg_color": "#f8daee", - "headerbar_border_color": "#554050", + "headerbar_fg_color": "#cde7ed", + "headerbar_border_color": "#334a4f", "headerbar_backdrop_color": "@headerbar_bg_color", "headerbar_shade_color": "rgba(0, 0, 0, 0.09)", - "card_bg_color": "#120F11", - "card_fg_color": "#f8daee", + "card_bg_color": "#0F1011", + "card_fg_color": "#cde7ed", "card_shade_color": "rgba(0, 0, 0, 0.09)", - "dialog_bg_color": "#554050", - "dialog_fg_color": "#f8daee", - "popover_bg_color": "#554050", - "popover_fg_color": "#f8daee", + "dialog_bg_color": "#334a4f", + "dialog_fg_color": "#cde7ed", + "popover_bg_color": "#334a4f", + "popover_fg_color": "#cde7ed", "thumbnail_bg_color": "#1a1b26", "thumbnail_fg_color": "#AEE5FA", "shade_color": "rgba(0, 0, 0, 0.36)", diff --git a/.config/ags/scss/_common.scss b/.config/ags/scss/_common.scss index 3ca445e49..1b3d0a44f 100644 --- a/.config/ags/scss/_common.scss +++ b/.config/ags/scss/_common.scss @@ -47,14 +47,14 @@ menu { animation-iteration-count: 1; } -menubar>menuitem { +menubar > menuitem { border-radius: 0.545rem; -gtk-outline-radius: 0.545rem; min-width: 13.636rem; min-height: 2.727rem; } -menu>menuitem { +menu > menuitem { padding: 0.4em 1.5rem; background: transparent; transition: 0.2s ease background; @@ -62,14 +62,33 @@ menu>menuitem { -gtk-outline-radius: 0.545rem; } -menu>menuitem:hover, -menu>menuitem:focus { +menu > menuitem:hover, +menu > menuitem:focus { background-color: mix($surfaceVariant, $onSurfaceVariant, 90%); } -menu>menuitem:active { +menu > menuitem:active { background-color: mix($surfaceVariant, $onSurfaceVariant, 80%); } +radio { + @include full-rounding; + margin: 0.273rem; + min-width: 15px; + min-height: 15px; + border: 0.068rem solid $outline; +} + +// radio:first-child { +// background-color: red; +// } + +radio:checked { + min-width: 8px; + min-height: 8px; + background-color: $onPrimary; + border: 0.477rem solid $primary; +} + tooltip { @include normal-rounding; background-color: $surfaceVariant; @@ -129,17 +148,17 @@ tooltip { border: 0.068rem solid $outline; } -.segment-container>*:first-child { +.segment-container > *:first-child { border-top-left-radius: 9999px; border-bottom-left-radius: 9999px; } -.segment-container>* { +.segment-container > * { border-right: 0.068rem solid $outline; padding: 0.341rem 0.682rem; } -.segment-container>*:last-child { +.segment-container > *:last-child { border-right: 0rem solid transparent; border-top-right-radius: 9999px; border-bottom-right-radius: 9999px; @@ -155,13 +174,13 @@ tooltip { } .segment-btn-enabled { - background-color: $secondaryContainer; + background-color: $secondaryContainer; color: $onSecondaryContainer; } .segment-btn-enabled:hover, .segment-btn-enabled:focus { - background-color: $secondaryContainer; + background-color: $secondaryContainer; color: $onSecondaryContainer; } @@ -187,4 +206,4 @@ tooltip { .gap-h-15 { min-width: 1.023rem; -} \ No newline at end of file +} diff --git a/.config/ags/scss/_material.scss b/.config/ags/scss/_material.scss index 4b1ab4eee..687527a0c 100644 --- a/.config/ags/scss/_material.scss +++ b/.config/ags/scss/_material.scss @@ -1,29 +1,29 @@ $darkmode: true; -$primary: #ffabf1; -$onPrimary: #551251; -$primaryContainer: #702c69; -$onPrimaryContainer: #ffd6f5; -$secondary: #dbbed2; -$onSecondary: #3d2b39; -$secondaryContainer: #554050; -$onSecondaryContainer: #f8daee; -$tertiary: #f5b9a6; -$onTertiary: #4c2619; -$tertiaryContainer: #663c2e; -$onTertiaryContainer: #ffdbcf; +$primary: #51d7ef; +$onPrimary: #00363f; +$primaryContainer: #004e5a; +$onPrimaryContainer: #9cefff; +$secondary: #b1cbd1; +$onSecondary: #1c3439; +$secondaryContainer: #334a4f; +$onSecondaryContainer: #cde7ed; +$tertiary: #bcc5ea; +$onTertiary: #262f4d; +$tertiaryContainer: #3d4665; +$onTertiaryContainer: #dae1ff; $error: #ffb4a9; $onError: #680003; $errorContainer: #930006; $onErrorContainer: #ffb4a9; -$colorbarbg: #120F11; -$background: #120F11; -$onBackground: #eae0e4; -$surface: #1f1a1d; -$onSurface: #eae0e4; -$surfaceVariant: #4e444b; -$onSurfaceVariant: #d1c2cb; -$outline: #9a8d95; +$colorbarbg: #0F1011; +$background: #0F1011; +$onBackground: #e1e3e4; +$surface: #191c1d; +$onSurface: #e1e3e4; +$surfaceVariant: #3f484a; +$onSurfaceVariant: #bfc8ca; +$outline: #899294; $shadow: #000000; -$inverseSurface: #eae0e4; -$inverseOnSurface: #342f32; -$inversePrimary: #8c4483; +$inverseSurface: #e1e3e4; +$inverseOnSurface: #2d3132; +$inversePrimary: #006877; diff --git a/.config/ags/services/brightness.js b/.config/ags/services/brightness.js index b86558c3c..8032b14ae 100644 --- a/.config/ags/services/brightness.js +++ b/.config/ags/services/brightness.js @@ -1,4 +1,5 @@ -import { Service, Utils } from '../imports.js'; +import Service from 'resource:///com/github/Aylur/ags/service.js'; +import * as Utils from 'resource:///com/github/Aylur/ags/utils.js'; const { exec, execAsync } = Utils; const clamp = (num, min, max) => Math.min(Math.max(num, min), max); @@ -41,7 +42,7 @@ class BrightnessService extends Service { this._screenValue = current / max; } - // overwriting connectWidget method, let's you + // overwriting connectWidget method, lets you // change the default event that widgets connect to connectWidget(widget, callback, event = 'screen-changed') { super.connectWidget(widget, callback, event); diff --git a/.config/ags/services/chatgpt.js b/.config/ags/services/chatgpt.js index 19aa23e64..abfa68fe2 100644 --- a/.config/ags/services/chatgpt.js +++ b/.config/ags/services/chatgpt.js @@ -1,5 +1,6 @@ -import { Utils, Widget } from '../imports.js'; import Service from 'resource:///com/github/Aylur/ags/service.js'; +import * as Utils from 'resource:///com/github/Aylur/ags/utils.js'; + import Gio from 'gi://Gio'; import GLib from 'gi://GLib'; import Soup from 'gi://Soup?version=3.0'; diff --git a/.config/ags/services/indicator.js b/.config/ags/services/indicator.js index fcb89487a..f74f2a1a6 100644 --- a/.config/ags/services/indicator.js +++ b/.config/ags/services/indicator.js @@ -1,4 +1,5 @@ -import { Service, Utils } from '../imports.js'; +import Service from 'resource:///com/github/Aylur/ags/service.js'; +import * as Utils from 'resource:///com/github/Aylur/ags/utils.js'; const { exec, execAsync } = Utils; const clamp = (num, min, max) => Math.min(Math.max(num, min), max); diff --git a/.config/ags/services/messages.js b/.config/ags/services/messages.js index 5de546678..b282b3f45 100644 --- a/.config/ags/services/messages.js +++ b/.config/ags/services/messages.js @@ -1,5 +1,5 @@ const { Notify, GLib, Gio } = imports.gi; -import { Utils } from '../imports.js'; +import * as Utils from 'resource:///com/github/Aylur/ags/utils.js'; import Battery from 'resource:///com/github/Aylur/ags/service/battery.js'; @@ -17,7 +17,6 @@ const FIRST_RUN_NOTIF_BODY = `Looks like this is your first run.\nHit { // Note that we add a little delay to make sure the cool circular progress works diff --git a/.config/ags/services/sway.js b/.config/ags/services/sway.js new file mode 100644 index 000000000..d32e7ef86 --- /dev/null +++ b/.config/ags/services/sway.js @@ -0,0 +1,417 @@ +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = function (d, b) { + extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; + return extendStatics(d, b); + }; + return function (d, b) { + if (typeof b !== "function" && b !== null) + throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var __generator = (this && this.__generator) || function (thisArg, body) { + var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; + return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; + function verb(n) { return function (v) { return step([n, v]); }; } + function step(op) { + if (f) throw new TypeError("Generator is already executing."); + while (g && (g = 0, op[0] && (_ = 0)), _) try { + if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; + if (y = 0, t) op = [op[0] & 2, t.value]; + switch (op[0]) { + case 0: case 1: t = op; break; + case 4: _.label++; return { value: op[1], done: false }; + case 5: _.label++; y = op[1]; op = [0]; continue; + case 7: op = _.ops.pop(); _.trys.pop(); continue; + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } + if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } + if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } + if (t[2]) _.ops.pop(); + _.trys.pop(); continue; + } + op = body.call(thisArg, _); + } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } + if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; + } +}; +var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) { + if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { + if (ar || !(i in from)) { + if (!ar) ar = Array.prototype.slice.call(from, 0, i); + ar[i] = from[i]; + } + } + return to.concat(ar || Array.prototype.slice.call(from)); +}; +var _a, _b, _c, _d; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.sway = exports.Sway = exports.SwayActives = exports.SwayActiveID = exports.SwayActiveClient = void 0; +var _1 = require("gi://GLib"); +var _2 = require("gi://Gio"); +var service_js_1 = require("../service.js"); +var SIS = _1.default.getenv('SWAYSOCK'); +var SwayActiveClient = /** @class */ (function (_super) { + __extends(SwayActiveClient, _super); + function SwayActiveClient() { + var _this = _super !== null && _super.apply(this, arguments) || this; + _this._id = 0; + _this._name = ''; + _this._class = ''; + return _this; + } + Object.defineProperty(SwayActiveClient.prototype, "id", { + get: function () { return this._id; }, + enumerable: false, + configurable: true + }); + Object.defineProperty(SwayActiveClient.prototype, "name", { + get: function () { return this._name; }, + enumerable: false, + configurable: true + }); + Object.defineProperty(SwayActiveClient.prototype, "class", { + get: function () { return this._class; }, + enumerable: false, + configurable: true + }); + SwayActiveClient.prototype.updateProperty = function (prop, value) { + _super.prototype.updateProperty.call(this, prop, value); + this.emit('changed'); + }; + return SwayActiveClient; +}(service_js_1.default)); +exports.SwayActiveClient = SwayActiveClient; +_a = SwayActiveClient; +(function () { + service_js_1.default.register(_a, {}, { + 'id': ['int'], + 'name': ['string'], + 'class': ['string'], + }); +})(); +var SwayActiveID = /** @class */ (function (_super) { + __extends(SwayActiveID, _super); + function SwayActiveID() { + var _this = _super !== null && _super.apply(this, arguments) || this; + _this._id = 1; + _this._name = ''; + return _this; + } + Object.defineProperty(SwayActiveID.prototype, "id", { + get: function () { return this._id; }, + enumerable: false, + configurable: true + }); + Object.defineProperty(SwayActiveID.prototype, "name", { + get: function () { return this._name; }, + enumerable: false, + configurable: true + }); + SwayActiveID.prototype.update = function (id, name) { + _super.prototype.updateProperty.call(this, 'id', id); + _super.prototype.updateProperty.call(this, 'name', name); + this.emit('changed'); + }; + return SwayActiveID; +}(service_js_1.default)); +exports.SwayActiveID = SwayActiveID; +_b = SwayActiveID; +(function () { + service_js_1.default.register(_b, {}, { + 'id': ['int'], + 'name': ['string'], + }); +})(); +var SwayActives = /** @class */ (function (_super) { + __extends(SwayActives, _super); + function SwayActives() { + var _this = _super.call(this) || this; + _this._client = new SwayActiveClient; + _this._monitor = new SwayActiveID; + _this._workspace = new SwayActiveID; + ['client', 'workspace', 'monitor'].forEach(function (obj) { + _this["_".concat(obj)].connect('changed', function () { + _this.notify(obj); + _this.emit('changed'); + }); + }); + return _this; + } + Object.defineProperty(SwayActives.prototype, "client", { + get: function () { return this._client; }, + enumerable: false, + configurable: true + }); + Object.defineProperty(SwayActives.prototype, "monitor", { + get: function () { return this._monitor; }, + enumerable: false, + configurable: true + }); + Object.defineProperty(SwayActives.prototype, "workspace", { + get: function () { return this._workspace; }, + enumerable: false, + configurable: true + }); + return SwayActives; +}(service_js_1.default)); +exports.SwayActives = SwayActives; +_c = SwayActives; +(function () { + service_js_1.default.register(_c, {}, { + 'client': ['jsobject'], + 'monitor': ['jsobject'], + 'workspace': ['jsobject'], + }); +})(); +var Sway = /** @class */ (function (_super) { + __extends(Sway, _super); + function Sway() { + var _this = this; + if (!SIS) + console.error('Sway is not running'); + _this = _super.call(this) || this; + _this._decoder = new TextDecoder(); + _this._encoder = new TextEncoder(); + _this._active = new SwayActives(); + _this._monitors = new Map(); + _this._workspaces = new Map(); + _this._clients = new Map(); + var socket = new _2.default.SocketClient().connect(new _2.default.UnixSocketAddress({ + path: "".concat(SIS), + }), null); + _this._watchSocket(socket.get_input_stream()); + _this._output_stream = socket.get_output_stream(); + _this.send(4 /* PAYLOAD_TYPE.MESSAGE_GET_TREE */, ''); + _this.send(2 /* PAYLOAD_TYPE.MESSAGE_SUBSCRIBE */, JSON.stringify(['window', 'workspace'])); + _this._active.connect('changed', function () { return _this.emit('changed'); }); + ['monitor', 'workspace', 'client'].forEach(function (active) { + return _this._active.connect("notify::".concat(active), function () { return _this.notify('active'); }); + }); + return _this; + } + Object.defineProperty(Sway.prototype, "active", { + get: function () { return this._active; }, + enumerable: false, + configurable: true + }); + Object.defineProperty(Sway.prototype, "monitors", { + get: function () { return Array.from(this._monitors.values()); }, + enumerable: false, + configurable: true + }); + Object.defineProperty(Sway.prototype, "workspaces", { + get: function () { return Array.from(this._workspaces.values()); }, + enumerable: false, + configurable: true + }); + Object.defineProperty(Sway.prototype, "clients", { + get: function () { return Array.from(this._clients.values()); }, + enumerable: false, + configurable: true + }); + Sway.prototype.getMonitor = function (id) { return this._monitors.get(id); }; + Sway.prototype.getWorkspace = function (name) { return this._workspaces.get(name); }; + Sway.prototype.getClient = function (id) { return this._clients.get(id); }; + Sway.prototype.send = function (payloadType, payload) { + var pb = this._encoder.encode(payload); + var type = new Uint32Array([payloadType]); + var pl = new Uint32Array([pb.length]); + var magic_string = this._encoder.encode('i3-ipc'); + var data = new Uint8Array(__spreadArray(__spreadArray(__spreadArray(__spreadArray([], magic_string, true), (new Uint8Array(pl.buffer)), true), (new Uint8Array(type.buffer)), true), pb, true)); + this._output_stream.write(data, null); + }; + Sway.prototype._watchSocket = function (stream) { + var _this = this; + stream.read_bytes_async(14, _1.default.PRIORITY_DEFAULT, null, function (_, resultHeader) { + var data = stream.read_bytes_finish(resultHeader).get_data(); + if (!data) + return; + var payloadLength = new Uint32Array(data.slice(6, 10).buffer)[0]; + var payloadType = new Uint32Array(data.slice(10, 14).buffer)[0]; + stream.read_bytes_async(payloadLength, _1.default.PRIORITY_DEFAULT, null, function (_, resultPayload) { + var data = stream.read_bytes_finish(resultPayload).get_data(); + if (!data) + return; + _this._onEvent(payloadType, JSON.parse(_this._decoder.decode(data))); + _this._watchSocket(stream); + }); + }); + }; + Sway.prototype._onEvent = function (event_type, event) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_e) { + if (!event) + return [2 /*return*/]; + try { + switch (event_type) { + case 2147483648 /* PAYLOAD_TYPE.EVENT_WORKSPACE */: + this._handleWorkspaceEvent(event); + break; + case 2147483651 /* PAYLOAD_TYPE.EVENT_WINDOW */: + this._handleWindowEvent(event); + break; + case 4 /* PAYLOAD_TYPE.MESSAGE_GET_TREE */: + this._handleTreeMessage(event); + break; + default: + break; + } + } + catch (error) { + logError(error); + } + this.emit('changed'); + return [2 /*return*/]; + }); + }); + }; + Sway.prototype._handleWorkspaceEvent = function (workspaceEvent) { + var workspace = workspaceEvent.current; + switch (workspaceEvent.change) { + case 'init': + this._workspaces.set(workspace.name, workspace); + this.notify('workspaces'); + break; + case 'empty': + this._workspaces.delete(workspace.name); + this.notify('workspaces'); + break; + case 'focus': + this._active.workspace.update(workspace.id, workspace.name); + this._active.monitor.update(1, workspace.output); + this._workspaces.set(workspace.name, workspace); + this._workspaces.set(workspaceEvent.old.name, workspaceEvent.old); + this.notify('workspaces'); + break; + case 'rename': + if (this._active.workspace.id === workspace.id) + this._active.workspace.updateProperty('name', workspace.name); + this._workspaces.set(workspace.name, workspace); + this.notify('workspaces'); + break; + case 'reload': + break; + case 'move': + case 'urgent': + default: + this._workspaces.set(workspace.name, workspace); + this.notify('workspaces'); + } + }; + Sway.prototype._handleWindowEvent = function (clientEvent) { + var _e; + var client = clientEvent.container; + var id = client.id; + switch (clientEvent.change) { + case 'new': + this._clients.set(id, client); + this.notify('clients'); + break; + case 'close': + this._clients.delete(id); + this.notify('clients'); + break; + case 'focus': + if (this._active.client.id === id) + return; + // eslint-disable-next-line no-case-declarations + var current_active = this._clients.get(this._active.client.id); + if (current_active) + current_active.focused = false; + this._active.client.updateProperty('id', id); + this._active.client.updateProperty('name', client.name); + this._active.client.updateProperty('class', client.shell === 'xwayland' + ? ((_e = client.window_properties) === null || _e === void 0 ? void 0 : _e.class) || '' + : client.app_id); + break; + case 'title': + if (client.focused) + this._active.client.updateProperty('name', client.name); + this._clients.set(id, client); + this.notify('clients'); + break; + case 'fullscreen_mode': + case 'move': + case 'floating': + case 'urgent': + case 'mark': + default: + this._clients.set(id, client); + this.notify('clients'); + } + }; + Sway.prototype._handleTreeMessage = function (node) { + var _this = this; + var _e; + switch (node.type) { + case 'root': + this._workspaces.clear(); + this._clients.clear(); + this._monitors.clear(); + node.nodes.map(function (n) { return _this._handleTreeMessage(n); }); + ['workspaces', 'clients', 'monitors'].forEach(function (t) { + _this.notify(t); + }); + break; + case 'output': + this._monitors.set(node.id, node); + if (node.active) + this._active.monitor.updateProperty('name', node.name); + node.nodes.map(function (n) { return _this._handleTreeMessage(n); }); + this.notify('monitors'); + break; + case 'workspace': + this._workspaces.set(node.name, node); + // I think I'm missing something. There has to be a better way. + // eslint-disable-next-line no-case-declarations + var hasFocusedChild_1 = function (n) { return n.nodes.some(function (c) { return c.focused || hasFocusedChild_1(c); }); }; + if (hasFocusedChild_1(node)) + this._active.workspace.update(node.id, node.name); + node.nodes.map(function (n) { return _this._handleTreeMessage(n); }); + this.notify('workspaces'); + break; + case 'con': + case 'floating_con': + this._clients.set(node.id, node); + if (node.focused) { + this._active.client.updateProperty('id', node.id); + this._active.client.updateProperty('name', node.name); + this._active.client.updateProperty('class', node.shell === 'xwayland' + ? ((_e = node.window_properties) === null || _e === void 0 ? void 0 : _e.class) || '' + : node.app_id); + } + node.nodes.map(function (n) { return _this._handleTreeMessage(n); }); + this.notify('clients'); + break; + } + }; + return Sway; +}(service_js_1.default)); +exports.Sway = Sway; +_d = Sway; +(function () { + service_js_1.default.register(_d, {}, { + 'active': ['jsobject'], + 'monitors': ['jsobject'], + 'workspaces': ['jsobject'], + 'clients': ['jsobject'], + }); +})(); +exports.sway = new Sway; +exports.default = exports.sway; diff --git a/.config/ags/services/todo.js b/.config/ags/services/todo.js index f0dabb47f..83b71327c 100644 --- a/.config/ags/services/todo.js +++ b/.config/ags/services/todo.js @@ -1,5 +1,6 @@ -const { Gio, Gdk, GLib, Gtk } = imports.gi; -import { Service, Utils } from '../imports.js'; +const { Gio, GLib } = imports.gi; +import Service from 'resource:///com/github/Aylur/ags/service.js'; +import * as Utils from 'resource:///com/github/Aylur/ags/utils.js'; const { exec, execAsync } = Utils; const clamp = (num, min, max) => Math.min(Math.max(num, min), max); diff --git a/.config/ags/services/waifus.js b/.config/ags/services/waifus.js index b5bfdfb30..11afb77d3 100644 --- a/.config/ags/services/waifus.js +++ b/.config/ags/services/waifus.js @@ -1,6 +1,6 @@ -const { Gdk, Gio, GLib } = imports.gi; -import { Utils, Widget } from '../imports.js'; +import Widget from 'resource:///com/github/Aylur/ags/widget.js'; import Service from 'resource:///com/github/Aylur/ags/service.js'; +import * as Utils from 'resource:///com/github/Aylur/ags/utils.js'; // Usage from my python waifu fetcher, for reference // Usage: waifu-get.py [OPTION]... [TAG]... diff --git a/.config/ags/style.css b/.config/ags/style.css index c4e1f4b7d..19b3c16b3 100644 --- a/.config/ags/style.css +++ b/.config/ags/style.css @@ -41,16 +41,16 @@ transition: 0ms; } .txt { - color: #eae0e4; } + color: #e1e3e4; } .txt-primary { - color: #ffc4f5; } + color: #85e3f4; } .txt-onSecondaryContainer { - color: #f8daee; } + color: #cde7ed; } .txt-onSurfaceVariant { - color: #d1c2cb; } + color: #bfc8ca; } .txt-shadow { text-shadow: 1px 2px 8px rgba(0, 0, 0, 0.69); @@ -104,10 +104,10 @@ font-size: 0px; } .txt-subtext { - color: #a9a1a4; } + color: #a1a3a4; } .txt-action { - color: #c9c0c4; } + color: #c1c3c4; } .txt-semibold { font-weight: 500; } @@ -131,14 +131,14 @@ font-family: "SpaceMono NF", "SpaceMono Nerd Font", "JetBrains Mono NF", "JetBrains Mono Nerd Font", monospace; } .separator-line { - background-color: #9a8d95; + background-color: #899294; min-width: 0.068rem; min-height: 0.068rem; } .separator-circle { border-radius: 9999px; -gtk-outline-radius: 9999px; - background-color: #9a8d95; + background-color: #899294; margin: 0rem 0.682rem; min-width: 0.273rem; min-height: 0.273rem; } @@ -396,10 +396,10 @@ transition: 500ms cubic-bezier(0.85, 0, 0.15, 1); } * { - caret-color: #ffc4f5; } + caret-color: #85e3f4; } * selection { - background-color: #dbbed2; - color: #3d2b39; } + background-color: #b1cbd1; + color: #1c3439; } @keyframes appear { from { @@ -414,13 +414,13 @@ tooltip { animation-iteration-count: 1; } menu { - border-top: 1px solid rgba(62, 56, 60, 0.121); - border-left: 1px solid rgba(62, 56, 60, 0.121); - border-right: 1px solid rgba(48, 42, 46, 0.1105); - border-bottom: 1px solid rgba(48, 42, 46, 0.1105); + border-top: 1px solid rgba(54, 58, 60, 0.121); + border-left: 1px solid rgba(54, 58, 60, 0.121); + border-right: 1px solid rgba(40, 44, 46, 0.1105); + border-bottom: 1px solid rgba(40, 44, 46, 0.1105); padding: 0.681rem; - background: #3b3338; - color: #d1c2cb; + background: #2f3638; + color: #bfc8ca; border-radius: 1.159rem; -gtk-outline-radius: 1.159rem; animation-name: appear; @@ -443,51 +443,65 @@ menu > menuitem { menu > menuitem:hover, menu > menuitem:focus { - background-color: #4a4147; } + background-color: #3d4547; } menu > menuitem:active { - background-color: #595055; } + background-color: #4c5355; } + +radio { + border-radius: 9999px; + -gtk-outline-radius: 9999px; + margin: 0.273rem; + min-width: 15px; + min-height: 15px; + border: 0.068rem solid #899294; } + +radio:checked { + min-width: 8px; + min-height: 8px; + background-color: #00363f; + border: 0.477rem solid #85e3f4; } tooltip { border-radius: 1.159rem; -gtk-outline-radius: 1.159rem; - background-color: #3b3338; - color: #d1c2cb; - border: 1px solid #d1c2cb; } + background-color: #2f3638; + color: #bfc8ca; + border: 1px solid #bfc8ca; } .configtoggle-box { padding: 0.205rem 0.341rem; border: 0.136rem solid transparent; } .configtoggle-box:focus { - border: 0.136rem solid #716a6e; } + border: 0.136rem solid #696c6e; } .switch-bg { transition: 300ms cubic-bezier(0.1, 1, 0, 1); border-radius: 9999px; -gtk-outline-radius: 9999px; - background-color: #191418; - border: 0.136rem solid #eae0e4; + background-color: #121618; + border: 0.136rem solid #e1e3e4; min-width: 2.864rem; min-height: 1.637rem; } .switch-bg-true { - background-color: #ffc4f5; - border: 0.136rem solid #ffc4f5; } + background-color: #85e3f4; + border: 0.136rem solid #85e3f4; } .switch-fg { border-radius: 9999px; -gtk-outline-radius: 9999px; transition: 300ms cubic-bezier(0.1, 1, 0, 1); - background-color: #eae0e4; - color: #211b1f; + background-color: #e1e3e4; + color: #191d1f; min-width: 0.819rem; min-height: 0.819rem; margin-left: 0.477rem; } .switch-fg-true { - background-color: #551251; - color: #ffc4f5; + background-color: #00363f; + color: #85e3f4; min-width: 1.431rem; min-height: 1.431rem; margin-left: 1.431rem; } @@ -500,14 +514,14 @@ tooltip { .segment-container { border-radius: 9999px; -gtk-outline-radius: 9999px; - border: 0.068rem solid #9a8d95; } + border: 0.068rem solid #899294; } .segment-container > *:first-child { border-top-left-radius: 9999px; border-bottom-left-radius: 9999px; } .segment-container > * { - border-right: 0.068rem solid #9a8d95; + border-right: 0.068rem solid #899294; padding: 0.341rem 0.682rem; } .segment-container > *:last-child { @@ -516,20 +530,20 @@ tooltip { border-bottom-right-radius: 9999px; } .segment-btn { - color: #eae0e4; } + color: #e1e3e4; } .segment-btn:focus, .segment-btn:hover { background-color: rgba(128, 128, 128, 0.3); } .segment-btn-enabled { - background-color: #554050; - color: #f8daee; } + background-color: #334a4f; + color: #cde7ed; } .segment-btn-enabled:hover, .segment-btn-enabled:focus { - background-color: #554050; - color: #f8daee; } + background-color: #334a4f; + color: #cde7ed; } .gap-v-5 { min-height: 0.341rem; } @@ -553,7 +567,7 @@ tooltip { min-height: 2.727rem; } .bar-bg { - background-color: #100d10; + background-color: #0b0f10; min-height: 2.727rem; } .bar-sidespace { @@ -563,7 +577,7 @@ tooltip { padding: 0.273rem 0rem; } .bar-group { - background-color: rgba(59, 51, 56, 0.45); } + background-color: rgba(47, 54, 56, 0.45); } .bar-group-pad { padding: 0.205rem; } @@ -622,23 +636,23 @@ tooltip { .bar-ws { min-width: 1.774rem; - color: #676165; - color: #726c6f; } + color: #616465; + color: #6b6e6f; } .bar-ws-active { - background-color: #554050; - color: #f8daee; } + background-color: #334a4f; + color: #cde7ed; } .bar-ws-occupied { - background-color: #3b3338; - color: #d1c2cb; } + background-color: #2f3638; + color: #bfc8ca; } .bar-separator { border-radius: 9999px; -gtk-outline-radius: 9999px; min-width: 0.341rem; min-height: 0.341rem; - background-color: rgba(53, 47, 51, 0.31); + background-color: rgba(45, 49, 51, 0.31); margin: 0rem 0.341rem; } .bar-clock-box { @@ -651,7 +665,7 @@ tooltip { .bar-date { font-family: "Gabarito", "Poppins", "Lexend", sans-serif; font-size: 1rem; - color: #eae0e4; } + color: #e1e3e4; } .bar-batt { border-radius: 9999px; @@ -659,8 +673,8 @@ tooltip { min-height: 1.77rem; min-width: 1.77rem; border-radius: 10rem; - background-color: #554050; - color: #f8daee; } + background-color: #334a4f; + color: #cde7ed; } .bar-sidemodule { min-width: 26rem; } @@ -678,8 +692,8 @@ tooltip { min-width: 0.068rem; min-height: 1.636rem; padding: 0rem; - background-color: #554050; - color: #f8daee; } + background-color: #334a4f; + color: #cde7ed; } .bar-batt-circprog-low { transition: 1000ms cubic-bezier(0.1, 1, 0, 1); @@ -701,23 +715,23 @@ tooltip { min-height: 1.77rem; min-width: 1.77rem; border-radius: 10rem; - background-color: #554050; - color: #f8daee; } + background-color: #334a4f; + color: #cde7ed; } .bar-music-circprog { transition: 1000ms cubic-bezier(0.1, 1, 0, 1); min-width: 0.068rem; min-height: 1.636rem; padding: 0rem; - background-color: #554050; - color: #f8daee; } + background-color: #334a4f; + color: #cde7ed; } .bar-music-playstate-playing { min-height: 1.77rem; min-width: 1.77rem; border-radius: 10rem; - background-color: #554050; - color: #f8daee; } + background-color: #334a4f; + color: #cde7ed; } .bar-music-playstate-txt { transition: 100ms cubic-bezier(0.05, 0.7, 0.1, 1); @@ -785,7 +799,7 @@ tooltip { min-width: 0.68rem; margin: 0rem 0.137rem; border-radius: 10rem; - background-color: #f8daee; } + background-color: #cde7ed; } .bar-prog-batt-low progress { background-color: #930006; } @@ -801,16 +815,16 @@ tooltip { border-radius: 10rem; min-width: 0.681rem; min-height: 0.681rem; - background-color: #d1c2cb; } + background-color: #bfc8ca; } .bar-batt-chargestate-charging-smaller { border-radius: 10rem; min-width: 0.409rem; min-height: 0.409rem; - background-color: #d1c2cb; } + background-color: #bfc8ca; } .corner { - background-color: #100d10; + background-color: #0b0f10; border-radius: 1.705rem; -gtk-outline-radius: 1.705rem; } @@ -822,7 +836,7 @@ tooltip { .bar-topdesc { margin-top: -0.136rem; margin-bottom: -0.341rem; - color: #a9a1a4; } + color: #a1a3a4; } .bar-space-button { padding: 0.341rem; } @@ -865,36 +879,36 @@ tooltip { padding: 0rem 0.614rem; } .bar-statusicons-hover { - background-color: #262225; } + background-color: #202425; } .bar-statusicons-active { - background-color: #3c373a; } + background-color: #36393a; } .bar-util-btn { border-radius: 9999px; -gtk-outline-radius: 9999px; min-height: 1.77rem; min-width: 1.77rem; - background-color: #3b3338; } + background-color: #2f3638; } .bar-util-btn:hover, .bar-util-btn:focus { - background-color: #4a4147; } + background-color: #3d4547; } .bar-util-btn:active { - background-color: #595055; } + background-color: #4c5355; } .cheatsheet-bg { border-radius: 1.705rem; -gtk-outline-radius: 1.705rem; - border-top: 1px solid rgba(169, 161, 165, 0.19); - border-left: 1px solid rgba(169, 161, 165, 0.19); - border-right: 1px solid rgba(134, 126, 130, 0.145); - border-bottom: 1px solid rgba(134, 126, 130, 0.145); + border-top: 1px solid rgba(161, 163, 165, 0.19); + border-left: 1px solid rgba(161, 163, 165, 0.19); + border-right: 1px solid rgba(125, 128, 130, 0.145); + border-bottom: 1px solid rgba(125, 128, 130, 0.145); box-shadow: 0px 2px 3px rgba(0, 0, 0, 0.45); margin: 0.476rem; margin-bottom: 0.682rem; - background-color: #100d10; + background-color: #0b0f10; padding: 1.364rem; } .cheatsheet-key { @@ -905,16 +919,16 @@ tooltip { padding: 0.136rem 0.205rem; border-radius: 0.409rem; -gtk-outline-radius: 0.409rem; - color: #ffc4f5; - border: 0.068rem solid #ffc4f5; - box-shadow: 0rem 0.136rem 0rem #ffc4f5; + color: #85e3f4; + border: 0.068rem solid #85e3f4; + box-shadow: 0rem 0.136rem 0rem #85e3f4; font-weight: 500; } .cheatsheet-key-notkey { min-height: 1.364rem; padding: 0.136rem 0.205rem; margin: 0.17rem; - color: #ffd6f5; } + color: #9cefff; } .cheatsheet-closebtn { transition: 300ms cubic-bezier(0.1, 1, 0, 1); @@ -943,12 +957,12 @@ tooltip { .bg-time-clock { font-family: 'Gabarito'; font-size: 5.795rem; - color: #eae0e4; } + color: #e1e3e4; } .bg-time-date { font-family: 'Gabarito'; font-size: 2.591rem; - color: #eae0e4; } + color: #e1e3e4; } .bg-distro-box { border-radius: 1.705rem; @@ -959,12 +973,12 @@ tooltip { .bg-distro-txt { font-family: 'Gabarito'; font-size: 1.432rem; - color: #eae0e4; } + color: #e1e3e4; } .bg-distro-name { font-family: 'Gabarito'; font-size: 1.432rem; - color: #f8daee; } + color: #cde7ed; } .bg-graph { color: rgba(255, 255, 255, 0.5); @@ -973,25 +987,25 @@ tooltip { .bg-quicklaunch-title { font-family: "Rubik", "Geist", "AR One Sans", "Reddit Sans", "Inter", "Roboto", "Ubuntu", "Noto Sans", sans-serif; - color: #d1c2cb; } + color: #bfc8ca; } .bg-quicklaunch-btn { font-family: "Rubik", "Geist", "AR One Sans", "Reddit Sans", "Inter", "Roboto", "Ubuntu", "Noto Sans", sans-serif; border-radius: 9999px; -gtk-outline-radius: 9999px; - background-color: #3b3338; - color: #d1c2cb; - border: 0.068rem solid #a9a1a4; + background-color: #2f3638; + color: #bfc8ca; + border: 0.068rem solid #a1a3a4; min-width: 4.432rem; min-height: 2.045rem; padding: 0.273rem 0.682rem; } .bg-quicklaunch-btn:hover, .bg-quicklaunch-btn:focus { - background-color: #433a3f; } + background-color: #363d3f; } .bg-quicklaunch-btn:active { - background-color: #4a4147; } + background-color: #3d4547; } .bg-system-bg { border-radius: 1.159rem; @@ -1003,14 +1017,14 @@ tooltip { min-height: 4.091rem; font-size: 0px; padding: 0rem; - background-color: #3b3338; } + background-color: #2f3638; } .dock-bg { border-radius: 1.705rem; -gtk-outline-radius: 1.705rem; box-shadow: 0px 2px 3px rgba(0, 0, 0, 0.45); margin: 0.476rem; - background-color: #100d10; + background-color: #0b0f10; padding: 0.682rem; } .dock-app-btn { @@ -1020,10 +1034,10 @@ tooltip { .dock-app-btn:hover, .dock-app-btn:focus { - background-color: rgba(43, 37, 41, 0.31); } + background-color: rgba(35, 39, 41, 0.31); } .dock-app-btn:active { - background-color: rgba(63, 57, 61, 0.31); } + background-color: rgba(55, 59, 61, 0.31); } .dock-app-icon { min-width: 3.409rem; @@ -1031,20 +1045,20 @@ tooltip { .dock-separator { min-width: 0.068rem; - background-color: #3b3338; } + background-color: #2f3638; } .osd-bg { min-width: 8.864rem; min-height: 3.409rem; } .osd-value { - border-top: 1px solid rgba(169, 161, 165, 0.19); - border-left: 1px solid rgba(169, 161, 165, 0.19); - border-right: 1px solid rgba(134, 126, 130, 0.145); - border-bottom: 1px solid rgba(134, 126, 130, 0.145); + border-top: 1px solid rgba(161, 163, 165, 0.19); + border-left: 1px solid rgba(161, 163, 165, 0.19); + border-right: 1px solid rgba(125, 128, 130, 0.145); + border-bottom: 1px solid rgba(125, 128, 130, 0.145); box-shadow: 0px 2px 3px rgba(0, 0, 0, 0.45); margin: 0.476rem; - background-color: #100d10; + background-color: #0b0f10; border-radius: 1.023rem; padding: 0.625rem 1.023rem; padding-top: 0.313rem; } @@ -1059,36 +1073,36 @@ tooltip { min-height: 0.954rem; min-width: 0.068rem; border-radius: 10rem; - background-color: #554050; } + background-color: #334a4f; } .osd-progress progress { transition: 200ms cubic-bezier(0.1, 1, 0, 1); min-height: 0.680rem; min-width: 0.680rem; margin: 0rem 0.137rem; border-radius: 10rem; - background-color: #f8daee; } + background-color: #cde7ed; } .osd-icon { - color: #ffd6f5; } + color: #9cefff; } .osd-label { font-size: 1.023rem; font-weight: 500; - color: #eae0e4; + color: #e1e3e4; margin-top: 0.341rem; } .osd-value-txt { font-family: "Gabarito", "Poppins", "Lexend", sans-serif; font-size: 1.688rem; font-weight: 500; - color: #eae0e4; } + color: #e1e3e4; } .osd-notifs { padding-top: 0.313rem; } .osd-colorscheme { border-radius: 1.023rem; - background-color: #100d10; + background-color: #0b0f10; padding: 1.023rem; box-shadow: 0px 2px 3px rgba(0, 0, 0, 0.45); margin: 0.476rem; } @@ -1106,46 +1120,46 @@ tooltip { margin: 0.409rem; } .osd-color-primary { - background-color: #ffc4f5; - color: #551251; } + background-color: #85e3f4; + color: #00363f; } .osd-color-primary box { - background-color: #551251; } + background-color: #00363f; } .osd-color-primaryContainer { - background-color: #7e4178; - color: #ffd6f5; } + background-color: #1a606b; + color: #9cefff; } .osd-color-primaryContainer box { - background-color: #ffd6f5; } + background-color: #9cefff; } .osd-color-secondary { - background-color: #dbbed2; - color: #3d2b39; } + background-color: #b1cbd1; + color: #1c3439; } .osd-color-secondary box { - background-color: #3d2b39; } + background-color: #1c3439; } .osd-color-secondaryContainer { - background-color: #554050; - color: #f8daee; } + background-color: #334a4f; + color: #cde7ed; } .osd-color-secondaryContainer box { - background-color: #f8daee; } + background-color: #cde7ed; } .osd-color-surfaceVariant { - background-color: #3b3338; - color: #d1c2cb; } + background-color: #2f3638; + color: #bfc8ca; } .osd-color-surfaceVariant box { - background-color: #d1c2cb; } + background-color: #bfc8ca; } .osd-color-surface { - background-color: #211b1f; - color: #eae0e4; } + background-color: #191d1f; + color: #e1e3e4; } .osd-color-surface box { - background-color: #eae0e4; } + background-color: #e1e3e4; } .osd-color-background { - background-color: #100d10; - color: #eae0e4; } + background-color: #0b0f10; + color: #e1e3e4; } .osd-color-background box { - background-color: #eae0e4; } + background-color: #e1e3e4; } .osd-show { transition: 200ms cubic-bezier(0.1, 1, 0, 1); } @@ -1160,29 +1174,29 @@ tooltip { transition: 300ms cubic-bezier(0.1, 1, 0, 1); border-radius: 1.705rem; -gtk-outline-radius: 1.705rem; - border-top: 1px solid rgba(169, 161, 165, 0.19); - border-left: 1px solid rgba(169, 161, 165, 0.19); - border-right: 1px solid rgba(134, 126, 130, 0.145); - border-bottom: 1px solid rgba(134, 126, 130, 0.145); + border-top: 1px solid rgba(161, 163, 165, 0.19); + border-left: 1px solid rgba(161, 163, 165, 0.19); + border-right: 1px solid rgba(125, 128, 130, 0.145); + border-bottom: 1px solid rgba(125, 128, 130, 0.145); box-shadow: 0px 2px 3px rgba(0, 0, 0, 0.45); margin: 0.476rem; min-width: 13.636rem; min-height: 3.409rem; padding: 0rem 1.364rem; padding-right: 2.864rem; - background-color: #100d10; - color: #eae0e4; + background-color: #0b0f10; + color: #e1e3e4; caret-color: transparent; } .overview-search-box selection { - background-color: #dbbed2; - color: #3d2b39; } + background-color: #b1cbd1; + color: #1c3439; } .overview-search-box-extended { min-width: 25.909rem; - caret-color: #f8daee; } + caret-color: #cde7ed; } .overview-search-prompt { - color: #a9a1a4; } + color: #a1a3a4; } .overview-search-icon { margin: 0rem 1.023rem; } @@ -1198,16 +1212,16 @@ tooltip { .overview-search-results { border-radius: 1.705rem; -gtk-outline-radius: 1.705rem; - border-top: 1px solid rgba(169, 161, 165, 0.19); - border-left: 1px solid rgba(169, 161, 165, 0.19); - border-right: 1px solid rgba(134, 126, 130, 0.145); - border-bottom: 1px solid rgba(134, 126, 130, 0.145); + border-top: 1px solid rgba(161, 163, 165, 0.19); + border-left: 1px solid rgba(161, 163, 165, 0.19); + border-right: 1px solid rgba(125, 128, 130, 0.145); + border-bottom: 1px solid rgba(125, 128, 130, 0.145); box-shadow: 0px 2px 3px rgba(0, 0, 0, 0.45); margin: 0.476rem; min-width: 28.773rem; padding: 0.682rem; - background-color: #100d10; - color: #eae0e4; } + background-color: #0b0f10; + color: #e1e3e4; } .overview-search-results-icon { margin: 0rem 0.682rem; @@ -1241,43 +1255,43 @@ tooltip { .overview-tasks { border-radius: 1.705rem; -gtk-outline-radius: 1.705rem; - border-top: 1px solid rgba(169, 161, 165, 0.19); - border-left: 1px solid rgba(169, 161, 165, 0.19); - border-right: 1px solid rgba(134, 126, 130, 0.145); - border-bottom: 1px solid rgba(134, 126, 130, 0.145); + border-top: 1px solid rgba(161, 163, 165, 0.19); + border-left: 1px solid rgba(161, 163, 165, 0.19); + border-right: 1px solid rgba(125, 128, 130, 0.145); + border-bottom: 1px solid rgba(125, 128, 130, 0.145); box-shadow: 0px 2px 3px rgba(0, 0, 0, 0.45); margin: 0.476rem; padding: 0.341rem; - background-color: #100d10; - color: #eae0e4; } + background-color: #0b0f10; + color: #e1e3e4; } .overview-tasks-workspace { border-radius: 1.159rem; -gtk-outline-radius: 1.159rem; margin: 0.341rem; - background-color: rgba(54, 47, 51, 0.1147); } + background-color: rgba(46, 49, 51, 0.1147); } .overview-tasks-workspace-number { font-family: "Rubik", "Geist", "AR One Sans", "Reddit Sans", "Inter", "Roboto", "Ubuntu", "Noto Sans", sans-serif; - color: rgba(220, 210, 214, 0.31); } + color: rgba(211, 213, 214, 0.31); } .overview-tasks-window { border-radius: 1.159rem; -gtk-outline-radius: 1.159rem; transition: 300ms cubic-bezier(0.1, 1, 0, 1); - background-color: rgba(85, 64, 80, 0.5); - color: #f8daee; - border: 0.068rem solid rgba(248, 218, 238, 0.07); } + background-color: rgba(51, 74, 79, 0.5); + color: #cde7ed; + border: 0.068rem solid rgba(205, 231, 237, 0.07); } .overview-tasks-window:hover, .overview-tasks-window:focus { - background-color: rgba(108, 82, 103, 0.525); } + background-color: rgba(62, 95, 102, 0.525); } .overview-tasks-window:active { - background-color: rgba(128, 97, 121, 0.55); } + background-color: rgba(72, 112, 120, 0.55); } .overview-tasks-window-selected { - background-color: rgba(128, 97, 121, 0.55); } + background-color: rgba(72, 112, 120, 0.55); } .overview-tasks-window-dragging { opacity: 0.2; } @@ -1285,13 +1299,13 @@ tooltip { .osk-window { border-radius: 1.705rem; -gtk-outline-radius: 1.705rem; - border-top: 1px solid rgba(169, 161, 165, 0.19); - border-left: 1px solid rgba(169, 161, 165, 0.19); - border-right: 1px solid rgba(134, 126, 130, 0.145); - border-bottom: 1px solid rgba(134, 126, 130, 0.145); + border-top: 1px solid rgba(161, 163, 165, 0.19); + border-left: 1px solid rgba(161, 163, 165, 0.19); + border-right: 1px solid rgba(125, 128, 130, 0.145); + border-bottom: 1px solid rgba(125, 128, 130, 0.145); box-shadow: 0px 2px 3px rgba(0, 0, 0, 0.45); margin: 0.476rem; - background-color: #100d10; } + background-color: #0b0f10; } .osk-body { padding: 1.023rem; @@ -1308,7 +1322,7 @@ tooltip { .osk-dragline { border-radius: 9999px; -gtk-outline-radius: 9999px; - background-color: #3b3338; + background-color: #2f3638; min-height: 0.273rem; min-width: 10.227rem; margin-top: 0.545rem; @@ -1316,8 +1330,8 @@ tooltip { .osk-key { border-radius: 0.682rem; - background-color: rgba(59, 51, 56, 0.31); - color: #d1c2cb; + background-color: rgba(47, 54, 56, 0.31); + color: #bfc8ca; padding: 0.188rem; font-weight: 500; font-size: 1.091rem; } @@ -1359,31 +1373,31 @@ tooltip { .osk-control-button { border-radius: 0.682rem; - background-color: rgba(59, 51, 56, 0.31); - color: #d1c2cb; + background-color: rgba(47, 54, 56, 0.31); + color: #bfc8ca; font-weight: 500; font-size: 1.091rem; padding: 0.682rem; } .osk-control-button:hover, .osk-control-button:focus { - background-color: rgba(74, 65, 71, 0.31); } + background-color: rgba(61, 69, 71, 0.31); } .osk-control-button:active { - background-color: rgba(104, 94, 100, 0.31); + background-color: rgba(90, 98, 100, 0.31); font-size: 1.091rem; } .sidebar-right { transition: 300ms cubic-bezier(0.1, 1, 0, 1); - border-top: 1px solid rgba(169, 161, 165, 0.19); - border-left: 1px solid rgba(169, 161, 165, 0.19); - border-right: 1px solid rgba(134, 126, 130, 0.145); - border-bottom: 1px solid rgba(134, 126, 130, 0.145); + border-top: 1px solid rgba(161, 163, 165, 0.19); + border-left: 1px solid rgba(161, 163, 165, 0.19); + border-right: 1px solid rgba(125, 128, 130, 0.145); + border-bottom: 1px solid rgba(125, 128, 130, 0.145); box-shadow: 0px 2px 3px rgba(0, 0, 0, 0.45); margin: 0.476rem; border-radius: 1.297rem; min-width: 27.818rem; - background-color: #100d10; + background-color: #0b0f10; padding: 1.023rem; } .sideright-show { @@ -1395,15 +1409,15 @@ tooltip { .sidebar-left { transition: 300ms cubic-bezier(0.1, 1, 0, 1); - border-top: 1px solid rgba(169, 161, 165, 0.19); - border-left: 1px solid rgba(169, 161, 165, 0.19); - border-right: 1px solid rgba(134, 126, 130, 0.145); - border-bottom: 1px solid rgba(134, 126, 130, 0.145); + border-top: 1px solid rgba(161, 163, 165, 0.19); + border-left: 1px solid rgba(161, 163, 165, 0.19); + border-right: 1px solid rgba(125, 128, 130, 0.145); + border-bottom: 1px solid rgba(125, 128, 130, 0.145); box-shadow: 0px 2px 3px rgba(0, 0, 0, 0.45); margin: 0.476rem; border-radius: 1.297rem; min-width: 27.818rem; - background-color: #100d10; + background-color: #0b0f10; padding: 1.023rem; } .sideleft-show { @@ -1417,12 +1431,12 @@ tooltip { border-radius: 1.159rem; -gtk-outline-radius: 1.159rem; padding: 0.341rem; - background-color: rgba(33, 27, 31, 0.31); } + background-color: rgba(25, 29, 31, 0.31); } .sidebar-group-nopad { border-radius: 1.159rem; -gtk-outline-radius: 1.159rem; - background-color: rgba(33, 27, 31, 0.31); } + background-color: rgba(25, 29, 31, 0.31); } .sidebar-group-invisible { padding: 0.341rem; } @@ -1434,13 +1448,13 @@ tooltip { border-radius: 9999px; -gtk-outline-radius: 9999px; padding: 0.341rem; - background-color: rgba(33, 27, 31, 0.31); } + background-color: rgba(25, 29, 31, 0.31); } .sidebar-iconbutton { border-radius: 9999px; -gtk-outline-radius: 9999px; transition: 300ms cubic-bezier(0.1, 1, 0, 1); - color: #eae0e4; + color: #e1e3e4; min-width: 2.727rem; min-height: 2.727rem; } @@ -1454,13 +1468,13 @@ tooltip { .sidebar-button { transition: 300ms cubic-bezier(0.1, 1, 0, 1); padding: 0rem 0.818rem; - background-color: #554050; - color: #f8daee; } + background-color: #334a4f; + color: #cde7ed; } .sidebar-button-nopad { transition: 300ms cubic-bezier(0.1, 1, 0, 1); - background-color: #554050; - color: #f8daee; } + background-color: #334a4f; + color: #cde7ed; } .sidebar-button:hover, .sidebar-button:focus { @@ -1493,20 +1507,20 @@ tooltip { -gtk-outline-radius: 0.818rem; } .sidebar-button-active { - background-color: #ffc4f5; - color: #551251; } + background-color: #85e3f4; + color: #00363f; } .sidebar-button-active:hover, .sidebar-button-active:focus { - background-color: rgba(246, 191, 237, 0.79); } + background-color: rgba(133, 220, 236, 0.79); } .sidebar-button-active:active { - background-color: rgba(228, 182, 221, 0.58); } + background-color: rgba(132, 206, 220, 0.58); } .sidebar-buttons-separator { min-width: 0.068rem; min-height: 0.068rem; - background-color: #d1c2cb; } + background-color: #bfc8ca; } .sidebar-navrail { padding: 0rem 1.159rem; } @@ -1524,13 +1538,13 @@ tooltip { background-color: rgba(128, 128, 128, 0.7); } .sidebar-navrail-btn-active > box > label:first-child { - background-color: #554050; - color: #f8daee; } + background-color: #334a4f; + color: #cde7ed; } .sidebar-navrail-btn-active:hover > box > label:first-child, .sidebar-navrail-btn-active:focus > box > label:first-child { - background-color: rgba(86, 65, 81, 0.93); - color: rgba(246, 216, 236, 0.93); } + background-color: rgba(52, 75, 80, 0.93); + color: rgba(204, 229, 235, 0.93); } .sidebar-sysinfo-grouppad { padding: 1.159rem; } @@ -1540,8 +1554,8 @@ tooltip { min-width: 0.818rem; min-height: 4.091rem; padding: 0.409rem; - background-color: #554050; - color: #f8daee; + background-color: #334a4f; + color: #cde7ed; font-size: 0px; } .sidebar-memory-swap-circprog { @@ -1550,16 +1564,16 @@ tooltip { min-height: 2.255rem; padding: 0.409rem; margin: 0.918rem; - background-color: #554050; - color: #f8daee; + background-color: #334a4f; + color: #cde7ed; font-size: 0px; } .sidebar-cpu-circprog { min-width: 0.818rem; min-height: 3.409rem; padding: 0.409rem; - background-color: #554050; - color: #f8daee; + background-color: #334a4f; + color: #cde7ed; transition: 1000ms cubic-bezier(0.1, 1, 0, 1); font-size: 0px; } @@ -1574,14 +1588,14 @@ tooltip { -gtk-outline-radius: 9999px; min-width: 0.273rem; min-height: 2.045rem; - background-color: rgba(209, 194, 203, 0.31); } + background-color: rgba(191, 200, 202, 0.31); } .sidebar-scrollbar slider:hover, .sidebar-scrollbar slider:focus { - background-color: rgba(209, 194, 203, 0.448); } + background-color: rgba(191, 200, 202, 0.448); } .sidebar-scrollbar slider:active { - background-color: #867b82; } + background-color: #777f81; } .sidebar-calendar-btn { border-radius: 9999px; @@ -1589,7 +1603,7 @@ tooltip { transition: 300ms cubic-bezier(0.1, 1, 0, 1); min-height: 2.523rem; min-width: 2.523rem; - color: #eae0e4; } + color: #e1e3e4; } .sidebar-calendar-btn:hover, .sidebar-calendar-btn:focus { @@ -1603,18 +1617,18 @@ tooltip { margin-right: -10.341rem; } .sidebar-calendar-btn-today { - background-color: #ffc4f5; - color: #551251; } + background-color: #85e3f4; + color: #00363f; } .sidebar-calendar-btn-today:hover, .sidebar-calendar-btn-today:focus { - background-color: rgba(246, 191, 237, 0.79); } + background-color: rgba(133, 220, 236, 0.79); } .sidebar-calendar-btn-today:active { - background-color: rgba(228, 182, 221, 0.58); } + background-color: rgba(132, 206, 220, 0.58); } .sidebar-calendar-btn-othermonth { - color: #867e82; } + color: #7d8082; } .sidebar-calendar-header { margin: 0.341rem; } @@ -1623,40 +1637,40 @@ tooltip { border-radius: 9999px; -gtk-outline-radius: 9999px; padding: 0rem 0.682rem; - background-color: rgba(59, 51, 56, 0.31); - color: #d1c2cb; } + background-color: rgba(47, 54, 56, 0.31); + color: #bfc8ca; } .sidebar-calendar-monthyear-btn:hover, .sidebar-calendar-monthyear-btn:focus { background-color: rgba(128, 128, 128, 0.3); - color: #cabbc4; } + color: #b8c1c3; } .sidebar-calendar-monthyear-btn:active { background-color: rgba(128, 128, 128, 0.7); - color: #bbadb5; } + color: #a9b2b4; } .sidebar-calendar-monthshift-btn { border-radius: 9999px; -gtk-outline-radius: 9999px; min-width: 2.045rem; min-height: 2.045rem; - background-color: rgba(59, 51, 56, 0.31); - color: #d1c2cb; } + background-color: rgba(47, 54, 56, 0.31); + color: #bfc8ca; } .sidebar-calendar-monthshift-btn:hover { background-color: rgba(128, 128, 128, 0.3); - color: #cabbc4; } + color: #b8c1c3; } .sidebar-calendar-monthshift-btn:active { background-color: rgba(128, 128, 128, 0.7); - color: #bbadb5; } + color: #a9b2b4; } .sidebar-selector-tab { border-radius: 0.818rem; -gtk-outline-radius: 0.818rem; transition: 300ms cubic-bezier(0.1, 1, 0, 1); min-height: 2.5rem; - color: #eae0e4; } + color: #e1e3e4; } .sidebar-selector-tab:hover, .sidebar-selector-tab:focus { @@ -1666,7 +1680,7 @@ tooltip { background-color: rgba(128, 128, 128, 0.7); } .sidebar-selector-tab-active > box > label { - color: #ffc4f5; } + color: #85e3f4; } .sidebar-selector-highlight-offset { margin-top: -0.205rem; @@ -1674,14 +1688,14 @@ tooltip { .sidebar-selector-highlight { transition: 180ms ease-in-out; - color: #ffc4f5; + color: #85e3f4; min-height: 0.205rem; } .sidebar-todo-item { padding-right: 0.545rem; } .sidebar-todo-item-even { - background-color: rgba(59, 51, 56, 0.1); } + background-color: rgba(47, 54, 56, 0.1); } .sidebar-todo-item-action { border-radius: 9999px; @@ -1700,7 +1714,7 @@ tooltip { min-width: 0rem; } .sidebar-todo-crosser-crossed { - background-color: #eae0e4; } + background-color: #e1e3e4; } .sidebar-todo-crosser-removed { background-color: #ffb4a9; } @@ -1708,17 +1722,17 @@ tooltip { .sidebar-todo-new { border-radius: 9999px; -gtk-outline-radius: 9999px; - color: #f8daee; + color: #cde7ed; margin: 0.341rem; padding: 0.205rem 0.545rem; - border: 0.068rem solid #eae0e4; } + border: 0.068rem solid #e1e3e4; } .sidebar-todo-newz, .sidebar-todo-new:focus { - background-color: #5a4555; } + background-color: #384f54; } .sidebar-todo-new:active { - background-color: #765f70; } + background-color: #52696f; } .sidebar-todo-add { border-radius: 9999px; @@ -1726,15 +1740,15 @@ tooltip { transition: 300ms cubic-bezier(0.1, 1, 0, 1); min-width: 1.705rem; min-height: 1.705rem; - color: #f8daee; - border: 0.068rem solid #eae0e4; } + color: #cde7ed; + border: 0.068rem solid #e1e3e4; } .sidebar-todo-add:hover, .sidebar-todo-add:focus { - background-color: #5a4555; } + background-color: #384f54; } .sidebar-todo-add:active { - background-color: #765f70; } + background-color: #52696f; } .sidebar-todo-add-available { transition: 300ms cubic-bezier(0.1, 1, 0, 1); @@ -1742,44 +1756,44 @@ tooltip { -gtk-outline-radius: 9999px; min-width: 1.705rem; min-height: 1.705rem; - background-color: #ffc4f5; - color: #551251; - border: 0.068rem solid #ffc4f5; } + background-color: #85e3f4; + color: #00363f; + border: 0.068rem solid #85e3f4; } .sidebar-todo-add-available:hover, .sidebar-todo-add-available:focus { - background-color: #fabff0; } + background-color: #81deef; } .sidebar-todo-add-available:active { - background-color: #dda0d4; } + background-color: #6ac0d0; } .sidebar-todo-entry { transition: 300ms cubic-bezier(0.1, 1, 0, 1); border-radius: 0.818rem; -gtk-outline-radius: 0.818rem; - background-color: #3b3338; - color: #d1c2cb; - caret-color: #d1c2cb; + background-color: #2f3638; + color: #bfc8ca; + caret-color: #bfc8ca; margin: 0rem 0.341rem; min-height: 1.773rem; min-width: 0rem; padding: 0.205rem 0.682rem; - border: 0.068rem solid #867b82; } + border: 0.068rem solid #777f81; } .sidebar-todo-entry:focus { - border: 0.068rem solid #c2b4bc; } + border: 0.068rem solid #b1b9bb; } .sidebar-module { border-radius: 1.159rem; -gtk-outline-radius: 1.159rem; padding: 0.341rem; - background-color: rgba(33, 27, 31, 0.31); } + background-color: rgba(25, 29, 31, 0.31); } .sidebar-module-btn-arrow { border-radius: 9999px; -gtk-outline-radius: 9999px; font-family: "Material Symbols Rounded", "Material Symbols Outlined", "Material Symbols Sharp"; - background-color: rgba(59, 51, 56, 0.31); + background-color: rgba(47, 54, 56, 0.31); min-width: 1.705rem; min-height: 1.705rem; } @@ -1787,7 +1801,7 @@ tooltip { border-radius: 9999px; -gtk-outline-radius: 9999px; padding: 0.341rem; - background-color: rgba(33, 27, 31, 0.31); } + background-color: rgba(25, 29, 31, 0.31); } .sidebar-chat-apiswitcher-icon { transition: 300ms cubic-bezier(0.1, 1, 0, 1); @@ -1795,11 +1809,11 @@ tooltip { -gtk-outline-radius: 9999px; min-width: 2.182rem; min-height: 2.182rem; - color: #eae0e4; } + color: #e1e3e4; } .sidebar-chat-apiswitcher-icon-enabled { - background-color: #554050; - color: #f8daee; } + background-color: #334a4f; + color: #cde7ed; } .sidebar-chat-viewport { transition: 300ms cubic-bezier(0.1, 1, 0, 1); @@ -1808,12 +1822,12 @@ tooltip { .sidebar-chat-textarea { border-radius: 1.159rem; -gtk-outline-radius: 1.159rem; - border: 0.068rem solid #776c73; + border: 0.068rem solid #697072; padding: 0.682rem; } .sidebar-chat-entry { - color: #d1c2cb; - caret-color: #d1c2cb; + color: #bfc8ca; + caret-color: #bfc8ca; min-height: 1.773rem; min-width: 0rem; } @@ -1822,25 +1836,25 @@ tooltip { min-width: 1.705rem; min-height: 1.705rem; border-radius: 0.478rem; - background-color: #776c73; } + background-color: #697072; } .sidebar-chat-send:hover, .sidebar-chat-send:focus { - background-color: #7b6f77; } + background-color: #6c7476; } .sidebar-chat-send:active { - background-color: #91828c; } + background-color: #7d888b; } .sidebar-chat-send-available { - background-color: #ffc4f5; - color: #551251; } + background-color: #85e3f4; + color: #00363f; } .sidebar-chat-send-available:hover, .sidebar-chat-send-available:focus { - background-color: #fabff0; } + background-color: #81deef; } .sidebar-chat-send-available:active { - background-color: #dda0d4; } + background-color: #6ac0d0; } .sidebar-chat-message { margin: 0.682rem; } @@ -1850,16 +1864,16 @@ tooltip { border-radius: 9999px; -gtk-outline-radius: 9999px; min-width: 0.136rem; - background-color: #eae0e4; } + background-color: #e1e3e4; } .sidebar-chat-indicator-user { - background-color: #eae0e4; } + background-color: #e1e3e4; } .sidebar-chat-indicator-bot { - background-color: #ffc4f5; } + background-color: #85e3f4; } .sidebar-chat-indicator-System { - background-color: #dbbed2; } + background-color: #b1cbd1; } .sidebar-chat-name { font-family: "Gabarito", "Poppins", "Lexend", sans-serif; @@ -1878,19 +1892,19 @@ tooltip { .sidebar-chat-codeblock { border-radius: 1.159rem; -gtk-outline-radius: 1.159rem; - background-color: rgba(89, 80, 85, 0.31); - color: #d1c2cb; + background-color: rgba(76, 83, 85, 0.31); + color: #bfc8ca; margin: 0rem 0.682rem; - border: 0.068rem solid rgba(248, 218, 238, 0.07); } + border: 0.068rem solid rgba(205, 231, 237, 0.07); } .sidebar-chat-codeblock-topbar { font-family: "Rubik", "Geist", "AR One Sans", "Reddit Sans", "Inter", "Roboto", "Ubuntu", "Noto Sans", sans-serif; margin: 0.273rem; margin-bottom: 0rem; - background-color: rgba(122, 103, 117, 0.517); - color: #f8daee; + background-color: rgba(93, 112, 116, 0.517); + color: #cde7ed; border-radius: 0.886rem; - border: 0.068rem solid #654f60; + border: 0.068rem solid #425a5f; border-top-left-radius: 0.886rem; border-top-right-radius: 0.886rem; padding: 0.341rem 0.477rem; } @@ -1907,10 +1921,10 @@ tooltip { .sidebar-chat-codeblock-topbar-btn:hover, .sidebar-chat-codeblock-topbar-btn:focus { - background-color: #765f70; } + background-color: #52696f; } .sidebar-chat-codeblock-topbar-btn:active { - background-color: #967e8f; } + background-color: #71898e; } .sidebar-chat-codeblock-code { font-family: "JetBrains Mono NF", "JetBrains Mono Nerd Font", "JetBrains Mono NL", "SpaceMono NF", "SpaceMono Nerd Font", monospace; @@ -1918,7 +1932,7 @@ tooltip { .sidebar-chat-divider { min-height: 1px; - background-color: #776c73; + background-color: #697072; margin: 0rem 0.545rem; } .sidebar-chat-welcome-txt { @@ -1949,7 +1963,7 @@ tooltip { padding: 0.341rem 0.477rem; } .sidebar-chat-chip-action { - border: 0.068rem solid #776c73; } + border: 0.068rem solid #697072; } .sidebar-chat-chip-action:hover, .sidebar-chat-chip-action:focus { @@ -1959,16 +1973,16 @@ tooltip { background-color: rgba(128, 128, 128, 0.7); } .sidebar-chat-chip-action-active { - color: #776c73; - border: 0.068rem solid #776c73; } + color: #697072; + border: 0.068rem solid #697072; } .sidebar-chat-chip-toggle { transition: 300ms cubic-bezier(0.1, 1, 0, 1); border-radius: 0.818rem; -gtk-outline-radius: 0.818rem; padding: 0.341rem 0.477rem; - background-color: rgba(59, 51, 56, 0.31); - color: #d1c2cb; } + background-color: rgba(47, 54, 56, 0.31); + color: #bfc8ca; } .sidebar-chat-chip-toggle:focus, .sidebar-chat-chip-toggle:hover { @@ -1983,7 +1997,7 @@ tooltip { transition: 300ms cubic-bezier(0.1, 1, 0, 1); min-height: 2.386rem; min-width: 2.386rem; - color: #eae0e4; } + color: #e1e3e4; } .sidebar-pin:hover, .sidebar-pin:focus { @@ -1993,16 +2007,16 @@ tooltip { background-color: rgba(128, 128, 128, 0.7); } .sidebar-pin-enabled { - background-color: #ffc4f5; } + background-color: #85e3f4; } .sidebar-pin-enabled label { - color: #551251; } + color: #00363f; } .sidebar-pin-enabled:hover, .sidebar-pin-enabled:focus { - background-color: #eeb2e5; } + background-color: #78d2e2; } .sidebar-pin-enabled:active { - background-color: #dda0d4; } + background-color: #6ac0d0; } .sidebar-waifu-heading { font-family: "Gabarito", "Poppins", "Lexend", sans-serif; @@ -2045,24 +2059,24 @@ tooltip { .session-bg { margin-top: -2.727rem; - background-color: rgba(16, 13, 16, 0.64); } + background-color: rgba(11, 15, 16, 0.64); } .session-button { border-radius: 1.705rem; -gtk-outline-radius: 1.705rem; min-width: 8.182rem; min-height: 8.182rem; - background-color: #3b3338; - color: #d1c2cb; + background-color: #2f3638; + color: #bfc8ca; font-size: 3rem; } .session-button-focused { - background-color: #554050; - color: #f8daee; } + background-color: #334a4f; + color: #cde7ed; } .session-button-desc { - background-color: #2e272c; - color: #ded1d8; + background-color: #242a2c; + color: #d0d6d7; border-bottom-left-radius: 1.705rem; border-bottom-right-radius: 1.705rem; padding: 0.205rem 0.341rem; @@ -2073,31 +2087,31 @@ tooltip { -gtk-outline-radius: 1.705rem; min-width: 8.182rem; min-height: 5.455rem; - background-color: #3b3338; - color: #d1c2cb; + background-color: #2f3638; + color: #bfc8ca; font-size: 3rem; } .notif-low { border-radius: 1.159rem; -gtk-outline-radius: 1.159rem; - background-color: rgba(59, 51, 56, 0.45); - color: #d1c2cb; + background-color: rgba(47, 54, 56, 0.45); + color: #bfc8ca; padding: 0.818rem; padding-right: 1.363rem; } .notif-normal { border-radius: 1.159rem; -gtk-outline-radius: 1.159rem; - background-color: rgba(59, 51, 56, 0.45); - color: #d1c2cb; + background-color: rgba(47, 54, 56, 0.45); + color: #bfc8ca; padding: 0.818rem; padding-right: 1.363rem; } .notif-critical { border-radius: 1.159rem; -gtk-outline-radius: 1.159rem; - background-color: #554050; - color: #f8daee; + background-color: #334a4f; + color: #cde7ed; padding: 0.818rem; padding-right: 1.363rem; } @@ -2105,8 +2119,8 @@ tooltip { border-radius: 1.159rem; -gtk-outline-radius: 1.159rem; min-width: 30.682rem; - background-color: #100d10; - color: #d1c2cb; + background-color: #0b0f10; + color: #bfc8ca; padding: 0.818rem; padding-right: 1.363rem; } @@ -2114,8 +2128,8 @@ tooltip { border-radius: 1.159rem; -gtk-outline-radius: 1.159rem; min-width: 30.682rem; - background-color: #100d10; - color: #d1c2cb; + background-color: #0b0f10; + color: #bfc8ca; padding: 0.818rem; padding-right: 1.363rem; } @@ -2123,19 +2137,19 @@ tooltip { border-radius: 1.159rem; -gtk-outline-radius: 1.159rem; min-width: 30.682rem; - background-color: #554050; - color: #f8daee; + background-color: #334a4f; + color: #cde7ed; padding: 0.818rem; padding-right: 1.363rem; } .notif-body-low { - color: #a0939a; } + color: #8f989a; } .notif-body-normal { - color: #a0939a; } + color: #8f989a; } .notif-body-critical { - color: #c2a7ba; } + color: #9ab3b9; } .notif-icon { border-radius: 9999px; @@ -2144,20 +2158,20 @@ tooltip { min-height: 3.409rem; } .notif-icon-material { - background-color: #554050; - color: #f8daee; } + background-color: #334a4f; + color: #cde7ed; } .notif-icon-material-low { - background-color: #554050; - color: #f8daee; } + background-color: #334a4f; + color: #cde7ed; } .notif-icon-material-normal { - background-color: #554050; - color: #f8daee; } + background-color: #334a4f; + color: #cde7ed; } .notif-icon-material-critical { - background-color: #f8daee; - color: #554050; } + background-color: #cde7ed; + color: #334a4f; } .notif-expand-btn { border-radius: 1.159rem; @@ -2185,20 +2199,20 @@ tooltip { background-color: rgba(128, 128, 128, 0.7); } .notif-listaction-btn-enabled { - background-color: #554050; - color: #f8daee; } + background-color: #334a4f; + color: #cde7ed; } .notif-listaction-btn-enabled:hover, .notif-listaction-btn-enabled:focus { - background-color: #654f60; } + background-color: #425a5f; } .notif-listaction-btn-enabled:active { - background-color: #7e6778; } + background-color: #5a7177; } .osd-notif { border-radius: 1.159rem; -gtk-outline-radius: 1.159rem; - background-color: rgba(16, 13, 16, 0.46); + background-color: rgba(11, 15, 16, 0.46); min-width: 30.682rem; } .notif-circprog-low { @@ -2206,21 +2220,21 @@ tooltip { min-width: 0.136rem; min-height: 3.136rem; padding: 0rem; - color: #f8daee; } + color: #cde7ed; } .notif-circprog-normal { transition: 0ms linear; min-width: 0.136rem; min-height: 3.136rem; padding: 0rem; - color: #f8daee; } + color: #cde7ed; } .notif-circprog-critical { transition: 0ms linear; min-width: 0.136rem; min-height: 3.136rem; padding: 0rem; - color: #554050; } + color: #334a4f; } .notif-actions { min-height: 2.045rem; } @@ -2230,8 +2244,8 @@ tooltip { -gtk-outline-radius: 0.818rem; } .notif-action-low { - background-color: rgba(51, 44, 48, 0.31); - color: #d1c2cb; } + background-color: rgba(42, 46, 48, 0.31); + color: #bfc8ca; } .notif-action-low:focus, .notif-action-low:hover { @@ -2241,8 +2255,8 @@ tooltip { background-color: rgba(128, 128, 128, 0.7); } .notif-action-normal { - background-color: rgba(51, 44, 48, 0.31); - color: #d1c2cb; } + background-color: rgba(42, 46, 48, 0.31); + color: #bfc8ca; } .notif-action-normal:focus, .notif-action-normal:hover { @@ -2252,15 +2266,15 @@ tooltip { background-color: rgba(128, 128, 128, 0.7); } .notif-action-critical { - background-color: #654f60; - color: #d1c2cb; } + background-color: #425a5f; + color: #bfc8ca; } .notif-action-critical:focus, .notif-action-critical:hover { - background-color: #725c6c; } + background-color: #4f666b; } .notif-action-critical:active { - background-color: #7a6374; } + background-color: #566e73; } .osd-music { transition: 300ms cubic-bezier(0.1, 1, 0, 1); @@ -2270,9 +2284,9 @@ tooltip { border-radius: 1.159rem; -gtk-outline-radius: 1.159rem; min-width: 29.659rem; - background-color: #100d10; + background-color: #0b0f10; padding: 0rem 1.023rem; - background: linear-gradient(127deg, rgba(47, 41, 46, 0.7), rgba(47, 41, 46, 0.55) 70.71%), linear-gradient(217deg, rgba(78, 68, 75, 0.7), rgba(78, 68, 75, 0.55) 70.71%), radial-gradient(circle at 0% 100%, #554050 13%, rgba(0, 0, 0, 0) 100%), linear-gradient(336deg, rgba(85, 64, 80, 0.7), rgba(85, 64, 80, 0.55) 70.71%), linear-gradient(#100d10, #100d10); } + background: linear-gradient(127deg, rgba(37, 44, 45, 0.7), rgba(37, 44, 45, 0.55) 70.71%), linear-gradient(217deg, rgba(63, 72, 74, 0.7), rgba(63, 72, 74, 0.55) 70.71%), radial-gradient(circle at 0% 100%, #334a4f 13%, rgba(0, 0, 0, 0) 100%), linear-gradient(336deg, rgba(51, 74, 79, 0.7), rgba(51, 74, 79, 0.55) 70.71%), linear-gradient(#0b0f10, #0b0f10); } .osd-music-cover-fallback { transition: 300ms cubic-bezier(0.1, 1, 0, 1); @@ -2280,8 +2294,8 @@ tooltip { -gtk-outline-radius: 0.818rem; min-width: 7.5rem; min-height: 7.5rem; - background-color: rgba(33, 27, 31, 0.31); - color: #dad0d5; } + background-color: rgba(25, 29, 31, 0.31); + color: #d1d4d5; } .osd-music-cover { border-radius: 0.818rem; @@ -2307,13 +2321,13 @@ tooltip { transition: 300ms cubic-bezier(0.1, 1, 0, 1); font-family: "Gabarito", "Poppins", "Lexend", sans-serif; font-size: 1.364rem; - color: #dad0d5; } + color: #d1d4d5; } .osd-music-artists { transition: 300ms cubic-bezier(0.1, 1, 0, 1); font-family: "Rubik", "Geist", "AR One Sans", "Reddit Sans", "Inter", "Roboto", "Ubuntu", "Noto Sans", sans-serif; font-size: 0.955rem; - color: rgba(205, 196, 201, 0.9); } + color: rgba(196, 200, 201, 0.9); } .osd-music-pill { transition: 300ms cubic-bezier(0.1, 1, 0, 1); @@ -2322,8 +2336,8 @@ tooltip { font-family: "Gabarito", "Poppins", "Lexend", sans-serif; min-width: 1.833rem; padding: 0.273rem 0.682rem; - background-color: rgba(55, 46, 53, 0.5); - color: #dad0d5; } + background-color: rgba(40, 50, 52, 0.5); + color: #d1d4d5; } .osd-music-controls { transition: 300ms cubic-bezier(0.1, 1, 0, 1); @@ -2332,8 +2346,8 @@ tooltip { font-family: "Gabarito", "Poppins", "Lexend", sans-serif; min-width: 1.833rem; padding: 0.205rem; - background-color: rgba(55, 46, 53, 0.5); - color: #dad0d5; } + background-color: rgba(40, 50, 52, 0.5); + color: #d1d4d5; } .osd-music-controlbtn { transition: 300ms cubic-bezier(0.1, 1, 0, 1); @@ -2344,10 +2358,10 @@ tooltip { .osd-music-controlbtn:hover, .osd-music-controlbtn:focus { - background-color: rgba(96, 87, 93, 0.55); } + background-color: rgba(82, 91, 92, 0.55); } .osd-music-controlbtn:active { - background-color: rgba(111, 102, 108, 0.575); } + background-color: rgba(99, 106, 108, 0.575); } .osd-music-controlbtn-txt { transition: 300ms cubic-bezier(0.1, 1, 0, 1); @@ -2361,15 +2375,15 @@ tooltip { min-width: 0.409rem; min-height: 3.068rem; padding: 0.273rem; - color: #dad0d5; } + color: #d1d4d5; } .osd-music-playstate { transition: 300ms cubic-bezier(0.1, 1, 0, 1); min-height: 3.068rem; min-width: 3.068rem; border-radius: 10rem; - background-color: rgba(55, 46, 53, 0.5); - color: #dad0d5; } + background-color: rgba(40, 50, 52, 0.5); + color: #d1d4d5; } .osd-music-playstate-btn > label { transition: 50ms cubic-bezier(0.05, 0.7, 0.1, 1); diff --git a/.config/ags/widgets/bar/leftspace.js b/.config/ags/widgets/bar/leftspace.js index 588dc8733..9f7d6111e 100644 --- a/.config/ags/widgets/bar/leftspace.js +++ b/.config/ags/widgets/bar/leftspace.js @@ -1,44 +1,42 @@ -import { App, Service, Utils, Widget } from '../../imports.js'; +import App from 'resource:///com/github/Aylur/ags/app.js'; +import Widget from 'resource:///com/github/Aylur/ags/widget.js'; import Hyprland from 'resource:///com/github/Aylur/ags/service/hyprland.js'; -const { CONFIG_DIR, exec, execAsync } = Utils; -import { setupCursorHover } from "../../lib/cursorhover.js"; import { RoundedCorner } from "../../lib/roundedcorner.js"; import Brightness from '../../services/brightness.js'; import Indicator from '../../services/indicator.js'; -// Removes everything after the last -// em dash, en dash, minus, vertical bar, or middle dot (note: maybe add open parenthesis?) -// For example: -// • Discord | #ricing-theming | r/unixporn — Mozilla Firefox --> • Discord | #ricing-theming -// GJS Error · Issue #112 · Aylur/ags — Mozilla Firefox --> GJS Error · Issue #112 -function truncateTitle(str) { - let lastDash = -1; - let found = -1; // 0: em dash, 1: en dash, 2: minus, 3: vertical bar, 4: middle dot - for (let i = str.length - 1; i >= 0; i--) { - if (str[i] === '—') { - found = 0; - lastDash = i; - } - else if (str[i] === '–' && found < 1) { - found = 1; - lastDash = i; - } - else if (str[i] === '-' && found < 2) { - found = 2; - lastDash = i; - } - else if (str[i] === '|' && found < 3) { - found = 3; - lastDash = i; - } - else if (str[i] === '·' && found < 4) { - found = 4; - lastDash = i; - } +const WindowTitle = async () => Widget.Scrollable({ + hexpand: true, vexpand: true, + hscroll: 'automatic', vscroll: 'never', + child: Widget.Box({ + vertical: true, + children: [ + Widget.Label({ + xalign: 0, + className: 'txt-smaller bar-topdesc txt', + setup: (self) => self.hook(Hyprland.active.client, label => { // Hyprland.active.client + label.label = Hyprland.active.client.class.length === 0 ? 'Desktop' : Hyprland.active.client.class; + }), + }), + Widget.Label({ + xalign: 0, + className: 'txt txt-smallie', + setup: (self) => self.hook(Hyprland.active.client, label => { // Hyprland.active.client + label.label = Hyprland.active.client.title.length === 0 ? `Workspace ${Hyprland.active.workspace.id}` : Hyprland.active.client.title; + }), + }) + ] + }) +}) + +const OptionalWindowTitle = async () => { + try { + return await WindowTitle(); + } catch { + return null; } - if (lastDash === -1) return str; - return str.substring(0, lastDash); -} +}; +const OptionalWindowTitleInstance = await OptionalWindowTitle(); export const ModuleLeftSpace = () => Widget.EventBox({ onScrollUp: () => { @@ -65,29 +63,7 @@ export const ModuleLeftSpace = () => Widget.EventBox({ vertical: true, className: 'bar-space-button', children: [ - Widget.Scrollable({ - hexpand: true, vexpand: true, - hscroll: 'automatic', vscroll: 'never', - child: Widget.Box({ - vertical: true, - children: [ - Widget.Label({ - xalign: 0, - className: 'txt-smaller bar-topdesc txt', - setup: (self) => self.hook(Hyprland.active.client, label => { // Hyprland.active.client - label.label = Hyprland.active.client._class.length === 0 ? 'Desktop' : Hyprland.active.client._class; - }), - }), - Widget.Label({ - xalign: 0, - className: 'txt txt-smallie', - setup: (self) => self.hook(Hyprland.active.client, label => { // Hyprland.active.client - label.label = Hyprland.active.client._title.length === 0 ? `Workspace ${Hyprland.active.workspace.id}` : Hyprland.active.client._title; - }), - }) - ] - }) - }) + OptionalWindowTitleInstance, ] })] }), diff --git a/.config/ags/widgets/bar/main.js b/.config/ags/widgets/bar/main.js index aefc3a173..eb3ef88a3 100644 --- a/.config/ags/widgets/bar/main.js +++ b/.config/ags/widgets/bar/main.js @@ -1,13 +1,18 @@ -const { Gdk, Gtk } = imports.gi; -import { App, Service, Utils, Widget } from '../../imports.js'; -const { execAsync, exec } = Utils; +const { Gtk } = imports.gi; +import Widget from 'resource:///com/github/Aylur/ags/widget.js'; import { ModuleLeftSpace } from "./leftspace.js"; import { ModuleMusic } from "./music.js"; import { ModuleRightSpace } from "./rightspace.js"; import { ModuleSystem } from "./system.js"; -import ModuleWorkspaces from "./workspaces.js"; -import { RoundedCorner } from "../../lib/roundedcorner.js"; +const OptionalWorkspaces = async () => { + try { + return (await import('./workspaces_hyprland.js')).default(); + } catch { + // return (await import('./workspaces_sway.js')).default(); + return Box({}); + } +}; const left = Widget.Box({ className: 'bar-sidemodule', @@ -18,7 +23,7 @@ const left = Widget.Box({ const center = Widget.Box({ children: [ - ModuleWorkspaces(), + await OptionalWorkspaces(), ], }); diff --git a/.config/ags/widgets/bar/music.js b/.config/ags/widgets/bar/music.js index b8c9dbee8..d2c683b0c 100644 --- a/.config/ags/widgets/bar/music.js +++ b/.config/ags/widgets/bar/music.js @@ -1,6 +1,6 @@ -import { Service, Utils, Widget } from '../../imports.js'; +import Widget from 'resource:///com/github/Aylur/ags/widget.js'; +import * as Utils from 'resource:///com/github/Aylur/ags/utils.js'; import Mpris from 'resource:///com/github/Aylur/ags/service/mpris.js'; -import Audio from 'resource:///com/github/Aylur/ags/service/audio.js'; import Hyprland from 'resource:///com/github/Aylur/ags/service/hyprland.js'; const { execAsync, exec } = Utils; import { AnimatedCircProg } from "../../lib/animatedcircularprogress.js"; @@ -23,10 +23,10 @@ const TrackProgress = () => { return AnimatedCircProg({ className: 'bar-music-circprog', vpack: 'center', hpack: 'center', - connections: [ // Update on change/once every 3 seconds - [Mpris, _updateProgress], - [3000, _updateProgress] - ] + extraSetup: (self) => self + .hook(Mpris, _updateProgress) + .poll(3000, _updateProgress) + , }) } @@ -53,17 +53,17 @@ export const ModuleMusic = () => Widget.EventBox({ // TODO: use cairo to make bu vpack: 'center', className: 'bar-music-playstate-txt', justification: 'center', - connections: [[Mpris, label => { + setup: (self) => self.hook(Mpris, label => { const mpris = Mpris.getPlayer(''); label.label = `${mpris !== null && mpris.playBackStatus == 'Playing' ? 'pause' : 'play_arrow'}`; - }]], + }), })], - connections: [[Mpris, label => { + setup: (self) => self.hook(Mpris, label => { const mpris = Mpris.getPlayer(''); if (!mpris) return; label.toggleClassName('bar-music-playstate-playing', mpris !== null && mpris.playBackStatus == 'Playing'); label.toggleClassName('bar-music-playstate', mpris !== null || mpris.playBackStatus == 'Paused'); - }]], + }), }), overlays: [ TrackProgress(), @@ -74,13 +74,13 @@ export const ModuleMusic = () => Widget.EventBox({ // TODO: use cairo to make bu hexpand: true, child: Widget.Label({ className: 'txt-smallie txt-onSurfaceVariant', - connections: [[Mpris, label => { + setup: (self) => self.hook(Mpris, label => { const mpris = Mpris.getPlayer(''); if (mpris) label.label = `${trimTrackTitle(mpris.trackTitle)} • ${mpris.trackArtists.join(', ')}`; else label.label = 'No media'; - }]], + }), }) }) ] diff --git a/.config/ags/widgets/bar/rightspace.js b/.config/ags/widgets/bar/rightspace.js index 28ec69737..fb4e7b8a7 100644 --- a/.config/ags/widgets/bar/rightspace.js +++ b/.config/ags/widgets/bar/rightspace.js @@ -1,6 +1,8 @@ -import { App, Utils, Widget } from '../../imports.js'; +import App from 'resource:///com/github/Aylur/ags/app.js'; +import Widget from 'resource:///com/github/Aylur/ags/widget.js'; +import * as Utils from 'resource:///com/github/Aylur/ags/utils.js'; + import Audio from 'resource:///com/github/Aylur/ags/service/audio.js'; -import Mpris from 'resource:///com/github/Aylur/ags/service/mpris.js'; import SystemTray from 'resource:///com/github/Aylur/ags/service/systemtray.js'; const { execAsync } = Utils; import Indicator from '../../services/indicator.js'; @@ -33,8 +35,8 @@ export const ModuleRightSpace = () => { // onHover: () => { barStatusIcons.toggleClassName('bar-statusicons-hover', true) }, // onHoverLost: () => { barStatusIcons.toggleClassName('bar-statusicons-hover', false) }, onPrimaryClick: () => App.toggleWindow('sideright'), - onSecondaryClickRelease: () => execAsync(['bash', '-c', 'playerctl next || playerctl position `bc <<< "100 * $(playerctl metadata mpris:length) / 1000000 / 100"` &']), - onMiddleClickRelease: () => Mpris.getPlayer('')?.playPause(), + onSecondaryClickRelease: () => execAsync(['bash', '-c', 'playerctl next || playerctl position `bc <<< "100 * $(playerctl metadata mpris:length) / 1000000 / 100"` &']).catch(print), + onMiddleClickRelease: () => execAsync('playerctl play-pause').catch(print), child: Widget.Box({ homogeneous: false, children: [ @@ -51,19 +53,20 @@ export const ModuleRightSpace = () => { Widget.Revealer({ transition: 'slide_left', revealChild: false, - properties: [ - ['count', 0], - ['update', (self, diff) => { - self._count += diff; - self.revealChild = (self._count > 0); - }]], + attribute: { + 'count': 0, + 'update': (self, diff) => { + self.attribute.count += diff; + self.revealChild = (self.attribute.count > 0); + } + }, child: Widget.Box({ vpack: 'center', className: 'separator-circle', }), setup: (self) => self - .hook(SystemTray, (self) => self._update(self, 1), 'added') - .hook(SystemTray, (self) => self._update(self, -1), 'removed') + .hook(SystemTray, (self) => self.attribute.update(self, 1), 'added') + .hook(SystemTray, (self) => self.attribute.update(self, -1), 'removed') , }), barStatusIcons, diff --git a/.config/ags/widgets/bar/system.js b/.config/ags/widgets/bar/system.js index 1766c5480..d1b8238e8 100644 --- a/.config/ags/widgets/bar/system.js +++ b/.config/ags/widgets/bar/system.js @@ -1,6 +1,7 @@ // This is for the right pill of the bar. // For the cool memory indicator on the sidebar, see sysinfo.js -import { Service, Utils, Widget } from '../../imports.js'; +import Widget from 'resource:///com/github/Aylur/ags/widget.js'; +import * as Utils from 'resource:///com/github/Aylur/ags/utils.js'; const { Box, Label, Button, Overlay, Revealer, Scrollable, Stack, EventBox } = Widget; const { exec, execAsync } = Utils; const { GLib } = imports.gi; @@ -21,9 +22,9 @@ const BatBatteryProgress = () => { return AnimatedCircProg({ className: 'bar-batt-circprog', vpack: 'center', hpack: 'center', - connections: [ - [Battery, _updateProgress], - ], + extraSetup: (self) => self + .hook(Battery, _updateProgress) + , }) } @@ -147,13 +148,6 @@ const BarResource = (name, icon, command) => { const resourceCircProg = AnimatedCircProg({ className: 'bar-batt-circprog', vpack: 'center', hpack: 'center', - connections: [[5000, (progress) => execAsync(['bash', '-c', command]) - .then((output) => { - progress.css = `font-size: ${Number(output)}px;`; - resourceLabel.label = `${Math.round(Number(output))}%`; - widget.tooltipText = `${name}: ${Math.round(Number(output))}%`; - }).catch(print) - ]], }); const widget = Box({ className: 'spacing-h-4 txt-onSurfaceVariant', @@ -170,7 +164,15 @@ const BarResource = (name, icon, command) => { }), overlays: [resourceCircProg] }), - ] + ], + setup: (self) => self + .poll(5000, () => execAsync(['bash', '-c', command]) + .then((output) => { + resourceCircProg.css = `font-size: ${Number(output)}px;`; + resourceLabel.label = `${Math.round(Number(output))}%`; + widget.tooltipText = `${name}: ${Math.round(Number(output))}%`; + }).catch(print)) + , }); return widget; } diff --git a/.config/ags/widgets/bar/tray.js b/.config/ags/widgets/bar/tray.js index 1d1c2e4b9..67d65a833 100644 --- a/.config/ags/widgets/bar/tray.js +++ b/.config/ags/widgets/bar/tray.js @@ -1,24 +1,28 @@ -const { GLib, Gdk, Gtk } = imports.gi; -import { Service, Widget } from '../../imports.js'; +const { Gtk } = imports.gi; +import Widget from 'resource:///com/github/Aylur/ags/widget.js'; import SystemTray from 'resource:///com/github/Aylur/ags/service/systemtray.js'; const { Box, Icon, Button, Revealer } = Widget; const { Gravity } = imports.gi.Gdk; const revealerDuration = 200; -const SysTrayItem = item => Button({ +const SysTrayItem = (item) => Button({ className: 'bar-systray-item', child: Icon({ hpack: 'center', - binds: [['icon', item, 'icon']], - setup: (self) => Utils.timeout(1, () => { - const styleContext = self.get_parent().get_style_context(); - const width = styleContext.get_property('min-width', Gtk.StateFlags.NORMAL); - const height = styleContext.get_property('min-height', Gtk.StateFlags.NORMAL); - self.size = Math.max(width, height, 1); // im too lazy to add another box lol - }), + setup: (self) => { + self.hook(item, (self) => self.icon = item.icon); + Utils.timeout(1, () => { + const styleContext = self.get_parent().get_style_context(); + const width = styleContext.get_property('min-width', Gtk.StateFlags.NORMAL); + const height = styleContext.get_property('min-height', Gtk.StateFlags.NORMAL); + self.size = Math.max(width, height, 1); // im too lazy to add another box lol + }) + }, }), - binds: [['tooltipMarkup', item, 'tooltip-markup']], + setup: (self) => self + .hook(item, (self) => self.tooltipMarkup = item['tooltip-markup']) + , onClicked: btn => item.menu.popup_at_widget(btn, Gravity.SOUTH, Gravity.NORTH, null), onSecondaryClick: btn => item.menu.popup_at_widget(btn, Gravity.SOUTH, Gravity.NORTH, null), }); @@ -26,34 +30,34 @@ const SysTrayItem = item => Button({ export const Tray = (props = {}) => { const trayContent = Box({ className: 'margin-right-5 spacing-h-15', - properties: [ - ['items', new Map()], - ['onAdded', (box, id) => { + attribute: { + items: new Map(), + onAdded: (box, id) => { const item = SystemTray.getItem(id); if (!item) return; item.menu.className = 'menu'; - if (box._items.has(id) || !item) + if (box.attribute.items.has(id) || !item) return; const widget = SysTrayItem(item); - box._items.set(id, widget); + box.attribute.items.set(id, widget); box.add(widget); box.show_all(); - if (box._items.size === 1) + if (box.attribute.items.size === 1) trayRevealer.revealChild = true; - }], - ['onRemoved', (box, id) => { - if (!box._items.has(id)) + }, + onRemoved: (box, id) => { + if (!box.attribute.items.has(id)) return; - box._items.get(id).destroy(); - box._items.delete(id); - if (box._items.size === 0) + box.attribute.items.get(id).destroy(); + box.attribute.items.delete(id); + if (box.attribute.items.size === 0) trayRevealer.revealChild = false; - }], - ], + }, + }, setup: (self) => self - .hook(SystemTray, (box, id) => box._onAdded(box, id), 'added') - .hook(SystemTray, (box, id) => box._onRemoved(box, id), 'removed') + .hook(SystemTray, (box, id) => box.attribute.onAdded(box, id), 'added') + .hook(SystemTray, (box, id) => box.attribute.onRemoved(box, id), 'removed') , }); const trayRevealer = Widget.Revealer({ diff --git a/.config/ags/widgets/bar/workspaces.js b/.config/ags/widgets/bar/workspaces_hyprland.js similarity index 84% rename from .config/ags/widgets/bar/workspaces.js rename to .config/ags/widgets/bar/workspaces_hyprland.js index d1cd15378..bbc4514a1 100644 --- a/.config/ags/widgets/bar/workspaces.js +++ b/.config/ags/widgets/bar/workspaces_hyprland.js @@ -3,7 +3,8 @@ const Lang = imports.lang; const Cairo = imports.cairo; const Pango = imports.gi.Pango; const PangoCairo = imports.gi.PangoCairo; -import { App, Service, Utils, Widget } from '../../imports.js'; +import App from 'resource:///com/github/Aylur/ags/app.js'; +import Widget from 'resource:///com/github/Aylur/ags/widget.js'; const { Box, DrawingArea, EventBox } = Widget; import Hyprland from 'resource:///com/github/Aylur/ags/service/hyprland.js'; @@ -16,11 +17,11 @@ const dummyOccupiedWs = Box({ className: 'bar-ws bar-ws-occupied' }); // Not sho const WorkspaceContents = (count = 10) => { return DrawingArea({ css: `transition: 90ms cubic-bezier(0.1, 1, 0, 1);`, - properties: [ - ['initialized', false], - ['workspaceMask', 0], - ['updateMask', (self) => { - if (self._initialized) return; // We only need this to run once + attribute: { + initialized: false, + workspaceMask: 0, + updateMask: (self) => { + if (self.attribute.initialized) return; // We only need this to run once const workspaces = Hyprland.workspaces; let workspaceMask = 0; for (let i = 0; i < workspaces.length; i++) { @@ -31,21 +32,21 @@ const WorkspaceContents = (count = 10) => { workspaceMask |= (1 << ws.id); } } - self._workspaceMask = workspaceMask; - self._initialized = true; - }], - ['toggleMask', (self, occupied, name) => { - if (occupied) self._workspaceMask |= (1 << parseInt(name)); - else self._workspaceMask &= ~(1 << parseInt(name)); - }] - ], + self.attribute.workspaceMask = workspaceMask; + self.attribute.initialized = true; + }, + toggleMask: (self, occupied, name) => { + if (occupied) self.attribute.workspaceMask |= (1 << parseInt(name)); + else self.attribute.workspaceMask &= ~(1 << parseInt(name)); + }, + }, setup: (area) => area .hook(Hyprland.active.workspace, (area) => area.setCss(`font-size: ${Hyprland.active.workspace.id}px;`) ) - .hook(Hyprland, (self) => self._updateMask(self), 'notify::workspaces') - .hook(Hyprland, (self, name) => self._toggleMask(self, true, name), 'workspace-added') - .hook(Hyprland, (self, name) => self._toggleMask(self, false, name), 'workspace-removed') + .hook(Hyprland, (self) => self.attribute.updateMask(self), 'notify::workspaces') + .hook(Hyprland, (self, name) => self.attribute.toggleMask(self, true, name), 'workspace-added') + .hook(Hyprland, (self, name) => self.attribute.toggleMask(self, false, name), 'workspace-removed') .on('draw', Lang.bind(area, (area, cr) => { const allocation = area.get_allocation(); const { width, height } = allocation; @@ -85,12 +86,12 @@ const WorkspaceContents = (count = 10) => { // Draw workspace numbers for (let i = 1; i <= count; i++) { - if (area._workspaceMask & (1 << i)) { + if (area.attribute.workspaceMask & (1 << i)) { // Draw bg highlight cr.setSourceRGBA(occupiedbg.red, occupiedbg.green, occupiedbg.blue, occupiedbg.alpha); const wsCenterX = -(workspaceRadius) + (workspaceDiameter * i); const wsCenterY = height / 2; - if (!(area._workspaceMask & (1 << (i - 1)))) { // Left + if (!(area.attribute.workspaceMask & (1 << (i - 1)))) { // Left cr.arc(wsCenterX, wsCenterY, workspaceRadius, 0.5 * Math.PI, 1.5 * Math.PI); cr.fill(); } @@ -98,7 +99,7 @@ const WorkspaceContents = (count = 10) => { cr.rectangle(wsCenterX - workspaceRadius, wsCenterY - workspaceRadius, workspaceRadius, workspaceRadius * 2) cr.fill(); } - if (!(area._workspaceMask & (1 << (i + 1)))) { // Right + if (!(area.attribute.workspaceMask & (1 << (i + 1)))) { // Right cr.arc(wsCenterX, wsCenterY, workspaceRadius, -0.5 * Math.PI, 0.5 * Math.PI); cr.fill(); } @@ -141,9 +142,7 @@ export default () => EventBox({ onScrollDown: () => Hyprland.sendMessage(`dispatch workspace +1`), onMiddleClickRelease: () => App.toggleWindow('overview'), onSecondaryClickRelease: () => App.toggleWindow('osk'), - properties: [ - ['clicked', false], - ], + attribute: { clicked: false }, child: Box({ homogeneous: true, className: 'bar-group-margin', @@ -158,8 +157,7 @@ export default () => EventBox({ setup: (self) => { self.add_events(Gdk.EventMask.POINTER_MOTION_MASK); self.on('motion-notify-event', (self, event) => { - if (!self._clicked) return; - console.log('switching move'); + if (!self.attribute.clicked) return; const [_, cursorX, cursorY] = event.get_coords(); const widgetWidth = self.get_allocation().width; const wsId = Math.ceil(cursorX * NUM_OF_WORKSPACES / widgetWidth); @@ -167,13 +165,12 @@ export default () => EventBox({ }) self.on('button-press-event', (self, event) => { if (!(event.get_button()[1] === 1)) return; // We're only interested in left-click here - console.log('switching'); - self._clicked = true; + self.attribute.clicked = true; const [_, cursorX, cursorY] = event.get_coords(); const widgetWidth = self.get_allocation().width; const wsId = Math.ceil(cursorX * NUM_OF_WORKSPACES / widgetWidth); Hyprland.sendMessage(`dispatch workspace ${wsId}`); }) - self.on('button-release-event', (self) => self._clicked = false); + self.on('button-release-event', (self) => self.attribute.clicked = false); } }) diff --git a/.config/ags/widgets/bar/workspaces_sway.js b/.config/ags/widgets/bar/workspaces_sway.js new file mode 100644 index 000000000..700848668 --- /dev/null +++ b/.config/ags/widgets/bar/workspaces_sway.js @@ -0,0 +1,58 @@ +import Widget from "resource:///com/github/Aylur/ags/widget.js"; +import Sway from "../../services/sway.js"; +import * as Utils from "resource:///com/github/Aylur/ags/utils.js"; +import options from "../../options.js"; +import { range } from "../../utils.js"; + + +const dispatch = (arg) => Utils.execAsync(`swaymsg workspace ${arg}`); + +const Workspaces = () => { + const ws = options.workspaces.value || 20; + return Widget.Box({ + children: range(ws).map((i) => + Widget.Button({ + setup: (btn) => (btn.id = i), + on_clicked: () => dispatch(i), + child: Widget.Label({ + label: `${i}`, + class_name: "indicator", + vpack: "center", + }), + setup: (self) => self.hook(Sway, (btn) => { + btn.toggleClassName("active", Sway.active.workspace.name == i); + btn.toggleClassName( + "occupied", + Sway.getWorkspace(`${i}`)?.nodes.length > 0, + ); + }), + }) + ), + setup: (self) => self.hook(Sway.active.workspace, + (box) => box.children.map((btn) => { + btn.visible = Sway.workspaces.some( + (ws) => ws.name == btn.id, + ); + }) + ), + }); +}; + +export default () => Widget.EventBox({ + class_name: "workspaces panel-button", + child: Widget.Box({ + // its nested like this to keep it consistent with other PanelButton widgets + child: Widget.EventBox({ + on_scroll_up: () => dispatch("next"), + on_scroll_down: () => dispatch("prev"), + class_name: "eventbox", + // binds: [["child", options.workspaces, "value", Workspaces]], + setup: (self) => self + .hook(options.workspaces, (self) => Selection.child = Workspaces(), "value") + , + }), + }), + setup: (self) => { + console.log('[LOG] Sway workspace module loaded') + } +}); diff --git a/.config/ags/widgets/cheatsheet/keybinds.js b/.config/ags/widgets/cheatsheet/keybinds.js index 589688260..765c511b7 100644 --- a/.config/ags/widgets/cheatsheet/keybinds.js +++ b/.config/ags/widgets/cheatsheet/keybinds.js @@ -1,4 +1,4 @@ -import { Widget } from '../../imports.js'; +import Widget from 'resource:///com/github/Aylur/ags/widget.js'; import { keybindList } from "../../data/keybinds.js"; export const Keybinds = () => Widget.Box({ diff --git a/.config/ags/widgets/cheatsheet/main.js b/.config/ags/widgets/cheatsheet/main.js index 21887de7d..2eced0f03 100644 --- a/.config/ags/widgets/cheatsheet/main.js +++ b/.config/ags/widgets/cheatsheet/main.js @@ -1,5 +1,6 @@ const { Gdk, Gtk } = imports.gi; -import { Service, Widget } from '../../imports.js'; +import Widget from 'resource:///com/github/Aylur/ags/widget.js'; +import Service from 'resource:///com/github/Aylur/ags/service.js'; import { Keybinds } from "./keybinds.js"; import { setupCursorHover } from "../../lib/cursorhover.js"; diff --git a/.config/ags/widgets/desktopbackground/main.js b/.config/ags/widgets/desktopbackground/main.js index c35309def..13f613cec 100644 --- a/.config/ags/widgets/desktopbackground/main.js +++ b/.config/ags/widgets/desktopbackground/main.js @@ -1,5 +1,6 @@ const { Gdk, Gtk } = imports.gi; -import { App, Service, Utils, Widget } from '../../imports.js'; +import Widget from 'resource:///com/github/Aylur/ags/widget.js'; +import * as Utils from 'resource:///com/github/Aylur/ags/utils.js'; const { execAsync, exec } = Utils; import TimeAndLaunchesWidget from './timeandlaunches.js' diff --git a/.config/ags/widgets/desktopbackground/system.js b/.config/ags/widgets/desktopbackground/system.js index e6dcf6461..f69e42c8b 100644 --- a/.config/ags/widgets/desktopbackground/system.js +++ b/.config/ags/widgets/desktopbackground/system.js @@ -1,4 +1,5 @@ -import { App, Service, Utils, Widget } from '../../imports.js'; +import Widget from 'resource:///com/github/Aylur/ags/widget.js'; +import * as Utils from 'resource:///com/github/Aylur/ags/utils.js'; const { execAsync, exec } = Utils; const { Box, EventBox, Label, Revealer, Overlay } = Widget; import { AnimatedCircProg } from '../../lib/animatedcircularprogress.js' @@ -24,7 +25,9 @@ const ResourceValue = (name, icon, interval, valueUpdateCmd, displayFunc, props Label({ xalign: 1, className: 'titlefont txt-norm txt-onSecondaryContainer', - connections: [[interval, (label) => displayFunc(label)]] + setup: (self) => self + .poll(interval, (label) => displayFunc(label)) + , }) ] }) @@ -32,11 +35,13 @@ const ResourceValue = (name, icon, interval, valueUpdateCmd, displayFunc, props Overlay({ child: AnimatedCircProg({ className: 'bg-system-circprog', - connections: [[interval, (self) => { - execAsync(['bash', '-c', `${valueUpdateCmd}`]).then((newValue) => { - self.css = `font-size: ${Math.round(newValue)}px;` - }).catch(print); - }]] + extraSetup: (self) => self + .poll(interval, (self) => { + execAsync(['bash', '-c', `${valueUpdateCmd}`]).then((newValue) => { + self.css = `font-size: ${Math.round(newValue)}px;` + }).catch(print); + }) + , }), overlays: [ MaterialIcon(`${icon}`, 'hugeass'), @@ -143,7 +148,7 @@ export default () => Box({ const firstChild = child.get_children()[0]; firstChild.revealChild = !firstChild.revealChild; } - + }, }) ], diff --git a/.config/ags/widgets/desktopbackground/timeandlaunches.js b/.config/ags/widgets/desktopbackground/timeandlaunches.js index 1f9b01305..8897992d8 100644 --- a/.config/ags/widgets/desktopbackground/timeandlaunches.js +++ b/.config/ags/widgets/desktopbackground/timeandlaunches.js @@ -1,5 +1,9 @@ -const { GLib, Gio } = imports.gi; -import { App, Service, Utils, Widget } from '../../imports.js'; +const { GLib } = imports.gi; +import App from 'resource:///com/github/Aylur/ags/app.js'; +import Widget from 'resource:///com/github/Aylur/ags/widget.js'; +import Service from 'resource:///com/github/Aylur/ags/service.js'; +import * as Utils from 'resource:///com/github/Aylur/ags/utils.js'; + import Variable from 'resource:///com/github/Aylur/ags/variable.js'; const { execAsync, exec } = Utils; const { Box, Label, Button, Revealer, EventBox } = Widget; diff --git a/.config/ags/widgets/dock/dock.js b/.config/ags/widgets/dock/dock.js index c2ac08011..f0192d8cc 100644 --- a/.config/ags/widgets/dock/dock.js +++ b/.config/ags/widgets/dock/dock.js @@ -1,12 +1,14 @@ -const { Gdk, Gtk } = imports.gi; -import { App, Service, Utils, Widget, SCREEN_HEIGHT, SCREEN_WIDTH } from '../../imports.js'; +const { Gtk } = imports.gi; +import { SCREEN_HEIGHT, SCREEN_WIDTH } from '../../imports.js'; +import Widget from 'resource:///com/github/Aylur/ags/widget.js'; +import * as Utils from 'resource:///com/github/Aylur/ags/utils.js'; +const { EventBox } = Widget; + import Hyprland from 'resource:///com/github/Aylur/ags/service/hyprland.js'; import Applications from 'resource:///com/github/Aylur/ags/service/applications.js'; const { execAsync, exec } = Utils; -const { Box, EventBox, Label, Revealer, Overlay } = Widget; -import { AnimatedCircProg } from '../../lib/animatedcircularprogress.js' -import { MaterialIcon } from '../../lib/materialicon.js'; -import { setupCursorHover, setupCursorHoverAim } from "../../lib/cursorhover.js"; +const { Box, Revealer } = Widget; +import { setupCursorHover } from "../../lib/cursorhover.js"; const ANIMATION_TIME = 150; const pinnedApps = [ @@ -41,9 +43,9 @@ const DockSeparator = (props = {}) => Box({ }) const AppButton = ({ icon, ...rest }) => Widget.Revealer({ - properties: [ - ['workspace', 0], - ], + attribute: { + 'workspace': 0 + }, revealChild: false, transition: 'slide_right', transitionDuration: ANIMATION_TIME, @@ -80,12 +82,12 @@ const AppButton = ({ icon, ...rest }) => Widget.Revealer({ const Taskbar = () => Widget.Box({ className: 'dock-apps', - properties: [ - ['map', new Map()], - ['clientSortFunc', (a, b) => { - return a._workspace > b._workspace; - }], - ['update', (box) => { + attribute: { + 'map': new Map(), + 'clientSortFunc': (a, b) => { + return a.attribute.workspace > b.attribute.workspace; + }, + 'update': (box) => { for (let i = 0; i < Hyprland.clients.length; i++) { const client = Hyprland.clients[i]; if (client["pid"] == -1) return; @@ -99,15 +101,15 @@ const Taskbar = () => Widget.Box({ tooltipText: `${client.title} (${appClass})`, onClicked: () => focus(client), }); - newButton._workspace = client.workspace.id; + newButton.attribute.workspace = client.workspace.id; newButton.revealChild = true; - box._map.set(client.address, newButton); + box.attribute.map.set(client.address, newButton); } - box.children = Array.from(box._map.values()); - }], - ['add', (box, address) => { + box.children = Array.from(box.attribute.map.values()); + }, + 'add': (box, address) => { if (!address) { // First active emit is undefined - box._update(box); + box.attribute.update(box); return; } const newClient = Hyprland.clients.find(client => { @@ -120,29 +122,29 @@ const Taskbar = () => Widget.Box({ tooltipText: `${newClient.title} (${appClass})`, onClicked: () => focus(newClient), }) - newButton._workspace = newClient.workspace.id; - box._map.set(address, newButton); - box.children = Array.from(box._map.values()); + newButton.attribute.workspace = newClient.workspace.id; + box.attribute.map.set(address, newButton); + box.children = Array.from(box.attribute.map.values()); newButton.revealChild = true; - }], - ['remove', (box, address) => { + }, + 'remove': (box, address) => { if (!address) return; - const removedButton = box._map.get(address); + const removedButton = box.attribute.map.get(address); if (!removedButton) return; removedButton.revealChild = false; Utils.timeout(ANIMATION_TIME, () => { removedButton.destroy(); - box._map.delete(address); - box.children = Array.from(box._map.values()); + box.attribute.map.delete(address); + box.children = Array.from(box.attribute.map.values()); }) - }], - ], + }, + }, setup: (self) => { - self.hook(Hyprland, (box, address) => box._add(box, address), 'client-added') - .hook(Hyprland, (box, address) => box._remove(box, address), 'client-removed') - Utils.timeout(100, () => self._update(self)); + self.hook(Hyprland, (box, address) => box.attribute.add(box, address), 'client-added') + .hook(Hyprland, (box, address) => box.attribute.remove(box, address), 'client-removed') + Utils.timeout(100, () => self.attribute.update(self)); }, }); @@ -192,8 +194,8 @@ export default () => { ] }) const dockRevealer = Revealer({ - properties: [ - ['updateShow', self => { // I only use mouse to resize. I don't care about keyboard resize if that's a thing + attribute: { + 'updateShow': self => { // I only use mouse to resize. I don't care about keyboard resize if that's a thing const dockSize = [ dockContent.get_allocated_width(), dockContent.get_allocated_height() @@ -230,18 +232,18 @@ export default () => { } } self.revealChild = true; - }] - ], + } + }, revealChild: false, transition: 'slide_up', transitionDuration: 200, child: dockContent, // setup: (self) => self - // .hook(Hyprland, (self) => self._updateShow(self)) - // .hook(Hyprland.active.workspace, (self) => self._updateShow(self)) - // .hook(Hyprland.active.client, (self) => self._updateShow(self)) - // .hook(Hyprland, (self) => self._updateShow(self), 'client-added') - // .hook(Hyprland, (self) => self._updateShow(self), 'client-removed') + // .hook(Hyprland, (self) => self.attribute.updateShow(self)) + // .hook(Hyprland.active.workspace, (self) => self.attribute.updateShow(self)) + // .hook(Hyprland.active.client, (self) => self.attribute.updateShow(self)) + // .hook(Hyprland, (self) => self.attribute.updateShow(self), 'client-added') + // .hook(Hyprland, (self) => self.attribute.updateShow(self), 'client-removed') // , }) return EventBox({ @@ -249,7 +251,7 @@ export default () => { dockRevealer.revealChild = true; }, onHoverLost: () => { - if (Hyprland.active.client._class.length === 0) return; + if (Hyprland.active.client.attribute.class.length === 0) return; dockRevealer.revealChild = false; }, child: Box({ diff --git a/.config/ags/widgets/dock/main.js b/.config/ags/widgets/dock/main.js index ad73d6f1c..cc7bb0e46 100644 --- a/.config/ags/widgets/dock/main.js +++ b/.config/ags/widgets/dock/main.js @@ -1,4 +1,4 @@ -import { App, Widget } from '../../imports.js'; +import Widget from 'resource:///com/github/Aylur/ags/widget.js'; import Dock from './dock.js'; export default () => Widget.Window({ diff --git a/.config/ags/widgets/indicators/colorscheme.js b/.config/ags/widgets/indicators/colorscheme.js index 02cde92a0..3419e92b6 100644 --- a/.config/ags/widgets/indicators/colorscheme.js +++ b/.config/ags/widgets/indicators/colorscheme.js @@ -1,11 +1,6 @@ -const { Gio, GLib, Gtk } = imports.gi; -import { App, Service, Utils, Widget } from '../../imports.js'; -const { exec, execAsync } = Utils; -import Mpris from 'resource:///com/github/Aylur/ags/service/mpris.js'; +import Widget from 'resource:///com/github/Aylur/ags/widget.js'; const { Box, EventBox, Icon, Scrollable, Label, Button, Revealer } = Widget; -import { AnimatedCircProg } from "../../lib/animatedcircularprogress.js"; -import { MaterialIcon } from '../../lib/materialicon.js'; import { showColorScheme } from '../../variables.js'; const ColorBox = ({ diff --git a/.config/ags/widgets/indicators/indicatorvalues.js b/.config/ags/widgets/indicators/indicatorvalues.js index 76125c9b3..11d5f1474 100644 --- a/.config/ags/widgets/indicators/indicatorvalues.js +++ b/.config/ags/widgets/indicators/indicatorvalues.js @@ -1,13 +1,12 @@ // This file is for brightness/volume indicators -const { GLib, Gtk } = imports.gi; -import { App, Service, Utils, Widget } from '../../imports.js'; +import Widget from 'resource:///com/github/Aylur/ags/widget.js'; import Audio from 'resource:///com/github/Aylur/ags/service/audio.js'; const { Box, Label, ProgressBar, Revealer } = Widget; import { MarginRevealer } from '../../lib/advancedwidgets.js'; import Brightness from '../../services/brightness.js'; import Indicator from '../../services/indicator.js'; -const OsdValue = (name, labelConnections, progressConnections, props = {}) => Box({ // Volume +const OsdValue = (name, labelSetup, progressSetup, props = {}) => Box({ // Volume ...props, vertical: true, className: 'osd-bg osd-value', @@ -23,8 +22,7 @@ const OsdValue = (name, labelConnections, progressConnections, props = {}) => Bo }), Label({ hexpand: false, className: 'osd-value-txt', - label: '100', - connections: labelConnections, + setup: labelSetup, }), ] }), @@ -32,41 +30,49 @@ const OsdValue = (name, labelConnections, progressConnections, props = {}) => Bo className: 'osd-progress', hexpand: true, vertical: false, - connections: progressConnections, + setup: progressSetup, }) ], }); const brightnessIndicator = OsdValue('Brightness', - [[Brightness, self => { - self.label = `${Math.round(Brightness.screen_value * 100)}`; - }, 'notify::screen-value']], - [[Brightness, (progress) => { - const updateValue = Brightness.screen_value; - progress.value = updateValue; - }, 'notify::screen-value']], + (self) => self + .hook(Brightness, self => { + self.label = `${Math.round(Brightness.screen_value * 100)}`; + }, 'notify::screen-value') + , + (self) => self + .hook(Brightness, (progress) => { + const updateValue = Brightness.screen_value; + progress.value = updateValue; + }, 'notify::screen-value') + , ) const volumeIndicator = OsdValue('Volume', - [[Audio, (label) => { - label.label = `${Math.round(Audio.speaker?.volume * 100)}`; - }]], - [[Audio, (progress) => { - const updateValue = Audio.speaker?.volume; - if (!isNaN(updateValue)) progress.value = updateValue; - }]], + (self) => self + .hook(Audio, (label) => { + label.label = `${Math.round(Audio.speaker?.volume * 100)}`; + }) + , + (self) => self + .hook(Audio, (progress) => { + const updateValue = Audio.speaker?.volume; + if (!isNaN(updateValue)) progress.value = updateValue; + }) + , ); export default () => MarginRevealer({ transition: 'slide_down', showClass: 'osd-show', hideClass: 'osd-hide', - connections: [ - [Indicator, (revealer, value) => { - if(value > -1) revealer._show(); - else revealer._hide(); - }, 'popup'], - ], + extraSetup: (self) => self + .hook(Indicator, (revealer, value) => { + if (value > -1) revealer.attribute.show(); + else revealer.attribute.hide(); + }, 'popup') + , child: Box({ hpack: 'center', vertical: false, diff --git a/.config/ags/widgets/indicators/main.js b/.config/ags/widgets/indicators/main.js index b2204a15b..b7aa55900 100644 --- a/.config/ags/widgets/indicators/main.js +++ b/.config/ags/widgets/indicators/main.js @@ -1,4 +1,4 @@ -import { Widget } from '../../imports.js'; +import Widget from 'resource:///com/github/Aylur/ags/widget.js'; import Indicator from '../../services/indicator.js'; import IndicatorValues from './indicatorvalues.js'; import MusicControls from './musiccontrols.js'; diff --git a/.config/ags/widgets/indicators/musiccontrols.js b/.config/ags/widgets/indicators/musiccontrols.js index c6b3d2bb7..be51cc963 100644 --- a/.config/ags/widgets/indicators/musiccontrols.js +++ b/.config/ags/widgets/indicators/musiccontrols.js @@ -1,5 +1,7 @@ -const { Gio, GLib, Gtk } = imports.gi; -import { App, Service, Utils, Widget } from '../../imports.js'; +const { Gio, GLib } = imports.gi; +import App from 'resource:///com/github/Aylur/ags/app.js'; +import Widget from 'resource:///com/github/Aylur/ags/widget.js'; +import * as Utils from 'resource:///com/github/Aylur/ags/utils.js'; const { exec, execAsync } = Utils; import Mpris from 'resource:///com/github/Aylur/ags/service/mpris.js'; @@ -92,10 +94,10 @@ const TrackProgress = ({ player, ...rest }) => { ...rest, className: 'osd-music-circprog', vpack: 'center', - connections: [ // Update on change/once every 3 seconds - [Mpris, _updateProgress], - [3000, _updateProgress] - ], + extraSetup: (self) => self + .hook(Mpris, _updateProgress) + .poll(3000, _updateProgress) + , }) } @@ -106,13 +108,13 @@ const TrackTitle = ({ player, ...rest }) => Label({ truncate: 'end', // wrap: true, className: 'osd-music-title', - connections: [[player, (self) => { + setup: (self) => self.hook(player, (self) => { // Player name self.label = player.trackTitle.length > 0 ? trimTrackTitle(player.trackTitle) : 'No media'; // Font based on track/artist const fontForThisTrack = getTrackfont(player); self.css = `font-family: ${fontForThisTrack}, ${DEFAULT_MUSIC_FONT};`; - }, 'notify::track-title']] + }, 'notify::track-title'), }); const TrackArtists = ({ player, ...rest }) => Label({ @@ -120,9 +122,9 @@ const TrackArtists = ({ player, ...rest }) => Label({ xalign: 0, className: 'osd-music-artists', truncate: 'end', - connections: [[player, (self) => { + setup: (self) => self.hook(player, (self) => { self.label = player.trackArtists.length > 0 ? player.trackArtists.join(', ') : ''; - }, 'notify::track-artists']] + }, 'notify::track-artists'), }) const CoverArt = ({ player, ...rest }) => Box({ @@ -140,8 +142,8 @@ const CoverArt = ({ player, ...rest }) => Box({ }), overlays: [ // Real Box({ - properties: [ - ['updateCover', (self) => { + attribute: { + 'updateCover': (self) => { const player = Mpris.getPlayer(); // Player closed @@ -177,11 +179,11 @@ const CoverArt = ({ player, ...rest }) => Box({ App.applyCss(`${stylePath}`); }) .catch(print); - }], - ], + }, + }, className: 'osd-music-cover-art', - connections: [ - [player, (self) => self._updateCover(self), 'notify::cover-path'] + $: [ + [player, (self) => self.attribute.updateCover(self), 'notify::cover-path'] ], }) ] @@ -218,13 +220,13 @@ const TrackControls = ({ player, ...rest }) => Widget.Revealer({ }), ], }), - connections: [[Mpris, (self) => { + setup: (self) => szelf.hook(Mpris, (self) => { const player = Mpris.getPlayer(); if (!player) self.revealChild = false; else self.revealChild = true; - }, 'notify::play-back-status']] + }, 'notify::play-back-status'), }); const TrackSource = ({ player, ...rest }) => Widget.Revealer({ @@ -240,19 +242,19 @@ const TrackSource = ({ player, ...rest }) => Widget.Revealer({ hpack: 'fill', justification: 'center', className: 'icon-nerd', - connections: [[player, (self) => { + setup: (self) => self.hook(player, (self) => { self.label = detectMediaSource(player.trackCoverUrl); - }, 'notify::cover-path']] + }, 'notify::cover-path'), }), ], }), - connections: [[Mpris, (self) => { + setup: (self) => self.hook(Mpris, (self) => { const mpris = Mpris.getPlayer(''); if (!mpris) self.revealChild = false; else self.revealChild = true; - }]] + }), }); const TrackTime = ({ player, ...rest }) => { @@ -266,28 +268,26 @@ const TrackTime = ({ player, ...rest }) => { className: 'osd-music-pill spacing-h-5', children: [ Label({ - connections: [[1000, (self) => { + setup: (self) => self.poll(1000, (self) => { const player = Mpris.getPlayer(); if (!player) return; self.label = lengthStr(player.position); - }]] + }), }), Label({ label: '/' }), Label({ - connections: [[Mpris, (self) => { + setup: (self) => self.hook(Mpris, (self) => { const player = Mpris.getPlayer(); if (!player) return; self.label = lengthStr(player.length); - }]] + }), }), ], }), - connections: [[Mpris, (self) => { - if (!player) - self.revealChild = false; - else - self.revealChild = true; - }]] + setup: (self) => self.hook(Mpris, (self) => { + if (!player) self.revealChild = false; + else self.revealChild = true; + }), }) } @@ -306,15 +306,12 @@ const PlayState = ({ player }) => { justification: 'center', hpack: 'fill', vpack: 'center', - connections: [[player, (label) => { + setup: (self) => self.hook(player, (label) => { label.label = `${player.playBackStatus == 'Playing' ? 'pause' : 'play_arrow'}`; - }, 'notify::play-back-status']], + }, 'notify::play-back-status'), }), }), ], - // setup: self => Utils.timeout(1, () => { - // self.set_overlay_pass_through(self.get_children()[1], true); - // }), passThrough: true, }) }); @@ -358,19 +355,17 @@ export default () => MarginRevealer({ showClass: 'osd-show', hideClass: 'osd-hide', child: Box({ - connections: [[Mpris, box => { + setup: (self) => self.hook(Mpris, box => { let foundPlayer = false; Mpris.players.forEach((player, i) => { if (isRealPlayer(player)) { foundPlayer = true; - box._player = player; box.children = [MusicControlsWidget(player)]; } }); if (!foundPlayer) { - box._player = null; const children = box.get_children(); for (let i = 0; i < children.length; i++) { const child = children[i]; @@ -378,12 +373,10 @@ export default () => MarginRevealer({ } return; } - }, 'notify::players']], + }, 'notify::players'), + }), + setup: (self) => self.hook(showMusicControls, (revealer) => { + if (showMusicControls.value) revealer.attribute.show(); + else revealer.attribute.hide(); }), - connections: [ - [showMusicControls, (revealer) => { - if (showMusicControls.value) revealer._show(); - else revealer._hide(); - }], - ], }) diff --git a/.config/ags/widgets/indicators/notificationpopups.js b/.config/ags/widgets/indicators/notificationpopups.js index 84ac48e97..7ca3e8aea 100644 --- a/.config/ags/widgets/indicators/notificationpopups.js +++ b/.config/ags/widgets/indicators/notificationpopups.js @@ -1,9 +1,7 @@ // This file is for popup notifications -const { GLib, Gtk } = imports.gi; -import { App, Service, Utils, Widget } from '../../imports.js'; -import Audio from 'resource:///com/github/Aylur/ags/service/audio.js'; +import Widget from 'resource:///com/github/Aylur/ags/widget.js'; import Notifications from 'resource:///com/github/Aylur/ags/service/notifications.js'; -const { Box, EventBox, Icon, Scrollable, Label, Button, Revealer } = Widget; +const { Box } = Widget; import Notification from '../../lib/notification.js'; const PopupNotification = (notifObject) => Widget.Box({ @@ -39,41 +37,39 @@ const naiveNotifPopupList = Widget.Box({ const notifPopupList = Box({ vertical: true, className: 'osd-notifs spacing-v-5-revealer', - properties: [ - ['map', new Map()], - - ['dismiss', (box, id, force = false) => { - if (!id || !box._map.has(id) || box._map.get(id)._hovered && !force) + attribute: { + 'map': new Map(), + 'dismiss': (box, id, force = false) => { + if (!id || !box.attribute.map.has(id) || box.attribute.map.get(id).attribute.hovered && !force) return; - const notif = box._map.get(id); + const notif = box.attribute.map.get(id); notif.revealChild = false; - notif._destroyWithAnims(); - }], - - ['notify', (box, id) => { - // console.log('new notiffy', id, Notifications.getNotification(id)) + notif.attribute.destroyWithAnims(); + box.attribute.map.delete(id); + }, + 'notify': (box, id) => { if (!id || Notifications.dnd) return; if (!Notifications.getNotification(id)) return; - box._map.delete(id); + box.attribute.map.delete(id); const notif = Notifications.getNotification(id); const newNotif = Notification({ notifObject: notif, isPopup: true, }); - box._map.set(id, newNotif); - box.pack_end(box._map.get(id), false, false, 0); + box.attribute.map.set(id, newNotif); + box.pack_end(box.attribute.map.get(id), false, false, 0); box.show_all(); - // box.children = Array.from(box._map.values()).reverse(); - }], - ], + // box.children = Array.from(box.attribute.map.values()).reverse(); + }, + }, setup: (self) => self - .hook(Notifications, (box, id) => box._notify(box, id), 'notified') - .hook(Notifications, (box, id) => box._dismiss(box, id), 'dismissed') - .hook(Notifications, (box, id) => box._dismiss(box, id, true), 'closed') + .hook(Notifications, (box, id) => box.attribute.notify(box, id), 'notified') + .hook(Notifications, (box, id) => box.attribute.dismiss(box, id), 'dismissed') + .hook(Notifications, (box, id) => box.attribute.dismiss(box, id, true), 'closed') , }); diff --git a/.config/ags/widgets/onscreenkeyboard/onscreenkeyboard.js b/.config/ags/widgets/onscreenkeyboard/onscreenkeyboard.js index c0d1c62b3..75080861b 100644 --- a/.config/ags/widgets/onscreenkeyboard/onscreenkeyboard.js +++ b/.config/ags/widgets/onscreenkeyboard/onscreenkeyboard.js @@ -1,5 +1,9 @@ -const { GLib, Gdk, Gtk } = imports.gi; -import { App, Service, Utils, Widget } from '../../imports.js'; +const { Gtk } = imports.gi; +import App from 'resource:///com/github/Aylur/ags/app.js'; +import Widget from 'resource:///com/github/Aylur/ags/widget.js'; +import Service from 'resource:///com/github/Aylur/ags/service.js'; +import * as Utils from 'resource:///com/github/Aylur/ags/utils.js'; + import Hyprland from 'resource:///com/github/Aylur/ags/service/hyprland.js'; const { Box, EventBox, Button, Revealer } = Widget; const { execAsync, exec } = Utils; diff --git a/.config/ags/widgets/overview/actions.js b/.config/ags/widgets/overview/actions.js index 3229220c2..c5a429f53 100644 --- a/.config/ags/widgets/overview/actions.js +++ b/.config/ags/widgets/overview/actions.js @@ -1,6 +1,4 @@ -const { Gio, GLib } = imports.gi; -import { App, Service, Utils, Widget } from '../../imports.js'; -const { execAsync, exec } = Utils; +import * as Utils from 'resource:///com/github/Aylur/ags/utils.js'; import Hyprland from 'resource:///com/github/Aylur/ags/service/hyprland.js'; function moveClientToWorkspace(address, workspace) { diff --git a/.config/ags/widgets/overview/main.js b/.config/ags/widgets/overview/main.js index 9dde483a5..534fd8481 100644 --- a/.config/ags/widgets/overview/main.js +++ b/.config/ags/widgets/overview/main.js @@ -1,5 +1,5 @@ -import { Widget } from '../../imports.js'; -import { SearchAndWindows } from "./overview.js"; +import Widget from 'resource:///com/github/Aylur/ags/widget.js'; +import { SearchAndWindows } from "./windowcontent.js"; export default () => Widget.Window({ name: 'overview', diff --git a/.config/ags/widgets/overview/miscfunctions.js b/.config/ags/widgets/overview/miscfunctions.js index 8a3767429..42e2572f3 100644 --- a/.config/ags/widgets/overview/miscfunctions.js +++ b/.config/ags/widgets/overview/miscfunctions.js @@ -1,5 +1,6 @@ const { Gio, GLib } = imports.gi; -import { App, Service, Utils, Widget } from '../../imports.js'; +import App from 'resource:///com/github/Aylur/ags/app.js'; +import * as Utils from 'resource:///com/github/Aylur/ags/utils.js'; const { execAsync, exec } = Utils; import Todo from "../../services/todo.js"; diff --git a/.config/ags/widgets/overview/overview.js b/.config/ags/widgets/overview/overview.js deleted file mode 100644 index 7ae4fff05..000000000 --- a/.config/ags/widgets/overview/overview.js +++ /dev/null @@ -1,552 +0,0 @@ -const { Gdk, Gio, Gtk } = imports.gi; -import { App, Service, Utils, Variable, Widget, SCREEN_HEIGHT, SCREEN_WIDTH } from '../../imports.js'; -import Applications from 'resource:///com/github/Aylur/ags/service/applications.js'; -import Hyprland from 'resource:///com/github/Aylur/ags/service/hyprland.js'; -const { execAsync, exec } = Utils; -import { setupCursorHover, setupCursorHoverGrab } from "../../lib/cursorhover.js"; -import { DoubleRevealer } from "../../lib/advancedwidgets.js"; -import { execAndClose, expandTilde, hasUnterminatedBackslash, startsWithNumber, launchCustomCommand, ls } from './miscfunctions.js'; -import { - CalculationResultButton, CustomCommandButton, DirectoryButton, - DesktopEntryButton, ExecuteCommandButton, SearchButton -} from './searchbuttons.js'; -import { dumpToWorkspace, swapWorkspace } from "./actions.js"; - -// Add math funcs -const { abs, sin, cos, tan, cot, asin, acos, atan, acot } = Math; -const pi = Math.PI; -// trigonometric funcs for deg -const sind = x => sin(x * pi / 180); -const cosd = x => cos(x * pi / 180); -const tand = x => tan(x * pi / 180); -const cotd = x => cot(x * pi / 180); -const asind = x => asin(x) * 180 / pi; -const acosd = x => acos(x) * 180 / pi; -const atand = x => atan(x) * 180 / pi; -const acotd = x => acot(x) * 180 / pi; - -const MAX_RESULTS = 10; -const OVERVIEW_SCALE = 0.18; // = overview workspace box / screen size -const OVERVIEW_WS_NUM_SCALE = 0.09; -const OVERVIEW_WS_NUM_MARGIN_SCALE = 0.07; -const TARGET = [Gtk.TargetEntry.new('text/plain', Gtk.TargetFlags.SAME_APP, 0)]; -const searchPromptTexts = [ - 'Try "~/.config"', - 'Try "Files"', - 'Try "6*cos(pi)"', - 'Try "sudo pacman -Syu"', - 'Try "How to basic"', - 'Drag n\' drop to move windows', - 'Type to search', -] - -function truncateTitle(str) { - let lastDash = -1; - let found = -1; // 0: em dash, 1: en dash, 2: minus, 3: vertical bar, 4: middle dot - for (let i = str.length - 1; i >= 0; i--) { - if (str[i] === '—') { - found = 0; - lastDash = i; - } - else if (str[i] === '–' && found < 1) { - found = 1; - lastDash = i; - } - else if (str[i] === '-' && found < 2) { - found = 2; - lastDash = i; - } - else if (str[i] === '|' && found < 3) { - found = 3; - lastDash = i; - } - else if (str[i] === '·' && found < 4) { - found = 4; - lastDash = i; - } - } - if (lastDash === -1) return str; - return str.substring(0, lastDash); -} - -function iconExists(iconName) { - let iconTheme = Gtk.IconTheme.get_default(); - return iconTheme.has_icon(iconName); -} - -function substitute(str) { - const subs = [ - { from: 'code-url-handler', to: 'visual-studio-code' }, - { from: 'Code', to: 'visual-studio-code' }, - { from: 'GitHub Desktop', to: 'github-desktop' }, - { from: 'wpsoffice', to: 'wps-office2019-kprometheus' }, - { from: 'gnome-tweaks', to: 'org.gnome.tweaks' }, - { from: 'Minecraft* 1.20.1', to: 'minecraft' }, - { from: '', to: 'image-missing' }, - ]; - - for (const { from, to } of subs) { - if (from === str) - return to; - } - - if (!iconExists(str)) str = str.toLowerCase().replace(/\s+/g, '-'); // Turn into kebab-case - return str; -} - -const ContextWorkspaceArray = ({ label, actionFunc, thisWorkspace }) => Widget.MenuItem({ - label: `${label}`, - setup: (menuItem) => { - let submenu = new Gtk.Menu(); - submenu.className = 'menu'; - for (let i = 1; i <= 10; i++) { - let button = new Gtk.MenuItem({ - label: `Workspace ${i}` - }); - button.connect("activate", () => { - // execAsync([`${onClickBinary}`, `${thisWorkspace}`, `${i}`]).catch(print); - actionFunc(thisWorkspace, i); - }); - submenu.append(button); - } - menuItem.set_reserve_indicator(true); - menuItem.set_submenu(submenu); - } -}) - -const client = ({ address, size: [w, h], workspace: { id, name }, class: c, title, xwayland }) => { - const revealInfoCondition = (Math.min(w, h) * OVERVIEW_SCALE > 70); - if (w <= 0 || h <= 0) return null; - title = truncateTitle(title); - return Widget.Button({ - className: 'overview-tasks-window', - hpack: 'center', - vpack: 'center', - onClicked: () => { - Hyprland.sendMessage(`dispatch focuswindow address:${address}`); - App.closeWindow('overview'); - }, - onMiddleClickRelease: () => Hyprland.sendMessage(`dispatch closewindow address:${address}`), - onSecondaryClick: (button) => { - button.toggleClassName('overview-tasks-window-selected', true); - const menu = Widget.Menu({ - className: 'menu', - children: [ - Widget.MenuItem({ - child: Widget.Label({ - xalign: 0, - label: "Close (Middle-click)", - }), - onActivate: () => Hyprland.sendMessage(`dispatch closewindow address:${address}`), - }), - ContextWorkspaceArray({ - label: "Dump windows to workspace", - actionFunc: dumpToWorkspace, - thisWorkspace: Number(id) - }), - ContextWorkspaceArray({ - label: "Swap windows with workspace", - actionFunc: swapWorkspace, - thisWorkspace: Number(id) - }), - ], - }); - menu.connect("deactivate", () => { - button.toggleClassName('overview-tasks-window-selected', false); - }) - menu.connect("selection-done", () => { - button.toggleClassName('overview-tasks-window-selected', false); - }) - menu.popup_at_pointer(null); // Show the menu at the pointer's position - }, - child: Widget.Box({ - css: ` - min-width: ${Math.max(w * OVERVIEW_SCALE - 4, 1)}px; - min-height: ${Math.max(h * OVERVIEW_SCALE - 4, 1)}px; - `, - homogeneous: true, - child: Widget.Box({ - vertical: true, - vpack: 'center', - className: 'spacing-v-5', - children: [ - Widget.Icon({ - icon: substitute(c), - size: Math.min(w, h) * OVERVIEW_SCALE / 2.5, - }), - // TODO: Add xwayland tag instead of just having italics - DoubleRevealer({ - transition1: 'slide_right', - transition2: 'slide_down', - revealChild: revealInfoCondition, - child: Widget.Scrollable({ - hexpand: true, - vscroll: 'never', - hscroll: 'automatic', - child: Widget.Label({ - truncate: 'end', - className: `${xwayland ? 'txt txt-italic' : 'txt'}`, - css: ` - font-size: ${Math.min(SCREEN_WIDTH, SCREEN_HEIGHT) * OVERVIEW_SCALE / 14.6}px; - margin: 0px ${Math.min(SCREEN_WIDTH, SCREEN_HEIGHT) * OVERVIEW_SCALE / 10}px; - `, - // If the title is too short, include the class - label: (title.length <= 1 ? `${c}: ${title}` : title), - }) - }) - }) - ] - }) - }), - tooltipText: `${c}: ${title}`, - setup: (button) => { - setupCursorHoverGrab(button); - - button.drag_source_set(Gdk.ModifierType.BUTTON1_MASK, TARGET, Gdk.DragAction.MOVE); - button.drag_source_set_icon_name(substitute(c)); - // button.drag_source_set_icon_gicon(icon); - - button.connect('drag-begin', (button) => { // On drag start, add the dragging class - button.toggleClassName('overview-tasks-window-dragging', true); - }); - button.connect('drag-data-get', (_w, _c, data) => { // On drag finish, give address - data.set_text(address, address.length); - button.toggleClassName('overview-tasks-window-dragging', false); - }); - }, - }); -} - -const workspace = index => { - const fixed = Gtk.Fixed.new(); - const WorkspaceNumber = (index) => Widget.Label({ - className: 'overview-tasks-workspace-number', - label: `${index}`, - css: ` - margin: ${Math.min(SCREEN_WIDTH, SCREEN_HEIGHT) * OVERVIEW_SCALE * OVERVIEW_WS_NUM_MARGIN_SCALE}px; - font-size: ${SCREEN_HEIGHT * OVERVIEW_SCALE * OVERVIEW_WS_NUM_SCALE}px; - `, - }) - const widget = Widget.Box({ - className: 'overview-tasks-workspace', - vpack: 'center', - css: ` - min-width: ${SCREEN_WIDTH * OVERVIEW_SCALE}px; - min-height: ${SCREEN_HEIGHT * OVERVIEW_SCALE}px; - `, - children: [Widget.EventBox({ - hexpand: true, - vexpand: true, - onPrimaryClick: () => { - Hyprland.sendMessage(`dispatch workspace ${index}`) - App.closeWindow('overview'); - }, - setup: (eventbox) => { - eventbox.drag_dest_set(Gtk.DestDefaults.ALL, TARGET, Gdk.DragAction.COPY); - eventbox.connect('drag-data-received', (_w, _c, _x, _y, data) => { - Hyprland.sendMessage(`dispatch movetoworkspacesilent ${index},address:${data.get_text()}`) - }); - }, - child: fixed, - })], - }); - widget.update = (clients) => { - clients = clients.filter(({ workspace: { id } }) => id === index); - - // this is for my monitor layout - // shifts clients back by SCREEN_WIDTHpx if necessary - clients = clients.map(client => { - const [x, y] = client.at; - if (x > SCREEN_WIDTH) - client.at = [x - SCREEN_WIDTH, y]; - return client; - }); - - const children = fixed.get_children(); - for (let i = 0; i < children.length; i++) { - const child = children[i]; - child.destroy(); - } - fixed.put(WorkspaceNumber(index), 0, 0); - - for (let i = 0; i < clients.length; i++) { - const c = clients[i]; - if (c.mapped) { - fixed.put(client(c), c.at[0] * OVERVIEW_SCALE, c.at[1] * OVERVIEW_SCALE); - } - } - - - - fixed.show_all(); - }; - return widget; -}; - -const arr = (s, n) => { - const array = []; - for (let i = 0; i < n; i++) - array.push(s + i); - - return array; -}; - -const OverviewRow = ({ startWorkspace, workspaces, windowName = 'overview' }) => Widget.Box({ - children: arr(startWorkspace, workspaces).map(workspace), - properties: [['update', box => { - if (!App.getWindow(windowName).visible) return; - execAsync('hyprctl -j clients').then(clients => { - const json = JSON.parse(clients); - const children = box.get_children(); - for (let i = 0; i < children.length; i++) { - const ch = children[i]; - ch.update(json) - } - - }).catch(print); - }]], - setup: (box) => { - box - // .hook(Hyprland, (box, name, data) => { // idk, does this make it lag occasionally? - // if (["changefloatingmode", "movewindow"].includes(name)) - // box._update(box); - // }, 'event') - .hook(Hyprland, (box) => box._update(box), 'client-added') - .hook(Hyprland, (box) => box._update(box), 'client-removed') - .hook(App, (box, name, visible) => { // Update on open - if (name == 'overview' && visible) box._update(box); - }) - }, -}); - - -export const SearchAndWindows = () => { - var _appSearchResults = []; - - const ClickToClose = ({ ...props }) => Widget.EventBox({ - ...props, - onPrimaryClick: () => App.closeWindow('overview'), - onSecondaryClick: () => App.closeWindow('overview'), - onMiddleClick: () => App.closeWindow('overview'), - }); - const resultsBox = Widget.Box({ - className: 'overview-search-results', - vertical: true, - vexpand: true, - }); - const resultsRevealer = Widget.Revealer({ - transitionDuration: 200, - revealChild: false, - transition: 'slide_down', - // duration: 200, - hpack: 'center', - child: resultsBox, - }); - const overviewRevealer = Widget.Revealer({ - revealChild: true, - transition: 'slide_down', - transitionDuration: 200, - child: Widget.Box({ - vertical: true, - className: 'overview-tasks', - children: [ - OverviewRow({ startWorkspace: 1, workspaces: 5 }), - OverviewRow({ startWorkspace: 6, workspaces: 5 }), - ] - }), - }); - const entryPromptRevealer = Widget.Revealer({ - transition: 'crossfade', - transitionDuration: 150, - revealChild: true, - hpack: 'center', - child: Widget.Label({ - className: 'overview-search-prompt txt-small txt', - label: searchPromptTexts[Math.floor(Math.random() * searchPromptTexts.length)], - }) - }); - - const entryIconRevealer = Widget.Revealer({ - transition: 'crossfade', - transitionDuration: 150, - revealChild: false, - hpack: 'end', - child: Widget.Label({ - className: 'txt txt-large icon-material overview-search-icon', - label: 'search', - }), - }); - - const entryIcon = Widget.Box({ - className: 'overview-search-prompt-box', - setup: box => box.pack_start(entryIconRevealer, true, true, 0), - }); - - const entry = Widget.Entry({ - className: 'overview-search-box txt-small txt', - hpack: 'center', - onAccept: (self) => { // This is when you hit Enter - const text = self.text; - if (text.length == 0) return; - const isAction = text.startsWith('>'); - const isDir = (['/', '~'].includes(entry.text[0])); - - if (startsWithNumber(text)) { // Eval on typing is dangerous, this is a workaround - try { - const fullResult = eval(text); - // copy - execAsync(['wl-copy', `${fullResult}`]).catch(print); - App.closeWindow('overview'); - return; - } catch (e) { - // console.log(e); - } - } - if (isDir) { - App.closeWindow('overview'); - execAsync(['bash', '-c', `xdg-open "${expandTilde(text)}"`, `&`]).catch(print); - return; - } - if (_appSearchResults.length > 0) { - App.closeWindow('overview'); - _appSearchResults[0].launch(); - return; - } - else if (text[0] == '>') { // Custom commands - App.closeWindow('overview'); - launchCustomCommand(text); - return; - } - // Fallback: Execute command - if (!isAction && exec(`bash -c "command -v ${text.split(' ')[0]}"`) != '') { - if (text.startsWith('sudo')) - execAndClose(text, true); - else - execAndClose(text, false); - } - - else { - App.closeWindow('overview'); - execAsync(['bash', '-c', `xdg-open 'https://www.google.com/search?q=${text} -site:quora.com' &`]).catch(print); // quora is useless - } - }, - onChange: (entry) => { - const isAction = entry.text[0] == '>'; - const isDir = (['/', '~'].includes(entry.text[0])); - const children = resultsBox.get_children(); - for (let i = 0; i < children.length; i++) { - const child = children[i]; - child.destroy(); - } - // check empty if so then dont do stuff - if (entry.text == '') { - resultsRevealer.set_reveal_child(false); - overviewRevealer.set_reveal_child(true); - entryPromptRevealer.set_reveal_child(true); - entryIconRevealer.set_reveal_child(false); - entry.toggleClassName('overview-search-box-extended', false); - return; - } - const text = entry.text; - resultsRevealer.set_reveal_child(true); - overviewRevealer.set_reveal_child(false); - entryPromptRevealer.set_reveal_child(false); - entryIconRevealer.set_reveal_child(true); - entry.toggleClassName('overview-search-box-extended', true); - _appSearchResults = Applications.query(text); - - // Calculate - if (startsWithNumber(text)) { // Eval on typing is dangerous, this is a small workaround. - try { - const fullResult = eval(text); - resultsBox.add(CalculationResultButton({ result: fullResult, text: text })); - } catch (e) { - // console.log(e); - } - } - if (isDir) { - var contents = []; - contents = ls({ path: text, silent: true }); - contents.forEach((item) => { - resultsBox.add(DirectoryButton(item)); - }) - } - if (isAction) { // Eval on typing is dangerous, this is a workaround. - resultsBox.add(CustomCommandButton({ text: entry.text })); - } - // Add application entries - let appsToAdd = MAX_RESULTS; - _appSearchResults.forEach(app => { - if (appsToAdd == 0) return; - resultsBox.add(DesktopEntryButton(app)); - appsToAdd--; - }); - - // Fallbacks - // if the first word is an actual command - if (!isAction && !hasUnterminatedBackslash(text) && exec(`bash -c "command -v ${text.split(' ')[0]}"`) != '') { - resultsBox.add(ExecuteCommandButton({ command: entry.text, terminal: entry.text.startsWith('sudo') })); - } - - // Add fallback: search - resultsBox.add(SearchButton({ text: entry.text })); - resultsBox.show_all(); - }, - }); - - return Widget.Box({ - vertical: true, - children: [ - ClickToClose({ // Top margin. Also works as a click-outside-to-close thing - child: Widget.Box({ - className: 'bar-height', - }) - }), - Widget.Box({ - hpack: 'center', - children: [ - entry, - Widget.Box({ - className: 'overview-search-icon-box', - setup: box => box.pack_start(entryPromptRevealer, true, true, 0), - }), - entryIcon, - ] - }), - overviewRevealer, - resultsRevealer, - ], - setup: (self) => self - .hook(App, (_b, name, visible) => { - if (name == 'overview' && !visible) { - entryPromptRevealer.child.label = searchPromptTexts[Math.floor(Math.random() * searchPromptTexts.length)]; - resultsBox.children = []; - entry.set_text(''); - } - }) - .on('key-press-event', (widget, event) => { // Typing - if (event.get_keyval()[1] >= 32 && event.get_keyval()[1] <= 126 && widget != entry) { - Utils.timeout(1, () => entry.grab_focus()); - entry.set_text(entry.text + String.fromCharCode(event.get_keyval()[1])); - entry.set_position(-1); - } - }) - , - // connections: [ - // [App, (_b, name, visible) => { - // if (name == 'overview' && !visible) { - // entryPromptRevealer.child.label = searchPromptTexts[Math.floor(Math.random() * searchPromptTexts.length)]; - // resultsBox.children = []; - // entry.set_text(''); - // } - // }], - // ['key-press-event', (widget, event) => { // Typing - // if (event.get_keyval()[1] >= 32 && event.get_keyval()[1] <= 126 && widget != entry) { - // Utils.timeout(1, () => entry.grab_focus()); - // entry.set_text(entry.text + String.fromCharCode(event.get_keyval()[1])); - // entry.set_position(-1); - // } - // }], - // ], - }); -}; diff --git a/.config/ags/widgets/overview/overview_hyprland.js b/.config/ags/widgets/overview/overview_hyprland.js new file mode 100644 index 000000000..e3452afe3 --- /dev/null +++ b/.config/ags/widgets/overview/overview_hyprland.js @@ -0,0 +1,308 @@ +const { Gdk, Gtk } = imports.gi; +import { SCREEN_HEIGHT, SCREEN_WIDTH } from '../../imports.js'; +import App from 'resource:///com/github/Aylur/ags/app.js'; +import Widget from 'resource:///com/github/Aylur/ags/widget.js'; +import * as Utils from 'resource:///com/github/Aylur/ags/utils.js'; + +import Hyprland from 'resource:///com/github/Aylur/ags/service/hyprland.js'; +const { execAsync, exec } = Utils; +import { setupCursorHoverGrab } from "../../lib/cursorhover.js"; +import { dumpToWorkspace, swapWorkspace } from "./actions.js"; + +const OVERVIEW_SCALE = 0.18; // = overview workspace box / screen size +const OVERVIEW_WS_NUM_SCALE = 0.09; +const OVERVIEW_WS_NUM_MARGIN_SCALE = 0.07; +const TARGET = [Gtk.TargetEntry.new('text/plain', Gtk.TargetFlags.SAME_APP, 0)]; + +function truncateTitle(str) { + let lastDash = -1; + let found = -1; // 0: em dash, 1: en dash, 2: minus, 3: vertical bar, 4: middle dot + for (let i = str.length - 1; i >= 0; i--) { + if (str[i] === '—') { + found = 0; + lastDash = i; + } + else if (str[i] === '–' && found < 1) { + found = 1; + lastDash = i; + } + else if (str[i] === '-' && found < 2) { + found = 2; + lastDash = i; + } + else if (str[i] === '|' && found < 3) { + found = 3; + lastDash = i; + } + else if (str[i] === '·' && found < 4) { + found = 4; + lastDash = i; + } + } + if (lastDash === -1) return str; + return str.substring(0, lastDash); +} + +function iconExists(iconName) { + let iconTheme = Gtk.IconTheme.get_default(); + return iconTheme.has_icon(iconName); +} + +function substitute(str) { + const subs = [ + { from: 'code-url-handler', to: 'visual-studio-code' }, + { from: 'Code', to: 'visual-studio-code' }, + { from: 'GitHub Desktop', to: 'github-desktop' }, + { from: 'wpsoffice', to: 'wps-office2019-kprometheus' }, + { from: 'gnome-tweaks', to: 'org.gnome.tweaks' }, + { from: 'Minecraft* 1.20.1', to: 'minecraft' }, + { from: '', to: 'image-missing' }, + ]; + + for (const { from, to } of subs) { + if (from === str) + return to; + } + + if (!iconExists(str)) str = str.toLowerCase().replace(/\s+/g, '-'); // Turn into kebab-case + return str; +} + +const ContextMenuWorkspaceArray = ({ label, actionFunc, thisWorkspace }) => Widget.MenuItem({ + label: `${label}`, + setup: (menuItem) => { + let submenu = new Gtk.Menu(); + submenu.className = 'menu'; + for (let i = 1; i <= 10; i++) { + let button = new Gtk.MenuItem({ + label: `Workspace ${i}` + }); + button.connect("activate", () => { + // execAsync([`${onClickBinary}`, `${thisWorkspace}`, `${i}`]).catch(print); + actionFunc(thisWorkspace, i); + }); + submenu.append(button); + } + menuItem.set_reserve_indicator(true); + menuItem.set_submenu(submenu); + } +}) + +const client = ({ address, size: [w, h], workspace: { id, name }, class: c, title, xwayland }) => { + const revealInfoCondition = (Math.min(w, h) * OVERVIEW_SCALE > 70); + if (w <= 0 || h <= 0) return null; + // title = truncateTitle(title); + return Widget.Button({ + className: 'overview-tasks-window', + hpack: 'center', + vpack: 'center', + onClicked: () => { + Hyprland.sendMessage(`dispatch focuswindow address:${address}`); + App.closeWindow('overview'); + }, + onMiddleClickRelease: () => Hyprland.sendMessage(`dispatch closewindow address:${address}`), + onSecondaryClick: (button) => { + button.toggleClassName('overview-tasks-window-selected', true); + const menu = Widget.Menu({ + className: 'menu', + children: [ + Widget.MenuItem({ + child: Widget.Label({ + xalign: 0, + label: "Close (Middle-click)", + }), + onActivate: () => Hyprland.sendMessage(`dispatch closewindow address:${address}`), + }), + ContextMenuWorkspaceArray({ + label: "Dump windows to workspace", + actionFunc: dumpToWorkspace, + thisWorkspace: Number(id) + }), + ContextMenuWorkspaceArray({ + label: "Swap windows with workspace", + actionFunc: swapWorkspace, + thisWorkspace: Number(id) + }), + ], + }); + menu.connect("deactivate", () => { + button.toggleClassName('overview-tasks-window-selected', false); + }) + menu.connect("selection-done", () => { + button.toggleClassName('overview-tasks-window-selected', false); + }) + menu.popup_at_pointer(null); // Show the menu at the pointer's position + }, + child: Widget.Box({ + css: ` + min-width: ${Math.max(w * OVERVIEW_SCALE - 4, 1)}px; + min-height: ${Math.max(h * OVERVIEW_SCALE - 4, 1)}px; + `, + homogeneous: true, + child: Widget.Box({ + vertical: true, + vpack: 'center', + className: 'spacing-v-5', + children: [ + Widget.Icon({ + icon: substitute(c), + size: Math.min(w, h) * OVERVIEW_SCALE / 2.5, + }), + // TODO: Add xwayland tag instead of just having italics + Widget.Revealer({ + transition: 'slide_down', + revealChild: revealInfoCondition, + child: Widget.Label({ + truncate: 'end', + className: `${xwayland ? 'txt txt-italic' : 'txt'}`, + css: ` + font-size: ${Math.min(SCREEN_WIDTH, SCREEN_HEIGHT) * OVERVIEW_SCALE / 14.6}px; + margin: 0px ${Math.min(SCREEN_WIDTH, SCREEN_HEIGHT) * OVERVIEW_SCALE / 10}px; + `, + // If the title is too short, include the class + label: (title.length <= 1 ? `${c}: ${title}` : title), + }) + }) + ] + }) + }), + tooltipText: `${c}: ${title}`, + setup: (button) => { + setupCursorHoverGrab(button); + + button.drag_source_set(Gdk.ModifierType.BUTTON1_MASK, TARGET, Gdk.DragAction.MOVE); + button.drag_source_set_icon_name(substitute(c)); + // button.drag_source_set_icon_gicon(icon); + + button.connect('drag-begin', (button) => { // On drag start, add the dragging class + button.toggleClassName('overview-tasks-window-dragging', true); + }); + button.connect('drag-data-get', (_w, _c, data) => { // On drag finish, give address + data.set_text(address, address.length); + button.toggleClassName('overview-tasks-window-dragging', false); + }); + }, + }); +} + +const workspace = index => { + const fixed = Gtk.Fixed.new(); + const WorkspaceNumber = (index) => Widget.Label({ + className: 'overview-tasks-workspace-number', + label: `${index}`, + css: ` + margin: ${Math.min(SCREEN_WIDTH, SCREEN_HEIGHT) * OVERVIEW_SCALE * OVERVIEW_WS_NUM_MARGIN_SCALE}px; + font-size: ${SCREEN_HEIGHT * OVERVIEW_SCALE * OVERVIEW_WS_NUM_SCALE}px; + `, + }) + const widget = Widget.Box({ + className: 'overview-tasks-workspace', + vpack: 'center', + css: ` + min-width: ${SCREEN_WIDTH * OVERVIEW_SCALE}px; + min-height: ${SCREEN_HEIGHT * OVERVIEW_SCALE}px; + `, + children: [Widget.EventBox({ + hexpand: true, + vexpand: true, + onPrimaryClick: () => { + Hyprland.sendMessage(`dispatch workspace ${index}`) + App.closeWindow('overview'); + }, + setup: (eventbox) => { + eventbox.drag_dest_set(Gtk.DestDefaults.ALL, TARGET, Gdk.DragAction.COPY); + eventbox.connect('drag-data-received', (_w, _c, _x, _y, data) => { + Hyprland.sendMessage(`dispatch movetoworkspacesilent ${index},address:${data.get_text()}`) + }); + }, + child: fixed, + })], + }); + widget.update = (clients) => { + clients = clients.filter(({ workspace: { id } }) => id === index); + + // this is for my monitor layout + // shifts clients back by SCREEN_WIDTHpx if necessary + clients = clients.map(client => { + const [x, y] = client.at; + if (x > SCREEN_WIDTH) + client.at = [x - SCREEN_WIDTH, y]; + return client; + }); + + const children = fixed.get_children(); + for (let i = 0; i < children.length; i++) { + const child = children[i]; + child.destroy(); + } + fixed.put(WorkspaceNumber(index), 0, 0); + + for (let i = 0; i < clients.length; i++) { + const c = clients[i]; + if (c.mapped) { + fixed.put(client(c), c.at[0] * OVERVIEW_SCALE, c.at[1] * OVERVIEW_SCALE); + } + } + + + + fixed.show_all(); + }; + return widget; +}; + +const arr = (s, n) => { + const array = []; + for (let i = 0; i < n; i++) + array.push(s + i); + + return array; +}; + +const OverviewRow = ({ startWorkspace, workspaces, windowName = 'overview' }) => Widget.Box({ + children: arr(startWorkspace, workspaces).map(workspace), + attribute: { + 'update': box => { + if (!App.getWindow(windowName).visible) return; + execAsync('hyprctl -j clients').then(clients => { + const json = JSON.parse(clients); + const children = box.get_children(); + for (let i = 0; i < children.length; i++) { + const ch = children[i]; + ch.update(json) + } + + }).catch(print); + } + }, + setup: (box) => { + box + // .hook(Hyprland, (box, name, data) => { // idk, does this make it lag occasionally? + // if (["changefloatingmode", "movewindow"].includes(name)) + // box.attribute.update(box); + // }, 'event') + .hook(Hyprland, (box) => box.attribute.update(box), 'client-added') + .hook(Hyprland, (box) => box.attribute.update(box), 'client-removed') + .hook(App, (box, name, visible) => { // Update on open + if (name == 'overview' && visible) box.attribute.update(box); + }) + }, +}); + + +export default () => { + const overviewRevealer = Widget.Revealer({ + revealChild: true, + transition: 'slide_down', + transitionDuration: 200, + child: Widget.Box({ + vertical: true, + className: 'overview-tasks', + children: [ + OverviewRow({ startWorkspace: 1, workspaces: 5 }), + OverviewRow({ startWorkspace: 6, workspaces: 5 }), + ] + }), + }); + return overviewRevealer; +}; diff --git a/.config/ags/widgets/overview/searchbuttons.js b/.config/ags/widgets/overview/searchbuttons.js index f084d033e..475cbaf9f 100644 --- a/.config/ags/widgets/overview/searchbuttons.js +++ b/.config/ags/widgets/overview/searchbuttons.js @@ -1,5 +1,7 @@ -const { Gdk, Gtk } = imports.gi; -import { App, Service, Utils, Widget } from '../../imports.js'; +const { Gtk } = imports.gi; +import App from 'resource:///com/github/Aylur/ags/app.js'; +import Widget from 'resource:///com/github/Aylur/ags/widget.js'; +import * as Utils from 'resource:///com/github/Aylur/ags/utils.js'; const { execAsync, exec } = Utils; import { searchItem } from './searchitem.js'; import { execAndClose, startsWithNumber, launchCustomCommand } from './miscfunctions.js'; @@ -54,16 +56,16 @@ export const DirectoryButton = ({ parentPath, name, type, icon }) => { }) ] }), - connections: [ - ['focus-in-event', (button) => { + setup: (self) => self + .on('focus-in-event', (button) => { actionText.revealChild = true; actionTextRevealer.revealChild = true; - }], - ['focus-out-event', (button) => { + }) + .on('focus-out-event', (button) => { actionText.revealChild = false; actionTextRevealer.revealChild = false; - }], - ] + }) + , }) } @@ -128,16 +130,16 @@ export const DesktopEntryButton = (app) => { }) ] }), - connections: [ - ['focus-in-event', (button) => { + setup: (self) => self + .on('focus-in-event', (button) => { actionText.revealChild = true; actionTextRevealer.revealChild = true; - }], - ['focus-out-event', (button) => { + }) + .on('focus-out-event', (button) => { actionText.revealChild = false; actionTextRevealer.revealChild = false; - }], - ] + }) + , }) } diff --git a/.config/ags/widgets/overview/searchitem.js b/.config/ags/widgets/overview/searchitem.js index f64c195db..97b65d3ba 100644 --- a/.config/ags/widgets/overview/searchitem.js +++ b/.config/ags/widgets/overview/searchitem.js @@ -1,8 +1,4 @@ -const { Gdk, Gtk } = imports.gi; -import { App, Service, Utils, Widget } from '../../imports.js'; -const { execAsync, exec } = Utils; -import { setupCursorHover, setupCursorHoverAim } from "../../lib/cursorhover.js"; -import { MaterialIcon } from '../../lib/materialicon.js'; +import Widget from 'resource:///com/github/Aylur/ags/widget.js'; export const searchItem = ({ materialIconName, name, actionName, content, onActivate }) => { const actionText = Widget.Revealer({ @@ -55,15 +51,15 @@ export const searchItem = ({ materialIconName, name, actionName, content, onActi }) ] }), - connections: [ - ['focus-in-event', (button) => { + setup: (self) => self + .on('focus-in-event', (button) => { actionText.revealChild = true; actionTextRevealer.revealChild = true; - }], - ['focus-out-event', (button) => { + }) + .on('focus-out-event', (button) => { actionText.revealChild = false; actionTextRevealer.revealChild = false; - }], - ] + }) + , }); } diff --git a/.config/ags/widgets/overview/windowcontent.js b/.config/ags/widgets/overview/windowcontent.js new file mode 100644 index 000000000..b5d8b7295 --- /dev/null +++ b/.config/ags/widgets/overview/windowcontent.js @@ -0,0 +1,244 @@ +const { Gtk } = imports.gi; +import App from 'resource:///com/github/Aylur/ags/app.js'; +import Widget from 'resource:///com/github/Aylur/ags/widget.js'; +import * as Utils from 'resource:///com/github/Aylur/ags/utils.js'; + +import Applications from 'resource:///com/github/Aylur/ags/service/applications.js'; +const { execAsync, exec } = Utils; +import { execAndClose, expandTilde, hasUnterminatedBackslash, startsWithNumber, launchCustomCommand, ls } from './miscfunctions.js'; +import { + CalculationResultButton, CustomCommandButton, DirectoryButton, + DesktopEntryButton, ExecuteCommandButton, SearchButton +} from './searchbuttons.js'; + +// Add math funcs +const { abs, sin, cos, tan, cot, asin, acos, atan, acot } = Math; +const pi = Math.PI; +// trigonometric funcs for deg +const sind = x => sin(x * pi / 180); +const cosd = x => cos(x * pi / 180); +const tand = x => tan(x * pi / 180); +const cotd = x => cot(x * pi / 180); +const asind = x => asin(x) * 180 / pi; +const acosd = x => acos(x) * 180 / pi; +const atand = x => atan(x) * 180 / pi; +const acotd = x => acot(x) * 180 / pi; + +const MAX_RESULTS = 10; +const OVERVIEW_SCALE = 0.18; // = overview workspace box / screen size +const OVERVIEW_WS_NUM_SCALE = 0.09; +const OVERVIEW_WS_NUM_MARGIN_SCALE = 0.07; +const TARGET = [Gtk.TargetEntry.new('text/plain', Gtk.TargetFlags.SAME_APP, 0)]; + +function iconExists(iconName) { + let iconTheme = Gtk.IconTheme.get_default(); + return iconTheme.has_icon(iconName); +} + +const OptionalOverview = async () => { + try { + return (await import('./overview_hyprland.js')).default(); + } catch { + return null; + // return (await import('./overview_hyprland.js')).default(); + } +}; + +const overviewContent = await OptionalOverview(); + +export const SearchAndWindows = () => { + var _appSearchResults = []; + + const ClickToClose = ({ ...props }) => Widget.EventBox({ + ...props, + onPrimaryClick: () => App.closeWindow('overview'), + onSecondaryClick: () => App.closeWindow('overview'), + onMiddleClick: () => App.closeWindow('overview'), + }); + const resultsBox = Widget.Box({ + className: 'overview-search-results', + vertical: true, + vexpand: true, + }); + const resultsRevealer = Widget.Revealer({ + transitionDuration: 200, + revealChild: false, + transition: 'slide_down', + // duration: 200, + hpack: 'center', + child: resultsBox, + }); + const entryPromptRevealer = Widget.Revealer({ + transition: 'crossfade', + transitionDuration: 150, + revealChild: true, + hpack: 'center', + child: Widget.Label({ + className: 'overview-search-prompt txt-small txt', + label: 'Type to search' + }) + }); + + const entryIconRevealer = Widget.Revealer({ + transition: 'crossfade', + transitionDuration: 150, + revealChild: false, + hpack: 'end', + child: Widget.Label({ + className: 'txt txt-large icon-material overview-search-icon', + label: 'search', + }), + }); + + const entryIcon = Widget.Box({ + className: 'overview-search-prompt-box', + setup: box => box.pack_start(entryIconRevealer, true, true, 0), + }); + + const entry = Widget.Entry({ + className: 'overview-search-box txt-small txt', + hpack: 'center', + onAccept: (self) => { // This is when you hit Enter + const text = self.text; + if (text.length == 0) return; + const isAction = text.startsWith('>'); + const isDir = (['/', '~'].includes(entry.text[0])); + + if (startsWithNumber(text)) { // Eval on typing is dangerous, this is a workaround + try { + const fullResult = eval(text); + // copy + execAsync(['wl-copy', `${fullResult}`]).catch(print); + App.closeWindow('overview'); + return; + } catch (e) { + // console.log(e); + } + } + if (isDir) { + App.closeWindow('overview'); + execAsync(['bash', '-c', `xdg-open "${expandTilde(text)}"`, `&`]).catch(print); + return; + } + if (_appSearchResults.length > 0) { + App.closeWindow('overview'); + _appSearchResults[0].launch(); + return; + } + else if (text[0] == '>') { // Custom commands + App.closeWindow('overview'); + launchCustomCommand(text); + return; + } + // Fallback: Execute command + if (!isAction && exec(`bash -c "command -v ${text.split(' ')[0]}"`) != '') { + if (text.startsWith('sudo')) + execAndClose(text, true); + else + execAndClose(text, false); + } + + else { + App.closeWindow('overview'); + execAsync(['bash', '-c', `xdg-open 'https://www.google.com/search?q=${text} -site:quora.com' &`]).catch(print); // quora is useless + } + }, + onChange: (entry) => { // this is when you type + const isAction = entry.text[0] == '>'; + const isDir = (['/', '~'].includes(entry.text[0])); + resultsBox.get_children().forEach(ch => ch.destroy()); + + // check empty if so then dont do stuff + if (entry.text == '') { + resultsRevealer.revealChild = false; + overviewContent.revealChild = true; + entryPromptRevealer.revealChild = true; + entryIconRevealer.revealChild = false; + entry.toggleClassName('overview-search-box-extended', false); + return; + } + const text = entry.text; + resultsRevealer.revealChild = true; + overviewContent.revealChild = false; + entryPromptRevealer.revealChild = false; + entryIconRevealer.revealChild = true; + entry.toggleClassName('overview-search-box-extended', true); + _appSearchResults = Applications.query(text); + + // Calculate + if (startsWithNumber(text)) { // Eval on typing is dangerous, this is a small workaround. + try { + const fullResult = eval(text); + resultsBox.add(CalculationResultButton({ result: fullResult, text: text })); + } catch (e) { + // console.log(e); + } + } + if (isDir) { + var contents = []; + contents = ls({ path: text, silent: true }); + contents.forEach((item) => { + resultsBox.add(DirectoryButton(item)); + }) + } + if (isAction) { // Eval on typing is dangerous, this is a workaround. + resultsBox.add(CustomCommandButton({ text: entry.text })); + } + // Add application entries + let appsToAdd = MAX_RESULTS; + _appSearchResults.forEach(app => { + if (appsToAdd == 0) return; + resultsBox.add(DesktopEntryButton(app)); + appsToAdd--; + }); + + // Fallbacks + // if the first word is an actual command + if (!isAction && !hasUnterminatedBackslash(text) && exec(`bash -c "command -v ${text.split(' ')[0]}"`) != '') { + resultsBox.add(ExecuteCommandButton({ command: entry.text, terminal: entry.text.startsWith('sudo') })); + } + + // Add fallback: search + resultsBox.add(SearchButton({ text: entry.text })); + resultsBox.show_all(); + }, + }); + return Widget.Box({ + vertical: true, + children: [ + ClickToClose({ // Top margin. Also works as a click-outside-to-close thing + child: Widget.Box({ + className: 'bar-height', + }) + }), + Widget.Box({ + hpack: 'center', + children: [ + entry, + Widget.Box({ + className: 'overview-search-icon-box', + setup: box => box.pack_start(entryPromptRevealer, true, true, 0), + }), + entryIcon, + ] + }), + overviewContent, + resultsRevealer, + ], + setup: (self) => self + .hook(App, (_b, name, visible) => { + if (name == 'overview' && !visible) { + resultsBox.children = []; + entry.set_text(''); + } + }) + .on('key-press-event', (widget, event) => { // Typing + if (event.get_keyval()[1] >= 32 && event.get_keyval()[1] <= 126 && widget != entry) { + Utils.timeout(1, () => entry.grab_focus()); + entry.set_text(entry.text + String.fromCharCode(event.get_keyval()[1])); + entry.set_position(-1); + } + }) + , + }); +}; diff --git a/.config/ags/widgets/screencorners/main.js b/.config/ags/widgets/screencorners/main.js index baaf55081..74e9dd52f 100644 --- a/.config/ags/widgets/screencorners/main.js +++ b/.config/ags/widgets/screencorners/main.js @@ -1,5 +1,5 @@ import Cairo from 'gi://cairo?version=1.0'; -import { Widget } from '../../imports.js'; +import Widget from 'resource:///com/github/Aylur/ags/widget.js'; import { RoundedCorner } from "../../lib/roundedcorner.js"; const dummyRegion = new Cairo.Region(); diff --git a/.config/ags/widgets/session/main.js b/.config/ags/widgets/session/main.js index 589aa04b5..8508ba317 100644 --- a/.config/ags/widgets/session/main.js +++ b/.config/ags/widgets/session/main.js @@ -1,5 +1,4 @@ -const { Gdk, Gtk } = imports.gi; -import { Widget } from '../../imports.js'; +import Widget from 'resource:///com/github/Aylur/ags/widget.js'; import SessionScreen from "./sessionscreen.js"; export default () => Widget.Window({ // On-screen keyboard diff --git a/.config/ags/widgets/session/sessionscreen.js b/.config/ags/widgets/session/sessionscreen.js index 468508da1..0b760fd21 100644 --- a/.config/ags/widgets/session/sessionscreen.js +++ b/.config/ags/widgets/session/sessionscreen.js @@ -1,7 +1,11 @@ // This is for the cool memory indicator on the sidebar // For the right pill of the bar, see system.js const { Gdk, Gtk } = imports.gi; -import { App, Service, Utils, Widget, SCREEN_HEIGHT, SCREEN_WIDTH } from '../../imports.js'; +import { SCREEN_HEIGHT, SCREEN_WIDTH } from '../../imports.js'; +import App from 'resource:///com/github/Aylur/ags/app.js'; +import Widget from 'resource:///com/github/Aylur/ags/widget.js'; +import * as Utils from 'resource:///com/github/Aylur/ags/utils.js'; + const { exec, execAsync } = Utils; const SessionButton = (name, icon, command, props = {}) => { @@ -41,16 +45,16 @@ const SessionButton = (name, icon, command, props = {}) => { button.get_window().set_cursor(cursor); buttonDescription.revealChild = false; }, - connections: [ - ['focus-in-event', (self) => { + setup: (self) => self + .on('focus-in-event', (self) => { buttonDescription.revealChild = true; self.toggleClassName('session-button-focused', true); - }], - ['focus-out-event', (self) => { + }) + .on('focus-out-event', (self) => { buttonDescription.revealChild = false; self.toggleClassName('session-button-focused', false); - }], - ], + }) + , ...props, }); } @@ -134,10 +138,10 @@ export default () => { ] }) ], - connections: [ - [App, (_b, name, visible) => { + setup: (self) => self + .hook(App, (_b, name, visible) => { if (visible) lockButton.grab_focus(); // Lock is the default option - }], - ], + }) + , }); } diff --git a/.config/ags/widgets/sideleft/apis/chatgpt.js b/.config/ags/widgets/sideleft/apis/chatgpt.js index d0d650c08..745ab5c46 100644 --- a/.config/ags/widgets/sideleft/apis/chatgpt.js +++ b/.config/ags/widgets/sideleft/apis/chatgpt.js @@ -1,5 +1,8 @@ -const { Gdk, GLib, Gtk, Pango } = imports.gi; -import { App, Utils, Widget } from '../../../imports.js'; +const { Gtk } = imports.gi; +import App from 'resource:///com/github/Aylur/ags/app.js'; +import Widget from 'resource:///com/github/Aylur/ags/widget.js'; +import * as Utils from 'resource:///com/github/Aylur/ags/utils.js'; + const { Box, Button, Entry, EventBox, Icon, Label, Revealer, Scrollable, Stack } = Widget; const { execAsync, exec } = Utils; import ChatGPT from '../../../services/chatgpt.js'; @@ -64,14 +67,14 @@ const chatGPTInfo = Box({ export const chatGPTSettings = MarginRevealer({ transition: 'slide_down', revealChild: true, - connections: [ - [ChatGPT, (self) => Utils.timeout(200, () => { - self._hide(); - }), 'newMsg'], - [ChatGPT, (self) => Utils.timeout(200, () => { - self._show(); - }), 'clear'], - ], + extraSetup: (self) => self + .hook(ChatGPT, (self) => Utils.timeout(200, () => { + self.attribute.hide(); + }), 'newMsg') + .hook(ChatGPT, (self) => Utils.timeout(200, () => { + self.attribute.show(); + }), 'clear') + , child: Box({ vertical: true, className: 'sidebar-chat-settings', @@ -126,9 +129,11 @@ export const openaiApiKeyInstructions = Box({ children: [Revealer({ transition: 'slide_down', transitionDuration: 150, - connections: [[ChatGPT, (self, hasKey) => { - self.revealChild = (ChatGPT.key.length == 0); - }, 'hasKey']], + setup: (self) => self + .hook(ChatGPT, (self, hasKey) => { + self.revealChild = (ChatGPT.key.length == 0); + }, 'hasKey') + , child: Button({ child: Label({ useMarkup: true, @@ -163,13 +168,13 @@ export const chatGPTWelcome = Box({ export const chatContent = Box({ className: 'spacing-v-15', vertical: true, - connections: [ - [ChatGPT, (box, id) => { + setup: (self) => self + .hook(ChatGPT, (box, id) => { const message = ChatGPT.messages[id]; if (!message) return; box.add(ChatMessage(message, chatGPTView)) - }, 'newMsg'], - ] + }, 'newMsg') + , }); const clearChat = () => { @@ -197,7 +202,7 @@ export const chatGPTView = Scrollable({ const vScrollbar = scrolledWindow.get_vscrollbar(); vScrollbar.get_style_context().add_class('sidebar-scrollbar'); // Avoid click-to-scroll-widget-to-view behavior - Utils.timeout(1, () => { + Utils.timeout(1, () => { const viewport = scrolledWindow.child; viewport.set_focus_vadjustment(new Gtk.Adjustment(undefined)); }) diff --git a/.config/ags/widgets/sideleft/apis/chatgpt_chatmessage.js b/.config/ags/widgets/sideleft/apis/chatgpt_chatmessage.js index 65c228d67..a8cb84e54 100644 --- a/.config/ags/widgets/sideleft/apis/chatgpt_chatmessage.js +++ b/.config/ags/widgets/sideleft/apis/chatgpt_chatmessage.js @@ -1,6 +1,8 @@ -const { Gdk, Gio, GLib, Gtk, Pango } = imports.gi; -import { App, Utils, Widget } from '../../../imports.js'; -const { Box, Button, Entry, EventBox, Icon, Label, Revealer, Scrollable, Stack } = Widget; +const { Gdk, Gio, GLib, Gtk } = imports.gi; +import App from 'resource:///com/github/Aylur/ags/app.js'; +import Widget from 'resource:///com/github/Aylur/ags/widget.js'; +import * as Utils from 'resource:///com/github/Aylur/ags/utils.js'; +const { Box, Button, Label, Scrollable } = Widget; const { execAsync, exec } = Utils; import { MaterialIcon } from "../../../lib/materialicon.js"; import md2pango from "../../../lib/md2pango.js"; @@ -112,11 +114,11 @@ const CodeBlock = (content = '', lang = 'txt') => { const sourceView = HighlightedCode(content, lang); const codeBlock = Box({ - properties: [ - ['updateText', (text) => { + attribute: { + 'updateText': (text) => { sourceView.get_buffer().set_text(text, -1); - }] - ], + } + }, className: 'sidebar-chat-codeblock', vertical: true, children: [ @@ -149,8 +151,8 @@ const Divider = () => Box({ const MessageContent = (content) => { const contentBox = Box({ vertical: true, - properties: [ - ['fullUpdate', (self, content, useCursor = false) => { + attribute: { + 'fullUpdate': (self, content, useCursor = false) => { // Clear and add first text widget const children = contentBox.get_children(); for (let i = 0; i < children.length; i++) { @@ -175,7 +177,7 @@ const MessageContent = (content) => { contentBox.add(CodeBlock('', codeBlockRegex.exec(line)[1])); } else { - lastLabel._updateText(blockContent); + lastLabel.attribute.updateText(blockContent); contentBox.add(TextBlock()); } @@ -201,7 +203,7 @@ const MessageContent = (content) => { if (!inCode) lastLabel.label = `${md2pango(blockContent)}${useCursor ? CHATGPT_CURSOR : ''}`; else - lastLabel._updateText(blockContent); + lastLabel.attribute.updateText(blockContent); } // Debug: plain text // contentBox.add(Label({ @@ -214,10 +216,10 @@ const MessageContent = (content) => { // label: '------------------------------\n' + md2pango(content), // })) contentBox.show_all(); - }] - ] + } + } }); - contentBox._fullUpdate(contentBox, content, false); + contentBox.attribute.fullUpdate(contentBox, content, false); return contentBox; } @@ -243,17 +245,17 @@ export const ChatMessage = (message, scrolledWindow) => { }), messageContentBox, ], - connections: [ - [message, (self, isThinking) => { + setup: (self) => self + .hook(message, (self, isThinking) => { messageContentBox.toggleClassName('thinking', message.thinking); - }, 'notify::thinking'], - [message, (self) => { // Message update - messageContentBox._fullUpdate(messageContentBox, message.content, message.role != 'user'); - }, 'notify::content'], - [message, (label, isDone) => { // Remove the cursor - messageContentBox._fullUpdate(messageContentBox, message.content, false); - }, 'notify::done'], - ] + }, 'notify::thinking') + .hook(message, (self) => { // Message update + messageContentBox.attribute.fullUpdate(messageContentBox, message.content, message.role != 'user'); + }, 'notify::content') + .hook(message, (label, isDone) => { // Remove the cursor + messageContentBox.attribute.fullUpdate(messageContentBox, message.content, false); + }, 'notify::done') + , }) ] }); diff --git a/.config/ags/widgets/sideleft/apis/waifu.js b/.config/ags/widgets/sideleft/apis/waifu.js index 1ac731ac7..c77054dd6 100644 --- a/.config/ags/widgets/sideleft/apis/waifu.js +++ b/.config/ags/widgets/sideleft/apis/waifu.js @@ -1,17 +1,28 @@ -const { Gdk, GdkPixbuf, Gio, GLib, Gtk, Pango } = imports.gi; -import { App, Utils, Widget } from '../../../imports.js'; -const { Box, Button, Entry, EventBox, Icon, Label, Overlay, Revealer, Scrollable, Stack } = Widget; +const { Gdk, GdkPixbuf, Gio, GLib, Gtk } = imports.gi; +import Widget from 'resource:///com/github/Aylur/ags/widget.js'; +import * as Utils from 'resource:///com/github/Aylur/ags/utils.js'; +const { Box, Button, Label, Overlay, Revealer, Scrollable, Stack } = Widget; const { execAsync, exec } = Utils; import { MaterialIcon } from "../../../lib/materialicon.js"; import { MarginRevealer } from '../../../lib/advancedwidgets.js'; -import { setupCursorHover, setupCursorHoverInfo } from "../../../lib/cursorhover.js"; +import { setupCursorHover } from "../../../lib/cursorhover.js"; import WaifuService from '../../../services/waifus.js'; +async function getImageViewerApp(preferredApp) { + Utils.execAsync(['bash', '-c', `command -v ${preferredApp}`]) + .then((output) => { + if (output != '') return preferredApp; + else return 'xdg-open'; + }); +} + const IMAGE_REVEAL_DELAY = 13; // Some wait for inits n other weird stuff +const IMAGE_VIEWER_APP = getImageViewerApp('loupe'); // Gnome's image viewer cuz very comfortable zooming +const USER_CACHE_DIR = GLib.get_user_cache_dir(); // Create cache folder and clear pics from previous session -Utils.exec(`bash -c 'mkdir -p ${GLib.get_user_cache_dir()}/ags/media/waifus'`); -Utils.exec(`bash -c 'rm ${GLib.get_user_cache_dir()}/ags/media/waifus/*'`); +Utils.exec(`bash -c 'mkdir -p ${USER_CACHE_DIR}/ags/media/waifus'`); +Utils.exec(`bash -c 'rm ${USER_CACHE_DIR}/ags/media/waifus/*'`); export function fileExists(filePath) { let file = Gio.File.new_for_path(filePath); @@ -96,17 +107,17 @@ const WaifuImage = (taglist) => { ImageAction({ name: 'Go to source', icon: 'link', - action: () => execAsync(['xdg-open', `${thisBlock._imageData.source}`]).catch(print), + action: () => execAsync(['xdg-open', `${thisBlock.attribute.imageData.source}`]).catch(print), }), ImageAction({ name: 'Hoard', icon: 'save', - action: () => execAsync(['bash', '-c', `mkdir -p ~/Pictures/waifus && cp ${thisBlock._imagePath} ~/Pictures/waifus`]).catch(print), + action: () => execAsync(['bash', '-c', `mkdir -p ~/Pictures/homework${thisBlock.attribute.isNsfw ? '/🌶️' : ''} && cp ${thisBlock.attribute.imagePath} ~/Pictures/homework${thisBlock.attribute.isNsfw ? '/🌶️/' : ''}`]).catch(print), }), ImageAction({ name: 'Open externally', icon: 'open_in_new', - action: () => execAsync(['xdg-open', `${thisBlock._imagePath}`]).catch(print), + action: () => execAsync([IMAGE_VIEWER_APP, `${thisBlock.attribute.imagePath}`]).catch(print), }), ] }) @@ -116,13 +127,6 @@ const WaifuImage = (taglist) => { const blockImage = Widget.DrawingArea({ className: 'sidebar-waifu-image', }); - // const blockImage = Box({}); - // const blockImage = Image({ - // hpack: 'start', - // vertical: true, - // className: 'sidebar-waifu-image', - // // homogeneous: true, - // }) const blockImageRevealer = Revealer({ transition: 'slide_down', transitionDuration: 150, @@ -138,17 +142,19 @@ const WaifuImage = (taglist) => { }); const thisBlock = Box({ className: 'sidebar-chat-message', - properties: [ - ['imagePath', ''], - ['imageData', ''], - ['update', (imageData, force = false) => { - thisBlock._imageData = imageData; - const { status, signature, url, extension, source, dominant_color, is_nsfw, width, height, tags } = thisBlock._imageData; + attribute: { + 'imagePath': '', + 'isNsfw': false, + 'imageData': '', + 'update': (imageData, force = false) => { + thisBlock.attribute.imageData = imageData; + const { status, signature, url, extension, source, dominant_color, is_nsfw, width, height, tags } = thisBlock.attribute.imageData; + thisBlock.attribute.isNsfw = is_nsfw; if (status != 200) { downloadState.shown = 'error'; return; } - thisBlock._imagePath = `${GLib.get_user_cache_dir()}/ags/media/waifus/${signature}${extension}`; + thisBlock.attribute.imagePath = `${USER_CACHE_DIR}/ags/media/waifus/${signature}${extension}`; downloadState.shown = 'download'; // Width/height const widgetWidth = Math.min(Math.floor(waifuContent.get_allocated_width() * 0.85), width); @@ -156,7 +162,7 @@ const WaifuImage = (taglist) => { blockImage.set_size_request(widgetWidth, widgetHeight); const showImage = () => { downloadState.shown = 'done'; - const pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_scale(thisBlock._imagePath, widgetWidth, widgetHeight, false); + const pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_scale(thisBlock.attribute.imagePath, widgetWidth, widgetHeight, false); blockImage.set_size_request(widgetWidth, widgetHeight); blockImage.connect("draw", (widget, cr) => { @@ -182,19 +188,19 @@ const WaifuImage = (taglist) => { Utils.timeout(IMAGE_REVEAL_DELAY + blockImageRevealer.transitionDuration, () => blockImageActions.revealChild = true ); - downloadIndicator._hide(); + downloadIndicator.attribute.hide(); } // Show - if (!force && fileExists(thisBlock._imagePath)) showImage(); - else Utils.execAsync(['bash', '-c', `wget -O '${thisBlock._imagePath}' '${url}'`]) + if (!force && fileExists(thisBlock.attribute.imagePath)) showImage(); + else Utils.execAsync(['bash', '-c', `wget -O '${thisBlock.attribute.imagePath}' '${url}'`]) .then(showImage) .catch(print); blockHeading.get_children().forEach((child) => { child.setCss(`border-color: ${dominant_color};`); }) colorIndicator.css = `background-color: ${dominant_color};`; - }], - ], + }, + }, children: [ colorIndicator, Box({ @@ -218,25 +224,25 @@ const waifuContent = Box({ className: 'spacing-v-15', vertical: true, vexpand: true, - properties: [ - ['map', new Map()], - ], - connections: [ - [WaifuService, (box, id) => { + attribute: { + 'map': new Map(), + }, + setup: (self) => self + .hook(WaifuService, (box, id) => { if (id === undefined) return; const newImageBlock = WaifuImage(WaifuService.queries[id]); box.add(newImageBlock); box.show_all(); - box._map.set(id, newImageBlock); - }, 'newResponse'], - [WaifuService, (box, id) => { + box.attribute.map.set(id, newImageBlock); + }, 'newResponse') + .hook(WaifuService, (box, id) => { if (id === undefined) return; const data = WaifuService.responses[id]; if (!data) return; - const imageBlock = box._map.get(id); - imageBlock._update(data); - }, 'updateResponse'], - ] + const imageBlock = box.attribute.map.get(id); + imageBlock.attribute.update(data); + }, 'updateResponse') + , }); export const waifuView = Scrollable({ @@ -313,6 +319,7 @@ export const waifuCommands = Box({ }); const clearChat = () => { + waifuContent.attribute.map.clear(); const kids = waifuContent.get_children(); for (let i = 0; i < kids.length; i++) { const child = kids[i]; @@ -328,7 +335,7 @@ export const sendMessage = (text) => { else if (text.startsWith('/test')) { const newImage = WaifuImage(['/test']); waifuContent.add(newImage); - Utils.timeout(IMAGE_REVEAL_DELAY, () => newImage._update({ // Needs timeout or inits won't make it + Utils.timeout(IMAGE_REVEAL_DELAY, () => newImage.attribute.update({ // Needs timeout or inits won't make it // This is an image uploaded to my github repo status: 200, url: 'https://picsum.photos/400/600', diff --git a/.config/ags/widgets/sideleft/apiwidgets.js b/.config/ags/widgets/sideleft/apiwidgets.js index 3c9b565d6..475bd496f 100644 --- a/.config/ags/widgets/sideleft/apiwidgets.js +++ b/.config/ags/widgets/sideleft/apiwidgets.js @@ -1,5 +1,6 @@ -const { Gtk, Gdk } = imports.gi; -import { App, Utils, Widget } from '../../imports.js'; +import App from 'resource:///com/github/Aylur/ags/app.js'; +import Widget from 'resource:///com/github/Aylur/ags/widget.js'; +import * as Utils from 'resource:///com/github/Aylur/ags/utils.js'; const { Box, Button, Entry, EventBox, Icon, Label, Revealer, Scrollable, Stack } = Widget; const { execAsync, exec } = Utils; import { setupCursorHover, setupCursorHoverInfo } from "../../lib/cursorhover.js"; @@ -32,12 +33,12 @@ APIS[currentApiId].tabIcon.toggleClassName('sidebar-chat-apiswitcher-icon-enable export const chatEntry = Entry({ className: 'sidebar-chat-entry', hexpand: true, - connections: [ - [ChatGPT, (self) => { + setup: (self) => self + .hook(ChatGPT, (self) => { if (APIS[currentApiId].name != 'ChatGPT') return; self.placeholderText = (ChatGPT.key.length > 0 ? 'Ask a question...' : 'Enter OpenAI API Key...'); - }, 'hasKey'] - ], + }, 'hasKey') + , onChange: (entry) => { chatSendButton.toggleClassName('sidebar-chat-send-available', entry.text.length > 0); }, @@ -83,7 +84,7 @@ function switchToTab(id) { apiContentStack.shown = APIS[id].name; apiCommandStack.shown = APIS[id].name; chatEntry.placeholderText = APIS[id].placeholderText, - currentApiId = id; + currentApiId = id; } const apiSwitcher = Box({ homogeneous: true, @@ -104,10 +105,10 @@ const apiSwitcher = Box({ }) export default Widget.Box({ - properties: [ - ['nextTab', () => switchToTab(Math.min(currentApiId + 1, APIS.length - 1))], - ['prevTab', () => switchToTab(Math.max(0, currentApiId-1))], - ], + attribute: { + 'nextTab': () => switchToTab(Math.min(currentApiId + 1, APIS.length - 1)), + 'prevTab': () => switchToTab(Math.max(0, currentApiId - 1)), + }, vertical: true, className: 'spacing-v-10', homogeneous: false, diff --git a/.config/ags/widgets/sideleft/module.js b/.config/ags/widgets/sideleft/module.js index b4acaa8e2..319b5a35c 100644 --- a/.config/ags/widgets/sideleft/module.js +++ b/.config/ags/widgets/sideleft/module.js @@ -1,7 +1,5 @@ -const { Gdk, Gtk } = imports.gi; -import { Utils, Widget } from '../../imports.js'; -const { execAsync, exec } = Utils; -const { Box, Button, EventBox, Label, Scrollable } = Widget; +import Widget from 'resource:///com/github/Aylur/ags/widget.js'; +const { Box, Button, Label } = Widget; export const SidebarModule = ({ name, diff --git a/.config/ags/widgets/sideleft/quickscripts.js b/.config/ags/widgets/sideleft/quickscripts.js index c2df1a708..13bf9c1a1 100644 --- a/.config/ags/widgets/sideleft/quickscripts.js +++ b/.config/ags/widgets/sideleft/quickscripts.js @@ -1,5 +1,5 @@ -const { Gdk, Gtk } = imports.gi; -import { Utils, Widget } from '../../imports.js'; +import Widget from 'resource:///com/github/Aylur/ags/widget.js'; +import * as Utils from 'resource:///com/github/Aylur/ags/utils.js'; const { execAsync, exec } = Utils; const { Box, Button, EventBox, Label, Scrollable } = Widget; import { SidebarModule } from './module.js'; diff --git a/.config/ags/widgets/sideleft/sideleft.js b/.config/ags/widgets/sideleft/sideleft.js index fc8ceccf4..278ba5838 100644 --- a/.config/ags/widgets/sideleft/sideleft.js +++ b/.config/ags/widgets/sideleft/sideleft.js @@ -1,5 +1,7 @@ -const { Gdk, Gtk } = imports.gi; -import { Utils, Widget } from '../../imports.js'; +const { Gdk } = imports.gi; +import App from 'resource:///com/github/Aylur/ags/app.js'; +import Widget from 'resource:///com/github/Aylur/ags/widget.js'; +import * as Utils from 'resource:///com/github/Aylur/ags/utils.js'; const { Box, Button, EventBox, Label, Revealer, Scrollable, Stack } = Widget; const { execAsync, exec } = Utils; import { MaterialIcon } from "../../lib/materialicon.js"; @@ -93,20 +95,20 @@ const navBar = Box({ }); const pinButton = Button({ - properties: [ - ['enabled', false], - ['toggle', (self) => { - self._enabled = !self._enabled; - self.toggleClassName('sidebar-pin-enabled', self._enabled); + attribute: { + 'enabled': false, + 'toggle': (self) => { + self.attribute.enabled = !self.attribute.enabled; + self.toggleClassName('sidebar-pin-enabled', self.attribute.enabled); const sideleftWindow = App.getWindow('sideleft'); const barWindow = App.getWindow('bar'); const cornerTopLeftWindow = App.getWindow('cornertl'); const sideleftContent = sideleftWindow.get_children()[0].get_children()[0].get_children()[1]; - sideleftContent.toggleClassName('sidebar-pinned', self._enabled); + sideleftContent.toggleClassName('sidebar-pinned', self.attribute.enabled); - if (self._enabled) { + if (self.attribute.enabled) { sideleftWindow.layer = 'bottom'; barWindow.layer = 'bottom'; cornerTopLeftWindow.layer = 'bottom'; @@ -118,19 +120,20 @@ const pinButton = Button({ cornerTopLeftWindow.layer = 'top'; sideleftWindow.exclusivity = 'normal'; } - }], - ], + }, + }, vpack: 'start', className: 'sidebar-pin', child: MaterialIcon('push_pin', 'larger'), tooltipText: 'Pin sidebar', - onClicked: (self) => self._toggle(self), + onClicked: (self) => self.attribute.toggle(self), // QoL: Focus Pin button on open. Hit keybind -> space/enter = toggle pin state - connections: [[App, (self, currentName, visible) => { - if (currentName === 'sideleft' && visible) { - self.grab_focus(); - } - }]] + setup: (self) => self + .hook(App, (self, currentName, visible) => { + if (currentName === 'sideleft' && visible) + self.grab_focus(); + }) + , }) export default () => Box({ @@ -158,19 +161,20 @@ export default () => Box({ }), contentStack, ], - connections: [[App, (self, currentName, visible) => { - if (currentName === 'sideleft') { - self.toggleClassName('sidebar-pinned', pinButton._enabled && visible); - } - }]] + setup: (self) => self + .hook(App, (self, currentName, visible) => { + if (currentName === 'sideleft') + self.toggleClassName('sidebar-pinned', pinButton.attribute.enabled && visible); + }) + , }), ], - connections: [ - ['key-press-event', (widget, event) => { // Handle keybinds + setup: (self) => self + .on('key-press-event', (widget, event) => { // Handle keybinds if (event.get_state()[1] & Gdk.ModifierType.CONTROL_MASK) { // Pin sidebar if (event.get_keyval()[1] == Gdk.KEY_p) - pinButton._toggle(pinButton); + pinButton.attribute.toggle(pinButton); // Switch sidebar tab else if (event.get_keyval()[1] === Gdk.KEY_Tab) switchToTab((currentTabId + 1) % contents.length); @@ -186,8 +190,8 @@ export default () => Box({ event.get_keyval()[1] >= 32 && event.get_keyval()[1] <= 126 && widget != chatEntry && event.get_keyval()[1] != Gdk.KEY_space) || - ((event.get_state()[1] & Gdk.ModifierType.CONTROL_MASK) && - event.get_keyval()[1] === Gdk.KEY_v) + ((event.get_state()[1] & Gdk.ModifierType.CONTROL_MASK) && + event.get_keyval()[1] === Gdk.KEY_v) ) { chatEntry.grab_focus(); chatEntry.set_text(chatEntry.text + String.fromCharCode(event.get_keyval()[1])); @@ -197,15 +201,15 @@ export default () => Box({ else if (!(event.get_state()[1] & Gdk.ModifierType.CONTROL_MASK) && event.get_keyval()[1] === Gdk.KEY_Page_Down) { const toSwitchTab = contentStack.get_visible_child(); - toSwitchTab._nextTab(); + toSwitchTab.attribute.nextTab(); } else if (!(event.get_state()[1] & Gdk.ModifierType.CONTROL_MASK) && event.get_keyval()[1] === Gdk.KEY_Page_Up) { const toSwitchTab = contentStack.get_visible_child(); - toSwitchTab._prevTab(); + toSwitchTab.attribute.prevTab(); } } - }], - ], + }) + , }); diff --git a/.config/ags/widgets/sideleft/toolbox.js b/.config/ags/widgets/sideleft/toolbox.js index bdbbdb52b..1fbf71792 100644 --- a/.config/ags/widgets/sideleft/toolbox.js +++ b/.config/ags/widgets/sideleft/toolbox.js @@ -1,5 +1,5 @@ -const { Gdk, Gtk } = imports.gi; -import { Utils, Widget } from '../../imports.js'; +import Widget from 'resource:///com/github/Aylur/ags/widget.js'; +import * as Utils from 'resource:///com/github/Aylur/ags/utils.js'; const { Box, Button, EventBox, Label, Revealer, Scrollable, Stack } = Widget; const { execAsync, exec } = Utils; import { QuickScripts } from './quickscripts.js'; diff --git a/.config/ags/widgets/sideright/calendar.js b/.config/ags/widgets/sideright/calendar.js index 391d0599f..d952505d0 100644 --- a/.config/ags/widgets/sideright/calendar.js +++ b/.config/ags/widgets/sideright/calendar.js @@ -1,6 +1,7 @@ -const { Gio, Gdk, GLib, Gtk } = imports.gi; -import { App, Widget, Utils } from '../../imports.js'; -const { Box, Button, CenterBox, Label, Revealer } = Widget; +const { Gio } = imports.gi; +import Widget from 'resource:///com/github/Aylur/ags/widget.js'; +import * as Utils from 'resource:///com/github/Aylur/ags/utils.js'; +const { Box, Button, Label } = Widget; import { MaterialIcon } from "../../lib/materialicon.js"; import { getCalendarLayout } from "../../lib/calendarlayout.js"; import { setupCursorHover } from "../../lib/cursorhover.js"; diff --git a/.config/ags/widgets/sideright/notificationlist.js b/.config/ags/widgets/sideright/notificationlist.js index 8e7d7801f..a4c4b7ca0 100644 --- a/.config/ags/widgets/sideright/notificationlist.js +++ b/.config/ags/widgets/sideright/notificationlist.js @@ -1,15 +1,11 @@ -// This file is for the notification widget on the sidebar +// This file is for the notification list on the sidebar // For the popup notifications, see onscreendisplay.js // The actual widget for each single notification is in lib/notification.js - -const { GLib, Gtk } = imports.gi; -import { Service, Utils, Widget } from '../../imports.js'; +import Widget from 'resource:///com/github/Aylur/ags/widget.js'; import Notifications from 'resource:///com/github/Aylur/ags/service/notifications.js'; -const { lookUpIcon, timeout } = Utils; -const { Box, Button, Icon, Label, Revealer, Scrollable, Stack } = Widget; +const { Box, Button, Label, Scrollable, Stack } = Widget; import { MaterialIcon } from "../../lib/materialicon.js"; import { setupCursorHover } from "../../lib/cursorhover.js"; -import { ConfigToggle, ConfigSegmentedSelection, ConfigGap } from '../../lib/configwidgets.js'; import Notification from "../../lib/notification.js"; export default (props) => { @@ -35,8 +31,8 @@ export default (props) => { vertical: true, vpack: 'start', className: 'spacing-v-5-revealer', - connections: [ - [Notifications, (box, id) => { + setup: (self) => self + .hook(Notifications, (box, id) => { if (box.get_children().length == 0) { // On init there's no notif, or 1st notif Notifications.notifications .forEach(n => { @@ -58,17 +54,16 @@ export default (props) => { box.pack_end(NewNotif, false, false, 0); box.show_all(); } - }, 'notified'], - - [Notifications, (box, id) => { + }, 'notified') + .hook(Notifications, (box, id) => { if (!id) return; for (const ch of box.children) { if (ch._id === id) { - ch._destroyWithAnims(); + ch.attribute.destroyWithAnims(); } } - }, 'closed'], - ], + }, 'closed') + , }); const ListActionButton = (icon, name, action) => Button({ className: 'notif-listaction-btn', @@ -100,7 +95,7 @@ export default (props) => { Label({ hexpand: true, xalign: 0, - className: 'txt-title-small margin-left-10', + className: 'txt-title-small margin-left-10', // ^ (extra margin on the left so that it looks similarly spaced // when compared to borderless "Clear" button on the right) label: 'Notifications', diff --git a/.config/ags/widgets/sideright/quicktoggles.js b/.config/ags/widgets/sideright/quicktoggles.js index f7e7e1a0f..6deae3fb0 100644 --- a/.config/ags/widgets/sideright/quicktoggles.js +++ b/.config/ags/widgets/sideright/quicktoggles.js @@ -1,5 +1,7 @@ const { GLib } = imports.gi; -import { Widget, Utils, Service } from '../../imports.js'; +import Widget from 'resource:///com/github/Aylur/ags/widget.js'; +import * as Utils from 'resource:///com/github/Aylur/ags/utils.js'; + import Bluetooth from 'resource:///com/github/Aylur/ags/service/bluetooth.js'; import Network from 'resource:///com/github/Aylur/ags/service/network.js'; import Hyprland from 'resource:///com/github/Aylur/ags/service/hyprland.js'; @@ -20,21 +22,19 @@ function expandTilde(path) { export const ToggleIconWifi = (props = {}) => Widget.Button({ className: 'txt-small sidebar-iconbutton', tooltipText: 'Wifi | Right-click to configure', - onClicked: Network.toggleWifi, + onClicked: () => Network.toggleWifi(), onSecondaryClickRelease: () => { execAsync(['bash', '-c', 'XDG_CURRENT_DESKTOP="gnome" gnome-control-center wifi', '&']); App.closeWindow('sideright'); }, child: NetworkIndicator(), - connections: [ - [Network, button => { + setup: (self) => { + setupCursorHover(self); + self.hook(Network, button => { button.toggleClassName('sidebar-button-active', [Network.wifi?.internet, Network.wired?.internet].includes('connected')) - }], - [Network, button => { button.tooltipText = (`${Network.wifi?.ssid} | Right-click to configure` || 'Unknown'); - }], - ], - setup: setupCursorHover, + }); + }, ...props, }); @@ -53,12 +53,12 @@ export const ToggleIconBluetooth = (props = {}) => Widget.Button({ App.closeWindow('sideright'); }, child: BluetoothIndicator(), - connections: [ - [Bluetooth, button => { + setup: (self) => { + setupCursorHover(self); + self.hook(Bluetooth, button => { button.toggleClassName('sidebar-button-active', Bluetooth?.enabled) - }], - ], - setup: setupCursorHover, + }); + }, ...props, }); @@ -82,24 +82,24 @@ export const HyprToggleIcon = (icon, name, hyprlandConfigValue, props = {}) => W }) export const ModuleNightLight = (props = {}) => Widget.Button({ // TODO: Make this work - properties: [ - ['enabled', false], - ['yellowlight', undefined], - ], + attribute: { + enabled: false, + yellowlight: undefined, + }, className: 'txt-small sidebar-iconbutton', tooltipText: 'Night Light', onClicked: (self) => { - self._enabled = !self._enabled; - self.toggleClassName('sidebar-button-active', self._enabled); - // if (self._enabled) Utils.execAsync(['bash', '-c', 'wlsunset & disown']) - if (self._enabled) Utils.execAsync('wlsunset') + self.attribute.enabled = !self.attribute.enabled; + self.toggleClassName('sidebar-button-active', self.attribute.enabled); + // if (self.attribute.enabled) Utils.execAsync(['bash', '-c', 'wlsunset & disown']) + if (self.attribute.enabled) Utils.execAsync('wlsunset') else Utils.execAsync('pkill wlsunset'); }, child: MaterialIcon('nightlight', 'norm'), setup: (self) => { setupCursorHover(self); - self._enabled = !!exec('pidof wlsunset'); - self.toggleClassName('sidebar-button-active', self._enabled); + self.attribute.enabled = !!exec('pidof wlsunset'); + self.toggleClassName('sidebar-button-active', self.attribute.enabled); }, ...props, }); @@ -131,17 +131,17 @@ export const ModuleInvertColors = (props = {}) => Widget.Button({ }) export const ModuleIdleInhibitor = (props = {}) => Widget.Button({ // TODO: Make this work - properties: [ - ['enabled', false], - ['inhibitor', undefined], - ], + attribute: { + enabled: false, + inhibitor: undefined, + }, className: 'txt-small sidebar-iconbutton', tooltipText: 'Keep system awake', onClicked: (self) => { - self._enabled = !self._enabled; - self.toggleClassName('sidebar-button-active', self._enabled); - if (self._enabled) { - self._inhibitor = Utils.subprocess( + self.attribute.enabled = !self.attribute.enabled; + self.toggleClassName('sidebar-button-active', self.attribute.enabled); + if (self.attribute.enabled) { + self.attribute.inhibitor = Utils.subprocess( ['wayland-idle-inhibitor.py'], (output) => print(output), (err) => logError(err), @@ -149,7 +149,7 @@ export const ModuleIdleInhibitor = (props = {}) => Widget.Button({ // TODO: Make ); } else { - self._inhibitor.force_exit(); + self.attribute.inhibitor.force_exit(); } }, child: MaterialIcon('coffee', 'norm'), diff --git a/.config/ags/widgets/sideright/sideright.js b/.config/ags/widgets/sideright/sideright.js index 3c14cd51b..ff5751744 100644 --- a/.config/ags/widgets/sideright/sideright.js +++ b/.config/ags/widgets/sideright/sideright.js @@ -1,5 +1,5 @@ -const { GLib, Gdk, Gtk } = imports.gi; -import { Utils, Widget } from '../../imports.js'; +import Widget from 'resource:///com/github/Aylur/ags/widget.js'; +import * as Utils from 'resource:///com/github/Aylur/ags/utils.js'; const { execAsync, exec } = Utils; const { Box, EventBox } = Widget; import { @@ -17,44 +17,19 @@ import { import ModuleNotificationList from "./notificationlist.js"; import { ModuleCalendar } from "./calendar.js"; -// const NUM_OF_TOGGLES_PER_LINE = 5; -// const togglesFlowBox = Widget.FlowBox({ -// className: 'sidebar-group spacing-h-10', -// setup: (self) => { -// self.set_max_children_per_line(NUM_OF_TOGGLES_PER_LINE); -// self.add(ToggleIconWifi({ hexpand: true })); -// self.add(ToggleIconBluetooth({ hexpand: true })); -// self.add(HyprToggleIcon('mouse', 'Raw input', 'input:force_no_accel', { hexpand: true })); -// self.add(HyprToggleIcon('front_hand', 'No touchpad while typing', 'input:touchpad:disable_while_typing', { hexpand: true })); -// self.add(ModuleNightLight({ hexpand: true })); -// // Setup flowbox rearrange -// self.connect('child-activated', (self, child) => { -// if (child.get_index() === 0) { -// self.reorder_child(child, self.get_children().length - 1); -// } else { -// self.reorder_child(child, 0); -// } -// }); -// } -// }) - const timeRow = Box({ className: 'spacing-h-5 sidebar-group-invisible-morehorizpad', children: [ - // Widget.Label({ - // className: 'txt-title txt', - // connections: [[5000, label => { - // label.label = GLib.DateTime.new_now_local().format("%H:%M"); - // }]], - // }), Widget.Label({ hpack: 'center', className: 'txt-small txt', - connections: [[5000, label => { - execAsync(['bash', '-c', `uptime -p | sed -e 's/up //;s/ hours,/h/;s/ minutes/m/'`]).then(upTimeString => { - label.label = `System uptime: ${upTimeString}`; - }).catch(print); - }]], + setup: (self) => self + .poll(5000, label => { + execAsync(['bash', '-c', `uptime -p | sed -e 's/up //;s/ hours,/h/;s/ minutes/m/'`]).then(upTimeString => { + label.label = `Uptime: ${upTimeString}`; + }).catch(print); + }) + , }), Widget.Box({ hexpand: true }), // ModuleEditIcon({ hpack: 'end' }), // TODO: Make this work diff --git a/.config/ags/widgets/sideright/todolist.js b/.config/ags/widgets/sideright/todolist.js index 6360cc962..7ef455320 100644 --- a/.config/ags/widgets/sideright/todolist.js +++ b/.config/ags/widgets/sideright/todolist.js @@ -1,6 +1,6 @@ -const { Gio, Gdk, GLib, Gtk } = imports.gi; -import { App, Widget, Utils } from '../../imports.js'; -const { Box, Button, CenterBox, Label, Revealer } = Widget; +import Widget from 'resource:///com/github/Aylur/ags/widget.js'; +import * as Utils from 'resource:///com/github/Aylur/ags/utils.js'; +const { Box, Button, Label, Revealer } = Widget; import { MaterialIcon } from "../../lib/materialicon.js"; import Todo from "../../services/todo.js"; import { setupCursorHover } from "../../lib/cursorhover.js"; @@ -73,33 +73,36 @@ const todoListItem = (task, id, isDone, isEven = false) => { } const todoItems = (isDone) => Widget.Scrollable({ + hscroll: 'never', + vscroll: 'automatic', child: Widget.Box({ vertical: true, - connections: [[Todo, (self) => { - self.children = Todo.todo_json.map((task, i) => { - if (task.done != isDone) return null; - return todoListItem(task, i, isDone); - }) - if (self.children.length == 0) { - self.homogeneous = true; - self.children = [ - Widget.Box({ - hexpand: true, - vertical: true, - vpack: 'center', - className: 'txt', - children: [ - MaterialIcon(`${isDone ? 'checklist' : 'check_circle'}`, 'badonkers'), - Label({ label: `${isDone ? 'Finished tasks will go here' : 'Nothing here!'}` }) - ] - }) - ] - } - else self.homogeneous = false; - }, 'updated']] + setup: (self) => self + .hook(Todo, (self) => { + self.children = Todo.todo_json.map((task, i) => { + if (task.done != isDone) return null; + return todoListItem(task, i, isDone); + }) + if (self.children.length == 0) { + self.homogeneous = true; + self.children = [ + Widget.Box({ + hexpand: true, + vertical: true, + vpack: 'center', + className: 'txt', + children: [ + MaterialIcon(`${isDone ? 'checklist' : 'check_circle'}`, 'badonkers'), + Label({ label: `${isDone ? 'Finished tasks will go here' : 'Nothing here!'}` }) + ] + }) + ] + } + else self.homogeneous = false; + }, 'updated') + , }), setup: (listContents) => { - listContents.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC); const vScrollbar = listContents.get_vscrollbar(); vScrollbar.get_style_context().add_class('sidebar-scrollbar'); }