From b0f857f0d1a1bec3d9c56a6e76d54932bfc6bf01 Mon Sep 17 00:00:00 2001 From: 2 * r + 2 * t <61896496+soramanew@users.noreply.github.com> Date: Tue, 8 Apr 2025 16:01:36 +1000 Subject: feat: add navbar For controlling sidebar panes + other stuff later --- src/modules/bar.tsx | 11 +-- src/modules/navbar.tsx | 120 ++++++++++++++++++++++++++ src/modules/notifpopups.tsx | 17 ++-- src/modules/osds.tsx | 3 +- src/modules/session.tsx | 2 +- src/modules/sidebar/index.tsx | 46 ++++++++-- src/modules/sidebar/modules/notifications.tsx | 6 +- 7 files changed, 174 insertions(+), 31 deletions(-) create mode 100644 src/modules/navbar.tsx (limited to 'src/modules') diff --git a/src/modules/bar.tsx b/src/modules/bar.tsx index 447b69d..5a0fee3 100644 --- a/src/modules/bar.tsx +++ b/src/modules/bar.tsx @@ -1,4 +1,3 @@ -import type SideBar from "@/modules/sidebar"; import type { Monitor } from "@/services/monitors"; import Players from "@/services/players"; import Updates from "@/services/updates"; @@ -18,6 +17,7 @@ import AstalNetwork from "gi://AstalNetwork"; import AstalNotifd from "gi://AstalNotifd"; import AstalTray from "gi://AstalTray"; import AstalWp from "gi://AstalWp"; +import { switchPane } from "./sidebar"; interface ClassNameProps { beforeSpacer: boolean; @@ -75,15 +75,6 @@ const hookFocusedClientProp = ( callback(lastClient); }; -const switchPane = (monitor: Monitor, name: string) => { - const sidebar = App.get_window(`sidebar${monitor.id}`) as SideBar | null; - if (sidebar) { - if (sidebar.visible && sidebar.shown.get() === name) sidebar.hide(); - else sidebar.show(); - sidebar.shown.set(name); - } -}; - const getClassName = ({ beforeSpacer, afterSpacer, first, last }: ClassNameProps) => `${beforeSpacer ? "before-spacer" : ""} ${afterSpacer ? "after-spacer" : ""}` + ` ${first ? "first" : ""} ${last ? "last" : ""}`; diff --git a/src/modules/navbar.tsx b/src/modules/navbar.tsx new file mode 100644 index 0000000..b844ff4 --- /dev/null +++ b/src/modules/navbar.tsx @@ -0,0 +1,120 @@ +import type { Monitor } from "@/services/monitors"; +import type { AstalWidget } from "@/utils/types"; +import { Variable } from "astal"; +import { Astal, Gtk } from "astal/gtk3"; +import { navbar as config } from "config"; +import AstalHyprland from "gi://AstalHyprland"; +import SideBar, { awaitSidebar, paneNames, switchPane, type PaneName } from "./sidebar"; + +const getPaneIcon = (name: PaneName) => { + if (name === "dashboard") return "dashboard"; + if (name === "audio") return "tune"; + if (name === "connectivity") return "settings_ethernet"; + if (name === "packages") return "package_2"; + if (name === "notifpane") return "notifications"; + return "date_range"; +}; + +const getPaneName = (name: PaneName) => { + if (name === "dashboard") return "Dash"; + if (name === "audio") return "Audio"; + if (name === "connectivity") return "Conn"; + if (name === "packages") return "Pkgs"; + if (name === "notifpane") return "Alrts"; + return "Time"; +}; + +const hookIsCurrent = ( + self: AstalWidget, + sidebar: Variable, + name: PaneName, + callback: (isCurrent: boolean) => void +) => { + const unsub = sidebar.subscribe(s => { + if (!s) return; + self.hook(s.shown, (_, v) => callback(s.visible && v === name)); + self.hook(s, "notify::visible", () => callback(s.visible && s.shown.get() === name)); + callback(s.visible && s.shown.get() === name); + unsub(); + }); +}; + +const PaneButton = ({ + monitor, + name, + sidebar, +}: { + monitor: Monitor; + name: PaneName; + sidebar: Variable; +}) => ( + +); + +export default ({ monitor }: { monitor: Monitor }) => { + const sidebar = Variable(null); + awaitSidebar(monitor).then(s => sidebar.set(s)); + + return ( + { + const hyprland = AstalHyprland.get_default(); + const visible = Variable(config.persistent.get()); + + visible.poll(100, () => { + const width = self.visible + ? Math.max(config.appearWidth.get(), self.get_allocated_width()) + : config.appearWidth.get(); + return hyprland.get_cursor_position().x < width; + }); + if (config.persistent.get()) visible.stopPoll(); + + self.hook(config.persistent, (_, v) => { + if (v) { + visible.stopPoll(); + visible.set(true); + } else visible.startPoll(); + }); + + self.hook(visible, (_, v) => self.set_visible(v)); + self.connect("destroy", () => visible.drop()); + }} + > + { + const shown = sidebar.get()?.shown; + if (!shown) return; + const idx = paneNames.indexOf(shown.get()); + if (event.delta_y > 0) shown.set(paneNames[Math.min(paneNames.length - 1, idx + 1)]); + else shown.set(paneNames[Math.max(0, idx - 1)]); + }} + > + + {paneNames.map(n => ( + + ))} + + + + ); +}; diff --git a/src/modules/notifpopups.tsx b/src/modules/notifpopups.tsx index 57e2a64..c8f4e13 100644 --- a/src/modules/notifpopups.tsx +++ b/src/modules/notifpopups.tsx @@ -1,11 +1,11 @@ import type { Monitor } from "@/services/monitors"; -import { idle, timeout } from "astal"; -import { App, Astal, Gtk } from "astal/gtk3"; +import { setupChildClickthrough } from "@/utils/widgets"; +import Notification from "@/widgets/notification"; +import { Astal, Gtk } from "astal/gtk3"; import { notifpopups as config } from "config"; import AstalNotifd from "gi://AstalNotifd"; -import { setupChildClickthrough } from "../utils/widgets"; -import Notification from "../widgets/notification"; import type SideBar from "./sidebar"; +import { awaitSidebar } from "./sidebar"; export default ({ monitor }: { monitor: Monitor }) => ( ( }); self.hook(notifd, "resolved", (_, id) => map.get(id)?.destroyWithAnims()); - let sidebar: SideBar | null; - - const awaitSidebar = () => { - sidebar = App.get_window(`sidebar${monitor.id}`) as SideBar | null; - if (!sidebar) timeout(100, awaitSidebar); - }; - idle(awaitSidebar); + let sidebar: SideBar | null = null; + awaitSidebar(monitor).then(s => (sidebar = s)); // Change input region to child region so can click through empty space setupChildClickthrough(self); diff --git a/src/modules/osds.tsx b/src/modules/osds.tsx index 4bbc87b..0f38823 100644 --- a/src/modules/osds.tsx +++ b/src/modules/osds.tsx @@ -1,4 +1,5 @@ import Monitors, { type Monitor } from "@/services/monitors"; +import { capitalize } from "@/utils/strings"; import PopupWindow from "@/widgets/popupwindow"; import { bind, execAsync, register, timeout, Variable, type Time } from "astal"; import { App, Astal, Gtk, Widget } from "astal/gtk3"; @@ -282,7 +283,7 @@ class LockOsd extends Widget.Window { this.add( ); diff --git a/src/modules/session.tsx b/src/modules/session.tsx index 4f4a987..40d3b31 100644 --- a/src/modules/session.tsx +++ b/src/modules/session.tsx @@ -1,6 +1,6 @@ +import PopupWindow from "@/widgets/popupwindow"; import { execAsync } from "astal"; import { App, Astal, Gtk } from "astal/gtk3"; -import PopupWindow from "../widgets/popupwindow"; const Item = ({ icon, label, cmd, isDefault }: { icon: string; label: string; cmd: string; isDefault?: boolean }) => ( diff --git a/src/modules/sidebar/index.tsx b/src/modules/sidebar/index.tsx index 60675d6..55d635c 100644 --- a/src/modules/sidebar/index.tsx +++ b/src/modules/sidebar/index.tsx @@ -9,9 +9,42 @@ import NotifPane from "./notifpane"; import Packages from "./packages"; import Time from "./time"; +export const paneNames = ["dashboard", "audio", "connectivity", "packages", "notifpane", "time"] as const; +export type PaneName = (typeof paneNames)[number]; + +export const switchPane = (monitor: Monitor, name: PaneName) => { + const sidebar = App.get_window(`sidebar${monitor.id}`) as SideBar | null; + if (sidebar) { + if (sidebar.visible && sidebar.shown.get() === name) sidebar.hide(); + else sidebar.show(); + sidebar.shown.set(name); + } +}; + +export const awaitSidebar = (monitor: Monitor) => + new Promise(resolve => { + let sidebar: SideBar | null = null; + + const awaitSidebar = () => { + sidebar = App.get_window(`sidebar${monitor.id}`) as SideBar | null; + if (sidebar) resolve(sidebar); + else idle(awaitSidebar); + }; + idle(awaitSidebar); + }); + +const getPane = (name: PaneName) => { + if (name === "dashboard") return ; + if (name === "audio") return diff --git a/src/modules/sidebar/modules/notifications.tsx b/src/modules/sidebar/modules/notifications.tsx index 9a9f440..e9347ec 100644 --- a/src/modules/sidebar/modules/notifications.tsx +++ b/src/modules/sidebar/modules/notifications.tsx @@ -68,7 +68,11 @@ export default ({ compact }: { compact?: boolean }) => ( />