Initial commit
This commit is contained in:
45
ags/widget/bar/bar.tsx
Normal file
45
ags/widget/bar/bar.tsx
Normal file
@ -0,0 +1,45 @@
|
||||
import { App, Astal, Gdk, Gtk } from "astal/gtk4"
|
||||
import { Binding } from "astal"
|
||||
|
||||
import Battery from "gi://AstalBattery";
|
||||
|
||||
import { BatteryInfo } from "./components/battery";
|
||||
import DateTime from "@lib/widgets/datetime";
|
||||
import Workspace from "./workspace";
|
||||
import TrayView from "./tray";
|
||||
|
||||
export default function Bar(monitor_id: number) {
|
||||
const { BOTTOM, LEFT, RIGHT } = Astal.WindowAnchor
|
||||
const CENTER = Gtk.Align.CENTER;
|
||||
|
||||
const battery = Battery.get_default();
|
||||
|
||||
const openQuickSettings = (_self: Gtk.Button, state: Gdk.ButtonEvent) => {
|
||||
if (state.get_button() === Gdk.BUTTON_PRIMARY)
|
||||
App.get_window("quick_settings")?.show()
|
||||
}
|
||||
|
||||
return <window
|
||||
visible
|
||||
name={`bar_${monitor_id}`}
|
||||
monitor={monitor_id}
|
||||
cssClasses={["bar"]}
|
||||
exclusivity={Astal.Exclusivity.EXCLUSIVE}
|
||||
anchor={BOTTOM | LEFT | RIGHT}
|
||||
application={App}>
|
||||
<box halign={CENTER} cssClasses={["inner"]}>
|
||||
{[
|
||||
Workspace(),
|
||||
<menubutton hasFrame={false}>
|
||||
<DateTime format="%d.%m.%Y %H:%M:%S" interval={1000} />
|
||||
<popover>
|
||||
<Gtk.Calendar />
|
||||
</popover>
|
||||
</menubutton>,
|
||||
BatteryInfo({ battery }),
|
||||
<button hasFrame={false} iconName={"applications-system-symbolic"} onButtonPressed={openQuickSettings} />,
|
||||
TrayView()
|
||||
]}
|
||||
</box>
|
||||
</window>
|
||||
}
|
53
ags/widget/bar/battery_info.tsx
Normal file
53
ags/widget/bar/battery_info.tsx
Normal file
@ -0,0 +1,53 @@
|
||||
import { App, Astal, Gtk } from "astal/gtk4";
|
||||
import { bind } from "astal";
|
||||
|
||||
import { getBatteryIcon } from "@/lib/icons";
|
||||
import { hideWindow } from "@lib/utils";
|
||||
|
||||
import PowerProfiles from "gi://AstalPowerProfiles?version=0.1";
|
||||
import Battery from "gi://AstalBattery?version=0.1";
|
||||
import Hyprland from "gi://AstalHyprland";
|
||||
|
||||
export default function BatteryInfo(_monitor_id: number) {
|
||||
const { BOTTOM, LEFT, RIGHT } = Astal.WindowAnchor
|
||||
const CENTER = Gtk.Align.CENTER;
|
||||
|
||||
const hypr = Hyprland.get_default();
|
||||
const power = PowerProfiles.get_default();
|
||||
const battery = Battery.get_default();
|
||||
|
||||
const percentage = bind(battery, "percentage").as(p => Math.floor(p * 100));
|
||||
const charging = bind(battery, "charging");
|
||||
|
||||
return <window
|
||||
visible={false}
|
||||
name={"battery_info"}
|
||||
monitor={bind(hypr, "focusedMonitor").as(monitor => monitor.id)}
|
||||
cssClasses={["battery_info"]}
|
||||
keymode={Astal.Keymode.EXCLUSIVE}
|
||||
exclusivity={Astal.Exclusivity.IGNORE}
|
||||
anchor={BOTTOM | LEFT | RIGHT}
|
||||
onKeyPressed={hideWindow}
|
||||
application={App}>
|
||||
<box halign={CENTER} cssClasses={["inner"]} spacing={10}>
|
||||
{percentage.as(p => <>
|
||||
<image
|
||||
iconSize={Gtk.IconSize.LARGE}
|
||||
iconName={getBatteryIcon(p, charging)}
|
||||
/>
|
||||
|
||||
<label cssClasses={["percentage"]}>{percentage.as(p => `${p}%`)}</label>
|
||||
</>)}
|
||||
|
||||
{power.get_profiles().map(profile => <button
|
||||
label={profile.profile}
|
||||
cssClasses={bind(power, "active_profile").as(active =>
|
||||
active === profile.profile
|
||||
? ["active"]
|
||||
: []
|
||||
)}
|
||||
onClicked={() => power.set_active_profile(profile.profile)}
|
||||
/>)}
|
||||
</box>
|
||||
</window>
|
||||
}
|
26
ags/widget/bar/components/battery.tsx
Normal file
26
ags/widget/bar/components/battery.tsx
Normal file
@ -0,0 +1,26 @@
|
||||
import { App, Gdk } from "astal/gtk4";
|
||||
import { bind } from "astal";
|
||||
|
||||
import Battery from "gi://AstalBattery";
|
||||
|
||||
import { getBatteryIcon } from "@/lib/icons";
|
||||
import { openOnButton } from "@/lib/utils";
|
||||
|
||||
export function BatteryInfo({ battery }: { battery: Battery.Device }) {
|
||||
const percentage = bind(battery, "percentage").as(p => Math.floor(p * 100));
|
||||
const charging = bind(battery, "charging");
|
||||
|
||||
return (
|
||||
<box>
|
||||
{percentage.as(p => <button hasFrame={false}>
|
||||
<box onButtonPressed={(_self, event) =>
|
||||
openOnButton(event, Gdk.BUTTON_PRIMARY)
|
||||
(() => App.toggle_window("battery_info"))
|
||||
}>
|
||||
<label>{percentage.as(p => `${p}%`)}</label>
|
||||
<image iconName={getBatteryIcon(p, charging)} />
|
||||
</box>
|
||||
</button>)}
|
||||
</box>
|
||||
);
|
||||
};
|
30
ags/widget/bar/tray.tsx
Normal file
30
ags/widget/bar/tray.tsx
Normal file
@ -0,0 +1,30 @@
|
||||
import { hook } from "astal/gtk4";
|
||||
import { bind } from "astal";
|
||||
|
||||
import Tray from "gi://AstalTray";
|
||||
|
||||
export default function TrayView() {
|
||||
const tray = Tray.get_default();
|
||||
const items = bind(tray, "items");
|
||||
|
||||
return <box spacing={items.as(items => items.length)} cssClasses={["tray"]}>
|
||||
{items.as(items => items.map(item => {
|
||||
const button = <menubutton
|
||||
cssClasses={["item"]}
|
||||
tooltipMarkup={bind(item, "tooltipMarkup")}
|
||||
menuModel={bind(item, "menuModel")}
|
||||
hasFrame={false}
|
||||
primary
|
||||
setup={self => self.insert_action_group("dbusmenu", item.actionGroup)}
|
||||
>
|
||||
<image gicon={item.gicon} />
|
||||
</menubutton>;
|
||||
|
||||
hook(button, item, "notify::action-group", self => {
|
||||
self.insert_action_group("dbusmenu", item.actionGroup);
|
||||
});
|
||||
|
||||
return button;
|
||||
}))}
|
||||
</box>
|
||||
}
|
18
ags/widget/bar/workspace.tsx
Normal file
18
ags/widget/bar/workspace.tsx
Normal file
@ -0,0 +1,18 @@
|
||||
import Hyprland from "gi://AstalHyprland";
|
||||
import { bind, Variable } from "astal";
|
||||
|
||||
export default function Workspace() {
|
||||
const hypr = Hyprland.get_default();
|
||||
const lastWorkspaceId = Variable(hypr.focusedWorkspace.id);
|
||||
|
||||
return <button hasFrame={false}>
|
||||
{bind(hypr, "focusedWorkspace").as(workspace => {
|
||||
// This is a hack; sometimes when disconnecting monitor
|
||||
// focusedWorkspace is null for a while.
|
||||
// Therefore an error occurs when trying to reference id.
|
||||
if (workspace) lastWorkspaceId.set(workspace.id)
|
||||
|
||||
return `workspace ${workspace?.id ?? lastWorkspaceId.get()}`
|
||||
})}
|
||||
</button>
|
||||
}
|
Reference in New Issue
Block a user