summaryrefslogtreecommitdiff
path: root/src/services
diff options
context:
space:
mode:
Diffstat (limited to 'src/services')
-rw-r--r--src/services/palette.ts31
-rw-r--r--src/services/schemes.ts67
-rw-r--r--src/services/wallpapers.ts27
3 files changed, 86 insertions, 39 deletions
diff --git a/src/services/palette.ts b/src/services/palette.ts
index 7f6dc0c..da7ef09 100644
--- a/src/services/palette.ts
+++ b/src/services/palette.ts
@@ -41,18 +41,24 @@ export default class Palette extends GObject.Object {
return this.instance;
}
- #isLight: boolean;
- #name: string;
+ #mode: "light" | "dark";
+ #scheme: string;
+ #flavour?: string;
#colours!: IPalette;
@property(Boolean)
- get isLight() {
- return this.#isLight;
+ get mode() {
+ return this.#mode;
}
@property(String)
- get name() {
- return this.#name;
+ get scheme() {
+ return this.#scheme;
+ }
+
+ @property(String)
+ get flavour() {
+ return this.#flavour;
}
@property(Object)
@@ -246,16 +252,17 @@ export default class Palette extends GObject.Object {
constructor() {
super();
- this.#isLight = readFile(`${STATE}/scheme/current-mode.txt`) === "light";
+ this.#mode = readFile(`${STATE}/scheme/current-mode.txt`) === "light" ? "light" : "dark";
monitorFile(`${STATE}/scheme/current-mode.txt`, async file => {
- this.#isLight = (await readFileAsync(file)) === "light";
- this.notify("is-light");
+ this.#mode = (await readFileAsync(file)) === "light" ? "light" : "dark";
+ this.notify("mode");
});
- this.#name = readFile(`${STATE}/scheme/current-name.txt`);
+ [this.#scheme, this.#flavour] = readFile(`${STATE}/scheme/current-name.txt`).split("-");
monitorFile(`${STATE}/scheme/current-name.txt`, async file => {
- this.#name = await readFileAsync(file);
- this.notify("name");
+ [this.#scheme, this.#flavour] = (await readFileAsync(file)).split("-");
+ this.notify("scheme");
+ this.notify("flavour");
});
this.update();
diff --git a/src/services/schemes.ts b/src/services/schemes.ts
index 4c51744..3f248bc 100644
--- a/src/services/schemes.ts
+++ b/src/services/schemes.ts
@@ -1,7 +1,25 @@
import { basename } from "@/utils/strings";
-import { execAsync, GLib, GObject, monitorFile, property, readFileAsync, register } from "astal";
+import { monitorDirectory } from "@/utils/system";
+import { execAsync, GLib, GObject, property, readFileAsync, register } from "astal";
import type { IPalette } from "./palette";
+export interface Colours {
+ light?: IPalette;
+ dark?: IPalette;
+}
+
+export interface Flavour {
+ name: string;
+ scheme: string;
+ colours: Colours;
+}
+
+export interface Scheme {
+ name: string;
+ flavours?: { [k: string]: Flavour };
+ colours?: Colours;
+}
+
const DATA = `${GLib.get_user_data_dir()}/caelestia`;
@register({ GTypeName: "Schemes" })
@@ -13,21 +31,58 @@ export default class Schemes extends GObject.Object {
return this.instance;
}
- #map: { [k: string]: IPalette } = {};
+ readonly #schemeDir: string = `${DATA}/scripts/data/schemes`;
+
+ #map: { [k: string]: Scheme } = {};
@property(Object)
get map() {
return this.#map;
}
- async parseScheme(path: string) {
+ async parseMode(path: string): Promise<IPalette> {
const schemeColours = (await readFileAsync(path)).split("\n").map(l => l.split(" "));
return schemeColours.reduce((acc, [name, hex]) => ({ ...acc, [name]: `#${hex}` }), {} as IPalette);
}
+ async parseFlavour(scheme: string, name: string): Promise<Flavour> {
+ const path = `${this.#schemeDir}/${scheme}/${name}`;
+
+ let light = undefined;
+ let dark = undefined;
+ if (GLib.file_test(`${path}/light.txt`, GLib.FileTest.EXISTS))
+ light = await this.parseMode(`${path}/light.txt`);
+ if (GLib.file_test(`${path}/dark.txt`, GLib.FileTest.EXISTS)) dark = await this.parseMode(`${path}/dark.txt`);
+
+ return { name, scheme, colours: { light, dark } };
+ }
+
+ async parseScheme(name: string): Promise<Scheme> {
+ const path = `${this.#schemeDir}/${name}`;
+
+ const flavours = await execAsync(`find ${path}/ -mindepth 1 -maxdepth 1 -type d`);
+ if (flavours.trim())
+ return {
+ name,
+ flavours: (
+ await Promise.all(flavours.split("\n").map(f => this.parseFlavour(name, basename(f))))
+ ).reduce((acc, f) => ({ ...acc, [f.name]: f }), {} as { [k: string]: Flavour }),
+ };
+
+ let light = undefined;
+ let dark = undefined;
+ if (GLib.file_test(`${path}/light.txt`, GLib.FileTest.EXISTS))
+ light = await this.parseMode(`${path}/light.txt`);
+ if (GLib.file_test(`${path}/dark.txt`, GLib.FileTest.EXISTS)) dark = await this.parseMode(`${path}/dark.txt`);
+ return { name, colours: { light, dark } };
+ }
+
async update() {
- const schemes = await execAsync(`find ${DATA}/scripts/data/schemes/ -type f`);
- for (const scheme of schemes.split("\n")) this.#map[basename(scheme)] = await this.parseScheme(scheme);
+ const schemes = await execAsync(`find ${this.#schemeDir}/ -mindepth 1 -maxdepth 1 -type d`);
+ for (const scheme of schemes.split("\n")) {
+ const name = basename(scheme);
+ this.#map[name] = await this.parseScheme(name);
+ }
this.notify("map");
}
@@ -35,6 +90,6 @@ export default class Schemes extends GObject.Object {
super();
this.update().catch(console.error);
- monitorFile(`${DATA}/scripts/data/schemes`, () => this.update().catch(console.error));
+ monitorDirectory(this.#schemeDir, () => this.update().catch(console.error), true);
}
}
diff --git a/src/services/wallpapers.ts b/src/services/wallpapers.ts
index 7d29a14..39bced4 100644
--- a/src/services/wallpapers.ts
+++ b/src/services/wallpapers.ts
@@ -1,5 +1,6 @@
import { basename } from "@/utils/strings";
-import { execAsync, Gio, GLib, GObject, property, register } from "astal";
+import { monitorDirectory } from "@/utils/system";
+import { execAsync, GLib, GObject, property, register } from "astal";
import { wallpapers as config } from "config";
export interface Wallpaper {
@@ -55,28 +56,12 @@ export default class Wallpapers extends GObject.Object {
this.update().catch(console.error);
- const monitorDir = ({ path, recursive }: { path: string; recursive: boolean }) => {
- const file = Gio.file_new_for_path(path.replace("~", HOME));
- const monitor = file.monitor_directory(null, null);
- monitor.connect("changed", () => this.update().catch(console.error));
-
- const monitors = [monitor];
-
- if (recursive) {
- const enumerator = file.enumerate_children("standard::*", null, null);
- let child;
- while ((child = enumerator.next_file(null)))
- if (child.get_file_type() === Gio.FileType.DIRECTORY)
- monitors.push(...monitorDir({ path: `${path}/${child.get_name()}`, recursive }));
- }
-
- return monitors;
- };
-
- let monitors = config.paths.get().flatMap(monitorDir);
+ let monitors = config.paths
+ .get()
+ .flatMap(p => monitorDirectory(p.path, () => this.update().catch(console.error), p.recursive));
config.paths.subscribe(v => {
for (const m of monitors) m.cancel();
- monitors = v.flatMap(monitorDir);
+ monitors = v.flatMap(p => monitorDirectory(p.path, () => this.update().catch(console.error), p.recursive));
});
}
}