From 41e4b0b05f0aaf19e4e61147c11013ebea299542 Mon Sep 17 00:00:00 2001 From: caem Date: Mon, 24 Jun 2024 01:08:43 +0200 Subject: [PATCH] Switch to waybar --- users/hu/packages/ags/ags.nix | 16 -- users/hu/packages/ags/config/assets/nixos.svg | 1 - users/hu/packages/ags/config/bar.js | 210 ------------------ users/hu/packages/ags/config/config.js | 12 - users/hu/packages/ags/config/style.css | 206 ----------------- users/hu/packages/ags/config/vendor/Media.js | 158 ------------- .../ags/config/vendor/notificationPopups.js | 148 ------------ users/hu/packages/hyprland.nix | 10 +- users/hu/packages/waybar.nix | 53 +++++ users/hu/user.nix | 2 +- 10 files changed, 57 insertions(+), 759 deletions(-) delete mode 100644 users/hu/packages/ags/ags.nix delete mode 100644 users/hu/packages/ags/config/assets/nixos.svg delete mode 100644 users/hu/packages/ags/config/bar.js delete mode 100644 users/hu/packages/ags/config/config.js delete mode 100644 users/hu/packages/ags/config/style.css delete mode 100644 users/hu/packages/ags/config/vendor/Media.js delete mode 100644 users/hu/packages/ags/config/vendor/notificationPopups.js create mode 100644 users/hu/packages/waybar.nix diff --git a/users/hu/packages/ags/ags.nix b/users/hu/packages/ags/ags.nix deleted file mode 100644 index afd5fa2..0000000 --- a/users/hu/packages/ags/ags.nix +++ /dev/null @@ -1,16 +0,0 @@ -{ pkgs, ... }: - -{ - # TODO: config - programs.ags = { - enable = true; - configDir = ./config; - - extraPackages = with pkgs; [ - gtksourceview - webkitgtk - accountsservice - ]; - }; -} - diff --git a/users/hu/packages/ags/config/assets/nixos.svg b/users/hu/packages/ags/config/assets/nixos.svg deleted file mode 100644 index fb26b80..0000000 --- a/users/hu/packages/ags/config/assets/nixos.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/users/hu/packages/ags/config/bar.js b/users/hu/packages/ags/config/bar.js deleted file mode 100644 index e9087d9..0000000 --- a/users/hu/packages/ags/config/bar.js +++ /dev/null @@ -1,210 +0,0 @@ -const hyprland = await Service.import("hyprland"); -const audio = await Service.import("audio"); - -import { Media } from "./vendor/Media.js"; - -const VolumeWidget = (properties) => { - return Widget.Box({ - class_name: "app-volume", - children: [ - Widget.Box({ - class_name: "app-mixer", - vertical: true, - hexpand: true, - children: [ - Widget.Label({ - class_name: "app-mixer-label", - label: properties.description, - truncate: "end", - maxWidthChars: 60, - wrap: false, - justification: "left", - }), - Widget.Box({ - class_name: "app-volume-slider", - children: [ - Widget.Icon({ - class_name: "volume-icon", - icon: "audio-volume-high-symbolic", - }), - Widget.Slider({ - hexpand: true, - draw_value: false, - on_change: ({ value }) => properties.volume = value, - setup: self => self.hook(properties, () => { - self.value = properties.volume || 0 - }), - }), - ], - }), - // Widget.Label(properties.stream.name), - ], - }), - ], - }); -}; - -const VolumeWidgets = () => { - if (!audio || !audio.apps) { - return []; - } - - let widgets = []; - for (let i = 0; i < audio.apps.length; i++) { - widgets.push(VolumeWidget(audio.apps[i])); - } - - return widgets; -}; - -const Qsd = () => Widget.Box({ - name: "qsd", - class_name: "qsd", - vpack: "start", - vertical: true, - children: [ - Widget.Box({ - name: "qsd-power", - class_name: "qsd-power", - hpack: "end", - children: [ - Widget.Button({ - child: Widget.Icon({ - icon: "system-reboot-symbolic" - }), - }), - Widget.Button({ - on_clicked: () => { - console.log(audio.apps) - }, - child: Widget.Icon({ - icon: "system-shutdown-symbolic" - }), - }), - ], - }), - Widget.Box({ - name: "qsd-volume-mixer", - class_name: "qsd-volume-mixer", - children: [ - Widget.Box({ - class_name: "qsd-volume-slider-container", - vertical: true, - vpack: "start", - }).hook(audio, self => { - self.children = [ - Widget.Box({ - class_name: "master-volume", - children: [ - Widget.Icon({ - class_name: "volume-icon", - icon: "audio-volume-high-symbolic", - }), - Widget.Label("master"), - Widget.Slider({ - hexpand: true, - draw_value: false, - on_change: ({ value }) => audio.speaker.volume = value, - setup: self => self.hook(audio.speaker, () => { - self.value = audio.speaker.volume || 0 - }), - }), - ] - }) - ].concat(VolumeWidgets()); - }), - ], - }), - Media(), - ], -}); - -const Menu = () => { - return Widget.Window({ - name: "shell-menu", - class_name: "shell-menu", - exclusivity: "normal", - anchor: ["top", "right"], - margins: [5, 5], - // keymode: "on-demand", - layer: "top", - monitor: 0, - child: Qsd(), - }); -} - -App.addWindow(Menu()); -App.toggleWindow("shell-menu"); - -const MenuButton = () => { - return Widget.Button({ - on_clicked: () => App.toggleWindow("shell-menu"), - child: Widget.Icon({ - icon: "nixos" - }), - class_name: "menu_button", - }); -} - -const data = Variable("", { - poll: [1000, 'date "+%H:%M:%S"'], -}); - -const Clock = () => { - return Widget.Label({ - class_name: "clock", - label: data.bind(), - }); -} - -const End = () => { - return Widget.Box({ - hpack: "end", - spacing: 8, - children: [ - Clock(), - MenuButton(), - ], - }); -} - -const Workspaces = () => { - const activeId = hyprland.active.workspace.bind("id"); - const workspaces = hyprland.bind("workspaces") - .as((ws) => - ws.sort((a, b) => a.id - b.id).map(({ id }) => Widget.Button({ - on_clicked: () => hyprland.messageAsync(`dispatch workspace ${id}`), - child: Widget.Label(`${id}`), - class_name: activeId.as((i) => `${i === id ? "focused" : ""}`), - }) - ) - ); - - return Widget.Box({ - class_name: "workspaces", - children: workspaces, - }); -} - -const Start = () => { - return Widget.Box({ - children: [ - Workspaces(), - ], - }); -} - -export const Bar = () => { - return Widget.Window({ - name: "bar", - class_name: "bar", - monitor: 0, - anchor: ["top", "left", "right"], - exclusivity: "exclusive", - child: Widget.CenterBox({ - start_widget: Start(), - end_widget: End(), - }), - }); -} - diff --git a/users/hu/packages/ags/config/config.js b/users/hu/packages/ags/config/config.js deleted file mode 100644 index 7d59086..0000000 --- a/users/hu/packages/ags/config/config.js +++ /dev/null @@ -1,12 +0,0 @@ -import { Bar } from "./bar.js"; -import { NotificationPopups } from "./vendor/notificationPopups.js"; - -App.addIcons(`${App.configDir}/assets`); -App.config({ - style: "./style.css", - windows: [ - Bar(), - NotificationPopups(), - ], -}); - diff --git a/users/hu/packages/ags/config/style.css b/users/hu/packages/ags/config/style.css deleted file mode 100644 index 93c8198..0000000 --- a/users/hu/packages/ags/config/style.css +++ /dev/null @@ -1,206 +0,0 @@ -* { - font-family: 'Go Mono Nerd Font'; - font-size: 12pt; -} - -window.bar { - background-color: @theme_bg_color; - color: @theme_fg_color; - border-bottom: 1px solid @theme_selected_bg_color; -} - -button { - min-width: 0; - padding: 0 6pt 0 6pt; - background-color: transparent; - margin: 3pt 0 3pt 0; -} - -button:active { - background-color: @theme_selected_bg_color; - color: @theme_bg_color; -} - -button:hover { - border-bottom: 3pt solid @theme_fg_color; - margin-bottom: 0pt; /* Prevent bar from resizing from added bottom length from the border */ -} - -label { - font-weight: bold; -} - -.workspaces button.focused { - border-bottom: 3pt solid @theme_selected_bg_color; - margin-bottom: 0pt ; /* Prevent bar from resizing from added bottom length from the border */ -} - -.client-title { - color: @theme_selected_bg_color; -} - -.notification { - color: yellow; -} - -/* -levelbar block, -highlight { - min-height: 40pt; -} -*/ - -window.notification-popups box.notifications { - padding: .5em; -} - -window.notification-popups * { - font-size: 10pt; -} - -.icon { - min-width: 38px; - min-height: 38px; - margin-right: 1em; -} - -.icon image { - font-size: 38px; - /* to center the icon */ - margin: 5px; - color: @theme_fg_color; -} - -.icon box { - min-width: 38px; - min-height: 38px; - border-radius: 7px; -} - -.notification { - min-width: 350px; - border-radius: 11px; - padding: 1em; - margin: .5em; - border: 1px solid @theme_selected_bg_color; - background-color: @theme_bg_color; -} - -.notification.critical { - border: 1px solid lightcoral; -} - -.title { - color: @theme_fg_color; -} - -.body { - color: @theme_unfocused_fg_color; -} - -.actions .action-button { - margin: 0 .4em; - margin-top: .8em; -} - -.actions .action-button:first-child { - margin-left: 0; -} - -.actions .action-button:last-child { - margin-right: 0; -} - -.qsd { - border: 1px solid @theme_selected_bg_color; - background-color: @theme_bg_color; - border-radius: 10pt; - padding: 12pt; - color: @theme_fg_color; -} - -.qsd-power { - border: 1px solid @theme_selected_bg_color; - border-radius: 10pt; - padding: 6pt; - margin-bottom: 6pt; -} - -.qsd-volume-mixer { - border: 1px solid @theme_selected_bg_color; - padding: 12pt; - border-radius: 10pt; -} - -.qsd-volume-slider-container { - min-width: 250pt; -} - -.volume-icon { - padding-right: 8pt; -} - -.app-mixer { - border: 1px solid @theme_selected_bg_color; - padding: 12pt; - border-radius: 10pt; - margin-top: 6pt; -} - -.app-mixer-label { - font-size: 10pt; -} - -.player { - border: 1px solid @theme_selected_bg_color; - padding: 12pt; - border-radius: 10pt; - margin-top: 8pt; - padding: 10px; - min-width: 350px; -} - -.player .img { - min-width: 100px; - min-height: 100px; - background-size: cover; - background-position: center; - border-radius: 13px; - margin-right: 1em; -} - -.player .title { - font-size: 1.2em; -} - -.player .artist { - font-size: 1.1em; - color: @insensitive_fg_color; -} - -.player scale.position { - padding: 0; - margin-bottom: .3em; -} - -.player scale.position trough { - min-height: 8px; -} - -.player scale.position highlight { - background-color: @theme_fg_color; -} - -.player scale.position slider { - all: unset; -} - -.player button { - min-height: 1em; - min-width: 1em; - padding: .3em; -} - -.player button.play-pause { - margin: 0 .3em; -} diff --git a/users/hu/packages/ags/config/vendor/Media.js b/users/hu/packages/ags/config/vendor/Media.js deleted file mode 100644 index d6871b4..0000000 --- a/users/hu/packages/ags/config/vendor/Media.js +++ /dev/null @@ -1,158 +0,0 @@ -/* - * This snippet is taken from the ags examples directory. It is licensed under GPLv3. - * More information available here: https://github.com/Aylur/ags/blob/main/LICENSE - * */ - -const mpris = await Service.import("mpris") -const players = mpris.bind("players") - -const FALLBACK_ICON = "audio-x-generic-symbolic" -const PLAY_ICON = "media-playback-start-symbolic" -const PAUSE_ICON = "media-playback-pause-symbolic" -const PREV_ICON = "media-skip-backward-symbolic" -const NEXT_ICON = "media-skip-forward-symbolic" - -/** @param {number} length */ -function lengthStr(length) { - const min = Math.floor(length / 60) - const sec = Math.floor(length % 60) - const sec0 = sec < 10 ? "0" : "" - return `${min}:${sec0}${sec}` -} - -/** @param {import('types/service/mpris').MprisPlayer} player */ -function Player(player) { - const img = Widget.Box({ - class_name: "img", - vpack: "start", - css: player.bind("cover_path").transform(p => ` - background-image: url('${p}'); - `), - }) - - const title = Widget.Label({ - class_name: "title", - wrap: true, - hpack: "start", - label: player.bind("track_title"), - }) - - const artist = Widget.Label({ - class_name: "artist", - wrap: true, - hpack: "start", - label: player.bind("track_artists").transform(a => a.join(", ")), - }) - - const positionSlider = Widget.Slider({ - class_name: "position", - draw_value: false, - on_change: ({ value }) => player.position = value * player.length, - visible: player.bind("length").as(l => l > 0), - setup: self => { - function update() { - const value = player.position / player.length - self.value = value > 0 ? value : 0 - } - self.hook(player, update) - self.hook(player, update, "position") - self.poll(1000, update) - }, - }) - - const positionLabel = Widget.Label({ - class_name: "position", - hpack: "start", - setup: self => { - const update = (_, time) => { - self.label = lengthStr(time || player.position) - self.visible = player.length > 0 - } - - self.hook(player, update, "position") - self.poll(1000, update) - }, - }) - - const lengthLabel = Widget.Label({ - class_name: "length", - hpack: "end", - visible: player.bind("length").transform(l => l > 0), - label: player.bind("length").transform(lengthStr), - }) - - const icon = Widget.Icon({ - class_name: "icon", - hexpand: true, - hpack: "end", - vpack: "start", - tooltip_text: player.identity || "", - icon: player.bind("entry").transform(entry => { - const name = `${entry}-symbolic` - return Utils.lookUpIcon(name) ? name : FALLBACK_ICON - }), - }) - - const playPause = Widget.Button({ - class_name: "play-pause", - on_clicked: () => player.playPause(), - visible: player.bind("can_play"), - child: Widget.Icon({ - icon: player.bind("play_back_status").transform(s => { - switch (s) { - case "Playing": return PAUSE_ICON - case "Paused": - case "Stopped": return PLAY_ICON - } - }), - }), - }) - - const prev = Widget.Button({ - on_clicked: () => player.previous(), - visible: player.bind("can_go_prev"), - child: Widget.Icon(PREV_ICON), - }) - - const next = Widget.Button({ - on_clicked: () => player.next(), - visible: player.bind("can_go_next"), - child: Widget.Icon(NEXT_ICON), - }) - - return Widget.Box( - { class_name: "player" }, - img, - Widget.Box( - { - vertical: true, - hexpand: true, - }, - Widget.Box([ - title, - icon, - ]), - artist, - Widget.Box({ vexpand: true }), - positionSlider, - Widget.CenterBox({ - start_widget: positionLabel, - center_widget: Widget.Box([ - prev, - playPause, - next, - ]), - end_widget: lengthLabel, - }), - ), - ) -} - -export function Media() { - return Widget.Box({ - vertical: true, - css: "min-height: 2px; min-width: 2px;", // small hack to make it visible - visible: players.as(p => p.length > 0), - children: players.as(p => p.map(Player)), - }) -} diff --git a/users/hu/packages/ags/config/vendor/notificationPopups.js b/users/hu/packages/ags/config/vendor/notificationPopups.js deleted file mode 100644 index 781c3eb..0000000 --- a/users/hu/packages/ags/config/vendor/notificationPopups.js +++ /dev/null @@ -1,148 +0,0 @@ -/* - * This snippet is taken from the ags examples directory. It is licensed under GPLv3. - * More information available here: https://github.com/Aylur/ags/blob/main/LICENSE - * - * Modifications have been made. - * */ - -const notifications = await Service.import("notifications") - -/** @param {import('resource:///com/github/Aylur/ags/service/notifications.js').Notification} n */ -function NotificationIcon({ 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), - }) -} - -/** @param {import('resource:///com/github/Aylur/ags/service/notifications.js').Notification} n */ -function Notification(n) { - /* Setting the max width in gtk css is not supported for some reason - * so we have to split the length of the lines here by inserting newline - * characters where appropriate. */ - let body_text = n.body; - for (let i = 0; i < body_text.length; i += 40) { - let left = body_text.substring(0, i); - let right = body_text.substring(i); - body_text = left + "\n" + right; - } - - const icon = Widget.Box({ - vpack: "start", - class_name: "icon", - child: NotificationIcon(n), - }) - - const title = Widget.Label({ - class_name: "title", - xalign: 0, - justification: "left", - hexpand: true, - max_width_chars: 24, - truncate: "end", - wrap: true, - label: n.summary, - use_markup: true, - }) - - const body = Widget.Label({ - class_name: "body", - hexpand: true, - use_markup: true, - xalign: 0, - justification: "left", - label: body_text, - wrap: 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), - })), - }) - - return Widget.EventBox( - { - attribute: { id: n.id }, - on_primary_click: n.dismiss, - }, - Widget.Box( - { - class_name: `notification ${n.urgency}`, - vertical: true, - }, - Widget.Box([ - icon, - Widget.Box( - { vertical: true }, - title, - body, - ), - ]), - actions, - ), - ) -} - -export function NotificationPopups(monitor = 0) { - const list = Widget.Box({ - vertical: true, - children: notifications.popups.map(Notification), - }) - - function onNotified(_, /** @type {number} */ id) { - const n = notifications.getNotification(id) - if (n) - list.children = [Notification(n), ...list.children] - } - - function onDismissed(_, /** @type {number} */ id) { - list.children.find(n => n.attribute.id === id)?.destroy() - } - - list.hook(notifications, onNotified, "notified") - .hook(notifications, onDismissed, "dismissed") - - return Widget.Window({ - monitor, - name: `notifications${monitor}`, - class_name: "notification-popups", - anchor: ["top", "right"], - child: Widget.Box({ - css: "min-width: 2px; min-height: 2px;", - class_name: "notifications", - vertical: true, - child: list, - - /** this is a simple one liner that could be used instead of - hooking into the 'notified' and 'dismissed' signals. - but its not very optimized becuase it will recreate - the whole list everytime a notification is added or dismissed */ - // children: notifications.bind('popups') - // .as(popups => popups.map(Notification)) - }), - }) -} - diff --git a/users/hu/packages/hyprland.nix b/users/hu/packages/hyprland.nix index 8be0514..7b45ef9 100644 --- a/users/hu/packages/hyprland.nix +++ b/users/hu/packages/hyprland.nix @@ -34,9 +34,9 @@ }; general = { - gaps_in = 5; - gaps_out = 10; - border_size = 1; + gaps_in = 3; + gaps_out = 6; + border_size = 2; layout = "master"; allow_tearing = true; "col.inactive_border" = "rgb(242424)"; @@ -99,10 +99,6 @@ "$mod SHIFT, 8, movetoworkspace, 8" "$mod SHIFT, 9, movetoworkspace, 9" ]; - - exec-once = [ - "ags" - ]; }; }; } diff --git a/users/hu/packages/waybar.nix b/users/hu/packages/waybar.nix new file mode 100644 index 0000000..7682d64 --- /dev/null +++ b/users/hu/packages/waybar.nix @@ -0,0 +1,53 @@ +{ ... }: + +{ + programs.waybar = { + enable = true; + systemd = { + enable = true; + }; + + settings = { + bar = { + layer = "top"; + position = "top"; + height = 32; + output = [ + "DP-1" + ]; + + modules-left = [ "hyprland/workspaces" "hyprland/submap" ]; + modules-center = [ "hyprland/window" ]; + modules-right = [ "clock" ]; + }; + }; + style = '' + * { + all: unset; + border-radius: 0; + font-family: "Go Mono Nerd Font"; + font-size: 11pt; + min-height: 0; + } + + window#waybar { + color: #c5c9c5; + background: #181616; + border-bottom: 2px solid rgba(53,132,228, 1); + } + + #workspaces button { + padding: 0 8pt 0 8pt; + } + + #workspaces button.active { + color: #3584e4; + } + + #clock { + padding: 0 8pt 0 8pt; + } + ''; + }; +} + diff --git a/users/hu/user.nix b/users/hu/user.nix index 6a2babb..93ba187 100644 --- a/users/hu/user.nix +++ b/users/hu/user.nix @@ -39,7 +39,7 @@ ./packages/rofi.nix ./packages/fastfetch.nix ./packages/nvim/neovim.nix - ./packages/ags/ags.nix + ./packages/waybar.nix ]; }; };