feat(agsV2): add workspaces and fix types
All checks were successful
Discord / discord commits (push) Has been skipped
All checks were successful
Discord / discord commits (push) Has been skipped
This commit is contained in:
parent
2dcc17cbb2
commit
cb617cbb91
9 changed files with 215 additions and 20 deletions
|
@ -12,7 +12,7 @@ in
|
|||
pname = "${pname}-types";
|
||||
version = "0.0.0";
|
||||
|
||||
npmDepsHash = "sha256-8De8tRUKzRhD1jyx0anYNPMhxZyIr2nI45HdK6nb8jI=";
|
||||
npmDepsHash = "sha256-3ll4Xd5F8ZH/7q/gOF0jgerM6QRk71d93XIwtDssfxU=";
|
||||
|
||||
src = ./.;
|
||||
dontNpmBuild = true;
|
||||
|
@ -22,8 +22,7 @@ in
|
|||
${concatMapStringsSep "\n" (p: "-g ${p.package.dev}/share/gir-1.0 \\") withGirNames}
|
||||
-g ${ts-for-gir-src}/girs \
|
||||
--ignoreVersionConflicts \
|
||||
--package \
|
||||
-e gjs -o ./types
|
||||
-o ./types
|
||||
'';
|
||||
|
||||
installPhase = ''
|
||||
|
|
BIN
lib/mk-types/package-lock.json
generated
BIN
lib/mk-types/package-lock.json
generated
Binary file not shown.
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"dependencies": {
|
||||
"@ts-for-gir/cli": "^3.3.0"
|
||||
"@ts-for-gir/cli": "4.0.0-beta.16"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -51,7 +51,10 @@ export default ({
|
|||
gdkmonitor = Gdk.Display.get_default()?.get_monitor(0) as Gdk.Monitor,
|
||||
child,
|
||||
...rest
|
||||
}: Widget.WindowProps) => {
|
||||
}: {
|
||||
anchor: Astal.WindowAnchor
|
||||
gdkmonitor?: Gdk.Monitor
|
||||
} & Widget.WindowProps) => {
|
||||
const monitor = get_hyprland_monitor_desc(gdkmonitor);
|
||||
const BarVisible = Variable(true);
|
||||
|
||||
|
@ -143,7 +146,6 @@ export default ({
|
|||
name={`bar-${monitor}`}
|
||||
layer={Astal.Layer.OVERLAY}
|
||||
gdkmonitor={gdkmonitor}
|
||||
margins={[-1, -1, -1, -1]}
|
||||
anchor={anchor}
|
||||
{...rest}
|
||||
>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { bind, Widget } from 'astal';
|
||||
import { bind } from 'astal';
|
||||
|
||||
import AstalBattery from 'gi://AstalBattery';
|
||||
const Battery = AstalBattery.get_default();
|
||||
|
@ -7,12 +7,11 @@ import Separator from '../../misc/separator';
|
|||
|
||||
|
||||
const LOW_BATT = 20;
|
||||
const SPACING = 8;
|
||||
|
||||
export default () => (
|
||||
<box className="bar-item battery">
|
||||
<icon
|
||||
setup={(self: Widget.Icon) => {
|
||||
setup={(self) => {
|
||||
const update = () => {
|
||||
const percent = Math.round(Battery.get_percentage() * 100);
|
||||
const level = Math.floor(percent / 10) * 10;
|
||||
|
@ -37,7 +36,7 @@ export default () => (
|
|||
}}
|
||||
/>
|
||||
|
||||
<Separator size={SPACING} />
|
||||
<Separator size={8} />
|
||||
|
||||
<label label={bind(Battery, 'percentage').as((v) => `${Math.round(v * 100)}%`)} />
|
||||
</box>
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
import { bind, Widget } from 'astal';
|
||||
|
||||
import Pango from 'gi://Pango?version=1.0';
|
||||
import { bind } from 'astal';
|
||||
|
||||
import AstalApps from 'gi://AstalApps?version=0.1';
|
||||
const Applications = AstalApps.Apps.new();
|
||||
|
@ -11,8 +9,6 @@ const Hyprland = AstalHyprland.get_default();
|
|||
import Separator from '../../misc/separator';
|
||||
|
||||
|
||||
const SPACING = 8;
|
||||
|
||||
export default () => {
|
||||
const focused = bind(Hyprland, 'focusedClient');
|
||||
|
||||
|
@ -23,10 +19,10 @@ export default () => {
|
|||
>
|
||||
<icon
|
||||
css="font-size: 32px;"
|
||||
setup={(self: Widget.Icon) => {
|
||||
setup={(self) => {
|
||||
self.hook(Hyprland, 'notify::focused-client', () => {
|
||||
const app = Applications.query(
|
||||
Hyprland.get_focused_client().get_class(),
|
||||
Hyprland.get_focused_client()?.get_class() ?? '',
|
||||
false,
|
||||
)[0];
|
||||
|
||||
|
@ -35,12 +31,12 @@ export default () => {
|
|||
}}
|
||||
/>
|
||||
|
||||
<Separator size={SPACING} />
|
||||
<Separator size={8} />
|
||||
|
||||
{focused.as((client) => (client && (
|
||||
<label
|
||||
label={bind(client, 'title').as(String)}
|
||||
truncate={Pango.EllipsizeMode.END}
|
||||
truncate
|
||||
/>
|
||||
)))}
|
||||
</box>
|
||||
|
|
167
nixosModules/ags/v2/widgets/bar/items/workspaces.tsx
Normal file
167
nixosModules/ags/v2/widgets/bar/items/workspaces.tsx
Normal file
|
@ -0,0 +1,167 @@
|
|||
import { Gtk, idle, timeout, Widget } from 'astal';
|
||||
|
||||
import AstalHyprland from 'gi://AstalHyprland?version=0.1';
|
||||
const Hyprland = AstalHyprland.get_default();
|
||||
|
||||
|
||||
const URGENT_DURATION = 1000;
|
||||
|
||||
const Workspace = ({ id = 0 }) => (
|
||||
<revealer
|
||||
name={id.toString()}
|
||||
transitionType={Gtk.RevealerTransitionType.SLIDE_RIGHT}
|
||||
>
|
||||
<eventbox
|
||||
cursor="pointer"
|
||||
tooltip_text={id.toString()}
|
||||
|
||||
onClickRelease={() => {
|
||||
Hyprland.message_async(`dispatch workspace ${id}`, () => { /**/ });
|
||||
}}
|
||||
>
|
||||
<box
|
||||
valign={Gtk.Align.CENTER}
|
||||
className="button"
|
||||
|
||||
setup={(self) => idle(() => {
|
||||
const update = (
|
||||
_: Widget.Box,
|
||||
addr?: string,
|
||||
) => {
|
||||
const workspace = Hyprland.get_workspace(id);
|
||||
const occupied = workspace && workspace.get_clients().length > 0;
|
||||
|
||||
self.toggleClassName('occupied', occupied);
|
||||
|
||||
if (!addr) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Deal with urgent windows
|
||||
const client = Hyprland.get_client(addr);
|
||||
const isThisUrgent = client &&
|
||||
client.workspace.id === id;
|
||||
|
||||
if (isThisUrgent) {
|
||||
self.toggleClassName('urgent', true);
|
||||
|
||||
// Only show for a sec when urgent is current workspace
|
||||
if (Hyprland.get_focused_workspace().get_id() === id) {
|
||||
timeout(URGENT_DURATION, () => {
|
||||
self.toggleClassName('urgent', false);
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
self
|
||||
.hook(Hyprland, 'event', update)
|
||||
|
||||
// Deal with urgent windows
|
||||
.hook(Hyprland, 'urgent', update)
|
||||
|
||||
.hook(Hyprland, 'notify::focused-workspace', () => {
|
||||
if (Hyprland.get_focused_workspace().get_id() === id) {
|
||||
self.toggleClassName('urgent', false);
|
||||
}
|
||||
});
|
||||
})}
|
||||
/>
|
||||
</eventbox>
|
||||
</revealer>
|
||||
);
|
||||
|
||||
export default () => {
|
||||
const L_PADDING = 2;
|
||||
const WS_WIDTH = 30;
|
||||
|
||||
const updateHighlight = (self: Widget.Box) => {
|
||||
const currentId = Hyprland.get_focused_workspace().get_id().toString();
|
||||
|
||||
const indicators = ((self.get_parent() as Widget.Overlay)
|
||||
.child as Widget.Box)
|
||||
.children as Widget.Revealer[];
|
||||
|
||||
const currentIndex = indicators.findIndex((w) => w.name === currentId);
|
||||
|
||||
if (currentIndex >= 0) {
|
||||
self.css = `margin-left: ${L_PADDING + (currentIndex * WS_WIDTH)}px`;
|
||||
}
|
||||
};
|
||||
|
||||
const highlight = (
|
||||
<box
|
||||
className="button active"
|
||||
|
||||
valign={Gtk.Align.CENTER}
|
||||
halign={Gtk.Align.START}
|
||||
|
||||
setup={(self) => {
|
||||
self.hook(Hyprland, 'notify::focused-workspace', updateHighlight);
|
||||
}}
|
||||
/>
|
||||
) as Widget.Box;
|
||||
|
||||
let workspaces: Widget.Revealer[] = [];
|
||||
|
||||
return (
|
||||
<box
|
||||
className="bar-item"
|
||||
>
|
||||
<overlay
|
||||
className="workspaces"
|
||||
passThrough
|
||||
overlay={highlight}
|
||||
>
|
||||
<box
|
||||
setup={(self) => {
|
||||
const refresh = () => {
|
||||
(self.children as Widget.Revealer[]).forEach((rev) => {
|
||||
rev.reveal_child = false;
|
||||
});
|
||||
|
||||
workspaces.forEach((ws) => {
|
||||
ws.reveal_child = true;
|
||||
});
|
||||
};
|
||||
|
||||
const updateWorkspaces = () => {
|
||||
Hyprland.get_workspaces().forEach((ws) => {
|
||||
const currentWs = (self.children as Widget.Revealer[])
|
||||
.find((ch) => ch.name === ws.id.toString());
|
||||
|
||||
if (!currentWs && ws.id > 0) {
|
||||
self.add(Workspace({ id: ws.id }));
|
||||
}
|
||||
});
|
||||
|
||||
// Make sure the order is correct
|
||||
workspaces.forEach((workspace, i) => {
|
||||
(workspace.get_parent() as Widget.Box)
|
||||
.reorder_child(workspace, i);
|
||||
});
|
||||
};
|
||||
|
||||
self.hook(Hyprland, 'event', () => {
|
||||
workspaces = (self.children as Widget.Revealer[])
|
||||
.filter((ch) => {
|
||||
return Hyprland.get_workspaces().find((ws) => {
|
||||
return ws.id.toString() === ch.name;
|
||||
});
|
||||
})
|
||||
.sort((a, b) => parseInt(a.name ?? '0') - parseInt(b.name ?? '0'));
|
||||
|
||||
updateWorkspaces();
|
||||
refresh();
|
||||
|
||||
// Make sure the highlight doesn't go too far
|
||||
const TEMP_TIMEOUT = 100;
|
||||
|
||||
timeout(TEMP_TIMEOUT, () => updateHighlight(highlight));
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</overlay>
|
||||
</box>
|
||||
);
|
||||
};
|
|
@ -4,7 +4,7 @@
|
|||
border-radius: 7px;
|
||||
background-color: darken($window_bg_color, 3%);
|
||||
font-size: 20px;
|
||||
min-height: 30px;
|
||||
min-height: 35px;
|
||||
|
||||
.battery icon {
|
||||
&.charging {
|
||||
|
@ -15,5 +15,32 @@
|
|||
color: red;
|
||||
}
|
||||
}
|
||||
|
||||
.workspaces {
|
||||
.button {
|
||||
margin: 0 2.5px;
|
||||
min-height: 22px;
|
||||
min-width: 22px;
|
||||
border-radius: 100%;
|
||||
border: 2px solid transparent;
|
||||
}
|
||||
|
||||
.occupied {
|
||||
border: 2px solid $window_bg_color;
|
||||
background: $accent_color;
|
||||
transition: background-color 0.6s ease-in-out;
|
||||
}
|
||||
|
||||
.urgent {
|
||||
border: 2px solid $window_bg_color;
|
||||
background: red;
|
||||
transition: background-color 0.6s ease-in-out;
|
||||
}
|
||||
|
||||
.active {
|
||||
border: 2px solid #50fa7b;
|
||||
transition: margin-left 0.5s cubic-bezier(0.34, 1.56, 0.64, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ import { Astal, Gtk } from 'astal';
|
|||
import Battery from './items/battery';
|
||||
import Clock from './items/clock';
|
||||
import CurrentClient from './items/current-client';
|
||||
import Workspaces from './items/workspaces';
|
||||
|
||||
import BarRevealer from './fullscreen';
|
||||
import Separator from '../misc/separator';
|
||||
|
@ -20,6 +21,10 @@ export default () => (
|
|||
|
||||
<centerbox className="bar widget">
|
||||
<box hexpand halign={Gtk.Align.START}>
|
||||
<Workspaces />
|
||||
|
||||
<Separator size={8} />
|
||||
|
||||
<CurrentClient />
|
||||
</box>
|
||||
|
||||
|
|
Loading…
Reference in a new issue