From 22b5993f7942a607ab1a9d37bf9838d905cc0993 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Thu, 11 Jan 2024 16:49:37 +0700 Subject: [PATCH] ags: sync --- .config/ags/config.js | 14 +- .config/ags/imports.js | 2 +- .config/ags/lib/actioncenter.js | 245 ----- ...dvancedrevealers.js => advancedwidgets.js} | 64 +- .config/ags/lib/animatedcircularprogress.js | 8 +- .config/ags/lib/calendarlayout.js | 2 - .config/ags/lib/configwidgets.js | 37 +- .config/ags/lib/cursorhover.js | 4 +- .config/ags/lib/materialicon.js | 4 +- .config/ags/lib/md2pango.js | 29 +- .config/ags/lib/navigationindicator.js | 5 +- .config/ags/lib/notification.js | 56 +- .config/ags/lib/popupwindow.js | 3 +- .config/ags/lib/roundedcorner.js | 2 +- .config/ags/lib/separator.js | 2 +- .config/ags/lib/statusicons.js | 46 +- .config/ags/scripts/README.md | 0 .../scripts/color_generation/applycolor.sh | 1 - .../color_generation/pywal_to_material.scss | 0 .../specials/_material_badapple.scss | 0 .../scripts/color_generation/switchcolor.sh | 5 - .../scripts/color_generation/switchwall.sh | 2 +- .config/ags/scripts/record-script.sh | 2 +- .config/ags/scripts/templates/foot/foot.ini | 0 .../ags/scripts/templates/fuzzel/fuzzel.ini | 0 .../scripts/templates/gradience/preset.json | 41 +- .../templates/gradience/preset_template.json | 11 +- .../ags/scripts/templates/gtklock/main.scss | 0 .../ags/scripts/templates/gtklock/style.css | 0 .../ags/scripts/templates/hypr/colors.conf | 8 +- .config/ags/scss/_bar.scss | 12 +- .config/ags/scss/_cheatsheet.scss | 4 +- .config/ags/scss/_colors.scss | 0 .config/ags/scss/_common.scss | 47 +- .config/ags/scss/_dock.scss | 0 .config/ags/scss/_lib_classes.scss | 169 +-- .config/ags/scss/_lib_mixins.scss | 49 +- .config/ags/scss/_material.scss | 46 +- .config/ags/scss/_musicmaterial.scss | 30 +- .config/ags/scss/_musicwal.scss | 25 - .config/ags/scss/_notifications.scss | 32 +- .config/ags/scss/_osk.scss | 8 +- .config/ags/scss/_sidebars.scss | 163 +-- .config/ags/services/brightness.js | 5 +- .config/ags/services/chatgpt.js | 18 +- .config/ags/services/indicator.js | 3 +- .config/ags/services/messages.js | 3 +- .config/ags/services/sway.js | 417 ++++++++ .config/ags/services/todo.js | 7 +- .config/ags/services/waifus.js | 211 ++-- .config/ags/style.css | 962 ++++++++++-------- .config/ags/widgets/bar/leftspace.js | 92 +- .config/ags/widgets/bar/main.js | 17 +- .config/ags/widgets/bar/music.js | 42 +- .config/ags/widgets/bar/rightspace.js | 32 +- .config/ags/widgets/bar/system.js | 202 ++-- .config/ags/widgets/bar/tray.js | 60 +- .../{workspaces.js => workspaces_hyprland.js} | 53 +- .config/ags/widgets/bar/workspaces_sway.js | 58 ++ .config/ags/widgets/cheatsheet/keybinds.js | 4 +- .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 | 91 +- .config/ags/widgets/dock/main.js | 2 +- .config/ags/widgets/indicators/colorscheme.js | 7 +- .../ags/widgets/indicators/indicatorvalues.js | 60 +- .config/ags/widgets/indicators/main.js | 2 +- .../ags/widgets/indicators/musiccontrols.js | 109 +- .../widgets/indicators/notificationpopups.js | 44 +- .../onscreenkeyboard/onscreenkeyboard.js | 10 +- .config/ags/widgets/overview/actions.js | 4 +- .config/ags/widgets/overview/main.js | 4 +- .config/ags/widgets/overview/miscfunctions.js | 11 +- .config/ags/widgets/overview/overview.js | 547 ---------- .../ags/widgets/overview/overview_hyprland.js | 308 ++++++ .config/ags/widgets/overview/searchbuttons.js | 32 +- .config/ags/widgets/overview/searchitem.js | 18 +- .config/ags/widgets/overview/windowcontent.js | 244 +++++ .config/ags/widgets/screencorners/main.js | 11 +- .config/ags/widgets/session/main.js | 3 +- .config/ags/widgets/session/sessionscreen.js | 29 +- .config/ags/widgets/sideleft/apis/chatgpt.js | 85 +- .../sideleft/apis/chatgpt_chatmessage.js | 82 +- .config/ags/widgets/sideleft/apis/waifu.js | 332 +++++- .config/ags/widgets/sideleft/apiwidgets.js | 29 +- .config/ags/widgets/sideleft/module.js | 6 +- .config/ags/widgets/sideleft/quickscripts.js | 4 +- .config/ags/widgets/sideleft/sideleft.js | 70 +- .config/ags/widgets/sideleft/toolbox.js | 4 +- .config/ags/widgets/sideright/calendar.js | 7 +- .../ags/widgets/sideright/notificationlist.js | 182 ++-- .config/ags/widgets/sideright/quicktoggles.js | 110 +- .config/ags/widgets/sideright/sideright.js | 43 +- .config/ags/widgets/sideright/todolist.js | 55 +- 96 files changed, 3346 insertions(+), 2598 deletions(-) delete mode 100644 .config/ags/lib/actioncenter.js rename .config/ags/lib/{advancedrevealers.js => advancedwidgets.js} (53%) mode change 100755 => 100644 .config/ags/scripts/README.md mode change 100755 => 100644 .config/ags/scripts/color_generation/pywal_to_material.scss mode change 100755 => 100644 .config/ags/scripts/color_generation/specials/_material_badapple.scss mode change 100755 => 100644 .config/ags/scripts/templates/foot/foot.ini mode change 100755 => 100644 .config/ags/scripts/templates/fuzzel/fuzzel.ini mode change 100755 => 100644 .config/ags/scripts/templates/gtklock/main.scss mode change 100755 => 100644 .config/ags/scripts/templates/gtklock/style.css mode change 100755 => 100644 .config/ags/scripts/templates/hypr/colors.conf mode change 100755 => 100644 .config/ags/scss/_colors.scss mode change 100755 => 100644 .config/ags/scss/_dock.scss mode change 100755 => 100644 .config/ags/scss/_material.scss mode change 100755 => 100644 .config/ags/scss/_musicmaterial.scss create mode 100644 .config/ags/services/sway.js rename .config/ags/widgets/bar/{workspaces.js => workspaces_hyprland.js} (83%) 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 25df63fbc..6a008a9f9 100644 --- a/.config/ags/config.js +++ b/.config/ags/config.js @@ -1,10 +1,12 @@ -"strict mode"; +"use strict"; // Import -import { App, Utils } from './imports.js'; +const { GLib } = imports.gi; +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'; @@ -16,8 +18,6 @@ import SideRight from './widgets/sideright/main.js'; const CLOSE_ANIM_TIME = 210; // Longer than actual anim time (see styles) to make sure widgets animate fully -// Init cache -Utils.exec(`bash -c 'mkdir -p ~/.cache/ags/user/colorschemes'`); // SCSS compilation Utils.exec(`bash -c 'echo "" > ${App.configDir}/scss/_musicwal.scss'`); // reset music styles Utils.exec(`bash -c 'echo "" > ${App.configDir}/scss/_musicmaterial.scss'`); // reset music styles @@ -43,8 +43,8 @@ export default { CornerTopright(), CornerBottomleft(), CornerBottomright(), - // DesktopBackground(), - // Dock(), // Buggy + DesktopBackground(), // If you're going to uncomment these, + // Dock(), // Buggy // uncomment the import statement too. Overview(), Indicator(), Cheatsheet(), 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/advancedrevealers.js b/.config/ags/lib/advancedwidgets.js similarity index 53% rename from .config/ags/lib/advancedrevealers.js rename to .config/ags/lib/advancedwidgets.js index cab2d4ca6..096c55fde 100644 --- a/.config/ags/lib/advancedrevealers.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, Entry, EventBox, Icon, Label, 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,51 +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, - css: `min-height: 0px;`, - properties: [ - ['revealChild', true], // It'll be set to false after init if it's supposed to hide - ['transition', transition], - ['show', (self) => { - if (self._revealChild) return; - self.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.NEVER); + 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); - self._revealChild = true; + widget.attribute.revealChild = true; child.css = 'margin: 0px;'; - }], - ['hide', (self) => { - if (!self._revealChild) return; + }, + 'hide': () => { + if (!widget.attribute.revealChild) return; child.toggleClassName(hideClass, true); child.toggleClassName(showClass, false); - self._revealChild = false; - if (self._transition == 'slide_left') + widget.attribute.revealChild = false; + if (widget.attribute.transition == 'slide_left') child.css = `margin-right: -${child.get_allocated_width()}px;`; - else if (self._transition == 'slide_right') + else if (widget.attribute.transition == 'slide_right') child.css = `margin-left: -${child.get_allocated_width()}px;`; - else if (self._transition == 'slide_up') + else if (widget.attribute.transition == 'slide_up') child.css = `margin-bottom: -${child.get_allocated_height()}px;`; - else if (self._transition == 'slide_down') + else if (widget.attribute.transition == 'slide_down') child.css = `margin-top: -${child.get_allocated_height()}px;`; - }], - ['toggle', (self) => { + }, + 'toggle': () => { console.log('toggle'); - if (self._revealChild) self._hide(self); - else self._show(self); - }], - ...extraProperties, - ], - setup: (self) => { - if (!revealChild) - self.set_policy(Gtk.PolicyType.ALWAYS, Gtk.PolicyType.ALWAYS); - else - self.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.NEVER); - self.child = child; + 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 c9cde2982..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,22 +37,25 @@ export const ConfigToggle = ({ icon, name, desc = '', initValue, onChange, ...re ] }); const interactionWrapper = Button({ - child: widgetContent, - onClicked: () => { // mouse up/kb press - value = !value; - toggleIcon.toggleClassName('switch-fg-toggling-false', false); - if (!value) { - toggleIcon.label = ''; - toggleIcon.toggleClassName('txt-poof', true); + attribute: { + toggle: (newValue) => { + value = !value; + toggleIcon.toggleClassName('switch-fg-toggling-false', false); + if (!value) { + toggleIcon.label = ''; + toggleIcon.toggleClassName('txt-poof', true); + } + toggleButtonIndicator.toggleClassName('switch-fg-true', value); + toggleButton.toggleClassName('switch-bg-true', value); + if (value) Utils.timeout(1, () => { + toggleIcon.label = 'check'; + toggleIcon.toggleClassName('txt-poof', false); + }) + onChange(interactionWrapper, value); } - toggleButtonIndicator.toggleClassName('switch-fg-true', value); - toggleButton.toggleClassName('switch-bg-true', value); - if(value) Utils.timeout(1, () => { - toggleIcon.label = 'check'; - toggleIcon.toggleClassName('txt-poof', false); - }) - onChange(interactionWrapper, value); }, + child: widgetContent, + 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/md2pango.js b/.config/ags/lib/md2pango.js index e14a5cb60..ec94dd1f0 100644 --- a/.config/ags/lib/md2pango.js +++ b/.config/ags/lib/md2pango.js @@ -57,7 +57,7 @@ const pad = (lines, start = 1, end = 1) => { return lines.map((l) => l.padEnd(len + end, ' ').padStart(len + end + start, ' ')) } -export function convert(text) { +export default (text) => { let lines = text.split('\n') // Indicates if the current line is within a code block @@ -205,33 +205,6 @@ export function convert(text) { return output.join('\n') } -const readFile = (f) => { - // node.js only and when running from the command line - const fs = require('fs') - return fs.readFileSync(f, 'utf8') -} - -let __is_nodejs_main = false -try { - // node.js specific checks and exports - __is_nodejs_main = (require.main === module) - exports.convert = convert -} catch (e) { } - -if (__is_nodejs_main) { - // running in node.js called from the CLI - let args = process.argv.slice(2) - if (args.length == 0 || args.find((a) => a == '-h')) { - console.log(`Usage: ${process.argv[1]} FILE [FILE...]`) - process.exit(0) - } - for (let i = 0; i < args.length; i++) { - const f = args[i]; - process.stdout.write(convert(readFile(f))); - } - -} - export const markdownTest = `# Heading 1 ## Heading 2 ### Heading 3 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 e3adcc62c..10eee4a86 100644 --- a/.config/ags/lib/notification.js +++ b/.config/ags/lib/notification.js @@ -1,13 +1,13 @@ // 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"; import { setupCursorHover } from "./cursorhover.js"; import { AnimatedCircProg } from "./animatedcircularprogress.js"; -import { MarginRevealer } from './advancedrevealers.js'; function guessMessageType(summary) { if (summary.includes('recording')) return 'screen_record'; @@ -93,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(); } @@ -109,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, @@ -159,18 +159,23 @@ export default ({ label: notifObject.body, }), Box({ - homogeneous: true, - className: 'notif-actions', + className: 'notif-actions spacing-h-5', children: [ Button({ + hexpand: true, className: `notif-action notif-action-${notifObject.urgency}`, - label: 'Close', onClicked: () => destroyWithAnims(), + child: Label({ + label: 'Close', + }) }), ...notifObject.actions.map(action => Widget.Button({ + hexpand: true, className: `notif-action notif-action-${notifObject.urgency}`, onClicked: () => notifObject.invoke(action.id), - label: action.label, + child: Label({ + label: action.label, + }) })) ], }) @@ -258,8 +263,13 @@ export default ({ className: `${isPopup ? 'popup-' : ''}notif-${notifObject.urgency} spacing-h-10`, children: [ notifIcon, - notifText, - notifExpandButton, + Box({ + className: 'spacing-h-5', + children: [ + notifText, + notifExpandButton, + ] + }) ] }) @@ -334,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')); @@ -354,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]; @@ -387,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 48c0bce47..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 => { @@ -99,7 +100,7 @@ const NetworkWiredIndicator = () => Widget.Stack({ return; const { internet } = Network.wired; - if (internet === 'connected' || internet === 'connecting') + if (['connecting', 'connected'].includes(internet)) stack.shown = internet; else if (Network.connectivity !== 'full') stack.shown = 'disconnected'; @@ -135,7 +136,7 @@ const NetworkWifiIndicator = () => Widget.Stack({ if (Network.wifi.internet == 'connected') { stack.shown = String(Math.ceil(Network.wifi.strength / 25)); } - else if (Network.wifi.internet == 'disconnected' || Network.wifi.internet == 'connecting') { + else if (["disconnected", "connecting"].includes(Network.wifi.internet)) { stack.shown = Network.wifi.internet; } }), @@ -154,14 +155,14 @@ export const NetworkIndicator = () => Widget.Stack({ return; } const primary = Network.primary || 'fallback'; - if (primary == 'wifi' || primary == 'wired') + if (['wifi', 'wired'].includes(primary)) stack.shown = primary; else stack.shown = 'fallback'; }), }); -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/README.md b/.config/ags/scripts/README.md old mode 100755 new mode 100644 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/pywal_to_material.scss b/.config/ags/scripts/color_generation/pywal_to_material.scss old mode 100755 new mode 100644 diff --git a/.config/ags/scripts/color_generation/specials/_material_badapple.scss b/.config/ags/scripts/color_generation/specials/_material_badapple.scss old mode 100755 new mode 100644 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/record-script.sh b/.config/ags/scripts/record-script.sh index 904b98f80..83c2df3fa 100755 --- a/.config/ags/scripts/record-script.sh +++ b/.config/ags/scripts/record-script.sh @@ -17,6 +17,6 @@ if [[ "$(pidof wf-recorder)" == "" ]]; then wf-recorder --pixel-format yuv420p -f './recording_'"$(getdate)"'.mp4' -t --geometry "$(slurp)" & disown fi else - /usr/bin/kill --signal SIGINT wf-recorder + kill --signal SIGINT wf-recorder notify-send "Recording Stopped" "Stopped" -a 'record-script.sh' fi diff --git a/.config/ags/scripts/templates/foot/foot.ini b/.config/ags/scripts/templates/foot/foot.ini old mode 100755 new mode 100644 diff --git a/.config/ags/scripts/templates/fuzzel/fuzzel.ini b/.config/ags/scripts/templates/fuzzel/fuzzel.ini old mode 100755 new mode 100644 diff --git a/.config/ags/scripts/templates/gradience/preset.json b/.config/ags/scripts/templates/gradience/preset.json index 8591b87f8..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,26 +99,31 @@ "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)", - "scrollbar_outline_color": "rgba(0, 0, 0, 0.5)" + "scrollbar_outline_color": "rgba(0, 0, 0, 0.5)", + + "sidebar_bg_color": "@window_bg_color", + "sidebar_fg_color":"@window_fg_color", + "sidebar_border_color": "@sidebar_bg_color", + "sidebar_backdrop_color": "@sidebar_bg_color" }, "palette": { "blue_": {}, @@ -132,8 +137,8 @@ "dark_": {} }, "custom_css": { - "gtk4": "@define-color sidebar_bg_color @window_bg_color; @define-color sidebar_fg_color @window_fg_color; @define-color sidebar_border_color @window_bg_color; @define-color sidebar_backdrop_color @window_bg_color; ", - "gtk3": "@define-color sidebar_bg_color @window_bg_color; @define-color sidebar_fg_color @window_fg_color; @define-color sidebar_border_color @window_bg_color; @define-color sidebar_backdrop_color @window_bg_color; " + "gtk4": "", + "gtk3": "" }, "plugins": {} } \ No newline at end of file diff --git a/.config/ags/scripts/templates/gradience/preset_template.json b/.config/ags/scripts/templates/gradience/preset_template.json index 0f2bc011f..aeb57489c 100644 --- a/.config/ags/scripts/templates/gradience/preset_template.json +++ b/.config/ags/scripts/templates/gradience/preset_template.json @@ -118,7 +118,12 @@ "thumbnail_bg_color": "#1a1b26", "thumbnail_fg_color": "#AEE5FA", "shade_color": "rgba(0, 0, 0, 0.36)", - "scrollbar_outline_color": "rgba(0, 0, 0, 0.5)" + "scrollbar_outline_color": "rgba(0, 0, 0, 0.5)", + + "sidebar_bg_color": "@window_bg_color", + "sidebar_fg_color":"@window_fg_color", + "sidebar_border_color": "@sidebar_bg_color", + "sidebar_backdrop_color": "@sidebar_bg_color" }, "palette": { "blue_": {}, @@ -132,8 +137,8 @@ "dark_": {} }, "custom_css": { - "gtk4": "@define-color sidebar_bg_color @window_bg_color; @define-color sidebar_fg_color @window_fg_color; @define-color sidebar_border_color @window_bg_color; @define-color sidebar_backdrop_color @window_bg_color; ", - "gtk3": "@define-color sidebar_bg_color @window_bg_color; @define-color sidebar_fg_color @window_fg_color; @define-color sidebar_border_color @window_bg_color; @define-color sidebar_backdrop_color @window_bg_color; " + "gtk4": "", + "gtk3": "" }, "plugins": {} } \ No newline at end of file diff --git a/.config/ags/scripts/templates/gtklock/main.scss b/.config/ags/scripts/templates/gtklock/main.scss old mode 100755 new mode 100644 diff --git a/.config/ags/scripts/templates/gtklock/style.css b/.config/ags/scripts/templates/gtklock/style.css old mode 100755 new mode 100644 diff --git a/.config/ags/scripts/templates/hypr/colors.conf b/.config/ags/scripts/templates/hypr/colors.conf old mode 100755 new mode 100644 index f62ab7a71..0c1ba7f08 --- a/.config/ags/scripts/templates/hypr/colors.conf +++ b/.config/ags/scripts/templates/hypr/colors.conf @@ -1,4 +1,4 @@ -$SLURP_COMMAND="$(slurp -d -c {{ $onSecondaryContainer }}BB -b {{ $secondaryContainer }}22 -s 00000000)" +$SLURP_COMMAND="$(slurp -d -c {{ $onSecondaryContainer }}BB -b {{ $secondaryContainer }}44 -s 00000000)" general { col.active_border = rgba({{ $onPrimary }}FF) @@ -6,13 +6,13 @@ general { } plugin { - droidbars { + droidbars { # This is my hyprbars mod that broke :( # example config bar_height = 30 background_color = rgba({{ $background }}FF) # background_color_active = rgba({{ $surfaceVariant }}FF) # Not added yet text_color = rgba({{ $onSecondaryContainer }}FF) - font_family = Lexend + font_family = Rubik, Geist, AR One Sans, Reddit Sans, Inter, Roboto, Ubuntu, Noto Sans, sans-serif button_font_fmily = JetBrainsMono NF # example buttons (R -> L) @@ -24,7 +24,7 @@ plugin { } hyprbars { # Honestly idk if it works like css, but well, why not - bar_text_font = Geist, AR One Sans, Reddit Sans, Inter, Roboto, Ubuntu, Noto Sans, sans-serif + bar_text_font = Rubik, Geist, AR One Sans, Reddit Sans, Inter, Roboto, Ubuntu, Noto Sans, sans-serif bar_height = 30 bar_padding = 10 bar_button_padding = 5 diff --git a/.config/ags/scss/_bar.scss b/.config/ags/scss/_bar.scss index dfde74374..840142d99 100644 --- a/.config/ags/scss/_bar.scss +++ b/.config/ags/scss/_bar.scss @@ -4,10 +4,7 @@ $black: black; $white: white; $bar_ws_width: 1.774rem; -$bar_subgroup_bg: mix($surfaceVariant, $primary, 89%); -@if $darkmode ==true { - $bar_subgroup_bg: $surfaceVariant; -} +$bar_subgroup_bg: $surfaceVariant; @mixin bar-group-rounding { @include small-rounding; @@ -45,8 +42,7 @@ $bar_subgroup_bg: mix($surfaceVariant, $primary, 89%); } .bar-group-pad-system { - padding-left: 1.023rem; - padding-right: 0.341rem; + padding: 0rem 0.341rem; } .bar-group-pad-music { @@ -131,6 +127,10 @@ $bar_subgroup_bg: mix($surfaceVariant, $primary, 89%); margin: 0rem 0.341rem; } +.bar-clock-box { + margin: 0rem 0.682rem; +} + .bar-clock { @include titlefont; font-size: 1.2727rem; diff --git a/.config/ags/scss/_cheatsheet.scss b/.config/ags/scss/_cheatsheet.scss index 5e124b1e1..b32b0c463 100644 --- a/.config/ags/scss/_cheatsheet.scss +++ b/.config/ags/scss/_cheatsheet.scss @@ -39,11 +39,11 @@ .cheatsheet-closebtn:hover, .cheatsheet-closebtn:focus { - background-color: $surfaceVariant; + background-color: $hovercolor; } .cheatsheet-closebtn:active { - background-color: mix($surfaceVariant, $onSurfaceVariant, 70%); + background-color: $activecolor; } .cheatsheet-category-title { diff --git a/.config/ags/scss/_colors.scss b/.config/ags/scss/_colors.scss old mode 100755 new mode 100644 diff --git a/.config/ags/scss/_common.scss b/.config/ags/scss/_common.scss index 8332cb62e..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,15 +62,31 @@ 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 { + background-color: mix($surfaceVariant, $onSurfaceVariant, 80%); +} -.separator-line { - background-color: $surfaceVariant; - min-width: 0.068rem; - min-height: 0.068rem; +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 { @@ -132,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; @@ -154,18 +170,17 @@ tooltip { .segment-btn:focus, .segment-btn:hover { - background-color: $surfaceVariant; - color: $onSurfaceVariant; + background-color: $hovercolor; } .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; } @@ -191,4 +206,4 @@ tooltip { .gap-h-15 { min-width: 1.023rem; -} \ No newline at end of file +} diff --git a/.config/ags/scss/_dock.scss b/.config/ags/scss/_dock.scss old mode 100755 new mode 100644 diff --git a/.config/ags/scss/_lib_classes.scss b/.config/ags/scss/_lib_classes.scss index ad586d2aa..e2ae27387 100644 --- a/.config/ags/scss/_lib_classes.scss +++ b/.config/ags/scss/_lib_classes.scss @@ -21,12 +21,11 @@ } .test { - background-image: linear-gradient(45deg, - #F4D609 0%, #F4D609 10%, #212121 10%, #212121 20%, - #F4D609 20%, #F4D609 30%, #212121 30%, #212121 40%, - #F4D609 40%, #F4D609 50%, #212121 50%, #212121 60%, - #F4D609 60%, #F4D609 70%, #212121 70%, #212121 80%, - #F4D609 80%, #F4D609 90%, #212121 90%, #212121 100%); + background-image: linear-gradient( + 45deg, #f4d609 0%, #f4d609 10%, #212121 10%, #212121 20%, #f4d609 20%, #f4d609 30%, #212121 30%, + #212121 40%, #f4d609 40%, #f4d609 50%, #212121 50%, #212121 60%, #f4d609 60%, + #f4d609 70%, #212121 70%, #212121 80%, #f4d609 80%, #f4d609 90%, #212121 90%, #212121 100% + ); background-repeat: repeat; } @@ -178,191 +177,204 @@ @include icon-nerd; } -.separator-circle { - @include full-rounding; - background-color: $onSurface; - margin: 0rem 0.682rem; - min-width: 0.545rem; - min-height: 0.545rem; +.separator-line { + background-color: $outline; + min-width: 0.068rem; + min-height: 0.068rem; } -.spacing-h-3>* { +.separator-circle { + @include full-rounding; + background-color: $outline; + margin: 0rem 0.682rem; + min-width: 0.273rem; + min-height: 0.273rem; +} + +.spacing-h-3 > * { margin-right: 0.205rem; } -.spacing-h-3>*:last-child { +.spacing-h-3 > *:last-child { margin-right: 0rem; } -.spacing-v-15>* { +.spacing-v-3 > * { + margin-bottom: 0.205rem; +} + +.spacing-v-3 > *:last-child { + margin-bottom: 0rem; +} + +.spacing-v-15 > * { margin-bottom: 1.023rem; } -.spacing-v-15>*:last-child { +.spacing-v-15 > *:last-child { margin-bottom: 0rem; } -.spacing-h-15>* { +.spacing-h-15 > * { margin-right: 1.023rem; } -.spacing-h-15>*:last-child { +.spacing-h-15 > *:last-child { margin-right: 0rem; } -.spacing-h-15>revealer>* { +.spacing-h-15 > revealer > * { margin-right: 1.023rem; } -.spacing-h-15>revealer:last-child>* { +.spacing-h-15 > revealer:last-child > * { margin-right: 0rem; } -.spacing-h-15>scrolledwindow>* { +.spacing-h-15 > scrolledwindow > * { margin-right: 1.023rem; } -.spacing-h-15>scrolledwindow:last-child>* { +.spacing-h-15 > scrolledwindow:last-child > * { margin-right: 0rem; } -.spacing-v-5>box { +.spacing-v-5 > box { margin-bottom: 0.341rem; } -.spacing-v-5>box:last-child { +.spacing-v-5 > box:last-child { margin-bottom: 0rem; } -.spacing-v-5>* { +.spacing-v-5 > * { margin-bottom: 0.341rem; } -.spacing-v-5>*:last-child { +.spacing-v-5 > *:last-child { margin-bottom: 0rem; } -.spacing-v-5-revealer>revealer>* { +.spacing-v-5-revealer > revealer > * { margin-bottom: 0.341rem; } -.spacing-v-5-revealer>revealer:last-child>* { +.spacing-v-5-revealer > revealer:last-child > * { margin-bottom: 0rem; } -.spacing-v-5-revealer>scrolledwindow>* { +.spacing-v-5-revealer > scrolledwindow > * { margin-bottom: 0.341rem; } -.spacing-v-5-revealer>scrolledwindow:last-child>* { +.spacing-v-5-revealer > scrolledwindow:last-child > * { margin-bottom: 0rem; } -.spacing-h-4>* { +.spacing-h-4 > * { margin-right: 0.273rem; } -.spacing-h-4>*:last-child { +.spacing-h-4 > *:last-child { margin-right: 0rem; } -.spacing-h-5>* { +.spacing-h-5 > * { margin-right: 0.341rem; } -.spacing-h-5>*:last-child { +.spacing-h-5 > *:last-child { margin-right: 0rem; } -.spacing-h-5>widget>* { +.spacing-h-5 > widget > * { margin-right: 0.341rem; } -.spacing-h-5>widget:last-child>* { +.spacing-h-5 > widget:last-child > * { margin-right: 0rem; } -.spacing-h-5>revealer>* { +.spacing-h-5 > revealer > * { margin-right: 0.341rem; } -.spacing-h-5>revealer:last-child>* { +.spacing-h-5 > revealer:last-child > * { margin-right: 0rem; } -.spacing-h-5>scrolledwindow>* { +.spacing-h-5 > scrolledwindow > * { margin-right: 0.341rem; } -.spacing-h-5>scrolledwindow:last-child>* { +.spacing-h-5 > scrolledwindow:last-child > * { margin-right: 0rem; } -.spacing-v-minus5>* { +.spacing-v-minus5 > * { margin-bottom: -0.341rem; } -.spacing-v-minus5>*:last-child { +.spacing-v-minus5 > *:last-child { margin-bottom: 0rem; } -.spacing-h-10>* { +.spacing-h-10 > * { margin-right: 0.682rem; } -.spacing-h-10>*:last-child { +.spacing-h-10 > *:last-child { margin-right: 0rem; } -.spacing-h-10>revealer>* { +.spacing-h-10 > revealer > * { margin-right: 0.682rem; } -.spacing-h-10>revealer:last-child>* { +.spacing-h-10 > revealer:last-child > * { margin-right: 0rem; } -.spacing-h-10>scrolledwindow>* { +.spacing-h-10 > scrolledwindow > * { margin-right: 0.682rem; } -.spacing-h-10>scrolledwindow:last-child>* { +.spacing-h-10 > scrolledwindow:last-child > * { margin-right: 0rem; } -.spacing-h-10>flowboxchild>* { +.spacing-h-10 > flowboxchild > * { margin-right: 0.682rem; } -.spacing-h-10>flowboxchild:last-child>* { +.spacing-h-10 > flowboxchild:last-child > * { margin-right: 0rem; } -.spacing-v-10>* { +.spacing-v-10 > * { margin-bottom: 0.682rem; } -.spacing-v-10>*:last-child { +.spacing-v-10 > *:last-child { margin-bottom: 0rem; } -.spacing-h-20>* { +.spacing-h-20 > * { margin-right: 1.364rem; } -.spacing-h-20>*:last-child { +.spacing-h-20 > *:last-child { margin-right: 0rem; } -.spacing-v-20>* { +.spacing-v-20 > * { margin-bottom: 1.364rem; } -.spacing-v-20>*:last-child { +.spacing-v-20 > *:last-child { margin-bottom: 0rem; } - .anim-enter { @include anim-enter; } @@ -429,51 +441,51 @@ color: transparent; } -.spacing-h--5>box { +.spacing-h--5 > box { margin-right: -0.341rem; } -.spacing-h--5>box:last-child { +.spacing-h--5 > box:last-child { margin-right: 0rem; } -.spacing-v--5>* { +.spacing-v--5 > * { margin-bottom: -0.341rem; } -.spacing-v--5>*:last-child { +.spacing-v--5 > *:last-child { margin-bottom: 0rem; } -.spacing-h--10>* { +.spacing-h--10 > * { margin-left: -1.364rem; } -.spacing-h--10>*:first-child { +.spacing-h--10 > *:first-child { margin-left: 0rem; } -.spacing-v--10>* { +.spacing-v--10 > * { margin-bottom: -0.682rem; } -.spacing-v--10>*:last-child { +.spacing-v--10 > *:last-child { margin-bottom: 0rem; } -.spacing-v--10>* { +.spacing-v--10 > * { margin-bottom: -0.682rem; } -.spacing-v--10>*:last-child { +.spacing-v--10 > *:last-child { margin-bottom: 0rem; } -.spacing-h--20>* { +.spacing-h--20 > * { margin-left: -1.364rem; } -.spacing-h--20>*:first-child { +.spacing-h--20 > *:first-child { margin-left: 0rem; } @@ -484,11 +496,24 @@ .menu-decel { @include menu_decel; } - .element-show { @include element_easeInOut; } - .element-hide { @include element_easeInOut; -} \ No newline at end of file +} +.element-move { + @include element_easeInOut; +} +.element-decel { + @include element_decel; +} +.element-bounceout { + @include element_bounceOut; +} +.element-accel { + @include element_accel; +} +.page-move { + @include page_move; +} diff --git a/.config/ags/scss/_lib_mixins.scss b/.config/ags/scss/_lib_mixins.scss index b43dc52e1..54009bbd1 100644 --- a/.config/ags/scss/_lib_mixins.scss +++ b/.config/ags/scss/_lib_mixins.scss @@ -30,56 +30,38 @@ $rounding_large: 1.705rem; @mixin titlefont { // Geometric sans-serif - font-family: - 'Gabarito', - 'Poppins', - 'Lexend', - sans-serif; + font-family: "Gabarito", "Poppins", "Lexend", sans-serif; } @mixin mainfont { // Other clean sans-serif - font-family: - 'Rubik', - 'Geist', - 'AR One Sans', - 'Reddit Sans', - 'Inter', - 'Roboto', - 'Ubuntu', - 'Noto Sans', - sans-serif; + font-family: "Rubik", "Geist", "AR One Sans", "Reddit Sans", "Inter", + "Roboto", "Ubuntu", "Noto Sans", sans-serif; // font-weight: 500; } @mixin icon-material { // Material Design Icons - font-family: - 'Material Symbols Rounded', - 'Material Symbols Outlined', - 'Material Symbols Sharp'; + font-family: "Material Symbols Rounded", "Material Symbols Outlined", + "Material Symbols Sharp"; } @mixin icon-nerd { // Nerd Fonts - font-family: - 'SpaceMono NF', 'SpaceMono Nerd Font', - 'JetBrains Mono NF', 'JetBrains Mono Nerd Font', - monospace; + font-family: "SpaceMono NF", "SpaceMono Nerd Font", "JetBrains Mono NF", + "JetBrains Mono Nerd Font", monospace; } @mixin techfont { // Monospace for sys info n stuff. Doesn't have to be a nerd font, but it's cool. - font-family: 'JetBrains Mono NF', 'JetBrains Mono Nerd Font', 'JetBrains Mono NL', 'SpaceMono NF', 'SpaceMono Nerd Font', monospace; + font-family: "JetBrains Mono NF", "JetBrains Mono Nerd Font", + "JetBrains Mono NL", "SpaceMono NF", "SpaceMono Nerd Font", monospace; } @mixin readingfont { // The most readable fonts, for a comfortable reading experience // in stuff like ChatGPT widget - font-family: - 'Lexend', - 'Noto Sans', - sans-serif; + font-family: "Lexend", "Noto Sans", sans-serif; // font-weight: 500; } @@ -91,7 +73,6 @@ $rounding_large: 1.705rem; color: $actiontext; } - $elevation_margin: 0.476rem; @mixin elevation-safe { @@ -164,14 +145,18 @@ $elevation_margin: 0.476rem; @mixin element_decel { transition: 300ms cubic-bezier(0, 0.55, 0.45, 1); } - +@mixin element_bounceOut { + transition: transform 200ms cubic-bezier(0.34, 1.56, 0.64, 1); +} @mixin element_accel { transition: 300ms cubic-bezier(0.55, 0, 1, 0.45); } - @mixin element_easeInOut { transition: 300ms cubic-bezier(0.85, 0, 0.15, 1); } +@mixin page_move { + transition: 500ms cubic-bezier(0.85, 0, 0.15, 1); +} @function tint($color, $percentage) { @return mix(rgb(245, 250, 255), $color, $percentage); @@ -215,4 +200,4 @@ $overlay2: mix($onSurface, rgba(0, 0, 0, 0), 40%); } $white: white; -$black: black; \ No newline at end of file +$black: black; diff --git a/.config/ags/scss/_material.scss b/.config/ags/scss/_material.scss old mode 100755 new mode 100644 index 4b1ab4eee..687527a0c --- 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/scss/_musicmaterial.scss b/.config/ags/scss/_musicmaterial.scss old mode 100755 new mode 100644 index 0c924dc64..8b1378917 --- a/.config/ags/scss/_musicmaterial.scss +++ b/.config/ags/scss/_musicmaterial.scss @@ -1,29 +1 @@ -$darkmode: true; -$primary: #ecb1ff; -$onPrimary: #4f076e; -$primaryContainer: #682886; -$onPrimaryContainer: #f9d8ff; -$secondary: #d4c0d8; -$onSecondary: #392c3d; -$secondaryContainer: #504254; -$onSecondaryContainer: #f1dcf4; -$tertiary: #f5b7b5; -$onTertiary: #4c2525; -$tertiaryContainer: #663b3a; -$onTertiaryContainer: #ffdad8; -$error: #ffb4a9; -$onError: #680003; -$errorContainer: #930006; -$onErrorContainer: #ffb4a9; -$colorbarbg: #120F12; -$background: #120F12; -$onBackground: #e8e0e5; -$surface: #1e1a1e; -$onSurface: #e8e0e5; -$surfaceVariant: #4c444d; -$onSurfaceVariant: #cec3cd; -$outline: #978e97; -$shadow: #000000; -$inverseSurface: #e8e0e5; -$inverseOnSurface: #332f33; -$inversePrimary: #8342a1; + diff --git a/.config/ags/scss/_musicwal.scss b/.config/ags/scss/_musicwal.scss index f96182baf..8b1378917 100644 --- a/.config/ags/scss/_musicwal.scss +++ b/.config/ags/scss/_musicwal.scss @@ -1,26 +1 @@ -// SCSS Variables -// Generated by 'wal' -$wallpaper: "/home/end/.cache/ags/media/c77cd3721bb54437609b42bd5254d1a16437f855"; -// Special -$background: #0C0820; -$foreground: #e5c7e7; -$cursor: #e5c7e7; - -// Colors -$color0: #0C0820; -$color1: #3F26DE; -$color2: #671AD9; -$color3: #A152BD; -$color4: #9E1EEA; -$color5: #E424F5; -$color6: #E65BF0; -$color7: #e5c7e7; -$color8: #a08ba1; -$color9: #3F26DE; -$color10: #671AD9; -$color11: #A152BD; -$color12: #9E1EEA; -$color13: #E424F5; -$color14: #E65BF0; -$color15: #e5c7e7; diff --git a/.config/ags/scss/_notifications.scss b/.config/ags/scss/_notifications.scss index 40bb15fa6..24357c0b4 100644 --- a/.config/ags/scss/_notifications.scss +++ b/.config/ags/scss/_notifications.scss @@ -108,20 +108,34 @@ $notif_surface: $t_background; background: $activecolor; } -.notif-closeall-btn { +.notif-listaction-btn { @include notif-rounding; - padding: 0.341rem 0.341rem; + padding: 0.341rem 0.682rem; } -.notif-closeall-btn:hover, -.notif-closeall-btn:focus { +.notif-listaction-btn:hover, +.notif-listaction-btn:focus { background-color: $hovercolor; } -.notif-closeall-btn:active { +.notif-listaction-btn:active { background-color: $activecolor; } +.notif-listaction-btn-enabled { + background-color: $secondaryContainer; + color: $onSecondaryContainer; +} + +.notif-listaction-btn-enabled:hover, +.notif-listaction-btn-enabled:focus { + background-color: mix($secondaryContainer, $onSecondaryContainer, 90%); +} + +.notif-listaction-btn-enabled:active { + background-color: mix($secondaryContainer, $onSecondaryContainer, 75%); +} + .osd-notif { @include notif-rounding; background-color: transparentize( @@ -170,11 +184,11 @@ $notif_surface: $t_background; .notif-action-low:focus, .notif-action-low:hover { - background-color: mix($t_onSurfaceVariant, $t_surface, 18%); + background-color: $hovercolor; } .notif-action-low:active { - background-color: mix($t_onSurfaceVariant, $t_surface, 23%); + background-color: $activecolor; } .notif-action-normal { @@ -184,11 +198,11 @@ $notif_surface: $t_background; .notif-action-normal:focus, .notif-action-normal:hover { - background-color: mix($t_onSurfaceVariant, $t_surface, 18%); + background-color: $hovercolor; } .notif-action-normal:active { - background-color: mix($t_onSurfaceVariant, $t_surface, 23%); + background-color: $activecolor; } .notif-action-critical { diff --git a/.config/ags/scss/_osk.scss b/.config/ags/scss/_osk.scss index c04ec8d9a..ced6bf7ff 100644 --- a/.config/ags/scss/_osk.scss +++ b/.config/ags/scss/_osk.scss @@ -50,16 +50,16 @@ $osk_key_fontsize: 1.091rem; .osk-key:hover, .osk-key:focus { - background-color: mix($t_surfaceVariant, $t_onSurfaceVariant, 90%); + background-color: $hovercolor; } .osk-key:active { - background-color: mix($t_surfaceVariant, $t_onSurfaceVariant, 70%); + background-color: $activecolor; font-size: $osk_key_fontsize; } .osk-key-active { - background-color: mix($t_surfaceVariant, $t_onSurfaceVariant, 70%); + background-color: $activecolor; } .osk-key-normal { @@ -109,4 +109,4 @@ $osk_key_fontsize: 1.091rem; .osk-control-button:active { background-color: mix($t_surfaceVariant, $t_onSurfaceVariant, 70%); font-size: $osk_key_fontsize; -} \ No newline at end of file +} diff --git a/.config/ags/scss/_sidebars.scss b/.config/ags/scss/_sidebars.scss index 6eb0abb24..7773f82a6 100644 --- a/.config/ags/scss/_sidebars.scss +++ b/.config/ags/scss/_sidebars.scss @@ -85,11 +85,11 @@ $onChatgpt: $onPrimary; .sidebar-iconbutton:hover, .sidebar-iconbutton:focus { - background-color: mix($t_secondaryContainer, $t_onSecondaryContainer, 80%); + background-color: $hovercolor; } .sidebar-iconbutton:active { - background-color: mix($t_secondaryContainer, $t_onSecondaryContainer, 60%); + background-color: $activecolor; } .sidebar-button { @@ -107,20 +107,20 @@ $onChatgpt: $onPrimary; .sidebar-button:hover, .sidebar-button:focus { - background-color: mix($t_secondaryContainer, $t_onSecondaryContainer, 80%); + background-color: $hovercolor; } .sidebar-button:active { - background-color: mix($t_secondaryContainer, $t_onSecondaryContainer, 60%); + background-color: $activecolor; } .sidebar-button-nopad:hover, .sidebar-button-nopad:focus { - background-color: mix($t_secondaryContainer, $t_onSecondaryContainer, 80%); + background-color: $hovercolor; } .sidebar-button-nopad:active { - background-color: mix($t_secondaryContainer, $t_onSecondaryContainer, 60%); + background-color: $activecolor; } .sidebar-button-left { @@ -148,11 +148,11 @@ $onChatgpt: $onPrimary; .sidebar-button-active:hover, .sidebar-button-active:focus { - background-color: mix($primary, $hovercolor, 90%); + background-color: mix($primary, $hovercolor, 70%); } .sidebar-button-active:active { - background-color: mix($primary, $hovercolor, 70%); + background-color: mix($primary, $hovercolor, 40%); } .sidebar-buttons-separator { @@ -166,27 +166,27 @@ $onChatgpt: $onPrimary; padding: 0rem $rounding_medium; } -.sidebar-navrail-btn>box>label { +.sidebar-navrail-btn > box > label { @include full-rounding; @include menu_decel; } -.sidebar-navrail-btn:hover>box>label:first-child, -.sidebar-navrail-btn:focus>box>label:first-child { - background-color: mix($t_surfaceVariant, $onSurfaceVariant, 90%); +.sidebar-navrail-btn:hover > box > label:first-child, +.sidebar-navrail-btn:focus > box > label:first-child { + background-color: $hovercolor; } -.sidebar-navrail-btn:active>box>label:first-child { - background-color: mix($surfaceVariant, $onSurfaceVariant, 75%); +.sidebar-navrail-btn:active > box > label:first-child { + background-color: $activecolor; } -.sidebar-navrail-btn-active>box>label:first-child { +.sidebar-navrail-btn-active > box > label:first-child { background-color: $secondaryContainer; color: $onSecondaryContainer; } -.sidebar-navrail-btn-active:hover>box>label:first-child, -.sidebar-navrail-btn-active:focus>box>label:first-child { +.sidebar-navrail-btn-active:hover > box > label:first-child, +.sidebar-navrail-btn-active:focus > box > label:first-child { background-color: mix($secondaryContainer, $hovercolor, 90%); color: mix($onSecondaryContainer, $hovercolor, 90%); } @@ -279,11 +279,11 @@ $onChatgpt: $onPrimary; .sidebar-calendar-btn-today:hover, .sidebar-calendar-btn-today:focus { - background-color: mix($primary, $hovercolor, 90%); + background-color: mix($primary, $hovercolor, 70%); } .sidebar-calendar-btn-today:active { - background-color: mix($primary, $hovercolor, 70%); + background-color: mix($primary, $hovercolor, 40%); } .sidebar-calendar-btn-othermonth { @@ -303,12 +303,12 @@ $onChatgpt: $onPrimary; .sidebar-calendar-monthyear-btn:hover, .sidebar-calendar-monthyear-btn:focus { - background-color: mix($t_surfaceVariant, $onSurfaceVariant, 95%); + background-color: $hovercolor; color: mix($onSurfaceVariant, $surfaceVariant, 95%); } .sidebar-calendar-monthyear-btn:active { - background-color: mix($surfaceVariant, $onSurfaceVariant, 85%); + background-color: $activecolor; color: mix($onSurfaceVariant, $surfaceVariant, 85%); } @@ -321,12 +321,12 @@ $onChatgpt: $onPrimary; } .sidebar-calendar-monthshift-btn:hover { - background-color: mix($t_surfaceVariant, $onSurfaceVariant, 95%); + background-color: $hovercolor; color: mix($onSurfaceVariant, $surfaceVariant, 95%); } .sidebar-calendar-monthshift-btn:active { - background-color: mix($surfaceVariant, $onSurfaceVariant, 85%); + background-color: $activecolor; color: mix($onSurfaceVariant, $surfaceVariant, 85%); } @@ -339,14 +339,14 @@ $onChatgpt: $onPrimary; .sidebar-selector-tab:hover, .sidebar-selector-tab:focus { - background-color: mix($t_surfaceVariant, $onSurfaceVariant, 90%); + background-color: $hovercolor; } .sidebar-selector-tab:active { - background-color: mix($surfaceVariant, $onSurfaceVariant, 75%); + background-color: $activecolor; } -.sidebar-selector-tab-active>box>label { +.sidebar-selector-tab-active > box > label { color: $primary; } @@ -378,11 +378,11 @@ $onChatgpt: $onPrimary; .sidebar-todo-item-action:hover, .sidebar-todo-item-action:focus { - background-color: mix($t_surface, $t_onSurface, 80%); + background-color: $hovercolor; } .sidebar-todo-item-action:active { - background-color: mix($t_surface, $t_onSurface, 65%); + background-color: $activecolor; } .sidebar-todo-crosser { @@ -398,23 +398,6 @@ $onChatgpt: $onPrimary; background-color: $error; } -.sidebar-clipboard-item { - border-radius: $rounding_small; - min-height: 2.045rem; - padding: 0.341rem; - background-color: $t_secondaryContainer; - color: $onSecondaryContainer; -} - -.sidebar-clipboard-item:hover, -.sidebar-clipboard-item:focus { - background-color: mix($t_secondaryContainer, $t_onSecondaryContainer, 90%); -} - -.sidebar-clipboard-item:active { - background-color: mix($t_secondaryContainer, $t_onSecondaryContainer, 80%); -} - .sidebar-todo-new { @include full-rounding; color: $onSecondaryContainer; @@ -423,7 +406,7 @@ $onChatgpt: $onPrimary; border: 0.068rem solid $onSurface; } -.sidebar-todo-new:hover, +.sidebar-todo-newz, .sidebar-todo-new:focus { background-color: mix($t_secondaryContainer, $t_onSecondaryContainer, 97%); } @@ -509,7 +492,7 @@ $onChatgpt: $onPrimary; .sidebar-chat-apiswitcher-icon { @include menu_decel; @include full-rounding; - min-width: 2.182rem; + min-width: 2.182rem; min-height: 2.182rem; color: $onSurface; } @@ -548,11 +531,19 @@ $onChatgpt: $onPrimary; .sidebar-chat-send:hover, .sidebar-chat-send:focus { - background-color: mix($sidebar_chat_textboxareaColor, $t_onSecondaryContainer, 97%); + background-color: mix( + $sidebar_chat_textboxareaColor, + $t_onSecondaryContainer, + 97% + ); } .sidebar-chat-send:active { - background-color: mix($sidebar_chat_textboxareaColor, $t_onSecondaryContainer, 80%); + background-color: mix( + $sidebar_chat_textboxareaColor, + $t_onSecondaryContainer, + 80% + ); } .sidebar-chat-send-available { @@ -574,8 +565,10 @@ $onChatgpt: $onPrimary; } .sidebar-chat-indicator { + @include menu_decel; @include full-rounding; min-width: 0.136rem; + background-color: $onBackground; } .sidebar-chat-indicator-user { @@ -594,7 +587,6 @@ $onChatgpt: $onPrimary; @include titlefont; padding: 0.341rem; margin-left: -0.136rem; - padding: 0.341rem; padding-left: 0.818rem; } @@ -621,7 +613,7 @@ $onChatgpt: $onPrimary; @include mainfont; margin: 0.273rem; margin-bottom: 0rem; - background-color: $secondaryContainer; + background-color: mix($t_secondaryContainer, $t_onSurfaceVariant, 30%); color: $onSecondaryContainer; border-radius: $rounding_medium - 0.273rem; border: 0.068rem solid mix($secondaryContainer, $onSecondaryContainer, 90%); @@ -637,7 +629,7 @@ $onChatgpt: $onPrimary; .sidebar-chat-codeblock-topbar-btn { @include full-rounding; - padding: 0.273rem; + padding: 0.273rem 0.477rem; } .sidebar-chat-codeblock-topbar-btn:hover, @@ -695,12 +687,11 @@ $onChatgpt: $onPrimary; .sidebar-chat-chip-action:hover, .sidebar-chat-chip-action:focus { - background-color: $sidebar_chat_textboxareaColor; + background-color: $hovercolor; } .sidebar-chat-chip-action:active { - background-color: mix($sidebar_chat_textboxareaColor, $onSurfaceVariant, 70%); - color: mix($sidebar_chat_textboxareaColor, $surfaceVariant, 70%); + background-color: $activecolor; } .sidebar-chat-chip-action-active { @@ -708,6 +699,21 @@ $onChatgpt: $onPrimary; border: 0.068rem solid $sidebar_chat_textboxareaColor; } +.sidebar-chat-chip-toggle { + @include menu_decel; + @include small-rounding; + padding: 0.341rem 0.477rem; + background-color: $t_surfaceVariant; + color: $onSurfaceVariant; +} +.sidebar-chat-chip-toggle:focus, +.sidebar-chat-chip-toggle:hover { + background-color: $hovercolor; +} +.sidebar-chat-chip-toggle:active { + background-color: $activecolor; +} + .sidebar-pin { @include small-rounding; @include menu_decel; @@ -718,11 +724,11 @@ $onChatgpt: $onPrimary; .sidebar-pin:hover, .sidebar-pin:focus { - background-color: mix($t_surfaceVariant, $onSurfaceVariant, 90%); + background-color: $hovercolor; } .sidebar-pin:active { - background-color: mix($surfaceVariant, $onSurfaceVariant, 75%); + background-color: $activecolor; } .sidebar-pin-enabled { @@ -741,3 +747,46 @@ $onChatgpt: $onPrimary; background-color: mix($primary, $onPrimary, 80%); } +.sidebar-waifu-heading { + @include titlefont; + padding: 0.341rem; + margin-left: -0.136rem; + padding-left: 0.818rem; +} +.sidebar-waifu-content { + margin-left: 0.682rem; +} +.sidebar-waifu-txt { + @include readingfont; + margin-left: 0.682rem; +} +.sidebar-waifu-image { + margin-left: 0.682rem; + @include normal-rounding; + background-size: cover; + background-repeat: no-repeat; + background-position: center; +} +.sidebar-waifu-image-actions { + padding: 0.313rem; +} +$waifu_image_overlay_transparency: 0.7; +.sidebar-waifu-image-action { + @include full-rounding; + min-width: 1.875rem; + min-height: 1.875rem; + background-color: rgba( + 0, + 0, + 0, + $waifu_image_overlay_transparency + ); // Fixed cuz on image + color: rgba(255, 255, 255, $waifu_image_overlay_transparency); +} +.sidebar-waifu-image-action:hover, +.sidebar-waifu-image-action:focus { + background-color: rgba(30, 30, 30, $waifu_image_overlay_transparency); +} +.sidebar-waifu-image-action:active { + background-color: rgba(60, 60, 60, $waifu_image_overlay_transparency); +} 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 28729f8d4..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'; @@ -44,7 +45,17 @@ function expandTilde(path) { // We're using many models to not be restricted to 3 messages per minute. // The whole chat will be sent every request anyway. -const KEY_FILE_LOCATION = `~/.cache/ags/user/openai_api_key.txt`; +const KEY_FILE_LOCATION = `${GLib.get_user_cache_dir()}/ags/user/openai_api_key.txt`; +const APIDOM_FILE_LOCATION = `${GLib.get_user_cache_dir()}/ags/user/openai_api_dom.txt`; +function replaceapidom(URL) { + //Utils.writeFile(URL, "/tmp/openai-url-old.log"); // For debugging + if (fileExists(expandTilde(APIDOM_FILE_LOCATION))) { + var contents = Utils.readFile(expandTilde(APIDOM_FILE_LOCATION)).trim(); + var URL = URL.toString().replace("api.openai.com", contents); + } + //Utils.writeFile(URL, "/tmp/openai-url.log"); // For debugging + return URL; +} const CHAT_MODELS = ["gpt-3.5-turbo-1106", "gpt-3.5-turbo", "gpt-3.5-turbo-16k", "gpt-3.5-turbo-0613"] const ONE_CYCLE_COUNT = 3; @@ -126,7 +137,8 @@ class ChatGPTService extends Service { _modelIndex = 0; _key = ''; _decoder = new TextDecoder(); - url = GLib.Uri.parse('https://api.openai.com/v1/chat/completions', GLib.UriFlags.NONE); + + url = GLib.Uri.parse(replaceapidom('https://api.openai.com/v1/chat/completions'), GLib.UriFlags.NONE); constructor() { super(); 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 d6489f33c..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); @@ -63,7 +64,7 @@ class TodoService extends Service { super(); this._todoPath = `${GLib.get_user_cache_dir()}/ags/user/todo.json`; if (!fileExists(this._todoPath)) { // No? create file with empty array - Utils.exec(`bash -c 'mkdir -p ~/.cache/ags/user'`); + Utils.exec(`bash -c 'mkdir -p ${GLib.get_user_cache_dir()}/ags/user'`); Utils.exec(`touch ${this._todoPath}`); Utils.writeFile("[]", this._todoPath).then(() => { this._todoJson = JSON.parse(Utils.readFile(this._todoPath)) diff --git a/.config/ags/services/waifus.js b/.config/ags/services/waifus.js index 3674713e6..11afb77d3 100644 --- a/.config/ags/services/waifus.js +++ b/.config/ags/services/waifus.js @@ -1,68 +1,35 @@ -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 Gio from 'gi://Gio'; -import GLib from 'gi://GLib'; -import Soup from 'gi://Soup?version=3.0'; -import { fileExists } from './messages.js'; +import * as Utils from 'resource:///com/github/Aylur/ags/utils.js'; -class WaifuResponse extends Service { - static { - Service.register(this, - { - 'delta': ['string'], - }, - { - 'content': ['string'], - 'thinking': ['boolean'], - 'done': ['boolean'], - }); - } +// Usage from my python waifu fetcher, for reference +// Usage: waifu-get.py [OPTION]... [TAG]... +// Options: +// --im\tUse waifu.im API. You can use many tags +// --pics\tUse waifu.pics API. Use 1 tag only. +// --nekos\tUse nekos.life (old) API. No tags. +// --segs\tForce NSFW images - _role = ''; - _content = ''; - _thinking = false; - _done = false; +// Tags: +// waifu.im (type): +// maid waifu marin-kitagawa mori-calliope raiden-shogun oppai selfies uniform +// waifu.im (nsfw tags): +// ecchi hentai ero ass paizuri oral milf - constructor(role, content, thinking = false, done = false) { - super(); - this._role = role; - this._content = content; - this._thinking = thinking; - this._done = done; - } - - get done() { return this._done } - set done(isDone) { this._done = isDone; this.notify('done') } - - get role() { return this._role } - set role(role) { this._role = role; this.emit('changed') } - - get content() { return this._content } - set content(content) { - this._content = content; - this.notify('content') - this.emit('changed') - } - - get label() { return this._parserState.parsed + this._parserState.stack.join('') } - - get thinking() { return this._thinking } - set thinking(thinking) { - this._thinking = thinking; - this.notify('thinking') - this.emit('changed') - } - - addDelta(delta) { - if (this.thinking) { - this.thinking = false; - this.content = delta; - } - else { - this.content += delta; - } - this.emit('delta', delta); - } +function paramStringFromObj(params) { + return Object.entries(params) + .map(([key, value]) => { + if (Array.isArray(value)) { // If it's an array, repeat + if (value.length == 0) return ''; + let thisKey = `${encodeURIComponent(key)}=${encodeURIComponent(value[0])}` + for (let i = 1; i < value.length; i++) { + thisKey += `&${encodeURIComponent(key)}=${encodeURIComponent(value[i])}`; + } + return thisKey; + } + return `${key}=${value}`; + }) + .join('&'); } class WaifuService extends Service { @@ -76,17 +43,20 @@ class WaifuService extends Service { 'nekos': {}, 'pics': {}, } - _url = 'https://api.waifu.im/search'; + _baseUrl = 'https://api.waifu.im/search'; _mode = 'im'; // Allowed: im _responses = []; + _queries = []; _nsfw = false; _minHeight = 600; + _status = 0; static { Service.register(this, { 'initialized': [], 'clear': [], - 'newResponse': ['string'], + 'newResponse': ['int'], + 'updateResponse': ['int'], }); } @@ -97,71 +67,90 @@ class WaifuService extends Service { clear() { this._responses = []; + this._queries = []; this.emit('clear'); } get mode() { return this._mode } set mode(value) { this._mode = value; - this._url = this._endpoints[this._mode]; + this._baseUrl = this._endpoints[this._mode]; } get nsfw() { return this._nsfw } set nsfw(value) { this._nsfw = value } + get queries() { return this._queries } get responses() { return this._responses } - readResponseRecursive(stream, response) { - stream.read_line_async( - 0, null, - (stream, res) => { - if (!stream) return; - const [bytes] = stream.read_line_finish(res); - const line = this._decoder.decode(bytes); - if (line && line != '') { - let data = line.substr(6); - if (data == '[DONE]') return; - try { - const result = JSON.parse(data); - if (result.choices[0].finish_reason === 'stop') { - response.done = true; - return; - } - response.addDelta(result.choices[0].delta.content); - } - catch { - response.addDelta(line + '\n'); - } - } - this.readResponseRecursive(stream, response); - }); - } - - fetch(msg) { - const taglist = msg.split(' '); - this.emit('newResponse', msg); - this._responses.push(msg); - + async fetch(msg) { + // Init + const userArgs = msg.split(' '); + let taglist = []; + this._nsfw = false; + // Construct body/headers + for (let i = 0; i < userArgs.length; i++) { + const thisArg = userArgs[i]; + if (thisArg == '--im') this._mode = 'im'; + else if (thisArg == '--nekos') this._mode = 'nekos'; + else if (thisArg.includes('pics')) this._mode = 'pics'; + else if (thisArg.includes('segs') || thisArg.includes('sex') || thisArg.includes('lewd')) this._nsfw = true; + else { + taglist.push(thisArg); + if(['ecchi', 'hentai', 'ero', 'ass', 'paizuri', 'oral', 'milf'].includes(thisArg)) this._nsfw = true; + } + } + const newMessageId = this._queries.length; + this._queries.push(taglist); + this.emit('newResponse', newMessageId); const params = { 'included_tags': taglist, 'height': `>=${this._minHeight}`, 'nsfw': this._nsfw, }; - - const session = new Soup.Session(); - const message = new Soup.Message({ + const paramString = paramStringFromObj(params); + // Fetch + // Note: body isn't included since passing directly to url is more reliable + const options = { method: 'GET', - uri: GLib.Uri.parse(this._url, GLib.UriFlags.NONE), - }); - session.send_message(message, (session, message) => { - if (message.status_code === 200) { - const responseBody = message.response_body.data; - const data = JSON.parse(responseBody); - // Process the response data as needed - console.log(data); - log(data); - } else { - logError('Request failed with status code: ' + message.status_code); - } - }); + headers: this._headers[this._mode], + }; + var status = 0; + Utils.fetch(`${this._endpoints[this._mode]}?${paramString}`, options) + .then(result => { + status = result.status; + return result.text(); + }) + .then((dataString) => { // Store interesting stuff and emit + const parsedData = JSON.parse(dataString); + if (!parsedData.images) this._responses.push({ + status: status, + signature: -1, + url: '', + extension: '', + source: '', + dominant_color: '#383A40', + is_nsfw: false, + width: 0, + height: 0, + tags: [], + }); + else { + const imageData = parsedData.images[0]; + this._responses.push({ + status: status, + signature: imageData?.signature || -1, + url: imageData?.url || undefined, + extension: imageData.extension, + source: imageData?.source, + dominant_color: imageData?.dominant_color || '#9392A6', + is_nsfw: imageData?.is_nsfw || false, + width: imageData?.width || 0, + height: imageData?.height || 0, + tags: imageData?.tags.map(obj => obj["name"]) || [], + }); + } + this.emit('updateResponse', newMessageId); + }) + .catch(console.error) } } diff --git a/.config/ags/style.css b/.config/ags/style.css index c50978b5c..19b3c16b3 100644 --- a/.config/ags/style.css +++ b/.config/ags/style.css @@ -16,7 +16,7 @@ margin-top: 0rem; } } .test { - background-image: linear-gradient(45deg, #F4D609 0%, #F4D609 10%, #212121 10%, #212121 20%, #F4D609 20%, #F4D609 30%, #212121 30%, #212121 40%, #F4D609 40%, #F4D609 50%, #212121 50%, #212121 60%, #F4D609 60%, #F4D609 70%, #212121 70%, #212121 80%, #F4D609 80%, #F4D609 90%, #212121 90%, #212121 100%); + background-image: linear-gradient(45deg, #f4d609 0%, #f4d609 10%, #212121 10%, #212121 20%, #f4d609 20%, #f4d609 30%, #212121 30%, #212121 40%, #f4d609 40%, #f4d609 50%, #212121 50%, #212121 60%, #f4d609 60%, #f4d609 70%, #212121 70%, #212121 80%, #f4d609 80%, #f4d609 90%, #212121 90%, #212121 100%); background-repeat: repeat; } .test-size { @@ -24,90 +24,90 @@ min-width: 3rem; } .txt-title { - font-family: 'Gabarito', 'Poppins', 'Lexend', sans-serif; + font-family: "Gabarito", "Poppins", "Lexend", sans-serif; font-size: 2.045rem; } .txt-title-small { - font-family: 'Gabarito', 'Poppins', 'Lexend', sans-serif; + font-family: "Gabarito", "Poppins", "Lexend", sans-serif; font-size: 1.364rem; } .techfont { - font-family: 'JetBrains Mono NF', 'JetBrains Mono Nerd Font', 'JetBrains Mono NL', 'SpaceMono NF', 'SpaceMono Nerd Font', monospace; } + font-family: "JetBrains Mono NF", "JetBrains Mono Nerd Font", "JetBrains Mono NL", "SpaceMono NF", "SpaceMono Nerd Font", monospace; } .txt-reading { - font-family: 'Lexend', 'Noto Sans', sans-serif; } + font-family: "Lexend", "Noto Sans", sans-serif; } .no-anim { 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); margin: 10px; } .txt-badonkers { - font-family: 'Rubik', 'Geist', 'AR One Sans', 'Reddit Sans', 'Inter', 'Roboto', 'Ubuntu', 'Noto Sans', sans-serif; + font-family: "Rubik", "Geist", "AR One Sans", "Reddit Sans", "Inter", "Roboto", "Ubuntu", "Noto Sans", sans-serif; font-size: 3rem; } .txt-tiddies { - font-family: 'Rubik', 'Geist', 'AR One Sans', 'Reddit Sans', 'Inter', 'Roboto', 'Ubuntu', 'Noto Sans', sans-serif; + font-family: "Rubik", "Geist", "AR One Sans", "Reddit Sans", "Inter", "Roboto", "Ubuntu", "Noto Sans", sans-serif; font-size: 2.7273rem; } .txt-hugerass { - font-family: 'Rubik', 'Geist', 'AR One Sans', 'Reddit Sans', 'Inter', 'Roboto', 'Ubuntu', 'Noto Sans', sans-serif; + font-family: "Rubik", "Geist", "AR One Sans", "Reddit Sans", "Inter", "Roboto", "Ubuntu", "Noto Sans", sans-serif; font-size: 2.045rem; } .txt-hugeass { - font-family: 'Rubik', 'Geist', 'AR One Sans', 'Reddit Sans', 'Inter', 'Roboto', 'Ubuntu', 'Noto Sans', sans-serif; + font-family: "Rubik", "Geist", "AR One Sans", "Reddit Sans", "Inter", "Roboto", "Ubuntu", "Noto Sans", sans-serif; font-size: 1.8182rem; } .txt-larger { - font-family: 'Rubik', 'Geist', 'AR One Sans', 'Reddit Sans', 'Inter', 'Roboto', 'Ubuntu', 'Noto Sans', sans-serif; + font-family: "Rubik", "Geist", "AR One Sans", "Reddit Sans", "Inter", "Roboto", "Ubuntu", "Noto Sans", sans-serif; font-size: 1.6363rem; } .txt-large { - font-family: 'Rubik', 'Geist', 'AR One Sans', 'Reddit Sans', 'Inter', 'Roboto', 'Ubuntu', 'Noto Sans', sans-serif; + font-family: "Rubik", "Geist", "AR One Sans", "Reddit Sans", "Inter", "Roboto", "Ubuntu", "Noto Sans", sans-serif; font-size: 1.4545rem; } .txt-norm { - font-family: 'Rubik', 'Geist', 'AR One Sans', 'Reddit Sans', 'Inter', 'Roboto', 'Ubuntu', 'Noto Sans', sans-serif; + font-family: "Rubik", "Geist", "AR One Sans", "Reddit Sans", "Inter", "Roboto", "Ubuntu", "Noto Sans", sans-serif; font-size: 1.2727rem; } .txt-small { - font-family: 'Rubik', 'Geist', 'AR One Sans', 'Reddit Sans', 'Inter', 'Roboto', 'Ubuntu', 'Noto Sans', sans-serif; + font-family: "Rubik", "Geist", "AR One Sans", "Reddit Sans", "Inter", "Roboto", "Ubuntu", "Noto Sans", sans-serif; font-size: 1.0909rem; } .txt-smallie { - font-family: 'Rubik', 'Geist', 'AR One Sans', 'Reddit Sans', 'Inter', 'Roboto', 'Ubuntu', 'Noto Sans', sans-serif; + font-family: "Rubik", "Geist", "AR One Sans", "Reddit Sans", "Inter", "Roboto", "Ubuntu", "Noto Sans", sans-serif; font-size: 1rem; } .txt-smaller { - font-family: 'Rubik', 'Geist', 'AR One Sans', 'Reddit Sans', 'Inter', 'Roboto', 'Ubuntu', 'Noto Sans', sans-serif; + font-family: "Rubik", "Geist", "AR One Sans", "Reddit Sans", "Inter", "Roboto", "Ubuntu", "Noto Sans", sans-serif; font-size: 0.9091rem; } .txt-tiny { - font-family: 'Rubik', 'Geist', 'AR One Sans', 'Reddit Sans', 'Inter', 'Roboto', 'Ubuntu', 'Noto Sans', sans-serif; + font-family: "Rubik", "Geist", "AR One Sans", "Reddit Sans", "Inter", "Roboto", "Ubuntu", "Noto Sans", sans-serif; font-size: 0.7273rem; } .txt-poof { font-size: 0px; } .txt-subtext { - color: #a9a1a4; } + color: #a1a3a4; } .txt-action { - color: #c9c0c4; } + color: #c1c3c4; } .txt-semibold { font-weight: 500; } @@ -119,24 +119,29 @@ font-style: italic; } .titlefont { - font-family: 'Gabarito', 'Poppins', 'Lexend', sans-serif; } + font-family: "Gabarito", "Poppins", "Lexend", sans-serif; } .mainfont { - font-family: 'Rubik', 'Geist', 'AR One Sans', 'Reddit Sans', 'Inter', 'Roboto', 'Ubuntu', 'Noto Sans', sans-serif; } + font-family: "Rubik", "Geist", "AR One Sans", "Reddit Sans", "Inter", "Roboto", "Ubuntu", "Noto Sans", sans-serif; } .icon-material { - font-family: 'Material Symbols Rounded', 'Material Symbols Outlined', 'Material Symbols Sharp'; } + font-family: "Material Symbols Rounded", "Material Symbols Outlined", "Material Symbols Sharp"; } .icon-nerd { - font-family: 'SpaceMono NF', 'SpaceMono Nerd Font', 'JetBrains Mono NF', 'JetBrains Mono Nerd Font', monospace; } + font-family: "SpaceMono NF", "SpaceMono Nerd Font", "JetBrains Mono NF", "JetBrains Mono Nerd Font", monospace; } + +.separator-line { + background-color: #899294; + min-width: 0.068rem; + min-height: 0.068rem; } .separator-circle { border-radius: 9999px; -gtk-outline-radius: 9999px; - background-color: #eae0e4; + background-color: #899294; margin: 0rem 0.682rem; - min-width: 0.545rem; - min-height: 0.545rem; } + min-width: 0.273rem; + min-height: 0.273rem; } .spacing-h-3 > * { margin-right: 0.205rem; } @@ -144,6 +149,12 @@ .spacing-h-3 > *:last-child { margin-right: 0rem; } +.spacing-v-3 > * { + margin-bottom: 0.205rem; } + +.spacing-v-3 > *:last-child { + margin-bottom: 0rem; } + .spacing-v-15 > * { margin-bottom: 1.023rem; } @@ -369,11 +380,26 @@ .element-hide { transition: 300ms cubic-bezier(0.85, 0, 0.15, 1); } +.element-move { + transition: 300ms cubic-bezier(0.85, 0, 0.15, 1); } + +.element-decel { + transition: 300ms cubic-bezier(0, 0.55, 0.45, 1); } + +.element-bounceout { + transition: transform 200ms cubic-bezier(0.34, 1.56, 0.64, 1); } + +.element-accel { + transition: 300ms cubic-bezier(0.55, 0, 1, 0.45); } + +.page-move { + 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 { @@ -388,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; @@ -417,53 +443,65 @@ menu > menuitem { menu > menuitem:hover, menu > menuitem:focus { - background-color: #4a4147; } + background-color: #3d4547; } -.separator-line { - background-color: #3b3338; - min-width: 0.068rem; - min-height: 0.068rem; } +menu > menuitem:active { + 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; } @@ -476,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 { @@ -492,21 +530,20 @@ tooltip { border-bottom-right-radius: 9999px; } .segment-btn { - color: #eae0e4; } + color: #e1e3e4; } .segment-btn:focus, .segment-btn:hover { - background-color: #3b3338; - color: #d1c2cb; } + 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; } @@ -530,7 +567,7 @@ tooltip { min-height: 2.727rem; } .bar-bg { - background-color: #100d10; + background-color: #0b0f10; min-height: 2.727rem; } .bar-sidespace { @@ -540,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; } @@ -549,8 +586,7 @@ tooltip { padding: 0rem 0.681rem; } .bar-group-pad-system { - padding-left: 1.023rem; - padding-right: 0.341rem; } + padding: 0rem 0.341rem; } .bar-group-pad-music { padding-right: 1.023rem; @@ -600,33 +636,36 @@ 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 { + margin: 0rem 0.682rem; } + .bar-clock { - font-family: 'Gabarito', 'Poppins', 'Lexend', sans-serif; + font-family: "Gabarito", "Poppins", "Lexend", sans-serif; font-size: 1.2727rem; } .bar-date { - font-family: 'Gabarito', 'Poppins', 'Lexend', sans-serif; + font-family: "Gabarito", "Poppins", "Lexend", sans-serif; font-size: 1rem; - color: #eae0e4; } + color: #e1e3e4; } .bar-batt { border-radius: 9999px; @@ -634,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; } @@ -653,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); @@ -676,27 +715,27 @@ 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); - font-family: 'Material Symbols Rounded', 'Material Symbols Outlined', 'Material Symbols Sharp'; } + font-family: "Material Symbols Rounded", "Material Symbols Outlined", "Material Symbols Sharp"; } .bar-music-cover { background-position: center; @@ -760,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; } @@ -776,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; } @@ -797,7 +836,7 @@ tooltip { .bar-topdesc { margin-top: -0.136rem; margin-bottom: -0.341rem; - color: #a9a1a4; } + color: #a1a3a4; } .bar-space-button { padding: 0.341rem; } @@ -840,56 +879,56 @@ 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 { - font-family: 'JetBrains Mono NF', 'JetBrains Mono Nerd Font', 'JetBrains Mono NL', 'SpaceMono NF', 'SpaceMono Nerd Font', monospace; + font-family: "JetBrains Mono NF", "JetBrains Mono Nerd Font", "JetBrains Mono NL", "SpaceMono NF", "SpaceMono Nerd Font", monospace; min-height: 1.364rem; min-width: 1.364rem; margin: 0.17rem; 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); @@ -900,13 +939,13 @@ tooltip { .cheatsheet-closebtn:hover, .cheatsheet-closebtn:focus { - background-color: #3b3338; } + background-color: rgba(128, 128, 128, 0.3); } .cheatsheet-closebtn:active { - background-color: #685e64; } + background-color: rgba(128, 128, 128, 0.7); } .cheatsheet-category-title { - font-family: 'Gabarito', 'Poppins', 'Lexend', sans-serif; + font-family: "Gabarito", "Poppins", "Lexend", sans-serif; font-size: 1.705rem; } .bg-time-box { @@ -918,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; @@ -934,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); @@ -947,26 +986,26 @@ tooltip { border: 0.682rem solid; } .bg-quicklaunch-title { - font-family: 'Rubik', 'Geist', 'AR One Sans', 'Reddit Sans', 'Inter', 'Roboto', 'Ubuntu', 'Noto Sans', sans-serif; - color: #d1c2cb; } + font-family: "Rubik", "Geist", "AR One Sans", "Reddit Sans", "Inter", "Roboto", "Ubuntu", "Noto Sans", sans-serif; + color: #bfc8ca; } .bg-quicklaunch-btn { - font-family: 'Rubik', 'Geist', 'AR One Sans', 'Reddit Sans', 'Inter', 'Roboto', 'Ubuntu', 'Noto Sans', sans-serif; + 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; @@ -978,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 { @@ -995,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; @@ -1006,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; } @@ -1034,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-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; } @@ -1081,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); } @@ -1135,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; } @@ -1173,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; @@ -1195,7 +1234,7 @@ tooltip { .overview-search-results-txt-cmd { margin-right: 0.682rem; - font-family: 'JetBrains Mono NF', 'JetBrains Mono Nerd Font', 'JetBrains Mono NL', 'SpaceMono NF', 'SpaceMono Nerd Font', monospace; + font-family: "JetBrains Mono NF", "JetBrains Mono Nerd Font", "JetBrains Mono NL", "SpaceMono NF", "SpaceMono Nerd Font", monospace; font-size: 1.227rem; } .overview-search-result-btn { @@ -1216,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); } + font-family: "Rubik", "Geist", "AR One Sans", "Reddit Sans", "Inter", "Roboto", "Ubuntu", "Noto Sans", sans-serif; + 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; } @@ -1260,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; @@ -1283,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; @@ -1291,22 +1330,22 @@ 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; } .osk-key:hover, .osk-key:focus { - background-color: rgba(74, 65, 71, 0.31); } + background-color: rgba(128, 128, 128, 0.3); } .osk-key:active { - background-color: rgba(104, 94, 100, 0.31); + background-color: rgba(128, 128, 128, 0.7); font-size: 1.091rem; } .osk-key-active { - background-color: rgba(104, 94, 100, 0.31); } + background-color: rgba(128, 128, 128, 0.7); } .osk-key-normal { min-width: 2.5rem; @@ -1334,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 { @@ -1370,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 { @@ -1392,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; } @@ -1409,47 +1448,47 @@ 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; } .sidebar-iconbutton:hover, .sidebar-iconbutton:focus { - background-color: #765f70; } + background-color: rgba(128, 128, 128, 0.3); } .sidebar-iconbutton:active { - background-color: #967e8f; } + background-color: rgba(128, 128, 128, 0.7); } .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 { - background-color: #765f70; } + background-color: rgba(128, 128, 128, 0.3); } .sidebar-button:active { - background-color: #967e8f; } + background-color: rgba(128, 128, 128, 0.7); } .sidebar-button-nopad:hover, .sidebar-button-nopad:focus { - background-color: #765f70; } + background-color: rgba(128, 128, 128, 0.3); } .sidebar-button-nopad:active { - background-color: #967e8f; } + background-color: rgba(128, 128, 128, 0.7); } .sidebar-button-left { border-top-left-radius: 0.818rem; @@ -1468,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(253, 195, 243, 0.93); } + background-color: rgba(133, 220, 236, 0.79); } .sidebar-button-active:active { - background-color: rgba(246, 191, 237, 0.79); } + 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; } @@ -1493,19 +1532,19 @@ tooltip { .sidebar-navrail-btn:hover > box > label:first-child, .sidebar-navrail-btn:focus > box > label:first-child { - background-color: rgba(116, 105, 111, 0.379); } + background-color: rgba(128, 128, 128, 0.3); } .sidebar-navrail-btn:active > box > label:first-child { - background-color: #61575d; } + 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; } @@ -1515,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 { @@ -1525,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; } @@ -1549,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; @@ -1564,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 { @@ -1578,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(253, 195, 243, 0.93); } + background-color: rgba(133, 220, 236, 0.79); } .sidebar-calendar-btn-today:active { - background-color: rgba(246, 191, 237, 0.79); } + background-color: rgba(132, 206, 220, 0.58); } .sidebar-calendar-btn-othermonth { - color: #867e82; } + color: #7d8082; } .sidebar-calendar-header { margin: 0.341rem; } @@ -1598,50 +1637,50 @@ 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(92, 83, 89, 0.3445); - color: #cabbc4; } + background-color: rgba(128, 128, 128, 0.3); + color: #b8c1c3; } .sidebar-calendar-monthyear-btn:active { - background-color: #52484e; - color: #bbadb5; } + background-color: rgba(128, 128, 128, 0.7); + 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(92, 83, 89, 0.3445); - color: #cabbc4; } + background-color: rgba(128, 128, 128, 0.3); + color: #b8c1c3; } .sidebar-calendar-monthshift-btn:active { - background-color: #52484e; - color: #bbadb5; } + background-color: rgba(128, 128, 128, 0.7); + 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 { - background-color: rgba(116, 105, 111, 0.379); } + background-color: rgba(128, 128, 128, 0.3); } .sidebar-selector-tab:active { - background-color: #61575d; } + 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; @@ -1649,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; @@ -1665,49 +1704,35 @@ tooltip { .sidebar-todo-item-action:hover, .sidebar-todo-item-action:focus { - background-color: rgba(73, 66, 70, 0.31); } + background-color: rgba(128, 128, 128, 0.3); } .sidebar-todo-item-action:active { - background-color: rgba(103, 96, 100, 0.31); } + background-color: rgba(128, 128, 128, 0.7); } .sidebar-todo-crosser { transition: margin 200ms cubic-bezier(0.1, 1, 0, 1), background-color 0ms; min-width: 0rem; } .sidebar-todo-crosser-crossed { - background-color: #eae0e4; } + background-color: #e1e3e4; } .sidebar-todo-crosser-removed { background-color: #ffb4a9; } -.sidebar-clipboard-item { - border-radius: 0.818rem; - min-height: 2.045rem; - padding: 0.341rem; - background-color: #554050; - color: #f8daee; } - -.sidebar-clipboard-item:hover, -.sidebar-clipboard-item:focus { - background-color: #654f60; } - -.sidebar-clipboard-item:active { - background-color: #765f70; } - .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-new:hover, +.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; @@ -1715,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); @@ -1731,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); + font-family: "Material Symbols Rounded", "Material Symbols Outlined", "Material Symbols Sharp"; + background-color: rgba(47, 54, 56, 0.31); min-width: 1.705rem; min-height: 1.705rem; } @@ -1776,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); @@ -1784,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); @@ -1797,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; } @@ -1811,48 +1836,49 @@ 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; } .sidebar-chat-indicator { + transition: 300ms cubic-bezier(0.1, 1, 0, 1); border-radius: 9999px; -gtk-outline-radius: 9999px; - min-width: 0.136rem; } + min-width: 0.136rem; + 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; + font-family: "Gabarito", "Poppins", "Lexend", sans-serif; padding: 0.341rem; margin-left: -0.136rem; - padding: 0.341rem; padding-left: 0.818rem; } .sidebar-chat-txtblock { @@ -1861,24 +1887,24 @@ tooltip { padding-left: 0.818rem; } .sidebar-chat-txt { - font-family: 'Lexend', 'Noto Sans', sans-serif; } + font-family: "Lexend", "Noto Sans", sans-serif; } .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; + font-family: "Rubik", "Geist", "AR One Sans", "Reddit Sans", "Inter", "Roboto", "Ubuntu", "Noto Sans", sans-serif; margin: 0.273rem; margin-bottom: 0rem; - background-color: #554050; - 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; } @@ -1891,22 +1917,22 @@ tooltip { .sidebar-chat-codeblock-topbar-btn { border-radius: 9999px; -gtk-outline-radius: 9999px; - padding: 0.273rem; } + padding: 0.273rem 0.477rem; } .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; + font-family: "JetBrains Mono NF", "JetBrains Mono Nerd Font", "JetBrains Mono NL", "SpaceMono NF", "SpaceMono Nerd Font", monospace; padding: 0.682rem; } .sidebar-chat-divider { min-height: 1px; - background-color: #776c73; + background-color: #697072; margin: 0rem 0.545rem; } .sidebar-chat-welcome-txt { @@ -1937,19 +1963,33 @@ 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 { - background-color: #776c73; } + background-color: rgba(128, 128, 128, 0.3); } .sidebar-chat-chip-action:active { - background-color: #92868d; - color: #655b61; } + 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(47, 54, 56, 0.31); + color: #bfc8ca; } + +.sidebar-chat-chip-toggle:focus, +.sidebar-chat-chip-toggle:hover { + background-color: rgba(128, 128, 128, 0.3); } + +.sidebar-chat-chip-toggle:active { + background-color: rgba(128, 128, 128, 0.7); } .sidebar-pin { border-radius: 0.818rem; @@ -1957,47 +1997,86 @@ 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 { - background-color: rgba(116, 105, 111, 0.379); } + background-color: rgba(128, 128, 128, 0.3); } .sidebar-pin:active { - background-color: #61575d; } + 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; + padding: 0.341rem; + margin-left: -0.136rem; + padding-left: 0.818rem; } + +.sidebar-waifu-content { + margin-left: 0.682rem; } + +.sidebar-waifu-txt { + font-family: "Lexend", "Noto Sans", sans-serif; + margin-left: 0.682rem; } + +.sidebar-waifu-image { + margin-left: 0.682rem; + border-radius: 1.159rem; + -gtk-outline-radius: 1.159rem; + background-size: cover; + background-repeat: no-repeat; + background-position: center; } + +.sidebar-waifu-image-actions { + padding: 0.313rem; } + +.sidebar-waifu-image-action { + border-radius: 9999px; + -gtk-outline-radius: 9999px; + min-width: 1.875rem; + min-height: 1.875rem; + background-color: rgba(0, 0, 0, 0.7); + color: rgba(255, 255, 255, 0.7); } + +.sidebar-waifu-image-action:hover, +.sidebar-waifu-image-action:focus { + background-color: rgba(30, 30, 30, 0.7); } + +.sidebar-waifu-image-action:active { + background-color: rgba(60, 60, 60, 0.7); } .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; @@ -2008,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; } @@ -2040,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; } @@ -2049,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; } @@ -2058,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; @@ -2079,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; @@ -2107,22 +2186,33 @@ tooltip { .notif-expand-btn:active { background: rgba(128, 128, 128, 0.7); } -.notif-closeall-btn { +.notif-listaction-btn { border-radius: 1.159rem; -gtk-outline-radius: 1.159rem; - padding: 0.341rem 0.341rem; } + padding: 0.341rem 0.682rem; } -.notif-closeall-btn:hover, -.notif-closeall-btn:focus { +.notif-listaction-btn:hover, +.notif-listaction-btn:focus { background-color: rgba(128, 128, 128, 0.3); } -.notif-closeall-btn:active { +.notif-listaction-btn:active { background-color: rgba(128, 128, 128, 0.7); } +.notif-listaction-btn-enabled { + background-color: #334a4f; + color: #cde7ed; } + +.notif-listaction-btn-enabled:hover, +.notif-listaction-btn-enabled:focus { + background-color: #425a5f; } + +.notif-listaction-btn-enabled:active { + 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 { @@ -2130,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; } @@ -2154,37 +2244,37 @@ 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 { - background-color: rgba(65, 57, 62, 0.31); } + background-color: rgba(128, 128, 128, 0.3); } .notif-action-low:active { - background-color: rgba(73, 65, 71, 0.31); } + 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 { - background-color: rgba(65, 57, 62, 0.31); } + background-color: rgba(128, 128, 128, 0.3); } .notif-action-normal:active { - background-color: rgba(73, 65, 71, 0.31); } + 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); @@ -2194,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); @@ -2204,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; @@ -2229,35 +2319,35 @@ tooltip { .osd-music-title { transition: 300ms cubic-bezier(0.1, 1, 0, 1); - font-family: 'Gabarito', 'Poppins', 'Lexend', sans-serif; + 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-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); border-radius: 9999px; -gtk-outline-radius: 9999px; - font-family: 'Gabarito', 'Poppins', 'Lexend', sans-serif; + 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); border-radius: 9999px; -gtk-outline-radius: 9999px; - font-family: 'Gabarito', 'Poppins', 'Lexend', sans-serif; + 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); @@ -2268,15 +2358,15 @@ 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); transition: 100ms cubic-bezier(0.05, 0.7, 0.1, 1); - font-family: 'Material Symbols Rounded', 'Material Symbols Outlined', 'Material Symbols Sharp'; + font-family: "Material Symbols Rounded", "Material Symbols Outlined", "Material Symbols Sharp"; font-size: 1.364rem; margin: -0.1rem 0rem; } @@ -2285,19 +2375,19 @@ 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); - font-family: 'Material Symbols Rounded', 'Material Symbols Outlined', 'Material Symbols Sharp'; + font-family: "Material Symbols Rounded", "Material Symbols Outlined", "Material Symbols Sharp"; font-size: 1.364rem; margin: -0.1rem 0rem; } diff --git a/.config/ags/widgets/bar/leftspace.js b/.config/ags/widgets/bar/leftspace.js index 16df27325..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}` : truncateTitle(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 0c2c496a6..d2c683b0c 100644 --- a/.config/ags/widgets/bar/music.js +++ b/.config/ags/widgets/bar/music.js @@ -1,10 +1,18 @@ -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"; import { showMusicControls } from '../../variables.js'; +function trimTrackTitle(title) { + var cleanedTitle = title; + cleanedTitle = cleanedTitle.replace(/【[^】]*】/, ''); // Remove stuff like【C93】 at beginning + cleanedTitle = cleanedTitle.replace(/\[FREE DOWNLOAD\]/g, ''); // Remove F-777's [FREE DOWNLOAD] + return cleanedTitle.trim(); +} + const TrackProgress = () => { const _updateProgress = (circprog) => { const mpris = Mpris.getPlayer(''); @@ -15,19 +23,19 @@ 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) + , }) } -export const ModuleMusic = () => Widget.EventBox({ - onScrollUp: () => execAsync('hyprctl dispatch workspace -1'), - onScrollDown: () => execAsync('hyprctl dispatch workspace +1'), +export const ModuleMusic = () => Widget.EventBox({ // TODO: use cairo to make button bounce smaller on click + onScrollUp: () => Hyprland.sendMessage(`dispatch workspace -1`), + onScrollDown: () => Hyprland.sendMessage(`dispatch workspace +1`), onPrimaryClickRelease: () => showMusicControls.setValue(!showMusicControls.value), onSecondaryClickRelease: () => execAsync(['bash', '-c', 'playerctl next || playerctl position `bc <<< "100 * $(playerctl metadata mpris:length) / 1000000 / 100"` &']), - onMiddleClickRelease: () => Mpris.getPlayer('')?.playPause(), + onMiddleClickRelease: () => execAsync('playerctl play-pause').catch(print), child: Widget.Box({ className: 'bar-group-margin bar-sides', children: [ @@ -45,17 +53,17 @@ export const ModuleMusic = () => Widget.EventBox({ 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(), @@ -66,13 +74,13 @@ export const ModuleMusic = () => Widget.EventBox({ 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 = `${mpris.trackTitle} • ${mpris.trackArtists.join(', ')}`; + 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 9a7687ff4..fb4e7b8a7 100644 --- a/.config/ags/widgets/bar/rightspace.js +++ b/.config/ags/widgets/bar/rightspace.js @@ -1,6 +1,9 @@ -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'; import { StatusIcons } from "../../lib/statusicons.js"; @@ -32,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: [ @@ -43,10 +46,29 @@ export const ModuleRightSpace = () => { children: [ Widget.Box({ hexpand: true, - className: 'spacing-h-15 txt', + className: 'spacing-h-5 txt', children: [ Widget.Box({ hexpand: true, }), barTray, + Widget.Revealer({ + transition: 'slide_left', + revealChild: false, + 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.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 c90ba4ba2..d1b8238e8 100644 --- a/.config/ags/widgets/bar/system.js +++ b/.config/ags/widgets/bar/system.js @@ -1,9 +1,11 @@ // 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; +import Hyprland from 'resource:///com/github/Aylur/ags/service/hyprland.js'; import Battery from 'resource:///com/github/Aylur/ags/service/battery.js'; import { MaterialIcon } from '../../lib/materialicon.js'; import { AnimatedCircProg } from "../../lib/animatedcircularprogress.js"; @@ -20,15 +22,15 @@ const BatBatteryProgress = () => { return AnimatedCircProg({ className: 'bar-batt-circprog', vpack: 'center', hpack: 'center', - connections: [ - [Battery, _updateProgress], - ], + extraSetup: (self) => self + .hook(Battery, _updateProgress) + , }) } const BarClock = () => Widget.Box({ vpack: 'center', - className: 'spacing-h-5 txt-onSurfaceVariant', + className: 'spacing-h-5 txt-onSurfaceVariant bar-clock-box', children: [ Widget.Label({ className: 'bar-clock', @@ -59,75 +61,39 @@ const UtilButton = ({ name, icon, onClicked }) => Button({ label: `${icon}`, }) -const Utilities = () => Scrollable({ - hexpand: true, - child: Box({ - hpack: 'center', - className: 'spacing-h-5', - children: [ - UtilButton({ - name: 'Screen snip', icon: 'screenshot_region', onClicked: () => { - Utils.execAsync(['bash', '-c', `grim -g "$(slurp -d -c e2e2e2BB -b 31313122 -s 00000000)" - | wl-copy &`]) - .catch(print) - } - }), - UtilButton({ - name: 'Color picker', icon: 'colorize', onClicked: () => { - Utils.execAsync(['hyprpicker', '-a']).catch(print) - } - }), - UtilButton({ - name: 'Toggle on-screen keyboard', icon: 'keyboard', onClicked: () => { - App.toggleWindow('osk'); - } - }), - ] - }) +const Utilities = () => Box({ + hpack: 'center', + className: 'spacing-h-5 txt-onSurfaceVariant', + children: [ + UtilButton({ + name: 'Screen snip', icon: 'screenshot_region', onClicked: () => { + Utils.execAsync(['bash', '-c', `grim -g "$(slurp -d -c e2e2e2BB -b 31313122 -s 00000000)" - | wl-copy &`]) + .catch(print) + } + }), + UtilButton({ + name: 'Color picker', icon: 'colorize', onClicked: () => { + Utils.execAsync(['hyprpicker', '-a']).catch(print) + } + }), + UtilButton({ + name: 'Toggle on-screen keyboard', icon: 'keyboard', onClicked: () => { + App.toggleWindow('osk'); + } + }), + ] }) const BarBattery = () => Box({ className: 'spacing-h-4 txt-onSurfaceVariant', children: [ - // Revealer({ // A dot for charging state - // transitionDuration: 150, - // revealChild: false, - // transition: 'crossfade', - // child: Widget.Box({ - // className: 'spacing-h-3', - // children: [ - // Widget.Box({ - // vpack: 'center', - // className: 'bar-batt-chargestate-charging-smaller', - // setup: (self) => self.hook(Battery, box => { - // box.toggleClassName('bar-batt-chargestate-low', Battery.percent <= BATTERY_LOW); - // box.toggleClassName('bar-batt-chargestate-full', Battery.charged); - // }), - // }), - // Widget.Box({ - // vpack: 'center', - // className: 'bar-batt-chargestate-charging', - // setup: (self) => self.hook(Battery, box => { - // box.toggleClassName('bar-batt-chargestate-low', Battery.percent <= BATTERY_LOW); - // box.toggleClassName('bar-batt-chargestate-full', Battery.charged); - // }), - // }), - // ] - // }), - // setup: (self) => self.hook(Battery, revealer => { - // revealer.revealChild = Battery.charging; - // }), - // }), - Stack({ - transition: 'slide_up_down', - items: [ - ['discharging', Widget.Label({ - className: 'txt-norm txt', - label: '•', - }),], - ['charging', MaterialIcon('bolt', 'norm')], - ], + Revealer({ + transitionDuration: 150, + revealChild: false, + transition: 'slide_right', + child: MaterialIcon('bolt', 'norm'), setup: (self) => self.hook(Battery, revealer => { - self.shown = Battery.charging ? 'charging' : 'discharging'; + self.revealChild = Battery.charging; }), }), Label({ @@ -156,21 +122,101 @@ const BarBattery = () => Box({ ] }); +const BarResourceValue = (name, icon, command) => Widget.Box({ + vpack: 'center', + className: 'bar-batt spacing-h-5', + children: [ + MaterialIcon(icon, 'small'), + Widget.ProgressBar({ // Progress + vpack: 'center', hexpand: true, + className: 'bar-prog-batt', + setup: (self) => self.poll(5000, (progress) => execAsync(['bash', '-c', command]) + .then((output) => { + progress.value = Number(output) / 100; + progress.tooltipText = `${name}: ${Number(output)}%` + }) + .catch(print) + ), + }), + ] +}); + +const BarResource = (name, icon, command) => { + const resourceLabel = Label({ + className: 'txt-smallie txt-onSurfaceVariant', + }); + const resourceCircProg = AnimatedCircProg({ + className: 'bar-batt-circprog', + vpack: 'center', hpack: 'center', + }); + const widget = Box({ + className: 'spacing-h-4 txt-onSurfaceVariant', + children: [ + resourceLabel, + Overlay({ + child: Widget.Box({ + vpack: 'center', + className: 'bar-batt', + homogeneous: true, + children: [ + MaterialIcon(icon, 'small'), + ], + }), + 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; +} + +const BarGroup = ({ child }) => Widget.Box({ + className: 'bar-group-margin bar-sides', + children: [ + Widget.Box({ + className: 'bar-group bar-group-standalone bar-group-pad-system', + children: [child], + }), + ] +}); + export const ModuleSystem = () => Widget.EventBox({ - onScrollUp: () => execAsync('hyprctl dispatch workspace -1'), - onScrollDown: () => execAsync('hyprctl dispatch workspace +1'), + onScrollUp: () => Hyprland.sendMessage(`dispatch workspace -1`), + onScrollDown: () => Hyprland.sendMessage(`dispatch workspace +1`), onPrimaryClick: () => App.toggleWindow('sideright'), child: Widget.Box({ - className: 'bar-group-margin bar-sides', + className: 'spacing-h-5', children: [ - Widget.Box({ - className: 'bar-group bar-group-standalone bar-group-pad-system spacing-h-5', - children: [ - BarClock(), - Utilities(), - BarBattery(), + BarGroup({ child: BarClock() }), + Stack({ + transition: 'slide_up_down', + transitionDuration: 150, + items: [ + ['laptop', Box({ + className: 'spacing-h-5', children: [ + BarGroup({ child: Utilities() }), + BarGroup({ child: BarBattery() }), + ] + })], + ['desktop', Box({ + className: 'spacing-h-5', children: [ + BarGroup({ child: BarResource('RAM usage', 'memory', `free | awk '/^Mem/ {printf("%.2f\\n", ($3/$2) * 100)}'`), }), + BarGroup({ child: BarResource('Swap usage', 'swap_horiz', `free | awk '/^Swap/ {printf("%.2f\\n", ($3/$2) * 100)}'`), }), + ] + })], ], - }), + setup: (stack) => Utils.timeout(10, () => { + if (!Battery.available) stack.shown = 'desktop'; + else stack.shown = 'laptop'; + }) + }) ] }) }); diff --git a/.config/ags/widgets/bar/tray.js b/.config/ags/widgets/bar/tray.js index 34720765a..67d65a833 100644 --- a/.config/ags/widgets/bar/tray.js +++ b/.config/ags/widgets/bar/tray.js @@ -1,59 +1,63 @@ -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), }); export const Tray = (props = {}) => { const trayContent = Box({ - className: 'bar-systray spacing-h-10', - properties: [ - ['items', new Map()], - ['onAdded', (box, id) => { + className: 'margin-right-5 spacing-h-15', + 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 83% rename from .config/ags/widgets/bar/workspaces.js rename to .config/ags/widgets/bar/workspaces_hyprland.js index b3be638f8..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'; @@ -15,15 +16,12 @@ const dummyOccupiedWs = Box({ className: 'bar-ws bar-ws-occupied' }); // Not sho // Font size = workspace id const WorkspaceContents = (count = 10) => { return DrawingArea({ - properties: [ - ['workspaceMask', 0], - ], - css: `transition: 500ms cubic-bezier(0.1, 1, 0, 1);`, - setup: (area) => area - .hook(Hyprland.active.workspace, (area) => - area.setCss(`font-size: ${Hyprland.active.workspace.id}px;`) - ) - .hook(Hyprland, (area) => { + css: `transition: 90ms cubic-bezier(0.1, 1, 0, 1);`, + 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++) { @@ -34,8 +32,21 @@ const WorkspaceContents = (count = 10) => { workspaceMask |= (1 << ws.id); } } - area._workspaceMask = workspaceMask; - }, 'notify::workspaces') + 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.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; @@ -75,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(); } @@ -88,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(); } @@ -131,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', @@ -148,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); @@ -157,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 1ad7e05df..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({ @@ -38,7 +38,7 @@ export const Keybinds = () => Widget.Box({ children: category.binds.map((keybinds, i) => Widget.Box({ // Binds vertical: false, children: keybinds.keys.map((key, i) => Widget.Label({ // Specific keys - className: `${key == 'OR' || key == '+' ? 'cheatsheet-key-notkey' : 'cheatsheet-key'} txt-small`, + className: `${['OR', '+'].includes(key) ? 'cheatsheet-key-notkey' : 'cheatsheet-key'} txt-small`, label: key, })) })) 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 4714d268b..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,28 +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)); }, }); @@ -191,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() @@ -229,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({ @@ -248,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 236f65c12..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/advancedrevealers.js'; +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(revealer); - else revealer._hide(revealer); - }, '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 7e59f5a50..be51cc963 100644 --- a/.config/ags/widgets/indicators/musiccontrols.js +++ b/.config/ags/widgets/indicators/musiccontrols.js @@ -1,10 +1,12 @@ -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'; const { Box, EventBox, Icon, Scrollable, Label, Button, Revealer } = Widget; -import { MarginRevealer } from '../../lib/advancedrevealers.js'; +import { MarginRevealer } from '../../lib/advancedwidgets.js'; import { AnimatedCircProg } from "../../lib/animatedcircularprogress.js"; import { MaterialIcon } from '../../lib/materialicon.js'; import { showMusicControls } from '../../variables.js'; @@ -17,7 +19,7 @@ function expandTilde(path) { } } -const LIGHTDARK_FILE_LOCATION = '~/.cache/ags/user/colormode.txt' +const LIGHTDARK_FILE_LOCATION = `${GLib.get_user_cache_dir()}/ags/user/colormode.txt`; const lightDark = Utils.readFile(expandTilde(LIGHTDARK_FILE_LOCATION)).trim(); const COVER_COLORSCHEME_SUFFIX = '_colorscheme.css'; const PREFERRED_PLAYER = 'plasma-browser-integration'; @@ -74,6 +76,12 @@ function getTrackfont(player) { if (title.includes('東方')) return 'Crimson Text, serif'; // Serif for Touhou stuff return DEFAULT_MUSIC_FONT; } +function trimTrackTitle(title) { + var cleanedTitle = title; + cleanedTitle = cleanedTitle.replace(/【[^】]*】/, ''); // Remove stuff like【C93】 at beginning + cleanedTitle = cleanedTitle.replace(/\[FREE DOWNLOAD\]/g, ''); // Remove F-777's [FREE DOWNLOAD] + return cleanedTitle.trim(); +} const TrackProgress = ({ player, ...rest }) => { const _updateProgress = (circprog) => { @@ -86,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) + , }) } @@ -100,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 ? player.trackTitle : 'No media'; + 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({ @@ -114,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({ @@ -134,8 +142,8 @@ const CoverArt = ({ player, ...rest }) => Box({ }), overlays: [ // Real Box({ - properties: [ - ['updateCover', (self) => { + attribute: { + 'updateCover': (self) => { const player = Mpris.getPlayer(); // Player closed @@ -165,17 +173,17 @@ const CoverArt = ({ player, ...rest }) => Box({ `${App.configDir}/scripts/color_generation/generate_colors_material.py --path '${coverPath}' > ${App.configDir}/scss/_musicmaterial.scss ${lightDark}`]) .then(() => { exec(`wal -i "${player.coverPath}" -n -t -s -e -q ${lightDark}`) - exec(`bash -c "cp ~/.cache/wal/colors.scss ${App.configDir}/scss/_musicwal.scss"`) + exec(`cp ${GLib.get_user_cache_dir()}/wal/colors.scss ${App.configDir}/scss/_musicwal.scss`); exec(`sassc ${App.configDir}/scss/_music.scss ${stylePath}`); self.css = `background-image: url('${coverPath}');`; 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'] ], }) ] @@ -194,6 +202,7 @@ const TrackControls = ({ player, ...rest }) => Widget.Revealer({ children: [ Button({ className: 'osd-music-controlbtn', + onClicked: () => execAsync('playerctl previous').catch(print), child: Label({ className: 'icon-material osd-music-controlbtn-txt', label: 'skip_previous', @@ -201,6 +210,9 @@ const TrackControls = ({ player, ...rest }) => Widget.Revealer({ }), Button({ className: 'osd-music-controlbtn', + onClicked: () => execAsync(['bash', '-c', 'playerctl next || playerctl position `bc <<< "100 * $(playerctl metadata mpris:length) / 1000000 / 100"`']) + .catch(print) + , child: Label({ className: 'icon-material osd-music-controlbtn-txt', label: 'skip_next', @@ -208,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({ @@ -230,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 }) => { @@ -256,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; + }), }) } @@ -291,22 +301,17 @@ const PlayState = ({ player }) => { overlays: [ Widget.Button({ className: 'osd-music-playstate-btn', - onClicked: () => { - Mpris.getPlayer().playPause() - }, + onClicked: () => execAsync('playerctl play-pause').catch(print), child: Widget.Label({ 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, }) }); @@ -350,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]; @@ -370,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(revealer); - else revealer._hide(revealer); - }], - ], }) 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 a347408f9..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; @@ -83,7 +87,7 @@ const keyboardItself = (kbJson) => { children: row.map(key => { return Button({ className: `osk-key osk-key-${key.shape}`, - hexpand: (key.shape == "space" || key.shape == "expand"), + hexpand: ["space", "expand"].includes(key.shape), label: key.label, setup: (button) => { let pressed = false; 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 8cc5d4b87..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"; @@ -21,12 +22,12 @@ export function launchCustomCommand(command) { execAsync([`bash`, `-c`, `${App.configDir}/scripts/color_generation/switchcolor.sh`, `&`]).catch(print); } else if (args[0] == '>light') { // Light mode - execAsync([`bash`, `-c`, `mkdir -p ~/.cache/ags/user && echo "-l" > ~/.cache/ags/user/colormode.txt`]) + execAsync([`bash`, `-c`, `mkdir -p ${GLib.get_user_cache_dir()}/ags/user && echo "-l" > ${GLib.get_user_cache_dir()}/ags/user/colormode.txt`]) .then(execAsync(['bash', '-c', `${App.configDir}/scripts/color_generation/switchwall.sh --noswitch`]).catch(print)) .catch(print); } else if (args[0] == '>dark') { // Dark mode - execAsync([`bash`, `-c`, `mkdir -p ~/.cache/ags/user && echo "" > ~/.cache/ags/user/colormode.txt`]) + execAsync([`bash`, `-c`, `mkdir -p ${GLib.get_user_cache_dir()}/ags/user && echo "" > ${GLib.get_user_cache_dir()}/ags/user/colormode.txt`]) .then(execAsync(['bash', '-c', `${App.configDir}/scripts/color_generation/switchwall.sh --noswitch`]).catch(print)) .catch(print); } @@ -34,10 +35,10 @@ export function launchCustomCommand(command) { execAsync([`bash`, `-c`, `${App.configDir}/scripts/color_generation/applycolor.sh --bad-apple`]).catch(print); } else if (args[0] == '>material') { // Light mode - execAsync([`bash`, `-c`, `mkdir -p ~/.cache/ags/user && echo "material" > ~/.cache/ags/user/colorbackend.txt`]).catch(print); + execAsync([`bash`, `-c`, `mkdir -p ${GLib.get_user_cache_dir()}/ags/user && echo "material" > ${GLib.get_user_cache_dir()}/ags/user/colorbackend.txt`]).catch(print); } else if (args[0] == '>pywal') { // Dark mode - execAsync([`bash`, `-c`, `mkdir -p ~/.cache/ags/user && echo "pywal" > ~/.cache/ags/user/colorbackend.txt`]).catch(print); + execAsync([`bash`, `-c`, `mkdir -p ${GLib.get_user_cache_dir()}/ags/user && echo "pywal" > ${GLib.get_user_cache_dir()}/ags/user/colorbackend.txt`]).catch(print); } else if (args[0] == '>todo') { // Todo Todo.add(args.slice(1).join(' ')); diff --git a/.config/ags/widgets/overview/overview.js b/.config/ags/widgets/overview/overview.js deleted file mode 100644 index f4deac393..000000000 --- a/.config/ags/widgets/overview/overview.js +++ /dev/null @@ -1,547 +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/advancedrevealers.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', -] - -const overviewTick = Variable(false); - -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); - overviewTick.value = !overviewTick.value; - }); - 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: () => { - execAsync([`bash`, `-c`, `hyprctl dispatch focuswindow address:${address}`, `&`]).catch(print); - App.closeWindow('overview'); - }, - onMiddleClickRelease: () => execAsync([`bash`, `-c`, `hyprctl dispatch closewindow address:${address}`, `&`]).catch(print), - 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: () => { - execAsync([`bash`, `-c`, `hyprctl dispatch closewindow address:${address}`, `&`]) - .catch(print); - } - }), - 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, - onPrimaryClickRelease: () => { - execAsync([`bash`, `-c`, `hyprctl dispatch workspace ${index}`, `&`]).catch(print); - 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) => { - overviewTick.value = !overviewTick.value; - execAsync([`bash`, `-c`, `hyprctl dispatch movetoworkspacesilent ${index},address:${data.get_text()}`, `&`]).catch(print); - }); - }, - 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 => { - 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._update(box), - connections: [ - // Update on change - [overviewTick, box => { if (!App.getWindow(windowName).visible) return; Utils.timeout(2, () => box._update(box)); }], - [Hyprland, box => { if (!App.getWindow(windowName).visible) return; box._update(box); }, 'client-added'], - [Hyprland, box => { if (!App.getWindow(windowName).visible) return; box._update(box); }, 'client-removed'], - // Update on show - [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 = (entry.text[0] == '/' || 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); // fuck quora - } - }, - // Actually onChange but this is ta workaround for a bug - connections: [ - ['notify::text', (entry) => { // This is when you type - const isAction = entry.text[0] == '>'; - const isDir = (entry.text[0] == '/' || 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); - } - else { - 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, - ], - 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 1e70d443f..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; - }], - ] + }) + , }) } @@ -167,6 +169,6 @@ export const SearchButton = ({ text = '' }) => searchItem({ content: `${text}`, onActivate: () => { App.closeWindow('overview'); - execAsync(['bash', '-c', `xdg-open 'https://www.google.com/search?q=${text} -site:quora.com' &`]).catch(print); // fuck quora + execAsync(['bash', '-c', `xdg-open 'https://www.google.com/search?q=${text} -site:quora.com' &`]).catch(print); // quora is useless }, }); \ No newline at end of file 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 1c6c61b38..74e9dd52f 100644 --- a/.config/ags/widgets/screencorners/main.js +++ b/.config/ags/widgets/screencorners/main.js @@ -1,6 +1,10 @@ -import { Widget } from '../../imports.js'; +import Cairo from 'gi://cairo?version=1.0'; +import Widget from 'resource:///com/github/Aylur/ags/widget.js'; import { RoundedCorner } from "../../lib/roundedcorner.js"; +const dummyRegion = new Cairo.Region(); +const enableClickthrough = (self) => self.input_shape_combine_region(dummyRegion); + export const CornerTopleft = () => Widget.Window({ name: 'cornertl', layer: 'top', @@ -8,6 +12,7 @@ export const CornerTopleft = () => Widget.Window({ exclusivity: 'normal', visible: true, child: RoundedCorner('topleft', { className: 'corner', }), + setup: enableClickthrough, }); export const CornerTopright = () => Widget.Window({ name: 'cornertr', @@ -16,6 +21,7 @@ export const CornerTopright = () => Widget.Window({ exclusivity: 'normal', visible: true, child: RoundedCorner('topright', { className: 'corner', }), + setup: enableClickthrough, }); export const CornerBottomleft = () => Widget.Window({ name: 'cornerbl', @@ -24,6 +30,7 @@ export const CornerBottomleft = () => Widget.Window({ exclusivity: 'ignore', visible: true, child: RoundedCorner('bottomleft', { className: 'corner-black', }), + setup: enableClickthrough, }); export const CornerBottomright = () => Widget.Window({ name: 'cornerbr', @@ -32,5 +39,5 @@ export const CornerBottomright = () => Widget.Window({ exclusivity: 'ignore', visible: true, child: RoundedCorner('bottomright', { className: 'corner-black', }), + setup: enableClickthrough, }); - 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 994fc9cd6..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,23 +45,24 @@ 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, }); } export default () => { // lock, logout, sleep - const lockButton = SessionButton('Lock', 'lock', () => { App.closeWindow('session'); execAsync('gtklock') }); + // const lockButton = SessionButton('Lock', 'lock', () => { App.closeWindow('session'); execAsync('gtklock') }); + const lockButton = SessionButton('Lock', 'lock', () => { App.closeWindow('session'); execAsync('swaylock') }); const logoutButton = SessionButton('Logout', 'logout', () => { App.closeWindow('session'); execAsync(['bash', '-c', 'loginctl terminate-user $USER']) }); const sleepButton = SessionButton('Sleep', 'sleep', () => { App.closeWindow('session'); execAsync('systemctl suspend') }); // hibernate, shutdown, reboot @@ -133,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 898a6a3fb..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'; @@ -8,7 +11,7 @@ import { setupCursorHover, setupCursorHoverInfo } from "../../../lib/cursorhover import { SystemMessage, ChatMessage } from "./chatgpt_chatmessage.js"; import { ConfigToggle, ConfigSegmentedSelection, ConfigGap } from '../../../lib/configwidgets.js'; import { markdownTest } from '../../../lib/md2pango.js'; -import { MarginRevealer } from '../../../lib/advancedrevealers.js'; +import { MarginRevealer } from '../../../lib/advancedwidgets.js'; export const chatGPTTabIcon = Box({ hpack: 'center', @@ -64,14 +67,14 @@ const chatGPTInfo = Box({ export const chatGPTSettings = MarginRevealer({ transition: 'slide_down', revealChild: true, - connections: [ - [ChatGPT, (self) => Utils.timeout(200, () => { - self._hide(self); - }), 'newMsg'], - [ChatGPT, (self) => Utils.timeout(200, () => { - self._show(self); - }), '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,46 +202,36 @@ 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)); }) + // Always scroll to bottom with new content + const adjustment = scrolledWindow.get_vadjustment(); + adjustment.connect("changed", () => { + adjustment.set_value(adjustment.get_upper() - adjustment.get_page_size()); + }) } }); +const CommandButton = (command) => Button({ + className: 'sidebar-chat-chip sidebar-chat-chip-action txt txt-small', + onClicked: () => sendMessage(command), + setup: setupCursorHover, + label: command, +}); + export const chatGPTCommands = Box({ className: 'spacing-h-5', children: [ Box({ hexpand: true }), - Button({ - className: 'sidebar-chat-chip sidebar-chat-chip-action txt txt-small', - onClicked: () => chatContent.add(SystemMessage( - `Key stored in:\n\`${ChatGPT.keyPath}\`\nTo update this key, type \`/key YOUR_API_KEY\``, - '/key', - chatGPTView)), - setup: setupCursorHover, - label: '/key', - }), - Button({ - className: 'sidebar-chat-chip sidebar-chat-chip-action txt txt-small', - onClicked: () => chatContent.add(SystemMessage( - `Currently using \`${ChatGPT.modelName}\``, - '/model', - chatGPTView - )), - setup: setupCursorHover, - label: '/model', - }), - Button({ - className: 'sidebar-chat-chip sidebar-chat-chip-action txt txt-small', - onClicked: () => clearChat(), - setup: setupCursorHover, - label: '/clear', - }), + CommandButton('/key'), + CommandButton('/model'), + CommandButton('/clear'), ] }); -export const chatGPTSendMessage = (text) => { +export const sendMessage = (text) => { // Check if text or API key is empty if (text.length == 0) return; if (ChatGPT.key.length == 0) { diff --git a/.config/ags/widgets/sideleft/apis/chatgpt_chatmessage.js b/.config/ags/widgets/sideleft/apis/chatgpt_chatmessage.js index 99faf5368..a8cb84e54 100644 --- a/.config/ags/widgets/sideleft/apis/chatgpt_chatmessage.js +++ b/.config/ags/widgets/sideleft/apis/chatgpt_chatmessage.js @@ -1,16 +1,17 @@ -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 { convert } from "../../../lib/md2pango.js"; +import md2pango from "../../../lib/md2pango.js"; import GtkSource from "gi://GtkSource?version=3.0"; const CUSTOM_SOURCEVIEW_SCHEME_PATH = `${App.configDir}/data/sourceviewtheme.xml`; const CUSTOM_SCHEME_ID = 'custom'; const USERNAME = GLib.get_user_name(); const CHATGPT_CURSOR = ' (o) '; -const MESSAGE_SCROLL_DELAY = 13; // In milliseconds, the time before an updated message scrolls to bottom /////////////////////// Custom source view colorscheme ///////////////////////// @@ -102,8 +103,8 @@ const CodeBlock = (content = '', lang = 'txt') => { ] }), onClicked: (self) => { - const copyContent = sourceView.get_buffer().get_text(0, 0, 0); // TODO: fix this - console.log(copyContent); + const buffer = sourceView.get_buffer(); + const copyContent = buffer.get_text(buffer.get_start_iter(), buffer.get_end_iter(), false); // TODO: fix this execAsync([`wl-copy`, `${copyContent}`]).catch(print); }, }), @@ -113,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: [ @@ -125,7 +126,11 @@ const CodeBlock = (content = '', lang = 'txt') => { Box({ className: 'sidebar-chat-codeblock-code', homogeneous: true, - children: [sourceView,], + children: [Scrollable({ + vscroll: 'never', + hscroll: 'automatic', + child: sourceView, + })], }) ] }) @@ -146,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++) { @@ -164,16 +169,15 @@ const MessageContent = (content) => { // Code blocks const codeBlockRegex = /^\s*```([a-zA-Z0-9]+)?\n?/; if (codeBlockRegex.test(line)) { - // console.log(`code at line ${index}`); const kids = self.get_children(); const lastLabel = kids[kids.length - 1]; const blockContent = lines.slice(lastProcessed, index).join('\n'); if (!inCode) { - lastLabel.label = convert(blockContent); + lastLabel.label = md2pango(blockContent); contentBox.add(CodeBlock('', codeBlockRegex.exec(line)[1])); } else { - lastLabel._updateText(blockContent); + lastLabel.attribute.updateText(blockContent); contentBox.add(TextBlock()); } @@ -186,7 +190,7 @@ const MessageContent = (content) => { const kids = self.get_children(); const lastLabel = kids[kids.length - 1]; const blockContent = lines.slice(lastProcessed, index).join('\n'); - lastLabel.label = convert(blockContent); + lastLabel.label = md2pango(blockContent); contentBox.add(Divider()); contentBox.add(TextBlock()); lastProcessed = index + 1; @@ -197,9 +201,9 @@ const MessageContent = (content) => { const lastLabel = kids[kids.length - 1]; let blockContent = lines.slice(lastProcessed, lines.length).join('\n'); if (!inCode) - lastLabel.label = `${convert(blockContent)}${useCursor ? CHATGPT_CURSOR : ''}`; + lastLabel.label = `${md2pango(blockContent)}${useCursor ? CHATGPT_CURSOR : ''}`; else - lastLabel._updateText(blockContent); + lastLabel.attribute.updateText(blockContent); } // Debug: plain text // contentBox.add(Label({ @@ -209,13 +213,13 @@ const MessageContent = (content) => { // xalign: 0, // wrap: true, // selectable: true, - // label: '------------------------------\n' + convert(content), + // label: '------------------------------\n' + md2pango(content), // })) contentBox.show_all(); - }] - ] + } + } }); - contentBox._fullUpdate(contentBox, content, false); + contentBox.attribute.fullUpdate(contentBox, content, false); return contentBox; } @@ -241,22 +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'); - Utils.timeout(MESSAGE_SCROLL_DELAY, () => { - if (!scrolledWindow) return; - var adjustment = scrolledWindow.get_vadjustment(); - adjustment.set_value(adjustment.get_upper() - adjustment.get_page_size()); - }); - }, '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') + , }) ] }); @@ -286,11 +285,6 @@ export const SystemMessage = (content, commandName, scrolledWindow) => { ], }) ], - setup: (self) => Utils.timeout(MESSAGE_SCROLL_DELAY, () => { - if (!scrolledWindow) return; - var adjustment = scrolledWindow.get_vadjustment(); - adjustment.set_value(adjustment.get_upper() - adjustment.get_page_size()); - }) }); return thisMessage; } diff --git a/.config/ags/widgets/sideleft/apis/waifu.js b/.config/ags/widgets/sideleft/apis/waifu.js index e4e7dd631..c77054dd6 100644 --- a/.config/ags/widgets/sideleft/apis/waifu.js +++ b/.config/ags/widgets/sideleft/apis/waifu.js @@ -1,11 +1,41 @@ -const { Gdk, 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, 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 { setupCursorHover, setupCursorHoverInfo } from "../../../lib/cursorhover.js"; +import { MarginRevealer } from '../../../lib/advancedwidgets.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 ${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); + return file.query_exists(null); +} + +const CommandButton = (command) => Button({ + className: 'sidebar-chat-chip sidebar-chat-chip-action txt txt-small', + onClicked: () => sendMessage(command), + setup: setupCursorHover, + label: command, +}); + export const waifuTabIcon = Box({ hpack: 'center', className: 'sidebar-chat-apiswitcher-icon', @@ -15,18 +45,204 @@ export const waifuTabIcon = Box({ ] }); +const WaifuImage = (taglist) => { + const ImageState = (icon, name) => Box({ + className: 'spacing-h-5 txt', + children: [ + Box({ hexpand: true }), + Label({ + className: 'sidebar-waifu-txt txt-smallie', + xalign: 0, + label: name, + }), + MaterialIcon(icon, 'norm'), + ] + }) + const ImageAction = ({ name, icon, action }) => Button({ + className: 'sidebar-waifu-image-action txt-norm icon-material', + tooltipText: name, + label: icon, + onClicked: action, + setup: setupCursorHover, + }) + const colorIndicator = Box({ + className: `sidebar-chat-indicator`, + }); + const downloadState = Stack({ + homogeneous: false, + transition: 'slide_up_down', + transitionDuration: 150, + items: [ + ['api', ImageState('api', 'Calling API')], + ['download', ImageState('downloading', 'Downloading image')], + ['done', ImageState('done', 'Finished!')], + ['error', ImageState('error', 'Error')], + ] + }); + const downloadIndicator = MarginRevealer({ + vpack: 'center', + transition: 'slide_left', + revealChild: true, + child: downloadState, + }); + const blockHeading = Box({ + hpack: 'fill', + className: 'sidebar-waifu-content spacing-h-5', + children: [ + ...taglist.map((tag) => CommandButton(tag)), + Box({ hexpand: true }), + downloadIndicator, + ] + }); + const blockImageActions = Revealer({ + transition: 'crossfade', + revealChild: false, + child: Box({ + vertical: true, + children: [ + Box({ + className: 'sidebar-waifu-image-actions spacing-h-3', + children: [ + Box({ hexpand: true }), + ImageAction({ + name: 'Go to source', + icon: 'link', + action: () => execAsync(['xdg-open', `${thisBlock.attribute.imageData.source}`]).catch(print), + }), + ImageAction({ + name: 'Hoard', + icon: 'save', + 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([IMAGE_VIEWER_APP, `${thisBlock.attribute.imagePath}`]).catch(print), + }), + ] + }) + ], + }) + }) + const blockImage = Widget.DrawingArea({ + className: 'sidebar-waifu-image', + }); + const blockImageRevealer = Revealer({ + transition: 'slide_down', + transitionDuration: 150, + revealChild: false, + child: Overlay({ + child: Box({ + homogeneous: true, + className: 'sidebar-waifu-image', + children: [blockImage], + }), + overlays: [blockImageActions], + }), + }); + const thisBlock = Box({ + className: 'sidebar-chat-message', + 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.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); + const widgetHeight = Math.ceil(widgetWidth * height / width); + blockImage.set_size_request(widgetWidth, widgetHeight); + const showImage = () => { + downloadState.shown = 'done'; + 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) => { + const borderRadius = widget.get_style_context().get_property('border-radius', Gtk.StateFlags.NORMAL); + + // Draw a rounded rectangle + cr.arc(borderRadius, borderRadius, borderRadius, Math.PI, 1.5 * Math.PI); + cr.arc(widgetWidth - borderRadius, borderRadius, borderRadius, 1.5 * Math.PI, 2 * Math.PI); + cr.arc(widgetWidth - borderRadius, widgetHeight - borderRadius, borderRadius, 0, 0.5 * Math.PI); + cr.arc(borderRadius, widgetHeight - borderRadius, borderRadius, 0.5 * Math.PI, Math.PI); + cr.closePath(); + cr.clip(); + + // Paint image as bg + Gdk.cairo_set_source_pixbuf(cr, pixbuf, 0, 0); + cr.paint(); + }); + + // Reveal stuff + Utils.timeout(IMAGE_REVEAL_DELAY, () => { + blockImageRevealer.revealChild = true; + }) + Utils.timeout(IMAGE_REVEAL_DELAY + blockImageRevealer.transitionDuration, + () => blockImageActions.revealChild = true + ); + downloadIndicator.attribute.hide(); + } + // Show + 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({ + vertical: true, + className: 'spacing-v-5', + children: [ + blockHeading, + Box({ + vertical: true, + hpack: 'start', + children: [blockImageRevealer], + }) + ] + }) + ], + }); + return thisBlock; +} + const waifuContent = Box({ className: 'spacing-v-15', vertical: true, - connections: [ - [WaifuService, (box, id) => { - const message = WaifuService.responses[id]; - if (!message) return; - box.add(Label({ - label: message, - })) - }, 'newResponse'], - ] + vexpand: true, + 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.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.attribute.map.get(id); + imageBlock.attribute.update(data); + }, 'updateResponse') + , }); export const waifuView = Scrollable({ @@ -48,25 +264,91 @@ export const waifuView = Scrollable({ const viewport = scrolledWindow.child; viewport.set_focus_vadjustment(new Gtk.Adjustment(undefined)); }) + // Always scroll to bottom with new content + const adjustment = scrolledWindow.get_vadjustment(); + adjustment.connect("changed", () => { + adjustment.set_value(adjustment.get_upper() - adjustment.get_page_size()); + }) } }); +const waifuTags = Revealer({ + revealChild: false, + transition: 'crossfade', + transitionDuration: 150, + child: Box({ + className: 'spacing-h-5', + children: [ + Scrollable({ + vscroll: 'never', + hscroll: 'automatic', + hexpand: true, + child: Box({ + className: 'spacing-h-5', + children: [ + CommandButton('waifu'), + CommandButton('maid'), + CommandButton('uniform'), + CommandButton('oppai'), + CommandButton('selfies'), + CommandButton('marin-kitagawa'), + CommandButton('raiden-shogun'), + CommandButton('mori-calliope'), + ] + }) + }), + Box({ className: 'separator-line' }), + ] + }) +}); + export const waifuCommands = Box({ className: 'spacing-h-5', - children: [ - Box({ hexpand: true }), - Button({ - className: 'sidebar-chat-chip sidebar-chat-chip-action txt txt-small', - onClicked: () => { - // command do something - }, + setup: (self) => { + self.pack_end(CommandButton('/clear'), false, false, 0); + self.pack_start(Button({ + className: 'sidebar-chat-chip-toggle', setup: setupCursorHover, - label: '/call', - }), - ] + label: 'Tags →', + onClicked: () => { + waifuTags.revealChild = !waifuTags.revealChild; + } + }), false, false, 0); + self.pack_start(waifuTags, true, true, 0); + } }); -export const waifuCallAPI = (text) => { +const clearChat = () => { + waifuContent.attribute.map.clear(); + const kids = waifuContent.get_children(); + for (let i = 0; i < kids.length; i++) { + const child = kids[i]; + if (child) child.destroy(); + } +} + +export const sendMessage = (text) => { // Do something on send - WaifuService.fetch(text); + // Commands + if (text.startsWith('/')) { + if (text.startsWith('/clear')) clearChat(); + else if (text.startsWith('/test')) { + const newImage = WaifuImage(['/test']); + waifuContent.add(newImage); + 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', + extension: '', + signature: 0, + source: 'https://picsum.photos/400/600', + dominant_color: '#9392A6', + is_nsfw: false, + width: 300, + height: 200, + tags: ['/test'], + }, true)); + } + } + else WaifuService.fetch(text); } \ No newline at end of file diff --git a/.config/ags/widgets/sideleft/apiwidgets.js b/.config/ags/widgets/sideleft/apiwidgets.js index 573b65dab..475bd496f 100644 --- a/.config/ags/widgets/sideleft/apiwidgets.js +++ b/.config/ags/widgets/sideleft/apiwidgets.js @@ -1,12 +1,13 @@ -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"; // APIs import ChatGPT from '../../services/chatgpt.js'; -import { chatGPTView, chatGPTCommands, chatGPTSendMessage, chatGPTTabIcon } from './apis/chatgpt.js'; -import { waifuView, waifuCommands, waifuCallAPI, waifuTabIcon } from './apis/waifu.js'; +import { chatGPTView, chatGPTCommands, sendMessage as chatGPTSendMessage, chatGPTTabIcon } from './apis/chatgpt.js'; +import { waifuView, waifuCommands, sendMessage as waifuSendMessage, waifuTabIcon } from './apis/waifu.js'; const APIS = [ { @@ -19,7 +20,7 @@ const APIS = [ }, { name: 'Waifus', - sendCommand: waifuCallAPI, + sendCommand: waifuSendMessage, contentWidget: waifuView, commandBar: waifuCommands, tabIcon: waifuTabIcon, @@ -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 a335eb276..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,26 +161,27 @@ 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); else if (event.get_keyval()[1] === Gdk.KEY_Page_Up) - switchToTab(Math.max(currentTabId - 1), 0); + switchToTab(Math.max(currentTabId - 1, 0)); else if (event.get_keyval()[1] === Gdk.KEY_Page_Down) - switchToTab(Math.min(currentTabId + 1), contents.length); + switchToTab(Math.min(currentTabId + 1, contents.length - 1)); } if (contentStack.shown == 'apis') { // If api tab is focused // Automatically focus entry when typing @@ -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 6f5b1240d..a4c4b7ca0 100644 --- a/.config/ags/widgets/sideright/notificationlist.js +++ b/.config/ags/widgets/sideright/notificationlist.js @@ -1,113 +1,137 @@ -// 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, Icon, Scrollable, Label, Button, Revealer } = Widget; +const { Box, Button, Label, Scrollable, Stack } = Widget; import { MaterialIcon } from "../../lib/materialicon.js"; import { setupCursorHover } from "../../lib/cursorhover.js"; import Notification from "../../lib/notification.js"; -const NotificationList = Box({ - vertical: true, - vpack: 'start', - className: 'spacing-v-5-revealer', - connections: [ - [Notifications, (box, id) => { - if (box.children.length == 0) { - Notifications.notifications - .forEach(n => { - box.pack_end(Notification({ - notifObject: n, - isPopup: false, - }), false, false, 0) - }); - box.show_all(); - } - else if (id) { +export default (props) => { + const notifEmptyContent = Box({ + homogeneous: true, + children: [Box({ + vertical: true, + vpack: 'center', + className: 'txt spacing-v-10', + children: [ + Box({ + vertical: true, + className: 'spacing-v-5', + children: [ + MaterialIcon('notifications_active', 'badonkers'), + Label({ label: 'No notifications', className: 'txt-small' }), + ] + }), + ] + })] + }); + const notificationList = Box({ + vertical: true, + vpack: 'start', + className: 'spacing-v-5-revealer', + 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 => { + box.pack_end(Notification({ + notifObject: n, + isPopup: false, + }), false, false, 0) + }); + box.show_all(); + return; + } + // 2nd or later notif const notif = Notifications.getNotification(id); - const NewNotif = Notification({ notifObject: notif, isPopup: false, }); - if (NewNotif) { box.pack_end(NewNotif, false, false, 0); box.show_all(); } - } - }, 'notified'], - - [Notifications, (box, id) => { - if (!id) return; - for (const ch of box.children) { - if (ch._id === id) { - ch._destroyWithAnims(); + }, 'notified') + .hook(Notifications, (box, id) => { + if (!id) return; + for (const ch of box.children) { + if (ch._id === id) { + ch.attribute.destroyWithAnims(); + } } - } - }, 'closed'], - - [Notifications, box => box.visible = Notifications.notifications.length > 0], - ], -}); - -export default (props) => { - const listTitle = Revealer({ - revealChild: false, - connections: [[Notifications, (revealer) => { - revealer.revealChild = (Notifications.notifications.length > 0); - }]], + }, 'closed') + , + }); + const ListActionButton = (icon, name, action) => Button({ + className: 'notif-listaction-btn', + onClicked: action, child: Box({ - vpack: 'start', - className: 'sidebar-group-invisible txt', + className: 'spacing-h-5', children: [ + MaterialIcon(icon, 'norm'), Label({ - hexpand: true, - xalign: 0, - className: 'txt-title-small', - label: 'Notifications', - }), - Button({ - className: 'notif-closeall-btn', - onClicked: () => { - Notifications.clear(); - }, - child: Box({ - className: 'spacing-h-5', - children: [ - MaterialIcon('clear_all', 'norm'), - Label({ - className: 'txt-small', - label: 'Clear', - }) - ] - }), - setup: button => { - setupCursorHover(button); - }, + className: 'txt-small', + label: name, }) ] - }) + }), + setup: setupCursorHover, }); - const listContents = Scrollable({ + const silenceButton = ListActionButton('notifications_paused', 'Silence', (self) => { + Notifications.dnd = !Notifications.dnd; + self.toggleClassName('notif-listaction-btn-enabled', Notifications.dnd); + }); + const clearButton = ListActionButton('clear_all', 'Clear', () => { + notificationList.get_children().forEach(ch => ch.destroy()); + Notifications.clear(); + }); + const listTitle = Box({ + vpack: 'start', + className: 'sidebar-group-invisible txt spacing-h-5', + children: [ + Label({ + hexpand: true, + xalign: 0, + 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', + }), + silenceButton, + clearButton, + ] + }); + const notifList = Scrollable({ hexpand: true, hscroll: 'never', vscroll: 'automatic', child: Box({ vexpand: true, - children: [NotificationList], - }) + // homogeneous: true, + children: [notificationList], + }), + setup: (self) => { + const vScrollbar = self.get_vscrollbar(); + vScrollbar.get_style_context().add_class('sidebar-scrollbar'); + } + }); + const listContents = Stack({ + transition: 'crossfade', + transitionDuration: 150, + items: [ + ['empty', notifEmptyContent], + ['list', notifList] + ], + setup: (self) => self + .hook(Notifications, (self) => self.shown = (Notifications.notifications.length > 0 ? 'list' : 'empty')) + , }); - listContents.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC); - const vScrollbar = listContents.get_vscrollbar(); - vScrollbar.get_style_context().add_class('sidebar-scrollbar'); return Box({ ...props, - className: 'sidebar-group-invisible spacing-v-5', + className: 'sidebar-group spacing-v-5', vertical: true, children: [ listTitle, diff --git a/.config/ags/widgets/sideright/quicktoggles.js b/.config/ags/widgets/sideright/quicktoggles.js index 263fcb52f..6deae3fb0 100644 --- a/.config/ags/widgets/sideright/quicktoggles.js +++ b/.config/ags/widgets/sideright/quicktoggles.js @@ -1,28 +1,40 @@ -import { Widget, Utils, Service } from '../../imports.js'; +const { GLib } = imports.gi; +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'; const { execAsync, exec } = Utils; import { BluetoothIndicator, NetworkIndicator } from "../../lib/statusicons.js"; import { setupCursorHover } from "../../lib/cursorhover.js"; import { MaterialIcon } from '../../lib/materialicon.js'; +function expandTilde(path) { + if (path.startsWith('~')) { + console.log(GLib.get_home_dir() + path.slice(1)); + return GLib.get_home_dir() + path.slice(1); + } else { + return 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 => { - button.toggleClassName('sidebar-button-active', Network.wifi?.internet == 'connected' || Network.wired?.internet == 'connected') - }], - [Network, button => { + setup: (self) => { + setupCursorHover(self); + self.hook(Network, button => { + button.toggleClassName('sidebar-button-active', [Network.wifi?.internet, Network.wired?.internet].includes('connected')) button.tooltipText = (`${Network.wifi?.ssid} | Right-click to configure` || 'Unknown'); - }], - ], - setup: setupCursorHover, + }); + }, ...props, }); @@ -31,21 +43,22 @@ export const ToggleIconBluetooth = (props = {}) => Widget.Button({ tooltipText: 'Bluetooth | Right-click to configure', onClicked: () => { const status = Bluetooth?.enabled; - if (status) + if (status) exec('rfkill block bluetooth'); - else + else exec('rfkill unblock bluetooth'); }, onSecondaryClickRelease: () => { execAsync(['bash', '-c', 'blueberry &']); + 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, }); @@ -69,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, }); @@ -95,15 +108,22 @@ export const ModuleInvertColors = (props = {}) => Widget.Button({ className: 'txt-small sidebar-iconbutton', tooltipText: 'Color inversion', onClicked: (button) => { - const shaderPath = JSON.parse(exec('hyprctl -j getoption decoration:screen_shader')).str; - if (shaderPath != "[[EMPTY]]" && shaderPath != "") { - execAsync(['bash', '-c', `hyprctl keyword decoration:screen_shader ''`]).catch(print); - button.toggleClassName('sidebar-button-active', false); - } - else { - execAsync(['bash', '-c', `hyprctl keyword decoration:screen_shader ~/.config/hypr/shaders/invert.frag`]).catch(print); - button.toggleClassName('sidebar-button-active', true); - } + // const shaderPath = JSON.parse(exec('hyprctl -j getoption decoration:screen_shader')).str; + Hyprland.sendMessage('j/getoption decoration:screen_shader') + .then((output) => { + const shaderPath = JSON.parse(output)["str"].trim(); + console.log(output) + console.log(shaderPath) + if (shaderPath != "[[EMPTY]]" && shaderPath != "") { + execAsync(['bash', '-c', `hyprctl keyword decoration:screen_shader '[[EMPTY]]'`]).catch(print); + button.toggleClassName('sidebar-button-active', false); + } + else { + Hyprland.sendMessage(`j/keyword decoration:screen_shader ${expandTilde('~/.config/hypr/shaders/invert.frag')}`) + .catch(print); + button.toggleClassName('sidebar-button-active', true); + } + }) }, child: MaterialIcon('invert_colors', 'norm'), setup: setupCursorHover, @@ -111,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), @@ -129,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'); }