1
0
Fork 0

Add mostly final ags config

This commit is contained in:
Avery 2024-09-08 20:21:34 +02:00
parent c310042564
commit bce65f6835
Signed by: Avery
GPG key ID: B684FD451B692E04
23 changed files with 999 additions and 156 deletions

View file

@ -13,7 +13,7 @@ include_toc: true
#### Programs
# TODO: add a file manager
# TODO: add a file manager and desktop manager
| Name | Type |
| -----------------: | :------------------ |
@ -23,6 +23,7 @@ include_toc: true
| Neovim | Text editor |
| Firefox | Web browser |
| qBittorrent | Torrent client |
| mpv | Video player |
| LibreOffice | Office suite |
| GIMP | Photo editor |
| Inkscape | Vector image editor |

View file

@ -1,4 +1,4 @@
{ pkgs, config, inputs, ... }: {
{ pkgs, config, ... }: {
home = {
username = "avery";
homeDirectory = "/home/avery";

View file

@ -17,6 +17,7 @@
users = {
defaultUserShell = pkgs.zsh;
users.avery = {
description = "Avery";
extraGroups = [ "wheel" ];
isNormalUser = true;
hashedPasswordFile = config.sops.secrets.avery_password.path;

View file

@ -67,7 +67,7 @@
typeset -g POWERLEVEL9K_EMPTY_LINE_RIGHT_PROMPT_FIRST_SEGMENT_START_SYMBOL='%{%}'
fi
typeset -g POWERLEVEL9K_BACKGROUND="#181825"
typeset -g POWERLEVEL9K_BACKGROUND="black"
typeset -g POWERLEVEL9K_LEFT_SUBSEGMENT_SEPARATOR=''
typeset -g POWERLEVEL9K_RIGHT_SUBSEGMENT_SEPARATOR=''
@ -93,11 +93,11 @@
typeset -g POWERLEVEL9K_PROMPT_CHAR_LEFT_PROMPT_FIRST_SEGMENT_START_SYMBOL=
typeset -g POWERLEVEL9K_PROMPT_CHAR_LEFT_{LEFT,RIGHT}_WHITESPACE=
typeset -g POWERLEVEL9K_DIR_FOREGROUND="#89dceb"
typeset -g POWERLEVEL9K_DIR_FOREGROUND="blue"
typeset -g POWERLEVEL9K_SHORTEN_STRATEGY=truncate_to_unique
typeset -g POWERLEVEL9K_SHORTEN_DELIMITER=
typeset -g POWERLEVEL9K_DIR_SHORTENED_FOREGROUND="#89dceb"
typeset -g POWERLEVEL9K_DIR_ANCHOR_FOREGROUND="#74c7ec"
typeset -g POWERLEVEL9K_DIR_SHORTENED_FOREGROUND="blue"
typeset -g POWERLEVEL9K_DIR_ANCHOR_FOREGROUND="blue"
typeset -g POWERLEVEL9K_DIR_ANCHOR_BOLD=true
local anchor_files=(
.bzr
@ -544,7 +544,7 @@
typeset -g POWERLEVEL9K_WIFI_FOREGROUND=68
typeset -g POWERLEVEL9K_TIME_FOREGROUND="#cdd6f4"
typeset -g POWERLEVEL9K_TIME_FOREGROUND="white"
typeset -g POWERLEVEL9K_TIME_FORMAT='%D{%H:%M:%S}'
typeset -g POWERLEVEL9K_TIME_UPDATE_ON_COMMAND=false
typeset -g POWERLEVEL9K_TIME_PREFIX='%F{#bac2de}at '

View file

@ -0,0 +1,91 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
version="1.1"
id="svg1"
width="108"
height="108"
viewBox="0 0 108 108"
sodipodi:docname="gpu-symbolic.svg"
inkscape:version="1.3.2 (091e20ef0f, 2023-11-25)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs1" />
<sodipodi:namedview
id="namedview1"
pagecolor="#6f6f6f"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
showgrid="false"
inkscape:zoom="7.3397687"
inkscape:cx="55.110729"
inkscape:cy="64.034716"
inkscape:window-width="2508"
inkscape:window-height="1432"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="0"
inkscape:current-layer="svg1" />
<g
id="g2"
transform="matrix(0.99893805,0,0,0.99893805,-8.5128578,-11.201106)">
<circle
style="display:inline;fill:#ffffff;stroke-width:0.58613"
id="circle2"
cx="83.544762"
cy="66.08548"
r="9.1276808" />
<path
id="rect21"
style="fill:#ffffff;stroke-width:0.995843"
d="m 30.796875,34.894531 c -6.696118,0 -12.085937,5.391773 -12.085937,12.087891 v 38.207031 c 0,6.696118 5.389819,12.085938 12.085937,12.085938 h 73.753905 c 6.69612,0 12.08594,-5.38982 12.08594,-12.085938 V 46.982422 c 0,-6.696118 -5.38982,-12.087891 -12.08594,-12.087891 z M 83.544922,50.511719 A 15.572804,15.572804 0 0 1 99.117188,66.085938 15.572804,15.572804 0 0 1 83.544922,81.658203 15.572804,15.572804 0 0 1 67.972656,66.085938 15.572804,15.572804 0 0 1 83.544922,50.511719 Z" />
<rect
style="fill:#ffffff;stroke-width:0.658796"
id="rect22"
width="42.856728"
height="62.381294"
x="18.710653"
y="34.894833"
rx="0" />
<rect
style="fill:#ffffff;stroke-width:0.933947"
id="rect23"
width="7.2571454"
height="17.917709"
x="18.711"
y="90.456131"
ry="2" />
<rect
style="fill:#ffffff;stroke-width:0.966324"
id="rect24"
width="48.787354"
height="13.831649"
x="51.524902"
y="93.012451"
ry="1.8675644" />
<rect
style="fill:#ffffff"
id="rect1"
width="8.3176746"
height="15.143582"
x="18.711"
y="22.167"
ry="2" />
<rect
style="fill:#ffffff;stroke-width:0.887038"
id="rect2"
width="15.388794"
height="8.3993673"
x="8.5219078"
y="22.167"
ry="2" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.8 KiB

View file

@ -1,10 +1,12 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
viewBox="0 0 576 512"
viewBox="0 0 576 576"
version="1.1"
id="svg1"
sodipodi:docname="memory-symbolic.svg"
sodipodi:docname="ram-custom-symbolic.svg"
inkscape:version="1.3.2 (091e20ef0f, 2023-11-25)"
width="576"
height="576"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
@ -13,25 +15,25 @@
id="defs1" />
<sodipodi:namedview
id="namedview1"
pagecolor="#ffffff"
pagecolor="#000000"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:zoom="0.18793403"
inkscape:cx="-106.42032"
inkscape:cy="1069.5242"
inkscape:window-width="1254"
inkscape:window-height="714"
inkscape:zoom="1.5034722"
inkscape:cx="192.55427"
inkscape:cy="351.85219"
inkscape:window-width="2508"
inkscape:window-height="1432"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="0"
inkscape:current-layer="svg1" />
<!--!Font Awesome Free 6.6.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2024 Fonticons, Inc.-->
<path
d="M64 64C28.7 64 0 92.7 0 128l0 7.4c0 6.8 4.4 12.6 10.1 16.3C23.3 160.3 32 175.1 32 192s-8.7 31.7-21.9 40.3C4.4 236 0 241.8 0 248.6L0 320l576 0 0-71.4c0-6.8-4.4-12.6-10.1-16.3C552.7 223.7 544 208.9 544 192s8.7-31.7 21.9-40.3c5.7-3.7 10.1-9.5 10.1-16.3l0-7.4c0-35.3-28.7-64-64-64L64 64zM576 352L0 352l0 64c0 17.7 14.3 32 32 32l48 0 0-32c0-8.8 7.2-16 16-16s16 7.2 16 16l0 32 96 0 0-32c0-8.8 7.2-16 16-16s16 7.2 16 16l0 32 96 0 0-32c0-8.8 7.2-16 16-16s16 7.2 16 16l0 32 96 0 0-32c0-8.8 7.2-16 16-16s16 7.2 16 16l0 32 48 0c17.7 0 32-14.3 32-32l0-64zM192 160l0 64c0 17.7-14.3 32-32 32s-32-14.3-32-32l0-64c0-17.7 14.3-32 32-32s32 14.3 32 32zm128 0l0 64c0 17.7-14.3 32-32 32s-32-14.3-32-32l0-64c0-17.7 14.3-32 32-32s32 14.3 32 32zm128 0l0 64c0 17.7-14.3 32-32 32s-32-14.3-32-32l0-64c0-17.7 14.3-32 32-32s32 14.3 32 32z"
d="M 64,96 C 28.7,96 0,124.7 0,160 v 7.4 c 0,6.8 4.4,12.6 10.1,16.3 13.2,8.6 21.9,23.4 21.9,40.3 0,16.9 -8.7,31.7 -21.9,40.3 C 4.4,268 0,273.8 0,280.6 V 352 H 576 V 280.6 C 576,273.8 571.6,268 565.9,264.3 552.7,255.7 544,240.9 544,224 c 0,-16.9 8.7,-31.7 21.9,-40.3 5.7,-3.7 10.1,-9.5 10.1,-16.3 V 160 C 576,124.7 547.3,96 512,96 Z M 576,384 H 0 v 64 c 0,17.7 14.3,32 32,32 h 48 v -32 c 0,-8.8 7.2,-16 16,-16 8.8,0 16,7.2 16,16 v 32 h 96 v -32 c 0,-8.8 7.2,-16 16,-16 8.8,0 16,7.2 16,16 v 32 h 96 v -32 c 0,-8.8 7.2,-16 16,-16 8.8,0 16,7.2 16,16 v 32 h 96 v -32 c 0,-8.8 7.2,-16 16,-16 8.8,0 16,7.2 16,16 v 32 h 48 c 17.7,0 32,-14.3 32,-32 z M 192,192 v 64 c 0,17.7 -14.3,32 -32,32 -17.7,0 -32,-14.3 -32,-32 v -64 c 0,-17.7 14.3,-32 32,-32 17.7,0 32,14.3 32,32 z m 128,0 v 64 c 0,17.7 -14.3,32 -32,32 -17.7,0 -32,-14.3 -32,-32 v -64 c 0,-17.7 14.3,-32 32,-32 17.7,0 32,14.3 32,32 z m 128,0 v 64 c 0,17.7 -14.3,32 -32,32 -17.7,0 -32,-14.3 -32,-32 v -64 c 0,-17.7 14.3,-32 32,-32 17.7,0 32,14.3 32,32 z"
id="path1"
style="fill:#ffffff" />
</svg>

Before

Width:  |  Height:  |  Size: 2 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

Before After
Before After

View file

@ -1,13 +1,17 @@
import cpu from "./services/cpu.js";
import ram from "./services/ram.js";
import { ProfilePicture } from "./widgets/bar/profile-picture.js";
import {
ProcessorUsage,
MemoryUsage,
graphics_card_usage,
volume_widget,
} from "./widgets/bar/system-stats.js";
import { extended_bar } from "./widgets/bar-extended/extended-bar.js";
import { launcher } from "./widgets/launcher/launcher.js";
const { speaker } = await Service.import("audio");
import { popup_clock } from "./widgets/popup-clock/popup-clock.js";
import { date } from "./state.js";
const mpris = await Service.import("mpris");
const sway = await Service.import("sway");
const players = mpris.bind("players");
const date = Variable("", {
poll: [1000, 'date "+%H %M %S %b %e"'],
});
App.addIcons(`${App.configDir}/assets`);
@ -43,67 +47,6 @@ function Workspaces() {
});
}
function ProcessorUsage() {
return Widget.Box({
class_name: "system-stats",
css: cpu.bind("current-usage").as((usage) => {
let level = (usage * 100).toFixed(0);
return `
background: linear-gradient(
90deg, rgba(26, 27, 38, 0.6) ${level}%, rgba(26, 27, 38, 0.4) ${level}%
)`;
}),
children: [
Widget.Icon({
class_names: ["system-stats-icon"],
icon: "microchip-symbolic",
size: 16,
}),
Widget.Label({
class_names: ["system-stats-text"],
hexpand: true,
label: cpu.bind("current-usage").as((usage) => {
return `${(usage * 100).toFixed(0)}%`;
}),
}),
],
vertical: true,
});
}
function MemoryUsage() {
return Widget.Box({
class_name: "system-stats",
css: ram.bind("current-usage-percentage").as((usage) => {
let level = (usage * 100).toFixed(0);
return `
background: linear-gradient(
90deg, rgba(26, 27, 38, 0.6) ${level}%, rgba(26, 27, 38, 0.4) ${level}%
)`;
}),
children: [
Widget.Icon({
class_names: ["system-stats-icon"],
icon: "ram-custom-symbolic",
size: 16,
}),
Widget.Label({
class_names: ["system-stats-text"],
hexpand: true,
label: ram.bind("current-usage-percentage").as((usage) => {
return `${(usage * 100).toFixed(0)}%`;
}),
}),
],
tooltip_text: ram.bind("current-usage").as((usage) => {
let usageGb = (usage / 1024 ** 2).toFixed(2);
let totalGb = (ram.total_available / 1024 ** 2).toFixed(2);
return `${usageGb}/${totalGb}GB (${(ram.current_usage_percentage * 100).toFixed(2)}%)`;
}),
vertical: true,
});
}
function CurrentSong(player) {
return Widget.Box({
class_name: "music-indicator",
@ -155,57 +98,6 @@ function CTest() {
});
}
function ProfilePicture() {
return Widget.Box({
class_name: "profile-picture",
css: "background-image: url('/home/avery/.face.icon'); background-size: cover",
});
}
function VolumeWidget() {
return Widget.Box({
class_name: "volume-widget",
children: [
Widget.Icon({
icon: speaker.bind("volume").as((l) => {
let level = l.toFixed(2) * 100;
if (level == 0) {
return "audio-volume-muted";
} else if (level > 0 && level <= 30) {
return "audio-volume-low";
} else if (level > 30 && level <= 70) {
return "audio-volume-medium";
} else {
return "audio-volume-high";
}
}),
size: 10,
}),
Widget.Box({
class_name: "volume-box",
css: speaker.bind("volume").as((l) => {
let level = l.toFixed(2) * 100;
if (level >= 0 && level <= 100) {
return `
background: linear-gradient(
90deg, #7aa2f7 ${level}%, #24283b ${level}%
);
`;
} else if (level > 100 && level <= 200) {
return `
background: linear-gradient(
90deg, #f7768e ${level - 100}%, #7aa2f7 ${level - 100}%
);
`;
} else {
return "background: #f7768e";
}
}),
hpack: "fill",
}),
],
});
}
function ClockWidget() {
return Widget.Box({
children: [
@ -239,11 +131,14 @@ const barContainer = Widget.Box({
spacing: 6,
vertical: true,
children: [
ProfilePicture(),
Workspaces(),
Widget.Box({ expand: true, vpack: "fill" }), // Separator
CTest(),
ProcessorUsage(),
MemoryUsage(),
graphics_card_usage,
volume_widget,
ClockWidget(),
],
});
@ -252,6 +147,7 @@ const bar = Widget.Window({
name: "bar",
anchor: ["left", "top", "bottom"],
exclusivity: "exclusive",
margins: [4, 0, 4, 4],
child: barContainer,
});
@ -266,5 +162,5 @@ Utils.monitorFile(
App.config({
style: "./style.css",
windows: [bar, launcher],
windows: [bar, extended_bar, launcher, popup_clock],
});

View file

@ -1,16 +1,25 @@
class CPUService extends Service {
static {
Service.register(this, {}, { "current-usage": ["float", "r"] });
Service.register(
this,
{},
{ "current-usage": ["float", "r"], temperature: ["float", "r"] },
);
}
#previousIdle = 0.0;
#previousTotal = 0.0;
#currentUsage = 0.0;
#temperature = 0.0;
get current_usage() {
return this.#currentUsage;
}
get temperature() {
return this.#temperature;
}
constructor() {
super();
this.#update();
@ -20,6 +29,10 @@ class CPUService extends Service {
}
#update() {
this.#temperature =
Utils.exec(
"sh -c 'cat /sys/devices/pci0000:00/0000:00:18.3/hwmon/hwmon1/temp1_input'",
) / 1000;
const currentValues = Utils.exec(
"sh -c 'cat /proc/stat | grep cpu | head -n 1 | tr -s \" \"'",
)
@ -33,6 +46,7 @@ class CPUService extends Service {
this.#previousIdle = idle;
this.#previousTotal = total;
this.changed("current-usage");
this.changed("temperature");
}
}

View file

@ -0,0 +1,43 @@
class GPUService extends Service {
static {
Service.register(
this,
{},
{ "current-usage": ["float", "r"], temperature: ["float", "r"] },
);
}
#currentUsage = 0;
#temperature = 0;
get current_usage() {
return this.#currentUsage;
}
get temperature() {
return this.#temperature;
}
constructor() {
super();
this.#update();
const interval = setInterval(() => {
this.#update();
}, 2000);
}
#update() {
this.#currentUsage = Utils.exec(
"sh -c 'cat /sys/class/drm/card?/device/gpu_busy_percent'",
);
this.#temperature =
Utils.exec(
"sh -c 'cat /sys/class/drm/card?/device/hwmon/hwmon?/temp1_input'",
) / 1000;
this.changed("current-usage");
this.changed("temperature");
}
}
const gpu = new GPUService();
export default gpu;

View file

@ -0,0 +1,55 @@
export const date = Variable("", {
poll: [1000, 'date "+%H %M %S %Y-%m-%d"'],
});
class User {
constructor(user_string) {
var split_string = user_string.split(":");
this.username = split_string[0];
this.uid = split_string[2];
this.gid = split_string[3];
this.real_name = split_string[4];
if (this.real_name == "") {
this.real_name = this.username;
}
this.home_directory = split_string[5];
}
}
var is_bar_extended = false;
var current_menu = "bar";
// TODO(maybe): watch for changes to real name
var uid = Utils.exec("sh -c 'echo $UID'");
export const CURRENT_USER = new User(
Utils.exec(`grep -P '\\w+:x:${uid}' /etc/passwd`),
);
export const HOSTNAME = Utils.exec("hostname");
export function on_window_event(_, window_name, visible) {
console.log(`is ${window_name} visible => ${visible}`);
console.log(`current menu is ${current_menu}`);
console.log(`is bar extended => ${is_bar_extended}`);
if (window_name != "bar" && visible) {
var previous_menu = current_menu;
current_menu = window_name;
if (previous_menu != "bar") {
App.getWindow(previous_menu).visible = false;
}
App.getWindow("bar").css = "opacity: 0";
if (window_name == "bar_extended") {
is_bar_extended = true;
}
} else if (window_name != "bar" && !visible) {
if (
(window_name == "bar_extended" && current_menu == "bar_extended") ||
!is_bar_extended
) {
is_bar_extended = false;
current_menu = "bar";
App.getWindow("bar").css = "opacity: 1";
} else if (window_name != "bar_extended" && is_bar_extended) {
App.getWindow("bar_extended").visible = true;
}
}
}

View file

@ -11,11 +11,15 @@ window {
.bar {
background-color: @bg;
border-radius: 8px;
margin: 4px 0px 4px 4px;
padding: 4px 4px;
min-width: 32px;
}
.extended_bar,
.launcher {
min-width: 360px;
}
.volume-widget {
margin: 4px;
}
@ -30,7 +34,7 @@ window {
border-radius: 8px;
background-color: @bg;
font-weight: bold;
font-family: "Iosevka Nerd Font";
font-family: monospace;
font-size: 1.2em;
padding: 4px 0;
}
@ -67,8 +71,8 @@ window {
background-color: @bg;
border-radius: 8px;
color: white;
font-family: "Iosevka Nerd Font";
font-weight: bold;
font-family: monospace;
font-weight: 700;
font-size: 0.95em;
padding: 4px 0;
}
@ -77,7 +81,7 @@ window {
background-color: @bg;
border-radius: 8px;
color: #c0caf5;
font-family: "Iosevka Nerd Font";
font-family: monospace;
font-weight: bold;
font-size: 1em;
min-height: 20px;
@ -89,13 +93,11 @@ window {
}
.occupied {
border-radius: 8px;
min-width: 24px;
}
.active {
color: @bg-noa;
border-radius: 8px;
min-width: 32px;
}
@ -158,7 +160,6 @@ window {
.launcher-search:focus {
border: 2px solid white;
outline: none;
}
@ -180,6 +181,117 @@ window {
}
.application_name {
font-size: 1.4em;
font-size: 1.2em;
font-weight: 500;
}
/*
* Extended bar
*/
.profile_block {
background-color: @bg;
background-blend-mode: darken;
border-radius: 8px;
color: white;
padding: 4px;
}
.username {
font-weight: 600;
font-size: 1.4em;
text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.6);
}
.hostname {
font-weight: 600;
font-size: 1.1em;
color: rgba(255, 255, 255, 0.6);
font-family: monospace;
}
.workspace-button-big {
color: white;
font-family: "sans-serif";
font-weight: 400;
padding: 4px 8px;
}
.active {
color: @bg-noa;
}
.workspace-name {
font-weight: 500;
font-size: 1.2em;
}
.clock-big {
font-size: 1.4em;
color: white;
}
.system-stats-big {
padding: 4px 8px;
}
.system-stats-title {
font-family: sans-serif;
font-size: 1.2em;
font-weight: 500;
}
.currently-playing-big {
background-color: @bg;
border-radius: 8px;
padding: 4px;
}
.album-art-big {
border-radius: 8px;
min-width: 72px;
min-height: 72px;
}
.currently-playing-title {
color: white;
font-size: 1.2em;
font-weight: 700;
text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.2);
}
.currently-playing-artists {
color: white;
font-weight: 600;
text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.2);
}
calendar {
background-color: @bg;
border: none;
border-radius: 8px;
color: rgb(220, 220, 220);
font-family: sans-serif;
font-weight: 500;
padding: 1px;
}
calendar .header,
calendar .highlight {
background-color: @normal;
color: white;
}
calendar .button {
background-color: transparent;
color: white;
}
calendar:selected {
background-color: rgba(255, 255, 255, 0.8);
color: black;
}
calendar:indeterminate {
color: rgb(90, 90, 90);
}

View file

@ -0,0 +1,41 @@
import { date } from "../../state.js";
function BlinkingDots() {
return Widget.Label({
class_name: "blinking-dots",
label: ":",
});
}
export function Clock() {
return Widget.Box({
children: [
Widget.Box({ hexpand: true, hpack: "fill" }), // Separator
Widget.Box({
children: [
Widget.Label({
label: date.bind().as((d) => {
return d.split(" ")[0];
}),
}),
BlinkingDots(),
Widget.Label({
label: date.bind().as((d) => {
return d.split(" ")[1];
}),
}),
BlinkingDots(),
Widget.Label({
label: date.bind().as((d) => {
return d.split(" ")[2];
}),
}),
],
}),
Widget.Box({ hexpand: true, hpack: "fill" }), // Separator
],
class_names: ["clock", "clock-big"],
hpack: "fill",
spacing: 8,
});
}

View file

@ -0,0 +1,78 @@
const mpris = await Service.import("mpris");
const players = mpris.bind("players");
// TODO: rework
export const currently_playing_controller = Widget.Box({
vertical: true,
visible: players.as((p) => p.length > 0),
children: players.as((p) => p.map(CurrentlyPlaying)),
});
function CurrentlyPlaying(player) {
return Widget.Box({
class_name: "currently-playing-big",
css: player.bind("cover_path").as((url) => {
if (url == undefined) {
return "";
}
console.log(url);
return `
background-image: url('${url}');
background-blend-mode: darken;
background-position: center;
background-size: cover;
`;
}),
spacing: 4,
children: [
Widget.Box({
class_name: "album-art-big",
css: player.bind("cover_path").as((url) => {
if (url == undefined) {
return `
background-color: rgba(0, 0, 0, 0.2);
background-image: url('${App.configDir}/assets/music-symbolic.svg');
background-size: 50% 50%;
background-repeat: no-repeat;
background-position: center;
`;
}
return `background-image: url('${url}'); background-size: cover;`;
}),
}),
Widget.Box({
children: [
Widget.Label({
class_name: "currently-playing-title",
label: player.bind("track-title"),
xalign: 0.5,
hexpand: true,
truncate: "end",
}),
Widget.Label({
class_name: "currently-playing-artists",
label: player.bind("track-artists").as((artists) => {
return artists.join(", ");
}),
xalign: 0.5,
hexpand: true,
truncate: "end",
}),
],
vpack: "center",
vertical: true,
}),
// Widget.Icon({
// class_name: "playback-status",
// icon: player.bind("play-back-status").as((status) => {
// if (status == "Playing") {
// return "media-playback-start";
// } else if (status == "Paused") {
// return "media-playback-pause";
// }
// return "";
// }),
// }),
],
});
}

View file

@ -0,0 +1,45 @@
import { Clock } from "./big-clock.js";
import { currently_playing_controller } from "./currently-playing.js";
import { ProfileBlock } from "./profile-block.js";
import {
graphics_card_usage,
memory_usage,
processor_usage,
volume_widget,
} from "./system-stats-big.js";
import { workspaces } from "./workspaces.js";
import { on_window_event } from "../../state.js";
export const extended_bar = Widget.Window({
name: "bar_extended",
anchor: ["left", "top", "bottom"],
margins: [4, 0, 4, 4],
child: Widget.Box({
class_names: ["bar", "extended_bar"],
vpack: "fill",
spacing: 6,
vertical: true,
children: [
ProfileBlock(),
workspaces,
Widget.Box({ expand: true, vpack: "fill" }), // Separator
currently_playing_controller,
processor_usage,
memory_usage,
graphics_card_usage,
volume_widget,
Widget.Calendar({}),
Clock(),
],
}),
exclusivity: "ignore",
visible: false,
layer: "overlay",
setup: (self) => {
self.hook(App, (_, window_name, visible) => {
if (window_name == self.name) {
on_window_event(_, window_name, visible);
}
});
},
});

View file

@ -0,0 +1,54 @@
import { ProfilePicture } from "../bar/profile-picture.js";
import { CURRENT_USER, HOSTNAME } from "../../state.js";
const CURRENT_WALLPAPER_PATH =
"/home/avery/.local/share/wallpapers/.current_path";
const wallpaperPath = Variable(Utils.readFile(CURRENT_WALLPAPER_PATH));
const wallpaperMonitor = Utils.monitorFile(
CURRENT_WALLPAPER_PATH,
(file, event) => {
if (event === 1) {
wallpaperPath.value = Utils.readFile(file);
}
},
);
export function ProfileBlock() {
return Widget.Box({
class_name: "profile_block",
css: wallpaperPath.bind().as((path) => {
path =
path
.replace("\n", "")
.replace("/", "\\/")
.replace("wallpapers", "wallpaper_thumbnails") + ".jpg";
return `
background-image: url('${path}');
background-size: cover;
background-position: center;
`;
}),
spacing: 8,
children: [
ProfilePicture(40),
Widget.Box({
vertical: true,
vpack: "center",
children: [
Widget.Label({
class_name: "username",
label: CURRENT_USER.real_name,
xalign: 0,
}),
Widget.Label({
class_name: "hostname",
label: HOSTNAME,
xalign: 0,
}),
],
}),
],
});
}

View file

@ -0,0 +1,155 @@
import cpu from "../../services/cpu.js";
import ram from "../../services/ram.js";
import gpu from "../../services/gpu.js";
const { speaker } = await Service.import("audio");
const PROCESSOR_NAME = Utils.exec(
'bash -c \'cat /proc/cpuinfo | grep "model name" | head -n 1 | cut -d ":" -f 2 | cut -d " " -f 3,4,5\'',
);
const GRAPHICS_CARD_NAME = "Radeon RX 6700 XT";
export const processor_usage = Widget.Box({
class_names: ["system-stats", "system-stats-big"],
css: cpu.bind("current-usage").as((usage) => {
let level = (usage * 100).toFixed(0);
return `
background: linear-gradient(
90deg, rgba(26, 27, 38, 0.8) ${level}%, rgba(26, 27, 38, 0.4) ${level}%
)`;
}),
spacing: 6,
children: [
Widget.Icon({
class_names: ["system-stats-icon"],
icon: "microchip-symbolic",
size: 16,
}),
Widget.Label({
class_name: "system-stats-title",
label: PROCESSOR_NAME,
}),
Widget.Label({
class_name: "system-stats-text-big",
hexpand: true,
xalign: 1,
label: cpu.bind("current-usage").as((usage) => {
return `${(usage * 100).toFixed(0)}% (${cpu.temperature.toFixed(0)}ºC)`;
}),
}),
],
});
export const memory_usage = Widget.Box({
class_names: ["system-stats", "system-stats-big"],
css: ram.bind("current-usage-percentage").as((usage) => {
let level = (usage * 100).toFixed(0);
return `
background: linear-gradient(
90deg, rgba(26, 27, 38, 0.8) ${level}%, rgba(26, 27, 38, 0.4) ${level}%
)`;
}),
spacing: 6,
children: [
Widget.Icon({
class_names: ["system-stats-icon"],
icon: "ram-custom-symbolic",
size: 16,
}),
Widget.Label({
class_name: "system-stats-title",
label: "Memoria",
}),
Widget.Label({
class_name: "system-stats-text-big",
hexpand: true,
xalign: 1,
label: ram.bind("current-usage").as((usage) => {
let usageGb = (usage / 1024 ** 2).toFixed(2);
let totalGb = (ram.total_available / 1024 ** 2).toFixed(2);
return `${usageGb}/${totalGb}GiB (${(ram.current_usage_percentage * 100).toFixed(2)}%)`;
}),
}),
],
});
export const graphics_card_usage = Widget.Box({
class_names: ["system-stats", "system-stats-big"],
css: gpu.bind("current-usage").as((usage) => {
var level = Number(usage).toFixed(0);
return `
background: linear-gradient(
90deg, rgba(26, 27, 38, 0.8) ${level}%, rgba(26, 27, 38, 0.4) ${level}%
)`;
}),
spacing: 6,
children: [
Widget.Icon({
class_names: ["system-stats-icon"],
icon: "gpu-symbolic",
size: 16,
}),
Widget.Label({
class_name: "system-stats-title",
label: GRAPHICS_CARD_NAME,
}),
Widget.Label({
class_name: "system-stats-text-big",
hexpand: true,
xalign: 1,
label: gpu.bind("current-usage").as((usage) => {
return `${Number(usage).toFixed(0)}% (${gpu.temperature.toFixed(0)}ºC)`;
}),
}),
],
});
export const volume_widget = Widget.Box({
class_names: ["system-stats", "system-stats-big"],
css: speaker.bind("volume").as((l) => {
let level = l.toFixed(2) * 100;
if (level >= 0 && level <= 100) {
return `
background: linear-gradient(
90deg, rgba(26, 27, 38, 0.8) ${level}%, rgba(26, 27, 38, 0.4) ${level}%
);`;
} else if (level > 100 && level <= 200) {
return `
background: linear-gradient(
90deg, rgba(226, 27, 38, 0.4) ${level - 100}%, rgba(26, 27, 38, 0.8) ${level - 100}%
);`;
} else {
return "background: rgba(226, 27, 38, 0.4)";
}
}),
spacing: 6,
children: [
Widget.Icon({
class_names: ["system-stats-icon"],
icon: speaker.bind("volume").as((l) => {
let level = l.toFixed(2) * 100;
if (level == 0) {
return "audio-volume-muted";
} else if (level > 0 && level <= 30) {
return "audio-volume-low";
} else if (level > 30 && level <= 70) {
return "audio-volume-medium";
} else {
return "audio-volume-high";
}
}),
size: 16,
}),
Widget.Label({
class_name: "system-stats-title",
label: "Volumen",
}),
Widget.Label({
class_name: "system-stats-text-big",
hexpand: true,
xalign: 1,
label: speaker.bind("volume").as((l) => {
return `${(l * 100).toFixed(0)}%`;
}),
}),
],
});

View file

@ -0,0 +1,81 @@
const sway = await Service.import("sway");
function getWorkspaceWindows(node) {
var nodes = [];
node.nodes.concat(node.floating_nodes).forEach((child_node) => {
if (
child_node.app_id != undefined ||
child_node.window_properties != undefined
) {
nodes.push(child_node);
} else {
nodes = nodes.concat(getWorkspaceWindows(child_node));
}
});
return nodes;
}
export const workspaces = Widget.Box({
children: Array.from({ length: 10 }, (_, i) => {
i += 1;
return Widget.Box({
class_names: ["workspace-button", "workspace-button-big"],
spacing: 16,
children: [
Widget.Label({
class_name: "workspace-name",
label: `Escritorio ${i.toString()}`,
}),
Widget.Box({
children: [
Widget.Label({
label: "dummy",
hexpand: true,
xalign: 1,
truncate: "end",
setup: (label) => {
label.hook(sway, (label) => {
const ws = sway.getWorkspace(`${i}`);
if (ws === undefined) {
label.visible = false;
return;
}
var nodes = getWorkspaceWindows(ws);
if (nodes.length == 1) {
label.label = nodes[0].name;
label.visible = true;
} else if (nodes.length > 0) {
label.label = `${nodes.length} ventanas abiertas`;
label.visible = true;
} else {
label.label = "No hay ventanas abiertas";
label.visible = false;
}
});
},
}),
],
}),
],
setup: (btn) => {
btn.hook(
sway,
(btn) => {
const ws = sway.getWorkspace(`${i}`);
btn.toggleClassName(
"occupied",
ws?.nodes.length + ws?.floating_nodes.length > 0,
);
},
"notify::workspaces",
);
btn.hook(sway.active.workspace, (btn) => {
btn.toggleClassName("active", sway.active.workspace.name == i);
});
},
});
}),
spacing: 4,
vertical: true,
});

View file

@ -0,0 +1,12 @@
// TODO: user-agnostic, reload if changed
export function ProfilePicture(size = 32) {
return Widget.Box({
class_name: "profile-picture",
css: `
background-image: url('/home/avery/.face.icon');
background-size: cover;
min-width: ${size}px;
min-height: ${size}px;
`,
});
}

View file

@ -0,0 +1,141 @@
import cpu from "../../services/cpu.js";
import gpu from "../../services/gpu.js";
import ram from "../../services/ram.js";
const { speaker } = await Service.import("audio");
export function ProcessorUsage() {
return Widget.Box({
class_name: "system-stats",
css: cpu.bind("current-usage").as((usage) => {
let level = (usage * 100).toFixed(0);
return `
background: linear-gradient(
90deg, rgba(26, 27, 38, 0.8) ${level}%, rgba(26, 27, 38, 0.4) ${level}%
)`;
}),
spacing: 2,
children: [
Widget.Icon({
class_names: ["system-stats-icon"],
icon: "microchip-symbolic",
size: 16,
}),
Widget.Label({
class_names: ["system-stats-text"],
hexpand: true,
label: cpu.bind("current-usage").as((usage) => {
return `${(usage * 100).toFixed(0)}%`;
}),
}),
],
vertical: true,
});
}
export function MemoryUsage() {
return Widget.Box({
class_name: "system-stats",
css: ram.bind("current-usage-percentage").as((usage) => {
let level = (usage * 100).toFixed(0);
return `
background: linear-gradient(
90deg, rgba(26, 27, 38, 0.8) ${level}%, rgba(26, 27, 38, 0.4) ${level}%
)`;
}),
spacing: 2,
children: [
Widget.Icon({
class_names: ["system-stats-icon"],
icon: "ram-custom-symbolic",
size: 16,
}),
Widget.Label({
class_names: ["system-stats-text"],
hexpand: true,
label: ram.bind("current-usage-percentage").as((usage) => {
return `${(usage * 100).toFixed(0)}%`;
}),
}),
],
tooltip_text: ram.bind("current-usage").as((usage) => {
let usageGb = (usage / 1024 ** 2).toFixed(2);
let totalGb = (ram.total_available / 1024 ** 2).toFixed(2);
return `${usageGb}/${totalGb}GiB (${(ram.current_usage_percentage * 100).toFixed(2)}%)`;
}),
vertical: true,
});
}
export const graphics_card_usage = Widget.Box({
class_name: "system-stats",
css: gpu.bind("current-usage").as((usage) => {
var level = Number(usage).toFixed(0);
return `
background: linear-gradient(
90deg, rgba(26, 27, 38, 0.8) ${level}%, rgba(26, 27, 38, 0.4) ${level}%
)`;
}),
spacing: 2,
children: [
Widget.Icon({
class_names: ["system-stats-icon"],
icon: "gpu-symbolic",
size: 16,
}),
Widget.Label({
class_names: ["system-stats-text"],
hexpand: true,
label: gpu.bind("current-usage").as((usage) => {
return `${Number(usage).toFixed(0)}%`;
}),
}),
],
vertical: true,
});
export const volume_widget = Widget.Box({
class_name: "system-stats",
css: speaker.bind("volume").as((l) => {
let level = l.toFixed(2) * 100;
if (level >= 0 && level <= 100) {
return `
background: linear-gradient(
90deg, rgba(26, 27, 38, 0.8) ${level}%, rgba(26, 27, 38, 0.4) ${level}%
);`;
} else if (level > 100 && level <= 200) {
return `
background: linear-gradient(
90deg, rgba(226, 27, 38, 0.4) ${level - 100}%, rgba(26, 27, 38, 0.8) ${level - 100}%
);`;
} else {
return "background: rgba(226, 27, 38, 0.4)";
}
}),
spacing: 2,
vertical: true,
children: [
Widget.Icon({
class_names: ["system-stats-icon"],
icon: speaker.bind("volume").as((l) => {
let level = l.toFixed(2) * 100;
if (level == 0) {
return "audio-volume-muted";
} else if (level > 0 && level <= 30) {
return "audio-volume-low";
} else if (level > 30 && level <= 70) {
return "audio-volume-medium";
} else {
return "audio-volume-high";
}
}),
size: 16,
}),
Widget.Label({
class_name: "system-stats-text",
hexpand: true,
label: speaker.bind("volume").as((l) => {
return `${(l * 100).toFixed(0)}%`;
}),
}),
],
});

View file

@ -10,7 +10,7 @@ export const Application = (application) =>
children: [
Widget.Icon({
icon: application.icon_name || "",
size: 32,
size: 24,
}),
Widget.Label({
class_name: "application_name",
@ -20,6 +20,6 @@ export const Application = (application) =>
truncate: "end",
}),
],
spacing: 8,
spacing: 4,
}),
});

View file

@ -1,13 +1,14 @@
import { Application } from "./application.js";
import { on_window_event } from "../../state.js";
const { query } = await Service.import("applications");
const Launcher = ({ width = 500, height = 600, spacing = 4 }) => {
const Launcher = () => {
let applications = query("").map(Application);
const list = Widget.Box({
css: "background-color: transparent",
vertical: true,
spacing,
spacing: 4,
children: applications,
});
@ -54,20 +55,20 @@ const Launcher = ({ width = 500, height = 600, spacing = 4 }) => {
return Widget.Box({
class_name: "launcher",
vertical: true,
spacing,
spacing: 4,
children: [
searchBox,
Widget.Scrollable({
hscroll: "never",
css: `min-width: ${width}px; min-height: ${height}px;`,
child: list,
vexpand: true,
}),
],
setup: (self) =>
self.hook(App, (_, windowName, visible) => {
if (windowName == "launcher" && visible) {
self.hook(App, (_, window_name, visible) => {
if (window_name == "launcher" && visible) {
repopulate();
applications[0].grab_focus(); // Scrolls application list to top
searchBox.text = "";
searchBox.grab_focus();
}
@ -77,11 +78,20 @@ const Launcher = ({ width = 500, height = 600, spacing = 4 }) => {
export const launcher = Widget.Window({
name: "launcher",
setup: (self) =>
anchor: ["left", "top", "bottom"],
setup: (self) => {
self.hook(App, (_, window_name, visible) => {
if (window_name == self.name) {
on_window_event(_, window_name, visible);
}
});
self.keybind("Escape", () => {
App.closeWindow("launcher");
}),
});
},
visible: false,
margins: [4, 0, 4, 4],
exclusivity: "ignore",
keymode: "exclusive",
child: Launcher({}),
});

View file

@ -0,0 +1,10 @@
import { Clock } from "../bar-extended/big-clock.js";
export const popup_clock = Widget.Window({
name: "popup_clock",
visible: false,
anchor: ["right", "top"],
margins: [16, 16, 0, 0],
layer: "overlay",
child: Clock(),
});

View file

@ -1,4 +1,5 @@
{ ... }: {
{ pkgs, ... }: {
home.packages = with pkgs; [ pciutils ];
programs.ags = {
enable = true;
# configDir = ./widgets;