Implemented Wallpaper Selector and Matugen's Wallpaper based auto-theming. (#73)
* Implement matugen - WIP * Added matugen * Add types and cleanup code * Matugen implementation updates and added more options such as scheme and contrast. * Code cleanup and matugen settings renamed for clarity. * Makon maroon a primary matugen color. * Updates to handle variations of matugen colors * Finalizing matugen and wrapping up variations. * Minor styling updates of the settings dialog. * Do a swww dependency check. * Dependency logic update * Switch shouldn't double trigger notifications now when checking dependency. * Logic was inverted * Add matugen to dependency checker. * Fixed dependency checking conditional * Update dependency list in readme and check for matugen before doing matugen operations * Styling fixes * OSD Fix * Remove unused code from wallpaper service. * Color fixes for matugen. * Nix updates for new dependencies * Change default wallpaper to empty. * Added custom notification service for startup, cleaned up code and updated readme.
This commit is contained in:
@@ -37,12 +37,24 @@ export class Opt<T = unknown> extends Variable<T> {
|
||||
|
||||
reset() {
|
||||
if (this.persistent)
|
||||
return
|
||||
return;
|
||||
|
||||
if (JSON.stringify(this.value) !== JSON.stringify(this.initial)) {
|
||||
this.value = this.initial
|
||||
return this.id;
|
||||
}
|
||||
}
|
||||
|
||||
doResetColor() {
|
||||
if (this.persistent)
|
||||
return;
|
||||
|
||||
const isColor = /^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/.test(`${this.value}`);
|
||||
if ((JSON.stringify(this.value) !== JSON.stringify(this.initial)) && isColor) {
|
||||
this.value = this.initial
|
||||
return this.id
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,13 +77,13 @@ function getOptions(object: object, path = ""): Opt[] {
|
||||
})
|
||||
}
|
||||
|
||||
export function mkOptions<T extends object>(cacheFile: string, object: T) {
|
||||
export function mkOptions<T extends object>(cacheFile: string, object: T, confFile: string = "config.json") {
|
||||
for (const opt of getOptions(object))
|
||||
opt.init(cacheFile)
|
||||
|
||||
Utils.ensureDirectory(cacheFile.split("/").slice(0, -1).join("/"))
|
||||
|
||||
const configFile = `${TMP}/config.json`
|
||||
const configFile = `${TMP}/${confFile}`
|
||||
const values = getOptions(object).reduce((obj, { id, value }) => ({ [id]: value, ...obj }), {})
|
||||
Utils.writeFileSync(JSON.stringify(values, null, 2), configFile)
|
||||
Utils.monitorFile(configFile, () => {
|
||||
@@ -98,12 +110,27 @@ export function mkOptions<T extends object>(cacheFile: string, object: T) {
|
||||
: await sleep().then(() => reset(list))
|
||||
}
|
||||
|
||||
async function resetTheme(
|
||||
[opt, ...list] = getOptions(object),
|
||||
id = opt?.doResetColor(),
|
||||
): Promise<Array<string>> {
|
||||
if (!opt)
|
||||
return sleep().then(() => [])
|
||||
|
||||
return id
|
||||
? [id, ...(await sleep(50).then(() => resetTheme(list)))]
|
||||
: await sleep().then(() => resetTheme(list))
|
||||
}
|
||||
|
||||
return Object.assign(object, {
|
||||
configFile,
|
||||
array: () => getOptions(object),
|
||||
async reset() {
|
||||
return (await reset()).join("\n")
|
||||
},
|
||||
async resetTheme() {
|
||||
return (await resetTheme()).join("\n")
|
||||
},
|
||||
handler(deps: string[], callback: () => void) {
|
||||
for (const opt of getOptions(object)) {
|
||||
if (deps.some(i => opt.id.startsWith(i)))
|
||||
|
||||
59
lib/types/defaults/options.ts
Normal file
59
lib/types/defaults/options.ts
Normal file
@@ -0,0 +1,59 @@
|
||||
export const defaultColorMap = {
|
||||
"rosewater": "#f5e0dc",
|
||||
"flamingo": "#f2cdcd",
|
||||
"pink": "#f5c2e7",
|
||||
"mauve": "#cba6f7",
|
||||
"red": "#f38ba8",
|
||||
"maroon": "#eba0ac",
|
||||
"peach": "#fab387",
|
||||
"yellow": "#f9e2af",
|
||||
"green": "#a6e3a1",
|
||||
"teal": "#94e2d5",
|
||||
"sky": "#89dceb",
|
||||
"sapphire": "#74c7ec",
|
||||
"blue": "#89b4fa",
|
||||
"lavender": "#b4befe",
|
||||
"text": "#cdd6f4",
|
||||
"subtext1": "#bac2de",
|
||||
"subtext2": "#a6adc8",
|
||||
"overlay2": "#9399b2",
|
||||
"overlay1": "#7f849c",
|
||||
"overlay0": "#6c7086",
|
||||
"surface2": "#585b70",
|
||||
"surface1": "#45475a",
|
||||
"surface0": "#313244",
|
||||
"base2": "#242438",
|
||||
"base": "#1e1e2e",
|
||||
"mantle": "#181825",
|
||||
"crust": "#11111b",
|
||||
"surface1_2": "#454759",
|
||||
"text2": "#cdd6f3",
|
||||
"pink2": "#f5c2e6",
|
||||
"red2": "#f38ba7",
|
||||
"mantle2": "#181824",
|
||||
"surface0_2": "#313243",
|
||||
"surface2_2": "#585b69",
|
||||
"overlay1_2": "#7f849b",
|
||||
"lavender2": "#b4befd",
|
||||
"mauve2": "#cba6f6",
|
||||
"green2": "#a6e3a0",
|
||||
"sky2": "#89dcea",
|
||||
"teal2": "#94e2d4",
|
||||
"yellow2": "#f9e2ad",
|
||||
"maroon2": "#eba0ab",
|
||||
"crust2": "#11111a",
|
||||
"pink3": "#f5c2e8",
|
||||
"red3": "#f38ba9",
|
||||
"mantle3": "#181826",
|
||||
"surface0_3": "#313245",
|
||||
"surface2_3": "#585b71",
|
||||
"overlay1_3": "#7f849d",
|
||||
"lavender3": "#b4beff",
|
||||
"mauve3": "#cba6f8",
|
||||
"green3": "#a6e3a2",
|
||||
"sky3": "#89dcec",
|
||||
"teal3": "#94e2d6",
|
||||
"yellow3": "#f9e2ae",
|
||||
"maroon3": "#eba0ad",
|
||||
"crust3": "#11111c",
|
||||
};
|
||||
11
lib/types/notification.d.ts
vendored
Normal file
11
lib/types/notification.d.ts
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
export interface NotificationArgs {
|
||||
appName?: string;
|
||||
body?: string;
|
||||
iconName?: string;
|
||||
id?: number;
|
||||
summary?: string;
|
||||
urgency?: Urgency;
|
||||
category?: string;
|
||||
timeout?: number;
|
||||
transient?: boolean;
|
||||
}
|
||||
82
lib/types/options.d.ts
vendored
82
lib/types/options.d.ts
vendored
@@ -1,4 +1,5 @@
|
||||
import { Opt } from "lib/option";
|
||||
import { Variable } from "types/variable";
|
||||
|
||||
export type Unit = "imperial" | "metric";
|
||||
export type PowerOptions = "sleep" | "reboot" | "logout" | "shutdown";
|
||||
@@ -17,12 +18,91 @@ export type RowProps<T> = {
|
||||
| "enum"
|
||||
| "boolean"
|
||||
| "img"
|
||||
| "wallpaper"
|
||||
| "font"
|
||||
enums?: string[]
|
||||
max?: number
|
||||
min?: number
|
||||
subtitle?: string
|
||||
disabledBinding?: Variable<boolean>
|
||||
subtitle?: string | VarType<any> | Opt,
|
||||
dependencies?: string[],
|
||||
increment?: number
|
||||
}
|
||||
|
||||
export type OSDOrientation = "horizontal" | "vertical";
|
||||
|
||||
export type HexColor = `#${string}`;
|
||||
|
||||
export type MatugenColors = {
|
||||
"background": HexColor,
|
||||
"error": HexColor,
|
||||
"error_container": HexColor,
|
||||
"inverse_on_surface": HexColor,
|
||||
"inverse_primary": HexColor,
|
||||
"inverse_surface": HexColor,
|
||||
"on_background": HexColor,
|
||||
"on_error": HexColor,
|
||||
"on_error_container": HexColor,
|
||||
"on_primary": HexColor,
|
||||
"on_primary_container": HexColor,
|
||||
"on_primary_fixed": HexColor,
|
||||
"on_primary_fixed_variant": HexColor,
|
||||
"on_secondary": HexColor,
|
||||
"on_secondary_container": HexColor,
|
||||
"on_secondary_fixed": HexColor,
|
||||
"on_secondary_fixed_variant": HexColor,
|
||||
"on_surface": HexColor,
|
||||
"on_surface_variant": HexColor,
|
||||
"on_tertiary": HexColor,
|
||||
"on_tertiary_container": HexColor,
|
||||
"on_tertiary_fixed": HexColor,
|
||||
"on_tertiary_fixed_variant": HexColor,
|
||||
"outline": HexColor,
|
||||
"outline_variant": HexColor,
|
||||
"primary": HexColor,
|
||||
"primary_container": HexColor,
|
||||
"primary_fixed": HexColor,
|
||||
"primary_fixed_dim": HexColor,
|
||||
"scrim": HexColor,
|
||||
"secondary": HexColor,
|
||||
"secondary_container": HexColor,
|
||||
"secondary_fixed": HexColor,
|
||||
"secondary_fixed_dim": HexColor,
|
||||
"shadow": HexColor,
|
||||
"surface": HexColor,
|
||||
"surface_bright": HexColor,
|
||||
"surface_container": HexColor,
|
||||
"surface_container_high": HexColor,
|
||||
"surface_container_highest": HexColor,
|
||||
"surface_container_low": HexColor,
|
||||
"surface_container_lowest": HexColor,
|
||||
"surface_dim": HexColor,
|
||||
"surface_variant": HexColor,
|
||||
"tertiary": HexColor,
|
||||
"tertiary_container": HexColor,
|
||||
"tertiary_fixed": HexColor,
|
||||
"tertiary_fixed_dim": HexColor
|
||||
}
|
||||
|
||||
type MatugenScheme =
|
||||
| "content"
|
||||
| "expressive"
|
||||
| "fidelity"
|
||||
| "fruit-salad"
|
||||
| "monochrome"
|
||||
| "neutral"
|
||||
| "rainbow"
|
||||
| "tonal-spot";
|
||||
|
||||
type MatugenVariation =
|
||||
| "standard_1"
|
||||
| "standard_2"
|
||||
| "standard_3"
|
||||
| "monochrome_1"
|
||||
| "monochrome_2"
|
||||
| "monochrome_3"
|
||||
| "vivid_1"
|
||||
| "vivid_2"
|
||||
| "vivid_3"
|
||||
|
||||
type MatugenTheme = "light" | "dark";
|
||||
|
||||
36
lib/utils.ts
36
lib/utils.ts
@@ -4,6 +4,8 @@ import icons, { substitutes } from "./icons"
|
||||
import Gtk from "gi://Gtk?version=3.0"
|
||||
import Gdk from "gi://Gdk"
|
||||
import GLib from "gi://GLib?version=2.0"
|
||||
import GdkPixbuf from "gi://GdkPixbuf";
|
||||
import { NotificationArgs } from "types/utils/notify"
|
||||
|
||||
export type Binding<T> = import("types/service").Binding<any, any, T>
|
||||
|
||||
@@ -73,7 +75,12 @@ export function dependencies(...bins: string[]) {
|
||||
|
||||
if (missing.length > 0) {
|
||||
console.warn(Error(`missing dependencies: ${missing.join(", ")}`))
|
||||
Utils.notify(`missing dependencies: ${missing.join(", ")}`)
|
||||
Notify({
|
||||
summary: "Dependencies not found!",
|
||||
body: `The following dependencies are missing: ${missing.join(", ")}`,
|
||||
iconName: icons.ui.warning,
|
||||
timeout: 7000
|
||||
});
|
||||
}
|
||||
|
||||
return missing.length === 0
|
||||
@@ -111,3 +118,30 @@ export function createSurfaceFromWidget(widget: Gtk.Widget) {
|
||||
widget.draw(cr)
|
||||
return surface
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure that the provided filepath is a valid image
|
||||
*/
|
||||
export const isAnImage = (imgFilePath: string): boolean => {
|
||||
try {
|
||||
GdkPixbuf.Pixbuf.new_from_file(imgFilePath);
|
||||
return true;
|
||||
} catch (error) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export const Notify = (notifPayload: NotificationArgs): void => {
|
||||
let command = 'notify-send';
|
||||
command += ` "${notifPayload.summary} "`;
|
||||
if (notifPayload.body) command += ` "${notifPayload.body}" `;
|
||||
if (notifPayload.appName) command += ` -a "${notifPayload.appName}"`;
|
||||
if (notifPayload.iconName) command += ` -i "${notifPayload.iconName}"`;
|
||||
if (notifPayload.urgency) command += ` -u "${notifPayload.urgency}"`;
|
||||
if (notifPayload.timeout !== undefined) command += ` -t ${notifPayload.timeout}`;
|
||||
if (notifPayload.category) command += ` -c "${notifPayload.category}"`;
|
||||
if (notifPayload.transient) command += ` -e`;
|
||||
if (notifPayload.id !== undefined) command += ` -r ${notifPayload.id}`;
|
||||
|
||||
Utils.execAsync(command)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user