Merge branch 'myputer'
2
.gitignore
vendored
|
|
@ -1,2 +1,4 @@
|
|||
ISSUES/
|
||||
secrets/
|
||||
|
||||
result
|
||||
|
|
|
|||
25
DEVDOC.md
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
## Users
|
||||
|
||||
#### me
|
||||
My main personal account, used on my PC and laptop.
|
||||
Contains a hyprland graphical environment by default.
|
||||
|
||||
#### ae
|
||||
Primary account on my servers. Contains the bare
|
||||
essentials for my work, no graphical environment.
|
||||
|
||||
|
||||
#### friends
|
||||
A simple account I let me friends connect to.
|
||||
Limited functionality, mostly just for letting
|
||||
them test small things or for giving them files.
|
||||
|
||||
|
||||
## Setup Guide
|
||||
##### Adding a New Server
|
||||
Enable an ssh server on the remote host, then on the
|
||||
local machine set `.ssh/config` to have a profile for
|
||||
your desired host and have a key pair that's authorised
|
||||
to your desired user.
|
||||
|
||||
NOTE: these keys must have permission 600 (only readable/writable by you)
|
||||
0
INSPIRATION
Normal file → Executable file
15
TODO
Normal file → Executable file
|
|
@ -17,15 +17,20 @@ Get hyprcursor working with Bibata-Modern-Ice
|
|||
Get a GRUB theme working
|
||||
Get SDDM and a theme working
|
||||
|
||||
Make a custom hyprlock screen
|
||||
|
||||
|
||||
|
||||
Get waybar (or another bar) working
|
||||
|
||||
Get AGS working
|
||||
Make an applauncher in AGS
|
||||
Remove hyprland splash screen on init
|
||||
Made lolcathost home modular
|
||||
|
||||
Overtime just install more programs that I need regularly: ie
|
||||
- btop/htop/etc
|
||||
|
||||
Get GTK Bibata Cursors to be the same size as my system cursor (NOT SURE WHAT I DID...)
|
||||
|
||||
|
||||
Get waybar (or another bar) working
|
||||
|
||||
Get a QT theme
|
||||
|
||||
|
|
@ -35,12 +40,10 @@ Bind new terminal to SUPER+Enter instead of SUPER+Q
|
|||
|
||||
Join Rio Terminal's discord and ask if they support nerdfonts or if I'm doing something wrong
|
||||
|
||||
Figure out how to modularise my dotfiles
|
||||
|
||||
|
||||
Change Dell loading screen (Boot Graphics Resource Table, aka BGRT)
|
||||
|
||||
Get GTK Bibata Cursors to be the same size as my system cursor
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
3
TODO_UI
Executable file
|
|
@ -0,0 +1,3 @@
|
|||
1. Create more themes for my applauncher
|
||||
2. Create more themes for hyprlock
|
||||
check out: https://github.com/MrVivekRajan/Hyprlock-Styles
|
||||
59
deploy
|
|
@ -1,3 +1,58 @@
|
|||
#!/usr/bin/env bash
|
||||
sudo nixos-rebuild switch --flake .
|
||||
#nixos-rebuild build --flake .# --cores 8 -j 1
|
||||
set -e
|
||||
|
||||
usage="Usage: $(basename $0) [OPTIONS]
|
||||
|
||||
Options:
|
||||
-f, --fresh Remove old content in the nixstore (good for debugging)
|
||||
-b, --bootloader Reinstall the bootloader
|
||||
-h, --help Show this message (^_^)"
|
||||
|
||||
# delete all cached entries
|
||||
# to make the system from scratch
|
||||
collect_garbage () {
|
||||
sudo nix-collect-garbage --delete-old
|
||||
}
|
||||
|
||||
rebuild_flake () {
|
||||
# make sure all changes are visible to nixos
|
||||
git add . --verbose
|
||||
if [ "$1" = "reinstall-bootloader" ]; then
|
||||
sudo nixos-rebuild switch --flake . --install-bootloader
|
||||
else
|
||||
sudo nixos-rebuild switch --flake .
|
||||
#nixos-rebuild build --flake .# --cores 8 -j 1
|
||||
fi
|
||||
}
|
||||
|
||||
# check which flags were given
|
||||
flag_fresh=false
|
||||
flag_bootloader=false
|
||||
for flag in "$@"; do
|
||||
case "$flag" in
|
||||
-f|--fresh)
|
||||
flag_fresh=true ;;
|
||||
-b|--bootloader)
|
||||
flag_bootloader=true ;;
|
||||
-h|--help)
|
||||
echo "$usage"
|
||||
exit 0 ;;
|
||||
*)
|
||||
echo "[!] Unknown flag \"$flag\""
|
||||
exit 1 ;;
|
||||
esac
|
||||
done
|
||||
|
||||
# delete cached items in nixstore
|
||||
if [ "$flag_fresh" = true ]; then
|
||||
collect_garbage
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# nixos-rebuild switch ...
|
||||
if [ "$flag_bootloader" = true ]; then
|
||||
collect_garbage
|
||||
rebuild_flake "reinstall-bootloader"
|
||||
else
|
||||
rebuild_flake
|
||||
fi
|
||||
|
|
|
|||
13
deploy-remote
Executable file
|
|
@ -0,0 +1,13 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
set -e # terminate if any command fails
|
||||
|
||||
echo "[+] Adding keys to ssh-agent"
|
||||
ssh-add ~/.ssh/id_hyrule
|
||||
printf "\n"
|
||||
|
||||
git add .
|
||||
# Deploy to all Colmena hives
|
||||
colmena build --experimental-flake-eval
|
||||
colmena apply --experimental-flake-eval
|
||||
# colmena apply --on hyrule --experimental-flake-eval
|
||||
205
flake.lock
generated
|
|
@ -21,7 +21,7 @@
|
|||
},
|
||||
"ags_2": {
|
||||
"inputs": {
|
||||
"nixpkgs": "nixpkgs_4",
|
||||
"nixpkgs": "nixpkgs_5",
|
||||
"systems": "systems_3"
|
||||
},
|
||||
"locked": {
|
||||
|
|
@ -71,7 +71,46 @@
|
|||
"type": "github"
|
||||
}
|
||||
},
|
||||
"colmena": {
|
||||
"inputs": {
|
||||
"flake-compat": "flake-compat",
|
||||
"flake-utils": "flake-utils",
|
||||
"nix-github-actions": "nix-github-actions",
|
||||
"nixpkgs": "nixpkgs_2",
|
||||
"stable": "stable"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1734374287,
|
||||
"narHash": "sha256-rINodqeUuezuCWOnpJgrH7u9vJ86fYT+Dj8Mu8T/IBc=",
|
||||
"owner": "zhaofengli",
|
||||
"repo": "colmena",
|
||||
"rev": "47b6414d800c8471e98ca072bc0835345741a56a",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "zhaofengli",
|
||||
"repo": "colmena",
|
||||
"rev": "47b6414d800c8471e98ca072bc0835345741a56a",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"flake-compat": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1650374568,
|
||||
"narHash": "sha256-Z+s0J8/r907g149rllvwhb4pKi8Wam5ij0st8PwAh+E=",
|
||||
"owner": "edolstra",
|
||||
"repo": "flake-compat",
|
||||
"rev": "b4a34015c698c7793d592d66adbab377907a2be8",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "edolstra",
|
||||
"repo": "flake-compat",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"flake-compat_2": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1696426674,
|
||||
|
|
@ -87,7 +126,7 @@
|
|||
"type": "github"
|
||||
}
|
||||
},
|
||||
"flake-compat_2": {
|
||||
"flake-compat_3": {
|
||||
"locked": {
|
||||
"lastModified": 1696426674,
|
||||
"narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=",
|
||||
|
|
@ -101,22 +140,6 @@
|
|||
"url": "https://flakehub.com/f/edolstra/flake-compat/1.tar.gz"
|
||||
}
|
||||
},
|
||||
"flake-compat_3": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1696426674,
|
||||
"narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=",
|
||||
"owner": "edolstra",
|
||||
"repo": "flake-compat",
|
||||
"rev": "0f9255e01c2351cc7d116c072cb317785dd33b33",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "edolstra",
|
||||
"repo": "flake-compat",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"flake-compat_4": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
|
|
@ -133,6 +156,37 @@
|
|||
"type": "github"
|
||||
}
|
||||
},
|
||||
"flake-compat_5": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1696426674,
|
||||
"narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=",
|
||||
"owner": "edolstra",
|
||||
"repo": "flake-compat",
|
||||
"rev": "0f9255e01c2351cc7d116c072cb317785dd33b33",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "edolstra",
|
||||
"repo": "flake-compat",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"flake-utils": {
|
||||
"locked": {
|
||||
"lastModified": 1659877975,
|
||||
"narHash": "sha256-zllb8aq3YO3h8B/U0/J1WBgAL8EX5yWf5pMj3G0NAmc=",
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"rev": "c0e246b9b83f637f4681389ecabcb2681b4f3af0",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"gitignore": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
|
|
@ -157,7 +211,7 @@
|
|||
},
|
||||
"grub2-themes": {
|
||||
"inputs": {
|
||||
"nixpkgs": "nixpkgs_2"
|
||||
"nixpkgs": "nixpkgs_3"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1730004881,
|
||||
|
|
@ -173,26 +227,6 @@
|
|||
"type": "github"
|
||||
}
|
||||
},
|
||||
"home-manager": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1730633670,
|
||||
"narHash": "sha256-ZFJqIXpvVKvzOVFKWNRDyIyAo+GYdmEPaYi1bZB6uf0=",
|
||||
"owner": "nix-community",
|
||||
"repo": "home-manager",
|
||||
"rev": "8f6ca7855d409aeebe2a582c6fd6b6a8d0bf5661",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-community",
|
||||
"repo": "home-manager",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"hyprcursor": {
|
||||
"inputs": {
|
||||
"hyprlang": [
|
||||
|
|
@ -230,7 +264,7 @@
|
|||
"hyprlang": "hyprlang",
|
||||
"hyprutils": "hyprutils",
|
||||
"hyprwayland-scanner": "hyprwayland-scanner",
|
||||
"nixpkgs": "nixpkgs_3",
|
||||
"nixpkgs": "nixpkgs_4",
|
||||
"pre-commit-hooks": "pre-commit-hooks",
|
||||
"systems": "systems_2",
|
||||
"xdph": "xdph"
|
||||
|
|
@ -306,7 +340,7 @@
|
|||
"hyprpanel": {
|
||||
"inputs": {
|
||||
"ags": "ags_2",
|
||||
"nixpkgs": "nixpkgs_5"
|
||||
"nixpkgs": "nixpkgs_6"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1731270736,
|
||||
|
|
@ -388,10 +422,31 @@
|
|||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nix-github-actions": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
"colmena",
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1729742964,
|
||||
"narHash": "sha256-B4mzTcQ0FZHdpeWcpDYPERtyjJd/NIuaQ9+BV1h+MpA=",
|
||||
"owner": "nix-community",
|
||||
"repo": "nix-github-actions",
|
||||
"rev": "e04df33f62cdcf93d73e9a04142464753a16db67",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-community",
|
||||
"repo": "nix-github-actions",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixcord": {
|
||||
"inputs": {
|
||||
"flake-compat": "flake-compat_2",
|
||||
"nixpkgs": "nixpkgs_6"
|
||||
"flake-compat": "flake-compat_3",
|
||||
"nixpkgs": "nixpkgs_7"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1730720546,
|
||||
|
|
@ -440,6 +495,22 @@
|
|||
}
|
||||
},
|
||||
"nixpkgs_2": {
|
||||
"locked": {
|
||||
"lastModified": 1734119587,
|
||||
"narHash": "sha256-AKU6qqskl0yf2+JdRdD0cfxX4b9x3KKV5RqA6wijmPM=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "3566ab7246670a43abd2ffa913cc62dad9cdf7d5",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"ref": "nixos-unstable",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs_3": {
|
||||
"locked": {
|
||||
"lastModified": 1730808093,
|
||||
"narHash": "sha256-oOenwoxpzQsBNi7KltgnXqq6e0+CxlfNXKn3k27w6cQ=",
|
||||
|
|
@ -455,7 +526,7 @@
|
|||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs_3": {
|
||||
"nixpkgs_4": {
|
||||
"locked": {
|
||||
"lastModified": 1730785428,
|
||||
"narHash": "sha256-Zwl8YgTVJTEum+L+0zVAWvXAGbWAuXHax3KzuejaDyo=",
|
||||
|
|
@ -471,7 +542,7 @@
|
|||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs_4": {
|
||||
"nixpkgs_5": {
|
||||
"locked": {
|
||||
"lastModified": 1725634671,
|
||||
"narHash": "sha256-v3rIhsJBOMLR8e/RNWxr828tB+WywYIoajrZKFM+0Gg=",
|
||||
|
|
@ -487,7 +558,7 @@
|
|||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs_5": {
|
||||
"nixpkgs_6": {
|
||||
"locked": {
|
||||
"lastModified": 1729880355,
|
||||
"narHash": "sha256-RP+OQ6koQQLX5nw0NmcDrzvGL8HDLnyXt/jHhL1jwjM=",
|
||||
|
|
@ -503,7 +574,7 @@
|
|||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs_6": {
|
||||
"nixpkgs_7": {
|
||||
"locked": {
|
||||
"lastModified": 1730768919,
|
||||
"narHash": "sha256-8AKquNnnSaJRXZxc5YmF/WfmxiHX6MMZZasRP6RRQkE=",
|
||||
|
|
@ -519,23 +590,23 @@
|
|||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs_7": {
|
||||
"nixpkgs_8": {
|
||||
"locked": {
|
||||
"lastModified": 1730785428,
|
||||
"narHash": "sha256-Zwl8YgTVJTEum+L+0zVAWvXAGbWAuXHax3KzuejaDyo=",
|
||||
"lastModified": 1739357830,
|
||||
"narHash": "sha256-9xim3nJJUFbVbJCz48UP4fGRStVW5nv4VdbimbKxJ3I=",
|
||||
"owner": "nixos",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "4aa36568d413aca0ea84a1684d2d46f55dbabad7",
|
||||
"rev": "0ff09db9d034a04acd4e8908820ba0b410d7a33a",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nixos",
|
||||
"ref": "nixos-unstable",
|
||||
"ref": "nixos-24.11",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs_8": {
|
||||
"nixpkgs_9": {
|
||||
"locked": {
|
||||
"lastModified": 1730200266,
|
||||
"narHash": "sha256-l253w0XMT8nWHGXuXqyiIC/bMvh1VRszGXgdpQlfhvU=",
|
||||
|
|
@ -553,7 +624,7 @@
|
|||
},
|
||||
"pre-commit-hooks": {
|
||||
"inputs": {
|
||||
"flake-compat": "flake-compat",
|
||||
"flake-compat": "flake-compat_2",
|
||||
"gitignore": "gitignore",
|
||||
"nixpkgs": [
|
||||
"hyprland",
|
||||
|
|
@ -578,20 +649,20 @@
|
|||
"root": {
|
||||
"inputs": {
|
||||
"ags": "ags",
|
||||
"colmena": "colmena",
|
||||
"grub2-themes": "grub2-themes",
|
||||
"home-manager": "home-manager",
|
||||
"hyprland": "hyprland",
|
||||
"hyprpanel": "hyprpanel",
|
||||
"nix-flatpak": "nix-flatpak",
|
||||
"nixcord": "nixcord",
|
||||
"nixpkgs": "nixpkgs_7",
|
||||
"nixpkgs": "nixpkgs_8",
|
||||
"spicetify-nix": "spicetify-nix",
|
||||
"swww": "swww"
|
||||
}
|
||||
},
|
||||
"spicetify-nix": {
|
||||
"inputs": {
|
||||
"flake-compat": "flake-compat_3",
|
||||
"flake-compat": "flake-compat_4",
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
]
|
||||
|
|
@ -610,10 +681,26 @@
|
|||
"type": "github"
|
||||
}
|
||||
},
|
||||
"stable": {
|
||||
"locked": {
|
||||
"lastModified": 1730883749,
|
||||
"narHash": "sha256-mwrFF0vElHJP8X3pFCByJR365Q2463ATp2qGIrDUdlE=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "dba414932936fde69f0606b4f1d87c5bc0003ede",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"ref": "nixos-24.05",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"swww": {
|
||||
"inputs": {
|
||||
"flake-compat": "flake-compat_4",
|
||||
"nixpkgs": "nixpkgs_8",
|
||||
"flake-compat": "flake-compat_5",
|
||||
"nixpkgs": "nixpkgs_9",
|
||||
"utils": "utils"
|
||||
},
|
||||
"locked": {
|
||||
|
|
|
|||
88
flake.nix
|
|
@ -2,13 +2,14 @@
|
|||
description = "Emile's Nix Dotfiles";
|
||||
|
||||
inputs = {
|
||||
#nixpkgs.url = "github:nixos/nixpkgs/nixos-24.05";
|
||||
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
|
||||
# nixpkgs.url = "github:nixos/nixpkgs/nixos-24.05";
|
||||
nixpkgs.url = "github:nixos/nixpkgs/nixos-24.11";
|
||||
#nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
|
||||
|
||||
home-manager = {
|
||||
url = "github:nix-community/home-manager";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
};
|
||||
#home-manager = {
|
||||
# url = "github:nix-community/home-manager";
|
||||
# inputs.nixpkgs.follows = "nixpkgs";
|
||||
#};
|
||||
|
||||
spicetify-nix = {
|
||||
url = "github:Gerg-L/spicetify-nix";
|
||||
|
|
@ -30,31 +31,51 @@
|
|||
ags.url = "github:Aylur/ags";
|
||||
|
||||
hyprpanel.url = "github:Jas-SinghFSU/HyprPanel";
|
||||
|
||||
# colmena.url = "github:zhaofengli/colmena";
|
||||
colmena.url = "github:zhaofengli/colmena/?rev=47b6414d800c8471e98ca072bc0835345741a56a";
|
||||
# alternative to colmena (currently in testing)
|
||||
#deploy-rs.url = "github:serokell/deploy-rs";
|
||||
|
||||
#wishlist.url = "path:/home/me/nixdots/flakes/wishlist";
|
||||
};
|
||||
|
||||
outputs = {
|
||||
self,
|
||||
nixpkgs,
|
||||
home-manager,
|
||||
#home-manager,
|
||||
hyprland,
|
||||
grub2-themes,
|
||||
nixcord,
|
||||
colmena,
|
||||
#deploy-rs,
|
||||
...
|
||||
} @ inputs: let
|
||||
system = "x86_64-linux";
|
||||
|
||||
pkgs = import nixpkgs {
|
||||
inherit system;
|
||||
config.allowUnfree = true;
|
||||
|
||||
config = {
|
||||
allowUnfree = true;
|
||||
};
|
||||
};
|
||||
|
||||
# TODO: come back to this its really cool
|
||||
# this is just something I'm experimenting with
|
||||
PROJECT_ROOT = builtins.toString ./.;
|
||||
in {
|
||||
# `nix develop` shell
|
||||
devShells."x86_64-linux".default = pkgs.mkShell {
|
||||
buildInputs = [
|
||||
#colmena-new
|
||||
];
|
||||
};
|
||||
|
||||
nixosConfigurations = {
|
||||
# i be on my puter fr
|
||||
myputer = nixpkgs.lib.nixosSystem {
|
||||
# nix passes these to every single module above
|
||||
# nix passes these to every single module
|
||||
specialArgs = {inherit inputs pkgs;};
|
||||
|
||||
modules = [
|
||||
|
|
@ -72,6 +93,55 @@
|
|||
grub2-themes.nixosModules.default
|
||||
];
|
||||
};
|
||||
|
||||
# meine vps
|
||||
# hyrule = nixpkgs.lib.nixosSystem {
|
||||
# # manually set system architecture since
|
||||
# # this is for a remote deployment
|
||||
# system = "x86_64-linux";
|
||||
# specialargs = {inherit inputs pkgs;};
|
||||
#
|
||||
# modules = [
|
||||
# ./hosts/hyrule
|
||||
# ];
|
||||
# };
|
||||
};
|
||||
|
||||
# remote deployment with deploy-rs
|
||||
# deploy.nodes.hyrule = {
|
||||
# hostname = "imbored.dev";
|
||||
# # create a primary profile called "system"
|
||||
# profiles.system = {
|
||||
# user = "root"; # user to deploy to
|
||||
# path = deploy-rs.lib.x86_64-linux.activate.nixos self.nixosConfigurations.hyrule;
|
||||
#
|
||||
# # ssh configuration for reaching the server
|
||||
# sshUser = "ae";
|
||||
# #interactiveSudo = true; # TODO: use this and revoke passwordless sudo for ae
|
||||
# sshOpts = ["-i" "/home/me/.ssh/id_hyrule"];
|
||||
# remoteBuild = false; # build locally then deploy to remote host
|
||||
# };
|
||||
# };
|
||||
|
||||
# remote deployment to my servers!!
|
||||
colmenaHive = colmena.lib.makeHive {
|
||||
meta = {
|
||||
# set nixpkgs global
|
||||
nixpkgs = pkgs;
|
||||
# set nixpkgs per server
|
||||
nodeNixpkgs = {
|
||||
hyrule = import nixpkgs {
|
||||
system = "x86_64-linux";
|
||||
config.allowUnfree = false;
|
||||
};
|
||||
};
|
||||
|
||||
# we can use `specialArgs.inputs` to inject wishlist into hyrule's module
|
||||
#specialArgs.inputs = with inputs; {inherit wishlist;};
|
||||
};
|
||||
|
||||
# meine vps
|
||||
hyrule = import ./hosts/hyrule;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
|
|||
31
flakes/wishlist/README
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
#### wishlist.nix
|
||||
This is a simple Nix flake defining a service from which
|
||||
wishlist can run automatically. This flake runs wishlist-0.15.1
|
||||
and lacks configurability unfortunately. However this was an
|
||||
intentional choice, allowing wishlist to read from the user's
|
||||
`~/.ssh/config` file, which can be configured seperately using
|
||||
the something akin to the follow home-manager snippet:
|
||||
```nix
|
||||
programs.ssh = {
|
||||
enable = true;
|
||||
addKeysToAgent = "yes"; # always add keys to ssh-agent
|
||||
|
||||
matchBlocks = {
|
||||
hyrule = {
|
||||
hostname = "imbored.dev";
|
||||
user = "ae";
|
||||
port = 22;
|
||||
identityFile = "/home/me/.ssh/id_hyrule";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
```
|
||||
|
||||
This decision was mostly selfish as it was easiest...
|
||||
But it comes at the cost of not being able to set the
|
||||
port wishlist listens on. So for now you're stuck with `2222`.
|
||||
|
||||
###### The Future!! (woooowwww)
|
||||
Create an option for wishlist that is used to construct
|
||||
the `config.yaml` file
|
||||
93
flakes/wishlist/flake.nix
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
{
|
||||
inputs = {
|
||||
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
||||
flake-utils.url = "github:numtide/flake-utils";
|
||||
};
|
||||
|
||||
outputs = {
|
||||
self,
|
||||
config,
|
||||
nixpkgs,
|
||||
lib,
|
||||
flake-utils,
|
||||
}: let
|
||||
cfg = config.services.wishlist;
|
||||
supportedSystems = ["x86_64-linux" "i686-linux" "aarch64-linux" "x86_64-darwin" "aarch64-darwin"];
|
||||
in {
|
||||
# TODO: 1. add options (ie one to set whether the server should be enabled),
|
||||
# 2. create a systemd service
|
||||
# 3. create a main program
|
||||
# 4. celibrate
|
||||
|
||||
# TODO: do I need to make this a home-manager option and set the yaml config?
|
||||
|
||||
# define what settings a user can change
|
||||
options = {
|
||||
services.wishlist = with lib; {
|
||||
enable = mkEnableOption "wishlist";
|
||||
|
||||
port = mkOption {
|
||||
type = types.port;
|
||||
default = 2222;
|
||||
description = "Port to listen on";
|
||||
};
|
||||
|
||||
package = mkOption {
|
||||
type = types.package;
|
||||
default = self.packages.${nixpkgs.system}.default;
|
||||
description = "Package to use";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
# define a systemd service for wishlist ^_^
|
||||
config = lib.mkIf cfg.enable {
|
||||
systemd.services.wishlist = {
|
||||
description = "Single entrypoint for multiple SSH endpoints";
|
||||
wantedBy = ["multi-user.target"];
|
||||
|
||||
serviceConfig = {
|
||||
DynamicUser = "yes";
|
||||
ExecStart = "${cfg.package}/bin/wishlist serve";
|
||||
Restart = "always";
|
||||
RestartSec = "2s";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
packages = flake-utils.lib.eachSystem supportedSystems (
|
||||
system: let
|
||||
version = "0.15.1";
|
||||
#pkgs = nixpkgs.legacyPackages.${system};
|
||||
pkgs = import nixpkgs {
|
||||
inherit system;
|
||||
config.allowUnfree = false;
|
||||
};
|
||||
#lib = pkgs.lib;
|
||||
in rec {
|
||||
defaultPackage = self.packages.${system}.wishlist;
|
||||
wishlist = pkgs.buildGoModule {
|
||||
pname = "wishlist";
|
||||
inherit version;
|
||||
meta = with lib; {
|
||||
description = "Single entrypoint for multiple SSH endpoints";
|
||||
homepage = "https://github.com/charmbracelet/wishlist";
|
||||
changelog = "https://github.com/charmbracelet/wishlist/releases/tag/v${version}";
|
||||
license = licenses.mit;
|
||||
maintainers = with maintainers; [caarlos0 penguwin];
|
||||
mainProgram = "wishlist";
|
||||
};
|
||||
|
||||
src = pkgs.fetchFromGitHub {
|
||||
owner = "charmbracelet";
|
||||
repo = "wishlist";
|
||||
rev = "v${version}";
|
||||
# rev = "d7f058e115a8b4a4131406d01dde84fb4a8e93c4";
|
||||
hash = "53fojA+gdvpSVNjx6QncH16F8/x+lpY5SkNs7obW2XQ=";
|
||||
};
|
||||
vendorSha256 = "0x6rss3fwv2398wrd5kyzkrqaphzvh4ykwfqai9glxm01y6fhxz7";
|
||||
};
|
||||
}
|
||||
);
|
||||
};
|
||||
}
|
||||
99
flakes/wishlist/wishlist.nix
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
# NOTE: Wishlist service fails on nix because of readonly file system
|
||||
# and it can't find a config file for itself, it needs to write that
|
||||
# itself I suppose :(
|
||||
# So:
|
||||
# 1. Get it to write that file, and
|
||||
# 2. Allow it to inherit profiles from configured ssh
|
||||
{
|
||||
self,
|
||||
config,
|
||||
pkgs,
|
||||
lib,
|
||||
}: let
|
||||
cfg = config.services.wishlist;
|
||||
in {
|
||||
options = {
|
||||
services.wishlist = with lib; {
|
||||
enable = mkEnableOption "wishlist";
|
||||
|
||||
name = mkOption {
|
||||
type = types.str;
|
||||
default =
|
||||
};
|
||||
|
||||
port = mkOption {
|
||||
type = types.port;
|
||||
default = 2222;
|
||||
description = "Port to listen on";
|
||||
};
|
||||
|
||||
#configPath = mkOption {
|
||||
# type = types.path;
|
||||
# default = ;
|
||||
# description = "Path to config file";
|
||||
#};
|
||||
|
||||
package = mkOption {
|
||||
type = types.package;
|
||||
default = self.packages.${nixpkgs.system}.default;
|
||||
description = "Package to use";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
# define a systemd service for wishlist ^_^
|
||||
config = lib.mkIf cfg.enable {
|
||||
systemd.services.wishlist = {
|
||||
description = "Single entrypoint for multiple SSH endpoints";
|
||||
wantedBy = ["multi-user.target"];
|
||||
|
||||
serviceConfig = let
|
||||
wishlistServiceConfig = pkgs.writeText "config.yaml" ''
|
||||
hello world!
|
||||
'';
|
||||
in {
|
||||
DynamicUser = "yes";
|
||||
ExecStart = "${pkgs.wishlist}/bin/wishlist serve --config ${wishlistServiceConfig}";
|
||||
Restart = "always";
|
||||
RestartSec = "2s";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
/*
|
||||
packages = flake-utils.lib.eachSystem supportedSystems (
|
||||
system: let
|
||||
version = "0.15.1";
|
||||
#pkgs = nixpkgs.legacyPackages.${system};
|
||||
pkgs = import nixpkgs {
|
||||
inherit system;
|
||||
config.allowUnfree = false;
|
||||
};
|
||||
#lib = pkgs.lib;
|
||||
in rec {
|
||||
defaultPackage = self.packages.${system}.wishlist;
|
||||
wishlist = pkgs.buildGoModule {
|
||||
pname = "wishlist";
|
||||
inherit version;
|
||||
meta = with lib; {
|
||||
description = "Single entrypoint for multiple SSH endpoints";
|
||||
homepage = "https://github.com/charmbracelet/wishlist";
|
||||
changelog = "https://github.com/charmbracelet/wishlist/releases/tag/v${version}";
|
||||
license = licenses.mit;
|
||||
maintainers = with maintainers; [caarlos0 penguwin];
|
||||
mainProgram = "wishlist";
|
||||
};
|
||||
|
||||
src = pkgs.fetchFromGitHub {
|
||||
owner = "charmbracelet";
|
||||
repo = "wishlist";
|
||||
rev = "v${version}";
|
||||
# rev = "d7f058e115a8b4a4131406d01dde84fb4a8e93c4";
|
||||
hash = "53fojA+gdvpSVNjx6QncH16F8/x+lpY5SkNs7obW2XQ=";
|
||||
};
|
||||
vendorSha256 = "0x6rss3fwv2398wrd5kyzkrqaphzvh4ykwfqai9glxm01y6fhxz7";
|
||||
};
|
||||
}
|
||||
);
|
||||
*/
|
||||
}
|
||||
56
homes/ae/default.nix
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
{
|
||||
inputs,
|
||||
outputs,
|
||||
lib,
|
||||
config,
|
||||
pkgs,
|
||||
...
|
||||
}: {
|
||||
nixpkgs = {
|
||||
config.allowUnfree = false;
|
||||
};
|
||||
|
||||
imports = [
|
||||
];
|
||||
|
||||
home = {
|
||||
username = "ae";
|
||||
homeDirectory = "/home/ae";
|
||||
};
|
||||
|
||||
programs = {
|
||||
};
|
||||
|
||||
# Nicely reload system units when changing configs
|
||||
systemd.user.startServices = "sd-switch";
|
||||
|
||||
# ssh = {
|
||||
# enable = true;
|
||||
# forwardAgent = true;
|
||||
# addKeysToAgent = "yes";
|
||||
|
||||
# matchBlocks = {
|
||||
# hyrule = {
|
||||
# hostname = "imbored.dev";
|
||||
# user = "ae";
|
||||
# port = 22;
|
||||
# identityFile = "/home/ae/.ssh/id_hyrule";
|
||||
# };
|
||||
# };
|
||||
# };
|
||||
|
||||
# SERVICE: webfishing (example for wishlist)
|
||||
#systemd.user.services.webfishing = {
|
||||
# Unit.Description = "I be out here webfishing frfr";
|
||||
|
||||
# Install.WantedBy = ["default.target"];
|
||||
|
||||
# Service = {
|
||||
# Type = "exec";
|
||||
# ExecStart = "echo $HOME; cat $HOME/.ssh/config";
|
||||
# Restart = "always";
|
||||
# };
|
||||
#};
|
||||
|
||||
home.stateVersion = "24.11"; # DO NOT MODIFY
|
||||
}
|
||||
|
|
@ -1 +0,0 @@
|
|||
openai-symbolic.svg
|
||||
|
|
@ -1,54 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
width="20"
|
||||
height="20"
|
||||
viewBox="0 0 20 20"
|
||||
fill="none"
|
||||
version="1.1"
|
||||
id="svg9"
|
||||
sodipodi:docname="oxygen.svg"
|
||||
inkscape:version="1.3.2 (091e20ef0f, 2023-11-25, custom)"
|
||||
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="defs9" />
|
||||
<sodipodi:namedview
|
||||
id="namedview9"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:zoom="7.6782609"
|
||||
inkscape:cx="-11.916761"
|
||||
inkscape:cy="11.786523"
|
||||
inkscape:window-width="1627"
|
||||
inkscape:window-height="1028"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg9" />
|
||||
<g
|
||||
id="g9"
|
||||
transform="translate(0.7158741,-0.307456)">
|
||||
<path
|
||||
d="m 12.821126,8.892686 c 0,2.99523 -2.42813,5.42337 -5.4233602,5.42337 -2.99523,0 -5.42334,-2.42814 -5.42334,-5.42337 0,-2.99523 2.42811,-5.42334 5.42334,-5.42334 2.9952302,0 5.4233602,2.42811 5.4233602,5.42334 z"
|
||||
fill="white"
|
||||
id="path7"
|
||||
style="fill:#000000" />
|
||||
<path
|
||||
d="m 16.593826,4.412536 c 0,1.04182 -0.8445,1.88638 -1.8863,1.88638 -1.0419,0 -1.8864,-0.84456 -1.8864,-1.88638 0,-1.041819 0.8445,-1.88638 1.8864,-1.88638 1.0418,0 1.8863,0.844561 1.8863,1.88638 z"
|
||||
fill="white"
|
||||
id="path8"
|
||||
style="fill:#000000" />
|
||||
<path
|
||||
d="m 16.593826,15.495056 c 0,1.4325 -1.1612,2.5937 -2.5937,2.5937 -1.4325,0 -2.5938,-1.1612 -2.5938,-2.5937 0,-1.4325 1.1613,-2.5938 2.5938,-2.5938 1.4325,0 2.5937,1.1613 2.5937,2.5938 z"
|
||||
fill="white"
|
||||
id="path9"
|
||||
style="fill:#000000" />
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 306 KiB |
|
|
@ -1,113 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
version="1.0"
|
||||
width="20"
|
||||
height="19.999941"
|
||||
id="svg2424"
|
||||
sodipodi:docname="archlinux-logo-black-scalable.f931920e6cdb.svg"
|
||||
viewBox="0 0 166.18749 166.187"
|
||||
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:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<sodipodi:namedview
|
||||
id="namedview1"
|
||||
pagecolor="#505050"
|
||||
bordercolor="#ffffff"
|
||||
borderopacity="1"
|
||||
inkscape:showpageshadow="0"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pagecheckerboard="1"
|
||||
inkscape:deskcolor="#505050"
|
||||
inkscape:zoom="16.650008"
|
||||
inkscape:cx="13.093087"
|
||||
inkscape:cy="16.366359"
|
||||
inkscape:window-width="1340"
|
||||
inkscape:window-height="768"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="g2424" />
|
||||
<defs
|
||||
id="defs2426">
|
||||
<linearGradient
|
||||
x1="112.49854"
|
||||
y1="6.1372099"
|
||||
x2="112.49853"
|
||||
y2="129.3468"
|
||||
id="path1082_2_"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="translate(287,-83)">
|
||||
<stop
|
||||
id="stop193"
|
||||
style="stop-color:#ffffff;stop-opacity:0"
|
||||
offset="0" />
|
||||
<stop
|
||||
id="stop195"
|
||||
style="stop-color:#ffffff;stop-opacity:0.27450982"
|
||||
offset="1" />
|
||||
<midPointStop
|
||||
offset="0"
|
||||
style="stop-color:#FFFFFF"
|
||||
id="midPointStop197" />
|
||||
<midPointStop
|
||||
offset="0.5"
|
||||
style="stop-color:#FFFFFF"
|
||||
id="midPointStop199" />
|
||||
<midPointStop
|
||||
offset="1"
|
||||
style="stop-color:#000000"
|
||||
id="midPointStop201" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
x1="541.33502"
|
||||
y1="104.50665"
|
||||
x2="606.91248"
|
||||
y2="303.14029"
|
||||
id="linearGradient2544"
|
||||
xlink:href="#path1082_2_"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(-0.3937741,0,0,0.393752,357.51969,122.00151)" />
|
||||
<linearGradient
|
||||
id="linearGradient3388">
|
||||
<stop
|
||||
id="stop3390"
|
||||
style="stop-color:#000000;stop-opacity:0"
|
||||
offset="0" />
|
||||
<stop
|
||||
id="stop3392"
|
||||
style="stop-color:#000000;stop-opacity:0.37113401"
|
||||
offset="1" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
x1="490.72305"
|
||||
y1="237.72447"
|
||||
x2="490.72305"
|
||||
y2="183.9644"
|
||||
id="linearGradient4416"
|
||||
xlink:href="#linearGradient3388"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.749107,0,0,0.749107,-35.459862,91.44108)" />
|
||||
</defs>
|
||||
<g
|
||||
transform="translate(-57.527313,-146.42741)"
|
||||
id="layer1">
|
||||
<g
|
||||
transform="matrix(0.8746356,0,0,0.8746356,14.730518,23.408954)"
|
||||
id="g2424"
|
||||
style="fill:#000000">
|
||||
<g
|
||||
transform="matrix(0.6378586,0,0,0.6378586,36.486487,2.17139)"
|
||||
id="g2809"
|
||||
style="fill:#000000;fill-opacity:1" />
|
||||
<path
|
||||
d="m 143.91698,140.65081 c -8.45709,20.73453 -13.55799,34.29734 -22.97385,54.41552 5.7731,6.11948 12.85931,13.24593 24.36729,21.29458 -12.37221,-5.09109 -20.81157,-10.20242 -27.11844,-15.50646 -12.0505,25.14523 -30.930177,60.96349 -69.243121,129.80406 30.112687,-17.38458 53.455511,-28.10236 75.209891,-32.19198 -0.93414,-4.01773 -1.46524,-8.36369 -1.42916,-12.89823 l 0.0357,-0.96469 c 0.47781,-19.2924 10.51371,-34.12825 22.40218,-33.12093 11.88848,1.00732 21.12927,17.4729 20.65146,36.76531 -0.0899,3.63022 -0.49934,7.12245 -1.21479,10.36146 21.51819,4.20934 44.61141,14.89968 74.31666,32.04906 -5.85729,-10.78369 -11.08544,-20.5044 -16.07812,-29.7624 -7.86429,-6.09535 -16.06714,-14.02847 -32.79938,-22.61656 11.50078,2.98839 19.73519,6.43619 26.15375,10.29 -50.76203,-94.51003 -54.87267,-107.06846 -72.2801,-147.91874 z"
|
||||
id="path2518"
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.14333" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 4.1 KiB |
|
|
@ -1,318 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
id="SVGRoot"
|
||||
width="20"
|
||||
height="20"
|
||||
version="1.1"
|
||||
viewBox="0 0 17.921003 17.921002"
|
||||
sodipodi:docname="cachyos-symbolic.svg"
|
||||
inkscape:version="1.3.2 (091e20ef0f, 2023-11-25, custom)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<sodipodi:namedview
|
||||
id="namedview30"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:zoom="32"
|
||||
inkscape:cx="10.671875"
|
||||
inkscape:cy="11.234375"
|
||||
inkscape:window-width="1687"
|
||||
inkscape:window-height="1028"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="SVGRoot" />
|
||||
<defs
|
||||
id="defs6">
|
||||
<linearGradient
|
||||
id="linearGradient939"
|
||||
x1="237.19"
|
||||
x2="237.07001"
|
||||
y1="296.20001"
|
||||
y2="304.07999"
|
||||
gradientTransform="matrix(0.04476,0,0,0.044679,-8.5042241,-4.351186)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
xlink:href="#linearGradient937" />
|
||||
<linearGradient
|
||||
id="linearGradient937">
|
||||
<stop
|
||||
stop-color="#001313"
|
||||
offset="0"
|
||||
id="stop1" />
|
||||
<stop
|
||||
stop-color="#001313"
|
||||
stop-opacity="0"
|
||||
offset="1"
|
||||
id="stop2" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient5185"
|
||||
x1="994.81"
|
||||
x2="982.34003"
|
||||
y1="1533.3"
|
||||
y2="1556.8"
|
||||
gradientTransform="matrix(0.084141,0,0,0.083989,-76.242924,-126.39098)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
xlink:href="#linearGradient4353" />
|
||||
<linearGradient
|
||||
id="linearGradient4353">
|
||||
<stop
|
||||
stop-color="#020202"
|
||||
offset="0"
|
||||
id="stop3" />
|
||||
<stop
|
||||
stop-color="#020202"
|
||||
stop-opacity="0"
|
||||
offset="1"
|
||||
id="stop4" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient9102"
|
||||
x1="1022.5"
|
||||
x2="1018.6"
|
||||
y1="1582.4"
|
||||
y2="1575.6"
|
||||
gradientTransform="matrix(0.086381,0,0,0.081808,-79.103924,-124.69099)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
xlink:href="#linearGradient4353" />
|
||||
<linearGradient
|
||||
id="linearGradient11890"
|
||||
x1="940.42999"
|
||||
x2="930.59003"
|
||||
y1="1612.5"
|
||||
y2="1594.5"
|
||||
gradientTransform="matrix(0.084141,0,0,0.083989,-76.242924,-126.39098)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
xlink:href="#linearGradient4353" />
|
||||
<linearGradient
|
||||
id="linearGradient11670"
|
||||
x1="965.59998"
|
||||
x2="951.65997"
|
||||
y1="1571.4"
|
||||
y2="1571.3"
|
||||
gradientTransform="matrix(0.084141,0,0,0.083989,-76.242924,-126.39098)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
xlink:href="#linearGradient4353" />
|
||||
<linearGradient
|
||||
id="linearGradient13770"
|
||||
x1="946.22998"
|
||||
x2="961.37"
|
||||
y1="1655.9"
|
||||
y2="1655.8"
|
||||
gradientTransform="matrix(0.084141,0,0,0.083989,-76.242924,-126.39098)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
xlink:href="#linearGradient4353" />
|
||||
<linearGradient
|
||||
id="linearGradient2816"
|
||||
x1="366.14999"
|
||||
x2="350.92001"
|
||||
y1="427.32001"
|
||||
y2="419.64001"
|
||||
gradientTransform="matrix(0.04476,0,0,0.044679,-10.832924,-4.155886)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
xlink:href="#linearGradient937" />
|
||||
<linearGradient
|
||||
id="linearGradient12421"
|
||||
x1="936.34003"
|
||||
x2="933.38"
|
||||
y1="1628.8"
|
||||
y2="1623"
|
||||
gradientTransform="matrix(0.084141,0,0,0.083989,-76.242924,-126.39098)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
xlink:href="#linearGradient4353" />
|
||||
<linearGradient
|
||||
id="linearGradient13391"
|
||||
x1="950.33002"
|
||||
x2="941.96997"
|
||||
y1="1618.6"
|
||||
y2="1645.8"
|
||||
gradientTransform="matrix(0.084141,0,0,0.083989,-76.242924,-126.39098)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
xlink:href="#linearGradient4353" />
|
||||
<linearGradient
|
||||
id="linearGradient13599"
|
||||
x1="1008.2"
|
||||
x2="1015.7"
|
||||
y1="1681.3"
|
||||
y2="1668.4"
|
||||
gradientTransform="matrix(0.084141,0,0,0.083989,-77.884838,-124.43841)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
xlink:href="#linearGradient4353" />
|
||||
<linearGradient
|
||||
id="linearGradient18175"
|
||||
x1="1148.3"
|
||||
x2="1145.4"
|
||||
y1="1585.5"
|
||||
y2="1630"
|
||||
gradientTransform="matrix(0.34992,0,0,0.34992,-282.87,-491.67)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
xlink:href="#linearGradient18299" />
|
||||
<linearGradient
|
||||
id="linearGradient18299">
|
||||
<stop
|
||||
stop-color="#008066"
|
||||
stop-opacity="0"
|
||||
offset="0"
|
||||
id="stop5" />
|
||||
<stop
|
||||
stop-color="#0fc"
|
||||
offset="1"
|
||||
id="stop6" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient18632"
|
||||
x1="1148.3"
|
||||
x2="1145.4"
|
||||
y1="1585.5"
|
||||
y2="1630"
|
||||
gradientTransform="matrix(0.26565,0,0,0.26565,-211.15,-375.49)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
xlink:href="#linearGradient18299" />
|
||||
<linearGradient
|
||||
id="linearGradient18659"
|
||||
x1="1148.3"
|
||||
x2="1145.4"
|
||||
y1="1585.5"
|
||||
y2="1630"
|
||||
gradientTransform="matrix(0.13679,0,0,0.13679,-53.624,-195.03)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
xlink:href="#linearGradient18299" />
|
||||
<linearGradient
|
||||
id="linearGradient3254"
|
||||
x1="348.04999"
|
||||
x2="361.20999"
|
||||
y1="194.78"
|
||||
y2="187.24001"
|
||||
gradientTransform="matrix(0.04476,0,0,0.044679,-10.832924,-4.155886)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
xlink:href="#linearGradient937" />
|
||||
</defs>
|
||||
<circle
|
||||
cx="87.449997"
|
||||
cy="87.449997"
|
||||
r="87.449997"
|
||||
opacity="0"
|
||||
stroke-width="0.27971"
|
||||
id="circle6" />
|
||||
<path
|
||||
d="m 4.0610759,2.168314 6.5887001,3.6879 2.1127,-3.6528 z"
|
||||
fill="#00aa88"
|
||||
id="path7"
|
||||
style="fill:#000000" />
|
||||
<path
|
||||
d="m 6.1499759,12.423014 -1.9125,3.7456 h 8.5747001 l 2.1664,-3.7456 z"
|
||||
fill="#00aa88"
|
||||
id="path8"
|
||||
style="fill:#7a7a7a;fill-opacity:0.68506807" />
|
||||
<path
|
||||
d="m 4.0610759,2.168314 6.5887001,3.6879 H 6.1237759 l -1.8859,3.2605 1.9121,3.306 -1.9125,3.7456 -4.13689997,-7.1525 3.96049997,-6.8475"
|
||||
fill="#00ccff"
|
||||
id="path9"
|
||||
style="fill:#7a7a7a;fill-opacity:0.69262218" />
|
||||
<path
|
||||
d="m 6.0909759,5.821714 6.7111001,-3.7832 -2.169,3.5579 z"
|
||||
fill="url(#linearGradient9102)"
|
||||
id="path12"
|
||||
style="fill:url(#linearGradient9102)" />
|
||||
<path
|
||||
d="m 6.1236759,5.856214 6.6388001,-3.6528 -2.1127,3.6528 z"
|
||||
fill="#00aa88"
|
||||
id="path13"
|
||||
style="fill:#000000" />
|
||||
<path
|
||||
d="m 0.10057593,9.015814 6.02309997,-3.1596 -1.8859,3.2605 z"
|
||||
fill="#00aa88"
|
||||
id="path14"
|
||||
style="fill:#1a1a1a" />
|
||||
<path
|
||||
d="m 6.1236759,5.856214 -2.0626,-3.6879 0.17673,6.9484 z"
|
||||
fill="#00aa88"
|
||||
id="path16"
|
||||
style="fill:#1a1a1a" />
|
||||
<path
|
||||
d="m 4.2378759,9.116714 -3.1586,1.5811 3.1583,5.4705 z"
|
||||
fill="#00aa88"
|
||||
id="path19"
|
||||
style="fill:#1a1a1a" />
|
||||
<path
|
||||
d="m 1.0792259,10.698014 5.0708,1.7248 -1.9121,-3.306 z"
|
||||
fill="#00aa88"
|
||||
id="path23"
|
||||
style="fill:#1a1a1a" />
|
||||
<g
|
||||
transform="matrix(0.14699,0,0,0.14672,-0.75949407,-0.14715599)"
|
||||
id="g26"
|
||||
style="fill:#1a1a1a">
|
||||
<circle
|
||||
cx="117.95"
|
||||
cy="75.441002"
|
||||
r="9.6893997"
|
||||
fill="#00ccff"
|
||||
id="circle25"
|
||||
style="fill:#1a1a1a" />
|
||||
<circle
|
||||
cx="118.08"
|
||||
cy="75.341003"
|
||||
r="9.6893997"
|
||||
fill="url(#linearGradient18175)"
|
||||
id="circle26"
|
||||
style="fill:#1a1a1a" />
|
||||
</g>
|
||||
<g
|
||||
transform="matrix(0.14699,0,0,0.14672,-0.11248407,-0.47061599)"
|
||||
id="g28"
|
||||
style="fill:#1a1a1a">
|
||||
<circle
|
||||
cx="93.138"
|
||||
cy="55.044998"
|
||||
r="7.3558998"
|
||||
fill="#00ccff"
|
||||
id="circle27"
|
||||
style="fill:#1a1a1a" />
|
||||
<circle
|
||||
cx="93.238998"
|
||||
cy="54.969002"
|
||||
r="7.3558998"
|
||||
fill="url(#linearGradient18632)"
|
||||
id="circle28"
|
||||
style="fill:#1a1a1a" />
|
||||
</g>
|
||||
<g
|
||||
transform="matrix(0.14699,0,0,0.14672,-0.08243407,-0.04714599)"
|
||||
id="g30"
|
||||
style="fill:#000000">
|
||||
<circle
|
||||
cx="103.06"
|
||||
cy="26.657"
|
||||
r="3.7876999"
|
||||
fill="#00ccff"
|
||||
id="circle29"
|
||||
style="fill:#000000" />
|
||||
<circle
|
||||
cx="103.11"
|
||||
cy="26.618"
|
||||
r="3.7876999"
|
||||
fill="url(#linearGradient18659)"
|
||||
id="circle30"
|
||||
style="fill:#000000" />
|
||||
</g>
|
||||
<path
|
||||
d="m 6.1236759,5.856214 -2.0626,-3.6879 0.52544,-0.0074 1.9387,3.4465 z"
|
||||
fill="url(#linearGradient3254)"
|
||||
id="path30"
|
||||
style="fill:url(#linearGradient3254)" />
|
||||
<path
|
||||
d="M 12.808567,16.168211 6.1524738,12.428132 4.2457352,16.165572 Z"
|
||||
fill="#00ccff"
|
||||
id="path17"
|
||||
style="fill:#1a1a1a;fill-opacity:1"
|
||||
sodipodi:nodetypes="cccc" />
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 9 KiB |
|
|
@ -1,10 +0,0 @@
|
|||
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_26_18)">
|
||||
<path d="M3 7.06015V4.74436C4.12 4.69624 4.90412 4.62466 5.35237 4.52962C6.06664 4.37804 6.64769 4.07549 7.09553 3.62195C7.40205 3.31158 7.63448 2.89754 7.7928 2.37985C7.8839 2.06947 7.92946 1.8387 7.92946 1.68752H10.9001V19H7.25588V7.06015H3ZM12.4228 5.65444V4.52962L15.0783 1H16.1879V4.64211H17V5.65444H16.1879V7.05594H15.0084V5.65444H12.4228ZM14.9823 2.53985L13.4031 4.64511H15.0102V2.53985H14.9823Z" fill="black"/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_26_18">
|
||||
<rect width="20" height="20" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 660 B |
|
|
@ -1,65 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
||||
|
||||
<svg
|
||||
fill="#000000"
|
||||
width="20"
|
||||
height="20"
|
||||
viewBox="0 0 380.95238 380.95238"
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
sodipodi:docname="crosshair-symbolic.svg"
|
||||
inkscape:version="1.3.2 (091e20ef0f, 2023-11-25, custom)"
|
||||
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"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/">
|
||||
<defs
|
||||
id="defs1" />
|
||||
<sodipodi:namedview
|
||||
id="namedview1"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:zoom="35"
|
||||
inkscape:cx="10.371429"
|
||||
inkscape:cy="7.9571429"
|
||||
inkscape:window-width="1430"
|
||||
inkscape:window-height="1028"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg1" />
|
||||
<title
|
||||
id="title1">ionicons-v5_logos</title>
|
||||
<metadata
|
||||
id="metadata1">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:title>ionicons-v5_logos</dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<rect
|
||||
style="fill:#000000;stroke-width:23.0377"
|
||||
id="rect1"
|
||||
width="380.95239"
|
||||
height="57.142857"
|
||||
x="-3.5527137e-15"
|
||||
y="161.90475" />
|
||||
<rect
|
||||
style="fill:#000000;stroke-width:23.0451;stroke-dasharray:none"
|
||||
id="rect1-5"
|
||||
width="57.142857"
|
||||
height="380.95239"
|
||||
x="161.90475"
|
||||
y="0" />
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.8 KiB |
|
|
@ -1,91 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
||||
|
||||
<svg
|
||||
width="20"
|
||||
height="20"
|
||||
viewBox="-30.5 0 317.00242 317.00243"
|
||||
version="1.1"
|
||||
preserveAspectRatio="xMidYMid"
|
||||
id="svg12"
|
||||
sodipodi:docname="debian-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="defs12" />
|
||||
<sodipodi:namedview
|
||||
id="namedview12"
|
||||
pagecolor="#505050"
|
||||
bordercolor="#ffffff"
|
||||
borderopacity="1"
|
||||
inkscape:showpageshadow="0"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pagecheckerboard="1"
|
||||
inkscape:deskcolor="#505050"
|
||||
inkscape:zoom="17.5"
|
||||
inkscape:cx="13.742857"
|
||||
inkscape:cy="12.628571"
|
||||
inkscape:window-width="1295"
|
||||
inkscape:window-height="867"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg12" />
|
||||
<g
|
||||
fill="#A80030"
|
||||
id="g12"
|
||||
style="fill:#1a1a1a"
|
||||
transform="translate(0.05835351,0.0538775)">
|
||||
<path
|
||||
d="m 152.79662,167.42537 c -5.25095,0.0731 0.9935,2.70583 7.84865,3.76069 1.8935,-1.47856 3.61167,-2.97466 5.14283,-4.42984 -4.26913,1.04609 -8.61424,1.06947 -12.99148,0.66915"
|
||||
id="path1"
|
||||
style="fill:#1a1a1a" />
|
||||
<path
|
||||
d="m 180.9799,160.40073 c 3.12661,-4.31588 5.40581,-9.04086 6.20938,-13.92654 -0.70129,3.4831 -2.59187,6.4899 -4.3714,9.66326 -9.81521,6.18016 -0.92337,-3.67011 -0.006,-7.41328 -10.55448,13.2837 -1.44934,7.96554 -1.83213,11.67656"
|
||||
id="path2"
|
||||
style="fill:#1a1a1a" />
|
||||
<path
|
||||
d="m 191.38244,133.33075 c 0.63409,-9.45579 -1.86135,-6.46652 -2.69999,-2.85777 0.9789,0.50844 1.75324,6.66522 2.69999,2.85777"
|
||||
id="path3"
|
||||
style="fill:#1a1a1a" />
|
||||
<path
|
||||
d="m 132.88569,4.0879643 c 2.80225,0.5025946 6.05451,0.8883068 5.59867,1.5574589 3.06524,-0.6720742 3.76069,-1.2915513 -5.59867,-1.5574589"
|
||||
id="path4"
|
||||
style="fill:#1a1a1a" />
|
||||
<path
|
||||
d="m 138.48436,5.6454232 -1.98116,0.4090887 1.84382,-0.1636355 0.13734,-0.2454532"
|
||||
id="path5"
|
||||
style="fill:#1a1a1a" />
|
||||
<path
|
||||
d="m 225.86569,136.91612 c 0.31266,8.49151 -2.48375,12.61162 -5.00549,19.90509 l -4.53796,2.26752 c -3.71394,7.21165 0.35941,4.57887 -2.29967,10.31487 -5.79737,5.15452 -17.59373,16.12979 -21.36903,17.13205 -2.75551,-0.0614 1.86719,-3.25225 2.47206,-4.50289 -7.76099,5.32984 -6.22691,8.0006 -18.09633,11.23824 l -0.34772,-0.77142 c -29.27322,13.77168 -69.93663,-13.52038 -69.40189,-50.75913 -0.31266,2.36394 -0.88831,1.77369 -1.537,2.7292 -1.51071,-19.15996 8.848,-38.40465 26.31901,-46.262078 17.08821,-8.459369 37.12187,-4.987959 49.36238,6.419768 -6.72366,-8.807092 -20.1067,-18.14308 -35.96765,-17.269383 -15.53661,0.245453 -30.07094,10.1191 -34.92156,20.837223 -7.9597,5.01133 -8.88307,19.31775 -12.351558,21.93592 -4.666532,34.29623 8.777878,49.11401 31.520278,66.54411 3.57953,2.41362 1.00811,2.77888 1.49318,4.61685 -7.55646,-3.53861 -14.4759,-8.88014 -20.16515,-15.41972 3.01849,4.41816 6.27659,8.71359 10.48728,12.08857 -7.12399,-2.41362 -16.64115,-17.26354 -19.42003,-17.8684 12.28143,21.98851 49.827,38.56245 69.48663,30.33976 -9.09638,0.33604 -20.65313,0.18702 -30.8745,-3.59121 -4.29251,-2.20908 -10.13079,-6.78503 -9.08761,-7.64119 26.83037,10.02267 54.54612,7.59151 77.7619,-11.0191 5.90549,-4.59932 12.3574,-12.4246 14.22168,-12.53272 -2.8081,4.22238 0.47921,2.03083 -1.67727,5.75938 5.88504,-9.49085 -2.5568,-3.86296 6.08374,-16.38984 l 3.19089,4.39478 c -1.18636,-7.87788 9.78306,-17.44471 8.66975,-29.90438 2.5159,-3.81037 2.80811,4.09965 0.13734,12.86584 3.70517,-9.72462 0.97597,-11.28793 1.92856,-19.31191 1.02857,2.69707 2.37856,5.56361 3.07109,8.4097 -2.41362,-9.39735 2.47791,-15.82589 3.68764,-21.28722 -1.1922,-0.52889 -3.72563,4.15517 -4.3042,-6.94574 0.0847,-4.8214 1.34123,-2.52759 1.82629,-3.71394 -0.94675,-0.54351 -3.4305,-4.23991 -4.9412,-11.328836 1.09577,-1.665575 2.9279,4.318806 4.41815,4.564256 -0.95843,-5.636653 -2.6094,-9.935006 -2.67661,-14.259657 -4.35387,-9.0993 -1.53992,1.212656 -5.07269,-3.906796 -4.63439,-14.45544 3.84543,-3.354527 4.41815,-9.923322 7.02464,10.177541 11.03079,25.950835 12.86876,32.484565 -1.40259,-7.965545 -3.67011,-15.68271 -6.4373,-23.148578 2.13311,0.897073 -3.43634,-16.389844 2.77304,-4.941206 -6.63308,-24.40506 -28.38783,-47.208829 -48.40103,-57.909419 2.44869,2.241221 5.54023,5.055166 4.42984,5.496398 -9.95254,-5.925941 -8.20223,-6.387627 -9.62819,-8.891834 -8.10872,-3.299008 -8.64054,0.265908 -14.01129,0.0058 -15.28238,-8.105755 -18.22782,-7.243747 -32.2917,-12.32229 l 0.63993,2.9892691 c -10.12494,-3.3720592 -11.79636,1.279863 -22.73948,0.011688 -0.66623,-0.520127 3.50647,-1.8818077 6.93989,-2.3814803 -9.7889,1.2915513 -9.33014,-1.9285607 -18.90866,0.3564916 2.36103,-1.656809 4.85647,-2.7525822 7.37529,-4.1610159 -7.98308,0.4850622 -19.05769,4.6460781 -15.63888,0.8620082 C 96.316085,8.9298206 73.190888,17.085295 60.214012,29.25276 L 59.804924,26.526476 C 53.858528,33.665073 33.874548,47.845838 32.282025,57.091242 l -1.589602,0.371102 C 27.59796,62.7016 25.596347,68.63923 23.141816,74.030433 19.09476,80.926499 17.21003,76.683665 17.785676,77.764828 9.8259803,93.903375 5.8724309,107.46466 2.4565407,118.58603 4.8906182,122.224 2.514982,140.48688 3.4354314,155.10304 -0.56194899,227.28965 54.098137,297.37822 113.84553,313.5606 c 8.75742,3.13245 21.78105,3.01264 32.85859,3.33407 -13.07039,-3.73732 -14.75934,-1.98116 -27.49076,-6.41977 -9.18404,-4.32465 -11.19734,-9.26293 -17.70185,-14.90836 l 2.57434,4.54965 c -12.757724,-4.51458 -7.419118,-5.58698 -17.798281,-8.8743 l 2.74966,-3.59121 c -4.134717,-0.31266 -10.951887,-6.96912 -12.816162,-10.65384 l -4.523352,0.17825 C 66.26268,270.46895 63.366917,265.63586 63.577306,261.8927 l -1.461031,2.60356 c -1.656809,-2.84317 -19.995669,-25.15019 -10.481436,-19.95768 -1.767847,-1.6159 -4.117185,-2.62986 -6.665222,-7.2584 l 1.937326,-2.21493 c -4.57887,-5.89087 -8.427226,-13.44148 -8.135019,-15.95737 2.442843,3.299 4.137639,3.91556 5.814902,4.47952 -11.562598,-28.68881 -12.211295,-1.58084 -20.968714,-29.20309 l 1.852587,-0.14902 c -1.420122,-2.13895 -2.28213,-4.46199 -3.424657,-6.7412 l 0.80649,-8.03567 c -8.324954,-9.62527 -2.328884,-40.9264 -1.127916,-58.09351 0.832787,-6.9808 6.948662,-14.41161 11.600585,-26.064789 l -2.8344,-0.487985 c 5.417502,-9.449947 30.932945,-37.951737 42.749763,-36.484862 5.724319,-7.191194 -1.136683,-0.0263 -2.255832,-1.837977 12.573631,-13.011941 16.527181,-9.192806 25.012848,-11.533378 9.1519,-5.432112 -7.854502,2.118495 -3.51524,-2.071741 15.82004,-4.041212 11.21195,-9.186962 31.85047,-11.23825 2.17694,1.238955 -5.05224,1.913951 -6.86684,3.521085 13.18142,-6.448991 41.71243,-4.982116 60.24414,3.579525 21.50346,10.04897 45.66306,39.75465 46.61565,67.704172 l 1.08409,0.2922 c -0.54935,11.10968 1.70064,23.95799 -2.19739,35.76019 l 2.65323,-5.58698"
|
||||
id="path6"
|
||||
style="fill:#1a1a1a" />
|
||||
<path
|
||||
d="m 95.483297,174.6341 -0.736359,3.68179 c 3.450955,4.68699 6.188932,9.76553 10.595392,13.4298 -3.17043,-6.18893 -5.525615,-8.74573 -9.859033,-17.11159"
|
||||
id="path7"
|
||||
style="fill:#1a1a1a" />
|
||||
<path
|
||||
d="m 103.64169,174.31267 c -1.82629,-2.01915 -2.90745,-4.4503 -4.117181,-6.87269 1.157141,4.25744 3.526931,7.91586 5.733081,11.63565 l -1.6159,-4.76296"
|
||||
id="path8"
|
||||
style="fill:#1a1a1a" />
|
||||
<path
|
||||
d="m 248.00323,142.93557 -0.77142,1.9344 c -1.41428,10.04605 -4.46784,19.98691 -9.14898,29.20309 5.17205,-9.72462 8.51781,-20.36093 9.9204,-31.13749"
|
||||
id="path9"
|
||||
style="fill:#1a1a1a" />
|
||||
<path
|
||||
d="M 133.92302,1.5691471 C 137.47332,0.26882968 142.65122,0.85616408 146.41775,0 141.50869,0.4120107 136.623,0.65746388 131.79868,1.279863 l 2.12434,0.2892841"
|
||||
id="path10"
|
||||
style="fill:#1a1a1a" />
|
||||
<path
|
||||
d="m 9.2824769,67.847351 c 0.8181771,7.573984 -5.6980203,10.513578 1.4434981,5.519774 3.827901,-8.623004 -1.4960952,-2.38148 -1.4434981,-5.519774"
|
||||
id="path11"
|
||||
style="fill:#1a1a1a" />
|
||||
<path
|
||||
d="M 0.89031567,102.9004 C 2.5354364,97.85108 2.8334867,94.81798 3.46173,91.895919 -1.084998,97.707899 1.3695338,98.946854 0.89031567,102.9004"
|
||||
id="path12"
|
||||
style="fill:#1a1a1a" />
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 8.3 KiB |
|
|
@ -1,96 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
width="20mm"
|
||||
height="20mm"
|
||||
inkscape:version="1.3.2 (091e20ef0f, 2023-11-25, custom)"
|
||||
sodipodi:docname="EndeavourOS Logo.svg"
|
||||
version="1.1"
|
||||
viewBox="0 0 48.231007 48.231007"
|
||||
id="svg8"
|
||||
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"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/">
|
||||
<defs
|
||||
id="defs8" />
|
||||
<sodipodi:namedview
|
||||
id="cvfa"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:current-layer="g3"
|
||||
inkscape:cx="52.728754"
|
||||
inkscape:cy="60.739468"
|
||||
inkscape:document-rotation="0"
|
||||
inkscape:document-units="mm"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-height="1028"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:window-width="1316"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:zoom="4.930896"
|
||||
pagecolor="#ffffff"
|
||||
showgrid="false"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1" />
|
||||
<title
|
||||
id="title1">EndeavourOS Logo</title>
|
||||
<metadata
|
||||
id="metadata1">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title>EndeavourOS Logo</dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
transform="translate(-66.790568,-123.01834)"
|
||||
inkscape:groupmode="layer"
|
||||
inkscape:label="Layer 1"
|
||||
id="g8">
|
||||
<g
|
||||
transform="translate(76.2,-12.7)"
|
||||
id="g7">
|
||||
<g
|
||||
transform="matrix(1.47,0,0,1.47,-519,105)"
|
||||
id="g6">
|
||||
<g
|
||||
transform="matrix(0.963,0,0,0.983,13.5,0.76)"
|
||||
id="g5">
|
||||
<g
|
||||
transform="matrix(0.678,0,0,0.678,452,49.2)"
|
||||
id="g3">
|
||||
<g
|
||||
id="g9"
|
||||
transform="translate(6.8384014e-4,3.6851185)">
|
||||
<path
|
||||
d="m -127,-42.3 c 4.57,6.45 23.8,31.4 10.7,36.6 -6.12,2.81 -34,-1.65 -33.6,-0.921 -2,3.28 -3.59,5.92 -3.59,5.92 0,0 21.5,0.967 38.1,-1.27 23.7,-3.18 -4.88,-33.5 -11.6,-40.3 z"
|
||||
style="fill:#333333;fill-opacity:0.7;stroke-width:0.585"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path1" />
|
||||
<path
|
||||
d="m -127,-42.3 c -1.52,0.209 -29.4,34.5 -29.4,34.5 0,0 2.01,0.57 6.58,1.23 1.48,-1.15 22.3,-36.2 22.9,-35.7 -0.0107,-0.0141 -0.028,-0.0193 -0.0522,-0.016 z"
|
||||
style="fill:#333333;fill-opacity:0.7;stroke-width:0.585"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path2" />
|
||||
<path
|
||||
d="m -127,-42.3 c -0.96,-0.156 -22.9,35.7 -22.9,35.7 0,0 19.9,2.1 28.1,1.96 23.1,-0.39 0.176,-30.6 -5.16,-37.7 -0.007,-0.007 -0.0151,-0.0108 -0.0248,-0.0124 z"
|
||||
style="fill:#1a1a1a;stroke-width:0.585"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path3" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 3.3 KiB |
|
|
@ -1,38 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
viewBox="0 0 448.00288 448.00288"
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
sodipodi:docname="Fa-Team-Fontawesome-Brands-FontAwesome-Brands-Fedora.svg"
|
||||
width="19.999744"
|
||||
height="19.999744"
|
||||
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="#505050"
|
||||
bordercolor="#ffffff"
|
||||
borderopacity="1"
|
||||
inkscape:showpageshadow="0"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pagecheckerboard="1"
|
||||
inkscape:deskcolor="#505050"
|
||||
inkscape:zoom="13.671875"
|
||||
inkscape:cx="19.2"
|
||||
inkscape:cy="17.664"
|
||||
inkscape:window-width="1313"
|
||||
inkscape:window-height="908"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg1" />
|
||||
<!--! Font Awesome Free 6.2.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2022 Fonticons, Inc. -->
|
||||
<path
|
||||
d="M 0.0413,223.8 C 0.1219,100.2 100.3,0 224,0 347.7,0 448,100.3 448,224 448,347.7 347.8,447.9 224.1,448 H 50.93 C 22.84,448 0.0832,425.3 0.0416,397.2 H 0 V 223.8 Z M 342.6,160.7 c 0,-39.7 -35.6,-68.5 -73.2,-68.5 -34.9,0 -65.8,26.3 -70.1,59.9 -0.2,3.8 -0.4,5 -0.4,8.5 -0.1,21.1 0,42.8 -0.8,64.4 0.9,26.1 1,52.1 0,76.6 0,27.1 -19.4,45.5 -44.7,45.5 -25.3,0 -45.8,-20.2 -45.8,-45.5 0.5,-27.7 22.6,-45.3 48.5,-46.1 h 0.2 l 26.3,-0.2 V 218 l -26.3,0.2 c -47.1,-0.4 -84.58,36.5 -85.94,83.4 0,45.6 37.54,82.9 83.04,82.9 43,0 78.7,-33.6 82.6,-75.6 l 0.2,-53.5 32.6,-0.3 c 25.3,0.2 25,-37.8 -0.2,-37.3 l -32.4,0.3 c 0,-6.4 0.1,-12.8 0.1,-19.2 0.1,-12.7 0.1,-25.4 -0.1,-38.2 0.1,-16.5 15.8,-31.2 33.2,-31.2 17.5,0 35.9,8.7 35.9,31.2 0,3.2 -0.1,5.1 -0.3,6.3 -1.9,10.5 5.2,20.4 15.7,21.9 10.6,1.5 20.2,-6.1 21.2,-16.6 0.6,-4.2 0.7,-7.9 0.7,-11.6 z"
|
||||
id="path1" />
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 2.1 KiB |
|
|
@ -1,52 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
role="img"
|
||||
viewBox="0 0 24.000009 24.000009"
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
sodipodi:docname="flatpak_logo_icon_248537.svg"
|
||||
width="20"
|
||||
height="20"
|
||||
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"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/">
|
||||
<defs
|
||||
id="defs1" />
|
||||
<sodipodi:namedview
|
||||
id="namedview1"
|
||||
pagecolor="#505050"
|
||||
bordercolor="#ffffff"
|
||||
borderopacity="1"
|
||||
inkscape:showpageshadow="0"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pagecheckerboard="1"
|
||||
inkscape:deskcolor="#505050"
|
||||
inkscape:zoom="18.229167"
|
||||
inkscape:cx="11.190857"
|
||||
inkscape:cy="11.766857"
|
||||
inkscape:window-width="1164"
|
||||
inkscape:window-height="648"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg1" />
|
||||
<title
|
||||
id="title1">Flatpak</title>
|
||||
<path
|
||||
d="m 12.000004,7.3336774e-5 c -0.556,0 -1.110999,0.143999993226 -1.609999,0.431999993226 L 2.7870046,4.8220733 a 3.217,3.217 0 0 0 -1.61,2.788 v 8.7799997 c 0,1.151 0.612,2.212 1.61,2.788 l 7.6030004,4.39 a 3.217,3.217 0 0 0 3.219999,0 l 7.603,-4.39 a 3.217,3.217 0 0 0 1.61,-2.788 V 7.6100733 a 3.217,3.217 0 0 0 -1.61,-2.788 l -7.603,-4.38999997 a 3.218,3.218 0 0 0 -1.61,-0.431999993226 z m 0,2.357999963226 c 0.15,0 0.299,0.039 0.431,0.115 l 7.604,4.39 c 0.132,0.077 0.24,0.187 0.315,0.316 l -8.35,4.8209997 v 9.642 a 0.863,0.863 0 0 1 -0.431,-0.116 l -7.6039994,-4.39 a 0.866,0.866 0 0 1 -0.431,-0.746 V 7.6100733 c 0,-0.153 0.041,-0.302 0.116,-0.43 l 8.3499994,4.8199997 z"
|
||||
id="path1" />
|
||||
<metadata
|
||||
id="metadata1">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:title>Flatpak</dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 2.1 KiB |
|
|
@ -1,40 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
width="98"
|
||||
height="96"
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
sodipodi:docname="github-symbolic.svg"
|
||||
inkscape:version="1.3.2 (091e20ef0f, 2023-11-25, custom)"
|
||||
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="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:zoom="2.4081633"
|
||||
inkscape:cx="32.597458"
|
||||
inkscape:cy="46.716102"
|
||||
inkscape:window-width="1339"
|
||||
inkscape:window-height="1028"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg1" />
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
clip-rule="evenodd"
|
||||
d="M48.854 0C21.839 0 0 22 0 49.217c0 21.756 13.993 40.172 33.405 46.69 2.427.49 3.316-1.059 3.316-2.362 0-1.141-.08-5.052-.08-9.127-13.59 2.934-16.42-5.867-16.42-5.867-2.184-5.704-5.42-7.17-5.42-7.17-4.448-3.015.324-3.015.324-3.015 4.934.326 7.523 5.052 7.523 5.052 4.367 7.496 11.404 5.378 14.235 4.074.404-3.178 1.699-5.378 3.074-6.6-10.839-1.141-22.243-5.378-22.243-24.283 0-5.378 1.94-9.778 5.014-13.2-.485-1.222-2.184-6.275.486-13.038 0 0 4.125-1.304 13.426 5.052a46.97 46.97 0 0 1 12.214-1.63c4.125 0 8.33.571 12.213 1.63 9.302-6.356 13.427-5.052 13.427-5.052 2.67 6.763.97 11.816.485 13.038 3.155 3.422 5.015 7.822 5.015 13.2 0 18.905-11.404 23.06-22.324 24.283 1.78 1.548 3.316 4.481 3.316 9.126 0 6.6-.08 11.897-.08 13.526 0 1.304.89 2.853 3.316 2.364 19.412-6.52 33.405-24.935 33.405-46.691C97.707 22 75.788 0 48.854 0z"
|
||||
fill="#fff"
|
||||
id="path1"
|
||||
style="fill:#000000" />
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.9 KiB |
|
|
@ -1,56 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
||||
|
||||
<svg
|
||||
fill="#000000"
|
||||
width="20"
|
||||
height="20"
|
||||
viewBox="0 0 380.95238 380.95238"
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
sodipodi:docname="google-gemini-symbolic.svg"
|
||||
inkscape:version="1.3.2 (091e20ef0f, 2023-11-25, custom)"
|
||||
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"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/">
|
||||
<defs
|
||||
id="defs1" />
|
||||
<sodipodi:namedview
|
||||
id="namedview1"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:zoom="17.5"
|
||||
inkscape:cx="10.828571"
|
||||
inkscape:cy="16.971429"
|
||||
inkscape:window-width="1351"
|
||||
inkscape:window-height="981"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg1" />
|
||||
<title
|
||||
id="title1">ionicons-v5_logos</title>
|
||||
<path
|
||||
d="m 190.47617,352.20814 v 0 0 C 177.81956,268.68717 112.26524,203.13276 28.744252,190.4762 v 0 0 C 112.26524,177.81957 177.81956,112.26522 190.47617,28.744235 v 0 0 c 12.65659,83.520985 78.2109,149.075335 161.73196,161.731965 v 0 0 c -83.52106,12.65656 -149.07537,78.21097 -161.73196,161.73194 z"
|
||||
fill="#076eff"
|
||||
id="path19"
|
||||
style="fill:#000000;stroke-width:4.44566" />
|
||||
<metadata
|
||||
id="metadata1">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:title>ionicons-v5_logos</dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 16 KiB |
|
|
@ -1,77 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
height="20"
|
||||
width="19.999744"
|
||||
version="1.1"
|
||||
id="svg8"
|
||||
sodipodi:docname="nixos-symbolic.svg"
|
||||
viewBox="0 0 512.00001 512.00656"
|
||||
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="defs8" />
|
||||
<sodipodi:namedview
|
||||
id="namedview8"
|
||||
pagecolor="#505050"
|
||||
bordercolor="#ffffff"
|
||||
borderopacity="1"
|
||||
inkscape:showpageshadow="0"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pagecheckerboard="1"
|
||||
inkscape:deskcolor="#505050"
|
||||
inkscape:zoom="27.34375"
|
||||
inkscape:cx="8.832"
|
||||
inkscape:cy="15.817143"
|
||||
inkscape:window-width="1075"
|
||||
inkscape:window-height="1028"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg8" />
|
||||
<g
|
||||
fill-rule="evenodd"
|
||||
transform="matrix(1.2756532,0,0,-1.2756532,9.0810546e-6,478.03773)"
|
||||
id="g8"
|
||||
style="fill:#000000">
|
||||
<path
|
||||
d="m 122.453,169.761 97.758,-169.34 -44.926,-0.422 -26.101,45.496 -26.286,-45.25 -22.32,0.008 -11.433,19.75 37.449,64.394 -26.582,46.258 z"
|
||||
fill="#5277c3"
|
||||
id="path1"
|
||||
style="fill:#000000" />
|
||||
<path
|
||||
d="M 157.738,239.515 59.961,70.183 37.133,108.882 63.484,154.229 11.152,154.366 0,173.702 l 11.391,19.777 74.488,-0.234 26.769,46.152 z"
|
||||
fill="#7ebae4"
|
||||
id="path2"
|
||||
style="fill:#000000" />
|
||||
<path
|
||||
d="M 165.238,104.155 360.77,104.143 338.672,65.026 286.223,65.171 312.27,19.784 301.102,0.456 278.277,0.429 241.238,65.058 187.883,65.167 Z"
|
||||
fill="#7ebae4"
|
||||
id="path3"
|
||||
style="fill:#000000" />
|
||||
<path
|
||||
d="m 279.043,178.35 -97.758,169.34 44.926,0.422 26.101,-45.496 26.286,45.254 22.32,-0.008 11.434,-19.754 -37.45,-64.39 26.582,-46.262 z"
|
||||
fill="#7ebae4"
|
||||
id="path4"
|
||||
style="fill:#000000" />
|
||||
<g
|
||||
fill="#5277c3"
|
||||
id="g7"
|
||||
style="fill:#000000">
|
||||
<path
|
||||
d="m 122.453,169.761 97.758,-169.34 -44.926,-0.422 -26.101,45.496 -26.286,-45.25 -22.32,0.008 -11.433,19.75 37.449,64.394 -26.582,46.258 z"
|
||||
id="path5"
|
||||
style="fill:#000000" />
|
||||
<path
|
||||
d="m 236,244.386 -195.535,0.011 22.101,39.118 52.45,-0.149 -26.047,45.391 11.168,19.328 22.82,0.023 37.043,-64.625 53.352,-0.109 z"
|
||||
id="path6"
|
||||
style="fill:#000000" />
|
||||
<path
|
||||
d="m 243.625,108.636 97.777,169.328 22.825,-38.696 -26.348,-45.351 52.332,-0.137 11.152,-19.336 -11.39,-19.777 -74.489,0.238 -26.769,-46.152 z"
|
||||
id="path7"
|
||||
style="fill:#000000" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 2.7 KiB |
|
|
@ -1,60 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
width="20"
|
||||
height="20.000149"
|
||||
viewBox="0 0 853.78869 853.79504"
|
||||
fill="none"
|
||||
version="1.1"
|
||||
id="svg5"
|
||||
sodipodi:docname="ollama-symbolic.svg"
|
||||
inkscape:version="1.3.2 (091e20ef0f, 2023-11-25, custom)"
|
||||
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="defs5" />
|
||||
<sodipodi:namedview
|
||||
id="namedview5"
|
||||
pagecolor="#505050"
|
||||
bordercolor="#eeeeee"
|
||||
borderopacity="1"
|
||||
inkscape:showpageshadow="0"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#505050"
|
||||
showguides="false"
|
||||
inkscape:zoom="23.606557"
|
||||
inkscape:cx="13.004861"
|
||||
inkscape:cy="9.8065973"
|
||||
inkscape:window-width="1374"
|
||||
inkscape:window-height="848"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg5" />
|
||||
<g
|
||||
id="g5"
|
||||
transform="translate(103.8943,1.5259608e-5)">
|
||||
<path
|
||||
d="M 140.629,0.23994313 C 132.66,1.5272641 123.097,5.6956941 116.354,10.845014 c -20.413,15.5091 -36.2287,48.4278 -42.9105,89.437996 -2.5133,15.509 -4.2297,37.026 -4.2297,53.455 0,19.371 2.2681,44.136 5.5171,61.239 0.7356,3.801 1.1034,7.173 0.7969,7.418 -0.2452,0.245 -3.249,2.697 -6.6206,5.394 -11.5245,9.195 -24.7043,23.356 -33.7768,36.291 -17.4095,24.704 -28.6888898,52.78 -33.4090698,83.185 -1.83902799,12.015 -2.32943599,36.29 -0.85821199,48.305 3.24895199,27.708 11.58588179,51.125 25.86898179,72.581 l 4.6589,6.927 -1.3486,2.268 c -9.563,16.061 -17.716,39.294 -21.5166498,61.607 -3.00375,17.655 -3.37156,22.375 -3.37156,46.037 0,23.847 0.30651,28.567 3.12635,45.057 3.3715598,19.739 10.2372598,40.642 17.8998598,54.558 2.5134,4.536 8.6435,13.976 9.3791,14.467 0.2452,0.122 -0.4904,2.39 -1.6551,5.026 -8.8274,19.31 -16.3674,44.995 -19.4938,66.635 -2.2068,14.834 -2.5133,19.616 -2.5133,35.248 0,19.922 1.1034,29.608 5.2719,45.485 l 0.613,2.329 H 44.019 70.3172 l -1.7165,-3.249 c -10.605,-19.616 -11.5858,-56.029 -2.452,-92.38 4.1685,-16.797 8.8887,-29.118 17.716,-46.099 l 5.2719,-10.298 v -6.314 c 0,-5.885 -0.1226,-6.559 -2.0229,-10.421 -1.4713,-2.943 -3.4329,-5.456 -6.9271,-8.889 -5.9462,-5.762 -10.2372,-11.831 -13.6701,-19.31 -15.08,-32.735 -18.0225,-81.346 -7.4174,-122.786 4.4137,-17.287 11.7085,-32.673 19.3711,-41.071 5.2106,-5.763 7.9078,-12.199 7.9078,-18.881 0,-6.927 -2.452,-12.628 -7.9691,-18.574 -15.8157,-16.919 -25.5625,-37.517 -29.0567,-61.485 -4.9654,-34.145 4.0459,-71.355 24.5204,-100.84 20.0455,-28.935 48.1824,-47.509 79.6304,-52.474 7.049,-1.165 20.229,-0.981 27.585,0.368 8.031,1.41 13.057,0.98 18.207,-1.472 6.375,-3.003 9.563,-6.743 13.302,-15.325 3.31,-7.662 5.885,-11.831 12.812,-20.474 8.337,-10.36 16.367,-17.41 29.24,-25.931 14.713,-9.624 31.448,-16.612 48.122,-19.984 6.068,-1.226 8.888,-1.41 20.229,-1.41 11.341,0 14.161,0.184 20.229,1.41 24.459,4.966 48.735,17.594 68.106,35.493 4.168,3.862 14.16,16.245 17.348,21.395 1.226,2.022 3.372,6.314 4.72,9.501 3.739,8.582 6.927,12.322 13.302,15.325 4.966,2.391 10.176,2.882 17.9,1.594 12.199,-2.084 21.578,-1.9 33.532,0.552 40.704,8.214 76.136,41.746 91.829,86.68 13.67,39.416 9.808,80.672 -10.544,112.18 -3.433,5.334 -6.866,9.625 -11.831,14.897 -10.728,11.463 -10.728,25.685 -0.061,37.455 17.532,19.187 28.505,66.389 25.194,108.012 -2.206,27.463 -9.256,52.045 -18.942,65.96 -1.716,2.452 -5.271,6.62 -7.969,9.195 -3.494,3.433 -5.455,5.946 -6.927,8.889 -1.9,3.862 -2.023,4.536 -2.023,10.421 v 6.314 l 5.272,10.298 c 8.828,16.981 13.548,29.302 17.716,46.099 9.012,35.861 8.215,71.538 -2.084,91.829 -0.858,1.716 -1.594,3.31 -1.594,3.494 0,0.184 11.709,0.306 26.053,0.306 h 25.992 l 0.674,-2.636 c 0.368,-1.409 0.981,-3.555 1.287,-4.781 0.675,-2.697 2.023,-10.666 3.127,-18.329 1.042,-7.724 1.042,-36.168 0,-44.75 -3.923,-31.141 -10.483,-55.845 -21.21,-79.201 -1.165,-2.636 -1.901,-4.904 -1.656,-5.026 0.307,-0.184 2.023,-2.636 3.862,-5.395 13.364,-20.229 21.578,-45.669 25.747,-79.262 1.103,-9.257 1.103,-49.041 0,-57.93 -2.943,-22.926 -6.498,-38.497 -12.383,-54.251 -2.452,-6.559 -8.95,-20.413 -11.708,-24.888 l -1.349,-2.268 4.659,-6.927 c 14.283,-21.456 22.62,-44.873 25.869,-72.581 1.471,-12.015 0.981,-36.29 -0.858,-48.305 -4.782,-30.467 -16,-58.42 -33.409,-83.185 -9.073,-12.935 -22.253,-27.096 -33.777,-36.291 -3.372,-2.697 -6.376,-5.149 -6.621,-5.394 -0.306,-0.245 0.062,-3.617 0.797,-7.418 7.418,-38.681 7.172,-86.924 -0.613,-124.624596 -6.743,-32.8573 -19.003,-58.9716 -34.819,-74.0516 C 523.209,4.2857941 510.336,-0.86349287 494.888,0.11732413 459.456,2.2015541 430.89,42.966714 419.61,107.21001 c -1.839,10.36 -3.432,22.498 -3.432,25.808 0,1.287 -0.246,2.329 -0.552,2.329 -0.307,0 -2.697,-1.226 -5.272,-2.758 -27.34,-16.184 -57.746,-24.827 -87.354,-24.827 -29.608,0 -60.014,8.643 -87.354,24.827 -2.575,1.532 -4.965,2.758 -5.272,2.758 -0.306,0 -0.552,-1.042 -0.552,-2.329 0,-3.433 -1.655,-15.938 -3.432,-25.808 C 216.152,49.525914 192.674,11.335414 161.472,1.7111341 157.181,0.42381313 144.982,-0.43436787 140.629,0.23994313 Z M 151.051,50.139014 c 8.827,6.9883 18.635,26.9724 24.275,49.3473 1.042,4.045696 2.145,8.704696 2.452,10.420696 0.245,1.656 0.919,5.395 1.471,8.276 2.391,12.996 3.494,27.034 3.617,44.137 l 0.061,16.858 -4.23,6.252 -4.229,6.314 h -9.87 c -11.524,0 -22.988,1.472 -33.961,4.414 -3.923,0.981 -7.724,1.962 -8.459,2.146 -1.165,0.245 -1.349,-0.123 -2.023,-5.15 -3.617,-27.279 -3.433,-57.5 0.552,-82.634 4.413,-28.014096 14.712,-53.392696 24.765,-60.871396 2.391,-1.7778 2.82,-1.7165 5.579,0.4904 z m 349.538,-0.4292 c 6.069,4.475 12.751,16.3674 17.716,31.57 9.992,30.405196 12.812,72.151196 7.54,111.874196 -0.674,5.027 -0.858,5.395 -2.023,5.15 -0.735,-0.184 -4.536,-1.165 -8.459,-2.146 -10.973,-2.942 -22.437,-4.414 -33.961,-4.414 h -9.87 l -4.229,-6.314 -4.23,-6.252 0.061,-16.858 c 0.123,-23.785 2.33,-42.359 7.601,-63.017596 5.579,-22.191 15.448,-42.1751 24.214,-49.1634 2.759,-2.2069 3.188,-2.2682 5.64,-0.4292 z"
|
||||
fill="#000000"
|
||||
id="path1" />
|
||||
<path
|
||||
d="m 313.498,358.23701 c -13.303,1.288 -16.919,1.778 -23.295,3.066 -10.36,2.145 -24.214,6.927 -33.838,11.647 -33.47,16.367 -56.519,43.646 -63.569,75.216 -1.41,6.253 -1.594,8.337 -1.594,18.881 0,10.421 0.184,12.689 1.533,18.635 9.379,41.256 47.385,71.723 96.549,77.301 10.666,1.165 56.765,1.165 67.431,0 39.478,-4.475 73.439,-25.869 88.703,-55.907 4.045,-8.03 6.007,-13.241 7.846,-21.394 1.349,-5.946 1.533,-8.214 1.533,-18.635 0,-10.544 -0.184,-12.628 -1.594,-18.881 -10.238,-45.853 -54.742,-81.959 -109.3,-88.825 -7.111,-0.858 -25.746,-1.594 -30.405,-1.104 z m 22.926,33.348 c 18.207,1.962 36.536,8.46 51.248,18.268 7.908,5.272 19.065,16.306 23.846,23.54 5.885,8.949 9.256,18.083 10.789,29.179 0.674,5.088 0.307,8.95 -1.533,17.164 -2.881,12.26 -11.831,25.072 -23.907,34.022 -5.64,4.107 -17.348,10.054 -24.52,12.383 -13.609,4.352 -22.498,5.149 -54.252,4.904 -20.719,-0.184 -24.398,-0.368 -30.344,-1.471 -20.29,-3.801 -36.351,-11.893 -47.998,-24.214 -9.441,-9.931 -13.732,-19.003 -16.061,-33.654 -1.042,-6.805 0.919,-18.084 4.904,-27.586 4.843,-11.586 17.348,-25.991 29.731,-34.267 14.344,-9.563 33.225,-16.367 50.573,-18.206 6.682,-0.736 20.842,-0.736 27.524,-0.062 z"
|
||||
fill="#000000"
|
||||
id="path2" />
|
||||
<path
|
||||
d="m 299.584,436.33601 c -4.659,2.513 -7.908,8.888 -6.927,13.608 1.103,5.088 5.578,10.238 12.566,14.468 3.74,2.268 3.985,2.574 4.169,4.842 0.122,1.349 -0.368,5.211 -1.042,8.644 -0.736,3.371 -1.288,6.927 -1.288,7.908 0.062,2.636 2.514,6.927 5.088,9.011 2.269,1.839 2.698,1.9 9.073,2.084 5.824,0.184 7.05,0.061 9.379,-1.042 6.008,-2.943 7.54,-8.337 5.333,-18.697 -1.839,-8.643 -1.471,-9.992 3.127,-12.628 4.842,-2.82 9.992,-7.785 11.524,-11.157 2.943,-6.436 0.245,-13.731 -6.253,-17.103 -1.593,-0.797 -3.555,-1.164 -6.436,-1.164 -4.475,0 -7.356,1.042 -12.628,4.413 l -3.004,1.901 -1.9,-1.165 c -7.785,-4.598 -9.195,-5.149 -13.916,-5.088 -3.371,0 -5.21,0.306 -6.865,1.165 z"
|
||||
fill="#000000"
|
||||
id="path3" />
|
||||
<path
|
||||
d="m 150.744,365.16501 c -10.85,3.433 -18.942,11.402 -23.11,22.743 -2.023,5.395 -3.004,13.916 -2.146,18.513 2.023,10.973 11.034,20.965 21.272,23.724 12.873,3.371 22.497,1.164 31.018,-7.295 4.965,-4.843 7.663,-9.073 10.36,-15.939 1.961,-4.842 2.084,-5.7 2.084,-12.566 l 0.061,-7.356 -2.574,-5.272 c -4.108,-8.337 -11.525,-14.529 -20.107,-16.797 -4.843,-1.226 -12.628,-1.164 -16.858,0.245 z"
|
||||
fill="#000000"
|
||||
id="path4" />
|
||||
<path
|
||||
d="m 478.153,364.98201 c -8.398,2.268 -15.877,8.52 -19.862,16.735 l -2.574,5.272 0.061,7.356 c 0,6.866 0.123,7.724 2.084,12.566 2.698,6.866 5.395,11.096 10.36,15.939 8.521,8.459 18.145,10.666 31.019,7.295 7.417,-1.962 14.834,-8.215 18.39,-15.51 3.065,-6.191 3.8,-10.666 2.82,-17.716 -2.268,-16.122 -11.709,-27.83 -25.747,-31.937 -4.107,-1.226 -12.076,-1.226 -16.551,0 z"
|
||||
fill="#000000"
|
||||
id="path5" />
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 8.8 KiB |
|
|
@ -1,38 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
viewBox="0 0 322.58065 322.58064"
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
sodipodi:docname="openai-symbolic.svg"
|
||||
width="20"
|
||||
height="20"
|
||||
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="#505050"
|
||||
bordercolor="#ffffff"
|
||||
borderopacity="1"
|
||||
inkscape:showpageshadow="0"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pagecheckerboard="1"
|
||||
inkscape:deskcolor="#505050"
|
||||
inkscape:zoom="30.935922"
|
||||
inkscape:cx="9.0348044"
|
||||
inkscape:cy="14.917933"
|
||||
inkscape:window-width="1183"
|
||||
inkscape:window-height="1028"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg1" />
|
||||
<path
|
||||
d="m 298.66868,131.77215 c 7.30439,-21.92321 4.7891,-45.939129 -6.89187,-65.880296 C 274.21007,35.30601 238.89549,19.570397 204.40593,26.975391 189.0627,9.6903649 167.01876,-0.13936259 143.90833,0.0014933 108.65412,-0.07899576 77.374064,22.618921 66.528162,56.162739 43.880552,60.800921 24.33177,74.977058 12.892261,95.069141 -4.8052718,125.57449 -0.77075743,164.02814 22.872905,190.18709 c -7.304382,21.92321 -4.789099,45.93913 6.891877,65.8803 17.566738,30.58585 52.881316,46.32146 87.370878,38.91646 15.33316,17.28503 37.38717,27.11476 60.49759,26.96384 35.27433,0.0905 66.56446,-22.62749 77.41036,-56.20149 22.64761,-4.63818 42.19639,-18.81432 53.6359,-38.9064 17.67741,-30.50536 13.63284,-68.92883 -10.00077,-95.08777 z M 177.65337,300.90986 c -14.11577,0.0201 -27.78885,-4.91989 -38.62469,-13.96485 0.493,-0.26159 1.34819,-0.73446 1.90156,-1.07654 l 64.10954,-37.02497 c 3.27993,-1.86131 5.29215,-5.35253 5.27203,-9.12545 v -90.37916 l 27.09463,15.64506 c 0.29178,0.14086 0.48294,0.42257 0.52318,0.74453 v 74.84477 c -0.0402,33.28222 -26.99402,60.26618 -60.27625,60.33661 z M 48.025738,245.54345 c -7.072976,-12.21422 -9.618443,-26.53121 -7.19371,-40.42564 0.472874,0.28171 1.307948,0.79483 1.901554,1.13691 l 64.109538,37.02497 c 3.24974,1.90155 7.2742,1.90155 10.534,0 l 78.26556,-45.19461 v 31.29012 c 0.0201,0.32196 -0.1308,0.63386 -0.38232,0.83508 l -64.80376,37.41735 c -28.86539,16.62099 -65.72938,6.74096 -82.4208,-22.08418 z M 31.153218,105.60314 c 7.042793,-12.234331 18.160346,-21.591185 31.400797,-26.450712 0,0.553362 -0.03018,1.529292 -0.03018,2.213449 v 74.059993 c -0.02012,3.76287 1.992105,7.25408 5.261973,9.11539 l 78.265542,45.18455 -27.09463,15.64506 c -0.27165,0.1811 -0.61373,0.21129 -0.91556,0.0805 L 53.227344,188.00382 C 24.42232,171.32247 14.542287,134.46853 31.143157,105.6132 Z m 222.612632,51.80478 -78.26556,-45.19461 27.09463,-15.634999 c 0.27165,-0.181101 0.61373,-0.211284 0.91557,-0.08049 l 64.81382,37.417349 c 28.85533,16.6713 38.74542,53.5856 22.07412,82.44093 -7.05285,12.21421 -18.16034,21.57107 -31.39073,26.44066 V 166.5233 c 0.0302,-3.76286 -1.97199,-7.24401 -5.23179,-9.11538 z m 26.96383,-40.58661 c -0.47287,-0.29178 -1.30794,-0.79483 -1.90155,-1.13691 L 214.71859,78.659433 c -3.24975,-1.901555 -7.2742,-1.901555 -10.53401,0 L 125.91903,123.85404 V 92.563919 c -0.0201,-0.321957 0.13079,-0.633852 0.38232,-0.835074 l 64.80376,-37.387171 c 28.86539,-16.651176 65.76963,-6.74096 82.41074,22.134493 7.03273,12.194093 9.5782,26.470833 7.19371,40.345143 z M 111.18953,172.59017 84.08484,156.94511 c -0.291773,-0.14086 -0.482934,-0.42257 -0.523179,-0.74453 V 81.355816 c 0.02012,-33.322473 27.054379,-60.326555 60.376859,-60.306432 14.09564,0 27.73854,4.950077 38.57438,13.964853 -0.493,0.261589 -1.33813,0.734462 -1.90155,1.076541 l -64.10954,37.02497 c -3.27993,1.86131 -5.29216,5.342462 -5.27204,9.115387 l -0.0402,90.338915 z m 14.71943,-31.73282 34.86183,-20.13232 34.86183,20.12226 v 40.2546 l -34.86183,20.12226 -34.86183,-20.12226 z"
|
||||
id="path1"
|
||||
style="stroke-width:1.00611" />
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 4 KiB |
|
|
@ -1,39 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
version="1.1"
|
||||
width="20.000015"
|
||||
height="20"
|
||||
id="svg1"
|
||||
sodipodi:docname="openrouter-symbolic.svg"
|
||||
viewBox="0 0 47.999998 47.999962"
|
||||
inkscape:version="1.3.2 (091e20ef0f, 2023-11-25, custom)"
|
||||
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="#505050"
|
||||
bordercolor="#eeeeee"
|
||||
borderopacity="1"
|
||||
inkscape:showpageshadow="0"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#505050"
|
||||
inkscape:zoom="19.666667"
|
||||
inkscape:cx="6.7118644"
|
||||
inkscape:cy="10.805085"
|
||||
inkscape:window-width="1908"
|
||||
inkscape:window-height="1028"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg1" />
|
||||
<path
|
||||
d="m 32.999999,2.9999808 c 3.980422,0.5880984 6.862472,1.8203168 10.3125,3.875 0.883008,0.5130469 1.766016,1.0260937 2.675781,1.5546875 0.663867,0.5182031 1.327735,1.0364062 2.011719,1.5703125 0,0.9900002 0,1.9800002 0,3.0000002 -2.311036,1.335928 -4.623718,2.668844 -6.9375,4 -0.659355,0.381562 -1.318711,0.763125 -1.998047,1.15625 -4.951172,2.84375 -4.951172,2.84375 -6.064453,2.84375 0,-1.65 0,-3.3 0,-5 -6.609294,1.004133 -10.792298,2.789518 -16,7 3.696448,3.823912 6.292078,6.155833 11.6875,6.625 0.808242,0.07477 1.616484,0.149531 2.449219,0.226562 0.614883,0.04898 1.229765,0.09797 1.863281,0.148438 0,-0.99 0,-1.98 0,-3 4.062255,0.578231 6.847624,1.891177 10.3125,4.0625 0.883008,0.547852 1.766016,1.095703 2.675781,1.660156 0.663867,0.421524 1.327735,0.843047 2.011719,1.277344 -1.156668,3.470003 -1.857267,3.847015 -4.875,5.6875 -0.698672,0.436992 -1.397344,0.873984 -2.117188,1.324219 -2.007812,0.988281 -2.007812,0.988281 -5.007812,0.988281 0,0.66 0,1.32 0,2 -0.99,0.33 -1.98,0.66 -3,1 0,-1.32 0,-2.64 0,-4 C 32.359335,40.962601 31.718671,40.925211 31.058593,40.8867 22.287404,40.220037 16.393127,37.373973 9.2226552,32.429668 6.2608222,30.524517 3.2830902,29.257335 -8.4473381e-7,27.999981 c 0,-3.3 0,-6.6 0,-10 C 1.6232682,17.32911 3.2486752,16.663411 4.8749992,15.999981 c 0.904922,-0.37125 1.809844,-0.7425 2.742188,-1.125 2.382812,-0.875 2.382812,-0.875 4.3828118,-0.875 0,-0.66 0,-1.32 0,-2 0.99,0 1.98,0 3,0 0,-0.66 0,-1.32 0,-2.0000002 6.284532,-3.3279791 10.886587,-4.4516452 18,-4 0,-0.99 0,-1.98 0,-3 z"
|
||||
fill="#93a2b8"
|
||||
id="path1"
|
||||
style="fill:#000000" />
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 2.6 KiB |
|
|
@ -1,85 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
||||
|
||||
<svg
|
||||
fill="#000000"
|
||||
height="20.000002"
|
||||
width="20"
|
||||
version="1.1"
|
||||
id="Capa_1"
|
||||
viewBox="0 0 493.42511 493.42516"
|
||||
xml:space="preserve"
|
||||
sodipodi:docname="ubuntu-logo-svgrepo-com.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="defs9" /><sodipodi:namedview
|
||||
id="namedview9"
|
||||
pagecolor="#505050"
|
||||
bordercolor="#ffffff"
|
||||
borderopacity="1"
|
||||
inkscape:showpageshadow="0"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pagecheckerboard="1"
|
||||
inkscape:deskcolor="#505050"
|
||||
inkscape:zoom="12.374369"
|
||||
inkscape:cx="24.76894"
|
||||
inkscape:cy="15.515943"
|
||||
inkscape:window-width="1415"
|
||||
inkscape:window-height="753"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="Capa_1" />
|
||||
<g
|
||||
id="ubuntu"
|
||||
transform="translate(5.5573583e-4,0.00107926)">
|
||||
<g
|
||||
id="g2">
|
||||
<g
|
||||
id="g1">
|
||||
<path
|
||||
d="m 168.839,241.198 c 0,-38.117 17.894,-72.05 45.685,-93.896 L 171.988,79.22 c -35.648,25.603 -62.472,62.66 -75.127,105.796 19.811,12.751 32.949,35.031 32.949,60.353 0,24.424 -12.143,45.957 -30.783,58.918 13.606,40.86 40.12,75.838 74.706,100.113 l 39.559,-70.358 c -27.105,-21.838 -44.453,-55.318 -44.453,-92.844 z"
|
||||
id="path1" />
|
||||
</g>
|
||||
</g>
|
||||
<g
|
||||
id="g3">
|
||||
<path
|
||||
d="m 109.704,245.368 c 0,28.484 -23.132,51.592 -51.609,51.592 -28.491,0 -51.606,-23.107 -51.606,-51.592 0,-28.47 23.115,-51.577 51.606,-51.577 28.477,0 51.609,23.107 51.609,51.577 z"
|
||||
id="path2" />
|
||||
</g>
|
||||
<g
|
||||
id="g5">
|
||||
<g
|
||||
id="g4">
|
||||
<path
|
||||
d="m 399.494,370.126 c 12.002,0 23.301,2.936 33.23,8.149 30.924,-32.591 50.906,-75.595 54.211,-123.228 l -80.148,-1.551 c -6.171,60.111 -56.954,106.941 -118.677,106.941 -17.084,0 -33.388,-3.594 -48.101,-10.093 l -39.841,69.704 c 26.56,13.069 56.376,20.411 87.941,20.411 13.622,0 26.981,-1.379 39.854,-4.006 2.746,-37.072 33.717,-66.327 71.531,-66.327 z"
|
||||
id="path3" />
|
||||
</g>
|
||||
</g>
|
||||
<g
|
||||
id="g6">
|
||||
<path
|
||||
d="m 451.071,441.847 c 0,28.478 -23.084,51.576 -51.577,51.576 -28.493,0 -51.594,-23.098 -51.594,-51.576 0,-28.5 23.101,-51.592 51.594,-51.592 28.493,0 51.577,23.092 51.577,51.592 z"
|
||||
id="path5" />
|
||||
</g>
|
||||
<g
|
||||
id="g8">
|
||||
<g
|
||||
id="g7">
|
||||
<path
|
||||
d="m 438.211,110.152 c -11.677,8.269 -25.968,13.163 -41.399,13.163 -39.637,0 -71.73,-32.102 -71.73,-71.715 0,-2.104 0.094,-4.139 0.25,-6.181 -12.05,-2.307 -24.503,-3.491 -37.222,-3.491 -31.859,0 -61.988,7.498 -88.689,20.777 l 39.607,69.75 c 14.979,-6.748 31.593,-10.544 49.082,-10.544 61.177,0 111.601,46.074 118.491,105.414 l 80.147,-2.447 C 483.209,181.12 465.487,141.372 438.211,110.152 Z"
|
||||
id="path6" />
|
||||
</g>
|
||||
</g>
|
||||
<g
|
||||
id="g9">
|
||||
<path
|
||||
d="m 448.374,51.601 c 0,28.492 -23.038,51.592 -51.561,51.592 -28.491,0 -51.592,-23.1 -51.592,-51.592 C 345.22,23.107 368.321,0 396.812,0 c 28.523,0 51.562,23.107 51.562,51.601 z"
|
||||
id="path8" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 3.1 KiB |
|
|
@ -1,339 +0,0 @@
|
|||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Lesser General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) year name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License.
|
||||
|
|
@ -1,95 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<style-scheme id="custom-light" _name="Custom" version="1.0">
|
||||
<author>end_4</author>
|
||||
<_description>Catppuccin port but very random</_description>
|
||||
|
||||
<style name="bracket-match" background="#E3E6EB" bold="true"/>
|
||||
<style name="bracket-mismatch" background="#E3E6EB" underline="true"/>
|
||||
<style name="c:preprocessor" foreground="#DF8E1D"/>
|
||||
<style name="css:at-rules" foreground="#8839EF"/>
|
||||
<style name="css:color" foreground="#DF8E1D"/>
|
||||
<style name="css:keyword" foreground="#256BF5"/>
|
||||
<style name="current-line" background="#E3E6EB"/>
|
||||
<style name="cursor" foreground="#DC8A78"/>
|
||||
<style name="def:base-n-integer" foreground="#DF8E1D"/>
|
||||
<style name="def:boolean" foreground="#DF8E1D"/>
|
||||
<style name="def:builtin" foreground="#DF8E1D"/>
|
||||
<style name="def:character" foreground="#DF8E1D"/>
|
||||
<style name="def:comment" foreground="#9DA1B1"/>
|
||||
<style name="def:complex" foreground="#DF8E1D"/>
|
||||
<style name="def:decimal" foreground="#DF8E1D"/>
|
||||
<style name="def:doc-comment" foreground="#9DA1B1"/>
|
||||
<style name="def:doc-comment-element" foreground="#9DA1B1"/>
|
||||
<style name="def:error" foreground="#D53055" background="#EAEDF2"/>
|
||||
<style name="def:floating-point" foreground="#DF8E1D"/>
|
||||
<style name="def:function" foreground="#256BF5"/>
|
||||
<style name="def:identifier" foreground="#000000"/>
|
||||
<style name="def:keyword" foreground="#8839EF"/>
|
||||
<style name="def:note" foreground="#9DA1B1"/>
|
||||
<style name="def:number" foreground="#FE640B"/>
|
||||
<style name="def:operator" foreground="#8839EF"/>
|
||||
<style name="def:preprocessor" foreground="#256BF5"/>
|
||||
<style name="def:reserved" foreground="#8839EF"/>
|
||||
<style name="def:shebang" foreground="#9DA1B1"/>
|
||||
<style name="def:special-char" foreground="#256BF5"/>
|
||||
<style name="def:special-constant" foreground="#DF8E1D"/>
|
||||
<style name="def:statement" foreground="#8839EF"/>
|
||||
<style name="def:string" foreground="#4AA537"/>
|
||||
<style name="def:type" foreground="#256BF5" italic="true"/>
|
||||
<style name="diff:added-line" foreground="#282D32" background="#ACF2BD"/>
|
||||
<style name="diff:changed-line" foreground="#282D32" background="#F1F2C3"/>
|
||||
<style name="diff:location" foreground="#9DA1B1"/>
|
||||
<style name="diff:removed-line" foreground="#282D32" background="#FFEEF0"/>
|
||||
<style name="draw-spaces" foreground="#3b3a32"/>
|
||||
<style name="html:dtd" foreground="#4AA537"/>
|
||||
<style name="html:tag" foreground="#8839EF"/>
|
||||
<style name="js:function" foreground="#256BF5"/>
|
||||
<style name="line-numbers" foreground="#9699AA" background="#EAEDF2"/>
|
||||
<style name="perl:builtin" foreground="#256BF5"/>
|
||||
<style name="perl:include-statement" foreground="#8839EF"/>
|
||||
<style name="perl:special-variable" foreground="#DF8E1D"/>
|
||||
<style name="perl:variable" foreground="#000000"/>
|
||||
<style name="php:string" foreground="#4AA537"/>
|
||||
<style name="python:builtin-constant" foreground="#8839EF"/>
|
||||
<style name="python:builtin-function" foreground="#256BF5"/>
|
||||
<style name="python:module-handler" foreground="#8839EF"/>
|
||||
<style name="python:special-variable" foreground="#8839EF"/>
|
||||
<style name="ruby:attribute-definition" foreground="#8839EF"/>
|
||||
<style name="ruby:builtin" foreground="#000000"/>
|
||||
<style name="ruby:class-variable" foreground="#000000"/>
|
||||
<style name="ruby:constant" foreground="#000000"/>
|
||||
<style name="ruby:global-variable" foreground="#256BF5"/>
|
||||
<style name="ruby:instance-variable" foreground="#000000"/>
|
||||
<style name="ruby:module-handler" foreground="#8839EF"/>
|
||||
<style name="ruby:predefined-variable" foreground="#DF8E1D"/>
|
||||
<style name="ruby:regex" foreground="#f6aa11"/>
|
||||
<style name="ruby:special-variable" foreground="#8839EF"/>
|
||||
<style name="ruby:symbol" foreground="#DF8E1D"/>
|
||||
<style name="rubyonrails:attribute-definition" foreground="#8839EF"/>
|
||||
<style name="rubyonrails:block-parameter" foreground="#fd971f" italic="true"/>
|
||||
<style name="rubyonrails:builtin" foreground="#000000"/>
|
||||
<style name="rubyonrails:class-inherit" foreground="#256BF5" underline="true" italic="true"/>
|
||||
<style name="rubyonrails:class-name" foreground="#256BF5"/>
|
||||
<style name="rubyonrails:class-variable" foreground="#000000"/>
|
||||
<style name="rubyonrails:complex-interpolation" foreground="#DF8E1D"/>
|
||||
<style name="rubyonrails:constant" foreground="#000000"/>
|
||||
<style name="rubyonrails:global-variable" foreground="#256BF5"/>
|
||||
<style name="rubyonrails:instance-variable" foreground="#000000"/>
|
||||
<style name="rubyonrails:module-handler" foreground="#8839EF"/>
|
||||
<style name="rubyonrails:module-name" foreground="#256BF5"/>
|
||||
<style name="rubyonrails:predefined-variable" foreground="#DF8E1D"/>
|
||||
<style name="rubyonrails:rails" foreground="#000000"/>
|
||||
<style name="rubyonrails:regex" foreground="#f6aa11"/>
|
||||
<style name="rubyonrails:simple-interpolation" foreground="#DF8E1D"/>
|
||||
<style name="rubyonrails:special-variable" foreground="#8839EF"/>
|
||||
<style name="rubyonrails:symbol" foreground="#DF8E1D"/>
|
||||
<style name="search-match" background="#E3E6EB" bold="true" underline="true"/>
|
||||
<style name="selection" foreground="#f8f8f2" background="#444444"/>
|
||||
<style name="text" foreground="#f8f8f2" background="#222222"/>
|
||||
<style name="xml:attribute-name" foreground="#256BF5"/>
|
||||
<style name="xml:element-name" foreground="#8839EF"/>
|
||||
<style name="xml:entity" foreground="#c8cecc"/>
|
||||
<style name="xml:namespace" foreground="#8839EF"/>
|
||||
<style name="xml:tag" foreground="#8839EF"/>
|
||||
|
||||
</style-scheme>
|
||||
|
|
@ -1,121 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
Copyright (C) 2014 Leo Iannacone <info@leoiannacone.com>
|
||||
|
||||
This file was generated from a textmate theme named Monokai Extended
|
||||
with tm2gtksw2 tool. (Alexandre da Silva)
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA.
|
||||
-->
|
||||
|
||||
<!-- MODIFIED -->
|
||||
|
||||
<style-scheme id="custom" _name="Custom" version="1.0">
|
||||
<author>Leo Iannacone</author>
|
||||
<_description>Based on SublimeText Monokai Extended - Generated with tm2gtksw2</_description>
|
||||
|
||||
<style name="bracket-match" background="#333333" bold="true"/>
|
||||
<style name="bracket-mismatch" background="#333333" underline="true"/>
|
||||
<style name="c:preprocessor" foreground="#be84ff"/>
|
||||
<style name="css:at-rules" foreground="#f92672"/>
|
||||
<style name="css:color" foreground="#be84ff"/>
|
||||
<style name="css:keyword" foreground="#66d9ef"/>
|
||||
<style name="current-line" background="#333333"/>
|
||||
<style name="cursor" foreground="#f8f8f0"/>
|
||||
<style name="def:base-n-integer" foreground="#be84ff"/>
|
||||
<style name="def:boolean" foreground="#be84ff"/>
|
||||
<style name="def:builtin" foreground="#be84ff"/>
|
||||
<style name="def:character" foreground="#be84ff"/>
|
||||
<style name="def:comment" foreground="#75715e"/>
|
||||
<style name="def:complex" foreground="#be84ff"/>
|
||||
<style name="def:decimal" foreground="#be84ff"/>
|
||||
<style name="def:doc-comment" foreground="#75715e"/>
|
||||
<style name="def:doc-comment-element" foreground="#75715e"/>
|
||||
<style name="def:error" foreground="#f8f8f0" background="#f92672"/>
|
||||
<style name="def:floating-point" foreground="#be84ff"/>
|
||||
<style name="def:function" foreground="#a6e22e"/>
|
||||
<style name="def:identifier" foreground="#ffffff"/>
|
||||
<style name="def:keyword" foreground="#f92672"/>
|
||||
<style name="def:note" foreground="#75715e"/>
|
||||
<style name="def:number" foreground="#be84ff"/>
|
||||
<style name="def:operator" foreground="#f92672"/>
|
||||
<style name="def:preprocessor" foreground="#66d9ef"/>
|
||||
<style name="def:reserved" foreground="#f92672"/>
|
||||
<style name="def:shebang" foreground="#75715e"/>
|
||||
<style name="def:special-char" foreground="#66d9ef"/>
|
||||
<style name="def:special-constant" foreground="#be84ff"/>
|
||||
<style name="def:statement" foreground="#f92672"/>
|
||||
<style name="def:string" foreground="#e6db74"/>
|
||||
<style name="def:type" foreground="#66d9ef" italic="true"/>
|
||||
<style name="diff:added-line" foreground="#a6e22e"/>
|
||||
<style name="diff:changed-line" foreground="#e6db74"/>
|
||||
<style name="diff:location" foreground="#75715e"/>
|
||||
<style name="diff:removed-line" foreground="#f92672"/>
|
||||
<style name="draw-spaces" foreground="#3b3a32"/>
|
||||
<style name="html:dtd" foreground="#e6db74"/>
|
||||
<style name="html:tag" foreground="#f92672"/>
|
||||
<style name="js:function" foreground="#66d9ef"/>
|
||||
<style name="line-numbers" foreground="#bebeba" background="#333333"/>
|
||||
<style name="perl:builtin" foreground="#a6e22e"/>
|
||||
<style name="perl:include-statement" foreground="#f92672"/>
|
||||
<style name="perl:special-variable" foreground="#be84ff"/>
|
||||
<style name="perl:variable" foreground="#ffffff"/>
|
||||
<style name="php:string" foreground="#e6db74"/>
|
||||
<style name="python:builtin-constant" foreground="#f92672"/>
|
||||
<style name="python:builtin-function" foreground="#a6e22e"/>
|
||||
<style name="python:module-handler" foreground="#f92672"/>
|
||||
<style name="python:special-variable" foreground="#f92672"/>
|
||||
<style name="ruby:attribute-definition" foreground="#f92672"/>
|
||||
<style name="ruby:builtin" foreground="#ffffff"/>
|
||||
<style name="ruby:class-variable" foreground="#ffffff"/>
|
||||
<style name="ruby:constant" foreground="#ffffff"/>
|
||||
<style name="ruby:global-variable" foreground="#a6e22e"/>
|
||||
<style name="ruby:instance-variable" foreground="#ffffff"/>
|
||||
<style name="ruby:module-handler" foreground="#f92672"/>
|
||||
<style name="ruby:predefined-variable" foreground="#be84ff"/>
|
||||
<style name="ruby:regex" foreground="#f6aa11"/>
|
||||
<style name="ruby:special-variable" foreground="#f92672"/>
|
||||
<style name="ruby:symbol" foreground="#be84ff"/>
|
||||
<style name="rubyonrails:attribute-definition" foreground="#f92672"/>
|
||||
<style name="rubyonrails:block-parameter" foreground="#fd971f" italic="true"/>
|
||||
<style name="rubyonrails:builtin" foreground="#ffffff"/>
|
||||
<style name="rubyonrails:class-inherit" foreground="#a6e22e" underline="true" italic="true"/>
|
||||
<style name="rubyonrails:class-name" foreground="#66d9ef"/>
|
||||
<style name="rubyonrails:class-variable" foreground="#ffffff"/>
|
||||
<style name="rubyonrails:complex-interpolation" foreground="#be84ff"/>
|
||||
<style name="rubyonrails:constant" foreground="#ffffff"/>
|
||||
<style name="rubyonrails:global-variable" foreground="#a6e22e"/>
|
||||
<style name="rubyonrails:instance-variable" foreground="#ffffff"/>
|
||||
<style name="rubyonrails:module-handler" foreground="#f92672"/>
|
||||
<style name="rubyonrails:module-name" foreground="#66d9ef"/>
|
||||
<style name="rubyonrails:predefined-variable" foreground="#be84ff"/>
|
||||
<style name="rubyonrails:rails" foreground="#ffffff"/>
|
||||
<style name="rubyonrails:regex" foreground="#f6aa11"/>
|
||||
<style name="rubyonrails:simple-interpolation" foreground="#be84ff"/>
|
||||
<style name="rubyonrails:special-variable" foreground="#f92672"/>
|
||||
<style name="rubyonrails:symbol" foreground="#be84ff"/>
|
||||
<style name="search-match" background="#333333" bold="true" underline="true"/>
|
||||
<style name="selection" foreground="#f8f8f2" background="#444444"/>
|
||||
<style name="text" foreground="#f8f8f2" background="#222222"/>
|
||||
<style name="xml:attribute-name" foreground="#a6e22e"/>
|
||||
<style name="xml:element-name" foreground="#f92672"/>
|
||||
<style name="xml:entity" foreground="#c8cecc"/>
|
||||
<style name="xml:namespace" foreground="#f92672"/>
|
||||
<style name="xml:tag" foreground="#f92672"/>
|
||||
|
||||
|
||||
</style-scheme>
|
||||
|
||||
|
|
@ -1,81 +0,0 @@
|
|||
"use strict";
|
||||
// Import
|
||||
import Gdk from 'gi://Gdk';
|
||||
import GLib from 'gi://GLib';
|
||||
import App from 'resource:///com/github/Aylur/ags/app.js'
|
||||
import * as Utils from 'resource:///com/github/Aylur/ags/utils.js'
|
||||
// Stuff
|
||||
import userOptions from './modules/.configuration/user_options.js';
|
||||
import { firstRunWelcome, startBatteryWarningService } from './services/messages.js';
|
||||
import { startAutoDarkModeService } from './services/darkmode.js';
|
||||
// Widgets
|
||||
import { Bar, BarCornerTopleft, BarCornerTopright } from './modules/bar/main.js';
|
||||
import Cheatsheet from './modules/cheatsheet/main.js';
|
||||
// import DesktopBackground from './modules/desktopbackground/main.js';
|
||||
import Dock from './modules/dock/main.js';
|
||||
import Corner from './modules/screencorners/main.js';
|
||||
import Crosshair from './modules/crosshair/main.js';
|
||||
import Indicator from './modules/indicators/main.js';
|
||||
import Osk from './modules/onscreenkeyboard/main.js';
|
||||
import Overview from './modules/overview/main.js';
|
||||
import Session from './modules/session/main.js';
|
||||
import SideLeft from './modules/sideleft/main.js';
|
||||
import SideRight from './modules/sideright/main.js';
|
||||
import { COMPILED_STYLE_DIR } from './init.js';
|
||||
|
||||
const range = (length, start = 1) => Array.from({ length }, (_, i) => i + start);
|
||||
function forMonitors(widget) {
|
||||
const n = Gdk.Display.get_default()?.get_n_monitors() || 1;
|
||||
return range(n, 0).map(widget).flat(1);
|
||||
}
|
||||
function forMonitorsAsync(widget) {
|
||||
const n = Gdk.Display.get_default()?.get_n_monitors() || 1;
|
||||
return range(n, 0).forEach((n) => widget(n).catch(print))
|
||||
}
|
||||
|
||||
// Start stuff
|
||||
handleStyles(true);
|
||||
startAutoDarkModeService().catch(print);
|
||||
firstRunWelcome().catch(print);
|
||||
startBatteryWarningService().catch(print)
|
||||
|
||||
const Windows = () => [
|
||||
// forMonitors(DesktopBackground),
|
||||
forMonitors(Crosshair),
|
||||
Overview(),
|
||||
forMonitors(Indicator),
|
||||
forMonitors(Cheatsheet),
|
||||
SideLeft(),
|
||||
SideRight(),
|
||||
forMonitors(Osk),
|
||||
forMonitors(Session),
|
||||
...(userOptions.dock.enabled ? [forMonitors(Dock)] : []),
|
||||
...(userOptions.appearance.fakeScreenRounding !== 0 ? [
|
||||
forMonitors((id) => Corner(id, 'top left', true)),
|
||||
forMonitors((id) => Corner(id, 'top right', true)),
|
||||
forMonitors((id) => Corner(id, 'bottom left', true)),
|
||||
forMonitors((id) => Corner(id, 'bottom right', true)),
|
||||
] : []),
|
||||
...(userOptions.appearance.barRoundCorners ? [
|
||||
forMonitors(BarCornerTopleft),
|
||||
forMonitors(BarCornerTopright),
|
||||
] : []),
|
||||
];
|
||||
|
||||
const CLOSE_ANIM_TIME = 210; // Longer than actual anim time to make sure widgets animate fully
|
||||
const closeWindowDelays = {}; // For animations
|
||||
for (let i = 0; i < (Gdk.Display.get_default()?.get_n_monitors() || 1); i++) {
|
||||
closeWindowDelays[`osk${i}`] = CLOSE_ANIM_TIME;
|
||||
}
|
||||
|
||||
App.config({
|
||||
css: `${COMPILED_STYLE_DIR}/style.css`,
|
||||
stackTraceOnError: true,
|
||||
closeWindowDelay: closeWindowDelays,
|
||||
windows: Windows().flat(1),
|
||||
});
|
||||
|
||||
// Stuff that don't need to be toggled. And they're async so ugh...
|
||||
forMonitorsAsync(Bar);
|
||||
// Bar().catch(print); // Use this to debug the bar. Single monitor only.
|
||||
|
||||
|
|
@ -1,24 +0,0 @@
|
|||
// Want only the overview from my config? this is what you're looking for!
|
||||
// Remember to install: `dart-sass`, `ags`, `material-symbols`, and `xorg-xrandr`
|
||||
// To launch this, run the following
|
||||
// ags -c ~/.config/ags/config_overviewOnly.js
|
||||
// To toggle the overview, run:
|
||||
// ags -t overview
|
||||
// You might wanna add that as a keybind (in hyprland.conf)
|
||||
// bind = Super, Tab, exec, ags -t overview
|
||||
|
||||
// Import
|
||||
import App from 'resource:///com/github/Aylur/ags/app.js'
|
||||
// Widgets
|
||||
import Overview from './modules/overview/main.js';
|
||||
import { COMPILED_STYLE_DIR } from './init.js';
|
||||
|
||||
handleStyles(true);
|
||||
|
||||
App.config({
|
||||
css: `${COMPILED_STYLE_DIR}/style.css`,
|
||||
stackTraceOnError: true,
|
||||
windows: [
|
||||
Overview(),
|
||||
],
|
||||
});
|
||||
|
|
@ -1,55 +0,0 @@
|
|||
const Gio = imports.gi.Gio;
|
||||
const GLib = imports.gi.GLib;
|
||||
import configOptions from "../modules/.configuration/user_options.js";
|
||||
const { langCode, Extra_logs } = configOptions.i18n
|
||||
const translations = {};
|
||||
|
||||
let currentLanguage = langCode || getLanguageCode();
|
||||
|
||||
function getLanguageCode() {
|
||||
let langEnv = GLib.getenv('LANG') || GLib.getenv('LANGUAGE') || 'Default.';
|
||||
let langCode = langEnv.split('.')[0];
|
||||
return langCode;
|
||||
}
|
||||
|
||||
// Load language file
|
||||
function loadLanguage(lang) {
|
||||
if (!translations[lang]) {
|
||||
try {
|
||||
let filePath = `~/.config/ags/i18n/locales/${lang}.json`;
|
||||
filePath = filePath.replace(/^~/, GLib.get_home_dir());
|
||||
let file = Gio.File.new_for_path(filePath);
|
||||
let [success, contents] = file.load_contents(null);
|
||||
if (success) {
|
||||
let decoder = new TextDecoder('utf-8');
|
||||
let jsonString = decoder.decode(contents);
|
||||
translations[lang] = JSON.parse(jsonString);
|
||||
}
|
||||
} catch (error) {
|
||||
if (Extra_logs || lang === "Default")
|
||||
console.warn(`Failed to load language file, language code: ${lang}:\n`, error);
|
||||
return;
|
||||
}
|
||||
}
|
||||
currentLanguage = currentLanguage || lang;
|
||||
}
|
||||
|
||||
// Initialize default language
|
||||
function init() {
|
||||
try {
|
||||
loadLanguage(currentLanguage);
|
||||
if (Extra_logs)
|
||||
console.log(getString("Initialization complete!") || "Initialization complete!");
|
||||
loadLanguage("Default");
|
||||
} catch (error) {
|
||||
console.error('Failed to initialize default language:', error);
|
||||
}
|
||||
}
|
||||
|
||||
// Get translation, if no corresponding value, return the key
|
||||
function getString(key) {
|
||||
if (key && !translations[currentLanguage]?.[key] && Extra_logs)
|
||||
console.warn(`${translations[currentLanguage]["Not found"] || "Not found"}:::${key}`);
|
||||
return translations[currentLanguage]?.[key] || translations['Default']?.[key] || key;
|
||||
}
|
||||
export { getString, init };
|
||||
|
|
@ -1,241 +0,0 @@
|
|||
{
|
||||
"No media": "No media",
|
||||
"Powered by Google": "Powered by Google",
|
||||
"Uses gemini-pro.\nNot affiliated, endorsed, or sponsored by Google.\n\nPrivacy: Chat messages aren't linked to your account,\n but will be read by human reviewers to improve the model.": "Uses gemini-pro.\nNot affiliated, endorsed, or sponsored by Google.\n\nPrivacy: Chat messages aren't linked to your account,\n but will be read by human reviewers to improve the model.",
|
||||
"Precise": "Precise",
|
||||
"Balanced": "Balanced",
|
||||
"Creative": "Creative",
|
||||
"Gemini's temperature value.\n Precise = 0\n Balanced = 0.5\n Creative = 1": "Gemini's temperature value.\n Precise = 0\n Balanced = 0.5\n Creative = 1",
|
||||
"Enhancements": "Enhancements",
|
||||
"Tells Gemini:\n- It's a Linux sidebar assistant\n- Be brief and use bullet points": "Tells Gemini:\n- It's a Linux sidebar assistant\n- Be brief and use bullet points",
|
||||
"Safety": "Safety",
|
||||
"When turned off, tells the API (not the model) \nto not block harmful/explicit content": "When turned off, tells the API (not the model) \nto not block harmful/explicit content",
|
||||
"History": "History",
|
||||
"Saves chat history\nMessages in previous chats won't show automatically, but they are there": "Saves chat history\nMessages in previous chats won't show automatically, but they are there",
|
||||
"Key stored in:": "Key stored in:",
|
||||
"To update this key, type": "To update this key, type",
|
||||
"Updated API Key at": "Updated API Key at",
|
||||
"Currently using": "Currently using",
|
||||
"Select ChatGPT-compatible API provider": "Select ChatGPT-compatible API provider",
|
||||
"Official OpenAI API.\nPricing: Free for the first $5 or 3 months, whichever is less.": "Official OpenAI API.\nPricing: Free for the first $5 or 3 months, whichever is less.",
|
||||
"Official Ollama API.\nPricing: Free.": "Official Ollama API.\nPricing: Free.",
|
||||
"A unified interface for LLMs": "A unified interface for LLMs",
|
||||
"An API from Tornado Softwares\nPricing: Free: 100/day\nRequires you to join their Discord for a key": "An API from Tornado Softwares\nPricing: Free: 100/day\nRequires you to join their Discord for a key",
|
||||
"An API from @zukixa on GitHub.\nNote: Keys are IP-locked so it's buggy sometimes\nPricing: Free: 10/min, 800/day.\nRequires you to join their Discord for a key": "An API from @zukixa on GitHub.\nNote: Keys are IP-locked so it's buggy sometimes\nPricing: Free: 10/min, 800/day.\nRequires you to join their Discord for a key",
|
||||
"Provider shown above": "Provider shown above",
|
||||
"Uses gpt-3.5-turbo.\nNot affiliated, endorsed, or sponsored by OpenAI.\n\nPrivacy: OpenAI claims they do not use your data\nwhen you use their API. Idk about others.": "Uses gpt-3.5-turbo.\nNot affiliated, endorsed, or sponsored by OpenAI.\n\nPrivacy: OpenAI claims they do not use your data\nwhen you use their API. Idk about others.",
|
||||
"The model's temperature value.\n Precise = 0\n Balanced = 0.5\n Creative = 1": "The model's temperature value.\n Precise = 0\n Balanced = 0.5\n Creative = 1",
|
||||
"An API key is required\nYou can grab one <u>here</u>, then enter it below": "An API key is required\nYou can grab one <u>here</u>, then enter it below",
|
||||
"Tells the model:\n- It's a Linux sidebar assistant\n- Be brief and use bullet points": "Tells the model:\n- It's a Linux sidebar assistant\n- Be brief and use bullet points",
|
||||
"Powered by waifu.im + other APIs": "Powered by waifu.im + other APIs",
|
||||
"Type tags for a random pic.\nNSFW content will not be returned unless\nyou explicitly request such a tag.\n\nDisclaimer: Not affiliated with the providers\nnor responsible for any of their content.": "Type tags for a random pic.\nNSFW content will not be returned unless\nyou explicitly request such a tag.\n\nDisclaimer: Not affiliated with the providers\nnor responsible for any of their content.",
|
||||
"Tags →": "Tags →",
|
||||
"Invalid command.": "Invalid command.",
|
||||
"Anime booru": "Anime booru",
|
||||
"Powered by yande.re and konachan": "Powered by yande.re and konachan",
|
||||
"An image booru. May contain NSFW content.\nWatch your back.\n\nDisclaimer: Not affiliated with the provider\nnor responsible for any of its content.": "An image booru. May contain NSFW content.\nWatch your back.\n\nDisclaimer: Not affiliated with the provider\nnor responsible for any of its content.",
|
||||
"Lewds": "Lewds",
|
||||
"Shows naughty stuff when enabled.\nYa like those? Add this to user_options.js:\n\t'sidebar': {\n\t'image': {\n\t\t'allowNsfw': true,\n\t}\n}": "Shows naughty stuff when enabled.\nYa like those? Add this to user_options.js:\n\t'sidebar': {\n\t'image': {\n\t\t'allowNsfw': true,\n\t}\n}",
|
||||
"Save in folder by tags": "Save in folder by tags",
|
||||
"Saves images in folders by their tags": "Saves images in folders by their tags",
|
||||
"Message Gemini...": "Message Gemini...",
|
||||
"Enter Google AI API Key...": "Enter Google AI API Key...",
|
||||
"Message the model...": "Message the model...",
|
||||
"Enter API Key...": "Enter API Key...",
|
||||
"Enter tags": "Enter tags",
|
||||
"Quick scripts": "Quick scripts",
|
||||
"Change screen resolution": "Change screen resolution",
|
||||
"Update packages": "Update packages",
|
||||
"Trim system generations to 5": "Trim system generations to 5",
|
||||
"Trim home manager generations to 5": "Trim home manager generations to 5",
|
||||
"Remove orphan packages": "Remove orphan packages",
|
||||
"Uninstall unused flatpak packages": "Uninstall unused flatpak packages",
|
||||
"<span strikethrough=\"true\">Inaccurate</span> Color picker": "<span strikethrough=\"true\">Inaccurate</span> Color picker",
|
||||
"Result": "Result",
|
||||
"Type to search": "Type to search",
|
||||
"illogical-impulse": "illogical-impulse",
|
||||
"RAM Usage": "RAM Usage",
|
||||
"Swap Usage": "Swap Usage",
|
||||
"CPU Usage": "CPU Usage",
|
||||
"Uptime:": "Uptime:",
|
||||
"Screen snip": "Screen snip",
|
||||
"Color picker": "Color picker",
|
||||
"Toggle on-screen keyboard": "Toggle on-screen keyboard",
|
||||
"Night Light": "Night Light",
|
||||
"Color inversion": "Color inversion",
|
||||
"Keep system awake": "Keep system awake",
|
||||
"Cloudflare WARP": "Cloudflare WARP",
|
||||
"Session": "Session",
|
||||
"Bluetooth | Right-click to configure": "Bluetooth | Right-click to configure",
|
||||
"Wifi | Right-click to configure": "Wifi | Right-click to configure",
|
||||
"Right-click to configure": "Right-click to configure",
|
||||
"Unknown": "Unknown",
|
||||
"Reload Environment config": "Reload Environment config",
|
||||
"Open Settings": "Open Settings",
|
||||
"Notifications": "Notifications",
|
||||
"Audio controls": "Audio controls",
|
||||
"Bluetooth": "Bluetooth",
|
||||
"Wifi networks": "Wifi networks",
|
||||
"Live config": "Live config",
|
||||
"Silence": "Silence",
|
||||
"Clear": "Clear",
|
||||
"No notifications": "No notifications",
|
||||
"notifications": "notifications",
|
||||
"Close": "Close",
|
||||
"Now": "Now",
|
||||
"Yesterday": "Yesterday",
|
||||
"No audio source": "No audio source",
|
||||
"Remove device": "Remove device",
|
||||
"Connected": "Connected",
|
||||
"Paired": "Paired",
|
||||
"More": "More",
|
||||
"Selected": "Selected",
|
||||
"Current network": "Current network",
|
||||
"Authentication": "Authentication",
|
||||
"Effects": "Effects",
|
||||
"Transparency": "Transparency",
|
||||
"[AGS]\nMake shell elements transparent\nBlur is also recommended if you enable this": "[AGS]\nMake shell elements transparent\nBlur is also recommended if you enable this",
|
||||
"Blur": "Blur",
|
||||
"[Hyprland]\nEnable blur on transparent elements\nDoesn't affect performance/power consumption unless you have transparent windows.": "[Hyprland]\nEnable blur on transparent elements\nDoesn't affect performance/power consumption unless you have transparent windows.",
|
||||
"X-ray": "X-ray",
|
||||
"[Hyprland]\nMake everything behind a window/layer except the wallpaper not rendered on its blurred surface\nRecommended to improve performance (if you don't abuse transparency/blur) ": "[Hyprland]\nMake everything behind a window/layer except the wallpaper not rendered on its blurred surface\nRecommended to improve performance (if you don't abuse transparency/blur) ",
|
||||
"Size": "Size",
|
||||
"[Hyprland]\nAdjust the blur radius. Generally doesn't affect performance\nHigher = more color spread": "[Hyprland]\nAdjust the blur radius. Generally doesn't affect performance\nHigher = more color spread",
|
||||
"Passes": "Passes",
|
||||
"[Hyprland] Adjust the number of runs of the blur algorithm\nMore passes = more spread and power consumption\n4 is recommended\n2- would look weird and 6+ would look lame.": "[Hyprland] Adjust the number of runs of the blur algorithm\nMore passes = more spread and power consumption\n4 is recommended\n2- would look weird and 6+ would look lame.",
|
||||
"Animations": "Animations",
|
||||
"[Hyprland] [GTK]\nEnable animations": "[Hyprland] [GTK]\nEnable animations",
|
||||
"Choreography delay": "Choreography delay",
|
||||
"In milliseconds, the delay between animations of a series": "In milliseconds, the delay between animations of a series",
|
||||
"Developer": "Developer",
|
||||
"Show FPS": "Show FPS",
|
||||
"[Hyprland]\nShow FPS overlay on top-left corner": "[Hyprland]\nShow FPS overlay on top-left corner",
|
||||
"Log to stdout": "Log to stdout",
|
||||
"[Hyprland]\nPrint LOG, ERR, WARN, etc. messages to the console": "[Hyprland]\nPrint LOG, ERR, WARN, etc. messages to the console",
|
||||
"Damage tracking": "Damage tracking",
|
||||
"[Hyprland]\nEnable damage tracking\nGenerally, leave it on.\nTurn off only when a shader doesn't work": "[Hyprland]\nEnable damage tracking\nGenerally, leave it on.\nTurn off only when a shader doesn't work",
|
||||
"Damage blink": "Damage blink",
|
||||
"[Hyprland] [Epilepsy warning!]\nShow screen damage flashes": "[Hyprland] [Epilepsy warning!]\nShow screen damage flashes",
|
||||
"Not all changes are saved": "Not all changes are saved",
|
||||
"Mo": "Mo",
|
||||
"Tu": "Tu",
|
||||
"We": "We",
|
||||
"Th": "Th",
|
||||
"Fr": "Fr",
|
||||
"Sa": "Sa",
|
||||
"Su": "Su",
|
||||
"Calendar": "Calendar",
|
||||
"To Do": "To Do",
|
||||
"Unfinished": "Unfinished",
|
||||
"Done": "Done",
|
||||
"Finished tasks will go here": "Finished tasks will go here",
|
||||
"Nothing here!": "Nothing here!",
|
||||
"+ New task": "+ New task",
|
||||
"Add a task...": "Add a task...",
|
||||
"Color scheme": "Color scheme",
|
||||
"Options": "Options",
|
||||
"Dark Mode": "Dark Mode",
|
||||
"Ya should go to sleep!": "Ya should go to sleep!",
|
||||
"Use Gradience": "Use Gradience",
|
||||
"Theme GTK apps using accent color\n(drawback: dark/light mode switching requires restart)": "Theme GTK apps using accent color\n(drawback: dark/light mode switching requires restart)",
|
||||
"Scheme styles": "Scheme styles",
|
||||
"Vibrant": "Vibrant",
|
||||
"Vibrant+": "Vibrant+",
|
||||
"Expressive": "Expressive",
|
||||
"Monochrome": "Monochrome",
|
||||
"Rainbow": "Rainbow",
|
||||
"Fidelity": "Fidelity",
|
||||
"Fruit Salad": "Fruit Salad",
|
||||
"Tonal Spot": "Tonal Spot",
|
||||
"Content": "Content",
|
||||
"Use arrow keys to navigate.\nEnter to select, Esc to cancel.": "Use arrow keys to navigate.\nEnter to select, Esc to cancel.",
|
||||
"Lock": "Lock",
|
||||
"Logout": "Logout",
|
||||
"Sleep": "Sleep",
|
||||
"Hibernate": "Hibernate",
|
||||
"Shutdown": "Shutdown",
|
||||
"Reboot": "Reboot",
|
||||
"Cancel": "Cancel",
|
||||
"Cheat sheet": "Cheat sheet",
|
||||
"Keybinds": "Keybinds",
|
||||
"Periodic table": "Periodic table",
|
||||
"Essentials for beginners": "Essentials for beginners",
|
||||
"Make shell elements transparent": "Make shell elements transparent",
|
||||
"Actions": "Actions",
|
||||
"Window management": "Window management",
|
||||
"Window arrangement": "Window arrangement",
|
||||
"Workspace management": "Workspace management",
|
||||
"Workspace navigation": "Workspace navigation",
|
||||
"Widgets": "Widgets",
|
||||
"Media": "Media",
|
||||
"Apps": "Apps",
|
||||
"Neutral": "Neutral",
|
||||
"Launch foot (terminal)": "Launch foot (terminal)",
|
||||
"Open app launcher": "Open app launcher",
|
||||
"Change wallpaper": "Change wallpaper",
|
||||
"Clipboard history >> clipboard": "Clipboard history >> clipboard",
|
||||
"Pick emoji >> clipboard": "Pick emoji >> clipboard",
|
||||
"Screen snip >> edit": "Screen snip >> edit",
|
||||
"Screen snip to text >> clipboard": "Screen snip to text >> clipboard",
|
||||
"Pick color (Hex) >> clipboard": "Pick color (Hex) >> clipboard",
|
||||
"Screenshot >> clipboard": "Screenshot >> clipboard",
|
||||
"Screenshot >> clipboard & file": "Screenshot >> clipboard & file",
|
||||
"Record region (no sound)": "Record region (no sound)",
|
||||
"Record screen (with sound)": "Record screen (with sound)",
|
||||
"Suspend system": "Suspend system",
|
||||
"Move focus in direction": "Move focus in direction",
|
||||
"Move window": "Move window",
|
||||
"Resize window": "Resize window",
|
||||
"Close window": "Close window",
|
||||
"Pick and kill a window": "Pick and kill a window",
|
||||
"Window: move in direction": "Window: move in direction",
|
||||
"Window: split ratio +/- 0.1": "Window: split ratio +/- 0.1",
|
||||
"Float/unfloat window": "Float/unfloat window",
|
||||
"Toggle fake fullscreen": "Toggle fake fullscreen",
|
||||
"Toggle fullscreen": "Toggle fullscreen",
|
||||
"Toggle maximization": "Toggle maximization",
|
||||
"Focus workspace # (1, 2, 3, 4, ...)": "Focus workspace # (1, 2, 3, 4, ...)",
|
||||
"Workspace: focus left/right": "Workspace: focus left/right",
|
||||
"Workspace: toggle special": "Workspace: toggle special",
|
||||
"Window: move to workspace # (1, 2, 3, 4, ...)": "Window: move to workspace # (1, 2, 3, 4, ...)",
|
||||
"Window: move to workspace left/right": "Window: move to workspace left/right",
|
||||
"Window: move to workspace special": "Window: move to workspace special",
|
||||
"Window: pin (show on all workspaces)": "Window: pin (show on all workspaces)",
|
||||
"Restart widgets": "Restart widgets",
|
||||
"Cycle bar mode (normal, focus)": "Cycle bar mode (normal, focus)",
|
||||
"Toggle overview/launcher": "Toggle overview/launcher",
|
||||
"Show cheatsheet": "Show cheatsheet",
|
||||
"Toggle left sidebar": "Toggle left sidebar",
|
||||
"Toggle right sidebar": "Toggle right sidebar",
|
||||
"Toggle music controls": "Toggle music controls",
|
||||
"View color scheme and options": "View color scheme and options",
|
||||
"Toggle power menu": "Toggle power menu",
|
||||
"Toggle crosshair": "Toggle crosshair",
|
||||
"Next track": "Next track",
|
||||
"Previous track": "Previous track",
|
||||
"Play/pause media": "Play/pause media",
|
||||
"Launch Zed (editor)": "Launch Zed (editor)",
|
||||
"Launch VSCode (editor)": "Launch VSCode (editor)",
|
||||
"Launch Nautilus (file manager)": "Launch Nautilus (file manager)",
|
||||
"Launch Firefox (browser)": "Launch Firefox (browser)",
|
||||
"Launch GNOME Text Editor": "Launch GNOME Text Editor",
|
||||
"Launch WPS Office": "Launch WPS Office",
|
||||
"Launch GNOME Settings": "Launch GNOME Settings",
|
||||
"Launch pavucontrol (volume mixer)": "Launch pavucontrol (volume mixer)",
|
||||
"Launch EasyEffects (equalizer & other audio effects)": "Launch EasyEffects (equalizer & other audio effects)",
|
||||
"Launch GNOME System monitor": "Launch GNOME System monitor",
|
||||
"Toggle fallback launcher: anyrun": "Toggle fallback launcher: anyrun",
|
||||
"Toggle fallback launcher: fuzzel": "Toggle fallback launcher: fuzzel",
|
||||
"Initialization complete!": "Initialization complete!",
|
||||
"Not found": "Not found:",
|
||||
"Calling API": "Calling API",
|
||||
"Downloading image": "Downloading image",
|
||||
"Finished!": "Finished!",
|
||||
"Error": "Error",
|
||||
"Not found!": "Not found!",
|
||||
"Go to file url": "Go to file url",
|
||||
"Save image": "Save image",
|
||||
"Hoard": "Hoard",
|
||||
"Open externally": "Open externally",
|
||||
"You are an assistant on a sidebar of a Wayland Linux desktop. Please always use a casual tone when answering your questions, unless requested otherwise or making writing suggestions. These are the steps you should take to respond to the user's queries:\n1. If it's a writing- or grammar-related question or a sentence in quotation marks, Please point out errors and correct when necessary using underlines, and make the writing more natural where appropriate without making too major changes. If you're given a sentence in quotes but is grammatically correct, explain briefly concepts that are uncommon.\n2. If it's a question about system tasks, give a bash command in a code block with brief explanation.\n3. Otherwise, when asked to summarize information or explaining concepts, you are should use bullet points and headings. For mathematics expressions, you *have to* use LaTeX within a code block with the language set as \"latex\". \nNote: Use casual language, be short, while ensuring the factual correctness of your response. If you are unsure or don’t have enough information to provide a confident answer, simply say “I don’t know” or “I’m not sure.”. \nThanks!": "You are an assistant on a sidebar of a Wayland Linux desktop. Please always use a casual tone when answering your questions, unless requested otherwise or making writing suggestions. These are the steps you should take to respond to the user's queries:\n1. If it's a writing- or grammar-related question or a sentence in quotation marks, Please point out errors and correct when necessary using underlines, and make the writing more natural where appropriate without making too major changes. If you're given a sentence in quotes but is grammatically correct, explain briefly concepts that are uncommon.\n2. If it's a question about system tasks, give a bash command in a code block with brief explanation.\n3. Otherwise, when asked to summarize information or explaining concepts, you are should use bullet points and headings. For mathematics expressions, you *have to* use LaTeX within a code block with the language set as \"latex\". \nNote: Use casual language, be short, while ensuring the factual correctness of your response. If you are unsure or don’t have enough information to provide a confident answer, simply say “I don’t know” or “I’m not sure.”. \nThanks!"
|
||||
}
|
||||
|
|
@ -1,241 +0,0 @@
|
|||
{
|
||||
"No media": "无媒体活动",
|
||||
"Powered by Google": "由 Google 提供技术支持",
|
||||
"Uses gemini-pro.\nNot affiliated, endorsed, or sponsored by Google.\n\nPrivacy: Chat messages aren't linked to your account,\n but will be read by human reviewers to improve the model.": "使用 Gemini Pro\n不隶属于、不受 Google 赞助或支持。\n\n隐私:聊天信息不会与你的账户关联,\n但会被人类审阅者阅读,用于改进模型。",
|
||||
"Precise": "精确",
|
||||
"Balanced": "平衡",
|
||||
"Creative": "创意",
|
||||
"Gemini's temperature value.\n Precise = 0\n Balanced = 0.5\n Creative = 1": "Gemini 的 temperature 值\n 精确 = 0\n 平衡 = 0.5\n 创意 = 1",
|
||||
"Enhancements": "增强功能",
|
||||
"Tells Gemini:\n- It's a Linux sidebar assistant\n- Be brief and use bullet points": "告诉 Gemini:\n- 它是一个 Linux 侧边栏助手\n- 保持简洁并使用项目符号",
|
||||
"Safety": "安全",
|
||||
"When turned off, tells the API (not the model) \nto not block harmful/explicit content": "当关闭时,告诉 API(而不是模型)\n不要屏蔽有害/显露的内容",
|
||||
"History": "历史",
|
||||
"Saves chat history\nMessages in previous chats won't show automatically, but they are there": "保存聊天历史\n以前聊天中的消息不会自动显示,但它们仍然存在",
|
||||
"Key stored in:": "密钥值储存在:",
|
||||
"To update this key, type": "要更新此密钥,请输入",
|
||||
"Updated API Key at": "更新了 API 密钥于",
|
||||
"Currently using": "当前使用",
|
||||
"Select ChatGPT-compatible API provider": "选择与 ChatGPT 兼容的 API 提供商",
|
||||
"Official OpenAI API.\nPricing: Free for the first $5 or 3 months, whichever is less.": "官方 OpenAI API。\n定价:前 $5 或前 3 个月免费,取较小者。",
|
||||
"Official Ollama API.\nPricing: Free.": "官方 Ollama API。\n定价:免费。",
|
||||
"A unified interface for LLMs": "LLM 的统一接口",
|
||||
"An API from Tornado Softwares\nPricing: Free: 100/day\nRequires you to join their Discord for a key": "来自 Tornado Softwares 的 API\n定价:免费:每天 100 次请求\n需要加入他们的 Discord 以获取密钥",
|
||||
"An API from @zukixa on GitHub.\nNote: Keys are IP-locked so it's buggy sometimes\nPricing: Free: 10/min, 800/day.\nRequires you to join their Discord for a key": "来自 GitHub 上的 @zukixa 的 API。\n注意:密钥与 IP 绑定,所以有时会出错。\n定价:免费:每分钟 10 次,每天 800 次。\n需要加入他们的 Discord 才能获得密钥。",
|
||||
"Provider shown above": "上述显示的提供商",
|
||||
"Uses gpt-3.5-turbo.\nNot affiliated, endorsed, or sponsored by OpenAI.\n\nPrivacy: OpenAI claims they do not use your data\nwhen you use their API. Idk about others.": "使用 gpt-3.5-turbo。\n与 OpenAI 无关联,未获得其认可或赞助。\n\n隐私:OpenAI 声明,当您使用他们的 API 时,他们不会使用您的数据。\n我不清楚其他人的情况。",
|
||||
"The model's temperature value.\n Precise = 0\n Balanced = 0.5\n Creative = 1": "模型的 temperature 值。\n 精确 = 0\n 平衡 = 0.5\n 创意 = 1",
|
||||
"An API key is required\nYou can grab one <u>here</u>, then enter it below": "需要 API 密钥\n您可以在<u>这里</u>获取一个,然后在下面输入",
|
||||
"Tells the model:\n- It's a Linux sidebar assistant\n- Be brief and use bullet points": "告诉模型:\n- 它是一个 Linux 侧边栏助手\n- 保持简洁并使用项目符号",
|
||||
"Powered by waifu.im + other APIs": "由 waifu.im + 其他 API 提供支持",
|
||||
"Type tags for a random pic.\nNSFW content will not be returned unless\nyou explicitly request such a tag.\n\nDisclaimer: Not affiliated with the providers\nnor responsible for any of their content.": "输入标签以获取随机图片。\n除非您明确请求,否则不会返回 NSFW 内容。\n\n免责声明:与提供商无关联\n我也不对他们的任何内容负责。",
|
||||
"Tags →": "标签 →",
|
||||
"Invalid command.": "无效命令。",
|
||||
"Anime booru": "动漫图库",
|
||||
"Powered by yande.re and konachan": "由 yande.re 和 konachan 提供支持",
|
||||
"An image booru. May contain NSFW content.\nWatch your back.\n\nDisclaimer: Not affiliated with the provider\nnor responsible for any of its content.": "一个图片图库。可能包含 NSFW 内容。\n小心。\n\n免责声明:与提供商无关联\n也不对它的任何内容负责。",
|
||||
"Lewds": "不雅内容",
|
||||
"Shows naughty stuff when enabled.\nYa like those? Add this to user_options.js:\n\t'sidebar': {\n\t'image': {\n\t\t'allowNsfw': true,\n\t}\n}": "启用时显示不雅内容。\n你喜欢这些?添加到 user_options.js 中:\n'sidebar': {\n\t'image': {\n\t\t'allowNsfw': true,\n\t}\n}",
|
||||
"Save in folder by tags": "按标签保存到文件夹",
|
||||
"Saves images in folders by their tags": "按标签将图片保存到文件夹中",
|
||||
"Message Gemini...": "向 Gemini 发送消息...",
|
||||
"Enter Google AI API Key...": "输入 Google AI API 密钥...",
|
||||
"Message the model...": "向模型发送消息...",
|
||||
"Enter API Key...": "输入 API 密钥...",
|
||||
"Enter tags": "输入标签",
|
||||
"Quick scripts": "快速脚本",
|
||||
"Change screen resolution": "更改屏幕分辨率",
|
||||
"Update packages": "更新软件包",
|
||||
"Trim system generations to 5": "将系统代数修剪为 5",
|
||||
"Trim home manager generations to 5": "将 home manager 代数修剪为 5",
|
||||
"Remove orphan packages": "移除孤立软件包",
|
||||
"Uninstall unused flatpak packages": "卸载未使用的 Flatpak 软件包",
|
||||
"<span strikethrough=\"true\">Inaccurate</span> Color picker": "<span strikethrough=\"true\">不准确</span> 颜色选择器",
|
||||
"Result": "结果",
|
||||
"Type to search": "输入以搜索",
|
||||
"illogical-impulse": "illogical-impulse",
|
||||
"RAM Usage": "RAM 使用情况",
|
||||
"Swap Usage": "Swap 使用情况",
|
||||
"CPU Usage": "CPU 使用情况",
|
||||
"Uptime:": "运行时间:",
|
||||
"Screen snip": "屏幕截图",
|
||||
"Color picker": "颜色选择器",
|
||||
"Toggle on-screen keyboard": "切换屏幕键盘",
|
||||
"Night Light": "夜灯",
|
||||
"Color inversion": "颜色反转",
|
||||
"Keep system awake": "保持系统唤醒",
|
||||
"Cloudflare WARP": "Cloudflare WARP",
|
||||
"Session": "会话",
|
||||
"Bluetooth | Right-click to configure": "蓝牙 | 右键单击以配置",
|
||||
"Wifi | Right-click to configure": "Wi-Fi | 右键单击以配置",
|
||||
"Right-click to configure": "右键单击以配置",
|
||||
"Unknown": "未知",
|
||||
"Reload Environment config": "重新加载环境配置",
|
||||
"Open Settings": "打开设置",
|
||||
"Notifications": "通知",
|
||||
"Audio controls": "音频控制",
|
||||
"Bluetooth": "蓝牙",
|
||||
"Wifi networks": "Wi-Fi 网络",
|
||||
"Live config": "实时配置",
|
||||
"Silence": "静音",
|
||||
"Clear": "清除",
|
||||
"No notifications": "无通知",
|
||||
"notifications": "条通知",
|
||||
"Close": "关闭",
|
||||
"Now": "现在",
|
||||
"Yesterday": "昨天",
|
||||
"No audio source": "没有音频源",
|
||||
"Remove device": "移除设备",
|
||||
"Connected": "已连接",
|
||||
"Paired": "已配对",
|
||||
"More": "更多",
|
||||
"Selected": "已选中",
|
||||
"Current network": "当前网络",
|
||||
"Authentication": "身份验证",
|
||||
"Effects": "效果",
|
||||
"Transparency": "透明度",
|
||||
"[AGS]\nMake shell elements transparent\nBlur is also recommended if you enable this": "[AGS]\n使外壳元素透明\n如果启用此功能,也建议使用模糊效果",
|
||||
"Blur": "模糊",
|
||||
"[Hyprland]\nEnable blur on transparent elements\nDoesn't affect performance/power consumption unless you have transparent windows.": "[Hyprland]\n在透明元素上启用模糊效果\n除非您有透明窗口,否则不会影响性能/功耗。",
|
||||
"X-ray": "X-ray",
|
||||
"[Hyprland]\nMake everything behind a window/layer except the wallpaper not rendered on its blurred surface\nRecommended to improve performance (if you don't abuse transparency/blur) ": "[Hyprland]\n使窗口/图层后面的所有内容(除了壁纸)在其模糊表面上不渲染\n建议提高性能(如果您不滥用透明度/模糊)",
|
||||
"Size": "大小",
|
||||
"[Hyprland]\nAdjust the blur radius. Generally doesn't affect performance\nHigher = more color spread": "[Hyprland]\n调整模糊半径。通常不会影响性能\n数值越高 = 颜色扩散越大",
|
||||
"Passes": "次数",
|
||||
"[Hyprland] Adjust the number of runs of the blur algorithm\nMore passes = more spread and power consumption\n4 is recommended\n2- would look weird and 6+ would look lame.": "[Hyprland]\n调整模糊算法的运行次数\n次数越多 = 扩散越大,功耗越高\n建议使用 4 次\n2 次看起来很奇怪,6 次以上看起来很糟糕。",
|
||||
"Animations": "动画",
|
||||
"[Hyprland] [GTK]\nEnable animations": "[Hyprland] [GTK]\n启用动画",
|
||||
"Choreography delay": "间隔",
|
||||
"In milliseconds, the delay between animations of a series": "以毫秒为单位,一系列动画之间的延迟",
|
||||
"Developer": "开发者选项",
|
||||
"Show FPS": "显示 FPS",
|
||||
"[Hyprland]\nShow FPS overlay on top-left corner": "[Hyprland]\n在左上角显示 FPS 叠加层",
|
||||
"Log to stdout": "输出日志",
|
||||
"[Hyprland]\nPrint LOG, ERR, WARN, etc. messages to the console": "[Hyprland]\n将 LOG、ERR、WARN 等消息打印到控制台",
|
||||
"Damage tracking": "Damage tracking",
|
||||
"[Hyprland]\nEnable damage tracking\nGenerally, leave it on.\nTurn off only when a shader doesn't work": "[Hyprland]\n启用 Damage tracking \n通常情况下,保持启用状态\n仅当着色器无法正常工作时才禁用",
|
||||
"Damage blink": "显示视图更新",
|
||||
"[Hyprland] [Epilepsy warning!]\nShow screen damage flashes": "[Hyprland] [癫痫警告!]\n屏幕视图更新时闪烁",
|
||||
"Not all changes are saved": "并非所有更改都已保存",
|
||||
"Mo": "一",
|
||||
"Tu": "二",
|
||||
"We": "三",
|
||||
"Th": "四",
|
||||
"Fr": "五",
|
||||
"Sa": "六",
|
||||
"Su": "日",
|
||||
"Calendar": "日历",
|
||||
"To Do": "待办",
|
||||
"Unfinished": "未完成",
|
||||
"Done": "已完成",
|
||||
"Finished tasks will go here": "已完成的任务将显示在此处",
|
||||
"Nothing here!": "这里什么也没有!",
|
||||
"+ New task": "+ 新任务",
|
||||
"Add a task...": "添加任务...",
|
||||
"Color scheme": "配色方案",
|
||||
"Options": "选项",
|
||||
"Dark Mode": "深色模式",
|
||||
"Ya should go to sleep!": "你应该去睡觉!",
|
||||
"Use Gradience": "GTK 主题",
|
||||
"Theme GTK apps using accent color\n(drawback: dark/light mode switching requires restart)": "使用强调色对 GTK 应用程序进行主题化\n(缺点:深色/浅色模式切换需要重启)",
|
||||
"Scheme styles": "样式方案",
|
||||
"Vibrant": "鲜艳",
|
||||
"Vibrant+": "鲜艳+",
|
||||
"Expressive": "表现力",
|
||||
"Monochrome": "黑白",
|
||||
"Rainbow": "彩虹",
|
||||
"Fidelity": "保真度",
|
||||
"Fruit Salad": "水果沙拉",
|
||||
"Tonal Spot": "色调点",
|
||||
"Content": "内容",
|
||||
"Use arrow keys to navigate.\nEnter to select, Esc to cancel.": "使用箭头键导航。\n回车键选择,Esc 键取消。",
|
||||
"Lock": "锁屏",
|
||||
"Logout": "注销",
|
||||
"Sleep": "睡眠",
|
||||
"Hibernate": "休眠",
|
||||
"Shutdown": "关机",
|
||||
"Reboot": "重启",
|
||||
"Cancel": "取消",
|
||||
"Cheat sheet": "备忘单",
|
||||
"Keybinds": "按键绑定",
|
||||
"Periodic table": "元素周期表",
|
||||
"Essentials for beginners": "初学者必备",
|
||||
"Make shell elements transparent": "使外壳元素透明",
|
||||
"Actions": "操作",
|
||||
"Window management": "窗口管理",
|
||||
"Window arrangement": "窗口排列",
|
||||
"Workspace management": "工作区管理",
|
||||
"Workspace navigation": "工作区导航",
|
||||
"Widgets": "小部件",
|
||||
"Media": "媒体",
|
||||
"Apps": "应用程序",
|
||||
"Neutral": "中性",
|
||||
"Launch foot (terminal)": "启动终端(foot)",
|
||||
"Open app launcher": "打开应用程序启动器",
|
||||
"Change wallpaper": "更改壁纸",
|
||||
"Clipboard history >> clipboard": "剪贴板历史 >> 剪贴板",
|
||||
"Pick emoji >> clipboard": "选择表情符号 >> 剪贴板",
|
||||
"Screen snip >> edit": "屏幕截图 >> 编辑",
|
||||
"Screen snip to text >> clipboard": "屏幕截图转文字 >> 剪贴板",
|
||||
"Pick color (Hex) >> clipboard": "选择颜色(十六进制)>> 剪贴板",
|
||||
"Screenshot >> clipboard": "屏幕截图 >> 剪贴板",
|
||||
"Screenshot >> clipboard & file": "屏幕截图 >> 剪贴板和文件",
|
||||
"Record region (no sound)": "录制区域(无声音)",
|
||||
"Record screen (with sound)": "录制屏幕(带声音)",
|
||||
"Suspend system": "挂起系统",
|
||||
"Move focus in direction": "在方向上移动焦点",
|
||||
"Move window": "移动窗口",
|
||||
"Resize window": "调整窗口大小",
|
||||
"Close window": "关闭窗口",
|
||||
"Pick and kill a window": "选择并关闭一个窗口",
|
||||
"Window: move in direction": "窗口:在方向上移动",
|
||||
"Window: split ratio +/- 0.1": "窗口:分割比例 +/- 0.1",
|
||||
"Float/unfloat window": "浮动/取消浮动窗口",
|
||||
"Toggle fake fullscreen": "切换伪全屏",
|
||||
"Toggle fullscreen": "切换全屏",
|
||||
"Toggle maximization": "切换最大化",
|
||||
"Focus workspace # (1, 2, 3, 4, ...)": "聚焦工作区 #(1, 2, 3, 4, ...)",
|
||||
"Workspace: focus left/right": "工作区:聚焦左右",
|
||||
"Workspace: toggle special": "工作区:切换特殊工作区",
|
||||
"Window: move to workspace # (1, 2, 3, 4, ...)": "窗口:移动到工作区 #(1, 2, 3, 4, ...)",
|
||||
"Window: move to workspace left/right": "窗口:移动到左右工作区",
|
||||
"Window: move to workspace special": "窗口:移动到特殊工作区",
|
||||
"Window: pin (show on all workspaces)": "窗口:固定(在所有工作区显示)",
|
||||
"Restart widgets": "重启小部件",
|
||||
"Cycle bar mode (normal, focus)": "循环栏模式(正常,聚焦)",
|
||||
"Toggle overview/launcher": "切换概览/启动器",
|
||||
"Show cheatsheet": "显示快捷键表",
|
||||
"Toggle left sidebar": "切换左侧边栏",
|
||||
"Toggle right sidebar": "切换右侧边栏",
|
||||
"Toggle music controls": "切换音乐控制",
|
||||
"View color scheme and options": "查看配色方案和选项",
|
||||
"Toggle power menu": "切换电源菜单",
|
||||
"Toggle crosshair": "切换准星",
|
||||
"Next track": "下一曲目",
|
||||
"Previous track": "上一曲目",
|
||||
"Play/pause media": "播放/暂停媒体",
|
||||
"Launch Zed (editor)": "启动 Zed(编辑器)",
|
||||
"Launch VSCode (editor)": "启动 VSCode(编辑器)",
|
||||
"Launch Nautilus (file manager)": "启动 Nautilus(文件管理器)",
|
||||
"Launch Firefox (browser)": "启动 Firefox(浏览器)",
|
||||
"Launch GNOME Text Editor": "启动 GNOME 文本编辑器",
|
||||
"Launch WPS Office": "启动 WPS 办公软件",
|
||||
"Launch GNOME Settings": "启动 GNOME 设置",
|
||||
"Launch pavucontrol (volume mixer)": "启动 pavucontrol(音量混合器)",
|
||||
"Launch EasyEffects (equalizer & other audio effects)": "启动 EasyEffects(均衡器和其他音频效果)",
|
||||
"Launch GNOME System monitor": "启动 GNOME 系统监视器",
|
||||
"Toggle fallback launcher: anyrun": "切换备用启动器:anyrun",
|
||||
"Toggle fallback launcher: fuzzel": "切换备用启动器:fuzzel",
|
||||
"Initialization complete!": "初始化完成!",
|
||||
"Not found": "未找到",
|
||||
"Calling API": "调用 API",
|
||||
"Downloading image": "正在下载图片",
|
||||
"Finished!": "完成!",
|
||||
"Error": "错误",
|
||||
"Not found!": "未找到!",
|
||||
"Go to file url": "前往文件链接",
|
||||
"Save image": "保存图片",
|
||||
"Hoard": "保存",
|
||||
"Open externally": "在外部打开",
|
||||
"You are an assistant on a sidebar of a Wayland Linux desktop. Please always use a casual tone when answering your questions, unless requested otherwise or making writing suggestions. These are the steps you should take to respond to the user's queries:\n1. If it's a writing- or grammar-related question or a sentence in quotation marks, Please point out errors and correct when necessary using underlines, and make the writing more natural where appropriate without making too major changes. If you're given a sentence in quotes but is grammatically correct, explain briefly concepts that are uncommon.\n2. If it's a question about system tasks, give a bash command in a code block with brief explanation.\n3. Otherwise, when asked to summarize information or explaining concepts, you are should use bullet points and headings. For mathematics expressions, you *have to* use LaTeX within a code block with the language set as \"latex\". \nNote: Use casual language, be short, while ensuring the factual correctness of your response. If you are unsure or don’t have enough information to provide a confident answer, simply say “I don’t know” or “I’m not sure.”. \nThanks!": "你是 Wayland Linux 桌面侧边栏上的助手。除非有其他要求或提供建议,否则请始终保持轻松的语气回答问题。这是你回答用户查询的步骤:\n1. 如果是写作或语法相关的问题,或者引号中的句子,请指出错误并在必要时进行更正,使用下划线,并在适当的地方使写作更自然,不要进行太大更改。如果你给出的句子在引号中但语法正确,请简要解释不常见概念。\n2. 如果是关于系统任务的问题,请给出bash命令,并在代码块中简要说明。\n3. 否则,在总结信息或解释概念时,你应该使用项目符号和标题。对于数学表达式,你必须在代码块中使用 LaTeX,并将语言设置为\"latex\"。\n注意:使用轻松的语言,简洁,同时确保回答的事实正确性。如果你不确定或没有足够的信息来提供自信的答案,只需说“我不知道”或“我不确定”。\n谢谢!"
|
||||
}
|
||||
|
|
@ -1,30 +0,0 @@
|
|||
import GLib from 'gi://GLib';
|
||||
import App from 'resource:///com/github/Aylur/ags/app.js'
|
||||
import * as Utils from 'resource:///com/github/Aylur/ags/utils.js'
|
||||
import { darkMode } from './modules/.miscutils/system.js';
|
||||
export const COMPILED_STYLE_DIR = `${GLib.get_user_cache_dir()}/ags/user/generated`
|
||||
globalThis['handleStyles'] = (resetMusic) => {
|
||||
// Reset
|
||||
Utils.exec(`mkdir -p "${GLib.get_user_state_dir()}/ags/scss"`);
|
||||
if (resetMusic) {
|
||||
Utils.exec(`bash -c 'echo "" > ${GLib.get_user_state_dir()}/ags/scss/_musicwal.scss'`); // reset music styles
|
||||
Utils.exec(`bash -c 'echo "" > ${GLib.get_user_state_dir()}/ags/scss/_musicmaterial.scss'`); // reset music styles
|
||||
}
|
||||
// Generate overrides
|
||||
let lightdark = darkMode.value ? "dark" : "light";
|
||||
Utils.writeFileSync(
|
||||
`@mixin symbolic-icon {
|
||||
-gtk-icon-theme: '${userOptions.icons.symbolicIconTheme[lightdark]}';
|
||||
}
|
||||
`,
|
||||
`${GLib.get_user_state_dir()}/ags/scss/_lib_mixins_overrides.scss`)
|
||||
// Compile and apply
|
||||
async function applyStyle() {
|
||||
Utils.exec(`mkdir -p ${COMPILED_STYLE_DIR}`);
|
||||
Utils.exec(`sass -I "${GLib.get_user_state_dir()}/ags/scss" -I "${App.configDir}/scss/fallback" "${App.configDir}/scss/main.scss" "${COMPILED_STYLE_DIR}/style.css"`);
|
||||
App.resetCss();
|
||||
App.applyCss(`${COMPILED_STYLE_DIR}/style.css`);
|
||||
console.log('[LOG] Styles loaded')
|
||||
}
|
||||
applyStyle().catch(print);
|
||||
}
|
||||
|
|
@ -1,27 +0,0 @@
|
|||
const { Gdk } = imports.gi;
|
||||
import * as Utils from 'resource:///com/github/Aylur/ags/utils.js';
|
||||
const { execAsync, exec } = Utils;
|
||||
|
||||
export let monitors;
|
||||
|
||||
// Mixes with Gdk monitor size cuz it reports monitor size scaled
|
||||
async function updateStuff() {
|
||||
monitors = JSON.parse(exec('hyprctl monitors -j'))
|
||||
const display = Gdk.Display.get_default();
|
||||
monitors.forEach((monitor, i) => {
|
||||
const gdkMonitor = display.get_monitor(i);
|
||||
monitor.realWidth = monitor.width;
|
||||
monitor.realHeight = monitor.height;
|
||||
if (userOptions.monitors.scaleMethod.toLowerCase == "gdk") {
|
||||
monitor.width = gdkMonitor.get_geometry().width;
|
||||
monitor.height = gdkMonitor.get_geometry().height;
|
||||
}
|
||||
else { // == "division"
|
||||
monitor.width = Math.ceil(monitor.realWidth / monitor.scale);
|
||||
monitor.height = Math.ceil(monitor.realHeight / monitor.scale);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
updateStuff().catch(print);
|
||||
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
export const quotes = [
|
||||
{
|
||||
quote: 'Nvidia, fuck you',
|
||||
author: 'Linus Torvalds',
|
||||
},
|
||||
{
|
||||
quote: 'reproducible system? cock and vagina?',
|
||||
author: 'vaxry',
|
||||
},
|
||||
{
|
||||
quote: "haha pointers hee hee i love pointe-\\\nProcess Vaxry exited with signal SIGSEGV",
|
||||
author: 'vaxry',
|
||||
}
|
||||
];
|
||||
|
|
@ -1,94 +0,0 @@
|
|||
export const WWO_CODE = {
|
||||
"113": "Sunny",
|
||||
"116": "PartlyCloudy",
|
||||
"119": "Cloudy",
|
||||
"122": "VeryCloudy",
|
||||
"143": "Fog",
|
||||
"176": "LightShowers",
|
||||
"179": "LightSleetShowers",
|
||||
"182": "LightSleet",
|
||||
"185": "LightSleet",
|
||||
"200": "ThunderyShowers",
|
||||
"227": "LightSnow",
|
||||
"230": "HeavySnow",
|
||||
"248": "Fog",
|
||||
"260": "Fog",
|
||||
"263": "LightShowers",
|
||||
"266": "LightRain",
|
||||
"281": "LightSleet",
|
||||
"284": "LightSleet",
|
||||
"293": "LightRain",
|
||||
"296": "LightRain",
|
||||
"299": "HeavyShowers",
|
||||
"302": "HeavyRain",
|
||||
"305": "HeavyShowers",
|
||||
"308": "HeavyRain",
|
||||
"311": "LightSleet",
|
||||
"314": "LightSleet",
|
||||
"317": "LightSleet",
|
||||
"320": "LightSnow",
|
||||
"323": "LightSnowShowers",
|
||||
"326": "LightSnowShowers",
|
||||
"329": "HeavySnow",
|
||||
"332": "HeavySnow",
|
||||
"335": "HeavySnowShowers",
|
||||
"338": "HeavySnow",
|
||||
"350": "LightSleet",
|
||||
"353": "LightShowers",
|
||||
"356": "HeavyShowers",
|
||||
"359": "HeavyRain",
|
||||
"362": "LightSleetShowers",
|
||||
"365": "LightSleetShowers",
|
||||
"368": "LightSnowShowers",
|
||||
"371": "HeavySnowShowers",
|
||||
"374": "LightSleetShowers",
|
||||
"377": "LightSleet",
|
||||
"386": "ThunderyShowers",
|
||||
"389": "ThunderyHeavyRain",
|
||||
"392": "ThunderySnowShowers",
|
||||
"395": "HeavySnowShowers",
|
||||
}
|
||||
|
||||
export const WEATHER_SYMBOL = {
|
||||
"Unknown": "air",
|
||||
"Cloudy": "cloud",
|
||||
"Fog": "foggy",
|
||||
"HeavyRain": "rainy",
|
||||
"HeavyShowers": "rainy",
|
||||
"HeavySnow": "snowing",
|
||||
"HeavySnowShowers": "snowing",
|
||||
"LightRain": "rainy",
|
||||
"LightShowers": "rainy",
|
||||
"LightSleet": "rainy",
|
||||
"LightSleetShowers": "rainy",
|
||||
"LightSnow": "cloudy_snowing",
|
||||
"LightSnowShowers": "cloudy_snowing",
|
||||
"PartlyCloudy": "partly_cloudy_day",
|
||||
"Sunny": "clear_day",
|
||||
"ThunderyHeavyRain": "thunderstorm",
|
||||
"ThunderyShowers": "thunderstorm",
|
||||
"ThunderySnowShowers": "thunderstorm",
|
||||
"VeryCloudy": "cloud",
|
||||
}
|
||||
|
||||
export const NIGHT_WEATHER_SYMBOL = {
|
||||
"Unknown": "air",
|
||||
"Cloudy": "cloud",
|
||||
"Fog": "foggy",
|
||||
"HeavyRain": "rainy",
|
||||
"HeavyShowers": "rainy",
|
||||
"HeavySnow": "snowing",
|
||||
"HeavySnowShowers": "snowing",
|
||||
"LightRain": "rainy",
|
||||
"LightShowers": "rainy",
|
||||
"LightSleet": "rainy",
|
||||
"LightSleetShowers": "rainy",
|
||||
"LightSnow": "cloudy_snowing",
|
||||
"LightSnowShowers": "cloudy_snowing",
|
||||
"PartlyCloudy": "partly_cloudy_night",
|
||||
"Sunny": "clear_night",
|
||||
"ThunderyHeavyRain": "thunderstorm",
|
||||
"ThunderyShowers": "thunderstorm",
|
||||
"ThunderySnowShowers": "thunderstorm",
|
||||
"VeryCloudy": "cloud",
|
||||
}
|
||||
|
|
@ -1,106 +0,0 @@
|
|||
const { Gtk } = imports.gi;
|
||||
const Lang = imports.lang;
|
||||
import Widget from 'resource:///com/github/Aylur/ags/widget.js'
|
||||
import * as Utils from 'resource:///com/github/Aylur/ags/utils.js'
|
||||
|
||||
// -- Styling --
|
||||
// min-height for diameter
|
||||
// min-width for trough stroke
|
||||
// padding for space between trough and progress
|
||||
// margin for space between widget and parent
|
||||
// background-color for trough color
|
||||
// color for progress color
|
||||
// -- Usage --
|
||||
// font size for progress value (0-100px) (hacky i know, but i want animations)
|
||||
export const AnimatedCircProg = ({
|
||||
initFrom = 0,
|
||||
initTo = 0,
|
||||
initAnimTime = 2900,
|
||||
initAnimPoints = 1,
|
||||
extraSetup = () => { },
|
||||
...rest
|
||||
}) => Widget.DrawingArea({
|
||||
...rest,
|
||||
css: `${initFrom != initTo ? 'font-size: ' + initFrom + 'px; transition: ' + initAnimTime + 'ms linear;' : ''}`,
|
||||
setup: (area) => {
|
||||
const styleContext = area.get_style_context();
|
||||
const width = styleContext.get_property('min-height', Gtk.StateFlags.NORMAL);
|
||||
const height = styleContext.get_property('min-height', Gtk.StateFlags.NORMAL);
|
||||
const padding = styleContext.get_padding(Gtk.StateFlags.NORMAL).left;
|
||||
const marginLeft = styleContext.get_margin(Gtk.StateFlags.NORMAL).left;
|
||||
const marginRight = styleContext.get_margin(Gtk.StateFlags.NORMAL).right;
|
||||
const marginTop = styleContext.get_margin(Gtk.StateFlags.NORMAL).top;
|
||||
const marginBottom = styleContext.get_margin(Gtk.StateFlags.NORMAL).bottom;
|
||||
area.set_size_request(width + marginLeft + marginRight, height + marginTop + marginBottom);
|
||||
area.connect('draw', Lang.bind(area, (area, cr) => {
|
||||
const styleContext = area.get_style_context();
|
||||
const width = styleContext.get_property('min-height', Gtk.StateFlags.NORMAL);
|
||||
const height = styleContext.get_property('min-height', Gtk.StateFlags.NORMAL);
|
||||
const padding = styleContext.get_padding(Gtk.StateFlags.NORMAL).left;
|
||||
const marginLeft = styleContext.get_margin(Gtk.StateFlags.NORMAL).left;
|
||||
const marginRight = styleContext.get_margin(Gtk.StateFlags.NORMAL).right;
|
||||
const marginTop = styleContext.get_margin(Gtk.StateFlags.NORMAL).top;
|
||||
const marginBottom = styleContext.get_margin(Gtk.StateFlags.NORMAL).bottom;
|
||||
area.set_size_request(width + marginLeft + marginRight, height + marginTop + marginBottom);
|
||||
|
||||
const progressValue = styleContext.get_property('font-size', Gtk.StateFlags.NORMAL) / 100.0;
|
||||
|
||||
const bg_stroke = styleContext.get_property('min-width', Gtk.StateFlags.NORMAL);
|
||||
const fg_stroke = bg_stroke - padding;
|
||||
const radius = Math.min(width, height) / 2.0 - Math.max(bg_stroke, fg_stroke) / 2.0;
|
||||
const center_x = width / 2.0 + marginLeft;
|
||||
const center_y = height / 2.0 + marginTop;
|
||||
const start_angle = -Math.PI / 2.0;
|
||||
const end_angle = start_angle + (2 * Math.PI * progressValue);
|
||||
const start_x = center_x + Math.cos(start_angle) * radius;
|
||||
const start_y = center_y + Math.sin(start_angle) * radius;
|
||||
const end_x = center_x + Math.cos(end_angle) * radius;
|
||||
const end_y = center_y + Math.sin(end_angle) * radius;
|
||||
|
||||
// Draw background
|
||||
const background_color = styleContext.get_property('background-color', Gtk.StateFlags.NORMAL);
|
||||
cr.setSourceRGBA(background_color.red, background_color.green, background_color.blue, background_color.alpha);
|
||||
cr.arc(center_x, center_y, radius, 0, 2 * Math.PI);
|
||||
cr.setLineWidth(bg_stroke);
|
||||
cr.stroke();
|
||||
|
||||
if (progressValue == 0) return;
|
||||
|
||||
// Draw progress
|
||||
const color = styleContext.get_property('color', Gtk.StateFlags.NORMAL);
|
||||
cr.setSourceRGBA(color.red, color.green, color.blue, color.alpha);
|
||||
cr.arc(center_x, center_y, radius, start_angle, end_angle);
|
||||
cr.setLineWidth(fg_stroke);
|
||||
cr.stroke();
|
||||
|
||||
// Draw rounded ends for progress arcs
|
||||
cr.setLineWidth(0);
|
||||
cr.arc(start_x, start_y, fg_stroke / 2, 0, 0 - 0.01);
|
||||
cr.fill();
|
||||
cr.arc(end_x, end_y, fg_stroke / 2, 0, 0 - 0.01);
|
||||
cr.fill();
|
||||
}));
|
||||
|
||||
// Init animation
|
||||
if (initFrom != initTo) {
|
||||
area.css = `font-size: ${initFrom}px; transition: ${initAnimTime}ms linear;`;
|
||||
Utils.timeout(20, () => {
|
||||
area.css = `font-size: ${initTo}px;`;
|
||||
}, area)
|
||||
const transitionDistance = initTo - initFrom;
|
||||
const oneStep = initAnimTime / initAnimPoints;
|
||||
area.css = `
|
||||
font-size: ${initFrom}px;
|
||||
transition: ${oneStep}ms linear;
|
||||
`;
|
||||
for (let i = 0; i < initAnimPoints; i++) {
|
||||
Utils.timeout(Math.max(10, i * oneStep), () => {
|
||||
if(!area) return;
|
||||
area.css = `${initFrom != initTo ? 'font-size: ' + (initFrom + (transitionDistance / initAnimPoints * (i + 1))) + 'px;' : ''}`;
|
||||
});
|
||||
}
|
||||
}
|
||||
else area.css = 'font-size: 0px;';
|
||||
extraSetup(area);
|
||||
},
|
||||
})
|
||||
|
|
@ -1,71 +0,0 @@
|
|||
const { Gtk } = imports.gi;
|
||||
const Lang = imports.lang;
|
||||
import Widget from 'resource:///com/github/Aylur/ags/widget.js';
|
||||
|
||||
// min-height/min-width for height/width
|
||||
// background-color/color for background/indicator color
|
||||
// padding for pad of indicator
|
||||
// font-size for selected index (0-based)
|
||||
export const NavigationIndicator = ({count, vertical, ...props}) => Widget.DrawingArea({
|
||||
...props,
|
||||
setup: (area) => {
|
||||
const styleContext = area.get_style_context();
|
||||
const width = Math.max(styleContext.get_property('min-width', Gtk.StateFlags.NORMAL), area.get_allocated_width());
|
||||
const height = Math.max(styleContext.get_property('min-height', Gtk.StateFlags.NORMAL), area.get_allocated_height());
|
||||
area.set_size_request(width, height);
|
||||
|
||||
area.connect('draw', Lang.bind(area, (area, cr) => {
|
||||
const styleContext = area.get_style_context();
|
||||
const width = Math.max(styleContext.get_property('min-width', Gtk.StateFlags.NORMAL), area.get_allocated_width());
|
||||
const height = Math.max(styleContext.get_property('min-height', Gtk.StateFlags.NORMAL), area.get_allocated_height());
|
||||
// console.log('allocated width/height:', area.get_allocated_width(), '/', area.get_allocated_height())
|
||||
area.set_size_request(width, height);
|
||||
const paddingLeft = styleContext.get_padding(Gtk.StateFlags.NORMAL).left;
|
||||
const paddingRight = styleContext.get_padding(Gtk.StateFlags.NORMAL).right;
|
||||
const paddingTop = styleContext.get_padding(Gtk.StateFlags.NORMAL).top;
|
||||
const paddingBottom = styleContext.get_padding(Gtk.StateFlags.NORMAL).bottom;
|
||||
|
||||
const selectedCell = styleContext.get_property('font-size', Gtk.StateFlags.NORMAL);
|
||||
|
||||
let cellWidth = width;
|
||||
let cellHeight = height;
|
||||
if (vertical) cellHeight /= count;
|
||||
else cellWidth /= count;
|
||||
const indicatorWidth = cellWidth - paddingLeft - paddingRight;
|
||||
const indicatorHeight = cellHeight - paddingTop - paddingBottom;
|
||||
|
||||
const background_color = styleContext.get_property('background-color', Gtk.StateFlags.NORMAL);
|
||||
const color = styleContext.get_property('color', Gtk.StateFlags.NORMAL);
|
||||
cr.setLineWidth(2);
|
||||
// Background
|
||||
cr.setSourceRGBA(background_color.red, background_color.green, background_color.blue, background_color.alpha);
|
||||
cr.rectangle(0, 0, width, height);
|
||||
cr.fill();
|
||||
|
||||
// The indicator line
|
||||
cr.setSourceRGBA(color.red, color.green, color.blue, color.alpha);
|
||||
if (vertical) {
|
||||
cr.rectangle(paddingLeft, paddingTop + cellHeight * selectedCell + indicatorWidth / 2, indicatorWidth, indicatorHeight - indicatorWidth);
|
||||
cr.stroke();
|
||||
cr.rectangle(paddingLeft, paddingTop + cellHeight * selectedCell + indicatorWidth / 2, indicatorWidth, indicatorHeight - indicatorWidth);
|
||||
cr.fill();
|
||||
cr.arc(paddingLeft + indicatorWidth / 2, paddingTop + cellHeight * selectedCell + indicatorWidth / 2, indicatorWidth / 2, Math.PI, 2 * Math.PI);
|
||||
cr.fill();
|
||||
cr.arc(paddingLeft + indicatorWidth / 2, paddingTop + cellHeight * selectedCell + indicatorHeight - indicatorWidth / 2, indicatorWidth / 2, 0, Math.PI);
|
||||
cr.fill();
|
||||
}
|
||||
else {
|
||||
cr.rectangle(paddingLeft + cellWidth * selectedCell + indicatorHeight / 2, paddingTop, indicatorWidth - indicatorHeight, indicatorHeight);
|
||||
cr.stroke();
|
||||
cr.rectangle(paddingLeft + cellWidth * selectedCell + indicatorHeight / 2, paddingTop, indicatorWidth - indicatorHeight, indicatorHeight);
|
||||
cr.fill();
|
||||
cr.arc(paddingLeft + cellWidth * selectedCell + indicatorHeight / 2, paddingTop + indicatorHeight / 2, indicatorHeight / 2, 0.5 * Math.PI, 1.5 * Math.PI);
|
||||
cr.fill();
|
||||
cr.arc(paddingLeft + cellWidth * selectedCell + indicatorWidth - indicatorHeight / 2, paddingTop + indicatorHeight / 2, indicatorHeight / 2, -0.5 * Math.PI, 0.5 * Math.PI);
|
||||
cr.fill();
|
||||
}
|
||||
}))
|
||||
},
|
||||
})
|
||||
|
||||
|
||||
|
|
@ -1,50 +0,0 @@
|
|||
import Widget from 'resource:///com/github/Aylur/ags/widget.js';
|
||||
const { Gtk } = imports.gi;
|
||||
const Lang = imports.lang;
|
||||
|
||||
export const RoundedCorner = (place, props) => Widget.DrawingArea({
|
||||
...props,
|
||||
hpack: place.includes('left') ? 'start' : 'end',
|
||||
vpack: place.includes('top') ? 'start' : 'end',
|
||||
setup: (widget) => Utils.timeout(1, () => {
|
||||
const c = widget.get_style_context().get_property('background-color', Gtk.StateFlags.NORMAL);
|
||||
const r = widget.get_style_context().get_property('border-radius', Gtk.StateFlags.NORMAL);
|
||||
widget.set_size_request(r, r);
|
||||
widget.connect('draw', Lang.bind(widget, (widget, cr) => {
|
||||
const c = widget.get_style_context().get_property('background-color', Gtk.StateFlags.NORMAL);
|
||||
const r = widget.get_style_context().get_property('border-radius', Gtk.StateFlags.NORMAL);
|
||||
// const borderColor = widget.get_style_context().get_property('color', Gtk.StateFlags.NORMAL);
|
||||
// const borderWidth = widget.get_style_context().get_border(Gtk.StateFlags.NORMAL).left; // ur going to write border-width: something anyway
|
||||
widget.set_size_request(r, r);
|
||||
|
||||
switch (place) {
|
||||
case 'topleft':
|
||||
cr.arc(r, r, r, Math.PI, 3 * Math.PI / 2);
|
||||
cr.lineTo(0, 0);
|
||||
break;
|
||||
|
||||
case 'topright':
|
||||
cr.arc(0, r, r, 3 * Math.PI / 2, 2 * Math.PI);
|
||||
cr.lineTo(r, 0);
|
||||
break;
|
||||
|
||||
case 'bottomleft':
|
||||
cr.arc(r, 0, r, Math.PI / 2, Math.PI);
|
||||
cr.lineTo(0, r);
|
||||
break;
|
||||
|
||||
case 'bottomright':
|
||||
cr.arc(0, 0, r, 0, Math.PI / 2);
|
||||
cr.lineTo(r, r);
|
||||
break;
|
||||
}
|
||||
|
||||
cr.closePath();
|
||||
cr.setSourceRGBA(c.red, c.green, c.blue, c.alpha);
|
||||
cr.fill();
|
||||
// cr.setLineWidth(borderWidth);
|
||||
// cr.setSourceRGBA(borderColor.red, borderColor.green, borderColor.blue, borderColor.alpha);
|
||||
// cr.stroke();
|
||||
}));
|
||||
}),
|
||||
});
|
||||
|
|
@ -1,49 +0,0 @@
|
|||
import Widget from 'resource:///com/github/Aylur/ags/widget.js';
|
||||
const { Gtk } = imports.gi;
|
||||
const Lang = imports.lang;
|
||||
|
||||
export const AnimatedSlider = ({
|
||||
className,
|
||||
value,
|
||||
...rest
|
||||
}) => {
|
||||
return Widget.DrawingArea({
|
||||
className: `${className}`,
|
||||
setup: (self) => {
|
||||
self.connect('draw', Lang.bind(self, (self, cr) => {
|
||||
const styleContext = self.get_style_context();
|
||||
const allocatedWidth = self.get_allocated_width();
|
||||
const allocatedHeight = self.get_allocated_height();
|
||||
console.log(allocatedHeight, allocatedWidth)
|
||||
const minWidth = styleContext.get_property('min-width', Gtk.StateFlags.NORMAL);
|
||||
const minHeight = styleContext.get_property('min-height', Gtk.StateFlags.NORMAL);
|
||||
const radius = styleContext.get_property('border-radius', Gtk.StateFlags.NORMAL);
|
||||
const bg = styleContext.get_property('background-color', Gtk.StateFlags.NORMAL);
|
||||
const fg = styleContext.get_property('color', Gtk.StateFlags.NORMAL);
|
||||
const value = styleContext.get_property('font-size', Gtk.StateFlags.NORMAL) / 100;
|
||||
self.set_size_request(-1, minHeight);
|
||||
const width = allocatedHeight;
|
||||
const height = minHeight;
|
||||
|
||||
cr.arc(radius, radius, radius, -1 * Math.PI, -0.5 * Math.PI); // Top-left
|
||||
cr.arc(width - radius, radius, radius, -0.5 * Math.PI, 0); // Top-right
|
||||
cr.arc(width - radius, height - radius, radius, 0, 0.5 * Math.PI); // Bottom-left
|
||||
cr.arc(radius, height - radius, radius, 0.5 * Math.PI, 1 * Math.PI); // Bottom-right
|
||||
cr.setSourceRGBA(bg.red, bg.green, bg.blue, bg.alpha);
|
||||
cr.closePath();
|
||||
cr.fill();
|
||||
|
||||
// const valueWidth = width * value;
|
||||
// cr.arc(radius, radius, radius, -1 * Math.PI, -0.5 * Math.PI); // Top-left
|
||||
// cr.arc(valueWidth - radius, radius, radius, -0.5 * Math.PI, 0); // Top-right
|
||||
// cr.arc(valueWidth - radius, height - radius, radius, 0, 0.5 * Math.PI); // Bottom-left
|
||||
// cr.arc(radius, height - radius, radius, 0.5 * Math.PI, 1 * Math.PI); // Bottom-right
|
||||
// cr.setSourceRGBA(fg.red, fg.green, fg.blue, fg.alpha);
|
||||
// cr.closePath();
|
||||
// cr.fill();
|
||||
|
||||
}));
|
||||
},
|
||||
...rest,
|
||||
})
|
||||
}
|
||||
|
|
@ -1,23 +0,0 @@
|
|||
import App from 'resource:///com/github/Aylur/ags/app.js';
|
||||
import Widget from 'resource:///com/github/Aylur/ags/widget.js';
|
||||
import { monitors } from '../.commondata/hyprlanddata.js';
|
||||
const { Box, EventBox } = Widget;
|
||||
|
||||
export const clickCloseRegion = ({ name, multimonitor = true, monitor = 0, expand = true, fillMonitor = '' }) => {
|
||||
return EventBox({
|
||||
child: Box({
|
||||
expand: expand,
|
||||
css: `
|
||||
min-width: ${fillMonitor.includes('h') ? monitors[monitor].width : 0}px;
|
||||
min-height: ${fillMonitor.includes('v') ? monitors[monitor].height : 0}px;
|
||||
`,
|
||||
}),
|
||||
setup: (self) => self.on('button-press-event', (self, event) => { // Any mouse button
|
||||
if (multimonitor) closeWindowOnAllMonitors(name);
|
||||
else App.closeWindow(name);
|
||||
}),
|
||||
})
|
||||
}
|
||||
|
||||
export default clickCloseRegion;
|
||||
|
||||
|
|
@ -1,219 +0,0 @@
|
|||
import Variable from 'resource:///com/github/Aylur/ags/variable.js';
|
||||
import Widget from 'resource:///com/github/Aylur/ags/widget.js';
|
||||
import * as Utils from 'resource:///com/github/Aylur/ags/utils.js';
|
||||
import { MaterialIcon } from './materialicon.js';
|
||||
import { setupCursorHover } from '../.widgetutils/cursorhover.js';
|
||||
const { Box, Button, Label, Revealer, SpinButton } = Widget;
|
||||
|
||||
export const ConfigToggle = ({
|
||||
icon, name, desc = '', initValue,
|
||||
expandWidget = true,
|
||||
onChange = () => { }, extraSetup = () => { },
|
||||
...rest
|
||||
}) => {
|
||||
const enabled = Variable(initValue);
|
||||
const toggleIcon = Label({
|
||||
className: `icon-material txt-bold ${enabled.value ? '' : 'txt-poof'}`,
|
||||
label: `${enabled.value ? 'check' : ''}`,
|
||||
setup: (self) => self.hook(enabled, (self) => {
|
||||
self.toggleClassName('switch-fg-toggling-false', false);
|
||||
if (!enabled.value) {
|
||||
self.label = '';
|
||||
self.toggleClassName('txt-poof', true);
|
||||
}
|
||||
else Utils.timeout(1, () => {
|
||||
toggleIcon.label = 'check';
|
||||
toggleIcon.toggleClassName('txt-poof', false);
|
||||
})
|
||||
}),
|
||||
})
|
||||
const toggleButtonIndicator = Box({
|
||||
className: `switch-fg ${enabled.value ? 'switch-fg-true' : ''}`,
|
||||
vpack: 'center',
|
||||
hpack: 'start',
|
||||
homogeneous: true,
|
||||
children: [toggleIcon,],
|
||||
setup: (self) => self.hook(enabled, (self) => {
|
||||
self.toggleClassName('switch-fg-true', enabled.value);
|
||||
}),
|
||||
});
|
||||
const toggleButton = Box({
|
||||
hpack: 'end',
|
||||
className: `switch-bg ${enabled.value ? 'switch-bg-true' : ''}`,
|
||||
homogeneous: true,
|
||||
children: [toggleButtonIndicator],
|
||||
setup: (self) => self.hook(enabled, (self) => {
|
||||
self.toggleClassName('switch-bg-true', enabled.value);
|
||||
}),
|
||||
});
|
||||
const widgetContent = Box({
|
||||
tooltipText: desc,
|
||||
className: 'txt spacing-h-5 configtoggle-box',
|
||||
children: [
|
||||
...(icon !== undefined ? [MaterialIcon(icon, 'norm')] : []),
|
||||
...(name !== undefined ? [Label({
|
||||
className: 'txt txt-small',
|
||||
label: name,
|
||||
})] : []),
|
||||
...(expandWidget ? [Box({ hexpand: true })] : []),
|
||||
toggleButton,
|
||||
]
|
||||
});
|
||||
const interactionWrapper = Button({
|
||||
attribute: {
|
||||
enabled: enabled,
|
||||
toggle: (newValue) => {
|
||||
enabled.value = !enabled.value;
|
||||
onChange(interactionWrapper, enabled.value);
|
||||
}
|
||||
},
|
||||
child: widgetContent,
|
||||
onClicked: (self) => self.attribute.toggle(self),
|
||||
setup: (self) => {
|
||||
setupCursorHover(self);
|
||||
self.connect('pressed', () => { // mouse down
|
||||
toggleIcon.toggleClassName('txt-poof', true);
|
||||
toggleIcon.toggleClassName('switch-fg-true', false);
|
||||
if (!enabled.value) toggleIcon.toggleClassName('switch-fg-toggling-false', true);
|
||||
});
|
||||
extraSetup(self)
|
||||
},
|
||||
...rest,
|
||||
});
|
||||
interactionWrapper.enabled = enabled;
|
||||
return interactionWrapper;
|
||||
}
|
||||
|
||||
export const ConfigSegmentedSelection = ({
|
||||
icon, name, desc = '',
|
||||
options = [{ name: 'Option 1', value: 0 }, { name: 'Option 2', value: 1 }],
|
||||
initIndex = 0,
|
||||
onChange,
|
||||
...rest
|
||||
}) => {
|
||||
let lastSelected = initIndex;
|
||||
let value = options[initIndex].value;
|
||||
const widget = Box({
|
||||
tooltipText: desc,
|
||||
className: 'segment-container',
|
||||
// homogeneous: true,
|
||||
children: options.map((option, id) => {
|
||||
const selectedIcon = Revealer({
|
||||
revealChild: id == initIndex,
|
||||
transition: 'slide_right',
|
||||
transitionDuration: userOptions.animations.durationSmall,
|
||||
child: MaterialIcon('check', 'norm')
|
||||
});
|
||||
return Button({
|
||||
setup: setupCursorHover,
|
||||
className: `segment-btn ${id == initIndex ? 'segment-btn-enabled' : ''}`,
|
||||
child: Box({
|
||||
hpack: 'center',
|
||||
className: 'spacing-h-5',
|
||||
children: [
|
||||
selectedIcon,
|
||||
Label({
|
||||
label: option.name,
|
||||
})
|
||||
]
|
||||
}),
|
||||
onClicked: (self) => {
|
||||
value = option.value;
|
||||
const kids = widget.get_children();
|
||||
kids[lastSelected].toggleClassName('segment-btn-enabled', false);
|
||||
kids[lastSelected].get_children()[0].get_children()[0].revealChild = false;
|
||||
lastSelected = id;
|
||||
self.toggleClassName('segment-btn-enabled', true);
|
||||
selectedIcon.revealChild = true;
|
||||
onChange(option.value, option.name);
|
||||
}
|
||||
})
|
||||
}),
|
||||
...rest,
|
||||
});
|
||||
return widget;
|
||||
|
||||
}
|
||||
|
||||
export const ConfigMulipleSelection = ({
|
||||
icon, name, desc = '',
|
||||
optionsArr = [
|
||||
[{ name: 'Option 1', value: 0 }, { name: 'Option 2', value: 1 }],
|
||||
[{ name: 'Option 3', value: 0 }, { name: 'Option 4', value: 1 }],
|
||||
],
|
||||
initIndex = [0, 0],
|
||||
onChange,
|
||||
...rest
|
||||
}) => {
|
||||
let lastSelected = initIndex;
|
||||
const widget = Box({
|
||||
tooltipText: desc,
|
||||
className: 'multipleselection-container spacing-v-3',
|
||||
vertical: true,
|
||||
children: optionsArr.map((options, grp) => Box({
|
||||
className: 'spacing-h-5',
|
||||
hpack: 'center',
|
||||
children: options.map((option, id) => Button({
|
||||
setup: setupCursorHover,
|
||||
className: `multipleselection-btn ${id == initIndex[1] && grp == initIndex[0] ? 'multipleselection-btn-enabled' : ''}`,
|
||||
label: option.name,
|
||||
onClicked: (self) => {
|
||||
const kidsg = widget.get_children();
|
||||
const kids = kidsg.flatMap(widget => widget.get_children());
|
||||
kids.forEach(kid => {
|
||||
kid.toggleClassName('multipleselection-btn-enabled', false);
|
||||
});
|
||||
lastSelected = id;
|
||||
self.toggleClassName('multipleselection-btn-enabled', true);
|
||||
onChange(option.value, option.name);
|
||||
}
|
||||
})),
|
||||
})),
|
||||
...rest,
|
||||
});
|
||||
return widget;
|
||||
|
||||
}
|
||||
|
||||
export const ConfigGap = ({ vertical = true, size = 5, ...rest }) => Box({
|
||||
className: `gap-${vertical ? 'v' : 'h'}-${size}`,
|
||||
...rest,
|
||||
})
|
||||
|
||||
export const ConfigSpinButton = ({
|
||||
icon, name, desc = '', initValue,
|
||||
minValue = 0, maxValue = 100, step = 1,
|
||||
expandWidget = true,
|
||||
onChange = () => { }, extraSetup = () => { },
|
||||
...rest
|
||||
}) => {
|
||||
const value = Variable(initValue);
|
||||
const spinButton = SpinButton({
|
||||
className: 'spinbutton',
|
||||
range: [minValue, maxValue],
|
||||
increments: [step, step],
|
||||
onValueChanged: ({ value: newValue }) => {
|
||||
value.value = newValue;
|
||||
onChange(spinButton, newValue);
|
||||
},
|
||||
});
|
||||
spinButton.value = value.value;
|
||||
const widgetContent = Box({
|
||||
tooltipText: desc,
|
||||
className: 'txt spacing-h-5 configtoggle-box',
|
||||
children: [
|
||||
...(icon !== undefined ? [MaterialIcon(icon, 'norm')] : []),
|
||||
...(name !== undefined ? [Label({
|
||||
className: 'txt txt-small',
|
||||
label: name,
|
||||
})] : []),
|
||||
...(expandWidget ? [Box({ hexpand: true })] : []),
|
||||
spinButton,
|
||||
],
|
||||
setup: (self) => {
|
||||
extraSetup(self);
|
||||
},
|
||||
...rest,
|
||||
});
|
||||
return widgetContent;
|
||||
}
|
||||
|
|
@ -1,7 +0,0 @@
|
|||
import Widget from 'resource:///com/github/Aylur/ags/widget.js';
|
||||
|
||||
export const MaterialIcon = (icon, size, props = {}) => Widget.Label({
|
||||
className: `icon-material txt-${size}`,
|
||||
label: icon,
|
||||
...props,
|
||||
})
|
||||
|
|
@ -1,462 +0,0 @@
|
|||
// This file is for the actual widget for each single notification
|
||||
const { GLib, Gdk, Gtk } = imports.gi;
|
||||
import Widget from 'resource:///com/github/Aylur/ags/widget.js'
|
||||
import * as Utils from 'resource:///com/github/Aylur/ags/utils.js'
|
||||
const { Box, EventBox, Icon, Overlay, Label, Button, Revealer } = Widget;
|
||||
import { MaterialIcon } from './materialicon.js';
|
||||
import { setupCursorHover } from "../.widgetutils/cursorhover.js";
|
||||
import { AnimatedCircProg } from "./cairo_circularprogress.js";
|
||||
|
||||
function guessMessageType(summary) {
|
||||
const str = summary.toLowerCase();
|
||||
if (str.includes('reboot')) return 'restart_alt';
|
||||
if (str.includes('recording')) return 'screen_record';
|
||||
if (str.includes('battery') || summary.includes('power')) return 'power';
|
||||
if (str.includes('screenshot')) return 'screenshot_monitor';
|
||||
if (str.includes('welcome')) return 'waving_hand';
|
||||
if (str.includes('time')) return 'scheduleb';
|
||||
if (str.includes('installed')) return 'download';
|
||||
if (str.includes('update')) return 'update';
|
||||
if (str.startsWith('file')) return 'folder_copy';
|
||||
return 'chat';
|
||||
}
|
||||
|
||||
function exists(widget) {
|
||||
return widget !== null;
|
||||
}
|
||||
|
||||
const getFriendlyNotifTimeString = (timeObject) => {
|
||||
const messageTime = GLib.DateTime.new_from_unix_local(timeObject);
|
||||
const oneMinuteAgo = GLib.DateTime.new_now_local().add_seconds(-60);
|
||||
if (messageTime.compare(oneMinuteAgo) > 0)
|
||||
return getString('Now');
|
||||
else if (messageTime.get_day_of_year() == GLib.DateTime.new_now_local().get_day_of_year())
|
||||
return messageTime.format(userOptions.time.format);
|
||||
else if (messageTime.get_day_of_year() == GLib.DateTime.new_now_local().get_day_of_year() - 1)
|
||||
return getString('Yesterday');
|
||||
else
|
||||
return messageTime.format(userOptions.time.dateFormat);
|
||||
}
|
||||
|
||||
const NotificationIcon = (notifObject) => {
|
||||
// { appEntry, appIcon, image }, urgency = 'normal'
|
||||
if (notifObject.image) {
|
||||
return Box({
|
||||
valign: Gtk.Align.CENTER,
|
||||
hexpand: false,
|
||||
className: 'notif-icon',
|
||||
css: `
|
||||
background-image: url("${notifObject.image}");
|
||||
background-size: auto 100%;
|
||||
background-repeat: no-repeat;
|
||||
background-position: center;
|
||||
`,
|
||||
});
|
||||
}
|
||||
|
||||
let icon = 'NO_ICON';
|
||||
if (Utils.lookUpIcon(notifObject.appIcon))
|
||||
icon = notifObject.appIcon;
|
||||
if (Utils.lookUpIcon(notifObject.appEntry))
|
||||
icon = notifObject.appEntry;
|
||||
|
||||
return Box({
|
||||
vpack: 'center',
|
||||
hexpand: false,
|
||||
className: `notif-icon notif-icon-material-${notifObject.urgency}`,
|
||||
homogeneous: true,
|
||||
children: [
|
||||
(icon != 'NO_ICON' ?
|
||||
Icon({
|
||||
vpack: 'center',
|
||||
icon: icon,
|
||||
})
|
||||
:
|
||||
MaterialIcon(`${notifObject.urgency == 'critical' ? 'release_alert' : guessMessageType(notifObject.summary.toLowerCase())}`, 'hugerass', {
|
||||
hexpand: true,
|
||||
})
|
||||
)
|
||||
],
|
||||
});
|
||||
};
|
||||
|
||||
export default ({
|
||||
notifObject,
|
||||
isPopup = false,
|
||||
props = {},
|
||||
} = {}) => {
|
||||
const popupTimeout = notifObject.timeout || (notifObject.urgency == 'critical' ? 8000 : 3000);
|
||||
const command = (isPopup ?
|
||||
() => notifObject.dismiss() :
|
||||
() => notifObject.close()
|
||||
)
|
||||
const destroyWithAnims = () => {
|
||||
widget.sensitive = false;
|
||||
notificationBox.setCss(middleClickClose);
|
||||
Utils.timeout(userOptions.animations.durationSmall, () => {
|
||||
if (wholeThing) wholeThing.revealChild = false;
|
||||
}, wholeThing);
|
||||
Utils.timeout(userOptions.animations.durationSmall * 2, () => {
|
||||
command();
|
||||
if (wholeThing) {
|
||||
wholeThing.destroy();
|
||||
wholeThing = null;
|
||||
}
|
||||
}, wholeThing);
|
||||
}
|
||||
const widget = EventBox({
|
||||
onHover: (self) => {
|
||||
self.window.set_cursor(Gdk.Cursor.new_from_name(display, 'grab'));
|
||||
if (!wholeThing.attribute.hovered)
|
||||
wholeThing.attribute.hovered = true;
|
||||
},
|
||||
onHoverLost: (self) => {
|
||||
self.window.set_cursor(null);
|
||||
if (wholeThing.attribute.hovered)
|
||||
wholeThing.attribute.hovered = false;
|
||||
if (isPopup) {
|
||||
command();
|
||||
}
|
||||
},
|
||||
onMiddleClick: (self) => {
|
||||
destroyWithAnims();
|
||||
},
|
||||
setup: (self) => {
|
||||
self.on("button-press-event", () => {
|
||||
wholeThing.attribute.held = true;
|
||||
notificationContent.toggleClassName(`${isPopup ? 'popup-' : ''}notif-clicked-${notifObject.urgency}`, true);
|
||||
Utils.timeout(800, () => {
|
||||
if (wholeThing?.attribute.held) {
|
||||
Utils.execAsync(['wl-copy', `${notifObject.body}`]).catch(print);
|
||||
notifTextSummary.label = notifObject.summary + " (copied)";
|
||||
Utils.timeout(3000, () => notifTextSummary.label = notifObject.summary)
|
||||
}
|
||||
})
|
||||
}).on("button-release-event", () => {
|
||||
wholeThing.attribute.held = false;
|
||||
notificationContent.toggleClassName(`${isPopup ? 'popup-' : ''}notif-clicked-${notifObject.urgency}`, false);
|
||||
})
|
||||
}
|
||||
});
|
||||
let wholeThing = Revealer({
|
||||
attribute: {
|
||||
'close': undefined,
|
||||
'destroyWithAnims': destroyWithAnims,
|
||||
'dragging': false,
|
||||
'held': false,
|
||||
'hovered': false,
|
||||
'id': notifObject.id,
|
||||
},
|
||||
revealChild: false,
|
||||
transition: 'slide_down',
|
||||
transitionDuration: userOptions.animations.durationLarge,
|
||||
child: Box({ // Box to make sure css-based spacing works
|
||||
homogeneous: true,
|
||||
}),
|
||||
});
|
||||
|
||||
const display = Gdk.Display.get_default();
|
||||
const notifTextPreview = Revealer({
|
||||
transition: 'slide_down',
|
||||
transitionDuration: userOptions.animations.durationSmall,
|
||||
revealChild: true,
|
||||
child: Label({
|
||||
xalign: 0,
|
||||
className: `txt-smallie notif-body-${notifObject.urgency}`,
|
||||
useMarkup: true,
|
||||
xalign: 0,
|
||||
justify: Gtk.Justification.LEFT,
|
||||
maxWidthChars: 1,
|
||||
truncate: 'end',
|
||||
label: notifObject.body.split("\n")[0],
|
||||
}),
|
||||
});
|
||||
const notifTextExpanded = Revealer({
|
||||
transition: 'slide_up',
|
||||
transitionDuration: userOptions.animations.durationSmall,
|
||||
revealChild: false,
|
||||
child: Box({
|
||||
vertical: true,
|
||||
className: 'spacing-v-10',
|
||||
children: [
|
||||
Label({
|
||||
xalign: 0,
|
||||
className: `txt-smallie notif-body-${notifObject.urgency}`,
|
||||
useMarkup: true,
|
||||
xalign: 0,
|
||||
justify: Gtk.Justification.LEFT,
|
||||
maxWidthChars: 1,
|
||||
wrap: true,
|
||||
label: notifObject.body,
|
||||
}),
|
||||
Box({
|
||||
className: 'notif-actions spacing-h-5',
|
||||
children: [
|
||||
Button({
|
||||
hexpand: true,
|
||||
className: `notif-action notif-action-${notifObject.urgency}`,
|
||||
onClicked: () => destroyWithAnims(),
|
||||
setup: setupCursorHover,
|
||||
child: Label({
|
||||
label: getString('Close'),
|
||||
}),
|
||||
}),
|
||||
...notifObject.actions.map(action => Widget.Button({
|
||||
hexpand: true,
|
||||
className: `notif-action notif-action-${notifObject.urgency}`,
|
||||
onClicked: () => notifObject.invoke(action.id),
|
||||
setup: setupCursorHover,
|
||||
child: Label({
|
||||
label: action.label,
|
||||
}),
|
||||
}))
|
||||
],
|
||||
})
|
||||
]
|
||||
}),
|
||||
});
|
||||
const notifIcon = Box({
|
||||
vpack: 'start',
|
||||
homogeneous: true,
|
||||
children: [
|
||||
Overlay({
|
||||
child: NotificationIcon(notifObject),
|
||||
overlays: isPopup ? [AnimatedCircProg({
|
||||
className: `notif-circprog-${notifObject.urgency}`,
|
||||
vpack: 'center', hpack: 'center',
|
||||
initFrom: (isPopup ? 100 : 0),
|
||||
initTo: 0,
|
||||
initAnimTime: popupTimeout,
|
||||
})] : [],
|
||||
}),
|
||||
]
|
||||
});
|
||||
|
||||
const notifTextSummary = Label({
|
||||
xalign: 0,
|
||||
className: 'txt-small txt-semibold titlefont',
|
||||
justify: Gtk.Justification.LEFT,
|
||||
hexpand: true,
|
||||
maxWidthChars: 1,
|
||||
truncate: 'end',
|
||||
ellipsize: 3,
|
||||
useMarkup: notifObject.summary.startsWith('<'),
|
||||
label: notifObject.summary,
|
||||
});
|
||||
const initTimeString = getFriendlyNotifTimeString(notifObject.time);
|
||||
const notifTextBody = Label({
|
||||
vpack: 'center',
|
||||
justification: 'right',
|
||||
className: 'txt-smaller txt-semibold',
|
||||
label: initTimeString,
|
||||
setup: initTimeString == 'Now' ? (self) => {
|
||||
let id = Utils.timeout(60000, () => {
|
||||
self.label = getFriendlyNotifTimeString(notifObject.time);
|
||||
id = null;
|
||||
});
|
||||
self.connect('destroy', () => { if (id) GLib.source_remove(id) });
|
||||
} : () => { },
|
||||
});
|
||||
const notifText = Box({
|
||||
valign: Gtk.Align.CENTER,
|
||||
vertical: true,
|
||||
hexpand: true,
|
||||
children: [
|
||||
Box({
|
||||
children: [
|
||||
notifTextSummary,
|
||||
notifTextBody,
|
||||
]
|
||||
}),
|
||||
notifTextPreview,
|
||||
notifTextExpanded,
|
||||
]
|
||||
});
|
||||
const notifExpandButton = Button({
|
||||
vpack: 'start',
|
||||
className: 'notif-expand-btn',
|
||||
onClicked: (self) => {
|
||||
if (notifTextPreview.revealChild) { // Expanding...
|
||||
notifTextPreview.revealChild = false;
|
||||
notifTextExpanded.revealChild = true;
|
||||
self.child.label = 'expand_less';
|
||||
expanded = true;
|
||||
}
|
||||
else {
|
||||
notifTextPreview.revealChild = true;
|
||||
notifTextExpanded.revealChild = false;
|
||||
self.child.label = 'expand_more';
|
||||
expanded = false;
|
||||
}
|
||||
},
|
||||
child: MaterialIcon('expand_more', 'norm', {
|
||||
vpack: 'center',
|
||||
}),
|
||||
setup: setupCursorHover,
|
||||
});
|
||||
const notificationContent = Box({
|
||||
...props,
|
||||
className: `${isPopup ? 'popup-' : ''}notif-${notifObject.urgency} spacing-h-10`,
|
||||
children: [
|
||||
notifIcon,
|
||||
Box({
|
||||
className: 'spacing-h-5',
|
||||
children: [
|
||||
notifText,
|
||||
notifExpandButton,
|
||||
]
|
||||
})
|
||||
]
|
||||
})
|
||||
|
||||
// Gesture stuff
|
||||
const gesture = Gtk.GestureDrag.new(widget);
|
||||
var initDirX = 0;
|
||||
var initDirVertical = -1; // -1: unset, 0: horizontal, 1: vertical
|
||||
var expanded = false;
|
||||
// in px
|
||||
const startMargin = 0;
|
||||
const MOVE_THRESHOLD = 10;
|
||||
const DRAG_CONFIRM_THRESHOLD = 100;
|
||||
// in rem
|
||||
const maxOffset = 10.227;
|
||||
const endMargin = 20.455;
|
||||
const disappearHeight = 6.818;
|
||||
const leftAnim1 = `transition: ${userOptions.animations.durationSmall}ms cubic-bezier(0.05, 0.7, 0.1, 1);
|
||||
margin-left: -${Number(maxOffset + endMargin)}rem;
|
||||
margin-right: ${Number(maxOffset + endMargin)}rem;
|
||||
opacity: 0;`;
|
||||
|
||||
const rightAnim1 = `transition: ${userOptions.animations.durationSmall}ms cubic-bezier(0.05, 0.7, 0.1, 1);
|
||||
margin-left: ${Number(maxOffset + endMargin)}rem;
|
||||
margin-right: -${Number(maxOffset + endMargin)}rem;
|
||||
opacity: 0;`;
|
||||
|
||||
const middleClickClose = `transition: ${userOptions.animations.durationSmall}ms cubic-bezier(0.85, 0, 0.15, 1);
|
||||
margin-left: ${Number(maxOffset + endMargin)}rem;
|
||||
margin-right: -${Number(maxOffset + endMargin)}rem;
|
||||
opacity: 0;`;
|
||||
|
||||
const notificationBox = Box({
|
||||
attribute: {
|
||||
'leftAnim1': leftAnim1,
|
||||
'rightAnim1': rightAnim1,
|
||||
'middleClickClose': middleClickClose,
|
||||
'ready': false,
|
||||
},
|
||||
homogeneous: true,
|
||||
children: [notificationContent],
|
||||
setup: (self) => self
|
||||
.hook(gesture, self => {
|
||||
var offset_x = gesture.get_offset()[1];
|
||||
var offset_y = gesture.get_offset()[2];
|
||||
// Which dir?
|
||||
if (initDirVertical == -1) {
|
||||
if (Math.abs(offset_y) > MOVE_THRESHOLD)
|
||||
initDirVertical = 1;
|
||||
if (initDirX == 0 && Math.abs(offset_x) > MOVE_THRESHOLD) {
|
||||
initDirVertical = 0;
|
||||
initDirX = (offset_x > 0 ? 1 : -1);
|
||||
}
|
||||
}
|
||||
// Horizontal drag
|
||||
if (initDirVertical == 0 && offset_x > MOVE_THRESHOLD) {
|
||||
if (initDirX < 0)
|
||||
self.setCss(`margin-left: 0px; margin-right: 0px;`);
|
||||
else
|
||||
self.setCss(`
|
||||
margin-left: ${Number(offset_x + startMargin - MOVE_THRESHOLD)}px;
|
||||
margin-right: -${Number(offset_x + startMargin - MOVE_THRESHOLD)}px;
|
||||
`);
|
||||
}
|
||||
else if (initDirVertical == 0 && offset_x < -MOVE_THRESHOLD) {
|
||||
if (initDirX > 0)
|
||||
self.setCss(`margin-left: 0px; margin-right: 0px;`);
|
||||
else {
|
||||
offset_x = Math.abs(offset_x);
|
||||
self.setCss(`
|
||||
margin-right: ${Number(offset_x + startMargin - MOVE_THRESHOLD)}px;
|
||||
margin-left: -${Number(offset_x + startMargin - MOVE_THRESHOLD)}px;
|
||||
`);
|
||||
}
|
||||
}
|
||||
// Update dragging
|
||||
wholeThing.attribute.dragging = Math.abs(offset_x) > MOVE_THRESHOLD;
|
||||
if (Math.abs(offset_x) > MOVE_THRESHOLD ||
|
||||
Math.abs(offset_y) > MOVE_THRESHOLD) wholeThing.attribute.held = false;
|
||||
widget.window?.set_cursor(Gdk.Cursor.new_from_name(display, 'grabbing'));
|
||||
// Vertical drag
|
||||
if (initDirVertical == 1 && offset_y > MOVE_THRESHOLD && !expanded) {
|
||||
notifTextPreview.revealChild = false;
|
||||
notifTextExpanded.revealChild = true;
|
||||
expanded = true;
|
||||
notifExpandButton.child.label = 'expand_less';
|
||||
}
|
||||
else if (initDirVertical == 1 && offset_y < -MOVE_THRESHOLD && expanded) {
|
||||
notifTextPreview.revealChild = true;
|
||||
notifTextExpanded.revealChild = false;
|
||||
expanded = false;
|
||||
notifExpandButton.child.label = 'expand_more';
|
||||
}
|
||||
|
||||
}, 'drag-update')
|
||||
.hook(gesture, self => {
|
||||
if (!self.attribute.ready) {
|
||||
wholeThing.revealChild = true;
|
||||
self.attribute.ready = true;
|
||||
return;
|
||||
}
|
||||
const offset_h = gesture.get_offset()[1];
|
||||
|
||||
if (Math.abs(offset_h) > DRAG_CONFIRM_THRESHOLD && offset_h * initDirX > 0) {
|
||||
if (offset_h > 0) {
|
||||
self.setCss(rightAnim1);
|
||||
widget.sensitive = false;
|
||||
}
|
||||
else {
|
||||
self.setCss(leftAnim1);
|
||||
widget.sensitive = false;
|
||||
}
|
||||
Utils.timeout(userOptions.animations.durationSmall, () => {
|
||||
if (wholeThing) wholeThing.revealChild = false;
|
||||
}, wholeThing);
|
||||
Utils.timeout(userOptions.animations.durationSmall * 2, () => {
|
||||
command();
|
||||
if (wholeThing) {
|
||||
wholeThing.destroy();
|
||||
wholeThing = null;
|
||||
}
|
||||
}, wholeThing);
|
||||
}
|
||||
else {
|
||||
self.setCss(`transition: margin 200ms cubic-bezier(0.05, 0.7, 0.1, 1), opacity 200ms cubic-bezier(0.05, 0.7, 0.1, 1);
|
||||
margin-left: ${startMargin}px;
|
||||
margin-right: ${startMargin}px;
|
||||
margin-bottom: unset; margin-top: unset;
|
||||
opacity: 1;`);
|
||||
if (widget.window)
|
||||
widget.window.set_cursor(Gdk.Cursor.new_from_name(display, 'grab'));
|
||||
|
||||
wholeThing.attribute.dragging = false;
|
||||
}
|
||||
initDirX = 0;
|
||||
initDirVertical = -1;
|
||||
}, 'drag-end')
|
||||
,
|
||||
})
|
||||
widget.add(notificationBox);
|
||||
wholeThing.child.children = [widget];
|
||||
if (isPopup) Utils.timeout(popupTimeout, () => {
|
||||
if (wholeThing) {
|
||||
wholeThing.revealChild = false;
|
||||
Utils.timeout(userOptions.animations.durationSmall, () => {
|
||||
if (wholeThing) {
|
||||
wholeThing.destroy();
|
||||
wholeThing = null;
|
||||
}
|
||||
command();
|
||||
}, wholeThing);
|
||||
}
|
||||
})
|
||||
return wholeThing;
|
||||
}
|
||||
|
|
@ -1,306 +0,0 @@
|
|||
import App from 'resource:///com/github/Aylur/ags/app.js';
|
||||
import Audio from 'resource:///com/github/Aylur/ags/service/audio.js';
|
||||
import Widget from 'resource:///com/github/Aylur/ags/widget.js';
|
||||
import * as Utils from 'resource:///com/github/Aylur/ags/utils.js';
|
||||
|
||||
import { MaterialIcon } from './materialicon.js';
|
||||
import Bluetooth from 'resource:///com/github/Aylur/ags/service/bluetooth.js';
|
||||
import Network from 'resource:///com/github/Aylur/ags/service/network.js';
|
||||
import Notifications from 'resource:///com/github/Aylur/ags/service/notifications.js';
|
||||
import { languages } from './statusicons_languages.js';
|
||||
|
||||
// A guessing func to try to support langs not listed in data/languages.js
|
||||
function isLanguageMatch(abbreviation, word) {
|
||||
const lowerAbbreviation = abbreviation.toLowerCase();
|
||||
const lowerWord = word.toLowerCase();
|
||||
let j = 0;
|
||||
for (let i = 0; i < lowerWord.length; i++) {
|
||||
if (lowerWord[i] === lowerAbbreviation[j]) {
|
||||
j++;
|
||||
}
|
||||
if (j === lowerAbbreviation.length) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
export const MicMuteIndicator = () => Widget.Revealer({
|
||||
transition: 'slide_left',
|
||||
transitionDuration: userOptions.animations.durationSmall,
|
||||
revealChild: false,
|
||||
setup: (self) => self.hook(Audio, (self) => {
|
||||
self.revealChild = Audio.microphone?.stream?.isMuted;
|
||||
}),
|
||||
child: MaterialIcon('mic_off', 'norm'),
|
||||
});
|
||||
|
||||
export const NotificationIndicator = (notifCenterName = 'sideright') => {
|
||||
const widget = Widget.Revealer({
|
||||
transition: 'slide_left',
|
||||
transitionDuration: userOptions.animations.durationSmall,
|
||||
revealChild: false,
|
||||
setup: (self) => self
|
||||
.hook(Notifications, (self, id) => {
|
||||
if (!id || Notifications.dnd) return;
|
||||
if (!Notifications.getNotification(id)) return;
|
||||
self.revealChild = true;
|
||||
}, 'notified')
|
||||
.hook(App, (self, currentName, visible) => {
|
||||
if (visible && currentName === notifCenterName) {
|
||||
self.revealChild = false;
|
||||
}
|
||||
})
|
||||
,
|
||||
child: Widget.Box({
|
||||
children: [
|
||||
MaterialIcon('notifications', 'norm'),
|
||||
Widget.Label({
|
||||
className: 'txt-small titlefont',
|
||||
attribute: {
|
||||
unreadCount: 0,
|
||||
update: (self) => self.label = `${self.attribute.unreadCount}`,
|
||||
},
|
||||
setup: (self) => self
|
||||
.hook(Notifications, (self, id) => {
|
||||
if (!id || Notifications.dnd) return;
|
||||
if (!Notifications.getNotification(id)) return;
|
||||
self.attribute.unreadCount++;
|
||||
self.attribute.update(self);
|
||||
}, 'notified')
|
||||
.hook(App, (self, currentName, visible) => {
|
||||
if (visible && currentName === notifCenterName) {
|
||||
self.attribute.unreadCount = 0;
|
||||
self.attribute.update(self);
|
||||
}
|
||||
})
|
||||
,
|
||||
})
|
||||
]
|
||||
})
|
||||
});
|
||||
return widget;
|
||||
}
|
||||
|
||||
export const BluetoothIndicator = () => Widget.Stack({
|
||||
transition: 'slide_up_down',
|
||||
transitionDuration: userOptions.animations.durationSmall,
|
||||
children: {
|
||||
'false': Widget.Label({ className: 'txt-norm icon-material', label: 'bluetooth_disabled' }),
|
||||
'true': Widget.Label({ className: 'txt-norm icon-material', label: 'bluetooth' }),
|
||||
},
|
||||
setup: (self) => self
|
||||
.hook(Bluetooth, stack => {
|
||||
stack.shown = String(Bluetooth.enabled);
|
||||
})
|
||||
,
|
||||
});
|
||||
|
||||
const BluetoothDevices = () => Widget.Box({
|
||||
className: 'spacing-h-5',
|
||||
setup: self => self.hook(Bluetooth, self => {
|
||||
self.children = Bluetooth.connected_devices.map((device) => {
|
||||
return Widget.Box({
|
||||
className: 'bar-bluetooth-device spacing-h-5',
|
||||
vpack: 'center',
|
||||
tooltipText: device.name,
|
||||
children: [
|
||||
Widget.Icon(`${device.iconName}-symbolic`),
|
||||
...(device.batteryPercentage ? [Widget.Label({
|
||||
className: 'txt-smallie',
|
||||
label: `${device.batteryPercentage}`,
|
||||
setup: (self) => {
|
||||
self.hook(device, (self) => {
|
||||
self.label = `${device.batteryPercentage}`;
|
||||
}, 'notify::batteryPercentage')
|
||||
}
|
||||
})] : []),
|
||||
]
|
||||
});
|
||||
});
|
||||
self.visible = Bluetooth.connected_devices.length > 0;
|
||||
}, 'notify::connected-devices'),
|
||||
})
|
||||
|
||||
const NetworkWiredIndicator = () => Widget.Stack({
|
||||
transition: 'slide_up_down',
|
||||
transitionDuration: userOptions.animations.durationSmall,
|
||||
children: {
|
||||
'fallback': SimpleNetworkIndicator(),
|
||||
'unknown': Widget.Label({ className: 'txt-norm icon-material', label: 'wifi_off' }),
|
||||
'disconnected': Widget.Label({ className: 'txt-norm icon-material', label: 'signal_wifi_off' }),
|
||||
'connected': Widget.Label({ className: 'txt-norm icon-material', label: 'lan' }),
|
||||
'connecting': Widget.Label({ className: 'txt-norm icon-material', label: 'settings_ethernet' }),
|
||||
},
|
||||
setup: (self) => self.hook(Network, stack => {
|
||||
if (!Network.wired)
|
||||
return;
|
||||
|
||||
const { internet } = Network.wired;
|
||||
if (['connecting', 'connected'].includes(internet))
|
||||
stack.shown = internet;
|
||||
else if (Network.connectivity !== 'full')
|
||||
stack.shown = 'disconnected';
|
||||
else
|
||||
stack.shown = 'fallback';
|
||||
}),
|
||||
});
|
||||
|
||||
const SimpleNetworkIndicator = () => Widget.Icon({
|
||||
setup: (self) => self.hook(Network, self => {
|
||||
const icon = Network[Network.primary || 'wifi']?.iconName;
|
||||
self.icon = icon || '';
|
||||
self.visible = icon;
|
||||
}),
|
||||
});
|
||||
|
||||
const NetworkWifiIndicator = () => Widget.Stack({
|
||||
transition: 'slide_up_down',
|
||||
transitionDuration: userOptions.animations.durationSmall,
|
||||
children: {
|
||||
'disabled': Widget.Label({ className: 'txt-norm icon-material', label: 'wifi_off' }),
|
||||
'disconnected': Widget.Label({ className: 'txt-norm icon-material', label: 'signal_wifi_off' }),
|
||||
'connecting': Widget.Label({ className: 'txt-norm icon-material', label: 'settings_ethernet' }),
|
||||
'0': Widget.Label({ className: 'txt-norm icon-material', label: 'signal_wifi_0_bar' }),
|
||||
'1': Widget.Label({ className: 'txt-norm icon-material', label: 'network_wifi_1_bar' }),
|
||||
'2': Widget.Label({ className: 'txt-norm icon-material', label: 'network_wifi_2_bar' }),
|
||||
'3': Widget.Label({ className: 'txt-norm icon-material', label: 'network_wifi_3_bar' }),
|
||||
'4': Widget.Label({ className: 'txt-norm icon-material', label: 'signal_wifi_4_bar' }),
|
||||
},
|
||||
setup: (self) => self.hook(Network, (stack) => {
|
||||
if (!Network.wifi) {
|
||||
return;
|
||||
}
|
||||
if (Network.wifi.internet == 'connected') {
|
||||
stack.shown = String(Math.ceil(Network.wifi.strength / 25));
|
||||
}
|
||||
else if (["disconnected", "connecting"].includes(Network.wifi.internet)) {
|
||||
stack.shown = Network.wifi.internet;
|
||||
}
|
||||
}),
|
||||
});
|
||||
|
||||
export const NetworkIndicator = () => Widget.Stack({
|
||||
transition: 'slide_up_down',
|
||||
transitionDuration: userOptions.animations.durationSmall,
|
||||
children: {
|
||||
'fallback': SimpleNetworkIndicator(),
|
||||
'wifi': NetworkWifiIndicator(),
|
||||
'wired': NetworkWiredIndicator(),
|
||||
},
|
||||
setup: (self) => self.hook(Network, stack => {
|
||||
if (!Network.primary) {
|
||||
stack.shown = 'wifi';
|
||||
return;
|
||||
}
|
||||
const primary = Network.primary || 'fallback';
|
||||
if (['wifi', 'wired'].includes(primary))
|
||||
stack.shown = primary;
|
||||
else
|
||||
stack.shown = 'fallback';
|
||||
}),
|
||||
});
|
||||
|
||||
const HyprlandXkbKeyboardLayout = async ({ useFlag } = {}) => {
|
||||
try {
|
||||
const Hyprland = (await import('resource:///com/github/Aylur/ags/service/hyprland.js')).default;
|
||||
var languageStackArray = [];
|
||||
|
||||
const updateCurrentKeyboards = () => {
|
||||
var initLangs = [];
|
||||
JSON.parse(Utils.exec('hyprctl -j devices')).keyboards
|
||||
.forEach(keyboard => {
|
||||
initLangs.push(...keyboard.layout.split(',').map(lang => lang.trim()));
|
||||
});
|
||||
initLangs = [...new Set(initLangs)];
|
||||
languageStackArray = Array.from({ length: initLangs.length }, (_, i) => {
|
||||
const lang = languages.find(lang => lang.layout == initLangs[i]);
|
||||
// if (!lang) return [
|
||||
// initLangs[i],
|
||||
// Widget.Label({ label: initLangs[i] })
|
||||
// ];
|
||||
// return [
|
||||
// lang.layout,
|
||||
// Widget.Label({ label: (useFlag ? lang.flag : lang.layout) })
|
||||
// ];
|
||||
// Object
|
||||
if (!lang) return {
|
||||
[initLangs[i]]: Widget.Label({ label: initLangs[i] })
|
||||
};
|
||||
return {
|
||||
[lang.layout]: Widget.Label({ label: (useFlag ? lang.flag : lang.layout) })
|
||||
};
|
||||
});
|
||||
};
|
||||
updateCurrentKeyboards();
|
||||
const widgetRevealer = Widget.Revealer({
|
||||
transition: 'slide_left',
|
||||
transitionDuration: userOptions.animations.durationSmall,
|
||||
revealChild: languageStackArray.length > 1,
|
||||
});
|
||||
const widgetKids = {
|
||||
...languageStackArray.reduce((obj, lang) => {
|
||||
return { ...obj, ...lang };
|
||||
}, {}),
|
||||
'undef': Widget.Label({ label: '?' }),
|
||||
}
|
||||
const widgetContent = Widget.Stack({
|
||||
transition: 'slide_up_down',
|
||||
transitionDuration: userOptions.animations.durationSmall,
|
||||
children: widgetKids,
|
||||
setup: (self) => self.hook(Hyprland, (stack, kbName, layoutName) => {
|
||||
if (!kbName) {
|
||||
return;
|
||||
}
|
||||
var lang = languages.find(lang => layoutName.includes(lang.name));
|
||||
if (lang) {
|
||||
widgetContent.shown = lang.layout;
|
||||
}
|
||||
else { // Attempt to support langs not listed
|
||||
lang = languageStackArray.find(lang => isLanguageMatch(lang[0], layoutName));
|
||||
if (!lang) stack.shown = 'undef';
|
||||
else stack.shown = lang[0];
|
||||
}
|
||||
}, 'keyboard-layout'),
|
||||
});
|
||||
widgetRevealer.child = widgetContent;
|
||||
return widgetRevealer;
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
const OptionalKeyboardLayout = async () => {
|
||||
try {
|
||||
return await HyprlandXkbKeyboardLayout({ useFlag: userOptions.appearance.keyboardUseFlag });
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
const createKeyboardLayoutInstances = async () => {
|
||||
const Hyprland = (await import('resource:///com/github/Aylur/ags/service/hyprland.js')).default;
|
||||
const monitorsCount = Hyprland.monitors.length
|
||||
const instances = await Promise.all(
|
||||
Array.from({ length: monitorsCount }, () => OptionalKeyboardLayout())
|
||||
);
|
||||
|
||||
return instances;
|
||||
};
|
||||
const optionalKeyboardLayoutInstances = await createKeyboardLayoutInstances()
|
||||
|
||||
export const StatusIcons = (props = {}, monitor = 0) => Widget.Box({
|
||||
...props,
|
||||
child: Widget.Box({
|
||||
className: 'spacing-h-15',
|
||||
children: [
|
||||
MicMuteIndicator(),
|
||||
optionalKeyboardLayoutInstances[monitor],
|
||||
NotificationIndicator(),
|
||||
NetworkIndicator(),
|
||||
Widget.Box({
|
||||
className: 'spacing-h-5',
|
||||
children: [BluetoothIndicator(), BluetoothDevices()]
|
||||
})
|
||||
]
|
||||
})
|
||||
});
|
||||
|
|
@ -1,62 +0,0 @@
|
|||
// For keyboard layout in statusicons.js
|
||||
// This list is not exhaustive. It just includes known/possible languages of users of my dotfiles
|
||||
// Add your language here if you use multi-lang xkb input. Else, ignore
|
||||
// Note that something like "French (Canada)" should go before "French"
|
||||
// and "English (US)" should go before "English"
|
||||
export const languages = [
|
||||
{
|
||||
layout: 'us',
|
||||
name: 'English (US)',
|
||||
flag: '🇺🇸'
|
||||
},
|
||||
{
|
||||
layout: 'ru',
|
||||
name: 'Russian',
|
||||
flag: '🇷🇺',
|
||||
},
|
||||
{
|
||||
layout: 'pl',
|
||||
name: 'Polish',
|
||||
flag: '🇷🇵🇵🇱',
|
||||
},
|
||||
{
|
||||
layout: 'ro',
|
||||
name: 'Romanian',
|
||||
flag: '🇷🇴',
|
||||
},
|
||||
{
|
||||
layout: 'ca',
|
||||
name: 'French (Canada)',
|
||||
flag: '🇫🇷',
|
||||
},
|
||||
{
|
||||
layout: 'fr',
|
||||
name: 'French',
|
||||
flag: '🇫🇷',
|
||||
},
|
||||
{
|
||||
layout: 'tr',
|
||||
name: 'Turkish',
|
||||
flag: '🇹🇷',
|
||||
},
|
||||
{
|
||||
layout: 'jp',
|
||||
name: 'Japanese',
|
||||
flag: '🇯🇵',
|
||||
},
|
||||
{
|
||||
layout: 'cn',
|
||||
name: 'Chinese',
|
||||
flag: '🇨🇳',
|
||||
},
|
||||
{
|
||||
layout: 'vn',
|
||||
name: 'Vietnamese',
|
||||
flag: '🇻🇳',
|
||||
},
|
||||
{
|
||||
layout: 'undef',
|
||||
name: 'Undefined',
|
||||
flag: '🧐',
|
||||
},
|
||||
]
|
||||
|
|
@ -1,279 +0,0 @@
|
|||
import Variable from 'resource:///com/github/Aylur/ags/variable.js';
|
||||
import Widget from 'resource:///com/github/Aylur/ags/widget.js';
|
||||
const { Box, Button, EventBox, Label, Overlay, Stack } = Widget;
|
||||
import { MaterialIcon } from './materialicon.js';
|
||||
import { NavigationIndicator } from './cairo_navigationindicator.js';
|
||||
import { setupCursorHover } from '../.widgetutils/cursorhover.js';
|
||||
import { DoubleRevealer } from '../.widgethacks/advancedrevealers.js';
|
||||
|
||||
export const TabContainer = ({ icons, names, children, className = '', setup = () => { }, ...rest }) => {
|
||||
const shownIndex = Variable(0);
|
||||
let previousShownIndex = 0;
|
||||
const count = Math.min(icons.length, names.length, children.length);
|
||||
const tabs = Box({
|
||||
homogeneous: true,
|
||||
children: Array.from({ length: count }, (_, i) => Button({ // Tab button
|
||||
className: 'tab-btn',
|
||||
onClicked: () => shownIndex.value = i,
|
||||
setup: setupCursorHover,
|
||||
child: Box({
|
||||
hpack: 'center',
|
||||
vpack: 'center',
|
||||
className: 'spacing-h-5 txt-small',
|
||||
children: [
|
||||
MaterialIcon(icons[i], 'norm'),
|
||||
Label({
|
||||
label: names[i],
|
||||
})
|
||||
]
|
||||
})
|
||||
})),
|
||||
setup: (self) => self.hook(shownIndex, (self) => {
|
||||
self.children[previousShownIndex].toggleClassName('tab-btn-active', false);
|
||||
self.children[shownIndex.value].toggleClassName('tab-btn-active', true);
|
||||
previousShownIndex = shownIndex.value;
|
||||
}),
|
||||
});
|
||||
const tabIndicatorLine = Box({
|
||||
vertical: true,
|
||||
homogeneous: true,
|
||||
setup: (self) => self.hook(shownIndex, (self) => {
|
||||
self.children[0].css = `font-size: ${shownIndex.value}px;`;
|
||||
}),
|
||||
children: [NavigationIndicator({
|
||||
className: 'tab-indicator',
|
||||
count: count,
|
||||
css: `font-size: ${shownIndex.value}px;`,
|
||||
})],
|
||||
});
|
||||
const tabSection = Box({
|
||||
homogeneous: true,
|
||||
children: [EventBox({
|
||||
onScrollUp: () => mainBox.prevTab(),
|
||||
onScrollDown: () => mainBox.nextTab(),
|
||||
child: Box({
|
||||
vertical: true,
|
||||
children: [
|
||||
tabs,
|
||||
tabIndicatorLine
|
||||
]
|
||||
})
|
||||
})]
|
||||
});
|
||||
const contentStack = Stack({
|
||||
transition: 'slide_left_right',
|
||||
children: children.reduce((acc, currentValue, index) => {
|
||||
acc[index] = currentValue;
|
||||
return acc;
|
||||
}, {}),
|
||||
setup: (self) => self.hook(shownIndex, (self) => {
|
||||
self.shown = `${shownIndex.value}`;
|
||||
}),
|
||||
});
|
||||
const mainBox = Box({
|
||||
attribute: {
|
||||
children: children,
|
||||
shown: shownIndex,
|
||||
names: names,
|
||||
},
|
||||
vertical: true,
|
||||
className: `spacing-v-5 ${className}`,
|
||||
setup: (self) => {
|
||||
self.pack_start(tabSection, false, false, 0);
|
||||
self.pack_end(contentStack, true, true, 0);
|
||||
setup(self);
|
||||
},
|
||||
...rest,
|
||||
});
|
||||
mainBox.nextTab = () => shownIndex.value = Math.min(shownIndex.value + 1, count - 1);
|
||||
mainBox.prevTab = () => shownIndex.value = Math.max(shownIndex.value - 1, 0);
|
||||
mainBox.cycleTab = () => shownIndex.value = (shownIndex.value + 1) % count;
|
||||
|
||||
return mainBox;
|
||||
}
|
||||
|
||||
|
||||
export const IconTabContainer = ({
|
||||
iconWidgets, names, children, className = '',
|
||||
setup = () => { }, onChange = () => { },
|
||||
tabsHpack = 'center', tabSwitcherClassName = '',
|
||||
...rest
|
||||
}) => {
|
||||
const shownIndex = Variable(0);
|
||||
let previousShownIndex = 0;
|
||||
const count = Math.min(iconWidgets.length, names.length, children.length);
|
||||
const tabs = Box({
|
||||
hpack: tabsHpack,
|
||||
className: `spacing-h-5 ${tabSwitcherClassName}`,
|
||||
children: iconWidgets.map((icon, i) => Button({
|
||||
className: 'tab-icon',
|
||||
tooltipText: names[i],
|
||||
child: icon,
|
||||
setup: setupCursorHover,
|
||||
onClicked: () => shownIndex.value = i,
|
||||
})),
|
||||
setup: (self) => self.hook(shownIndex, (self) => {
|
||||
self.children[previousShownIndex].toggleClassName('tab-icon-active', false);
|
||||
self.children[shownIndex.value].toggleClassName('tab-icon-active', true);
|
||||
previousShownIndex = shownIndex.value;
|
||||
}),
|
||||
});
|
||||
const tabSection = Box({
|
||||
homogeneous: true,
|
||||
children: [EventBox({
|
||||
onScrollUp: () => mainBox.prevTab(),
|
||||
onScrollDown: () => mainBox.nextTab(),
|
||||
child: Box({
|
||||
vertical: true,
|
||||
hexpand: true,
|
||||
children: [
|
||||
tabs,
|
||||
]
|
||||
})
|
||||
})]
|
||||
});
|
||||
const contentStack = Stack({
|
||||
transition: 'slide_left_right',
|
||||
children: children.reduce((acc, currentValue, index) => {
|
||||
acc[index] = currentValue;
|
||||
return acc;
|
||||
}, {}),
|
||||
setup: (self) => self.hook(shownIndex, (self) => {
|
||||
self.shown = `${shownIndex.value}`;
|
||||
}),
|
||||
});
|
||||
const mainBox = Box({
|
||||
attribute: {
|
||||
children: children,
|
||||
shown: shownIndex,
|
||||
names: names,
|
||||
},
|
||||
vertical: true,
|
||||
className: `spacing-v-5 ${className}`,
|
||||
setup: (self) => {
|
||||
self.pack_start(tabSection, false, false, 0);
|
||||
self.pack_end(contentStack, true, true, 0);
|
||||
setup(self);
|
||||
self.hook(shownIndex, (self) => onChange(self, shownIndex.value));
|
||||
},
|
||||
...rest,
|
||||
});
|
||||
mainBox.nextTab = () => shownIndex.value = Math.min(shownIndex.value + 1, count - 1);
|
||||
mainBox.prevTab = () => shownIndex.value = Math.max(shownIndex.value - 1, 0);
|
||||
mainBox.cycleTab = () => shownIndex.value = (shownIndex.value + 1) % count;
|
||||
mainBox.shown = shownIndex;
|
||||
|
||||
return mainBox;
|
||||
}
|
||||
|
||||
export const ExpandingIconTabContainer = ({
|
||||
icons, names, children, className = '',
|
||||
setup = () => { }, onChange = () => { },
|
||||
tabsHpack = 'center', tabSwitcherClassName = '',
|
||||
transitionDuration = userOptions.animations.durationLarge,
|
||||
...rest
|
||||
}) => {
|
||||
const shownIndex = Variable(0);
|
||||
let previousShownIndex = 0;
|
||||
const count = Math.min(icons.length, names.length, children.length);
|
||||
const tabs = Box({
|
||||
hpack: tabsHpack,
|
||||
className: `spacing-h-5 ${tabSwitcherClassName}`,
|
||||
children: icons.map((icon, i) => {
|
||||
const tabIcon = MaterialIcon(icon, 'norm', { hexpand: true });
|
||||
const tabName = DoubleRevealer({
|
||||
transition1: 'slide_right',
|
||||
transition2: 'crossfade',
|
||||
duration1: 0,
|
||||
duration2: 0,
|
||||
// duration1: userOptions.animations.durationSmall,
|
||||
// duration2: userOptions.animations.durationSmall,
|
||||
child: Label({
|
||||
className: 'margin-left-5 txt-small',
|
||||
label: names[i],
|
||||
}),
|
||||
revealChild: i === shownIndex.value,
|
||||
})
|
||||
const button = Button({
|
||||
className: 'tab-icon-expandable',
|
||||
tooltipText: names[i],
|
||||
child: Box({
|
||||
homogeneous: true,
|
||||
children: [Box({
|
||||
hpack: 'center',
|
||||
children: [
|
||||
tabIcon,
|
||||
tabName,
|
||||
]
|
||||
})],
|
||||
}),
|
||||
setup: setupCursorHover,
|
||||
onClicked: () => shownIndex.value = i,
|
||||
});
|
||||
button.toggleFocus = (value) => {
|
||||
tabIcon.hexpand = !value;
|
||||
button.toggleClassName('tab-icon-expandable-active', value);
|
||||
tabName.toggleRevealChild(value);
|
||||
}
|
||||
return button;
|
||||
}),
|
||||
setup: (self) => self.hook(shownIndex, (self) => {
|
||||
self.children[previousShownIndex].toggleFocus(false);
|
||||
self.children[shownIndex.value].toggleFocus(true);
|
||||
previousShownIndex = shownIndex.value;
|
||||
}),
|
||||
});
|
||||
const tabSection = Box({
|
||||
homogeneous: true,
|
||||
children: [EventBox({
|
||||
onScrollUp: () => mainBox.prevTab(),
|
||||
onScrollDown: () => mainBox.nextTab(),
|
||||
child: Box({
|
||||
vertical: true,
|
||||
hexpand: true,
|
||||
children: [
|
||||
tabs,
|
||||
]
|
||||
})
|
||||
})]
|
||||
});
|
||||
const contentStack = Stack({
|
||||
transition: 'slide_left_right',
|
||||
transitionDuration: transitionDuration,
|
||||
children: children.reduce((acc, currentValue, index) => {
|
||||
acc[index] = currentValue;
|
||||
return acc;
|
||||
}, {}),
|
||||
setup: (self) => self.hook(shownIndex, (self) => {
|
||||
self.shown = `${shownIndex.value}`;
|
||||
}),
|
||||
});
|
||||
const mainBox = Box({
|
||||
attribute: {
|
||||
children: children,
|
||||
shown: shownIndex,
|
||||
names: names,
|
||||
},
|
||||
vertical: true,
|
||||
className: `spacing-v-5 ${className}`,
|
||||
setup: (self) => {
|
||||
self.pack_start(tabSection, false, false, 0);
|
||||
self.pack_end(contentStack, true, true, 0);
|
||||
setup(self);
|
||||
self.hook(shownIndex, (self) => onChange(self, shownIndex.value));
|
||||
},
|
||||
...rest,
|
||||
});
|
||||
mainBox.nextTab = () => shownIndex.value = Math.min(shownIndex.value + 1, count - 1);
|
||||
mainBox.prevTab = () => shownIndex.value = Math.max(shownIndex.value - 1, 0);
|
||||
mainBox.cycleTab = () => shownIndex.value = (shownIndex.value + 1) % count;
|
||||
mainBox.focusName = (name) => {
|
||||
const focusIndex = names.indexOf(name);
|
||||
if (focusIndex !== -1) {
|
||||
shownIndex.value = focusIndex;
|
||||
}
|
||||
}
|
||||
mainBox.shown = shownIndex;
|
||||
|
||||
return mainBox;
|
||||
}
|
||||
|
|
@ -1,262 +0,0 @@
|
|||
import GLib from 'gi://GLib';
|
||||
import * as Utils from 'resource:///com/github/Aylur/ags/utils.js'
|
||||
import userOverrides from '../../user_options.js';
|
||||
|
||||
// Default options.
|
||||
// Add overrides in ~/.config/ags/user_options.js
|
||||
let configOptions = {
|
||||
// General stuff
|
||||
'ai': {
|
||||
'defaultGPTProvider': "openai",
|
||||
'defaultTemperature': 0.9,
|
||||
'enhancements': true,
|
||||
'useHistory': true,
|
||||
'safety': true,
|
||||
'writingCursor': " ...", // Warning: Using weird characters can mess up Markdown rendering
|
||||
'proxyUrl': null, // Can be "socks5://127.0.0.1:9050" or "http://127.0.0.1:8080" for example. Leave it blank if you don't need it.
|
||||
},
|
||||
'animations': {
|
||||
'choreographyDelay': 35,
|
||||
'durationSmall': 110,
|
||||
'durationLarge': 180,
|
||||
},
|
||||
'appearance': {
|
||||
'autoDarkMode': { // Turns on dark mode in certain hours. Time in 24h format
|
||||
'enabled': false,
|
||||
'from': "18:10",
|
||||
'to': "6:10",
|
||||
},
|
||||
'keyboardUseFlag': false, // Use flag emoji instead of abbreviation letters
|
||||
'layerSmoke': false,
|
||||
'layerSmokeStrength': 0.2,
|
||||
'barRoundCorners': 1, // 0: No, 1: Yes
|
||||
'fakeScreenRounding': 1, // 0: None | 1: Always | 2: When not fullscreen
|
||||
},
|
||||
'apps': {
|
||||
'bluetooth': "blueberry",
|
||||
'imageViewer': "loupe",
|
||||
'network': "XDG_CURRENT_DESKTOP=\"gnome\" gnome-control-center wifi",
|
||||
'settings': "XDG_CURRENT_DESKTOP=\"gnome\" gnome-control-center",
|
||||
'taskManager': "gnome-usage",
|
||||
'terminal': "foot", // This is only for shell actions
|
||||
},
|
||||
'battery': {
|
||||
'low': 20,
|
||||
'critical': 10,
|
||||
'warnLevels': [20, 15, 5],
|
||||
'warnTitles': ["Low battery", "Very low battery", 'Critical Battery'],
|
||||
'warnMessages': ["Plug in the charger", "You there?", 'PLUG THE CHARGER ALREADY'],
|
||||
'suspendThreshold': 3,
|
||||
},
|
||||
'brightness': {
|
||||
// Object of controller names for each monitor, either "brightnessctl" or "ddcutil" or "auto"
|
||||
// 'default' one will be used if unspecified
|
||||
// Examples
|
||||
// 'eDP-1': "brightnessctl",
|
||||
// 'DP-1': "ddcutil",
|
||||
'controllers': {
|
||||
'default': "auto",
|
||||
},
|
||||
},
|
||||
'cheatsheet': {
|
||||
'keybinds': {
|
||||
'configPath': "" // Path to hyprland keybind config file. Leave empty for default (~/.config/hypr/hyprland/keybinds.conf)
|
||||
}
|
||||
},
|
||||
'gaming': {
|
||||
'crosshair': {
|
||||
'size': 20,
|
||||
'color': 'rgba(113,227,32,0.9)',
|
||||
},
|
||||
},
|
||||
'i18n': {
|
||||
'langCode': "",//Customize the locale, such as zh_CN,Optional value references "~/.config/ags/i18n/locales/"
|
||||
'extraLogs': false
|
||||
},
|
||||
'monitors': {
|
||||
'scaleMethod': "division", // Either "division" [default] or "gdk"
|
||||
},
|
||||
'music': {
|
||||
'preferredPlayer': "plasma-browser-integration",
|
||||
},
|
||||
'onScreenKeyboard': {
|
||||
'layout': "qwerty_full", // See modules/onscreenkeyboard/onscreenkeyboard.js for available layouts
|
||||
},
|
||||
'overview': {
|
||||
'scale': 0.18, // Relative to screen size
|
||||
'numOfRows': 2,
|
||||
'numOfCols': 5,
|
||||
'wsNumScale': 0.09,
|
||||
'wsNumMarginScale': 0.07,
|
||||
},
|
||||
'sidebar': {
|
||||
'ai': {
|
||||
'extraGptModels': {
|
||||
'oxygen3': {
|
||||
'name': 'Oxygen (GPT-3.5)',
|
||||
'logo_name': 'ai-oxygen-symbolic',
|
||||
'description': 'An API from Tornado Softwares\nPricing: Free: 100/day\nRequires you to join their Discord for a key',
|
||||
'base_url': 'https://app.oxyapi.uk/v1/chat/completions',
|
||||
'key_get_url': 'https://discord.com/invite/kM6MaCqGKA',
|
||||
'key_file': 'oxygen_key.txt',
|
||||
'model': 'gpt-3.5-turbo',
|
||||
},
|
||||
}
|
||||
},
|
||||
'image': {
|
||||
'columns': 2,
|
||||
'batchCount': 20,
|
||||
'allowNsfw': false,
|
||||
'saveInFolderByTags': false,
|
||||
},
|
||||
'pages': {
|
||||
'order': ["apis", "tools"],
|
||||
'apis': {
|
||||
'order': ["gemini", "gpt", "waifu", "booru"],
|
||||
}
|
||||
},
|
||||
},
|
||||
'search': {
|
||||
'enableFeatures': {
|
||||
'actions': true,
|
||||
'commands': true,
|
||||
'mathResults': true,
|
||||
'directorySearch': true,
|
||||
'aiSearch': true,
|
||||
'webSearch': true,
|
||||
},
|
||||
'engineBaseUrl': "https://www.google.com/search?q=",
|
||||
'excludedSites': ["quora.com"],
|
||||
},
|
||||
'time': {
|
||||
// See https://docs.gtk.org/glib/method.DateTime.format.html
|
||||
// Here's the 12h format: "%I:%M%P"
|
||||
// For seconds, add "%S" and set interval to 1000
|
||||
'format': "%H:%M",
|
||||
'interval': 5000,
|
||||
'dateFormatLong': "%A, %d/%m", // On bar
|
||||
'dateInterval': 5000,
|
||||
'dateFormat': "%d/%m", // On notif time
|
||||
},
|
||||
'weather': {
|
||||
'city': "",
|
||||
'preferredUnit': "C", // Either C or F
|
||||
},
|
||||
'workspaces': {
|
||||
'shown': 10,
|
||||
},
|
||||
'dock': {
|
||||
'enabled': false,
|
||||
'hiddenThickness': 5,
|
||||
'pinnedApps': ['firefox', 'org.gnome.Nautilus'],
|
||||
'layer': 'top',
|
||||
'monitorExclusivity': true, // Dock will move to other monitor along with focus if enabled
|
||||
'searchPinnedAppIcons': false, // Try to search for the correct icon if the app class isn't an icon name
|
||||
'trigger': ['client-added', 'client-removed'], // client_added, client_move, workspace_active, client_active
|
||||
// Automatically hide dock after `interval` ms since trigger
|
||||
'autoHide': [
|
||||
{
|
||||
'trigger': 'client-added',
|
||||
'interval': 500,
|
||||
},
|
||||
{
|
||||
'trigger': 'client-removed',
|
||||
'interval': 500,
|
||||
},
|
||||
],
|
||||
},
|
||||
// Longer stuff
|
||||
'icons': {
|
||||
// Find the window's icon by its class with levenshteinDistance
|
||||
// The file names are processed at startup, so if there
|
||||
// are too many files in the search path it'll affect performance
|
||||
// Example: ['/usr/share/icons/Tela-nord/scalable/apps']
|
||||
'searchPaths': [''],
|
||||
'symbolicIconTheme': {
|
||||
"dark": "Adwaita",
|
||||
"light": "Adwaita",
|
||||
},
|
||||
substitutions: {
|
||||
'code-url-handler': "visual-studio-code",
|
||||
'Code': "visual-studio-code",
|
||||
'GitHub Desktop': "github-desktop",
|
||||
'Minecraft* 1.20.1': "minecraft",
|
||||
'gnome-tweaks': "org.gnome.tweaks",
|
||||
'pavucontrol-qt': "pavucontrol",
|
||||
'wps': "wps-office2019-kprometheus",
|
||||
'wpsoffice': "wps-office2019-kprometheus",
|
||||
'': "image-missing",
|
||||
},
|
||||
regexSubstitutions: [
|
||||
{
|
||||
regex: /^steam_app_(\d+)$/,
|
||||
replace: "steam_icon_$1",
|
||||
}
|
||||
]
|
||||
},
|
||||
'keybinds': {
|
||||
// Format: Mod1+Mod2+key. CaSe SeNsItIvE!
|
||||
// Modifiers: Shift Ctrl Alt Hyper Meta
|
||||
// See https://docs.gtk.org/gdk3/index.html#constants for the other keys (they are listed as KEY_key)
|
||||
'overview': {
|
||||
'altMoveLeft': "Ctrl+b",
|
||||
'altMoveRight': "Ctrl+f",
|
||||
'deleteToEnd': "Ctrl+k",
|
||||
},
|
||||
'sidebar': {
|
||||
'apis': {
|
||||
'nextTab': "Page_Down",
|
||||
'prevTab': "Page_Up",
|
||||
},
|
||||
'options': { // Right sidebar
|
||||
'nextTab': "Page_Down",
|
||||
'prevTab': "Page_Up",
|
||||
},
|
||||
'pin': "Ctrl+p",
|
||||
'cycleTab': "Ctrl+Tab",
|
||||
'nextTab': "Ctrl+Page_Down",
|
||||
'prevTab': "Ctrl+Page_Up",
|
||||
},
|
||||
'cheatsheet': {
|
||||
'keybinds': {
|
||||
'nextTab': "Page_Down",
|
||||
'prevTab': "Page_Up",
|
||||
},
|
||||
'nextTab': "Ctrl+Page_Down",
|
||||
'prevTab': "Ctrl+Page_Up",
|
||||
'cycleTab': "Ctrl+Tab",
|
||||
}
|
||||
},
|
||||
'bar': {
|
||||
// Array of bar modes for each monitor. Hit Ctrl+Alt+Slash to cycle.
|
||||
// Modes: "normal", "focus" (workspace indicator only), "nothing"
|
||||
// Example for four monitors: ["normal", "focus", "normal", "nothing"]
|
||||
'modes': ["normal"]
|
||||
},
|
||||
}
|
||||
|
||||
// Override defaults with user's options
|
||||
let optionsOkay = true;
|
||||
function overrideConfigRecursive(userOverrides, configOptions = {}, check = true) {
|
||||
for (const [key, value] of Object.entries(userOverrides)) {
|
||||
if (configOptions[key] === undefined && check) {
|
||||
optionsOkay = false;
|
||||
}
|
||||
else if (typeof value === 'object' && !(value instanceof Array)) {
|
||||
if (key === "substitutions" || key === "regexSubstitutions" || key === "extraGptModels") {
|
||||
overrideConfigRecursive(value, configOptions[key], false);
|
||||
} else overrideConfigRecursive(value, configOptions[key]);
|
||||
} else {
|
||||
configOptions[key] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
overrideConfigRecursive(userOverrides, configOptions);
|
||||
if (!optionsOkay) Utils.timeout(2000, () => Utils.execAsync(['notify-send',
|
||||
'Update your user options',
|
||||
'One or more config options don\'t exist',
|
||||
'-a', 'ags',
|
||||
]).catch(print))
|
||||
|
||||
globalThis['userOptions'] = configOptions;
|
||||
export default configOptions;
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
const { Gio, GLib, Gtk } = imports.gi;
|
||||
|
||||
export function fileExists(filePath) {
|
||||
let file = Gio.File.new_for_path(filePath);
|
||||
return file.query_exists(null);
|
||||
}
|
||||
|
||||
export function expandTilde(path) {
|
||||
if (path.startsWith('~')) {
|
||||
return GLib.get_home_dir() + path.slice(1);
|
||||
} else {
|
||||
return path;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,28 +0,0 @@
|
|||
const { Gtk } = imports.gi;
|
||||
|
||||
export function iconExists(iconName) {
|
||||
let iconTheme = Gtk.IconTheme.get_default();
|
||||
return iconTheme.has_icon(iconName);
|
||||
}
|
||||
|
||||
export function substitute(str) {
|
||||
// Normal substitutions
|
||||
if (userOptions.icons.substitutions[str])
|
||||
return userOptions.icons.substitutions[str];
|
||||
|
||||
// Regex substitutions
|
||||
for (let i = 0; i < userOptions.icons.regexSubstitutions.length; i++) {
|
||||
const substitution = userOptions.icons.regexSubstitutions[i];
|
||||
const replacedName = str.replace(
|
||||
substitution.regex,
|
||||
substitution.replace,
|
||||
);
|
||||
if (replacedName != str) return replacedName;
|
||||
}
|
||||
|
||||
// Guess: convert to kebab case
|
||||
if (!iconExists(str)) str = str.toLowerCase().replace(/\s+/g, "-");
|
||||
|
||||
// Original string
|
||||
return str;
|
||||
}
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
|
||||
export function clamp(x, min, max) {
|
||||
return Math.min(Math.max(x, min), max);
|
||||
}
|
||||
|
|
@ -1,78 +0,0 @@
|
|||
// Converts from Markdown to Pango. This does not support code blocks.
|
||||
// For illogical-impulse, code blocks are treated separately, in their own GtkSourceView widgets.
|
||||
// Partly inherited from https://github.com/ubunatic/md2pango
|
||||
|
||||
const monospaceFonts = 'JetBrains Mono NF, JetBrains Mono Nerd Font, JetBrains Mono NL, SpaceMono NF, SpaceMono Nerd Font, monospace';
|
||||
|
||||
const replacements = {
|
||||
'indents': [
|
||||
{ name: 'BULLET', re: /^(\s*)([\*\-]\s)(.*)(\s*)$/, sub: ' $1- $3' },
|
||||
{ name: 'NUMBERING', re: /^(\s*[0-9]+\.\s)(.*)(\s*)$/, sub: ' $1 $2' },
|
||||
],
|
||||
'escapes': [
|
||||
{ name: 'COMMENT', re: /<!--[\s\S]*?-->/, sub: '' },
|
||||
{ name: 'AMPERSTAND', re: /&/g, sub: '&' },
|
||||
{ name: 'LESSTHAN', re: /</g, sub: '<' },
|
||||
{ name: 'GREATERTHAN', re: />/g, sub: '>' },
|
||||
],
|
||||
'sections': [
|
||||
{ name: 'H1', re: /^(#\s+)(.*)(\s*)$/, sub: '<span font_weight="bold" size="170%">$2</span>' },
|
||||
{ name: 'H2', re: /^(##\s+)(.*)(\s*)$/, sub: '<span font_weight="bold" size="150%">$2</span>' },
|
||||
{ name: 'H3', re: /^(###\s+)(.*)(\s*)$/, sub: '<span font_weight="bold" size="125%">$2</span>' },
|
||||
{ name: 'H4', re: /^(####\s+)(.*)(\s*)$/, sub: '<span font_weight="bold" size="100%">$2</span>' },
|
||||
{ name: 'H5', re: /^(#####\s+)(.*)(\s*)$/, sub: '<span font_weight="bold" size="90%">$2</span>' },
|
||||
],
|
||||
'styles': [
|
||||
{ name: 'BOLD', re: /(\*\*)(\S[\s\S]*?\S)(\*\*)/g, sub: "<b>$2</b>" },
|
||||
{ name: 'UND', re: /(__)(\S[\s\S]*?\S)(__)/g, sub: "<u>$2</u>" },
|
||||
{ name: 'EMPH', re: /\*(\S.*?\S)\*/g, sub: "<i>$1</i>" },
|
||||
// { name: 'EMPH', re: /_(\S.*?\S)_/g, sub: "<i>$1</i>" },
|
||||
{ name: 'HEXCOLOR', re: /#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})/g, sub: '<span bgcolor="#$1" fgcolor="#000000" font_family="' + monospaceFonts + '">#$1</span>' },
|
||||
{ name: 'INLCODE', re: /(`)([^`]*)(`)/g, sub: '<span font_weight="bold" font_family="' + monospaceFonts + '">$2</span>' },
|
||||
// { name: 'UND', re: /(__|\*\*)(\S[\s\S]*?\S)(__|\*\*)/g, sub: "<u>$2</u>" },
|
||||
],
|
||||
}
|
||||
|
||||
const replaceCategory = (text, replaces) => {
|
||||
for (const type of replaces) {
|
||||
text = text.replace(type.re, type.sub);
|
||||
}
|
||||
return text;
|
||||
}
|
||||
|
||||
// Main function
|
||||
|
||||
export default (text) => {
|
||||
let lines = text.split('\n')
|
||||
let output = [];
|
||||
// Replace
|
||||
for (const line of lines) {
|
||||
let result = line;
|
||||
result = replaceCategory(result, replacements.indents);
|
||||
result = replaceCategory(result, replacements.escapes);
|
||||
result = replaceCategory(result, replacements.sections);
|
||||
result = replaceCategory(result, replacements.styles);
|
||||
output.push(result)
|
||||
}
|
||||
// Remove trailing whitespaces
|
||||
output = output.map(line => line.replace(/ +$/, ''))
|
||||
return output.join('\n');
|
||||
}
|
||||
|
||||
export const markdownTest = `## Inline formatting
|
||||
- **Bold** *Italics* __Underline__
|
||||
- \`Monospace text\` 🤓
|
||||
- Colors
|
||||
- Nvidia green #7ABB08
|
||||
- Soundcloud orange #FF5500
|
||||
## Code block
|
||||
\`\`\`cpp
|
||||
#include <bits/stdc++.h>
|
||||
const std::string GREETING="UwU";
|
||||
int main() { std::cout << GREETING; }
|
||||
\`\`\`
|
||||
## LaTeX
|
||||
\`\`\`latex
|
||||
\\frac{d}{dx} \\left( \\frac{x-438}{x^2+23x-7} \\right) = \\frac{-x^2 + 869}{(x^2+23x-7)^2} \\\\ → \\\\ cos(2x) = 2cos^2(x) - 1 = 1 - 2sin^2(x) = cos^2(x) - sin^2(x)
|
||||
\`\`\`
|
||||
`;
|
||||
|
|
@ -1,61 +0,0 @@
|
|||
const { GLib } = imports.gi;
|
||||
import Variable from 'resource:///com/github/Aylur/ags/variable.js';
|
||||
import * as Utils from 'resource:///com/github/Aylur/ags/utils.js';
|
||||
const { execAsync, exec } = Utils;
|
||||
|
||||
export const distroID = exec(`bash -c 'cat /etc/os-release | grep "^ID=" | cut -d "=" -f 2 | sed "s/\\"//g"'`).trim();
|
||||
export const isDebianDistro = (distroID == 'linuxmint' || distroID == 'ubuntu' || distroID == 'debian' || distroID == 'zorin' || distroID == 'popos' || distroID == 'raspbian' || distroID == 'kali');
|
||||
export const isArchDistro = (distroID == 'arch' || distroID == 'endeavouros' || distroID == 'cachyos');
|
||||
export const hasFlatpak = !!exec(`bash -c 'command -v flatpak'`);
|
||||
|
||||
const LIGHTDARK_FILE_LOCATION = `${GLib.get_user_state_dir()}/ags/user/colormode.txt`;
|
||||
export const darkMode = Variable(!(Utils.readFile(LIGHTDARK_FILE_LOCATION).split('\n')[0].trim() == 'light'));
|
||||
darkMode.connect('changed', ({ value }) => {
|
||||
let lightdark = value ? "dark" : "light";
|
||||
execAsync([`bash`, `-c`, `mkdir -p ${GLib.get_user_state_dir()}/ags/user && sed -i "1s/.*/${lightdark}/" ${GLib.get_user_state_dir()}/ags/user/colormode.txt`])
|
||||
.then(execAsync(['bash', '-c', `${App.configDir}/scripts/color_generation/switchcolor.sh`]))
|
||||
.then(execAsync(['bash', '-c', `command -v darkman && darkman set ${lightdark}`])) // Optional darkman integration
|
||||
.catch(print);
|
||||
});
|
||||
globalThis['darkMode'] = darkMode;
|
||||
export const hasPlasmaIntegration = !!Utils.exec('bash -c "command -v plasma-browser-integration-host"');
|
||||
|
||||
export const getDistroIcon = () => {
|
||||
// Arches
|
||||
if(distroID == 'arch') return 'arch-symbolic';
|
||||
if(distroID == 'endeavouros') return 'endeavouros-symbolic';
|
||||
if(distroID == 'cachyos') return 'cachyos-symbolic';
|
||||
// Funny flake
|
||||
if(distroID == 'nixos') return 'nixos-symbolic';
|
||||
// Cool thing
|
||||
if(distroID == 'fedora') return 'fedora-symbolic';
|
||||
// Debians
|
||||
if(distroID == 'linuxmint') return 'ubuntu-symbolic';
|
||||
if(distroID == 'ubuntu') return 'ubuntu-symbolic';
|
||||
if(distroID == 'debian') return 'debian-symbolic';
|
||||
if(distroID == 'zorin') return 'ubuntu-symbolic';
|
||||
if(distroID == 'popos') return 'ubuntu-symbolic';
|
||||
if(distroID == 'raspbian') return 'debian-symbolic';
|
||||
if(distroID == 'kali') return 'debian-symbolic';
|
||||
return 'linux-symbolic';
|
||||
}
|
||||
|
||||
export const getDistroName = () => {
|
||||
// Arches
|
||||
if(distroID == 'arch') return 'Arch Linux';
|
||||
if(distroID == 'endeavouros') return 'EndeavourOS';
|
||||
if(distroID == 'cachyos') return 'CachyOS';
|
||||
// Funny flake
|
||||
if(distroID == 'nixos') return 'NixOS';
|
||||
// Cool thing
|
||||
if(distroID == 'fedora') return 'Fedora';
|
||||
// Debians
|
||||
if(distroID == 'linuxmint') return 'Linux Mint';
|
||||
if(distroID == 'ubuntu') return 'Ubuntu';
|
||||
if(distroID == 'debian') return 'Debian';
|
||||
if(distroID == 'zorin') return 'Zorin';
|
||||
if(distroID == 'popos') return 'Pop!_OS';
|
||||
if(distroID == 'raspbian') return 'Raspbian';
|
||||
if(distroID == 'kali') return 'Kali Linux';
|
||||
return 'Linux';
|
||||
}
|
||||
|
|
@ -1,86 +0,0 @@
|
|||
import Widget from 'resource:///com/github/Aylur/ags/widget.js';
|
||||
|
||||
const { Revealer, Scrollable } = Widget;
|
||||
|
||||
export const MarginRevealer = ({
|
||||
transition = 'slide_down',
|
||||
child,
|
||||
revealChild,
|
||||
showClass = 'element-show', // These are for animation curve, they don't really hide
|
||||
hideClass = 'element-hide', // Don't put margins in these classes!
|
||||
extraSetup = () => { },
|
||||
...rest
|
||||
}) => {
|
||||
const widget = Scrollable({
|
||||
...rest,
|
||||
attribute: {
|
||||
'revealChild': true, // It'll be set to false after init if it's supposed to hide
|
||||
'transition': transition,
|
||||
'show': () => {
|
||||
if (widget.attribute.revealChild) return;
|
||||
widget.hscroll = 'never';
|
||||
widget.vscroll = 'never';
|
||||
child.toggleClassName(hideClass, false);
|
||||
child.toggleClassName(showClass, true);
|
||||
widget.attribute.revealChild = true;
|
||||
child.css = 'margin: 0px;';
|
||||
},
|
||||
'hide': () => {
|
||||
if (!widget.attribute.revealChild) return;
|
||||
child.toggleClassName(hideClass, true);
|
||||
child.toggleClassName(showClass, false);
|
||||
widget.attribute.revealChild = false;
|
||||
if (widget.attribute.transition == 'slide_left')
|
||||
child.css = `margin-right: -${child.get_allocated_width()}px;`;
|
||||
else if (widget.attribute.transition == 'slide_right')
|
||||
child.css = `margin-left: -${child.get_allocated_width()}px;`;
|
||||
else if (widget.attribute.transition == 'slide_up')
|
||||
child.css = `margin-bottom: -${child.get_allocated_height()}px;`;
|
||||
else if (widget.attribute.transition == 'slide_down')
|
||||
child.css = `margin-top: -${child.get_allocated_height()}px;`;
|
||||
},
|
||||
'toggle': () => {
|
||||
if (widget.attribute.revealChild) widget.attribute.hide();
|
||||
else widget.attribute.show();
|
||||
},
|
||||
},
|
||||
child: child,
|
||||
hscroll: `${revealChild ? 'never' : 'always'}`,
|
||||
vscroll: `${revealChild ? 'never' : 'always'}`,
|
||||
setup: (self) => {
|
||||
extraSetup(self);
|
||||
}
|
||||
});
|
||||
child.toggleClassName(`${revealChild ? showClass : hideClass}`, true);
|
||||
return widget;
|
||||
}
|
||||
|
||||
// TODO: Allow reveal update. Currently this just helps at declaration
|
||||
export const DoubleRevealer = ({
|
||||
transition1 = 'slide_right',
|
||||
transition2 = 'slide_left',
|
||||
duration1 = 150,
|
||||
duration2 = 150,
|
||||
child,
|
||||
revealChild,
|
||||
...rest
|
||||
}) => {
|
||||
const r2 = Revealer({
|
||||
transition: transition2,
|
||||
transitionDuration: duration2,
|
||||
revealChild: revealChild,
|
||||
child: child,
|
||||
});
|
||||
const r1 = Revealer({
|
||||
transition: transition1,
|
||||
transitionDuration: duration1,
|
||||
revealChild: revealChild,
|
||||
child: r2,
|
||||
...rest,
|
||||
})
|
||||
r1.toggleRevealChild = (value) => {
|
||||
r1.revealChild = value;
|
||||
r2.revealChild = value;
|
||||
}
|
||||
return r1;
|
||||
}
|
||||
|
|
@ -1,36 +0,0 @@
|
|||
import App from 'resource:///com/github/Aylur/ags/app.js';
|
||||
import Widget from 'resource:///com/github/Aylur/ags/widget.js';
|
||||
const { Box, Window } = Widget;
|
||||
|
||||
|
||||
export default ({
|
||||
name,
|
||||
child,
|
||||
showClassName = "",
|
||||
hideClassName = "",
|
||||
...props
|
||||
}) => {
|
||||
return Window({
|
||||
name,
|
||||
visible: false,
|
||||
layer: 'top',
|
||||
...props,
|
||||
|
||||
child: Box({
|
||||
setup: (self) => {
|
||||
self.keybind("Escape", () => closeEverything());
|
||||
if (showClassName != "" && hideClassName !== "") {
|
||||
self.hook(App, (self, currentName, visible) => {
|
||||
if (currentName === name) {
|
||||
self.toggleClassName(hideClassName, !visible);
|
||||
}
|
||||
});
|
||||
|
||||
if (showClassName !== "" && hideClassName !== "")
|
||||
self.className = `${showClassName} ${hideClassName}`;
|
||||
}
|
||||
},
|
||||
child: child,
|
||||
}),
|
||||
});
|
||||
}
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
import Cairo from 'gi://cairo?version=1.0';
|
||||
|
||||
export const dummyRegion = new Cairo.Region();
|
||||
export const enableClickthrough = (self) => self.input_shape_combine_region(dummyRegion);
|
||||
|
|
@ -1,57 +0,0 @@
|
|||
const { Gdk } = imports.gi;
|
||||
|
||||
export function setupCursorHover(button) { // Hand pointing cursor on hover
|
||||
const display = Gdk.Display.get_default();
|
||||
button.connect('enter-notify-event', () => {
|
||||
const cursor = Gdk.Cursor.new_from_name(display, 'pointer');
|
||||
button.get_window().set_cursor(cursor);
|
||||
});
|
||||
|
||||
button.connect('leave-notify-event', () => {
|
||||
const cursor = Gdk.Cursor.new_from_name(display, 'default');
|
||||
button.get_window().set_cursor(cursor);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
export function setupCursorHoverAim(button) { // Crosshair cursor on hover
|
||||
button.connect('enter-notify-event', () => {
|
||||
const display = Gdk.Display.get_default();
|
||||
const cursor = Gdk.Cursor.new_from_name(display, 'crosshair');
|
||||
button.get_window().set_cursor(cursor);
|
||||
});
|
||||
|
||||
button.connect('leave-notify-event', () => {
|
||||
const display = Gdk.Display.get_default();
|
||||
const cursor = Gdk.Cursor.new_from_name(display, 'default');
|
||||
button.get_window().set_cursor(cursor);
|
||||
});
|
||||
}
|
||||
|
||||
export function setupCursorHoverGrab(button) { // Hand ready to grab on hover
|
||||
button.connect('enter-notify-event', () => {
|
||||
const display = Gdk.Display.get_default();
|
||||
const cursor = Gdk.Cursor.new_from_name(display, 'grab');
|
||||
button.get_window().set_cursor(cursor);
|
||||
});
|
||||
|
||||
button.connect('leave-notify-event', () => {
|
||||
const display = Gdk.Display.get_default();
|
||||
const cursor = Gdk.Cursor.new_from_name(display, 'default');
|
||||
button.get_window().set_cursor(cursor);
|
||||
});
|
||||
}
|
||||
|
||||
export function setupCursorHoverInfo(button) { // "?" mark cursor on hover
|
||||
const display = Gdk.Display.get_default();
|
||||
button.connect('enter-notify-event', () => {
|
||||
const cursor = Gdk.Cursor.new_from_name(display, 'help');
|
||||
button.get_window().set_cursor(cursor);
|
||||
});
|
||||
|
||||
button.connect('leave-notify-event', () => {
|
||||
const cursor = Gdk.Cursor.new_from_name(display, 'default');
|
||||
button.get_window().set_cursor(cursor);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -1,25 +0,0 @@
|
|||
const { Gdk } = imports.gi;
|
||||
|
||||
const MODS = {
|
||||
'Shift': Gdk.ModifierType.SHIFT_MASK,
|
||||
'Ctrl': Gdk.ModifierType.CONTROL_MASK,
|
||||
'Alt': Gdk.ModifierType.ALT_MASK,
|
||||
'Hyper': Gdk.ModifierType.HYPER_MASK,
|
||||
'Meta': Gdk.ModifierType.META_MASK
|
||||
}
|
||||
|
||||
export const checkKeybind = (event, keybind) => {
|
||||
const pressedModMask = event.get_state()[1];
|
||||
const pressedKey = event.get_keyval()[1];
|
||||
const keys = keybind.split('+');
|
||||
for (let i = 0; i < keys.length; i++) {
|
||||
if (keys[i] in MODS) {
|
||||
if (!(pressedModMask & MODS[keys[i]])) {
|
||||
return false;
|
||||
}
|
||||
} else if (pressedKey !== Gdk[`KEY_${keys[i]}`]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
@ -1,213 +0,0 @@
|
|||
const { GLib, Gdk, Gtk } = imports.gi;
|
||||
const Lang = imports.lang;
|
||||
const Cairo = imports.cairo;
|
||||
const Pango = imports.gi.Pango;
|
||||
const PangoCairo = imports.gi.PangoCairo;
|
||||
import App from 'resource:///com/github/Aylur/ags/app.js';
|
||||
import * as Utils from 'resource:///com/github/Aylur/ags/utils.js'
|
||||
import Widget from 'resource:///com/github/Aylur/ags/widget.js';
|
||||
const { Box, DrawingArea, EventBox } = Widget;
|
||||
import Hyprland from 'resource:///com/github/Aylur/ags/service/hyprland.js';
|
||||
|
||||
const dummyWs = Box({ className: 'bar-ws-focus' }); // Not shown. Only for getting size props
|
||||
const dummyActiveWs = Box({ className: 'bar-ws-focus bar-ws-focus-active' }); // Not shown. Only for getting size props
|
||||
const dummyOccupiedWs = Box({ className: 'bar-ws-focus bar-ws-focus-occupied' }); // Not shown. Only for getting size props
|
||||
|
||||
const WS_TAKEN_WIDTH_MULTIPLIER = 1.4;
|
||||
const floor = Math.floor;
|
||||
const ceil = Math.ceil;
|
||||
|
||||
// Font size = workspace id
|
||||
const WorkspaceContents = (count = 10) => {
|
||||
return DrawingArea({
|
||||
className: 'menu-decel',
|
||||
attribute: {
|
||||
lastImmediateActiveWs: 0,
|
||||
immediateActiveWs: 0,
|
||||
initialized: false,
|
||||
workspaceMask: 0,
|
||||
workspaceGroup: 0,
|
||||
updateMask: (self) => {
|
||||
const offset = Math.floor((Hyprland.active.workspace.id - 1) / count) * userOptions.workspaces.shown;
|
||||
// if (self.attribute.initialized) return; // We only need this to run once
|
||||
const workspaces = Hyprland.workspaces;
|
||||
let workspaceMask = 0;
|
||||
for (let i = 0; i < workspaces.length; i++) {
|
||||
const ws = workspaces[i];
|
||||
if (ws.id <= offset || ws.id > offset + count) continue; // Out of range, ignore
|
||||
if (workspaces[i].windows > 0)
|
||||
workspaceMask |= (1 << (ws.id - offset));
|
||||
}
|
||||
// console.log('Mask:', workspaceMask.toString(2));
|
||||
self.attribute.workspaceMask = workspaceMask;
|
||||
// self.attribute.initialized = true;
|
||||
self.queue_draw();
|
||||
},
|
||||
toggleMask: (self, occupied, name) => {
|
||||
if (occupied) self.attribute.workspaceMask |= (1 << parseInt(name));
|
||||
else self.attribute.workspaceMask &= ~(1 << parseInt(name));
|
||||
self.queue_draw();
|
||||
},
|
||||
},
|
||||
setup: (area) => area
|
||||
.hook(Hyprland.active.workspace, (self) => {
|
||||
const newActiveWs = (Hyprland.active.workspace.id - 1) % count + 1;
|
||||
self.setCss(`font-size: ${newActiveWs}px;`);
|
||||
self.attribute.lastImmediateActiveWs = self.attribute.immediateActiveWs;
|
||||
self.attribute.immediateActiveWs = newActiveWs;
|
||||
const previousGroup = self.attribute.workspaceGroup;
|
||||
const currentGroup = Math.floor((Hyprland.active.workspace.id - 1) / count);
|
||||
if (currentGroup !== previousGroup) {
|
||||
self.attribute.updateMask(self);
|
||||
self.attribute.workspaceGroup = currentGroup;
|
||||
}
|
||||
})
|
||||
.hook(Hyprland, (self) => self.attribute.updateMask(self), 'notify::workspaces')
|
||||
.on('draw', Lang.bind(area, (area, cr) => {
|
||||
const offset = Math.floor((Hyprland.active.workspace.id - 1) / count) * userOptions.workspaces.shown;
|
||||
|
||||
const allocation = area.get_allocation();
|
||||
const { width, height } = allocation;
|
||||
|
||||
const workspaceStyleContext = dummyWs.get_style_context();
|
||||
const workspaceDiameter = workspaceStyleContext.get_property('min-width', Gtk.StateFlags.NORMAL);
|
||||
const workspaceRadius = workspaceDiameter / 2;
|
||||
const wsbg = workspaceStyleContext.get_property('background-color', Gtk.StateFlags.NORMAL);
|
||||
|
||||
const occupiedWorkspaceStyleContext = dummyOccupiedWs.get_style_context();
|
||||
const occupiedbg = occupiedWorkspaceStyleContext.get_property('background-color', Gtk.StateFlags.NORMAL);
|
||||
|
||||
const activeWorkspaceStyleContext = dummyActiveWs.get_style_context();
|
||||
const activeWorkspaceWidth = activeWorkspaceStyleContext.get_property('min-width', Gtk.StateFlags.NORMAL);
|
||||
// const activeWorkspaceWidth = 100;
|
||||
const activebg = activeWorkspaceStyleContext.get_property('background-color', Gtk.StateFlags.NORMAL);
|
||||
|
||||
const widgetStyleContext = area.get_style_context();
|
||||
const activeWs = widgetStyleContext.get_property('font-size', Gtk.StateFlags.NORMAL);
|
||||
const lastImmediateActiveWs = area.attribute.lastImmediateActiveWs;
|
||||
const immediateActiveWs = area.attribute.immediateActiveWs;
|
||||
|
||||
// Draw
|
||||
area.set_size_request(workspaceDiameter * WS_TAKEN_WIDTH_MULTIPLIER * (count - 1) + activeWorkspaceWidth, -1);
|
||||
for (let i = 1; i <= count; i++) {
|
||||
if (i == immediateActiveWs) continue;
|
||||
let colors = {};
|
||||
if (area.attribute.workspaceMask & (1 << i)) colors = occupiedbg;
|
||||
else colors = wsbg;
|
||||
|
||||
// if ((i == immediateActiveWs + 1 && immediateActiveWs < activeWs) ||
|
||||
// (i == immediateActiveWs + 1 && immediateActiveWs < activeWs)) {
|
||||
// const widthPercentage = (i == immediateActiveWs - 1) ?
|
||||
// 1 - (immediateActiveWs - activeWs) :
|
||||
// activeWs - immediateActiveWs;
|
||||
// cr.setSourceRGBA(colors.red * widthPercentage + activebg.red * (1 - widthPercentage),
|
||||
// colors.green * widthPercentage + activebg.green * (1 - widthPercentage),
|
||||
// colors.blue * widthPercentage + activebg.blue * (1 - widthPercentage),
|
||||
// colors.alpha);
|
||||
// }
|
||||
// else
|
||||
cr.setSourceRGBA(colors.red, colors.green, colors.blue, colors.alpha)
|
||||
|
||||
const centerX = (i <= activeWs) ?
|
||||
(-workspaceRadius + (workspaceDiameter * WS_TAKEN_WIDTH_MULTIPLIER * i))
|
||||
: -workspaceRadius + workspaceDiameter * WS_TAKEN_WIDTH_MULTIPLIER * (count - 1) + activeWorkspaceWidth - ((count - i) * workspaceDiameter * WS_TAKEN_WIDTH_MULTIPLIER);
|
||||
cr.arc(centerX, height / 2, workspaceRadius, 0, 2 * Math.PI);
|
||||
cr.fill();
|
||||
// What if shrinking
|
||||
if (i == floor(activeWs) && immediateActiveWs > activeWs) { // To right
|
||||
const widthPercentage = 1 - (ceil(activeWs) - activeWs);
|
||||
const leftX = centerX;
|
||||
const wsWidth = (activeWorkspaceWidth - (workspaceDiameter * 1.5)) * (1 - widthPercentage);
|
||||
cr.rectangle(leftX, height / 2 - workspaceRadius, wsWidth, workspaceDiameter);
|
||||
cr.fill();
|
||||
cr.arc(leftX + wsWidth, height / 2, workspaceRadius, 0, Math.PI * 2);
|
||||
cr.fill();
|
||||
}
|
||||
else if (i == ceil(activeWs) && immediateActiveWs < activeWs) { // To left
|
||||
const widthPercentage = activeWs - floor(activeWs);
|
||||
const rightX = centerX;
|
||||
const wsWidth = (activeWorkspaceWidth - (workspaceDiameter * 1.5)) * widthPercentage;
|
||||
const leftX = rightX - wsWidth;
|
||||
cr.rectangle(leftX, height / 2 - workspaceRadius, wsWidth, workspaceDiameter);
|
||||
cr.fill();
|
||||
cr.arc(leftX, height / 2, workspaceRadius, 0, Math.PI * 2);
|
||||
cr.fill();
|
||||
}
|
||||
}
|
||||
|
||||
let widthPercentage, leftX, rightX, activeWsWidth;
|
||||
cr.setSourceRGBA(activebg.red, activebg.green, activebg.blue, activebg.alpha);
|
||||
if (immediateActiveWs > activeWs) { // To right
|
||||
const immediateActiveWs = ceil(activeWs);
|
||||
widthPercentage = immediateActiveWs - activeWs;
|
||||
rightX = -workspaceRadius + workspaceDiameter * WS_TAKEN_WIDTH_MULTIPLIER * (count - 1) + activeWorkspaceWidth - ((count - immediateActiveWs) * workspaceDiameter * WS_TAKEN_WIDTH_MULTIPLIER);
|
||||
activeWsWidth = (activeWorkspaceWidth - (workspaceDiameter * 1.5)) * (1 - widthPercentage);
|
||||
leftX = rightX - activeWsWidth;
|
||||
|
||||
cr.arc(leftX, height / 2, workspaceRadius, 0, Math.PI * 2); // Should be 0.5 * Math.PI, 1.5 * Math.PI in theory but it leaves a weird 1px gap
|
||||
cr.fill();
|
||||
cr.rectangle(leftX, height / 2 - workspaceRadius, activeWsWidth, workspaceDiameter);
|
||||
cr.fill();
|
||||
cr.arc(leftX + activeWsWidth, height / 2, workspaceRadius, 0, Math.PI * 2);
|
||||
cr.fill();
|
||||
}
|
||||
else { // To left
|
||||
const immediateActiveWs = floor(activeWs);
|
||||
widthPercentage = 1 - (activeWs - immediateActiveWs);
|
||||
leftX = -workspaceRadius + (workspaceDiameter * WS_TAKEN_WIDTH_MULTIPLIER * immediateActiveWs);
|
||||
activeWsWidth = (activeWorkspaceWidth - (workspaceDiameter * 1.5)) * widthPercentage
|
||||
|
||||
cr.arc(leftX, height / 2, workspaceRadius, 0, Math.PI * 2); // Should be 0.5 * Math.PI, 1.5 * Math.PI in theory but it leaves a weird 1px gap
|
||||
cr.fill();
|
||||
cr.rectangle(leftX, height / 2 - workspaceRadius, activeWsWidth, workspaceDiameter);
|
||||
cr.fill();
|
||||
cr.arc(leftX + activeWsWidth, height / 2, workspaceRadius, 0, Math.PI * 2);
|
||||
cr.fill();
|
||||
}
|
||||
}))
|
||||
,
|
||||
})
|
||||
}
|
||||
|
||||
export default () => EventBox({
|
||||
onScrollUp: () => Hyprland.messageAsync(`dispatch workspace -1`).catch(print),
|
||||
onScrollDown: () => Hyprland.messageAsync(`dispatch workspace +1`).catch(print),
|
||||
onMiddleClick: () => toggleWindowOnAllMonitors('osk'),
|
||||
onSecondaryClick: () => App.toggleWindow('overview'),
|
||||
attribute: {
|
||||
clicked: false,
|
||||
ws_group: 0,
|
||||
},
|
||||
child: Box({
|
||||
homogeneous: true,
|
||||
// className: 'bar-group-margin',
|
||||
children: [Box({
|
||||
// className: 'bar-group bar-group-standalone bar-group-pad',
|
||||
css: 'min-width: 2px;',
|
||||
children: [WorkspaceContents(userOptions.workspaces.shown)],
|
||||
})]
|
||||
}),
|
||||
setup: (self) => {
|
||||
self.add_events(Gdk.EventMask.POINTER_MOTION_MASK);
|
||||
self.on('motion-notify-event', (self, event) => {
|
||||
if (!self.attribute.clicked) return;
|
||||
const [_, cursorX, cursorY] = event.get_coords();
|
||||
const widgetWidth = self.get_allocation().width;
|
||||
const wsId = Math.ceil(cursorX * userOptions.workspaces.shown / widgetWidth);
|
||||
Utils.execAsync([`${App.configDir}/scripts/hyprland/workspace_action.sh`, 'workspace', `${wsId}`])
|
||||
.catch(print);
|
||||
})
|
||||
self.on('button-press-event', (self, event) => {
|
||||
if (!(event.get_button()[1] === 1)) return; // We're only interested in left-click here
|
||||
self.attribute.clicked = true;
|
||||
const [_, cursorX, cursorY] = event.get_coords();
|
||||
const widgetWidth = self.get_allocation().width;
|
||||
// const wsId = Math.ceil(cursorX * NUM_OF_WORKSPACES_PER_GROUP / widgetWidth) + self.attribute.ws_group * NUM_OF_WORKSPACES_PER_GROUP;
|
||||
// Hyprland.messageAsync(`dispatch workspace ${wsId}`).catch(print);
|
||||
const wsId = Math.ceil(cursorX * userOptions.workspaces.shown / widgetWidth);
|
||||
Utils.execAsync([`${App.configDir}/scripts/hyprland/workspace_action.sh`, 'workspace', `${wsId}`])
|
||||
.catch(print);
|
||||
})
|
||||
self.on('button-release-event', (self) => self.attribute.clicked = false);
|
||||
}
|
||||
})
|
||||
|
|
@ -1,183 +0,0 @@
|
|||
const { GLib, Gdk, Gtk } = imports.gi;
|
||||
const Lang = imports.lang;
|
||||
const Cairo = imports.cairo;
|
||||
const Pango = imports.gi.Pango;
|
||||
const PangoCairo = imports.gi.PangoCairo;
|
||||
import Widget from "resource:///com/github/Aylur/ags/widget.js";
|
||||
import Sway from "../../../services/sway.js";
|
||||
import * as Utils from "resource:///com/github/Aylur/ags/utils.js";
|
||||
const { execAsync, exec } = Utils;
|
||||
const { Box, DrawingArea, EventBox } = Widget;
|
||||
|
||||
const dummyWs = Box({ className: 'bar-ws' }); // Not shown. Only for getting size props
|
||||
const dummyActiveWs = Box({ className: 'bar-ws bar-ws-active' }); // Not shown. Only for getting size props
|
||||
const dummyOccupiedWs = Box({ className: 'bar-ws bar-ws-occupied' }); // Not shown. Only for getting size props
|
||||
|
||||
const switchToWorkspace = (arg) => Utils.execAsync(`swaymsg workspace ${arg}`).catch(print);
|
||||
const switchToRelativeWorkspace = (self, num) =>
|
||||
execAsync([`${App.configDir}/scripts/sway/swayToRelativeWs.sh`, `${num}`]).catch(print);
|
||||
|
||||
const WorkspaceContents = (count = 10) => {
|
||||
return DrawingArea({
|
||||
css: `transition: 90ms cubic-bezier(0.1, 1, 0, 1);`,
|
||||
attribute: {
|
||||
initialized: false,
|
||||
workspaceMask: 0,
|
||||
updateMask: (self) => {
|
||||
if (self.attribute.initialized) return; // We only need this to run once
|
||||
const workspaces = Sway.workspaces;
|
||||
let workspaceMask = 0;
|
||||
// console.log('----------------')
|
||||
for (let i = 0; i < workspaces.length; i++) {
|
||||
const ws = workspaces[i];
|
||||
// console.log(ws.name, ',', ws.num);
|
||||
if (!Number(ws.name)) return;
|
||||
const id = Number(ws.name);
|
||||
if (id <= 0) continue; // Ignore scratchpads
|
||||
if (id > count) return; // Not rendered
|
||||
if (workspaces[i].windows > 0) {
|
||||
workspaceMask |= (1 << id);
|
||||
}
|
||||
}
|
||||
self.attribute.workspaceMask = workspaceMask;
|
||||
self.attribute.initialized = true;
|
||||
},
|
||||
toggleMask: (self, occupied, name) => {
|
||||
if (occupied) self.attribute.workspaceMask |= (1 << parseInt(name));
|
||||
else self.attribute.workspaceMask &= ~(1 << parseInt(name));
|
||||
},
|
||||
},
|
||||
setup: (area) => area
|
||||
.hook(Sway.active.workspace, (area) => {
|
||||
area.setCss(`font-size: ${Sway.active.workspace.name}px;`)
|
||||
})
|
||||
.hook(Sway, (self) => self.attribute.updateMask(self), 'notify::workspaces')
|
||||
// .hook(Hyprland, (self, name) => self.attribute.toggleMask(self, true, name), 'workspace-added')
|
||||
// .hook(Hyprland, (self, name) => self.attribute.toggleMask(self, false, name), 'workspace-removed')
|
||||
.on('draw', Lang.bind(area, (area, cr) => {
|
||||
const allocation = area.get_allocation();
|
||||
const { width, height } = allocation;
|
||||
|
||||
const workspaceStyleContext = dummyWs.get_style_context();
|
||||
const workspaceDiameter = workspaceStyleContext.get_property('min-width', Gtk.StateFlags.NORMAL);
|
||||
const workspaceRadius = workspaceDiameter / 2;
|
||||
const workspaceFontSize = workspaceStyleContext.get_property('font-size', Gtk.StateFlags.NORMAL) / 4 * 3;
|
||||
const workspaceFontFamily = workspaceStyleContext.get_property('font-family', Gtk.StateFlags.NORMAL);
|
||||
const wsbg = workspaceStyleContext.get_property('background-color', Gtk.StateFlags.NORMAL);
|
||||
const wsfg = workspaceStyleContext.get_property('color', Gtk.StateFlags.NORMAL);
|
||||
|
||||
const occupiedWorkspaceStyleContext = dummyOccupiedWs.get_style_context();
|
||||
const occupiedbg = occupiedWorkspaceStyleContext.get_property('background-color', Gtk.StateFlags.NORMAL);
|
||||
const occupiedfg = occupiedWorkspaceStyleContext.get_property('color', Gtk.StateFlags.NORMAL);
|
||||
|
||||
const activeWorkspaceStyleContext = dummyActiveWs.get_style_context();
|
||||
const activebg = activeWorkspaceStyleContext.get_property('background-color', Gtk.StateFlags.NORMAL);
|
||||
const activefg = activeWorkspaceStyleContext.get_property('color', Gtk.StateFlags.NORMAL);
|
||||
area.set_size_request(workspaceDiameter * count, -1);
|
||||
const widgetStyleContext = area.get_style_context();
|
||||
const activeWs = widgetStyleContext.get_property('font-size', Gtk.StateFlags.NORMAL);
|
||||
|
||||
const activeWsCenterX = -(workspaceDiameter / 2) + (workspaceDiameter * activeWs);
|
||||
const activeWsCenterY = height / 2;
|
||||
|
||||
// Font
|
||||
const layout = PangoCairo.create_layout(cr);
|
||||
const fontDesc = Pango.font_description_from_string(`${workspaceFontFamily[0]} ${workspaceFontSize}`);
|
||||
layout.set_font_description(fontDesc);
|
||||
cr.setAntialias(Cairo.Antialias.BEST);
|
||||
// Get kinda min radius for number indicators
|
||||
layout.set_text("0".repeat(count.toString().length), -1);
|
||||
const [layoutWidth, layoutHeight] = layout.get_pixel_size();
|
||||
const indicatorRadius = Math.max(layoutWidth, layoutHeight) / 2 * 1.2; // a bit smaller than sqrt(2)*radius
|
||||
const indicatorGap = workspaceRadius - indicatorRadius;
|
||||
|
||||
// Draw workspace numbers
|
||||
for (let i = 1; i <= count; i++) {
|
||||
if (area.attribute.workspaceMask & (1 << i)) {
|
||||
// Draw bg highlight
|
||||
cr.setSourceRGBA(occupiedbg.red, occupiedbg.green, occupiedbg.blue, occupiedbg.alpha);
|
||||
const wsCenterX = -(workspaceRadius) + (workspaceDiameter * i);
|
||||
const wsCenterY = height / 2;
|
||||
if (!(area.attribute.workspaceMask & (1 << (i - 1)))) { // Left
|
||||
cr.arc(wsCenterX, wsCenterY, workspaceRadius, 0.5 * Math.PI, 1.5 * Math.PI);
|
||||
cr.fill();
|
||||
}
|
||||
else {
|
||||
cr.rectangle(wsCenterX - workspaceRadius, wsCenterY - workspaceRadius, workspaceRadius, workspaceRadius * 2)
|
||||
cr.fill();
|
||||
}
|
||||
if (!(area.attribute.workspaceMask & (1 << (i + 1)))) { // Right
|
||||
cr.arc(wsCenterX, wsCenterY, workspaceRadius, -0.5 * Math.PI, 0.5 * Math.PI);
|
||||
cr.fill();
|
||||
}
|
||||
else {
|
||||
cr.rectangle(wsCenterX, wsCenterY - workspaceRadius, workspaceRadius, workspaceRadius * 2)
|
||||
cr.fill();
|
||||
}
|
||||
|
||||
// Set color for text
|
||||
cr.setSourceRGBA(occupiedfg.red, occupiedfg.green, occupiedfg.blue, occupiedfg.alpha);
|
||||
}
|
||||
else
|
||||
cr.setSourceRGBA(wsfg.red, wsfg.green, wsfg.blue, wsfg.alpha);
|
||||
layout.set_text(`${i}`, -1);
|
||||
const [layoutWidth, layoutHeight] = layout.get_pixel_size();
|
||||
const x = -workspaceRadius + (workspaceDiameter * i) - (layoutWidth / 2);
|
||||
const y = (height - layoutHeight) / 2;
|
||||
cr.moveTo(x, y);
|
||||
// cr.showText(text);
|
||||
PangoCairo.show_layout(cr, layout);
|
||||
cr.stroke();
|
||||
}
|
||||
|
||||
// Draw active ws
|
||||
// base
|
||||
cr.setSourceRGBA(activebg.red, activebg.green, activebg.blue, activebg.alpha);
|
||||
cr.arc(activeWsCenterX, activeWsCenterY, indicatorRadius, 0, 2 * Math.PI);
|
||||
cr.fill();
|
||||
// inner decor
|
||||
cr.setSourceRGBA(activefg.red, activefg.green, activefg.blue, activefg.alpha);
|
||||
cr.arc(activeWsCenterX, activeWsCenterY, indicatorRadius * 0.2, 0, 2 * Math.PI);
|
||||
cr.fill();
|
||||
}))
|
||||
,
|
||||
})
|
||||
}
|
||||
|
||||
export default () => EventBox({
|
||||
onScrollUp: (self) => switchToRelativeWorkspace(self, -1),
|
||||
onScrollDown: (self) => switchToRelativeWorkspace(self, +1),
|
||||
onMiddleClick: () => toggleWindowOnAllMonitors('osk'),
|
||||
onSecondaryClick: () => App.toggleWindow('overview'),
|
||||
attribute: { clicked: false },
|
||||
child: Box({
|
||||
homogeneous: true,
|
||||
className: 'bar-group-margin',
|
||||
children: [Box({
|
||||
className: 'bar-group bar-group-standalone bar-group-pad',
|
||||
css: 'min-width: 2px;',
|
||||
children: [
|
||||
WorkspaceContents(10),
|
||||
]
|
||||
})]
|
||||
}),
|
||||
setup: (self) => {
|
||||
self.add_events(Gdk.EventMask.POINTER_MOTION_MASK);
|
||||
self.on('motion-notify-event', (self, event) => {
|
||||
if (!self.attribute.clicked) return;
|
||||
const [_, cursorX, cursorY] = event.get_coords();
|
||||
const widgetWidth = self.get_allocation().width;
|
||||
const wsId = Math.ceil(cursorX * userOptions.workspaces.shown / widgetWidth);
|
||||
switchToWorkspace(wsId);
|
||||
})
|
||||
self.on('button-press-event', (self, event) => {
|
||||
if (!(event.get_button()[1] === 1)) return; // We're only interested in left-click here
|
||||
self.attribute.clicked = true;
|
||||
const [_, cursorX, cursorY] = event.get_coords();
|
||||
const widgetWidth = self.get_allocation().width;
|
||||
const wsId = Math.ceil(cursorX * userOptions.workspaces.shown / widgetWidth);
|
||||
switchToWorkspace(wsId);
|
||||
})
|
||||
self.on('button-release-event', (self) => self.attribute.clicked = false);
|
||||
}
|
||||
});
|
||||
|
|
@ -1,129 +0,0 @@
|
|||
const { Gtk } = imports.gi;
|
||||
import Widget from 'resource:///com/github/Aylur/ags/widget.js';
|
||||
import Battery from 'resource:///com/github/Aylur/ags/service/battery.js';
|
||||
|
||||
import WindowTitle from "./normal/spaceleft.js";
|
||||
import Indicators from "./normal/spaceright.js";
|
||||
import Music from "./normal/music.js";
|
||||
import System from "./normal/system.js";
|
||||
import { enableClickthrough } from "../.widgetutils/clickthrough.js";
|
||||
import { RoundedCorner } from "../.commonwidgets/cairo_roundedcorner.js";
|
||||
import { currentShellMode } from '../../variables.js';
|
||||
|
||||
const NormalOptionalWorkspaces = async () => {
|
||||
try {
|
||||
return (await import('./normal/workspaces_hyprland.js')).default();
|
||||
} catch {
|
||||
try {
|
||||
return (await import('./normal/workspaces_sway.js')).default();
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const FocusOptionalWorkspaces = async () => {
|
||||
try {
|
||||
return (await import('./focus/workspaces_hyprland.js')).default();
|
||||
} catch {
|
||||
try {
|
||||
return (await import('./focus/workspaces_sway.js')).default();
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export const Bar = async (monitor = 0) => {
|
||||
const SideModule = (children) => Widget.Box({
|
||||
className: 'bar-sidemodule',
|
||||
children: children,
|
||||
});
|
||||
const normalBarContent = Widget.CenterBox({
|
||||
className: 'bar-bg',
|
||||
setup: (self) => {
|
||||
const styleContext = self.get_style_context();
|
||||
const minHeight = styleContext.get_property('min-height', Gtk.StateFlags.NORMAL);
|
||||
// execAsync(['bash', '-c', `hyprctl keyword monitor ,addreserved,${minHeight},0,0,0`]).catch(print);
|
||||
},
|
||||
startWidget: (await WindowTitle(monitor)),
|
||||
centerWidget: Widget.Box({
|
||||
className: 'spacing-h-4',
|
||||
children: [
|
||||
SideModule([Music()]),
|
||||
Widget.Box({
|
||||
homogeneous: true,
|
||||
children: [await NormalOptionalWorkspaces()],
|
||||
}),
|
||||
SideModule([System()]),
|
||||
]
|
||||
}),
|
||||
endWidget: Indicators(monitor),
|
||||
});
|
||||
const focusedBarContent = Widget.CenterBox({
|
||||
className: 'bar-bg-focus',
|
||||
startWidget: Widget.Box({}),
|
||||
centerWidget: Widget.Box({
|
||||
className: 'spacing-h-4',
|
||||
children: [
|
||||
SideModule([]),
|
||||
Widget.Box({
|
||||
homogeneous: true,
|
||||
children: [await FocusOptionalWorkspaces()],
|
||||
}),
|
||||
SideModule([]),
|
||||
]
|
||||
}),
|
||||
endWidget: Widget.Box({}),
|
||||
setup: (self) => {
|
||||
self.hook(Battery, (self) => {
|
||||
if (!Battery.available) return;
|
||||
self.toggleClassName('bar-bg-focus-batterylow', Battery.percent <= userOptions.battery.low);
|
||||
})
|
||||
}
|
||||
});
|
||||
const nothingContent = Widget.Box({
|
||||
className: 'bar-bg-nothing',
|
||||
})
|
||||
return Widget.Window({
|
||||
monitor,
|
||||
name: `bar${monitor}`,
|
||||
anchor: ['top', 'left', 'right'],
|
||||
exclusivity: 'exclusive',
|
||||
visible: true,
|
||||
child: Widget.Stack({
|
||||
homogeneous: false,
|
||||
transition: 'slide_up_down',
|
||||
transitionDuration: userOptions.animations.durationLarge,
|
||||
children: {
|
||||
'normal': normalBarContent,
|
||||
'focus': focusedBarContent,
|
||||
'nothing': nothingContent,
|
||||
},
|
||||
setup: (self) => self.hook(currentShellMode, (self) => {
|
||||
self.shown = currentShellMode.value[monitor];
|
||||
})
|
||||
}),
|
||||
});
|
||||
}
|
||||
|
||||
export const BarCornerTopleft = (monitor = 0) => Widget.Window({
|
||||
monitor,
|
||||
name: `barcornertl${monitor}`,
|
||||
layer: 'top',
|
||||
anchor: ['top', 'left'],
|
||||
exclusivity: 'normal',
|
||||
visible: true,
|
||||
child: RoundedCorner('topleft', { className: 'corner', }),
|
||||
setup: enableClickthrough,
|
||||
});
|
||||
export const BarCornerTopright = (monitor = 0) => Widget.Window({
|
||||
monitor,
|
||||
name: `barcornertr${monitor}`,
|
||||
layer: 'top',
|
||||
anchor: ['top', 'right'],
|
||||
exclusivity: 'normal',
|
||||
visible: true,
|
||||
child: RoundedCorner('topright', { className: 'corner', }),
|
||||
setup: enableClickthrough,
|
||||
});
|
||||
|
|
@ -1,230 +0,0 @@
|
|||
const { GLib } = imports.gi;
|
||||
import Widget from 'resource:///com/github/Aylur/ags/widget.js';
|
||||
import * as Utils from 'resource:///com/github/Aylur/ags/utils.js';
|
||||
import Mpris from 'resource:///com/github/Aylur/ags/service/mpris.js';
|
||||
const { Box, Button, EventBox, Label, Overlay, Revealer, Scrollable } = Widget;
|
||||
const { execAsync, exec } = Utils;
|
||||
import { AnimatedCircProg } from "../../.commonwidgets/cairo_circularprogress.js";
|
||||
import { MaterialIcon } from '../../.commonwidgets/materialicon.js';
|
||||
import { showMusicControls } from '../../../variables.js';
|
||||
|
||||
const CUSTOM_MODULE_CONTENT_INTERVAL_FILE = `${GLib.get_user_cache_dir()}/ags/user/scripts/custom-module-interval.txt`;
|
||||
const CUSTOM_MODULE_CONTENT_SCRIPT = `${GLib.get_user_cache_dir()}/ags/user/scripts/custom-module-poll.sh`;
|
||||
const CUSTOM_MODULE_LEFTCLICK_SCRIPT = `${GLib.get_user_cache_dir()}/ags/user/scripts/custom-module-leftclick.sh`;
|
||||
const CUSTOM_MODULE_RIGHTCLICK_SCRIPT = `${GLib.get_user_cache_dir()}/ags/user/scripts/custom-module-rightclick.sh`;
|
||||
const CUSTOM_MODULE_MIDDLECLICK_SCRIPT = `${GLib.get_user_cache_dir()}/ags/user/scripts/custom-module-middleclick.sh`;
|
||||
const CUSTOM_MODULE_SCROLLUP_SCRIPT = `${GLib.get_user_cache_dir()}/ags/user/scripts/custom-module-scrollup.sh`;
|
||||
const CUSTOM_MODULE_SCROLLDOWN_SCRIPT = `${GLib.get_user_cache_dir()}/ags/user/scripts/custom-module-scrolldown.sh`;
|
||||
|
||||
function trimTrackTitle(title) {
|
||||
if (!title) return '';
|
||||
const cleanPatterns = [
|
||||
/【[^】]*】/, // Touhou n weeb stuff
|
||||
" [FREE DOWNLOAD]", // F-777
|
||||
];
|
||||
cleanPatterns.forEach((expr) => title = title.replace(expr, ''));
|
||||
return title;
|
||||
}
|
||||
|
||||
const BarGroup = ({ child }) => Box({
|
||||
className: 'bar-group-margin bar-sides',
|
||||
children: [
|
||||
Box({
|
||||
className: 'bar-group bar-group-standalone bar-group-pad-system',
|
||||
children: [child],
|
||||
}),
|
||||
]
|
||||
});
|
||||
|
||||
const BarResource = (name, icon, command, circprogClassName = 'bar-batt-circprog', textClassName = 'txt-onSurfaceVariant', iconClassName = 'bar-batt') => {
|
||||
const resourceCircProg = AnimatedCircProg({
|
||||
className: `${circprogClassName}`,
|
||||
vpack: 'center',
|
||||
hpack: 'center',
|
||||
});
|
||||
const resourceProgress = Box({
|
||||
homogeneous: true,
|
||||
children: [Overlay({
|
||||
child: Box({
|
||||
vpack: 'center',
|
||||
className: `${iconClassName}`,
|
||||
homogeneous: true,
|
||||
children: [
|
||||
MaterialIcon(icon, 'small'),
|
||||
],
|
||||
}),
|
||||
overlays: [resourceCircProg]
|
||||
})]
|
||||
});
|
||||
const resourceLabel = Label({
|
||||
className: `txt-smallie ${textClassName}`,
|
||||
});
|
||||
const widget = Button({
|
||||
onClicked: () => Utils.execAsync(['bash', '-c', `${userOptions.apps.taskManager}`]).catch(print),
|
||||
child: Box({
|
||||
className: `spacing-h-4 ${textClassName}`,
|
||||
children: [
|
||||
resourceProgress,
|
||||
resourceLabel,
|
||||
],
|
||||
setup: (self) => self.poll(5000, () => execAsync(['bash', '-c', command])
|
||||
.then((output) => {
|
||||
resourceCircProg.css = `font-size: ${Number(output)}px;`;
|
||||
resourceLabel.label = `${Math.round(Number(output))}%`;
|
||||
widget.tooltipText = `${name}: ${Math.round(Number(output))}%`;
|
||||
}).catch(print))
|
||||
,
|
||||
})
|
||||
});
|
||||
return widget;
|
||||
}
|
||||
|
||||
const TrackProgress = () => {
|
||||
const _updateProgress = (circprog) => {
|
||||
const mpris = Mpris.getPlayer('');
|
||||
if (!mpris) return;
|
||||
// Set circular progress value
|
||||
circprog.css = `font-size: ${Math.max(mpris.position / mpris.length * 100, 0)}px;`
|
||||
}
|
||||
return AnimatedCircProg({
|
||||
className: 'bar-music-circprog',
|
||||
vpack: 'center', hpack: 'center',
|
||||
extraSetup: (self) => self
|
||||
.hook(Mpris, _updateProgress)
|
||||
.poll(3000, _updateProgress)
|
||||
,
|
||||
})
|
||||
}
|
||||
|
||||
const switchToRelativeWorkspace = async (self, num) => {
|
||||
try {
|
||||
const Hyprland = (await import('resource:///com/github/Aylur/ags/service/hyprland.js')).default;
|
||||
Hyprland.messageAsync(`dispatch workspace ${num > 0 ? '+' : ''}${num}`).catch(print);
|
||||
} catch {
|
||||
execAsync([`${App.configDir}/scripts/sway/swayToRelativeWs.sh`, `${num}`]).catch(print);
|
||||
}
|
||||
}
|
||||
|
||||
export default () => {
|
||||
// TODO: use cairo to make button bounce smaller on click, if that's possible
|
||||
const playingState = Box({ // Wrap a box cuz overlay can't have margins itself
|
||||
homogeneous: true,
|
||||
children: [Overlay({
|
||||
child: Box({
|
||||
vpack: 'center',
|
||||
className: 'bar-music-playstate',
|
||||
homogeneous: true,
|
||||
children: [Label({
|
||||
vpack: 'center',
|
||||
className: 'bar-music-playstate-txt',
|
||||
justification: 'center',
|
||||
setup: (self) => self.hook(Mpris, label => {
|
||||
const mpris = Mpris.getPlayer('');
|
||||
label.label = `${mpris !== null && mpris.playBackStatus == 'Playing' ? 'pause' : 'play_arrow'}`;
|
||||
}),
|
||||
})],
|
||||
setup: (self) => self.hook(Mpris, label => {
|
||||
const mpris = Mpris.getPlayer('');
|
||||
if (!mpris) return;
|
||||
label.toggleClassName('bar-music-playstate-playing', mpris !== null && mpris.playBackStatus == 'Playing');
|
||||
label.toggleClassName('bar-music-playstate', mpris !== null || mpris.playBackStatus == 'Paused');
|
||||
}),
|
||||
}),
|
||||
overlays: [
|
||||
TrackProgress(),
|
||||
]
|
||||
})]
|
||||
});
|
||||
const trackTitle = Label({
|
||||
hexpand: true,
|
||||
className: 'txt-smallie bar-music-txt',
|
||||
truncate: 'end',
|
||||
maxWidthChars: 1, // Doesn't matter, just needs to be non negative
|
||||
setup: (self) => self.hook(Mpris, label => {
|
||||
const mpris = Mpris.getPlayer('');
|
||||
if (mpris)
|
||||
label.label = `${trimTrackTitle(mpris.trackTitle)} • ${mpris.trackArtists.join(', ')}`;
|
||||
else
|
||||
label.label = getString('No media');
|
||||
}),
|
||||
})
|
||||
const musicStuff = Box({
|
||||
className: 'spacing-h-10',
|
||||
hexpand: true,
|
||||
children: [
|
||||
playingState,
|
||||
trackTitle,
|
||||
]
|
||||
})
|
||||
const SystemResourcesOrCustomModule = () => {
|
||||
// Check if $XDG_CACHE_HOME/ags/user/scripts/custom-module-poll.sh exists
|
||||
if (GLib.file_test(CUSTOM_MODULE_CONTENT_SCRIPT, GLib.FileTest.EXISTS)) {
|
||||
const interval = Number(Utils.readFile(CUSTOM_MODULE_CONTENT_INTERVAL_FILE)) || 5000;
|
||||
return BarGroup({
|
||||
child: Button({
|
||||
child: Label({
|
||||
className: 'txt-smallie txt-onSurfaceVariant',
|
||||
useMarkup: true,
|
||||
setup: (self) => Utils.timeout(1, () => {
|
||||
self.label = exec(CUSTOM_MODULE_CONTENT_SCRIPT);
|
||||
self.poll(interval, (self) => {
|
||||
const content = exec(CUSTOM_MODULE_CONTENT_SCRIPT);
|
||||
self.label = content;
|
||||
})
|
||||
})
|
||||
}),
|
||||
onPrimaryClickRelease: () => execAsync(CUSTOM_MODULE_LEFTCLICK_SCRIPT).catch(print),
|
||||
onSecondaryClickRelease: () => execAsync(CUSTOM_MODULE_RIGHTCLICK_SCRIPT).catch(print),
|
||||
onMiddleClickRelease: () => execAsync(CUSTOM_MODULE_MIDDLECLICK_SCRIPT).catch(print),
|
||||
onScrollUp: () => execAsync(CUSTOM_MODULE_SCROLLUP_SCRIPT).catch(print),
|
||||
onScrollDown: () => execAsync(CUSTOM_MODULE_SCROLLDOWN_SCRIPT).catch(print),
|
||||
})
|
||||
});
|
||||
} else return BarGroup({
|
||||
child: Box({
|
||||
children: [
|
||||
BarResource(getString('RAM Usage'), 'memory', `LANG=C free | awk '/^Mem/ {printf("%.2f\\n", ($3/$2) * 100)}'`,
|
||||
'bar-ram-circprog', 'bar-ram-txt', 'bar-ram-icon'),
|
||||
Revealer({
|
||||
revealChild: true,
|
||||
transition: 'slide_left',
|
||||
transitionDuration: userOptions.animations.durationLarge,
|
||||
child: Box({
|
||||
className: 'spacing-h-10 margin-left-10',
|
||||
children: [
|
||||
BarResource(getString('Swap Usage'), 'swap_horiz', `LANG=C free | awk '/^Swap/ {if ($2 > 0) printf("%.2f\\n", ($3/$2) * 100); else print "0";}'`,
|
||||
'bar-swap-circprog', 'bar-swap-txt', 'bar-swap-icon'),
|
||||
BarResource(getString('CPU Usage'), 'settings_motion_mode', `LANG=C top -bn1 | grep Cpu | sed 's/\\,/\\./g' | awk '{print $2}'`,
|
||||
'bar-cpu-circprog', 'bar-cpu-txt', 'bar-cpu-icon'),
|
||||
]
|
||||
}),
|
||||
setup: (self) => self.hook(Mpris, label => {
|
||||
const mpris = Mpris.getPlayer('');
|
||||
self.revealChild = (!mpris);
|
||||
}),
|
||||
})
|
||||
],
|
||||
})
|
||||
});
|
||||
}
|
||||
return EventBox({
|
||||
onScrollUp: (self) => switchToRelativeWorkspace(self, -1),
|
||||
onScrollDown: (self) => switchToRelativeWorkspace(self, +1),
|
||||
child: Box({
|
||||
className: 'spacing-h-4',
|
||||
children: [
|
||||
SystemResourcesOrCustomModule(),
|
||||
EventBox({
|
||||
child: BarGroup({ child: musicStuff }),
|
||||
onPrimaryClick: () => showMusicControls.setValue(!showMusicControls.value),
|
||||
onSecondaryClick: () => execAsync(['bash', '-c', 'playerctl next || playerctl position `bc <<< "100 * $(playerctl metadata mpris:length) / 1000000 / 100"` &']).catch(print),
|
||||
onMiddleClick: () => execAsync('playerctl play-pause').catch(print),
|
||||
setup: (self) => self.on('button-press-event', (self, event) => {
|
||||
if (event.get_button()[1] === 8) // Side button
|
||||
execAsync('playerctl previous').catch(print)
|
||||
}),
|
||||
})
|
||||
]
|
||||
})
|
||||
});
|
||||
}
|
||||
|
|
@ -1,78 +0,0 @@
|
|||
import App from 'resource:///com/github/Aylur/ags/app.js';
|
||||
import Widget from 'resource:///com/github/Aylur/ags/widget.js';
|
||||
import Brightness from '../../../services/brightness.js';
|
||||
import Indicator from '../../../services/indicator.js';
|
||||
|
||||
const WindowTitle = async () => {
|
||||
try {
|
||||
const Hyprland = (await import('resource:///com/github/Aylur/ags/service/hyprland.js')).default;
|
||||
return Widget.Scrollable({
|
||||
hexpand: true, vexpand: true,
|
||||
hscroll: 'automatic', vscroll: 'never',
|
||||
child: Widget.Box({
|
||||
vertical: true,
|
||||
children: [
|
||||
Widget.Label({
|
||||
xalign: 0,
|
||||
truncate: 'end',
|
||||
maxWidthChars: 1, // Doesn't matter, just needs to be non negative
|
||||
className: 'txt-smaller bar-wintitle-topdesc txt',
|
||||
setup: (self) => self.hook(Hyprland.active.client, label => { // Hyprland.active.client
|
||||
label.label = Hyprland.active.client.class.length === 0 ? 'Desktop' : Hyprland.active.client.class;
|
||||
}),
|
||||
}),
|
||||
Widget.Label({
|
||||
xalign: 0,
|
||||
truncate: 'end',
|
||||
maxWidthChars: 1, // Doesn't matter, just needs to be non negative
|
||||
className: 'txt-smallie bar-wintitle-txt',
|
||||
setup: (self) => self.hook(Hyprland.active.client, label => { // Hyprland.active.client
|
||||
label.label = Hyprland.active.client.title.length === 0 ? `Workspace ${Hyprland.active.workspace.id}` : Hyprland.active.client.title;
|
||||
}),
|
||||
})
|
||||
]
|
||||
})
|
||||
});
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export default async (monitor = 0) => {
|
||||
const optionalWindowTitleInstance = await WindowTitle();
|
||||
return Widget.EventBox({
|
||||
onScrollUp: () => {
|
||||
Indicator.popup(1); // Since the brightness and speaker are both on the same window
|
||||
Brightness[monitor].screen_value += 0.05;
|
||||
},
|
||||
onScrollDown: () => {
|
||||
Indicator.popup(1); // Since the brightness and speaker are both on the same window
|
||||
Brightness[monitor].screen_value -= 0.05;
|
||||
},
|
||||
onPrimaryClick: () => {
|
||||
App.toggleWindow('sideleft');
|
||||
},
|
||||
child: Widget.Box({
|
||||
homogeneous: false,
|
||||
children: [
|
||||
Widget.Box({ className: 'bar-corner-spacing' }),
|
||||
Widget.Overlay({
|
||||
overlays: [
|
||||
Widget.Box({ hexpand: true }),
|
||||
Widget.Box({
|
||||
className: 'bar-sidemodule', hexpand: true,
|
||||
children: [Widget.Box({
|
||||
vertical: true,
|
||||
className: 'bar-space-button',
|
||||
children: [
|
||||
optionalWindowTitleInstance,
|
||||
]
|
||||
})]
|
||||
}),
|
||||
]
|
||||
})
|
||||
]
|
||||
})
|
||||
});
|
||||
}
|
||||
|
|
@ -1,91 +0,0 @@
|
|||
import App from 'resource:///com/github/Aylur/ags/app.js';
|
||||
import Widget from 'resource:///com/github/Aylur/ags/widget.js';
|
||||
import * as Utils from 'resource:///com/github/Aylur/ags/utils.js';
|
||||
|
||||
import Audio from 'resource:///com/github/Aylur/ags/service/audio.js';
|
||||
import SystemTray from 'resource:///com/github/Aylur/ags/service/systemtray.js';
|
||||
const { execAsync } = Utils;
|
||||
import Indicator from '../../../services/indicator.js';
|
||||
import { StatusIcons } from '../../.commonwidgets/statusicons.js';
|
||||
import { Tray } from "./tray.js";
|
||||
|
||||
const SeparatorDot = () => Widget.Revealer({
|
||||
transition: 'slide_left',
|
||||
revealChild: false,
|
||||
attribute: {
|
||||
'count': SystemTray.items.length,
|
||||
'update': (self, diff) => {
|
||||
self.attribute.count += diff;
|
||||
self.revealChild = (self.attribute.count > 0);
|
||||
}
|
||||
},
|
||||
child: Widget.Box({
|
||||
vpack: 'center',
|
||||
className: 'separator-circle',
|
||||
}),
|
||||
setup: (self) => self
|
||||
.hook(SystemTray, (self) => self.attribute.update(self, 1), 'added')
|
||||
.hook(SystemTray, (self) => self.attribute.update(self, -1), 'removed')
|
||||
,
|
||||
});
|
||||
|
||||
export default (monitor = 0) => {
|
||||
const barTray = Tray();
|
||||
const barStatusIcons = StatusIcons({
|
||||
className: 'bar-statusicons',
|
||||
setup: (self) => self.hook(App, (self, currentName, visible) => {
|
||||
if (currentName === 'sideright') {
|
||||
self.toggleClassName('bar-statusicons-active', visible);
|
||||
}
|
||||
}),
|
||||
}, monitor);
|
||||
const SpaceRightDefaultClicks = (child) => Widget.EventBox({
|
||||
onHover: () => { barStatusIcons.toggleClassName('bar-statusicons-hover', true) },
|
||||
onHoverLost: () => { barStatusIcons.toggleClassName('bar-statusicons-hover', false) },
|
||||
onPrimaryClick: () => App.toggleWindow('sideright'),
|
||||
onSecondaryClick: () => execAsync(['bash', '-c', 'playerctl next || playerctl position `bc <<< "100 * $(playerctl metadata mpris:length) / 1000000 / 100"` &']).catch(print),
|
||||
onMiddleClick: () => execAsync('playerctl play-pause').catch(print),
|
||||
setup: (self) => self.on('button-press-event', (self, event) => {
|
||||
if (event.get_button()[1] === 8)
|
||||
execAsync('playerctl previous').catch(print)
|
||||
}),
|
||||
child: child,
|
||||
});
|
||||
const emptyArea = SpaceRightDefaultClicks(Widget.Box({ hexpand: true, }));
|
||||
const indicatorArea = SpaceRightDefaultClicks(Widget.Box({
|
||||
children: [
|
||||
SeparatorDot(),
|
||||
barStatusIcons
|
||||
],
|
||||
}));
|
||||
const actualContent = Widget.Box({
|
||||
hexpand: true,
|
||||
className: 'spacing-h-5 bar-spaceright',
|
||||
children: [
|
||||
emptyArea,
|
||||
barTray,
|
||||
indicatorArea
|
||||
],
|
||||
});
|
||||
|
||||
return Widget.EventBox({
|
||||
onScrollUp: () => {
|
||||
if (!Audio.speaker) return;
|
||||
if (Audio.speaker.volume <= 0.09) Audio.speaker.volume += 0.01;
|
||||
else Audio.speaker.volume += 0.03;
|
||||
Indicator.popup(1);
|
||||
},
|
||||
onScrollDown: () => {
|
||||
if (!Audio.speaker) return;
|
||||
if (Audio.speaker.volume <= 0.09) Audio.speaker.volume -= 0.01;
|
||||
else Audio.speaker.volume -= 0.03;
|
||||
Indicator.popup(1);
|
||||
},
|
||||
child: Widget.Box({
|
||||
children: [
|
||||
actualContent,
|
||||
SpaceRightDefaultClicks(Widget.Box({ className: 'bar-corner-spacing' })),
|
||||
]
|
||||
})
|
||||
});
|
||||
}
|
||||
|
|
@ -1,236 +0,0 @@
|
|||
// This is for the right pills of the bar.
|
||||
import Widget from 'resource:///com/github/Aylur/ags/widget.js';
|
||||
import * as Utils from 'resource:///com/github/Aylur/ags/utils.js';
|
||||
const { Box, Label, Button, Overlay, Revealer, Scrollable, Stack, EventBox } = Widget;
|
||||
const { exec, execAsync } = Utils;
|
||||
const { GLib } = imports.gi;
|
||||
import Battery from 'resource:///com/github/Aylur/ags/service/battery.js';
|
||||
import { MaterialIcon } from '../../.commonwidgets/materialicon.js';
|
||||
import { AnimatedCircProg } from "../../.commonwidgets/cairo_circularprogress.js";
|
||||
import { WWO_CODE, WEATHER_SYMBOL, NIGHT_WEATHER_SYMBOL } from '../../.commondata/weather.js';
|
||||
|
||||
const WEATHER_CACHE_FOLDER = `${GLib.get_user_cache_dir()}/ags/weather`;
|
||||
Utils.exec(`mkdir -p ${WEATHER_CACHE_FOLDER}`);
|
||||
|
||||
const BarBatteryProgress = () => {
|
||||
const _updateProgress = (circprog) => { // Set circular progress value
|
||||
circprog.css = `font-size: ${Math.abs(Battery.percent)}px;`
|
||||
|
||||
circprog.toggleClassName('bar-batt-circprog-low', Battery.percent <= userOptions.battery.low);
|
||||
circprog.toggleClassName('bar-batt-circprog-full', Battery.charged);
|
||||
}
|
||||
return AnimatedCircProg({
|
||||
className: 'bar-batt-circprog',
|
||||
vpack: 'center', hpack: 'center',
|
||||
extraSetup: (self) => self
|
||||
.hook(Battery, _updateProgress)
|
||||
,
|
||||
})
|
||||
}
|
||||
|
||||
const time = Variable('', {
|
||||
poll: [
|
||||
userOptions.time.interval,
|
||||
() => GLib.DateTime.new_now_local().format(userOptions.time.format),
|
||||
],
|
||||
})
|
||||
|
||||
const date = Variable('', {
|
||||
poll: [
|
||||
userOptions.time.dateInterval,
|
||||
() => GLib.DateTime.new_now_local().format(userOptions.time.dateFormatLong),
|
||||
],
|
||||
})
|
||||
|
||||
const BarClock = () => Widget.Box({
|
||||
vpack: 'center',
|
||||
className: 'spacing-h-4 bar-clock-box',
|
||||
children: [
|
||||
Widget.Label({
|
||||
className: 'bar-time',
|
||||
label: time.bind(),
|
||||
}),
|
||||
Widget.Label({
|
||||
className: 'txt-norm txt-onLayer1',
|
||||
label: '•',
|
||||
}),
|
||||
Widget.Label({
|
||||
className: 'txt-smallie bar-date',
|
||||
label: date.bind(),
|
||||
}),
|
||||
],
|
||||
});
|
||||
|
||||
const UtilButton = ({ name, icon, onClicked }) => Button({
|
||||
vpack: 'center',
|
||||
tooltipText: name,
|
||||
onClicked: onClicked,
|
||||
className: 'bar-util-btn icon-material txt-norm',
|
||||
label: `${icon}`,
|
||||
})
|
||||
|
||||
const Utilities = () => Box({
|
||||
hpack: 'center',
|
||||
className: 'spacing-h-4',
|
||||
children: [
|
||||
UtilButton({
|
||||
name: getString('Screen snip'), icon: 'screenshot_region', onClicked: () => {
|
||||
Utils.execAsync(`${App.configDir}/scripts/grimblast.sh copy area`)
|
||||
.catch(print)
|
||||
}
|
||||
}),
|
||||
UtilButton({
|
||||
name: getString('Color picker'), icon: 'colorize', onClicked: () => {
|
||||
Utils.execAsync(['hyprpicker', '-a']).catch(print)
|
||||
}
|
||||
}),
|
||||
UtilButton({
|
||||
name: getString('Toggle on-screen keyboard'), icon: 'keyboard', onClicked: () => {
|
||||
toggleWindowOnAllMonitors('osk');
|
||||
}
|
||||
}),
|
||||
]
|
||||
})
|
||||
|
||||
const BarBattery = () => Box({
|
||||
className: 'spacing-h-4 bar-batt-txt',
|
||||
children: [
|
||||
Revealer({
|
||||
transitionDuration: userOptions.animations.durationSmall,
|
||||
revealChild: false,
|
||||
transition: 'slide_right',
|
||||
child: MaterialIcon('bolt', 'norm', { tooltipText: "Charging" }),
|
||||
setup: (self) => self.hook(Battery, revealer => {
|
||||
self.revealChild = Battery.charging;
|
||||
}),
|
||||
}),
|
||||
Label({
|
||||
className: 'txt-smallie',
|
||||
setup: (self) => self.hook(Battery, label => {
|
||||
label.label = `${Number.parseFloat(Battery.percent.toFixed(1))}%`;
|
||||
}),
|
||||
}),
|
||||
Overlay({
|
||||
child: Widget.Box({
|
||||
vpack: 'center',
|
||||
className: 'bar-batt',
|
||||
homogeneous: true,
|
||||
children: [
|
||||
MaterialIcon('battery_full', 'small'),
|
||||
],
|
||||
setup: (self) => self.hook(Battery, box => {
|
||||
box.toggleClassName('bar-batt-low', Battery.percent <= userOptions.battery.low);
|
||||
box.toggleClassName('bar-batt-full', Battery.charged);
|
||||
}),
|
||||
}),
|
||||
overlays: [
|
||||
BarBatteryProgress(),
|
||||
]
|
||||
}),
|
||||
]
|
||||
});
|
||||
|
||||
const BarGroup = ({ child }) => Widget.Box({
|
||||
className: 'bar-group-margin bar-sides',
|
||||
children: [
|
||||
Widget.Box({
|
||||
className: 'bar-group bar-group-standalone bar-group-pad-system',
|
||||
children: [child],
|
||||
}),
|
||||
]
|
||||
});
|
||||
const BatteryModule = () => Stack({
|
||||
transition: 'slide_up_down',
|
||||
transitionDuration: userOptions.animations.durationLarge,
|
||||
children: {
|
||||
'laptop': Box({
|
||||
className: 'spacing-h-4', children: [
|
||||
BarGroup({ child: Utilities() }),
|
||||
BarGroup({ child: BarBattery() }),
|
||||
]
|
||||
}),
|
||||
'desktop': BarGroup({
|
||||
child: Box({
|
||||
hexpand: true,
|
||||
hpack: 'center',
|
||||
className: 'spacing-h-4 txt-onSurfaceVariant',
|
||||
children: [
|
||||
MaterialIcon('device_thermostat', 'small'),
|
||||
Label({
|
||||
label: 'Weather',
|
||||
})
|
||||
],
|
||||
setup: (self) => self.poll(900000, async (self) => {
|
||||
const WEATHER_CACHE_PATH = WEATHER_CACHE_FOLDER + '/wttr.in.txt';
|
||||
const updateWeatherForCity = (city) => execAsync(`curl https://wttr.in/${city.replace(/ /g, '%20')}?format=j1`)
|
||||
.then(output => {
|
||||
const weather = JSON.parse(output);
|
||||
Utils.writeFile(JSON.stringify(weather), WEATHER_CACHE_PATH)
|
||||
.catch(print);
|
||||
const weatherCode = weather.current_condition[0].weatherCode;
|
||||
const weatherDesc = weather.current_condition[0].weatherDesc[0].value;
|
||||
const temperature = weather.current_condition[0][`temp_${userOptions.weather.preferredUnit}`];
|
||||
const feelsLike = weather.current_condition[0][`FeelsLike${userOptions.weather.preferredUnit}`];
|
||||
const weatherSymbol = WEATHER_SYMBOL[WWO_CODE[weatherCode]];
|
||||
self.children[0].label = weatherSymbol;
|
||||
self.children[1].label = `${temperature}°${userOptions.weather.preferredUnit} • Feels like ${feelsLike}°${userOptions.weather.preferredUnit}`;
|
||||
self.tooltipText = weatherDesc;
|
||||
}).catch((err) => {
|
||||
try { // Read from cache
|
||||
const weather = JSON.parse(
|
||||
Utils.readFile(WEATHER_CACHE_PATH)
|
||||
);
|
||||
const weatherCode = weather.current_condition[0].weatherCode;
|
||||
const weatherDesc = weather.current_condition[0].weatherDesc[0].value;
|
||||
const temperature = weather.current_condition[0][`temp_${userOptions.weather.preferredUnit}`];
|
||||
const feelsLike = weather.current_condition[0][`FeelsLike${userOptions.weather.preferredUnit}`];
|
||||
const weatherSymbol = WEATHER_SYMBOL[WWO_CODE[weatherCode]];
|
||||
self.children[0].label = weatherSymbol;
|
||||
self.children[1].label = `${temperature}°${userOptions.weather.preferredUnit} • Feels like ${feelsLike}°${userOptions.weather.preferredUnit}`;
|
||||
self.tooltipText = weatherDesc;
|
||||
} catch (err) {
|
||||
print(err);
|
||||
}
|
||||
});
|
||||
if (userOptions.weather.city != '' && userOptions.weather.city != null) {
|
||||
updateWeatherForCity(userOptions.weather.city.replace(/ /g, '%20'));
|
||||
}
|
||||
else {
|
||||
Utils.execAsync('curl ipinfo.io')
|
||||
.then(output => {
|
||||
return JSON.parse(output)['city'].toLowerCase();
|
||||
})
|
||||
.then(updateWeatherForCity)
|
||||
.catch(print)
|
||||
}
|
||||
}),
|
||||
})
|
||||
}),
|
||||
},
|
||||
setup: (stack) => Utils.timeout(10, () => {
|
||||
if (!Battery.available) stack.shown = 'desktop';
|
||||
else stack.shown = 'laptop';
|
||||
})
|
||||
})
|
||||
|
||||
const switchToRelativeWorkspace = async (self, num) => {
|
||||
try {
|
||||
const Hyprland = (await import('resource:///com/github/Aylur/ags/service/hyprland.js')).default;
|
||||
Hyprland.messageAsync(`dispatch workspace ${num > 0 ? '+' : ''}${num}`).catch(print);
|
||||
} catch {
|
||||
execAsync([`${App.configDir}/scripts/sway/swayToRelativeWs.sh`, `${num}`]).catch(print);
|
||||
}
|
||||
}
|
||||
|
||||
export default () => Widget.EventBox({
|
||||
onScrollUp: (self) => switchToRelativeWorkspace(self, -1),
|
||||
onScrollDown: (self) => switchToRelativeWorkspace(self, +1),
|
||||
onPrimaryClick: () => App.toggleWindow('sideright'),
|
||||
child: Widget.Box({
|
||||
className: 'spacing-h-4',
|
||||
children: [
|
||||
BarGroup({ child: BarClock() }),
|
||||
BatteryModule(),
|
||||
]
|
||||
})
|
||||
});
|
||||
|
|
@ -1,36 +0,0 @@
|
|||
import Widget from 'resource:///com/github/Aylur/ags/widget.js';
|
||||
import SystemTray from 'resource:///com/github/Aylur/ags/service/systemtray.js';
|
||||
const { Box, Icon, Button, Revealer } = Widget;
|
||||
const { Gravity } = imports.gi.Gdk;
|
||||
|
||||
const SysTrayItem = (item) => item.id !== null ? Button({
|
||||
className: 'bar-systray-item',
|
||||
child: Icon({ hpack: 'center' }).bind('icon', item, 'icon'),
|
||||
setup: (self) => self
|
||||
.hook(item, (self) => self.tooltipMarkup = item['tooltip-markup'])
|
||||
,
|
||||
onPrimaryClick: (_, event) => item.activate(event),
|
||||
onSecondaryClick: (btn, event) => item.menu.popup_at_widget(btn, Gravity.SOUTH, Gravity.NORTH, null),
|
||||
}) : null;
|
||||
|
||||
export const Tray = (props = {}) => {
|
||||
const trayContent = Box({
|
||||
className: 'margin-right-5 spacing-h-15',
|
||||
setup: (self) => self
|
||||
.hook(SystemTray, (self) => {
|
||||
self.children = SystemTray.items.map(SysTrayItem);
|
||||
self.show_all();
|
||||
})
|
||||
,
|
||||
});
|
||||
const trayRevealer = Widget.Revealer({
|
||||
revealChild: true,
|
||||
transition: 'slide_left',
|
||||
transitionDuration: userOptions.animations.durationLarge,
|
||||
child: trayContent,
|
||||
});
|
||||
return Box({
|
||||
...props,
|
||||
children: [trayRevealer],
|
||||
});
|
||||
}
|
||||
|
|
@ -1,224 +0,0 @@
|
|||
const { GLib, Gdk, Gtk } = imports.gi;
|
||||
const Lang = imports.lang;
|
||||
const Cairo = imports.cairo;
|
||||
const Pango = imports.gi.Pango;
|
||||
const PangoCairo = imports.gi.PangoCairo;
|
||||
import App from 'resource:///com/github/Aylur/ags/app.js';
|
||||
import * as Utils from 'resource:///com/github/Aylur/ags/utils.js'
|
||||
import Widget from 'resource:///com/github/Aylur/ags/widget.js';
|
||||
const { Box, DrawingArea, EventBox } = Widget;
|
||||
import Hyprland from 'resource:///com/github/Aylur/ags/service/hyprland.js';
|
||||
|
||||
const dummyWs = Box({ className: 'bar-ws' }); // Not shown. Only for getting size props
|
||||
const dummyActiveWs = Box({ className: 'bar-ws bar-ws-active' }); // Not shown. Only for getting size props
|
||||
const dummyOccupiedWs = Box({ className: 'bar-ws bar-ws-occupied' }); // Not shown. Only for getting size props
|
||||
|
||||
const mix = (value1, value2, perc) => {
|
||||
return value1 * perc + value2 * (1 - perc);
|
||||
}
|
||||
|
||||
const getFontWeightName = (weight) => {
|
||||
switch (weight) {
|
||||
case Pango.Weight.ULTRA_LIGHT:
|
||||
return 'UltraLight';
|
||||
case Pango.Weight.LIGHT:
|
||||
return 'Light';
|
||||
case Pango.Weight.NORMAL:
|
||||
return 'Normal';
|
||||
case Pango.Weight.BOLD:
|
||||
return 'Bold';
|
||||
case Pango.Weight.ULTRA_BOLD:
|
||||
return 'UltraBold';
|
||||
case Pango.Weight.HEAVY:
|
||||
return 'Heavy';
|
||||
default:
|
||||
return 'Normal';
|
||||
}
|
||||
}
|
||||
|
||||
// Font size = workspace id
|
||||
const WorkspaceContents = (count = 10) => {
|
||||
return DrawingArea({
|
||||
className: 'bar-ws-container',
|
||||
attribute: {
|
||||
initialized: false,
|
||||
workspaceMask: 0,
|
||||
workspaceGroup: 0,
|
||||
updateMask: (self) => {
|
||||
const offset = Math.floor((Hyprland.active.workspace.id - 1) / count) * userOptions.workspaces.shown;
|
||||
// if (self.attribute.initialized) return; // We only need this to run once
|
||||
const workspaces = Hyprland.workspaces;
|
||||
let workspaceMask = 0;
|
||||
for (let i = 0; i < workspaces.length; i++) {
|
||||
const ws = workspaces[i];
|
||||
if (ws.id <= offset || ws.id > offset + count) continue; // Out of range, ignore
|
||||
if (workspaces[i].windows > 0)
|
||||
workspaceMask |= (1 << (ws.id - offset));
|
||||
}
|
||||
// console.log('Mask:', workspaceMask.toString(2));
|
||||
self.attribute.workspaceMask = workspaceMask;
|
||||
// self.attribute.initialized = true;
|
||||
self.queue_draw();
|
||||
},
|
||||
toggleMask: (self, occupied, name) => {
|
||||
if (occupied) self.attribute.workspaceMask |= (1 << parseInt(name));
|
||||
else self.attribute.workspaceMask &= ~(1 << parseInt(name));
|
||||
self.queue_draw();
|
||||
},
|
||||
},
|
||||
setup: (area) => area
|
||||
.hook(Hyprland.active.workspace, (self) => {
|
||||
self.setCss(`font-size: ${(Hyprland.active.workspace.id - 1) % count + 1}px;`);
|
||||
const previousGroup = self.attribute.workspaceGroup;
|
||||
const currentGroup = Math.floor((Hyprland.active.workspace.id - 1) / count);
|
||||
if (currentGroup !== previousGroup) {
|
||||
self.attribute.updateMask(self);
|
||||
self.attribute.workspaceGroup = currentGroup;
|
||||
}
|
||||
})
|
||||
.hook(Hyprland, (self) => self.attribute.updateMask(self), 'notify::workspaces')
|
||||
.on('draw', Lang.bind(area, (area, cr) => {
|
||||
const offset = Math.floor((Hyprland.active.workspace.id - 1) / count) * userOptions.workspaces.shown;
|
||||
|
||||
const allocation = area.get_allocation();
|
||||
const { width, height } = allocation;
|
||||
|
||||
const workspaceStyleContext = dummyWs.get_style_context();
|
||||
const workspaceDiameter = workspaceStyleContext.get_property('min-width', Gtk.StateFlags.NORMAL);
|
||||
const workspaceRadius = workspaceDiameter / 2;
|
||||
const workspaceFontSize = workspaceStyleContext.get_property('font-size', Gtk.StateFlags.NORMAL) / 4 * 3;
|
||||
const workspaceFontFamily = workspaceStyleContext.get_property('font-family', Gtk.StateFlags.NORMAL);
|
||||
const workspaceFontWeight = workspaceStyleContext.get_property('font-weight', Gtk.StateFlags.NORMAL);
|
||||
const wsbg = workspaceStyleContext.get_property('background-color', Gtk.StateFlags.NORMAL);
|
||||
const wsfg = workspaceStyleContext.get_property('color', Gtk.StateFlags.NORMAL);
|
||||
|
||||
const occupiedWorkspaceStyleContext = dummyOccupiedWs.get_style_context();
|
||||
const occupiedbg = occupiedWorkspaceStyleContext.get_property('background-color', Gtk.StateFlags.NORMAL);
|
||||
const occupiedfg = occupiedWorkspaceStyleContext.get_property('color', Gtk.StateFlags.NORMAL);
|
||||
|
||||
const activeWorkspaceStyleContext = dummyActiveWs.get_style_context();
|
||||
const activebg = activeWorkspaceStyleContext.get_property('background-color', Gtk.StateFlags.NORMAL);
|
||||
const activefg = activeWorkspaceStyleContext.get_property('color', Gtk.StateFlags.NORMAL);
|
||||
area.set_size_request(workspaceDiameter * count, -1);
|
||||
const widgetStyleContext = area.get_style_context();
|
||||
const activeWs = widgetStyleContext.get_property('font-size', Gtk.StateFlags.NORMAL);
|
||||
|
||||
const activeWsCenterX = -(workspaceDiameter / 2) + (workspaceDiameter * activeWs);
|
||||
const activeWsCenterY = height / 2;
|
||||
|
||||
// Font
|
||||
const layout = PangoCairo.create_layout(cr);
|
||||
const fontDesc = Pango.font_description_from_string(`${workspaceFontFamily[0]} ${getFontWeightName(workspaceFontWeight)} ${workspaceFontSize}`);
|
||||
layout.set_font_description(fontDesc);
|
||||
cr.setAntialias(Cairo.Antialias.BEST);
|
||||
// Get kinda min radius for number indicators
|
||||
layout.set_text("0".repeat(count.toString().length), -1);
|
||||
const [layoutWidth, layoutHeight] = layout.get_pixel_size();
|
||||
const indicatorRadius = Math.max(layoutWidth, layoutHeight) / 2 * 1.15; // smaller than sqrt(2)*radius
|
||||
const indicatorGap = workspaceRadius - indicatorRadius;
|
||||
|
||||
for (let i = 1; i <= count; i++) {
|
||||
if (area.attribute.workspaceMask & (1 << i)) {
|
||||
// Draw bg highlight
|
||||
cr.setSourceRGBA(occupiedbg.red, occupiedbg.green, occupiedbg.blue, occupiedbg.alpha);
|
||||
const wsCenterX = -(workspaceRadius) + (workspaceDiameter * i);
|
||||
const wsCenterY = height / 2;
|
||||
if (!(area.attribute.workspaceMask & (1 << (i - 1)))) { // Left
|
||||
cr.arc(wsCenterX, wsCenterY, workspaceRadius, 0.5 * Math.PI, 1.5 * Math.PI);
|
||||
cr.fill();
|
||||
}
|
||||
else {
|
||||
cr.rectangle(wsCenterX - workspaceRadius, wsCenterY - workspaceRadius, workspaceRadius, workspaceRadius * 2)
|
||||
cr.fill();
|
||||
}
|
||||
if (!(area.attribute.workspaceMask & (1 << (i + 1)))) { // Right
|
||||
cr.arc(wsCenterX, wsCenterY, workspaceRadius, -0.5 * Math.PI, 0.5 * Math.PI);
|
||||
cr.fill();
|
||||
}
|
||||
else {
|
||||
cr.rectangle(wsCenterX, wsCenterY - workspaceRadius, workspaceRadius, workspaceRadius * 2)
|
||||
cr.fill();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Draw active ws
|
||||
cr.setSourceRGBA(activebg.red, activebg.green, activebg.blue, activebg.alpha);
|
||||
cr.arc(activeWsCenterX, activeWsCenterY, indicatorRadius, 0, 2 * Math.PI);
|
||||
cr.fill();
|
||||
|
||||
// Draw workspace numbers
|
||||
for (let i = 1; i <= count; i++) {
|
||||
const inactivecolors = area.attribute.workspaceMask & (1 << i) ? occupiedfg : wsfg;
|
||||
if (i == activeWs) {
|
||||
cr.setSourceRGBA(activefg.red, activefg.green, activefg.blue, activefg.alpha);
|
||||
}
|
||||
// Moving to
|
||||
else if ((i == Math.floor(activeWs) && Hyprland.active.workspace.id < activeWs) || (i == Math.ceil(activeWs) && Hyprland.active.workspace.id > activeWs)) {
|
||||
cr.setSourceRGBA(mix(activefg.red, inactivecolors.red, 1 - Math.abs(activeWs - i)), mix(activefg.green, inactivecolors.green, 1 - Math.abs(activeWs - i)), mix(activefg.blue, inactivecolors.blue, 1 - Math.abs(activeWs - i)), activefg.alpha);
|
||||
}
|
||||
// Moving from
|
||||
else if ((i == Math.floor(activeWs) && Hyprland.active.workspace.id > activeWs) || (i == Math.ceil(activeWs) && Hyprland.active.workspace.id < activeWs)) {
|
||||
cr.setSourceRGBA(mix(activefg.red, inactivecolors.red, 1 - Math.abs(activeWs - i)), mix(activefg.green, inactivecolors.green, 1 - Math.abs(activeWs - i)), mix(activefg.blue, inactivecolors.blue, 1 - Math.abs(activeWs - i)), activefg.alpha);
|
||||
}
|
||||
// Inactive
|
||||
else
|
||||
cr.setSourceRGBA(inactivecolors.red, inactivecolors.green, inactivecolors.blue, inactivecolors.alpha);
|
||||
|
||||
layout.set_text(`${i + offset}`, -1);
|
||||
const [layoutWidth, layoutHeight] = layout.get_pixel_size();
|
||||
const x = -workspaceRadius + (workspaceDiameter * i) - (layoutWidth / 2);
|
||||
const y = (height - layoutHeight) / 2;
|
||||
cr.moveTo(x, y);
|
||||
PangoCairo.show_layout(cr, layout);
|
||||
cr.stroke();
|
||||
}
|
||||
}))
|
||||
,
|
||||
})
|
||||
}
|
||||
|
||||
export default () => EventBox({
|
||||
onScrollUp: () => Hyprland.messageAsync(`dispatch workspace -1`).catch(print),
|
||||
onScrollDown: () => Hyprland.messageAsync(`dispatch workspace +1`).catch(print),
|
||||
onMiddleClick: () => toggleWindowOnAllMonitors('osk'),
|
||||
onSecondaryClick: () => App.toggleWindow('overview'),
|
||||
attribute: {
|
||||
clicked: false,
|
||||
ws_group: 0,
|
||||
},
|
||||
child: Box({
|
||||
homogeneous: true,
|
||||
className: 'bar-group-margin',
|
||||
children: [Box({
|
||||
className: 'bar-group bar-group-standalone bar-group-pad',
|
||||
css: 'min-width: 2px;',
|
||||
children: [WorkspaceContents(userOptions.workspaces.shown)],
|
||||
})]
|
||||
}),
|
||||
setup: (self) => {
|
||||
self.add_events(Gdk.EventMask.POINTER_MOTION_MASK);
|
||||
self.on('motion-notify-event', (self, event) => {
|
||||
if (!self.attribute.clicked) return;
|
||||
const [_, cursorX, cursorY] = event.get_coords();
|
||||
const widgetWidth = self.get_allocation().width;
|
||||
const wsId = Math.ceil(cursorX * userOptions.workspaces.shown / widgetWidth);
|
||||
Utils.execAsync([`${App.configDir}/scripts/hyprland/workspace_action.sh`, 'workspace', `${wsId}`])
|
||||
.catch(print);
|
||||
})
|
||||
self.on('button-press-event', (self, event) => {
|
||||
if (event.get_button()[1] === 1) {
|
||||
self.attribute.clicked = true;
|
||||
const [_, cursorX, cursorY] = event.get_coords();
|
||||
const widgetWidth = self.get_allocation().width;
|
||||
const wsId = Math.ceil(cursorX * userOptions.workspaces.shown / widgetWidth);
|
||||
Utils.execAsync([`${App.configDir}/scripts/hyprland/workspace_action.sh`, 'workspace', `${wsId}`])
|
||||
.catch(print);
|
||||
}
|
||||
else if (event.get_button()[1] === 8) {
|
||||
Hyprland.messageAsync(`dispatch togglespecialworkspace`).catch(print);
|
||||
}
|
||||
})
|
||||
self.on('button-release-event', (self) => self.attribute.clicked = false);
|
||||
}
|
||||
})
|
||||
|
|
@ -1,183 +0,0 @@
|
|||
const { GLib, Gdk, Gtk } = imports.gi;
|
||||
const Lang = imports.lang;
|
||||
const Cairo = imports.cairo;
|
||||
const Pango = imports.gi.Pango;
|
||||
const PangoCairo = imports.gi.PangoCairo;
|
||||
import Widget from "resource:///com/github/Aylur/ags/widget.js";
|
||||
import Sway from "../../../services/sway.js";
|
||||
import * as Utils from "resource:///com/github/Aylur/ags/utils.js";
|
||||
const { execAsync, exec } = Utils;
|
||||
const { Box, DrawingArea, EventBox } = Widget;
|
||||
|
||||
const dummyWs = Box({ className: 'bar-ws' }); // Not shown. Only for getting size props
|
||||
const dummyActiveWs = Box({ className: 'bar-ws bar-ws-active' }); // Not shown. Only for getting size props
|
||||
const dummyOccupiedWs = Box({ className: 'bar-ws bar-ws-occupied' }); // Not shown. Only for getting size props
|
||||
|
||||
const switchToWorkspace = (arg) => Utils.execAsync(`swaymsg workspace ${arg}`).catch(print);
|
||||
const switchToRelativeWorkspace = (self, num) =>
|
||||
execAsync([`${App.configDir}/scripts/sway/swayToRelativeWs.sh`, `${num}`]).catch(print);
|
||||
|
||||
const WorkspaceContents = (count = 10) => {
|
||||
return DrawingArea({
|
||||
css: `transition: 90ms cubic-bezier(0.1, 1, 0, 1);`,
|
||||
attribute: {
|
||||
initialized: false,
|
||||
workspaceMask: 0,
|
||||
updateMask: (self) => {
|
||||
if (self.attribute.initialized) return; // We only need this to run once
|
||||
const workspaces = Sway.workspaces;
|
||||
let workspaceMask = 0;
|
||||
// console.log('----------------')
|
||||
for (let i = 0; i < workspaces.length; i++) {
|
||||
const ws = workspaces[i];
|
||||
// console.log(ws.name, ',', ws.num);
|
||||
if (!Number(ws.name)) return;
|
||||
const id = Number(ws.name);
|
||||
if (id <= 0) continue; // Ignore scratchpads
|
||||
if (id > count) return; // Not rendered
|
||||
if (workspaces[i].windows > 0) {
|
||||
workspaceMask |= (1 << id);
|
||||
}
|
||||
}
|
||||
self.attribute.workspaceMask = workspaceMask;
|
||||
self.attribute.initialized = true;
|
||||
},
|
||||
toggleMask: (self, occupied, name) => {
|
||||
if (occupied) self.attribute.workspaceMask |= (1 << parseInt(name));
|
||||
else self.attribute.workspaceMask &= ~(1 << parseInt(name));
|
||||
},
|
||||
},
|
||||
setup: (area) => area
|
||||
.hook(Sway.active.workspace, (area) => {
|
||||
area.setCss(`font-size: ${Sway.active.workspace.name}px;`)
|
||||
})
|
||||
.hook(Sway, (self) => self.attribute.updateMask(self), 'notify::workspaces')
|
||||
// .hook(Hyprland, (self, name) => self.attribute.toggleMask(self, true, name), 'workspace-added')
|
||||
// .hook(Hyprland, (self, name) => self.attribute.toggleMask(self, false, name), 'workspace-removed')
|
||||
.on('draw', Lang.bind(area, (area, cr) => {
|
||||
const allocation = area.get_allocation();
|
||||
const { width, height } = allocation;
|
||||
|
||||
const workspaceStyleContext = dummyWs.get_style_context();
|
||||
const workspaceDiameter = workspaceStyleContext.get_property('min-width', Gtk.StateFlags.NORMAL);
|
||||
const workspaceRadius = workspaceDiameter / 2;
|
||||
const workspaceFontSize = workspaceStyleContext.get_property('font-size', Gtk.StateFlags.NORMAL) / 4 * 3;
|
||||
const workspaceFontFamily = workspaceStyleContext.get_property('font-family', Gtk.StateFlags.NORMAL);
|
||||
const wsbg = workspaceStyleContext.get_property('background-color', Gtk.StateFlags.NORMAL);
|
||||
const wsfg = workspaceStyleContext.get_property('color', Gtk.StateFlags.NORMAL);
|
||||
|
||||
const occupiedWorkspaceStyleContext = dummyOccupiedWs.get_style_context();
|
||||
const occupiedbg = occupiedWorkspaceStyleContext.get_property('background-color', Gtk.StateFlags.NORMAL);
|
||||
const occupiedfg = occupiedWorkspaceStyleContext.get_property('color', Gtk.StateFlags.NORMAL);
|
||||
|
||||
const activeWorkspaceStyleContext = dummyActiveWs.get_style_context();
|
||||
const activebg = activeWorkspaceStyleContext.get_property('background-color', Gtk.StateFlags.NORMAL);
|
||||
const activefg = activeWorkspaceStyleContext.get_property('color', Gtk.StateFlags.NORMAL);
|
||||
area.set_size_request(workspaceDiameter * count, -1);
|
||||
const widgetStyleContext = area.get_style_context();
|
||||
const activeWs = widgetStyleContext.get_property('font-size', Gtk.StateFlags.NORMAL);
|
||||
|
||||
const activeWsCenterX = -(workspaceDiameter / 2) + (workspaceDiameter * activeWs);
|
||||
const activeWsCenterY = height / 2;
|
||||
|
||||
// Font
|
||||
const layout = PangoCairo.create_layout(cr);
|
||||
const fontDesc = Pango.font_description_from_string(`${workspaceFontFamily[0]} ${workspaceFontSize}`);
|
||||
layout.set_font_description(fontDesc);
|
||||
cr.setAntialias(Cairo.Antialias.BEST);
|
||||
// Get kinda min radius for number indicators
|
||||
layout.set_text("0".repeat(count.toString().length), -1);
|
||||
const [layoutWidth, layoutHeight] = layout.get_pixel_size();
|
||||
const indicatorRadius = Math.max(layoutWidth, layoutHeight) / 2 * 1.2; // a bit smaller than sqrt(2)*radius
|
||||
const indicatorGap = workspaceRadius - indicatorRadius;
|
||||
|
||||
// Draw workspace numbers
|
||||
for (let i = 1; i <= count; i++) {
|
||||
if (area.attribute.workspaceMask & (1 << i)) {
|
||||
// Draw bg highlight
|
||||
cr.setSourceRGBA(occupiedbg.red, occupiedbg.green, occupiedbg.blue, occupiedbg.alpha);
|
||||
const wsCenterX = -(workspaceRadius) + (workspaceDiameter * i);
|
||||
const wsCenterY = height / 2;
|
||||
if (!(area.attribute.workspaceMask & (1 << (i - 1)))) { // Left
|
||||
cr.arc(wsCenterX, wsCenterY, workspaceRadius, 0.5 * Math.PI, 1.5 * Math.PI);
|
||||
cr.fill();
|
||||
}
|
||||
else {
|
||||
cr.rectangle(wsCenterX - workspaceRadius, wsCenterY - workspaceRadius, workspaceRadius, workspaceRadius * 2)
|
||||
cr.fill();
|
||||
}
|
||||
if (!(area.attribute.workspaceMask & (1 << (i + 1)))) { // Right
|
||||
cr.arc(wsCenterX, wsCenterY, workspaceRadius, -0.5 * Math.PI, 0.5 * Math.PI);
|
||||
cr.fill();
|
||||
}
|
||||
else {
|
||||
cr.rectangle(wsCenterX, wsCenterY - workspaceRadius, workspaceRadius, workspaceRadius * 2)
|
||||
cr.fill();
|
||||
}
|
||||
|
||||
// Set color for text
|
||||
cr.setSourceRGBA(occupiedfg.red, occupiedfg.green, occupiedfg.blue, occupiedfg.alpha);
|
||||
}
|
||||
else
|
||||
cr.setSourceRGBA(wsfg.red, wsfg.green, wsfg.blue, wsfg.alpha);
|
||||
layout.set_text(`${i}`, -1);
|
||||
const [layoutWidth, layoutHeight] = layout.get_pixel_size();
|
||||
const x = -workspaceRadius + (workspaceDiameter * i) - (layoutWidth / 2);
|
||||
const y = (height - layoutHeight) / 2;
|
||||
cr.moveTo(x, y);
|
||||
// cr.showText(text);
|
||||
PangoCairo.show_layout(cr, layout);
|
||||
cr.stroke();
|
||||
}
|
||||
|
||||
// Draw active ws
|
||||
// base
|
||||
cr.setSourceRGBA(activebg.red, activebg.green, activebg.blue, activebg.alpha);
|
||||
cr.arc(activeWsCenterX, activeWsCenterY, indicatorRadius, 0, 2 * Math.PI);
|
||||
cr.fill();
|
||||
// inner decor
|
||||
cr.setSourceRGBA(activefg.red, activefg.green, activefg.blue, activefg.alpha);
|
||||
cr.arc(activeWsCenterX, activeWsCenterY, indicatorRadius * 0.2, 0, 2 * Math.PI);
|
||||
cr.fill();
|
||||
}))
|
||||
,
|
||||
})
|
||||
}
|
||||
|
||||
export default () => EventBox({
|
||||
onScrollUp: (self) => switchToRelativeWorkspace(self, -1),
|
||||
onScrollDown: (self) => switchToRelativeWorkspace(self, +1),
|
||||
onMiddleClick: () => toggleWindowOnAllMonitors('osk'),
|
||||
onSecondaryClick: () => App.toggleWindow('overview'),
|
||||
attribute: { clicked: false },
|
||||
child: Box({
|
||||
homogeneous: true,
|
||||
className: 'bar-group-margin',
|
||||
children: [Box({
|
||||
className: 'bar-group bar-group-standalone bar-group-pad',
|
||||
css: 'min-width: 2px;',
|
||||
children: [
|
||||
WorkspaceContents(10),
|
||||
]
|
||||
})]
|
||||
}),
|
||||
setup: (self) => {
|
||||
self.add_events(Gdk.EventMask.POINTER_MOTION_MASK);
|
||||
self.on('motion-notify-event', (self, event) => {
|
||||
if (!self.attribute.clicked) return;
|
||||
const [_, cursorX, cursorY] = event.get_coords();
|
||||
const widgetWidth = self.get_allocation().width;
|
||||
const wsId = Math.ceil(cursorX * userOptions.workspaces.shown / widgetWidth);
|
||||
switchToWorkspace(wsId);
|
||||
})
|
||||
self.on('button-press-event', (self, event) => {
|
||||
if (!(event.get_button()[1] === 1)) return; // We're only interested in left-click here
|
||||
self.attribute.clicked = true;
|
||||
const [_, cursorX, cursorY] = event.get_coords();
|
||||
const widgetWidth = self.get_allocation().width;
|
||||
const wsId = Math.ceil(cursorX * userOptions.workspaces.shown / widgetWidth);
|
||||
switchToWorkspace(wsId);
|
||||
})
|
||||
self.on('button-release-event', (self) => self.attribute.clicked = false);
|
||||
}
|
||||
});
|
||||
|
|
@ -1,122 +0,0 @@
|
|||
export const keybindList = [[
|
||||
{
|
||||
"icon": "pin_drop",
|
||||
"name": "Workspaces: navigation",
|
||||
"binds": [
|
||||
{ "keys": ["", "+", "#"], "action": "Go to workspace #" },
|
||||
{ "keys": ["", "+", "S"], "action": "Toggle special workspace" },
|
||||
{ "keys": ["", "+", "(Scroll ↑↓)"], "action": "Go to workspace -1/+1" },
|
||||
{ "keys": ["Ctrl", "", "+", "←"], "action": "Go to workspace on the left" },
|
||||
{ "keys": ["Ctrl", "", "+", "→"], "action": "Go to workspace on the right" },
|
||||
{ "keys": ["", "+", "PageUp"], "action": "Go to workspace on the left" },
|
||||
{ "keys": ["", "+", "PageDown"], "action": "Go to workspace on the right" }
|
||||
],
|
||||
"id": 1
|
||||
},
|
||||
{
|
||||
"icon": "overview_key",
|
||||
"name": "Workspaces: management",
|
||||
"binds": [
|
||||
{ "keys": ["", "Alt", "+", "#"], "action": "Move window to workspace #" },
|
||||
{ "keys": ["", "Alt", "+", "S"], "action": "Move window to special workspace" },
|
||||
{ "keys": ["", "Alt", "+", "PageUp"], "action": "Move window to workspace on the left" },
|
||||
{ "keys": ["", "Alt", "+", "PageDown"], "action": "Move window to workspace on the right" }
|
||||
],
|
||||
"id": 2
|
||||
},
|
||||
{
|
||||
"icon": "move_group",
|
||||
"name": "Windows",
|
||||
"binds": [
|
||||
{ "keys": ["", "+", "←↑→↓"], "action": "Focus window in direction" },
|
||||
{ "keys": ["", "Shift", "+", "←↑→↓"], "action": "Swap window in direction" },
|
||||
{ "keys": ["", "+", ";"], "action": "Split ratio -" },
|
||||
{ "keys": ["", "+", "'"], "action": "Split ratio +" },
|
||||
{ "keys": ["", "+", "Lmb"], "action": "Move window" },
|
||||
{ "keys": ["", "+", "Rmb"], "action": "Resize window" },
|
||||
{ "keys": ["", "Alt", "+", "Space"], "action": "Float window" },
|
||||
{ "keys": ["", "+", "F"], "action": "Fullscreen" },
|
||||
{ "keys": ["", "Alt", "+", "F"], "action": "Fake fullscreen" }
|
||||
],
|
||||
"id": 3
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"icon": "widgets",
|
||||
"name": "Widgets (AGS)",
|
||||
"binds": [
|
||||
{ "keys": ["", "OR", "", "+", "Tab"], "action": "Toggle overview/launcher" },
|
||||
{ "keys": ["Ctrl", "", "+", "R"], "action": "Restart AGS" },
|
||||
{ "keys": ["", "+", "/"], "action": "Toggle this cheatsheet" },
|
||||
{ "keys": ["", "+", "N"], "action": "Toggle system sidebar" },
|
||||
{ "keys": ["", "+", "B", "OR", "", "+", "O"], "action": "Toggle utilities sidebar" },
|
||||
{ "keys": ["", "+", "K"], "action": "Toggle virtual keyboard" },
|
||||
{ "keys": ["Ctrl", "Alt", "+", "Del"], "action": "Power/Session menu" },
|
||||
|
||||
{ "keys": ["Esc"], "action": "Exit a window" },
|
||||
{ "keys": ["rightCtrl"], "action": "Dismiss/close sidebar" },
|
||||
|
||||
{ "keys": ["Ctrl", "", "+", "T"], "action": "Change wallpaper+colorscheme" },
|
||||
|
||||
// { "keys": ["", "+", "B"], "action": "Toggle left sidebar" },
|
||||
// { "keys": ["", "+", "N"], "action": "Toggle right sidebar" },
|
||||
// { "keys": ["", "+", "G"], "action": "Toggle volume mixer" },
|
||||
// { "keys": ["", "+", "M"], "action": "Toggle useless audio visualizer" },
|
||||
// { "keys": ["(right)Ctrl"], "action": "Dismiss notification & close menus" }
|
||||
],
|
||||
"id": 4
|
||||
},
|
||||
{
|
||||
"icon": "construction",
|
||||
"name": "Utilities",
|
||||
"binds": [
|
||||
{ "keys": ["PrtSc"], "action": "Screenshot >> clipboard" },
|
||||
{ "keys": ["Ctrl", "PrtSc"], "action": "Screenshot >> file + clipboard" },
|
||||
{ "keys": ["", "Shift", "+", "S"], "action": "Screen snip >> clipboard" },
|
||||
{ "keys": ["", "Shift", "+", "T"], "action": "Image to text >> clipboard" },
|
||||
{ "keys": ["", "Shift", "+", "C"], "action": "Color picker" },
|
||||
{ "keys": ["", "Alt", "+", "R"], "action": "Record region" },
|
||||
{ "keys": ["Ctrl", "Alt", "+", "R"], "action": "Record region with sound" },
|
||||
{ "keys": ["", "Shift", "Alt", "+", "R"], "action": "Record screen with sound" }
|
||||
],
|
||||
"id": 5
|
||||
},
|
||||
],
|
||||
[
|
||||
{
|
||||
"icon": "apps",
|
||||
"name": "Apps",
|
||||
"binds": [
|
||||
{ "keys": ["", "+", "T"], "action": "Launch terminal: foot" },
|
||||
{ "keys": ["", "+", "W"], "action": "Launch browser: Firefox" },
|
||||
{ "keys": ["", "+", "C"], "action": "Launch editor: vscode" },
|
||||
{ "keys": ["", "+", "X"], "action": "Launch editor: GNOME Text Editor" },
|
||||
{ "keys": ["", "+", "I"], "action": "Launch settings: GNOME Control center" }
|
||||
],
|
||||
"id": 6
|
||||
},
|
||||
{
|
||||
"icon": "keyboard",
|
||||
"name": "Typing",
|
||||
"binds": [
|
||||
{ "keys": ["", "+", "V"], "action": "Clipboard history >> clipboard" },
|
||||
{ "keys": ["", "+", "."], "action": "Emoji picker >> clipboard" },
|
||||
],
|
||||
"id": 7
|
||||
},
|
||||
{
|
||||
"icon": "terminal",
|
||||
"name": "Launcher actions",
|
||||
"binds": [
|
||||
{ "keys": [">raw"], "action": "Toggle mouse acceleration" },
|
||||
{ "keys": [">img"], "action": "Select wallpaper and generate colorscheme" },
|
||||
{ "keys": [">light"], "action": "Switch to light theme" },
|
||||
{ "keys": [">dark"], "action": "Switch to dark theme" },
|
||||
{ "keys": [">badapple"], "action": "Apply black n' white colorscheme" },
|
||||
{ "keys": [">color"], "action": "Pick acccent color" },
|
||||
{ "keys": [">todo"], "action": "Type something after that to add a To-do item" },
|
||||
],
|
||||
"id": 8
|
||||
}
|
||||
]];
|
||||
|
|
@ -1,195 +0,0 @@
|
|||
export const periodicTable = [
|
||||
[
|
||||
{ name: 'Hydrogen', symbol: 'H', number: 1, weight: 1.01, type: 'nonmetal' },
|
||||
{ name: '', symbol: '', number: -1, weight: 0, type: 'empty' },
|
||||
{ name: '', symbol: '', number: -1, weight: 0, type: 'empty' },
|
||||
{ name: '', symbol: '', number: -1, weight: 0, type: 'empty' },
|
||||
{ name: '', symbol: '', number: -1, weight: 0, type: 'empty' },
|
||||
{ name: '', symbol: '', number: -1, weight: 0, type: 'empty' },
|
||||
{ name: '', symbol: '', number: -1, weight: 0, type: 'empty' },
|
||||
{ name: '', symbol: '', number: -1, weight: 0, type: 'empty' },
|
||||
{ name: '', symbol: '', number: -1, weight: 0, type: 'empty' },
|
||||
{ name: '', symbol: '', number: -1, weight: 0, type: 'empty' },
|
||||
{ name: '', symbol: '', number: -1, weight: 0, type: 'empty' },
|
||||
{ name: '', symbol: '', number: -1, weight: 0, type: 'empty' },
|
||||
{ name: '', symbol: '', number: -1, weight: 0, type: 'empty' },
|
||||
{ name: '', symbol: '', number: -1, weight: 0, type: 'empty' },
|
||||
{ name: '', symbol: '', number: -1, weight: 0, type: 'empty' },
|
||||
{ name: '', symbol: '', number: -1, weight: 0, type: 'empty' },
|
||||
{ name: '', symbol: '', number: -1, weight: 0, type: 'empty' },
|
||||
{ name: 'Helium', symbol: 'He', number: 2, weight: 4.00, type: 'noblegas' },
|
||||
],
|
||||
[
|
||||
{ name: 'Lithium', symbol: 'Li', number: 3, weight: 6.94, type: 'metal' },
|
||||
{ name: 'Beryllium', symbol: 'Be', number: 4, weight: 9.01, type: 'metal' },
|
||||
{ name: '', symbol: '', number: -1, weight: 0, type: 'empty' },
|
||||
{ name: '', symbol: '', number: -1, weight: 0, type: 'empty' },
|
||||
{ name: '', symbol: '', number: -1, weight: 0, type: 'empty' },
|
||||
{ name: '', symbol: '', number: -1, weight: 0, type: 'empty' },
|
||||
{ name: '', symbol: '', number: -1, weight: 0, type: 'empty' },
|
||||
{ name: '', symbol: '', number: -1, weight: 0, type: 'empty' },
|
||||
{ name: '', symbol: '', number: -1, weight: 0, type: 'empty' },
|
||||
{ name: '', symbol: '', number: -1, weight: 0, type: 'empty' },
|
||||
{ name: '', symbol: '', number: -1, weight: 0, type: 'empty' },
|
||||
{ name: '', symbol: '', number: -1, weight: 0, type: 'empty' },
|
||||
{ name: 'Boron', symbol: 'B', number: 5, weight: 10.81, type: 'nonmetal' },
|
||||
{ name: 'Carbon', symbol: 'C', number: 6, weight: 12.01, type: 'nonmetal' },
|
||||
{ name: 'Nitrogen', symbol: 'N', number: 7, weight: 14.01, type: 'nonmetal' },
|
||||
{ name: 'Oxygen', symbol: 'O', number: 8, weight: 16, type: 'nonmetal' },
|
||||
{ name: 'Fluorine', symbol: 'F', number: 9, weight: 19, type: 'nonmetal' },
|
||||
{ name: 'Neon', symbol: 'Ne', number: 10, weight: 20.18, type: 'noblegas' },
|
||||
|
||||
|
||||
],
|
||||
[
|
||||
{ name: 'Sodium', symbol: 'Na', number: 11, weight: 22.99, type: 'metal' },
|
||||
{ name: 'Magnesium', symbol: 'Mg', number: 12, weight: 24.31, type: 'metal' },
|
||||
{ name: '', symbol: '', number: -1, weight: 0, type: 'empty' },
|
||||
{ name: '', symbol: '', number: -1, weight: 0, type: 'empty' },
|
||||
{ name: '', symbol: '', number: -1, weight: 0, type: 'empty' },
|
||||
{ name: '', symbol: '', number: -1, weight: 0, type: 'empty' },
|
||||
{ name: '', symbol: '', number: -1, weight: 0, type: 'empty' },
|
||||
{ name: '', symbol: '', number: -1, weight: 0, type: 'empty' },
|
||||
{ name: '', symbol: '', number: -1, weight: 0, type: 'empty' },
|
||||
{ name: '', symbol: '', number: -1, weight: 0, type: 'empty' },
|
||||
{ name: '', symbol: '', number: -1, weight: 0, type: 'empty' },
|
||||
{ name: '', symbol: '', number: -1, weight: 0, type: 'empty' },
|
||||
{ name: 'Aluminum', symbol: 'Al', number: 13, weight: 26.98, type: 'metal' },
|
||||
{ name: 'Silicon', symbol: 'Si', number: 14, weight: 28.09, type: 'nonmetal' },
|
||||
{ name: 'Phosphorus', symbol: 'P', number: 15, weight: 30.97, type: 'nonmetal' },
|
||||
{ name: 'Sulfur', symbol: 'S', number: 16, weight: 32.07, type: 'nonmetal' },
|
||||
{ name: 'Chlorine', symbol: 'Cl', number: 17, weight: 35.45, type: 'nonmetal' },
|
||||
{ name: 'Argon', symbol: 'Ar', number: 18, weight: 39.95, type: 'noblegas' },
|
||||
],
|
||||
[
|
||||
{ name: 'Kalium', symbol: 'K', number: 19, weight: 39.098, type: 'metal' },
|
||||
{ name: 'Calcium', symbol: 'Ca', number: 20, weight: 40.078, type: 'metal' },
|
||||
{ name: 'Scandium', symbol: 'Sc', number: 21, weight: 44.956, type: 'metal' },
|
||||
{ name: 'Titanium', symbol: 'Ti', number: 22, weight: 47.87, type: 'metal' },
|
||||
{ name: 'Vanadium', symbol: 'V', number: 23, weight: 50.94, type: 'metal' },
|
||||
{ name: 'Chromium', symbol: 'Cr', number: 24, weight: 52, type: 'metal', icon: 'chromium-browser' },
|
||||
{ name: 'Manganese', symbol: 'Mn', number: 25, weight: 54.94, type: 'metal' },
|
||||
{ name: 'Iron', symbol: 'Fe', number: 26, weight: 55.85, type: 'metal' },
|
||||
{ name: 'Cobalt', symbol: 'Co', number: 27, weight: 58.93, type: 'metal' },
|
||||
{ name: 'Nickel', symbol: 'Ni', number: 28, weight: 58.69, type: 'metal' },
|
||||
{ name: 'Copper', symbol: 'Cu', number: 29, weight: 63.55, type: 'metal' },
|
||||
{ name: 'Zinc', symbol: 'Zn', number: 30, weight: 65.38, type: 'metal' },
|
||||
{ name: 'Gallium', symbol: 'Ga', number: 31, weight: 69.72, type: 'metal' },
|
||||
{ name: 'Germanium', symbol: 'Ge', number: 32, weight: 72.63, type: 'metal' },
|
||||
{ name: 'Arsenic', symbol: 'As', number: 33, weight: 74.92, type: 'nonmetal' },
|
||||
{ name: 'Selenium', symbol: 'Se', number: 34, weight: 78.96, type: 'nonmetal' },
|
||||
{ name: 'Bromine', symbol: 'Br', number: 35, weight: 79.904, type: 'nonmetal' },
|
||||
{ name: 'Krypton', symbol: 'Kr', number: 36, weight: 83.8, type: 'noblegas' },
|
||||
],
|
||||
[
|
||||
{ name: 'Rubidium', symbol: 'Rb', number: 37, weight: 85.47, type: 'metal' },
|
||||
{ name: 'Strontium', symbol: 'Sr', number: 38, weight: 87.62, type: 'metal' },
|
||||
{ name: 'Yttrium', symbol: 'Y', number: 39, weight: 88.91, type: 'metal' },
|
||||
{ name: 'Zirconium', symbol: 'Zr', number: 40, weight: 91.22, type: 'metal' },
|
||||
{ name: 'Niobium', symbol: 'Nb', number: 41, weight: 92.91, type: 'metal' },
|
||||
{ name: 'Molybdenum', symbol: 'Mo', number: 42, weight: 95.94, type: 'metal' },
|
||||
{ name: 'Technetium', symbol: 'Tc', number: 43, weight: 98, type: 'metal' },
|
||||
{ name: 'Ruthenium', symbol: 'Ru', number: 44, weight: 101.07, type: 'metal' },
|
||||
{ name: 'Rhodium', symbol: 'Rh', number: 45, weight: 102.91, type: 'metal' },
|
||||
{ name: 'Palladium', symbol: 'Pd', number: 46, weight: 106.42, type: 'metal' },
|
||||
{ name: 'Silver', symbol: 'Ag', number: 47, weight: 107.87, type: 'metal' },
|
||||
{ name: 'Cadmium', symbol: 'Cd', number: 48, weight: 112.41, type: 'metal' },
|
||||
{ name: 'Indium', symbol: 'In', number: 49, weight: 114.82, type: 'metal' },
|
||||
{ name: 'Tin', symbol: 'Sn', number: 50, weight: 118.71, type: 'metal' },
|
||||
{ name: 'Antimony', symbol: 'Sb', number: 51, weight: 121.76, type: 'metal' },
|
||||
{ name: 'Tellurium', symbol: 'Te', number: 52, weight: 127.6, type: 'nonmetal' },
|
||||
{ name: 'Iodine', symbol: 'I', number: 53, weight: 126.9, type: 'nonmetal' },
|
||||
{ name: 'Xenon', symbol: 'Xe', number: 54, weight: 131.29, type: 'noblegas' },
|
||||
],
|
||||
[
|
||||
{ name: 'Cesium', symbol: 'Cs', number: 55, weight: 132.91, type: 'metal' },
|
||||
{ name: 'Barium', symbol: 'Ba', number: 56, weight: 137.33, type: 'metal' },
|
||||
{ name: 'Lanthanum', symbol: 'La', number: 57, weight: 138.91, type: 'lanthanum' },
|
||||
{ name: 'Hafnium', symbol: 'Hf', number: 72, weight: 178.49, type: 'metal' },
|
||||
{ name: 'Tantalum', symbol: 'Ta', number: 73, weight: 180.95, type: 'metal' },
|
||||
{ name: 'Tungsten', symbol: 'W', number: 74, weight: 183.84, type: 'metal' },
|
||||
{ name: 'Rhenium', symbol: 'Re', number: 75, weight: 186.21, type: 'metal' },
|
||||
{ name: 'Osmium', symbol: 'Os', number: 76, weight: 190.23, type: 'metal' },
|
||||
{ name: 'Iridium', symbol: 'Ir', number: 77, weight: 192.22, type: 'metal' },
|
||||
{ name: 'Platinum', symbol: 'Pt', number: 78, weight: 195.09, type: 'metal' },
|
||||
{ name: 'Gold', symbol: 'Au', number: 79, weight: 196.97, type: 'metal' },
|
||||
{ name: 'Mercury', symbol: 'Hg', number: 80, weight: 200.59, type: 'metal' },
|
||||
{ name: 'Thallium', symbol: 'Tl', number: 81, weight: 204.38, type: 'metal' },
|
||||
{ name: 'Lead', symbol: 'Pb', number: 82, weight: 207.2, type: 'metal' },
|
||||
{ name: 'Bismuth', symbol: 'Bi', number: 83, weight: 208.98, type: 'metal' },
|
||||
{ name: 'Polonium', symbol: 'Po', number: 84, weight: 209, type: 'metal' },
|
||||
{ name: 'Astatine', symbol: 'At', number: 85, weight: 210, type: 'nonmetal' },
|
||||
{ name: 'Radon', symbol: 'Rn', number: 86, weight: 222, type: 'noblegas' },
|
||||
],
|
||||
[
|
||||
{ name: 'Francium', symbol: 'Fr', number: 87, weight: 223, type: 'metal' },
|
||||
{ name: 'Radium', symbol: 'Ra', number: 88, weight: 226, type: 'metal' },
|
||||
{ name: 'Actinium', symbol: 'Ac', number: 89, weight: 227, type: 'actinium' },
|
||||
{ name: 'Rutherfordium', symbol: 'Rf', number: 104, weight: 267, type: 'metal' },
|
||||
{ name: 'Dubnium', symbol: 'Db', number: 105, weight: 268, type: 'metal' },
|
||||
{ name: 'Seaborgium', symbol: 'Sg', number: 106, weight: 271, type: 'metal' },
|
||||
{ name: 'Bohrium', symbol: 'Bh', number: 107, weight: 272, type: 'metal' },
|
||||
{ name: 'Hassium', symbol: 'Hs', number: 108, weight: 277, type: 'metal' },
|
||||
{ name: 'Meitnerium', symbol: 'Mt', number: 109, weight: 278, type: 'metal' },
|
||||
{ name: 'Darmstadtium', symbol: 'Ds', number: 110, weight: 281, type: 'metal' },
|
||||
{ name: 'Roentgenium', symbol: 'Rg', number: 111, weight: 280, type: 'metal' },
|
||||
{ name: 'Copernicium', symbol: 'Cn', number: 112, weight: 285, type: 'metal' },
|
||||
{ name: 'Nihonium', symbol: 'Nh', number: 113, weight: 286, type: 'metal' },
|
||||
{ name: 'Flerovium', symbol: 'Fl', number: 114, weight: 289, type: 'metal' },
|
||||
{ name: 'Moscovium', symbol: 'Mc', number: 115, weight: 290, type: 'metal' },
|
||||
{ name: 'Livermorium', symbol: 'Lv', number: 116, weight: 293, type: 'metal' },
|
||||
{ name: 'Tennessine', symbol: 'Ts', number: 117, weight: 294, type: 'metal' },
|
||||
{ name: 'Oganesson', symbol: 'Og', number: 118, weight: 294, type: 'noblegas' },
|
||||
],
|
||||
]
|
||||
|
||||
export const series = [
|
||||
[
|
||||
{ name: '', symbol: '', number: -1, weight: 0, type: 'empty' },
|
||||
{ name: '', symbol: '', number: -1, weight: 0, type: 'empty' },
|
||||
{ name: '', symbol: '', number: -1, weight: 0, type: 'empty' },
|
||||
{ name: 'Cerium', symbol: 'Ce', number: 58, weight: 140.12, type: 'lanthanum' },
|
||||
{ name: 'Praseodymium', symbol: 'Pr', number: 59, weight: 140.91, type: 'lanthanum' },
|
||||
{ name: 'Neodymium', symbol: 'Nd', number: 60, weight: 144.24, type: 'lanthanum' },
|
||||
{ name: 'Promethium', symbol: 'Pm', number: 61, weight: 145, type: 'lanthanum' },
|
||||
{ name: 'Samarium', symbol: 'Sm', number: 62, weight: 150.36, type: 'lanthanum' },
|
||||
{ name: 'Europium', symbol: 'Eu', number: 63, weight: 151.96, type: 'lanthanum' },
|
||||
{ name: 'Gadolinium', symbol: 'Gd', number: 64, weight: 157.25, type: 'lanthanum' },
|
||||
{ name: 'Terbium', symbol: 'Tb', number: 65, weight: 158.93, type: 'lanthanum' },
|
||||
{ name: 'Dysprosium', symbol: 'Dy', number: 66, weight: 162.5, type: 'lanthanum' },
|
||||
{ name: 'Holmium', symbol: 'Ho', number: 67, weight: 164.93, type: 'lanthanum' },
|
||||
{ name: 'Erbium', symbol: 'Er', number: 68, weight: 167.26, type: 'lanthanum' },
|
||||
{ name: 'Thulium', symbol: 'Tm', number: 69, weight: 168.93, type: 'lanthanum' },
|
||||
{ name: 'Ytterbium', symbol: 'Yb', number: 70, weight: 173.04, type: 'lanthanum' },
|
||||
{ name: 'Lutetium', symbol: 'Lu', number: 71, weight: 174.97, type: 'lanthanum' },
|
||||
{ name: '', symbol: '', number: -1, weight: 0, type: 'empty' },
|
||||
],
|
||||
[
|
||||
{ name: '', symbol: '', number: -1, weight: 0, type: 'empty' },
|
||||
{ name: '', symbol: '', number: -1, weight: 0, type: 'empty' },
|
||||
{ name: '', symbol: '', number: -1, weight: 0, type: 'empty' },
|
||||
{ name: 'Thorium', symbol: 'Th', number: 90, weight: 232.04, type: 'actinium' },
|
||||
{ name: 'Protactinium', symbol: 'Pa', number: 91, weight: 231.04, type: 'actinium' },
|
||||
{ name: 'Uranium', symbol: 'U', number: 92, weight: 238.03, type: 'actinium' },
|
||||
{ name: 'Neptunium', symbol: 'Np', number: 93, weight: 237, type: 'actinium' },
|
||||
{ name: 'Plutonium', symbol: 'Pu', number: 94, weight: 244, type: 'actinium' },
|
||||
{ name: 'Americium', symbol: 'Am', number: 95, weight: 243, type: 'actinium' },
|
||||
{ name: 'Curium', symbol: 'Cm', number: 96, weight: 247, type: 'actinium' },
|
||||
{ name: 'Berkelium', symbol: 'Bk', number: 97, weight: 247, type: 'actinium' },
|
||||
{ name: 'Californium', symbol: 'Cf', number: 98, weight: 251, type: 'actinium' },
|
||||
{ name: 'Einsteinium', symbol: 'Es', number: 99, weight: 252, type: 'actinium' },
|
||||
{ name: 'Fermium', symbol: 'Fm', number: 100, weight: 257, type: 'actinium' },
|
||||
{ name: 'Mendelevium', symbol: 'Md', number: 101, weight: 258, type: 'actinium' },
|
||||
{ name: 'Nobelium', symbol: 'No', number: 102, weight: 259, type: 'actinium' },
|
||||
{ name: 'Lawrencium', symbol: 'Lr', number: 103, weight: 262, type: 'actinium' },
|
||||
{ name: '', symbol: '', number: -1, weight: 0, type: 'empty' },
|
||||
],
|
||||
];
|
||||
|
||||
export const niceTypes = {
|
||||
'metal': "Metal",
|
||||
'nonmetal': "Nonmetal",
|
||||
'noblegas': "Noble gas",
|
||||
'lanthanum': "Lanthanum",
|
||||
'actinium': "Actinium"
|
||||
}
|
||||
|
|
@ -1,126 +0,0 @@
|
|||
const { GLib, Gtk } = imports.gi;
|
||||
import App from "resource:///com/github/Aylur/ags/app.js";
|
||||
import * as Utils from "resource:///com/github/Aylur/ags/utils.js";
|
||||
import Widget from "resource:///com/github/Aylur/ags/widget.js";
|
||||
import { IconTabContainer } from "../.commonwidgets/tabcontainer.js";
|
||||
const { Box, Label, Scrollable } = Widget;
|
||||
|
||||
const HYPRLAND_KEYBIND_CONFIG_FILE = userOptions.cheatsheet.keybinds.configPath ?
|
||||
userOptions.cheatsheet.keybinds.configPath : `${GLib.get_user_config_dir()}/hypr/hyprland/keybinds.conf`;
|
||||
const KEYBIND_SECTIONS_PER_PAGE = 3;
|
||||
const getKeybindList = () => {
|
||||
let data = Utils.exec(`${App.configDir}/scripts/hyprland/get_keybinds.py --path ${HYPRLAND_KEYBIND_CONFIG_FILE}`);
|
||||
if (data == "\"error\"") {
|
||||
Utils.timeout(2000, () => Utils.execAsync(['notify-send',
|
||||
'Update path to keybinds',
|
||||
'Keybinds hyprland config file not found. Check your user options.',
|
||||
'-a', 'ags',
|
||||
]).catch(print))
|
||||
return { children: [] };
|
||||
}
|
||||
return JSON.parse(data);
|
||||
};
|
||||
const keybindList = getKeybindList();
|
||||
|
||||
const keySubstitutions = {
|
||||
"Super": "",
|
||||
"mouse_up": "Scroll ↓", // ikr, weird
|
||||
"mouse_down": "Scroll ↑", // trust me bro
|
||||
"mouse:272": "LMB",
|
||||
"mouse:273": "RMB",
|
||||
"mouse:275": "MouseBack",
|
||||
"Slash": "/",
|
||||
"Hash": "#"
|
||||
}
|
||||
|
||||
const substituteKey = (key) => {
|
||||
return keySubstitutions[key] || key;
|
||||
}
|
||||
|
||||
const Keybind = (keybindData, type) => { // type: either "keys" or "actions"
|
||||
const Key = (key) => Label({ // Specific keys
|
||||
vpack: 'center',
|
||||
className: `${['OR', '+'].includes(key) ? 'cheatsheet-key-notkey' : 'cheatsheet-key'} txt-small`,
|
||||
label: substituteKey(key),
|
||||
});
|
||||
const Action = (text) => Label({ // Binds
|
||||
xalign: 0,
|
||||
label: getString(text),
|
||||
className: "txt txt-small cheatsheet-action",
|
||||
})
|
||||
return Widget.Box({
|
||||
className: "spacing-h-10 cheatsheet-bind-lineheight",
|
||||
children: type == "keys" ? [
|
||||
...(keybindData.mods.length > 0 ? [
|
||||
...keybindData.mods.map(Key),
|
||||
Key("+"),
|
||||
] : []),
|
||||
Key(keybindData.key),
|
||||
] : [Action(keybindData.comment)],
|
||||
})
|
||||
}
|
||||
|
||||
const Section = (sectionData, scope) => {
|
||||
const keys = Box({
|
||||
vertical: true,
|
||||
className: 'spacing-v-5',
|
||||
children: sectionData.keybinds.map((data) => Keybind(data, "keys"))
|
||||
})
|
||||
const actions = Box({
|
||||
vertical: true,
|
||||
className: 'spacing-v-5',
|
||||
children: sectionData.keybinds.map((data) => Keybind(data, "actions"))
|
||||
})
|
||||
const name = Label({
|
||||
xalign: 0,
|
||||
className: "cheatsheet-category-title txt margin-bottom-10",
|
||||
label: getString(sectionData.name),
|
||||
})
|
||||
const binds = Box({
|
||||
className: 'spacing-h-10',
|
||||
children: [
|
||||
keys,
|
||||
actions,
|
||||
]
|
||||
})
|
||||
const childrenSections = Box({
|
||||
vertical: true,
|
||||
className: 'spacing-v-15',
|
||||
children: sectionData.children.map((data) => Section(data, scope + 1))
|
||||
})
|
||||
return Box({
|
||||
vertical: true,
|
||||
children: [
|
||||
...((sectionData.name && sectionData.name.length > 0) ? [name] : []),
|
||||
Box({
|
||||
className: 'spacing-v-10',
|
||||
children: [
|
||||
binds,
|
||||
childrenSections,
|
||||
]
|
||||
})
|
||||
]
|
||||
})
|
||||
};
|
||||
|
||||
export default () => {
|
||||
const numOfTabs = Math.ceil(keybindList.children.length / KEYBIND_SECTIONS_PER_PAGE);
|
||||
const keybindPages = Array.from({ length: numOfTabs }, (_, i) => ({
|
||||
iconWidget: Label({
|
||||
className: "txt txt-small",
|
||||
label: `${i + 1}`,
|
||||
}),
|
||||
name: `${i + 1}`,
|
||||
child: Box({
|
||||
className: 'spacing-h-30',
|
||||
children: keybindList.children.slice(
|
||||
KEYBIND_SECTIONS_PER_PAGE * i, 0 + KEYBIND_SECTIONS_PER_PAGE * (i + 1),
|
||||
).map(data => Section(data, 1)),
|
||||
}),
|
||||
}));
|
||||
return IconTabContainer({
|
||||
iconWidgets: keybindPages.map((kbp) => kbp.iconWidget),
|
||||
names: keybindPages.map((kbp) => kbp.name),
|
||||
children: keybindPages.map((kbp) => kbp.child),
|
||||
});
|
||||
};
|
||||
|
|
@ -1,146 +0,0 @@
|
|||
import Widget from 'resource:///com/github/Aylur/ags/widget.js';
|
||||
import { setupCursorHover } from "../.widgetutils/cursorhover.js";
|
||||
import PopupWindow from '../.widgethacks/popupwindow.js';
|
||||
import Keybinds from "./keybinds.js";
|
||||
import PeriodicTable from "./periodictable.js";
|
||||
import { ExpandingIconTabContainer } from '../.commonwidgets/tabcontainer.js';
|
||||
import { checkKeybind } from '../.widgetutils/keybind.js';
|
||||
import clickCloseRegion from '../.commonwidgets/clickcloseregion.js';
|
||||
|
||||
const cheatsheets = [
|
||||
{
|
||||
name: getString('Keybinds'),
|
||||
materialIcon: 'keyboard',
|
||||
contentWidget: Keybinds,
|
||||
},
|
||||
{
|
||||
name: getString('Periodic table'),
|
||||
materialIcon: 'experiment',
|
||||
contentWidget: PeriodicTable,
|
||||
},
|
||||
];
|
||||
|
||||
const CheatsheetHeader = () => Widget.CenterBox({
|
||||
vertical: false,
|
||||
startWidget: Widget.Box({}),
|
||||
centerWidget: Widget.Box({
|
||||
vertical: true,
|
||||
className: "spacing-h-15",
|
||||
children: [
|
||||
Widget.Box({
|
||||
hpack: 'center',
|
||||
className: 'spacing-h-5 cheatsheet-title',
|
||||
children: [
|
||||
Widget.Label({
|
||||
hpack: 'center',
|
||||
css: 'margin-right: 0.682rem;',
|
||||
className: 'txt-title',
|
||||
label: getString('Cheat sheet'),
|
||||
}),
|
||||
Widget.Label({
|
||||
vpack: 'center',
|
||||
className: "cheatsheet-key txt-small",
|
||||
label: "",
|
||||
}),
|
||||
Widget.Label({
|
||||
vpack: 'center',
|
||||
className: "cheatsheet-key-notkey txt-small",
|
||||
label: "+",
|
||||
}),
|
||||
Widget.Label({
|
||||
vpack: 'center',
|
||||
className: "cheatsheet-key txt-small",
|
||||
label: "/",
|
||||
})
|
||||
]
|
||||
}),
|
||||
]
|
||||
}),
|
||||
endWidget: Widget.Button({
|
||||
vpack: 'start',
|
||||
hpack: 'end',
|
||||
className: "cheatsheet-closebtn icon-material txt txt-hugeass",
|
||||
onClicked: () => {
|
||||
closeWindowOnAllMonitors('cheatsheet');
|
||||
},
|
||||
child: Widget.Label({
|
||||
className: 'icon-material txt txt-hugeass',
|
||||
label: 'close'
|
||||
}),
|
||||
setup: setupCursorHover,
|
||||
}),
|
||||
});
|
||||
|
||||
const sheetContents = [];
|
||||
const SheetContent = (id) => {
|
||||
sheetContents[id] = ExpandingIconTabContainer({
|
||||
tabsHpack: 'center',
|
||||
tabSwitcherClassName: 'sidebar-icontabswitcher',
|
||||
transitionDuration: userOptions.animations.durationLarge * 1.4,
|
||||
icons: cheatsheets.map((api) => api.materialIcon),
|
||||
names: cheatsheets.map((api) => api.name),
|
||||
children: cheatsheets.map((api) => api.contentWidget()),
|
||||
onChange: (self, id) => {
|
||||
self.shown = cheatsheets[id].name;
|
||||
}
|
||||
});
|
||||
return sheetContents[id];
|
||||
}
|
||||
|
||||
export default (id) => {
|
||||
const sheets = SheetContent(id);
|
||||
const widgetContent = Widget.Box({
|
||||
vertical: true,
|
||||
className: "cheatsheet-bg spacing-v-5",
|
||||
children: [
|
||||
CheatsheetHeader(),
|
||||
sheets,
|
||||
]
|
||||
});
|
||||
return PopupWindow({
|
||||
monitor: id,
|
||||
name: `cheatsheet${id}`,
|
||||
layer: 'top',
|
||||
keymode: 'on-demand',
|
||||
visible: false,
|
||||
anchor: ['top', 'bottom', 'left', 'right'],
|
||||
child: Widget.Box({
|
||||
vertical: true,
|
||||
children: [
|
||||
clickCloseRegion({ name: 'cheatsheet' }),
|
||||
Widget.Box({
|
||||
children: [
|
||||
clickCloseRegion({ name: 'cheatsheet' }),
|
||||
widgetContent,
|
||||
clickCloseRegion({ name: 'cheatsheet' }),
|
||||
]
|
||||
}),
|
||||
clickCloseRegion({ name: 'cheatsheet' }),
|
||||
],
|
||||
setup: (self) => self.on('key-press-event', (widget, event) => { // Typing
|
||||
// Whole sheet
|
||||
if (checkKeybind(event, userOptions.keybinds.cheatsheet.nextTab))
|
||||
sheetContents.forEach(tab => tab.nextTab())
|
||||
else if (checkKeybind(event, userOptions.keybinds.cheatsheet.prevTab))
|
||||
sheetContents.forEach(tab => tab.prevTab())
|
||||
else if (checkKeybind(event, userOptions.keybinds.cheatsheet.cycleTab))
|
||||
sheetContents.forEach(tab => tab.cycleTab())
|
||||
// Keybinds
|
||||
if (sheets.attribute.names[sheets.attribute.shown.value] == 'Keybinds') { // If Keybinds tab is focused
|
||||
if (checkKeybind(event, userOptions.keybinds.cheatsheet.keybinds.nextTab)) {
|
||||
sheetContents.forEach((sheet) => {
|
||||
const toSwitchTab = sheet.attribute.children[sheet.attribute.shown.value];
|
||||
toSwitchTab.nextTab();
|
||||
})
|
||||
}
|
||||
else if (checkKeybind(event, userOptions.keybinds.cheatsheet.keybinds.prevTab)) {
|
||||
sheetContents.forEach((sheet) => {
|
||||
const toSwitchTab = sheet.attribute.children[sheet.attribute.shown.value];
|
||||
toSwitchTab.prevTab();
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
});
|
||||
}
|
||||
|
|
@ -1,94 +0,0 @@
|
|||
import Widget from 'resource:///com/github/Aylur/ags/widget.js';
|
||||
import { niceTypes, periodicTable, series } from "./data_periodictable.js";
|
||||
const { Box, Button, Icon, Label, Revealer } = Widget;
|
||||
|
||||
export default () => {
|
||||
const ElementTile = (element) => {
|
||||
return Box({
|
||||
vertical: true,
|
||||
tooltipText: element.electronConfig ? `${element.electronConfig}` : null,
|
||||
className: `cheatsheet-periodictable-${element.type}`,
|
||||
children: element.name == '' ? null : [
|
||||
Box({
|
||||
className: 'padding-left-8 padding-right-8 padding-top-8',
|
||||
children: [
|
||||
Label({
|
||||
label: `${element.number}`,
|
||||
className: "cheatsheet-periodictable-elementnum txt-tiny txt-bold",
|
||||
}),
|
||||
Box({ hexpand: true }),
|
||||
Label({
|
||||
label: `${element.weight}`,
|
||||
className: "txt-smaller",
|
||||
})
|
||||
]
|
||||
}),
|
||||
element.icon ? Icon({
|
||||
icon: element.icon,
|
||||
className: "txt-hugerass txt-bold",
|
||||
}) : Label({
|
||||
label: `${element.symbol}`,
|
||||
className: "cheatsheet-periodictable-elementsymbol",
|
||||
}),
|
||||
Label({
|
||||
label: `${element.name}`,
|
||||
className: "txt-tiny",
|
||||
})
|
||||
]
|
||||
})
|
||||
}
|
||||
const BoardColor = (type) => Box({
|
||||
className: 'spacing-h-5',
|
||||
children: [
|
||||
Box({
|
||||
homogeneous: true,
|
||||
className: `cheatsheet-periodictable-legend-color-wrapper`,
|
||||
children: [Box({
|
||||
className: `cheatsheet-periodictable-legend-color-${type}`,
|
||||
})]
|
||||
}),
|
||||
Label({
|
||||
label: `${niceTypes[type]}`,
|
||||
className: "txt txt-small",
|
||||
})
|
||||
]
|
||||
})
|
||||
const mainBoard = Box({
|
||||
hpack: 'center',
|
||||
vertical: true,
|
||||
className: "spacing-v-3",
|
||||
children: periodicTable.map((row, _) => Box({ // Rows
|
||||
className: "spacing-h-5",
|
||||
children: row.map((element, _) => ElementTile(element))
|
||||
})),
|
||||
});
|
||||
const seriesBoard = Box({
|
||||
hpack: 'center',
|
||||
vertical: true,
|
||||
className: "spacing-v-3",
|
||||
children: series.map((row, _) => Box({ // Rows
|
||||
className: "spacing-h-5",
|
||||
children: row.map((element, _) => ElementTile(element))
|
||||
})),
|
||||
});
|
||||
const legend = Box({
|
||||
hpack: 'center',
|
||||
className: 'spacing-h-20',
|
||||
children: [
|
||||
BoardColor('metal'),
|
||||
BoardColor('nonmetal'),
|
||||
BoardColor('noblegas'),
|
||||
BoardColor('lanthanum'),
|
||||
BoardColor('actinium'),
|
||||
]
|
||||
})
|
||||
return Box({
|
||||
vertical: true,
|
||||
className: 'spacing-v-20',
|
||||
children: [
|
||||
mainBoard,
|
||||
seriesBoard,
|
||||
legend
|
||||
]
|
||||
})
|
||||
}
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
import Widget from 'resource:///com/github/Aylur/ags/widget.js';
|
||||
import { enableClickthrough } from "../.widgetutils/clickthrough.js";
|
||||
|
||||
export default (monitor = 0, ) => {
|
||||
return Widget.Window({
|
||||
monitor,
|
||||
name: `crosshair${monitor}`,
|
||||
layer: 'overlay',
|
||||
exclusivity: 'ignore',
|
||||
visible: false,
|
||||
child: Widget.Icon({
|
||||
icon: 'crosshair-symbolic',
|
||||
css: `
|
||||
font-size: ${userOptions.gaming.crosshair.size}px;
|
||||
color: ${userOptions.gaming.crosshair.color};
|
||||
`,
|
||||
}),
|
||||
setup: enableClickthrough,
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
export const quickLaunchItems = [
|
||||
{
|
||||
"name": "GitHub + Files×2",
|
||||
"command": "github-desktop & nautilus --new-window & nautilus --new-window &"
|
||||
},
|
||||
{
|
||||
"name": "Terminal×2",
|
||||
"command": "foot & foot &"
|
||||
},
|
||||
{
|
||||
"name": "Discord + Youtube + Github",
|
||||
"command": "xdg-open 'https://discord.com/app' && xdg-open 'https://youtube.com/' && xdg-open 'https://github.com/' &"
|
||||
},
|
||||
]
|
||||
|
|
@ -1,24 +0,0 @@
|
|||
import Widget from 'resource:///com/github/Aylur/ags/widget.js';
|
||||
|
||||
import WallpaperImage from './wallpaper.js';
|
||||
import TimeAndLaunchesWidget from './timeandlaunches.js'
|
||||
import SystemWidget from './system.js'
|
||||
|
||||
export default (monitor) => Widget.Window({
|
||||
name: `desktopbackground${monitor}`,
|
||||
// anchor: ['top', 'bottom', 'left', 'right'],
|
||||
layer: 'background',
|
||||
exclusivity: 'ignore',
|
||||
visible: true,
|
||||
child: Widget.Overlay({
|
||||
child: WallpaperImage(monitor),
|
||||
// child: Widget.Box({}),
|
||||
overlays: [
|
||||
TimeAndLaunchesWidget(),
|
||||
SystemWidget(),
|
||||
],
|
||||
setup: (self) => {
|
||||
self.set_overlay_pass_through(self.get_children()[1], true);
|
||||
},
|
||||
}),
|
||||
});
|
||||
|
|
@ -1,161 +0,0 @@
|
|||
import Widget from 'resource:///com/github/Aylur/ags/widget.js';
|
||||
import * as Utils from 'resource:///com/github/Aylur/ags/utils.js';
|
||||
const { execAsync, exec } = Utils;
|
||||
const { Box, EventBox, Label, Revealer, Overlay } = Widget;
|
||||
import { AnimatedCircProg } from "../.commonwidgets/cairo_circularprogress.js";
|
||||
import { MaterialIcon } from '../.commonwidgets/materialicon.js';
|
||||
|
||||
const ResourceValue = (name, icon, interval, valueUpdateCmd, displayFunc, props = {}) => Box({
|
||||
...props,
|
||||
className: 'bg-system-bg txt',
|
||||
children: [
|
||||
Revealer({
|
||||
transition: 'slide_left',
|
||||
transitionDuration: userOptions.animations.durationLarge,
|
||||
child: Box({
|
||||
vpack: 'center',
|
||||
vertical: true,
|
||||
className: 'margin-right-15',
|
||||
children: [
|
||||
Label({
|
||||
xalign: 1,
|
||||
className: 'txt-small txt',
|
||||
label: `${name}`,
|
||||
}),
|
||||
Label({
|
||||
xalign: 1,
|
||||
className: 'titlefont txt-norm txt-onSecondaryContainer',
|
||||
setup: (self) => self
|
||||
.poll(interval, (label) => displayFunc(label))
|
||||
,
|
||||
})
|
||||
]
|
||||
})
|
||||
}),
|
||||
Overlay({
|
||||
child: AnimatedCircProg({
|
||||
className: 'bg-system-circprog',
|
||||
extraSetup: (self) => self
|
||||
.poll(interval, (self) => {
|
||||
execAsync(['bash', '-c', `${valueUpdateCmd}`]).then((newValue) => {
|
||||
self.css = `font-size: ${Math.round(newValue)}px;`
|
||||
}).catch(print);
|
||||
})
|
||||
,
|
||||
}),
|
||||
overlays: [
|
||||
MaterialIcon(`${icon}`, 'hugeass'),
|
||||
],
|
||||
setup: self => self.set_overlay_pass_through(self.get_children()[1], true),
|
||||
}),
|
||||
]
|
||||
})
|
||||
|
||||
const resources = Box({
|
||||
vpack: 'fill',
|
||||
vertical: true,
|
||||
className: 'spacing-v-15',
|
||||
children: [
|
||||
ResourceValue('Memory', 'memory', 10000, `free | awk '/^Mem/ {printf("%.2f\\n", ($3/$2) * 100)}'`,
|
||||
(label) => {
|
||||
execAsync(['bash', '-c', `free -h | awk '/^Mem/ {print $3 " / " $2}' | sed 's/Gi/Gib/g'`])
|
||||
.then((output) => {
|
||||
label.label = `${output}`
|
||||
}).catch(print);
|
||||
}, { hpack: 'end' }),
|
||||
ResourceValue('Swap', 'swap_horiz', 10000, `free | awk '/^Swap/ {if ($2 > 0) printf("%.2f\\n", ($3/$2) * 100); else print "0";}'`,
|
||||
(label) => {
|
||||
execAsync(['bash', '-c', `free -h | awk '/^Swap/ {if ($2 != "0") print $3 " / " $2; else print "No swap"}' | sed 's/Gi/Gib/g'`])
|
||||
.then((output) => {
|
||||
label.label = `${output}`
|
||||
}).catch(print);
|
||||
}, { hpack: 'end' }),
|
||||
ResourceValue('Disk space', 'hard_drive_2', 3600000, `echo $(df --output=pcent / | tr -dc '0-9')`,
|
||||
(label) => {
|
||||
execAsync(['bash', '-c', `df -h --output=avail / | awk 'NR==2{print $1}'`])
|
||||
.then((output) => {
|
||||
label.label = `${output} available`
|
||||
}).catch(print);
|
||||
}, { hpack: 'end' }),
|
||||
]
|
||||
});
|
||||
|
||||
const distroAndVersion = Box({
|
||||
vertical: true,
|
||||
children: [
|
||||
Box({
|
||||
hpack: 'end',
|
||||
children: [
|
||||
Label({
|
||||
className: 'bg-distro-txt',
|
||||
xalign: 0,
|
||||
label: 'Hyping on ',
|
||||
}),
|
||||
Label({
|
||||
className: 'bg-distro-name',
|
||||
xalign: 0,
|
||||
label: '<distro>',
|
||||
setup: (label) => {
|
||||
execAsync([`grep`, `-oP`, `PRETTY_NAME="\\K[^"]+`, `/etc/os-release`]).then(distro => {
|
||||
label.label = distro;
|
||||
}).catch(print);
|
||||
},
|
||||
}),
|
||||
]
|
||||
}),
|
||||
Box({
|
||||
hpack: 'end',
|
||||
children: [
|
||||
Label({
|
||||
className: 'bg-distro-txt',
|
||||
xalign: 0,
|
||||
label: 'with ',
|
||||
}),
|
||||
Label({
|
||||
className: 'bg-distro-name',
|
||||
xalign: 0,
|
||||
label: 'An environment idk',
|
||||
setup: (label) => {
|
||||
// hyprctl will return unsuccessfully if Hyprland isn't running
|
||||
execAsync([`bash`, `-c`, `hyprctl version | grep -oP "Tag: v\\K\\d+\\.\\d+\\.\\d+"`]).then(version => {
|
||||
label.label = `Hyprland ${version}`;
|
||||
}).catch(() => execAsync([`bash`, `-c`, `sway -v | cut -d'-' -f1 | sed 's/sway version /v/'`]).then(version => {
|
||||
label.label = `Sway ${version}`;
|
||||
}).catch(print));
|
||||
},
|
||||
}),
|
||||
]
|
||||
})
|
||||
]
|
||||
})
|
||||
|
||||
export default () => Box({
|
||||
hpack: 'end',
|
||||
vpack: 'end',
|
||||
children: [
|
||||
EventBox({
|
||||
child: Box({
|
||||
hpack: 'end',
|
||||
vpack: 'end',
|
||||
className: 'bg-distro-box spacing-v-20',
|
||||
vertical: true,
|
||||
children: [
|
||||
resources,
|
||||
distroAndVersion,
|
||||
]
|
||||
}),
|
||||
onPrimaryClickRelease: () => {
|
||||
const kids = resources.get_children();
|
||||
for (let i = 0; i < kids.length; i++) {
|
||||
const child = kids[i];
|
||||
const firstChild = child.get_children()[0];
|
||||
firstChild.revealChild = !firstChild.revealChild;
|
||||
}
|
||||
|
||||
},
|
||||
})
|
||||
],
|
||||
})
|
||||
|
||||
|
||||
|
||||
|
|
@ -1,74 +0,0 @@
|
|||
const { GLib } = imports.gi;
|
||||
import App from 'resource:///com/github/Aylur/ags/app.js';
|
||||
import Widget from 'resource:///com/github/Aylur/ags/widget.js';
|
||||
import Service from 'resource:///com/github/Aylur/ags/service.js';
|
||||
import * as Utils from 'resource:///com/github/Aylur/ags/utils.js';
|
||||
|
||||
import Variable from 'resource:///com/github/Aylur/ags/variable.js';
|
||||
const { execAsync, exec } = Utils;
|
||||
const { Box, Label, Button, Revealer, EventBox } = Widget;
|
||||
import { setupCursorHover } from '../.widgetutils/cursorhover.js';
|
||||
import { quickLaunchItems } from './data_quicklaunches.js'
|
||||
|
||||
const TimeAndDate = () => Box({
|
||||
vertical: true,
|
||||
className: 'spacing-v--5',
|
||||
children: [
|
||||
Label({
|
||||
className: 'bg-time-clock',
|
||||
xalign: 0,
|
||||
label: GLib.DateTime.new_now_local().format(userOptions.time.format),
|
||||
setup: (self) => self.poll(userOptions.time.interval, label => {
|
||||
label.label = GLib.DateTime.new_now_local().format(userOptions.time.format);
|
||||
}),
|
||||
}),
|
||||
Label({
|
||||
className: 'bg-time-date',
|
||||
xalign: 0,
|
||||
label: GLib.DateTime.new_now_local().format(userOptions.time.dateFormatLong),
|
||||
setup: (self) => self.poll(userOptions.time.dateInterval, (label) => {
|
||||
label.label = GLib.DateTime.new_now_local().format(userOptions.time.dateFormatLong);
|
||||
}),
|
||||
}),
|
||||
]
|
||||
})
|
||||
|
||||
const QuickLaunches = () => Box({
|
||||
vertical: true,
|
||||
className: 'spacing-v-10',
|
||||
children: [
|
||||
Label({
|
||||
xalign: 0,
|
||||
className: 'bg-quicklaunch-title',
|
||||
label: 'Quick Launches',
|
||||
}),
|
||||
Box({
|
||||
hpack: 'start',
|
||||
className: 'spacing-h-5',
|
||||
children: quickLaunchItems.map((item, i) => Button({
|
||||
onClicked: () => {
|
||||
execAsync(['bash', '-c', `${item["command"]}`]).catch(print);
|
||||
},
|
||||
className: 'bg-quicklaunch-btn',
|
||||
child: Label({
|
||||
label: `${item["name"]}`,
|
||||
}),
|
||||
setup: (self) => {
|
||||
setupCursorHover(self);
|
||||
}
|
||||
})),
|
||||
})
|
||||
]
|
||||
})
|
||||
|
||||
export default () => Box({
|
||||
hpack: 'start',
|
||||
vpack: 'end',
|
||||
vertical: true,
|
||||
className: 'bg-time-box spacing-h--10',
|
||||
children: [
|
||||
TimeAndDate(),
|
||||
// QuickLaunches(),
|
||||
],
|
||||
})
|
||||
|
||||
|
|
@ -1,119 +0,0 @@
|
|||
const { Gdk, GdkPixbuf, Gio, GLib, Gtk } = imports.gi;
|
||||
import Widget from 'resource:///com/github/Aylur/ags/widget.js';
|
||||
import * as Utils from 'resource:///com/github/Aylur/ags/utils.js';
|
||||
const { exec, execAsync } = Utils;
|
||||
const { Box, Button, Label, Stack } = Widget;
|
||||
import Hyprland from 'resource:///com/github/Aylur/ags/service/hyprland.js';
|
||||
|
||||
import Wallpaper from '../../services/wallpaper.js';
|
||||
import { setupCursorHover } from '../.widgetutils/cursorhover.js';
|
||||
import { clamp } from '../.miscutils/mathfuncs.js';
|
||||
import { monitors } from '../.commondata/hyprlanddata.js';
|
||||
|
||||
const DISABLE_AGS_WALLPAPER = true;
|
||||
|
||||
const SWITCHWALL_SCRIPT_PATH = `${App.configDir}/scripts/color_generation/switchwall.sh`;
|
||||
const WALLPAPER_ZOOM_SCALE = 1.25; // For scrolling when we switch workspace
|
||||
const MAX_WORKSPACES = 10;
|
||||
|
||||
export default (monitor = 0) => {
|
||||
const WALLPAPER_OFFSCREEN_X = (WALLPAPER_ZOOM_SCALE - 1) * monitors[monitor].width;
|
||||
const WALLPAPER_OFFSCREEN_Y = (WALLPAPER_ZOOM_SCALE - 1) * monitors[monitor].height;
|
||||
const wallpaperImage = Widget.DrawingArea({
|
||||
attribute: {
|
||||
pixbuf: undefined,
|
||||
workspace: 1,
|
||||
sideleft: 0,
|
||||
sideright: 0,
|
||||
updatePos: (self) => {
|
||||
self.setCss(`font-size: ${self.attribute.workspace - self.attribute.sideleft + self.attribute.sideright}px;`)
|
||||
},
|
||||
},
|
||||
className: 'bg-wallpaper-transition',
|
||||
setup: (self) => {
|
||||
self.set_size_request(monitors[monitor].width, monitors[monitor].height);
|
||||
self
|
||||
// TODO: reduced updates using timeouts to reduce lag
|
||||
// .hook(Hyprland.active.workspace, (self) => {
|
||||
// self.attribute.workspace = Hyprland.active.workspace.id
|
||||
// self.attribute.updatePos(self);
|
||||
// })
|
||||
// .hook(App, (box, name, visible) => { // Update on open
|
||||
// if (self.attribute[name] === undefined) return;
|
||||
// self.attribute[name] = (visible ? 1 : 0);
|
||||
// self.attribute.updatePos(self);
|
||||
// })
|
||||
.on('draw', (self, cr) => {
|
||||
if (!self.attribute.pixbuf) return;
|
||||
const styleContext = self.get_style_context();
|
||||
const workspace = styleContext.get_property('font-size', Gtk.StateFlags.NORMAL);
|
||||
// Draw
|
||||
Gdk.cairo_set_source_pixbuf(cr, self.attribute.pixbuf,
|
||||
-(WALLPAPER_OFFSCREEN_X / (MAX_WORKSPACES + 1) * (clamp(workspace, 0, MAX_WORKSPACES + 1))),
|
||||
-WALLPAPER_OFFSCREEN_Y / 2);
|
||||
cr.paint();
|
||||
})
|
||||
.hook(Wallpaper, (self) => {
|
||||
if (DISABLE_AGS_WALLPAPER) return;
|
||||
const wallPath = Wallpaper.get(monitor);
|
||||
if (!wallPath || wallPath === "") return;
|
||||
self.attribute.pixbuf = GdkPixbuf.Pixbuf.new_from_file(wallPath);
|
||||
|
||||
const scale_x = monitors[monitor].width * WALLPAPER_ZOOM_SCALE / self.attribute.pixbuf.get_width();
|
||||
const scale_y = monitors[monitor].height * WALLPAPER_ZOOM_SCALE / self.attribute.pixbuf.get_height();
|
||||
const scale_factor = Math.max(scale_x, scale_y);
|
||||
|
||||
self.attribute.pixbuf = self.attribute.pixbuf.scale_simple(
|
||||
Math.round(self.attribute.pixbuf.get_width() * scale_factor),
|
||||
Math.round(self.attribute.pixbuf.get_height() * scale_factor),
|
||||
GdkPixbuf.InterpType.BILINEAR
|
||||
);
|
||||
self.queue_draw();
|
||||
}, 'updated');
|
||||
;
|
||||
}
|
||||
,
|
||||
});
|
||||
const wallpaperPrompt = Box({
|
||||
hpack: 'center',
|
||||
vpack: 'center',
|
||||
vertical: true,
|
||||
className: 'spacing-v-10',
|
||||
children: [
|
||||
Label({
|
||||
hpack: 'center',
|
||||
justification: 'center',
|
||||
className: 'txt-large',
|
||||
label: `No wallpaper loaded.\nAn image ≥ ${monitors[monitor].width * WALLPAPER_ZOOM_SCALE} × ${monitors[monitor].height * WALLPAPER_ZOOM_SCALE} is recommended.`,
|
||||
}),
|
||||
Button({
|
||||
hpack: 'center',
|
||||
className: 'btn-primary',
|
||||
label: `Select one`,
|
||||
setup: setupCursorHover,
|
||||
onClicked: (self) => Utils.execAsync([SWITCHWALL_SCRIPT_PATH]).catch(print),
|
||||
}),
|
||||
]
|
||||
});
|
||||
const stack = Stack({
|
||||
transition: 'crossfade',
|
||||
transitionDuration: userOptions.animations.durationLarge,
|
||||
children: {
|
||||
'disabled': Box({}),
|
||||
'image': wallpaperImage,
|
||||
'prompt': wallpaperPrompt,
|
||||
},
|
||||
setup: (self) => self
|
||||
.hook(Wallpaper, (self) => {
|
||||
if (DISABLE_AGS_WALLPAPER) {
|
||||
self.shown = 'disabled';
|
||||
return;
|
||||
}
|
||||
const wallPath = Wallpaper.get(monitor);
|
||||
self.shown = ((wallPath && wallPath != "") ? 'image' : 'prompt');
|
||||
}, 'updated')
|
||||
,
|
||||
})
|
||||
return stack;
|
||||
// return wallpaperImage;
|
||||
}
|
||||
|
|
@ -1,300 +0,0 @@
|
|||
const { Gtk, GLib } = imports.gi;
|
||||
import App from 'resource:///com/github/Aylur/ags/app.js';
|
||||
import Widget from 'resource:///com/github/Aylur/ags/widget.js';
|
||||
import * as Utils from 'resource:///com/github/Aylur/ags/utils.js';
|
||||
const { EventBox, Button } = Widget;
|
||||
|
||||
import Hyprland from 'resource:///com/github/Aylur/ags/service/hyprland.js';
|
||||
import Applications from 'resource:///com/github/Aylur/ags/service/applications.js';
|
||||
const { execAsync, exec } = Utils;
|
||||
const { Box, Revealer } = Widget;
|
||||
import { setupCursorHover } from '../.widgetutils/cursorhover.js';
|
||||
import { getAllFiles, searchIcons } from './icons.js'
|
||||
import { MaterialIcon } from '../.commonwidgets/materialicon.js';
|
||||
import { substitute } from '../.miscutils/icons.js';
|
||||
|
||||
const icon_files = userOptions.icons.searchPaths.map(e => getAllFiles(e)).flat(1)
|
||||
|
||||
let isPinned = false
|
||||
let cachePath = new Map()
|
||||
|
||||
let timers = []
|
||||
|
||||
function clearTimes() {
|
||||
timers.forEach(e => GLib.source_remove(e))
|
||||
timers = []
|
||||
}
|
||||
|
||||
function ExclusiveWindow(client) {
|
||||
const fn = [
|
||||
(client) => !(client !== null && client !== undefined),
|
||||
// Jetbrains
|
||||
(client) => client.title.includes("win"),
|
||||
// Vscode
|
||||
(client) => client.title === '' && client.class === ''
|
||||
]
|
||||
|
||||
for (const item of fn) { if (item(client)) { return true } }
|
||||
return false
|
||||
}
|
||||
|
||||
const focus = ({ address }) => Utils.execAsync(`hyprctl dispatch focuswindow address:${address}`).catch(print);
|
||||
|
||||
const DockSeparator = (props = {}) => Box({
|
||||
...props,
|
||||
className: 'dock-separator',
|
||||
})
|
||||
|
||||
const PinButton = () => Widget.Button({
|
||||
className: 'dock-app-btn dock-app-btn-animate',
|
||||
tooltipText: 'Pin Dock',
|
||||
child: Widget.Box({
|
||||
homogeneous: true,
|
||||
className: 'dock-app-icon txt',
|
||||
child: MaterialIcon('push_pin', 'hugeass')
|
||||
}),
|
||||
onClicked: (self) => {
|
||||
isPinned = !isPinned
|
||||
self.className = `${isPinned ? "pinned-dock-app-btn" : "dock-app-btn animate"} dock-app-btn-animate`
|
||||
},
|
||||
setup: setupCursorHover,
|
||||
})
|
||||
|
||||
const LauncherButton = () => Widget.Button({
|
||||
className: 'dock-app-btn dock-app-btn-animate',
|
||||
tooltipText: 'Open launcher',
|
||||
child: Widget.Box({
|
||||
homogeneous: true,
|
||||
className: 'dock-app-icon txt',
|
||||
child: MaterialIcon('apps', 'hugerass')
|
||||
}),
|
||||
onClicked: (self) => {
|
||||
App.toggleWindow('overview');
|
||||
},
|
||||
setup: setupCursorHover,
|
||||
})
|
||||
|
||||
const AppButton = ({ icon, ...rest }) => Widget.Revealer({
|
||||
attribute: {
|
||||
'workspace': 0
|
||||
},
|
||||
revealChild: false,
|
||||
transition: 'slide_right',
|
||||
transitionDuration: userOptions.animations.durationLarge,
|
||||
child: Widget.Button({
|
||||
...rest,
|
||||
className: 'dock-app-btn dock-app-btn-animate',
|
||||
child: Widget.Box({
|
||||
child: Widget.Overlay({
|
||||
child: Widget.Box({
|
||||
homogeneous: true,
|
||||
className: 'dock-app-icon',
|
||||
child: Widget.Icon({
|
||||
icon: icon,
|
||||
}),
|
||||
}),
|
||||
overlays: [Widget.Box({
|
||||
class_name: 'indicator',
|
||||
vpack: 'end',
|
||||
hpack: 'center',
|
||||
})],
|
||||
}),
|
||||
}),
|
||||
setup: (button) => {
|
||||
setupCursorHover(button);
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
const Taskbar = (monitor) => Widget.Box({
|
||||
className: 'dock-apps',
|
||||
attribute: {
|
||||
monitor: monitor,
|
||||
'map': new Map(),
|
||||
'clientSortFunc': (a, b) => {
|
||||
return a.attribute.workspace > b.attribute.workspace;
|
||||
},
|
||||
'update': (box, monitor) => {
|
||||
for (let i = 0; i < Hyprland.clients.length; i++) {
|
||||
const client = Hyprland.clients[i];
|
||||
if (client["pid"] == -1) return;
|
||||
const appClass = substitute(client.class);
|
||||
// for (const appName of userOptions.dock.pinnedApps) {
|
||||
// if (appClass.includes(appName.toLowerCase()))
|
||||
// return null;
|
||||
// }
|
||||
let appClassLower = appClass.toLowerCase()
|
||||
let path = ''
|
||||
if (cachePath[appClassLower]) { path = cachePath[appClassLower] }
|
||||
else {
|
||||
path = searchIcons(appClass.toLowerCase(), icon_files)
|
||||
cachePath[appClassLower] = path
|
||||
}
|
||||
if (path === '') { path = substitute(appClass) }
|
||||
const newButton = AppButton({
|
||||
icon: path,
|
||||
tooltipText: `${client.title} (${appClass})`,
|
||||
onClicked: () => focus(client),
|
||||
});
|
||||
newButton.attribute.workspace = client.workspace.id;
|
||||
newButton.revealChild = true;
|
||||
box.attribute.map.set(client.address, newButton);
|
||||
}
|
||||
box.children = Array.from(box.attribute.map.values());
|
||||
},
|
||||
'add': (box, address, monitor) => {
|
||||
if (!address) { // First active emit is undefined
|
||||
box.attribute.update(box);
|
||||
return;
|
||||
}
|
||||
const newClient = Hyprland.clients.find(client => {
|
||||
return client.address == address;
|
||||
});
|
||||
if (ExclusiveWindow(newClient)) { return }
|
||||
let appClass = newClient.class
|
||||
let appClassLower = appClass.toLowerCase()
|
||||
let path = ''
|
||||
if (cachePath[appClassLower]) { path = cachePath[appClassLower] }
|
||||
else {
|
||||
path = searchIcons(appClassLower, icon_files)
|
||||
cachePath[appClassLower] = path
|
||||
}
|
||||
if (path === '') { path = substitute(appClass) }
|
||||
const newButton = AppButton({
|
||||
icon: path,
|
||||
tooltipText: `${newClient.title} (${appClass})`,
|
||||
onClicked: () => focus(newClient),
|
||||
})
|
||||
newButton.attribute.workspace = newClient.workspace.id;
|
||||
box.attribute.map.set(address, newButton);
|
||||
box.children = Array.from(box.attribute.map.values());
|
||||
newButton.revealChild = true;
|
||||
},
|
||||
'remove': (box, address) => {
|
||||
if (!address) return;
|
||||
|
||||
const removedButton = box.attribute.map.get(address);
|
||||
if (!removedButton) return;
|
||||
removedButton.revealChild = false;
|
||||
|
||||
Utils.timeout(userOptions.animations.durationLarge, () => {
|
||||
removedButton.destroy();
|
||||
box.attribute.map.delete(address);
|
||||
box.children = Array.from(box.attribute.map.values());
|
||||
})
|
||||
},
|
||||
},
|
||||
setup: (self) => {
|
||||
self.hook(Hyprland, (box, address) => box.attribute.add(box, address, self.monitor), 'client-added')
|
||||
.hook(Hyprland, (box, address) => box.attribute.remove(box, address, self.monitor), 'client-removed')
|
||||
Utils.timeout(100, () => self.attribute.update(self));
|
||||
},
|
||||
});
|
||||
|
||||
const PinnedApps = () => Widget.Box({
|
||||
class_name: 'dock-apps',
|
||||
homogeneous: true,
|
||||
children: userOptions.dock.pinnedApps
|
||||
.map(term => ({ app: Applications.query(term)?.[0], term }))
|
||||
.filter(({ app }) => app)
|
||||
.map(({ app, term = true }) => {
|
||||
const newButton = AppButton({
|
||||
// different icon, emm...
|
||||
icon: userOptions.dock.searchPinnedAppIcons ?
|
||||
searchIcons(app.name, icon_files) :
|
||||
app.icon_name,
|
||||
onClicked: () => {
|
||||
for (const client of Hyprland.clients) {
|
||||
if (client.class.toLowerCase().includes(term))
|
||||
return focus(client);
|
||||
}
|
||||
|
||||
app.launch();
|
||||
},
|
||||
onMiddleClick: () => app.launch(),
|
||||
tooltipText: app.name,
|
||||
setup: (self) => {
|
||||
self.revealChild = true;
|
||||
self.hook(Hyprland, button => {
|
||||
const running = Hyprland.clients
|
||||
.find(client => client.class.toLowerCase().includes(term)) || false;
|
||||
|
||||
button.toggleClassName('notrunning', !running);
|
||||
button.toggleClassName('focused', Hyprland.active.client.address == running.address);
|
||||
button.set_tooltip_text(running ? running.title : app.name);
|
||||
}, 'notify::clients')
|
||||
},
|
||||
})
|
||||
newButton.revealChild = true;
|
||||
return newButton;
|
||||
}),
|
||||
});
|
||||
|
||||
export default (monitor = 0) => {
|
||||
const dockContent = Box({
|
||||
className: 'dock-bg spacing-h-5',
|
||||
children: [
|
||||
PinButton(),
|
||||
PinnedApps(),
|
||||
DockSeparator(),
|
||||
Taskbar(),
|
||||
LauncherButton(),
|
||||
]
|
||||
})
|
||||
const dockRevealer = Revealer({
|
||||
attribute: {
|
||||
'updateShow': self => { // I only use mouse to resize. I don't care about keyboard resize if that's a thing
|
||||
if (userOptions.dock.monitorExclusivity)
|
||||
self.revealChild = Hyprland.active.monitor.id === monitor;
|
||||
else
|
||||
self.revealChild = true;
|
||||
|
||||
return self.revealChild
|
||||
}
|
||||
},
|
||||
revealChild: false,
|
||||
transition: 'slide_up',
|
||||
transitionDuration: userOptions.animations.durationLarge,
|
||||
child: dockContent,
|
||||
setup: (self) => {
|
||||
const callback = (self, trigger) => {
|
||||
if (!userOptions.dock.trigger.includes(trigger)) return
|
||||
const flag = self.attribute.updateShow(self)
|
||||
|
||||
if (flag) clearTimes();
|
||||
|
||||
const hidden = userOptions.dock.autoHide.find(e => e["trigger"] === trigger)
|
||||
|
||||
if (hidden) {
|
||||
let id = Utils.timeout(hidden.interval, () => {
|
||||
if (!isPinned) { self.revealChild = false }
|
||||
timers = timers.filter(e => e !== id)
|
||||
})
|
||||
timers.push(id)
|
||||
}
|
||||
}
|
||||
|
||||
self
|
||||
// .hook(Hyprland, (self) => self.attribute.updateShow(self))
|
||||
.hook(Hyprland.active.workspace, self => callback(self, "workspace-active"))
|
||||
.hook(Hyprland.active.client, self => callback(self, "client-active"))
|
||||
.hook(Hyprland, self => callback(self, "client-added"), "client-added")
|
||||
.hook(Hyprland, self => callback(self, "client-removed"), "client-removed")
|
||||
},
|
||||
})
|
||||
return EventBox({
|
||||
onHover: () => {
|
||||
dockRevealer.revealChild = true;
|
||||
clearTimes()
|
||||
},
|
||||
child: Box({
|
||||
homogeneous: true,
|
||||
css: `min-height: ${userOptions.dock.hiddenThickness}px;`,
|
||||
children: [dockRevealer],
|
||||
}),
|
||||
setup: self => self.on("leave-notify-event", () => {
|
||||
if (!isPinned) dockRevealer.revealChild = false;
|
||||
clearTimes()
|
||||
})
|
||||
})
|
||||
}
|
||||
|
|
@ -1,63 +0,0 @@
|
|||
const { Gio, GLib } = imports.gi
|
||||
|
||||
const exists = (path) => Gio.File.new_for_path(path).query_exists(null);
|
||||
|
||||
export const levenshteinDistance = (a, b) => {
|
||||
if (!a.length) { return b.length }
|
||||
if (!b.length) { return a.length }
|
||||
|
||||
let f = Array.from(new Array(a.length + 1),
|
||||
() => new Array(b.length + 1).fill(0))
|
||||
|
||||
for (let i = 0; i <= b.length; i++) { f[0][i] = i; }
|
||||
for (let i = 0; i <= a.length; i++) { f[i][0] = i; }
|
||||
|
||||
for (let i = 1; i <= a.length; i++) {
|
||||
for (let j = 1; j <= b.length; j++) {
|
||||
if (a.charAt(i - 1) === b.charAt(j - 1)) {
|
||||
f[i][j] = f[i-1][j-1]
|
||||
} else {
|
||||
f[i][j] = Math.min(f[i-1][j-1], Math.min(f[i][j-1], f[i-1][j])) + 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return f[a.length][b.length]
|
||||
}
|
||||
|
||||
export const getAllFiles = (dir, files = []) => {
|
||||
if (!exists(dir)) { return [] }
|
||||
const file = Gio.File.new_for_path(dir);
|
||||
const enumerator = file.enumerate_children('standard::name,standard::type',
|
||||
Gio.FileQueryInfoFlags.NONE, null);
|
||||
|
||||
for (const info of enumerator) {
|
||||
if (info.get_file_type() === Gio.FileType.DIRECTORY) {
|
||||
files.push(getAllFiles(`${dir}/${info.get_name()}`))
|
||||
} else {
|
||||
files.push(`${dir}/${info.get_name()}`)
|
||||
}
|
||||
}
|
||||
|
||||
return files.flat(1);
|
||||
}
|
||||
|
||||
export const searchIcons = (appClass, files) => {
|
||||
appClass = appClass.toLowerCase()
|
||||
|
||||
if (!files.length) { return "" }
|
||||
|
||||
let appro = 0x3f3f3f3f
|
||||
let path = ""
|
||||
|
||||
for (const item of files) {
|
||||
let score = levenshteinDistance(item.split("/").pop().toLowerCase().split(".")[0], appClass)
|
||||
|
||||
if (score < appro) {
|
||||
appro = score
|
||||
path = item
|
||||
}
|
||||
}
|
||||
|
||||
return path
|
||||
}
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
import Widget from 'resource:///com/github/Aylur/ags/widget.js';
|
||||
import Dock from './dock.js';
|
||||
|
||||
export default (monitor = 0) => Widget.Window({
|
||||
monitor,
|
||||
name: `dock${monitor}`,
|
||||
layer: userOptions.dock.layer,
|
||||
anchor: ['bottom'],
|
||||
exclusivity: 'normal',
|
||||
visible: true,
|
||||
child: Dock(monitor),
|
||||
});
|
||||
|
|
@ -1,264 +0,0 @@
|
|||
const { Gio, GLib } = imports.gi;
|
||||
import Variable from 'resource:///com/github/Aylur/ags/variable.js';
|
||||
import Widget from 'resource:///com/github/Aylur/ags/widget.js';
|
||||
import { ConfigToggle, ConfigMulipleSelection } from '../.commonwidgets/configwidgets.js';
|
||||
import * as Utils from 'resource:///com/github/Aylur/ags/utils.js';
|
||||
const { execAsync } = Utils;
|
||||
import { setupCursorHover } from '../.widgetutils/cursorhover.js';
|
||||
import { showColorScheme } from '../../variables.js';
|
||||
import { MaterialIcon } from '../.commonwidgets/materialicon.js';
|
||||
import { darkMode } from '../.miscutils/system.js';
|
||||
|
||||
const ColorBox = ({
|
||||
name = 'Color',
|
||||
...rest
|
||||
}) => Widget.Box({
|
||||
...rest,
|
||||
homogeneous: true,
|
||||
children: [
|
||||
Widget.Label({
|
||||
label: `${name}`,
|
||||
})
|
||||
]
|
||||
})
|
||||
|
||||
const ColorSchemeSettingsRevealer = () => {
|
||||
const headerButtonIcon = MaterialIcon('expand_more', 'norm');
|
||||
const header = Widget.Button({
|
||||
className: 'osd-settings-btn-arrow',
|
||||
onClicked: () => {
|
||||
content.revealChild = !content.revealChild;
|
||||
headerButtonIcon.label = content.revealChild ? 'expand_less' : 'expand_more';
|
||||
},
|
||||
setup: setupCursorHover,
|
||||
hpack: 'end',
|
||||
child: headerButtonIcon,
|
||||
});
|
||||
const content = Widget.Revealer({
|
||||
revealChild: false,
|
||||
transition: 'slide_down',
|
||||
transitionDuration: 200,
|
||||
child: ColorSchemeSettings(),
|
||||
setup: (self) => self.hook(isHoveredColorschemeSettings, (revealer) => {
|
||||
if (isHoveredColorschemeSettings.value == false) {
|
||||
setTimeout(() => {
|
||||
if (isHoveredColorschemeSettings.value == false)
|
||||
revealer.revealChild = false;
|
||||
headerButtonIcon.label = 'expand_more';
|
||||
}, 1500);
|
||||
}
|
||||
}),
|
||||
});
|
||||
return Widget.EventBox({
|
||||
onHover: (self) => {
|
||||
isHoveredColorschemeSettings.setValue(true);
|
||||
},
|
||||
onHoverLost: (self) => {
|
||||
isHoveredColorschemeSettings.setValue(false);
|
||||
},
|
||||
child: Widget.Box({
|
||||
vertical: true,
|
||||
children: [
|
||||
header,
|
||||
content,
|
||||
]
|
||||
}),
|
||||
});
|
||||
}
|
||||
|
||||
function calculateSchemeInitIndex(optionsArr, searchValue = 'vibrant') {
|
||||
if (searchValue == '')
|
||||
searchValue = 'vibrant';
|
||||
const flatArray = optionsArr.flatMap(subArray => subArray);
|
||||
const result = flatArray.findIndex(element => element.value === searchValue);
|
||||
const rowIndex = Math.floor(result / optionsArr[0].length);
|
||||
const columnIndex = result % optionsArr[0].length;
|
||||
return [rowIndex, columnIndex];
|
||||
}
|
||||
|
||||
const schemeOptionsArr = [
|
||||
[
|
||||
{ name: getString('Tonal Spot'), value: 'tonalspot' },
|
||||
{ name: getString('Fruit Salad'), value: 'fruitsalad' },
|
||||
{ name: getString('Fidelity'), value: 'fidelity' },
|
||||
{ name: getString('Rainbow'), value: 'rainbow' },
|
||||
],
|
||||
[
|
||||
{ name: getString('Neutral'), value: 'neutral' },
|
||||
{ name: getString('Monochrome'), value: 'monochrome' },
|
||||
{ name: getString('Expressive'), value: 'expressive' },
|
||||
{ name: getString('Vibrant'), value: 'vibrant' },
|
||||
],
|
||||
[
|
||||
{ name: getString('Vibrant+'), value: 'morevibrant' },
|
||||
],
|
||||
//[
|
||||
// { name: getString('Content'), value: 'content' },
|
||||
//]
|
||||
];
|
||||
|
||||
const LIGHTDARK_FILE_LOCATION = `${GLib.get_user_state_dir()}/ags/user/colormode.txt`;
|
||||
const initTransparency = Utils.exec(`bash -c "sed -n \'2p\' ${LIGHTDARK_FILE_LOCATION}"`);
|
||||
const initTransparencyVal = (initTransparency == "transparent") ? 1 : 0;
|
||||
const initScheme = Utils.exec(`bash -c "sed -n \'3p\' ${LIGHTDARK_FILE_LOCATION}"`);
|
||||
const initSchemeIndex = calculateSchemeInitIndex(schemeOptionsArr, initScheme);
|
||||
|
||||
const ColorSchemeSettings = () => Widget.Box({
|
||||
className: 'osd-colorscheme-settings spacing-v-5 margin-20',
|
||||
vertical: true,
|
||||
vpack: 'center',
|
||||
children: [
|
||||
Widget.Box({
|
||||
vertical: true,
|
||||
children: [
|
||||
Widget.Label({
|
||||
xalign: 0,
|
||||
className: 'txt-norm titlefont txt',
|
||||
label: getString('Options'),
|
||||
hpack: 'center',
|
||||
}),
|
||||
//////////////////
|
||||
ConfigToggle({
|
||||
icon: 'dark_mode',
|
||||
name: getString('Dark Mode'),
|
||||
desc: getString('Ya should go to sleep!'),
|
||||
initValue: darkMode.value,
|
||||
onChange: (_, newValue) => {
|
||||
darkMode.value = !!newValue;
|
||||
},
|
||||
extraSetup: (self) => self.hook(darkMode, (self) => {
|
||||
self.enabled.value = darkMode.value;
|
||||
}),
|
||||
}),
|
||||
ConfigToggle({
|
||||
icon: 'border_clear',
|
||||
name: getString('Transparency'),
|
||||
desc: getString('Make shell elements transparent'),
|
||||
initValue: initTransparencyVal,
|
||||
onChange: (self, newValue) => {
|
||||
let transparency = newValue == 0 ? "opaque" : "transparent";
|
||||
execAsync([`bash`, `-c`, `mkdir -p ${GLib.get_user_state_dir()}/ags/user && sed -i "2s/.*/${transparency}/" ${GLib.get_user_state_dir()}/ags/user/colormode.txt`])
|
||||
.then(execAsync(['bash', '-c', `${App.configDir}/scripts/color_generation/switchcolor.sh`]))
|
||||
.catch(print);
|
||||
},
|
||||
}),
|
||||
Widget.Box({
|
||||
tooltipText: getString('Theme GTK apps using accent color\n(drawback: dark/light mode switching requires restart)'),
|
||||
className: 'txt spacing-h-5 configtoggle-box',
|
||||
children: [
|
||||
MaterialIcon('imagesearch_roller', 'norm'),
|
||||
Widget.Label({
|
||||
className: 'txt txt-small',
|
||||
label: getString('Use Gradience'),
|
||||
}),
|
||||
Widget.Box({ hexpand: true }),
|
||||
ConfigMulipleSelection({
|
||||
hpack: 'center',
|
||||
vpack: 'center',
|
||||
optionsArr: [
|
||||
[{ name: 'Off', value: 0 }, { name: 'On', value: 1 }],
|
||||
],
|
||||
initIndex: [-1, -1],
|
||||
onChange: (value, name) => {
|
||||
const ADWAITA_BLUE = "#3584E4";
|
||||
if (value) execAsync([`bash`, `-c`, `${App.configDir}/scripts/color_generation/switchcolor.sh - --yes-gradience`, `&`])
|
||||
.catch(print);
|
||||
else execAsync([`bash`, `-c`, `${App.configDir}/scripts/color_generation/switchcolor.sh "${ADWAITA_BLUE}" --no-gradience`, `&`])
|
||||
.catch(print);
|
||||
|
||||
},
|
||||
}),
|
||||
]
|
||||
}),
|
||||
]
|
||||
}),
|
||||
Widget.Box({
|
||||
vertical: true,
|
||||
className: 'spacing-v-5',
|
||||
children: [
|
||||
Widget.Label({
|
||||
xalign: 0,
|
||||
className: 'txt-norm titlefont txt margin-top-5',
|
||||
label: getString('Scheme styles'),
|
||||
hpack: 'center',
|
||||
}),
|
||||
//////////////////
|
||||
ConfigMulipleSelection({
|
||||
hpack: 'center',
|
||||
vpack: 'center',
|
||||
optionsArr: schemeOptionsArr,
|
||||
initIndex: initSchemeIndex,
|
||||
onChange: (value, name) => {
|
||||
execAsync([`bash`, `-c`, `mkdir -p ${GLib.get_user_state_dir()}/ags/user && sed -i "3s/.*/${value}/" ${GLib.get_user_state_dir()}/ags/user/colormode.txt`])
|
||||
.then(execAsync(['bash', '-c', `${App.configDir}/scripts/color_generation/switchcolor.sh`]))
|
||||
.catch(print);
|
||||
},
|
||||
}),
|
||||
]
|
||||
})
|
||||
]
|
||||
});
|
||||
|
||||
const ColorschemeContent = () => Widget.Box({
|
||||
className: 'osd-colorscheme spacing-v-5',
|
||||
vertical: true,
|
||||
hpack: 'center',
|
||||
children: [
|
||||
Widget.Label({
|
||||
xalign: 0,
|
||||
className: 'txt-norm titlefont txt',
|
||||
label: getString('Color scheme'),
|
||||
hpack: 'center',
|
||||
}),
|
||||
Widget.Box({
|
||||
className: 'spacing-h-5',
|
||||
hpack: 'center',
|
||||
children: [
|
||||
ColorBox({ name: 'P', className: 'osd-color osd-color-primary' }),
|
||||
ColorBox({ name: 'S', className: 'osd-color osd-color-secondary' }),
|
||||
ColorBox({ name: 'T', className: 'osd-color osd-color-tertiary' }),
|
||||
ColorBox({ name: 'Sf', className: 'osd-color osd-color-surface' }),
|
||||
ColorBox({ name: 'Sf-i', className: 'osd-color osd-color-inverseSurface' }),
|
||||
ColorBox({ name: 'E', className: 'osd-color osd-color-error' }),
|
||||
]
|
||||
}),
|
||||
Widget.Box({
|
||||
className: 'spacing-h-5',
|
||||
hpack: 'center',
|
||||
children: [
|
||||
ColorBox({ name: 'P-c', className: 'osd-color osd-color-primaryContainer' }),
|
||||
ColorBox({ name: 'S-c', className: 'osd-color osd-color-secondaryContainer' }),
|
||||
ColorBox({ name: 'T-c', className: 'osd-color osd-color-tertiaryContainer' }),
|
||||
ColorBox({ name: 'Sf-c', className: 'osd-color osd-color-surfaceContainer' }),
|
||||
ColorBox({ name: 'Sf-v', className: 'osd-color osd-color-surfaceVariant' }),
|
||||
ColorBox({ name: 'E-c', className: 'osd-color osd-color-errorContainer' }),
|
||||
]
|
||||
}),
|
||||
ColorSchemeSettingsRevealer(),
|
||||
]
|
||||
});
|
||||
|
||||
const isHoveredColorschemeSettings = Variable(false);
|
||||
|
||||
export default () => Widget.Revealer({
|
||||
transition: 'slide_down',
|
||||
transitionDuration: userOptions.animations.durationLarge,
|
||||
child: ColorschemeContent(),
|
||||
setup: (self) => {
|
||||
self
|
||||
.hook(showColorScheme, (revealer) => {
|
||||
if (showColorScheme.value == true)
|
||||
revealer.revealChild = true;
|
||||
else
|
||||
revealer.revealChild = isHoveredColorschemeSettings.value;
|
||||
})
|
||||
.hook(isHoveredColorschemeSettings, (revealer) => {
|
||||
if (isHoveredColorschemeSettings.value == false) {
|
||||
setTimeout(() => {
|
||||
if (isHoveredColorschemeSettings.value == false)
|
||||
revealer.revealChild = showColorScheme.value;
|
||||
}, 2000);
|
||||
}
|
||||
})
|
||||
},
|
||||
})
|
||||
|
|
@ -1,124 +0,0 @@
|
|||
// This file is for brightness/volume indicators
|
||||
import Widget from 'resource:///com/github/Aylur/ags/widget.js';
|
||||
import Audio from 'resource:///com/github/Aylur/ags/service/audio.js';
|
||||
const { Box, Label, ProgressBar } = Widget;
|
||||
import { MarginRevealer } from '../.widgethacks/advancedrevealers.js';
|
||||
import Brightness from '../../services/brightness.js';
|
||||
import Indicator from '../../services/indicator.js';
|
||||
|
||||
const OsdValue = ({
|
||||
name, nameSetup = undefined, labelSetup, progressSetup,
|
||||
extraClassName = '', extraProgressClassName = '',
|
||||
...rest
|
||||
}) => {
|
||||
const valueName = Label({
|
||||
xalign: 0, yalign: 0, hexpand: true,
|
||||
className: 'osd-label',
|
||||
label: `${name}`,
|
||||
setup: nameSetup,
|
||||
});
|
||||
const valueNumber = Label({
|
||||
hexpand: false, className: 'osd-value-txt',
|
||||
setup: labelSetup,
|
||||
});
|
||||
return Box({ // Volume
|
||||
vertical: true,
|
||||
hexpand: true,
|
||||
className: `osd-bg osd-value ${extraClassName}`,
|
||||
attribute: {
|
||||
'disable': () => {
|
||||
valueNumber.label = '';
|
||||
}
|
||||
},
|
||||
children: [
|
||||
Box({
|
||||
vexpand: true,
|
||||
children: [
|
||||
valueName,
|
||||
valueNumber,
|
||||
]
|
||||
}),
|
||||
ProgressBar({
|
||||
className: `osd-progress ${extraProgressClassName}`,
|
||||
hexpand: true,
|
||||
vertical: false,
|
||||
setup: progressSetup,
|
||||
})
|
||||
],
|
||||
...rest,
|
||||
});
|
||||
}
|
||||
|
||||
export default (monitor = 0) => {
|
||||
const brightnessIndicator = OsdValue({
|
||||
name: 'Brightness',
|
||||
extraClassName: 'osd-brightness',
|
||||
extraProgressClassName: 'osd-brightness-progress',
|
||||
labelSetup: (self) => self.hook(Brightness[monitor], self => {
|
||||
self.label = `${Math.round(Brightness[monitor].screen_value * 100)}`;
|
||||
}, 'notify::screen-value'),
|
||||
progressSetup: (self) => self.hook(Brightness[monitor], (progress) => {
|
||||
const updateValue = Brightness[monitor].screen_value;
|
||||
if (updateValue !== progress.value) Indicator.popup(1);
|
||||
progress.value = updateValue;
|
||||
}, 'notify::screen-value'),
|
||||
});
|
||||
|
||||
const volumeIndicator = OsdValue({
|
||||
name: 'Volume',
|
||||
extraClassName: 'osd-volume',
|
||||
extraProgressClassName: 'osd-volume-progress',
|
||||
attribute: { headphones: undefined , device: undefined},
|
||||
nameSetup: (self) => Utils.timeout(1, () => {
|
||||
const updateAudioDevice = (self) => {
|
||||
const usingHeadphones = (Audio.speaker?.stream?.port)?.toLowerCase().includes('headphone');
|
||||
if (volumeIndicator.attribute.headphones === undefined ||
|
||||
volumeIndicator.attribute.headphones !== usingHeadphones) {
|
||||
volumeIndicator.attribute.headphones = usingHeadphones;
|
||||
self.label = usingHeadphones ? 'Headphones' : 'Speakers';
|
||||
// Indicator.popup(1);
|
||||
}
|
||||
}
|
||||
self.hook(Audio, updateAudioDevice);
|
||||
Utils.timeout(1000, updateAudioDevice);
|
||||
}),
|
||||
labelSetup: (self) => self.hook(Audio, (label) => {
|
||||
const newDevice = (Audio.speaker?.name);
|
||||
const updateValue = Math.round(Audio.speaker?.volume * 100);
|
||||
if (!isNaN(updateValue)) {
|
||||
if (newDevice === volumeIndicator.attribute.device && updateValue != label.label) {
|
||||
Indicator.popup(1);
|
||||
}
|
||||
}
|
||||
volumeIndicator.attribute.device = newDevice;
|
||||
label.label = `${updateValue}`;
|
||||
}),
|
||||
progressSetup: (self) => self.hook(Audio, (progress) => {
|
||||
const updateValue = Audio.speaker?.volume;
|
||||
if (!isNaN(updateValue)) {
|
||||
if (updateValue > 1) progress.value = 1;
|
||||
else progress.value = updateValue;
|
||||
}
|
||||
}),
|
||||
});
|
||||
return MarginRevealer({
|
||||
transition: 'slide_down',
|
||||
showClass: 'osd-show',
|
||||
hideClass: 'osd-hide',
|
||||
extraSetup: (self) => self
|
||||
.hook(Indicator, (revealer, value) => {
|
||||
if (value > -1) revealer.attribute.show();
|
||||
else revealer.attribute.hide();
|
||||
}, 'popup')
|
||||
,
|
||||
child: Box({
|
||||
hpack: 'center',
|
||||
vertical: false,
|
||||
className: 'spacing-h--10',
|
||||
children: [
|
||||
brightnessIndicator,
|
||||
volumeIndicator,
|
||||
]
|
||||
})
|
||||
});
|
||||
}
|
||||
|
|
@ -1,32 +0,0 @@
|
|||
import Widget from 'resource:///com/github/Aylur/ags/widget.js';
|
||||
import Indicator from '../../services/indicator.js';
|
||||
import IndicatorValues from './indicatorvalues.js';
|
||||
import MusicControls from './musiccontrols.js';
|
||||
import ColorScheme from './colorscheme.js';
|
||||
import NotificationPopups from './notificationpopups.js';
|
||||
|
||||
export default (monitor = 0) => Widget.Window({
|
||||
name: `indicator${monitor}`,
|
||||
monitor,
|
||||
className: 'indicator',
|
||||
layer: 'overlay',
|
||||
// exclusivity: 'ignore',
|
||||
visible: true,
|
||||
anchor: ['top'],
|
||||
child: Widget.EventBox({
|
||||
onHover: () => { //make the widget hide when hovering
|
||||
Indicator.popup(-1);
|
||||
},
|
||||
child: Widget.Box({
|
||||
vertical: true,
|
||||
className: 'osd-window',
|
||||
css: 'min-height: 2px;',
|
||||
children: [
|
||||
IndicatorValues(monitor),
|
||||
MusicControls(),
|
||||
NotificationPopups(),
|
||||
ColorScheme(),
|
||||
]
|
||||
})
|
||||
}),
|
||||
});
|
||||
|
|
@ -1,408 +0,0 @@
|
|||
const { GLib } = imports.gi;
|
||||
import App from 'resource:///com/github/Aylur/ags/app.js';
|
||||
import Widget from 'resource:///com/github/Aylur/ags/widget.js';
|
||||
import * as Utils from 'resource:///com/github/Aylur/ags/utils.js';
|
||||
import Mpris from 'resource:///com/github/Aylur/ags/service/mpris.js';
|
||||
const { exec, execAsync } = Utils;
|
||||
const { Box, EventBox, Icon, Scrollable, Label, Button, Revealer } = Widget;
|
||||
|
||||
import { fileExists } from '../.miscutils/files.js';
|
||||
import { AnimatedCircProg } from "../.commonwidgets/cairo_circularprogress.js";
|
||||
import { showMusicControls } from '../../variables.js';
|
||||
import { darkMode, hasPlasmaIntegration } from '../.miscutils/system.js';
|
||||
|
||||
const COMPILED_STYLE_DIR = `${GLib.get_user_cache_dir()}/ags/user/generated`
|
||||
const LIGHTDARK_FILE_LOCATION = `${GLib.get_user_state_dir()}/ags/user/colormode.txt`;
|
||||
const colorMode = Utils.exec(`bash -c "sed -n \'1p\' '${LIGHTDARK_FILE_LOCATION}'"`);
|
||||
const lightDark = (colorMode == "light") ? '-l' : '';
|
||||
const COVER_COLORSCHEME_SUFFIX = '_colorscheme.css';
|
||||
var lastCoverPath = '';
|
||||
|
||||
function isRealPlayer(player) {
|
||||
return (
|
||||
// Remove unecessary native buses from browsers if there's plasma integration
|
||||
!(hasPlasmaIntegration && player.busName.startsWith('org.mpris.MediaPlayer2.firefox')) &&
|
||||
!(hasPlasmaIntegration && player.busName.startsWith('org.mpris.MediaPlayer2.chromium')) &&
|
||||
// playerctld just copies other buses and we don't need duplicates
|
||||
!player.busName.startsWith('org.mpris.MediaPlayer2.playerctld') &&
|
||||
// Non-instance mpd bus
|
||||
!(player.busName.endsWith('.mpd') && !player.busName.endsWith('MediaPlayer2.mpd'))
|
||||
);
|
||||
}
|
||||
|
||||
export const getPlayer = (name = userOptions.music.preferredPlayer) => Mpris.getPlayer(name) || Mpris.players[0] || null;
|
||||
function lengthStr(length) {
|
||||
const min = Math.floor(length / 60);
|
||||
const sec = Math.floor(length % 60);
|
||||
const sec0 = sec < 10 ? '0' : '';
|
||||
return `${min}:${sec0}${sec}`;
|
||||
}
|
||||
|
||||
function detectMediaSource(link) {
|
||||
if (link.startsWith("file://")) {
|
||||
if (link.includes('firefox-mpris'))
|
||||
return ' Firefox'
|
||||
return " File";
|
||||
}
|
||||
let url = link.replace(/(^\w+:|^)\/\//, '');
|
||||
let domain = url.match(/(?:[a-z]+\.)?([a-z]+\.[a-z]+)/i)[1];
|
||||
if (domain == 'ytimg.com') return ' Youtube';
|
||||
if (domain == 'discordapp.net') return ' Discord';
|
||||
if (domain == 'sndcdn.com') return ' SoundCloud';
|
||||
return domain;
|
||||
}
|
||||
|
||||
const DEFAULT_MUSIC_FONT = 'Gabarito, sans-serif';
|
||||
function getTrackfont(player) {
|
||||
const title = player.trackTitle;
|
||||
const artists = player.trackArtists.join(' ');
|
||||
if (artists.includes('TANO*C') || artists.includes('USAO') || artists.includes('Kobaryo'))
|
||||
return 'Chakra Petch'; // Rigid square replacement
|
||||
if (title.includes('東方'))
|
||||
return 'Crimson Text, serif'; // Serif for Touhou stuff
|
||||
return DEFAULT_MUSIC_FONT;
|
||||
}
|
||||
function trimTrackTitle(title) {
|
||||
if (!title) return '';
|
||||
const cleanPatterns = [
|
||||
/【[^】]*】/, // Touhou n weeb stuff
|
||||
" [FREE DOWNLOAD]", // F-777
|
||||
];
|
||||
cleanPatterns.forEach((expr) => title = title.replace(expr, ''));
|
||||
return title;
|
||||
}
|
||||
|
||||
const TrackProgress = ({ player, ...rest }) => {
|
||||
const _updateProgress = (circprog) => {
|
||||
// const player = Mpris.getPlayer();
|
||||
if (!player) return;
|
||||
// Set circular progress (see definition of AnimatedCircProg for explanation)
|
||||
circprog.css = `font-size: ${Math.max(player.position / player.length * 100, 0)}px;`
|
||||
}
|
||||
return AnimatedCircProg({
|
||||
...rest,
|
||||
className: 'osd-music-circprog',
|
||||
vpack: 'center',
|
||||
extraSetup: (self) => self
|
||||
.hook(Mpris, _updateProgress)
|
||||
.poll(3000, _updateProgress)
|
||||
,
|
||||
})
|
||||
}
|
||||
|
||||
const TrackTitle = ({ player, ...rest }) => Label({
|
||||
...rest,
|
||||
label: 'No music playing',
|
||||
xalign: 0,
|
||||
truncate: 'end',
|
||||
// wrap: true,
|
||||
className: 'osd-music-title',
|
||||
setup: (self) => self.hook(player, (self) => {
|
||||
// Player name
|
||||
self.label = player.trackTitle.length > 0 ? trimTrackTitle(player.trackTitle) : 'No media';
|
||||
// Font based on track/artist
|
||||
const fontForThisTrack = getTrackfont(player);
|
||||
self.css = `font-family: ${fontForThisTrack}, ${DEFAULT_MUSIC_FONT};`;
|
||||
}, 'notify::track-title'),
|
||||
});
|
||||
|
||||
const TrackArtists = ({ player, ...rest }) => Label({
|
||||
...rest,
|
||||
xalign: 0,
|
||||
className: 'osd-music-artists',
|
||||
truncate: 'end',
|
||||
setup: (self) => self.hook(player, (self) => {
|
||||
self.label = player.trackArtists.length > 0 ? player.trackArtists.join(', ') : '';
|
||||
}, 'notify::track-artists'),
|
||||
})
|
||||
|
||||
const CoverArt = ({ player, ...rest }) => {
|
||||
const fallbackCoverArt = Box({ // Fallback
|
||||
className: 'osd-music-cover-fallback',
|
||||
homogeneous: true,
|
||||
children: [Label({
|
||||
className: 'icon-material txt-gigantic txt-thin',
|
||||
label: 'music_note',
|
||||
})]
|
||||
});
|
||||
// const coverArtDrawingArea = Widget.DrawingArea({ className: 'osd-music-cover-art' });
|
||||
// const coverArtDrawingAreaStyleContext = coverArtDrawingArea.get_style_context();
|
||||
const realCoverArt = Box({
|
||||
className: 'osd-music-cover-art',
|
||||
homogeneous: true,
|
||||
// children: [coverArtDrawingArea],
|
||||
attribute: {
|
||||
'pixbuf': null,
|
||||
// 'showImage': (self, imagePath) => {
|
||||
// const borderRadius = coverArtDrawingAreaStyleContext.get_property('border-radius', Gtk.StateFlags.NORMAL);
|
||||
// const frameHeight = coverArtDrawingAreaStyleContext.get_property('min-height', Gtk.StateFlags.NORMAL);
|
||||
// const frameWidth = coverArtDrawingAreaStyleContext.get_property('min-width', Gtk.StateFlags.NORMAL);
|
||||
// let imageHeight = frameHeight;
|
||||
// let imageWidth = frameWidth;
|
||||
// // Get image dimensions
|
||||
// execAsync(['identify', '-format', '{"w":%w,"h":%h}', imagePath])
|
||||
// .then((output) => {
|
||||
// const imageDimensions = JSON.parse(output);
|
||||
// const imageAspectRatio = imageDimensions.w / imageDimensions.h;
|
||||
// const displayedAspectRatio = imageWidth / imageHeight;
|
||||
// if (imageAspectRatio >= displayedAspectRatio) {
|
||||
// imageWidth = imageHeight * imageAspectRatio;
|
||||
// } else {
|
||||
// imageHeight = imageWidth / imageAspectRatio;
|
||||
// }
|
||||
// // Real stuff
|
||||
// // TODO: fix memory leak(?)
|
||||
// // if (self.attribute.pixbuf) {
|
||||
// // self.attribute.pixbuf.unref();
|
||||
// // self.attribute.pixbuf = null;
|
||||
// // }
|
||||
// self.attribute.pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_size(imagePath, imageWidth, imageHeight);
|
||||
|
||||
// coverArtDrawingArea.set_size_request(frameWidth, frameHeight);
|
||||
// coverArtDrawingArea.connect("draw", (widget, cr) => {
|
||||
// // Clip a rounded rectangle area
|
||||
// cr.arc(borderRadius, borderRadius, borderRadius, Math.PI, 1.5 * Math.PI);
|
||||
// cr.arc(frameWidth - borderRadius, borderRadius, borderRadius, 1.5 * Math.PI, 2 * Math.PI);
|
||||
// cr.arc(frameWidth - borderRadius, frameHeight - borderRadius, borderRadius, 0, 0.5 * Math.PI);
|
||||
// cr.arc(borderRadius, frameHeight - borderRadius, borderRadius, 0.5 * Math.PI, Math.PI);
|
||||
// cr.closePath();
|
||||
// cr.clip();
|
||||
// // Paint image as bg, centered
|
||||
// Gdk.cairo_set_source_pixbuf(cr, self.attribute.pixbuf,
|
||||
// frameWidth / 2 - imageWidth / 2,
|
||||
// frameHeight / 2 - imageHeight / 2
|
||||
// );
|
||||
// cr.paint();
|
||||
// });
|
||||
// }).catch(print)
|
||||
// },
|
||||
'updateCover': (self) => {
|
||||
// const player = Mpris.getPlayer(); // Maybe no need to re-get player.. can't remember why I had this
|
||||
// Player closed
|
||||
// Note that cover path still remains, so we're checking title
|
||||
if (!player || player.trackTitle == "" || !player.coverPath) {
|
||||
self.css = `background-image: none;`; // CSS image
|
||||
App.applyCss(`${COMPILED_STYLE_DIR}/style.css`);
|
||||
return;
|
||||
}
|
||||
|
||||
const coverPath = player.coverPath;
|
||||
const stylePath = `${player.coverPath}${darkMode.value ? '' : '-l'}${COVER_COLORSCHEME_SUFFIX}`;
|
||||
if (player.coverPath == lastCoverPath) { // Since 'notify::cover-path' emits on cover download complete
|
||||
Utils.timeout(200, () => {
|
||||
// self.attribute.showImage(self, coverPath);
|
||||
self.css = `background-image: url('${coverPath}');`; // CSS image
|
||||
});
|
||||
}
|
||||
lastCoverPath = player.coverPath;
|
||||
|
||||
// If a colorscheme has already been generated, skip generation
|
||||
if (fileExists(stylePath)) {
|
||||
// self.attribute.showImage(self, coverPath)
|
||||
self.css = `background-image: url('${coverPath}');`; // CSS image
|
||||
App.applyCss(stylePath);
|
||||
return;
|
||||
}
|
||||
|
||||
// Generate colors
|
||||
execAsync(['bash', '-c',
|
||||
`${App.configDir}/scripts/color_generation/generate_colors_material.py --path '${coverPath}' --mode ${darkMode.value ? 'dark' : 'light'} > ${GLib.get_user_state_dir()}/ags/scss/_musicmaterial.scss`])
|
||||
.then(() => {
|
||||
exec(`wal -i "${player.coverPath}" -n -t -s -e -q ${darkMode.value ? '' : '-l'}`)
|
||||
exec(`cp ${GLib.get_user_cache_dir()}/wal/colors.scss ${GLib.get_user_state_dir()}/ags/scss/_musicwal.scss`);
|
||||
exec(`sass -I "${GLib.get_user_state_dir()}/ags/scss" -I "${App.configDir}/scss/fallback" "${App.configDir}/scss/_music.scss" "${stylePath}"`);
|
||||
Utils.timeout(200, () => {
|
||||
// self.attribute.showImage(self, coverPath)
|
||||
self.css = `background-image: url('${coverPath}');`; // CSS image
|
||||
});
|
||||
App.applyCss(`${stylePath}`);
|
||||
})
|
||||
.catch(print);
|
||||
},
|
||||
},
|
||||
setup: (self) => self
|
||||
.hook(player, (self) => {
|
||||
self.attribute.updateCover(self);
|
||||
}, 'notify::cover-path')
|
||||
,
|
||||
});
|
||||
return Box({
|
||||
...rest,
|
||||
className: 'osd-music-cover',
|
||||
children: [
|
||||
Widget.Overlay({
|
||||
child: fallbackCoverArt,
|
||||
overlays: [realCoverArt],
|
||||
})
|
||||
],
|
||||
})
|
||||
}
|
||||
|
||||
const TrackControls = ({ player, ...rest }) => Widget.Revealer({
|
||||
revealChild: false,
|
||||
transition: 'slide_right',
|
||||
transitionDuration: userOptions.animations.durationLarge,
|
||||
child: Widget.Box({
|
||||
...rest,
|
||||
vpack: 'center',
|
||||
className: 'osd-music-controls spacing-h-3',
|
||||
children: [
|
||||
Button({
|
||||
className: 'osd-music-controlbtn',
|
||||
onClicked: () => player.previous(),
|
||||
child: Label({
|
||||
className: 'icon-material osd-music-controlbtn-txt',
|
||||
label: 'skip_previous',
|
||||
})
|
||||
}),
|
||||
Button({
|
||||
className: 'osd-music-controlbtn',
|
||||
onClicked: () => player.next(),
|
||||
child: Label({
|
||||
className: 'icon-material osd-music-controlbtn-txt',
|
||||
label: 'skip_next',
|
||||
})
|
||||
}),
|
||||
],
|
||||
}),
|
||||
setup: (self) => self.hook(Mpris, (self) => {
|
||||
// const player = Mpris.getPlayer();
|
||||
if (!player)
|
||||
self.revealChild = false;
|
||||
else
|
||||
self.revealChild = true;
|
||||
}, 'notify::play-back-status'),
|
||||
});
|
||||
|
||||
const TrackSource = ({ player, ...rest }) => Widget.Revealer({
|
||||
revealChild: false,
|
||||
transition: 'slide_left',
|
||||
transitionDuration: userOptions.animations.durationLarge,
|
||||
child: Widget.Box({
|
||||
...rest,
|
||||
className: 'osd-music-pill spacing-h-5',
|
||||
homogeneous: true,
|
||||
children: [
|
||||
Label({
|
||||
hpack: 'fill',
|
||||
justification: 'center',
|
||||
className: 'icon-nerd',
|
||||
setup: (self) => self.hook(player, (self) => {
|
||||
self.label = detectMediaSource(player.trackCoverUrl);
|
||||
}, 'notify::cover-path'),
|
||||
}),
|
||||
],
|
||||
}),
|
||||
setup: (self) => self.hook(Mpris, (self) => {
|
||||
const mpris = Mpris.getPlayer('');
|
||||
if (!mpris)
|
||||
self.revealChild = false;
|
||||
else
|
||||
self.revealChild = true;
|
||||
}),
|
||||
});
|
||||
|
||||
const TrackTime = ({ player, ...rest }) => {
|
||||
return Widget.Revealer({
|
||||
revealChild: false,
|
||||
transition: 'slide_left',
|
||||
transitionDuration: userOptions.animations.durationLarge,
|
||||
child: Widget.Box({
|
||||
...rest,
|
||||
vpack: 'center',
|
||||
className: 'osd-music-pill spacing-h-5',
|
||||
children: [
|
||||
Label({
|
||||
setup: (self) => self.poll(1000, (self) => {
|
||||
// const player = Mpris.getPlayer();
|
||||
if (!player) return;
|
||||
self.label = lengthStr(player.position);
|
||||
}),
|
||||
}),
|
||||
Label({ label: '/' }),
|
||||
Label({
|
||||
setup: (self) => self.hook(Mpris, (self) => {
|
||||
// const player = Mpris.getPlayer();
|
||||
if (!player) return;
|
||||
self.label = lengthStr(player.length);
|
||||
}),
|
||||
}),
|
||||
],
|
||||
}),
|
||||
setup: (self) => self.hook(Mpris, (self) => {
|
||||
if (!player) self.revealChild = false;
|
||||
else self.revealChild = true;
|
||||
}),
|
||||
})
|
||||
}
|
||||
|
||||
const PlayState = ({ player }) => {
|
||||
var position = 0;
|
||||
const trackCircProg = TrackProgress({ player: player });
|
||||
return Widget.Button({
|
||||
className: 'osd-music-playstate',
|
||||
child: Widget.Overlay({
|
||||
child: trackCircProg,
|
||||
overlays: [
|
||||
Widget.Button({
|
||||
className: 'osd-music-playstate-btn',
|
||||
onClicked: () => player.playPause(),
|
||||
child: Widget.Label({
|
||||
justification: 'center',
|
||||
hpack: 'fill',
|
||||
vpack: 'center',
|
||||
setup: (self) => self.hook(player, (label) => {
|
||||
label.label = `${player.playBackStatus == 'Playing' ? 'pause' : 'play_arrow'}`;
|
||||
}, 'notify::play-back-status'),
|
||||
}),
|
||||
}),
|
||||
],
|
||||
passThrough: true,
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
const MusicControlsWidget = (player) => Box({
|
||||
className: 'osd-music spacing-h-20 test',
|
||||
children: [
|
||||
CoverArt({ player: player, vpack: 'center' }),
|
||||
Box({
|
||||
vertical: true,
|
||||
className: 'spacing-v-5 osd-music-info',
|
||||
children: [
|
||||
Box({
|
||||
vertical: true,
|
||||
vpack: 'center',
|
||||
hexpand: true,
|
||||
children: [
|
||||
TrackTitle({ player: player }),
|
||||
TrackArtists({ player: player }),
|
||||
]
|
||||
}),
|
||||
Box({ vexpand: true }),
|
||||
Box({
|
||||
className: 'spacing-h-10',
|
||||
setup: (box) => {
|
||||
box.pack_start(TrackControls({ player: player }), false, false, 0);
|
||||
box.pack_end(PlayState({ player: player }), false, false, 0);
|
||||
if(hasPlasmaIntegration || player.busName.startsWith('org.mpris.MediaPlayer2.chromium')) box.pack_end(TrackTime({ player: player }), false, false, 0)
|
||||
// box.pack_end(TrackSource({ vpack: 'center', player: player }), false, false, 0);
|
||||
}
|
||||
})
|
||||
]
|
||||
})
|
||||
]
|
||||
})
|
||||
|
||||
export default () => Revealer({
|
||||
transition: 'slide_down',
|
||||
transitionDuration: userOptions.animations.durationLarge,
|
||||
revealChild: false,
|
||||
child: Box({
|
||||
children: Mpris.bind("players")
|
||||
.as(players => players.map((player) => (isRealPlayer(player) ? MusicControlsWidget(player) : null)))
|
||||
}),
|
||||
setup: (self) => self.hook(showMusicControls, (revealer) => {
|
||||
revealer.revealChild = showMusicControls.value;
|
||||
}),
|
||||
})
|
||||
|
|
@ -1,45 +0,0 @@
|
|||
// This file is for popup notifications
|
||||
import Widget from 'resource:///com/github/Aylur/ags/widget.js';
|
||||
import Notifications from 'resource:///com/github/Aylur/ags/service/notifications.js';
|
||||
const { Box } = Widget;
|
||||
import Notification from '../.commonwidgets/notification.js';
|
||||
|
||||
export default () => Box({
|
||||
vertical: true,
|
||||
hpack: 'center',
|
||||
className: 'osd-notifs spacing-v-5-revealer',
|
||||
attribute: {
|
||||
'map': new Map(),
|
||||
'dismiss': (box, id, force = false) => {
|
||||
if (!id || !box.attribute.map.has(id))
|
||||
return;
|
||||
const notifWidget = box.attribute.map.get(id);
|
||||
if (notifWidget == null || notifWidget.attribute.hovered && !force)
|
||||
return; // cuz already destroyed
|
||||
|
||||
notifWidget.revealChild = false;
|
||||
notifWidget.attribute.destroyWithAnims();
|
||||
box.attribute.map.delete(id);
|
||||
},
|
||||
'notify': (box, id) => {
|
||||
if (!id || Notifications.dnd) return;
|
||||
if (!Notifications.getNotification(id)) return;
|
||||
|
||||
box.attribute.map.delete(id);
|
||||
|
||||
const notif = Notifications.getNotification(id);
|
||||
const newNotif = Notification({
|
||||
notifObject: notif,
|
||||
isPopup: true,
|
||||
});
|
||||
box.attribute.map.set(id, newNotif);
|
||||
box.pack_end(box.attribute.map.get(id), false, false, 0);
|
||||
box.show_all();
|
||||
},
|
||||
},
|
||||
setup: (self) => self
|
||||
.hook(Notifications, (box, id) => box.attribute.notify(box, id), 'notified')
|
||||
.hook(Notifications, (box, id) => box.attribute.dismiss(box, id), 'dismissed')
|
||||
.hook(Notifications, (box, id) => box.attribute.dismiss(box, id, true), 'closed')
|
||||
,
|
||||
});
|
||||
|
|
@ -1,218 +0,0 @@
|
|||
// We're going to use ydotool
|
||||
// See /usr/include/linux/input-event-codes.h for keycodes
|
||||
|
||||
export const DEFAULT_OSK_LAYOUT = "qwerty_full"
|
||||
export const oskLayouts = {
|
||||
qwerty_full: {
|
||||
name: "QWERTY - Full",
|
||||
name_short: "US",
|
||||
comment: "Like physical keyboard",
|
||||
// A key looks like this: { k: "a", ks: "A", t: "normal" } (key, key-shift, type)
|
||||
// key types are: normal, tab, caps, shift, control, fn (normal w/ half height), space, expand
|
||||
// keys: [
|
||||
// [{ k: "Esc", t: "fn" }, { k: "F1", t: "fn" }, { k: "F2", t: "fn" }, { k: "F3", t: "fn" }, { k: "F4", t: "fn" }, { k: "F5", t: "fn" }, { k: "F6", t: "fn" }, { k: "F7", t: "fn" }, { k: "F8", t: "fn" }, { k: "F9", t: "fn" }, { k: "F10", t: "fn" }, { k: "F11", t: "fn" }, { k: "F12", t: "fn" }, { k: "PrtSc", t: "fn" }, { k: "Del", t: "fn" }],
|
||||
// [{ k: "`", ks: "~", t: "normal" }, { k: "1", ks: "!", t: "normal" }, { k: "2", ks: "@", t: "normal" }, { k: "3", ks: "#", t: "normal" }, { k: "4", ks: "$", t: "normal" }, { k: "5", ks: "%", t: "normal" }, { k: "6", ks: "^", t: "normal" }, { k: "7", ks: "&", t: "normal" }, { k: "8", ks: "*", t: "normal" }, { k: "9", ks: "(", t: "normal" }, { k: "0", ks: ")", t: "normal" }, { k: "-", ks: "_", t: "normal" }, { k: "=", ks: "+", t: "normal" }, { k: "Backspace", t: "shift" }],
|
||||
// [{ k: "Tab", t: "tab" }, { k: "q", ks: "Q", t: "normal" }, { k: "w", ks: "W", t: "normal" }, { k: "e", ks: "E", t: "normal" }, { k: "r", ks: "R", t: "normal" }, { k: "t", ks: "T", t: "normal" }, { k: "y", ks: "Y", t: "normal" }, { k: "u", ks: "U", t: "normal" }, { k: "i", ks: "I", t: "normal" }, { k: "o", ks: "O", t: "normal" }, { k: "p", ks: "P", t: "normal" }, { k: "[", ks: "{", t: "normal" }, { k: "]", ks: "}", t: "normal" }, { k: "\\", ks: "|", t: "expand" }],
|
||||
// [{ k: "Caps", t: "caps" }, { k: "a", ks: "A", t: "normal" }, { k: "s", ks: "S", t: "normal" }, { k: "d", ks: "D", t: "normal" }, { k: "f", ks: "F", t: "normal" }, { k: "g", ks: "G", t: "normal" }, { k: "h", ks: "H", t: "normal" }, { k: "j", ks: "J", t: "normal" }, { k: "k", ks: "K", t: "normal" }, { k: "l", ks: "L", t: "normal" }, { k: ";", ks: ":", t: "normal" }, { k: "'", ks: '"', t: "normal" }, { k: "Enter", t: "expand" }],
|
||||
// [{ k: "Shift", t: "shift" }, { k: "z", ks: "Z", t: "normal" }, { k: "x", ks: "X", t: "normal" }, { k: "c", ks: "C", t: "normal" }, { k: "v", ks: "V", t: "normal" }, { k: "b", ks: "B", t: "normal" }, { k: "n", ks: "N", t: "normal" }, { k: "m", ks: "M", t: "normal" }, { k: ",", ks: "<", t: "normal" }, { k: ".", ks: ">", t: "normal" }, { k: "/", ks: "?", t: "normal" }, { k: "Shift", t: "expand" }],
|
||||
// [{ k: "Ctrl", t: "control" }, { k: "Fn", t: "normal" }, { k: "Win", t: "normal" }, { k: "Alt", t: "normal" }, { k: "Space", t: "space" }, { k: "Alt", t: "normal" }, { k: "Menu", t: "normal" }, { k: "Ctrl", t: "control" }]
|
||||
// ]
|
||||
// A normal key looks like this: {label: "a", labelShift: "A", shape: "normal", keycode: 30, type: "normal"}
|
||||
// A modkey looks like this: {label: "Ctrl", shape: "control", keycode: 29, type: "modkey"}
|
||||
// key types are: normal, tab, caps, shift, control, fn (normal w/ half height), space, expand
|
||||
keys: [
|
||||
[
|
||||
{ keytype: "normal", label: "Esc", shape: "fn", keycode: 1 },
|
||||
{ keytype: "normal", label: "F1", shape: "fn", keycode: 59 },
|
||||
{ keytype: "normal", label: "F2", shape: "fn", keycode: 60 },
|
||||
{ keytype: "normal", label: "F3", shape: "fn", keycode: 61 },
|
||||
{ keytype: "normal", label: "F4", shape: "fn", keycode: 62 },
|
||||
{ keytype: "normal", label: "F5", shape: "fn", keycode: 63 },
|
||||
{ keytype: "normal", label: "F6", shape: "fn", keycode: 64 },
|
||||
{ keytype: "normal", label: "F7", shape: "fn", keycode: 65 },
|
||||
{ keytype: "normal", label: "F8", shape: "fn", keycode: 66 },
|
||||
{ keytype: "normal", label: "F9", shape: "fn", keycode: 67 },
|
||||
{ keytype: "normal", label: "F10", shape: "fn", keycode: 68 },
|
||||
{ keytype: "normal", label: "F11", shape: "fn", keycode: 87 },
|
||||
{ keytype: "normal", label: "F12", shape: "fn", keycode: 88 },
|
||||
{ keytype: "normal", label: "PrtSc", shape: "fn", keycode: 99 },
|
||||
{ keytype: "normal", label: "Del", shape: "fn", keycode: 111 }
|
||||
],
|
||||
[
|
||||
{ keytype: "normal", label: "`", labelShift: "~", shape: "normal", keycode: 41 },
|
||||
{ keytype: "normal", label: "1", labelShift: "!", shape: "normal", keycode: 2 },
|
||||
{ keytype: "normal", label: "2", labelShift: "@", shape: "normal", keycode: 3 },
|
||||
{ keytype: "normal", label: "3", labelShift: "#", shape: "normal", keycode: 4 },
|
||||
{ keytype: "normal", label: "4", labelShift: "$", shape: "normal", keycode: 5 },
|
||||
{ keytype: "normal", label: "5", labelShift: "%", shape: "normal", keycode: 6 },
|
||||
{ keytype: "normal", label: "6", labelShift: "^", shape: "normal", keycode: 7 },
|
||||
{ keytype: "normal", label: "7", labelShift: "&", shape: "normal", keycode: 8 },
|
||||
{ keytype: "normal", label: "8", labelShift: "*", shape: "normal", keycode: 9 },
|
||||
{ keytype: "normal", label: "9", labelShift: "(", shape: "normal", keycode: 10 },
|
||||
{ keytype: "normal", label: "0", labelShift: ")", shape: "normal", keycode: 11 },
|
||||
{ keytype: "normal", label: "-", labelShift: "_", shape: "normal", keycode: 12 },
|
||||
{ keytype: "normal", label: "=", labelShift: "+", shape: "normal", keycode: 13 },
|
||||
{ keytype: "normal", label: "Backspace", shape: "expand", keycode: 14 }
|
||||
],
|
||||
[
|
||||
{ keytype: "normal", label: "Tab", shape: "tab", keycode: 15 },
|
||||
{ keytype: "normal", label: "q", labelShift: "Q", shape: "normal", keycode: 16 },
|
||||
{ keytype: "normal", label: "w", labelShift: "W", shape: "normal", keycode: 17 },
|
||||
{ keytype: "normal", label: "e", labelShift: "E", shape: "normal", keycode: 18 },
|
||||
{ keytype: "normal", label: "r", labelShift: "R", shape: "normal", keycode: 19 },
|
||||
{ keytype: "normal", label: "t", labelShift: "T", shape: "normal", keycode: 20 },
|
||||
{ keytype: "normal", label: "y", labelShift: "Y", shape: "normal", keycode: 21 },
|
||||
{ keytype: "normal", label: "u", labelShift: "U", shape: "normal", keycode: 22 },
|
||||
{ keytype: "normal", label: "i", labelShift: "I", shape: "normal", keycode: 23 },
|
||||
{ keytype: "normal", label: "o", labelShift: "O", shape: "normal", keycode: 24 },
|
||||
{ keytype: "normal", label: "p", labelShift: "P", shape: "normal", keycode: 25 },
|
||||
{ keytype: "normal", label: "[", labelShift: "{", shape: "normal", keycode: 26 },
|
||||
{ keytype: "normal", label: "]", labelShift: "}", shape: "normal", keycode: 27 },
|
||||
{ keytype: "normal", label: "\\", labelShift: "|", shape: "expand", keycode: 43 }
|
||||
],
|
||||
[
|
||||
//{ keytype: "normal", label: "Caps", shape: "caps", keycode: 58 }, // not needed as double-pressing shift does that
|
||||
{ keytype: "spacer", label: "", shape: "empty" },
|
||||
{ keytype: "spacer", label: "", shape: "empty" },
|
||||
{ keytype: "normal", label: "a", labelShift: "A", shape: "normal", keycode: 30 },
|
||||
{ keytype: "normal", label: "s", labelShift: "S", shape: "normal", keycode: 31 },
|
||||
{ keytype: "normal", label: "d", labelShift: "D", shape: "normal", keycode: 32 },
|
||||
{ keytype: "normal", label: "f", labelShift: "F", shape: "normal", keycode: 33 },
|
||||
{ keytype: "normal", label: "g", labelShift: "G", shape: "normal", keycode: 34 },
|
||||
{ keytype: "normal", label: "h", labelShift: "H", shape: "normal", keycode: 35 },
|
||||
{ keytype: "normal", label: "j", labelShift: "J", shape: "normal", keycode: 36 },
|
||||
{ keytype: "normal", label: "k", labelShift: "K", shape: "normal", keycode: 37 },
|
||||
{ keytype: "normal", label: "l", labelShift: "L", shape: "normal", keycode: 38 },
|
||||
{ keytype: "normal", label: ";", labelShift: ":", shape: "normal", keycode: 39 },
|
||||
{ keytype: "normal", label: "'", labelShift: '"', shape: "normal", keycode: 40 },
|
||||
{ keytype: "normal", label: "Enter", shape: "expand", keycode: 28 }
|
||||
],
|
||||
[
|
||||
{ keytype: "modkey", label: "Shift", labelShift: "Shift ⇧", labelCaps: "Locked ⇩", shape: "shift", keycode: 42 },
|
||||
{ keytype: "normal", label: "z", labelShift: "Z", shape: "normal", keycode: 44 },
|
||||
{ keytype: "normal", label: "x", labelShift: "X", shape: "normal", keycode: 45 },
|
||||
{ keytype: "normal", label: "c", labelShift: "C", shape: "normal", keycode: 46 },
|
||||
{ keytype: "normal", label: "v", labelShift: "V", shape: "normal", keycode: 47 },
|
||||
{ keytype: "normal", label: "b", labelShift: "B", shape: "normal", keycode: 48 },
|
||||
{ keytype: "normal", label: "n", labelShift: "N", shape: "normal", keycode: 49 },
|
||||
{ keytype: "normal", label: "m", labelShift: "M", shape: "normal", keycode: 50 },
|
||||
{ keytype: "normal", label: ",", labelShift: "<", shape: "normal", keycode: 51 },
|
||||
{ keytype: "normal", label: ".", labelShift: ">", shape: "normal", keycode: 52 },
|
||||
{ keytype: "normal", label: "/", labelShift: "?", shape: "normal", keycode: 53 },
|
||||
{ keytype: "modkey", label: "Shift", labelShift: "Shift ⇧", labelCaps: "Locked ⇩", shape: "expand", keycode: 54 } // optional
|
||||
],
|
||||
[
|
||||
{ keytype: "modkey", label: "Ctrl", shape: "control", keycode: 29 },
|
||||
// { label: "Super", shape: "normal", keycode: 125 }, // dangerous
|
||||
{ keytype: "modkey", label: "Alt", shape: "normal", keycode: 56 },
|
||||
{ keytype: "normal", label: "Space", shape: "space", keycode: 57 },
|
||||
{ keytype: "modkey", label: "Alt", shape: "normal", keycode: 100 },
|
||||
// { label: "Super", shape: "normal", keycode: 126 }, // dangerous
|
||||
{ keytype: "normal", label: "Menu", shape: "normal", keycode: 139 },
|
||||
{ keytype: "modkey", label: "Ctrl", shape: "control", keycode: 97 }
|
||||
]
|
||||
]
|
||||
},
|
||||
qwertz_full: {
|
||||
name: "QWERTZ - Full",
|
||||
name_short: "DE",
|
||||
comment: "Keyboard layout commonly used in German-speaking countries",
|
||||
keys: [
|
||||
[
|
||||
{ keytype: "normal", label: "Esc", shape: "fn", keycode: 1 },
|
||||
{ keytype: "normal", label: "F1", shape: "fn", keycode: 59 },
|
||||
{ keytype: "normal", label: "F2", shape: "fn", keycode: 60 },
|
||||
{ keytype: "normal", label: "F3", shape: "fn", keycode: 61 },
|
||||
{ keytype: "normal", label: "F4", shape: "fn", keycode: 62 },
|
||||
{ keytype: "normal", label: "F5", shape: "fn", keycode: 63 },
|
||||
{ keytype: "normal", label: "F6", shape: "fn", keycode: 64 },
|
||||
{ keytype: "normal", label: "F7", shape: "fn", keycode: 65 },
|
||||
{ keytype: "normal", label: "F8", shape: "fn", keycode: 66 },
|
||||
{ keytype: "normal", label: "F9", shape: "fn", keycode: 67 },
|
||||
{ keytype: "normal", label: "F10", shape: "fn", keycode: 68 },
|
||||
{ keytype: "normal", label: "F11", shape: "fn", keycode: 87 },
|
||||
{ keytype: "normal", label: "F12", shape: "fn", keycode: 88 },
|
||||
{ keytype: "normal", label: "Druck", shape: "fn", keycode: 99 },
|
||||
{ keytype: "normal", label: "Entf", shape: "fn", keycode: 111 }
|
||||
],
|
||||
[
|
||||
{ keytype: "normal", label: "^", labelShift: "°", labelAlt: "′", shape: "normal", keycode: 41 },
|
||||
{ keytype: "normal", label: "1", labelShift: "!", labelAlt: "¹", shape: "normal", keycode: 2 },
|
||||
{ keytype: "normal", label: "2", labelShift: "\"", labelAlt: "²", shape: "normal", keycode: 3 },
|
||||
{ keytype: "normal", label: "3", labelShift: "§", labelAlt: "³", shape: "normal", keycode: 4 },
|
||||
{ keytype: "normal", label: "4", labelShift: "$", labelAlt: "¼", shape: "normal", keycode: 5 },
|
||||
{ keytype: "normal", label: "5", labelShift: "%", labelAlt: "½", shape: "normal", keycode: 6 },
|
||||
{ keytype: "normal", label: "6", labelShift: "&", labelAlt: "¬", shape: "normal", keycode: 7 },
|
||||
{ keytype: "normal", label: "7", labelShift: "/", labelAlt: "{", shape: "normal", keycode: 8 },
|
||||
{ keytype: "normal", label: "8", labelShift: "(", labelAlt: "[", shape: "normal", keycode: 9 },
|
||||
{ keytype: "normal", label: "9", labelShift: ")", labelAlt: "]", shape: "normal", keycode: 10 },
|
||||
{ keytype: "normal", label: "0", labelShift: "=", labelAlt: "}", shape: "normal", keycode: 11 },
|
||||
{ keytype: "normal", label: "ß", labelShift: "?", labelAlt: "\\", shape: "normal", keycode: 12 },
|
||||
{ keytype: "normal", label: "´", labelShift: "`", labelAlt: "¸", shape: "normal", keycode: 13 },
|
||||
{ keytype: "normal", label: "⟵", shape: "expand", keycode: 14 }
|
||||
],
|
||||
[
|
||||
{ keytype: "normal", label: "Tab ⇆", shape: "tab", keycode: 15 },
|
||||
{ keytype: "normal", label: "q", labelShift: "Q", labelAlt: "@", shape: "normal", keycode: 16 },
|
||||
{ keytype: "normal", label: "w", labelShift: "W", labelAlt: "ſ", shape: "normal", keycode: 17 },
|
||||
{ keytype: "normal", label: "e", labelShift: "E", labelAlt: "€", shape: "normal", keycode: 18 },
|
||||
{ keytype: "normal", label: "r", labelShift: "R", labelAlt: "¶", shape: "normal", keycode: 19 },
|
||||
{ keytype: "normal", label: "t", labelShift: "T", labelAlt: "ŧ", shape: "normal", keycode: 20 },
|
||||
{ keytype: "normal", label: "z", labelShift: "Z", labelAlt: "←", shape: "normal", keycode: 21 },
|
||||
{ keytype: "normal", label: "u", labelShift: "U", labelAlt: "↓", shape: "normal", keycode: 22 },
|
||||
{ keytype: "normal", label: "i", labelShift: "I", labelAlt: "→", shape: "normal", keycode: 23 },
|
||||
{ keytype: "normal", label: "o", labelShift: "O", labelAlt: "ø", shape: "normal", keycode: 24 },
|
||||
{ keytype: "normal", label: "p", labelShift: "P", labelAlt: "þ", shape: "normal", keycode: 25 },
|
||||
{ keytype: "normal", label: "ü", labelShift: "Ü", labelAlt: "¨", shape: "normal", keycode: 26 },
|
||||
{ keytype: "normal", label: "+", labelShift: "*", labelAlt: "~", shape: "normal", keycode: 27 },
|
||||
{ keytype: "normal", label: "↵", shape: "expand", keycode: 28 }
|
||||
],
|
||||
[
|
||||
//{ keytype: "normal", label: "Umschalt ⇩", shape: "caps", keycode: 58 },
|
||||
{ keytype: "spacer", label: "", shape: "empty" },
|
||||
{ keytype: "spacer", label: "", shape: "empty" },
|
||||
{ keytype: "normal", label: "a", labelShift: "A", labelAlt: "æ", shape: "normal", keycode: 30 },
|
||||
{ keytype: "normal", label: "s", labelShift: "S", labelAlt: "ſ", shape: "normal", keycode: 31 },
|
||||
{ keytype: "normal", label: "d", labelShift: "D", labelAlt: "ð", shape: "normal", keycode: 32 },
|
||||
{ keytype: "normal", label: "f", labelShift: "F", labelAlt: "đ", shape: "normal", keycode: 33 },
|
||||
{ keytype: "normal", label: "g", labelShift: "G", labelAlt: "ŋ", shape: "normal", keycode: 34 },
|
||||
{ keytype: "normal", label: "h", labelShift: "H", labelAlt: "ħ", shape: "normal", keycode: 35 },
|
||||
{ keytype: "normal", label: "j", labelShift: "J", labelAlt: "", shape: "normal", keycode: 36 },
|
||||
{ keytype: "normal", label: "k", labelShift: "K", labelAlt: "ĸ", shape: "normal", keycode: 37 },
|
||||
{ keytype: "normal", label: "l", labelShift: "L", labelAlt: "ł", shape: "normal", keycode: 38 },
|
||||
{ keytype: "normal", label: "ö", labelShift: "Ö", labelAlt: "˝", shape: "normal", keycode: 39 },
|
||||
{ keytype: "normal", label: "ä", labelShift: 'Ä', labelAlt: "^", shape: "normal", keycode: 40 },
|
||||
{ keytype: "normal", label: "#", labelShift: '\'', labelAlt: "’", shape: "normal", keycode: 43 },
|
||||
{ keytype: "spacer", label: "", shape: "empty" },
|
||||
//{ keytype: "normal", label: "↵", shape: "expand", keycode: 28 }
|
||||
],
|
||||
[
|
||||
{ keytype: "modkey", label: "Shift", labelShift: "Shift ⇧", labelCaps: "Locked ⇩", shape: "shift", keycode: 42 },
|
||||
{ keytype: "normal", label: "<", labelShift: ">", labelAlt: "|", shape: "normal", keycode: 86 },
|
||||
{ keytype: "normal", label: "y", labelShift: "Y", labelAlt: "»", shape: "normal", keycode: 44 },
|
||||
{ keytype: "normal", label: "x", labelShift: "X", labelAlt: "«", shape: "normal", keycode: 45 },
|
||||
{ keytype: "normal", label: "c", labelShift: "C", labelAlt: "¢", shape: "normal", keycode: 46 },
|
||||
{ keytype: "normal", label: "v", labelShift: "V", labelAlt: "„", shape: "normal", keycode: 47 },
|
||||
{ keytype: "normal", label: "b", labelShift: "B", labelAlt: "“", shape: "normal", keycode: 48 },
|
||||
{ keytype: "normal", label: "n", labelShift: "N", labelAlt: "”", shape: "normal", keycode: 49 },
|
||||
{ keytype: "normal", label: "m", labelShift: "M", labelAlt: "µ", shape: "normal", keycode: 50 },
|
||||
{ keytype: "normal", label: ",", labelShift: ";", labelAlt: "·", shape: "normal", keycode: 51 },
|
||||
{ keytype: "normal", label: ".", labelShift: ":", labelAlt: "…", shape: "normal", keycode: 52 },
|
||||
{ keytype: "normal", label: "-", labelShift: "_", labelAlt: "–", shape: "normal", keycode: 53 },
|
||||
{ keytype: "modkey", label: "Shift", labelShift: "Shift ⇧", labelCaps: "Locked ⇩", shape: "expand", keycode: 54 }, // optional
|
||||
],
|
||||
[
|
||||
{ keytype: "modkey", label: "Strg", shape: "control", keycode: 29 },
|
||||
//{ keytype: "normal", label: "", shape: "normal", keycode: 125 }, // dangerous
|
||||
{ keytype: "modkey", label: "Alt", shape: "normal", keycode: 56 },
|
||||
{ keytype: "normal", label: "Leertaste", shape: "space", keycode: 57 },
|
||||
{ keytype: "modkey", label: "Alt Gr", shape: "normal", keycode: 100 },
|
||||
// { label: "Super", shape: "normal", keycode: 126 }, // dangerous
|
||||
//{ keytype: "normal", label: "Menu", shape: "normal", keycode: 139 }, // doesn't work?
|
||||
{ keytype: "modkey", label: "Strg", shape: "control", keycode: 97 },
|
||||
{ keytype: "normal", label: "⇦", shape: "normal", keycode: 105 },
|
||||
{ keytype: "normal", label: "⇨", shape: "normal", keycode: 106 },
|
||||
]
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
import PopupWindow from '../.widgethacks/popupwindow.js';
|
||||
import OnScreenKeyboard from "./onscreenkeyboard.js";
|
||||
|
||||
export default (id) => PopupWindow({
|
||||
monitor: id,
|
||||
anchor: ['bottom'],
|
||||
name: `osk${id}`,
|
||||
showClassName: 'osk-show',
|
||||
hideClassName: 'osk-hide',
|
||||
child: OnScreenKeyboard({ id: id }),
|
||||
});
|
||||
|
|
@ -1,267 +0,0 @@
|
|||
const { Gtk } = imports.gi;
|
||||
import App from 'resource:///com/github/Aylur/ags/app.js';
|
||||
import Widget from 'resource:///com/github/Aylur/ags/widget.js';
|
||||
import * as Utils from 'resource:///com/github/Aylur/ags/utils.js';
|
||||
|
||||
const { Box, EventBox, Button, Revealer } = Widget;
|
||||
const { execAsync } = Utils;
|
||||
import { MaterialIcon } from '../.commonwidgets/materialicon.js';
|
||||
import { DEFAULT_OSK_LAYOUT, oskLayouts } from './data_keyboardlayouts.js';
|
||||
import { setupCursorHoverGrab } from '../.widgetutils/cursorhover.js';
|
||||
|
||||
const keyboardLayout = oskLayouts[userOptions.onScreenKeyboard.layout] ? userOptions.onScreenKeyboard.layout : DEFAULT_OSK_LAYOUT;
|
||||
const keyboardJson = oskLayouts[keyboardLayout];
|
||||
|
||||
async function startYdotoolIfNeeded() {
|
||||
const running = exec('pidof ydotool')
|
||||
if (!running) execAsync(['ydotoold']).catch(print);
|
||||
}
|
||||
|
||||
function releaseAllKeys() {
|
||||
const keycodes = Array.from(Array(249).keys());
|
||||
execAsync([`ydotool`, `key`, ...keycodes.map(keycode => `${keycode}:0`)])
|
||||
.then(console.log('[OSK] Released all keys'))
|
||||
.catch(print);
|
||||
}
|
||||
class ShiftMode {
|
||||
static Off = new ShiftMode('Off');
|
||||
static Normal = new ShiftMode('Normal');
|
||||
static Locked = new ShiftMode('Locked');
|
||||
|
||||
constructor(name) {
|
||||
this.name = name;
|
||||
}
|
||||
toString() {
|
||||
return `ShiftMode.${this.name}`;
|
||||
}
|
||||
}
|
||||
var modsPressed = false;
|
||||
|
||||
const TopDecor = () => Box({
|
||||
vertical: true,
|
||||
children: [
|
||||
Box({
|
||||
hpack: 'center',
|
||||
className: 'osk-dragline',
|
||||
homogeneous: true,
|
||||
children: [EventBox({
|
||||
setup: setupCursorHoverGrab,
|
||||
})]
|
||||
})
|
||||
]
|
||||
});
|
||||
|
||||
const KeyboardControlButton = (icon, text, runFunction) => Button({
|
||||
className: 'osk-control-button spacing-h-10',
|
||||
onClicked: () => runFunction(),
|
||||
child: Widget.Box({
|
||||
children: [
|
||||
MaterialIcon(icon, 'norm'),
|
||||
Widget.Label({
|
||||
label: `${text}`,
|
||||
}),
|
||||
]
|
||||
})
|
||||
})
|
||||
|
||||
const KeyboardControls = () => Box({
|
||||
vertical: true,
|
||||
className: 'spacing-v-5',
|
||||
children: [
|
||||
Button({
|
||||
className: 'osk-control-button txt-norm icon-material',
|
||||
onClicked: () => {
|
||||
releaseAllKeys();
|
||||
toggleWindowOnAllMonitors('osk');
|
||||
},
|
||||
label: 'keyboard_hide',
|
||||
}),
|
||||
Button({
|
||||
className: 'osk-control-button txt-norm',
|
||||
label: `${keyboardJson['name_short']}`,
|
||||
}),
|
||||
Button({
|
||||
className: 'osk-control-button txt-norm icon-material',
|
||||
onClicked: () => { // TODO: Proper clipboard widget, since fuzzel doesn't receive mouse inputs
|
||||
execAsync([`bash`, `-c`, "pkill fuzzel || cliphist list | fuzzel --match-mode fzf --dmenu | cliphist decode | wl-copy"]).catch(print);
|
||||
},
|
||||
label: 'assignment',
|
||||
}),
|
||||
]
|
||||
})
|
||||
|
||||
var shiftMode = ShiftMode.Off;
|
||||
var shiftButton;
|
||||
var rightShiftButton;
|
||||
var allButtons = [];
|
||||
const KeyboardItself = (kbJson) => {
|
||||
return Box({
|
||||
vertical: true,
|
||||
className: 'spacing-v-5',
|
||||
children: kbJson.keys.map(row => Box({
|
||||
vertical: false,
|
||||
className: 'spacing-h-5',
|
||||
children: row.map(key => {
|
||||
return Button({
|
||||
className: `osk-key osk-key-${key.shape}`,
|
||||
hexpand: ["space", "expand"].includes(key.shape),
|
||||
label: key.label,
|
||||
attribute:
|
||||
{ key: key },
|
||||
setup: (button) => {
|
||||
let pressed = false;
|
||||
allButtons = allButtons.concat(button);
|
||||
if (key.keytype == "normal") {
|
||||
button.connect('pressed', () => { // mouse down
|
||||
execAsync(`ydotool key ${key.keycode}:1`).catch(print);
|
||||
});
|
||||
button.connect('clicked', () => { // release
|
||||
execAsync(`ydotool key ${key.keycode}:0`).catch(print);
|
||||
|
||||
if (shiftMode == ShiftMode.Normal) {
|
||||
shiftMode = ShiftMode.Off;
|
||||
if (typeof shiftButton !== 'undefined') {
|
||||
execAsync(`ydotool key 42:0`).catch(print);
|
||||
shiftButton.toggleClassName('osk-key-active', false);
|
||||
}
|
||||
if (typeof rightShiftButton !== 'undefined') {
|
||||
execAsync(`ydotool key 54:0`).catch(print);
|
||||
rightShiftButton.toggleClassName('osk-key-active', false);
|
||||
}
|
||||
allButtons.forEach(button => {
|
||||
if (typeof button.attribute.key.labelShift !== 'undefined') button.label = button.attribute.key.label;
|
||||
})
|
||||
}
|
||||
});
|
||||
}
|
||||
else if (key.keytype == "modkey") {
|
||||
button.connect('pressed', () => { // release
|
||||
if (pressed) {
|
||||
execAsync(`ydotool key ${key.keycode}:0`).catch(print);
|
||||
button.toggleClassName('osk-key-active', false);
|
||||
pressed = false;
|
||||
if (key.keycode == 100) { // Alt Gr button
|
||||
allButtons.forEach(button => { if (typeof button.attribute.key.labelAlt !== 'undefined') button.label = button.attribute.key.label; });
|
||||
}
|
||||
}
|
||||
else {
|
||||
execAsync(`ydotool key ${key.keycode}:1`).catch(print);
|
||||
button.toggleClassName('osk-key-active', true);
|
||||
if (!(key.keycode == 42 || key.keycode == 54)) pressed = true;
|
||||
else switch (shiftMode.name) { // This toggles the shift button state
|
||||
case "Off": {
|
||||
shiftMode = ShiftMode.Normal;
|
||||
allButtons.forEach(button => { if (typeof button.attribute.key.labelShift !== 'undefined') button.label = button.attribute.key.labelShift; })
|
||||
if (typeof shiftButton !== 'undefined') {
|
||||
shiftButton.toggleClassName('osk-key-active', true);
|
||||
}
|
||||
if (typeof rightShiftButton !== 'undefined') {
|
||||
rightShiftButton.toggleClassName('osk-key-active', true);
|
||||
}
|
||||
} break;
|
||||
case "Normal": {
|
||||
shiftMode = ShiftMode.Locked;
|
||||
if (typeof shiftButton !== 'undefined') shiftButton.label = key.labelCaps;
|
||||
if (typeof rightShiftButton !== 'undefined') rightShiftButton.label = key.labelCaps;
|
||||
} break;
|
||||
case "Locked": {
|
||||
shiftMode = ShiftMode.Off;
|
||||
if (typeof shiftButton !== 'undefined') {
|
||||
shiftButton.label = key.label;
|
||||
shiftButton.toggleClassName('osk-key-active', false);
|
||||
}
|
||||
if (typeof rightShiftButton !== 'undefined') {
|
||||
rightShiftButton.label = key.label;
|
||||
rightShiftButton.toggleClassName('osk-key-active', false);
|
||||
}
|
||||
execAsync(`ydotool key ${key.keycode}:0`).catch(print);
|
||||
|
||||
allButtons.forEach(button => { if (typeof button.attribute.key.labelShift !== 'undefined') button.label = button.attribute.key.label; }
|
||||
)
|
||||
};
|
||||
}
|
||||
if (key.keycode == 100) { // Alt Gr button
|
||||
allButtons.forEach(button => { if (typeof button.attribute.key.labelAlt !== 'undefined') button.label = button.attribute.key.labelAlt; });
|
||||
}
|
||||
modsPressed = true;
|
||||
}
|
||||
});
|
||||
if (key.keycode == 42) shiftButton = button;
|
||||
else if (key.keycode == 54) rightShiftButton = button;
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
}))
|
||||
})
|
||||
}
|
||||
|
||||
const KeyboardWindow = () => Box({
|
||||
vexpand: true,
|
||||
hexpand: true,
|
||||
vertical: true,
|
||||
className: 'osk-window spacing-v-5',
|
||||
children: [
|
||||
TopDecor(),
|
||||
Box({
|
||||
className: 'osk-body spacing-h-10',
|
||||
children: [
|
||||
KeyboardControls(),
|
||||
Widget.Box({ className: 'separator-line' }),
|
||||
KeyboardItself(keyboardJson),
|
||||
],
|
||||
})
|
||||
],
|
||||
setup: (self) => self.hook(App, (self, name, visible) => { // Update on open
|
||||
if (!name) return;
|
||||
if (name.startsWith('osk') && visible) {
|
||||
self.setCss(`margin-bottom: -0px;`);
|
||||
}
|
||||
}),
|
||||
});
|
||||
|
||||
export default ({ id }) => {
|
||||
const kbWindow = KeyboardWindow();
|
||||
const gestureEvBox = EventBox({ child: kbWindow })
|
||||
const gesture = Gtk.GestureDrag.new(gestureEvBox);
|
||||
gesture.connect('drag-begin', async () => {
|
||||
try {
|
||||
const Hyprland = (await import('resource:///com/github/Aylur/ags/service/hyprland.js')).default;
|
||||
Hyprland.messageAsync('j/cursorpos').then((out) => {
|
||||
gesture.startY = JSON.parse(out).y;
|
||||
}).catch(print);
|
||||
} catch {
|
||||
return;
|
||||
}
|
||||
});
|
||||
gesture.connect('drag-update', async () => {
|
||||
try {
|
||||
const Hyprland = (await import('resource:///com/github/Aylur/ags/service/hyprland.js')).default;
|
||||
Hyprland.messageAsync('j/cursorpos').then((out) => {
|
||||
const currentY = JSON.parse(out).y;
|
||||
const offset = gesture.startY - currentY;
|
||||
|
||||
if (offset > 0) return;
|
||||
|
||||
kbWindow.setCss(`
|
||||
margin-bottom: ${offset}px;
|
||||
`);
|
||||
}).catch(print);
|
||||
} catch {
|
||||
return;
|
||||
}
|
||||
});
|
||||
gesture.connect('drag-end', () => {
|
||||
var offset = gesture.get_offset()[2];
|
||||
if (offset > 50) {
|
||||
App.closeWindow(`osk${id}`);
|
||||
}
|
||||
else {
|
||||
kbWindow.setCss(`
|
||||
transition: margin-bottom 170ms cubic-bezier(0.05, 0.7, 0.1, 1);
|
||||
margin-bottom: 0px;
|
||||
`);
|
||||
}
|
||||
})
|
||||
return gestureEvBox;
|
||||
};
|
||||
|
|
@ -1,28 +0,0 @@
|
|||
import * as Utils from 'resource:///com/github/Aylur/ags/utils.js';
|
||||
import Hyprland from 'resource:///com/github/Aylur/ags/service/hyprland.js';
|
||||
|
||||
function moveClientToWorkspace(address, workspace) {
|
||||
Utils.execAsync(['bash', '-c', `hyprctl dispatch movetoworkspacesilent ${workspace},address:${address} &`]);
|
||||
}
|
||||
|
||||
export function dumpToWorkspace(from, to) {
|
||||
if (from == to) return;
|
||||
Hyprland.clients.forEach(client => {
|
||||
if (client.workspace.id == from) {
|
||||
moveClientToWorkspace(client.address, to);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export function swapWorkspace(workspaceA, workspaceB) {
|
||||
if (workspaceA == workspaceB) return;
|
||||
const clientsA = [];
|
||||
const clientsB = [];
|
||||
Hyprland.clients.forEach(client => {
|
||||
if (client.workspace.id == workspaceA) clientsA.push(client.address);
|
||||
if (client.workspace.id == workspaceB) clientsB.push(client.address);
|
||||
});
|
||||
|
||||
clientsA.forEach((address) => moveClientToWorkspace(address, workspaceB));
|
||||
clientsB.forEach((address) => moveClientToWorkspace(address, workspaceA));
|
||||
}
|
||||
|
|
@ -1,28 +0,0 @@
|
|||
import Widget from 'resource:///com/github/Aylur/ags/widget.js';
|
||||
import { SearchAndWindows } from "./windowcontent.js";
|
||||
import PopupWindow from '../.widgethacks/popupwindow.js';
|
||||
import { clickCloseRegion } from '../.commonwidgets/clickcloseregion.js';
|
||||
|
||||
export default (id = '') => PopupWindow({
|
||||
name: `overview${id}`,
|
||||
// exclusivity: 'ignore',
|
||||
keymode: 'on-demand',
|
||||
visible: false,
|
||||
anchor: ['top', 'bottom', 'left', 'right'],
|
||||
layer: 'top',
|
||||
child: Widget.Box({
|
||||
vertical: true,
|
||||
children: [
|
||||
clickCloseRegion({ name: 'overview', multimonitor: false, expand: false }),
|
||||
Widget.Box({
|
||||
children: [
|
||||
clickCloseRegion({ name: 'overview', multimonitor: false }),
|
||||
SearchAndWindows(),
|
||||
clickCloseRegion({ name: 'overview', multimonitor: false }),
|
||||
]
|
||||
}),
|
||||
clickCloseRegion({ name: 'overview', multimonitor: false }),
|
||||
]
|
||||
}),
|
||||
})
|
||||
|
||||