From 9e32cd4b61b7a22554d1ac046d685a916a926f3f Mon Sep 17 00:00:00 2001 From: 2 * r + 2 * t <61896496+soramanew@users.noreply.github.com> Date: Thu, 16 Jan 2025 22:29:13 +1100 Subject: updates: make popup window --- app.tsx | 2 + scss/bar.scss | 2 +- scss/updates.scss | 74 +++++++++++++++++++++++++++++++++++ src/modules/bar.tsx | 29 ++++++++------ src/modules/updates.tsx | 102 ++++++++++++++++++++++++++++++++++++++++++++++++ src/services/updates.ts | 46 ++++++++++++++++------ src/utils/widgets.ts | 11 +++++- style.scss | 1 + 8 files changed, 238 insertions(+), 29 deletions(-) create mode 100644 scss/updates.scss create mode 100644 src/modules/updates.tsx diff --git a/app.tsx b/app.tsx index 708532f..9743792 100644 --- a/app.tsx +++ b/app.tsx @@ -5,6 +5,7 @@ import Launcher from "./src/modules/launcher"; import Notifications from "./src/modules/notifications"; import NotifPopups from "./src/modules/notifpopups"; import Osds from "./src/modules/osds"; +import Updates from "./src/modules/updates"; import Monitors from "./src/services/monitors"; import Players from "./src/services/players"; @@ -26,6 +27,7 @@ App.start({ ; Monitors.get_default().forEach(m => ); ; + ; console.log("Caelestia started"); }, diff --git a/scss/bar.scss b/scss/bar.scss index 1d73319..7598f1b 100644 --- a/scss/bar.scss +++ b/scss/bar.scss @@ -88,7 +88,7 @@ color: scheme.$rosewater; } - .updates { + .pkg-updates { color: scheme.$blue; } diff --git a/scss/updates.scss b/scss/updates.scss new file mode 100644 index 0000000..11f9a3e --- /dev/null +++ b/scss/updates.scss @@ -0,0 +1,74 @@ +@use "sass:color"; +@use "scheme"; +@use "lib"; +@use "font"; + +.updates { + @include lib.rounded(8); + @include lib.border(scheme.$blue, 0.4, 2); + @include lib.shadow; + @include font.mono; + + min-width: lib.s(600); + min-height: lib.s(400); + background-color: scheme.$base; + color: scheme.$blue; + padding: lib.s(10) lib.s(12); + font-size: lib.s(14); + + .wrapper { + @include lib.element-decel; + + &:hover, + &:focus { + color: color.mix(scheme.$blue, scheme.$base, 80%); + } + + &:active { + color: color.mix(scheme.$blue, scheme.$base, 60%); + } + } + + .header { + @include lib.spacing(8); + + padding: 0 lib.s(5); + margin-bottom: lib.s(8); + font-size: lib.s(15); + + button { + @include lib.rounded(5); + @include lib.element-decel; + + padding: lib.s(3) lib.s(8); + + &:hover, + &:focus { + background-color: scheme.$surface0; + } + + &:active { + background-color: scheme.$surface1; + } + } + } + + .icon { + font-size: lib.s(32); + } + + .repos { + @include lib.spacing($vertical: true); + + .repo { + .header { + font-size: lib.s(16); + } + + .list { + color: scheme.$text; + margin-left: lib.s(12); + } + } + } +} diff --git a/src/modules/bar.tsx b/src/modules/bar.tsx index aeb6e42..cf08634 100644 --- a/src/modules/bar.tsx +++ b/src/modules/bar.tsx @@ -221,14 +221,7 @@ const Network = () => ( network.wifi.scan(); execAsync( "uwsm app -- foot -T nmtui fish -c 'sleep .1; set -e COLORTERM; TERM=xterm-old nmtui connect'" - ).catch(err => { - // Idk why but foot always throws this error when it opens - if ( - err.message !== - "warn: wayland.c:1619: compositor does not implement the XDG toplevel icon protocol\nwarn: terminal.c:1973: slave exited with signal 1 (Hangup)" - ) - console.error(err); - }); + ).catch(() => {}); // Ignore errors }); }} setup={self => { @@ -372,8 +365,16 @@ const StatusIcons = () => ( ); const PkgUpdates = () => ( - { + if (event.button === Astal.MouseButton.PRIMARY) { + const popup = App.get_window("updates") as PopupWindow | null; + if (popup) { + if (popup.visible) popup.hide(); + else popup.popup_at_widget(self, event); + } + } + }} setup={self => setupCustomTooltip( self, @@ -381,9 +382,11 @@ const PkgUpdates = () => ( ) } > - + + + ); const Unread = () => { diff --git a/src/modules/updates.tsx b/src/modules/updates.tsx new file mode 100644 index 0000000..0a8cbea --- /dev/null +++ b/src/modules/updates.tsx @@ -0,0 +1,102 @@ +import { bind, execAsync, Variable } from "astal"; +import { App, Astal, Gtk } from "astal/gtk3"; +import Updates, { Repo as IRepo, Update as IUpdate } from "../services/updates"; +import { MenuItem } from "../utils/widgets"; +import PopupWindow from "../widgets/popupwindow"; + +const constructItem = (label: string, exec: string, quiet = true) => + new MenuItem({ + label, + onActivate() { + App.get_window("updates")?.hide(); + execAsync(exec).catch(e => !quiet && console.error(e)); + }, + }); + +const Update = (update: IUpdate) => { + const menu = new Gtk.Menu(); + menu.append(constructItem("Open info in browser", `xdg-open '${update.url}'`, false)); + menu.append(constructItem("Open info in terminal", `uwsm app -- foot -H pacman -Qi ${update.name}`)); + menu.append(constructItem("Reinstall", `uwsm app -T -- yay -S ${update.name}`)); + menu.append(constructItem("Remove with dependencies", `uwsm app -T -- yay -Rns ${update.name}`)); + + return ( + + ); +}; + +const Repo = (repo: IRepo) => { + const expanded = Variable(false); + + return ( + + + + + {repo.updates.map(Update)} + + + + ); +}; + +const List = () => ( + + {bind(Updates.get_default(), "updateData").as(d => d.repos.map(Repo))} + +); + +export default () => ( + + + +