diff options
| author | 2 * r + 2 * t <61896496+soramanew@users.noreply.github.com> | 2025-03-27 21:02:05 +1100 |
|---|---|---|
| committer | 2 * r + 2 * t <61896496+soramanew@users.noreply.github.com> | 2025-03-27 21:02:05 +1100 |
| commit | 3b2130f286b9d2a15b73d55e48c532a43cf9fe08 (patch) | |
| tree | b2cfb040709a223fa3a0a4f6c6b41dedaaab6fb6 /src | |
| parent | sidebar: package news module (diff) | |
| download | caelestia-shell-3b2130f286b9d2a15b73d55e48c532a43cf9fe08.tar.gz caelestia-shell-3b2130f286b9d2a15b73d55e48c532a43cf9fe08.tar.bz2 caelestia-shell-3b2130f286b9d2a15b73d55e48c532a43cf9fe08.zip | |
sidebar: updates module
Diffstat (limited to 'src')
| -rw-r--r-- | src/modules/sidebar/modules/news.tsx | 2 | ||||
| -rw-r--r-- | src/modules/sidebar/modules/updates.tsx | 109 | ||||
| -rw-r--r-- | src/modules/sidebar/packages.tsx | 1 |
3 files changed, 111 insertions, 1 deletions
diff --git a/src/modules/sidebar/modules/news.tsx b/src/modules/sidebar/modules/news.tsx index f3be53e..aba37c7 100644 --- a/src/modules/sidebar/modules/news.tsx +++ b/src/modules/sidebar/modules/news.tsx @@ -99,7 +99,7 @@ export default () => ( > <NoNews /> <scrollable - expand={bind(Updates.get_default(), "news").as(n => !!n)} + className={bind(Updates.get_default(), "news").as(n => (n ? "expanded" : ""))} hscroll={Gtk.PolicyType.NEVER} name="list" > diff --git a/src/modules/sidebar/modules/updates.tsx b/src/modules/sidebar/modules/updates.tsx new file mode 100644 index 0000000..3b159c6 --- /dev/null +++ b/src/modules/sidebar/modules/updates.tsx @@ -0,0 +1,109 @@ +import Palette from "@/services/palette"; +import Updates, { Repo as IRepo, Update as IUpdate } from "@/services/updates"; +import { MenuItem, setupCustomTooltip } from "@/utils/widgets"; +import { bind, execAsync, GLib, Variable } from "astal"; +import { Astal, Gtk } from "astal/gtk3"; + +const constructItem = (label: string, exec: string, quiet = true) => + new MenuItem({ label, onActivate: () => 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(new Gtk.SeparatorMenuItem({ visible: true })); + menu.append(constructItem("Reinstall", `uwsm app -- foot -H -- yay -S ${update.name}`)); + menu.append(constructItem("Remove with dependencies", `uwsm app -- foot -H -- yay -Rns ${update.name}`)); + + return ( + <button + onClick={(_, event) => event.button === Astal.MouseButton.SECONDARY && menu.popup_at_pointer(null)} + onDestroy={() => menu.destroy()} + > + <label + truncate + useMarkup + xalign={0} + label={bind(Palette.get_default(), "colours").as( + c => + `${update.name} <span foreground="${c.teal}">(${update.version.old} -> ${ + update.version.new + })</span>\n <span foreground="${c.subtext0}">${GLib.markup_escape_text( + update.description, + update.description.length + )}</span>` + )} + setup={self => setupCustomTooltip(self, `${update.name} • ${update.description}`)} + /> + </button> + ); +}; + +const Repo = ({ repo }: { repo: IRepo }) => { + const expanded = Variable(false); + + return ( + <box vertical className="repo"> + <button className="wrapper" cursor="pointer" onClicked={() => expanded.set(!expanded.get())}> + <box className="header"> + <label className="icon" label={repo.icon} /> + <label label={`${repo.name} (${repo.updates.length})`} /> + <box hexpand /> + <label className="icon" label={bind(expanded).as(e => (e ? "expand_less" : "expand_more"))} /> + </box> + </button> + <revealer + revealChild={bind(expanded)} + transitionType={Gtk.RevealerTransitionType.SLIDE_DOWN} + transitionDuration={200} + > + <box vertical className="body"> + {repo.updates.map(Update)} + </box> + </revealer> + </box> + ); +}; + +const List = () => ( + <box vertical valign={Gtk.Align.START} className="list"> + {bind(Updates.get_default(), "updateData").as(d => d.repos.map(r => <Repo repo={r} />))} + </box> +); + +const NoUpdates = () => ( + <box homogeneous name="empty"> + <box vertical halign={Gtk.Align.CENTER} valign={Gtk.Align.CENTER} className="empty"> + <label className="icon" label="deployed_code_history" /> + <label label="All packages up to date!" /> + </box> + </box> +); + +export default () => ( + <box vertical className="updates"> + <box className="header-bar"> + <label + label={bind(Updates.get_default(), "numUpdates").as(n => `${n} update${n === 1 ? "" : "s"} available`)} + /> + <box hexpand /> + <button + className={bind(Updates.get_default(), "loading").as(l => (l ? "enabled" : ""))} + sensitive={bind(Updates.get_default(), "loading").as(l => !l)} + cursor="pointer" + onClicked={() => Updates.get_default().getUpdates()} + label={bind(Updates.get_default(), "loading").as(l => (l ? " Loading" : " Reload"))} + /> + </box> + <stack + transitionType={Gtk.StackTransitionType.CROSSFADE} + transitionDuration={200} + shown={bind(Updates.get_default(), "numUpdates").as(n => (n > 0 ? "list" : "empty"))} + > + <NoUpdates /> + <scrollable expand hscroll={Gtk.PolicyType.NEVER} name="list"> + <List /> + </scrollable> + </stack> + </box> +); diff --git a/src/modules/sidebar/packages.tsx b/src/modules/sidebar/packages.tsx index 97381b1..c073850 100644 --- a/src/modules/sidebar/packages.tsx +++ b/src/modules/sidebar/packages.tsx @@ -3,6 +3,7 @@ import Updates from "./modules/updates"; export default () => ( <box vertical className="pane packages" name="packages"> + <Updates /> <box className="separator" /> <News /> </box> |