Fix: An issue that would cause Matugen colors to not apply. (#929)
* Eslint updates * linter fixes * Type fixes * More type fixes * Fix isvis * More type fixes * Type Fixes * Consolidate logic to manage options * Linter fixes * Package lock update * Update configs * Version checker * Debug pipeline * Package lock update * Update ci * Strict check * Revert ci * Eslint * Remove rule since it causes issues in CI * Actual matugen fix
This commit is contained in:
25
.eslintrc.js
25
.eslintrc.js
@@ -1,25 +0,0 @@
|
|||||||
module.exports = {
|
|
||||||
parser: '@typescript-eslint/parser',
|
|
||||||
parserOptions: {
|
|
||||||
project: 'tsconfig.json',
|
|
||||||
tsconfigRootDir: __dirname,
|
|
||||||
sourceType: 'module',
|
|
||||||
},
|
|
||||||
plugins: ['@typescript-eslint', 'import'],
|
|
||||||
extends: ['plugin:@typescript-eslint/recommended', 'plugin:prettier/recommended'],
|
|
||||||
root: true,
|
|
||||||
ignorePatterns: ["/*", "!/src"],
|
|
||||||
env: {
|
|
||||||
es6: true,
|
|
||||||
browser: true,
|
|
||||||
},
|
|
||||||
rules: {
|
|
||||||
'@typescript-eslint/interface-name-prefix': 'off',
|
|
||||||
'@typescript-eslint/explicit-function-return-type': 'error',
|
|
||||||
'@typescript-eslint/explicit-module-boundary-types': 'error',
|
|
||||||
'@typescript-eslint/no-explicit-any': 'error',
|
|
||||||
'import/extensions': ['off'],
|
|
||||||
'import/no-unresolved': 'off',
|
|
||||||
quotes: ['error', 'single', { avoidEscape: true, allowTemplateLiterals: true }],
|
|
||||||
},
|
|
||||||
};
|
|
||||||
72
.eslintrc.json
Normal file
72
.eslintrc.json
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
{
|
||||||
|
"parser": "@typescript-eslint/parser",
|
||||||
|
"parserOptions": {
|
||||||
|
"project": "tsconfig.json",
|
||||||
|
"tsconfigRootDir": ".",
|
||||||
|
"sourceType": "module"
|
||||||
|
},
|
||||||
|
"plugins": ["@typescript-eslint/eslint-plugin", "prettier"],
|
||||||
|
"extends": ["plugin:@typescript-eslint/recommended", "plugin:prettier/recommended"],
|
||||||
|
"root": true,
|
||||||
|
"env": {
|
||||||
|
"node": true,
|
||||||
|
"jest": true
|
||||||
|
},
|
||||||
|
"ignorePatterns": ["/*", "!/src"],
|
||||||
|
"rules": {
|
||||||
|
"@typescript-eslint/interface-name-prefix": "off",
|
||||||
|
"@typescript-eslint/explicit-function-return-type": "error",
|
||||||
|
"@typescript-eslint/no-explicit-any": "error",
|
||||||
|
"@typescript-eslint/no-non-null-assertion": "error",
|
||||||
|
"@typescript-eslint/prefer-enum-initializers": "error",
|
||||||
|
"@typescript-eslint/no-mixed-enums": "error",
|
||||||
|
"@typescript-eslint/no-unused-vars": "error",
|
||||||
|
"@typescript-eslint/explicit-member-accessibility": [
|
||||||
|
"error",
|
||||||
|
{
|
||||||
|
"accessibility": "explicit",
|
||||||
|
"overrides": {
|
||||||
|
"constructors": "no-public"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"quotes": [
|
||||||
|
"error",
|
||||||
|
"single",
|
||||||
|
{
|
||||||
|
"allowTemplateLiterals": false,
|
||||||
|
"avoidEscape": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"prettier/prettier": [
|
||||||
|
"error",
|
||||||
|
{
|
||||||
|
"singleQuote": true,
|
||||||
|
"trailingComma": "all",
|
||||||
|
"printWidth": 110,
|
||||||
|
"tabWidth": 4
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"no-param-reassign": [
|
||||||
|
"error",
|
||||||
|
{ "props": true, "ignorePropertyModificationsFor": ["self", "ref", "el"] }
|
||||||
|
],
|
||||||
|
"@typescript-eslint/naming-convention": [
|
||||||
|
"error",
|
||||||
|
{
|
||||||
|
"selector": "typeLike",
|
||||||
|
"format": ["PascalCase"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"selector": "enumMember",
|
||||||
|
"format": ["UPPER_CASE"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"selector": "memberLike",
|
||||||
|
"modifiers": ["private"],
|
||||||
|
"format": null,
|
||||||
|
"leadingUnderscore": "require"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
"singleQuote": true,
|
"singleQuote": true,
|
||||||
"semi": true,
|
"semi": true,
|
||||||
"trailingComma": "all",
|
"trailingComma": "all",
|
||||||
"printWidth": 120,
|
"printWidth": 110,
|
||||||
"tabWidth": 4,
|
"tabWidth": 4,
|
||||||
"useTabs": false,
|
"useTabs": false,
|
||||||
"overrides": [
|
"overrides": [
|
||||||
|
|||||||
10
app.ts
10
app.ts
@@ -1,10 +1,10 @@
|
|||||||
import './src/lib/session';
|
import './src/lib/session';
|
||||||
import './src/scss/style';
|
import './src/scss/style';
|
||||||
import './src/globals/useTheme';
|
import './src/shared/useTheme';
|
||||||
import './src/globals/wallpaper';
|
import './src/shared/wallpaper';
|
||||||
import './src/globals/systray';
|
import './src/shared/systray';
|
||||||
import './src/globals/dropdown';
|
import './src/shared/dropdown';
|
||||||
import './src/globals/utilities';
|
import './src/shared/utilities';
|
||||||
import './src/components/bar/utils/sideEffects';
|
import './src/components/bar/utils/sideEffects';
|
||||||
|
|
||||||
import AstalHyprland from 'gi://AstalHyprland?version=0.1';
|
import AstalHyprland from 'gi://AstalHyprland?version=0.1';
|
||||||
|
|||||||
1392
package-lock.json
generated
1392
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -4,8 +4,8 @@
|
|||||||
"description": "A customizable panel built for Hyprland.",
|
"description": "A customizable panel built for Hyprland.",
|
||||||
"main": "app.ts",
|
"main": "app.ts",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"lint": "eslint --config .eslintrc.js .",
|
"lint": "eslint --config .eslintrc.json .",
|
||||||
"lint:fix": "eslint --config .eslintrc.js . --fix",
|
"lint:fix": "eslint --config .eslintrc.json . --fix",
|
||||||
"format": "prettier --write 'modules/**/*.ts'"
|
"format": "prettier --write 'modules/**/*.ts'"
|
||||||
},
|
},
|
||||||
"keywords": [],
|
"keywords": [],
|
||||||
@@ -24,6 +24,6 @@
|
|||||||
"eslint-plugin-prettier": "^5.2.1",
|
"eslint-plugin-prettier": "^5.2.1",
|
||||||
"prettier": "^3.3.3",
|
"prettier": "^3.3.3",
|
||||||
"tsconfig-paths": "^4.2.0",
|
"tsconfig-paths": "^4.2.0",
|
||||||
"typescript": "^5.6.2"
|
"typescript": "5.7.3"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
308
scripts/makeTheme.ts
Normal file → Executable file
308
scripts/makeTheme.ts
Normal file → Executable file
@@ -21,179 +21,181 @@
|
|||||||
* ts-node makeTheme.ts theme.json updatedTheme.json --vivid
|
* ts-node makeTheme.ts theme.json updatedTheme.json --vivid
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const fs = require('fs');
|
(() => {
|
||||||
const path = require('path');
|
const fs = require('fs');
|
||||||
|
const path = require('path');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prints the usage/help text.
|
* Prints the usage/help text.
|
||||||
*/
|
*/
|
||||||
function printUsage(): void {
|
function printUsage(): void {
|
||||||
console.log(`
|
console.log(`
|
||||||
Usage:
|
Usage:
|
||||||
ts-node makeTheme.ts <input.json> <output.json> [--vivid | --base | --both]
|
ts-node makeTheme.ts <input.json> <output.json> [--vivid | --base | --both]
|
||||||
|
|
||||||
Options:
|
Options:
|
||||||
--help Show this help message
|
--help Show this help message
|
||||||
|
|
||||||
Transforms:
|
Transforms:
|
||||||
--vivid Swap .background with .text (or .total), set .icon = old background
|
--vivid Swap .background with .text (or .total), set .icon = old background
|
||||||
--base Set .icon = .text (or .total), leave .background alone
|
--base Set .icon = .text (or .total), leave .background alone
|
||||||
--both Apply makeVividTheme, then makeBaseTheme
|
--both Apply makeVividTheme, then makeBaseTheme
|
||||||
`);
|
`);
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reads a file as UTF-8 and returns a parsed JSON object.
|
|
||||||
*/
|
|
||||||
async function readJson(filePath: string): Promise<Record<string, unknown>> {
|
|
||||||
const raw = await fs.promises.readFile(path.resolve(filePath), 'utf8');
|
|
||||||
return JSON.parse(raw) as Record<string, unknown>;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Executes the "vivid" transformation on the input data.
|
|
||||||
* For each key matching "theme.bar.buttons.*":
|
|
||||||
* - If it has .background and .text (or .total), swap them.
|
|
||||||
* - Set .icon to the old background.
|
|
||||||
*/
|
|
||||||
function makeVividTheme(data: Record<string, unknown>): void {
|
|
||||||
data['theme.bar.buttons.style'] = 'default';
|
|
||||||
|
|
||||||
const prefix = 'theme.bar.buttons.';
|
|
||||||
const grouped: Record<string, Record<string, unknown>> = {};
|
|
||||||
|
|
||||||
for (const key of Object.keys(data)) {
|
|
||||||
if (!key.startsWith(prefix)) continue;
|
|
||||||
|
|
||||||
// Split: ["theme", "bar", "buttons", ...theRest]
|
|
||||||
const parts = key.split('.');
|
|
||||||
const rest = parts.slice(3);
|
|
||||||
if (rest.length < 2) continue; // need at least <name> and <prop>
|
|
||||||
|
|
||||||
// Last segment is the property (e.g. "text", "background")
|
|
||||||
// The rest form the "name" (e.g. "modules.updates")
|
|
||||||
const prop = rest.pop()!;
|
|
||||||
const name = rest.join('.');
|
|
||||||
|
|
||||||
if (!grouped[name]) grouped[name] = {};
|
|
||||||
grouped[name][prop] = data[key];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const name of Object.keys(grouped)) {
|
/**
|
||||||
const props = grouped[name];
|
* Reads a file as UTF-8 and returns a parsed JSON object.
|
||||||
const hasBg = Object.prototype.hasOwnProperty.call(props, 'background');
|
*/
|
||||||
const hasTxt = Object.prototype.hasOwnProperty.call(props, 'text');
|
async function readJson(filePath: string): Promise<Record<string, unknown>> {
|
||||||
const hasTot = Object.prototype.hasOwnProperty.call(props, 'total');
|
const raw = await fs.promises.readFile(path.resolve(filePath), 'utf8');
|
||||||
if (!hasBg || (!hasTxt && !hasTot)) continue;
|
return JSON.parse(raw);
|
||||||
|
|
||||||
const oldBackground = props['background'];
|
|
||||||
let textKey: 'text' | 'total' | undefined;
|
|
||||||
if (hasTxt) textKey = 'text';
|
|
||||||
else if (hasTot) textKey = 'total';
|
|
||||||
if (!textKey) continue;
|
|
||||||
|
|
||||||
const oldText = props[textKey];
|
|
||||||
props[textKey] = oldBackground;
|
|
||||||
props['icon'] = oldBackground;
|
|
||||||
props['background'] = oldText;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write the changes back to the original data
|
/**
|
||||||
for (const name of Object.keys(grouped)) {
|
* Executes the "vivid" transformation on the input data.
|
||||||
for (const prop of Object.keys(grouped[name])) {
|
* For each key matching "theme.bar.buttons.*":
|
||||||
const fullKey = prefix + name + '.' + prop;
|
* - If it has .background and .text (or .total), swap them.
|
||||||
data[fullKey] = grouped[name][prop];
|
* - Set .icon to the old background.
|
||||||
|
*/
|
||||||
|
function makeVividTheme(data: Record<string, unknown>): void {
|
||||||
|
data['theme.bar.buttons.style'] = 'default';
|
||||||
|
|
||||||
|
const prefix = 'theme.bar.buttons.';
|
||||||
|
const grouped: Record<string, Record<string, unknown>> = {};
|
||||||
|
|
||||||
|
for (const key of Object.keys(data)) {
|
||||||
|
if (!key.startsWith(prefix)) continue;
|
||||||
|
|
||||||
|
// Split: ["theme", "bar", "buttons", ...theRest]
|
||||||
|
const parts = key.split('.');
|
||||||
|
const rest = parts.slice(3);
|
||||||
|
if (rest.length < 2) continue; // need at least <name> and <prop>
|
||||||
|
|
||||||
|
// Last segment is the property (e.g. "text", "background")
|
||||||
|
// The rest form the "name" (e.g. "modules.updates")
|
||||||
|
const prop = rest.pop()!;
|
||||||
|
const name = rest.join('.');
|
||||||
|
|
||||||
|
if (!grouped[name]) grouped[name] = {};
|
||||||
|
grouped[name][prop] = data[key];
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const name of Object.keys(grouped)) {
|
||||||
|
const props = grouped[name];
|
||||||
|
const hasBg = Object.prototype.hasOwnProperty.call(props, 'background');
|
||||||
|
const hasTxt = Object.prototype.hasOwnProperty.call(props, 'text');
|
||||||
|
const hasTot = Object.prototype.hasOwnProperty.call(props, 'total');
|
||||||
|
if (!hasBg || (!hasTxt && !hasTot)) continue;
|
||||||
|
|
||||||
|
const oldBackground = props['background'];
|
||||||
|
let textKey: 'text' | 'total' | undefined;
|
||||||
|
if (hasTxt) textKey = 'text';
|
||||||
|
else if (hasTot) textKey = 'total';
|
||||||
|
if (!textKey) continue;
|
||||||
|
|
||||||
|
const oldText = props[textKey];
|
||||||
|
props[textKey] = oldBackground;
|
||||||
|
props['icon'] = oldBackground;
|
||||||
|
props['background'] = oldText;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write the changes back to the original data
|
||||||
|
for (const name of Object.keys(grouped)) {
|
||||||
|
for (const prop of Object.keys(grouped[name])) {
|
||||||
|
const fullKey = prefix + name + '.' + prop;
|
||||||
|
data[fullKey] = grouped[name][prop];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Executes the "base" transformation on the input data.
|
* Executes the "base" transformation on the input data.
|
||||||
* For each key matching "theme.bar.buttons.*":
|
* For each key matching "theme.bar.buttons.*":
|
||||||
* - If it has .text or .total, set .icon to that value.
|
* - If it has .text or .total, set .icon to that value.
|
||||||
* - Leave .background alone.
|
* - Leave .background alone.
|
||||||
*/
|
*/
|
||||||
function makeBaseTheme(data: Record<string, unknown>): void {
|
function makeBaseTheme(data: Record<string, unknown>): void {
|
||||||
data['theme.bar.buttons.style'] = 'default';
|
data['theme.bar.buttons.style'] = 'default';
|
||||||
|
|
||||||
const prefix = 'theme.bar.buttons.';
|
const prefix = 'theme.bar.buttons.';
|
||||||
const grouped: Record<string, Record<string, unknown>> = {};
|
const grouped: Record<string, Record<string, unknown>> = {};
|
||||||
|
|
||||||
for (const key of Object.keys(data)) {
|
for (const key of Object.keys(data)) {
|
||||||
if (!key.startsWith(prefix)) continue;
|
if (!key.startsWith(prefix)) continue;
|
||||||
|
|
||||||
const parts = key.split('.');
|
const parts = key.split('.');
|
||||||
const rest = parts.slice(3);
|
const rest = parts.slice(3);
|
||||||
if (rest.length < 2) continue;
|
if (rest.length < 2) continue;
|
||||||
|
|
||||||
const prop = rest.pop()!;
|
const prop = rest.pop()!;
|
||||||
const name = rest.join('.');
|
const name = rest.join('.');
|
||||||
if (!grouped[name]) grouped[name] = {};
|
if (!grouped[name]) grouped[name] = {};
|
||||||
grouped[name][prop] = data[key];
|
grouped[name][prop] = data[key];
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const name of Object.keys(grouped)) {
|
for (const name of Object.keys(grouped)) {
|
||||||
const props = grouped[name];
|
const props = grouped[name];
|
||||||
const hasTxt = Object.prototype.hasOwnProperty.call(props, 'text');
|
const hasTxt = Object.prototype.hasOwnProperty.call(props, 'text');
|
||||||
const hasTot = Object.prototype.hasOwnProperty.call(props, 'total');
|
const hasTot = Object.prototype.hasOwnProperty.call(props, 'total');
|
||||||
if (!hasTxt && !hasTot) continue;
|
if (!hasTxt && !hasTot) continue;
|
||||||
|
|
||||||
const value = hasTxt ? props['text'] : props['total'];
|
const value = hasTxt ? props['text'] : props['total'];
|
||||||
props['icon'] = value;
|
props['icon'] = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const name of Object.keys(grouped)) {
|
for (const name of Object.keys(grouped)) {
|
||||||
for (const prop of Object.keys(grouped[name])) {
|
for (const prop of Object.keys(grouped[name])) {
|
||||||
const fullKey = prefix + name + '.' + prop;
|
const fullKey = prefix + name + '.' + prop;
|
||||||
data[fullKey] = grouped[name][prop];
|
data[fullKey] = grouped[name][prop];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Main CLI entry point.
|
* Main CLI entry point.
|
||||||
*/
|
*/
|
||||||
async function main(): Promise<void> {
|
async function main(): Promise<void> {
|
||||||
const [, , ...args] = process.argv;
|
const [, , ...args] = process.argv;
|
||||||
if (args.includes('--help') || args.length < 2) {
|
if (args.includes('--help') || args.length < 2) {
|
||||||
printUsage();
|
printUsage();
|
||||||
process.exit(0);
|
process.exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
const input = args[0];
|
||||||
|
const output = args[1];
|
||||||
|
const mode = args[2] || '--vivid';
|
||||||
|
|
||||||
|
let data: Record<string, unknown>;
|
||||||
|
try {
|
||||||
|
data = await readJson(input);
|
||||||
|
} catch (e) {
|
||||||
|
console.error(`Failed to read/parse: ${input}`, e);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mode === '--vivid') makeVividTheme(data);
|
||||||
|
else if (mode === '--base') makeBaseTheme(data);
|
||||||
|
else if (mode === '--both') {
|
||||||
|
makeVividTheme(data);
|
||||||
|
makeBaseTheme(data);
|
||||||
|
} else {
|
||||||
|
console.error(`Unknown mode: ${mode}`);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
fs.writeFileSync(path.resolve(output), JSON.stringify(data, null, 2), 'utf8');
|
||||||
|
console.log(`Wrote updated theme to: ${output}`);
|
||||||
|
} catch (e) {
|
||||||
|
console.error(`Failed to write file: ${output}`, e);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const input = args[0];
|
if (require.main === module) {
|
||||||
const output = args[1];
|
main().catch((e) => {
|
||||||
const mode = args[2] || '--vivid';
|
console.error(e);
|
||||||
|
process.exit(1);
|
||||||
let data: Record<string, unknown>;
|
});
|
||||||
try {
|
|
||||||
data = await readJson(input);
|
|
||||||
} catch (e) {
|
|
||||||
console.error(`Failed to read/parse: ${input}`, e);
|
|
||||||
process.exit(1);
|
|
||||||
}
|
}
|
||||||
|
})();
|
||||||
if (mode === '--vivid') makeVividTheme(data);
|
|
||||||
else if (mode === '--base') makeBaseTheme(data);
|
|
||||||
else if (mode === '--both') {
|
|
||||||
makeVividTheme(data);
|
|
||||||
makeBaseTheme(data);
|
|
||||||
} else {
|
|
||||||
console.error(`Unknown mode: ${mode}`);
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
fs.writeFileSync(path.resolve(output), JSON.stringify(data, null, 2), 'utf8');
|
|
||||||
console.log(`Wrote updated theme to: ${output}`);
|
|
||||||
} catch (e) {
|
|
||||||
console.error(`Failed to write file: ${output}`, e);
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (require.main === module) {
|
|
||||||
main().catch((e) => {
|
|
||||||
console.error(e);
|
|
||||||
process.exit(1);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,176 +1,178 @@
|
|||||||
#!/usr/bin/env ts-node
|
#!/usr/bin/env ts-node
|
||||||
/// <reference types="node" />
|
/// <reference types="node" />
|
||||||
|
|
||||||
/**
|
(() => {
|
||||||
* Prints usage/help information to the console.
|
/**
|
||||||
* Called whenever the user passes `--help` or when arguments are missing/invalid.
|
* Prints usage/help information to the console.
|
||||||
*/
|
* Called whenever the user passes `--help` or when arguments are missing/invalid.
|
||||||
function printUsage(): void {
|
*/
|
||||||
console.log(`
|
function printUsage(): void {
|
||||||
Usage:
|
console.log(`
|
||||||
ts-node updateColors.ts <theme.json> <original_palette.json> <new_palette.json> <output.json>
|
Usage:
|
||||||
|
ts-node updateColors.ts <theme.json> <original_palette.json> <new_palette.json> <output.json>
|
||||||
|
|
||||||
Options:
|
Options:
|
||||||
--help Show this help message
|
--help Show this help message
|
||||||
|
|
||||||
Description:
|
Description:
|
||||||
This script reads a theme JSON file containing old color codes, an "original" palette JSON
|
This script reads a theme JSON file containing old color codes, an "original" palette JSON
|
||||||
(which maps color name → old hex code), and a "new" palette JSON (mapping the same color name
|
(which maps color name → old hex code), and a "new" palette JSON (mapping the same color name
|
||||||
→ new hex code). It then replaces all old hex codes in the theme with the corresponding new hex codes,
|
→ new hex code). It then replaces all old hex codes in the theme with the corresponding new hex codes,
|
||||||
and saves the result to the specified output JSON file.
|
and saves the result to the specified output JSON file.
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
ts-node updateColors.ts theme.json original_palette.json new_palette.json updated_theme.json
|
ts-node updateColors.ts theme.json original_palette.json new_palette.json updated_theme.json
|
||||||
|
|
||||||
node updateColors.js theme.json original_palette.json new_palette.json updated_theme.json
|
node updateColors.js theme.json original_palette.json new_palette.json updated_theme.json
|
||||||
`);
|
`);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
type Palette = Record<string, string | Record<string, string>>;
|
||||||
* Recursively walks a palette to build a map from old hex → new hex,
|
type ColorMap = Record<string, string>;
|
||||||
* keyed by the same property name in the new palette if it exists.
|
|
||||||
*
|
|
||||||
* Example:
|
|
||||||
* originalPalette = { bg: "#24283b", git: { add: "#449dab" } }
|
|
||||||
* newPalette = { bg: "#222436", git: { add: "#b8db87" } }
|
|
||||||
*
|
|
||||||
* => colorMap = {
|
|
||||||
* "#24283b": "#222436",
|
|
||||||
* "#449dab": "#b8db87"
|
|
||||||
* }
|
|
||||||
*
|
|
||||||
* @param original - The "old" palette.
|
|
||||||
* @param updated - The "new" palette containing updated hex codes.
|
|
||||||
* @returns A map of { oldHex.toLowerCase(): newHex }.
|
|
||||||
*/
|
|
||||||
function buildColorMap(original: Palette, updated: Palette): ColorMap {
|
|
||||||
const map: ColorMap = {};
|
|
||||||
|
|
||||||
for (const [key, oldVal] of Object.entries(original)) {
|
/**
|
||||||
const newVal = updated[key];
|
* Recursively walks a palette to build a map from old hex → new hex,
|
||||||
|
* keyed by the same property name in the new palette if it exists.
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
* originalPalette = { bg: "#24283b", git: { add: "#449dab" } }
|
||||||
|
* newPalette = { bg: "#222436", git: { add: "#b8db87" } }
|
||||||
|
*
|
||||||
|
* => colorMap = {
|
||||||
|
* "#24283b": "#222436",
|
||||||
|
* "#449dab": "#b8db87"
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* @param original - The "old" palette.
|
||||||
|
* @param updated - The "new" palette containing updated hex codes.
|
||||||
|
* @returns A map of { oldHex.toLowerCase(): newHex }.
|
||||||
|
*/
|
||||||
|
function buildColorMap(original: Palette, updated: Palette): ColorMap {
|
||||||
|
const map: ColorMap = {};
|
||||||
|
|
||||||
if (typeof oldVal === 'string' && typeof newVal === 'string') {
|
for (const [key, oldVal] of Object.entries(original)) {
|
||||||
map[oldVal.toLowerCase()] = newVal;
|
const newVal = updated[key];
|
||||||
} else if (oldVal && typeof oldVal === 'object') {
|
|
||||||
const oldNested = oldVal as Record<string, string>;
|
|
||||||
const newNested = newVal && typeof newVal === 'object' ? (newVal as Record<string, string>) : {};
|
|
||||||
|
|
||||||
for (const [nestedKey, nestedOldHex] of Object.entries(oldNested)) {
|
if (typeof oldVal === 'string' && typeof newVal === 'string') {
|
||||||
const nestedNewHex = newNested[nestedKey];
|
map[oldVal.toLowerCase()] = newVal;
|
||||||
|
} else if (oldVal && typeof oldVal === 'object') {
|
||||||
|
const oldNested = oldVal as Record<string, string>;
|
||||||
|
const newNested =
|
||||||
|
newVal && typeof newVal === 'object' ? (newVal as Record<string, string>) : {};
|
||||||
|
|
||||||
if (typeof nestedOldHex === 'string' && typeof nestedNewHex === 'string') {
|
for (const [nestedKey, nestedOldHex] of Object.entries(oldNested)) {
|
||||||
map[nestedOldHex.toLowerCase()] = nestedNewHex;
|
const nestedNewHex = newNested[nestedKey];
|
||||||
|
|
||||||
|
if (typeof nestedOldHex === 'string' && typeof nestedNewHex === 'string') {
|
||||||
|
map[nestedOldHex.toLowerCase()] = nestedNewHex;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
return map;
|
/**
|
||||||
}
|
* Recursively replace all string values in a data structure (object, array, etc.)
|
||||||
|
* if they appear in colorMap.
|
||||||
|
*
|
||||||
|
* @param node - The current portion of JSON to transform (can be object, array, string, etc.).
|
||||||
|
* @param colorMap - An object with oldHex.toLowerCase() → newHex mappings.
|
||||||
|
* @returns The transformed data with replaced colors.
|
||||||
|
*/
|
||||||
|
function replaceColorsInTheme(node: unknown, colorMap: ColorMap): unknown {
|
||||||
|
if (Array.isArray(node)) {
|
||||||
|
return node.map((item) => replaceColorsInTheme(item, colorMap));
|
||||||
|
} else if (node && typeof node === 'object') {
|
||||||
|
const result: Record<string, unknown> = {};
|
||||||
|
|
||||||
/**
|
for (const [key, val] of Object.entries(node)) {
|
||||||
* Recursively replace all string values in a data structure (object, array, etc.)
|
result[key] = replaceColorsInTheme(val, colorMap);
|
||||||
* if they appear in colorMap.
|
|
||||||
*
|
|
||||||
* @param node - The current portion of JSON to transform (can be object, array, string, etc.).
|
|
||||||
* @param colorMap - An object with oldHex.toLowerCase() → newHex mappings.
|
|
||||||
* @returns The transformed data with replaced colors.
|
|
||||||
*/
|
|
||||||
function replaceColorsInTheme(node: unknown, colorMap: ColorMap): unknown {
|
|
||||||
if (Array.isArray(node)) {
|
|
||||||
return node.map((item) => replaceColorsInTheme(item, colorMap));
|
|
||||||
} else if (node && typeof node === 'object') {
|
|
||||||
const result: Record<string, unknown> = {};
|
|
||||||
|
|
||||||
for (const [key, val] of Object.entries(node)) {
|
|
||||||
result[key] = replaceColorsInTheme(val, colorMap);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
} else if (typeof node === 'string') {
|
|
||||||
const lower = node.toLowerCase();
|
|
||||||
return colorMap[lower] ? colorMap[lower] : node;
|
|
||||||
} else {
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A minimal utility wrapper to read a file asynchronously.
|
|
||||||
*
|
|
||||||
* @param filePath - The file path to read from.
|
|
||||||
* @param encoding - The file encoding (default 'utf8').
|
|
||||||
* @returns A Promise resolving to the file contents as a string.
|
|
||||||
*/
|
|
||||||
async function readFile(filePath: string, encoding: BufferEncoding = 'utf8'): Promise<string> {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
const fs = require('fs');
|
|
||||||
fs.readFile(filePath, encoding, (err: Error, data: string) => {
|
|
||||||
if (err) {
|
|
||||||
reject(err);
|
|
||||||
} else {
|
|
||||||
resolve(data);
|
|
||||||
}
|
}
|
||||||
|
return result;
|
||||||
|
} else if (typeof node === 'string') {
|
||||||
|
const lower = node.toLowerCase();
|
||||||
|
return colorMap[lower] ? colorMap[lower] : node;
|
||||||
|
} else {
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A minimal utility wrapper to read a file asynchronously.
|
||||||
|
*
|
||||||
|
* @param filePath - The file path to read from.
|
||||||
|
* @param encoding - The file encoding (default 'utf8').
|
||||||
|
* @returns A Promise resolving to the file contents as a string.
|
||||||
|
*/
|
||||||
|
async function readFile(filePath: string, encoding: BufferEncoding = 'utf8'): Promise<string> {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const fs = require('fs');
|
||||||
|
fs.readFile(filePath, encoding, (err: Error, data: string) => {
|
||||||
|
if (err) {
|
||||||
|
reject(err);
|
||||||
|
} else {
|
||||||
|
resolve(data);
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Main function that:
|
|
||||||
* 1. Checks for --help or missing arguments.
|
|
||||||
* 2. Reads and parses the theme, original palette, and new palette.
|
|
||||||
* 3. Builds the color map and applies color replacements.
|
|
||||||
* 4. Writes the result as JSON to a new file.
|
|
||||||
*
|
|
||||||
* @example
|
|
||||||
* ```bash
|
|
||||||
* ts-node updateColors.ts theme.json original_palette.json new_palette.json output.json
|
|
||||||
* ```
|
|
||||||
*/
|
|
||||||
async function main(): Promise<void> {
|
|
||||||
const [, , ...args] = process.argv;
|
|
||||||
|
|
||||||
if (args.length === 0) {
|
|
||||||
printUsage();
|
|
||||||
process.exit(0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (args.length < 4) {
|
/**
|
||||||
console.error('Error: Not enough arguments provided.\n');
|
* Main function that:
|
||||||
printUsage();
|
* 1. Checks for --help or missing arguments.
|
||||||
process.exit(1);
|
* 2. Reads and parses the theme, original palette, and new palette.
|
||||||
} else if (args.length > 4) {
|
* 3. Builds the color map and applies color replacements.
|
||||||
console.error('Error: Too many arguments provided.\n');
|
* 4. Writes the result as JSON to a new file.
|
||||||
printUsage();
|
*
|
||||||
process.exit(1);
|
* @example
|
||||||
|
* ```bash
|
||||||
|
* ts-node updateColors.ts theme.json original_palette.json new_palette.json output.json
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
async function main(): Promise<void> {
|
||||||
|
const [, , ...args] = process.argv;
|
||||||
|
|
||||||
|
if (args.length === 0) {
|
||||||
|
printUsage();
|
||||||
|
process.exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (args.length < 4) {
|
||||||
|
console.error('Error: Not enough arguments provided.\n');
|
||||||
|
printUsage();
|
||||||
|
process.exit(1);
|
||||||
|
} else if (args.length > 4) {
|
||||||
|
console.error('Error: Too many arguments provided.\n');
|
||||||
|
printUsage();
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
const [themePath, originalPath, newPath, outputPath] = args;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const themeData = JSON.parse(await readFile(themePath, 'utf8'));
|
||||||
|
const originalPalette: Palette = JSON.parse(await readFile(originalPath, 'utf8'));
|
||||||
|
const newPalette: Palette = JSON.parse(await readFile(newPath, 'utf8'));
|
||||||
|
const fs = require('fs');
|
||||||
|
|
||||||
|
const colorMap = buildColorMap(originalPalette, newPalette);
|
||||||
|
const updatedTheme = replaceColorsInTheme(themeData, colorMap);
|
||||||
|
|
||||||
|
fs.writeFileSync(outputPath, JSON.stringify(updatedTheme, null, 2), 'utf8');
|
||||||
|
|
||||||
|
console.log(`Successfully wrote updated theme to: ${outputPath}`);
|
||||||
|
} catch (err) {
|
||||||
|
console.error('Error:', err);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const [themePath, originalPath, newPath, outputPath] = args;
|
if (require.main === module) {
|
||||||
|
main().catch((err) => {
|
||||||
try {
|
console.error(err);
|
||||||
const themeData = JSON.parse(await readFile(themePath, 'utf8'));
|
process.exit(1);
|
||||||
const originalPalette: Palette = JSON.parse(await readFile(originalPath, 'utf8'));
|
});
|
||||||
const newPalette: Palette = JSON.parse(await readFile(newPath, 'utf8'));
|
|
||||||
const fs = require('fs');
|
|
||||||
|
|
||||||
const colorMap = buildColorMap(originalPalette, newPalette);
|
|
||||||
const updatedTheme = replaceColorsInTheme(themeData, colorMap);
|
|
||||||
|
|
||||||
fs.writeFileSync(outputPath, JSON.stringify(updatedTheme, null, 2), 'utf8');
|
|
||||||
|
|
||||||
console.log(`Successfully wrote updated theme to: ${outputPath}`);
|
|
||||||
} catch (err) {
|
|
||||||
console.error('Error:', err);
|
|
||||||
process.exit(1);
|
|
||||||
}
|
}
|
||||||
}
|
})();
|
||||||
|
|
||||||
if (require.main === module) {
|
|
||||||
main().catch((err) => {
|
|
||||||
console.error(err);
|
|
||||||
process.exit(1);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
type Palette = Record<string, string | Record<string, string>>;
|
|
||||||
|
|
||||||
type ColorMap = Record<string, string>;
|
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ import { Command, ParsedCommand } from './types';
|
|||||||
* 5. Validates required arguments.
|
* 5. Validates required arguments.
|
||||||
*/
|
*/
|
||||||
export class CommandParser {
|
export class CommandParser {
|
||||||
private registry: CommandRegistry;
|
private _registry: CommandRegistry;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a CommandParser with the provided command registry.
|
* Constructs a CommandParser with the provided command registry.
|
||||||
@@ -22,7 +22,7 @@ export class CommandParser {
|
|||||||
* @param registry - The command registry containing available commands.
|
* @param registry - The command registry containing available commands.
|
||||||
*/
|
*/
|
||||||
constructor(registry: CommandRegistry) {
|
constructor(registry: CommandRegistry) {
|
||||||
this.registry = registry;
|
this._registry = registry;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -33,20 +33,22 @@ export class CommandParser {
|
|||||||
* @throws If no command token is found.
|
* @throws If no command token is found.
|
||||||
* @throws If the command token is not registered.
|
* @throws If the command token is not registered.
|
||||||
*/
|
*/
|
||||||
parse(input: string): ParsedCommand {
|
public parse(input: string): ParsedCommand {
|
||||||
const tokens = this.tokenize(input);
|
const tokens = this._tokenize(input);
|
||||||
|
|
||||||
if (tokens.length === 0) {
|
if (tokens.length === 0) {
|
||||||
throw new Error('No command provided.');
|
throw new Error('No command provided.');
|
||||||
}
|
}
|
||||||
|
|
||||||
const commandName = tokens.shift()!;
|
const commandName = tokens.shift() ?? 'non-existent-command';
|
||||||
const command = this.registry.get(commandName);
|
const command = this._registry.get(commandName);
|
||||||
if (!command) {
|
if (!command) {
|
||||||
throw new Error(`Unknown command: "${commandName}". Use "hyprpanel explain" for available commands.`);
|
throw new Error(
|
||||||
|
`Unknown command: "${commandName}". Use "hyprpanel explain" for available commands.`,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const args = this.parseArgs(command, tokens);
|
const args = this._parseArgs(command, tokens);
|
||||||
return { command, args };
|
return { command, args };
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -56,10 +58,10 @@ export class CommandParser {
|
|||||||
* @param input - The raw input string to break into tokens.
|
* @param input - The raw input string to break into tokens.
|
||||||
* @returns An array of tokens.
|
* @returns An array of tokens.
|
||||||
*/
|
*/
|
||||||
private tokenize(input: string): string[] {
|
private _tokenize(input: string): string[] {
|
||||||
const regex = /(?:[^\s"']+|"[^"]*"|'[^']*')+/g;
|
const regex = /(?:[^\s"']+|"[^"]*"|'[^']*')+/g;
|
||||||
const matches = input.match(regex);
|
const matches = input.match(regex);
|
||||||
return matches ? matches.map((token) => this.stripQuotes(token)) : [];
|
return matches ? matches.map((token) => this._stripQuotes(token)) : [];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -68,7 +70,7 @@ export class CommandParser {
|
|||||||
* @param str - The token from which to strip leading or trailing quotes.
|
* @param str - The token from which to strip leading or trailing quotes.
|
||||||
* @returns The token without its outer quotes.
|
* @returns The token without its outer quotes.
|
||||||
*/
|
*/
|
||||||
private stripQuotes(str: string): string {
|
private _stripQuotes(str: string): string {
|
||||||
return str.replace(/^["'](.+(?=["']$))["']$/, '$1');
|
return str.replace(/^["'](.+(?=["']$))["']$/, '$1');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -81,13 +83,13 @@ export class CommandParser {
|
|||||||
* @throws If required arguments are missing.
|
* @throws If required arguments are missing.
|
||||||
* @throws If there are too many tokens for the command definition.
|
* @throws If there are too many tokens for the command definition.
|
||||||
*/
|
*/
|
||||||
private parseArgs(command: Command, tokens: string[]): Record<string, unknown> {
|
private _parseArgs(command: Command, tokens: string[]): Record<string, unknown> {
|
||||||
const args: Record<string, unknown> = {};
|
const args: Record<string, unknown> = {};
|
||||||
let currentIndex = 0;
|
let currentIndex = 0;
|
||||||
|
|
||||||
for (const argDef of command.args) {
|
for (const argDef of command.args) {
|
||||||
if (currentIndex >= tokens.length) {
|
if (currentIndex >= tokens.length) {
|
||||||
if (argDef.required) {
|
if (argDef.required === true) {
|
||||||
throw new Error(`Missing required argument: "${argDef.name}".`);
|
throw new Error(`Missing required argument: "${argDef.name}".`);
|
||||||
}
|
}
|
||||||
if (argDef.default !== undefined) {
|
if (argDef.default !== undefined) {
|
||||||
@@ -97,13 +99,13 @@ export class CommandParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (argDef.type === 'object') {
|
if (argDef.type === 'object') {
|
||||||
const { objectValue, nextIndex } = this.parseObjectTokens(tokens, currentIndex);
|
const { objectValue, nextIndex } = this._parseObjectTokens(tokens, currentIndex);
|
||||||
args[argDef.name] = objectValue;
|
args[argDef.name] = objectValue;
|
||||||
currentIndex = nextIndex;
|
currentIndex = nextIndex;
|
||||||
} else {
|
} else {
|
||||||
const value = tokens[currentIndex];
|
const value = tokens[currentIndex];
|
||||||
currentIndex++;
|
currentIndex++;
|
||||||
args[argDef.name] = this.convertType(value, argDef.type);
|
args[argDef.name] = this._convertType(value, argDef.type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -125,7 +127,10 @@ export class CommandParser {
|
|||||||
* @returns An object containing the parsed JSON object and the next token index.
|
* @returns An object containing the parsed JSON object and the next token index.
|
||||||
* @throws If the reconstructed JSON is invalid.
|
* @throws If the reconstructed JSON is invalid.
|
||||||
*/
|
*/
|
||||||
private parseObjectTokens(tokens: string[], startIndex: number): { objectValue: unknown; nextIndex: number } {
|
private _parseObjectTokens(
|
||||||
|
tokens: string[],
|
||||||
|
startIndex: number,
|
||||||
|
): { objectValue: unknown; nextIndex: number } {
|
||||||
let braceCount = 0;
|
let braceCount = 0;
|
||||||
let started = false;
|
let started = false;
|
||||||
const objectTokens: string[] = [];
|
const objectTokens: string[] = [];
|
||||||
@@ -142,7 +147,6 @@ export class CommandParser {
|
|||||||
|
|
||||||
objectTokens.push(token);
|
objectTokens.push(token);
|
||||||
|
|
||||||
// Once we've started and braceCount returns to 0, we assume the object is complete
|
|
||||||
if (started && braceCount === 0) break;
|
if (started && braceCount === 0) break;
|
||||||
if (token.includes('{')) started = true;
|
if (token.includes('{')) started = true;
|
||||||
}
|
}
|
||||||
@@ -166,7 +170,7 @@ export class CommandParser {
|
|||||||
* @returns The converted value.
|
* @returns The converted value.
|
||||||
* @throws If the token cannot be converted to the expected type.
|
* @throws If the token cannot be converted to the expected type.
|
||||||
*/
|
*/
|
||||||
private convertType(value: string, type: 'string' | 'number' | 'boolean' | 'object'): unknown {
|
private _convertType(value: string, type: 'string' | 'number' | 'boolean' | 'object'): unknown {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 'number': {
|
case 'number': {
|
||||||
const num = Number(value);
|
const num = Number(value);
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import { Command } from './types';
|
|||||||
* and retrieval of all commands for listing and help functionalities.
|
* and retrieval of all commands for listing and help functionalities.
|
||||||
*/
|
*/
|
||||||
export class CommandRegistry {
|
export class CommandRegistry {
|
||||||
private commands: Map<string, Command> = new Map();
|
private _commands: Map<string, Command> = new Map();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Registers a command. If a command with the same name or alias already exists,
|
* Registers a command. If a command with the same name or alias already exists,
|
||||||
@@ -15,18 +15,18 @@ export class CommandRegistry {
|
|||||||
* @param command - The command to register.
|
* @param command - The command to register.
|
||||||
* @throws If a command with the same name or alias already exists.
|
* @throws If a command with the same name or alias already exists.
|
||||||
*/
|
*/
|
||||||
register(command: Command): void {
|
public register(command: Command): void {
|
||||||
if (this.commands.has(command.name)) {
|
if (this._commands.has(command.name)) {
|
||||||
throw new Error(`Command "${command.name}" is already registered.`);
|
throw new Error(`Command "${command.name}" is already registered.`);
|
||||||
}
|
}
|
||||||
this.commands.set(command.name, command);
|
this._commands.set(command.name, command);
|
||||||
|
|
||||||
if (command.aliases) {
|
if (command.aliases) {
|
||||||
for (const alias of command.aliases) {
|
for (const alias of command.aliases) {
|
||||||
if (this.commands.has(alias)) {
|
if (this._commands.has(alias)) {
|
||||||
throw new Error(`Alias "${alias}" is already in use.`);
|
throw new Error(`Alias "${alias}" is already in use.`);
|
||||||
}
|
}
|
||||||
this.commands.set(alias, command);
|
this._commands.set(alias, command);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -37,8 +37,8 @@ export class CommandRegistry {
|
|||||||
* @param commandName - The name or alias of the command to retrieve.
|
* @param commandName - The name or alias of the command to retrieve.
|
||||||
* @returns The command if found, otherwise undefined.
|
* @returns The command if found, otherwise undefined.
|
||||||
*/
|
*/
|
||||||
get(commandName: string): Command | undefined {
|
public get(commandName: string): Command | undefined {
|
||||||
return this.commands.get(commandName);
|
return this._commands.get(commandName);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -46,8 +46,8 @@ export class CommandRegistry {
|
|||||||
*
|
*
|
||||||
* @returns An array of all registered commands.
|
* @returns An array of all registered commands.
|
||||||
*/
|
*/
|
||||||
getAll(): Command[] {
|
public getAll(): Command[] {
|
||||||
const unique = new Set<Command>(this.commands.values());
|
const unique = new Set<Command>(this._commands.values());
|
||||||
return Array.from(unique);
|
return Array.from(unique);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import { ResponseCallback } from './types';
|
|||||||
* 3. Handles any errors and passes the result back via the response callback.
|
* 3. Handles any errors and passes the result back via the response callback.
|
||||||
*/
|
*/
|
||||||
export class RequestHandler {
|
export class RequestHandler {
|
||||||
private parser: CommandParser;
|
private _parser: CommandParser;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates an instance of RequestHandler.
|
* Creates an instance of RequestHandler.
|
||||||
@@ -16,7 +16,7 @@ export class RequestHandler {
|
|||||||
* @param parser - The CommandParser instance to use.
|
* @param parser - The CommandParser instance to use.
|
||||||
*/
|
*/
|
||||||
constructor(parser: CommandParser) {
|
constructor(parser: CommandParser) {
|
||||||
this.parser = parser;
|
this._parser = parser;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -26,20 +26,20 @@ export class RequestHandler {
|
|||||||
* @param response - The callback to handle the response.
|
* @param response - The callback to handle the response.
|
||||||
* @returns A promise that resolves when the request is handled.
|
* @returns A promise that resolves when the request is handled.
|
||||||
*/
|
*/
|
||||||
async initializeRequestHandler(input: string, response: ResponseCallback): Promise<void> {
|
public async initializeRequestHandler(input: string, response: ResponseCallback): Promise<void> {
|
||||||
try {
|
try {
|
||||||
const parsed = this.parser.parse(input);
|
const parsed = this._parser.parse(input);
|
||||||
const { command, args } = parsed;
|
const { command, args } = parsed;
|
||||||
|
|
||||||
const result = command.handler(args);
|
const result = command.handler(args);
|
||||||
if (result instanceof Promise) {
|
if (result instanceof Promise) {
|
||||||
const resolved = await result;
|
const resolved = await result;
|
||||||
response(this.formatOutput(resolved));
|
response(this._formatOutput(resolved));
|
||||||
} else {
|
} else {
|
||||||
response(this.formatOutput(result));
|
response(this._formatOutput(result));
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
response(this.formatError(error));
|
response(this._formatError(error));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -49,7 +49,7 @@ export class RequestHandler {
|
|||||||
* @param output - The output to format.
|
* @param output - The output to format.
|
||||||
* @returns A string representation of the output.
|
* @returns A string representation of the output.
|
||||||
*/
|
*/
|
||||||
private formatOutput(output: unknown): string {
|
private _formatOutput(output: unknown): string {
|
||||||
if (typeof output === 'string') {
|
if (typeof output === 'string') {
|
||||||
return output;
|
return output;
|
||||||
} else if (typeof output === 'number' || typeof output === 'boolean') {
|
} else if (typeof output === 'number' || typeof output === 'boolean') {
|
||||||
@@ -71,7 +71,7 @@ export class RequestHandler {
|
|||||||
* @param error - The error to format.
|
* @param error - The error to format.
|
||||||
* @returns A string representation of the error.
|
* @returns A string representation of the error.
|
||||||
*/
|
*/
|
||||||
private formatError(error: unknown): string {
|
private _formatError(error: unknown): string {
|
||||||
if (error instanceof Error) {
|
if (error instanceof Error) {
|
||||||
return `Error: ${error.message}`;
|
return `Error: ${error.message}`;
|
||||||
} else if (typeof error === 'string') {
|
} else if (typeof error === 'string') {
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
import { errorHandler } from 'src/lib/utils';
|
import { errorHandler } from 'src/lib/utils';
|
||||||
import { BarLayouts } from 'src/lib/types/options';
|
|
||||||
import { Command } from '../../types';
|
import { Command } from '../../types';
|
||||||
|
import { setWallpaper } from 'src/shared/wallpaper';
|
||||||
|
import { useTheme } from 'src/shared/useTheme';
|
||||||
|
import { setLayout } from 'src/shared/utilities';
|
||||||
|
import { BarLayouts } from 'src/lib/options/options.types';
|
||||||
|
|
||||||
export const appearanceCommands: Command[] = [
|
export const appearanceCommands: Command[] = [
|
||||||
{
|
{
|
||||||
@@ -58,7 +61,8 @@ export const appearanceCommands: Command[] = [
|
|||||||
args: [
|
args: [
|
||||||
{
|
{
|
||||||
name: 'layout',
|
name: 'layout',
|
||||||
description: 'Bar layout to apply. Wiki: https://hyprpanel.com/configuration/panel.html#layouts',
|
description:
|
||||||
|
'Bar layout to apply. Wiki: https://hyprpanel.com/configuration/panel.html#layouts',
|
||||||
type: 'object',
|
type: 'object',
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -110,9 +110,9 @@ function checkServiceStatus(services: string[]): ServiceStatus {
|
|||||||
const enabledResult = runCommand(`systemctl is-enabled ${svc}`);
|
const enabledResult = runCommand(`systemctl is-enabled ${svc}`);
|
||||||
const enabledStatus = enabledResult.stdout;
|
const enabledStatus = enabledResult.stdout;
|
||||||
|
|
||||||
if (enabledResult && (enabledStatus === 'enabled' || enabledStatus === 'static')) {
|
if (enabledResult !== undefined && (enabledStatus === 'enabled' || enabledStatus === 'static')) {
|
||||||
return 'INSTALLED';
|
return 'INSTALLED';
|
||||||
} else if (enabledResult && enabledStatus === 'disabled') {
|
} else if (enabledResult !== undefined && enabledStatus === 'disabled') {
|
||||||
return 'DISABLED';
|
return 'DISABLED';
|
||||||
} else {
|
} else {
|
||||||
return 'MISSING';
|
return 'MISSING';
|
||||||
@@ -174,7 +174,7 @@ function getDependencyStatus(dep: Dependency): string {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!dep.description) {
|
if (dep.description === undefined) {
|
||||||
return ` ${colorText(textStatus, color)} ${dep.package}`;
|
return ` ${colorText(textStatus, color)} ${dep.package}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,10 @@ import { errorHandler } from 'src/lib/utils';
|
|||||||
import { Command } from '../../types';
|
import { Command } from '../../types';
|
||||||
import { execAsync, Gio, GLib } from 'astal';
|
import { execAsync, Gio, GLib } from 'astal';
|
||||||
import { checkDependencies } from './checkDependencies';
|
import { checkDependencies } from './checkDependencies';
|
||||||
|
import options from 'src/options';
|
||||||
|
import { clearAllNotifications } from 'src/shared/notification';
|
||||||
|
import { getSystrayItems } from 'src/shared/systray';
|
||||||
|
import { idleInhibit } from 'src/shared/utilities';
|
||||||
|
|
||||||
const audio = AstalWp.get_default();
|
const audio = AstalWp.get_default();
|
||||||
|
|
||||||
@@ -15,7 +19,7 @@ export const utilityCommands: Command[] = [
|
|||||||
args: [],
|
args: [],
|
||||||
handler: (): string => {
|
handler: (): string => {
|
||||||
try {
|
try {
|
||||||
return getSystrayItems();
|
return getSystrayItems() ?? 'No items found!';
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
errorHandler(error);
|
errorHandler(error);
|
||||||
}
|
}
|
||||||
@@ -88,7 +92,8 @@ export const utilityCommands: Command[] = [
|
|||||||
{
|
{
|
||||||
name: 'idleInhibit',
|
name: 'idleInhibit',
|
||||||
aliases: ['idi'],
|
aliases: ['idi'],
|
||||||
description: 'Enables/Disables the Idle Inhibitor. Toggles the Inhibitor if no parameter is provided.',
|
description:
|
||||||
|
'Enables/Disables the Idle Inhibitor. Toggles the Inhibitor if no parameter is provided.',
|
||||||
category: 'Utility',
|
category: 'Utility',
|
||||||
args: [
|
args: [
|
||||||
{
|
{
|
||||||
@@ -100,7 +105,7 @@ export const utilityCommands: Command[] = [
|
|||||||
],
|
],
|
||||||
handler: (args: Record<string, unknown>): boolean => {
|
handler: (args: Record<string, unknown>): boolean => {
|
||||||
try {
|
try {
|
||||||
const shouldInhibit = args['shouldInhibit'] ?? !idleInhibit.get();
|
const shouldInhibit = args['shouldInhibit'] ?? idleInhibit.get() === false;
|
||||||
idleInhibit.set(Boolean(shouldInhibit));
|
idleInhibit.set(Boolean(shouldInhibit));
|
||||||
|
|
||||||
return idleInhibit.get();
|
return idleInhibit.get();
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { errorHandler } from 'src/lib/utils';
|
|||||||
import { Command } from '../../types';
|
import { Command } from '../../types';
|
||||||
import { App } from 'astal/gtk3';
|
import { App } from 'astal/gtk3';
|
||||||
import { BarVisibility } from 'src/cli/utils/BarVisibility';
|
import { BarVisibility } from 'src/cli/utils/BarVisibility';
|
||||||
|
import { isWindowVisible } from 'src/shared/utilities';
|
||||||
|
|
||||||
export const windowManagementCommands: Command[] = [
|
export const windowManagementCommands: Command[] = [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ export function createExplainCommand(registry: CommandRegistry): Command {
|
|||||||
handler: (args: Record<string, unknown>): string => {
|
handler: (args: Record<string, unknown>): string => {
|
||||||
const commandName = args['commandName'] as string | undefined;
|
const commandName = args['commandName'] as string | undefined;
|
||||||
|
|
||||||
if (commandName) {
|
if (commandName !== undefined) {
|
||||||
return formatCommandExplain(registry, commandName);
|
return formatCommandExplain(registry, commandName);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -134,7 +134,7 @@ function organizeCommandsByCategory(commands: Command[]): CategoryMap {
|
|||||||
const categoryMap: CategoryMap = {};
|
const categoryMap: CategoryMap = {};
|
||||||
|
|
||||||
commands.forEach((cmd) => {
|
commands.forEach((cmd) => {
|
||||||
if (!categoryMap[cmd.category]) {
|
if (categoryMap[cmd.category] === undefined) {
|
||||||
categoryMap[cmd.category] = [];
|
categoryMap[cmd.category] = [];
|
||||||
}
|
}
|
||||||
categoryMap[cmd.category].push(cmd);
|
categoryMap[cmd.category].push(cmd);
|
||||||
@@ -183,7 +183,8 @@ function formatArguments(args: PositionalArg[]): string {
|
|||||||
return (
|
return (
|
||||||
args
|
args
|
||||||
.map((arg) => {
|
.map((arg) => {
|
||||||
const requirement = arg.required ? `${ANSI_FG_RED}(required)` : `${ANSI_FG_CYAN}(optional)`;
|
const requirement =
|
||||||
|
arg.required === true ? `${ANSI_FG_RED}(required)` : `${ANSI_FG_CYAN}(optional)`;
|
||||||
const defaultValue =
|
const defaultValue =
|
||||||
arg.default !== undefined
|
arg.default !== undefined
|
||||||
? ` ${ANSI_FG_MAGENTA}[default: ${JSON.stringify(arg.default)}]${ANSI_RESET}`
|
? ` ${ANSI_FG_MAGENTA}[default: ${JSON.stringify(arg.default)}]${ANSI_RESET}`
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { BarToggleStates } from 'src/lib/types/cli';
|
import { BarToggleStates } from 'src/lib/types/cli.types';
|
||||||
|
|
||||||
export class BarVisibility {
|
export class BarVisibility {
|
||||||
private static _toggleStates: BarToggleStates = {};
|
private static _toggleStates: BarToggleStates = {};
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ export class CustomModules {
|
|||||||
|
|
||||||
return customModuleComponents;
|
return customModuleComponents;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(`Failed to build custom modules in ${CONFIG_DIR}: ${error}`);
|
console.error(`Failed to build custom modules in ${CONFIG_DIR}: ${error}`);
|
||||||
throw new Error(`Failed to build custom modules in ${CONFIG_DIR}: ${error}`);
|
throw new Error(`Failed to build custom modules in ${CONFIG_DIR}: ${error}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,7 +48,11 @@ export function getIcon(moduleName: string, commandOutput: string, moduleIcon: C
|
|||||||
* - No matching icon is found for the alt text
|
* - No matching icon is found for the alt text
|
||||||
* - Corresponding icon value is not a string
|
* - Corresponding icon value is not a string
|
||||||
*/
|
*/
|
||||||
function getIconFromObject(moduleName: string, commandOutput: string, iconObject: Record<string, unknown>): string {
|
function getIconFromObject(
|
||||||
|
moduleName: string,
|
||||||
|
commandOutput: string,
|
||||||
|
iconObject: Record<string, unknown>,
|
||||||
|
): string {
|
||||||
try {
|
try {
|
||||||
const commandResults: CommandResults = parseCommandOutputJson(moduleName, commandOutput);
|
const commandResults: CommandResults = parseCommandOutputJson(moduleName, commandOutput);
|
||||||
|
|
||||||
@@ -115,7 +119,7 @@ function getIconFromArray(moduleName: string, commandOutput: string, iconArray:
|
|||||||
|
|
||||||
const iconForStep = iconArray.find((_, index) => resultsPercentage <= step * (index + 1));
|
const iconForStep = iconArray.find((_, index) => resultsPercentage <= step * (index + 1));
|
||||||
|
|
||||||
return iconForStep || ERROR_ICON;
|
return iconForStep ?? ERROR_ICON;
|
||||||
} catch {
|
} catch {
|
||||||
return ERROR_ICON;
|
return ERROR_ICON;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,7 +29,10 @@ export function getLabel(moduleName: string, commandOutput: string, labelConfig:
|
|||||||
* @param commandOutput - The processed command output (either a string or object)
|
* @param commandOutput - The processed command output (either a string or object)
|
||||||
* @returns The extracted value as a string, or empty string if not found
|
* @returns The extracted value as a string, or empty string if not found
|
||||||
*/
|
*/
|
||||||
function getValueForTemplateVariable(templatePath: string, commandOutput: string | Record<string, unknown>): string {
|
function getValueForTemplateVariable(
|
||||||
|
templatePath: string,
|
||||||
|
commandOutput: string | Record<string, unknown>,
|
||||||
|
): string {
|
||||||
if (typeof commandOutput === 'string') {
|
if (typeof commandOutput === 'string') {
|
||||||
return getTemplateValueForStringOutput(templatePath, commandOutput);
|
return getTemplateValueForStringOutput(templatePath, commandOutput);
|
||||||
}
|
}
|
||||||
@@ -62,7 +65,10 @@ function getTemplateValueForStringOutput(templatePath: string, commandOutput: st
|
|||||||
* @param commandOutput - The object representing parsed command output
|
* @param commandOutput - The object representing parsed command output
|
||||||
* @returns The extracted value as a string, or empty string if path is invalid or value is not primitive
|
* @returns The extracted value as a string, or empty string if path is invalid or value is not primitive
|
||||||
*/
|
*/
|
||||||
function getTemplateValueForObjectOutput(templatePath: string, commandOutput: Record<string, unknown>): string {
|
function getTemplateValueForObjectOutput(
|
||||||
|
templatePath: string,
|
||||||
|
commandOutput: Record<string, unknown>,
|
||||||
|
): string {
|
||||||
const pathParts = templatePath.split('.');
|
const pathParts = templatePath.split('.');
|
||||||
|
|
||||||
function isRecord(value: unknown): value is Record<string, unknown> {
|
function isRecord(value: unknown): value is Record<string, unknown> {
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import { BarBoxChild } from 'src/lib/types/bar.js';
|
|
||||||
import { CustomBarModule } from '../types';
|
import { CustomBarModule } from '../types';
|
||||||
import { Module } from '../../shared/Module';
|
import { Module } from '../../shared/Module';
|
||||||
import { Astal } from 'astal/gtk3';
|
import { Astal } from 'astal/gtk3';
|
||||||
@@ -6,6 +5,7 @@ import { bind, Variable } from 'astal';
|
|||||||
import { getIcon } from './helpers/icon';
|
import { getIcon } from './helpers/icon';
|
||||||
import { getLabel } from './helpers/label';
|
import { getLabel } from './helpers/label';
|
||||||
import { initActionListener, initCommandPoller, setupModuleInteractions } from './setup';
|
import { initActionListener, initCommandPoller, setupModuleInteractions } from './setup';
|
||||||
|
import { BarBoxChild } from 'src/lib/types/bar.types';
|
||||||
|
|
||||||
export const ModuleContainer = (moduleName: string, moduleMetadata: CustomBarModule): BarBoxChild => {
|
export const ModuleContainer = (moduleName: string, moduleMetadata: CustomBarModule): BarBoxChild => {
|
||||||
const {
|
const {
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ import { bind, Variable } from 'astal';
|
|||||||
import { getLayoutForMonitor, isLayoutEmpty } from './utils/monitors';
|
import { getLayoutForMonitor, isLayoutEmpty } from './utils/monitors';
|
||||||
import { GdkMonitorMapper } from './utils/GdkMonitorMapper';
|
import { GdkMonitorMapper } from './utils/GdkMonitorMapper';
|
||||||
import { CustomModules } from './custom_modules/CustomModules';
|
import { CustomModules } from './custom_modules/CustomModules';
|
||||||
|
import { idleInhibit } from 'src/shared/utilities';
|
||||||
|
|
||||||
const { layouts } = options.bar;
|
const { layouts } = options.bar;
|
||||||
const { location } = options.theme.bar;
|
const { location } = options.theme.bar;
|
||||||
@@ -82,7 +83,7 @@ export const Bar = async (monitor: number): Promise<JSX.Element> => {
|
|||||||
...customWidgets,
|
...customWidgets,
|
||||||
};
|
};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error);
|
console.error(error);
|
||||||
}
|
}
|
||||||
const hyprlandMonitor = gdkMonitorMapper.mapGdkToHyprland(monitor);
|
const hyprlandMonitor = gdkMonitorMapper.mapGdkToHyprland(monitor);
|
||||||
|
|
||||||
@@ -93,7 +94,7 @@ export const Bar = async (monitor: number): Promise<JSX.Element> => {
|
|||||||
|
|
||||||
const computeClassName = bind(layouts).as(() => {
|
const computeClassName = bind(layouts).as(() => {
|
||||||
const foundLayout = getLayoutForMonitor(hyprlandMonitor, layouts.get());
|
const foundLayout = getLayoutForMonitor(hyprlandMonitor, layouts.get());
|
||||||
return !isLayoutEmpty(foundLayout) ? `bar` : '';
|
return !isLayoutEmpty(foundLayout) ? 'bar' : '';
|
||||||
});
|
});
|
||||||
|
|
||||||
const computeAnchor = bind(location).as((loc) => {
|
const computeAnchor = bind(location).as((loc) => {
|
||||||
@@ -104,19 +105,22 @@ export const Bar = async (monitor: number): Promise<JSX.Element> => {
|
|||||||
return Astal.WindowAnchor.TOP | Astal.WindowAnchor.LEFT | Astal.WindowAnchor.RIGHT;
|
return Astal.WindowAnchor.TOP | Astal.WindowAnchor.LEFT | Astal.WindowAnchor.RIGHT;
|
||||||
});
|
});
|
||||||
|
|
||||||
const computeLayer = Variable.derive([bind(options.theme.bar.layer), bind(options.tear)], (barLayer, tear) => {
|
const computeLayer = Variable.derive(
|
||||||
if (tear && barLayer === 'overlay') {
|
[bind(options.theme.bar.layer), bind(options.tear)],
|
||||||
return Astal.Layer.TOP;
|
(barLayer, tear) => {
|
||||||
}
|
if (tear && barLayer === 'overlay') {
|
||||||
const layerMap = {
|
return Astal.Layer.TOP;
|
||||||
overlay: Astal.Layer.OVERLAY,
|
}
|
||||||
top: Astal.Layer.TOP,
|
const layerMap = {
|
||||||
bottom: Astal.Layer.BOTTOM,
|
overlay: Astal.Layer.OVERLAY,
|
||||||
background: Astal.Layer.BACKGROUND,
|
top: Astal.Layer.TOP,
|
||||||
};
|
bottom: Astal.Layer.BOTTOM,
|
||||||
|
background: Astal.Layer.BACKGROUND,
|
||||||
|
};
|
||||||
|
|
||||||
return layerMap[barLayer];
|
return layerMap[barLayer];
|
||||||
});
|
},
|
||||||
|
);
|
||||||
|
|
||||||
const computeBorderLocation = bind(borderLocation).as((brdrLcn) =>
|
const computeBorderLocation = bind(borderLocation).as((brdrLcn) =>
|
||||||
brdrLcn !== 'none' ? 'bar-panel withBorder' : 'bar-panel',
|
brdrLcn !== 'none' ? 'bar-panel withBorder' : 'bar-panel',
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { BatteryIconKeys, BatteryIcons } from 'src/lib/types/battery';
|
import { BatteryIconKeys, BatteryIcons } from 'src/lib/types/battery.types';
|
||||||
|
|
||||||
const batteryIcons: BatteryIcons = {
|
const batteryIcons: BatteryIcons = {
|
||||||
0: '',
|
0: '',
|
||||||
|
|||||||
@@ -2,15 +2,22 @@ import AstalBattery from 'gi://AstalBattery?version=0.1';
|
|||||||
import { Astal } from 'astal/gtk3';
|
import { Astal } from 'astal/gtk3';
|
||||||
import { openMenu } from '../../utils/menu';
|
import { openMenu } from '../../utils/menu';
|
||||||
import options from 'src/options';
|
import options from 'src/options';
|
||||||
import { BarBoxChild } from 'src/lib/types/bar.js';
|
|
||||||
import { runAsyncCommand, throttledScrollHandler } from 'src/components/bar/utils/helpers.js';
|
import { runAsyncCommand, throttledScrollHandler } from 'src/components/bar/utils/helpers.js';
|
||||||
import Variable from 'astal/variable';
|
import Variable from 'astal/variable';
|
||||||
import { bind } from 'astal';
|
import { bind } from 'astal';
|
||||||
import { onMiddleClick, onPrimaryClick, onScroll, onSecondaryClick } from 'src/lib/shared/eventHandlers';
|
import { onMiddleClick, onPrimaryClick, onScroll, onSecondaryClick } from 'src/lib/shared/eventHandlers';
|
||||||
import { getBatteryIcon } from './helpers';
|
import { getBatteryIcon } from './helpers';
|
||||||
|
import { BarBoxChild } from 'src/lib/types/bar.types';
|
||||||
|
|
||||||
const batteryService = AstalBattery.get_default();
|
const batteryService = AstalBattery.get_default();
|
||||||
const { label: show_label, rightClick, middleClick, scrollUp, scrollDown, hideLabelWhenFull } = options.bar.battery;
|
const {
|
||||||
|
label: show_label,
|
||||||
|
rightClick,
|
||||||
|
middleClick,
|
||||||
|
scrollUp,
|
||||||
|
scrollDown,
|
||||||
|
hideLabelWhenFull,
|
||||||
|
} = options.bar.battery;
|
||||||
|
|
||||||
const BatteryLabel = (): BarBoxChild => {
|
const BatteryLabel = (): BarBoxChild => {
|
||||||
const batIcon = Variable.derive(
|
const batIcon = Variable.derive(
|
||||||
@@ -55,10 +62,18 @@ const BatteryLabel = (): BarBoxChild => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
const componentTooltip = Variable.derive(
|
const componentTooltip = Variable.derive(
|
||||||
[bind(batteryService, 'charging'), bind(batteryService, 'timeToFull'), bind(batteryService, 'timeToEmpty')],
|
[
|
||||||
|
bind(batteryService, 'charging'),
|
||||||
|
bind(batteryService, 'timeToFull'),
|
||||||
|
bind(batteryService, 'timeToEmpty'),
|
||||||
|
],
|
||||||
(isCharging, timeToFull, timeToEmpty) => {
|
(isCharging, timeToFull, timeToEmpty) => {
|
||||||
const timeRemaining = isCharging ? timeToFull : timeToEmpty;
|
const timeRemaining = isCharging ? timeToFull : timeToEmpty;
|
||||||
return generateTooltip(timeRemaining, isCharging, Math.floor(batteryService.percentage * 100) === 100);
|
return generateTooltip(
|
||||||
|
timeRemaining,
|
||||||
|
isCharging,
|
||||||
|
Math.floor(batteryService.percentage * 100) === 100,
|
||||||
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -68,7 +83,9 @@ const BatteryLabel = (): BarBoxChild => {
|
|||||||
const isCharged = Math.round(percentage) === 100;
|
const isCharged = Math.round(percentage) === 100;
|
||||||
|
|
||||||
const icon = <label className={'bar-button-icon battery txt-icon'} label={batIcon()} />;
|
const icon = <label className={'bar-button-icon battery txt-icon'} label={batIcon()} />;
|
||||||
const label = <label className={'bar-button-label battery'} label={`${Math.floor(percentage * 100)}%`} />;
|
const label = (
|
||||||
|
<label className={'bar-button-label battery'} label={`${Math.floor(percentage * 100)}%`} />
|
||||||
|
);
|
||||||
|
|
||||||
const children = [icon];
|
const children = [icon];
|
||||||
|
|
||||||
@@ -135,7 +152,9 @@ const BatteryLabel = (): BarBoxChild => {
|
|||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
disconnectFunctions.push(onScroll(self, throttledHandler, scrollUp.get(), scrollDown.get()));
|
disconnectFunctions.push(
|
||||||
|
onScroll(self, throttledHandler, scrollUp.get(), scrollDown.get()),
|
||||||
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
import options from 'src/options.js';
|
import options from 'src/options.js';
|
||||||
import { openMenu } from '../../utils/menu.js';
|
import { openMenu } from '../../utils/menu.js';
|
||||||
import { BarBoxChild } from 'src/lib/types/bar.js';
|
|
||||||
import { runAsyncCommand, throttledScrollHandler } from 'src/components/bar/utils/helpers.js';
|
import { runAsyncCommand, throttledScrollHandler } from 'src/components/bar/utils/helpers.js';
|
||||||
import { Variable, bind } from 'astal';
|
import { Variable, bind } from 'astal';
|
||||||
import { onMiddleClick, onPrimaryClick, onScroll, onSecondaryClick } from 'src/lib/shared/eventHandlers.js';
|
import { onMiddleClick, onPrimaryClick, onScroll, onSecondaryClick } from 'src/lib/shared/eventHandlers.js';
|
||||||
import AstalBluetooth from 'gi://AstalBluetooth?version=0.1';
|
import AstalBluetooth from 'gi://AstalBluetooth?version=0.1';
|
||||||
import { Astal } from 'astal/gtk3';
|
import { Astal } from 'astal/gtk3';
|
||||||
|
import { BarBoxChild } from 'src/lib/types/bar.types.js';
|
||||||
|
|
||||||
const bluetoothService = AstalBluetooth.get_default();
|
const bluetoothService = AstalBluetooth.get_default();
|
||||||
|
|
||||||
@@ -20,7 +20,11 @@ const Bluetooth = (): BarBoxChild => {
|
|||||||
const connectDevices = devices.filter((device) => device.connected);
|
const connectDevices = devices.filter((device) => device.connected);
|
||||||
|
|
||||||
const label =
|
const label =
|
||||||
isPowered && connectDevices.length ? ` Connected (${connectDevices.length})` : isPowered ? 'On' : 'Off';
|
isPowered && connectDevices.length
|
||||||
|
? ` Connected (${connectDevices.length})`
|
||||||
|
: isPowered
|
||||||
|
? 'On'
|
||||||
|
: 'Off';
|
||||||
|
|
||||||
return <label label={label} className={'bar-button-label bluetooth'} />;
|
return <label label={label} className={'bar-button-label bluetooth'} />;
|
||||||
};
|
};
|
||||||
@@ -102,7 +106,9 @@ const Bluetooth = (): BarBoxChild => {
|
|||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
disconnectFunctions.push(onScroll(self, throttledHandler, scrollUp.get(), scrollDown.get()));
|
disconnectFunctions.push(
|
||||||
|
onScroll(self, throttledHandler, scrollUp.get(), scrollDown.get()),
|
||||||
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
import { Variable, bind } from 'astal';
|
import { Variable, bind } from 'astal';
|
||||||
import { Astal } from 'astal/gtk3';
|
import { Astal } from 'astal/gtk3';
|
||||||
import { BarBoxChild } from 'src/lib/types/bar';
|
|
||||||
import { Module } from '../../shared/Module';
|
import { Module } from '../../shared/Module';
|
||||||
import { inputHandler } from '../../utils/helpers';
|
import { inputHandler } from '../../utils/helpers';
|
||||||
import options from 'src/options';
|
import options from 'src/options';
|
||||||
import { initSettingsTracker, initVisibilityTracker } from './helpers';
|
import { initSettingsTracker, initVisibilityTracker } from './helpers';
|
||||||
import AstalCava from 'gi://AstalCava?version=0.1';
|
import AstalCava from 'gi://AstalCava?version=0.1';
|
||||||
|
import { BarBoxChild } from 'src/lib/types/bar.types';
|
||||||
|
|
||||||
const {
|
const {
|
||||||
icon,
|
icon,
|
||||||
@@ -46,7 +46,7 @@ export const Cava = (): BarBoxChild => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return Module({
|
return Module({
|
||||||
isVis,
|
isVis: bind(isVis),
|
||||||
label: labelBinding(),
|
label: labelBinding(),
|
||||||
showIconBinding: bind(label),
|
showIconBinding: bind(label),
|
||||||
textIcon: bind(icon),
|
textIcon: bind(icon),
|
||||||
|
|||||||
@@ -1,20 +1,24 @@
|
|||||||
import { openMenu } from '../../utils/menu';
|
import { openMenu } from '../../utils/menu';
|
||||||
import options from 'src/options';
|
import options from 'src/options';
|
||||||
import { BarBoxChild } from 'src/lib/types/bar.js';
|
|
||||||
import { runAsyncCommand, throttledScrollHandler } from 'src/components/bar/utils/helpers.js';
|
import { runAsyncCommand, throttledScrollHandler } from 'src/components/bar/utils/helpers.js';
|
||||||
import { bind, Variable } from 'astal';
|
import { bind, Variable } from 'astal';
|
||||||
import { onMiddleClick, onPrimaryClick, onScroll, onSecondaryClick } from 'src/lib/shared/eventHandlers';
|
import { onMiddleClick, onPrimaryClick, onScroll, onSecondaryClick } from 'src/lib/shared/eventHandlers';
|
||||||
import { Astal } from 'astal/gtk3';
|
import { Astal } from 'astal/gtk3';
|
||||||
import { systemTime } from 'src/globals/time';
|
import { systemTime } from 'src/shared/time';
|
||||||
|
import { BarBoxChild } from 'src/lib/types/bar.types';
|
||||||
|
|
||||||
const { format, icon, showIcon, showTime, rightClick, middleClick, scrollUp, scrollDown } = options.bar.clock;
|
const { format, icon, showIcon, showTime, rightClick, middleClick, scrollUp, scrollDown } = options.bar.clock;
|
||||||
const { style } = options.theme.bar.buttons;
|
const { style } = options.theme.bar.buttons;
|
||||||
|
|
||||||
const time = Variable.derive([systemTime, format], (c, f) => c.format(f) || '');
|
const time = Variable.derive([systemTime, format], (c, f) => c.format(f) ?? '');
|
||||||
|
|
||||||
const Clock = (): BarBoxChild => {
|
const Clock = (): BarBoxChild => {
|
||||||
const ClockTime = (): JSX.Element => <label className={'bar-button-label clock bar'} label={bind(time)} />;
|
const ClockTime = (): JSX.Element => (
|
||||||
const ClockIcon = (): JSX.Element => <label className={'bar-button-icon clock txt-icon bar'} label={bind(icon)} />;
|
<label className={'bar-button-label clock bar'} label={bind(time)} />
|
||||||
|
);
|
||||||
|
const ClockIcon = (): JSX.Element => (
|
||||||
|
<label className={'bar-button-icon clock txt-icon bar'} label={bind(icon)} />
|
||||||
|
);
|
||||||
|
|
||||||
const componentClassName = Variable.derive(
|
const componentClassName = Variable.derive(
|
||||||
[bind(style), bind(showIcon), bind(showTime)],
|
[bind(style), bind(showIcon), bind(showTime)],
|
||||||
@@ -95,7 +99,9 @@ const Clock = (): BarBoxChild => {
|
|||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
disconnectFunctions.push(onScroll(self, throttledHandler, scrollUp.get(), scrollDown.get()));
|
disconnectFunctions.push(
|
||||||
|
onScroll(self, throttledHandler, scrollUp.get(), scrollDown.get()),
|
||||||
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ export const computeCPU = (): number => {
|
|||||||
const currentCpuData = new GTop.glibtop_cpu();
|
const currentCpuData = new GTop.glibtop_cpu();
|
||||||
GTop.glibtop_get_cpu(currentCpuData);
|
GTop.glibtop_get_cpu(currentCpuData);
|
||||||
|
|
||||||
// Calculate the differences from the previous to current data
|
|
||||||
const totalDiff = currentCpuData.total - previousCpuData.total;
|
const totalDiff = currentCpuData.total - previousCpuData.total;
|
||||||
const idleDiff = currentCpuData.idle - previousCpuData.idle;
|
const idleDiff = currentCpuData.idle - previousCpuData.idle;
|
||||||
|
|
||||||
|
|||||||
@@ -2,10 +2,10 @@ import { Module } from '../../shared/Module';
|
|||||||
import options from 'src/options';
|
import options from 'src/options';
|
||||||
import { inputHandler } from 'src/components/bar/utils/helpers';
|
import { inputHandler } from 'src/components/bar/utils/helpers';
|
||||||
import { computeCPU } from './helpers';
|
import { computeCPU } from './helpers';
|
||||||
import { BarBoxChild } from 'src/lib/types/bar';
|
|
||||||
import { FunctionPoller } from 'src/lib/poller/FunctionPoller';
|
import { FunctionPoller } from 'src/lib/poller/FunctionPoller';
|
||||||
import { bind, Variable } from 'astal';
|
import { bind, Variable } from 'astal';
|
||||||
import { Astal } from 'astal/gtk3';
|
import { Astal } from 'astal/gtk3';
|
||||||
|
import { BarBoxChild } from 'src/lib/types/bar.types';
|
||||||
|
|
||||||
const { label, round, leftClick, rightClick, middleClick, scrollUp, scrollDown, pollingInterval, icon } =
|
const { label, round, leftClick, rightClick, middleClick, scrollUp, scrollDown, pollingInterval, icon } =
|
||||||
options.bar.customModules.cpu;
|
options.bar.customModules.cpu;
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import { Variable } from 'astal';
|
import { Variable } from 'astal';
|
||||||
import GLib from 'gi://GLib?version=2.0';
|
import GLib from 'gi://GLib?version=2.0';
|
||||||
import { convertCelsiusToFahrenheit } from 'src/globals/weather';
|
import { convertCelsiusToFahrenheit } from 'src/shared/weather';
|
||||||
import { UnitType } from 'src/lib/types/weather';
|
|
||||||
import options from 'src/options';
|
import options from 'src/options';
|
||||||
|
import { UnitType } from 'src/lib/types/weather.types';
|
||||||
const { sensor } = options.bar.customModules.cpuTemp;
|
const { sensor } = options.bar.customModules.cpuTemp;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -25,7 +25,7 @@ export const getCPUTemperature = (round: Variable<boolean>, unit: Variable<UnitT
|
|||||||
const [success, tempInfoBytes] = GLib.file_get_contents(sensor.get());
|
const [success, tempInfoBytes] = GLib.file_get_contents(sensor.get());
|
||||||
const tempInfo = new TextDecoder('utf-8').decode(tempInfoBytes);
|
const tempInfo = new TextDecoder('utf-8').decode(tempInfoBytes);
|
||||||
|
|
||||||
if (!success || !tempInfoBytes) {
|
if (!success || tempInfoBytes === null) {
|
||||||
console.error(`Failed to read ${sensor.get()} or file content is null.`);
|
console.error(`Failed to read ${sensor.get()} or file content is null.`);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,11 +2,11 @@ import options from 'src/options';
|
|||||||
import { Module } from '../../shared/Module';
|
import { Module } from '../../shared/Module';
|
||||||
import { inputHandler } from 'src/components/bar/utils/helpers';
|
import { inputHandler } from 'src/components/bar/utils/helpers';
|
||||||
import { getCPUTemperature } from './helpers';
|
import { getCPUTemperature } from './helpers';
|
||||||
import { BarBoxChild } from 'src/lib/types/bar';
|
|
||||||
import { FunctionPoller } from 'src/lib/poller/FunctionPoller';
|
import { FunctionPoller } from 'src/lib/poller/FunctionPoller';
|
||||||
import { UnitType } from 'src/lib/types/weather';
|
|
||||||
import { bind, Variable } from 'astal';
|
import { bind, Variable } from 'astal';
|
||||||
import { Astal } from 'astal/gtk3';
|
import { Astal } from 'astal/gtk3';
|
||||||
|
import { UnitType } from 'src/lib/types/weather.types';
|
||||||
|
import { BarBoxChild } from 'src/lib/types/bar.types';
|
||||||
|
|
||||||
const {
|
const {
|
||||||
label,
|
label,
|
||||||
|
|||||||
@@ -3,31 +3,37 @@ import { Module } from '../../shared/Module';
|
|||||||
import { inputHandler } from '../../utils/helpers';
|
import { inputHandler } from '../../utils/helpers';
|
||||||
import Variable from 'astal/variable';
|
import Variable from 'astal/variable';
|
||||||
import { bind } from 'astal';
|
import { bind } from 'astal';
|
||||||
import { BarBoxChild } from 'src/lib/types/bar';
|
|
||||||
import { Astal } from 'astal/gtk3';
|
import { Astal } from 'astal/gtk3';
|
||||||
|
import { idleInhibit } from 'src/shared/utilities';
|
||||||
|
import { BarBoxChild } from 'src/lib/types/bar.types';
|
||||||
|
|
||||||
const { label, onIcon, offIcon, onLabel, offLabel, rightClick, middleClick, scrollUp, scrollDown } =
|
const { label, onIcon, offIcon, onLabel, offLabel, rightClick, middleClick, scrollUp, scrollDown } =
|
||||||
options.bar.customModules.hypridle;
|
options.bar.customModules.hypridle;
|
||||||
|
|
||||||
function toggleInhibit(): void {
|
function toggleInhibit(): void {
|
||||||
idleInhibit.set(!idleInhibit.get());
|
idleInhibit.set(idleInhibit.get() === false);
|
||||||
}
|
}
|
||||||
|
|
||||||
export const Hypridle = (): BarBoxChild => {
|
export const Hypridle = (): BarBoxChild => {
|
||||||
const iconBinding = Variable.derive([bind(idleInhibit), bind(onIcon), bind(offIcon)], (active, onIcn, offIcn) => {
|
const iconBinding = Variable.derive(
|
||||||
return active ? onIcn : offIcn;
|
[bind(idleInhibit), bind(onIcon), bind(offIcon)],
|
||||||
});
|
(active, onIcn, offIcn) => {
|
||||||
|
return active === true ? onIcn : offIcn;
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
const labelBinding = Variable.derive(
|
const labelBinding = Variable.derive(
|
||||||
[bind(idleInhibit), bind(onLabel), bind(offLabel)],
|
[bind(idleInhibit), bind(onLabel), bind(offLabel)],
|
||||||
(active, onLbl, offLbl) => {
|
(active, onLbl, offLbl) => {
|
||||||
return active ? onLbl : offLbl;
|
return active === true ? onLbl : offLbl;
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
const hypridleModule = Module({
|
const hypridleModule = Module({
|
||||||
textIcon: iconBinding(),
|
textIcon: iconBinding(),
|
||||||
tooltipText: bind(idleInhibit).as((active) => `Idle Inhibitor: ${active ? 'Enabled' : 'Disabled'}`),
|
tooltipText: bind(idleInhibit).as(
|
||||||
|
(active) => `Idle Inhibitor: ${active === true ? 'Enabled' : 'Disabled'}`,
|
||||||
|
),
|
||||||
boxClass: 'hypridle',
|
boxClass: 'hypridle',
|
||||||
label: labelBinding(),
|
label: labelBinding(),
|
||||||
showLabelBinding: bind(label),
|
showLabelBinding: bind(label),
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ const { temperature } = options.bar.customModules.hyprsunset;
|
|||||||
* This command checks if the hyprsunset process is currently running by using the `pgrep` command.
|
* This command checks if the hyprsunset process is currently running by using the `pgrep` command.
|
||||||
* It returns 'yes' if the process is found and 'no' otherwise.
|
* It returns 'yes' if the process is found and 'no' otherwise.
|
||||||
*/
|
*/
|
||||||
export const isActiveCommand = `bash -c "pgrep -x 'hyprsunset' > /dev/null && echo 'yes' || echo 'no'"`;
|
export const isActiveCommand = "bash -c \"pgrep -x 'hyprsunset' > /dev/null && echo 'yes' || echo 'no'\"";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A variable to track the active state of the hyprsunset process.
|
* A variable to track the active state of the hyprsunset process.
|
||||||
@@ -33,7 +33,7 @@ export const toggleSunset = (isActive: Variable<boolean>): void => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
execAsync(`bash -c "pkill hyprsunset "`).then(() => {
|
execAsync('bash -c "pkill hyprsunset "').then(() => {
|
||||||
execAsync(isActiveCommand).then((res) => {
|
execAsync(isActiveCommand).then((res) => {
|
||||||
isActive.set(res === 'yes');
|
isActive.set(res === 'yes');
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
import options from 'src/options';
|
import options from 'src/options';
|
||||||
import { Module } from '../../shared/Module';
|
import { Module } from '../../shared/Module';
|
||||||
import { inputHandler, throttleInput } from 'src/components/bar/utils/helpers';
|
import { inputHandler, throttleInput } from 'src/components/bar/utils/helpers';
|
||||||
import { BarBoxChild } from 'src/lib/types/bar';
|
|
||||||
import { checkSunsetStatus, isActive, toggleSunset } from './helpers';
|
import { checkSunsetStatus, isActive, toggleSunset } from './helpers';
|
||||||
import { FunctionPoller } from 'src/lib/poller/FunctionPoller';
|
import { FunctionPoller } from 'src/lib/poller/FunctionPoller';
|
||||||
import { bind, Variable } from 'astal';
|
import { bind, Variable } from 'astal';
|
||||||
import { Astal } from 'astal/gtk3';
|
import { Astal } from 'astal/gtk3';
|
||||||
|
import { BarBoxChild } from 'src/lib/types/bar.types';
|
||||||
|
|
||||||
const {
|
const {
|
||||||
label,
|
label,
|
||||||
@@ -25,24 +25,35 @@ const dummyVar = Variable(undefined);
|
|||||||
|
|
||||||
checkSunsetStatus();
|
checkSunsetStatus();
|
||||||
|
|
||||||
const sunsetPoller = new FunctionPoller<undefined, []>(dummyVar, [], bind(pollingInterval), checkSunsetStatus);
|
const sunsetPoller = new FunctionPoller<undefined, []>(
|
||||||
|
dummyVar,
|
||||||
|
[],
|
||||||
|
bind(pollingInterval),
|
||||||
|
checkSunsetStatus,
|
||||||
|
);
|
||||||
|
|
||||||
sunsetPoller.initialize('hyprsunset');
|
sunsetPoller.initialize('hyprsunset');
|
||||||
|
|
||||||
const throttledToggleSunset = throttleInput(() => toggleSunset(isActive), 1000);
|
const throttledToggleSunset = throttleInput(() => toggleSunset(isActive), 1000);
|
||||||
|
|
||||||
export const Hyprsunset = (): BarBoxChild => {
|
export const Hyprsunset = (): BarBoxChild => {
|
||||||
const iconBinding = Variable.derive([bind(isActive), bind(onIcon), bind(offIcon)], (active, onIcn, offIcn) => {
|
const iconBinding = Variable.derive(
|
||||||
return active ? onIcn : offIcn;
|
[bind(isActive), bind(onIcon), bind(offIcon)],
|
||||||
});
|
(active, onIcn, offIcn) => {
|
||||||
|
return active ? onIcn : offIcn;
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
const tooltipBinding = Variable.derive([isActive, temperature], (active, temp) => {
|
const tooltipBinding = Variable.derive([isActive, temperature], (active, temp) => {
|
||||||
return `Hyprsunset ${active ? 'enabled' : 'disabled'}\nTemperature: ${temp}`;
|
return `Hyprsunset ${active ? 'enabled' : 'disabled'}\nTemperature: ${temp}`;
|
||||||
});
|
});
|
||||||
|
|
||||||
const labelBinding = Variable.derive([bind(isActive), bind(onLabel), bind(offLabel)], (active, onLbl, offLbl) => {
|
const labelBinding = Variable.derive(
|
||||||
return active ? onLbl : offLbl;
|
[bind(isActive), bind(onLabel), bind(offLabel)],
|
||||||
});
|
(active, onLbl, offLbl) => {
|
||||||
|
return active ? onLbl : offLbl;
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
const hyprsunsetModule = Module({
|
const hyprsunsetModule = Module({
|
||||||
textIcon: iconBinding(),
|
textIcon: iconBinding(),
|
||||||
|
|||||||
@@ -2,10 +2,8 @@ import {
|
|||||||
HyprctlDeviceLayout,
|
HyprctlDeviceLayout,
|
||||||
HyprctlKeyboard,
|
HyprctlKeyboard,
|
||||||
KbLabelType,
|
KbLabelType,
|
||||||
LayoutKeys,
|
} from 'src/lib/types/customModules/kbLayout.types.js';
|
||||||
LayoutValues,
|
import { LayoutKeys, layoutMap, LayoutValues } from './layouts';
|
||||||
} from 'src/lib/types/customModules/kbLayout';
|
|
||||||
import { layoutMap } from './layouts';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves the keyboard layout from a given JSON string and format.
|
* Retrieves the keyboard layout from a given JSON string and format.
|
||||||
@@ -32,8 +30,21 @@ export const getKeyboardLayout = (layoutData: string, format: KbLabelType): Layo
|
|||||||
mainKb = keyboards[keyboards.length - 1];
|
mainKb = keyboards[keyboards.length - 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
const layout: LayoutKeys = mainKb['active_keymap'] as LayoutKeys;
|
if (!isValidLayout(mainKb.active_keymap)) {
|
||||||
|
return layoutMap['Unknown Layout'];
|
||||||
|
}
|
||||||
|
|
||||||
|
const layout: LayoutKeys = mainKb.active_keymap;
|
||||||
|
|
||||||
const foundLayout: LayoutValues = layoutMap[layout];
|
const foundLayout: LayoutValues = layoutMap[layout];
|
||||||
|
|
||||||
return format === 'code' ? foundLayout || layout : layout;
|
return format === 'code' ? (foundLayout ?? layout) : layout;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function isValidLayout(kbLayout: string): kbLayout is LayoutKeys {
|
||||||
|
if (!Object.keys(layoutMap).includes(kbLayout)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import { LayoutKeys, LayoutValues } from 'src/lib/types/customModules/kbLayout';
|
// Create a const object with all layouts
|
||||||
|
const layoutMapObj = {
|
||||||
export const layoutMap: Record<LayoutKeys, LayoutValues> = {
|
|
||||||
'Abkhazian (Russia)': 'RU (Ab)',
|
'Abkhazian (Russia)': 'RU (Ab)',
|
||||||
Akan: 'GH (Akan)',
|
Akan: 'GH (Akan)',
|
||||||
Albanian: 'AL',
|
Albanian: 'AL',
|
||||||
@@ -585,3 +584,8 @@ export const layoutMap: Record<LayoutKeys, LayoutValues> = {
|
|||||||
Yoruba: 'NG (Yoruba)',
|
Yoruba: 'NG (Yoruba)',
|
||||||
'Unknown Layout': 'Unknown',
|
'Unknown Layout': 'Unknown',
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
|
export type LayoutKeys = keyof typeof layoutMapObj;
|
||||||
|
export type LayoutValues = (typeof layoutMapObj)[LayoutKeys];
|
||||||
|
|
||||||
|
export const layoutMap = layoutMapObj;
|
||||||
|
|||||||
@@ -2,11 +2,11 @@ import options from 'src/options';
|
|||||||
import { Module } from '../../shared/Module';
|
import { Module } from '../../shared/Module';
|
||||||
import { inputHandler } from 'src/components/bar/utils/helpers';
|
import { inputHandler } from 'src/components/bar/utils/helpers';
|
||||||
import { getKeyboardLayout } from './helpers';
|
import { getKeyboardLayout } from './helpers';
|
||||||
import { BarBoxChild } from 'src/lib/types/bar';
|
|
||||||
import { bind } from 'astal';
|
import { bind } from 'astal';
|
||||||
import { useHook } from 'src/lib/shared/hookHandler';
|
import { useHook } from 'src/lib/shared/hookHandler';
|
||||||
import { Astal } from 'astal/gtk3';
|
import { Astal } from 'astal/gtk3';
|
||||||
import AstalHyprland from 'gi://AstalHyprland?version=0.1';
|
import AstalHyprland from 'gi://AstalHyprland?version=0.1';
|
||||||
|
import { BarBoxChild } from 'src/lib/types/bar.types';
|
||||||
|
|
||||||
const hyprlandService = AstalHyprland.get_default();
|
const hyprlandService = AstalHyprland.get_default();
|
||||||
const { label, labelType, icon, leftClick, rightClick, middleClick, scrollUp, scrollDown } =
|
const { label, labelType, icon, leftClick, rightClick, middleClick, scrollUp, scrollDown } =
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { MediaTags } from 'src/lib/types/audio.js';
|
|
||||||
import { Opt } from 'src/lib/option';
|
|
||||||
import AstalMpris from 'gi://AstalMpris?version=0.1';
|
import AstalMpris from 'gi://AstalMpris?version=0.1';
|
||||||
import { Variable } from 'astal';
|
import { Variable } from 'astal';
|
||||||
|
import { MediaTags } from 'src/lib/types/audio.types';
|
||||||
|
import { Opt } from 'src/lib/options';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves the icon for a given media player.
|
* Retrieves the icon for a given media player.
|
||||||
@@ -82,8 +82,8 @@ export const generateMediaLabel = (
|
|||||||
const currentPlayer = activePlayer.get();
|
const currentPlayer = activePlayer.get();
|
||||||
|
|
||||||
if (!currentPlayer || !show_label.get()) {
|
if (!currentPlayer || !show_label.get()) {
|
||||||
songIcon.set(getIconForPlayer(activePlayer.get()?.identity || ''));
|
songIcon.set(getIconForPlayer(activePlayer.get()?.identity ?? ''));
|
||||||
return `Media`;
|
return 'Media';
|
||||||
}
|
}
|
||||||
|
|
||||||
const { title, identity, artist, album, busName } = currentPlayer;
|
const { title, identity, artist, album, busName } = currentPlayer;
|
||||||
@@ -107,7 +107,7 @@ export const generateMediaLabel = (
|
|||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
const value = p1 !== undefined ? mediaTags[p1] : '';
|
const value = p1 !== undefined ? mediaTags[p1] : '';
|
||||||
const suffix = p2?.length ? p2.slice(1) : '';
|
const suffix = p2 !== undefined && p2.length > 0 ? p2.slice(1) : '';
|
||||||
return value ? value + suffix : '';
|
return value ? value + suffix : '';
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -4,10 +4,10 @@ import { runAsyncCommand, throttledScrollHandler } from 'src/components/bar/util
|
|||||||
import { generateMediaLabel } from './helpers/index.js';
|
import { generateMediaLabel } from './helpers/index.js';
|
||||||
import { onMiddleClick, onPrimaryClick, onScroll, onSecondaryClick } from 'src/lib/shared/eventHandlers.js';
|
import { onMiddleClick, onPrimaryClick, onScroll, onSecondaryClick } from 'src/lib/shared/eventHandlers.js';
|
||||||
import { bind, Variable } from 'astal';
|
import { bind, Variable } from 'astal';
|
||||||
import { BarBoxChild } from 'src/lib/types/bar.js';
|
|
||||||
import { Astal } from 'astal/gtk3';
|
import { Astal } from 'astal/gtk3';
|
||||||
import { activePlayer, mediaAlbum, mediaArtist, mediaTitle } from 'src/globals/media.js';
|
import { activePlayer, mediaAlbum, mediaArtist, mediaTitle } from 'src/shared/media.js';
|
||||||
import AstalMpris from 'gi://AstalMpris?version=0.1';
|
import AstalMpris from 'gi://AstalMpris?version=0.1';
|
||||||
|
import { BarBoxChild } from 'src/lib/types/bar.types.js';
|
||||||
|
|
||||||
const mprisService = AstalMpris.get_default();
|
const mprisService = AstalMpris.get_default();
|
||||||
const {
|
const {
|
||||||
@@ -49,15 +49,18 @@ const Media = (): BarBoxChild => {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
const componentClassName = Variable.derive([options.theme.bar.buttons.style, show_label], (style: string) => {
|
const componentClassName = Variable.derive(
|
||||||
const styleMap: Record<string, string> = {
|
[options.theme.bar.buttons.style, show_label],
|
||||||
default: 'style1',
|
(style: string) => {
|
||||||
split: 'style2',
|
const styleMap: Record<string, string> = {
|
||||||
wave: 'style3',
|
default: 'style1',
|
||||||
wave2: 'style3',
|
split: 'style2',
|
||||||
};
|
wave: 'style3',
|
||||||
return `media-container ${styleMap[style]}`;
|
wave2: 'style3',
|
||||||
});
|
};
|
||||||
|
return `media-container ${styleMap[style]}`;
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
const component = (
|
const component = (
|
||||||
<box
|
<box
|
||||||
@@ -68,14 +71,17 @@ const Media = (): BarBoxChild => {
|
|||||||
componentClassName.drop();
|
componentClassName.drop();
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<label className={'bar-button-icon media txt-icon bar'} label={bind(songIcon).as((icn) => icn || '')} />
|
<label
|
||||||
|
className={'bar-button-icon media txt-icon bar'}
|
||||||
|
label={bind(songIcon).as((icn) => icn || '')}
|
||||||
|
/>
|
||||||
<label className={'bar-button-label media'} label={mediaLabel()} />
|
<label className={'bar-button-label media'} label={mediaLabel()} />
|
||||||
</box>
|
</box>
|
||||||
);
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
component,
|
component,
|
||||||
isVis,
|
isVis: bind(isVis),
|
||||||
boxClass: 'media',
|
boxClass: 'media',
|
||||||
props: {
|
props: {
|
||||||
setup: (self: Astal.Button): void => {
|
setup: (self: Astal.Button): void => {
|
||||||
@@ -113,7 +119,9 @@ const Media = (): BarBoxChild => {
|
|||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
disconnectFunctions.push(onScroll(self, throttledHandler, scrollUp.get(), scrollDown.get()));
|
disconnectFunctions.push(
|
||||||
|
onScroll(self, throttledHandler, scrollUp.get(), scrollDown.get()),
|
||||||
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -4,14 +4,15 @@ import { openMenu } from '../../utils/menu.js';
|
|||||||
import { getDistroIcon } from '../../../../lib/utils.js';
|
import { getDistroIcon } from '../../../../lib/utils.js';
|
||||||
import { Variable, bind } from 'astal';
|
import { Variable, bind } from 'astal';
|
||||||
import { onMiddleClick, onPrimaryClick, onScroll, onSecondaryClick } from 'src/lib/shared/eventHandlers.js';
|
import { onMiddleClick, onPrimaryClick, onScroll, onSecondaryClick } from 'src/lib/shared/eventHandlers.js';
|
||||||
import { BarBoxChild } from 'src/lib/types/bar.js';
|
|
||||||
import { Astal } from 'astal/gtk3';
|
import { Astal } from 'astal/gtk3';
|
||||||
|
import { BarBoxChild } from 'src/lib/types/bar.types.js';
|
||||||
|
|
||||||
const { rightClick, middleClick, scrollUp, scrollDown, autoDetectIcon, icon } = options.bar.launcher;
|
const { rightClick, middleClick, scrollUp, scrollDown, autoDetectIcon, icon } = options.bar.launcher;
|
||||||
|
|
||||||
const Menu = (): BarBoxChild => {
|
const Menu = (): BarBoxChild => {
|
||||||
const iconBinding = Variable.derive([autoDetectIcon, icon], (autoDetect: boolean, iconValue: string): string =>
|
const iconBinding = Variable.derive(
|
||||||
autoDetect ? getDistroIcon() : iconValue,
|
[autoDetectIcon, icon],
|
||||||
|
(autoDetect: boolean, iconValue: string): string => (autoDetect ? getDistroIcon() : iconValue),
|
||||||
);
|
);
|
||||||
|
|
||||||
const componentClassName = bind(options.theme.bar.buttons.style).as((style: string) => {
|
const componentClassName = bind(options.theme.bar.buttons.style).as((style: string) => {
|
||||||
@@ -75,7 +76,9 @@ const Menu = (): BarBoxChild => {
|
|||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
disconnectFunctions.push(onScroll(self, throttledHandler, scrollUp.get(), scrollDown.get()));
|
disconnectFunctions.push(
|
||||||
|
onScroll(self, throttledHandler, scrollUp.get(), scrollDown.get()),
|
||||||
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
import options from 'src/options';
|
import options from 'src/options';
|
||||||
import { Module } from '../../shared/Module';
|
import { Module } from '../../shared/Module';
|
||||||
import { bind, Variable } from 'astal';
|
import { bind, Variable } from 'astal';
|
||||||
import { BarBoxChild } from 'src/lib/types/bar';
|
|
||||||
import { Astal } from 'astal/gtk3';
|
import { Astal } from 'astal/gtk3';
|
||||||
import { inputHandler } from '../../utils/helpers';
|
import { inputHandler } from '../../utils/helpers';
|
||||||
import AstalWp from 'gi://AstalWp?version=0.1';
|
import AstalWp from 'gi://AstalWp?version=0.1';
|
||||||
|
import { BarBoxChild } from 'src/lib/types/bar.types';
|
||||||
|
|
||||||
const wireplumber = AstalWp.get_default() as AstalWp.Wp;
|
const wireplumber = AstalWp.get_default() as AstalWp.Wp;
|
||||||
const audioService = wireplumber.audio;
|
const audioService = wireplumber.audio;
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import GLib from 'gi://GLib';
|
import GLib from 'gi://GLib';
|
||||||
import { Variable } from 'astal';
|
import { Variable } from 'astal';
|
||||||
import { NetworkResourceData } from 'src/lib/types/customModules/network';
|
import { RateUnit } from 'src/lib/types/bar.types';
|
||||||
import { GET_DEFAULT_NETSTAT_DATA } from 'src/lib/types/defaults/netstat';
|
import { NetworkResourceData } from 'src/lib/types/customModules/network.types';
|
||||||
import { RateUnit } from 'src/lib/types/bar';
|
import { getDefaultNetstatData } from 'src/lib/types/defaults/netstat.types';
|
||||||
|
|
||||||
let previousNetUsage = { rx: 0, tx: 0, time: 0 };
|
let previousNetUsage = { rx: 0, tx: 0, time: 0 };
|
||||||
|
|
||||||
@@ -97,16 +97,20 @@ const isValidInterface = (iface: NetworkUsage | null, interfaceName: string): bo
|
|||||||
*/
|
*/
|
||||||
const getNetworkUsage = (interfaceName: string = ''): NetworkUsage => {
|
const getNetworkUsage = (interfaceName: string = ''): NetworkUsage => {
|
||||||
const [success, data] = GLib.file_get_contents('/proc/net/dev');
|
const [success, data] = GLib.file_get_contents('/proc/net/dev');
|
||||||
|
const defaultStats = { name: '', rx: 0, tx: 0 };
|
||||||
|
|
||||||
if (!success) {
|
if (!success) {
|
||||||
console.error('Failed to read /proc/net/dev');
|
console.error('Failed to read /proc/net/dev');
|
||||||
return { name: '', rx: 0, tx: 0 };
|
return defaultStats;
|
||||||
}
|
}
|
||||||
|
|
||||||
const lines = new TextDecoder('utf-8').decode(data).split('\n');
|
const lines = new TextDecoder('utf-8').decode(data).split('\n');
|
||||||
|
|
||||||
for (const line of lines) {
|
for (const line of lines) {
|
||||||
const iface = parseInterfaceData(line);
|
const iface = parseInterfaceData(line);
|
||||||
|
|
||||||
if (isValidInterface(iface, interfaceName)) {
|
if (isValidInterface(iface, interfaceName)) {
|
||||||
return iface!;
|
return iface ?? defaultStats;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -131,9 +135,9 @@ export const computeNetwork = (
|
|||||||
dataType: Variable<RateUnit>,
|
dataType: Variable<RateUnit>,
|
||||||
): NetworkResourceData => {
|
): NetworkResourceData => {
|
||||||
const rateUnit = dataType.get();
|
const rateUnit = dataType.get();
|
||||||
const interfaceName = interfaceNameVar ? interfaceNameVar.get() : '';
|
const interfaceName = interfaceNameVar.get();
|
||||||
|
|
||||||
const DEFAULT_NETSTAT_DATA = GET_DEFAULT_NETSTAT_DATA(rateUnit);
|
const DEFAULT_NETSTAT_DATA = getDefaultNetstatData(rateUnit);
|
||||||
try {
|
try {
|
||||||
const { rx, tx, name } = getNetworkUsage(interfaceName);
|
const { rx, tx, name } = getNetworkUsage(interfaceName);
|
||||||
const currentTime = Date.now();
|
const currentTime = Date.now();
|
||||||
|
|||||||
@@ -2,14 +2,14 @@ import options from 'src/options';
|
|||||||
import { Module } from '../../shared/Module';
|
import { Module } from '../../shared/Module';
|
||||||
import { inputHandler } from 'src/components/bar/utils/helpers';
|
import { inputHandler } from 'src/components/bar/utils/helpers';
|
||||||
import { computeNetwork } from './helpers';
|
import { computeNetwork } from './helpers';
|
||||||
import { BarBoxChild, NetstatLabelType, RateUnit } from 'src/lib/types/bar';
|
import { NETWORK_LABEL_TYPES } from 'src/lib/types/defaults/bar.types';
|
||||||
import { NetworkResourceData } from 'src/lib/types/customModules/network';
|
|
||||||
import { NETWORK_LABEL_TYPES } from 'src/lib/types/defaults/bar';
|
|
||||||
import { GET_DEFAULT_NETSTAT_DATA } from 'src/lib/types/defaults/netstat';
|
|
||||||
import { FunctionPoller } from 'src/lib/poller/FunctionPoller';
|
import { FunctionPoller } from 'src/lib/poller/FunctionPoller';
|
||||||
import { bind, Variable } from 'astal';
|
import { bind, Variable } from 'astal';
|
||||||
import AstalNetwork from 'gi://AstalNetwork?version=0.1';
|
import AstalNetwork from 'gi://AstalNetwork?version=0.1';
|
||||||
import { Astal } from 'astal/gtk3';
|
import { Astal } from 'astal/gtk3';
|
||||||
|
import { RateUnit, BarBoxChild, NetstatLabelType } from 'src/lib/types/bar.types';
|
||||||
|
import { NetworkResourceData } from 'src/lib/types/customModules/network.types';
|
||||||
|
import { getDefaultNetstatData } from 'src/lib/types/defaults/netstat.types';
|
||||||
|
|
||||||
const networkService = AstalNetwork.get_default();
|
const networkService = AstalNetwork.get_default();
|
||||||
const {
|
const {
|
||||||
@@ -28,7 +28,7 @@ const {
|
|||||||
pollingInterval,
|
pollingInterval,
|
||||||
} = options.bar.customModules.netstat;
|
} = options.bar.customModules.netstat;
|
||||||
|
|
||||||
export const networkUsage = Variable<NetworkResourceData>(GET_DEFAULT_NETSTAT_DATA(rateUnit.get()));
|
export const networkUsage = Variable<NetworkResourceData>(getDefaultNetstatData(rateUnit.get()));
|
||||||
|
|
||||||
const netstatPoller = new FunctionPoller<
|
const netstatPoller = new FunctionPoller<
|
||||||
NetworkResourceData,
|
NetworkResourceData,
|
||||||
@@ -69,7 +69,8 @@ export const Netstat = (): BarBoxChild => {
|
|||||||
|
|
||||||
const labelBinding = Variable.derive(
|
const labelBinding = Variable.derive(
|
||||||
[bind(networkUsage), bind(labelType)],
|
[bind(networkUsage), bind(labelType)],
|
||||||
(networkService: NetworkResourceData, lblTyp: NetstatLabelType) => renderNetworkLabel(lblTyp, networkService),
|
(networkService: NetworkResourceData, lblTyp: NetstatLabelType) =>
|
||||||
|
renderNetworkLabel(lblTyp, networkService),
|
||||||
);
|
);
|
||||||
|
|
||||||
const netstatModule = Module({
|
const netstatModule = Module({
|
||||||
@@ -98,7 +99,8 @@ export const Netstat = (): BarBoxChild => {
|
|||||||
fn: () => {
|
fn: () => {
|
||||||
labelType.set(
|
labelType.set(
|
||||||
NETWORK_LABEL_TYPES[
|
NETWORK_LABEL_TYPES[
|
||||||
(NETWORK_LABEL_TYPES.indexOf(labelType.get()) + 1) % NETWORK_LABEL_TYPES.length
|
(NETWORK_LABEL_TYPES.indexOf(labelType.get()) + 1) %
|
||||||
|
NETWORK_LABEL_TYPES.length
|
||||||
] as NetstatLabelType,
|
] as NetstatLabelType,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
@@ -107,7 +109,9 @@ export const Netstat = (): BarBoxChild => {
|
|||||||
fn: () => {
|
fn: () => {
|
||||||
labelType.set(
|
labelType.set(
|
||||||
NETWORK_LABEL_TYPES[
|
NETWORK_LABEL_TYPES[
|
||||||
(NETWORK_LABEL_TYPES.indexOf(labelType.get()) - 1 + NETWORK_LABEL_TYPES.length) %
|
(NETWORK_LABEL_TYPES.indexOf(labelType.get()) -
|
||||||
|
1 +
|
||||||
|
NETWORK_LABEL_TYPES.length) %
|
||||||
NETWORK_LABEL_TYPES.length
|
NETWORK_LABEL_TYPES.length
|
||||||
] as NetstatLabelType,
|
] as NetstatLabelType,
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ const handleWiredIcon = (): void => {
|
|||||||
wiredIconBinding?.drop();
|
wiredIconBinding?.drop();
|
||||||
wiredIconBinding = undefined;
|
wiredIconBinding = undefined;
|
||||||
|
|
||||||
if (!networkService.wired) {
|
if (networkService.wired === null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -38,7 +38,7 @@ const handleWirelessIcon = (): void => {
|
|||||||
wirelessIconBinding?.drop();
|
wirelessIconBinding?.drop();
|
||||||
wirelessIconBinding = undefined;
|
wirelessIconBinding = undefined;
|
||||||
|
|
||||||
if (!networkService.wifi) {
|
if (networkService.wifi === null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,8 +5,8 @@ import { bind, Variable } from 'astal';
|
|||||||
import { onPrimaryClick, onSecondaryClick, onMiddleClick, onScroll } from 'src/lib/shared/eventHandlers';
|
import { onPrimaryClick, onSecondaryClick, onMiddleClick, onScroll } from 'src/lib/shared/eventHandlers';
|
||||||
import { Astal, Gtk } from 'astal/gtk3';
|
import { Astal, Gtk } from 'astal/gtk3';
|
||||||
import AstalNetwork from 'gi://AstalNetwork?version=0.1';
|
import AstalNetwork from 'gi://AstalNetwork?version=0.1';
|
||||||
import { BarBoxChild } from 'src/lib/types/bar.js';
|
|
||||||
import { formatWifiInfo, wiredIcon, wirelessIcon } from './helpers';
|
import { formatWifiInfo, wiredIcon, wirelessIcon } from './helpers';
|
||||||
|
import { BarBoxChild } from 'src/lib/types/bar.types';
|
||||||
|
|
||||||
const networkService = AstalNetwork.get_default();
|
const networkService = AstalNetwork.get_default();
|
||||||
const { label, truncation, truncation_size, rightClick, middleClick, scrollDown, scrollUp, showWifiInfo } =
|
const { label, truncation, truncation_size, rightClick, middleClick, scrollDown, scrollUp, showWifiInfo } =
|
||||||
@@ -20,7 +20,9 @@ const Network = (): BarBoxChild => {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
const NetworkIcon = (): JSX.Element => <icon className={'bar-button-icon network-icon'} icon={iconBinding()} />;
|
const NetworkIcon = (): JSX.Element => (
|
||||||
|
<icon className={'bar-button-icon network-icon'} icon={iconBinding()} />
|
||||||
|
);
|
||||||
|
|
||||||
const networkLabel = Variable.derive(
|
const networkLabel = Variable.derive(
|
||||||
[
|
[
|
||||||
@@ -32,14 +34,16 @@ const Network = (): BarBoxChild => {
|
|||||||
|
|
||||||
bind(networkService, 'state'),
|
bind(networkService, 'state'),
|
||||||
bind(networkService, 'connectivity'),
|
bind(networkService, 'connectivity'),
|
||||||
...(networkService.wifi ? [bind(networkService.wifi, 'enabled')] : []),
|
...(networkService.wifi !== null ? [bind(networkService.wifi, 'enabled')] : []),
|
||||||
],
|
],
|
||||||
(primaryNetwork, showLabel, trunc, tSize, showWifiInfo) => {
|
(primaryNetwork, showLabel, trunc, tSize, showWifiInfo) => {
|
||||||
if (!showLabel) {
|
if (!showLabel) {
|
||||||
return <box />;
|
return <box />;
|
||||||
}
|
}
|
||||||
if (primaryNetwork === AstalNetwork.Primary.WIRED) {
|
if (primaryNetwork === AstalNetwork.Primary.WIRED) {
|
||||||
return <label className={'bar-button-label network-label'} label={'Wired'.substring(0, tSize)} />;
|
return (
|
||||||
|
<label className={'bar-button-label network-label'} label={'Wired'.substring(0, tSize)} />
|
||||||
|
);
|
||||||
}
|
}
|
||||||
const networkWifi = networkService.wifi;
|
const networkWifi = networkService.wifi;
|
||||||
if (networkWifi != null) {
|
if (networkWifi != null) {
|
||||||
@@ -54,11 +58,15 @@ const Network = (): BarBoxChild => {
|
|||||||
<label
|
<label
|
||||||
className={'bar-button-label network-label'}
|
className={'bar-button-label network-label'}
|
||||||
label={
|
label={
|
||||||
networkWifi.active_access_point
|
networkWifi.active_access_point !== null
|
||||||
? `${trunc ? networkWifi.ssid.substring(0, tSize) : networkWifi.ssid}`
|
? `${trunc ? networkWifi.ssid.substring(0, tSize) : networkWifi.ssid}`
|
||||||
: '--'
|
: '--'
|
||||||
}
|
}
|
||||||
tooltipText={showWifiInfo && networkWifi.active_access_point ? formatWifiInfo(networkWifi) : ''}
|
tooltipText={
|
||||||
|
showWifiInfo && networkWifi.active_access_point !== null
|
||||||
|
? formatWifiInfo(networkWifi)
|
||||||
|
: ''
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -135,7 +143,9 @@ const Network = (): BarBoxChild => {
|
|||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
disconnectFunctions.push(onScroll(self, throttledHandler, scrollUp.get(), scrollDown.get()));
|
disconnectFunctions.push(
|
||||||
|
onScroll(self, throttledHandler, scrollUp.get(), scrollDown.get()),
|
||||||
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -3,13 +3,14 @@ import { Astal, Gtk } from 'astal/gtk3';
|
|||||||
import { openMenu } from '../../utils/menu';
|
import { openMenu } from '../../utils/menu';
|
||||||
import options from 'src/options';
|
import options from 'src/options';
|
||||||
import { filterNotifications } from 'src/lib/shared/notifications.js';
|
import { filterNotifications } from 'src/lib/shared/notifications.js';
|
||||||
import { BarBoxChild } from 'src/lib/types/bar.js';
|
|
||||||
import { runAsyncCommand, throttledScrollHandler } from 'src/components/bar/utils/helpers.js';
|
import { runAsyncCommand, throttledScrollHandler } from 'src/components/bar/utils/helpers.js';
|
||||||
import { bind, Variable } from 'astal';
|
import { bind, Variable } from 'astal';
|
||||||
import { onMiddleClick, onPrimaryClick, onScroll, onSecondaryClick } from 'src/lib/shared/eventHandlers';
|
import { onMiddleClick, onPrimaryClick, onScroll, onSecondaryClick } from 'src/lib/shared/eventHandlers';
|
||||||
|
import { BarBoxChild } from 'src/lib/types/bar.types';
|
||||||
|
|
||||||
const notifdService = AstalNotifd.get_default();
|
const notifdService = AstalNotifd.get_default();
|
||||||
const { show_total, rightClick, middleClick, scrollUp, scrollDown, hideCountWhenZero } = options.bar.notifications;
|
const { show_total, rightClick, middleClick, scrollUp, scrollDown, hideCountWhenZero } =
|
||||||
|
options.bar.notifications;
|
||||||
const { ignore } = options.notifications;
|
const { ignore } = options.notifications;
|
||||||
|
|
||||||
export const Notifications = (): BarBoxChild => {
|
export const Notifications = (): BarBoxChild => {
|
||||||
@@ -122,7 +123,9 @@ export const Notifications = (): BarBoxChild => {
|
|||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
disconnectFunctions.push(onScroll(self, throttledHandler, scrollUp.get(), scrollDown.get()));
|
disconnectFunctions.push(
|
||||||
|
onScroll(self, throttledHandler, scrollUp.get(), scrollDown.get()),
|
||||||
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import options from 'src/options';
|
import options from 'src/options';
|
||||||
import { Module } from '../../shared/Module';
|
import { Module } from '../../shared/Module';
|
||||||
import { inputHandler } from 'src/components/bar/utils/helpers';
|
import { inputHandler } from 'src/components/bar/utils/helpers';
|
||||||
import { BarBoxChild } from 'src/lib/types/bar';
|
|
||||||
import { bind, Variable } from 'astal';
|
import { bind, Variable } from 'astal';
|
||||||
import { Astal } from 'astal/gtk3';
|
import { Astal } from 'astal/gtk3';
|
||||||
|
import { BarBoxChild } from 'src/lib/types/bar.types';
|
||||||
|
|
||||||
const { icon, leftClick, rightClick, middleClick, scrollUp, scrollDown } = options.bar.customModules.power;
|
const { icon, leftClick, rightClick, middleClick, scrollUp, scrollDown } = options.bar.customModules.power;
|
||||||
|
|
||||||
@@ -11,7 +11,7 @@ export const Power = (): BarBoxChild => {
|
|||||||
const powerModule = Module({
|
const powerModule = Module({
|
||||||
tooltipText: 'Power Menu',
|
tooltipText: 'Power Menu',
|
||||||
textIcon: bind(icon),
|
textIcon: bind(icon),
|
||||||
showLabelBinding: Variable(false),
|
showLabelBinding: bind(Variable(false)),
|
||||||
boxClass: 'powermodule',
|
boxClass: 'powermodule',
|
||||||
props: {
|
props: {
|
||||||
setup: (self: Astal.Button) => {
|
setup: (self: Astal.Button) => {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { divide } from 'src/components/bar/utils/helpers';
|
import { divide } from 'src/components/bar/utils/helpers';
|
||||||
import { GenericResourceData } from 'src/lib/types/customModules/generic';
|
|
||||||
import { GLib, Variable } from 'astal';
|
import { GLib, Variable } from 'astal';
|
||||||
|
import { GenericResourceData } from 'src/lib/types/customModules/generic.types';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculates the RAM usage.
|
* Calculates the RAM usage.
|
||||||
@@ -16,7 +16,7 @@ export const calculateRamUsage = (round: Variable<boolean>): GenericResourceData
|
|||||||
try {
|
try {
|
||||||
const [success, meminfoBytes] = GLib.file_get_contents('/proc/meminfo');
|
const [success, meminfoBytes] = GLib.file_get_contents('/proc/meminfo');
|
||||||
|
|
||||||
if (!success || !meminfoBytes) {
|
if (!success || meminfoBytes === null) {
|
||||||
throw new Error('Failed to read /proc/meminfo or file content is null.');
|
throw new Error('Failed to read /proc/meminfo or file content is null.');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,12 +2,12 @@ import options from 'src/options';
|
|||||||
import { Module } from '../../shared/Module';
|
import { Module } from '../../shared/Module';
|
||||||
import { calculateRamUsage } from './helpers';
|
import { calculateRamUsage } from './helpers';
|
||||||
import { formatTooltip, inputHandler, renderResourceLabel } from 'src/components/bar/utils/helpers';
|
import { formatTooltip, inputHandler, renderResourceLabel } from 'src/components/bar/utils/helpers';
|
||||||
import { LABEL_TYPES } from 'src/lib/types/defaults/bar';
|
import { LABEL_TYPES } from 'src/lib/types/defaults/bar.types';
|
||||||
import { FunctionPoller } from 'src/lib/poller/FunctionPoller';
|
import { FunctionPoller } from 'src/lib/poller/FunctionPoller';
|
||||||
import { GenericResourceData } from 'src/lib/types/customModules/generic';
|
|
||||||
import { bind, Variable } from 'astal';
|
import { bind, Variable } from 'astal';
|
||||||
import { BarBoxChild, ResourceLabelType } from 'src/lib/types/bar';
|
|
||||||
import { Astal } from 'astal/gtk3';
|
import { Astal } from 'astal/gtk3';
|
||||||
|
import { BarBoxChild, ResourceLabelType } from 'src/lib/types/bar.types';
|
||||||
|
import { GenericResourceData } from 'src/lib/types/customModules/generic.types';
|
||||||
|
|
||||||
const { label, labelType, round, leftClick, rightClick, middleClick, pollingInterval, icon } =
|
const { label, labelType, round, leftClick, rightClick, middleClick, pollingInterval, icon } =
|
||||||
options.bar.customModules.ram;
|
options.bar.customModules.ram;
|
||||||
@@ -68,7 +68,8 @@ export const Ram = (): BarBoxChild => {
|
|||||||
fn: () => {
|
fn: () => {
|
||||||
labelType.set(
|
labelType.set(
|
||||||
LABEL_TYPES[
|
LABEL_TYPES[
|
||||||
(LABEL_TYPES.indexOf(labelType.get()) - 1 + LABEL_TYPES.length) % LABEL_TYPES.length
|
(LABEL_TYPES.indexOf(labelType.get()) - 1 + LABEL_TYPES.length) %
|
||||||
|
LABEL_TYPES.length
|
||||||
] as ResourceLabelType,
|
] as ResourceLabelType,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import GTop from 'gi://GTop';
|
|||||||
|
|
||||||
import { divide } from 'src/components/bar/utils/helpers';
|
import { divide } from 'src/components/bar/utils/helpers';
|
||||||
import { Variable } from 'astal';
|
import { Variable } from 'astal';
|
||||||
import { GenericResourceData } from 'src/lib/types/customModules/generic';
|
import { GenericResourceData } from 'src/lib/types/customModules/generic.types';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Computes the storage usage for the root filesystem.
|
* Computes the storage usage for the root filesystem.
|
||||||
|
|||||||
@@ -2,12 +2,12 @@ import options from 'src/options';
|
|||||||
import { Module } from '../../shared/Module';
|
import { Module } from '../../shared/Module';
|
||||||
import { formatTooltip, inputHandler, renderResourceLabel } from 'src/components/bar/utils/helpers';
|
import { formatTooltip, inputHandler, renderResourceLabel } from 'src/components/bar/utils/helpers';
|
||||||
import { computeStorage } from './helpers';
|
import { computeStorage } from './helpers';
|
||||||
import { BarBoxChild, ResourceLabelType } from 'src/lib/types/bar';
|
import { LABEL_TYPES } from 'src/lib/types/defaults/bar.types';
|
||||||
import { GenericResourceData } from 'src/lib/types/customModules/generic';
|
|
||||||
import { LABEL_TYPES } from 'src/lib/types/defaults/bar';
|
|
||||||
import { FunctionPoller } from 'src/lib/poller/FunctionPoller';
|
import { FunctionPoller } from 'src/lib/poller/FunctionPoller';
|
||||||
import { bind, Variable } from 'astal';
|
import { bind, Variable } from 'astal';
|
||||||
import { Astal } from 'astal/gtk3';
|
import { Astal } from 'astal/gtk3';
|
||||||
|
import { BarBoxChild, ResourceLabelType } from 'src/lib/types/bar.types';
|
||||||
|
import { GenericResourceData } from 'src/lib/types/customModules/generic.types';
|
||||||
|
|
||||||
const { label, labelType, icon, round, leftClick, rightClick, middleClick, pollingInterval } =
|
const { label, labelType, icon, round, leftClick, rightClick, middleClick, pollingInterval } =
|
||||||
options.bar.customModules.storage;
|
options.bar.customModules.storage;
|
||||||
@@ -66,7 +66,8 @@ export const Storage = (): BarBoxChild => {
|
|||||||
fn: () => {
|
fn: () => {
|
||||||
labelType.set(
|
labelType.set(
|
||||||
LABEL_TYPES[
|
LABEL_TYPES[
|
||||||
(LABEL_TYPES.indexOf(labelType.get()) - 1 + LABEL_TYPES.length) % LABEL_TYPES.length
|
(LABEL_TYPES.indexOf(labelType.get()) - 1 + LABEL_TYPES.length) %
|
||||||
|
LABEL_TYPES.length
|
||||||
] as ResourceLabelType,
|
] as ResourceLabelType,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
import options from 'src/options';
|
import options from 'src/options';
|
||||||
import { Module } from '../../shared/Module';
|
import { Module } from '../../shared/Module';
|
||||||
import { inputHandler } from 'src/components/bar/utils/helpers';
|
import { inputHandler } from 'src/components/bar/utils/helpers';
|
||||||
import { BarBoxChild } from 'src/lib/types/bar';
|
|
||||||
import { capitalizeFirstLetter } from 'src/lib/utils';
|
import { capitalizeFirstLetter } from 'src/lib/utils';
|
||||||
import { getInitialSubmap, isSubmapEnabled } from './helpers';
|
import { getInitialSubmap, isSubmapEnabled } from './helpers';
|
||||||
import { bind, Variable } from 'astal';
|
import { bind, Variable } from 'astal';
|
||||||
import { Astal } from 'astal/gtk3';
|
import { Astal } from 'astal/gtk3';
|
||||||
import AstalHyprland from 'gi://AstalHyprland?version=0.1';
|
import AstalHyprland from 'gi://AstalHyprland?version=0.1';
|
||||||
|
import { BarBoxChild } from 'src/lib/types/bar.types';
|
||||||
|
|
||||||
const hyprlandService = AstalHyprland.get_default();
|
const hyprlandService = AstalHyprland.get_default();
|
||||||
const {
|
const {
|
||||||
|
|||||||
@@ -2,8 +2,8 @@ import { isMiddleClick, isPrimaryClick, isSecondaryClick, Notify } from '../../.
|
|||||||
import options from '../../../../options';
|
import options from '../../../../options';
|
||||||
import AstalTray from 'gi://AstalTray?version=0.1';
|
import AstalTray from 'gi://AstalTray?version=0.1';
|
||||||
import { bind, Gio, Variable } from 'astal';
|
import { bind, Gio, Variable } from 'astal';
|
||||||
import { BarBoxChild } from 'src/lib/types/bar';
|
|
||||||
import { Gdk, Gtk } from 'astal/gtk3';
|
import { Gdk, Gtk } from 'astal/gtk3';
|
||||||
|
import { BarBoxChild } from 'src/lib/types/bar.types';
|
||||||
|
|
||||||
const systemtray = AstalTray.get_default();
|
const systemtray = AstalTray.get_default();
|
||||||
const { ignore, customIcons } = options.bar.systray;
|
const { ignore, customIcons } = options.bar.systray;
|
||||||
@@ -28,7 +28,13 @@ const MenuCustomIcon = ({ iconLabel, iconColor, item }: MenuCustomIconProps): JS
|
|||||||
};
|
};
|
||||||
|
|
||||||
const MenuDefaultIcon = ({ item }: MenuEntryProps): JSX.Element => {
|
const MenuDefaultIcon = ({ item }: MenuEntryProps): JSX.Element => {
|
||||||
return <icon className={'systray-icon'} gIcon={bind(item, 'gicon')} tooltipMarkup={bind(item, 'tooltipMarkup')} />;
|
return (
|
||||||
|
<icon
|
||||||
|
className={'systray-icon'}
|
||||||
|
gIcon={bind(item, 'gicon')}
|
||||||
|
tooltipMarkup={bind(item, 'tooltipMarkup')}
|
||||||
|
/>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const MenuEntry = ({ item, child }: MenuEntryProps): JSX.Element => {
|
const MenuEntry = ({ item, child }: MenuEntryProps): JSX.Element => {
|
||||||
@@ -37,10 +43,10 @@ const MenuEntry = ({ item, child }: MenuEntryProps): JSX.Element => {
|
|||||||
const entryBinding = Variable.derive(
|
const entryBinding = Variable.derive(
|
||||||
[bind(item, 'menuModel'), bind(item, 'actionGroup')],
|
[bind(item, 'menuModel'), bind(item, 'actionGroup')],
|
||||||
(menuModel, actionGroup) => {
|
(menuModel, actionGroup) => {
|
||||||
if (!menuModel) {
|
if (menuModel === null) {
|
||||||
return console.error(`Menu Model not found for ${item.id}`);
|
return console.error(`Menu Model not found for ${item.id}`);
|
||||||
}
|
}
|
||||||
if (!actionGroup) {
|
if (actionGroup === null) {
|
||||||
return console.error(`Action Group not found for ${item.id}`);
|
return console.error(`Action Group not found for ${item.id}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -85,7 +91,9 @@ const SysTray = (): BarBoxChild => {
|
|||||||
isVis.set(filteredTray.length > 0);
|
isVis.set(filteredTray.length > 0);
|
||||||
|
|
||||||
return filteredTray.map((item) => {
|
return filteredTray.map((item) => {
|
||||||
const matchedCustomIcon = Object.keys(custIcons).find((iconRegex) => item.id.match(iconRegex));
|
const matchedCustomIcon = Object.keys(custIcons).find((iconRegex) =>
|
||||||
|
item.id.match(iconRegex),
|
||||||
|
);
|
||||||
|
|
||||||
if (matchedCustomIcon !== undefined) {
|
if (matchedCustomIcon !== undefined) {
|
||||||
const iconLabel = custIcons[matchedCustomIcon].icon || '';
|
const iconLabel = custIcons[matchedCustomIcon].icon || '';
|
||||||
@@ -122,7 +130,7 @@ const SysTray = (): BarBoxChild => {
|
|||||||
component,
|
component,
|
||||||
isVisible: true,
|
isVisible: true,
|
||||||
boxClass: 'systray',
|
boxClass: 'systray',
|
||||||
isVis,
|
isVis: bind(isVis),
|
||||||
isBox: true,
|
isBox: true,
|
||||||
props: {},
|
props: {},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
import options from 'src/options';
|
import options from 'src/options';
|
||||||
import { Module } from '../../shared/Module';
|
import { Module } from '../../shared/Module';
|
||||||
import { inputHandler } from 'src/components/bar/utils/helpers';
|
import { inputHandler } from 'src/components/bar/utils/helpers';
|
||||||
import { BarBoxChild } from 'src/lib/types/bar';
|
|
||||||
import { BashPoller } from 'src/lib/poller/BashPoller';
|
import { BashPoller } from 'src/lib/poller/BashPoller';
|
||||||
import { bind, Variable } from 'astal';
|
import { bind, Variable } from 'astal';
|
||||||
import { Astal } from 'astal/gtk3';
|
import { Astal } from 'astal/gtk3';
|
||||||
|
import { BarBoxChild } from 'src/lib/types/bar.types';
|
||||||
|
|
||||||
const {
|
const {
|
||||||
updateCommand,
|
updateCommand,
|
||||||
@@ -75,7 +75,7 @@ export const Updates = (): BarBoxChild => {
|
|||||||
textIcon: updatesIcon(),
|
textIcon: updatesIcon(),
|
||||||
tooltipText: bind(pendingUpdatesTooltip),
|
tooltipText: bind(pendingUpdatesTooltip),
|
||||||
boxClass: 'updates',
|
boxClass: 'updates',
|
||||||
isVis: isVis,
|
isVis: bind(isVis),
|
||||||
label: bind(pendingUpdates),
|
label: bind(pendingUpdates),
|
||||||
showLabelBinding: bind(label),
|
showLabelBinding: bind(label),
|
||||||
props: {
|
props: {
|
||||||
|
|||||||
@@ -1,6 +1,4 @@
|
|||||||
import { VolumeIcons } from 'src/lib/types/volume';
|
const icons: Record<number, string> = {
|
||||||
|
|
||||||
const icons: VolumeIcons = {
|
|
||||||
101: '',
|
101: '',
|
||||||
66: '',
|
66: '',
|
||||||
34: '',
|
34: '',
|
||||||
|
|||||||
@@ -4,9 +4,9 @@ import { runAsyncCommand, throttledScrollHandler } from 'src/components/bar/util
|
|||||||
import { bind, Variable } from 'astal';
|
import { bind, Variable } from 'astal';
|
||||||
import { onMiddleClick, onPrimaryClick, onScroll, onSecondaryClick } from 'src/lib/shared/eventHandlers.js';
|
import { onMiddleClick, onPrimaryClick, onScroll, onSecondaryClick } from 'src/lib/shared/eventHandlers.js';
|
||||||
import { getIcon } from './helpers/index.js';
|
import { getIcon } from './helpers/index.js';
|
||||||
import { BarBoxChild } from 'src/lib/types/bar.js';
|
|
||||||
import { Astal } from 'astal/gtk3';
|
import { Astal } from 'astal/gtk3';
|
||||||
import AstalWp from 'gi://AstalWp?version=0.1';
|
import AstalWp from 'gi://AstalWp?version=0.1';
|
||||||
|
import { BarBoxChild } from 'src/lib/types/bar.types.js';
|
||||||
|
|
||||||
const wireplumber = AstalWp.get_default() as AstalWp.Wp;
|
const wireplumber = AstalWp.get_default() as AstalWp.Wp;
|
||||||
const audioService = wireplumber?.audio;
|
const audioService = wireplumber?.audio;
|
||||||
@@ -118,7 +118,9 @@ const Volume = (): BarBoxChild => {
|
|||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
disconnectFunctions.push(onScroll(self, throttledHandler, scrollUp.get(), scrollDown.get()));
|
disconnectFunctions.push(
|
||||||
|
onScroll(self, throttledHandler, scrollUp.get(), scrollDown.get()),
|
||||||
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,12 +1,13 @@
|
|||||||
import options from 'src/options';
|
import options from 'src/options';
|
||||||
import { Module } from '../../shared/Module';
|
import { Module } from '../../shared/Module';
|
||||||
import { inputHandler } from 'src/components/bar/utils/helpers';
|
import { inputHandler } from 'src/components/bar/utils/helpers';
|
||||||
import { getWeatherStatusTextIcon, globalWeatherVar } from 'src/globals/weather';
|
import { getWeatherStatusTextIcon, globalWeatherVar } from 'src/shared/weather';
|
||||||
import { BarBoxChild } from 'src/lib/types/bar';
|
|
||||||
import { bind, Variable } from 'astal';
|
import { bind, Variable } from 'astal';
|
||||||
import { Astal } from 'astal/gtk3';
|
import { Astal } from 'astal/gtk3';
|
||||||
|
import { BarBoxChild } from 'src/lib/types/bar.types';
|
||||||
|
|
||||||
const { label, unit, leftClick, rightClick, middleClick, scrollUp, scrollDown } = options.bar.customModules.weather;
|
const { label, unit, leftClick, rightClick, middleClick, scrollUp, scrollDown } =
|
||||||
|
options.bar.customModules.weather;
|
||||||
|
|
||||||
export const Weather = (): BarBoxChild => {
|
export const Weather = (): BarBoxChild => {
|
||||||
const iconBinding = Variable.derive([bind(globalWeatherVar)], (wthr) => {
|
const iconBinding = Variable.derive([bind(globalWeatherVar)], (wthr) => {
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ function trackClientUpdates(client: AstalHyprland.Client): void {
|
|||||||
clientBinding?.drop();
|
clientBinding?.drop();
|
||||||
clientBinding = undefined;
|
clientBinding = undefined;
|
||||||
|
|
||||||
if (!client) {
|
if (client === null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -68,7 +68,11 @@ export const getWindowMatch = (hyprlandClient: AstalHyprland.Client): Record<str
|
|||||||
*
|
*
|
||||||
* @returns The title of the window as a string.
|
* @returns The title of the window as a string.
|
||||||
*/
|
*/
|
||||||
export const getTitle = (client: AstalHyprland.Client, useCustomTitle: boolean, useClassName: boolean): string => {
|
export const getTitle = (
|
||||||
|
client: AstalHyprland.Client,
|
||||||
|
useCustomTitle: boolean,
|
||||||
|
useClassName: boolean,
|
||||||
|
): string => {
|
||||||
if (client === null || useCustomTitle) return getWindowMatch(client).label;
|
if (client === null || useCustomTitle) return getWindowMatch(client).label;
|
||||||
|
|
||||||
const title = client.title;
|
const title = client.title;
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
import { runAsyncCommand, throttledScrollHandler } from 'src/components/bar/utils/helpers';
|
import { runAsyncCommand, throttledScrollHandler } from 'src/components/bar/utils/helpers';
|
||||||
import { BarBoxChild } from 'src/lib/types/bar';
|
|
||||||
import options from 'src/options';
|
import options from 'src/options';
|
||||||
import AstalHyprland from 'gi://AstalHyprland?version=0.1';
|
import AstalHyprland from 'gi://AstalHyprland?version=0.1';
|
||||||
import { onMiddleClick, onPrimaryClick, onScroll, onSecondaryClick } from 'src/lib/shared/eventHandlers';
|
import { onMiddleClick, onPrimaryClick, onScroll, onSecondaryClick } from 'src/lib/shared/eventHandlers';
|
||||||
import { bind, Variable } from 'astal';
|
import { bind, Variable } from 'astal';
|
||||||
import { clientTitle, getTitle, getWindowMatch, truncateTitle } from './helpers/title';
|
import { clientTitle, getTitle, getWindowMatch, truncateTitle } from './helpers/title';
|
||||||
import { Astal } from 'astal/gtk3';
|
import { Astal } from 'astal/gtk3';
|
||||||
|
import { BarBoxChild } from 'src/lib/types/bar.types';
|
||||||
|
|
||||||
const hyprlandService = AstalHyprland.get_default();
|
const hyprlandService = AstalHyprland.get_default();
|
||||||
const { leftClick, rightClick, middleClick, scrollDown, scrollUp } = options.bar.windowtitle;
|
const { leftClick, rightClick, middleClick, scrollDown, scrollUp } = options.bar.windowtitle;
|
||||||
@@ -14,7 +14,12 @@ const ClientTitle = (): BarBoxChild => {
|
|||||||
const { custom_title, class_name, label, icon, truncation, truncation_size } = options.bar.windowtitle;
|
const { custom_title, class_name, label, icon, truncation, truncation_size } = options.bar.windowtitle;
|
||||||
|
|
||||||
const ClientIcon = ({ client }: ClientIconProps): JSX.Element => {
|
const ClientIcon = ({ client }: ClientIconProps): JSX.Element => {
|
||||||
return <label className={'bar-button-icon windowtitle txt-icon bar'} label={getWindowMatch(client).icon} />;
|
return (
|
||||||
|
<label
|
||||||
|
className={'bar-button-icon windowtitle txt-icon bar'}
|
||||||
|
label={getWindowMatch(client).icon}
|
||||||
|
/>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const ClientLabel = ({
|
const ClientLabel = ({
|
||||||
@@ -28,7 +33,10 @@ const ClientTitle = (): BarBoxChild => {
|
|||||||
return (
|
return (
|
||||||
<label
|
<label
|
||||||
className={`bar-button-label windowtitle ${showIcon ? '' : 'no-icon'}`}
|
className={`bar-button-label windowtitle ${showIcon ? '' : 'no-icon'}`}
|
||||||
label={truncateTitle(getTitle(client, useCustomTitle, useClassName), truncate ? truncationSize : -1)}
|
label={truncateTitle(
|
||||||
|
getTitle(client, useCustomTitle, useClassName),
|
||||||
|
truncate ? truncationSize : -1,
|
||||||
|
)}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@@ -131,7 +139,9 @@ const ClientTitle = (): BarBoxChild => {
|
|||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
disconnectFunctions.push(onScroll(self, throttledHandler, scrollUp.get(), scrollDown.get()));
|
disconnectFunctions.push(
|
||||||
|
onScroll(self, throttledHandler, scrollUp.get(), scrollDown.get()),
|
||||||
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { Variable } from 'astal';
|
import { Variable } from 'astal';
|
||||||
import AstalHyprland from 'gi://AstalHyprland?version=0.1';
|
import AstalHyprland from 'gi://AstalHyprland?version=0.1';
|
||||||
import { MonitorMap, WorkspaceMonitorMap, WorkspaceRule } from 'src/lib/types/workspace';
|
import { MonitorMap, WorkspaceMonitorMap, WorkspaceRule } from 'src/lib/types/workspace.types';
|
||||||
import { range } from 'src/lib/utils';
|
import { range } from 'src/lib/utils';
|
||||||
import options from 'src/options';
|
import options from 'src/options';
|
||||||
|
|
||||||
@@ -172,7 +172,7 @@ function isWorkspaceIgnored(ignoredWorkspacesVariable: Variable<string>, workspa
|
|||||||
* @param ignoredWorkspacesVariable - A Variable that contains the ignored workspaces pattern.
|
* @param ignoredWorkspacesVariable - A Variable that contains the ignored workspaces pattern.
|
||||||
*/
|
*/
|
||||||
function navigateWorkspace(direction: 'next' | 'prev', ignoredWorkspacesVariable: Variable<string>): void {
|
function navigateWorkspace(direction: 'next' | 'prev', ignoredWorkspacesVariable: Variable<string>): void {
|
||||||
const allHyprlandWorkspaces = hyprlandService.get_workspaces() || [];
|
const allHyprlandWorkspaces = hyprlandService.get_workspaces() ?? [];
|
||||||
|
|
||||||
const activeWorkspaceIds = allHyprlandWorkspaces
|
const activeWorkspaceIds = allHyprlandWorkspaces
|
||||||
.filter((workspaceInstance) => hyprlandService.focusedMonitor.id === workspaceInstance.monitor?.id)
|
.filter((workspaceInstance) => hyprlandService.focusedMonitor.id === workspaceInstance.monitor?.id)
|
||||||
@@ -187,7 +187,8 @@ function navigateWorkspace(direction: 'next' | 'prev', ignoredWorkspacesVariable
|
|||||||
const workspaceIndex = assignedOrOccupiedWorkspaces.indexOf(hyprlandService.focusedWorkspace?.id);
|
const workspaceIndex = assignedOrOccupiedWorkspaces.indexOf(hyprlandService.focusedWorkspace?.id);
|
||||||
const step = direction === 'next' ? 1 : -1;
|
const step = direction === 'next' ? 1 : -1;
|
||||||
|
|
||||||
let newIndex = (workspaceIndex + step + assignedOrOccupiedWorkspaces.length) % assignedOrOccupiedWorkspaces.length;
|
let newIndex =
|
||||||
|
(workspaceIndex + step + assignedOrOccupiedWorkspaces.length) % assignedOrOccupiedWorkspaces.length;
|
||||||
let attempts = 0;
|
let attempts = 0;
|
||||||
|
|
||||||
while (attempts < assignedOrOccupiedWorkspaces.length) {
|
while (attempts < assignedOrOccupiedWorkspaces.length) {
|
||||||
@@ -196,7 +197,8 @@ function navigateWorkspace(direction: 'next' | 'prev', ignoredWorkspacesVariable
|
|||||||
hyprlandService.dispatch('workspace', targetWorkspaceNumber.toString());
|
hyprlandService.dispatch('workspace', targetWorkspaceNumber.toString());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
newIndex = (newIndex + step + assignedOrOccupiedWorkspaces.length) % assignedOrOccupiedWorkspaces.length;
|
newIndex =
|
||||||
|
(newIndex + step + assignedOrOccupiedWorkspaces.length) % assignedOrOccupiedWorkspaces.length;
|
||||||
attempts++;
|
attempts++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -321,7 +323,9 @@ export function getWorkspacesToRender(
|
|||||||
);
|
);
|
||||||
|
|
||||||
const activeWorkspacesForCurrentMonitor = activeWorkspaceIds.filter((workspaceId) => {
|
const activeWorkspacesForCurrentMonitor = activeWorkspaceIds.filter((workspaceId) => {
|
||||||
const metadataForWorkspace = allWorkspaceInstances.find((workspaceObj) => workspaceObj.id === workspaceId);
|
const metadataForWorkspace = allWorkspaceInstances.find(
|
||||||
|
(workspaceObj) => workspaceObj.id === workspaceId,
|
||||||
|
);
|
||||||
|
|
||||||
if (metadataForWorkspace) {
|
if (metadataForWorkspace) {
|
||||||
return metadataForWorkspace?.monitor?.id === monitorId;
|
return metadataForWorkspace?.monitor?.id === monitorId;
|
||||||
@@ -334,6 +338,8 @@ export function getWorkspacesToRender(
|
|||||||
) {
|
) {
|
||||||
return workspaceMonitorRules[currentMonitorInstance.name].includes(workspaceId);
|
return workspaceMonitorRules[currentMonitorInstance.name].includes(workspaceId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
});
|
});
|
||||||
|
|
||||||
if (isMonitorSpecific) {
|
if (isMonitorSpecific) {
|
||||||
@@ -347,12 +353,16 @@ export function getWorkspacesToRender(
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
allPotentialWorkspaces = [...new Set([...activeWorkspacesForCurrentMonitor, ...validWorkspaceNumbers])];
|
allPotentialWorkspaces = [
|
||||||
|
...new Set([...activeWorkspacesForCurrentMonitor, ...validWorkspaceNumbers]),
|
||||||
|
];
|
||||||
} else {
|
} else {
|
||||||
allPotentialWorkspaces = [...new Set([...allPotentialWorkspaces, ...activeWorkspaceIds])];
|
allPotentialWorkspaces = [...new Set([...allPotentialWorkspaces, ...activeWorkspaceIds])];
|
||||||
}
|
}
|
||||||
|
|
||||||
return allPotentialWorkspaces.filter((workspace) => !isWorkspaceIgnored(ignored, workspace)).sort((a, b) => a - b);
|
return allPotentialWorkspaces
|
||||||
|
.filter((workspace) => !isWorkspaceIgnored(ignored, workspace))
|
||||||
|
.sort((a, b) => a - b);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import AstalHyprland from 'gi://AstalHyprland?version=0.1';
|
import AstalHyprland from 'gi://AstalHyprland?version=0.1';
|
||||||
import { defaultApplicationIconMap } from 'src/lib/constants/appIcons';
|
import { defaultApplicationIconMap } from 'src/lib/constants/appIcons';
|
||||||
import { AppIconOptions, WorkspaceIconMap } from 'src/lib/types/workspace';
|
import { WorkspaceIconMap, AppIconOptions } from 'src/lib/types/workspace.types';
|
||||||
import { isValidGjsColor } from 'src/lib/utils';
|
import { isValidGjsColor } from 'src/lib/utils';
|
||||||
import options from 'src/options';
|
import options from 'src/options';
|
||||||
|
|
||||||
@@ -40,7 +40,7 @@ const getWsIcon = (wsIconMap: WorkspaceIconMap, i: number): string => {
|
|||||||
const iconEntry = wsIconMap[i];
|
const iconEntry = wsIconMap[i];
|
||||||
const defaultIcon = `${i}`;
|
const defaultIcon = `${i}`;
|
||||||
|
|
||||||
if (!iconEntry) {
|
if (iconEntry === undefined) {
|
||||||
return defaultIcon;
|
return defaultIcon;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -77,8 +77,10 @@ export const getWsColor = (
|
|||||||
monitor: number,
|
monitor: number,
|
||||||
): string => {
|
): string => {
|
||||||
const iconEntry = wsIconMap[i];
|
const iconEntry = wsIconMap[i];
|
||||||
const hasColor = typeof iconEntry === 'object' && 'color' in iconEntry && isValidGjsColor(iconEntry.color);
|
const hasColor =
|
||||||
if (!iconEntry) {
|
typeof iconEntry === 'object' && 'color' in iconEntry && isValidGjsColor(iconEntry.color);
|
||||||
|
|
||||||
|
if (iconEntry === undefined) {
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -150,7 +152,7 @@ export const getAppIcon = (
|
|||||||
let icons = workspaceClients.reduce((iconAccumulator, [clientClass, clientTitle]) => {
|
let icons = workspaceClients.reduce((iconAccumulator, [clientClass, clientTitle]) => {
|
||||||
const icon = findIconForClient(clientClass, clientTitle);
|
const icon = findIconForClient(clientClass, clientTitle);
|
||||||
|
|
||||||
if (icon) {
|
if (icon !== undefined) {
|
||||||
iconAccumulator.push(icon);
|
iconAccumulator.push(icon);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -193,7 +195,8 @@ export const renderClassnames = (
|
|||||||
monitor: number,
|
monitor: number,
|
||||||
i: number,
|
i: number,
|
||||||
): string => {
|
): string => {
|
||||||
const isWorkspaceActive = hyprlandService.focusedWorkspace?.id === i || isWorkspaceActiveOnMonitor(monitor, i);
|
const isWorkspaceActive =
|
||||||
|
hyprlandService.focusedWorkspace?.id === i || isWorkspaceActiveOnMonitor(monitor, i);
|
||||||
const isActive = isWorkspaceActive ? 'active' : '';
|
const isActive = isWorkspaceActive ? 'active' : '';
|
||||||
|
|
||||||
if (showIcons) {
|
if (showIcons) {
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
import options from 'src/options';
|
import options from 'src/options';
|
||||||
import { initThrottledScrollHandlers } from './helpers';
|
import { initThrottledScrollHandlers } from './helpers';
|
||||||
import { BarBoxChild } from 'src/lib/types/bar';
|
|
||||||
import { WorkspaceModule } from './workspaces';
|
import { WorkspaceModule } from './workspaces';
|
||||||
import { bind, Variable } from 'astal';
|
import { bind, Variable } from 'astal';
|
||||||
import { GtkWidget } from 'src/lib/types/widget';
|
|
||||||
import { Astal, Gdk } from 'astal/gtk3';
|
import { Astal, Gdk } from 'astal/gtk3';
|
||||||
import { isScrollDown, isScrollUp } from 'src/lib/utils';
|
import { isScrollDown, isScrollUp } from 'src/lib/utils';
|
||||||
|
import { BarBoxChild } from 'src/lib/types/bar.types';
|
||||||
|
import { GtkWidget } from 'src/lib/types/widget.types';
|
||||||
|
|
||||||
const { scroll_speed } = options.bar.workspaces;
|
const { scroll_speed } = options.bar.workspaces;
|
||||||
|
|
||||||
@@ -29,7 +29,8 @@ const Workspaces = (monitor = -1): BarBoxChild => {
|
|||||||
self.disconnect(scrollHandlers);
|
self.disconnect(scrollHandlers);
|
||||||
}
|
}
|
||||||
|
|
||||||
const { throttledScrollUp, throttledScrollDown } = initThrottledScrollHandlers(scroll_speed);
|
const { throttledScrollUp, throttledScrollDown } =
|
||||||
|
initThrottledScrollHandlers(scroll_speed);
|
||||||
|
|
||||||
scrollHandlers = self.connect('scroll-event', (_: GtkWidget, event: Gdk.Event) => {
|
scrollHandlers = self.connect('scroll-event', (_: GtkWidget, event: Gdk.Event) => {
|
||||||
if (isScrollUp(event)) {
|
if (isScrollUp(event)) {
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
import options from 'src/options';
|
import options from 'src/options';
|
||||||
import { forceUpdater, getWorkspacesToRender, initWorkspaceEvents, workspaceRules } from './helpers';
|
import { forceUpdater, getWorkspacesToRender, initWorkspaceEvents, workspaceRules } from './helpers';
|
||||||
import { getAppIcon, getWsColor, renderClassnames, renderLabel } from './helpers/utils';
|
import { getAppIcon, getWsColor, renderClassnames, renderLabel } from './helpers/utils';
|
||||||
import { ApplicationIcons, WorkspaceIconMap } from 'src/lib/types/workspace';
|
|
||||||
import { bind, Variable } from 'astal';
|
import { bind, Variable } from 'astal';
|
||||||
import AstalHyprland from 'gi://AstalHyprland?version=0.1';
|
import AstalHyprland from 'gi://AstalHyprland?version=0.1';
|
||||||
import { Gtk } from 'astal/gtk3';
|
import { Gtk } from 'astal/gtk3';
|
||||||
import { isPrimaryClick } from 'src/lib/utils';
|
import { isPrimaryClick } from 'src/lib/utils';
|
||||||
|
import { WorkspaceIconMap, ApplicationIcons } from 'src/lib/types/workspace.types';
|
||||||
|
|
||||||
const hyprlandService = AstalHyprland.get_default();
|
const hyprlandService = AstalHyprland.get_default();
|
||||||
const {
|
const {
|
||||||
@@ -145,7 +145,9 @@ export const WorkspaceModule = ({ monitor }: WorkspaceModuleProps): JSX.Element
|
|||||||
monitor,
|
monitor,
|
||||||
)}
|
)}
|
||||||
setup={(self) => {
|
setup={(self) => {
|
||||||
const currentWsClients = clients.filter((client) => client?.workspace?.id === wsId);
|
const currentWsClients = clients.filter(
|
||||||
|
(client) => client?.workspace?.id === wsId,
|
||||||
|
);
|
||||||
self.toggleClassName('occupied', currentWsClients.length > 0);
|
self.toggleClassName('occupied', currentWsClients.length > 0);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
import options from 'src/options';
|
import options from 'src/options';
|
||||||
import { BarBoxChild } from 'src/lib/types/bar.js';
|
|
||||||
import { inputHandler } from 'src/components/bar/utils/helpers.js';
|
import { inputHandler } from 'src/components/bar/utils/helpers.js';
|
||||||
import { bind, Variable } from 'astal';
|
import { bind, Variable } from 'astal';
|
||||||
import { Astal } from 'astal/gtk3';
|
import { Astal } from 'astal/gtk3';
|
||||||
import { systemTime } from 'src/globals/time';
|
import { systemTime } from 'src/shared/time';
|
||||||
import { GLib } from 'astal';
|
import { GLib } from 'astal';
|
||||||
import { Module } from '../../shared/Module';
|
import { Module } from '../../shared/Module';
|
||||||
|
import { BarBoxChild } from 'src/lib/types/bar.types';
|
||||||
|
|
||||||
const {
|
const {
|
||||||
format,
|
format,
|
||||||
|
|||||||
@@ -24,18 +24,50 @@ export const CustomModuleSettings = (): JSX.Element => {
|
|||||||
type="boolean"
|
type="boolean"
|
||||||
/>
|
/>
|
||||||
<Option opt={options.bar.customModules.microphone.label} title="Show Label" type="boolean" />
|
<Option opt={options.bar.customModules.microphone.label} title="Show Label" type="boolean" />
|
||||||
<Option opt={options.bar.customModules.microphone.mutedIcon} title="Muted Icon" type="string" />
|
<Option
|
||||||
<Option opt={options.bar.customModules.microphone.unmutedIcon} title="Unmuted Icon" type="string" />
|
opt={options.bar.customModules.microphone.mutedIcon}
|
||||||
<Option opt={options.theme.bar.buttons.modules.microphone.spacing} title="Spacing" type="string" />
|
title="Muted Icon"
|
||||||
<Option opt={options.bar.customModules.microphone.leftClick} title="Left Click" type="string" />
|
type="string"
|
||||||
<Option opt={options.bar.customModules.microphone.rightClick} title="Right Click" type="string" />
|
/>
|
||||||
<Option opt={options.bar.customModules.microphone.middleClick} title="Middle Click" type="string" />
|
<Option
|
||||||
|
opt={options.bar.customModules.microphone.unmutedIcon}
|
||||||
|
title="Unmuted Icon"
|
||||||
|
type="string"
|
||||||
|
/>
|
||||||
|
<Option
|
||||||
|
opt={options.theme.bar.buttons.modules.microphone.spacing}
|
||||||
|
title="Spacing"
|
||||||
|
type="string"
|
||||||
|
/>
|
||||||
|
<Option
|
||||||
|
opt={options.bar.customModules.microphone.leftClick}
|
||||||
|
title="Left Click"
|
||||||
|
type="string"
|
||||||
|
/>
|
||||||
|
<Option
|
||||||
|
opt={options.bar.customModules.microphone.rightClick}
|
||||||
|
title="Right Click"
|
||||||
|
type="string"
|
||||||
|
/>
|
||||||
|
<Option
|
||||||
|
opt={options.bar.customModules.microphone.middleClick}
|
||||||
|
title="Middle Click"
|
||||||
|
type="string"
|
||||||
|
/>
|
||||||
<Option opt={options.bar.customModules.microphone.scrollUp} title="Scroll Up" type="string" />
|
<Option opt={options.bar.customModules.microphone.scrollUp} title="Scroll Up" type="string" />
|
||||||
<Option opt={options.bar.customModules.microphone.scrollDown} title="Scroll Down" type="string" />
|
<Option
|
||||||
|
opt={options.bar.customModules.microphone.scrollDown}
|
||||||
|
title="Scroll Down"
|
||||||
|
type="string"
|
||||||
|
/>
|
||||||
|
|
||||||
{/* RAM Section */}
|
{/* RAM Section */}
|
||||||
<Header title="RAM" />
|
<Header title="RAM" />
|
||||||
<Option opt={options.theme.bar.buttons.modules.ram.enableBorder} title="Button Border" type="boolean" />
|
<Option
|
||||||
|
opt={options.theme.bar.buttons.modules.ram.enableBorder}
|
||||||
|
title="Button Border"
|
||||||
|
type="boolean"
|
||||||
|
/>
|
||||||
<Option opt={options.bar.customModules.ram.icon} title="Ram Icon" type="string" />
|
<Option opt={options.bar.customModules.ram.icon} title="Ram Icon" type="string" />
|
||||||
<Option opt={options.bar.customModules.ram.label} title="Show Label" type="boolean" />
|
<Option opt={options.bar.customModules.ram.label} title="Show Label" type="boolean" />
|
||||||
<Option opt={options.theme.bar.buttons.modules.ram.spacing} title="Spacing" type="string" />
|
<Option opt={options.theme.bar.buttons.modules.ram.spacing} title="Spacing" type="string" />
|
||||||
@@ -60,7 +92,11 @@ export const CustomModuleSettings = (): JSX.Element => {
|
|||||||
|
|
||||||
{/* CPU Section */}
|
{/* CPU Section */}
|
||||||
<Header title="CPU" />
|
<Header title="CPU" />
|
||||||
<Option opt={options.theme.bar.buttons.modules.cpu.enableBorder} title="Button Border" type="boolean" />
|
<Option
|
||||||
|
opt={options.theme.bar.buttons.modules.cpu.enableBorder}
|
||||||
|
title="Button Border"
|
||||||
|
type="boolean"
|
||||||
|
/>
|
||||||
<Option opt={options.bar.customModules.cpu.icon} title="Cpu Icon" type="string" />
|
<Option opt={options.bar.customModules.cpu.icon} title="Cpu Icon" type="string" />
|
||||||
<Option opt={options.bar.customModules.cpu.label} title="Show Label" type="boolean" />
|
<Option opt={options.bar.customModules.cpu.label} title="Show Label" type="boolean" />
|
||||||
<Option opt={options.theme.bar.buttons.modules.cpu.spacing} title="Spacing" type="string" />
|
<Option opt={options.theme.bar.buttons.modules.cpu.spacing} title="Spacing" type="string" />
|
||||||
@@ -100,9 +136,17 @@ export const CustomModuleSettings = (): JSX.Element => {
|
|||||||
enums={['imperial', 'metric']}
|
enums={['imperial', 'metric']}
|
||||||
/>
|
/>
|
||||||
<Option opt={options.bar.customModules.cpuTemp.showUnit} title="Show Unit" type="boolean" />
|
<Option opt={options.bar.customModules.cpuTemp.showUnit} title="Show Unit" type="boolean" />
|
||||||
<Option opt={options.bar.customModules.cpuTemp.icon} title="Cpu Temperature Icon" type="string" />
|
<Option
|
||||||
|
opt={options.bar.customModules.cpuTemp.icon}
|
||||||
|
title="Cpu Temperature Icon"
|
||||||
|
type="string"
|
||||||
|
/>
|
||||||
<Option opt={options.bar.customModules.cpuTemp.label} title="Show Label" type="boolean" />
|
<Option opt={options.bar.customModules.cpuTemp.label} title="Show Label" type="boolean" />
|
||||||
<Option opt={options.theme.bar.buttons.modules.cpuTemp.spacing} title="Spacing" type="string" />
|
<Option
|
||||||
|
opt={options.theme.bar.buttons.modules.cpuTemp.spacing}
|
||||||
|
title="Spacing"
|
||||||
|
type="string"
|
||||||
|
/>
|
||||||
<Option opt={options.bar.customModules.cpuTemp.round} title="Round" type="boolean" />
|
<Option opt={options.bar.customModules.cpuTemp.round} title="Round" type="boolean" />
|
||||||
<Option
|
<Option
|
||||||
opt={options.bar.customModules.cpuTemp.pollingInterval}
|
opt={options.bar.customModules.cpuTemp.pollingInterval}
|
||||||
@@ -113,10 +157,22 @@ export const CustomModuleSettings = (): JSX.Element => {
|
|||||||
increment={1000}
|
increment={1000}
|
||||||
/>
|
/>
|
||||||
<Option opt={options.bar.customModules.cpuTemp.leftClick} title="Left Click" type="string" />
|
<Option opt={options.bar.customModules.cpuTemp.leftClick} title="Left Click" type="string" />
|
||||||
<Option opt={options.bar.customModules.cpuTemp.rightClick} title="Right Click" type="string" />
|
<Option
|
||||||
<Option opt={options.bar.customModules.cpuTemp.middleClick} title="Middle Click" type="string" />
|
opt={options.bar.customModules.cpuTemp.rightClick}
|
||||||
|
title="Right Click"
|
||||||
|
type="string"
|
||||||
|
/>
|
||||||
|
<Option
|
||||||
|
opt={options.bar.customModules.cpuTemp.middleClick}
|
||||||
|
title="Middle Click"
|
||||||
|
type="string"
|
||||||
|
/>
|
||||||
<Option opt={options.bar.customModules.cpuTemp.scrollUp} title="Scroll Up" type="string" />
|
<Option opt={options.bar.customModules.cpuTemp.scrollUp} title="Scroll Up" type="string" />
|
||||||
<Option opt={options.bar.customModules.cpuTemp.scrollDown} title="Scroll Down" type="string" />
|
<Option
|
||||||
|
opt={options.bar.customModules.cpuTemp.scrollDown}
|
||||||
|
title="Scroll Down"
|
||||||
|
type="string"
|
||||||
|
/>
|
||||||
|
|
||||||
{/* Storage Section */}
|
{/* Storage Section */}
|
||||||
<Header title="Storage" />
|
<Header title="Storage" />
|
||||||
@@ -127,7 +183,11 @@ export const CustomModuleSettings = (): JSX.Element => {
|
|||||||
/>
|
/>
|
||||||
<Option opt={options.bar.customModules.storage.icon} title="Storage Icon" type="string" />
|
<Option opt={options.bar.customModules.storage.icon} title="Storage Icon" type="string" />
|
||||||
<Option opt={options.bar.customModules.storage.label} title="Show Label" type="boolean" />
|
<Option opt={options.bar.customModules.storage.label} title="Show Label" type="boolean" />
|
||||||
<Option opt={options.theme.bar.buttons.modules.storage.spacing} title="Spacing" type="string" />
|
<Option
|
||||||
|
opt={options.theme.bar.buttons.modules.storage.spacing}
|
||||||
|
title="Spacing"
|
||||||
|
type="string"
|
||||||
|
/>
|
||||||
<Option
|
<Option
|
||||||
opt={options.bar.customModules.storage.labelType}
|
opt={options.bar.customModules.storage.labelType}
|
||||||
title="Label Type"
|
title="Label Type"
|
||||||
@@ -144,8 +204,16 @@ export const CustomModuleSettings = (): JSX.Element => {
|
|||||||
increment={1000}
|
increment={1000}
|
||||||
/>
|
/>
|
||||||
<Option opt={options.bar.customModules.storage.leftClick} title="Left Click" type="string" />
|
<Option opt={options.bar.customModules.storage.leftClick} title="Left Click" type="string" />
|
||||||
<Option opt={options.bar.customModules.storage.rightClick} title="Right Click" type="string" />
|
<Option
|
||||||
<Option opt={options.bar.customModules.storage.middleClick} title="Middle Click" type="string" />
|
opt={options.bar.customModules.storage.rightClick}
|
||||||
|
title="Right Click"
|
||||||
|
type="string"
|
||||||
|
/>
|
||||||
|
<Option
|
||||||
|
opt={options.bar.customModules.storage.middleClick}
|
||||||
|
title="Middle Click"
|
||||||
|
type="string"
|
||||||
|
/>
|
||||||
|
|
||||||
{/* Netstat Section */}
|
{/* Netstat Section */}
|
||||||
<Header title="Netstat" />
|
<Header title="Netstat" />
|
||||||
@@ -171,7 +239,11 @@ export const CustomModuleSettings = (): JSX.Element => {
|
|||||||
/>
|
/>
|
||||||
<Option opt={options.bar.customModules.netstat.icon} title="Netstat Icon" type="string" />
|
<Option opt={options.bar.customModules.netstat.icon} title="Netstat Icon" type="string" />
|
||||||
<Option opt={options.bar.customModules.netstat.label} title="Show Label" type="boolean" />
|
<Option opt={options.bar.customModules.netstat.label} title="Show Label" type="boolean" />
|
||||||
<Option opt={options.bar.customModules.netstat.networkInLabel} title="Network In Label" type="string" />
|
<Option
|
||||||
|
opt={options.bar.customModules.netstat.networkInLabel}
|
||||||
|
title="Network In Label"
|
||||||
|
type="string"
|
||||||
|
/>
|
||||||
<Option
|
<Option
|
||||||
opt={options.bar.customModules.netstat.networkOutLabel}
|
opt={options.bar.customModules.netstat.networkOutLabel}
|
||||||
title="Network Out Label"
|
title="Network Out Label"
|
||||||
@@ -183,7 +255,11 @@ export const CustomModuleSettings = (): JSX.Element => {
|
|||||||
type="enum"
|
type="enum"
|
||||||
enums={['GiB', 'MiB', 'KiB', 'auto']}
|
enums={['GiB', 'MiB', 'KiB', 'auto']}
|
||||||
/>
|
/>
|
||||||
<Option opt={options.theme.bar.buttons.modules.netstat.spacing} title="Spacing" type="string" />
|
<Option
|
||||||
|
opt={options.theme.bar.buttons.modules.netstat.spacing}
|
||||||
|
title="Spacing"
|
||||||
|
type="string"
|
||||||
|
/>
|
||||||
<Option
|
<Option
|
||||||
opt={options.bar.customModules.netstat.labelType}
|
opt={options.bar.customModules.netstat.labelType}
|
||||||
title="Label Type"
|
title="Label Type"
|
||||||
@@ -200,8 +276,16 @@ export const CustomModuleSettings = (): JSX.Element => {
|
|||||||
increment={1000}
|
increment={1000}
|
||||||
/>
|
/>
|
||||||
<Option opt={options.bar.customModules.netstat.leftClick} title="Left Click" type="string" />
|
<Option opt={options.bar.customModules.netstat.leftClick} title="Left Click" type="string" />
|
||||||
<Option opt={options.bar.customModules.netstat.rightClick} title="Right Click" type="string" />
|
<Option
|
||||||
<Option opt={options.bar.customModules.netstat.middleClick} title="Middle Click" type="string" />
|
opt={options.bar.customModules.netstat.rightClick}
|
||||||
|
title="Right Click"
|
||||||
|
type="string"
|
||||||
|
/>
|
||||||
|
<Option
|
||||||
|
opt={options.bar.customModules.netstat.middleClick}
|
||||||
|
title="Middle Click"
|
||||||
|
type="string"
|
||||||
|
/>
|
||||||
|
|
||||||
{/* Keyboard Layout Section */}
|
{/* Keyboard Layout Section */}
|
||||||
<Header title="Keyboard Layout" />
|
<Header title="Keyboard Layout" />
|
||||||
@@ -210,7 +294,11 @@ export const CustomModuleSettings = (): JSX.Element => {
|
|||||||
title="Button Border"
|
title="Button Border"
|
||||||
type="boolean"
|
type="boolean"
|
||||||
/>
|
/>
|
||||||
<Option opt={options.bar.customModules.kbLayout.icon} title="Keyboard Layout Icon" type="string" />
|
<Option
|
||||||
|
opt={options.bar.customModules.kbLayout.icon}
|
||||||
|
title="Keyboard Layout Icon"
|
||||||
|
type="string"
|
||||||
|
/>
|
||||||
<Option opt={options.bar.customModules.kbLayout.label} title="Show Label" type="boolean" />
|
<Option opt={options.bar.customModules.kbLayout.label} title="Show Label" type="boolean" />
|
||||||
<Option
|
<Option
|
||||||
opt={options.bar.customModules.kbLayout.labelType}
|
opt={options.bar.customModules.kbLayout.labelType}
|
||||||
@@ -218,12 +306,28 @@ export const CustomModuleSettings = (): JSX.Element => {
|
|||||||
type="enum"
|
type="enum"
|
||||||
enums={['layout', 'code']}
|
enums={['layout', 'code']}
|
||||||
/>
|
/>
|
||||||
<Option opt={options.theme.bar.buttons.modules.kbLayout.spacing} title="Spacing" type="string" />
|
<Option
|
||||||
|
opt={options.theme.bar.buttons.modules.kbLayout.spacing}
|
||||||
|
title="Spacing"
|
||||||
|
type="string"
|
||||||
|
/>
|
||||||
<Option opt={options.bar.customModules.kbLayout.leftClick} title="Left Click" type="string" />
|
<Option opt={options.bar.customModules.kbLayout.leftClick} title="Left Click" type="string" />
|
||||||
<Option opt={options.bar.customModules.kbLayout.rightClick} title="Right Click" type="string" />
|
<Option
|
||||||
<Option opt={options.bar.customModules.kbLayout.middleClick} title="Middle Click" type="string" />
|
opt={options.bar.customModules.kbLayout.rightClick}
|
||||||
|
title="Right Click"
|
||||||
|
type="string"
|
||||||
|
/>
|
||||||
|
<Option
|
||||||
|
opt={options.bar.customModules.kbLayout.middleClick}
|
||||||
|
title="Middle Click"
|
||||||
|
type="string"
|
||||||
|
/>
|
||||||
<Option opt={options.bar.customModules.kbLayout.scrollUp} title="Scroll Up" type="string" />
|
<Option opt={options.bar.customModules.kbLayout.scrollUp} title="Scroll Up" type="string" />
|
||||||
<Option opt={options.bar.customModules.kbLayout.scrollDown} title="Scroll Down" type="string" />
|
<Option
|
||||||
|
opt={options.bar.customModules.kbLayout.scrollDown}
|
||||||
|
title="Scroll Down"
|
||||||
|
type="string"
|
||||||
|
/>
|
||||||
|
|
||||||
{/* Updates Section */}
|
{/* Updates Section */}
|
||||||
<Header title="Updates" />
|
<Header title="Updates" />
|
||||||
@@ -253,7 +357,11 @@ export const CustomModuleSettings = (): JSX.Element => {
|
|||||||
title="Updates Available Icon"
|
title="Updates Available Icon"
|
||||||
type="string"
|
type="string"
|
||||||
/>
|
/>
|
||||||
<Option opt={options.bar.customModules.updates.icon.updated} title="No Updates Icon" type="string" />
|
<Option
|
||||||
|
opt={options.bar.customModules.updates.icon.updated}
|
||||||
|
title="No Updates Icon"
|
||||||
|
type="string"
|
||||||
|
/>
|
||||||
<Option opt={options.bar.customModules.updates.label} title="Show Label" type="boolean" />
|
<Option opt={options.bar.customModules.updates.label} title="Show Label" type="boolean" />
|
||||||
<Option
|
<Option
|
||||||
opt={options.bar.customModules.updates.autoHide}
|
opt={options.bar.customModules.updates.autoHide}
|
||||||
@@ -262,7 +370,11 @@ export const CustomModuleSettings = (): JSX.Element => {
|
|||||||
type="boolean"
|
type="boolean"
|
||||||
/>
|
/>
|
||||||
<Option opt={options.bar.customModules.updates.padZero} title="Pad with 0" type="boolean" />
|
<Option opt={options.bar.customModules.updates.padZero} title="Pad with 0" type="boolean" />
|
||||||
<Option opt={options.theme.bar.buttons.modules.updates.spacing} title="Spacing" type="string" />
|
<Option
|
||||||
|
opt={options.theme.bar.buttons.modules.updates.spacing}
|
||||||
|
title="Spacing"
|
||||||
|
type="string"
|
||||||
|
/>
|
||||||
<Option
|
<Option
|
||||||
opt={options.bar.customModules.updates.pollingInterval}
|
opt={options.bar.customModules.updates.pollingInterval}
|
||||||
title="Polling Interval"
|
title="Polling Interval"
|
||||||
@@ -273,10 +385,22 @@ export const CustomModuleSettings = (): JSX.Element => {
|
|||||||
increment={1000}
|
increment={1000}
|
||||||
/>
|
/>
|
||||||
<Option opt={options.bar.customModules.updates.leftClick} title="Left Click" type="string" />
|
<Option opt={options.bar.customModules.updates.leftClick} title="Left Click" type="string" />
|
||||||
<Option opt={options.bar.customModules.updates.rightClick} title="Right Click" type="string" />
|
<Option
|
||||||
<Option opt={options.bar.customModules.updates.middleClick} title="Middle Click" type="string" />
|
opt={options.bar.customModules.updates.rightClick}
|
||||||
|
title="Right Click"
|
||||||
|
type="string"
|
||||||
|
/>
|
||||||
|
<Option
|
||||||
|
opt={options.bar.customModules.updates.middleClick}
|
||||||
|
title="Middle Click"
|
||||||
|
type="string"
|
||||||
|
/>
|
||||||
<Option opt={options.bar.customModules.updates.scrollUp} title="Scroll Up" type="string" />
|
<Option opt={options.bar.customModules.updates.scrollUp} title="Scroll Up" type="string" />
|
||||||
<Option opt={options.bar.customModules.updates.scrollDown} title="Scroll Down" type="string" />
|
<Option
|
||||||
|
opt={options.bar.customModules.updates.scrollDown}
|
||||||
|
title="Scroll Down"
|
||||||
|
type="string"
|
||||||
|
/>
|
||||||
|
|
||||||
{/* Submap Section */}
|
{/* Submap Section */}
|
||||||
<Header title="Submap" />
|
<Header title="Submap" />
|
||||||
@@ -291,15 +415,39 @@ export const CustomModuleSettings = (): JSX.Element => {
|
|||||||
subtitle="Displays current submap name instead of Enabled/Disabled text."
|
subtitle="Displays current submap name instead of Enabled/Disabled text."
|
||||||
type="boolean"
|
type="boolean"
|
||||||
/>
|
/>
|
||||||
<Option opt={options.bar.customModules.submap.enabledIcon} title="Enabled Icon" type="string" />
|
<Option
|
||||||
<Option opt={options.bar.customModules.submap.disabledIcon} title="Disabled Icon" type="string" />
|
opt={options.bar.customModules.submap.enabledIcon}
|
||||||
<Option opt={options.bar.customModules.submap.enabledText} title="Enabled Text" type="string" />
|
title="Enabled Icon"
|
||||||
<Option opt={options.bar.customModules.submap.disabledText} title="Disabled Text" type="string" />
|
type="string"
|
||||||
|
/>
|
||||||
|
<Option
|
||||||
|
opt={options.bar.customModules.submap.disabledIcon}
|
||||||
|
title="Disabled Icon"
|
||||||
|
type="string"
|
||||||
|
/>
|
||||||
|
<Option
|
||||||
|
opt={options.bar.customModules.submap.enabledText}
|
||||||
|
title="Enabled Text"
|
||||||
|
type="string"
|
||||||
|
/>
|
||||||
|
<Option
|
||||||
|
opt={options.bar.customModules.submap.disabledText}
|
||||||
|
title="Disabled Text"
|
||||||
|
type="string"
|
||||||
|
/>
|
||||||
<Option opt={options.bar.customModules.submap.label} title="Show Label" type="boolean" />
|
<Option opt={options.bar.customModules.submap.label} title="Show Label" type="boolean" />
|
||||||
<Option opt={options.theme.bar.buttons.modules.submap.spacing} title="Spacing" type="string" />
|
<Option
|
||||||
|
opt={options.theme.bar.buttons.modules.submap.spacing}
|
||||||
|
title="Spacing"
|
||||||
|
type="string"
|
||||||
|
/>
|
||||||
<Option opt={options.bar.customModules.submap.leftClick} title="Left Click" type="string" />
|
<Option opt={options.bar.customModules.submap.leftClick} title="Left Click" type="string" />
|
||||||
<Option opt={options.bar.customModules.submap.rightClick} title="Right Click" type="string" />
|
<Option opt={options.bar.customModules.submap.rightClick} title="Right Click" type="string" />
|
||||||
<Option opt={options.bar.customModules.submap.middleClick} title="Middle Click" type="string" />
|
<Option
|
||||||
|
opt={options.bar.customModules.submap.middleClick}
|
||||||
|
title="Middle Click"
|
||||||
|
type="string"
|
||||||
|
/>
|
||||||
<Option opt={options.bar.customModules.submap.scrollUp} title="Scroll Up" type="string" />
|
<Option opt={options.bar.customModules.submap.scrollUp} title="Scroll Up" type="string" />
|
||||||
<Option opt={options.bar.customModules.submap.scrollDown} title="Scroll Down" type="string" />
|
<Option opt={options.bar.customModules.submap.scrollDown} title="Scroll Down" type="string" />
|
||||||
|
|
||||||
@@ -317,12 +465,28 @@ export const CustomModuleSettings = (): JSX.Element => {
|
|||||||
type="enum"
|
type="enum"
|
||||||
enums={['imperial', 'metric']}
|
enums={['imperial', 'metric']}
|
||||||
/>
|
/>
|
||||||
<Option opt={options.theme.bar.buttons.modules.weather.spacing} title="Spacing" type="string" />
|
<Option
|
||||||
|
opt={options.theme.bar.buttons.modules.weather.spacing}
|
||||||
|
title="Spacing"
|
||||||
|
type="string"
|
||||||
|
/>
|
||||||
<Option opt={options.bar.customModules.weather.leftClick} title="Left Click" type="string" />
|
<Option opt={options.bar.customModules.weather.leftClick} title="Left Click" type="string" />
|
||||||
<Option opt={options.bar.customModules.weather.rightClick} title="Right Click" type="string" />
|
<Option
|
||||||
<Option opt={options.bar.customModules.weather.middleClick} title="Middle Click" type="string" />
|
opt={options.bar.customModules.weather.rightClick}
|
||||||
|
title="Right Click"
|
||||||
|
type="string"
|
||||||
|
/>
|
||||||
|
<Option
|
||||||
|
opt={options.bar.customModules.weather.middleClick}
|
||||||
|
title="Middle Click"
|
||||||
|
type="string"
|
||||||
|
/>
|
||||||
<Option opt={options.bar.customModules.weather.scrollUp} title="Scroll Up" type="string" />
|
<Option opt={options.bar.customModules.weather.scrollUp} title="Scroll Up" type="string" />
|
||||||
<Option opt={options.bar.customModules.weather.scrollDown} title="Scroll Down" type="string" />
|
<Option
|
||||||
|
opt={options.bar.customModules.weather.scrollDown}
|
||||||
|
title="Scroll Down"
|
||||||
|
type="string"
|
||||||
|
/>
|
||||||
|
|
||||||
{/* Hyprsunset Section */}
|
{/* Hyprsunset Section */}
|
||||||
<Header title="Hyprsunset" />
|
<Header title="Hyprsunset" />
|
||||||
@@ -337,12 +501,32 @@ export const CustomModuleSettings = (): JSX.Element => {
|
|||||||
title="Button Border"
|
title="Button Border"
|
||||||
type="boolean"
|
type="boolean"
|
||||||
/>
|
/>
|
||||||
<Option opt={options.bar.customModules.hyprsunset.onIcon} title="Enabled Icon" type="string" />
|
<Option
|
||||||
<Option opt={options.bar.customModules.hyprsunset.offIcon} title="Disabled Icon" type="string" />
|
opt={options.bar.customModules.hyprsunset.onIcon}
|
||||||
<Option opt={options.bar.customModules.hyprsunset.onLabel} title="Enabled Label" type="string" />
|
title="Enabled Icon"
|
||||||
<Option opt={options.bar.customModules.hyprsunset.offLabel} title="Disabled Label" type="string" />
|
type="string"
|
||||||
|
/>
|
||||||
|
<Option
|
||||||
|
opt={options.bar.customModules.hyprsunset.offIcon}
|
||||||
|
title="Disabled Icon"
|
||||||
|
type="string"
|
||||||
|
/>
|
||||||
|
<Option
|
||||||
|
opt={options.bar.customModules.hyprsunset.onLabel}
|
||||||
|
title="Enabled Label"
|
||||||
|
type="string"
|
||||||
|
/>
|
||||||
|
<Option
|
||||||
|
opt={options.bar.customModules.hyprsunset.offLabel}
|
||||||
|
title="Disabled Label"
|
||||||
|
type="string"
|
||||||
|
/>
|
||||||
<Option opt={options.bar.customModules.hyprsunset.label} title="Show Label" type="boolean" />
|
<Option opt={options.bar.customModules.hyprsunset.label} title="Show Label" type="boolean" />
|
||||||
<Option opt={options.theme.bar.buttons.modules.hyprsunset.spacing} title="Spacing" type="string" />
|
<Option
|
||||||
|
opt={options.theme.bar.buttons.modules.hyprsunset.spacing}
|
||||||
|
title="Spacing"
|
||||||
|
type="string"
|
||||||
|
/>
|
||||||
<Option
|
<Option
|
||||||
opt={options.bar.customModules.hyprsunset.pollingInterval}
|
opt={options.bar.customModules.hyprsunset.pollingInterval}
|
||||||
title="Polling Interval"
|
title="Polling Interval"
|
||||||
@@ -351,10 +535,22 @@ export const CustomModuleSettings = (): JSX.Element => {
|
|||||||
max={60 * 24 * 1000}
|
max={60 * 24 * 1000}
|
||||||
increment={1000}
|
increment={1000}
|
||||||
/>
|
/>
|
||||||
<Option opt={options.bar.customModules.hyprsunset.rightClick} title="Right Click" type="string" />
|
<Option
|
||||||
<Option opt={options.bar.customModules.hyprsunset.middleClick} title="Middle Click" type="string" />
|
opt={options.bar.customModules.hyprsunset.rightClick}
|
||||||
|
title="Right Click"
|
||||||
|
type="string"
|
||||||
|
/>
|
||||||
|
<Option
|
||||||
|
opt={options.bar.customModules.hyprsunset.middleClick}
|
||||||
|
title="Middle Click"
|
||||||
|
type="string"
|
||||||
|
/>
|
||||||
<Option opt={options.bar.customModules.hyprsunset.scrollUp} title="Scroll Up" type="string" />
|
<Option opt={options.bar.customModules.hyprsunset.scrollUp} title="Scroll Up" type="string" />
|
||||||
<Option opt={options.bar.customModules.hyprsunset.scrollDown} title="Scroll Down" type="string" />
|
<Option
|
||||||
|
opt={options.bar.customModules.hyprsunset.scrollDown}
|
||||||
|
title="Scroll Down"
|
||||||
|
type="string"
|
||||||
|
/>
|
||||||
|
|
||||||
{/* Hypridle Section */}
|
{/* Hypridle Section */}
|
||||||
<Header title="Hypridle" />
|
<Header title="Hypridle" />
|
||||||
@@ -364,11 +560,27 @@ export const CustomModuleSettings = (): JSX.Element => {
|
|||||||
type="boolean"
|
type="boolean"
|
||||||
/>
|
/>
|
||||||
<Option opt={options.bar.customModules.hypridle.onIcon} title="Enabled Icon" type="string" />
|
<Option opt={options.bar.customModules.hypridle.onIcon} title="Enabled Icon" type="string" />
|
||||||
<Option opt={options.bar.customModules.hypridle.offIcon} title="Disabled Icon" type="string" />
|
<Option
|
||||||
<Option opt={options.bar.customModules.hypridle.onLabel} title="Enabled Label" type="string" />
|
opt={options.bar.customModules.hypridle.offIcon}
|
||||||
<Option opt={options.bar.customModules.hypridle.offLabel} title="Disabled Label" type="string" />
|
title="Disabled Icon"
|
||||||
|
type="string"
|
||||||
|
/>
|
||||||
|
<Option
|
||||||
|
opt={options.bar.customModules.hypridle.onLabel}
|
||||||
|
title="Enabled Label"
|
||||||
|
type="string"
|
||||||
|
/>
|
||||||
|
<Option
|
||||||
|
opt={options.bar.customModules.hypridle.offLabel}
|
||||||
|
title="Disabled Label"
|
||||||
|
type="string"
|
||||||
|
/>
|
||||||
<Option opt={options.bar.customModules.hypridle.label} title="Show Label" type="boolean" />
|
<Option opt={options.bar.customModules.hypridle.label} title="Show Label" type="boolean" />
|
||||||
<Option opt={options.theme.bar.buttons.modules.hypridle.spacing} title="Spacing" type="string" />
|
<Option
|
||||||
|
opt={options.theme.bar.buttons.modules.hypridle.spacing}
|
||||||
|
title="Spacing"
|
||||||
|
type="string"
|
||||||
|
/>
|
||||||
<Option
|
<Option
|
||||||
opt={options.bar.customModules.hypridle.pollingInterval}
|
opt={options.bar.customModules.hypridle.pollingInterval}
|
||||||
title="Polling Interval"
|
title="Polling Interval"
|
||||||
@@ -377,10 +589,22 @@ export const CustomModuleSettings = (): JSX.Element => {
|
|||||||
max={60 * 24 * 1000}
|
max={60 * 24 * 1000}
|
||||||
increment={1000}
|
increment={1000}
|
||||||
/>
|
/>
|
||||||
<Option opt={options.bar.customModules.hypridle.rightClick} title="Right Click" type="string" />
|
<Option
|
||||||
<Option opt={options.bar.customModules.hypridle.middleClick} title="Middle Click" type="string" />
|
opt={options.bar.customModules.hypridle.rightClick}
|
||||||
|
title="Right Click"
|
||||||
|
type="string"
|
||||||
|
/>
|
||||||
|
<Option
|
||||||
|
opt={options.bar.customModules.hypridle.middleClick}
|
||||||
|
title="Middle Click"
|
||||||
|
type="string"
|
||||||
|
/>
|
||||||
<Option opt={options.bar.customModules.hypridle.scrollUp} title="Scroll Up" type="string" />
|
<Option opt={options.bar.customModules.hypridle.scrollUp} title="Scroll Up" type="string" />
|
||||||
<Option opt={options.bar.customModules.hypridle.scrollDown} title="Scroll Down" type="string" />
|
<Option
|
||||||
|
opt={options.bar.customModules.hypridle.scrollDown}
|
||||||
|
title="Scroll Down"
|
||||||
|
type="string"
|
||||||
|
/>
|
||||||
|
|
||||||
{/* Cava Section */}
|
{/* Cava Section */}
|
||||||
<Header title="Cava" />
|
<Header title="Cava" />
|
||||||
@@ -392,8 +616,16 @@ export const CustomModuleSettings = (): JSX.Element => {
|
|||||||
<Option opt={options.bar.customModules.cava.icon} title="Icon" type="string" />
|
<Option opt={options.bar.customModules.cava.icon} title="Icon" type="string" />
|
||||||
<Option opt={options.bar.customModules.cava.showIcon} title="Show Icon" type="boolean" />
|
<Option opt={options.bar.customModules.cava.showIcon} title="Show Icon" type="boolean" />
|
||||||
<Option opt={options.theme.bar.buttons.modules.cava.spacing} title="Spacing" type="string" />
|
<Option opt={options.theme.bar.buttons.modules.cava.spacing} title="Spacing" type="string" />
|
||||||
<Option opt={options.bar.customModules.cava.barCharacters} title="Bar Characters" type="object" />
|
<Option
|
||||||
<Option opt={options.bar.customModules.cava.spaceCharacter} title="Bar Separator" type="string" />
|
opt={options.bar.customModules.cava.barCharacters}
|
||||||
|
title="Bar Characters"
|
||||||
|
type="object"
|
||||||
|
/>
|
||||||
|
<Option
|
||||||
|
opt={options.bar.customModules.cava.spaceCharacter}
|
||||||
|
title="Bar Separator"
|
||||||
|
type="string"
|
||||||
|
/>
|
||||||
<Option
|
<Option
|
||||||
opt={options.bar.customModules.cava.showActiveOnly}
|
opt={options.bar.customModules.cava.showActiveOnly}
|
||||||
title="Auto Hide"
|
title="Auto Hide"
|
||||||
@@ -411,7 +643,11 @@ export const CustomModuleSettings = (): JSX.Element => {
|
|||||||
/>
|
/>
|
||||||
<Option opt={options.bar.customModules.cava.lowCutoff} title="Low Cutoff" type="number" />
|
<Option opt={options.bar.customModules.cava.lowCutoff} title="Low Cutoff" type="number" />
|
||||||
<Option opt={options.bar.customModules.cava.highCutoff} title="High Cutoff" type="number" />
|
<Option opt={options.bar.customModules.cava.highCutoff} title="High Cutoff" type="number" />
|
||||||
<Option opt={options.bar.customModules.cava.noiseReduction} title="Noise Reduction" type="float" />
|
<Option
|
||||||
|
opt={options.bar.customModules.cava.noiseReduction}
|
||||||
|
title="Noise Reduction"
|
||||||
|
type="float"
|
||||||
|
/>
|
||||||
<Option opt={options.bar.customModules.cava.stereo} title="Stereo" type="boolean" />
|
<Option opt={options.bar.customModules.cava.stereo} title="Stereo" type="boolean" />
|
||||||
<Option opt={options.bar.customModules.cava.leftClick} title="Left Click" type="string" />
|
<Option opt={options.bar.customModules.cava.leftClick} title="Left Click" type="string" />
|
||||||
<Option opt={options.bar.customModules.cava.rightClick} title="Right Click" type="string" />
|
<Option opt={options.bar.customModules.cava.rightClick} title="Right Click" type="string" />
|
||||||
@@ -427,8 +663,16 @@ export const CustomModuleSettings = (): JSX.Element => {
|
|||||||
type="boolean"
|
type="boolean"
|
||||||
/>
|
/>
|
||||||
<Option opt={options.bar.customModules.worldclock.icon} title="Icon" type="string" />
|
<Option opt={options.bar.customModules.worldclock.icon} title="Icon" type="string" />
|
||||||
<Option opt={options.bar.customModules.worldclock.showIcon} title="Show Icon" type="boolean" />
|
<Option
|
||||||
<Option opt={options.theme.bar.buttons.modules.worldclock.spacing} title="Spacing" type="string" />
|
opt={options.bar.customModules.worldclock.showIcon}
|
||||||
|
title="Show Icon"
|
||||||
|
type="boolean"
|
||||||
|
/>
|
||||||
|
<Option
|
||||||
|
opt={options.theme.bar.buttons.modules.worldclock.spacing}
|
||||||
|
title="Spacing"
|
||||||
|
type="string"
|
||||||
|
/>
|
||||||
<Option opt={options.bar.customModules.worldclock.format} title="Format" type="string" />
|
<Option opt={options.bar.customModules.worldclock.format} title="Format" type="string" />
|
||||||
<Option
|
<Option
|
||||||
opt={options.bar.customModules.worldclock.formatDiffDate}
|
opt={options.bar.customModules.worldclock.formatDiffDate}
|
||||||
@@ -436,13 +680,37 @@ export const CustomModuleSettings = (): JSX.Element => {
|
|||||||
subtitle="Format to use when the timezone is on a different calendar day than the local timezone."
|
subtitle="Format to use when the timezone is on a different calendar day than the local timezone."
|
||||||
type="string"
|
type="string"
|
||||||
/>
|
/>
|
||||||
<Option opt={options.bar.customModules.worldclock.divider} title="Date Divider" type="string" />
|
<Option
|
||||||
<Option opt={options.bar.customModules.worldclock.leftClick} title="Left Click" type="string" />
|
opt={options.bar.customModules.worldclock.divider}
|
||||||
<Option opt={options.bar.customModules.worldclock.rightClick} title="Right Click" type="string" />
|
title="Date Divider"
|
||||||
<Option opt={options.bar.customModules.worldclock.middleClick} title="Middle Click" type="string" />
|
type="string"
|
||||||
|
/>
|
||||||
|
<Option
|
||||||
|
opt={options.bar.customModules.worldclock.leftClick}
|
||||||
|
title="Left Click"
|
||||||
|
type="string"
|
||||||
|
/>
|
||||||
|
<Option
|
||||||
|
opt={options.bar.customModules.worldclock.rightClick}
|
||||||
|
title="Right Click"
|
||||||
|
type="string"
|
||||||
|
/>
|
||||||
|
<Option
|
||||||
|
opt={options.bar.customModules.worldclock.middleClick}
|
||||||
|
title="Middle Click"
|
||||||
|
type="string"
|
||||||
|
/>
|
||||||
<Option opt={options.bar.customModules.worldclock.scrollUp} title="Scroll Up" type="string" />
|
<Option opt={options.bar.customModules.worldclock.scrollUp} title="Scroll Up" type="string" />
|
||||||
<Option opt={options.bar.customModules.worldclock.scrollDown} title="Scroll Down" type="string" />
|
<Option
|
||||||
<Option opt={options.bar.customModules.worldclock.tz} title="Timezones Displayed" type="object" />
|
opt={options.bar.customModules.worldclock.scrollDown}
|
||||||
|
title="Scroll Down"
|
||||||
|
type="string"
|
||||||
|
/>
|
||||||
|
<Option
|
||||||
|
opt={options.bar.customModules.worldclock.tz}
|
||||||
|
title="Timezones Displayed"
|
||||||
|
type="object"
|
||||||
|
/>
|
||||||
|
|
||||||
{/* Power Section */}
|
{/* Power Section */}
|
||||||
<Header title="Power" />
|
<Header title="Power" />
|
||||||
@@ -455,7 +723,11 @@ export const CustomModuleSettings = (): JSX.Element => {
|
|||||||
<Option opt={options.bar.customModules.power.icon} title="Power Button Icon" type="string" />
|
<Option opt={options.bar.customModules.power.icon} title="Power Button Icon" type="string" />
|
||||||
<Option opt={options.bar.customModules.power.leftClick} title="Left Click" type="string" />
|
<Option opt={options.bar.customModules.power.leftClick} title="Left Click" type="string" />
|
||||||
<Option opt={options.bar.customModules.power.rightClick} title="Right Click" type="string" />
|
<Option opt={options.bar.customModules.power.rightClick} title="Right Click" type="string" />
|
||||||
<Option opt={options.bar.customModules.power.middleClick} title="Middle Click" type="string" />
|
<Option
|
||||||
|
opt={options.bar.customModules.power.middleClick}
|
||||||
|
title="Middle Click"
|
||||||
|
type="string"
|
||||||
|
/>
|
||||||
<Option opt={options.bar.customModules.power.scrollUp} title="Scroll Up" type="string" />
|
<Option opt={options.bar.customModules.power.scrollUp} title="Scroll Up" type="string" />
|
||||||
<Option opt={options.bar.customModules.power.scrollDown} title="Scroll Down" type="string" />
|
<Option opt={options.bar.customModules.power.scrollDown} title="Scroll Down" type="string" />
|
||||||
</box>
|
</box>
|
||||||
|
|||||||
@@ -32,13 +32,21 @@ export const CustomModuleTheme = (): JSX.Element => {
|
|||||||
}
|
}
|
||||||
type="color"
|
type="color"
|
||||||
/>
|
/>
|
||||||
<Option opt={options.theme.bar.buttons.modules.microphone.border} title="Border" type="color" />
|
<Option
|
||||||
|
opt={options.theme.bar.buttons.modules.microphone.border}
|
||||||
|
title="Border"
|
||||||
|
type="color"
|
||||||
|
/>
|
||||||
|
|
||||||
{/* RAM Module Section */}
|
{/* RAM Module Section */}
|
||||||
<Header title="RAM" />
|
<Header title="RAM" />
|
||||||
<Option opt={options.theme.bar.buttons.modules.ram.text} title="Text" type="color" />
|
<Option opt={options.theme.bar.buttons.modules.ram.text} title="Text" type="color" />
|
||||||
<Option opt={options.theme.bar.buttons.modules.ram.icon} title="Icon" type="color" />
|
<Option opt={options.theme.bar.buttons.modules.ram.icon} title="Icon" type="color" />
|
||||||
<Option opt={options.theme.bar.buttons.modules.ram.background} title="Label Background" type="color" />
|
<Option
|
||||||
|
opt={options.theme.bar.buttons.modules.ram.background}
|
||||||
|
title="Label Background"
|
||||||
|
type="color"
|
||||||
|
/>
|
||||||
<Option
|
<Option
|
||||||
opt={options.theme.bar.buttons.modules.ram.icon_background}
|
opt={options.theme.bar.buttons.modules.ram.icon_background}
|
||||||
title="Icon Background"
|
title="Icon Background"
|
||||||
@@ -54,7 +62,11 @@ export const CustomModuleTheme = (): JSX.Element => {
|
|||||||
<Header title="CPU" />
|
<Header title="CPU" />
|
||||||
<Option opt={options.theme.bar.buttons.modules.cpu.text} title="Text" type="color" />
|
<Option opt={options.theme.bar.buttons.modules.cpu.text} title="Text" type="color" />
|
||||||
<Option opt={options.theme.bar.buttons.modules.cpu.icon} title="Icon" type="color" />
|
<Option opt={options.theme.bar.buttons.modules.cpu.icon} title="Icon" type="color" />
|
||||||
<Option opt={options.theme.bar.buttons.modules.cpu.background} title="Label Background" type="color" />
|
<Option
|
||||||
|
opt={options.theme.bar.buttons.modules.cpu.background}
|
||||||
|
title="Label Background"
|
||||||
|
type="color"
|
||||||
|
/>
|
||||||
<Option
|
<Option
|
||||||
opt={options.theme.bar.buttons.modules.cpu.icon_background}
|
opt={options.theme.bar.buttons.modules.cpu.icon_background}
|
||||||
title="Icon Background"
|
title="Icon Background"
|
||||||
@@ -224,7 +236,11 @@ export const CustomModuleTheme = (): JSX.Element => {
|
|||||||
}
|
}
|
||||||
type="color"
|
type="color"
|
||||||
/>
|
/>
|
||||||
<Option opt={options.theme.bar.buttons.modules.hyprsunset.border} title="Border" type="color" />
|
<Option
|
||||||
|
opt={options.theme.bar.buttons.modules.hyprsunset.border}
|
||||||
|
title="Border"
|
||||||
|
type="color"
|
||||||
|
/>
|
||||||
|
|
||||||
{/* Hypridle Module Section */}
|
{/* Hypridle Module Section */}
|
||||||
<Header title="Hypridle" />
|
<Header title="Hypridle" />
|
||||||
@@ -250,7 +266,11 @@ export const CustomModuleTheme = (): JSX.Element => {
|
|||||||
<Header title="Cava" />
|
<Header title="Cava" />
|
||||||
<Option opt={options.theme.bar.buttons.modules.cava.text} title="Bars" type="color" />
|
<Option opt={options.theme.bar.buttons.modules.cava.text} title="Bars" type="color" />
|
||||||
<Option opt={options.theme.bar.buttons.modules.cava.icon} title="Icon" type="color" />
|
<Option opt={options.theme.bar.buttons.modules.cava.icon} title="Icon" type="color" />
|
||||||
<Option opt={options.theme.bar.buttons.modules.cava.background} title="Label Background" type="color" />
|
<Option
|
||||||
|
opt={options.theme.bar.buttons.modules.cava.background}
|
||||||
|
title="Label Background"
|
||||||
|
type="color"
|
||||||
|
/>
|
||||||
<Option
|
<Option
|
||||||
opt={options.theme.bar.buttons.modules.cava.icon_background}
|
opt={options.theme.bar.buttons.modules.cava.icon_background}
|
||||||
title="Icon Background"
|
title="Icon Background"
|
||||||
@@ -280,7 +300,11 @@ export const CustomModuleTheme = (): JSX.Element => {
|
|||||||
}
|
}
|
||||||
type="color"
|
type="color"
|
||||||
/>
|
/>
|
||||||
<Option opt={options.theme.bar.buttons.modules.worldclock.border} title="Border" type="color" />
|
<Option
|
||||||
|
opt={options.theme.bar.buttons.modules.worldclock.border}
|
||||||
|
title="Border"
|
||||||
|
type="color"
|
||||||
|
/>
|
||||||
|
|
||||||
{/* Power Module Section */}
|
{/* Power Module Section */}
|
||||||
<Header title="Power" />
|
<Header title="Power" />
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { bind, Variable } from 'astal';
|
import { bind, Variable } from 'astal';
|
||||||
import { BarBoxChild, BarModule } from 'src/lib/types/bar';
|
import { BarBoxChild, BarModuleProps } from 'src/lib/types/bar.types';
|
||||||
import { BarButtonStyles } from 'src/lib/types/options';
|
import { BarButtonStyles } from 'src/lib/options/options.types';
|
||||||
import options from 'src/options';
|
import options from 'src/options';
|
||||||
|
|
||||||
const { style } = options.theme.bar.buttons;
|
const { style } = options.theme.bar.buttons;
|
||||||
@@ -17,20 +17,20 @@ export const Module = ({
|
|||||||
props = {},
|
props = {},
|
||||||
showLabelBinding = bind(Variable(true)),
|
showLabelBinding = bind(Variable(true)),
|
||||||
showIconBinding = bind(Variable(true)),
|
showIconBinding = bind(Variable(true)),
|
||||||
showLabel,
|
showLabel = true,
|
||||||
labelHook,
|
labelHook,
|
||||||
hook,
|
hook,
|
||||||
}: BarModule): BarBoxChild => {
|
}: BarModuleProps): BarBoxChild => {
|
||||||
const getIconWidget = (useTxtIcn: boolean): JSX.Element | undefined => {
|
const getIconWidget = (useTxtIcn: boolean): JSX.Element | undefined => {
|
||||||
const className = `txt-icon bar-button-icon module-icon ${boxClass}`;
|
const className = `txt-icon bar-button-icon module-icon ${boxClass}`;
|
||||||
|
|
||||||
const icn = typeof icon === 'string' ? icon : icon?.get();
|
const icn = typeof icon === 'string' ? icon : icon?.get();
|
||||||
if (!useTxtIcn && icn?.length) {
|
if (!useTxtIcn && icn !== undefined && icn.length > 0) {
|
||||||
return <icon className={className} icon={icon} />;
|
return <icon className={className} icon={icon} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
const textIcn = typeof textIcon === 'string' ? textIcon : textIcon?.get();
|
const textIcn = typeof textIcon === 'string' ? textIcon : textIcon?.get();
|
||||||
if (textIcn?.length) {
|
if (textIcn !== undefined && textIcn.length > 0) {
|
||||||
return <label className={className} label={textIcon} />;
|
return <label className={className} label={textIcon} />;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,15 +1,14 @@
|
|||||||
import { BarBoxChild } from 'src/lib/types/bar';
|
import { BarBoxChild } from 'src/lib/types/bar.types';
|
||||||
import { Bind } from '../../../lib/types/variable';
|
|
||||||
import options from '../../../options';
|
import options from '../../../options';
|
||||||
import { bind } from 'astal';
|
import { bind, Binding } from 'astal';
|
||||||
|
|
||||||
const computeVisible = (child: BarBoxChild): Bind | boolean => {
|
const computeVisible = (child: BarBoxChild): Binding<boolean> | boolean => {
|
||||||
if (child.isVis !== undefined) {
|
if (child.isVis !== undefined) {
|
||||||
return bind(child.isVis);
|
return child.isVis;
|
||||||
}
|
}
|
||||||
return child.isVisible;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
return child.isVisible ?? true;
|
||||||
|
};
|
||||||
export const WidgetContainer = (child: BarBoxChild): JSX.Element => {
|
export const WidgetContainer = (child: BarBoxChild): JSX.Element => {
|
||||||
const buttonClassName = bind(options.theme.bar.buttons.style).as((style) => {
|
const buttonClassName = bind(options.theme.bar.buttons.style).as((style) => {
|
||||||
const styleMap = {
|
const styleMap = {
|
||||||
@@ -24,7 +23,7 @@ export const WidgetContainer = (child: BarBoxChild): JSX.Element => {
|
|||||||
return `bar_item_box_visible ${styleMap[style]} ${boxClassName}`;
|
return `bar_item_box_visible ${styleMap[style]} ${boxClassName}`;
|
||||||
});
|
});
|
||||||
|
|
||||||
if (child.isBox) {
|
if (child.isBox === true) {
|
||||||
return (
|
return (
|
||||||
<eventbox visible={computeVisible(child)} {...child.props}>
|
<eventbox visible={computeVisible(child)} {...child.props}>
|
||||||
<box className={buttonClassName}>{child.component}</box>
|
<box className={buttonClassName}>{child.component}</box>
|
||||||
|
|||||||
@@ -8,20 +8,20 @@ const hyprlandService = AstalHyprland.get_default();
|
|||||||
* It maintains internal state for monitors that have already been used so that duplicate assignments are avoided.
|
* It maintains internal state for monitors that have already been used so that duplicate assignments are avoided.
|
||||||
*/
|
*/
|
||||||
export class GdkMonitorMapper {
|
export class GdkMonitorMapper {
|
||||||
private usedGdkMonitors: Set<number>;
|
private _usedGdkMonitors: Set<number>;
|
||||||
private usedHyprlandMonitors: Set<number>;
|
private _usedHyprlandMonitors: Set<number>;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.usedGdkMonitors = new Set();
|
this._usedGdkMonitors = new Set();
|
||||||
this.usedHyprlandMonitors = new Set();
|
this._usedHyprlandMonitors = new Set();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resets the internal state for both GDK and Hyprland monitor mappings.
|
* Resets the internal state for both GDK and Hyprland monitor mappings.
|
||||||
*/
|
*/
|
||||||
public reset(): void {
|
public reset(): void {
|
||||||
this.usedGdkMonitors.clear();
|
this._usedGdkMonitors.clear();
|
||||||
this.usedHyprlandMonitors.clear();
|
this._usedHyprlandMonitors.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -44,7 +44,7 @@ export class GdkMonitorMapper {
|
|||||||
hyprlandMonitors,
|
hyprlandMonitors,
|
||||||
gdkMonitor,
|
gdkMonitor,
|
||||||
monitor,
|
monitor,
|
||||||
this.usedHyprlandMonitors,
|
this._usedHyprlandMonitors,
|
||||||
(mon) => mon.id,
|
(mon) => mon.id,
|
||||||
(mon, gdkMon) => this._matchMonitorKey(mon, gdkMon),
|
(mon, gdkMon) => this._matchMonitorKey(mon, gdkMon),
|
||||||
);
|
);
|
||||||
@@ -68,13 +68,14 @@ export class GdkMonitorMapper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const hyprlandMonitors = hyprlandService.get_monitors();
|
const hyprlandMonitors = hyprlandService.get_monitors();
|
||||||
const foundHyprlandMonitor = hyprlandMonitors.find((mon) => mon.id === monitor) || hyprlandMonitors[0];
|
const foundHyprlandMonitor =
|
||||||
|
hyprlandMonitors.find((mon) => mon.id === monitor) || hyprlandMonitors[0];
|
||||||
|
|
||||||
return this._matchMonitor(
|
return this._matchMonitor(
|
||||||
gdkCandidates,
|
gdkCandidates,
|
||||||
foundHyprlandMonitor,
|
foundHyprlandMonitor,
|
||||||
monitor,
|
monitor,
|
||||||
this.usedGdkMonitors,
|
this._usedGdkMonitors,
|
||||||
(candidate) => candidate.id,
|
(candidate) => candidate.id,
|
||||||
(candidate, hyprlandMonitor) => this._matchMonitorKey(hyprlandMonitor, candidate.monitor),
|
(candidate, hyprlandMonitor) => this._matchMonitorKey(hyprlandMonitor, candidate.monitor),
|
||||||
);
|
);
|
||||||
@@ -105,7 +106,9 @@ export class GdkMonitorMapper {
|
|||||||
// Direct match: candidate matches the source and has the same id as the target.
|
// Direct match: candidate matches the source and has the same id as the target.
|
||||||
const directMatch = candidates.find(
|
const directMatch = candidates.find(
|
||||||
(candidate) =>
|
(candidate) =>
|
||||||
compare(candidate, source) && !usedMonitors.has(getId(candidate)) && getId(candidate) === target,
|
compare(candidate, source) &&
|
||||||
|
!usedMonitors.has(getId(candidate)) &&
|
||||||
|
getId(candidate) === target,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (directMatch !== undefined) {
|
if (directMatch !== undefined) {
|
||||||
@@ -202,7 +205,7 @@ export class GdkMonitorMapper {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
const model = curMonitor.get_model() || '';
|
const model = curMonitor.get_model() ?? '';
|
||||||
const geometry = curMonitor.get_geometry();
|
const geometry = curMonitor.get_geometry();
|
||||||
const scaleFactor = curMonitor.get_scale_factor();
|
const scaleFactor = curMonitor.get_scale_factor();
|
||||||
|
|
||||||
|
|||||||
@@ -1,14 +1,18 @@
|
|||||||
import { ResourceLabelType } from 'src/lib/types/bar';
|
|
||||||
import { GenericResourceData, Postfix, UpdateHandlers } from 'src/lib/types/customModules/generic';
|
|
||||||
import { InputHandlerEventArgs, InputHandlerEvents, RunAsyncCommand } from 'src/lib/types/customModules/utils';
|
|
||||||
import { ThrottleFn } from 'src/lib/types/utils';
|
|
||||||
import { bind, Binding, execAsync, Variable } from 'astal';
|
import { bind, Binding, execAsync, Variable } from 'astal';
|
||||||
import { openMenu } from 'src/components/bar/utils/menu';
|
import { openMenu } from 'src/components/bar/utils/menu';
|
||||||
import options from 'src/options';
|
import options from 'src/options';
|
||||||
import { Gdk } from 'astal/gtk3';
|
import { Gdk } from 'astal/gtk3';
|
||||||
import { GtkWidget } from 'src/lib/types/widget';
|
|
||||||
import { onMiddleClick, onPrimaryClick, onSecondaryClick } from 'src/lib/shared/eventHandlers';
|
import { onMiddleClick, onPrimaryClick, onSecondaryClick } from 'src/lib/shared/eventHandlers';
|
||||||
import { isScrollDown, isScrollUp } from 'src/lib/utils';
|
import { isScrollDown, isScrollUp } from 'src/lib/utils';
|
||||||
|
import { ResourceLabelType } from 'src/lib/types/bar.types';
|
||||||
|
import { UpdateHandlers, Postfix, GenericResourceData } from 'src/lib/types/customModules/generic.types';
|
||||||
|
import {
|
||||||
|
RunAsyncCommand,
|
||||||
|
InputHandlerEvents,
|
||||||
|
InputHandlerEventArgs,
|
||||||
|
} from 'src/lib/types/customModules/utils.types';
|
||||||
|
import { ThrottleFn } from 'src/lib/types/utils.types';
|
||||||
|
import { GtkWidget } from 'src/lib/types/widget.types';
|
||||||
|
|
||||||
const { scrollSpeed } = options.bar.customModules;
|
const { scrollSpeed } = options.bar.customModules;
|
||||||
|
|
||||||
@@ -38,7 +42,12 @@ const handlePostInputUpdater = (postInputUpdater?: Variable<boolean>): void => {
|
|||||||
* @param fn An optional callback function to handle the command output.
|
* @param fn An optional callback function to handle the command output.
|
||||||
* @param postInputUpdater An optional Variable<boolean> that tracks the post input update state.
|
* @param postInputUpdater An optional Variable<boolean> that tracks the post input update state.
|
||||||
*/
|
*/
|
||||||
export const runAsyncCommand: RunAsyncCommand = (cmd, events, fn, postInputUpdater?: Variable<boolean>): void => {
|
export const runAsyncCommand: RunAsyncCommand = (
|
||||||
|
cmd,
|
||||||
|
events,
|
||||||
|
fn,
|
||||||
|
postInputUpdater?: Variable<boolean>,
|
||||||
|
): void => {
|
||||||
if (cmd.startsWith('menu:')) {
|
if (cmd.startsWith('menu:')) {
|
||||||
const menuName = cmd.split(':')[1].trim().toLowerCase();
|
const menuName = cmd.split(':')[1].trim().toLowerCase();
|
||||||
openMenu(events.clicked, events.event, `${menuName}menu`);
|
openMenu(events.clicked, events.event, `${menuName}menu`);
|
||||||
@@ -61,7 +70,8 @@ export const runAsyncCommand: RunAsyncCommand = (cmd, events, fn, postInputUpdat
|
|||||||
* which undo the toggle.
|
* which undo the toggle.
|
||||||
*/
|
*/
|
||||||
const throttledAsyncCommand = throttleInput(
|
const throttledAsyncCommand = throttleInput(
|
||||||
(cmd, events, fn, postInputUpdater?: Variable<boolean>) => runAsyncCommand(cmd, events, fn, postInputUpdater),
|
(cmd, events, fn, postInputUpdater?: Variable<boolean>) =>
|
||||||
|
runAsyncCommand(cmd, events, fn, postInputUpdater),
|
||||||
50,
|
50,
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -165,7 +175,12 @@ export const inputHandler = (
|
|||||||
const id = self.connect('scroll-event', (self: GtkWidget, event: Gdk.Event) => {
|
const id = self.connect('scroll-event', (self: GtkWidget, event: Gdk.Event) => {
|
||||||
const handleScroll = (input?: InputHandlerEventArgs): void => {
|
const handleScroll = (input?: InputHandlerEventArgs): void => {
|
||||||
if (input) {
|
if (input) {
|
||||||
throttledHandler(sanitizeInput(input.cmd), { clicked: self, event }, input.fn, postInputUpdater);
|
throttledHandler(
|
||||||
|
sanitizeInput(input.cmd),
|
||||||
|
{ clicked: self, event },
|
||||||
|
input.fn,
|
||||||
|
postInputUpdater,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -344,7 +359,11 @@ export const getPostfix = (sizeInBytes: number): Postfix => {
|
|||||||
*
|
*
|
||||||
* @returns The rendered resource label as a string.
|
* @returns The rendered resource label as a string.
|
||||||
*/
|
*/
|
||||||
export const renderResourceLabel = (lblType: ResourceLabelType, rmUsg: GenericResourceData, round: boolean): string => {
|
export const renderResourceLabel = (
|
||||||
|
lblType: ResourceLabelType,
|
||||||
|
rmUsg: GenericResourceData,
|
||||||
|
round: boolean,
|
||||||
|
): string => {
|
||||||
const { used, total, percentage, free } = rmUsg;
|
const { used, total, percentage, free } = rmUsg;
|
||||||
|
|
||||||
const formatFunctions = {
|
const formatFunctions = {
|
||||||
@@ -361,7 +380,7 @@ export const renderResourceLabel = (lblType: ResourceLabelType, rmUsg: GenericRe
|
|||||||
const postfix = getPostfix(total);
|
const postfix = getPostfix(total);
|
||||||
|
|
||||||
// Determine which format function to use
|
// Determine which format function to use
|
||||||
const formatUsed = formatFunctions[postfix] || formatFunctions['B'];
|
const formatUsed = formatFunctions[postfix] ?? formatFunctions['B'];
|
||||||
const usedSizeFormatted = formatUsed(used, round);
|
const usedSizeFormatted = formatUsed(used, round);
|
||||||
|
|
||||||
if (lblType === 'used/total') {
|
if (lblType === 'used/total') {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { App, Gdk } from 'astal/gtk3';
|
import { App, Gdk } from 'astal/gtk3';
|
||||||
import { GtkWidget } from 'src/lib/types/widget';
|
import { GtkWidget } from 'src/lib/types/widget.types';
|
||||||
import { calculateMenuPosition } from 'src/components/menus/shared/dropdown/locationHandler';
|
import { calculateMenuPosition } from 'src/components/menus/shared/dropdown/locationHandler';
|
||||||
|
|
||||||
export const closeAllMenus = (): void => {
|
export const closeAllMenus = (): void => {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { BarLayout, BarLayouts } from 'src/lib/types/options';
|
import { BarLayout, BarLayouts } from 'src/lib/options/options.types';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the bar layout configuration for a specific monitor
|
* Returns the bar layout configuration for a specific monitor
|
||||||
@@ -11,7 +11,7 @@ export const getLayoutForMonitor = (monitor: number, layouts: BarLayouts): BarLa
|
|||||||
const matchingKey = Object.keys(layouts).find((key) => key === monitor.toString());
|
const matchingKey = Object.keys(layouts).find((key) => key === monitor.toString());
|
||||||
const wildcard = Object.keys(layouts).find((key) => key === '*');
|
const wildcard = Object.keys(layouts).find((key) => key === '*');
|
||||||
|
|
||||||
if (matchingKey) {
|
if (matchingKey !== undefined) {
|
||||||
return layouts[matchingKey];
|
return layouts[matchingKey];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ const audioService = wireplumber.audio;
|
|||||||
|
|
||||||
const ActiveDeviceContainer = ({ children }: ActiveDeviceContainerProps): JSX.Element => {
|
const ActiveDeviceContainer = ({ children }: ActiveDeviceContainerProps): JSX.Element => {
|
||||||
return (
|
return (
|
||||||
<box className={'menu-items-section selected'} name={ActiveDeviceMenu.Devices} vertical>
|
<box className={'menu-items-section selected'} name={ActiveDeviceMenu.DEVICES} vertical>
|
||||||
{children}
|
{children}
|
||||||
</box>
|
</box>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -5,11 +5,11 @@ import { bind, Variable } from 'astal';
|
|||||||
import { isPrimaryClick } from 'src/lib/utils.js';
|
import { isPrimaryClick } from 'src/lib/utils.js';
|
||||||
|
|
||||||
export enum ActiveDeviceMenu {
|
export enum ActiveDeviceMenu {
|
||||||
Devices = 'devices',
|
DEVICES = 'devices',
|
||||||
Playbacks = 'playbacks',
|
PLAYBACKS = 'playbacks',
|
||||||
}
|
}
|
||||||
|
|
||||||
const activeMenu: Variable<ActiveDeviceMenu> = Variable(ActiveDeviceMenu.Devices);
|
const activeMenu: Variable<ActiveDeviceMenu> = Variable(ActiveDeviceMenu.DEVICES);
|
||||||
|
|
||||||
const Header = (): JSX.Element => (
|
const Header = (): JSX.Element => (
|
||||||
<box className={'menu-label-container volume selected'} halign={Gtk.Align.FILL}>
|
<box className={'menu-label-container volume selected'} halign={Gtk.Align.FILL}>
|
||||||
@@ -21,15 +21,15 @@ const Header = (): JSX.Element => (
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (activeMenu.get() === ActiveDeviceMenu.Devices) {
|
if (activeMenu.get() === ActiveDeviceMenu.DEVICES) {
|
||||||
activeMenu.set(ActiveDeviceMenu.Playbacks);
|
activeMenu.set(ActiveDeviceMenu.PLAYBACKS);
|
||||||
} else {
|
} else {
|
||||||
activeMenu.set(ActiveDeviceMenu.Devices);
|
activeMenu.set(ActiveDeviceMenu.DEVICES);
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
halign={Gtk.Align.END}
|
halign={Gtk.Align.END}
|
||||||
hexpand
|
hexpand
|
||||||
label={bind(activeMenu).as((menu) => (menu === ActiveDeviceMenu.Devices ? '' : ''))}
|
label={bind(activeMenu).as((menu) => (menu === ActiveDeviceMenu.DEVICES ? '' : ''))}
|
||||||
/>
|
/>
|
||||||
</box>
|
</box>
|
||||||
);
|
);
|
||||||
@@ -40,13 +40,13 @@ export const VolumeSliders = (): JSX.Element => {
|
|||||||
<Header />
|
<Header />
|
||||||
<revealer
|
<revealer
|
||||||
transitionType={Gtk.RevealerTransitionType.NONE}
|
transitionType={Gtk.RevealerTransitionType.NONE}
|
||||||
revealChild={bind(activeMenu).as((curMenu) => curMenu === ActiveDeviceMenu.Devices)}
|
revealChild={bind(activeMenu).as((curMenu) => curMenu === ActiveDeviceMenu.DEVICES)}
|
||||||
>
|
>
|
||||||
<ActiveDevices />
|
<ActiveDevices />
|
||||||
</revealer>
|
</revealer>
|
||||||
<revealer
|
<revealer
|
||||||
transitionType={Gtk.RevealerTransitionType.NONE}
|
transitionType={Gtk.RevealerTransitionType.NONE}
|
||||||
revealChild={bind(activeMenu).as((curMenu) => curMenu === ActiveDeviceMenu.Playbacks)}
|
revealChild={bind(activeMenu).as((curMenu) => curMenu === ActiveDeviceMenu.PLAYBACKS)}
|
||||||
>
|
>
|
||||||
<ActivePlaybacks />
|
<ActivePlaybacks />
|
||||||
</revealer>
|
</revealer>
|
||||||
|
|||||||
@@ -12,11 +12,11 @@ const NoStreams = (): JSX.Element => {
|
|||||||
|
|
||||||
export const ActivePlaybacks = (): JSX.Element => {
|
export const ActivePlaybacks = (): JSX.Element => {
|
||||||
return (
|
return (
|
||||||
<box className={'menu-items-section selected'} name={ActiveDeviceMenu.Playbacks} vertical>
|
<box className={'menu-items-section selected'} name={ActiveDeviceMenu.PLAYBACKS} vertical>
|
||||||
<scrollable className={'menu-scroller active-playbacks-scrollable'}>
|
<scrollable className={'menu-scroller active-playbacks-scrollable'}>
|
||||||
<box vertical>
|
<box vertical>
|
||||||
{bind(audioService, 'streams').as((streams) => {
|
{bind(audioService, 'streams').as((streams) => {
|
||||||
if (!streams || streams.length === 0) {
|
if (streams === null || streams.length === 0) {
|
||||||
return <NoStreams />;
|
return <NoStreams />;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -28,8 +28,8 @@ export const Slider = ({ device, type }: SliderProps): JSX.Element => {
|
|||||||
max={type === 'playback' ? bind(raiseMaximumVolume).as((raise) => (raise ? 1.5 : 1)) : 1}
|
max={type === 'playback' ? bind(raiseMaximumVolume).as((raise) => (raise ? 1.5 : 1)) : 1}
|
||||||
onDragged={({ value, dragging }) => {
|
onDragged={({ value, dragging }) => {
|
||||||
if (dragging) {
|
if (dragging) {
|
||||||
device.volume = value;
|
device.set_volume(value);
|
||||||
device.mute = false;
|
device.set_mute(false);
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
setup={(self) => {
|
setup={(self) => {
|
||||||
|
|||||||
@@ -16,12 +16,14 @@ export const SliderIcon = ({ type, device }: SliderIconProps): JSX.Element => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<button
|
<button
|
||||||
className={bind(device, 'mute').as((isMuted) => `menu-active-button ${type} ${isMuted ? 'muted' : ''}`)}
|
className={bind(device, 'mute').as(
|
||||||
|
(isMuted) => `menu-active-button ${type} ${isMuted ? 'muted' : ''}`,
|
||||||
|
)}
|
||||||
vexpand={false}
|
vexpand={false}
|
||||||
valign={Gtk.Align.END}
|
valign={Gtk.Align.END}
|
||||||
onClick={(_, event) => {
|
onClick={(_, event) => {
|
||||||
if (isPrimaryClick(event)) {
|
if (isPrimaryClick(event)) {
|
||||||
device.mute = !device.mute;
|
device.set_mute(!device.mute);
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
onDestroy={() => {
|
onDestroy={() => {
|
||||||
|
|||||||
@@ -20,7 +20,9 @@ const DeviceName = ({ device, type }: Omit<AudioDeviceProps, 'icon'>): JSX.Eleme
|
|||||||
truncate
|
truncate
|
||||||
wrap
|
wrap
|
||||||
className={bind(device, 'description').as((currentDesc) =>
|
className={bind(device, 'description').as((currentDesc) =>
|
||||||
device.description === currentDesc ? `menu-button-name active ${type}` : `menu-button-name ${type}`,
|
device.description === currentDesc
|
||||||
|
? `menu-button-name active ${type}`
|
||||||
|
: `menu-button-name ${type}`,
|
||||||
)}
|
)}
|
||||||
label={device.description}
|
label={device.description}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ export const InputDevices = (): JSX.Element => {
|
|||||||
<box className={'menu-items-section input'} vertical>
|
<box className={'menu-items-section input'} vertical>
|
||||||
<box className={'menu-container input'} vertical>
|
<box className={'menu-container input'} vertical>
|
||||||
{inputDevices.as((devices) => {
|
{inputDevices.as((devices) => {
|
||||||
if (!devices || devices.length === 0) {
|
if (devices === null || devices.length === 0) {
|
||||||
return <NotFoundButton type={'input'} />;
|
return <NotFoundButton type={'input'} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ export const PlaybackDevices = (): JSX.Element => {
|
|||||||
<box className={'menu-items-section playback'} vertical>
|
<box className={'menu-items-section playback'} vertical>
|
||||||
<box className={'menu-container playback'} vertical>
|
<box className={'menu-container playback'} vertical>
|
||||||
{playbackDevices.as((devices) => {
|
{playbackDevices.as((devices) => {
|
||||||
if (!devices || devices.length === 0) {
|
if (devices === null || devices.length === 0) {
|
||||||
return <NotFoundButton type={'playback'} />;
|
return <NotFoundButton type={'playback'} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ type IconVolumes = keyof typeof speakerIcons;
|
|||||||
*/
|
*/
|
||||||
const getIcon = (audioVol: number, isMuted: boolean): Record<string, string> => {
|
const getIcon = (audioVol: number, isMuted: boolean): Record<string, string> => {
|
||||||
const thresholds: IconVolumes[] = [101, 66, 34, 1, 0];
|
const thresholds: IconVolumes[] = [101, 66, 34, 1, 0];
|
||||||
const icon = isMuted ? 0 : thresholds.find((threshold) => threshold <= audioVol * 100) || 0;
|
const icon = isMuted ? 0 : (thresholds.find((threshold) => threshold <= audioVol * 100) ?? 0);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
spkr: speakerIcons[icon],
|
spkr: speakerIcons[icon],
|
||||||
|
|||||||
@@ -2,7 +2,13 @@ import { Gtk } from 'astal/gtk3';
|
|||||||
|
|
||||||
export const BluetoothDisabled = (): JSX.Element => {
|
export const BluetoothDisabled = (): JSX.Element => {
|
||||||
return (
|
return (
|
||||||
<box className={'bluetooth-items'} vertical expand valign={Gtk.Align.CENTER} halign={Gtk.Align.CENTER}>
|
<box
|
||||||
|
className={'bluetooth-items'}
|
||||||
|
vertical
|
||||||
|
expand
|
||||||
|
valign={Gtk.Align.CENTER}
|
||||||
|
halign={Gtk.Align.CENTER}
|
||||||
|
>
|
||||||
<label className={'bluetooth-disabled dim'} hexpand label={'Bluetooth is disabled'} />
|
<label className={'bluetooth-disabled dim'} hexpand label={'Bluetooth is disabled'} />
|
||||||
</box>
|
</box>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -2,7 +2,13 @@ import { Gtk } from 'astal/gtk3';
|
|||||||
|
|
||||||
export const NoBluetoothDevices = (): JSX.Element => {
|
export const NoBluetoothDevices = (): JSX.Element => {
|
||||||
return (
|
return (
|
||||||
<box className={'bluetooth-items'} vertical expand valign={Gtk.Align.CENTER} halign={Gtk.Align.CENTER}>
|
<box
|
||||||
|
className={'bluetooth-items'}
|
||||||
|
vertical
|
||||||
|
expand
|
||||||
|
valign={Gtk.Align.CENTER}
|
||||||
|
halign={Gtk.Align.CENTER}
|
||||||
|
>
|
||||||
<label className={'no-bluetooth-devices dim'} hexpand label={'No devices currently found'} />
|
<label className={'no-bluetooth-devices dim'} hexpand label={'No devices currently found'} />
|
||||||
<label className={'search-bluetooth-label dim'} hexpand label={"Press '' to search"} />
|
<label className={'search-bluetooth-label dim'} hexpand label={"Press '' to search"} />
|
||||||
</box>
|
</box>
|
||||||
|
|||||||
@@ -1,7 +1,12 @@
|
|||||||
import { Binding } from 'astal';
|
import { Binding } from 'astal';
|
||||||
import { ButtonProps } from 'astal/gtk3/widget';
|
import { ButtonProps } from 'astal/gtk3/widget';
|
||||||
|
|
||||||
export const ActionButton = ({ name = '', tooltipText = '', label = '', ...props }: ActionButtonProps): JSX.Element => {
|
export const ActionButton = ({
|
||||||
|
name = '',
|
||||||
|
tooltipText = '',
|
||||||
|
label = '',
|
||||||
|
...props
|
||||||
|
}: ActionButtonProps): JSX.Element => {
|
||||||
return (
|
return (
|
||||||
<button className={`menu-icon-button ${name} bluetooth`} {...props}>
|
<button className={`menu-icon-button ${name} bluetooth`} {...props}>
|
||||||
<label
|
<label
|
||||||
|
|||||||
@@ -41,7 +41,9 @@ export const getAvailableBluetoothDevices = (): AstalBluetooth.Device[] => {
|
|||||||
*/
|
*/
|
||||||
export const getConnectedBluetoothDevices = (): string[] => {
|
export const getConnectedBluetoothDevices = (): string[] => {
|
||||||
const availableDevices = getAvailableBluetoothDevices();
|
const availableDevices = getAvailableBluetoothDevices();
|
||||||
const connectedDeviceNames = availableDevices.filter((d) => d.connected || d.paired).map((d) => d.address);
|
const connectedDeviceNames = availableDevices
|
||||||
|
.filter((d) => d.connected || d.paired)
|
||||||
|
.map((d) => d.address);
|
||||||
|
|
||||||
return connectedDeviceNames;
|
return connectedDeviceNames;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ Variable.derive([bind(bluetoothService, 'adapter')], () => {
|
|||||||
discoveringBinding?.drop();
|
discoveringBinding?.drop();
|
||||||
discoveringBinding = undefined;
|
discoveringBinding = undefined;
|
||||||
|
|
||||||
if (!bluetoothService.adapter) {
|
if (bluetoothService.adapter === null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,14 @@ import { Controls } from './Controls';
|
|||||||
|
|
||||||
export const Header = (): JSX.Element => {
|
export const Header = (): JSX.Element => {
|
||||||
const MenuLabel = (): JSX.Element => {
|
const MenuLabel = (): JSX.Element => {
|
||||||
return <label className="menu-label" valign={Gtk.Align.CENTER} halign={Gtk.Align.START} label="Bluetooth" />;
|
return (
|
||||||
|
<label
|
||||||
|
className="menu-label"
|
||||||
|
valign={Gtk.Align.CENTER}
|
||||||
|
halign={Gtk.Align.START}
|
||||||
|
label="Bluetooth"
|
||||||
|
/>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -3,7 +3,12 @@ import Calendar from 'src/components/shared/Calendar';
|
|||||||
|
|
||||||
export const CalendarWidget = (): JSX.Element => {
|
export const CalendarWidget = (): JSX.Element => {
|
||||||
return (
|
return (
|
||||||
<box className={'calendar-menu-item-container calendar'} halign={Gtk.Align.FILL} valign={Gtk.Align.FILL} expand>
|
<box
|
||||||
|
className={'calendar-menu-item-container calendar'}
|
||||||
|
halign={Gtk.Align.FILL}
|
||||||
|
valign={Gtk.Align.FILL}
|
||||||
|
expand
|
||||||
|
>
|
||||||
<box className={'calendar-container-box'}>
|
<box className={'calendar-container-box'}>
|
||||||
<Calendar
|
<Calendar
|
||||||
className={'calendar-menu-widget'}
|
className={'calendar-menu-widget'}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import options from 'src/options';
|
import options from 'src/options';
|
||||||
import { bind, Variable } from 'astal';
|
import { bind, Variable } from 'astal';
|
||||||
import { Gtk } from 'astal/gtk3';
|
import { Gtk } from 'astal/gtk3';
|
||||||
import { systemTime } from 'src/globals/time';
|
import { systemTime } from 'src/shared/time';
|
||||||
|
|
||||||
const { military, hideSeconds } = options.menus.clock.time;
|
const { military, hideSeconds } = options.menus.clock.time;
|
||||||
|
|
||||||
@@ -16,7 +16,7 @@ export const MilitaryTime = (): JSX.Element => {
|
|||||||
<label
|
<label
|
||||||
className={'clock-content-time'}
|
className={'clock-content-time'}
|
||||||
label={bind(systemTime).as((time) => {
|
label={bind(systemTime).as((time) => {
|
||||||
return time?.format(hideSeconds ? '%H:%M' : '%H:%M:%S') || '';
|
return time?.format(hideSeconds ? '%H:%M' : '%H:%M:%S') ?? '';
|
||||||
})}
|
})}
|
||||||
/>
|
/>
|
||||||
</box>
|
</box>
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
import options from 'src/options';
|
import options from 'src/options';
|
||||||
import { bind, GLib, Variable } from 'astal';
|
import { bind, GLib, Variable } from 'astal';
|
||||||
import { Gtk } from 'astal/gtk3';
|
import { Gtk } from 'astal/gtk3';
|
||||||
import { systemTime } from 'src/globals/time';
|
import { systemTime } from 'src/shared/time';
|
||||||
|
|
||||||
const { military, hideSeconds } = options.menus.clock.time;
|
const { military, hideSeconds } = options.menus.clock.time;
|
||||||
|
|
||||||
const period = Variable('').poll(1000, (): string => GLib.DateTime.new_now_local().format('%p') || '');
|
const period = Variable('').poll(1000, (): string => GLib.DateTime.new_now_local().format('%p') ?? '');
|
||||||
|
|
||||||
export const StandardTime = (): JSX.Element => {
|
export const StandardTime = (): JSX.Element => {
|
||||||
const CurrentTime = ({ hideSeconds }: CurrentTimeProps): JSX.Element => {
|
const CurrentTime = ({ hideSeconds }: CurrentTimeProps): JSX.Element => {
|
||||||
@@ -14,7 +14,7 @@ export const StandardTime = (): JSX.Element => {
|
|||||||
<label
|
<label
|
||||||
className={'clock-content-time'}
|
className={'clock-content-time'}
|
||||||
label={bind(systemTime).as((time) => {
|
label={bind(systemTime).as((time) => {
|
||||||
return time?.format(hideSeconds ? '%I:%M' : '%I:%M:%S') || '';
|
return time?.format(hideSeconds ? '%I:%M' : '%I:%M:%S') ?? '';
|
||||||
})}
|
})}
|
||||||
/>
|
/>
|
||||||
</box>
|
</box>
|
||||||
|
|||||||
@@ -4,8 +4,18 @@ import { StandardTime } from './StandardTime';
|
|||||||
|
|
||||||
export const TimeWidget = (): JSX.Element => {
|
export const TimeWidget = (): JSX.Element => {
|
||||||
return (
|
return (
|
||||||
<box className={'calendar-menu-item-container clock'} valign={Gtk.Align.CENTER} halign={Gtk.Align.FILL} hexpand>
|
<box
|
||||||
<box className={'clock-content-items'} valign={Gtk.Align.CENTER} halign={Gtk.Align.CENTER} hexpand>
|
className={'calendar-menu-item-container clock'}
|
||||||
|
valign={Gtk.Align.CENTER}
|
||||||
|
halign={Gtk.Align.FILL}
|
||||||
|
hexpand
|
||||||
|
>
|
||||||
|
<box
|
||||||
|
className={'clock-content-items'}
|
||||||
|
valign={Gtk.Align.CENTER}
|
||||||
|
halign={Gtk.Align.CENTER}
|
||||||
|
hexpand
|
||||||
|
>
|
||||||
<StandardTime />
|
<StandardTime />
|
||||||
<MilitaryTime />
|
<MilitaryTime />
|
||||||
</box>
|
</box>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { isValidWeatherIconTitle } from 'src/globals/weather';
|
import { Weather, WeatherIconTitle } from 'src/lib/types/weather.types';
|
||||||
import { Weather, WeatherIconTitle } from 'src/lib/types/weather';
|
import { isValidWeatherIconTitle } from 'src/shared/weather';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves the next epoch time for weather data.
|
* Retrieves the next epoch time for weather data.
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { bind } from 'astal';
|
import { bind } from 'astal';
|
||||||
import { globalWeatherVar } from 'src/globals/weather';
|
import { globalWeatherVar } from 'src/shared/weather';
|
||||||
import { Gtk } from 'astal/gtk3';
|
import { Gtk } from 'astal/gtk3';
|
||||||
import { weatherIcons } from 'src/lib/icons/weather.js';
|
import { weatherIcons } from 'src/lib/icons/weather.js';
|
||||||
import { getIconQuery } from '../helpers';
|
import { getIconQuery } from '../helpers';
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import options from 'src/options';
|
import options from 'src/options';
|
||||||
import { globalWeatherVar } from 'src/globals/weather';
|
import { globalWeatherVar } from 'src/shared/weather';
|
||||||
import { getNextEpoch } from '../helpers';
|
import { getNextEpoch } from '../helpers';
|
||||||
import { bind, Variable } from 'astal';
|
import { bind, Variable } from 'astal';
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { globalWeatherVar } from 'src/globals/weather';
|
import { globalWeatherVar } from 'src/shared/weather';
|
||||||
import { getNextEpoch } from '../helpers';
|
import { getNextEpoch } from '../helpers';
|
||||||
import { bind } from 'astal';
|
import { bind } from 'astal';
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { bind } from 'astal';
|
import { bind } from 'astal';
|
||||||
import { Gtk } from 'astal/gtk3';
|
import { Gtk } from 'astal/gtk3';
|
||||||
import { getWeatherStatusTextIcon } from 'src/globals/weather.js';
|
import { getWeatherStatusTextIcon, globalWeatherVar } from 'src/shared/weather';
|
||||||
|
|
||||||
export const TodayIcon = (): JSX.Element => {
|
export const TodayIcon = (): JSX.Element => {
|
||||||
return (
|
return (
|
||||||
@@ -11,7 +11,7 @@ export const TodayIcon = (): JSX.Element => {
|
|||||||
>
|
>
|
||||||
<label
|
<label
|
||||||
className={'calendar-menu-weather today icon txt-icon'}
|
className={'calendar-menu-weather today icon txt-icon'}
|
||||||
label={bind(globalWeatherVar).as(getWeatherStatusTextIcon)}
|
label={bind(globalWeatherVar).as((weather) => getWeatherStatusTextIcon(weather))}
|
||||||
/>
|
/>
|
||||||
</box>
|
</box>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { getTemperature, globalWeatherVar } from 'src/globals/weather';
|
import { getTemperature, globalWeatherVar } from 'src/shared/weather';
|
||||||
import options from 'src/options';
|
import options from 'src/options';
|
||||||
import { getRainChance } from 'src/globals/weather';
|
import { getRainChance } from 'src/shared/weather';
|
||||||
import { Gtk } from 'astal/gtk3';
|
import { Gtk } from 'astal/gtk3';
|
||||||
import { bind, Variable } from 'astal';
|
import { bind, Variable } from 'astal';
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import options from 'src/options';
|
import options from 'src/options';
|
||||||
import { globalWeatherVar } from 'src/globals/weather';
|
import { globalWeatherVar } from 'src/shared/weather';
|
||||||
import { getTemperature, getWeatherIcon } from 'src/globals/weather';
|
import { getTemperature, getWeatherIcon } from 'src/shared/weather';
|
||||||
import { Gtk } from 'astal/gtk3';
|
import { Gtk } from 'astal/gtk3';
|
||||||
import { bind, Variable } from 'astal';
|
import { bind, Variable } from 'astal';
|
||||||
const { unit } = options.menus.clock.weather;
|
const { unit } = options.menus.clock.weather;
|
||||||
@@ -35,7 +35,9 @@ const Temperature = (): JSX.Element => {
|
|||||||
(weather) =>
|
(weather) =>
|
||||||
`calendar-menu-weather today temp label icon txt-icon ${getWeatherIcon(Math.ceil(weather.current.temp_f)).color}`,
|
`calendar-menu-weather today temp label icon txt-icon ${getWeatherIcon(Math.ceil(weather.current.temp_f)).color}`,
|
||||||
)}
|
)}
|
||||||
label={bind(globalWeatherVar).as((weather) => getWeatherIcon(Math.ceil(weather.current.temp_f)).icon)}
|
label={bind(globalWeatherVar).as(
|
||||||
|
(weather) => getWeatherIcon(Math.ceil(weather.current.temp_f)).icon,
|
||||||
|
)}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -18,7 +18,9 @@ const notifdService = AstalNotifd.get_default();
|
|||||||
export const WifiButton = (): JSX.Element => {
|
export const WifiButton = (): JSX.Element => {
|
||||||
return (
|
return (
|
||||||
<button
|
<button
|
||||||
className={bind(isWifiEnabled).as((isEnabled) => `dashboard-button wifi ${!isEnabled ? 'disabled' : ''}`)}
|
className={bind(isWifiEnabled).as(
|
||||||
|
(isEnabled) => `dashboard-button wifi ${!isEnabled ? 'disabled' : ''}`,
|
||||||
|
)}
|
||||||
onClick={(_, event) => {
|
onClick={(_, event) => {
|
||||||
if (isPrimaryClick(event)) {
|
if (isPrimaryClick(event)) {
|
||||||
networkService.wifi?.set_enabled(!networkService.wifi.enabled);
|
networkService.wifi?.set_enabled(!networkService.wifi.enabled);
|
||||||
@@ -27,7 +29,10 @@ export const WifiButton = (): JSX.Element => {
|
|||||||
tooltipText={'Toggle Wifi'}
|
tooltipText={'Toggle Wifi'}
|
||||||
expand
|
expand
|
||||||
>
|
>
|
||||||
<label className={'txt-icon'} label={bind(isWifiEnabled).as((isEnabled) => (isEnabled ? '' : ''))} />
|
<label
|
||||||
|
className={'txt-icon'}
|
||||||
|
label={bind(isWifiEnabled).as((isEnabled) => (isEnabled ? '' : ''))}
|
||||||
|
/>
|
||||||
</button>
|
</button>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@@ -68,7 +73,10 @@ export const NotificationsButton = (): JSX.Element => {
|
|||||||
tooltipText={'Toggle Notifications'}
|
tooltipText={'Toggle Notifications'}
|
||||||
expand
|
expand
|
||||||
>
|
>
|
||||||
<label className={'txt-icon'} label={bind(notifdService, 'dontDisturb').as((dnd) => (dnd ? '' : ''))} />
|
<label
|
||||||
|
className={'txt-icon'}
|
||||||
|
label={bind(notifdService, 'dontDisturb').as((dnd) => (dnd ? '' : ''))}
|
||||||
|
/>
|
||||||
</button>
|
</button>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ Variable.derive([bind(networkService, 'wifi')], () => {
|
|||||||
wifiEnabledBinding?.drop();
|
wifiEnabledBinding?.drop();
|
||||||
wifiEnabledBinding = undefined;
|
wifiEnabledBinding = undefined;
|
||||||
|
|
||||||
if (!networkService.wifi) {
|
if (networkService.wifi === null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user