const { exec, execAsync } = Utils; const KBD = 'tpacpi::kbd_backlight'; const INTERVAL = 500; const SCREEN_ICONS = { 90: 'display-brightness-high-symbolic', 70: 'display-brightness-medium-symbolic', 20: 'display-brightness-low-symbolic', 5: 'display-brightness-off-symbolic', }; class Brightness extends Service { static { Service.register(this, { screen: ['float'], kbd: ['float'], caps: ['int'], }, { 'screen-icon': ['string', 'rw'], 'caps-icon': ['string', 'rw'], }); } #kbd = 0; #kbdMax = 0; #screen = 0; #screenIcon = 'display-brightness-symbolic'; #capsName = 'input0::capslock'; #caps = 0; #capsIcon = 'caps-lock-symbolic'; get capsName() { return this.#capsName; } set capsName(value: string) { this.#capsName = value; } get kbd() { return this.#kbd; } get screen() { return this.#screen; } get screenIcon() { return this.#screenIcon; } get caps() { return this.#caps; } get capsIcon() { return this.#capsIcon; } set kbd(value) { if (value < 0 || value > this.#kbdMax) { return; } execAsync(`brightnessctl -d ${KBD} s ${value} -q`) .then(() => { this.#kbd = value; this.emit('kbd', this.#kbd); }) .catch(console.error); } set screen(percent) { if (percent < 0) { percent = 0; } if (percent > 1) { percent = 1; } execAsync(`brightnessctl s ${percent * 100}% -q`) .then(() => { this.#screen = percent; this.#getScreenIcon(); this.emit('screen', this.#screen); }) .catch(console.error); } constructor() { super(); try { this.#monitorKbdState(); this.#kbdMax = Number(exec(`brightnessctl -d ${KBD} m`)); this.#caps = Number(exec(`bash -c brightnessctl -d ${this.#capsName} g`)); this.#screen = Number(exec('brightnessctl g')) / Number(exec('brightnessctl m')); } catch (error) { console.error('missing dependancy: brightnessctl'); } } #getScreenIcon() { const brightness = this.#screen * 100; // eslint-disable-next-line for (const threshold of [4, 19, 69, 89]) { if (brightness > threshold + 1) { this.#screenIcon = SCREEN_ICONS[threshold + 1]; this.notify('screen-icon'); } } } fetchCapsState() { execAsync(`brightnessctl -d ${this.#capsName} g`) .then((out) => { this.#caps = Number(out); this.#capsIcon = this.#caps ? 'caps-lock-symbolic' : 'capslock-disabled-symbolic'; this.notify('caps-icon'); this.emit('caps', this.#caps); }) .catch(logError); } #monitorKbdState() { const interval = setInterval(() => { execAsync(`brightnessctl -d ${KBD} g`).then( (out) => { if (parseInt(out) !== this.#kbd) { this.#kbd = parseInt(out); this.emit('kbd', this.#kbd); return this.#kbd; } }, ).catch(() => { interval.destroy(); }); }, INTERVAL); } } const brightnessService = new Brightness(); export default brightnessService;