🔧 chore: use a different approach to compile stylesheets
also fixed promise calls not working(execAsync, subprocess), restored previous control center tile implementation temporarily
This commit is contained in:
+49
-57
@@ -2,7 +2,7 @@
|
|||||||
// import app from "ags/gtk4/app";
|
// import app from "ags/gtk4/app";
|
||||||
|
|
||||||
// fix can't convert non-null pointer to JS value (thanks Aylur!)
|
// fix can't convert non-null pointer to JS value (thanks Aylur!)
|
||||||
import "/usr/share/ags/js/src/overrides";
|
import "ags/overrides";
|
||||||
import {
|
import {
|
||||||
PluginApps,
|
PluginApps,
|
||||||
PluginClipboard,
|
PluginClipboard,
|
||||||
@@ -24,10 +24,10 @@ import { Gdk, Gtk } from "ags/gtk4";
|
|||||||
import { createRoot, getScope } from "ags";
|
import { createRoot, getScope } from "ags";
|
||||||
import { triggerOSD } from "./window/OSD";
|
import { triggerOSD } from "./window/OSD";
|
||||||
import { programArgs, programInvocationName } from "system";
|
import { programArgs, programInvocationName } from "system";
|
||||||
import { encoder, decoder } from "./scripts/utils";
|
import { setConsoleLogDomain } from "console";
|
||||||
import { initPlayer } from "./scripts/media";
|
import { initPlayer } from "./scripts/media";
|
||||||
|
|
||||||
import GObject, { register } from "ags/gobject";
|
import GObject, { register } from "ags/gobject";
|
||||||
|
|
||||||
import AstalNotifd from "gi://AstalNotifd";
|
import AstalNotifd from "gi://AstalNotifd";
|
||||||
import GLib from "gi://GLib?version=2.0";
|
import GLib from "gi://GLib?version=2.0";
|
||||||
import Gio from "gi://Gio?version=2.0";
|
import Gio from "gi://Gio?version=2.0";
|
||||||
@@ -50,16 +50,13 @@ Adw.init();
|
|||||||
GLib.unsetenv("LD_PRELOAD");
|
GLib.unsetenv("LD_PRELOAD");
|
||||||
|
|
||||||
@register({ GTypeName: "Shell", Implements: [Gio.ActionGroup]})
|
@register({ GTypeName: "Shell", Implements: [Gio.ActionGroup]})
|
||||||
export class Shell extends Gtk.Application implements Gio.ActionMap {
|
export class Shell extends Adw.Application implements Gio.ActionMap {
|
||||||
private static instance: Shell;
|
private static instance: Shell;
|
||||||
|
|
||||||
#loop!: GLib.MainLoop;
|
|
||||||
#scope!: ReturnType<typeof getScope>;
|
#scope!: ReturnType<typeof getScope>;
|
||||||
#connections = new Map<GObject.Object, Array<number> | number>();
|
#connections = new Map<GObject.Object, Array<number> | number>();
|
||||||
#stylesheet: Uint8Array|undefined;
|
#providers: Array<Gtk.CssProvider> = [];
|
||||||
#styleProvider: Gtk.CssProvider;
|
|
||||||
#gresource: Gio.Resource|null = null;
|
#gresource: Gio.Resource|null = null;
|
||||||
#icons: Record<string, Gio.BytesIcon> = {};
|
|
||||||
|
|
||||||
get scope() { return this.#scope; }
|
get scope() { return this.#scope; }
|
||||||
|
|
||||||
@@ -70,7 +67,8 @@ export class Shell extends Gtk.Application implements Gio.ActionMap {
|
|||||||
version: COLORSHELL_VERSION ?? "0.0.0-unknown",
|
version: COLORSHELL_VERSION ?? "0.0.0-unknown",
|
||||||
});
|
});
|
||||||
|
|
||||||
this.#styleProvider = Gtk.CssProvider.new();
|
setConsoleLogDomain("colorshell");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// load gresource from build-defined value + support env variables
|
// load gresource from build-defined value + support env variables
|
||||||
this.#gresource = Gio.Resource.load(GRESOURCES_FILE.split('/').filter(s =>
|
this.#gresource = Gio.Resource.load(GRESOURCES_FILE.split('/').filter(s =>
|
||||||
@@ -89,19 +87,8 @@ export class Shell extends Gtk.Application implements Gio.ActionMap {
|
|||||||
Gio.resources_register(this.#gresource);
|
Gio.resources_register(this.#gresource);
|
||||||
|
|
||||||
// add icons
|
// add icons
|
||||||
Gio.resources_enumerate_children(
|
Gtk.IconTheme.get_for_display(Gdk.Display.get_default()!)
|
||||||
"/io/github/retrozinndev/colorshell",
|
.add_resource_path("/io/github/retrozinndev/colorshell/icons")
|
||||||
Gio.ResourceLookupFlags.NONE
|
|
||||||
).filter(name =>
|
|
||||||
/symbolic$/.test(name) || name.endsWith("svg")
|
|
||||||
).map(name =>
|
|
||||||
`/io/github/retrozinndev/colorshell/${name}`
|
|
||||||
).forEach(path => {
|
|
||||||
const name = path.split('/')[path.split('/').length - 1];
|
|
||||||
const iconBytes = Gio.resources_lookup_data(path, null);
|
|
||||||
|
|
||||||
this.#icons[name] = Gio.BytesIcon.new(iconBytes);
|
|
||||||
});
|
|
||||||
} catch(_e) {
|
} catch(_e) {
|
||||||
const e = _e as Error;
|
const e = _e as Error;
|
||||||
console.error(`Error: couldn't load gresource! Stderr: ${e.message}\n${e.stack}`);
|
console.error(`Error: couldn't load gresource! Stderr: ${e.message}\n${e.stack}`);
|
||||||
@@ -122,37 +109,48 @@ export class Shell extends Gtk.Application implements Gio.ActionMap {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public resetStyle(): void {
|
public resetStyle(): void {
|
||||||
this.#stylesheet = undefined;
|
this.#providers.forEach(provider =>
|
||||||
Gtk.StyleContext.remove_provider_for_display(
|
Gtk.StyleContext.remove_provider_for_display(
|
||||||
Gdk.Display.get_default()!,
|
Gdk.Display.get_default()!,
|
||||||
this.#styleProvider
|
provider
|
||||||
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public getGIcon(name: string): Gio.BytesIcon {
|
public removeProvider(provider: Gtk.CssProvider): void {
|
||||||
if(!Object.hasOwn(this.#icons, name))
|
if(!this.#providers.includes(provider)) {
|
||||||
throw new Error(`Colorshell: No gicon found with name "${name}"`);
|
console.warn("Colorshell: Couldn't find the provided GtkCssProvider to remove. Was it added before?");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
return this.#icons[name];
|
for(let i = 0; i < this.#providers.length; i++) {
|
||||||
|
const prov = this.#providers[i];
|
||||||
|
if(prov === provider) {
|
||||||
|
this.#providers.splice(i, 1);
|
||||||
|
Gtk.StyleContext.remove_provider_for_display(
|
||||||
|
Gdk.Display.get_default()!,
|
||||||
|
provider
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public applyStyle(stylesheet: string): void {
|
public applyStyle(stylesheet: string): void {
|
||||||
const previous = this.#stylesheet ? decoder.decode(this.#stylesheet) : undefined;
|
try {
|
||||||
let final = "";
|
const provider = Gtk.CssProvider.new();
|
||||||
|
provider.load_from_string(stylesheet)
|
||||||
if(previous)
|
this.#providers.push(provider);
|
||||||
final = previous + "\n";
|
|
||||||
|
Gtk.StyleContext.add_provider_for_display(
|
||||||
this.#stylesheet = encoder.encode(stylesheet);
|
Gdk.Display.get_default()!,
|
||||||
final = final.concat(stylesheet);
|
provider,
|
||||||
|
Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION
|
||||||
this.#styleProvider.load_from_string(final);
|
);
|
||||||
|
} catch(e) {
|
||||||
Gtk.StyleContext.add_provider_for_display(
|
console.error(`Colorshell: Couldn't apply style. Stderr: ${e}`);
|
||||||
Gdk.Display.get_default()!,
|
return;
|
||||||
this.#styleProvider,
|
}
|
||||||
Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
vfunc_command_line(cmd: Gio.ApplicationCommandLine): number {
|
vfunc_command_line(cmd: Gio.ApplicationCommandLine): number {
|
||||||
@@ -186,26 +184,22 @@ export class Shell extends Gtk.Application implements Gio.ActionMap {
|
|||||||
|
|
||||||
vfunc_activate(): void {
|
vfunc_activate(): void {
|
||||||
super.vfunc_activate();
|
super.vfunc_activate();
|
||||||
|
this.hold();
|
||||||
this.main();
|
this.main();
|
||||||
}
|
}
|
||||||
|
|
||||||
private main(): void {
|
private main(): void {
|
||||||
this.#loop = GLib.MainLoop.new(null, false);
|
|
||||||
|
|
||||||
createRoot((dispose) => {
|
createRoot((dispose) => {
|
||||||
console.log(`Colorshell: Initializing things`);
|
console.log(`Colorshell: Initializing things`);
|
||||||
this.#connections.set(this, this.connect("shutdown", () => dispose()));
|
this.#connections.set(this, this.connect("shutdown", () => dispose()));
|
||||||
this.#scope = getScope();
|
this.#scope = getScope();
|
||||||
|
|
||||||
initPlayer();
|
initPlayer();
|
||||||
|
|
||||||
Stylesheet.getDefault();
|
|
||||||
|
|
||||||
// Init clipboard module
|
|
||||||
Clipboard.getDefault();
|
Clipboard.getDefault();
|
||||||
|
|
||||||
console.log("Initializing wallpaper handler");
|
console.log("Colorshell: Initializing wallpaper & Stylesheet handlers");
|
||||||
Wallpaper.getDefault();
|
Wallpaper.getDefault();
|
||||||
|
Stylesheet.getDefault();
|
||||||
|
|
||||||
console.log("Adding runner plugins");
|
console.log("Adding runner plugins");
|
||||||
runnerPlugins.forEach(plugin => Runner.addPlugin(plugin));
|
runnerPlugins.forEach(plugin => Runner.addPlugin(plugin));
|
||||||
@@ -233,12 +227,10 @@ export class Shell extends Gtk.Application implements Gio.ActionMap {
|
|||||||
ids.forEach(id => obj.disconnect(id))
|
ids.forEach(id => obj.disconnect(id))
|
||||||
: obj.disconnect(ids));
|
: obj.disconnect(ids));
|
||||||
});
|
});
|
||||||
|
|
||||||
this.#loop.run();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
quit(): void {
|
quit(): void {
|
||||||
this.#loop.is_running() && this.#loop.quit();
|
this.release();
|
||||||
super.quit();
|
super.quit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -284,4 +276,4 @@ export const generalConfig = new Config<keyof typeof generalConfigDefaults,
|
|||||||
`${GLib.get_user_config_dir()}/colorshell/config.json`, generalConfigDefaults
|
`${GLib.get_user_config_dir()}/colorshell/config.json`, generalConfigDefaults
|
||||||
);
|
);
|
||||||
|
|
||||||
Shell.getDefault().run([ programInvocationName, ...programArgs ]);
|
Shell.getDefault().runAsync([ programInvocationName, ...programArgs ]);
|
||||||
|
|||||||
@@ -1,27 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<gresources>
|
|
||||||
<gresource prefix="/io/github/retrozinndev/colorshell">
|
|
||||||
<!-- Sass -->
|
|
||||||
<file alias="style">style.scss</file>
|
|
||||||
<file alias="style-apps-window">style/_apps-window.scss</file>
|
|
||||||
<file alias="style-bar">style/_bar.scss</file>
|
|
||||||
<file alias="style-center-window">style/_center-window.scss</file>
|
|
||||||
<file alias="style-control-center">style/_control-center.scss</file>
|
|
||||||
<file alias="style-float-notifications">style/_float-notifications.scss</file>
|
|
||||||
<file alias="style-logout-menu">style/_logout-menu.scss</file>
|
|
||||||
<file alias="style-mixins">style/_mixins.scss</file>
|
|
||||||
<file alias="style-osd">style/_osd.scss</file>
|
|
||||||
<file alias="style-runner">style/_runner.scss</file>
|
|
||||||
|
|
||||||
<!-- Icons -->
|
|
||||||
<file alias="applications-other-symbolic">icons/applications-other-symbolic.svg</file>
|
|
||||||
<file alias="arrow-circular-top-right-symbolic">icons/arrow-circular-top-right-symbolic.svg</file>
|
|
||||||
<file alias="circle-filled-symbolic">icons/circle-filled-symbolic.svg</file>
|
|
||||||
<file alias="hourglass-symbolic">icons/hourglass-symbolic.svg</file>
|
|
||||||
<file alias="loop-arrow-symbolic">icons/loop-arrow-symbolic.svg</file>
|
|
||||||
<file alias="minus-circle-filled-symbolic">icons/minus-circle-filled-symbolic.svg</file>
|
|
||||||
<file alias="shield-danger-symbolic">icons/shield-danger-symbolic.svg</file>
|
|
||||||
<file alias="shield-safe-symbolic">icons/shield-safe-symbolic.svg</file>
|
|
||||||
<file alias="user-trash-symbolic">icons/user-trash-symbolic.svg</file>
|
|
||||||
</gresource>
|
|
||||||
</gresources>
|
|
||||||
@@ -7,7 +7,6 @@ import { timeout } from "ags/time";
|
|||||||
|
|
||||||
import AstalHyprland from "gi://AstalHyprland";
|
import AstalHyprland from "gi://AstalHyprland";
|
||||||
import AstalIO from "gi://AstalIO";
|
import AstalIO from "gi://AstalIO";
|
||||||
import { Shell } from "../app";
|
|
||||||
|
|
||||||
|
|
||||||
export namespace Runner {
|
export namespace Runner {
|
||||||
@@ -245,8 +244,7 @@ export function openRunner(props: RunnerProps, placeholders?: Array<Result>): As
|
|||||||
heightRequest={props.height} exclusivity={Astal.Exclusivity.IGNORE} halign={Gtk.Align.CENTER}
|
heightRequest={props.height} exclusivity={Astal.Exclusivity.IGNORE} halign={Gtk.Align.CENTER}
|
||||||
marginTop={(AstalHyprland.get_default().get_monitor(mon)?.height / 2) - (props.height! / 2)}
|
marginTop={(AstalHyprland.get_default().get_monitor(mon)?.height / 2) - (props.height! / 2)}
|
||||||
valign={Gtk.Align.START} hexpand orientation={Gtk.Orientation.VERTICAL}
|
valign={Gtk.Align.START} hexpand orientation={Gtk.Orientation.VERTICAL}
|
||||||
$={(self) => {
|
$={() => {
|
||||||
self.set_application(Shell.getDefault());
|
|
||||||
plugins.forEach(plugin =>
|
plugins.forEach(plugin =>
|
||||||
plugin.init?.());
|
plugin.init?.());
|
||||||
|
|
||||||
|
|||||||
+104
-73
@@ -1,8 +1,8 @@
|
|||||||
import { monitorFile, readFile } from "ags/file";
|
import { monitorFile, readFile, writeFileAsync } from "ags/file";
|
||||||
import { decoder } from "./utils";
|
import { decoder } from "./utils";
|
||||||
|
import { execAsync } from "ags/process";
|
||||||
import { Wallpaper } from "./wallpaper";
|
import { Wallpaper } from "./wallpaper";
|
||||||
import { Shell } from "../app";
|
import { Shell } from "../app";
|
||||||
import { exec } from "ags/process";
|
|
||||||
|
|
||||||
import Gio from "gi://Gio?version=2.0";
|
import Gio from "gi://Gio?version=2.0";
|
||||||
import GLib from "gi://GLib?version=2.0";
|
import GLib from "gi://GLib?version=2.0";
|
||||||
@@ -12,20 +12,15 @@ import GLib from "gi://GLib?version=2.0";
|
|||||||
export class Stylesheet {
|
export class Stylesheet {
|
||||||
private static instance: Stylesheet;
|
private static instance: Stylesheet;
|
||||||
#outputPath = Gio.File.new_for_path(`${GLib.get_user_cache_dir()}/colorshell/style`);
|
#outputPath = Gio.File.new_for_path(`${GLib.get_user_cache_dir()}/colorshell/style`);
|
||||||
#sassStyles!: {
|
#stylesPaths: Array<string>;
|
||||||
colors: string;
|
readonly #sassStyles = {
|
||||||
general: string;
|
modules: ["sass:color"].map(mod => `@use "${mod}";`).join('\n'),
|
||||||
|
colors: "",
|
||||||
|
mixins: "",
|
||||||
|
rules: ""
|
||||||
};
|
};
|
||||||
|
|
||||||
public get stylePath() { return this.#outputPath.get_path()!; }
|
public get stylePath() { return this.#outputPath.get_path()!; }
|
||||||
|
|
||||||
public compileSass(): string {
|
|
||||||
console.log("Stylesheet: Compiling Sass");
|
|
||||||
exec(`echo '${this.#sassStyles.colors}\n${this.#sassStyles.general}' \
|
|
||||||
| sass --stdin --no-source-map -s "${this.stylePath}.css"`);
|
|
||||||
|
|
||||||
return readFile(`${this.stylePath}/style.css`);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static getDefault(): Stylesheet {
|
public static getDefault(): Stylesheet {
|
||||||
if(!this.instance)
|
if(!this.instance)
|
||||||
@@ -34,54 +29,36 @@ export class Stylesheet {
|
|||||||
return this.instance;
|
return this.instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bundle(): string {
|
||||||
|
return `${this.#sassStyles.modules}\n\n${this.#sassStyles.colors
|
||||||
|
}\n${this.#sassStyles.mixins}\n${this.#sassStyles.rules}`.trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
private async compile(): Promise<void> {
|
||||||
|
const sass = this.bundle();
|
||||||
|
await writeFileAsync(`${this.stylePath}/sass.scss`, sass).catch(_e => {
|
||||||
|
const e = _e as Error;
|
||||||
|
console.error(`Stylesheet: Couldn't write Sass to cache. Stderr: ${
|
||||||
|
e.message}\n${e.stack}`);
|
||||||
|
});
|
||||||
|
await execAsync(
|
||||||
|
`bash -c "sass ${this.stylePath}/sass.scss ${this.stylePath}/style.css"`
|
||||||
|
).catch(_e => {
|
||||||
|
const e = _e as Error;
|
||||||
|
console.error(`Stylesheet: An error occurred on compile-time! Stderr: ${
|
||||||
|
e.message}\n${e.stack}`);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
public getStyleSheet(): string {
|
public getStyleSheet(): string {
|
||||||
const stylesNames: Array<string> = Gio.resources_enumerate_children(
|
return readFile(`${this.stylePath}/style.css`);
|
||||||
"/io/github/retrozinndev/colorshell",
|
|
||||||
Gio.ResourceLookupFlags.NONE
|
|
||||||
).filter(name =>
|
|
||||||
name.startsWith("style")
|
|
||||||
).map(name =>
|
|
||||||
`/io/github/retrozinndev/colorshell/${name}`
|
|
||||||
);
|
|
||||||
|
|
||||||
return stylesNames.map(path =>
|
|
||||||
Gio.resources_lookup_data(path, Gio.ResourceLookupFlags.NONE)
|
|
||||||
).map(bytes => decoder.decode(bytes.get_data()!)).join('\n');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
public getColorDefinitions(): string {
|
||||||
private objectToStyleSheet(colors: object & Record<string, string>): string {
|
|
||||||
return Object.keys(colors).map(name => {
|
|
||||||
const isBg = name.toLowerCase().startsWith('bg') || name.toLowerCase() === "background",
|
|
||||||
color = colors[name as keyof typeof colors];
|
|
||||||
|
|
||||||
// this will transform the color name's casing, example: bgPrimary -> bg-primary
|
|
||||||
return `
|
|
||||||
.${this.kebabify(name)} {
|
|
||||||
${isBg ? `background: ${color}` : `color: ${color}`}
|
|
||||||
}
|
|
||||||
`.trim();
|
|
||||||
}).join('\n')
|
|
||||||
}
|
|
||||||
|
|
||||||
private kebabify(str: string) {
|
|
||||||
return str.replace(/[A-Z]/, (c) => `-${c.toLowerCase()}`);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
public getColors(): string {
|
|
||||||
const data = Wallpaper.getDefault().getData();
|
const data = Wallpaper.getDefault().getData();
|
||||||
const colors = {
|
const colors = {
|
||||||
bgPrimary: `color.adjust($color: ${data.colors.color1}, $lightness: -28%)`,
|
...data.special,
|
||||||
bgSecondary: `color.adjust($color: ${data.colors.color1}, $lightness: -16%)`,
|
...data.colors
|
||||||
bgTertiary: `color.adjust($color: ${data.colors.color1}, $lightness: -4%)`,
|
|
||||||
bgLight: data.special.foreground,
|
|
||||||
bgTranslucent: `rgba(color.adjust($color: ${data.colors.color1}, $lightness: -28%), .7)`,
|
|
||||||
bgTranslucentPrimary: `rgba(color.adjust($color: ${data.colors.color1}, $lightness: -28%), .7)`,
|
|
||||||
bgTranslucentSecondary: `rgba(color.adjust($color: ${data.colors.color1}, $lightness: -16%), .7)`,
|
|
||||||
fgPrimary: data.special.foreground,
|
|
||||||
fgLight: `color.adjust($color: ${data.colors.color1}, $lightness: -28%)`,
|
|
||||||
fgDisabled: `color.adjust($color: ${data.special.foreground}, $lightness: -11%)`
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return Object.keys(colors).map(name =>
|
return Object.keys(colors).map(name =>
|
||||||
@@ -89,28 +66,82 @@ export class Stylesheet {
|
|||||||
).join('\n');
|
).join('\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
private updateColors(): void {
|
private organizeModuleImports(sass: string) {
|
||||||
this.#sassStyles.colors = this.getColors();
|
return sass.replaceAll(
|
||||||
Shell.getDefault().applyStyle(this.compileSass());
|
/[@](use|forward|import) ["'](.*)["']?[;]?\n/gi,
|
||||||
|
(_, impType, imp) => {
|
||||||
|
imp = (imp as string).replace(/["';]/g, "");
|
||||||
|
|
||||||
|
// add sass modules on top
|
||||||
|
if(!this.#sassStyles.modules.includes(imp) && /^(sass|.*http|.*https)/.test(imp))
|
||||||
|
this.#sassStyles.modules = this.#sassStyles.modules.concat(`\n@${impType} "${imp}";`);
|
||||||
|
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
).replace(/(colors|mixins|wal)\./g, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
public compileApply(): void {
|
||||||
|
this.compile().then(() => {
|
||||||
|
Shell.getDefault().resetStyle();
|
||||||
|
Shell.getDefault().applyStyle(this.getStyleSheet());
|
||||||
|
}).catch(_e => {
|
||||||
|
const e = _e as Error;
|
||||||
|
console.error(`Stylesheet: An error occurred at compile-time. Stderr: ${
|
||||||
|
e.message}\n${e.stack}`);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private getStyleData(path: string): string {
|
||||||
|
return decoder.decode(Gio.resources_lookup_data(path, null).get_data()!);
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
try {
|
if(!this.#outputPath.query_exists(null))
|
||||||
!this.#outputPath.query_exists(null) &&
|
this.#outputPath.make_directory_with_parents(null);
|
||||||
this.#outputPath.make_directory_with_parents(null);
|
|
||||||
} catch(_e) {
|
|
||||||
const e = _e as Error;
|
|
||||||
console.error(`Stylesheet: couldn't create output path. Stderr: ${e.message}\n${e.stack}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.#sassStyles = {
|
this.#stylesPaths = Gio.resources_enumerate_children(
|
||||||
colors: this.getColors(),
|
"/io/github/retrozinndev/colorshell/styles", null
|
||||||
general: this.getStyleSheet().replace(/colors\.[$]/g, "\$")
|
).map(name =>
|
||||||
};
|
`/io/github/retrozinndev/colorshell/styles/${name}`
|
||||||
Shell.getDefault().applyStyle(this.compileSass());
|
);
|
||||||
|
|
||||||
monitorFile(`${GLib.get_user_cache_dir()}/wal/colors.json`, () => {
|
// Rules won't change at runtime in a common build,
|
||||||
this.updateColors();
|
// so no need to worry about this.
|
||||||
|
// But in a development build, there should be support
|
||||||
|
// hot-reloading the gresource, this is a TODO
|
||||||
|
this.#stylesPaths.forEach(path => {
|
||||||
|
const name = path.split('/')[path.split('/').length - 1];
|
||||||
|
|
||||||
|
switch(name) {
|
||||||
|
case "colors":
|
||||||
|
this.#sassStyles.colors = `${this.getColorDefinitions()}\n${
|
||||||
|
this.organizeModuleImports(this.getStyleData(path))
|
||||||
|
}`;
|
||||||
|
break;
|
||||||
|
case "mixins":
|
||||||
|
this.#sassStyles.mixins = `${this.organizeModuleImports(
|
||||||
|
this.getStyleData(path)
|
||||||
|
)}`;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
this.#sassStyles.rules = `${this.#sassStyles.rules}\n${
|
||||||
|
this.organizeModuleImports(this.getStyleData(path))
|
||||||
|
}`;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.compileApply();
|
||||||
|
|
||||||
|
monitorFile(`${GLib.get_user_cache_dir()}/wal/colors`, () => {
|
||||||
|
this.#sassStyles.colors = `${this.getColorDefinitions()}\n${
|
||||||
|
this.organizeModuleImports(this.getStyleData(
|
||||||
|
"/io/github/retrozinndev/colorshell/styles/colors"
|
||||||
|
))
|
||||||
|
}`;
|
||||||
|
this.compileApply();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
import { execAsync } from "ags/process";
|
import { execAsync } from "ags/process";
|
||||||
import { timeout } from "ags/time";
|
import { timeout } from "ags/time";
|
||||||
import GObject, { register, getter } from "ags/gobject";
|
|
||||||
import { monitorFile, readFile } from "ags/file";
|
import { monitorFile, readFile } from "ags/file";
|
||||||
|
import GObject, { register, getter } from "ags/gobject";
|
||||||
|
|
||||||
import AstalIO from "gi://AstalIO";
|
import AstalIO from "gi://AstalIO";
|
||||||
import Gio from "gi://Gio?version=2.0";
|
import Gio from "gi://Gio?version=2.0";
|
||||||
import GLib from "gi://GLib?version=2.0";
|
import GLib from "gi://GLib?version=2.0";
|
||||||
|
import { decoder, encoder } from "./utils";
|
||||||
|
|
||||||
|
|
||||||
export { Wallpaper };
|
export { Wallpaper };
|
||||||
@@ -96,7 +97,7 @@ class Wallpaper extends GObject.Object {
|
|||||||
if(!loaded)
|
if(!loaded)
|
||||||
console.error("Wallpaper: Couldn't read changes inside the hyprpaper file!");
|
console.error("Wallpaper: Couldn't read changes inside the hyprpaper file!");
|
||||||
|
|
||||||
const content = new TextDecoder().decode(text);
|
const content = decoder.decode(text);
|
||||||
|
|
||||||
if(content) {
|
if(content) {
|
||||||
let setWall: boolean = true;
|
let setWall: boolean = true;
|
||||||
@@ -147,7 +148,7 @@ class Wallpaper extends GObject.Object {
|
|||||||
if(res) {
|
if(res) {
|
||||||
// success
|
// success
|
||||||
this.#ignoreWatch = true; // tell monitor to ignore this change
|
this.#ignoreWatch = true; // tell monitor to ignore this change
|
||||||
res.write_bytes_async(new TextEncoder().encode(`# This file was automatically generated by color-shell
|
res.write_bytes_async(encoder.encode(`# This file was automatically generated by color-shell
|
||||||
|
|
||||||
preload = ${this.#wallpaper}
|
preload = ${this.#wallpaper}
|
||||||
splash = ${this.#splash}
|
splash = ${this.#splash}
|
||||||
|
|||||||
-314
@@ -1,314 +0,0 @@
|
|||||||
@use "sass:color";
|
|
||||||
|
|
||||||
@use "./style/wal";
|
|
||||||
@use "./style/mixins";
|
|
||||||
@use "./style/functions";
|
|
||||||
@use "./style/colors";
|
|
||||||
|
|
||||||
@use "./style/bar";
|
|
||||||
@use "./style/osd";
|
|
||||||
@use "./style/control-center";
|
|
||||||
@use "./style/center-window";
|
|
||||||
@use "./style/float-notifications";
|
|
||||||
@use "./style/logout-menu";
|
|
||||||
@use "./style/apps-window";
|
|
||||||
@use "./style/runner";
|
|
||||||
|
|
||||||
|
|
||||||
* {
|
|
||||||
@include mixins.reset-props;
|
|
||||||
}
|
|
||||||
|
|
||||||
entry {
|
|
||||||
background: colors.$bg-primary;
|
|
||||||
padding: 10px 9px;
|
|
||||||
border-radius: 12px;
|
|
||||||
|
|
||||||
&:focus {
|
|
||||||
box-shadow: inset 0 0 0 2px colors.$bg-secondary;
|
|
||||||
}
|
|
||||||
|
|
||||||
& image.left {
|
|
||||||
margin-right: 6px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.custom-dialog-container {
|
|
||||||
background: colors.$bg-translucent;
|
|
||||||
padding: 18px;
|
|
||||||
border-radius: 24px;
|
|
||||||
|
|
||||||
& .title {
|
|
||||||
font-size: 21px;
|
|
||||||
font-weight: 700;
|
|
||||||
margin-bottom: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
& .text {
|
|
||||||
font-size: 16px;
|
|
||||||
font-weight: 400;
|
|
||||||
}
|
|
||||||
|
|
||||||
& .options {
|
|
||||||
& button {
|
|
||||||
@include mixins.button-reactive-primary;
|
|
||||||
background: colors.$bg-primary;
|
|
||||||
border-radius: 12px;
|
|
||||||
padding: 9px 6px;
|
|
||||||
|
|
||||||
& label {
|
|
||||||
font-size: 16px;
|
|
||||||
font-weight: 600;
|
|
||||||
}
|
|
||||||
|
|
||||||
margin: {
|
|
||||||
left: 4px;
|
|
||||||
right: 4px;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&.entry-popup-box entry {
|
|
||||||
margin-bottom: 10px;
|
|
||||||
|
|
||||||
&.password {
|
|
||||||
font-size: 14px;
|
|
||||||
font-family: "Adwaita Mono", "Cantarell Mono", "Noto Sans Mono", monospace;
|
|
||||||
font-weight: 400;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.notification {
|
|
||||||
background: colors.$bg-translucent-secondary;
|
|
||||||
border-radius: 16px;
|
|
||||||
|
|
||||||
& > .top {
|
|
||||||
padding: 8px;
|
|
||||||
padding-bottom: 0;
|
|
||||||
|
|
||||||
& .app-icon {
|
|
||||||
margin-right: 6px;
|
|
||||||
}
|
|
||||||
|
|
||||||
& .app-name {
|
|
||||||
font-size: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
& label.time {
|
|
||||||
font-size: 11px;
|
|
||||||
font-weight: 500;
|
|
||||||
color: colors.$fg-disabled;
|
|
||||||
margin-right: 6px;
|
|
||||||
}
|
|
||||||
|
|
||||||
& button.close {
|
|
||||||
padding: 2px;
|
|
||||||
border-radius: 8px;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background: colors.$bg-secondary;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
& icon.close {
|
|
||||||
font-size: 16px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
& .content {
|
|
||||||
padding: 6px;
|
|
||||||
padding-top: 0;
|
|
||||||
|
|
||||||
& .image {
|
|
||||||
$size: 78px;
|
|
||||||
min-width: $size;
|
|
||||||
min-height: $size;
|
|
||||||
background-size: cover;
|
|
||||||
background-position: center;
|
|
||||||
margin: 6px;
|
|
||||||
border-radius: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
& .summary {
|
|
||||||
font-size: 17.3px;
|
|
||||||
font-weight: 700;
|
|
||||||
margin-bottom: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
& .body {
|
|
||||||
font-size: 14.5px;
|
|
||||||
font-weight: 400;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
& .actions {
|
|
||||||
padding: 6px;
|
|
||||||
|
|
||||||
& button.action {
|
|
||||||
border-radius: 4px;
|
|
||||||
background: colors.$bg-secondary;
|
|
||||||
padding: 6px;
|
|
||||||
|
|
||||||
& label {
|
|
||||||
font-size: 14px;
|
|
||||||
font-weight: 600;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background: colors.$bg-tertiary;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:first-child {
|
|
||||||
border-top-left-radius: 12px;
|
|
||||||
border-bottom-left-radius: 12px;
|
|
||||||
}
|
|
||||||
&:last-child {
|
|
||||||
border-top-right-radius: 12px;
|
|
||||||
border-bottom-right-radius: 12px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tooltip > box {
|
|
||||||
padding: 7px 8px;
|
|
||||||
margin: 12px;
|
|
||||||
margin-top: 0;
|
|
||||||
border-radius: 12px;
|
|
||||||
background: rgba(colors.$bg-primary, .98);
|
|
||||||
box-shadow: 0 5px 6px 1px colors.$bg-translucent-primary;
|
|
||||||
|
|
||||||
& label {
|
|
||||||
font-size: 13.1px;
|
|
||||||
font-weight: 500;
|
|
||||||
color: colors.$fg-primary;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
popover.menu contents {
|
|
||||||
background: wal.$background;
|
|
||||||
border-radius: 14px;
|
|
||||||
padding: 4px;
|
|
||||||
|
|
||||||
& viewport > stack > * > * > * {
|
|
||||||
& > separator {
|
|
||||||
min-height: .5px;
|
|
||||||
margin: 3px 2px;
|
|
||||||
background: rgba(colors.$fg-disabled, .1);
|
|
||||||
}
|
|
||||||
|
|
||||||
& > *:not(separator) > * {
|
|
||||||
padding: 6px;
|
|
||||||
border-radius: 10px;
|
|
||||||
font-size: 12px;
|
|
||||||
font-weight: 600;
|
|
||||||
|
|
||||||
&:hover, &:focus {
|
|
||||||
background: wal.$color1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.button-row {
|
|
||||||
& > button {
|
|
||||||
$active-radius: 8px;
|
|
||||||
$corner-radius: calc($active-radius + 2px);
|
|
||||||
|
|
||||||
background: colors.$bg-secondary;
|
|
||||||
margin: 0 1px;
|
|
||||||
padding: 4px 6px;
|
|
||||||
border-radius: 2px;
|
|
||||||
transition: 120ms linear;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background: colors.$bg-tertiary;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:active {
|
|
||||||
border-radius: $active-radius;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:first-child {
|
|
||||||
margin-left: 0;
|
|
||||||
|
|
||||||
&:not(:active) {
|
|
||||||
border-top-left-radius: $corner-radius;
|
|
||||||
border-bottom-left-radius: $corner-radius;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&:last-child {
|
|
||||||
margin-right: 0;
|
|
||||||
|
|
||||||
&:not(:active) {
|
|
||||||
border-top-right-radius: $corner-radius;
|
|
||||||
border-bottom-right-radius: $corner-radius;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
selection {
|
|
||||||
background: colors.$bg-tertiary;
|
|
||||||
}
|
|
||||||
|
|
||||||
trough {
|
|
||||||
background: color.adjust($color: colors.$bg-primary, $lightness: -5%);
|
|
||||||
border-radius: 8px;
|
|
||||||
margin: 2px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
trough highlight {
|
|
||||||
background: wal.$color1;
|
|
||||||
min-height: .9em;
|
|
||||||
}
|
|
||||||
|
|
||||||
trough slider {
|
|
||||||
border-radius: 50%;
|
|
||||||
margin: -4px 0;
|
|
||||||
background: wal.$foreground;
|
|
||||||
min-width: 1.2em;
|
|
||||||
min-height: 1.2em;
|
|
||||||
}
|
|
||||||
|
|
||||||
scrollbar trough {
|
|
||||||
@include mixins.reset-props;
|
|
||||||
|
|
||||||
background: colors.$bg-translucent;
|
|
||||||
border-radius: 8px;
|
|
||||||
|
|
||||||
& slider {
|
|
||||||
@include mixins.reset-props;
|
|
||||||
|
|
||||||
min-width: .45em;
|
|
||||||
background: colors.$bg-tertiary;
|
|
||||||
border-radius: 12px;
|
|
||||||
|
|
||||||
&:hover, &:active, &:focus {
|
|
||||||
margin: 2px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&:hover, &:active, &:focus {
|
|
||||||
padding: 2px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
scale {
|
|
||||||
& marks mark {
|
|
||||||
& indicator {
|
|
||||||
color: colors.$fg-disabled;
|
|
||||||
min-width: 1px;
|
|
||||||
min-height: 6px;
|
|
||||||
}
|
|
||||||
|
|
||||||
& label {
|
|
||||||
font-size: 11px;
|
|
||||||
font-weight: 400;
|
|
||||||
color: colors.$fg-disabled;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -10,7 +10,6 @@ import GObject from "ags/gobject";
|
|||||||
import AstalBluetooth from "gi://AstalBluetooth";
|
import AstalBluetooth from "gi://AstalBluetooth";
|
||||||
import AstalNetwork from "gi://AstalNetwork";
|
import AstalNetwork from "gi://AstalNetwork";
|
||||||
import AstalWp from "gi://AstalWp";
|
import AstalWp from "gi://AstalWp";
|
||||||
import { Shell } from "../../app";
|
|
||||||
|
|
||||||
|
|
||||||
export const Status = () =>
|
export const Status = () =>
|
||||||
@@ -134,7 +133,7 @@ function StatusIcons() {
|
|||||||
: "preferences-system-notifications-symbolic")
|
: "preferences-system-notifications-symbolic")
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
<Gtk.Image gicon={Shell.getDefault().getGIcon("circle-filled-symbolic")} class={"notification-count"}
|
<Gtk.Image iconName={"circle-filled-symbolic"} class={"notification-count"}
|
||||||
visible={variableToBoolean(createBinding(Notifications.getDefault(), "history"))}
|
visible={variableToBoolean(createBinding(Notifications.getDefault(), "history"))}
|
||||||
/>
|
/>
|
||||||
</Gtk.Box>
|
</Gtk.Box>
|
||||||
|
|||||||
@@ -7,8 +7,24 @@ import GObject, { property, register, signal } from "ags/gobject";
|
|||||||
import Pango from "gi://Pango?version=1.0";
|
import Pango from "gi://Pango?version=1.0";
|
||||||
|
|
||||||
|
|
||||||
export { Tile };
|
export { Tile, TileProps };
|
||||||
|
|
||||||
|
type TileProps = {
|
||||||
|
class?: string | Accessor<string>;
|
||||||
|
icon?: string | Accessor<string>;
|
||||||
|
visible?: boolean | Accessor<boolean>;
|
||||||
|
iconSize?: number | Accessor<number>;
|
||||||
|
title: string | Accessor<string>;
|
||||||
|
description?: string | Accessor<string>;
|
||||||
|
toggleState?: boolean | Accessor<boolean>;
|
||||||
|
enableOnClickMore?: boolean | Accessor<boolean>;
|
||||||
|
onUnmap?: () => void;
|
||||||
|
onToggledOn: () => void;
|
||||||
|
onToggledOff: () => void;
|
||||||
|
onClickMore?: () => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* TODO: finish the tile class
|
||||||
@register({ GTypeName: "Tile" })
|
@register({ GTypeName: "Tile" })
|
||||||
class Tile extends Gtk.Box {
|
class Tile extends Gtk.Box {
|
||||||
@signal(Boolean) toggled(_state: boolean) {}
|
@signal(Boolean) toggled(_state: boolean) {}
|
||||||
@@ -119,8 +135,9 @@ class Tile extends Gtk.Box {
|
|||||||
return super.connect(signal, callback);
|
return super.connect(signal, callback);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
export function TileFun(props: TileProps): Gtk.Widget {
|
function Tile(props: TileProps): Gtk.Widget {
|
||||||
const subs: Array<() => void> = [];
|
const subs: Array<() => void> = [];
|
||||||
const [toggled, setToggled] = createState(((props.toggleState instanceof Accessor) ?
|
const [toggled, setToggled] = createState(((props.toggleState instanceof Accessor) ?
|
||||||
props.toggleState.get()
|
props.toggleState.get()
|
||||||
|
|||||||
+1
-1
@@ -31,7 +31,7 @@ export type WindowData = {
|
|||||||
* Also contains util functions to create dynamic windows, opening the window only on focused
|
* Also contains util functions to create dynamic windows, opening the window only on focused
|
||||||
* monitor, or all available monitors!
|
* monitor, or all available monitors!
|
||||||
*/
|
*/
|
||||||
@register()
|
@register({ GTypeName: "Windows" })
|
||||||
class Windows extends GObject.Object {
|
class Windows extends GObject.Object {
|
||||||
private static instance: (Windows | null);
|
private static instance: (Windows | null);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user