🔧 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";
|
||||
|
||||
// fix can't convert non-null pointer to JS value (thanks Aylur!)
|
||||
import "/usr/share/ags/js/src/overrides";
|
||||
import "ags/overrides";
|
||||
import {
|
||||
PluginApps,
|
||||
PluginClipboard,
|
||||
@@ -24,10 +24,10 @@ import { Gdk, Gtk } from "ags/gtk4";
|
||||
import { createRoot, getScope } from "ags";
|
||||
import { triggerOSD } from "./window/OSD";
|
||||
import { programArgs, programInvocationName } from "system";
|
||||
import { encoder, decoder } from "./scripts/utils";
|
||||
import { setConsoleLogDomain } from "console";
|
||||
import { initPlayer } from "./scripts/media";
|
||||
|
||||
import GObject, { register } from "ags/gobject";
|
||||
|
||||
import AstalNotifd from "gi://AstalNotifd";
|
||||
import GLib from "gi://GLib?version=2.0";
|
||||
import Gio from "gi://Gio?version=2.0";
|
||||
@@ -50,16 +50,13 @@ Adw.init();
|
||||
GLib.unsetenv("LD_PRELOAD");
|
||||
|
||||
@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;
|
||||
|
||||
#loop!: GLib.MainLoop;
|
||||
#scope!: ReturnType<typeof getScope>;
|
||||
#connections = new Map<GObject.Object, Array<number> | number>();
|
||||
#stylesheet: Uint8Array|undefined;
|
||||
#styleProvider: Gtk.CssProvider;
|
||||
#providers: Array<Gtk.CssProvider> = [];
|
||||
#gresource: Gio.Resource|null = null;
|
||||
#icons: Record<string, Gio.BytesIcon> = {};
|
||||
|
||||
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",
|
||||
});
|
||||
|
||||
this.#styleProvider = Gtk.CssProvider.new();
|
||||
setConsoleLogDomain("colorshell");
|
||||
|
||||
try {
|
||||
// load gresource from build-defined value + support env variables
|
||||
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);
|
||||
|
||||
// add icons
|
||||
Gio.resources_enumerate_children(
|
||||
"/io/github/retrozinndev/colorshell",
|
||||
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);
|
||||
});
|
||||
Gtk.IconTheme.get_for_display(Gdk.Display.get_default()!)
|
||||
.add_resource_path("/io/github/retrozinndev/colorshell/icons")
|
||||
} catch(_e) {
|
||||
const e = _e as Error;
|
||||
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 {
|
||||
this.#stylesheet = undefined;
|
||||
Gtk.StyleContext.remove_provider_for_display(
|
||||
Gdk.Display.get_default()!,
|
||||
this.#styleProvider
|
||||
this.#providers.forEach(provider =>
|
||||
Gtk.StyleContext.remove_provider_for_display(
|
||||
Gdk.Display.get_default()!,
|
||||
provider
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
public getGIcon(name: string): Gio.BytesIcon {
|
||||
if(!Object.hasOwn(this.#icons, name))
|
||||
throw new Error(`Colorshell: No gicon found with name "${name}"`);
|
||||
public removeProvider(provider: Gtk.CssProvider): void {
|
||||
if(!this.#providers.includes(provider)) {
|
||||
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 {
|
||||
const previous = this.#stylesheet ? decoder.decode(this.#stylesheet) : undefined;
|
||||
let final = "";
|
||||
|
||||
if(previous)
|
||||
final = previous + "\n";
|
||||
|
||||
this.#stylesheet = encoder.encode(stylesheet);
|
||||
final = final.concat(stylesheet);
|
||||
|
||||
this.#styleProvider.load_from_string(final);
|
||||
|
||||
Gtk.StyleContext.add_provider_for_display(
|
||||
Gdk.Display.get_default()!,
|
||||
this.#styleProvider,
|
||||
Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION
|
||||
);
|
||||
try {
|
||||
const provider = Gtk.CssProvider.new();
|
||||
provider.load_from_string(stylesheet)
|
||||
this.#providers.push(provider);
|
||||
|
||||
Gtk.StyleContext.add_provider_for_display(
|
||||
Gdk.Display.get_default()!,
|
||||
provider,
|
||||
Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION
|
||||
);
|
||||
} catch(e) {
|
||||
console.error(`Colorshell: Couldn't apply style. Stderr: ${e}`);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
vfunc_command_line(cmd: Gio.ApplicationCommandLine): number {
|
||||
@@ -186,26 +184,22 @@ export class Shell extends Gtk.Application implements Gio.ActionMap {
|
||||
|
||||
vfunc_activate(): void {
|
||||
super.vfunc_activate();
|
||||
this.hold();
|
||||
this.main();
|
||||
}
|
||||
|
||||
private main(): void {
|
||||
this.#loop = GLib.MainLoop.new(null, false);
|
||||
|
||||
createRoot((dispose) => {
|
||||
console.log(`Colorshell: Initializing things`);
|
||||
this.#connections.set(this, this.connect("shutdown", () => dispose()));
|
||||
this.#scope = getScope();
|
||||
|
||||
initPlayer();
|
||||
|
||||
Stylesheet.getDefault();
|
||||
|
||||
// Init clipboard module
|
||||
Clipboard.getDefault();
|
||||
|
||||
console.log("Initializing wallpaper handler");
|
||||
console.log("Colorshell: Initializing wallpaper & Stylesheet handlers");
|
||||
Wallpaper.getDefault();
|
||||
Stylesheet.getDefault();
|
||||
|
||||
console.log("Adding runner plugins");
|
||||
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))
|
||||
: obj.disconnect(ids));
|
||||
});
|
||||
|
||||
this.#loop.run();
|
||||
}
|
||||
|
||||
quit(): void {
|
||||
this.#loop.is_running() && this.#loop.quit();
|
||||
this.release();
|
||||
super.quit();
|
||||
}
|
||||
}
|
||||
@@ -284,4 +276,4 @@ export const generalConfig = new Config<keyof typeof 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 AstalIO from "gi://AstalIO";
|
||||
import { Shell } from "../app";
|
||||
|
||||
|
||||
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}
|
||||
marginTop={(AstalHyprland.get_default().get_monitor(mon)?.height / 2) - (props.height! / 2)}
|
||||
valign={Gtk.Align.START} hexpand orientation={Gtk.Orientation.VERTICAL}
|
||||
$={(self) => {
|
||||
self.set_application(Shell.getDefault());
|
||||
$={() => {
|
||||
plugins.forEach(plugin =>
|
||||
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 { execAsync } from "ags/process";
|
||||
import { Wallpaper } from "./wallpaper";
|
||||
import { Shell } from "../app";
|
||||
import { exec } from "ags/process";
|
||||
|
||||
import Gio from "gi://Gio?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 {
|
||||
private static instance: Stylesheet;
|
||||
#outputPath = Gio.File.new_for_path(`${GLib.get_user_cache_dir()}/colorshell/style`);
|
||||
#sassStyles!: {
|
||||
colors: string;
|
||||
general: string;
|
||||
#stylesPaths: Array<string>;
|
||||
readonly #sassStyles = {
|
||||
modules: ["sass:color"].map(mod => `@use "${mod}";`).join('\n'),
|
||||
colors: "",
|
||||
mixins: "",
|
||||
rules: ""
|
||||
};
|
||||
|
||||
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 {
|
||||
if(!this.instance)
|
||||
@@ -34,54 +29,36 @@ export class Stylesheet {
|
||||
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 {
|
||||
const stylesNames: Array<string> = Gio.resources_enumerate_children(
|
||||
"/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');
|
||||
return readFile(`${this.stylePath}/style.css`);
|
||||
}
|
||||
|
||||
/*
|
||||
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 {
|
||||
public getColorDefinitions(): string {
|
||||
const data = Wallpaper.getDefault().getData();
|
||||
const colors = {
|
||||
bgPrimary: `color.adjust($color: ${data.colors.color1}, $lightness: -28%)`,
|
||||
bgSecondary: `color.adjust($color: ${data.colors.color1}, $lightness: -16%)`,
|
||||
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%)`
|
||||
...data.special,
|
||||
...data.colors
|
||||
};
|
||||
|
||||
return Object.keys(colors).map(name =>
|
||||
@@ -89,28 +66,82 @@ export class Stylesheet {
|
||||
).join('\n');
|
||||
}
|
||||
|
||||
private updateColors(): void {
|
||||
this.#sassStyles.colors = this.getColors();
|
||||
Shell.getDefault().applyStyle(this.compileSass());
|
||||
private organizeModuleImports(sass: string) {
|
||||
return sass.replaceAll(
|
||||
/[@](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() {
|
||||
try {
|
||||
!this.#outputPath.query_exists(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}`);
|
||||
}
|
||||
if(!this.#outputPath.query_exists(null))
|
||||
this.#outputPath.make_directory_with_parents(null);
|
||||
|
||||
this.#sassStyles = {
|
||||
colors: this.getColors(),
|
||||
general: this.getStyleSheet().replace(/colors\.[$]/g, "\$")
|
||||
};
|
||||
Shell.getDefault().applyStyle(this.compileSass());
|
||||
this.#stylesPaths = Gio.resources_enumerate_children(
|
||||
"/io/github/retrozinndev/colorshell/styles", null
|
||||
).map(name =>
|
||||
`/io/github/retrozinndev/colorshell/styles/${name}`
|
||||
);
|
||||
|
||||
monitorFile(`${GLib.get_user_cache_dir()}/wal/colors.json`, () => {
|
||||
this.updateColors();
|
||||
// Rules won't change at runtime in a common build,
|
||||
// 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 { timeout } from "ags/time";
|
||||
import GObject, { register, getter } from "ags/gobject";
|
||||
import { monitorFile, readFile } from "ags/file";
|
||||
import GObject, { register, getter } from "ags/gobject";
|
||||
|
||||
import AstalIO from "gi://AstalIO";
|
||||
import Gio from "gi://Gio?version=2.0";
|
||||
import GLib from "gi://GLib?version=2.0";
|
||||
import { decoder, encoder } from "./utils";
|
||||
|
||||
|
||||
export { Wallpaper };
|
||||
@@ -96,7 +97,7 @@ class Wallpaper extends GObject.Object {
|
||||
if(!loaded)
|
||||
console.error("Wallpaper: Couldn't read changes inside the hyprpaper file!");
|
||||
|
||||
const content = new TextDecoder().decode(text);
|
||||
const content = decoder.decode(text);
|
||||
|
||||
if(content) {
|
||||
let setWall: boolean = true;
|
||||
@@ -147,7 +148,7 @@ class Wallpaper extends GObject.Object {
|
||||
if(res) {
|
||||
// success
|
||||
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}
|
||||
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 AstalNetwork from "gi://AstalNetwork";
|
||||
import AstalWp from "gi://AstalWp";
|
||||
import { Shell } from "../../app";
|
||||
|
||||
|
||||
export const Status = () =>
|
||||
@@ -134,7 +133,7 @@ function StatusIcons() {
|
||||
: "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"))}
|
||||
/>
|
||||
</Gtk.Box>
|
||||
|
||||
@@ -7,8 +7,24 @@ import GObject, { property, register, signal } from "ags/gobject";
|
||||
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" })
|
||||
class Tile extends Gtk.Box {
|
||||
@signal(Boolean) toggled(_state: boolean) {}
|
||||
@@ -119,8 +135,9 @@ class Tile extends Gtk.Box {
|
||||
return super.connect(signal, callback);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
export function TileFun(props: TileProps): Gtk.Widget {
|
||||
function Tile(props: TileProps): Gtk.Widget {
|
||||
const subs: Array<() => void> = [];
|
||||
const [toggled, setToggled] = createState(((props.toggleState instanceof Accessor) ?
|
||||
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
|
||||
* monitor, or all available monitors!
|
||||
*/
|
||||
@register()
|
||||
@register({ GTypeName: "Windows" })
|
||||
class Windows extends GObject.Object {
|
||||
private static instance: (Windows | null);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user