Refactor Polling Mechanism: Implement Class-Based Poller with Start/Stop Control (#528)
* custom module updates to class based. * Finish poller logic. * Use composition for pollers * Rename poller * Handle recorder polling. * Fix quotes in bash command * Remove logs
This commit is contained in:
@@ -1,77 +0,0 @@
|
||||
import GLib from 'gi://GLib?version=2.0';
|
||||
import { GenericFunction } from 'lib/types/customModules/generic';
|
||||
import { Bind } from 'lib/types/variable';
|
||||
import { Variable as VariableType } from 'types/variable';
|
||||
|
||||
/**
|
||||
* @param {VariableType<T>} targetVariable - The Variable to update with the function's result.
|
||||
* @param {Array<Bind>} trackers - Array of trackers to watch.
|
||||
* @param {Bind} pollingInterval - The polling interval in milliseconds.
|
||||
* @param {GenericFunction<T, P>} someFunc - The function to execute at each interval, which updates the Variable.
|
||||
* @param {...P} params - Parameters to pass to someFunc.
|
||||
*/
|
||||
export const pollVariable = <T, P extends unknown[], F extends GenericFunction<T, P>>(
|
||||
targetVariable: VariableType<T>,
|
||||
trackers: Array<Bind>,
|
||||
pollingInterval: Bind,
|
||||
someFunc: F,
|
||||
...params: P
|
||||
): void => {
|
||||
let intervalInstance: number | null = null;
|
||||
|
||||
const intervalFn = (pollIntrvl: number): void => {
|
||||
if (intervalInstance !== null) {
|
||||
GLib.source_remove(intervalInstance);
|
||||
}
|
||||
|
||||
intervalInstance = Utils.interval(pollIntrvl, () => {
|
||||
targetVariable.value = someFunc(...params);
|
||||
});
|
||||
};
|
||||
|
||||
Utils.merge([pollingInterval, ...trackers], (pollIntrvl: number) => {
|
||||
intervalFn(pollIntrvl);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {VariableType<T>} targetVariable - The Variable to update with the result of the command.
|
||||
* @param {Array<Bind>} trackers - Array of trackers to watch.
|
||||
* @param {Bind} pollingInterval - The polling interval in milliseconds.
|
||||
* @param {string} someCommand - The bash command to execute.
|
||||
* @param {GenericFunction<T, [unknown, ...P]>} someFunc - The function to execute after processing the command result;
|
||||
* with the first argument being the result of the command execution.
|
||||
* @param {...P} params - Additional parameters to pass to someFunc.
|
||||
*/
|
||||
export const pollVariableBash = <T, P extends unknown[], F extends GenericFunction<T, [string, ...P]>>(
|
||||
targetVariable: VariableType<T>,
|
||||
trackers: Array<Bind>,
|
||||
pollingInterval: Bind,
|
||||
someCommand: string,
|
||||
someFunc: F,
|
||||
...params: P
|
||||
): void => {
|
||||
let intervalInstance: number | null = null;
|
||||
|
||||
const intervalFn = (pollIntrvl: number): void => {
|
||||
if (intervalInstance !== null) {
|
||||
GLib.source_remove(intervalInstance);
|
||||
}
|
||||
|
||||
intervalInstance = Utils.interval(pollIntrvl, () => {
|
||||
Utils.execAsync(`bash -c "${someCommand}"`)
|
||||
.then((res: string) => {
|
||||
try {
|
||||
targetVariable.value = someFunc(res, ...params);
|
||||
} catch (error) {
|
||||
console.warn(`An error occurred when running interval bash function: ${error}`);
|
||||
}
|
||||
})
|
||||
.catch((err) => console.error(`Error running command "${someCommand}": ${err}`));
|
||||
});
|
||||
};
|
||||
|
||||
Utils.merge([pollingInterval, ...trackers], (pollIntrvl: number) => {
|
||||
intervalFn(pollIntrvl);
|
||||
});
|
||||
};
|
||||
@@ -1,16 +1,14 @@
|
||||
import options from 'options';
|
||||
|
||||
// Module initializer
|
||||
import { module } from '../module';
|
||||
|
||||
import options from 'options';
|
||||
import Button from 'types/widgets/button';
|
||||
|
||||
// Utility Methods
|
||||
import { inputHandler } from 'customModules/utils';
|
||||
import { computeCPU } from './computeCPU';
|
||||
import { pollVariable } from 'customModules/PollVar';
|
||||
import { BarBoxChild } from 'lib/types/bar';
|
||||
import { Attribute, Child } from 'lib/types/widget';
|
||||
import { FunctionPoller } from 'lib/poller/FunctionPoller';
|
||||
|
||||
// All the user configurable options for the cpu module that are needed
|
||||
const { label, round, leftClick, rightClick, middleClick, scrollUp, scrollDown, pollingInterval, icon } =
|
||||
@@ -18,7 +16,8 @@ const { label, round, leftClick, rightClick, middleClick, scrollUp, scrollDown,
|
||||
|
||||
export const cpuUsage = Variable(0);
|
||||
|
||||
pollVariable(
|
||||
// Instantiate the Poller class for CPU usage polling
|
||||
const cpuPoller = new FunctionPoller<number, []>(
|
||||
// Variable to poll and update with the result of the function passed in
|
||||
cpuUsage,
|
||||
// Variables that should trigger the polling function to update when they change
|
||||
@@ -29,6 +28,8 @@ pollVariable(
|
||||
computeCPU,
|
||||
);
|
||||
|
||||
cpuPoller.initialize('cpu');
|
||||
|
||||
export const Cpu = (): BarBoxChild => {
|
||||
const renderLabel = (cpuUsg: number, rnd: boolean): string => {
|
||||
return rnd ? `${Math.round(cpuUsg)}%` : `${cpuUsg.toFixed(2)}%`;
|
||||
|
||||
@@ -2,14 +2,14 @@ import GLib from 'gi://GLib?version=2.0';
|
||||
import { convertCelsiusToFahrenheit } from 'globals/weather';
|
||||
import { UnitType } from 'lib/types/weather';
|
||||
import options from 'options';
|
||||
import { Variable } from 'types/variable';
|
||||
import { Variable as VariableType } from 'types/variable';
|
||||
const { sensor } = options.bar.customModules.cpuTemp;
|
||||
|
||||
/**
|
||||
* Retrieves the current CPU temperature.
|
||||
* @returns CPU temperature in degrees Celsius
|
||||
*/
|
||||
export const getCPUTemperature = (round: Variable<boolean>, unit: Variable<UnitType>): number => {
|
||||
export const getCPUTemperature = (round: VariableType<boolean>, unit: VariableType<UnitType>): number => {
|
||||
try {
|
||||
if (sensor.value.length === 0) {
|
||||
return 0;
|
||||
@@ -23,13 +23,13 @@ export const getCPUTemperature = (round: Variable<boolean>, unit: Variable<UnitT
|
||||
return 0;
|
||||
}
|
||||
|
||||
let decimalTemp = parseInt(tempInfo) / 1000;
|
||||
let decimalTemp = parseInt(tempInfo, 10) / 1000;
|
||||
|
||||
if (unit.value === 'imperial') {
|
||||
decimalTemp = convertCelsiusToFahrenheit(decimalTemp);
|
||||
}
|
||||
|
||||
return round ? Math.round(decimalTemp) : parseFloat(decimalTemp.toFixed(2));
|
||||
return round.value ? Math.round(decimalTemp) : parseFloat(decimalTemp.toFixed(2));
|
||||
} catch (error) {
|
||||
console.error('Error calculating CPU Temp:', error);
|
||||
return 0;
|
||||
|
||||
@@ -8,9 +8,11 @@ import Button from 'types/widgets/button';
|
||||
// Utility Methods
|
||||
import { inputHandler } from 'customModules/utils';
|
||||
import { getCPUTemperature } from './helpers';
|
||||
import { pollVariable } from 'customModules/PollVar';
|
||||
import { BarBoxChild } from 'lib/types/bar';
|
||||
import { Attribute, Child } from 'lib/types/widget';
|
||||
import { FunctionPoller } from 'lib/poller/FunctionPoller';
|
||||
import { Variable as VariableType } from 'types/variable';
|
||||
import { UnitType } from 'lib/types/weather';
|
||||
|
||||
// All the user configurable options for the cpu module that are needed
|
||||
const {
|
||||
@@ -30,7 +32,7 @@ const {
|
||||
|
||||
export const cpuTemp = Variable(0);
|
||||
|
||||
pollVariable(
|
||||
const cpuTempPoller = new FunctionPoller<number, [VariableType<boolean>, VariableType<UnitType>]>(
|
||||
// Variable to poll and update with the result of the function passed in
|
||||
cpuTemp,
|
||||
// Variables that should trigger the polling function to update when they change
|
||||
@@ -43,6 +45,8 @@ pollVariable(
|
||||
unit,
|
||||
);
|
||||
|
||||
cpuTempPoller.initialize('cputemp');
|
||||
|
||||
export const CpuTemp = (): BarBoxChild => {
|
||||
const cpuTempModule = module({
|
||||
textIcon: icon.bind('value'),
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Variable as TVariable } from 'types/variable';
|
||||
|
||||
export const isActiveCommand = `bash -c "pgrep -x "hypridle" > /dev/null && echo "yes" || echo "no""`;
|
||||
export const isActiveCommand = `bash -c "pgrep -x 'hypridle' &>/dev/null && echo 'yes' || echo 'no'"`;
|
||||
|
||||
export const isActive = Variable(false);
|
||||
|
||||
|
||||
@@ -5,8 +5,8 @@ import { inputHandler, throttleInput } from 'customModules/utils';
|
||||
import Button from 'types/widgets/button';
|
||||
import { Attribute, Child } from 'lib/types/widget';
|
||||
import { BarBoxChild } from 'lib/types/bar';
|
||||
import { pollVariable } from 'customModules/PollVar';
|
||||
import { checkIdleStatus, isActive, toggleIdle } from './helpers';
|
||||
import { FunctionPoller } from 'lib/poller/FunctionPoller';
|
||||
|
||||
const { label, pollingInterval, onIcon, offIcon, onLabel, offLabel, rightClick, middleClick, scrollUp, scrollDown } =
|
||||
options.bar.customModules.hypridle;
|
||||
@@ -15,7 +15,14 @@ const dummyVar = Variable(undefined);
|
||||
|
||||
checkIdleStatus();
|
||||
|
||||
pollVariable(dummyVar, [], pollingInterval.bind('value'), checkIdleStatus);
|
||||
const idleStatusPoller = new FunctionPoller<undefined, []>(
|
||||
dummyVar,
|
||||
[],
|
||||
pollingInterval.bind('value'),
|
||||
checkIdleStatus,
|
||||
);
|
||||
|
||||
idleStatusPoller.initialize('hypridle');
|
||||
|
||||
const throttledToggleIdle = throttleInput(() => toggleIdle(isActive), 1000);
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ import { Variable as TVariable } from 'types/variable';
|
||||
|
||||
const { temperature } = options.bar.customModules.hyprsunset;
|
||||
|
||||
export const isActiveCommand = `bash -c "pgrep -x "hyprsunset" > /dev/null && echo "yes" || echo "no""`;
|
||||
export const isActiveCommand = `bash -c "pgrep -x 'hyprsunset' > /dev/null && echo 'yes' || echo 'no'"`;
|
||||
|
||||
export const isActive = Variable(false);
|
||||
|
||||
|
||||
@@ -5,8 +5,8 @@ import { inputHandler, throttleInput } from 'customModules/utils';
|
||||
import Button from 'types/widgets/button';
|
||||
import { Attribute, Child } from 'lib/types/widget';
|
||||
import { BarBoxChild } from 'lib/types/bar';
|
||||
import { pollVariable } from 'customModules/PollVar';
|
||||
import { checkSunsetStatus, isActive, toggleSunset } from './helpers';
|
||||
import { FunctionPoller } from 'lib/poller/FunctionPoller';
|
||||
|
||||
const {
|
||||
label,
|
||||
@@ -26,7 +26,9 @@ const dummyVar = Variable(undefined);
|
||||
|
||||
checkSunsetStatus();
|
||||
|
||||
pollVariable(dummyVar, [], pollingInterval.bind('value'), checkSunsetStatus);
|
||||
const sunsetPoller = new FunctionPoller<undefined, []>(dummyVar, [], pollingInterval.bind('value'), checkSunsetStatus);
|
||||
|
||||
sunsetPoller.initialize('hyprsunset');
|
||||
|
||||
const throttledToggleSunset = throttleInput(() => toggleSunset(isActive), 1000);
|
||||
|
||||
|
||||
@@ -3,13 +3,14 @@ import options from 'options';
|
||||
import { module } from '../module';
|
||||
import { inputHandler } from 'customModules/utils';
|
||||
import { computeNetwork } from './computeNetwork';
|
||||
import { BarBoxChild, NetstatLabelType } from 'lib/types/bar';
|
||||
import { BarBoxChild, NetstatLabelType, RateUnit } from 'lib/types/bar';
|
||||
import Button from 'types/widgets/button';
|
||||
import { NetworkResourceData } from 'lib/types/customModules/network';
|
||||
import { NETWORK_LABEL_TYPES } from 'lib/types/defaults/bar';
|
||||
import { GET_DEFAULT_NETSTAT_DATA } from 'lib/types/defaults/netstat';
|
||||
import { pollVariable } from 'customModules/PollVar';
|
||||
import { Attribute, Child } from 'lib/types/widget';
|
||||
import { FunctionPoller } from 'lib/poller/FunctionPoller';
|
||||
import { Variable as TVariable } from 'types/variable';
|
||||
|
||||
const {
|
||||
label,
|
||||
@@ -27,7 +28,10 @@ const {
|
||||
|
||||
export const networkUsage = Variable<NetworkResourceData>(GET_DEFAULT_NETSTAT_DATA(rateUnit.value));
|
||||
|
||||
pollVariable(
|
||||
const netstatPoller = new FunctionPoller<
|
||||
NetworkResourceData,
|
||||
[round: TVariable<boolean>, interfaceNameVar: TVariable<string>, dataType: TVariable<RateUnit>]
|
||||
>(
|
||||
// Variable to poll and update with the result of the function passed in
|
||||
networkUsage,
|
||||
// Variables that should trigger the polling function to update when they change
|
||||
@@ -48,6 +52,8 @@ pollVariable(
|
||||
rateUnit,
|
||||
);
|
||||
|
||||
netstatPoller.initialize('netstat');
|
||||
|
||||
export const Netstat = (): BarBoxChild => {
|
||||
const renderNetworkLabel = (lblType: NetstatLabelType, network: NetworkResourceData): string => {
|
||||
switch (lblType) {
|
||||
|
||||
@@ -16,8 +16,9 @@ import { BarBoxChild, ResourceLabelType } from 'lib/types/bar';
|
||||
|
||||
// Global Constants
|
||||
import { LABEL_TYPES } from 'lib/types/defaults/bar';
|
||||
import { pollVariable } from 'customModules/PollVar';
|
||||
import { Attribute, Child } from 'lib/types/widget';
|
||||
import { FunctionPoller } from 'lib/poller/FunctionPoller';
|
||||
import { Variable as TVariable } from 'types/variable';
|
||||
|
||||
// All the user configurable options for the ram module that are needed
|
||||
const { label, labelType, round, leftClick, rightClick, middleClick, pollingInterval, icon } =
|
||||
@@ -26,7 +27,15 @@ const { label, labelType, round, leftClick, rightClick, middleClick, pollingInte
|
||||
const defaultRamData: GenericResourceData = { total: 0, used: 0, percentage: 0, free: 0 };
|
||||
const ramUsage = Variable<GenericResourceData>(defaultRamData);
|
||||
|
||||
pollVariable(ramUsage, [round.bind('value')], pollingInterval.bind('value'), calculateRamUsage, round);
|
||||
const ramPoller = new FunctionPoller<GenericResourceData, [TVariable<boolean>]>(
|
||||
ramUsage,
|
||||
[round.bind('value')],
|
||||
pollingInterval.bind('value'),
|
||||
calculateRamUsage,
|
||||
round,
|
||||
);
|
||||
|
||||
ramPoller.initialize('ram');
|
||||
|
||||
export const Ram = (): BarBoxChild => {
|
||||
const ramModule = module({
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import options from 'options';
|
||||
import { module } from '../module';
|
||||
|
||||
import { formatTooltip, inputHandler, renderResourceLabel } from 'customModules/utils';
|
||||
import { computeStorage } from './computeStorage';
|
||||
import { BarBoxChild, ResourceLabelType } from 'lib/types/bar';
|
||||
import { GenericResourceData } from 'lib/types/customModules/generic';
|
||||
import Button from 'types/widgets/button';
|
||||
import { LABEL_TYPES } from 'lib/types/defaults/bar';
|
||||
import { pollVariable } from 'customModules/PollVar';
|
||||
import { Attribute, Child } from 'lib/types/widget';
|
||||
import { FunctionPoller } from 'lib/poller/FunctionPoller';
|
||||
import { Variable as TVariable } from 'types/variable';
|
||||
|
||||
const { label, labelType, icon, round, leftClick, rightClick, middleClick, pollingInterval } =
|
||||
options.bar.customModules.storage;
|
||||
@@ -17,7 +17,15 @@ const defaultStorageData = { total: 0, used: 0, percentage: 0, free: 0 };
|
||||
|
||||
const storageUsage = Variable<GenericResourceData>(defaultStorageData);
|
||||
|
||||
pollVariable(storageUsage, [round.bind('value')], pollingInterval.bind('value'), computeStorage, round);
|
||||
const storagePoller = new FunctionPoller<GenericResourceData, [TVariable<boolean>]>(
|
||||
storageUsage,
|
||||
[round.bind('value')],
|
||||
pollingInterval.bind('value'),
|
||||
computeStorage,
|
||||
round,
|
||||
);
|
||||
|
||||
storagePoller.initialize('storage');
|
||||
|
||||
export const Storage = (): BarBoxChild => {
|
||||
const storageModule = module({
|
||||
|
||||
@@ -3,10 +3,10 @@ import { module } from '../module';
|
||||
|
||||
import { inputHandler } from 'customModules/utils';
|
||||
import Button from 'types/widgets/button';
|
||||
import { Variable as VariableType } from 'types/variable';
|
||||
import { pollVariableBash } from 'customModules/PollVar';
|
||||
import { Variable as TVariable } from 'types/variable';
|
||||
import { Attribute, Child } from 'lib/types/widget';
|
||||
import { BarBoxChild } from 'lib/types/bar';
|
||||
import { BashPoller } from 'lib/poller/BashPoller';
|
||||
|
||||
const {
|
||||
updateCommand,
|
||||
@@ -21,7 +21,7 @@ const {
|
||||
scrollDown,
|
||||
} = options.bar.customModules.updates;
|
||||
|
||||
const pendingUpdates: VariableType<string> = Variable('0');
|
||||
const pendingUpdates: TVariable<string> = Variable('0');
|
||||
const postInputUpdater = Variable(true);
|
||||
|
||||
const processUpdateCount = (updateCount: string): string => {
|
||||
@@ -29,7 +29,7 @@ const processUpdateCount = (updateCount: string): string => {
|
||||
return `${updateCount.padStart(2, '0')}`;
|
||||
};
|
||||
|
||||
pollVariableBash(
|
||||
const updatesPoller = new BashPoller<string, []>(
|
||||
pendingUpdates,
|
||||
[padZero.bind('value'), postInputUpdater.bind('value')],
|
||||
pollingInterval.bind('value'),
|
||||
@@ -37,6 +37,8 @@ pollVariableBash(
|
||||
processUpdateCount,
|
||||
);
|
||||
|
||||
updatesPoller.initialize('updates');
|
||||
|
||||
export const Updates = (): BarBoxChild => {
|
||||
const updatesModule = module({
|
||||
textIcon: icon.bind('value'),
|
||||
|
||||
Reference in New Issue
Block a user