Move some (all) files around
Signed-off-by: Nikolaos Karaolidis <nick@karaolidis.com>
This commit is contained in:
3
hosts/common/user/configs/gui/ags/config/.gitignore
vendored
Normal file
3
hosts/common/user/configs/gui/ags/config/.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
node_modules
|
||||
types
|
||||
bun.lockb
|
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"arrowParens": "avoid",
|
||||
"bracketSameLine": true,
|
||||
"bracketSpacing": true,
|
||||
"singleQuote": true,
|
||||
"trailingComma": "all"
|
||||
}
|
27
hosts/common/user/configs/gui/ags/config/default.nix
Normal file
27
hosts/common/user/configs/gui/ags/config/default.nix
Normal file
@@ -0,0 +1,27 @@
|
||||
{
|
||||
pkgs ? import <nixpkgs> { },
|
||||
...
|
||||
}:
|
||||
pkgs.stdenv.mkDerivation {
|
||||
name = "ags-config";
|
||||
|
||||
src = ./.;
|
||||
|
||||
nativeBuildInputs = with pkgs; [ bun ];
|
||||
|
||||
phases = [
|
||||
"buildPhase"
|
||||
"installPhase"
|
||||
];
|
||||
|
||||
buildPhase = ''
|
||||
bun build $src/src/index.ts --outfile=index.js \
|
||||
--external="file://$src/*" \
|
||||
--external="gi://*"
|
||||
'';
|
||||
|
||||
installPhase = ''
|
||||
mkdir -p $out/share
|
||||
cp index.js $out/share/config.js
|
||||
'';
|
||||
}
|
116
hosts/common/user/configs/gui/ags/config/eslint.config.js
Normal file
116
hosts/common/user/configs/gui/ags/config/eslint.config.js
Normal file
@@ -0,0 +1,116 @@
|
||||
/* eslint no-use-before-define: 0 */
|
||||
|
||||
import globals from 'globals';
|
||||
import pluginJs from '@eslint/js';
|
||||
import tseslint from 'typescript-eslint';
|
||||
import typescriptEslint from '@typescript-eslint/eslint-plugin';
|
||||
import unicorn from 'eslint-plugin-unicorn';
|
||||
import prettier from 'eslint-plugin-prettier';
|
||||
import tsParser from '@typescript-eslint/parser';
|
||||
|
||||
export default [
|
||||
{ files: ['**/*.{js,mjs,cjs,ts}'] },
|
||||
{ languageOptions: { globals: globals.browser } },
|
||||
pluginJs.configs.recommended,
|
||||
...tseslint.configs.recommended,
|
||||
{
|
||||
plugins: {
|
||||
'@typescript-eslint': typescriptEslint,
|
||||
unicorn,
|
||||
prettier,
|
||||
},
|
||||
|
||||
languageOptions: {
|
||||
globals: {
|
||||
...globals.browser,
|
||||
},
|
||||
|
||||
parser: tsParser,
|
||||
ecmaVersion: 5,
|
||||
sourceType: 'script',
|
||||
|
||||
parserOptions: {
|
||||
project: ['./tsconfig.json'],
|
||||
},
|
||||
},
|
||||
|
||||
settings: {
|
||||
'import/resolver': {
|
||||
node: {
|
||||
extensions: ['.js', '.jsx', '.ts', '.tsx'],
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
rules: {
|
||||
curly: ['error', 'multi-line'],
|
||||
'eol-last': ['error', 'always'],
|
||||
semi: ['error', 'always'],
|
||||
quotes: ['error', 'single'],
|
||||
'no-await-in-loop': 'warn',
|
||||
'no-constructor-return': 'error',
|
||||
'no-duplicate-imports': 'error',
|
||||
'no-self-compare': 'error',
|
||||
'no-unreachable-loop': 'error',
|
||||
'no-trailing-spaces': 'error',
|
||||
'no-console': 'warn',
|
||||
'no-shadow': 'off',
|
||||
'@typescript-eslint/no-shadow': ['error'],
|
||||
'no-unused-vars': 'off',
|
||||
'@typescript-eslint/no-unused-vars': ['error'],
|
||||
'no-use-before-define': 'off',
|
||||
'@typescript-eslint/no-use-before-define': ['error'],
|
||||
'@typescript-eslint/require-await': 'warn',
|
||||
|
||||
'@typescript-eslint/no-misused-promises': ['error', {
|
||||
checksVoidReturn: false,
|
||||
}],
|
||||
'@typescript-eslint/naming-convention': [
|
||||
'error',
|
||||
{
|
||||
selector: 'default',
|
||||
format: ['camelCase'],
|
||||
leadingUnderscore: 'allowSingleOrDouble',
|
||||
},
|
||||
{
|
||||
selector: 'variableLike',
|
||||
format: ['camelCase', 'PascalCase'],
|
||||
leadingUnderscore: 'allowSingleOrDouble',
|
||||
},
|
||||
{
|
||||
selector: 'memberLike',
|
||||
format: ['camelCase'],
|
||||
},
|
||||
{
|
||||
selector: 'typeLike',
|
||||
format: ['PascalCase'],
|
||||
},
|
||||
{
|
||||
selector: 'property',
|
||||
format: ['snake_case'],
|
||||
},
|
||||
{
|
||||
selector: 'method',
|
||||
format: ['camelCase'],
|
||||
},
|
||||
{
|
||||
selector: ['enumMember', 'enum'],
|
||||
format: ['UPPER_CASE'],
|
||||
}
|
||||
],
|
||||
|
||||
'unicorn/empty-brace-spaces': 'off',
|
||||
'unicorn/expiring-todo-comments': 'off',
|
||||
'unicorn/no-array-for-each': 'off',
|
||||
|
||||
'unicorn/filename-case': ['error', {
|
||||
case: 'camelCase',
|
||||
}],
|
||||
|
||||
'unicorn/numeric-separators-style': 'off',
|
||||
'unicorn/prevent-abbreviations': 'off',
|
||||
},
|
||||
|
||||
"ignores": ["*.config.js"]
|
||||
}
|
||||
];
|
23
hosts/common/user/configs/gui/ags/config/package.json
Normal file
23
hosts/common/user/configs/gui/ags/config/package.json
Normal file
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"name": "ags",
|
||||
"module": "index.ts",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"lint": "eslint ."
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/eslintrc": "^3.1.0",
|
||||
"@eslint/js": "^9.6.0",
|
||||
"@types/bun": "^1.1.6",
|
||||
"@typescript-eslint/eslint-plugin": "^7.14.1",
|
||||
"@typescript-eslint/parser": "^7.14.1",
|
||||
"eslint": "9.x",
|
||||
"eslint-plugin-prettier": "^5.1.3",
|
||||
"eslint-plugin-unicorn": "^54.0.0",
|
||||
"globals": "^15.6.0",
|
||||
"typescript-eslint": "^7.14.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"typescript": "^5.0.0"
|
||||
}
|
||||
}
|
19
hosts/common/user/configs/gui/ags/config/src/index.ts
Normal file
19
hosts/common/user/configs/gui/ags/config/src/index.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
import gtk from 'gi://Gtk?version=3.0';
|
||||
import gdk from 'gi://Gdk';
|
||||
import { range } from 'lib';
|
||||
import themeInit from 'theme';
|
||||
import bar from 'widgets/bar/bar';
|
||||
|
||||
const forMonitors = (widget: (monitor: number) => gtk.Window) => {
|
||||
const n = gdk.Display.get_default()?.get_n_monitors() || 1;
|
||||
return range(n, 0).flatMap(widget);
|
||||
};
|
||||
|
||||
App.config({
|
||||
style: themeInit(),
|
||||
windows: [
|
||||
...forMonitors(bar),
|
||||
]
|
||||
});
|
||||
|
||||
Utils.execAsync('systemd-notify --ready')
|
3
hosts/common/user/configs/gui/ags/config/src/lib.ts
Normal file
3
hosts/common/user/configs/gui/ags/config/src/lib.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
export const range = (length: number, start = 1) => {
|
||||
return Array.from({ length }, (n, i) => i + start);
|
||||
};
|
25
hosts/common/user/configs/gui/ags/config/src/theme.ts
Normal file
25
hosts/common/user/configs/gui/ags/config/src/theme.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
export default () => {
|
||||
const css = `${App.configDir}/theme.css`;
|
||||
const scss = `${App.configDir}/theme.sass`;
|
||||
|
||||
let themeExists = true;
|
||||
|
||||
try {
|
||||
Utils.readFile(scss);
|
||||
Utils.exec(`sassc ${scss} ${css}`);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
themeExists = false;
|
||||
}
|
||||
|
||||
Utils.monitorFile(
|
||||
`${App.configDir}/theme.sass`,
|
||||
function () {
|
||||
Utils.exec(`sassc ${scss} ${css}`);
|
||||
App.resetCss();
|
||||
App.applyCss(css);
|
||||
},
|
||||
);
|
||||
|
||||
return themeExists ? css : undefined;
|
||||
};
|
@@ -0,0 +1,39 @@
|
||||
import gap from './gap/gap';
|
||||
import launcher from './launcher/launcher';
|
||||
import workspace from './workspace/workspace';
|
||||
import date from './date/date';
|
||||
import systray from './systray/systray';
|
||||
|
||||
export default (monitor: number) => Widget.Window({
|
||||
monitor,
|
||||
class_name: 'bar',
|
||||
name: `bar${monitor}`,
|
||||
exclusivity: 'exclusive',
|
||||
anchor: ['top', 'right', 'left'],
|
||||
child: Widget.CenterBox({
|
||||
class_name: 'widgets',
|
||||
start_widget: Widget.Box({
|
||||
hexpand: true,
|
||||
hpack: 'start',
|
||||
children: [
|
||||
launcher(),
|
||||
gap(),
|
||||
workspace(),
|
||||
],
|
||||
}),
|
||||
center_widget: Widget.Box({
|
||||
hexpand: true,
|
||||
hpack: 'center',
|
||||
children: [
|
||||
date(),
|
||||
],
|
||||
}),
|
||||
end_widget: Widget.Box({
|
||||
hexpand: true,
|
||||
hpack: 'end',
|
||||
children: [
|
||||
systray(),
|
||||
],
|
||||
}),
|
||||
}),
|
||||
});
|
@@ -0,0 +1,10 @@
|
||||
const icon = () => Widget.Icon({
|
||||
class_name: 'icon',
|
||||
icon: 'edit-paste-symbolic',
|
||||
});
|
||||
|
||||
export default () => Widget.EventBox({
|
||||
class_name: 'clipboard',
|
||||
child: icon(),
|
||||
onPrimaryClick: () => Utils.execAsync('bash -c "cliphist list | rofi -cache-dir $XDG_CACHE_HOME/rofi -dmenu -display-columns 2 | cliphist decode | wl-copy"'),
|
||||
});
|
@@ -0,0 +1,18 @@
|
||||
import glib from 'gi://GLib';
|
||||
|
||||
const clock = Variable(glib.DateTime.new_now_local(), {
|
||||
poll: [1000, () => glib.DateTime.new_now_local()]
|
||||
});
|
||||
|
||||
const time = Utils.derive([clock], (c) => c.format('%H:%M - %A, %d %B %Y') || '');
|
||||
|
||||
const label = () => Widget.Label({
|
||||
class_name: 'label',
|
||||
justification: 'center',
|
||||
label: time.bind(),
|
||||
});
|
||||
|
||||
export default () => Widget.EventBox({
|
||||
class_name: 'date',
|
||||
child: label(),
|
||||
});
|
@@ -0,0 +1,3 @@
|
||||
export default () => Widget.Box({
|
||||
class_name: 'gap',
|
||||
});
|
@@ -0,0 +1,10 @@
|
||||
const icon = () => Widget.Icon({
|
||||
class_name: 'icon',
|
||||
icon: 'nix-snowflake-symbolic',
|
||||
});
|
||||
|
||||
export default () => Widget.EventBox({
|
||||
class_name: 'launcher',
|
||||
child: icon(),
|
||||
onPrimaryClick: () => Utils.execAsync('bash -c "rofi -cache-dir $XDG_CACHE_HOME/rofi -show drun"'),
|
||||
});
|
@@ -0,0 +1,16 @@
|
||||
import gdk from 'gi://Gdk';
|
||||
|
||||
const systemtray = await Service.import('systemtray');
|
||||
|
||||
const systrayItem = item => Widget.EventBox({
|
||||
class_name: 'item',
|
||||
tooltip_markup: item.bind('tooltip_markup'),
|
||||
child: Widget.Icon({ class_name: 'icon' }).bind('icon', item, 'icon'),
|
||||
onPrimaryClick: (_, event: gdk.Event) => item.activate(event),
|
||||
onSecondaryClick: (_, event: gdk.Event) => item.openMenu(event),
|
||||
});
|
||||
|
||||
export default () => Widget.Box({
|
||||
class_name: 'systray',
|
||||
children: systemtray.bind('items').as(i => i.map(systrayItem))
|
||||
});
|
@@ -0,0 +1,23 @@
|
||||
import { range } from 'lib';
|
||||
|
||||
const hyprland = await Service.import('hyprland');
|
||||
const dispatch = ws => hyprland.messageAsync(`dispatch workspace ${ws}`);
|
||||
|
||||
const workspaceButton = (i: number) => Widget.Label({
|
||||
class_name: 'button',
|
||||
attribute: i,
|
||||
vpack: 'center',
|
||||
setup: self => self.hook(hyprland, () => {
|
||||
self.toggleClassName('active', hyprland.active.workspace.id === i);
|
||||
self.toggleClassName('occupied', (hyprland.getWorkspace(i)?.windows || 0) > 0);
|
||||
}),
|
||||
});
|
||||
|
||||
export default () => Widget.EventBox({
|
||||
class_name: 'workspace',
|
||||
onScrollUp: () => dispatch('e-1'),
|
||||
onScrollDown: () => dispatch('e+1'),
|
||||
child: Widget.Box({
|
||||
children: range(10).map(workspaceButton),
|
||||
}),
|
||||
});
|
18
hosts/common/user/configs/gui/ags/config/tsconfig.json
Normal file
18
hosts/common/user/configs/gui/ags/config/tsconfig.json
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2022",
|
||||
"module": "ES2022",
|
||||
"lib": [
|
||||
"ES2022"
|
||||
],
|
||||
"allowJs": true,
|
||||
"checkJs": true,
|
||||
"strict": true,
|
||||
"noImplicitAny": false,
|
||||
"baseUrl": "./src",
|
||||
"typeRoots": [
|
||||
"./types",
|
||||
],
|
||||
"skipLibCheck": true,
|
||||
}
|
||||
}
|
73
hosts/common/user/configs/gui/ags/default.nix
Normal file
73
hosts/common/user/configs/gui/ags/default.nix
Normal file
@@ -0,0 +1,73 @@
|
||||
{
|
||||
user ? throw "user argument is required",
|
||||
}:
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
inputs,
|
||||
...
|
||||
}:
|
||||
let
|
||||
hmConfig = config.home-manager.users.${user.name};
|
||||
agsConfig = import ./config { inherit pkgs; };
|
||||
in
|
||||
{
|
||||
home-manager.users.${user.name} = {
|
||||
imports = [ inputs.ags.homeManagerModules.default ];
|
||||
|
||||
programs.ags.enable = true;
|
||||
|
||||
xdg.configFile.ags = {
|
||||
source = "${agsConfig}/share/config.js";
|
||||
target = "ags/config.js";
|
||||
};
|
||||
|
||||
programs.matugen.settings.templates.ags = {
|
||||
input_path = ./theme.sass;
|
||||
output_path = "${hmConfig.xdg.configHome}/ags/theme.sass";
|
||||
};
|
||||
|
||||
systemd.user = {
|
||||
targets.tray.Unit = {
|
||||
BindsTo = [ "ags.service" ];
|
||||
After = [
|
||||
"graphical-session.target"
|
||||
"ags.service"
|
||||
];
|
||||
};
|
||||
|
||||
services.ags = {
|
||||
Unit = {
|
||||
Description = "Desktop widget shell";
|
||||
BindsTo = [ "graphical-session.target" ];
|
||||
After = [ "graphical-session.target" ];
|
||||
};
|
||||
|
||||
Service = {
|
||||
Type = "notify";
|
||||
NotifyAccess = "all";
|
||||
|
||||
ExecStart = lib.meta.getExe (
|
||||
pkgs.writeShellApplication {
|
||||
name = "init-ags";
|
||||
runtimeInputs = with pkgs; [
|
||||
inputs.ags.packages.${stdenv.hostPlatform.system}.default
|
||||
sassc
|
||||
hyprland
|
||||
nixos-icons
|
||||
rofi-wayland
|
||||
wl-clipboard
|
||||
cliphist
|
||||
libdbusmenu-gtk3
|
||||
];
|
||||
text = "exec ags";
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
Install.WantedBy = [ "graphical-session.target" ];
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
74
hosts/common/user/configs/gui/ags/theme.sass
Normal file
74
hosts/common/user/configs/gui/ags/theme.sass
Normal file
@@ -0,0 +1,74 @@
|
||||
.bar
|
||||
background-color: {{colors.surface.default.hex}}
|
||||
|
||||
@mixin interactive
|
||||
min-height: {{custom.font_size}}pt
|
||||
border-radius: .5 * {{custom.font_size}}pt
|
||||
transition: .25s
|
||||
|
||||
&:hover
|
||||
background-color: {{colors.surface_container_high.default.hex}}
|
||||
|
||||
&:active
|
||||
background-color: {{colors.surface_container_highest.default.hex}}
|
||||
|
||||
.widgets
|
||||
padding: .2 * {{custom.padding}}pt
|
||||
|
||||
.gap
|
||||
min-height: {{custom.font_size}}pt
|
||||
min-width: .5 * {{custom.padding}}pt
|
||||
|
||||
.launcher
|
||||
.clipboard
|
||||
@include interactive
|
||||
|
||||
min-width: {{custom.font_size}}pt
|
||||
|
||||
.icon
|
||||
font-size: {{custom.font_size}}pt
|
||||
padding: 0 .3 * {{custom.padding}}pt
|
||||
color: {{colors.on_surface.default.hex}}
|
||||
|
||||
.workspace
|
||||
@include interactive
|
||||
|
||||
.button
|
||||
font-size: 0
|
||||
transition: .5s
|
||||
margin: 0 .3 * {{custom.padding}}pt
|
||||
background-color: {{colors.outline_variant.default.hex}}
|
||||
min-width: .4 * {{custom.font_size}}pt
|
||||
min-height: .4 * {{custom.font_size}}pt
|
||||
border-radius: .5 * {{custom.font_size}}pt
|
||||
|
||||
&.occupied
|
||||
background-color: {{colors.on_surface.default.hex}}
|
||||
min-width: .6 * {{custom.font_size}}pt
|
||||
min-height: .6 * {{custom.font_size}}pt
|
||||
border-radius: .5 * {{custom.font_size}}pt
|
||||
|
||||
&.active
|
||||
background-color: {{colors.primary.default.hex}}
|
||||
min-width: 1.67 * {{custom.font_size}}pt
|
||||
min-height: {{custom.font_size}}pt
|
||||
border-radius: .4 * {{custom.font_size}}pt
|
||||
|
||||
.date
|
||||
@include interactive
|
||||
|
||||
.label
|
||||
color: {{colors.on_surface.default.hex}}
|
||||
font-size: {{custom.font_size}}pt
|
||||
font-family: {{custom.font_sans_serif_all}}
|
||||
font-weight: 500
|
||||
margin: 0 .5 * {{custom.padding}}pt
|
||||
|
||||
.systray
|
||||
.item
|
||||
@include interactive
|
||||
|
||||
.icon
|
||||
font-size: {{custom.font_size}}pt
|
||||
padding: 0 .3 * {{custom.padding}}pt
|
||||
color: {{colors.on_surface.default.hex}}
|
Reference in New Issue
Block a user