summaryrefslogtreecommitdiff
path: root/src/modules
diff options
context:
space:
mode:
Diffstat (limited to 'src/modules')
-rw-r--r--src/modules/bar.tsx25
-rw-r--r--src/modules/popdowns/index.tsx2
-rw-r--r--src/modules/popdowns/sideright.tsx127
3 files changed, 139 insertions, 15 deletions
diff --git a/src/modules/bar.tsx b/src/modules/bar.tsx
index c7f168e..5faee7a 100644
--- a/src/modules/bar.tsx
+++ b/src/modules/bar.tsx
@@ -1,4 +1,4 @@
-import { execAsync, GLib, register, Variable } from "astal";
+import { execAsync, register, Variable } from "astal";
import { bind, kebabify } from "astal/binding";
import { App, Astal, astalify, Gdk, Gtk, type ConstructProps } from "astal/gtk3";
import AstalBluetooth from "gi://AstalBluetooth";
@@ -13,7 +13,7 @@ import Players from "../services/players";
import Updates from "../services/updates";
import { getAppCategoryIcon } from "../utils/icons";
import { ellipsize } from "../utils/strings";
-import { osIcon } from "../utils/system";
+import { bindCurrentTime, osIcon } from "../utils/system";
import { setupCustomTooltip } from "../utils/widgets";
import type PopupWindow from "../widgets/popupwindow";
@@ -438,19 +438,14 @@ const NotifCount = () => (
);
const DateTime = () => (
- <box className="module date-time">
- <label className="icon" label="calendar_month" />
- <label
- setup={self => {
- const pollVar = Variable(null).poll(5000, () => {
- self.label =
- GLib.DateTime.new_now_local().format(config.dateTimeFormat) ?? new Date().toLocaleString();
- return null;
- });
- self.connect("destroy", () => pollVar.drop());
- }}
- />
- </box>
+ <button
+ onClick={(self, event) => event.button === Astal.MouseButton.PRIMARY && togglePopup(self, event, "sideright")}
+ >
+ <box className="module date-time">
+ <label className="icon" label="calendar_month" />
+ <label label={bindCurrentTime(config.dateTimeFormat)} />
+ </box>
+ </button>
);
const Power = () => (
diff --git a/src/modules/popdowns/index.tsx b/src/modules/popdowns/index.tsx
index 9ee9f77..c4f4664 100644
--- a/src/modules/popdowns/index.tsx
+++ b/src/modules/popdowns/index.tsx
@@ -2,6 +2,7 @@ import BluetoothDevices from "./bluetoothdevices";
import Media from "./media";
import Networks from "./networks";
import Notifications from "./notifications";
+import SideRight from "./sideright";
import Updates from "./updates";
export default () => {
@@ -10,6 +11,7 @@ export default () => {
<BluetoothDevices />;
<Networks />;
<Media />;
+ <SideRight />;
return null;
};
diff --git a/src/modules/popdowns/sideright.tsx b/src/modules/popdowns/sideright.tsx
new file mode 100644
index 0000000..86c0547
--- /dev/null
+++ b/src/modules/popdowns/sideright.tsx
@@ -0,0 +1,127 @@
+import { bind } from "astal";
+import { Astal, Gtk, type Gdk } from "astal/gtk3";
+import SWeather, { type WeatherData } from "../../services/weather";
+import { ellipsize } from "../../utils/strings";
+import { bindCurrentTime } from "../../utils/system";
+import { Calendar as WCal } from "../../utils/widgets";
+import PopupWindow from "../../widgets/popupwindow";
+
+const getHoursFromUpdate = (data: WeatherData, hours: number) => {
+ const updateTime = data.location.localtime_epoch;
+ const updateHourStart = updateTime - (updateTime % 3600);
+
+ let nextHour = new Date((updateHourStart + hours * 3600) * 1000).getHours();
+ if (nextHour >= 24) nextHour -= 24;
+
+ return nextHour;
+};
+
+const Time = () => (
+ <box className="time">
+ <box hexpand halign={Gtk.Align.CENTER}>
+ <label label={bindCurrentTime("%I:%M:%S")} />
+ <label className="ampm" label={bindCurrentTime("%p", c => (c.get_hour() < 12 ? "AM" : "PM"))} />
+ </box>
+ </box>
+);
+
+const Calendar = () => (
+ <box className="calendar">
+ <eventbox
+ setup={self => {
+ self.connect("button-press-event", (_, event: Gdk.Event) => {
+ if (event.get_button()[1] === Astal.MouseButton.MIDDLE) {
+ const now = new Date();
+ const child = self.get_child() as WCal | null;
+ if (!child) return;
+ child.select_month(now.getMonth(), now.getFullYear());
+ }
+ });
+ }}
+ >
+ <WCal
+ hexpand
+ showDetails={false}
+ day={0}
+ setup={self => {
+ const update = () => {
+ const now = new Date();
+ if (self.month === now.getMonth() && self.year === now.getFullYear()) self.day = now.getDate();
+ else self.day = 0;
+ };
+ self.connect("month-changed", update);
+ self.connect("next-month", update);
+ self.connect("prev-month", update);
+ self.connect("next-year", update);
+ self.connect("prev-year", update);
+ update();
+ }}
+ />
+ </eventbox>
+ </box>
+);
+
+const Weather = () => {
+ const weather = SWeather.get_default();
+
+ return (
+ <box vertical className="weather">
+ <centerbox className="current">
+ <label
+ halign={Gtk.Align.START}
+ valign={Gtk.Align.CENTER}
+ className="status-icon"
+ label={bind(weather, "icon")}
+ />
+ <box vertical halign={Gtk.Align.CENTER} valign={Gtk.Align.CENTER} className="status">
+ <box halign={Gtk.Align.CENTER} className="temperature">
+ <label label={bind(weather, "temperature").as(t => `${Math.round(t)}°C`)} />
+ <label
+ className={bind(weather, "tempColour").as(c => `temp-icon ${c}`)}
+ label={bind(weather, "tempIcon")}
+ />
+ </box>
+ <label label={bind(weather, "condition").as(c => ellipsize(c, 16))} />
+ </box>
+ <box vertical halign={Gtk.Align.END} valign={Gtk.Align.CENTER} className="other-data">
+ <label xalign={0} label={bind(weather, "wind").as(w => ` ${Math.round(w)} kph`)} />
+ <label xalign={0} label={bind(weather, "rainChance").as(r => ` ${r}%`)} />
+ </box>
+ </centerbox>
+ <box className="separator" />
+ <box className="forecast">
+ {Array.from({ length: 4 }).map((_, i) => (
+ <box vertical hexpand className="hour">
+ <label
+ label={bind(weather, "raw").as(r => {
+ const hour = getHoursFromUpdate(r, i + 1);
+ return `${hour % 12 || 12}${hour < 12 ? "AM" : "PM"}`;
+ })}
+ />
+ <label
+ className="icon"
+ label={bind(weather, "raw").as(r =>
+ weather.getIcon(weather.forecast[getHoursFromUpdate(r, i + 1)]?.condition.text ?? "")
+ )}
+ />
+ <label
+ label={bind(weather, "raw").as(
+ r => `${Math.round(weather.forecast[getHoursFromUpdate(r, i + 1)]?.temp_c) ?? "-"}°C`
+ )}
+ />
+ </box>
+ ))}
+ </box>
+ </box>
+ );
+};
+
+export default () => (
+ <PopupWindow name="sideright">
+ <box vertical className="sideright">
+ <Time />
+ <Calendar />
+ <Weather />
+ </box>
+ </PopupWindow>
+);