From 994302978c2c7cc42cb89aa2c0c8ddd3fa3423d7 Mon Sep 17 00:00:00 2001 From: Supertiger Date: Sat, 2 Aug 2025 09:09:07 +0100 Subject: [PATCH] Add charging icon and fix errors --- src/routes/waybar/Label.ts | 7 +- src/routes/waybar/configParser.ts | 471 +++++++++++---------------- src/routes/waybar/modules/battery.ts | 39 ++- src/routes/waybar/modules/clock.ts | 6 +- 4 files changed, 231 insertions(+), 292 deletions(-) diff --git a/src/routes/waybar/Label.ts b/src/routes/waybar/Label.ts index 6780c76..f7f385c 100644 --- a/src/routes/waybar/Label.ts +++ b/src/routes/waybar/Label.ts @@ -5,7 +5,7 @@ interface LabelOpts { config?: { [key: string]: any; format?: string; - states: string[]; + states?: Record; "format-icons"?: string[]; }; module: Module; @@ -20,9 +20,11 @@ export const createLabel = (opts: LabelOpts) => { if (!format) { return opts.config?.format || undefined; } - return opts.config["format-" + format] || undefined; + return format; }; + const setFormat = (value?: string) => (format = value || "format"); + const element = document.createElement("span"); if (opts.interval && opts.update) { setInterval(opts.update, opts.interval); @@ -86,5 +88,6 @@ export const createLabel = (opts: LabelOpts) => { set, getIcon, getState, + setFormat, }; }; diff --git a/src/routes/waybar/configParser.ts b/src/routes/waybar/configParser.ts index 2d48426..6afab5c 100644 --- a/src/routes/waybar/configParser.ts +++ b/src/routes/waybar/configParser.ts @@ -1,284 +1,201 @@ import { parse } from "jsonc-parser"; -/** - * A general interface for icon mappings, where a key maps to a single icon string or an array of icon strings. - */ -interface IconMap { - [key: string]: string | string[]; -} - -/** - * Common configuration properties for many Waybar modules. - */ -interface BaseModule { - format?: string; - "format-icons"?: IconMap; - tooltip?: boolean; -} - -/** - * Defines the states and icons for a module. - */ -interface ModuleWithStates extends BaseModule { - states?: { - [state: string]: number; - }; - "format-critical"?: string; - "format-alt"?: string; -} - -/** - * Interface for the `sway/workspaces` module. - * Note: This module is commented out in the original JSON, but the interface is included for completeness. - */ -interface SwayWorkspacesModule extends BaseModule { - "disable-scroll"?: boolean; - "all-outputs"?: boolean; - "warp-on-scroll"?: boolean; - "format-icons"?: { - [key: string]: string; - }; -} - -/** - * Interface for the `keyboard-state` module. - */ -interface KeyboardStateModule extends BaseModule { - numlock?: boolean; - capslock?: boolean; - "format-icons"?: { - locked: string; - unlocked: string; - }; -} - -/** - * Interface for the `sway/mode` module. - */ -interface SwayModeModule { - format?: string; -} - -/** - * Interface for the `sway/scratchpad` module. - */ -interface SwayScratchpadModule extends BaseModule { - "show-empty"?: boolean; - "format-icons"?: string[]; - "tooltip-format"?: string; -} - -/** - * Interface for the `mpd` module. - */ -interface MpdModule extends BaseModule { - "format-disconnected"?: string; - "format-stopped"?: string; - "unknown-tag"?: string; - interval?: number; - "consume-icons"?: { - on: string; - }; - "random-icons"?: { - on: string; - off: string; - }; - "repeat-icons"?: { - on: string; - }; - "single-icons"?: { - on: string; - }; - "state-icons"?: { - paused: string; - playing: string; - }; - "tooltip-format"?: string; - "tooltip-format-disconnected"?: string; -} - -/** - * Interface for the `idle_inhibitor` module. - */ -interface IdleInhibitorModule extends BaseModule { - "format-icons"?: { - activated: string; - deactivated: string; - }; -} - -/** - * Interface for the `tray` module. - */ -interface TrayModule { - "icon-size"?: number; - spacing?: number; - icons?: { - [appName: string]: string; - }; -} - -/** - * Interface for the `clock` module. - */ -interface ClockModule { - timezone?: string; - "tooltip-format"?: string; - "format-alt"?: string; -} - -/** - * Interface for the `cpu` module. - */ -interface CpuModule extends BaseModule { - tooltip?: boolean; -} - -/** - * Interface for the `memory` module. - */ -interface MemoryModule extends BaseModule {} - -/** - * Interface for the `temperature` module. - */ -interface TemperatureModule extends ModuleWithStates { - "thermal-zone"?: number; - "hwmon-path"?: string; - "critical-threshold"?: number; - "format-icons"?: string[]; -} - -/** - * Interface for the `backlight` module. - */ -interface BacklightModule extends BaseModule { - device?: string; - "format-icons"?: string[]; -} - -/** - * Interface for the `battery` module. - */ -interface BatteryModule extends ModuleWithStates { - bat?: string; // Used for battery#bat2 - "format-full"?: string; - "format-charging"?: string; - "format-plugged"?: string; - "format-good"?: string; - "format-icons"?: string[]; -} - -/** - * Interface for the `power-profiles-daemon` module. - */ -interface PowerProfilesDaemonModule extends BaseModule { - tooltip?: boolean; - "tooltip-format"?: string; - "format-icons"?: { - default: string; - performance: string; - balanced: string; - "power-saver": string; - }; -} - -/** - * Interface for the `network` module. - */ -interface NetworkModule { - interface?: string; - "format-wifi"?: string; - "format-ethernet"?: string; - "tooltip-format"?: string; - "format-linked"?: string; - "format-disconnected"?: string; - "format-alt"?: string; -} - -/** - * Interface for the `pulseaudio` module. - */ -interface PulseaudioModule extends BaseModule { - "scroll-step"?: number; - "format-bluetooth"?: string; - "format-bluetooth-muted"?: string; - "format-muted"?: string; - "format-source"?: string; - "format-source-muted"?: string; - "format-icons"?: { - headphone: string; - "hands-free": string; - headset: string; - phone: string; - portable: string; - car: string; - default: string[]; - }; - "on-click"?: string; -} - -/** - * Interface for the `custom/media` module. - */ -interface CustomMediaModule extends BaseModule { - "return-type"?: "json" | "text"; - "max-length"?: number; - "format-icons"?: { - [key: string]: string; - }; - escape?: boolean; - exec?: string; -} - -/** - * Interface for the `custom/power` module. - */ -interface CustomPowerModule extends BaseModule { - menu?: string; - "menu-file"?: string; - "menu-actions"?: { - shutdown: string; - reboot: string; - suspend: string; - hibernate: string; - }; -} - -/** - * The main interface for the entire Waybar configuration file. - * It combines the main settings with a generic index signature for module configurations. - */ export interface WaybarConfig { - layer?: "top" | "bottom" | "overlay"; - position?: "top" | "bottom" | "left" | "right"; - height?: number; - width?: number; - spacing?: number; - "modules-left"?: string[]; - "modules-center"?: string[]; - "modules-right"?: string[]; + height: number; + spacing: number; + "modules-left": string[]; + "modules-center": string[]; + "modules-right": string[]; + "keyboard-state": KeyboardState; + "sway/mode": Memory; + "sway/scratchpad": SwayScratchpad; + mpd: Mpd; + idle_inhibitor: IdleInhibitor; + tray: Tray; + clock: Clock; + cpu: CPU; + memory: Memory; + temperature: Temperature; + backlight: Backlight; + battery: Battery; + "battery#bat2": BatteryBat2; + "power-profiles-daemon": PowerProfilesDaemon; + network: Network; + pulseaudio: Pulseaudio; + "custom/media": CustomMedia; + "custom/power": CustomPower; +} +interface Backlight { + format: string; + "format-icons": string[]; +} +interface Battery { + states: States; + format: string; + "format-full": string; + "format-charging": string; + "format-plugged": string; + "format-alt": string; + "format-icons": string[]; + [key: string]: any; // Allow additional properties +} +interface States { + warning: number; + critical: number; + [key: string]: number; // Allow additional properties +} +interface BatteryBat2 { + bat: string; +} +interface Clock { + "tooltip-format": string; + "format-alt": string; +} +interface CPU { + format: string; + tooltip: boolean; +} +interface CustomMedia { + format: string; + "return-type": string; + "max-length": number; + "format-icons": CustomMediaFormatIcons; + escape: boolean; + exec: string; +} +interface CustomMediaFormatIcons { + spotify: string; + default: string; +} +interface CustomPower { + format: string; + tooltip: boolean; + menu: string; + "menu-file": string; + "menu-actions": MenuActions; +} +interface MenuActions { + shutdown: string; + reboot: string; + suspend: string; + hibernate: string; +} - // Module-specific configurations - "sway/workspaces"?: SwayWorkspacesModule; - "sway/mode"?: SwayModeModule; - "sway/scratchpad"?: SwayScratchpadModule; - "keyboard-state"?: KeyboardStateModule; - mpd?: MpdModule; - idle_inhibitor?: IdleInhibitorModule; - tray?: TrayModule; - clock?: ClockModule; - cpu?: CpuModule; - memory?: MemoryModule; - temperature?: TemperatureModule; - backlight?: BacklightModule; - battery?: BatteryModule; - "battery#bat2"?: BatteryModule; - "power-profiles-daemon"?: PowerProfilesDaemonModule; - network?: NetworkModule; - pulseaudio?: PulseaudioModule; - "custom/media"?: CustomMediaModule; - "custom/power"?: CustomPowerModule; +interface IdleInhibitor { + format: string; + "format-icons": IdleInhibitorFormatIcons; +} + +interface IdleInhibitorFormatIcons { + activated: string; + deactivated: string; +} + +interface KeyboardState { + numlock: boolean; + capslock: boolean; + format: string; + "format-icons": KeyboardStateFormatIcons; +} + +interface KeyboardStateFormatIcons { + locked: string; + unlocked: string; +} + +interface Memory { + format: string; +} + +interface Mpd { + format: string; + "format-disconnected": string; + "format-stopped": string; + "unknown-tag": string; + interval: number; + "consume-icons": Icons; + "random-icons": RandomIcons; + "repeat-icons": Icons; + "single-icons": Icons; + "state-icons": StateIcons; + "tooltip-format": string; + "tooltip-format-disconnected": string; +} + +interface Icons { + on: string; +} + +interface RandomIcons { + off: string; + on: string; +} + +interface StateIcons { + paused: string; + playing: string; +} + +interface Network { + "format-wifi": string; + "format-ethernet": string; + "tooltip-format": string; + "format-linked": string; + "format-disconnected": string; + "format-alt": string; +} + +interface PowerProfilesDaemon { + format: string; + "tooltip-format": string; + tooltip: boolean; + "format-icons": PowerProfilesDaemonFormatIcons; +} + +interface PowerProfilesDaemonFormatIcons { + default: string; + performance: string; + balanced: string; + "power-saver": string; +} + +interface Pulseaudio { + format: string; + "format-bluetooth": string; + "format-bluetooth-muted": string; + "format-muted": string; + "format-source": string; + "format-source-muted": string; + "format-icons": PulseaudioFormatIcons; + "on-click": string; +} + +interface PulseaudioFormatIcons { + headphone: string; + "hands-free": string; + headset: string; + phone: string; + portable: string; + car: string; + default: string[]; +} + +interface SwayScratchpad { + format: string; + "show-empty": boolean; + "format-icons": string[]; + tooltip: boolean; + "tooltip-format": string; +} + +interface Temperature { + "critical-threshold": number; + format: string; + "format-icons": string[]; +} + +interface Tray { + spacing: number; } export const parseConfig = async () => { diff --git a/src/routes/waybar/modules/battery.ts b/src/routes/waybar/modules/battery.ts index fc768f9..73e3bb0 100644 --- a/src/routes/waybar/modules/battery.ts +++ b/src/routes/waybar/modules/battery.ts @@ -2,6 +2,8 @@ import type { WaybarConfig } from "../configParser"; import type { Module } from "../createModule"; import { createLabel } from "../Label"; +type Status = "Unknown" | "Charging" | "Discharging" | "Plugged" | "Full"; + export const createBatteryModule = ( module: Module, config: WaybarConfig["battery"] @@ -15,8 +17,8 @@ export const createBatteryModule = ( module.element.appendChild(label.element); - const getState = (battery: {level: number, charging: boolean}) => { - let status = "Unknown"; + const getState = (battery: { level: number; charging: boolean }) => { + let status: Status = "Unknown"; if (battery.charging && battery.level < 1) { status = "Charging"; @@ -26,34 +28,47 @@ export const createBatteryModule = ( } if (battery.charging && battery.level === 1) { - status = "Plugged" + status = "Plugged"; } if (!battery.charging && battery.level < 1) { - status = "Discharging" + status = "Discharging"; } return status; - } + }; - let lastStatus = "Unknown" + let lastStatus = "Unknown"; const update = async () => { // const battery = await navigator.getBattery(); const battery = { - level: Math.random(), - charging: Math.random() > 0.5, + // level: Math.random(), + // charging: Math.random() > 0.5, + level: 0.1, + charging: true, }; const batteryPercent = Math.round(battery.level * 100); - const status = getState(battery); - module.element.classList.remove(lastStatus.toLowerCase()); - module.element.classList.add(status.toLowerCase()) + module.element.classList.add(status.toLowerCase()); lastStatus = status; module.element.title = status; + const state = label.getState(batteryPercent, true); - console.log(state) + + if (config) { + const _status = status.toLowerCase(); + let format = ""; + if (state && config["format-" + _status + "-" + state]) { + format = config["format-" + _status + "-" + state]; + } else if (config["format-" + _status]) { + format = config["format-" + _status]; + } else if (state && config["format-" + state]) { + format = config["format-" + state]; + } + label.setFormat(format); + } label.set({ capacity: batteryPercent, diff --git a/src/routes/waybar/modules/clock.ts b/src/routes/waybar/modules/clock.ts index 40f3af3..c3dc08f 100644 --- a/src/routes/waybar/modules/clock.ts +++ b/src/routes/waybar/modules/clock.ts @@ -1,6 +1,10 @@ +import type { WaybarConfig } from "../configParser"; import type { Module } from "../createModule"; -export const createClockModule = (module: Module) => { +export const createClockModule = ( + module: Module, + config: WaybarConfig["clock"] +) => { const update = () => { const date = new Date();