From 9d44a0ef14d5018d101c4a92420603cda7e922d3 Mon Sep 17 00:00:00 2001 From: gnat Date: Sat, 12 Oct 2024 00:46:39 -0700 Subject: [PATCH] begin astal rewrite in lua; implement workspace widget in statusbar --- config.js | 64 ---- icons/expansion-card.svg | 1 - icons/fan.svg | 1 - icons/memory-solid.svg | 1 - icons/microchip-solid.svg | 1 - icons/thermometer.svg | 1 - init.lua | 17 + lua/globals.lua | 15 + lua/lib/init.lua | 23 ++ lua/widgets/bar/init.lua | 9 + lua/widgets/bar/workspaces.lua | 48 +++ services/brightness.js | 44 --- services/mpd.js | 361 ---------------------- style/components/bar-control-center.scss | 68 ---- style/components/bar.scss | 75 ----- style/components/launcher.scss | 43 --- style/components/lock.scss | 28 -- style/components/notification-popups.scss | 98 ------ style/components/top-bar.scss | 126 -------- style/css | 212 ------------- style/mixins.scss | 27 -- style/style.css | 335 +------------------- style/style.scss | 19 +- style/widgets/bar.scss | 26 ++ utils/PopupWindow.js | 29 -- widgets/battery.js | 38 --- widgets/brightness.js | 63 ---- widgets/clock.js | 62 ---- widgets/hypractive.js | 10 - widgets/hyprworkspaces.js | 59 ---- widgets/marqueeLabel.js | 87 ------ widgets/mpd.js | 182 ----------- widgets/mpris.js | 114 ------- widgets/resourceDial.js | 24 -- widgets/systray.js | 14 - widgets/volume.js | 70 ----- windows/bar.js | 141 --------- windows/launcher.js | 93 ------ windows/lock.js | 76 ----- windows/menu.js | 49 --- windows/notifications.js | 185 ----------- windows/top-bar.js | 70 ----- 42 files changed, 161 insertions(+), 2848 deletions(-) delete mode 100644 config.js delete mode 100644 icons/expansion-card.svg delete mode 100644 icons/fan.svg delete mode 100644 icons/memory-solid.svg delete mode 100644 icons/microchip-solid.svg delete mode 100644 icons/thermometer.svg create mode 100644 init.lua create mode 100644 lua/globals.lua create mode 100644 lua/lib/init.lua create mode 100644 lua/widgets/bar/init.lua create mode 100644 lua/widgets/bar/workspaces.lua delete mode 100644 services/brightness.js delete mode 100644 services/mpd.js delete mode 100644 style/components/bar-control-center.scss delete mode 100644 style/components/bar.scss delete mode 100644 style/components/launcher.scss delete mode 100644 style/components/lock.scss delete mode 100644 style/components/notification-popups.scss delete mode 100644 style/components/top-bar.scss delete mode 100644 style/css delete mode 100644 style/mixins.scss create mode 100644 style/widgets/bar.scss delete mode 100644 utils/PopupWindow.js delete mode 100644 widgets/battery.js delete mode 100644 widgets/brightness.js delete mode 100644 widgets/clock.js delete mode 100644 widgets/hypractive.js delete mode 100644 widgets/hyprworkspaces.js delete mode 100644 widgets/marqueeLabel.js delete mode 100644 widgets/mpd.js delete mode 100644 widgets/mpris.js delete mode 100644 widgets/resourceDial.js delete mode 100644 widgets/systray.js delete mode 100644 widgets/volume.js delete mode 100644 windows/bar.js delete mode 100644 windows/launcher.js delete mode 100644 windows/lock.js delete mode 100644 windows/menu.js delete mode 100644 windows/notifications.js delete mode 100644 windows/top-bar.js diff --git a/config.js b/config.js deleted file mode 100644 index 67a415f..0000000 --- a/config.js +++ /dev/null @@ -1,64 +0,0 @@ -const { execAsync } = Utils - -// import { reveal_menu, reveal_launcher, Bar, FakeBar } from './windows/bar.js' -import { Bar, FakeBar } from './windows/top-bar.js' -import { NotificationPopups } from './windows/notifications.js' -import { Lock, show_lock } from './windows/lock.js' - -execAsync('mpDris2') - -Utils.monitorFile( - `./style/style.scss`, - - function() { - const scss = `./style/style.scss` - - const css = `./style/style.css` - - Utils.exec(`sassc ${scss} ${css}`) - App.resetCss() - App.applyCss(css) - }, -) - -App.addIcons('/usr/share/icons/Papirus/symbolic/status') - -App.config({ - windows: [ - Lock, - FakeBar, - Bar, - NotificationPopups, - ], - style: './style/style.css', - icons: './icons' -}) - -Object.defineProperty(globalThis, "lock", { - get() { - show_lock.value = true - } -}) - - - -/* -Object.defineProperty(globalThis, "swipeRight", { - get() { - if (reveal_menu.value) { - reveal_launcher.value = true - } else { - reveal_menu.value = true - } - } -}) - -Object.defineProperty(globalThis, "swipeLeft", { - get() { - if (reveal_launcher.value) { - reveal_launcher.value = false - } else { - reveal_menu.value = false - } - } -})*/ diff --git a/icons/expansion-card.svg b/icons/expansion-card.svg deleted file mode 100644 index 8b1ca84..0000000 --- a/icons/expansion-card.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/icons/fan.svg b/icons/fan.svg deleted file mode 100644 index 5e07b31..0000000 --- a/icons/fan.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/icons/memory-solid.svg b/icons/memory-solid.svg deleted file mode 100644 index f7160d7..0000000 --- a/icons/memory-solid.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/icons/microchip-solid.svg b/icons/microchip-solid.svg deleted file mode 100644 index 5e4b242..0000000 --- a/icons/microchip-solid.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/icons/thermometer.svg b/icons/thermometer.svg deleted file mode 100644 index c9a5f5a..0000000 --- a/icons/thermometer.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/init.lua b/init.lua new file mode 100644 index 0000000..7e30fb8 --- /dev/null +++ b/init.lua @@ -0,0 +1,17 @@ +require("lua.globals") + +local bar = require('lua.widgets.bar') + +local App = astal.App + +local scss = "./style/style.scss" +local css = "./style/style.css" + +astal.exec(string.format("sassc %s %s", scss, css)) + +App:start({ + css = css, + main = function() + bar:show_all() + end, +}) diff --git a/lua/globals.lua b/lua/globals.lua new file mode 100644 index 0000000..7211a72 --- /dev/null +++ b/lua/globals.lua @@ -0,0 +1,15 @@ +lgi = require('lgi') + +astal = require("astal") + +GLib = astal.GLib +Gtk = astal.Gtk +Gdk = astal.Gdk +Gio = astal.Gio + +Astal = astal.Astal +Widget = astal.Widget + +bind = astal.bind + +Variable = astal.Variable diff --git a/lua/lib/init.lua b/lua/lib/init.lua new file mode 100644 index 0000000..1626c8f --- /dev/null +++ b/lua/lib/init.lua @@ -0,0 +1,23 @@ +local M = {} + +function M.map(tbl, f) + local t = {} + for k,v in pairs(tbl) do + t[k] = f(v) + end + return t +end + +function M.sequence(start, stop) + local t = {} + for i=start,stop do + table.insert(t, i) + end + return t +end + +function ternary(cond, t, f) + if cond then return t else return f end +end + +return M diff --git a/lua/widgets/bar/init.lua b/lua/widgets/bar/init.lua new file mode 100644 index 0000000..612c9dc --- /dev/null +++ b/lua/widgets/bar/init.lua @@ -0,0 +1,9 @@ +local workspaces = require(... .. '.workspaces') + +return Astal.Window({ + namespace = "bar", + name = "bar", + anchor = Astal.WindowAnchor.TOP + Astal.WindowAnchor.LEFT + Astal.WindowAnchor.RIGHT, + exclusivity = "EXCLUSIVE", + child = workspaces, +}) diff --git a/lua/widgets/bar/workspaces.lua b/lua/widgets/bar/workspaces.lua new file mode 100644 index 0000000..c181db7 --- /dev/null +++ b/lua/widgets/bar/workspaces.lua @@ -0,0 +1,48 @@ +local Hyprland = astal.require("AstalHyprland") +local map, sequence = require('lua.lib').map, require('lua.lib').sequence + +local hypr = Hyprland.get_default() + +local map, sequence = require('lua.lib').map, require('lua.lib').sequence + +local hypr = Hyprland.get_default() + +local function workspace_row(start, stop) + return Widget.Box({ + children = map(sequence(start, stop), function(i) + return Widget.Button({ + setup = function(self) + self:hook(hypr, 'notify::focused-workspace', function(self, workspace) + self:toggle_class_name('focused', workspace:get_id() == i) + end) + self:hook(hypr, 'notify::workspaces', function(self, workspaces) + map(workspaces, function(workspace) + if workspace:get_id() == i then + -- ick + local count = 0 + for _ in ipairs(workspace:get_clients()) do + count = count + 1 + end + self:toggle_class_name('occupied', workspace:get_id() == i and count > 0) + end + end) + end) + end, + on_click_release = function() + hypr:message_async(string.format("dispatch workspace %d", i)) + end + }) + end) + }) +end + +return Widget.Box({ + class_name = 'workspaces', + vertical = true, + hexpand = false, + halign = 'START', + children = { + workspace_row(1, 5), + workspace_row(6, 10), + } +}) diff --git a/services/brightness.js b/services/brightness.js deleted file mode 100644 index 09e5057..0000000 --- a/services/brightness.js +++ /dev/null @@ -1,44 +0,0 @@ -class Brightness extends Service { - static { - Service.register( - this, - {}, - { - screen: ["float", "rw"], - }, - ); - } - - _screen = 0; - - get screen() { - return this._screen; - } - - set screen(percent) { - if (percent < 0) percent = 0; - - if (percent > 1) percent = 1; - - Utils.execAsync(`brightnessctl s ${percent * 100}% -q`) - .then(() => { - this._screen = percent; - this.changed("screen"); - }) - .catch(console.error); - } - - constructor() { - super(); - try { - this._screen = - Number(Utils.exec("brightnessctl g")) / - Number(Utils.exec("brightnessctl m")); - } catch (error) { - console.error("missing dependancy: brightnessctl"); - } - } -} - -const service = new Brightness(); -export default service; diff --git a/services/mpd.js b/services/mpd.js deleted file mode 100644 index 30c3da9..0000000 --- a/services/mpd.js +++ /dev/null @@ -1,361 +0,0 @@ -import Gio from "gi://Gio"; - -Gio._promisify(Gio.DataInputStream.prototype, "read_line_async"); - -class Mpd extends Service { - static { - Service.register( - this, - {}, - { - //TODO: parse some properties like duration into number? - partition: ["string", "r"], - volume: ["string", "r"], - repeat: ["string", "r"], - random: ["string", "r"], - single: ["string", "r"], - consume: ["string", "r"], - playlist: ["string", "r"], - playlistlength: ["string", "r"], - state: ["string", "r"], - song: ["string", "r"], - songid: ["string", "r"], - nextsong: ["string", "r"], - nextsongid: ["string", "r"], - elapsed: ["string", "r"], - duration: ["string", "r"], - bitrate: ["string", "r"], - mixrampdb: ["string", "r"], - audio: ["string", "r"], - - file: ["string", "r"], - "Last-Modified": ["string", "r"], - Artist: ["string", "r"], - Title: ["string", "r"], - Album: ["string", "r"], - Pos: ["string", "r"], - Id: ["string", "r"], - }, - ); - } - - #socket; - - #inputStream; - #outputStream; - - _decoder = new TextDecoder(); - _encoder = new TextEncoder(); - _messageHandlerQueue = []; - - //TODO: more properties? - - // Status - _partition; - _volume; - _repeat; - _random; - _single; - _consume; - _playlist; - _playlistlength; - _state; - _song; - _songid; - _nextsong; - _nextsongid; - _elapsed; - _duration; - _bitrate; - _mixrampdb; - _audio; - - _file; - _LastModified; - _Artist; - _Title; - _Album; - _Pos; - _Id; - - get partition() { - return this._partition; - } - - get volume() { - return this._volume; - } - - get repeat() { - return this._repeat; - } - - get random() { - return this._random; - } - - get single() { - return this._single; - } - - get consume() { - return this._consume; - } - - get playlist() { - return this._playlist; - } - - get playlistlength() { - return this._playlistlength; - } - - get state() { - return this._state; - } - - get song() { - return this._song; - } - - get songid() { - return this._songid; - } - - get nextsong() { - return this._nextsong; - } - - get nextsongid() { - return this._nextsongid; - } - - get elapsed() { - return this._elapsed; - } - - get duration() { - return this._duration; - } - - get bitrate() { - return this._bitrate; - } - - get mixrampdb() { - return this._mixrampdb; - } - - get audio() { - return this._audio; - } - - get file() { - return this._file; - } - - get Last_Modified() { - return this._LastModified; - } - - get Artist() { - return this._Artist; - } - - get Title() { - return this._Title; - } - - get Album() { - return this._Album; - } - - get Pos() { - return this._Pos; - } - - get Id() { - return this._Id; - } - - constructor() { - super(); - this._initSocket(); - } - - async _initSocket() { - try { - this.#socket = new Gio.SocketClient().connect_to_host( - "localhost", - 6600, - null, - ); - - this.#inputStream = new Gio.DataInputStream({ - base_stream: this.#socket.get_input_stream(), - }); - - this.#outputStream = new Gio.DataOutputStream({ - base_stream: this.#socket.get_output_stream(), - }); - - this._watchSocket(); - - //init properties - //[TODO): init more properties? - - this.send("status") - .then(this._updateProperties.bind(this)) - .catch(logError); - this.send("currentsong") - .then(this._updateProperties.bind(this)) - .catch(logError); - } catch (e) { - logError(e); - } - } - - async _watchSocket() { - let bufferedLines = []; - while (true) { - const [rawData] = await this.#inputStream.read_line_async(0, null); - const data = this._decoder.decode(rawData); - if (data == null) continue; - bufferedLines.push(data); - const { response, remain } = this._parseResponse(bufferedLines); - bufferedLines = remain; - - if (!response) continue; - switch (response.type) { - case "version": - console.log(`MPD Server Version ${response.payload}`); - break; - case "error": - this._handleMessage(new Error(response.payload), null); - break; - case "data": - this._handleMessage(null, response.payload); - break; - } - } - } - - _parseResponse(lines) { - let response; - let beginLine = 0; - - for (let i = 0; i < lines.length; i++) { - const line = lines[i]; - - const version = line.match(/^OK MPD (.+)/); - const error = line.match(/^ACK \[.*] {.*} (.+)/); - - if (version) { - response = { type: "version", payload: version[1] }; - beginLine = i + 1; - } else if (error) { - response = { type: "error", payload: error[1] }; - beginLine = i + 1; - } else if (line === "OK") { - response = { - type: "data", - payload: lines.slice(beginLine, i).join("\n"), - }; - beginLine = i + 1; - } - } - return { response, remain: lines.slice(beginLine) }; - } - - _handleMessage(err, msg) { - const { func } = this._messageHandlerQueue.shift(); - func(err, msg); - if (this._messageHandlerQueue.length === 0) { - this._idle(); - } - } - - async send(data) { - data = data.trim(); - const isIdle = data === "idle"; - - if (this._messageHandlerQueue[0]?.isIdle) { - this.#outputStream.write(this._encoder.encode("noidle\n"), null); - } - this.#outputStream.write(this._encoder.encode(`${data}\n`), null); - - return new Promise((resolve, reject) => { - this._messageHandlerQueue.push({ - isIdle, - func: (err, msg) => { - if (err != null) reject(err); - resolve(msg); - }, - }); - }); - } - - _idle() { - this.send("idle") - .then((msg) => { - for (const line of msg.split("\n")) { - const subsystem = /changed: (\w+)/.exec(line); - if (subsystem == null) continue; - - //TODO: only update those things that could have - //changed using a switch over the subsystems - this.send("status") - .then(this._updateProperties.bind(this)) - .catch(logError); - this.send("currentsong") - .then(this._updateProperties.bind(this)) - .catch(logError); - /* - switch(subsystem[1]) { - case "player": - break; - }*/ - } - }) - .catch(logError); - } - - _updateProperties(msg) { - for (const line of msg.split("\n")) { - const keyValue = line.match(/(.*): (.*)/); - if (keyValue == null) continue; - const deprecatedKeys = [ - "time", - "Time", //deprecated - "Format", //same as audio - ]; - if (deprecatedKeys.includes(keyValue[1])) continue; - if (!this.hasOwnProperty(`_${keyValue[1]}`)) continue; - this.updateProperty(keyValue[1], keyValue[2]); - this.emit("changed"); - } - } - - setCrossfade = (seconds) => this.send(`crossfade ${seconds}`); - setVolume = (volume) => this.send(`setvol ${volume}`); - - toggleShuffle = () => this.send(`random ${+this._random ? "0" : "1"}`); - toggleRepeat = () => this.send(`repeat ${+this._repeat ? "0" : "1"}`); - - next = () => this.send("next"); - playPause = () => this.send(`pause ${this._state === "pause" ? "0" : "1"}`); - pause = () => this.send("pause 1"); - play = () => this.send("pause 0"); - playSong = (songpos) => this.send(`play ${songpos}`); - playSongId = (songid) => this.send(`playid ${songid}`); - seekSong = (songpos, time) => this.send(`seek ${songpos} ${time}`); - seekSongId = (songid, time) => this.send(`seekid ${songid} ${time}`); - seekCur = (time) => this.send(`seekcur ${time}`); - previous = () => this.send("previous"); - stop = () => this.send("stop"); - - clearQueue = () => this.send("clear"); -} - -const service = new Mpd; -export default service; diff --git a/style/components/bar-control-center.scss b/style/components/bar-control-center.scss deleted file mode 100644 index 5d7dde3..0000000 --- a/style/components/bar-control-center.scss +++ /dev/null @@ -1,68 +0,0 @@ -#status-bar .Menu { - background-color: $bg-alt-1; - min-width: 640px; - - .mpd-controls { - background-color: $bg; - border-radius: 10px; - margin: 10px; - - .button { - font-size: 24px; - padding: 10px; - margin: 10px; - background-color: $bg-alt-1; - border-color: $bg-alt-1; - border-radius: 10px; - } - - .cover { - min-width: 250px; - min-height: 250px; - border-radius: 10px; - margin: 10px; - background: $bg; - background-size: cover; - } - - .title { - padding-top: 10px; - font-size: 20px; - font-weight: bold; - } - - .position { - margin: 10px; - margin-right: 20px; - min-height: 10px; - border-radius: 5px; - - trough { - background: $bg-alt-1; - border-radius: 5px; - min-height: 10px; - } - - slider { - min-height: 10px; - border-radius: 5px; - background: $mpd-progress-primary; - } - } - - .position-label { - margin-top: 75px; - } - } - - .dial-parent { - @include panel-dial($resource-dial-fg-cpu, $bg); - border-radius: 10px; - - - .dial-icon { - color: $fg; - } - } -} - diff --git a/style/components/bar.scss b/style/components/bar.scss deleted file mode 100644 index de73da7..0000000 --- a/style/components/bar.scss +++ /dev/null @@ -1,75 +0,0 @@ -* :not(selection) :not(tooltip) { - all: unset; -} - -#status-bar { - background-color: $bg; - - border-radius: 0 10px 10px 0; - - .dial-container { - margin-top: 10px; - - .battery-dial { - @include bar-dial($battery-dial-bg, $battery-dial-fg) - } - - .volume-dial { - @include bar-dial($volume-dial-bg, $volume-dial-fg) - } - - .brightness-dial { - @include bar-dial($brightness-dial-bg, $brightness-dial-fg) - } - } - - .workspace-container { - background-color: $bg-alt-1; - border-radius: 10px; - padding: 6px 0px; - margin: 0px 12px; - border: none; - - .ws-norm { - min-width: 15px; - border-radius: 10px; - margin: 2px 5px; - padding: 6px 10px; - background-color: $ws-inactive; - color: $fg; - } - - .ws-active { - color: $bg; - background-color: $ws-active; - } - } - - .menu-visibility-button { - border-radius: 0px 10px 10px 0px; - padding: 10px 0px 10px 2px; - background-color: $bg-alt-1 - } - - .clock { - background-color: $bg-alt-1; - margin: 8px; - margin-bottom: 10px; - padding: 6px 2px; - border-radius: 10px; - } - - .mpd-controls { - .button { - font-size: 14px; - margin: 2px; - margin-bottom: 8px; - font-family: 'Symbols Nerd Font Mono'; - - &:hover { - color: $button-hover-color; - } - } - } -} - diff --git a/style/components/launcher.scss b/style/components/launcher.scss deleted file mode 100644 index 5b93533..0000000 --- a/style/components/launcher.scss +++ /dev/null @@ -1,43 +0,0 @@ -.launcher { - min-width: 640px; - background: $bg-alt-1; - - .search { - > image { - margin-left: 10px; - } - - > entry { - padding: 5px; - margin: 10px; - background: $bg; - border: 5px solid $bg; - border-radius: 10px; - font-size: 32px; - } - } - - .entry { - margin: 0 10px 0 10px; - border: 10px solid $bg; - border-radius: 10px; - background: $bg; - - > box { - > image { - padding: 5px; - margin: 5px 10px 5px 10px; - background: $bg-alt-1; - border-radius: 5px; - } - - > label { - - } - } - } - - > scrolledwindow > * > box:last-child { - margin-bottom: 10px; - } -} diff --git a/style/components/lock.scss b/style/components/lock.scss deleted file mode 100644 index 14003cb..0000000 --- a/style/components/lock.scss +++ /dev/null @@ -1,28 +0,0 @@ -.lock-ready > box{ - box { - background: $bg; - padding: 20px; - border: 10px solid $hl-alt-1; - min-width: 300px; - margin: 15px; - } - - .img { - background: url('/home/catalie/.config/wallpaper'); - min-width: 300px; - min-height: 300px; - background-position: 25% 12.5%; - background-size: cover; - } - - box > entry { - background: $bg-alt-1; - font-size: 14px; - padding: 5px; - margin: 10px; - } -} - -.lock { - background: transparent; -} diff --git a/style/components/notification-popups.scss b/style/components/notification-popups.scss deleted file mode 100644 index 6d3c4ea..0000000 --- a/style/components/notification-popups.scss +++ /dev/null @@ -1,98 +0,0 @@ -#notifications { - background: transparent; -} - -.notifications { - opacity: 1; - min-width: 24rem; - .revealer { - + .revealer { - >*>box { - margin-top: 0; - } - } - - .notification { - margin-bottom: 25px; - min-width: 24rem; - padding: 0px; - border: 1px solid $fg; - border-right: none; - background: $bg; - } - - .urgency-indicator { - min-width: 15px; - margin-bottom: 25px; - - &.normal, &.low { - background: $hl-alt-2; - border: 1px solid $hl-alt-2; - } - - &.urgent { - background: $hl; - border: 1px solid $hl - } - } - - .body { - margin-right: 1em; - } - - .timeout-bar { - background: $bg-alt-1; - - > trough > progress { - background-image: none; - background-color: $hl-alt-1; - } - } - - .button { - font-size: 20px; - margin-left: 5px; - margin-right: 5px; - - &:hover { - color: $hl; - } - } - - .icon { - min-width: 68px; - min-height: 68px; - margin: 5px; - } - - .icon image { - font-size: 58px; - margin: 5px; - color: $fg; - } - - .icon box { - min-width: 68px; - min-height: 68px; - } - - .title { - font-size: 28px; - padding-right: 5px; - } - - .actions .action-button { - margin: 0 .4em; - margin-top: .8em; - border: 2px solid $fg; - } - - .actions .action-button:first-child { - margin-left: .5em; - } - - .actions .action-button:last-child { - margin-right: .5em; - } - } -} diff --git a/style/components/top-bar.scss b/style/components/top-bar.scss deleted file mode 100644 index e8b6c5d..0000000 --- a/style/components/top-bar.scss +++ /dev/null @@ -1,126 +0,0 @@ -$height: 50px; - -#status-bar { - background: transparent; - - .workspaces { - min-height: $height; - background: $bg; - padding: 5px; - padding-top: 15px; - - .workspace { - min-width: 10px; - min-height: 10px; - margin: 5px; - background-color: $bg-alt-1; - } - - .occupied { - background-color: $bg-alt-2; - } - - .focused { - background-color: $hl; - } - } - - .media-controls { - margin-top: 20px; - min-width: 220px; - - .button { - font-size: 20px; - } - } - - .progress-bar { - margin-top: 20px; - min-width: 200px; - min-height: 2px; - background: transparent; - - trough { - min-height: 2px; - background: $bg-alt-1; - } - - highlight { - min-height: 2px; - background: $mpd-progress-primary; - } - } - - .right { - min-height: $height; - background: $bg; - - - .battery-container { - padding-left: 10px; - padding-right: 10px; - .battery-dial { - @include bar-dial($battery-dial-bg, $battery-dial-fg); - } - } - - .sliderbox { - margin: 5px; - .volume { - .slider { - trough { - min-height: 10px; - min-width: 120px; - background: $bg-alt-1; - } - - highlight { - background: $hl-alt-1; - } - } - - button { - font-size: 20px; - margin: 5px; - } - } - - .brightness { - .slider { - trough { - min-height: 10px; - min-width: 120px; - background: $bg-alt-1; - } - - highlight { - background: $hl-alt-1; - } - } - - button { - font-size: 20px; - margin: 5px; - } - } - } - - separator { - background: $bg-alt-1; - padding: 1px; - margin-top: 10px; - margin-bottom: 10px; - } - - .clock { - background: $bg; - - .datetime { - margin: 1px; - font-size: 10pt; - } - } - - } -} - diff --git a/style/css b/style/css deleted file mode 100644 index c6186c5..0000000 --- a/style/css +++ /dev/null @@ -1,212 +0,0 @@ -* :not(selection) :not(tooltip) { - all: unset; } - -#status-bar { - background-color: #161616; - border-radius: 0 10px 10px 0; } - #status-bar .dial-container { - margin-top: 10px; } - #status-bar .dial-container .battery-dial { - color: #33B1FF; - background-color: #161616; - margin: 0px; - padding: 0px; - font-size: 5px; } - #status-bar .dial-container .battery-dial .dial-icon { - font-family: 'Symbols Nerd Font Mono'; - font-size: 16px; - color: #f2f4f8; } - #status-bar .dial-container .volume-dial { - color: #33B1FF; - background-color: #161616; - margin: 0px; - padding: 0px; - font-size: 5px; } - #status-bar .dial-container .volume-dial .dial-icon { - font-family: 'Symbols Nerd Font Mono'; - font-size: 16px; - color: #f2f4f8; } - #status-bar .dial-container .brightness-dial { - color: #33B1FF; - background-color: #161616; - margin: 0px; - padding: 0px; - font-size: 5px; } - #status-bar .dial-container .brightness-dial .dial-icon { - font-family: 'Symbols Nerd Font Mono'; - font-size: 16px; - color: #f2f4f8; } - #status-bar .workspace-container { - background-color: #262626; - border-radius: 10px; - padding: 6px 0px; - margin: 0px 12px; - border: none; } - #status-bar .workspace-container .ws-norm { - min-width: 15px; - border-radius: 10px; - margin: 2px 5px; - padding: 6px 10px; - background-color: #161616; - color: #f2f4f8; } - #status-bar .workspace-container .ws-active { - color: #161616; - background-color: #FF7EB6; } - #status-bar .menu-visibility-button { - border-radius: 0px 10px 10px 0px; - padding: 10px 0px 10px 2px; - background-color: #262626; } - #status-bar .clock { - background-color: #262626; - margin: 8px; - margin-bottom: 10px; - padding: 6px 2px; - border-radius: 10px; } - #status-bar .mpd-controls .button { - font-size: 14px; - margin: 2px; - margin-bottom: 8px; - font-family: 'Symbols Nerd Font Mono'; } - #status-bar .mpd-controls .button:hover { - color: #FF7EB6; } - -#status-bar .Menu { - background-color: #262626; - min-width: 640px; } - #status-bar .Menu .mpd-controls { - background-color: #161616; - border-radius: 10px; - margin: 10px; } - #status-bar .Menu .mpd-controls .button { - font-size: 24px; - padding: 10px; - margin: 10px; - background-color: #262626; - border-color: #262626; - border-radius: 10px; } - #status-bar .Menu .mpd-controls .cover { - min-width: 250px; - min-height: 250px; - border-radius: 10px; - margin: 10px; - background: #161616; - background-size: cover; } - #status-bar .Menu .mpd-controls .title { - padding-top: 10px; - font-size: 20px; - font-weight: bold; } - #status-bar .Menu .mpd-controls .position { - margin: 10px; - margin-right: 20px; - min-height: 10px; - border-radius: 5px; } - #status-bar .Menu .mpd-controls .position trough { - background: #262626; - border-radius: 5px; - min-height: 10px; } - #status-bar .Menu .mpd-controls .position highlight { - min-height: 10px; - border-radius: 5px; - background: #FF7Eb6; } - #status-bar .Menu .mpd-controls .position-label { - margin-top: 75px; } - #status-bar .Menu .dial-parent { - color: #FF7eb6; - background-color: #161616; - margin: 0px; - padding: 10px; - font-size: 8px; - margin-left: 10px; - border-radius: 10px; - border-radius: 10px; } - #status-bar .Menu .dial-parent .dial-icon { - font-family: 'Symbols Nerd Font Mono'; - font-size: 32px; - color: #f2f4f8; } - #status-bar .Menu .dial-parent .resource-dial { - min-width: 96px; - min-height: 96px; } - #status-bar .Menu .dial-parent .dial-icon { - color: #f2f4f8; } - -#notifications { - background: transparent; } - -.notifications { - opacity: 1; - min-width: 24rem; } - .notifications .revealer + .revealer > * > box { - margin-top: 0; } - .notifications .revealer .notification { - margin: 25px; - min-width: 24rem; - padding: 0px; - border: 2px solid #f2f4f8; - background: #161616; } - .notifications .revealer .notification.critical { - border: 2px solid #FF7EB6; } - .notifications .revealer .body { - margin-right: 1em; } - .notifications .revealer .timeout-bar { - margin: 5px 0px 0; - margin-top: 5px; - background: #262626; } - .notifications .revealer .timeout-bar > trough > progress { - background-image: none; - background-color: #33B1FF; } - .notifications .revealer .button { - font-size: 20px; - margin-left: 5px; - margin-right: 5px; } - .notifications .revealer .button:hover { - color: #FF7EB6; } - .notifications .revealer .icon { - min-width: 68px; - min-height: 68px; - margin-right: 1em; - margin-left: 1em; } - .notifications .revealer .icon image { - font-size: 58px; - margin: 5px; - color: #f2f4f8; } - .notifications .revealer .icon box { - min-width: 68px; - min-height: 68px; } - .notifications .revealer .title { - font-size: 24px; } - .notifications .revealer .actions .action-button { - margin: 0 .4em; - margin-top: .8em; - border: 2px solid #f2f4f8; } - .notifications .revealer .actions .action-button:first-child { - margin-left: .5em; } - .notifications .revealer .actions .action-button:last-child { - margin-right: .5em; } - -.launcher { - min-width: 640px; - background: #262626; } - .launcher .search > image { - margin-left: 10px; } - .launcher .search > entry { - padding: 5px; - margin: 10px; - background: #161616; - border: 5px solid #161616; - border-radius: 10px; - font-size: 32px; } - .launcher .entry { - margin: 0 10px 0 10px; - border: 10px solid #161616; - border-radius: 10px; - background: #161616; } - .launcher .entry > box > image { - padding: 5px; - margin: 5px 10px 5px 10px; - background: #262626; - border-radius: 5px; } - .launcher > scrolledwindow > * > box:last-child { - margin-bottom: 10px; } - -* :not(selection) :not(tooltip) { - all: unset; } diff --git a/style/mixins.scss b/style/mixins.scss deleted file mode 100644 index 4679390..0000000 --- a/style/mixins.scss +++ /dev/null @@ -1,27 +0,0 @@ -@mixin dial($_fg, $_bg, $margin, $padding, $font-size, $icon-font-size) { - color: $_fg; - background-color: $_bg; - margin: $margin; - padding: $padding; - font-size: $font-size; - - .dial-icon { - font-family: 'Symbols Nerd Font Mono'; - font-size: $icon-font-size; - color: $icon-color; - } -} - -@mixin bar-dial($_fg, $_bg) { - @include dial($_fg, $_bg, 0px, 0px, 5px, 16px) -} - -@mixin panel-dial($_fg, $_bg) { - @include dial($_fg, $_bg, 0px, 10px, 8px, 32px); - margin-left: 10px; - border-radius: 10px; - .resource-dial { - min-width: 96px; - min-height: 96px; - } -} diff --git a/style/style.css b/style/style.css index f0ffb51..e2ba035 100644 --- a/style/style.css +++ b/style/style.css @@ -1,320 +1,19 @@ -.lock-ready > box box { +* { + all: unset; } + +bar { + background: transparent; } + +box.workspaces { + min-height: 50px; background: #161616; - padding: 20px; - border: 10px solid #33B1FF; - min-width: 300px; - margin: 15px; } - -.lock-ready > box .img { - background: url("/home/catalie/.config/wallpaper"); - min-width: 300px; - min-height: 300px; - background-position: 25% 12.5%; - background-size: cover; } - -.lock-ready > box box > entry { - background: #262626; - font-size: 14px; - padding: 5px; - margin: 10px; } - -.lock { - background: transparent; } - -* :not(selection) :not(tooltip) { - all: unset; } - -#status-bar { - background-color: #161616; - border-radius: 0 10px 10px 0; } - #status-bar .dial-container { - margin-top: 10px; } - #status-bar .dial-container .battery-dial { - color: #42be65; - background-color: #161616; - margin: 0px; - padding: 0px; - font-size: 5px; } - #status-bar .dial-container .battery-dial .dial-icon { - font-family: 'Symbols Nerd Font Mono'; - font-size: 16px; - color: #f2f4f8; } - #status-bar .dial-container .volume-dial { - color: #33B1FF; - background-color: #161616; - margin: 0px; - padding: 0px; - font-size: 5px; } - #status-bar .dial-container .volume-dial .dial-icon { - font-family: 'Symbols Nerd Font Mono'; - font-size: 16px; - color: #f2f4f8; } - #status-bar .dial-container .brightness-dial { - color: #33B1FF; - background-color: #161616; - margin: 0px; - padding: 0px; - font-size: 5px; } - #status-bar .dial-container .brightness-dial .dial-icon { - font-family: 'Symbols Nerd Font Mono'; - font-size: 16px; - color: #f2f4f8; } - #status-bar .workspace-container { - background-color: #262626; - border-radius: 10px; - padding: 6px 0px; - margin: 0px 12px; - border: none; } - #status-bar .workspace-container .ws-norm { - min-width: 15px; - border-radius: 10px; - margin: 2px 5px; - padding: 6px 10px; - background-color: #161616; - color: #f2f4f8; } - #status-bar .workspace-container .ws-active { - color: #161616; - background-color: #FF7EB6; } - #status-bar .menu-visibility-button { - border-radius: 0px 10px 10px 0px; - padding: 10px 0px 10px 2px; - background-color: #262626; } - #status-bar .clock { - background-color: #262626; - margin: 8px; - margin-bottom: 10px; - padding: 6px 2px; - border-radius: 10px; } - #status-bar .mpd-controls .button { - font-size: 14px; - margin: 2px; - margin-bottom: 8px; - font-family: 'Symbols Nerd Font Mono'; } - #status-bar .mpd-controls .button:hover { - color: #FF7EB6; } - -#status-bar { - background: transparent; } - #status-bar .workspaces { - min-height: 50px; - background: #161616; - padding: 5px; - padding-top: 15px; } - #status-bar .workspaces .workspace { - min-width: 10px; - min-height: 10px; - margin: 5px; - background-color: #262626; } - #status-bar .workspaces .occupied { - background-color: #393939; } - #status-bar .workspaces .focused { - background-color: #FF7EB6; } - #status-bar .media-controls { - margin-top: 20px; - min-width: 220px; } - #status-bar .media-controls .button { - font-size: 20px; } - #status-bar .progress-bar { - margin-top: 20px; - min-width: 200px; - min-height: 2px; - background: transparent; } - #status-bar .progress-bar trough { - min-height: 2px; - background: #262626; } - #status-bar .progress-bar highlight { - min-height: 2px; - background: #FF7Eb6; } - #status-bar .right { - min-height: 50px; - background: #161616; } - #status-bar .right .battery-container { - padding-left: 10px; - padding-right: 10px; } - #status-bar .right .battery-container .battery-dial { - color: #42be65; - background-color: #161616; - margin: 0px; - padding: 0px; - font-size: 5px; } - #status-bar .right .battery-container .battery-dial .dial-icon { - font-family: 'Symbols Nerd Font Mono'; - font-size: 16px; - color: #f2f4f8; } - #status-bar .right .sliderbox { - margin: 5px; } - #status-bar .right .sliderbox .volume .slider trough { - min-height: 10px; - min-width: 120px; - background: #262626; } - #status-bar .right .sliderbox .volume .slider highlight { - background: #33B1FF; } - #status-bar .right .sliderbox .volume button { - font-size: 20px; - margin: 5px; } - #status-bar .right .sliderbox .brightness .slider trough { - min-height: 10px; - min-width: 120px; - background: #262626; } - #status-bar .right .sliderbox .brightness .slider highlight { - background: #33B1FF; } - #status-bar .right .sliderbox .brightness button { - font-size: 20px; - margin: 5px; } - #status-bar .right separator { - background: #262626; - padding: 1px; - margin-top: 10px; - margin-bottom: 10px; } - #status-bar .right .clock { - background: #161616; } - #status-bar .right .clock .datetime { - margin: 1px; - font-size: 10pt; } - -#status-bar .Menu { - background-color: #262626; - min-width: 640px; } - #status-bar .Menu .mpd-controls { - background-color: #161616; - border-radius: 10px; - margin: 10px; } - #status-bar .Menu .mpd-controls .button { - font-size: 24px; - padding: 10px; - margin: 10px; - background-color: #262626; - border-color: #262626; - border-radius: 10px; } - #status-bar .Menu .mpd-controls .cover { - min-width: 250px; - min-height: 250px; - border-radius: 10px; - margin: 10px; - background: #161616; - background-size: cover; } - #status-bar .Menu .mpd-controls .title { - padding-top: 10px; - font-size: 20px; - font-weight: bold; } - #status-bar .Menu .mpd-controls .position { - margin: 10px; - margin-right: 20px; - min-height: 10px; - border-radius: 5px; } - #status-bar .Menu .mpd-controls .position trough { - background: #262626; - border-radius: 5px; - min-height: 10px; } - #status-bar .Menu .mpd-controls .position slider { - min-height: 10px; - border-radius: 5px; - background: #FF7Eb6; } - #status-bar .Menu .mpd-controls .position-label { - margin-top: 75px; } - #status-bar .Menu .dial-parent { - color: #FF7eb6; - background-color: #161616; - margin: 0px; - padding: 10px; - font-size: 8px; - margin-left: 10px; - border-radius: 10px; - border-radius: 10px; } - #status-bar .Menu .dial-parent .dial-icon { - font-family: 'Symbols Nerd Font Mono'; - font-size: 32px; - color: #f2f4f8; } - #status-bar .Menu .dial-parent .resource-dial { - min-width: 96px; - min-height: 96px; } - #status-bar .Menu .dial-parent .dial-icon { - color: #f2f4f8; } - -#notifications { - background: transparent; } - -.notifications { - opacity: 1; - min-width: 24rem; } - .notifications .revealer + .revealer > * > box { - margin-top: 0; } - .notifications .revealer .notification { - margin-bottom: 25px; - min-width: 24rem; - padding: 0px; - border: 1px solid #f2f4f8; - border-right: none; - background: #161616; } - .notifications .revealer .urgency-indicator { - min-width: 15px; - margin-bottom: 25px; } - .notifications .revealer .urgency-indicator.normal, .notifications .revealer .urgency-indicator.low { - background: #42be65; - border: 1px solid #42be65; } - .notifications .revealer .urgency-indicator.urgent { - background: #FF7EB6; - border: 1px solid #FF7EB6; } - .notifications .revealer .body { - margin-right: 1em; } - .notifications .revealer .timeout-bar { - background: #262626; } - .notifications .revealer .timeout-bar > trough > progress { - background-image: none; - background-color: #33B1FF; } - .notifications .revealer .button { - font-size: 20px; - margin-left: 5px; - margin-right: 5px; } - .notifications .revealer .button:hover { - color: #FF7EB6; } - .notifications .revealer .icon { - min-width: 68px; - min-height: 68px; - margin: 5px; } - .notifications .revealer .icon image { - font-size: 58px; + padding: 5px; } + box.workspaces box > button { + min-width: 10px; + min-height: 10px; margin: 5px; - color: #f2f4f8; } - .notifications .revealer .icon box { - min-width: 68px; - min-height: 68px; } - .notifications .revealer .title { - font-size: 28px; - padding-right: 5px; } - .notifications .revealer .actions .action-button { - margin: 0 .4em; - margin-top: .8em; - border: 2px solid #f2f4f8; } - .notifications .revealer .actions .action-button:first-child { - margin-left: .5em; } - .notifications .revealer .actions .action-button:last-child { - margin-right: .5em; } - -.launcher { - min-width: 640px; - background: #262626; } - .launcher .search > image { - margin-left: 10px; } - .launcher .search > entry { - padding: 5px; - margin: 10px; - background: #161616; - border: 5px solid #161616; - border-radius: 10px; - font-size: 32px; } - .launcher .entry { - margin: 0 10px 0 10px; - border: 10px solid #161616; - border-radius: 10px; - background: #161616; } - .launcher .entry > box > image { - padding: 5px; - margin: 5px 10px 5px 10px; - background: #262626; - border-radius: 5px; } - .launcher > scrolledwindow > * > box:last-child { - margin-bottom: 10px; } - -* :not(selection) :not(tooltip) { - all: unset; } + background-color: #262626; } + box.workspaces box > button.occupied { + background-color: #393939; } + box.workspaces box > button.focused { + background-color: #FF7EB6; } diff --git a/style/style.scss b/style/style.scss index 259aa96..6b176e3 100644 --- a/style/style.scss +++ b/style/style.scss @@ -1,14 +1,7 @@ -@import 'colors.scss'; -@import 'mixins.scss'; - -// components -@import './components/lock.scss'; -@import './components/bar.scss'; -@import './components/top-bar.scss'; -@import './components/bar-control-center.scss'; -@import './components/notification-popups.scss'; -@import './components/launcher.scss'; - -* :not(selection) :not(tooltip) { - all: unset; +* { + all: unset; } + +@import 'colors.scss'; + +@import './widgets/bar.scss' diff --git a/style/widgets/bar.scss b/style/widgets/bar.scss new file mode 100644 index 0000000..ae13c07 --- /dev/null +++ b/style/widgets/bar.scss @@ -0,0 +1,26 @@ +$height: 50px; + +bar { + background: transparent +} + +box.workspaces { + min-height: $height; + background: $bg; + padding: 5px; + + box > button { + min-width: 10px; + min-height: 10px; + margin: 5px; + background-color: $bg-alt-1; + + &.occupied { + background-color: $bg-alt-2; + } + + &.focused { + background-color: $hl; + } + } +} diff --git a/utils/PopupWindow.js b/utils/PopupWindow.js deleted file mode 100644 index 015ea0d..0000000 --- a/utils/PopupWindow.js +++ /dev/null @@ -1,29 +0,0 @@ -export default ({ - name, - child, - transition = "slide_up", - transitionDuration = 250, - ...props -}) => { - const reveal = Variable(false) - const window = Widget.Window({ - name, - visible: false, - ...props, - - child: Widget.Box({ - css: `min-height: 2px; - min-width: 2px;`, - child: Widget.Revealer({ - transition, - transitionDuration, - hexpand: true, - vexpand: true, - child: child, - revealChild: reveal.bind() - }), - }), - }); - - return window, reveal; -} diff --git a/widgets/battery.js b/widgets/battery.js deleted file mode 100644 index 8fda125..0000000 --- a/widgets/battery.js +++ /dev/null @@ -1,38 +0,0 @@ -const battery = await Service.import('battery') - -const battery_dial = Widget.CircularProgress({ - className: 'battery-dial', - rounded: false, - inverted: false, - startAt: 0.75, - value: battery.bind('percent').as(p => p / 100), - child: Widget.Label({ - className: "dial-icon", - hexpand: true, - setup: (self) => { - self.hook(battery, (self) => { - console.log(battery) - const icons = [ - ["󰂎", "󰁺", "󰁻", "󰁼", "󰁽", "󰁾", "󰁿", "󰂀", "󰂁", "󰂂", "󰁹"], - ["󰢟", "󰢜", "󰂆", "󰂇", "󰂈", "󰢝", "󰂉", "󰢞", "󰂊", "󰂋", "󰂅"], - ]; - self.label = icons[Number(battery.charging)][Math.floor(battery.percent / 10)]; - self.tooltip_text = 'Battery ' + String(battery.percent) + '%'; - }); - } - }), - setup: (self) => { - self.hook(battery, (self) => { - if (battery.percent <= 30 && battery.charging === false) { - self.toggleClassName("battery-low", true); - } else { - self.toggleClassName("battery-low", false); - } - }); - } -}); - -export { - battery_dial -} - diff --git a/widgets/brightness.js b/widgets/brightness.js deleted file mode 100644 index d2f067b..0000000 --- a/widgets/brightness.js +++ /dev/null @@ -1,63 +0,0 @@ -const { exec, execAsync } = Utils; - -import Brightness from '../services/brightness.js' - -const brightness_dial = Widget.EventBox({ - className: 'eventbox-hide-pointer', - 'on-primary-click': () => {execAsync('hyprshade toggle blue-light-filter')}, - 'on-scroll-up': () => {Brightness.screen += 0.01}, - 'on-scroll-down': () => {Brightness.screen -= 0.01}, - child: Widget.CircularProgress({ - rounded: false, - className: 'brightness-dial', - inverted: false, - startAt: 0.75, - value: Brightness.bind('screen'), - child: Widget.Label({ - className: "dial-icon", - hexpand: true, - hpack: 'center', - setup: (self) => { - self.hook(Brightness, (self => { - const brightness = Brightness.screen * 100; - - self.label = ["󰃚", "󰃛", "󰃜", "󰃝", "󰃞", "󰃟", "󰃠"][Math.floor(brightness/15)] - self.tooltip_text = `Brightness ${Math.floor(brightness)}%`; - })) - } - }) - }) -}) - -const brightness_slider = Widget.Box({ - className: 'brightness', - children: [ - Widget.Button({ - on_clicked: () => execAsync('hyprshade toggle blue-light-filter'), - child: Widget.Icon().hook(Brightness, self => { - const brightness = Brightness.screen * 100; - const icon = [ - [80, 'display-brightness-high-symbolic'], - [50, 'display-brightness-medium-symbolic'], - [20, 'display-brightness-low-symbolic'], - [0, 'display-brightness-off-symbolic'] - ].find(([threshold]) => brightness >= threshold)?.[1]; - - self.icon = icon; - self.tooltip_text = `Brightness ${Math.floor(brightness)}%`; - }), - }), - Widget.Slider({ - className: 'slider', - hexpand: true, - drawValue: false, - onChange: ({ value }) => Brightness.screen = value, - value: Brightness.bind('screen'), - }) - ] -}); - -export { - brightness_dial, - brightness_slider -} diff --git a/widgets/clock.js b/widgets/clock.js deleted file mode 100644 index cbd1eee..0000000 --- a/widgets/clock.js +++ /dev/null @@ -1,62 +0,0 @@ -const { exec, execAsync } = Utils; - -const bar_clock = Widget.Box({ - className: 'clock', - vpack: 'end', - vertical: true, - setup: (self) => { - var month_and_date, hours_and_minutes, seconds; - self.poll(1000, self => { - execAsync("date +'%m/%d %H:%M %S'").then((time) => { - [month_and_date, hours_and_minutes, seconds] = time.split(' '); - }); - self.children = [ - Widget.Label({ - className: 'datetime', - label: month_and_date - }), - Widget.Label({ - className: 'datetime', - label: hours_and_minutes - }), - Widget.Label({ - className: 'datetime', - label: seconds - }), - ] - }) - } -}) - - -const horizontal_clock = Widget.Box({ - className: 'clock', - vpack: 'center', - vertical: true, - setup: (self) => { - var date_time, unix_seconds; - self.poll(1000, self => { - execAsync("date +'%d %b %H:%M:%S %s'").then((time) => { - let parts = time.split(' '); - date_time = `${parts[0]} ${parts[1]} ${parts[2]}`; - unix_seconds = parts[3]; - }); - self.children = [ - Widget.Label({ - className: 'datetime', - label: date_time - }), - Widget.Label({ - hpack: 'start', - className: 'datetime', - label: unix_seconds - }) - ]; - }); - } -}); - -export { - bar_clock, - horizontal_clock -} diff --git a/widgets/hypractive.js b/widgets/hypractive.js deleted file mode 100644 index 5980acd..0000000 --- a/widgets/hypractive.js +++ /dev/null @@ -1,10 +0,0 @@ -const hyprland = await Service.import('hyprland') - -const active_window = Widget.Label({ - className: 'active-window', - label: '',//hyprland.bind('active').as(c => c.client.title), -}) - -export { - active_window -} diff --git a/widgets/hyprworkspaces.js b/widgets/hyprworkspaces.js deleted file mode 100644 index 58d5d5d..0000000 --- a/widgets/hyprworkspaces.js +++ /dev/null @@ -1,59 +0,0 @@ -const hyprland = await Service.import('hyprland') - - -const goto_workspace = (ws) => hyprland.messageAsync(`dispatch workspace ${ws}`) - -const hyprworkspaces = Widget.EventBox({ - onScrollUp: () => goto_workspace('+1'), - onScrollDown: () => goto_workspace('-1'), - child: Widget.Box({ - vertical: true, - className: 'workspace-container', - children: Array.from({ length: 10 }, (_, i) => i + 1).map(i => Widget.Button({ - className: 'ws-norm', - attribute: i, - child: Widget.Label(String(i)), - onClicked: () => goto_workspace(i), - setup: self => self.hook(hyprland, self => self.attribute == hyprland.active.workspace.id ? - self.toggleClassName('ws-active', true) - : self.toggleClassName('ws-active', false)) - })), - - setup: self => self.hook(hyprland, () => self.children.forEach(btn => { - btn.visible = hyprland.workspaces.some(ws => ws.id === btn.attribute); - })), - }), -}) - -function workspace_row(start, length) { - return Widget.Box({ - vpack: 'center', - hpack: 'center', - className: 'workspace-row', - children: Array.from({ length: length }, (_, i) => i + 1 + start).map(i => Widget.Button({ - className: 'workspace', - attribute: i, - onClicked: () => goto_workspace(i), - setup: self => { - self.hook(hyprland, self => { - self.attribute == hyprland.active.workspace.id ? self.toggleClassName('focused', true) : self.toggleClassName('focused', false) - hyprland.workspaces.map(w => w.id).includes(self.attribute) ? self.toggleClassName('occupied', true) : self.toggleClassName('occupied', false) - }) - } - })) - }) -} - -const hyprworkspaces_grid = Widget.Box({ - className: 'workspaces', - vertical: true, - children: [ - workspace_row(0, 5), - workspace_row(5, 5) - ] -}) - -export { - hyprworkspaces, - hyprworkspaces_grid -} diff --git a/widgets/marqueeLabel.js b/widgets/marqueeLabel.js deleted file mode 100644 index e0423a4..0000000 --- a/widgets/marqueeLabel.js +++ /dev/null @@ -1,87 +0,0 @@ -const { Gtk, cairo } = imports.gi; -const register = Widget.register; - -class MarqueeLabel extends Gtk.DrawingArea { - static { - register(this, { - properties: { - label: ["string", "rw"], - "scroll-speed": ["int", "rw"], - }, - }); - } - - #xOffset; - #scrollDirection; - - get label() { - return this._label; - } - - set label(label) { - this._label = label; - this.queue_draw(); - this.notify("label"); - } - - get scroll_speed() { - return this._scrollSpeed; - } - - set scroll_speed(speed) { - this._scrollSpeed = speed; - this.notify("scroll-speed"); - } - - constructor(props) { - super(props); - - this._reset(); - - this.poll(this._scrollSpeed * 11, () => this.queue_draw()); - - this.on("size-allocate", () => this._reset()); - this.on("notify::label", () => this._reset()); - } - - _reset() { - this.#xOffset = 1; - this.#scrollDirection = 0; - } - - vfunc_draw(cr) { - const allocation = this.get_allocation(); - const styles = this.get_style_context(); - const width = allocation.width; - const height = allocation.height; - const color = styles.get_color(Gtk.StateFlags.NORMAL); - const [fontFamily] = styles.get_property( - "font-family", - Gtk.StateFlags.NORMAL, - ); - const fontSize = Math.floor( - styles.get_property("font-size", Gtk.StateFlags.NORMAL), - ); - - cr.setSourceRGB(color.red, color.green, color.blue); - cr.selectFontFace(fontFamily, null, null); - cr.setFontSize(fontSize); - - const labelWidth = cr.textExtents(this._label).width; - - if (labelWidth > width) { - this.#xOffset += this.#scrollDirection * this._scrollSpeed; - - if (this.#xOffset >= 1 || this.#xOffset <= width - labelWidth) { - this.#scrollDirection *= 0; - } - } else { - this.#xOffset = (width - labelWidth) / 3; - } - - cr.moveTo(this.#xOffset*1.475, fontSize); - cr.showText(this._label); - } -} - -export default MarqueeLabel; diff --git a/widgets/mpd.js b/widgets/mpd.js deleted file mode 100644 index 01bf9ae..0000000 --- a/widgets/mpd.js +++ /dev/null @@ -1,182 +0,0 @@ -const { Gtk } = imports.gi; - -import Mpd from '../services/mpd.js'; -import MarqueeLabel from './marqueeLabel.js' - -const Mpris = await Service.import("mpris"); - -const AspectFrame = Widget.subclass(Gtk.AspectFrame); - -function lengthString(length) { - return ( - `${Math.floor(length / 60) - .toString() - .padStart(2, "0")}:` + - `${Math.floor(length % 60) - .toString() - .padStart(2, "0")}` - ); -} - -const albumCover = Widget.Box({ - className: "cover", - setup: (self) => self.hook(Mpris, () => { - const mpd = Mpris.getPlayer("mpd"); - self.css = `background-image: url("${mpd?.coverPath}");`; - }), -}); - -const positionLabel = Widget.Label({ - className: 'position-label', - setup: (self) => self.poll(500, () => { - Mpd.send("status") - .then((msg) => { - const elapsed = msg?.match(/elapsed: (\d+\.\d+)/)?.[1]; - self.label = `${lengthString(elapsed || 0)} / ${lengthString(Mpd.duration || 0)}`; - }) - .catch((error) => logError(error)); - }), -}); - -const positionSlider = Widget.Slider({ - className: 'position', - vpack: 'end', - drawValue: false, - onChange: ({ value }) => { - Mpd.seekCur(value * Mpd.duration); - }, - setup: (self) => { - self.poll(500, () => { - Mpd.send("status") - .then((msg) => { - const elapsed = msg?.match(/elapsed: (\d+\.\d+)/)?.[1]; - self.value = elapsed / Mpd.duration || 0; - }) - .catch((error) => logError(error)); - }); - }, -}); - -const songTitle = Widget.Box({ - className: 'title', - children: [ - new MarqueeLabel({ - heightRequest: 30, - widthRequest: 350, - scrollSpeed: 1, - label: 'No Title', - setup: (self) => { - self.hook(Mpd, () => { - self.label = `${Mpd.Title || "No Title"}`; - }); - }, - }) - ] -}) - -const songArtist = Widget.Box({ - className: 'artist', - children: [ - new MarqueeLabel({ - heightRequest: 30, - widthRequest: 350, - scrollSpeed: 1, - label: 'No Artist', - setup: (self) => { - self.hook(Mpd, () => { - self.label = `${Mpd.Artist || "No Artist"}`; - }); - }, - }) - ] -}) - -const mediaControls = Widget.Box() - -const mpd_controls = () => Widget.CenterBox({ - className: 'mpd-controls', - hpack: 'center', - hexpand: true, - startWidget: Widget.Button({ - hpack: 'start', - className: 'button', - onClicked: () => Mpd.previous(), - child: Widget.Icon('media-skip-backward-symbolic') - }), - centerWidget: Widget.Button({ - hpack: 'center', - className: 'button', - onClicked: () => Mpd.playPause(), - child: Widget.Icon({ - setup: self => self.hook(Mpd, () => (Mpd.state === 'play') - ? self.icon = 'media-playback-pause-symbolic' - : self.icon = 'media-playback-start-symbolic') - }) - }), - endWidget: Widget.Button({ - hpack: 'end', - className: 'button', - onClicked: () => Mpd.next(), - child: Widget.Icon('media-skip-forward-symbolic') - }) -}) - -export const mpd_bar_controls = mpd_controls() - -export const mpd_menu_controls = Widget.Box({ - className: 'mpd-controls', - children: [ - albumCover, - Widget.Box({ - vertical: true, - hpack: 'end', - children: [ - Widget.Box({ - vertical: true, - children: [ - songTitle, - songArtist - ] - }), - mpd_controls(), - positionLabel, - positionSlider - ] - }) - ] -}) - -export const cover_with_controls = Widget.Box({ - className: 'cover', - hexpand: true, - vexpand: true, - child: Widget.Box({ - className: "cover", - vertical: true, - children: [ - mpd_controls(), - Widget.Slider({ - vpack: 'end', - className: 'progress-bar', - drawValue: false, - hexpand: false, - onChange: ({ value }) => Mpd.seekCur(value * Mpd.duration), - setup: (self) => { - self.poll(500, () => { - Mpd.send("status") - .then((msg) => { - const elapsed = msg?.match(/elapsed: (\d+\.\d+)/)?.[1]; - self.value = elapsed / Mpd.duration || 0; - }) - .catch((error) => logError(error)); - }); - }, - }) - ], - setup: (self) => - self.hook(Mpris, () => { - const mpd = Mpris.getPlayer("mpd"); - self.css = `background: linear-gradient(rgba(0, 0, 0, 0.6), rgba(0, 0, 0, 0.6)), url("${mpd?.coverPath}"); min-height: 60px; min-width: 250px; background-position: 50% 50%; background-size: cover; border: 5px solid #161616`; - }) - }) -}) diff --git a/widgets/mpris.js b/widgets/mpris.js deleted file mode 100644 index 07b24a9..0000000 --- a/widgets/mpris.js +++ /dev/null @@ -1,114 +0,0 @@ -const { Gtk, Gdk } = imports.gi; -const Mpris = await Service.import('mpris') - -const media_controls = (player) => Widget.CenterBox({ - className: 'media-controls', - hpack: 'center', - hexpand: true, - startWidget: Widget.Button({ - hpack: 'start', - className: 'button', - onClicked: () => player.previous(), - child: Widget.Icon('media-skip-backward-symbolic') - }), - centerWidget: Widget.Button({ - hpack: 'center', - className: 'button', - onClicked: () => player.playPause(), - child: Widget.Icon({ - setup: self => self.hook(Mpris, () => (player.playBackStatus === 'Playing') - ? self.icon = 'media-playback-pause-symbolic' - : self.icon = 'media-playback-start-symbolic') - }) - }), - endWidget: Widget.Button({ - hpack: 'end', - className: 'button', - onClicked: () => player.next(), - child: Widget.Icon('media-skip-forward-symbolic') - }) -}) - -const cover_with_controls = (player) => Widget.Box({ - className: "media", - children: [ - Widget.Box({ - vertical: true, - children: [ - media_controls(player), - Widget.Slider({ - vpack: 'end', - className: 'progress-bar', - drawValue: false, - hexpand: false, - onChange: ({ value }) => {player.position = (value * player.length)}, - setup: self => self.poll(500, self => { - if (!player) return - self.value = player.position/player.length - }) - }) - ], - }), - ], - setup: (self) => { - self.hook(Mpris, () => { - self.queue_draw() - self.css = `background: linear-gradient(rgba(0, 0, 0, 0.6), rgba(0, 0, 0, 0.6)), url("${player.coverPath}"); min-height: 60px; min-width: 250px; background-position: 50% 50%; background-size: cover; border: 5px solid #161616`; - }) - }, -}); - - -export const players = Widget.Stack({ - transition: "slide_up_down", - transitionDuration: 125, - children: {}, - setup: (self) => { - self.add_events(Gdk.EventMask.SCROLL_MASK); - self.add_events(Gdk.EventMask.SMOOTH_SCROLL_MASK); - - let currentDeltaY = 0; - - self.on("scroll-event", (_, event) => { - const childNames = Object.keys(self.children); - - const length = Object.keys(self.children).length - - const prevChild = childNames[((n)=>n>=0?n:length-1)((childNames.indexOf(self.get_visible_child_name()) - 1) % length)]; - const nextChild = childNames[(childNames.indexOf(self.get_visible_child_name()) + 1) % length]; - - const deltaY = event.get_scroll_deltas()[2]; - - currentDeltaY += deltaY; - - if (currentDeltaY > 10 && prevChild) { - self.set_visible_child_name(prevChild); - currentDeltaY = 0; - } - if (currentDeltaY < -10 && nextChild) { - self.set_visible_child_name(nextChild); - currentDeltaY = 0; - } - console.log(self.children) - }); - - self.hook(Mpris, (_, name) => { - if (!name) return; - self.add_named(cover_with_controls(Mpris.getPlayer(name)), name); - }, "player-added"); - self.hook(Mpris, (_, name) => { - if (!name) return; - - self.get_child_by_name(name).destroy(); - delete children[name] - console.log('destroyed') - }, "player-closed"); - }, -}); - -export const media = Widget.Revealer({ - revealChild: Mpris.bind("players").as((players) => players.length > 0), - transition: "slide_up", - transitionDuration: 125, - child: players, -}); diff --git a/widgets/resourceDial.js b/widgets/resourceDial.js deleted file mode 100644 index 9b2c424..0000000 --- a/widgets/resourceDial.js +++ /dev/null @@ -1,24 +0,0 @@ -const { Gio, GioUnix } = imports.gi; - -export const resource_dial = (label, icon, timeout, command, transformer) => { - let poll = Variable(100, { - poll: [timeout, command, v => Number(v)] - }) - - return Widget.Box({ - className: 'dial-parent', - children: [ - Widget.CircularProgress({ - startAt: 0.75, - className: 'resource-dial', - value: poll.bind().as(v => transformer(v)), - tooltipText: poll.bind().as(v => label(v)), - child: Widget.Icon({ - className: 'dial-icon', - icon: icon - }), - }) - ] - }) -} - diff --git a/widgets/systray.js b/widgets/systray.js deleted file mode 100644 index 193b83f..0000000 --- a/widgets/systray.js +++ /dev/null @@ -1,14 +0,0 @@ -const systemtray = await Service.import('systemtray') - -const SysTrayItem = item => Widget.Button({ - child: Widget.Icon().bind('icon', item, 'icon'), - tooltipMarkup: item.bind('tooltip_markup'), - onPrimaryClick: (_, event) => item.activate(event), - onSecondaryClick: (_, event) => item.openMenu(event), -}); - -export const systray = Widget.Box({ - className: 'systray', - vertical: true, - children: systemtray.bind('items').as(i => i.map(SysTrayItem)) -}) diff --git a/widgets/volume.js b/widgets/volume.js deleted file mode 100644 index 4347880..0000000 --- a/widgets/volume.js +++ /dev/null @@ -1,70 +0,0 @@ -const { exec, execAsync } = Utils - -const audio = await Service.import('audio') - -const volume_dial = Widget.EventBox({ - className: 'eventbox-hide-pointer', - 'on-scroll-up': () => {audio.speaker.volume += 0.01}, - 'on-scroll-down': () => {audio.speaker.volume -= 0.01}, - 'on-primary-click': () => {audio.speaker.is_muted = !audio.speaker.is_muted}, - child: Widget.CircularProgress({ - className: 'volume-dial', - rounded: false, - inverted: false, - startAt: 0.75, - value: audio.speaker.bind('volume'), - child: Widget.Icon({ - className: "dial-icon", - hexpand: true, - setup: (self) => { - self.hook(audio, (self => { - const vol = audio.speaker.volume * 100; - const icon = [ - [101, 'overamplified'], - [67, 'high'], - [34, 'medium'], - [1, 'low'], - [0, 'muted'], - ].find(([threshold]) => threshold <= vol)?.[1]; - - self.icon = `audio-volume-${icon}-symbolic`; - self.tooltip_text = `Volume ${Math.floor(vol)}%`; - })) - } - }) - }) -}) - -const volume_slider = Widget.Box({ - className: 'volume', - children: [ - Widget.Button({ - on_clicked: () => audio.speaker.is_muted = !audio.speaker.is_muted, - child: Widget.Icon().hook(audio.speaker, self => { - const vol = audio.speaker.volume * 100; - const icon = [ - [101, 'overamplified'], - [67, 'high'], - [34, 'medium'], - [1, 'low'], - [0, 'muted'], - ].find(([threshold]) => threshold <= vol)?.[1]; - - self.icon = `audio-volume-${icon}-symbolic`; - self.tooltip_text = `Volume ${Math.floor(vol)}%`; - }), - }), - Widget.Slider({ - className: 'slider', - hexpand: true, - drawValue: false, - onChange: ({ value }) => audio['speaker'].volume = value, - value: audio['speaker'].bind('volume'), - }) - ] -}) - -export { - volume_dial, - volume_slider -} diff --git a/windows/bar.js b/windows/bar.js deleted file mode 100644 index 9fadf99..0000000 --- a/windows/bar.js +++ /dev/null @@ -1,141 +0,0 @@ -import { battery_dial } from '../widgets/battery.js' -import { volume_dial } from '../widgets/volume.js' -import { brightness_dial } from '../widgets/brightness.js' -import { hyprworkspaces } from '../widgets/hyprworkspaces.js' -import { mpd_bar_controls } from '../widgets/mpd.js' -// import { systray } from '../widgets/systray.js' - -import { bar_clock} from '../widgets/clock.js' - -import { MenuWidget } from './menu.js' -import { reveal_launcher, launcher } from './launcher.js' - -export const FakeBar = Widget.Window({ - name: 'FakeBar', - exclusivity: 'exclusive', - anchor: ['left'], - margins: [0, 35], - child: Widget.Box({css: 'min-width: 1px;'}) -}) - -let reveal_menu = Variable(false) -let reveal_menu_button = Variable(false) - -const MenuRevealButton = Widget.Box({ - children: [ - Widget.Button({ - vexpand: false, - vpack: 'center', - className: 'menu-visibility-button', - 'on-primary-click': (self) => reveal_menu.value = !reveal_menu.value, - child: Widget.Icon({ - icon: reveal_menu.bind().as(reveal => !reveal ? 'go-next-symbolic' : 'go-previous-symbolic') - }) - }) - ] -}) - -const BarTopWidget = Widget.Box({ - vertical: true, - vpack: 'start', - children: [ - Widget.Box({ - className: 'dial-container', - vertical: true, - spacing: 8, - children: [ - battery_dial, - volume_dial, - brightness_dial - ] - }), - Widget.Box({ - css: 'margin-left: 35px; margin-right: 35px' - }) - ] -}) - -const BarMiddleWidget = Widget.Box({ - children: [ - Widget.EventBox({ - 'on-hover': () => reveal_menu_button.value = true, - child: Widget.Box({ - css: 'min-width: 1px; min-height: 40px;' - }) - }), - hyprworkspaces - ] -}) - -const BarEndWidget = Widget.Box({ - vertical: true, - vpack: 'end', - children: [ - // systray, - mpd_bar_controls, - bar_clock - ] -}) - -const BarWidget = Widget.CenterBox({ - homogeneous: false, - vertical: true, - spacing: 10, - startWidget: BarTopWidget, - centerWidget: BarMiddleWidget, - endWidget: BarEndWidget -}) - -const MenuButtonRevealer = Widget.Revealer({ - revealChild: reveal_menu_button.bind(), - transition: 'slide_right', - child: MenuRevealButton -}) - -const MenuRevealer = Widget.Revealer({ - revealChild: reveal_menu.bind(), - transition: 'slide_right', - transitionDuration: 500, - child: MenuWidget, -}) - -const LauncherRevealer = Widget.Revealer({ - revealChild: reveal_launcher.bind(), - transition: 'slide_right', - transitionDuration: 500, - child: launcher, -}) - -export const Bar = Widget.Window({ - name: 'status-bar', - exclusivity: 'ignore', - keymode: reveal_launcher.bind().as(v => v ? 'exclusive' : 'on-demand'), - anchor: ['top', 'left', 'bottom'], - child: Widget.Overlay({ - 'pass-through': true, - overlay: Widget.Box({ - children: [ - Widget.EventBox({ - 'on-hover': () => reveal_menu_button.value = true, - 'on-hover-lost': () => reveal_menu_button.value = false, - child: Widget.Box({ - css: 'margin-right: 4px;', - children: [MenuButtonRevealer] - }) - }), - ] - }), - child: Widget.Box({ - children: [ - LauncherRevealer, - MenuRevealer, - BarWidget - ] - }) - }) -}) - -export { - reveal_menu, - reveal_launcher -} diff --git a/windows/launcher.js b/windows/launcher.js deleted file mode 100644 index f5bf4eb..0000000 --- a/windows/launcher.js +++ /dev/null @@ -1,93 +0,0 @@ -const Applications = await Service.import("applications") - -const reveal_launcher = Variable(false) - -function appItem(app) { - return Widget.Button({ - className: 'entry', - onClicked: () => { - reveal_launcher.value = false - app.launch() - }, - attribute: { app }, - child: Widget.Box([ - Widget.Icon({ - icon: app.icon_name || '', - size: 42, - }), - Widget.Label({ - className: 'app-title', - label: app.name, - xalign: 0, - vpack: 'center', - truncate: 'end' - }) - ]) - }) -} - -function _launcher() { - let applications = Applications.query('').map(appItem) - - const list = Widget.Box({ - vertical: true, - children: applications, - spacing: 12 - }) - - function repopulate() { - applications = Applications.query('').map(appItem) - list.children = applications - } - - const entry = Widget.Box({ - className: 'search', - children: [ - Widget.Icon({ - icon: 'edit-find-symbolic', - size: 42, - }), - Widget.Entry({ - hexpand: true, - className: 'search', - on_accept: () => { - applications.filter((item) => item.visible)[0]?.attribute.app.launch() - reveal_launcher.value = false - }, - on_change: ({ text }) => applications.forEach(item => { - item.visible = item.attribute.app.match(text ?? '') - }) - }) - ] - }) - - return Widget.Box({ - vertical: true, - className: 'launcher', - children: [ - entry, - Widget.Scrollable({ - hscroll: 'never', - vexpand: true, - hexpand: true, - child: list - }) - ], - setup: self => self.hook(reveal_launcher, () => { - entry.text = '' - if (reveal_launcher.value) { - repopulate() - console.log('nya') - entry.text = '' - entry.grab_focus() - } - }, "changed") - }) -} - -const launcher = _launcher() - -export { - reveal_launcher, - launcher -} diff --git a/windows/lock.js b/windows/lock.js deleted file mode 100644 index 0e4974b..0000000 --- a/windows/lock.js +++ /dev/null @@ -1,76 +0,0 @@ -import { show_notification_popups } from './notifications.js' - -// TODO: const { Gdk, GtkSessionLock } = imports.gi; -const { authenticateUser, exec } = Utils - -export const show_lock = Variable(false) -const lock_ready = Variable(false) - -const username = Variable() - -const password_entry = Widget.Entry({ - visibility: false, - xalign: 0.5, - onAccept: (self) => { - authenticateUser(username.value, self.text) - .then(() => { - show_lock.value = false - exec('rm /tmp/lock-pixelated.png') - show_notification_popups.value = true - }) - .catch(() => self.text = '') - self.text = '' - username_entry.text = '' - username_entry.grab_focus() - }, - setup: self => self.text = '' -}) - -const username_entry = Widget.Entry({ - xalign: 0.5, - onAccept: (self) => { - username.value = self.text - password_entry.grab_focus() - }, -}) - -const login_container = Widget.Box({ - child: Widget.Box({ - className: lock_ready.bind().as(b => b ? 'lock-ready' : 'lock'), - vpack: 'center', - hpack: 'center', - hexpand: 'true', - vertical: true, - child: Widget.Box({ - vertical: true, - children: [ - Widget.Box({className: 'img'}), - Widget.Box({ - vertical: true, - children: [ - username_entry, - password_entry - ] - }) - ] - }) - }), - setup: self => self.hook(show_lock, () => { - self.css = 'min-width: 2560px; min-height: 1600px; background: url("/tmp/lock-pixelated.png");' - lock_ready.value = true - }) -}) - -export const Lock = Widget.Window({ - name: 'lock', - visible: show_lock.bind().as(b => { - if (b) { - exec(`bash -c "grim - | convert - -scale 12.5% -scale 800% -filter point /tmp/lock-pixelated.png"`) - show_notification_popups.value = false - } - return b - }), - exclusivity: 'ignore', - keymode: 'exclusive', - child: login_container, -}) diff --git a/windows/menu.js b/windows/menu.js deleted file mode 100644 index 5701ebf..0000000 --- a/windows/menu.js +++ /dev/null @@ -1,49 +0,0 @@ -import { mpd_menu_controls } from '../widgets/mpd.js' -import { resource_dial } from '../widgets/resourceDial.js' - -export const MenuWidget = Widget.Box({ - vertical: true, - className: 'Menu', - children: [ - mpd_menu_controls, - Widget.Box({ - children: [ - resource_dial( - (v) => `cpu: ${v}%`, - 'microchip-solid', - 1000, - "bash -c \"top -bn1 | grep 'Cpu(s)' | awk '{print \$2 + \$4}'\"", - v => v/100 - ), - resource_dial( - (v) => `mem: ${Math.round(100*v/31396)}%`, - 'memory-solid', - 1000, - "bash -c \"free -m | grep Mem | awk '{print $3}'\"", - v => v/31396 - ), - resource_dial( - (v) => `igpu: ${v}%`, - 'expansion-card', - 1000, - "bash -c \"cat /sys/class/drm/card1/device/gpu_busy_percent\"", - v => v/100 - ), - resource_dial( - (v) => `fan: ${v}rpm`, - 'fan', - 1000, - "bash -c \"sudo ectool pwmgetfanrpm | awk '{a+=\$4} END {print a/2}'\"", - v => v/5000 - ), - resource_dial( - (v) => `temp (cpu): ${v}`, - 'thermometer', - 1000, - "bash -c \"sudo ectool temps all | grep -E 'cpu' | awk '{print \$5}'\"", - v => v/100 - ), - ] - }) - ] -}) diff --git a/windows/notifications.js b/windows/notifications.js deleted file mode 100644 index fa959f8..0000000 --- a/windows/notifications.js +++ /dev/null @@ -1,185 +0,0 @@ -const Notifications = await Service.import('notifications') -const { Pango } = imports.gi; - -Notifications.popupTimeout = 3000; - -function notification_icon({ app_entry, app_icon, image }) { - if (image) { - return Widget.Box({ - css: `background-image: url("${image}");` - + 'background-size: contain;' - + 'background-repeat: no-repeat;' - + 'background-position: center;', - }) - } - - let icon = 'dialog-information-symbolic' - if (Utils.lookUpIcon(app_icon)) - icon = app_icon - - if (app_entry && Utils.lookUpIcon(app_entry)) - icon = app_entry - - return Widget.Box({ - child: Widget.Icon(icon), - }) -} - -const notification = (n) => { - const icon = Widget.Box({ - vpack: 'center', - hpack: 'start', - class_name: 'icon', - child: notification_icon(n), - }) - - const title = Widget.Label({ - className: 'title', - label: n.summary, - xalign: 0, - maxWidthChars: 40, - justify: 'left', - }) - - const body = Widget.Label({ - className: 'body', - label: n.body, - xalign: 0, - justification: 'left', - maxWidthChars: 26, - wrap: true, - wrapMode: Pango.WrapMode.WORD_CHAR, - useMarkup: true, - }) - - const actions = Widget.Box({ - class_name: "actions", - children: n.actions.map(({ id, label }) => Widget.Button({ - class_name: "action-button", - on_clicked: () => { - n.invoke(id) - n.dismiss() - }, - hexpand: true, - child: Widget.Label(label), - })), - }) - - // const buttons = Widget.Box({ - // hpack: 'end', - // children: [ - // Widget.Button({ - // className: 'button', - // onClicked: () => n.dismiss(), - // child: Widget.Label('') - // }) - // ] - // }) - - const timeout_progress = Widget.ProgressBar({ - className: 'timeout-bar', - hexpand: true, - vpack: 'end', - value: 1, - setup: (self) => { - self.poll(n.timeout/100, () => { - if (self.value > 0.01) { - self.value = self.value - .01 - } - else { n.dismiss() } // Notifications.forceTimeout doesn't work for notifications that are bugged. - }) - } - }) - - const layout = Widget.Button({ - child: Widget.Box({ - children: [ - Widget.Box({ - className: 'notification', - vertical: true, - children: [ - Widget.Box([ - icon, - Widget.Box({ - vertical: true, - children: [ - title, body - ] - }) - ]), - actions, - timeout_progress - ] - }), - Widget.Box({ - vexpand: false, - classNames: ['urgency-indicator', n.urgency] - }) - ] - }), - onPrimaryClick: n.dismiss, - }) - - return Widget.Revealer({ - className: 'revealer', - attribute: { id: n.id }, - vpack: 'start', - transition: 'slide_down', - transitionDuration: 250, - setup: (self) => { - Utils.timeout(1, () => self.set_reveal_child(true)); - self.on('notify::reveal-child', () => { - if (self.reveal_child) Utils.timeout(125, () => self.child.set_reveal_child(true)) - }) - }, - child: Widget.Revealer({ - className: 'revealer', - hpack: 'end', - transition: 'slide_left', - transitionDuration: 250, - setup: (self) => self.on('notify::reveal-child', () => { - if (!self.reveal_child) Utils.timeout(250, () => self.parent.set_reveal_child(false)) - }), - child: layout - }) - }) -} - -export const show_notification_popups = Variable(true) -export const NotificationPopups = Widget.Window({ - visible: show_notification_popups.bind(), - name: 'notifications', - anchor: ['top', 'right'], - layer: 'overlay', - margins: [15, 0, 0, 0], - child: Widget.Box({ - className: 'notifications', - vertical: true, - widthRequest: 2, - heightRequest: 2, - children: Notifications.popups.map(notification), - setup: (self) => self.hook(Notifications, (_, id) => { - if (!id || Notifications.dnd) return; - - const n = Notifications.getNotification(id) - - if (!n) return; - - self.children = [...self.children, notification(n)] - }, 'notified') - .hook(Notifications, (_, id) => { - if (!id) return; - - const n = self.children.find( - (child) => child.attribute.id === id, - ) - - if (!n) return; - - n.child.set_reveal_child(false) - - Utils.timeout(n.child.transition_duration, () => n.destroy()) - }, 'dismissed') - }) -}) - diff --git a/windows/top-bar.js b/windows/top-bar.js deleted file mode 100644 index b036b92..0000000 --- a/windows/top-bar.js +++ /dev/null @@ -1,70 +0,0 @@ -import { hyprworkspaces_grid } from '../widgets/hyprworkspaces.js' -import { volume_slider } from '../widgets/volume.js' -import { brightness_slider } from '../widgets/brightness.js' -import { battery_dial } from '../widgets/battery.js' -import { horizontal_clock } from '../widgets/clock.js' -import { active_window } from '../widgets/hypractive.js' -import { media } from '../widgets/mpris.js' - -export const FakeBar = Widget.Window({ - name: 'FakeBar', - exclusivity: 'exclusive', - anchor: ['left', 'top', 'right'], - margins: [35, 0], - child: Widget.Box({css: 'min-height: 1px;'}) -}) - -const left_box = Widget.Box({ - className: 'left', - hpack: 'start', - children: [ - hyprworkspaces_grid, - media - ] -}) - -const middle_box = Widget.Box({ - className: 'middle', - hpack: 'center', - children: [ - active_window - ] -}) - -const right_box = Widget.Box({ - className: 'right', - hpack: 'end', - children: [ - Widget.Box({ - className: 'sliderbox', - vertical: true, - children: [ - volume_slider, - brightness_slider - ] - }), - Widget.Box({ - className: 'battery-container', - children: [battery_dial] - }), - Widget.Separator({vertical: true}), - horizontal_clock - ] -}) - -const bar = Widget.Box({ - className: 'bar', - children: [ - left_box, - middle_box, - right_box - ] -}) - -export const Bar = Widget.Window({ - name: 'status-bar', - exclusivity: 'ignore', - // margins: [5, 5, 5, 5], - anchor: ['left', 'top', 'right'], - child: bar -})