Add systray
This commit is contained in:
parent
9fa4194b43
commit
46c13c0fb1
@ -1,3 +1,9 @@
|
||||
pika-hyprland-settings (1.1.3-99pika1) lunar; urgency=medium
|
||||
|
||||
* Add systray
|
||||
|
||||
-- ferrreo <harderthanfire@gmail.com> Sat, 01 Oct 2022 14:50:00 +0300
|
||||
|
||||
pika-hyprland-settings (1.1.2-99pika1) lunar; urgency=medium
|
||||
|
||||
* Fix weather
|
||||
|
@ -11,6 +11,11 @@ cp -f /etc/skel/.config/examples/.profile /etc/skel/
|
||||
then
|
||||
cp -a /etc/skel/. "${u}/"
|
||||
fi
|
||||
|
||||
if ! test -f "${u}/.config/ags/widgets/systray.js"
|
||||
then
|
||||
cp -af /etc/skel/.config/ags/. "${u}/.config/ags/"
|
||||
fi
|
||||
done
|
||||
|
||||
mkdir -p /etc/greetd/
|
||||
|
7
pika-hyprland-settings/etc/skel/.config/ags/barConfig.js
Normal file
7
pika-hyprland-settings/etc/skel/.config/ags/barConfig.js
Normal file
@ -0,0 +1,7 @@
|
||||
export default {
|
||||
numberOfWorkspaces: 10,
|
||||
city: "Stoke-On-Trent",
|
||||
weatherUpdateInterval: 900,
|
||||
isAmerican: false,
|
||||
sysinfoUpdateInterval: "2s",
|
||||
}
|
@ -14,4 +14,4 @@ export default {
|
||||
bar,
|
||||
calendar,
|
||||
],
|
||||
}
|
||||
};
|
163
pika-hyprland-settings/etc/skel/.config/ags/lib.js
Normal file
163
pika-hyprland-settings/etc/skel/.config/ags/lib.js
Normal file
@ -0,0 +1,163 @@
|
||||
import barConfig from './barConfig.js';
|
||||
|
||||
export const getTemp = (temp) => {
|
||||
if (barConfig?.isAmerican) {
|
||||
return Math.round((temp * 9 / 5) + 32) + "°F";
|
||||
}
|
||||
return temp + "°C";
|
||||
};
|
||||
|
||||
export const getWeatherSymbol = (weatherCode) => {
|
||||
const dt = new Date();
|
||||
const hour = dt.getHours();
|
||||
if (hour < 7 || hour > 21) {
|
||||
return NIGHT_WEATHER_SYMBOL[WWO_CODE[weatherCode]];
|
||||
}
|
||||
return WEATHER_SYMBOL[WWO_CODE[weatherCode]];
|
||||
};
|
||||
|
||||
export const getFormattedTime = () => {
|
||||
const date = new Date();
|
||||
let hours = date.getHours();
|
||||
let minutes = date.getMinutes();
|
||||
if (hours < 10) hours = "0" + hours;
|
||||
if (minutes < 10) minutes = "0" + minutes;
|
||||
return `${hours}:${minutes}`
|
||||
}
|
||||
|
||||
export const getFormattedDate = () => {
|
||||
const date = new Date();
|
||||
const day = date.getDay();
|
||||
const month = date.getMonth();
|
||||
let dayOfMonth = date.getDate();
|
||||
switch (dayOfMonth) {
|
||||
case 1:
|
||||
case 21:
|
||||
case 31:
|
||||
dayOfMonth += "st";
|
||||
break;
|
||||
case 2:
|
||||
case 22:
|
||||
dayOfMonth += "nd";
|
||||
break;
|
||||
case 3:
|
||||
case 23:
|
||||
dayOfMonth += "rd";
|
||||
break;
|
||||
default:
|
||||
dayOfMonth += "th";
|
||||
}
|
||||
|
||||
return `${days[day]}, ${dayOfMonth} ${months[month]}`;
|
||||
}
|
||||
|
||||
export const getBattery = (batt) => {
|
||||
if (batt?.charging) {
|
||||
return "battery_charging_full";
|
||||
}
|
||||
if (batt?.charged) {
|
||||
return "battery_full";
|
||||
}
|
||||
|
||||
return battIcons[Math.floor(battIcons.length * (batt?.percent / 100))];
|
||||
}
|
||||
|
||||
const battIcons = ["battery_0_bar","battery_1_bar","battery_2_bar","battery_3_bar","battery_4_bar","battery_5_bar", "battery_6_bar"];
|
||||
|
||||
const days = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];
|
||||
const months = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
|
||||
|
||||
const WWO_CODE = {
|
||||
"113": "Sunny",
|
||||
"116": "PartlyCloudy",
|
||||
"119": "Cloudy",
|
||||
"122": "VeryCloudy",
|
||||
"143": "Fog",
|
||||
"176": "LightShowers",
|
||||
"179": "LightSleetShowers",
|
||||
"182": "LightSleet",
|
||||
"185": "LightSleet",
|
||||
"200": "ThunderyShowers",
|
||||
"227": "LightSnow",
|
||||
"230": "HeavySnow",
|
||||
"248": "Fog",
|
||||
"260": "Fog",
|
||||
"263": "LightShowers",
|
||||
"266": "LightRain",
|
||||
"281": "LightSleet",
|
||||
"284": "LightSleet",
|
||||
"293": "LightRain",
|
||||
"296": "LightRain",
|
||||
"299": "HeavyShowers",
|
||||
"302": "HeavyRain",
|
||||
"305": "HeavyShowers",
|
||||
"308": "HeavyRain",
|
||||
"311": "LightSleet",
|
||||
"314": "LightSleet",
|
||||
"317": "LightSleet",
|
||||
"320": "LightSnow",
|
||||
"323": "LightSnowShowers",
|
||||
"326": "LightSnowShowers",
|
||||
"329": "HeavySnow",
|
||||
"332": "HeavySnow",
|
||||
"335": "HeavySnowShowers",
|
||||
"338": "HeavySnow",
|
||||
"350": "LightSleet",
|
||||
"353": "LightShowers",
|
||||
"356": "HeavyShowers",
|
||||
"359": "HeavyRain",
|
||||
"362": "LightSleetShowers",
|
||||
"365": "LightSleetShowers",
|
||||
"368": "LightSnowShowers",
|
||||
"371": "HeavySnowShowers",
|
||||
"374": "LightSleetShowers",
|
||||
"377": "LightSleet",
|
||||
"386": "ThunderyShowers",
|
||||
"389": "ThunderyHeavyRain",
|
||||
"392": "ThunderySnowShowers",
|
||||
"395": "HeavySnowShowers",
|
||||
}
|
||||
|
||||
const WEATHER_SYMBOL = {
|
||||
"Unknown": "air",
|
||||
"Cloudy": "cloud",
|
||||
"Fog": "foggy",
|
||||
"HeavyRain": "rainy",
|
||||
"HeavyShowers": "rainy",
|
||||
"HeavySnow": "snowing",
|
||||
"HeavySnowShowers": "snowing",
|
||||
"LightRain": "rainy",
|
||||
"LightShowers": "rainy",
|
||||
"LightSleet": "rainy",
|
||||
"LightSleetShowers": "rainy",
|
||||
"LightSnow": "cloudy_snowing",
|
||||
"LightSnowShowers": "cloudy_snowing",
|
||||
"PartlyCloudy": "partly_cloudy_day",
|
||||
"Sunny": "clear_day",
|
||||
"ThunderyHeavyRain": "thunderstorm",
|
||||
"ThunderyShowers": "thunderstorm",
|
||||
"ThunderySnowShowers": "thunderstorm",
|
||||
"VeryCloudy": "cloud",
|
||||
}
|
||||
|
||||
const NIGHT_WEATHER_SYMBOL = {
|
||||
"Unknown": "air",
|
||||
"Cloudy": "cloud",
|
||||
"Fog": "foggy",
|
||||
"HeavyRain": "rainy",
|
||||
"HeavyShowers": "rainy",
|
||||
"HeavySnow": "snowing",
|
||||
"HeavySnowShowers": "snowing",
|
||||
"LightRain": "rainy",
|
||||
"LightShowers": "rainy",
|
||||
"LightSleet": "rainy",
|
||||
"LightSleetShowers": "rainy",
|
||||
"LightSnow": "cloudy_snowing",
|
||||
"LightSnowShowers": "cloudy_snowing",
|
||||
"PartlyCloudy": "partly_cloudy_night",
|
||||
"Sunny": "clear_night",
|
||||
"ThunderyHeavyRain": "thunderstorm",
|
||||
"ThunderyShowers": "thunderstorm",
|
||||
"ThunderySnowShowers": "thunderstorm",
|
||||
"VeryCloudy": "cloud",
|
||||
}
|
@ -5,6 +5,7 @@ import { Mem } from "../widgets/mem.js";
|
||||
import { Clock } from "../widgets/clock.js";
|
||||
import { Weather } from '../widgets/weather.js';
|
||||
import { Batt } from '../widgets/batt.js';
|
||||
import { Systray } from "../widgets/systray.js";
|
||||
|
||||
export const System = () => Widget.EventBox({
|
||||
onPrimaryClick: () => App.toggleWindow('calendar'),
|
||||
@ -24,6 +25,7 @@ export const System = () => Widget.EventBox({
|
||||
Mem(),
|
||||
Batt(),
|
||||
Weather(),
|
||||
Systray(),
|
||||
Clock()
|
||||
],
|
||||
}),
|
||||
|
@ -1,6 +1,7 @@
|
||||
const { Widget } = ags;
|
||||
const { execAsync } = ags.Utils;
|
||||
import { gohypr } from '../services/gohypr.js';
|
||||
import barConfig from '../barConfig.js';
|
||||
|
||||
export const Workspaces = () => Widget.EventBox({
|
||||
onScrollUp: () => execAsync('hyprctl dispatch workspace -1'),
|
||||
@ -10,7 +11,7 @@ export const Workspaces = () => Widget.EventBox({
|
||||
Widget.Box({
|
||||
halign: 'center',
|
||||
children: [Widget.Box({
|
||||
children: Array.from({ length: 10 }, (_, i) => i + 1).map(i => (Widget.Button({
|
||||
children: Array.from({ length: barConfig?.numberOfWorkspaces }, (_, i) => i + 1).map(i => (Widget.Button({
|
||||
className: 'bar-ws-button',
|
||||
onClicked: () => execAsync(`hyprctl dispatch workspace ${i}`).catch(print),
|
||||
child: Widget.Label({
|
||||
|
@ -1,10 +1,10 @@
|
||||
[general]
|
||||
|
||||
mode = normal
|
||||
framerate = 15
|
||||
autosens = 0
|
||||
framerate = 30
|
||||
autosens = 1
|
||||
;overshoot = 10
|
||||
sensitivity = 750
|
||||
;sensitivity = 750
|
||||
bars = 15
|
||||
|
||||
[input]
|
||||
@ -35,4 +35,4 @@ gradient_color_8 = '#C1838E'
|
||||
[smoothing]
|
||||
monstercat = 1
|
||||
gravity = 1000000
|
||||
noise_reduction = 0.34
|
||||
noise_reduction = 34
|
||||
|
Binary file not shown.
@ -431,12 +431,17 @@ calendar {
|
||||
}
|
||||
|
||||
tooltip {
|
||||
background-color: $background;
|
||||
color: $onBackground;
|
||||
border-radius: 5rem;
|
||||
padding: 1rem;
|
||||
margin: 1rem;
|
||||
border: 1px solid $onBackground;
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
|
||||
> * > *{
|
||||
background-color: $background;
|
||||
border-radius: 1.5rem;
|
||||
color: $onBackground;
|
||||
padding: 1rem;
|
||||
margin: 0.5rem;
|
||||
box-shadow: 0.25rem 0 0.25rem 0 $background;
|
||||
}
|
||||
}
|
||||
|
||||
.musicbox {
|
||||
@ -464,3 +469,36 @@ tooltip {
|
||||
background-color: $secondaryContainer;
|
||||
}
|
||||
}
|
||||
|
||||
.systray-icon {
|
||||
margin-right: 0.5rem;
|
||||
margin-left: 0.25rem;
|
||||
}
|
||||
|
||||
menu {
|
||||
background: shade($background, 70%);
|
||||
border-radius: 12px;
|
||||
border: 2px solid shade($secondaryContainer, 40%);
|
||||
margin-top: 2rem;
|
||||
padding: 1rem 0;
|
||||
color: $onBackground;
|
||||
}
|
||||
|
||||
menu > menuitem {
|
||||
padding: 0.4em 1.5rem;
|
||||
background: transparent;
|
||||
transition: 0.2s ease background;
|
||||
}
|
||||
|
||||
menu > menuitem:hover {
|
||||
background: rgba(255, 255, 255, 0.4);
|
||||
}
|
||||
|
||||
menu > menuitem check:checked ~ label {
|
||||
color: $onBackground;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
menubar > menuitem {
|
||||
margin-left: 0.6rem;
|
||||
}
|
@ -1,8 +1,7 @@
|
||||
const { App } = ags;
|
||||
import { deflisten } from './deflisten.js';
|
||||
import barConfig from '../barConfig.js';
|
||||
|
||||
const udpateDelay = "2s";
|
||||
|
||||
export const gostat = deflisten('gostat', `${App.configDir}/programs/gostat ${udpateDelay}`, (line) => {
|
||||
export const gostat = deflisten('gostat', `${App.configDir}/programs/gostat ${barConfig.sysinfoUpdateInterval}`, (line) => {
|
||||
return JSON.parse(line);
|
||||
});
|
@ -1,5 +1,6 @@
|
||||
const { Widget } = ags;
|
||||
const { Battery } = ags.Service;
|
||||
import { getBattery } from '../lib.js';
|
||||
|
||||
export const Batt = () => Widget.Box({
|
||||
halign: 'end',
|
||||
@ -34,16 +35,3 @@ export const Batt = () => Widget.Box({
|
||||
}),
|
||||
],
|
||||
});
|
||||
|
||||
function getBattery(batt) {
|
||||
if (batt?.charging) {
|
||||
return "battery_charging_full";
|
||||
}
|
||||
if (batt?.charged) {
|
||||
return "battery_full";
|
||||
}
|
||||
|
||||
return battIcons[Math.floor(battIcons.length * (batt?.percent / 100))];
|
||||
}
|
||||
|
||||
const battIcons = ["battery_0_bar","battery_1_bar","battery_2_bar","battery_3_bar","battery_4_bar","battery_5_bar", "battery_6_bar"];
|
@ -1,4 +1,5 @@
|
||||
const { Widget } = ags;
|
||||
import { getFormattedTime, getFormattedDate } from '../lib.js';
|
||||
|
||||
export const Clock = () => Widget.Box({
|
||||
vertical: true,
|
||||
@ -22,40 +23,3 @@ export const Clock = () => Widget.Box({
|
||||
],
|
||||
});
|
||||
|
||||
function getFormattedTime() {
|
||||
const date = new Date();
|
||||
let hours = date.getHours();
|
||||
let minutes = date.getMinutes();
|
||||
if (hours < 10) hours = "0" + hours;
|
||||
if (minutes < 10) minutes = "0" + minutes;
|
||||
return `${hours}:${minutes}`
|
||||
}
|
||||
|
||||
function getFormattedDate() {
|
||||
const date = new Date();
|
||||
const day = date.getDay();
|
||||
const month = date.getMonth();
|
||||
let dayOfMonth = date.getDate();
|
||||
switch (dayOfMonth) {
|
||||
case 1:
|
||||
case 21:
|
||||
case 31:
|
||||
dayOfMonth += "st";
|
||||
break;
|
||||
case 2:
|
||||
case 22:
|
||||
dayOfMonth += "nd";
|
||||
break;
|
||||
case 3:
|
||||
case 23:
|
||||
dayOfMonth += "rd";
|
||||
break;
|
||||
default:
|
||||
dayOfMonth += "th";
|
||||
}
|
||||
|
||||
return `${days[day]}, ${dayOfMonth} ${months[month]}`;
|
||||
}
|
||||
|
||||
const days = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];
|
||||
const months = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
|
||||
|
@ -1,5 +1,6 @@
|
||||
const { Widget } = ags;
|
||||
import { gostat } from '../services/gostat.js';
|
||||
import { getTemp } from '../lib.js';
|
||||
|
||||
export const CpuTemp = () => Widget.Box({
|
||||
halign: 'end',
|
||||
@ -20,7 +21,7 @@ export const CpuTemp = () => Widget.Box({
|
||||
className: 'txt-norm txt',
|
||||
connections: [[gostat, label => {
|
||||
if (gostat?.state?.cputemp) {
|
||||
label.label = gostat?.state?.cputemp + "°C";
|
||||
label.label = getTemp(gostat?.state?.cputemp);
|
||||
}
|
||||
}]],
|
||||
}),
|
||||
|
@ -0,0 +1,29 @@
|
||||
const { SystemTray } = ags.Service;
|
||||
const { Widget } = ags;
|
||||
|
||||
export const Systray = () => Widget.Box({
|
||||
className: 'systray',
|
||||
connections: [[SystemTray, box => {
|
||||
const arr = SystemTray.items;
|
||||
box.children = arr.map(item =>{
|
||||
const icon = SystemTray.get_icon(item, 24);
|
||||
if (!icon) {
|
||||
return;
|
||||
}
|
||||
icon.set_margin_left(7);
|
||||
const btn = Widget.Button({
|
||||
//call the Activate function when icon is clicked
|
||||
//Note: if item.ItemIsMenu is true, left click should open menu
|
||||
onPrimaryClick: (_, event) => item.ActivateAsync(event.get_root_coords()[1], event.get_root_coords()[2]),
|
||||
//open menu on right click.
|
||||
//Note: if item.Menu is not set item.ContextMenuAsync(x, y) should be called.
|
||||
onSecondaryClick: (_, event) => {
|
||||
item.AgsMenu.popup_at_widget(btn, 8, 2, event);
|
||||
},
|
||||
//show icon
|
||||
className: 'systray-icon',
|
||||
child: icon,
|
||||
tooltipMarkup: SystemTray.get_tooltip_markup(item)
|
||||
} ); return btn;});
|
||||
}]],
|
||||
});
|
@ -27,7 +27,7 @@ export const Visualiser = () => Widget.Box({
|
||||
}
|
||||
let count = 0;
|
||||
for (const child of box.get_children()) {
|
||||
child.fraction = cvjson?.service.state[count] / 1000;
|
||||
child.fraction = cvjson?.service.state[count] / 1500;
|
||||
count++;
|
||||
}
|
||||
}],
|
||||
|
@ -1,7 +1,7 @@
|
||||
const { Widget } = ags;
|
||||
const { exec } = ags.Utils;
|
||||
|
||||
const city = "Stoke-On-Trent";
|
||||
const { execAsync } = ags.Utils;
|
||||
import barConfig from '../barConfig.js';
|
||||
import { getWeatherSymbol, getTemp } from '../lib.js';
|
||||
|
||||
export const Weather = () => Widget.Box({
|
||||
halign: 'end',
|
||||
@ -12,9 +12,9 @@ export const Weather = () => Widget.Box({
|
||||
Widget.Label({
|
||||
halign: 'end',
|
||||
valign: 'center',
|
||||
className: 'txt-larger txt',
|
||||
className: 'txt-larger txt icon-material',
|
||||
style: 'margin-right: 0.5rem; margin-top: 1px;',
|
||||
label: '🌦',
|
||||
label: 'rainy',
|
||||
}),
|
||||
Widget.Label({
|
||||
halign: 'end',
|
||||
@ -22,91 +22,16 @@ export const Weather = () => Widget.Box({
|
||||
className: 'txt-norm txt',
|
||||
}),
|
||||
],
|
||||
connections: [[900000, async box => {
|
||||
try {
|
||||
// timeout here is to delay enough on boot that network has time to connect - this is a hack but for something that updates so rarely it's fine
|
||||
setTimeout(() => {
|
||||
let weather = exec(`curl https://wttr.in/${city}?format=j1`);
|
||||
weather = JSON.parse(weather);
|
||||
const weatherCode = weather.current_condition[0].weatherCode;
|
||||
box.children[0].label = WEATHER_SYMBOL[WWO_CODE[weatherCode]];
|
||||
box.children[1].label = weather.current_condition[0].temp_C + "°C";
|
||||
}, 5000);
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
}
|
||||
connections: [[barConfig?.weatherUpdateInterval * 1000, async box => {
|
||||
setTimeout(() => {
|
||||
execAsync(`curl https://wttr.in/${barConfig?.city}?format=j1`)
|
||||
.then(output => {
|
||||
const weather = JSON.parse(output);
|
||||
const weatherCode = weather.current_condition[0].weatherCode;
|
||||
box.tooltipText = weather.current_condition[0].weatherDesc[0].value;
|
||||
box.children[0].label = getWeatherSymbol(weatherCode);
|
||||
box.children[1].label = getTemp(weather.current_condition[0].temp_C);
|
||||
}).catch(console.error)
|
||||
}, 5000);
|
||||
}]],
|
||||
});
|
||||
|
||||
const WWO_CODE = {
|
||||
"113": "Sunny",
|
||||
"116": "PartlyCloudy",
|
||||
"119": "Cloudy",
|
||||
"122": "VeryCloudy",
|
||||
"143": "Fog",
|
||||
"176": "LightShowers",
|
||||
"179": "LightSleetShowers",
|
||||
"182": "LightSleet",
|
||||
"185": "LightSleet",
|
||||
"200": "ThunderyShowers",
|
||||
"227": "LightSnow",
|
||||
"230": "HeavySnow",
|
||||
"248": "Fog",
|
||||
"260": "Fog",
|
||||
"263": "LightShowers",
|
||||
"266": "LightRain",
|
||||
"281": "LightSleet",
|
||||
"284": "LightSleet",
|
||||
"293": "LightRain",
|
||||
"296": "LightRain",
|
||||
"299": "HeavyShowers",
|
||||
"302": "HeavyRain",
|
||||
"305": "HeavyShowers",
|
||||
"308": "HeavyRain",
|
||||
"311": "LightSleet",
|
||||
"314": "LightSleet",
|
||||
"317": "LightSleet",
|
||||
"320": "LightSnow",
|
||||
"323": "LightSnowShowers",
|
||||
"326": "LightSnowShowers",
|
||||
"329": "HeavySnow",
|
||||
"332": "HeavySnow",
|
||||
"335": "HeavySnowShowers",
|
||||
"338": "HeavySnow",
|
||||
"350": "LightSleet",
|
||||
"353": "LightShowers",
|
||||
"356": "HeavyShowers",
|
||||
"359": "HeavyRain",
|
||||
"362": "LightSleetShowers",
|
||||
"365": "LightSleetShowers",
|
||||
"368": "LightSnowShowers",
|
||||
"371": "HeavySnowShowers",
|
||||
"374": "LightSleetShowers",
|
||||
"377": "LightSleet",
|
||||
"386": "ThunderyShowers",
|
||||
"389": "ThunderyHeavyRain",
|
||||
"392": "ThunderySnowShowers",
|
||||
"395": "HeavySnowShowers",
|
||||
}
|
||||
|
||||
const WEATHER_SYMBOL = {
|
||||
"Unknown": "✨",
|
||||
"Cloudy": "☁️",
|
||||
"Fog": "🌫",
|
||||
"HeavyRain": "🌧",
|
||||
"HeavyShowers": "🌧",
|
||||
"HeavySnow": "❄️",
|
||||
"HeavySnowShowers": "❄️",
|
||||
"LightRain": "🌦",
|
||||
"LightShowers": "🌦",
|
||||
"LightSleet": "🌧",
|
||||
"LightSleetShowers": "🌧",
|
||||
"LightSnow": "🌨",
|
||||
"LightSnowShowers": "🌨",
|
||||
"PartlyCloudy": "⛅️",
|
||||
"Sunny": "☀️",
|
||||
"ThunderyHeavyRain": "🌩",
|
||||
"ThunderyShowers": "⛈",
|
||||
"ThunderySnowShowers": "⛈",
|
||||
"VeryCloudy": "☁️",
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user