summaryrefslogtreecommitdiff
path: root/app.tsx
blob: 35a522c70df48d198bf88401cc06baeed8405fe0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
import Bar from "@/modules/bar";
import Launcher from "@/modules/launcher";
import NotifPopups from "@/modules/notifpopups";
import Osds from "@/modules/osds";
import ScreenCorners from "@/modules/screencorners";
import Session from "@/modules/session";
import SideBar from "@/modules/sidebar";
import Calendar from "@/services/calendar";
import Monitors from "@/services/monitors";
import Palette from "@/services/palette";
import Players from "@/services/players";
import Schemes from "@/services/schemes";
import Wallpapers from "@/services/wallpapers";
import { execAsync, idle, timeout, writeFileAsync } from "astal";
import { App } from "astal/gtk3";
import { style } from "config";
import { initConfig, updateConfig } from "config/funcs";

const isLayer = (name: string) =>
    ["base", "mantle", "crust"].includes(name) || name.startsWith("surface") || name.startsWith("overlay");

const applyTransparency = (name: string, hex: string) => {
    if (style.transparency.get() === "off" || !isLayer(name)) return hex;
    let amount = style.transparency.get() === "high" ? 0.58 : 0.78;
    if (Palette.get_default().mode === "light") amount = style.transparency.get() === "high" ? 0.53 : 0.63;
    return `color.change(${hex}, $alpha: ${amount})`;
};

const applyVibrancy = (hex: string) => (style.vibrant.get() ? `color.scale(${hex}, $saturation: 40%)` : hex);

const styleLoader = new (class {
    #running = false;
    #dirty = false;

    async run() {
        this.#dirty = true;
        if (this.#running) return;
        this.#running = true;
        while (this.#dirty) {
            this.#dirty = false;
            await this.#run();
        }
        this.#running = false;
    }

    async #run() {
        const schemeColours = Object.entries(Palette.get_default().colours)
            .map(([name, hex]) => `$${name}: ${applyVibrancy(applyTransparency(name, hex))};`)
            .join("\n");
        await writeFileAsync(
            `${SRC}/scss/scheme/_index.scss`,
            `@use "sass:color";\n$light: ${Palette.get_default().mode === "light"};\n${schemeColours}`
        );
        App.apply_css(await execAsync(`sass ${SRC}/style.scss`), true);
    }
})();

export const loadStyleAsync = () => styleLoader.run();

App.start({
    instanceName: "caelestia",
    icons: "assets/icons",
    async main() {
        const now = Date.now();

        await initConfig();

        loadStyleAsync().catch(console.error);
        style.transparency.subscribe(() => loadStyleAsync().catch(console.error));
        Palette.get_default().connect("notify::colours", () => loadStyleAsync().catch(console.error));
        Palette.get_default().connect("notify::mode", () => loadStyleAsync().catch(console.error));

        <Launcher />;
        <NotifPopups />;
        <Osds />;
        <Session />;
        Monitors.get_default().forEach(m => <SideBar monitor={m} />);
        Monitors.get_default().forEach(m => <Bar monitor={m} />);
        Monitors.get_default().forEach(m => <ScreenCorners monitor={m} />);

        // Init services
        timeout(1000, () => {
            idle(() => Schemes.get_default());
            idle(() => Wallpapers.get_default());
            idle(() => Calendar.get_default());
        });

        console.log(`Caelestia started in ${Date.now() - now}ms`);
    },
    requestHandler(request, res) {
        if (request === "reload-css") loadStyleAsync().catch(console.error);
        else if (request === "reload-config") updateConfig();
        else if (request.startsWith("show")) App.get_window(request.split(" ")[1])?.show();
        else if (request === "media play-pause") Players.get_default().lastPlayer?.play_pause();
        else if (request === "media next") Players.get_default().lastPlayer?.next();
        else if (request === "media previous") Players.get_default().lastPlayer?.previous();
        else if (request === "media stop") Players.get_default().lastPlayer?.stop();
        else if (request.startsWith("media")) {
            const player = Players.get_default().lastPlayer;
            const key = request.split(" ")[1];
            if (player === null) return res("No media");
            if (key in player) return res(player[key as keyof typeof player]);
            return res(`Invalid key: ${key}`);
        } else if (request.startsWith("brightness")) {
            const value = request.split(" ")[1];
            const num = parseFloat(value) / (value.includes("%") ? 100 : 1);
            if (isNaN(num)) return res("Syntax: brightness <value>[%][+ | -]");
            if (value.includes("+")) Monitors.get_default().active.brightness += num;
            else if (value.includes("-")) Monitors.get_default().active.brightness -= num;
            else Monitors.get_default().active.brightness = num;
        } else return res("Unknown command: " + request);

        console.log(`Request handled: ${request}`);
        res("OK");
    },
});