diff options
| author | 2025-03-02 14:16:48 +0300 | |
|---|---|---|
| committer | 2025-03-02 14:16:48 +0300 | |
| commit | 684dedeb1a527a74de31cb405168ad39ec802a51 (patch) | |
| tree | ef26e37bb8761a63f95896979449cbd60f307364 /widget | |
| parent | feat: initial commit (diff) | |
| download | ags-config-684dedeb1a527a74de31cb405168ad39ec802a51.tar.gz ags-config-684dedeb1a527a74de31cb405168ad39ec802a51.tar.bz2 ags-config-684dedeb1a527a74de31cb405168ad39ec802a51.tar.lz ags-config-684dedeb1a527a74de31cb405168ad39ec802a51.tar.xz ags-config-684dedeb1a527a74de31cb405168ad39ec802a51.tar.zst ags-config-684dedeb1a527a74de31cb405168ad39ec802a51.zip | |
feat: basic topbar features
Diffstat (limited to '')
| -rw-r--r-- | widget/Bar.tsx | 124 | 
1 files changed, 93 insertions, 31 deletions
| diff --git a/widget/Bar.tsx b/widget/Bar.tsx index c2db8c5..02aa3ba 100644 --- a/widget/Bar.tsx +++ b/widget/Bar.tsx @@ -1,36 +1,98 @@  import { App, Astal, Gtk, Gdk } from "astal/gtk4" -import { Variable } from "astal" +import { exec, GLib, Variable } from "astal" + +type NiriWorkspace = { +  id: number, +  idx: number, +  name: string | null, +  output: string, +  is_active: boolean, +  is_focused: boolean, +  active_window_id: number | null, +}; + +function getWorkspaces(): NiriWorkspace[] { +  // NOTE: this works only in non-systemd environment on NixOS +  // TODO: try to use Niri socket if it is documented +  return JSON.parse(exec("niri msg -j workspaces")); +} + +function getWorkspacesByOutput(output: string): NiriWorkspace[] { +  return getWorkspaces().filter(workspace => workspace.output == output).sort((a, b) => a.idx - b.idx); +} + +function focusWorkspace(idx: number) { +  // NOTE: this works only in non-systemd environment on NixOS +  // TODO: try to use Niri socket if it is documented +  exec(`niri msg action focus-workspace ${idx}`); +} + +type WorkspaceButtonArguments = { +  idx: number, +  isActive: boolean, +  isFocused: boolean, +}; + +function WorkspaceButton(args: WorkspaceButtonArguments) { +  const classes: string[] = []; +  args.isActive && classes.push("active"); +  args.isFocused && classes.push("focused"); +  return <button cssClasses={classes} onClicked={() => focusWorkspace(args.idx)} /> +} + +type WorkspacesArguments = { +  connector: string, +}; + +function Workspaces(args: WorkspacesArguments) { +  // NOTE: it is pretty inefficient and not so much responsive +  // TODO: it would be better to use Niri socket in the future +  const workspaces: Variable<NiriWorkspace[]> = Variable(getWorkspacesByOutput(args.connector)) +    .poll(1000, () => getWorkspacesByOutput(args.connector)); + +  // BUG: on workspace change there's no CSS transition +  // I guess it is due to rerender here +  return <box cssClasses={["Workspaces"]}> +    {workspaces(v => v.map(workspace => <WorkspaceButton idx={workspace.idx} isActive={workspace.is_active} isFocused={workspace.is_focused} />))} +  </box> +} + + +type TimeArguments = { +  format: string, +}; + +function Time(args: TimeArguments) { +  const time = Variable<GLib.DateTime>(GLib.DateTime.new_now_local()).poll(1000, () => GLib.DateTime.new_now_local()) + +  return <box> +    {time(v => v.format(args.format))} +  </box> +} -const time = Variable("").poll(1000, "date")  export default function Bar(gdkmonitor: Gdk.Monitor) { -    const { TOP, LEFT, RIGHT } = Astal.WindowAnchor - -    return <window -        visible -        cssClasses={["Bar"]} -        gdkmonitor={gdkmonitor} -        exclusivity={Astal.Exclusivity.EXCLUSIVE} -        anchor={TOP | LEFT | RIGHT} -        application={App}> -        <centerbox cssName="centerbox"> -            <button -                onClicked="echo hello" -                hexpand -                halign={Gtk.Align.CENTER} -            > -                Welcome to AGS! -            </button> -            <box /> -            <menubutton -                hexpand -                halign={Gtk.Align.CENTER} -            > -                <label label={time()} /> -                <popover> -                    <Gtk.Calendar /> -                </popover> -            </menubutton> -        </centerbox> -    </window> +  const { TOP, LEFT, RIGHT } = Astal.WindowAnchor + +  return <window +    visible +    name={"Bar"} +    cssClasses={["Bar"]} +    gdkmonitor={gdkmonitor} +    exclusivity={Astal.Exclusivity.EXCLUSIVE} +    anchor={TOP | LEFT | RIGHT} +    application={App}> +    <centerbox cssClasses={["bar-container"]}> +      <box halign={Gtk.Align.START}> +        <Workspaces connector={gdkmonitor.get_connector()!} /> +      </box> + +      <box halign={Gtk.Align.CENTER}> +      </box> + +      <box halign={Gtk.Align.END}> +        <Time format="%I:%M:%S %p %Z" /> +      </box> +    </centerbox> +  </window>  } | 
