diff options
| author | 2 * r + 2 * t <61896496+soramanew@users.noreply.github.com> | 2025-02-25 15:33:08 +1100 |
|---|---|---|
| committer | 2 * r + 2 * t <61896496+soramanew@users.noreply.github.com> | 2025-02-25 15:33:08 +1100 |
| commit | 01626b70f10b38a6c03e5701283a43e9920fc26d (patch) | |
| tree | 0042e856dc30df6760e81a245cac977b2abd3dd7 /src | |
| parent | launcher: italic xwayland windows (diff) | |
| download | caelestia-shell-01626b70f10b38a6c03e5701283a43e9920fc26d.tar.gz caelestia-shell-01626b70f10b38a6c03e5701283a43e9920fc26d.tar.bz2 caelestia-shell-01626b70f10b38a6c03e5701283a43e9920fc26d.zip | |
updates: show arch news
Diffstat (limited to 'src')
| -rw-r--r-- | src/modules/popdowns/updates.tsx | 48 | ||||
| -rw-r--r-- | src/services/palette.ts | 240 | ||||
| -rw-r--r-- | src/services/updates.ts | 16 |
3 files changed, 297 insertions, 7 deletions
diff --git a/src/modules/popdowns/updates.tsx b/src/modules/popdowns/updates.tsx index 9e98f66..fd98671 100644 --- a/src/modules/popdowns/updates.tsx +++ b/src/modules/popdowns/updates.tsx @@ -1,3 +1,4 @@ +import Palette from "@/services/palette"; import Updates, { Repo as IRepo, Update as IUpdate } from "@/services/updates"; import { MenuItem } from "@/utils/widgets"; import PopdownWindow from "@/widgets/popdownwindow"; @@ -35,8 +36,8 @@ const Update = (update: IUpdate) => { ); }; -const Repo = (repo: IRepo) => { - const expanded = Variable(false); +const Repo = ({ repo, first }: { repo: IRepo; first?: boolean }) => { + const expanded = Variable(first); return ( <box vertical className="repo"> @@ -61,9 +62,50 @@ const Repo = (repo: IRepo) => { ); }; +const News = ({ news }: { news: string }) => { + const expanded = Variable(true); + + return ( + <box vertical className="repo"> + <button className="wrapper" cursor="pointer" onClicked={() => expanded.set(!expanded.get())}> + <box className="header"> + <label className="icon" label="newspaper" /> + <label label="News" /> + <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} + > + <label + wrap + useMarkup + xalign={0} + className="news" + label={bind(Palette.get_default(), "teal").as(c => + news + .slice(0, news.lastIndexOf("\n")) // Remove last line cause it contains an unopened \x1b[0m + .replace(/^([0-9]{4}-[0-9]{2}-[0-9]{2} .+)$/gm, "<b>$1</b>") // Make titles bold + // Replace color codes with html spans + .replaceAll("\x1b[36m", `<span foreground="${c}">`) + .replaceAll("\x1b[0m", "</span>") + )} + /> + </revealer> + </box> + ); +}; + const List = () => ( <box vertical valign={Gtk.Align.START} className="repos"> - {bind(Updates.get_default(), "updateData").as(d => d.repos.map(Repo))} + {bind(Updates.get_default(), "updateData").as(d => + d.news + ? [<News news={d.news} />, ...d.repos.map(r => <Repo repo={r} />)] + : d.repos.map((r, i) => <Repo repo={r} first={i === 0} />) + )} </box> ); diff --git a/src/services/palette.ts b/src/services/palette.ts new file mode 100644 index 0000000..b925d50 --- /dev/null +++ b/src/services/palette.ts @@ -0,0 +1,240 @@ +import { GLib, GObject, monitorFile, property, readFile, register } from "astal"; + +export type Hex = `#${string}`; + +export interface IPalette { + rosewater: Hex; + flamingo: Hex; + pink: Hex; + mauve: Hex; + red: Hex; + maroon: Hex; + peach: Hex; + yellow: Hex; + green: Hex; + teal: Hex; + sky: Hex; + sapphire: Hex; + blue: Hex; + lavender: Hex; + text: Hex; + subtext1: Hex; + subtext0: Hex; + overlay2: Hex; + overlay1: Hex; + overlay0: Hex; + surface2: Hex; + surface1: Hex; + surface0: Hex; + base: Hex; + mantle: Hex; + crust: Hex; + accent: Hex; +} + +@register({ GTypeName: "Palette" }) +export default class Palette extends GObject.Object { + static instance: Palette; + static get_default() { + if (!this.instance) this.instance = new Palette(); + + return this.instance; + } + + #colours!: IPalette; + + @property(Object) + get colours() { + return this.#colours; + } + + @property(String) + get rosewater() { + return this.#colours.rosewater; + } + + @property(String) + get flamingo() { + return this.#colours.flamingo; + } + + @property(String) + get pink() { + return this.#colours.pink; + } + + @property(String) + get mauve() { + return this.#colours.mauve; + } + + @property(String) + get red() { + return this.#colours.red; + } + + @property(String) + get maroon() { + return this.#colours.maroon; + } + + @property(String) + get peach() { + return this.#colours.peach; + } + + @property(String) + get yellow() { + return this.#colours.yellow; + } + + @property(String) + get green() { + return this.#colours.green; + } + + @property(String) + get teal() { + return this.#colours.teal; + } + + @property(String) + get sky() { + return this.#colours.sky; + } + + @property(String) + get sapphire() { + return this.#colours.sapphire; + } + + @property(String) + get blue() { + return this.#colours.blue; + } + + @property(String) + get lavender() { + return this.#colours.lavender; + } + + @property(String) + get text() { + return this.#colours.text; + } + + @property(String) + get subtext1() { + return this.#colours.subtext1; + } + + @property(String) + get subtext0() { + return this.#colours.subtext0; + } + + @property(String) + get overlay2() { + return this.#colours.overlay2; + } + + @property(String) + get overlay1() { + return this.#colours.overlay1; + } + + @property(String) + get overlay0() { + return this.#colours.overlay0; + } + + @property(String) + get surface2() { + return this.#colours.surface2; + } + + @property(String) + get surface1() { + return this.#colours.surface1; + } + + @property(String) + get surface0() { + return this.#colours.surface0; + } + + @property(String) + get base() { + return this.#colours.base; + } + + @property(String) + get mantle() { + return this.#colours.mantle; + } + + @property(String) + get crust() { + return this.#colours.crust; + } + + @property(String) + get accent() { + return this.#colours.accent; + } + + #notify() { + this.notify("colours"); + this.notify("rosewater"); + this.notify("flamingo"); + this.notify("pink"); + this.notify("mauve"); + this.notify("red"); + this.notify("maroon"); + this.notify("peach"); + this.notify("yellow"); + this.notify("green"); + this.notify("teal"); + this.notify("sky"); + this.notify("sapphire"); + this.notify("blue"); + this.notify("lavender"); + this.notify("text"); + this.notify("subtext1"); + this.notify("subtext0"); + this.notify("overlay2"); + this.notify("overlay1"); + this.notify("overlay0"); + this.notify("surface2"); + this.notify("surface1"); + this.notify("surface0"); + this.notify("base"); + this.notify("mantle"); + this.notify("crust"); + this.notify("accent"); + } + + update() { + let schemeColours; + if (GLib.file_test(`${STATE}/scheme/current.txt`, GLib.FileTest.EXISTS)) { + const currentScheme = readFile(`${STATE}/scheme/current.txt`); + schemeColours = currentScheme.split("\n").map(l => l.split(" ")); + } else + schemeColours = readFile(`${SRC}/scss/scheme/_default.scss`) + .split("\n") + .map(l => { + const [name, hex] = l.split(":"); + return [name.slice(1), hex.trim().slice(1, -1)]; + }); + + this.#colours = schemeColours.reduce((acc, [name, hex]) => ({ ...acc, [name]: `#${hex}` }), {} as IPalette); + this.#notify(); + } + + constructor() { + super(); + + this.update(); + monitorFile(`${STATE}/scheme/current.txt`, () => this.update()); + } +} diff --git a/src/services/updates.ts b/src/services/updates.ts index 06e86b1..dc82080 100644 --- a/src/services/updates.ts +++ b/src/services/updates.ts @@ -23,6 +23,7 @@ export interface Data { cached?: boolean; repos: Repo[]; errors: string[]; + news: string; } @register({ GTypeName: "Updates" }) @@ -38,7 +39,7 @@ export default class Updates extends GObject.Object { #timeout?: GLib.Source; #loading = false; - #data: Data = { cached: true, repos: [], errors: [] }; + #data: Data = { cached: true, repos: [], errors: [], news: "" }; @property(Boolean) get loading() { @@ -60,11 +61,17 @@ export default class Updates extends GObject.Object { return this.#data.repos.reduce((acc, repo) => acc + repo.updates.length, 0); } + @property(String) + get news() { + return this.#data.news; + } + async #updateFromCache() { this.#data = JSON.parse(await readFileAsync(this.#cachePath)); this.notify("update-data"); this.notify("list"); this.notify("num-updates"); + this.notify("news"); } async getRepo(repo: string) { @@ -93,9 +100,9 @@ export default class Updates extends GObject.Object { this.notify("loading"); // Get new updates - Promise.allSettled([execAsync("checkupdates"), execAsync("yay -Qua")]) - .then(async ([pacman, yay]) => { - const data: Data = { repos: [], errors: [] }; + Promise.allSettled([execAsync("checkupdates"), execAsync("yay -Qua"), execAsync("yay -Pw")]) + .then(async ([pacman, yay, news]) => { + const data: Data = { repos: [], errors: [], news: news.status === "fulfilled" ? news.value : "" }; // Pacman updates (checkupdates) if (pacman.status === "fulfilled") { @@ -145,6 +152,7 @@ export default class Updates extends GObject.Object { this.notify("update-data"); this.notify("list"); this.notify("num-updates"); + this.notify("news"); } this.#loading = false; |