* Clean up unused code * Fix media player formatting issue for labels with new line characteres. * Refactor the media player handlers into a class. * More code cleanup and organize shared weather utils into distinct classes. * Flatten some nesting. * Move weather manager in dedicated class and build HTTP Utility class for Rest API calling. * Remove logs * Rebase master merge * Reorg code (WIP) * More reorg * Delete utility scripts * Reorg options * Finish moving all options over * Fix typescript issues * Update options imports to default * missed update * Screw barrel files honestly, work of the devil. * Only initialize power profiles if power-profiles-daemon is running. * Fix window positioning and weather service naming * style dir * More organization * Restructure types to be closer to their source * Remove lib types and constants * Update basic weather object to be saner with extensibility. * Service updates * Fix initialization strategy for services. * Fix Config Manager to only emit changed objects and added missing temp converters. * Update storage service to handle unit changes. * Added cpu temp sensor auto-discovery * Added missing JSDocs to services * remove unused * Migrate to network service. * Fix network password issue. * Move out password input into helper * Rename password mask constant to be less double-negativey. * Dropdown menu rename * Added a component to edit JSON in the settings dialog (rough/WIP) * Align settings * Add and style JSON Editor. * Adjust padding * perf(shortcuts): ⚡ avoid unnecessary polling when shortcuts are disabled Stops the recording poller when shortcuts are disabled, preventing redundant polling and reducing resource usage. * Fix types and return value if shortcut not enabled. * Move the swww daemon checking process outside of the wallpaper service into a dedicated deamon lifecyle processor. * Add more string formatters and use title case for weather status (as it was). * Fix startup errors. * Rgba fix * Remove zod from dependencies --------- Co-authored-by: KernelDiego <gonzalezdiego.contact@gmail.com>
127 lines
4.3 KiB
TypeScript
127 lines
4.3 KiB
TypeScript
import { ColorMapKey, HexColor, MatugenColors } from '../../lib/options/types';
|
|
import { getMatugenVariations } from './variations';
|
|
import icons from '../../lib/icons/icons';
|
|
import { SystemUtilities } from 'src/core/system/SystemUtilities';
|
|
import options from 'src/configuration';
|
|
import { isAnImage } from 'src/lib/validation/images';
|
|
import { defaultColorMap } from './defaults';
|
|
|
|
const MATUGEN_ENABLED = options.theme.matugen;
|
|
const MATUGEN_SETTINGS = options.theme.matugen_settings;
|
|
|
|
/**
|
|
* Service that integrates with Matugen to generate color schemes from wallpapers
|
|
*/
|
|
export class MatugenService {
|
|
private static _instance: MatugenService;
|
|
|
|
private constructor() {}
|
|
|
|
/**
|
|
* Gets the singleton instance of the MatugenService
|
|
*
|
|
* @returns The MatugenService instance
|
|
*/
|
|
public static getInstance(): MatugenService {
|
|
if (this._instance === undefined) {
|
|
this._instance = new MatugenService();
|
|
}
|
|
|
|
return this._instance;
|
|
}
|
|
|
|
/**
|
|
* Normalizes contrast value to be within Matugen's acceptable range
|
|
*
|
|
* @param contrast - The raw contrast value
|
|
* @returns Normalized contrast value between -1 and 1
|
|
*/
|
|
private _normalizeContrast(contrast: number): number {
|
|
return Math.max(-1, Math.min(1, contrast));
|
|
}
|
|
|
|
/**
|
|
* Generates a color scheme from the current wallpaper using Matugen
|
|
*
|
|
* @returns The generated color palette or undefined if generation fails
|
|
*/
|
|
public async generateMatugenColors(): Promise<MatugenColors | undefined> {
|
|
if (!MATUGEN_ENABLED.get() || !SystemUtilities.checkDependencies('matugen')) {
|
|
return;
|
|
}
|
|
|
|
const wallpaperPath = options.wallpaper.image.get();
|
|
|
|
if (!wallpaperPath || !isAnImage(wallpaperPath)) {
|
|
SystemUtilities.notify({
|
|
summary: 'Matugen Failed',
|
|
body: "Please select a wallpaper in 'Theming > General' first.",
|
|
iconName: icons.ui.warning,
|
|
});
|
|
|
|
return;
|
|
}
|
|
|
|
try {
|
|
const normalizedContrast = this._normalizeContrast(MATUGEN_SETTINGS.contrast.get());
|
|
const schemeType = MATUGEN_SETTINGS.scheme_type.get();
|
|
const mode = MATUGEN_SETTINGS.mode.get();
|
|
|
|
const baseCommand = `matugen image -q "${wallpaperPath}" -t scheme-${schemeType} --contrast ${normalizedContrast}`;
|
|
|
|
const jsonResult = await SystemUtilities.bash(`${baseCommand} --dry-run --json hex`);
|
|
await SystemUtilities.bash(baseCommand);
|
|
|
|
const parsedResult = JSON.parse(jsonResult);
|
|
return parsedResult?.colors?.[mode];
|
|
} catch (error) {
|
|
SystemUtilities.notify({
|
|
summary: 'Matugen Error',
|
|
body: `An error occurred: ${error}`,
|
|
iconName: icons.ui.info,
|
|
});
|
|
console.error(`An error occurred while generating matugen colors: ${error}`);
|
|
return;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Validates if a color string is a valid key in the default color map
|
|
*
|
|
* @param color - The color key to validate
|
|
* @returns Whether the color is a valid ColorMapKey
|
|
*/
|
|
public isColorKeyValid(color: string): color is ColorMapKey {
|
|
return Object.prototype.hasOwnProperty.call(defaultColorMap, color);
|
|
}
|
|
|
|
/**
|
|
* Maps a default color hex value to its Matugen-generated equivalent
|
|
*
|
|
* @param incomingHex - The original hex color to map
|
|
* @param matugenColors - The Matugen color palette to use for mapping
|
|
* @returns The mapped hex color or original if no mapping exists
|
|
*/
|
|
public getMatugenHex(incomingHex: HexColor, matugenColors?: MatugenColors): HexColor {
|
|
if (!MATUGEN_ENABLED.get() || !matugenColors) {
|
|
return incomingHex;
|
|
}
|
|
|
|
const variation = MATUGEN_SETTINGS.variation.get();
|
|
const matugenVariation = getMatugenVariations(matugenColors, variation);
|
|
|
|
for (const colorKey of Object.keys(defaultColorMap)) {
|
|
if (!this.isColorKeyValid(colorKey)) {
|
|
continue;
|
|
}
|
|
|
|
const colorValue = defaultColorMap[colorKey];
|
|
if (colorValue === incomingHex) {
|
|
return matugenVariation[colorKey] ?? incomingHex;
|
|
}
|
|
}
|
|
|
|
return incomingHex;
|
|
}
|
|
}
|