Files
custum-hyprpanel/src/components/bar/modules/workspaces/helpers/utils.ts
2025-03-28 09:29:56 -07:00

274 lines
10 KiB
TypeScript

import AstalHyprland from 'gi://AstalHyprland?version=0.1';
import { defaultApplicationIconMap } from 'src/lib/constants/appIcons';
import { AppIconOptions, WorkspaceIconMap } from 'src/lib/types/workspace';
import { isValidGjsColor } from 'src/lib/utils';
import options from 'src/options';
const hyprlandService = AstalHyprland.get_default();
const { monochrome, background } = options.theme.bar.buttons;
const { background: wsBackground, active } = options.theme.bar.buttons.workspaces;
const { showWsIcons, showAllActive, numbered_active_indicator: wsActiveIndicator } = options.bar.workspaces;
/**
* Determines if a workspace is active on a given monitor.
*
* This function checks if the workspace with the specified index is currently active on the given monitor.
* It uses the `showAllActive` setting and the `hyprlandService` to determine the active workspace on the monitor.
*
* @param monitor The index of the monitor to check.
* @param i The index of the workspace to check.
*
* @returns True if the workspace is active on the monitor, false otherwise.
*/
const isWorkspaceActiveOnMonitor = (monitor: number, i: number): boolean => {
return showAllActive.get() && hyprlandService.get_monitor(monitor)?.activeWorkspace?.id === i;
};
/**
* Retrieves the icon for a given workspace.
*
* This function returns the icon associated with a workspace from the provided workspace icon map.
* If no icon is found, it returns the workspace index as a string.
*
* @param wsIconMap The map of workspace icons where keys are workspace indices and values are icons or icon objects.
* @param i The index of the workspace for which to retrieve the icon.
*
* @returns The icon for the workspace as a string. If no icon is found, returns the workspace index as a string.
*/
const getWsIcon = (wsIconMap: WorkspaceIconMap, i: number): string => {
const iconEntry = wsIconMap[i];
const defaultIcon = `${i}`;
if (!iconEntry) {
return defaultIcon;
}
if (typeof iconEntry === 'string' && iconEntry !== '') {
return iconEntry;
}
const hasIcon = typeof iconEntry === 'object' && 'icon' in iconEntry && iconEntry.icon !== '';
if (hasIcon) {
return iconEntry.icon;
}
return defaultIcon;
};
/**
* Retrieves the color for a given workspace.
*
* This function determines the color styling for a workspace based on the provided workspace icon map,
* smart highlighting settings, and the monitor index. It returns a CSS string for the color and background.
*
* @param wsIconMap The map of workspace icons where keys are workspace indices and values are icon objects.
* @param i The index of the workspace for which to retrieve the color.
* @param smartHighlight A boolean indicating whether smart highlighting is enabled.
* @param monitor The index of the monitor to check for active workspaces.
*
* @returns A CSS string representing the color and background for the workspace. If no color is found, returns an empty string.
*/
export const getWsColor = (
wsIconMap: WorkspaceIconMap,
i: number,
smartHighlight: boolean,
monitor: number,
): string => {
const iconEntry = wsIconMap[i];
const hasColor = typeof iconEntry === 'object' && 'color' in iconEntry && isValidGjsColor(iconEntry.color);
if (!iconEntry) {
return '';
}
if (
showWsIcons.get() &&
smartHighlight &&
wsActiveIndicator.get() === 'highlight' &&
(hyprlandService.focusedWorkspace?.id === i || isWorkspaceActiveOnMonitor(monitor, i))
) {
const iconColor = monochrome.get() ? background.get() : wsBackground.get();
const iconBackground = hasColor && isValidGjsColor(iconEntry.color) ? iconEntry.color : active.get();
const colorCss = `color: ${iconColor};`;
const backgroundCss = `background: ${iconBackground};`;
return colorCss + backgroundCss;
}
if (hasColor && isValidGjsColor(iconEntry.color)) {
return `color: ${iconEntry.color}; border-bottom-color: ${iconEntry.color};`;
}
return '';
};
/**
* Retrieves the application icon for a given workspace.
*
* This function returns the appropriate application icon for the specified workspace index.
* It considers user-defined icons, default icons, and the option to remove duplicate icons.
*
* @param workspaceIndex The index of the workspace for which to retrieve the application icon.
* @param removeDuplicateIcons A boolean indicating whether to remove duplicate icons.
* @param options An object containing user-defined icon map, default icon, and empty icon.
*
* @returns The application icon for the workspace as a string. If no icons are found, returns the default or empty icon.
*/
export const getAppIcon = (
workspaceIndex: number,
removeDuplicateIcons: boolean,
{ iconMap: userDefinedIconMap, defaultIcon, emptyIcon }: AppIconOptions,
): string => {
const workspaceClients = hyprlandService
.get_clients()
.filter((client) => client?.workspace?.id === workspaceIndex)
.map((client) => [client.class, client.title]);
if (!workspaceClients.length) {
return emptyIcon;
}
const findIconForClient = (clientClass: string, clientTitle: string): string | undefined => {
const appIconMap = { ...userDefinedIconMap, ...defaultApplicationIconMap };
const iconEntry = Object.entries(appIconMap).find(([matcher]) => {
if (matcher.startsWith('class:')) {
return new RegExp(matcher.substring(6)).test(clientClass);
}
if (matcher.startsWith('title:')) {
return new RegExp(matcher.substring(6)).test(clientTitle);
}
return new RegExp(matcher, 'i').test(clientClass);
});
return iconEntry?.[1] ?? defaultIcon;
};
let icons = workspaceClients.reduce((iconAccumulator, [clientClass, clientTitle]) => {
const icon = findIconForClient(clientClass, clientTitle);
if (icon) {
iconAccumulator.push(icon);
}
return iconAccumulator;
}, []);
if (icons.length) {
if (removeDuplicateIcons) {
icons = [...new Set(icons)];
}
return icons.join(' ');
}
return defaultIcon;
};
/**
* Renders the class names for a workspace.
*
* This function generates the appropriate class names for a workspace based on various settings such as
* whether to show icons, numbered workspaces, workspace icons, and smart highlighting.
*
* @param showIcons A boolean indicating whether to show icons.
* @param showNumbered A boolean indicating whether to show numbered workspaces.
* @param numberedActiveIndicator The indicator for active numbered workspaces.
* @param showWsIcons A boolean indicating whether to show workspace icons.
* @param smartHighlight A boolean indicating whether smart highlighting is enabled.
* @param monitor The index of the monitor to check for active workspaces.
* @param i The index of the workspace for which to render class names.
*
* @returns The class names for the workspace as a string.
*/
export const renderClassnames = (
showIcons: boolean,
showNumbered: boolean,
numberedActiveIndicator: string,
showWsIcons: boolean,
smartHighlight: boolean,
monitor: number,
i: number,
): string => {
const isWorkspaceActive = hyprlandService.focusedWorkspace?.id === i || isWorkspaceActiveOnMonitor(monitor, i);
const isActive = isWorkspaceActive ? 'active' : '';
if (showIcons) {
return `workspace-icon txt-icon bar ${isActive}`;
}
if (showNumbered || showWsIcons) {
const numActiveInd = isWorkspaceActive ? numberedActiveIndicator : '';
const wsIconClass = showWsIcons ? 'txt-icon' : '';
const smartHighlightClass = smartHighlight ? 'smart-highlight' : '';
const className = `workspace-number can_${numberedActiveIndicator} ${numActiveInd} ${wsIconClass} ${smartHighlightClass} ${isActive}`;
return className.trim();
}
return `default ${isActive}`;
};
/**
* Renders the label for a workspace.
*
* This function generates the appropriate label for a workspace based on various settings such as
* whether to show icons, application icons, workspace icons, and workspace indicators.
*
* @param showIcons A boolean indicating whether to show icons.
* @param availableIndicator The indicator for available workspaces.
* @param activeIndicator The indicator for active workspaces.
* @param occupiedIndicator The indicator for occupied workspaces.
* @param showAppIcons A boolean indicating whether to show application icons.
* @param appIcons The application icons as a string.
* @param workspaceMask A boolean indicating whether to mask the workspace.
* @param showWorkspaceIcons A boolean indicating whether to show workspace icons.
* @param wsIconMap The map of workspace icons where keys are workspace indices and values are icons or icon objects.
* @param i The index of the workspace for which to render the label.
* @param index The index of the workspace in the list.
* @param monitor The index of the monitor to check for active workspaces.
*
* @returns The label for the workspace as a string.
*/
export const renderLabel = (
showIcons: boolean,
availableIndicator: string,
activeIndicator: string,
occupiedIndicator: string,
showAppIcons: boolean,
appIcons: string,
workspaceMask: boolean,
showWorkspaceIcons: boolean,
wsIconMap: WorkspaceIconMap,
i: number,
index: number,
monitor: number,
): string => {
if (showAppIcons) {
return appIcons;
}
if (showIcons) {
if (hyprlandService.focusedWorkspace?.id === i || isWorkspaceActiveOnMonitor(monitor, i)) {
return activeIndicator;
}
if ((hyprlandService.get_workspace(i)?.get_clients().length || 0) > 0) {
return occupiedIndicator;
}
if (monitor !== -1) {
return availableIndicator;
}
}
if (showWorkspaceIcons) {
return getWsIcon(wsIconMap, i);
}
return workspaceMask ? `${index + 1}` : `${i}`;
};