feat(ags): transfer remaining bar stuff from v1
All checks were successful
Discord / discord commits (push) Has been skipped

This commit is contained in:
matt1432 2025-02-28 00:59:30 -05:00
parent f0704cba04
commit 7d64a1fe25
8 changed files with 177 additions and 264 deletions

View file

@ -20,6 +20,8 @@
}
&.bluetooth icon,
&.heart-toggle label,
&.keyboard icon,
&.network icon,
&.tablet-mode icon {
min-width: 30px;

View file

@ -0,0 +1,29 @@
import { Variable } from 'astal';
import Persist from '../../misc/persist';
const HeartState = Variable('');
Persist({
name: 'heart',
variable: HeartState,
condition: '',
whenFalse: '󰣐',
});
export default () => (
<button
className="bar-item heart-toggle"
cursor="pointer"
onButtonReleaseEvent={() => {
HeartState.set(HeartState.get() === '' ? '󰣐' : '');
}}
>
<label
label={HeartState()}
css="margin-left: -6px; margin-right: 4px; font-size: 28px;"
/>
</button>
);

View file

@ -0,0 +1,87 @@
import { Variable } from 'astal';
import { Label } from 'astal/gtk3/widget';
import AstalHyprland from 'gi://AstalHyprland';
import { hyprMessage } from '../../../lib';
import { Gtk } from 'astal/gtk3';
/* Types */
interface Keyboard {
address: string
name: string
rules: string
model: string
layout: string
variant: string
options: string
active_keymap: string
main: boolean
}
const DEFAULT_KB = 'at-translated-set-2-keyboard';
export default () => {
const Hovered = Variable(false);
const hyprland = AstalHyprland.get_default();
const getKbdLayout = (self: Label, _: string, layout?: string) => {
if (layout) {
if (layout === 'error') {
return;
}
const shortName = layout.match(/\(([A-Za-z]+)\)/);
self.label = shortName ? shortName[1] : layout;
}
else {
// At launch, kb layout is undefined
hyprMessage('j/devices').then((obj) => {
const keyboards = Array.from(JSON.parse(obj)
.keyboards) as Keyboard[];
const kb = keyboards.find((v) => v.name === DEFAULT_KB);
if (kb) {
layout = kb.active_keymap;
const shortName = layout
.match(/\(([A-Za-z]+)\)/);
self.label = shortName ? shortName[1] : layout;
}
else {
self.label = 'None';
}
}).catch(print);
}
};
return (
<button
className="bar-item keyboard"
cursor="pointer"
onHover={() => Hovered.set(true)}
onHoverLost={() => Hovered.set(false)}
>
<box>
<icon icon="input-keyboard-symbolic" />
<revealer
revealChild={Hovered()}
transitionType={Gtk.RevealerTransitionType.SLIDE_LEFT}
>
<label
setup={(self) => {
self.hook(hyprland, 'keyboard-layout', getKbdLayout);
getKbdLayout(self, '');
}}
/>
</revealer>
</box>
</button>
);
};

View file

@ -7,6 +7,8 @@ import Bluetooth from './items/bluetooth';
import Brightness from './items/brightness';
import Clock from './items/clock';
import CurrentClient from './items/current-client';
import Heart from './items/heart';
import Keyboard from './items/keyboard-layout';
import Network from './items/network';
import NotifButton from './items/notif-button';
import SysTray from './items/tray';
@ -52,6 +54,10 @@ export default () => (
/>
</button>
<Separator size={8} />
<Heart />
<CurrentClient />
<Separator size={8} />
@ -70,6 +76,10 @@ export default () => (
<Separator size={8} />
<Keyboard />
<Separator size={8} />
<NotifButton />
<Separator size={8} />

View file

@ -0,0 +1,49 @@
import { execAsync, readFileAsync, timeout, GLib, type Variable } from 'astal';
const { get_home_dir } = GLib;
export default <T>({
name,
variable,
condition = true,
whenTrue = condition,
whenFalse = false,
}: {
name: string
variable: Variable<T>
condition?: boolean | string
whenTrue?: boolean | string
whenFalse?: boolean | string
}) => {
const cacheFile = `${get_home_dir()}/.cache/ags/.${name}`;
const stateCmd = () => ['bash', '-c',
`echo ${variable.get() === condition} > ${cacheFile}`];
const monitorState = () => {
variable.subscribe(() => {
execAsync(stateCmd()).catch(print);
});
};
readFileAsync(cacheFile)
.then((content) => {
// JSON.parse was the only way I found to reliably
// convert a string of 'true' or 'false' into a bool
const value = (JSON.parse(content) ? whenTrue : whenFalse) as T;
variable.set(value);
timeout(1000, () => {
monitorState();
});
})
.catch(() => {
execAsync(stateCmd())
.then(() => {
monitorState();
})
.catch(print);
});
};

View file

@ -1,184 +0,0 @@
.quick-settings {
font-size: 30px;
min-width: 500px;
padding: 0;
background-color: $bg;
border-radius: 30px 0 30px 30px;
border: 2px solid $contrast-bg;
}
.title {
font-size: 22px;
margin-top: 30px;
}
.grid-label {
font-size: 30px;
margin-left: 15px;
margin-right: 10px;
min-width: 50px;
}
.scrolled-indicator {
margin: 5px 0;
}
.menu {
margin: 10px;
padding: 0;
border: 1.5px solid $contrast-bg;
border-radius: 10px;
font-size: 12px;
scrolledwindow {
padding: 3px;
}
row {
padding: 0;
margin: 0;
}
.menu-item {
margin: 5px;
label {
font-size: 16px;
margin-left: 5px;
}
image {
font-size: 20px;
}
}
}
.sub-label {
font-size: 14px;
padding: 3px;
border: 2px solid $contrast-bg;
border-radius: 10px 20px 20px 10px;
min-width: 106px;
background: #1b1b1b;
margin-top: 5px;
}
.grid-chev {
margin-left: 10px;
margin-right: 12px;
font-size: 25px;
transition: -gtk-icon-transform 0.3s ease-in-out;
}
.button-grid {
font-size: 10px;
min-width: 440px;
background-color: $bgfull;
border-top: 2px solid $contrast-bg;
border-bottom: 2px solid $contrast-bg;
border-radius: 15px;
padding: 10px 15px;
}
.grid-button {
min-height: 65px;
min-width: 70px;
}
.left-part {
background: #1b1b1b;
border-top-left-radius: 15px;
border-bottom-left-radius: 15px;
border-left: 2px solid $contrast-bg;
border-top: 2px solid $contrast-bg;
border-bottom: 2px solid $contrast-bg;
transition: all 0.5s ease-in-out;
}
.right-part {
background: #1b1b1b;
border-top-right-radius: 30px;
border-bottom-right-radius: 30px;
border-right: 2px solid $contrast-bg;
border-top: 2px solid $contrast-bg;
border-bottom: 2px solid $contrast-bg;
transition: all 0.5s ease-in-out;
}
.right-part:hover,
.right-part:active {
color: $contrast-bg;
border: 2px solid $contrast-bg;
border-top-left-radius: 7px;
border-bottom-left-radius: 7px;
transition: all 0.5s ease-in-out;
}
.left-part:hover,
.left-part:active {
color: $contrast-bg;
border: 2px solid $contrast-bg;
border-top-right-radius: 7px;
border-bottom-right-radius: 7px;
transition: all 0.5s ease-in-out;
}
.player {
margin-top: 6px;
min-height: 220px;
opacity: 0;
}
.slider-box {
min-height: 100px;
min-width: 470px;
background-color: $bgfull;
border-top: 2px solid $contrast-bg;
border-bottom: 2px solid $contrast-bg;
border-radius: 15px;
margin-top: 30px;
margin-bottom: 20px;
.slider-label {
font-size: 30px;
min-width: 40px;
margin-right: -20px;
}
.slider {
min-height: 55px;
margin-right: -15px;
scale {
min-width: 400px;
margin-left: 18px;
margin-right: 20px;
highlight {
margin: 0;
background-color: #79659f;
border-radius: 2em;
}
trough {
background-color: #363847;
border-radius: 2em;
}
slider {
margin: -4px;
min-width: 20px;
min-height: 20px;
background: #3e4153;
border-radius: 100%;
transition: background-color 0.5s ease-in-out;
}
slider:hover {
background-color: #303240;
transition: background-color 0.5s ease-in-out;
}
}
}
}

View file

@ -1,26 +0,0 @@
const { Label } = Widget;
import CursorBox from '../../misc/cursorbox.ts';
import Persist from '../../misc/persist.ts';
const HeartState = Variable('');
Persist({
name: 'heart',
gobject: HeartState,
prop: 'value',
condition: '',
whenFalse: '󰣐',
});
export default () => CursorBox({
on_primary_click_release: () => {
HeartState.setValue(HeartState.value === '' ? '󰣐' : '');
},
child: Label({
class_name: 'heart-toggle',
label: HeartState.bind(),
}),
});

View file

@ -1,54 +0,0 @@
const Hyprland = await Service.import('hyprland');
const { Icon, Label } = Widget;
import HoverRevealer from './hover-revealer.ts';
const DEFAULT_KB = 'at-translated-set-2-keyboard';
// Types
import { Keyboard, LabelGeneric } from 'global-types';
const getKbdLayout = (self: LabelGeneric, _: string, layout: string) => {
if (layout) {
if (layout === 'error') {
return;
}
const shortName = layout.match(/\(([A-Za-z]+)\)/);
self.label = shortName ? shortName[1] : layout;
}
else {
// At launch, kb layout is undefined
Hyprland.messageAsync('j/devices').then((obj) => {
const keyboards = Array.from(JSON.parse(obj)
.keyboards) as Keyboard[];
const kb = keyboards.find((v) => v.name === DEFAULT_KB);
if (kb) {
layout = kb.active_keymap;
const shortName = layout
.match(/\(([A-Za-z]+)\)/);
self.label = shortName ? shortName[1] : layout;
}
else {
self.label = 'None';
}
}).catch(print);
}
};
export default () => HoverRevealer({
class_name: 'keyboard',
spacing: 4,
icon: Icon({
icon: 'input-keyboard-symbolic',
size: 20,
}),
label: Label({ css: 'font-size: 20px;' })
.hook(Hyprland, getKbdLayout, 'keyboard-layout'),
});