diff options
| author | 2 * r + 2 * t <61896496+soramanew@users.noreply.github.com> | 2025-04-26 22:36:23 +1000 |
|---|---|---|
| committer | 2 * r + 2 * t <61896496+soramanew@users.noreply.github.com> | 2025-04-26 22:36:23 +1000 |
| commit | 3c579d0e275cdaf6f2c9589abade94bde7905c82 (patch) | |
| tree | 4b825dc642cb6eb9a060e54bf8d69288fbee4904 /src/widgets | |
| parent | schemes: fix (diff) | |
| download | caelestia-shell-3c579d0e275cdaf6f2c9589abade94bde7905c82.tar.gz caelestia-shell-3c579d0e275cdaf6f2c9589abade94bde7905c82.tar.bz2 caelestia-shell-3c579d0e275cdaf6f2c9589abade94bde7905c82.zip | |
clean
Remove everything
Diffstat (limited to 'src/widgets')
| -rw-r--r-- | src/widgets/notification.tsx | 179 | ||||
| -rw-r--r-- | src/widgets/popupwindow.ts | 75 | ||||
| -rw-r--r-- | src/widgets/screencorner.tsx | 49 | ||||
| -rw-r--r-- | src/widgets/slider.tsx | 64 |
4 files changed, 0 insertions, 367 deletions
diff --git a/src/widgets/notification.tsx b/src/widgets/notification.tsx deleted file mode 100644 index 0dfd368..0000000 --- a/src/widgets/notification.tsx +++ /dev/null @@ -1,179 +0,0 @@ -import { desktopEntrySubs } from "@/utils/icons"; -import Thumbnailer from "@/utils/thumbnailer"; -import { setupCustomTooltip } from "@/utils/widgets"; -import { bind, GLib, register, timeout, Variable } from "astal"; -import { Astal, Gtk, Widget } from "astal/gtk3"; -import { notifpopups as config } from "config"; -import AstalNotifd from "gi://AstalNotifd"; - -const urgencyToString = (urgency: AstalNotifd.Urgency) => { - switch (urgency) { - case AstalNotifd.Urgency.LOW: - return "low"; - case AstalNotifd.Urgency.NORMAL: - return "normal"; - case AstalNotifd.Urgency.CRITICAL: - return "critical"; - } -}; - -const getTime = (time: number) => { - const messageTime = GLib.DateTime.new_from_unix_local(time); - const now = GLib.DateTime.new_now_local(); - const todayDay = now.get_day_of_year(); - - if (config.agoTime.get()) { - const diff = now.difference(messageTime) / 1e6; - if (diff < 60) return "Now"; - if (diff < 3600) { - const d = Math.floor(diff / 60); - return `${d} min${d === 1 ? "" : "s"} ago`; - } - if (diff < 86400) { - const d = Math.floor(diff / 3600); - return `${d} hour${d === 1 ? "" : "s"} ago`; - } - } else if (messageTime.get_day_of_year() === todayDay) { - const aMinuteAgo = GLib.DateTime.new_now_local().add_seconds(-60); - return aMinuteAgo !== null && messageTime.compare(aMinuteAgo) > 0 ? "Now" : messageTime.format("%H:%M")!; - } - - if (messageTime.get_day_of_year() === todayDay - 1) return "Yesterday"; - return messageTime.format("%d/%m")!; -}; - -const AppIcon = ({ appIcon, desktopEntry }: { appIcon: string; desktopEntry: string }) => { - // Try app icon - let icon = Astal.Icon.lookup_icon(appIcon) && appIcon; - // Try desktop entry - if (!icon) { - if (desktopEntrySubs.hasOwnProperty(desktopEntry)) icon = desktopEntrySubs[desktopEntry]; - else if (Astal.Icon.lookup_icon(desktopEntry)) icon = desktopEntry; - } - return icon ? <icon className="app-icon" icon={icon} /> : null; -}; - -const Image = ({ compact, icon }: { compact?: boolean; icon: string }) => { - if (GLib.file_test(icon, GLib.FileTest.EXISTS)) - return ( - <box - valign={Gtk.Align.START} - className={`image ${compact ? "small" : ""}`} - setup={self => - Thumbnailer.thumbnail(icon) - .then(p => (self.css = `background-image: url("${p}");`)) - .catch(console.error) - } - /> - ); - if (Astal.Icon.lookup_icon(icon)) - return <icon valign={Gtk.Align.START} className={`image ${compact ? "small" : ""}`} icon={icon} />; - return null; -}; - -@register() -export default class Notification extends Widget.Box { - readonly #revealer; - #destroyed = false; - - constructor({ - notification, - popup, - compact = popup, - }: { - notification: AstalNotifd.Notification; - popup?: boolean; - compact?: boolean; - }) { - super({ className: "notification" }); - - const time = Variable(getTime(notification.time)).poll(60000, () => getTime(notification.time)); - this.hook(config.agoTime, () => time.set(getTime(notification.time))); - - this.#revealer = ( - <revealer - revealChild={popup} - transitionType={Gtk.RevealerTransitionType.SLIDE_DOWN} - transitionDuration={150} - > - <box className="wrapper"> - <box vertical className={`inner ${urgencyToString(notification.urgency)}`}> - <box className="header"> - <AppIcon appIcon={notification.appIcon} desktopEntry={notification.appName} /> - <label className="app-name" label={notification.appName ?? "Unknown"} /> - <box hexpand /> - <label className="time" label={bind(time)} onDestroy={() => time.drop()} /> - </box> - <box hexpand className="separator" /> - <box className="content"> - {notification.image && <Image compact={compact} icon={notification.image} />} - <box vertical> - <label className="summary" xalign={0} label={notification.summary} truncate /> - {notification.body && ( - <label - className="body" - xalign={0} - label={compact ? notification.body.split("\n")[0] : notification.body} - wrap - lines={compact ? 1 : -1} - truncate={compact} - setup={self => compact && !popup && setupCustomTooltip(self, notification.body)} - /> - )} - </box> - </box> - {!popup && ( - <box className="actions"> - <button - hexpand - cursor="pointer" - onClicked={() => notification.dismiss()} - label="Close" - /> - {notification.actions.map(a => ( - <button hexpand cursor="pointer" onClicked={() => notification.invoke(a.id)}> - {notification.actionIcons ? <icon icon={a.label} /> : a.label} - </button> - ))} - </box> - )} - </box> - </box> - </revealer> - ) as Widget.Revealer; - this.add(this.#revealer); - - // Init animation - const width = this.get_preferred_width()[1]; - if (popup) this.css = `margin-left: ${width}px; margin-right: -${width}px;`; - timeout(1, () => { - this.#revealer.revealChild = true; - this.css = `transition: 300ms cubic-bezier(0.05, 0.9, 0.1, 1.1); margin-left: 0; margin-right: 0;`; - }); - - // Close popup after timeout if transient or expire enabled in config - if (popup && (config.expire.get() || notification.transient)) - timeout( - notification.expireTimeout > 0 - ? notification.expireTimeout - : notification.urgency === AstalNotifd.Urgency.CRITICAL - ? 10000 - : 5000, - () => this.destroyWithAnims() - ); - } - - destroyWithAnims() { - if (this.#destroyed) return; - this.#destroyed = true; - - const animTime = 120; - const animMargin = this.get_allocated_width(); - this.css = `transition: ${animTime}ms cubic-bezier(0.85, 0, 0.15, 1); - margin-left: ${animMargin}px; margin-right: -${animMargin}px;`; - timeout(animTime, () => { - this.#revealer.revealChild = false; - timeout(this.#revealer.transitionDuration, () => this.destroy()); - }); - } -} diff --git a/src/widgets/popupwindow.ts b/src/widgets/popupwindow.ts deleted file mode 100644 index 5ffa061..0000000 --- a/src/widgets/popupwindow.ts +++ /dev/null @@ -1,75 +0,0 @@ -import { Binding, register } from "astal"; -import { App, Astal, Gdk, Widget } from "astal/gtk3"; -import { bar } from "config"; -import AstalHyprland from "gi://AstalHyprland"; - -const extendProp = <T>( - prop: T | Binding<T | undefined> | undefined, - override: (prop: T | undefined) => T | undefined -) => prop && (prop instanceof Binding ? prop.as(override) : override(prop)); - -@register() -export default class PopupWindow extends Widget.Window { - constructor(props: Widget.WindowProps) { - super({ - keymode: Astal.Keymode.ON_DEMAND, - borderWidth: 20, // To allow shadow, cause if not it gets cut off - ...props, - visible: false, - application: App, - name: props.monitor ? extendProp(props.name, n => (n ? n + props.monitor : undefined)) : props.name, - namespace: extendProp(props.name, n => `caelestia-${n}`), - onKeyPressEvent: (self, event) => { - // Close window on escape - if (event.get_keyval()[1] === Gdk.KEY_Escape) self.hide(); - - return props.onKeyPressEvent?.(self, event); - }, - }); - } - - popup_at_widget(widget: JSX.Element, event: Gdk.Event | Astal.ClickEvent) { - const { width, height } = widget.get_allocation(); - const { width: mWidth, height: mHeight } = AstalHyprland.get_default().get_focused_monitor(); - const pWidth = this.get_preferred_width()[1]; - const pHeight = this.get_preferred_height()[1]; - const [, x, y] = event instanceof Gdk.Event ? event.get_coords() : [null, event.x, event.y]; - const { x: cx, y: cy } = AstalHyprland.get_default().get_cursor_position(); - - let marginLeft = 0; - let marginTop = 0; - if (bar.vertical.get()) { - marginLeft = cx + (width - x); - marginTop = cy + ((height - pHeight) / 2 - y); - if (marginTop < 0) marginTop = 0; - else if (marginTop + pHeight > mHeight) marginTop = mHeight - pHeight; - } else { - marginLeft = cx + ((width - pWidth) / 2 - x); - if (marginLeft < 0) marginLeft = 0; - else if (marginLeft + pWidth > mWidth) marginLeft = mWidth - pWidth; - marginTop = cy + (height - y); - } - - this.anchor = Astal.WindowAnchor.TOP | Astal.WindowAnchor.LEFT; - this.exclusivity = Astal.Exclusivity.IGNORE; - this.marginLeft = marginLeft; - this.marginTop = marginTop; - - this.show(); - } - - popup_at_corner(corner: `${"top" | "bottom"} ${"left" | "right"}`) { - let anchor = 0; - if (corner.includes("top")) anchor |= Astal.WindowAnchor.TOP; - else anchor |= Astal.WindowAnchor.BOTTOM; - if (corner.includes("left")) anchor |= Astal.WindowAnchor.LEFT; - else anchor |= Astal.WindowAnchor.RIGHT; - - this.anchor = anchor; - this.exclusivity = Astal.Exclusivity.NORMAL; - this.marginLeft = 0; - this.marginTop = 0; - - this.show(); - } -} diff --git a/src/widgets/screencorner.tsx b/src/widgets/screencorner.tsx deleted file mode 100644 index a55d782..0000000 --- a/src/widgets/screencorner.tsx +++ /dev/null @@ -1,49 +0,0 @@ -import type { Binding } from "astal"; -import { Gtk, type Widget } from "astal/gtk3"; -import type cairo from "cairo"; - -type Place = "topleft" | "topright" | "bottomleft" | "bottomright"; - -export default ({ place, ...rest }: Widget.DrawingAreaProps & { place: Place | Binding<Place> }) => ( - <drawingarea - {...rest} - className="screen-corner" - setup={self => { - self.connect("realize", () => self.get_window()?.set_pass_through(true)); - - const r = self.get_style_context().get_property("border-radius", Gtk.StateFlags.NORMAL) as number; - self.set_size_request(r, r); - self.connect("draw", (_, cr: cairo.Context) => { - const c = self.get_style_context().get_background_color(Gtk.StateFlags.NORMAL); - const r = self.get_style_context().get_property("border-radius", Gtk.StateFlags.NORMAL) as number; - self.set_size_request(r, r); - - switch (typeof place === "string" ? place : place.get()) { - case "topleft": - cr.arc(r, r, r, Math.PI, (3 * Math.PI) / 2); - cr.lineTo(0, 0); - break; - - case "topright": - cr.arc(0, r, r, (3 * Math.PI) / 2, 2 * Math.PI); - cr.lineTo(r, 0); - break; - - case "bottomleft": - cr.arc(r, 0, r, Math.PI / 2, Math.PI); - cr.lineTo(0, r); - break; - - case "bottomright": - cr.arc(0, 0, r, 0, Math.PI / 2); - cr.lineTo(r, r); - break; - } - - cr.closePath(); - cr.setSourceRGBA(c.red, c.green, c.blue, c.alpha); - cr.fill(); - }); - }} - /> -); diff --git a/src/widgets/slider.tsx b/src/widgets/slider.tsx deleted file mode 100644 index 0a66609..0000000 --- a/src/widgets/slider.tsx +++ /dev/null @@ -1,64 +0,0 @@ -import { bind, type Binding } from "astal"; -import { Gdk, Gtk, type Widget } from "astal/gtk3"; -import type cairo from "cairo"; - -export default ({ - value, - onChange, -}: { - value: Binding<number>; - onChange?: (self: Widget.DrawingArea, value: number) => void; -}) => ( - <drawingarea - hexpand - valign={Gtk.Align.CENTER} - className="slider" - css={bind(value).as(v => `font-size: ${Math.min(1, Math.max(0, v))}px;`)} - setup={self => { - const halfPi = Math.PI / 2; - - const styleContext = self.get_style_context(); - self.set_size_request(-1, styleContext.get_property("min-height", Gtk.StateFlags.NORMAL) as number); - - self.connect("draw", (_, cr: cairo.Context) => { - const styleContext = self.get_style_context(); - - const width = self.get_allocated_width(); - const height = styleContext.get_property("min-height", Gtk.StateFlags.NORMAL) as number; - self.set_size_request(-1, height); - - const progressValue = styleContext.get_property("font-size", Gtk.StateFlags.NORMAL) as number; - let radius = styleContext.get_property("border-radius", Gtk.StateFlags.NORMAL) as number; - - const bg = styleContext.get_background_color(Gtk.StateFlags.NORMAL); - cr.setSourceRGBA(bg.red, bg.green, bg.blue, bg.alpha); - - // Background - cr.arc(radius, radius, radius, -Math.PI, -halfPi); // Top left - cr.arc(width - radius, radius, radius, -halfPi, 0); // Top right - cr.arc(width - radius, height - radius, radius, 0, halfPi); // Bottom right - cr.arc(radius, height - radius, radius, halfPi, Math.PI); // Bottom left - cr.fill(); - - // Flatten when near 0 - radius = Math.min(radius, Math.min(width * progressValue, height) / 2); - - const progressPosition = width * progressValue - radius; - const fg = styleContext.get_color(Gtk.StateFlags.NORMAL); - cr.setSourceRGBA(fg.red, fg.green, fg.blue, fg.alpha); - - // Foreground - cr.arc(radius, radius, radius, -Math.PI, -halfPi); // Top left - cr.arc(progressPosition, radius, radius, -halfPi, 0); // Top right - cr.arc(progressPosition, height - radius, radius, 0, halfPi); // Bottom right - cr.arc(radius, height - radius, radius, halfPi, Math.PI); // Bottom left - cr.fill(); - }); - - self.add_events(Gdk.EventMask.BUTTON_PRESS_MASK); - self.connect("button-press-event", (_, event: Gdk.Event) => - onChange?.(self, event.get_coords()[1] / self.get_allocated_width()) - ); - }} - /> -); |