Added strict type checking to the project. (#236)

* Implement strict typing (WIP).

* changes

* Finish type checks

* Fix notification icon, matugen settings and update tsconfig.

* OSD Styling updates and added the ability to configure OSD duration.
This commit is contained in:
Jas Singh
2024-09-09 00:44:51 -07:00
committed by GitHub
parent 41dbc3829a
commit bb3b3dfdfb
56 changed files with 468 additions and 240 deletions

View File

@@ -10,7 +10,7 @@ export const substitutes = {
"preferences-system": "emblem-system-symbolic",
"com.github.Aylur.ags-symbolic": "controls-symbolic",
"com.github.Aylur.ags": "controls-symbolic",
}
} as const;
export default {
missing: "image-missing-symbolic",

View File

@@ -1,3 +1,4 @@
import { isHexColor } from "globals/variables"
import { Variable } from "resource:///com/github/Aylur/ags/variable.js"
type OptProps = {
@@ -49,7 +50,7 @@ export class Opt<T = unknown> extends Variable<T> {
if (this.persistent)
return;
const isColor = /^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/.test(`${this.value}`);
const isColor = isHexColor(this.value as string);
if ((JSON.stringify(this.value) !== JSON.stringify(this.initial)) && isColor) {
this.value = this.initial
return this.id
@@ -60,35 +61,37 @@ export class Opt<T = unknown> extends Variable<T> {
export const opt = <T>(initial: T, opts?: OptProps) => new Opt(initial, opts)
function getOptions(object: object, path = ""): Opt[] {
function getOptions(object: Record<string, unknown>, path = ""): Opt[] {
return Object.keys(object).flatMap(key => {
const obj: Opt = object[key]
const id = path ? path + "." + key : key
const obj = object[key];
const id = path ? path + "." + key : key;
if (obj instanceof Variable) {
obj.id = id
return obj
const optValue = obj as Opt;
optValue.id = id;
return optValue;
}
if (typeof obj === "object")
return getOptions(obj, id)
if (typeof obj === "object" && obj !== null) {
return getOptions(obj as Record<string, unknown>, id); // Recursively process nested objects
}
return []
})
return [];
});
}
export function mkOptions<T extends object>(cacheFile: string, object: T, confFile: string = "config.json") {
for (const opt of getOptions(object))
for (const opt of getOptions(object as Record<string, unknown>))
opt.init(cacheFile)
Utils.ensureDirectory(cacheFile.split("/").slice(0, -1).join("/"))
const configFile = `${TMP}/${confFile}`
const values = getOptions(object).reduce((obj, { id, value }) => ({ [id]: value, ...obj }), {})
const values = getOptions(object as Record<string, unknown>).reduce((obj, { id, value }) => ({ [id]: value, ...obj }), {})
Utils.writeFileSync(JSON.stringify(values, null, 2), configFile)
Utils.monitorFile(configFile, () => {
const cache = JSON.parse(Utils.readFile(configFile) || "{}")
for (const opt of getOptions(object)) {
for (const opt of getOptions(object as Record<string, unknown>)) {
if (JSON.stringify(cache[opt.id]) !== JSON.stringify(opt.value))
opt.value = cache[opt.id]
}
@@ -99,7 +102,7 @@ export function mkOptions<T extends object>(cacheFile: string, object: T, confFi
}
async function reset(
[opt, ...list] = getOptions(object),
[opt, ...list] = getOptions(object as Record<string, unknown>),
id = opt?.reset(),
): Promise<Array<string>> {
if (!opt)
@@ -111,7 +114,7 @@ export function mkOptions<T extends object>(cacheFile: string, object: T, confFi
}
async function resetTheme(
[opt, ...list] = getOptions(object),
[opt, ...list] = getOptions(object as Record<string, unknown>),
id = opt?.doResetColor(),
): Promise<Array<string>> {
if (!opt)
@@ -124,7 +127,7 @@ export function mkOptions<T extends object>(cacheFile: string, object: T, confFi
return Object.assign(object, {
configFile,
array: () => getOptions(object),
array: () => getOptions(object as Record<string, unknown>),
async reset() {
return (await reset()).join("\n")
},
@@ -132,7 +135,7 @@ export function mkOptions<T extends object>(cacheFile: string, object: T, confFi
return (await resetTheme()).join("\n")
},
handler(deps: string[], callback: () => void) {
for (const opt of getOptions(object)) {
for (const opt of getOptions(object as Record<string, unknown>)) {
if (deps.some(i => opt.id.startsWith(i)))
opt.connect("changed", callback)
}

View File

@@ -1,3 +1,5 @@
import { layoutMap } from "customModules/kblayout/layouts";
export type KbLabelType = "layout" | "code";
export type KbIcon = "" | "󰌌" | "" | "󰬴" | "󰗊";
@@ -26,3 +28,6 @@ export type HyprctlDeviceLayout = {
touch: any[];
switches: any[];
};
export type LayoutKeys = keyof typeof layoutMap;
export type LayoutValues = typeof layoutMap[LayoutKeys];

View File

@@ -0,0 +1,9 @@
import { Binding } from "lib/utils";
export type InputHandlerEvents = {
onPrimaryClick?: Binding,
onSecondaryClick?: Binding,
onMiddleClick?: Binding,
onScrollUp?: Binding,
onScrollDown?: Binding,
}

10
lib/types/dropdownmenu.d.ts vendored Normal file
View File

@@ -0,0 +1,10 @@
import { WindowProps } from "types/widgets/window";
export type DropdownMenuProps = {
name: string;
child: any;
layout?: string;
transition?: any;
exclusivity?: Exclusivity;
fixed?: boolean;
} & WindowProps;

3
lib/types/filechooser.d.ts vendored Normal file
View File

@@ -0,0 +1,3 @@
export type Config = {
[key: string]: string | number | boolean | object;
}

3
lib/types/mpris.d.ts vendored Normal file
View File

@@ -0,0 +1,3 @@
export type LoopStatus = 'none' | 'track' | 'playlist';
export type PlaybackStatus = 'playing' | 'paused' | 'stopped';

View File

@@ -1,3 +1,5 @@
import { WIFI_STATUS_MAP } from "globals/network";
export type AccessPoint = {
bssid: string | null;
address: string | null;
@@ -8,3 +10,5 @@ export type AccessPoint = {
frequency: number;
iconName: string | undefined;
}
export type WifiStatus = keyof typeof WIFI_STATUS_MAP;

View File

@@ -1,3 +1,5 @@
import icons from "modules/icons/index";
export interface NotificationArgs {
appName?: string;
body?: string;
@@ -9,3 +11,5 @@ export interface NotificationArgs {
timeout?: number;
transient?: boolean;
}
export type NotificationIcon = keyof typeof icons.notifications;

View File

@@ -1,6 +1,10 @@
import { Opt } from "lib/option";
import { Variable } from "types/variable";
export type RecursiveOptionsObject = {
[key: string]: RecursiveOptionsObject | Opt<string | number | boolean> | Opt<any>;
};
export type Unit = "imperial" | "metric";
export type PowerOptions = "sleep" | "reboot" | "logout" | "shutdown";
export type NotificationAnchor = "top" | "top right" | "top left" | "bottom" | "bottom right" | "bottom left" | "left" | "right";
@@ -117,3 +121,4 @@ type MatugenVariation =
| "vivid_3"
type MatugenTheme = "light" | "dark";

27
lib/types/popupwindow.d.ts vendored Normal file
View File

@@ -0,0 +1,27 @@
import { Widget } from "types/widgets/widget";
import { WindowProps } from "types/widgets/window";
import { Transition } from "./widget";
export type PopupWindowProps = {
name: string;
child: any;
layout?: Layouts;
transition?: any;
exclusivity?: Exclusivity;
} & WindowProps;
export type LayoutFunction = (
name: string,
child: Widget,
transition: Transition
) => {
center: () => Widget;
top: () => Widget;
"top-right": () => Widget;
"top-center": () => Widget;
"top-left": () => Widget;
"bottom-left": () => Widget;
"bottom-center": () => Widget;
"bottom-right": () => Widget;
};
export type Layouts = 'center' | 'top' | 'top-right' | 'top-center' | 'top-left' | 'bottom-left' | 'bottom-center' | 'bottom-right';

8
lib/types/powerprofiles.d.ts vendored Normal file
View File

@@ -0,0 +1,8 @@
import icons from "modules/icons/index";
import PowerProfiles from "types/service/powerprofiles.js"
export type PowerProfiles = InstanceType<typeof PowerProfiles>;
export type PowerProfile = "power-saver" | "balanced" | "performance";
export type PowerProfileObject = {
[key: string]: string;
}

3
lib/types/utils.d.ts vendored Normal file
View File

@@ -0,0 +1,3 @@
import { substitutes } from "lib/icons";
type SubstituteKeys = keyof typeof substitutes;

View File

@@ -1,3 +1,5 @@
import { weatherIcons } from "modules/icons/weather";
export type UnitType = "imperial" | "metric";
export type Weather = {
@@ -107,3 +109,10 @@ export type Location = {
localtime_epoch: number;
localtime: string;
}
export type TemperatureIconColorMap = {
[key: number]: string;
}
export type WeatherIconTitle = keyof typeof weatherIcons;
export type WeatherIcon = typeof weatherIcons[WeatherIconTitle];

View File

@@ -1,3 +1,6 @@
export type Exclusivity = 'normal' | 'ignore' | 'exclusive';
export type Anchor = "left" | "right" | "top" | "down";
export type Transition = "none" | "crossfade" | "slide_right" | "slide_left" | "slide_up" | "slide_down";
// Window
export type Layouts = 'center' | 'top' | 'top-right' | 'top-center' | 'top-left' | 'bottom-left' | 'bottom-center' | 'bottom-right';

View File

@@ -8,20 +8,29 @@ import Gdk from "gi://Gdk"
import GLib from "gi://GLib?version=2.0"
import GdkPixbuf from "gi://GdkPixbuf";
import { NotificationArgs } from "types/utils/notify"
import { SubstituteKeys } from "./types/utils";
export type Binding<T> = import("types/service").Binding<any, any, T>
/**
* @returns substitute icon || name || fallback icon
*/
export function icon(name: string | null, fallback = icons.missing) {
const validateSubstitute = (name: string): name is SubstituteKeys => name in substitutes;
if (!name)
return fallback || ""
if (GLib.file_test(name, GLib.FileTest.EXISTS))
return name
const icon = (substitutes[name] || name)
let icon: string = name;
if (validateSubstitute(name)) {
icon = substitutes[name];
}
if (Utils.lookUpIcon(icon))
return icon