Added ags to hyprland
This commit is contained in:
@@ -0,0 +1,99 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Function to get the current resolution
|
||||
get_current_resolution() {
|
||||
local output
|
||||
output=$(hyprctl monitors -j)
|
||||
local width height refreshRate
|
||||
width=$(echo "$output" | jq -r '.[0].width')
|
||||
height=$(echo "$output" | jq -r '.[0].height')
|
||||
refreshRate=$(echo "$output" | jq -r '.[0].refreshRate')
|
||||
echo "$width $height $refreshRate"
|
||||
}
|
||||
|
||||
# Function to update the Hyprland configuration with the new resolution
|
||||
update_resolution_config() {
|
||||
local newWidth="$1"
|
||||
local newHeight="$2"
|
||||
local newRefreshRate="$3"
|
||||
local currentRes
|
||||
currentRes=$(get_current_resolution)
|
||||
local width height refreshRate
|
||||
width=${newWidth:-$(echo "$currentRes" | awk '{print $1}')}
|
||||
height=${newHeight:-$(echo "$currentRes" | awk '{print $2}')}
|
||||
refreshRate=${newRefreshRate:-$(echo "$currentRes" | awk '{print $3}')}
|
||||
|
||||
local modelineOutput
|
||||
modelineOutput=$(gtf "$width" "$height" "$refreshRate")
|
||||
local modeline
|
||||
modeline=$(echo "$modelineOutput" | grep -oP 'Modeline "\K[^"]+')
|
||||
|
||||
if [ -z "$modeline" ]; then
|
||||
echo "Failed to generate modeline"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Extract the resolution and refresh rate from the modeline
|
||||
local resolution
|
||||
resolution=$(echo "$modeline" | grep -oP '^[0-9]+x[0-9]+')
|
||||
local rate
|
||||
rate=$(echo "$modeline" | grep -oP '[0-9]+.[0-9]+$')
|
||||
|
||||
if [ -z "$resolution" ] || [ -z "$rate" ]; then
|
||||
echo "Failed to extract resolution or refresh rate from modeline"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
local configPath="${HOME}/.config/hypr/hyprland/general.conf"
|
||||
local newConfigContent
|
||||
newConfigContent=$(sed "s/^monitor=.*$/monitor=eDP-1, $resolution@$rate, auto, 1/" "$configPath")
|
||||
|
||||
echo "$newConfigContent" > "$configPath"
|
||||
}
|
||||
|
||||
# Main script
|
||||
echo "Welcome to the Resolution Configurator"
|
||||
echo ""
|
||||
echo " +---------------------------+"
|
||||
echo " | _____ |"
|
||||
echo " | | | |"
|
||||
echo " | | | |"
|
||||
echo " | |_____| |"
|
||||
echo " | |"
|
||||
echo " +---------------------------+"
|
||||
echo ""
|
||||
echo "Current resolution and refresh rate:"
|
||||
currentRes=$(get_current_resolution)
|
||||
width=$(echo "$currentRes" | awk '{print $1}')
|
||||
height=$(echo "$currentRes" | awk '{print $2}')
|
||||
refreshRate=$(echo "$currentRes" | awk '{print $3}')
|
||||
|
||||
echo "Width: $width px"
|
||||
echo "Height: $height px"
|
||||
echo "Refresh Rate: $refreshRate Hz"
|
||||
|
||||
echo ""
|
||||
|
||||
read -p "Enter new width (or press Enter to keep current width): " newWidth
|
||||
read -p "Enter new height (or press Enter to keep current height): " newHeight
|
||||
read -p "Enter new refresh rate (or press Enter to keep current refresh rate): " newRefreshRate
|
||||
|
||||
# Validate inputs (if provided)
|
||||
if [[ ! "$newWidth" =~ ^[0-9]+$ && -n "$newWidth" ]]; then
|
||||
echo "Invalid width value."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ ! "$newHeight" =~ ^[0-9]+$ && -n "$newHeight" ]]; then
|
||||
echo "Invalid height value."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ ! "$newRefreshRate" =~ ^[0-9]+$ && -n "$newRefreshRate" ]]; then
|
||||
echo "Invalid refresh rate value."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
update_resolution_config "$newWidth" "$newHeight" "$newRefreshRate"
|
||||
|
||||
echo "Resolution updated successfully."
|
||||
198
home/desktops/hyprland/ags/modules/sideleft/tools/color.js
Normal file
198
home/desktops/hyprland/ags/modules/sideleft/tools/color.js
Normal file
@@ -0,0 +1,198 @@
|
||||
// It's weird, I know
|
||||
const { Gio, GLib } = imports.gi;
|
||||
import Service from 'resource:///com/github/Aylur/ags/service.js';
|
||||
import * as Utils from 'resource:///com/github/Aylur/ags/utils.js';
|
||||
const { exec, execAsync } = Utils;
|
||||
import { clamp } from '../../.miscutils/mathfuncs.js';
|
||||
|
||||
export class ColorPickerSelection extends Service {
|
||||
static {
|
||||
Service.register(this, {
|
||||
'picked': [],
|
||||
'assigned': ['int'],
|
||||
'hue': [],
|
||||
'sl': [],
|
||||
});
|
||||
}
|
||||
|
||||
_hue = 198;
|
||||
_xAxis = 94;
|
||||
_yAxis = 80;
|
||||
|
||||
get hue() { return this._hue; }
|
||||
set hue(value) {
|
||||
this._hue = clamp(value, 0, 360);
|
||||
this.emit('hue');
|
||||
this.emit('picked');
|
||||
this.emit('changed');
|
||||
}
|
||||
get xAxis() { return this._xAxis; }
|
||||
set xAxis(value) {
|
||||
this._xAxis = clamp(value, 0, 100);
|
||||
this.emit('sl');
|
||||
this.emit('picked');
|
||||
this.emit('changed');
|
||||
}
|
||||
get yAxis() { return this._yAxis; }
|
||||
set yAxis(value) {
|
||||
this._yAxis = clamp(value, 0, 100);
|
||||
this.emit('sl');
|
||||
this.emit('picked');
|
||||
this.emit('changed');
|
||||
}
|
||||
setColorFromHex(hexString, id) {
|
||||
const hsl = hexToHSL(hexString);
|
||||
this._hue = hsl.hue;
|
||||
this._xAxis = hsl.saturation;
|
||||
// this._yAxis = hsl.lightness;
|
||||
this._yAxis = (100 - hsl.saturation / 2) / 100 * hsl.lightness;
|
||||
// console.log(this._hue, this._xAxis, this._yAxis)
|
||||
this.emit('assigned', id);
|
||||
this.emit('changed');
|
||||
}
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.emit('changed');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export function hslToRgbValues(h, s, l) {
|
||||
h /= 360;
|
||||
s /= 100;
|
||||
l /= 100;
|
||||
let r, g, b;
|
||||
if (s === 0) {
|
||||
r = g = b = l; // achromatic
|
||||
} else {
|
||||
const hue2rgb = (p, q, t) => {
|
||||
if (t < 0) t += 1;
|
||||
if (t > 1) t -= 1;
|
||||
if (t < 1 / 6) return p + (q - p) * 6 * t;
|
||||
if (t < 1 / 2) return q;
|
||||
if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6;
|
||||
return p;
|
||||
};
|
||||
const q = l < 0.5 ? l * (1 + s) : l + s - l * s;
|
||||
const p = 2 * l - q;
|
||||
r = hue2rgb(p, q, h + 1 / 3);
|
||||
g = hue2rgb(p, q, h);
|
||||
b = hue2rgb(p, q, h - 1 / 3);
|
||||
}
|
||||
const to255 = x => Math.round(x * 255);
|
||||
r = to255(r);
|
||||
g = to255(g);
|
||||
b = to255(b);
|
||||
return `${Math.round(r)},${Math.round(g)},${Math.round(b)}`;
|
||||
// return `rgb(${r},${g},${b})`;
|
||||
}
|
||||
export function hslToHex(h, s, l) {
|
||||
h /= 360;
|
||||
s /= 100;
|
||||
l /= 100;
|
||||
let r, g, b;
|
||||
if (s === 0) {
|
||||
r = g = b = l; // achromatic
|
||||
} else {
|
||||
const hue2rgb = (p, q, t) => {
|
||||
if (t < 0) t += 1;
|
||||
if (t > 1) t -= 1;
|
||||
if (t < 1 / 6) return p + (q - p) * 6 * t;
|
||||
if (t < 1 / 2) return q;
|
||||
if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6;
|
||||
return p;
|
||||
};
|
||||
const q = l < 0.5 ? l * (1 + s) : l + s - l * s;
|
||||
const p = 2 * l - q;
|
||||
r = hue2rgb(p, q, h + 1 / 3);
|
||||
g = hue2rgb(p, q, h);
|
||||
b = hue2rgb(p, q, h - 1 / 3);
|
||||
}
|
||||
const toHex = x => {
|
||||
const hex = Math.round(x * 255).toString(16);
|
||||
return hex.length === 1 ? "0" + hex : hex;
|
||||
};
|
||||
return `#${toHex(r)}${toHex(g)}${toHex(b)}`;
|
||||
}
|
||||
|
||||
// export function hexToHSL(hex) {
|
||||
// // Remove the '#' if present
|
||||
// hex = hex.replace(/^#/, '');
|
||||
// // Parse the hex value into RGB components
|
||||
// const bigint = parseInt(hex, 16);
|
||||
// const r = (bigint >> 16) & 255;
|
||||
// const g = (bigint >> 8) & 255;
|
||||
// const b = bigint & 255;
|
||||
// // Normalize RGB values to range [0, 1]
|
||||
// const normalizedR = r / 255;
|
||||
// const normalizedG = g / 255;
|
||||
// const normalizedB = b / 255;
|
||||
// // Find the maximum and minimum values
|
||||
// const max = Math.max(normalizedR, normalizedG, normalizedB);
|
||||
// const min = Math.min(normalizedR, normalizedG, normalizedB);
|
||||
// // Calculate the lightness
|
||||
// const lightness = (max + min) / 2;
|
||||
// // If the color is grayscale, set saturation to 0
|
||||
// if (max === min) {
|
||||
// return {
|
||||
// hue: 0,
|
||||
// saturation: 0,
|
||||
// lightness: lightness * 100 // Convert to percentage
|
||||
// };
|
||||
// }
|
||||
// // Calculate the saturation
|
||||
// const d = max - min;
|
||||
// const saturation = lightness > 0.5 ? d / (2 - max - min) : d / (max + min);
|
||||
// // Calculate the hue
|
||||
// let hue;
|
||||
// if (max === normalizedR) {
|
||||
// hue = ((normalizedG - normalizedB) / d + (normalizedG < normalizedB ? 6 : 0)) * 60;
|
||||
// } else if (max === normalizedG) {
|
||||
// hue = ((normalizedB - normalizedR) / d + 2) * 60;
|
||||
// } else {
|
||||
// hue = ((normalizedR - normalizedG) / d + 4) * 60;
|
||||
// }
|
||||
// return {
|
||||
// hue: Math.round(hue),
|
||||
// saturation: Math.round(saturation * 100), // Convert to percentage
|
||||
// lightness: Math.round(lightness * 100) // Convert to percentage
|
||||
// };
|
||||
// }
|
||||
|
||||
export function hexToHSL(hex) {
|
||||
var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
|
||||
|
||||
var r = parseInt(result[1], 16);
|
||||
var g = parseInt(result[2], 16);
|
||||
var b = parseInt(result[3], 16);
|
||||
|
||||
r /= 255, g /= 255, b /= 255;
|
||||
var max = Math.max(r, g, b), min = Math.min(r, g, b);
|
||||
var h, s, l = (max + min) / 2;
|
||||
|
||||
if (max == min) {
|
||||
h = s = 0; // achromatic
|
||||
} else {
|
||||
var d = max - min;
|
||||
s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
|
||||
switch (max) {
|
||||
case r: h = (g - b) / d + (g < b ? 6 : 0); break;
|
||||
case g: h = (b - r) / d + 2; break;
|
||||
case b: h = (r - g) / d + 4; break;
|
||||
}
|
||||
h /= 6;
|
||||
}
|
||||
|
||||
s = s * 100;
|
||||
s = Math.round(s);
|
||||
l = l * 100;
|
||||
l = Math.round(l);
|
||||
h = Math.round(360 * h);
|
||||
|
||||
return {
|
||||
hue: h,
|
||||
saturation: s,
|
||||
lightness: l
|
||||
};
|
||||
}
|
||||
283
home/desktops/hyprland/ags/modules/sideleft/tools/colorpicker.js
Normal file
283
home/desktops/hyprland/ags/modules/sideleft/tools/colorpicker.js
Normal file
@@ -0,0 +1,283 @@
|
||||
// TODO: Make selection update when entry changes
|
||||
const { Gtk } = imports.gi;
|
||||
import App from 'resource:///com/github/Aylur/ags/app.js';
|
||||
import Variable from 'resource:///com/github/Aylur/ags/variable.js';
|
||||
import Widget from 'resource:///com/github/Aylur/ags/widget.js';
|
||||
import * as Utils from 'resource:///com/github/Aylur/ags/utils.js';
|
||||
const { execAsync, exec } = Utils;
|
||||
const { Box, Button, Entry, EventBox, Icon, Label, Overlay, Scrollable } = Widget;
|
||||
import SidebarModule from './module.js';
|
||||
import { MaterialIcon } from '../../.commonwidgets/materialicon.js';
|
||||
import { setupCursorHover } from '../../.widgetutils/cursorhover.js';
|
||||
|
||||
import { ColorPickerSelection, hslToHex, hslToRgbValues, hexToHSL } from './color.js';
|
||||
import { clamp } from '../../.miscutils/mathfuncs.js';
|
||||
|
||||
export default () => {
|
||||
const selectedColor = new ColorPickerSelection();
|
||||
function shouldUseBlackColor() {
|
||||
return ((selectedColor.xAxis < 40 || (45 <= selectedColor.hue && selectedColor.hue <= 195)) &&
|
||||
selectedColor.yAxis > 60);
|
||||
}
|
||||
const colorBlack = 'rgba(0,0,0,0.9)';
|
||||
const colorWhite = 'rgba(255,255,255,0.9)';
|
||||
const hueRange = Box({
|
||||
homogeneous: true,
|
||||
className: 'sidebar-module-colorpicker-wrapper',
|
||||
children: [Box({
|
||||
className: 'sidebar-module-colorpicker-hue',
|
||||
css: `background: linear-gradient(to bottom, #ff6666, #ffff66, #66dd66, #66ffff, #6666ff, #ff66ff, #ff6666);`,
|
||||
})],
|
||||
});
|
||||
const hueSlider = Box({
|
||||
vpack: 'start',
|
||||
className: 'sidebar-module-colorpicker-cursorwrapper',
|
||||
css: `margin-top: ${13.636 * selectedColor.hue / 360}rem;`,
|
||||
homogeneous: true,
|
||||
children: [Box({
|
||||
className: 'sidebar-module-colorpicker-hue-cursor',
|
||||
})],
|
||||
setup: (self) => self.hook(selectedColor, () => {
|
||||
const widgetHeight = hueRange.children[0].get_allocated_height();
|
||||
self.setCss(`margin-top: ${13.636 * selectedColor.hue / 360}rem;`)
|
||||
}),
|
||||
});
|
||||
const hueSelector = Box({
|
||||
children: [EventBox({
|
||||
child: Overlay({
|
||||
child: hueRange,
|
||||
overlays: [hueSlider],
|
||||
}),
|
||||
attribute: {
|
||||
clicked: false,
|
||||
setHue: (self, event) => {
|
||||
const widgetHeight = hueRange.children[0].get_allocated_height();
|
||||
const [_, cursorX, cursorY] = event.get_coords();
|
||||
const cursorYPercent = clamp(cursorY / widgetHeight, 0, 1);
|
||||
selectedColor.hue = Math.round(cursorYPercent * 360);
|
||||
}
|
||||
},
|
||||
setup: (self) => self
|
||||
.on('motion-notify-event', (self, event) => {
|
||||
if (!self.attribute.clicked) return;
|
||||
self.attribute.setHue(self, event);
|
||||
})
|
||||
.on('button-press-event', (self, event) => {
|
||||
if (!(event.get_button()[1] === 1)) return; // We're only interested in left-click here
|
||||
self.attribute.clicked = true;
|
||||
self.attribute.setHue(self, event);
|
||||
})
|
||||
.on('button-release-event', (self) => self.attribute.clicked = false)
|
||||
,
|
||||
})]
|
||||
});
|
||||
const saturationAndLightnessRange = Box({
|
||||
homogeneous: true,
|
||||
children: [Box({
|
||||
className: 'sidebar-module-colorpicker-saturationandlightness',
|
||||
attribute: {
|
||||
update: (self) => {
|
||||
// css: `background: linear-gradient(to right, #ffffff, color);`,
|
||||
self.setCss(`background:
|
||||
linear-gradient(to bottom, rgba(0,0,0,0), rgba(0,0,0,1)),
|
||||
linear-gradient(to right, #ffffff, ${hslToHex(selectedColor.hue, 100, 50)});
|
||||
`);
|
||||
},
|
||||
},
|
||||
setup: (self) => self
|
||||
.hook(selectedColor, self.attribute.update, 'hue')
|
||||
.hook(selectedColor, self.attribute.update, 'assigned')
|
||||
,
|
||||
})],
|
||||
});
|
||||
const saturationAndLightnessCursor = Box({
|
||||
className: 'sidebar-module-colorpicker-saturationandlightness-cursorwrapper',
|
||||
children: [Box({
|
||||
vpack: 'start',
|
||||
hpack: 'start',
|
||||
homogeneous: true,
|
||||
css: `
|
||||
margin-left: ${13.636 * selectedColor.xAxis / 100}rem;
|
||||
margin-top: ${13.636 * (100 - selectedColor.yAxis) / 100}rem;
|
||||
`, // Why 13.636rem? see class name in stylesheet
|
||||
attribute: {
|
||||
update: (self) => {
|
||||
const allocation = saturationAndLightnessRange.children[0].get_allocation();
|
||||
self.setCss(`
|
||||
margin-left: ${13.636 * selectedColor.xAxis / 100}rem;
|
||||
margin-top: ${13.636 * (100 - selectedColor.yAxis) / 100}rem;
|
||||
`); // Why 13.636rem? see class name in stylesheet
|
||||
}
|
||||
},
|
||||
setup: (self) => self
|
||||
.hook(selectedColor, self.attribute.update, 'sl')
|
||||
.hook(selectedColor, self.attribute.update, 'assigned')
|
||||
,
|
||||
children: [Box({
|
||||
className: 'sidebar-module-colorpicker-saturationandlightness-cursor',
|
||||
css: `
|
||||
background-color: ${hslToHex(selectedColor.hue, selectedColor.xAxis, selectedColor.yAxis / (1 + selectedColor.xAxis / 100))};
|
||||
border-color: ${shouldUseBlackColor() ? colorBlack : colorWhite};
|
||||
`,
|
||||
attribute: {
|
||||
update: (self) => {
|
||||
self.setCss(`
|
||||
background-color: ${hslToHex(selectedColor.hue, selectedColor.xAxis, selectedColor.yAxis / (1 + selectedColor.xAxis / 100))};
|
||||
border-color: ${shouldUseBlackColor() ? colorBlack : colorWhite};
|
||||
`);
|
||||
}
|
||||
},
|
||||
setup: (self) => self
|
||||
.hook(selectedColor, self.attribute.update, 'sl')
|
||||
.hook(selectedColor, self.attribute.update, 'hue')
|
||||
.hook(selectedColor, self.attribute.update, 'assigned')
|
||||
,
|
||||
})],
|
||||
})]
|
||||
});
|
||||
const saturationAndLightnessSelector = Box({
|
||||
homogeneous: true,
|
||||
className: 'sidebar-module-colorpicker-saturationandlightness-wrapper',
|
||||
children: [EventBox({
|
||||
child: Overlay({
|
||||
child: saturationAndLightnessRange,
|
||||
overlays: [saturationAndLightnessCursor],
|
||||
}),
|
||||
attribute: {
|
||||
clicked: false,
|
||||
setSaturationAndLightness: (self, event) => {
|
||||
const allocation = saturationAndLightnessRange.children[0].get_allocation();
|
||||
const [_, cursorX, cursorY] = event.get_coords();
|
||||
const cursorXPercent = clamp(cursorX / allocation.width, 0, 1);
|
||||
const cursorYPercent = clamp(cursorY / allocation.height, 0, 1);
|
||||
selectedColor.xAxis = Math.round(cursorXPercent * 100);
|
||||
selectedColor.yAxis = Math.round(100 - cursorYPercent * 100);
|
||||
}
|
||||
},
|
||||
setup: (self) => self
|
||||
.on('motion-notify-event', (self, event) => {
|
||||
if (!self.attribute.clicked) return;
|
||||
self.attribute.setSaturationAndLightness(self, event);
|
||||
})
|
||||
.on('button-press-event', (self, event) => {
|
||||
if (!(event.get_button()[1] === 1)) return; // We're only interested in left-click here
|
||||
self.attribute.clicked = true;
|
||||
self.attribute.setSaturationAndLightness(self, event);
|
||||
})
|
||||
.on('button-release-event', (self) => self.attribute.clicked = false)
|
||||
,
|
||||
})]
|
||||
});
|
||||
const resultColorBox = Box({
|
||||
className: 'sidebar-module-colorpicker-result-box',
|
||||
homogeneous: true,
|
||||
css: `background-color: ${hslToHex(selectedColor.hue, selectedColor.xAxis, selectedColor.yAxis / (1 + selectedColor.xAxis / 100))};`,
|
||||
children: [Label({
|
||||
className: 'txt txt-small',
|
||||
label: 'Result',
|
||||
}),],
|
||||
attribute: {
|
||||
update: (self) => {
|
||||
self.setCss(`background-color: ${hslToHex(selectedColor.hue, selectedColor.xAxis, selectedColor.yAxis / (1 + selectedColor.xAxis / 100))};`);
|
||||
self.children[0].setCss(`color: ${shouldUseBlackColor() ? colorBlack : colorWhite};`)
|
||||
}
|
||||
},
|
||||
setup: (self) => self
|
||||
.hook(selectedColor, self.attribute.update, 'sl')
|
||||
.hook(selectedColor, self.attribute.update, 'hue')
|
||||
.hook(selectedColor, self.attribute.update, 'assigned')
|
||||
,
|
||||
});
|
||||
const ResultBox = ({ colorSystemName, updateCallback, copyCallback }) => Box({
|
||||
children: [
|
||||
Box({
|
||||
vertical: true,
|
||||
hexpand: true,
|
||||
children: [
|
||||
Label({
|
||||
xalign: 0,
|
||||
className: 'txt-tiny',
|
||||
label: colorSystemName,
|
||||
}),
|
||||
Overlay({
|
||||
child: Entry({
|
||||
widthChars: 10,
|
||||
className: 'txt-small techfont',
|
||||
attribute: {
|
||||
id: 0,
|
||||
update: updateCallback,
|
||||
},
|
||||
setup: (self) => self
|
||||
.hook(selectedColor, self.attribute.update, 'sl')
|
||||
.hook(selectedColor, self.attribute.update, 'hue')
|
||||
.hook(selectedColor, self.attribute.update, 'assigned')
|
||||
// .on('activate', (self) => {
|
||||
// const newColor = self.text;
|
||||
// if (newColor.length != 7) return;
|
||||
// selectedColor.setColorFromHex(self.text, self.attribute.id);
|
||||
// })
|
||||
,
|
||||
}),
|
||||
})
|
||||
]
|
||||
}),
|
||||
Button({
|
||||
child: MaterialIcon('content_copy', 'norm'),
|
||||
onClicked: (self) => {
|
||||
copyCallback(self);
|
||||
self.child.label = 'done';
|
||||
Utils.timeout(1000, () => self.child.label = 'content_copy');
|
||||
},
|
||||
setup: setupCursorHover,
|
||||
})
|
||||
]
|
||||
});
|
||||
const resultHex = ResultBox({
|
||||
colorSystemName: 'Hex',
|
||||
updateCallback: (self, id) => {
|
||||
if (id && self.attribute.id === id) return;
|
||||
self.text = hslToHex(selectedColor.hue, selectedColor.xAxis, selectedColor.yAxis / (1 + selectedColor.xAxis / 100));
|
||||
},
|
||||
copyCallback: () => Utils.execAsync(['wl-copy', `${hslToHex(selectedColor.hue, selectedColor.xAxis, selectedColor.yAxis / (1 + selectedColor.xAxis / 100))}`]),
|
||||
})
|
||||
const resultRgb = ResultBox({
|
||||
colorSystemName: 'RGB',
|
||||
updateCallback: (self, id) => {
|
||||
if (id && self.attribute.id === id) return;
|
||||
self.text = hslToRgbValues(selectedColor.hue, selectedColor.xAxis, selectedColor.yAxis / (1 + selectedColor.xAxis / 100));
|
||||
},
|
||||
copyCallback: () => Utils.execAsync(['wl-copy', `rgb(${hslToRgbValues(selectedColor.hue, selectedColor.xAxis, selectedColor.yAxis / (1 + selectedColor.xAxis / 100))})`]),
|
||||
})
|
||||
const resultHsl = ResultBox({
|
||||
colorSystemName: 'HSL',
|
||||
updateCallback: (self, id) => {
|
||||
if (id && self.attribute.id === id) return;
|
||||
self.text = `${selectedColor.hue},${selectedColor.xAxis}%,${Math.round(selectedColor.yAxis / (1 + selectedColor.xAxis / 100))}%`;
|
||||
},
|
||||
copyCallback: () => Utils.execAsync(['wl-copy', `hsl(${selectedColor.hue},${selectedColor.xAxis}%,${Math.round(selectedColor.yAxis / (1 + selectedColor.xAxis / 100))}%)`]),
|
||||
})
|
||||
const result = Box({
|
||||
className: 'sidebar-module-colorpicker-result-area spacing-v-5 txt',
|
||||
hexpand: true,
|
||||
vertical: true,
|
||||
children: [
|
||||
resultColorBox,
|
||||
resultHex,
|
||||
resultRgb,
|
||||
resultHsl,
|
||||
]
|
||||
})
|
||||
return SidebarModule({
|
||||
icon: MaterialIcon('colorize', 'norm'),
|
||||
name: '<span strikethrough="true">Inaccurate</span> Color picker',
|
||||
revealChild: false,
|
||||
child: Box({
|
||||
className: 'spacing-h-5',
|
||||
children: [
|
||||
hueSelector,
|
||||
saturationAndLightnessSelector,
|
||||
result,
|
||||
]
|
||||
})
|
||||
});
|
||||
}
|
||||
57
home/desktops/hyprland/ags/modules/sideleft/tools/module.js
Normal file
57
home/desktops/hyprland/ags/modules/sideleft/tools/module.js
Normal file
@@ -0,0 +1,57 @@
|
||||
import Widget from 'resource:///com/github/Aylur/ags/widget.js';
|
||||
import { setupCursorHover } from '../../.widgetutils/cursorhover.js';
|
||||
import { MaterialIcon } from '../../.commonwidgets/materialicon.js';
|
||||
const { Box, Button, Icon, Label, Revealer } = Widget;
|
||||
|
||||
export default ({
|
||||
icon,
|
||||
name,
|
||||
child,
|
||||
revealChild = true,
|
||||
}) => {
|
||||
const headerButtonIcon = MaterialIcon(revealChild ? 'expand_less' : 'expand_more', 'norm');
|
||||
const header = Button({
|
||||
onClicked: () => {
|
||||
content.revealChild = !content.revealChild;
|
||||
headerButtonIcon.label = content.revealChild ? 'expand_less' : 'expand_more';
|
||||
},
|
||||
setup: setupCursorHover,
|
||||
child: Box({
|
||||
className: 'txt spacing-h-10',
|
||||
children: [
|
||||
icon,
|
||||
Label({
|
||||
className: 'txt-norm',
|
||||
label: `${name}`,
|
||||
useMarkup: true,
|
||||
}),
|
||||
Box({
|
||||
hexpand: true,
|
||||
}),
|
||||
Box({
|
||||
className: 'sidebar-module-btn-arrow',
|
||||
homogeneous: true,
|
||||
children: [headerButtonIcon],
|
||||
})
|
||||
]
|
||||
})
|
||||
});
|
||||
const content = Revealer({
|
||||
revealChild: revealChild,
|
||||
transition: 'slide_down',
|
||||
transitionDuration: userOptions.animations.durationLarge,
|
||||
child: Box({
|
||||
className: 'margin-top-5',
|
||||
homogeneous: true,
|
||||
children: [child],
|
||||
}),
|
||||
});
|
||||
return Box({
|
||||
className: 'sidebar-module',
|
||||
vertical: true,
|
||||
children: [
|
||||
header,
|
||||
content,
|
||||
]
|
||||
});
|
||||
}
|
||||
26
home/desktops/hyprland/ags/modules/sideleft/tools/name.js
Normal file
26
home/desktops/hyprland/ags/modules/sideleft/tools/name.js
Normal file
@@ -0,0 +1,26 @@
|
||||
const { Gtk } = imports.gi;
|
||||
import App from 'resource:///com/github/Aylur/ags/app.js';
|
||||
import Widget from 'resource:///com/github/Aylur/ags/widget.js';
|
||||
import * as Utils from 'resource:///com/github/Aylur/ags/utils.js';
|
||||
import { setupCursorHover } from '../../.widgetutils/cursorhover.js';
|
||||
const { execAsync, exec } = Utils;
|
||||
const { Box, Button, CenterBox, EventBox, Icon, Label, Scrollable } = Widget;
|
||||
|
||||
export default () => Box({
|
||||
className: 'txt sidebar-module techfont',
|
||||
children: [
|
||||
Label({
|
||||
label: 'illogical-impulse'
|
||||
}),
|
||||
Box({ hexpand: true }),
|
||||
Button({
|
||||
className: 'sidebar-module-btn-arrow',
|
||||
onClicked: () => execAsync(['xdg-open', 'https://github.com/end-4/dots-hyprland']).catch(print),
|
||||
child: Icon({
|
||||
className: 'txt txt-norm',
|
||||
icon: 'github-symbolic',
|
||||
}),
|
||||
setup: setupCursorHover,
|
||||
})
|
||||
]
|
||||
})
|
||||
@@ -0,0 +1,103 @@
|
||||
const { Gtk } = imports.gi;
|
||||
import App from 'resource:///com/github/Aylur/ags/app.js';
|
||||
import Widget from 'resource:///com/github/Aylur/ags/widget.js';
|
||||
import * as Utils from 'resource:///com/github/Aylur/ags/utils.js';
|
||||
const { execAsync, exec } = Utils;
|
||||
const { Box, Button, EventBox, Icon, Label, Scrollable } = Widget;
|
||||
import SidebarModule from './module.js';
|
||||
import { MaterialIcon } from '../../.commonwidgets/materialicon.js';
|
||||
import { setupCursorHover } from '../../.widgetutils/cursorhover.js';
|
||||
|
||||
import { distroID, isArchDistro, isDebianDistro, hasFlatpak } from '../../.miscutils/system.js';
|
||||
|
||||
const scripts = [
|
||||
{
|
||||
icon: 'desktop-symbolic',
|
||||
name: 'Change screen resolution',
|
||||
command: `bash ${App.configDir}/modules/sideleft/tools/changeres.sh`,
|
||||
enabled: true,
|
||||
},
|
||||
{
|
||||
icon: 'nixos-symbolic',
|
||||
name: 'Trim system generations to 5',
|
||||
command: `sudo ${App.configDir}/scripts/quickscripts/nixos-trim-generations.sh 5 0 system`,
|
||||
enabled: distroID == 'nixos',
|
||||
},
|
||||
{
|
||||
icon: 'nixos-symbolic',
|
||||
name: 'Trim home manager generations to 5',
|
||||
command: `${App.configDir}/scripts/quickscripts/nixos-trim-generations.sh 5 0 home-manager`,
|
||||
enabled: distroID == 'nixos',
|
||||
},
|
||||
{
|
||||
icon: 'ubuntu-symbolic',
|
||||
name: 'Update packages',
|
||||
command: `sudo apt update && sudo apt upgrade -y`,
|
||||
enabled: isDebianDistro,
|
||||
},
|
||||
{
|
||||
icon: 'fedora-symbolic',
|
||||
name: 'Update packages',
|
||||
command: `sudo dnf upgrade -y`,
|
||||
enabled: distroID == 'fedora',
|
||||
},
|
||||
{
|
||||
icon: 'arch-symbolic',
|
||||
name: 'Update packages',
|
||||
command: `sudo pacman -Syyu`,
|
||||
enabled: isArchDistro,
|
||||
},
|
||||
{
|
||||
icon: 'arch-symbolic',
|
||||
name: 'Remove orphan packages',
|
||||
command: `sudo pacman -R $(pacman -Qdtq)`,
|
||||
enabled: isArchDistro,
|
||||
},
|
||||
{
|
||||
icon: 'flatpak-symbolic',
|
||||
name: 'Uninstall unused flatpak packages',
|
||||
command: `flatpak uninstall --unused`,
|
||||
enabled: hasFlatpak,
|
||||
},
|
||||
];
|
||||
|
||||
export default () => SidebarModule({
|
||||
icon: MaterialIcon('code', 'norm'),
|
||||
name: 'Quick scripts',
|
||||
child: Box({
|
||||
vertical: true,
|
||||
className: 'spacing-v-5',
|
||||
children: scripts.map((script) => {
|
||||
if (!script.enabled) return null;
|
||||
const scriptStateIcon = MaterialIcon('not_started', 'norm');
|
||||
return Box({
|
||||
className: 'spacing-h-5 txt',
|
||||
children: [
|
||||
Icon({
|
||||
className: 'sidebar-module-btn-icon txt-large',
|
||||
icon: script.icon,
|
||||
}),
|
||||
Label({
|
||||
className: 'txt-small',
|
||||
hpack: 'start',
|
||||
hexpand: true,
|
||||
label: script.name,
|
||||
tooltipText: script.command,
|
||||
}),
|
||||
Button({
|
||||
className: 'sidebar-module-scripts-button',
|
||||
child: scriptStateIcon,
|
||||
onClicked: () => {
|
||||
closeEverything();
|
||||
execAsync([`bash`, `-c`, `${userOptions.apps.terminal} fish -C "${script.command}"`]).catch(print)
|
||||
.then(() => {
|
||||
scriptStateIcon.label = 'done';
|
||||
})
|
||||
},
|
||||
setup: setupCursorHover,
|
||||
}),
|
||||
],
|
||||
})
|
||||
}),
|
||||
})
|
||||
});
|
||||
Reference in New Issue
Block a user