From 01626b70f10b38a6c03e5701283a43e9920fc26d Mon Sep 17 00:00:00 2001
From: 2 * r + 2 * t <61896496+soramanew@users.noreply.github.com>
Date: Tue, 25 Feb 2025 15:33:08 +1100
Subject: updates: show arch news
---
app.tsx | 21 ++--
scss/popdowns/updates.scss | 9 +-
src/modules/popdowns/updates.tsx | 48 +++++++-
src/services/palette.ts | 240 +++++++++++++++++++++++++++++++++++++++
src/services/updates.ts | 16 ++-
5 files changed, 312 insertions(+), 22 deletions(-)
create mode 100644 src/services/palette.ts
diff --git a/app.tsx b/app.tsx
index dd473d8..0739d01 100644
--- a/app.tsx
+++ b/app.tsx
@@ -5,24 +5,17 @@ import Osds from "@/modules/osds";
import Popdowns from "@/modules/popdowns";
import Session from "@/modules/session";
import Monitors from "@/services/monitors";
+import Palette from "@/services/palette";
import Players from "@/services/players";
import type PopupWindow from "@/widgets/popupwindow";
-import { execAsync, GLib, monitorFile, readFileAsync, writeFileAsync } from "astal";
+import { execAsync, writeFileAsync } from "astal";
import { App } from "astal/gtk3";
import { initConfig, updateConfig } from "config";
export const loadStyleAsync = async () => {
- let schemeColours;
- if (GLib.file_test(`${STATE}/scheme/current.txt`, GLib.FileTest.EXISTS)) {
- const currentScheme = await readFileAsync(`${STATE}/scheme/current.txt`);
- schemeColours = currentScheme
- .split("\n")
- .map(l => {
- const [name, hex] = l.split(" ");
- return `$${name}: #${hex};`;
- })
- .join("\n");
- } else schemeColours = await readFileAsync(`${SRC}/scss/scheme/_default.scss`);
+ const schemeColours = Object.entries(Palette.get_default().colours)
+ .map(([name, hex]) => `$${name}: ${hex};`)
+ .join("\n");
await writeFileAsync(`${SRC}/scss/scheme/_index.scss`, schemeColours);
App.apply_css(await execAsync(`sass ${SRC}/style.scss`), true);
};
@@ -32,8 +25,10 @@ App.start({
icons: "assets/icons",
main() {
const now = Date.now();
+
loadStyleAsync().catch(console.error);
- monitorFile(`${STATE}/scheme/current.txt`, () => loadStyleAsync().catch(console.error));
+ Palette.get_default().connect("notify::colours", () => loadStyleAsync().catch(console.error));
+
initConfig();
;
diff --git a/scss/popdowns/updates.scss b/scss/popdowns/updates.scss
index f63b50e..7ab661f 100644
--- a/scss/popdowns/updates.scss
+++ b/scss/popdowns/updates.scss
@@ -9,7 +9,7 @@ $-accent: scheme.$blue;
@include lib.popdown-window($-accent);
min-width: lib.s(550);
- min-height: lib.s(450);
+ min-height: lib.s(800);
.wrapper {
@include lib.element-decel;
@@ -32,10 +32,15 @@ $-accent: scheme.$blue;
font-size: lib.s(16);
}
- .list {
+ .list,
+ .news {
color: scheme.$text;
margin-left: lib.s(12);
}
+
+ .news {
+ margin-bottom: lib.s(5);
+ }
}
}
}
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 (
@@ -61,9 +62,50 @@ const Repo = (repo: IRepo) => {
);
};
+const News = ({ news }: { news: string }) => {
+ const expanded = Variable(true);
+
+ return (
+
+
+
+
+
+ );
+};
+
const List = () => (
- {bind(Updates.get_default(), "updateData").as(d => d.repos.map(Repo))}
+ {bind(Updates.get_default(), "updateData").as(d =>
+ d.news
+ ? [, ...d.repos.map(r => )]
+ : d.repos.map((r, i) => )
+ )}
);
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;
--
cgit v1.2.3-freya