From 23d3b271b41bf3072aa69319e52156f7d0d1dafb Mon Sep 17 00:00:00 2001 From: retrozinndev Date: Sun, 16 Feb 2025 19:29:03 -0300 Subject: [PATCH] ags: finish center-window widget with big-media and calendar --- ags/scripts/notification-handler.ts | 95 ++++++++++--------- ags/scripts/runner/applications.ts | 0 ags/scripts/runner/math.ts | 0 ags/style.scss | 16 ++++ ags/style/_bar.scss | 20 +++- ags/style/_center-window.scss | 132 ++++++++++++++++++--------- ags/style/_float-notifications.scss | 41 +++++++++ ags/style/_mixins.scss | 10 -- ags/style/_wal.scss | 40 ++++---- ags/widget/Calendar.ts | 1 + ags/widget/Separator.ts | 7 +- ags/widget/bar/Audio.ts | 4 +- ags/widget/bar/Clock.ts | 5 +- ags/widget/bar/Media.ts | 8 +- ags/widget/center-window/BigMedia.ts | 108 ++++++++++++++-------- ags/window/CenterWindow.ts | 30 ++++-- ags/window/FloatingNotifications.ts | 18 +++- ags/window/Runner.ts | 37 ++++++++ ags/windows.ts | 3 +- 19 files changed, 394 insertions(+), 181 deletions(-) create mode 100644 ags/scripts/runner/applications.ts create mode 100644 ags/scripts/runner/math.ts create mode 100644 ags/style/_float-notifications.scss create mode 100644 ags/widget/Calendar.ts create mode 100644 ags/window/Runner.ts diff --git a/ags/scripts/notification-handler.ts b/ags/scripts/notification-handler.ts index 95f6085..3b75380 100644 --- a/ags/scripts/notification-handler.ts +++ b/ags/scripts/notification-handler.ts @@ -1,29 +1,30 @@ import AstalNotifd from "gi://AstalNotifd"; import { timeout } from "astal/time"; -import { Connectable } from "astal/binding"; -import { GObject, register, signal } from "astal"; +import { Subscribable } from "astal/binding"; +import { GObject, property, register, Variable } from "astal"; import { Windows } from "../windows"; +import { FloatingNotifications } from "../window/FloatingNotifications"; @register({ GTypeName: "Notifications" }) -class NotificationsClass extends GObject.Object implements Connectable { +class NotificationsClass extends GObject.Object implements Subscribable { private static instance: NotificationsClass; + + @property(AstalNotifd.Notifd) private notifd: AstalNotifd.Notifd; - public notifications: Array = []; + @property(Boolean) + private doNotDisturb: boolean = false; + + @property() public notificationHistory: Array = []; - @signal(AstalNotifd.Notification) - declare notificationAdded: (added: AstalNotifd.Notification) => void; - - @signal(Number) - declare notificationRemoved: (id: number) => void; - + @property() + public notifications: Variable> = new Variable>([]); public static getDefault(): NotificationsClass { if(!NotificationsClass.instance) { NotificationsClass.instance = new NotificationsClass(); - this.instance._init(); } return NotificationsClass.instance; @@ -36,13 +37,28 @@ class NotificationsClass extends GObject.Object implements Connectable { dontDisturb: false } as AstalNotifd.Notifd.ConstructorProps); - this.getNotifd().connect("notified", (_source: AstalNotifd.Notifd, id: number, _replaced: boolean) => { - this.addNotification(this.getNotifd().get_notification(id)); + this.getNotifd().connect("notified", (daemon: AstalNotifd.Notifd, id: number) => { + const notification: (AstalNotifd.Notification|null) = daemon.get_notification(id); + if(!notification) { + console.log("[LOG] Notification is null, ignoring"); + return; + } + + if(!this.doNotDisturb) { + this.handleNotification(notification); + return; + } + + this.addHistory(notification); }); } - public addNotification(notification: AstalNotifd.Notification) { - this.prependArray(this.notifications, this.getNotifd().get_notification(notification.id)); + public handleNotification(notification: AstalNotifd.Notification): void { + Windows.open(FloatingNotifications); + + let tmpArray = this.notifications.get().reverse(); + tmpArray.push(notification); + this.notifications.set(tmpArray.reverse()); // default timeout if undefined let notificationTimeout = 4000; @@ -56,47 +72,38 @@ class NotificationsClass extends GObject.Object implements Connectable { break; } - notification.urgency !== AstalNotifd.Urgency.CRITICAL ? + notification.urgency !== AstalNotifd.Urgency.CRITICAL && timeout(notificationTimeout, () => { - this.notifications.map((item: AstalNotifd.Notification) => - item.id === notification.id && (() => { - this.removeNotification(notification.id); - this.addToNotificationHistory(notification); - })()) - }) - : this.addToNotificationHistory(notification); + notification.dismiss(); + this.notifications.set(this.notifications.get().filter((item) => item.id !== notification.id)); + this.addHistory(notification); + }); - this.emit("notification-added", notification); } - public removeNotification(notificationId: number) { - if(this.notifications.length === 1) - Windows.close(Windows.getWindow("floating-notifications")!); - - this.notifications = this.notifications.filter((notification: AstalNotifd.Notification) => - notification.id !== notificationId); - - this.emit("notification-removed", notificationId); + public addHistory(notification: AstalNotifd.Notification): void { + let tmpArray: Array = this.notificationHistory.reverse() + .filter((item: AstalNotifd.Notification) => item.id !== notification.id); + tmpArray.push(notification); + this.notificationHistory = tmpArray.reverse(); } - public addToNotificationHistory(notification: AstalNotifd.Notification) { - this.prependArray(this.notificationHistory, notification); - } - - public removeFromNotificationHistory(notificationId: number) { + public removeHistory(notification: AstalNotifd.Notification) { this.notificationHistory = this.notificationHistory.filter((curNotification: AstalNotifd.Notification) => - curNotification.id !== notificationId); - } - - private prependArray(array: Array, item: any): Array { - let tmpArray = array.reverse(); - tmpArray.push(item); - return tmpArray.reverse(); + curNotification.id !== notification.id); } public getNotifd(): AstalNotifd.Notifd { return this.notifd; } + + get() { + return this.notifications.get(); + } + + subscribe(callback: (list: Array) => void) { + return this.notifications.subscribe(callback); + } } export const Notifications = new NotificationsClass(); diff --git a/ags/scripts/runner/applications.ts b/ags/scripts/runner/applications.ts new file mode 100644 index 0000000..e69de29 diff --git a/ags/scripts/runner/math.ts b/ags/scripts/runner/math.ts new file mode 100644 index 0000000..e69de29 diff --git a/ags/style.scss b/ags/style.scss index 5cf8c3e..9a880c1 100644 --- a/ags/style.scss +++ b/ags/style.scss @@ -2,11 +2,13 @@ @use "./style/wal"; @use "./style/mixins"; +@use "./style/colors"; @use "./style/bar"; @use "./style/osd"; @use "./style/control-center"; @use "./style/center-window"; +@use "./style/float-notifications"; * { @@ -16,3 +18,17 @@ window * { @include mixins.default-styles; } + +tooltip { + padding: 16px; + + & > box { + padding: 7px 8px; + border-radius: 10px; + background: rgba(colors.$bg-primary, .98); + font-size: 13.1px; + font-weight: 500; + color: colors.$fg-primary; + box-shadow: 0 1px 4px 1px rgba(colors.$bg-primary, .6); + } +} diff --git a/ags/style/_bar.scss b/ags/style/_bar.scss index 0a6646b..37de1dc 100644 --- a/ags/style/_bar.scss +++ b/ags/style/_bar.scss @@ -91,6 +91,10 @@ } } + .clock.open > button { + background-color: colors.$bg-primary; + } + .media-eventbox { & > .media { border-radius: 12px; @@ -98,6 +102,10 @@ padding: 0 8px; } + &:hover > .media { + box-shadow: inset 0 0 0 300px rgba(colors.$fg-primary, .2); + } + & .nf { margin-right: 4px; font-size: 14px; @@ -105,10 +113,9 @@ & .media-controls { transition: none; - padding-left: 6px; + padding: 0 6px; border-top-right-radius: 12px; border-bottom-right-radius: 12px; - background: linear-gradient(to left, colors.$bg-primary 45px, colors.$bg-primary); & > button { margin: 4px 1px; @@ -124,6 +131,12 @@ & .media > box { border-top-right-radius: 0; border-bottom-right-radius: 0; + padding: 0 6px; + } + + & .media { + padding-left: 0; + padding-right: 0; } } } @@ -154,7 +167,8 @@ .audio { @include mixins.reset-props; - &:hover > box { + &:hover > box, + &.open > box { background: colors.$bg-primary; } diff --git a/ags/style/_center-window.scss b/ags/style/_center-window.scss index ba39da2..f74f3d4 100644 --- a/ags/style/_center-window.scss +++ b/ags/style/_center-window.scss @@ -8,70 +8,118 @@ border-radius: 18px; padding: 12px; - & .left { - & > .top { - padding-bottom: 10px; + & .big-media { + padding: 6px; - & .time { - font-size: 28px; - font-weight: 800; + & > box > .image { + background-size: cover; + background-position: center center; + border-radius: 10px; + } + + & > .info { + padding: { + top: 4px; + bottom: 6px; + }; + + & .title { + font-size: 16px; + font-weight: 700; } - & .date { + & .artist { font-size: 14px; - font-weight: 500; + font-weight: 600; color: colors.$fg-disabled; } } - & .big-media { - padding: 6px 16px; + & slider { + background: transparent; + min-height: .6em; + } - & > box > .image { - background-size: cover; - background-position: center center; - border-radius: 10px; - } + & trough { + border-radius: 4px; + min-height: .6em; + } - & > .info { - padding: { - top: 4px; - bottom: 6px; - }; + & trough highlight { + border-radius: 4px; + min-height: .6em; + } - & .title { - font-size: 16px; - font-weight: 700; - } - - & .artist { - font-size: 14px; - font-weight: 600; - color: colors.$fg-disabled; + & .bottom { + & .controls { + margin-top: 5px; + & button { + padding: 7px; + & label { + font-size: 10px; + } } } - & > .controls { - padding: 8px 0; + & .elapsed, + & .length { + font-size: 12px; + color: colors.$fg-disabled; } } } - & .right { - & .calendar-box { - padding: 5px; - & calendar { + & .left .top { + padding-bottom: 10px; + + & .time { + font-size: 28px; + font-weight: 800; + } + + & .date { + font-size: 14px; + font-weight: 500; + color: colors.$fg-disabled; + } + } + + & .calendar-box { + & calendar { + $border-radius: 10px; + font-weight: 600; + padding-bottom: 2px; + + &.view { + background: colors.$bg-primary; + border-radius: $border-radius; + } + + &.header { + background: colors.$bg-secondary; + border-top-left-radius: $border-radius; + border-top-right-radius: $border-radius; + padding: 4px; + } + + &.button { + transition: 80ms linear; border-radius: 6px; - padding: 2px; - &.view { - background: funs.toRGB(color.adjust($color: wal.$color1, $lightness: -35%)); - - & header { - background: funs.toRGB(color.adjust($color: wal.$background, $lightness: -20%)); - } + &:hover { + background-color: colors.$bg-tertiary; } } + + &:selected { + background: colors.$bg-secondary; + border-radius: 6px; + } + + &.highlight { + background: transparent; + box-shadow: 0 2px 0 -1px rgba(colors.$bg-secondary, .5); + } } } } diff --git a/ags/style/_float-notifications.scss b/ags/style/_float-notifications.scss new file mode 100644 index 0000000..2144b85 --- /dev/null +++ b/ags/style/_float-notifications.scss @@ -0,0 +1,41 @@ +@use "./colors"; + +.floating-notifications-container { + padding: { + right: 6px; + top: 6px; + }; + + & > .notification { + background: colors.$bg-primary; + border-radius: 16px; + padding: 12px; + margin: 6px 0; + + & > .top { + & .app-name { + font-size: 12px; + color: colors.$fg-disabled; + } + } + + & .content { + & .image { + $size: 78px; + min-width: $size; + min-height: $size; + background-size: cover; + background-position: center 0; + margin: 6px; + } + } + + &:first-child { + margin-top: 0; + } + + &:last-child { + margin-bottom: 0; + } + } +} diff --git a/ags/style/_mixins.scss b/ags/style/_mixins.scss index ac75827..23cb574 100644 --- a/ags/style/_mixins.scss +++ b/ags/style/_mixins.scss @@ -69,16 +69,6 @@ } } - & tooltip { - padding: 8px; - border-radius: 14px; - - & label { - font-size: 14px; - color: colors.$fg-primary; - } - } - & trough { background: funs.toRGB(color.adjust($color: wal.$color1, $lightness: -20%)); border-radius: 8px; diff --git a/ags/style/_wal.scss b/ags/style/_wal.scss index c9e4351..32387bc 100644 --- a/ags/style/_wal.scss +++ b/ags/style/_wal.scss @@ -1,26 +1,26 @@ // SCSS Variables // Generated by 'wal' -$wallpaper: "/home/joaov/wallpapers/Miku, Rin and Luka Chibi.jpg"; +$wallpaper: "/home/joaov/wallpapers/Miku Bush.jpg"; // Special -$background: #3d2217; -$foreground: #cec7c5; -$cursor: #cec7c5; +$background: #0f1b06; +$foreground: #c3c6c0; +$cursor: #c3c6c0; // Colors -$color0: #3d2217; -$color1: #b38678; -$color2: #a4998a; -$color3: #b39e8a; -$color4: #a5a09b; -$color5: #aea299; -$color6: #b4aea2; -$color7: #a39c99; -$color8: #7f6f68; -$color9: #EFB3A1; -$color10: #DBCCB9; -$color11: #EFD3B9; -$color12: #DDD6CF; -$color13: #E8D8CD; -$color14: #F1E8D9; -$color15: #cec7c5; +$color0: #0f1b06; +$color1: #4e7278; +$color2: #5b7b94; +$color3: #71807c; +$color4: #7b9882; +$color5: #a3a881; +$color6: #778591; +$color7: #93988d; +$color8: #626d59; +$color9: #6898A1; +$color10: #7AA5C6; +$color11: #97ABA6; +$color12: #A5CBAE; +$color13: #DAE0AC; +$color14: #9FB2C2; +$color15: #c3c6c0; diff --git a/ags/widget/Calendar.ts b/ags/widget/Calendar.ts new file mode 100644 index 0000000..8ad1dfb --- /dev/null +++ b/ags/widget/Calendar.ts @@ -0,0 +1 @@ +//TODO diff --git a/ags/widget/Separator.ts b/ags/widget/Separator.ts index 8f5cbab..53d4559 100644 --- a/ags/widget/Separator.ts +++ b/ags/widget/Separator.ts @@ -1,3 +1,4 @@ +import { Binding } from "astal"; import { Gtk, Widget } from "astal/gtk3"; export interface SeparatorProps { @@ -6,21 +7,23 @@ export interface SeparatorProps { cssColor?: string; orientation?: Gtk.Orientation; size?: number; + visible?: boolean | Binding; } export function Separator(props: SeparatorProps) { return new Widget.Box({ className: `separator separator-${ props.orientation == Gtk.Orientation.VERTICAL ? "vertical" : "horizontal" } ${ props.class && props.class }`, + visible: props.visible, css: `.separator { background: ${ props.cssColor || "lightgray" }; opacity: ${ props.alpha || 1 }; } .separator-horizontal { - padding-right: ${props.size || 1 }px; + padding-bottom: ${props.size || 1 }px; margin: 7px 4px; } .separator-vertical { - padding-bottom: ${props.size || 1 }px; + padding-right: ${props.size || 1 }px; margin: 4px 7px; }`, } as Widget.BoxProps); diff --git a/ags/widget/bar/Audio.ts b/ags/widget/bar/Audio.ts index 98c1cce..40e5e60 100644 --- a/ags/widget/bar/Audio.ts +++ b/ags/widget/bar/Audio.ts @@ -2,12 +2,14 @@ import { bind, Process } from "astal"; import { Widget } from "astal/gtk3"; import AstalWp from "gi://AstalWp"; import { Wireplumber } from "../../scripts/volume"; +import { ControlCenter } from "../../window/ControlCenter"; const wp = AstalWp.get_default(); export function Audio() { return wp && new Widget.EventBox({ - className: "audio", + className: bind(ControlCenter, "visible").as((visible: boolean) => + visible ? "audio open" : "audio"), onClick: () => Process.exec_async("astal toggle control-center", () => {}), child: new Widget.Box({ children: [ diff --git a/ags/widget/bar/Clock.ts b/ags/widget/bar/Clock.ts index fdd44a0..3939e1d 100644 --- a/ags/widget/bar/Clock.ts +++ b/ags/widget/bar/Clock.ts @@ -1,12 +1,13 @@ import { Widget } from "astal/gtk3"; import { getDateTime } from "../../scripts/time"; -import { GLib } from "astal"; +import { bind, GLib } from "astal"; import { Windows } from "../../windows"; import { CenterWindow } from "../../window/CenterWindow"; export function Clock(): JSX.Element { return new Widget.Box({ - className: "clock", + className: bind(CenterWindow, "visible").as((visible: boolean) => + visible ? "clock open" : "clock"), child: new Widget.Button({ onClick: () => Windows.toggle(CenterWindow), label: getDateTime().as((dateTime: GLib.DateTime) => { diff --git a/ags/widget/bar/Media.ts b/ags/widget/bar/Media.ts index 6ab151a..49e1d20 100644 --- a/ags/widget/bar/Media.ts +++ b/ags/widget/bar/Media.ts @@ -2,6 +2,8 @@ import { bind, GLib, Process } from "astal"; import { Gtk, Widget } from "astal/gtk3"; import AstalMpris from "gi://AstalMpris"; import { Separator, SeparatorProps } from "../Separator"; +import { CenterWindow } from "../../window/CenterWindow"; +import { Windows } from "../../windows"; const mpris: AstalMpris.Mpris = AstalMpris.get_default(); @@ -66,7 +68,10 @@ export function Media(): Gtk.Widget { const mediaWidget = new Widget.EventBox({ className: "media-eventbox", - visible: bind(mpris, "players").as((players: Array) => players[0]).as(Boolean), + visible: bind(mpris, "players").as((players: Array) => { + return players[0] && players[0].get_available() || CenterWindow.is_visible(); + }), + onClick: () => Windows.toggle(CenterWindow), child: new Widget.Box({ className: "media", children: [ @@ -85,6 +90,7 @@ export function Media(): Gtk.Widget { label: bind(players[0], "title").as((title: string) => title || "No Title") } as Widget.LabelProps), Separator({ + orientation: Gtk.Orientation.VERTICAL, size: 2, cssColor: `rgb(180, 180, 180)`, alpha: 1 diff --git a/ags/widget/center-window/BigMedia.ts b/ags/widget/center-window/BigMedia.ts index 687749a..dcb5cfd 100644 --- a/ags/widget/center-window/BigMedia.ts +++ b/ags/widget/center-window/BigMedia.ts @@ -8,8 +8,11 @@ export const BigMedia: Gtk.Widget = new Widget.Box({ className: "big-media", orientation: Gtk.Orientation.VERTICAL, homogeneous: false, + width_request: 250, + visible: bind(AstalMpris.get_default(), "players").as((players: Array) => + players[0] ? true : false), children: bind(AstalMpris.get_default(), "players").as((players: Array) => - players[0] ? [ + players[0] && [ new Widget.Box({ halign: Gtk.Align.CENTER, child: new Widget.Box({ @@ -72,45 +75,70 @@ export const BigMedia: Gtk.Widget = new Widget.Box({ }) ] }), - new Widget.Box({ - className: "controls button-row", + new Widget.CenterBox({ + className: "bottom", + homogeneous: false, hexpand: true, - halign: Gtk.Align.CENTER, - children: [ - new Widget.Button({ - className: "link nf", - label: "󰌹", - tooltipText: "Copy link to Clipboard", - visible: bind(players[0], "metadata").as((_metadata: GLib.HashTable) => - players[0].get_meta("xesam:url") === null), - onClick: () => Process.exec(`wl-copy ${players[0].get_meta("xesam:url")?.get_string()[0]}`) - } as Widget.ButtonProps), - new Widget.Button({ - className: "previous nf", - label: "󰒮", - tooltipText: "Previous", - onClick: () => players[0].canGoPrevious && players[0].previous() - } as Widget.ButtonProps), - new Widget.Button({ - className: "pause nf", - tooltipText: bind(players[0], "playback_status").as((status: AstalMpris.PlaybackStatus) => - status === AstalMpris.PlaybackStatus.PLAYING ? "Pause" : "Play"), - label: bind(players[0], "playbackStatus").as((status: AstalMpris.PlaybackStatus) => - status === AstalMpris.PlaybackStatus.PLAYING ? "󰏤" : "󰐊"), - onClick: () => { - players[0].playbackStatus === AstalMpris.PlaybackStatus.PAUSED ? - players[0].play() - : - players[0].pause() - } - } as Widget.ButtonProps), - new Widget.Button({ - className: "next nf", - label: "󰒭", - tooltipText: "Next", - onClick: () => players[0].canGoNext && players[0].next() - } as Widget.ButtonProps) - ] + startWidget: new Widget.Label({ + className: "elapsed", + valign: Gtk.Align.START, + halign: Gtk.Align.START, + label: bind(players[0], "position").as((pos: number) => { + const sec: number = Math.floor(pos % 60); + return pos > 0 && players[0].length > 0 ? + `${Math.floor(pos / 60)}:${sec < 10 ? "0" : ""}${sec}` + : `0:00`; + }) + } as Widget.LabelProps), + centerWidget: new Widget.Box({ + className: "controls button-row", + children: [ + new Widget.Button({ + className: "link nf", + label: "󰌹", + tooltipText: "Copy link to Clipboard", + visible: bind(players[0], "metadata").as((_meta: GLib.HashTable) => + players[0].get_meta("xesam:url") === null), + onClick: () => Process.exec(`wl-copy ${players[0].get_meta("xesam:url")?.get_string()[0]}`) + } as Widget.ButtonProps), + new Widget.Button({ + className: "previous nf", + label: "󰒮", + tooltipText: "Previous", + onClick: () => players[0].canGoPrevious && players[0].previous() + } as Widget.ButtonProps), + new Widget.Button({ + className: "pause nf", + tooltipText: bind(players[0], "playback_status").as((status: AstalMpris.PlaybackStatus) => + status === AstalMpris.PlaybackStatus.PLAYING ? "Pause" : "Play"), + label: bind(players[0], "playbackStatus").as((status: AstalMpris.PlaybackStatus) => + status === AstalMpris.PlaybackStatus.PLAYING ? "󰏤" : "󰐊"), + onClick: () => { + players[0].playbackStatus === AstalMpris.PlaybackStatus.PAUSED ? + players[0].play() + : + players[0].pause() + } + } as Widget.ButtonProps), + new Widget.Button({ + className: "next nf", + label: "󰒭", + tooltipText: "Next", + onClick: () => players[0].canGoNext && players[0].next() + } as Widget.ButtonProps) + ] + } as Widget.BoxProps), + endWidget: new Widget.Label({ + className: "length", + valign: Gtk.Align.START, + halign: Gtk.Align.END, + label: bind(players[0], "length").as((len/* bananananananana */: number) => { + const sec: number = Math.floor(len % 60); + return len > 0 ? + `${Math.floor(len / 60)}:${sec < 10 ? "0" : ""}${sec}` + : "0:00"; + }) + } as Widget.LabelProps) }) - ] : new Widget.Box({ className: "empty no-media" })) + ]) } as Widget.BoxProps); diff --git a/ags/window/CenterWindow.ts b/ags/window/CenterWindow.ts index 1163386..d415f21 100644 --- a/ags/window/CenterWindow.ts +++ b/ags/window/CenterWindow.ts @@ -1,8 +1,9 @@ import { Astal, Gtk, Widget } from "astal/gtk3"; -import { GLib } from "astal"; +import { bind, GLib } from "astal"; import { getDateTime } from "../scripts/time"; import { BigMedia } from "../widget/center-window/BigMedia"; +import { Separator, SeparatorProps } from "../widget/Separator"; export const CenterWindow: Widget.Window = new Widget.Window({ className: "center-window", @@ -12,7 +13,6 @@ export const CenterWindow: Widget.Window = new Widget.Window({ layer: Astal.Layer.OVERLAY, exclusivity: Astal.Exclusivity.NORMAL, visible: false, - height_request: 400, margin_top: 10, anchor: Astal.WindowAnchor.TOP, child: new Widget.Box({ @@ -21,7 +21,6 @@ export const CenterWindow: Widget.Window = new Widget.Window({ new Widget.Box({ className: "vertical left", orientation: Gtk.Orientation.VERTICAL, - width_request: 300, children: [ new Widget.Box({ className: "top", @@ -36,18 +35,15 @@ export const CenterWindow: Widget.Window = new Widget.Window({ new Widget.Label({ className: "date", label: getDateTime().as((dateTime: GLib.DateTime) => - dateTime.format("%A, %B %d %Y")) + dateTime.format("%A, %B %d")) } as Widget.LabelProps) ] } as Widget.BoxProps), - BigMedia - ] - } as Widget.BoxProps), - new Widget.Box({ - className: "vertical right", - children: [ new Widget.Box({ className: "calendar-box", + vexpand: false, + hexpand: true, + valign: Gtk.Align.START, child: new Gtk.Calendar({ visible: true, show_heading: true, @@ -56,6 +52,20 @@ export const CenterWindow: Widget.Window = new Widget.Window({ } as Gtk.Calendar.ConstructorProps) } as Widget.BoxProps) ] + } as Widget.BoxProps), + Separator({ + visible: bind(BigMedia, "visible"), + orientation: Gtk.Orientation.VERTICAL, + alpha: .5, + cssColor: "gray", + size: 1 + } as SeparatorProps), + new Widget.Box({ + className: "vertical right", + orientation: Gtk.Orientation.VERTICAL, + children: [ + BigMedia + ] } as Widget.BoxProps) ] } as Widget.BoxProps) diff --git a/ags/window/FloatingNotifications.ts b/ags/window/FloatingNotifications.ts index 3d2d343..e0a6692 100644 --- a/ags/window/FloatingNotifications.ts +++ b/ags/window/FloatingNotifications.ts @@ -16,14 +16,22 @@ function NotificationWidget(notification: AstalNotifd.Notification): Gtk.Widget hexpand: true, vexpand: false, children: [ + new Widget.Icon({ + className: "icon", + visible: notification.appIcon !== "", + icon: notification.appIcon || "image-missing", + iconSize: Gtk.IconSize.DND, + css: ".icon { font-size: 24px; }" + }), new Widget.Label({ className: "app-name", halign: Gtk.Align.START, label: notification.appName || "Unknown Application" } as Widget.LabelProps), new Widget.Button({ - className: "close-button", - onClick: () => Notifications.removeNotification(notification.id) + className: "close nf", + onClick: () => notification.dismiss(), + label: "󰅖" } as Widget.ButtonProps) ] } as Widget.BoxProps), @@ -71,8 +79,8 @@ export const FloatingNotifications: Widget.Window = new Widget.Window({ className: "floating-notifications-container", orientation: Gtk.Orientation.VERTICAL, homogeneous: false, - children: bind(Notifications, "notifications").as((notifications: Array) => - notifications.map((notification: AstalNotifd.Notification) => - NotificationWidget(notification))) + children: Notifications.notifications().as((notifications: Array) => + notifications.map((item: AstalNotifd.Notification) => + NotificationWidget(item))) } as Widget.BoxProps) } as Widget.WindowProps); diff --git a/ags/window/Runner.ts b/ags/window/Runner.ts new file mode 100644 index 0000000..82410a7 --- /dev/null +++ b/ags/window/Runner.ts @@ -0,0 +1,37 @@ +import { Variable } from "astal"; +import { Astal, Gtk, Widget } from "astal/gtk3"; + +// TODO + +export interface RunnerProps { + anchor?: Astal.WindowAnchor; + width?: number; + height?: number; + entryPlaceHolder?: string; + resultsPlaceholder?: Array; +} + +export function Runner(props?: RunnerProps) { + + const entryText: Variable = new Variable(""); + + const resultsBox: Widget.Box = new Widget.Box({ + className: "results", + + } as Widget.BoxProps); + + return new Widget.Window({ + namespace: "runner", + widthRequest: props?.width || 600, + heightRequest: props?.height || 500, + child: new Widget.Box({ + className: "main", + children: [ + new Widget.Entry({ + className: "search", + onChanged: (entry) => entryText.set(entry.text), + } as Widget.EntryProps), + ] + } as Widget.BoxProps) + } as Widget.WindowProps); +} diff --git a/ags/windows.ts b/ags/windows.ts index e0d7ec7..dbe36f9 100644 --- a/ags/windows.ts +++ b/ags/windows.ts @@ -1,4 +1,4 @@ -import { Gtk, Widget } from "astal/gtk3"; +import { Gtk } from "astal/gtk3"; import { Bar } from "./window/Bar"; import { OSD } from "./window/OSD"; @@ -22,6 +22,7 @@ export const Windows = GObject.registerClass({ WindowsClass.windowsMap.set("control-center", ControlCenter); WindowsClass.windowsMap.set("center-window", CenterWindow); WindowsClass.windowsMap.set("logout-menu", LogoutMenu); + WindowsClass.windowsMap.set("floating-notifications", FloatingNotifications); } public _init(...args: any[]) {