From 96e1d0f10a319767eea22f07e00623d27052e12b Mon Sep 17 00:00:00 2001 From: Matthias Kesler Date: Fri, 17 Jan 2025 12:41:32 +0100 Subject: [PATCH] update 'timerDuration' to contain an updating timestamp of how long it is running --- src/main.ts | 75 ++++++++++++++++++++++++++++++---------------------- src/utils.ts | 12 +++++++++ 2 files changed, 56 insertions(+), 31 deletions(-) create mode 100644 src/utils.ts diff --git a/src/main.ts b/src/main.ts index ddb0db4..7e17403 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,5 +1,5 @@ // toggltrack module -// Peter Daniel +// Peter Daniel, Matthias Kesler import { InstanceBase, runEntrypoint, InstanceStatus, SomeCompanionConfigField } from '@companion-module/base' import { GetConfigFields, type ModuleConfig } from './config.js' @@ -10,6 +10,7 @@ import UpgradeScripts from './upgrades.js' import { UpdateFeedbacks } from './feedbacks.js' import { Toggl, ITimeEntry, IWorkspaceProject } from 'toggl-track' import { togglGetWorkspaces } from './toggl-extend.js' +import { timecodeSince } from './utils.js' export class TogglTrack extends InstanceBase { config!: ModuleConfig // Setup in init() @@ -20,6 +21,7 @@ export class TogglTrack extends InstanceBase { workspaceName: string = '' // name of workspace projects?: { id: number; label: string }[] intervalId?: NodeJS.Timeout + currentTimerUpdaterIntervalId?: NodeJS.Timeout constructor(internal: unknown) { super(internal) @@ -34,6 +36,8 @@ export class TogglTrack extends InstanceBase { if (this.config.startTimerPoller) { this.stopTimeEntryPoller() } + + clearInterval(this.currentTimerUpdaterIntervalId) } async init(config: ModuleConfig): Promise { @@ -154,15 +158,42 @@ export class TogglTrack extends InstanceBase { clearInterval(this.intervalId) } - private setCurrentProject(projectID: number | undefined): void { - let pName: string | undefined - if (typeof projectID === 'number') { - pName = this.projects!.find((v) => v.id == projectID)?.label + /** + * Set variables to this time entry + * @param entry running entry or undefined + */ + private setCurrentlyRunningTimeEntry(entry: ITimeEntry | undefined): void { + if (entry) { + this.setVariableValues({ + timerId: entry.id, + timerDescription: entry.description, + timerDuration: timecodeSince(new Date(entry.start)), + timerProject: this.projects!.find((v) => v.id == entry?.project_id)?.label, + timerProjectID: entry.project_id, + }) + + // in case there is on update thread running clear it + clearInterval(this.currentTimerUpdaterIntervalId) + + // Update timerDuration once per second + this.currentTimerUpdaterIntervalId = setInterval(() => { + // this harms the linter (handle unawaited promise in an non-async context) + void (async () => { + this.setVariableValues({ + timerDuration: timecodeSince(new Date(entry.start)), + }) + })() + }, 1000) // update every second + } else { + clearInterval(this.currentTimerUpdaterIntervalId) + this.setVariableValues({ + timerId: undefined, + timerDescription: undefined, + timerDuration: undefined, + timerProject: undefined, + timerProjectID: undefined, + }) } - this.setVariableValues({ - timerProject: pName, - timerProjectID: projectID, - }) this.checkFeedbacks('ProjectRunningState') } @@ -179,22 +210,12 @@ export class TogglTrack extends InstanceBase { if (entry) { this.log('info', 'Current timer id: ' + entry.id) - this.setVariableValues({ - timerId: entry.id, - timerDescription: entry.description, - timerDuration: entry.duration, - }) - this.setCurrentProject(entry.project_id) + this.setCurrentlyRunningTimeEntry(entry) return entry.id } else { this.log('info', 'No current timer') - this.setVariableValues({ - timerId: undefined, - timerDescription: undefined, - timerDuration: undefined, - }) - this.setCurrentProject(undefined) + this.setCurrentlyRunningTimeEntry(undefined) return null } } @@ -303,12 +324,7 @@ export class TogglTrack extends InstanceBase { project_id: project != 0 ? project : undefined, }) this.log('info', 'New timer started ' + newEntry.id + ' ' + newEntry.description) - this.setVariableValues({ - timerId: newEntry.id, - timerDescription: newEntry.description, - timerDuration: newEntry.duration, - }) - this.setCurrentProject(newEntry.project_id) + this.setCurrentlyRunningTimeEntry(newEntry) } else { this.log('info', 'A timer is already running ' + currentId + ' not starting a new one!') } @@ -328,13 +344,10 @@ export class TogglTrack extends InstanceBase { const updated: ITimeEntry = await this.toggl.timeEntry.stop(currentId, this.workspaceId) this.log('info', 'Stopped ' + updated.id + ', duration ' + updated.duration) + this.setCurrentlyRunningTimeEntry(undefined) this.setVariableValues({ - timerId: undefined, - timerDescription: undefined, - timerDuration: undefined, lastTimerDuration: updated.duration, }) - this.setCurrentProject(undefined) } else { this.log('warn', 'No running timer to stop or running timer id unknown') } diff --git a/src/utils.ts b/src/utils.ts new file mode 100644 index 0000000..11c2709 --- /dev/null +++ b/src/utils.ts @@ -0,0 +1,12 @@ +/** + * returns formatted timecode from date until now + * @param date start date + * @returns formatted string 0:00:00 - where hours and minutes are hidden if 0 + */ +export function timecodeSince(date: Date): string { + const dateObj = new Date(Date.now() - date.getTime()) + const hours = dateObj.getUTCHours() + const minutes = `0${dateObj.getUTCMinutes()}`.slice(-2) + const seconds = `0${dateObj.getSeconds()}`.slice(-2) + return (hours > 0 ? hours + ':' : '') + (hours > 0 || minutes !== '00' ? minutes + ':' : '') + seconds +}