From 9d45c91fd8ab561d6362c5839745a3057548c580 Mon Sep 17 00:00:00 2001 From: Leo Yao <45076643+leoccyao@users.noreply.github.com> Date: Tue, 2 Jan 2024 13:52:04 -0500 Subject: [PATCH 01/12] Remove duplicate status bar entry --- lib/toggl/TogglService.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/toggl/TogglService.ts b/lib/toggl/TogglService.ts index 142480b..ba7b7b1 100644 --- a/lib/toggl/TogglService.ts +++ b/lib/toggl/TogglService.ts @@ -77,7 +77,6 @@ export default class TogglService { constructor(plugin: MyPlugin) { this._plugin = plugin; this._statusBarItem = this._plugin.addStatusBarItem(); - this._statusBarItem = this._plugin.addStatusBarItem(); this._statusBarItem.setText("Connecting to Toggl..."); // Store a reference to the manager in a svelte store to avoid passing // of references around the component trees. From 276207fbff128c36c7de9bff5e7d5665f8c210d9 Mon Sep 17 00:00:00 2001 From: Leo Yao <45076643+leoccyao@users.noreply.github.com> Date: Tue, 2 Jan 2024 13:52:15 -0500 Subject: [PATCH 02/12] Expose status bar char limit option --- lib/ui/TogglSettingsTab.ts | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/lib/ui/TogglSettingsTab.ts b/lib/ui/TogglSettingsTab.ts index aa88738..fd36ee4 100644 --- a/lib/ui/TogglSettingsTab.ts +++ b/lib/ui/TogglSettingsTab.ts @@ -1,3 +1,4 @@ +import { DEFAULT_SETTINGS } from "lib/config/DefaultSettings"; import type MyPlugin from "main"; import { App, @@ -32,6 +33,7 @@ export default class TogglSettingsTab extends PluginSettingTab { this.addTestConnectionSetting(containerEl); this.addWorkspaceSetting(containerEl); this.addUpdateRealTimeSetting(containerEl); + this.addCharLimitStatusBarSetting(containerEl); } private addApiTokenSetting(containerEl: HTMLElement) { @@ -104,6 +106,26 @@ export default class TogglSettingsTab extends PluginSettingTab { }); } + private addCharLimitStatusBarSetting(containerEl: HTMLElement) { + new Setting(containerEl) + .setName("Status bar character limit") + .setDesc( + "Set a character limit for the time entry " + + "displayed in the status bar." + ) + .addText((text) => { + text.setPlaceholder(String(DEFAULT_SETTINGS.charLimitStatusBar)) + text.inputEl.type = "number" + text.setValue(String(this.plugin.settings.charLimitStatusBar)) + text.onChange(async (value) => { + this.plugin.settings.charLimitStatusBar = ( + value !== "" ? Number(value) : DEFAULT_SETTINGS.charLimitStatusBar + ); + await this.plugin.saveSettings(); + }); + }); + } + private async fetchWorkspaces() { // empty the dropdown's list const selectEl = this.workspaceDropdown.selectEl; From b8f4c8165c50966d855784e59a5f7cb698b50133 Mon Sep 17 00:00:00 2001 From: Leo Yao <45076643+leoccyao@users.noreply.github.com> Date: Tue, 2 Jan 2024 14:15:16 -0500 Subject: [PATCH 03/12] Split current timer and status bar intervals Allows for more frequent updating of status bar text without polling the Toggl API. So far, allows status bar status to update on the minute, instead of a few seconds later. --- lib/constants.ts | 5 +++++ lib/toggl/TogglService.ts | 17 +++++++++++++++-- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/lib/constants.ts b/lib/constants.ts index 6dc7020..6e66a32 100644 --- a/lib/constants.ts +++ b/lib/constants.ts @@ -3,6 +3,11 @@ */ export const ACTIVE_TIMER_POLLING_INTERVAL = 6000; +/** + * The interval in ms at which the status bar is updated + */ +export const STATUS_BAR_UPDATE_INTERVAL = 1000; + /** * The language string used for report code blocks. */ diff --git a/lib/toggl/TogglService.ts b/lib/toggl/TogglService.ts index ba7b7b1..a5a870f 100644 --- a/lib/toggl/TogglService.ts +++ b/lib/toggl/TogglService.ts @@ -1,4 +1,4 @@ -import { ACTIVE_TIMER_POLLING_INTERVAL } from "lib/constants"; +import { ACTIVE_TIMER_POLLING_INTERVAL, STATUS_BAR_UPDATE_INTERVAL } from "lib/constants"; import type { ClientId, EnrichedWithClient, @@ -71,6 +71,7 @@ export default class TogglService { private _statusBarItem: HTMLElement; private _currentTimerInterval: number = null; + private _statusBarInterval: number = null; private _currentTimeEntry: TimeEntry = null; private _ApiAvailable = ApiStatus.UNTESTED; @@ -90,6 +91,7 @@ export default class TogglService { */ public async setToken(token: string) { window.clearInterval(this._currentTimerInterval); + window.clearInterval(this._statusBarInterval); if (token != null && token != "") { try { this._apiManager = new TogglAPI(); @@ -107,6 +109,7 @@ export default class TogglService { // Fetch daily summary data and start polling for current timers. this.startTimerInterval(); + this.startStatusBarInterval(); this._apiManager .getDailySummary() .then((response) => setDailySummaryItems(response)); @@ -183,6 +186,17 @@ export default class TogglService { this._plugin.registerInterval(this._currentTimerInterval); } + /** + * Start updating the status bar periodically. + */ + private startStatusBarInterval() { + this.updateStatusBarText(); + this._statusBarInterval = window.setInterval(() => { + this.updateStatusBarText(); + }, STATUS_BAR_UPDATE_INTERVAL); + this._plugin.registerInterval(this._statusBarInterval); + } + private async updateCurrentTimer() { if (!this.isApiAvailable) { return; @@ -256,7 +270,6 @@ export default class TogglService { } this._currentTimeEntry = curr; - this.updateStatusBarText(); } /** From 923e6594d0c0deb19d1234d8b81a143f37deea15 Mon Sep 17 00:00:00 2001 From: Leo Yao <45076643+leoccyao@users.noreply.github.com> Date: Tue, 2 Jan 2024 15:03:20 -0500 Subject: [PATCH 04/12] Switch to moment-duration-format No change in functionality, but opens the door to custom format strings. --- lib/toggl/TogglService.ts | 7 +++++-- lib/util/millisecondsToTimeString.ts | 21 +++++++++++---------- package-lock.json | 11 +++++++++++ package.json | 1 + 4 files changed, 28 insertions(+), 12 deletions(-) diff --git a/lib/toggl/TogglService.ts b/lib/toggl/TogglService.ts index a5a870f..f9f53e6 100644 --- a/lib/toggl/TogglService.ts +++ b/lib/toggl/TogglService.ts @@ -30,6 +30,7 @@ import { import { apiStatusStore, togglService } from "lib/util/stores"; import type MyPlugin from "main"; import moment from "moment"; +import "moment-duration-format"; import { Notice } from "obsidian"; import { derived, get } from "svelte/store"; @@ -290,8 +291,10 @@ export default class TogglService { )}...`; } const duration = this.getTimerDuration(this._currentTimeEntry); - const minutes = Math.floor(duration / 60); - const time_string = `${minutes} minute${minutes != 1 ? "s" : ""}`; + const time_string = moment.duration(duration, 'seconds').format( + 'm [minute]', + { trim: false, trunc: true }, + ) timer_msg = `${title} (${time_string})`; } this._statusBarItem.setText(`Timer: ${timer_msg}`); diff --git a/lib/util/millisecondsToTimeString.ts b/lib/util/millisecondsToTimeString.ts index 74a3b16..09657aa 100644 --- a/lib/util/millisecondsToTimeString.ts +++ b/lib/util/millisecondsToTimeString.ts @@ -1,15 +1,16 @@ -export default function millisecondsToTimeString(ms: number): string { - const sec = Math.round((ms / 1000) % 60); - const min = Math.floor((ms / 1000 / 60) % 60); - const hr = Math.floor(ms / 1000 / 60 / 60); +import moment from "moment"; +import "moment-duration-format"; - return `${hr}:${min < 10 ? "0" + min : min}:${sec < 10 ? "0" + sec : sec}`; +export default function millisecondsToTimeString(ms: number): string { + return moment.duration(ms).format( + 'h:mm:ss', + { trim: false, trunc: true }, + ) } export function secondsToTimeString(seconds: number): string { - const sec = Math.round(seconds % 60); - const min = Math.floor((seconds / 60) % 60); - const hr = Math.floor(seconds / 60 / 60); - - return `${hr}:${min < 10 ? "0" + min : min}:${sec < 10 ? "0" + sec : sec}`; + return moment.duration(seconds, 'seconds').format( + 'h:mm:ss', + { trim: false, trunc: true }, + ) } diff --git a/package-lock.json b/package-lock.json index da3d6c0..89d0715 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,6 +11,7 @@ "dependencies": { "d3": "^7.2.1", "moment": "^2.29.4", + "moment-duration-format": "^2.3.2", "supports-color": "^9.2.2", "svelte-select": "^4.4.3", "toggl-client": "github:mcndt/toggl-client#b8d88805fb" @@ -5505,6 +5506,11 @@ "node": "*" } }, + "node_modules/moment-duration-format": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/moment-duration-format/-/moment-duration-format-2.3.2.tgz", + "integrity": "sha512-cBMXjSW+fjOb4tyaVHuaVE/A5TqkukDWiOfxxAjY+PEqmmBQlLwn+8OzwPiG3brouXKY5Un4pBjAeB6UToXHaQ==" + }, "node_modules/mri": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz", @@ -11485,6 +11491,11 @@ "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz", "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==" }, + "moment-duration-format": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/moment-duration-format/-/moment-duration-format-2.3.2.tgz", + "integrity": "sha512-cBMXjSW+fjOb4tyaVHuaVE/A5TqkukDWiOfxxAjY+PEqmmBQlLwn+8OzwPiG3brouXKY5Un4pBjAeB6UToXHaQ==" + }, "mri": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz", diff --git a/package.json b/package.json index 248f928..f906161 100644 --- a/package.json +++ b/package.json @@ -48,6 +48,7 @@ "dependencies": { "d3": "^7.2.1", "moment": "^2.29.4", + "moment-duration-format": "^2.3.2", "supports-color": "^9.2.2", "svelte-select": "^4.4.3", "toggl-client": "github:mcndt/toggl-client#b8d88805fb" From 273ddd11ae3da9a9d1a532266219b96598e3043c Mon Sep 17 00:00:00 2001 From: Leo Yao <45076643+leoccyao@users.noreply.github.com> Date: Tue, 2 Jan 2024 15:16:57 -0500 Subject: [PATCH 05/12] Expose status bar format string setting --- lib/config/DefaultSettings.ts | 1 + lib/config/PluginSettings.ts | 15 ++++++++++----- lib/toggl/TogglService.ts | 2 +- lib/ui/TogglSettingsTab.ts | 23 +++++++++++++++++++++++ 4 files changed, 35 insertions(+), 6 deletions(-) diff --git a/lib/config/DefaultSettings.ts b/lib/config/DefaultSettings.ts index f28c97d..ad75f0e 100644 --- a/lib/config/DefaultSettings.ts +++ b/lib/config/DefaultSettings.ts @@ -3,6 +3,7 @@ import type { PluginSettings } from "./PluginSettings"; export const DEFAULT_SETTINGS: PluginSettings = { apiToken: null, charLimitStatusBar: 40, + statusBarFormat: "m [minute]", updateInRealTime: true, workspace: { id: "none", name: "None selected" }, }; diff --git a/lib/config/PluginSettings.ts b/lib/config/PluginSettings.ts index cfdda1d..a8214cb 100644 --- a/lib/config/PluginSettings.ts +++ b/lib/config/PluginSettings.ts @@ -11,15 +11,20 @@ export interface PluginSettings { */ workspace: TogglWorkspace; + /** Has dismissed the update alert for 0.4.0 */ + hasDismissedAlert?: boolean; + + /** Update the day's total time in real-time in the sidebar */ + updateInRealTime?: boolean; + /** * The max. allowed characters in the title of a timer in * the status bar. */ charLimitStatusBar: number; - /** Has dismissed the update alert for 0.4.0 */ - hasDismissedAlert?: boolean; - - /** Update the day's total time in real-time in the sidebar */ - updateInRealTime?: boolean; + /** + * The time format for the status bar. + */ + statusBarFormat?: string; } diff --git a/lib/toggl/TogglService.ts b/lib/toggl/TogglService.ts index f9f53e6..ae0c122 100644 --- a/lib/toggl/TogglService.ts +++ b/lib/toggl/TogglService.ts @@ -292,7 +292,7 @@ export default class TogglService { } const duration = this.getTimerDuration(this._currentTimeEntry); const time_string = moment.duration(duration, 'seconds').format( - 'm [minute]', + this._plugin.settings.statusBarFormat, { trim: false, trunc: true }, ) timer_msg = `${title} (${time_string})`; diff --git a/lib/ui/TogglSettingsTab.ts b/lib/ui/TogglSettingsTab.ts index fd36ee4..1bfa594 100644 --- a/lib/ui/TogglSettingsTab.ts +++ b/lib/ui/TogglSettingsTab.ts @@ -33,7 +33,12 @@ export default class TogglSettingsTab extends PluginSettingTab { this.addTestConnectionSetting(containerEl); this.addWorkspaceSetting(containerEl); this.addUpdateRealTimeSetting(containerEl); + + containerEl.createEl("h2", { + text: "Status bar display options", + }); this.addCharLimitStatusBarSetting(containerEl); + this.addStatusBarFormatSetting(containerEl); } private addApiTokenSetting(containerEl: HTMLElement) { @@ -126,6 +131,24 @@ export default class TogglSettingsTab extends PluginSettingTab { }); } + private addStatusBarFormatSetting(containerEl: HTMLElement) { + new Setting(containerEl) + .setName("Status bar time format") + .setDesc( + "Time format for the status bar. " + + "See https://github.com/jsmreese/moment-duration-format for format options.", + ) + .addText((text) => + text + .setPlaceholder(DEFAULT_SETTINGS.statusBarFormat) + .setValue(this.plugin.settings.statusBarFormat || "") + .onChange(async (value) => { + this.plugin.settings.statusBarFormat = value; + await this.plugin.saveSettings(); + }), + ); + } + private async fetchWorkspaces() { // empty the dropdown's list const selectEl = this.workspaceDropdown.selectEl; From 33dc7ca17d45ca719d15170aa445f8723612ea27 Mon Sep 17 00:00:00 2001 From: Leo Yao <45076643+leoccyao@users.noreply.github.com> Date: Tue, 2 Jan 2024 18:14:14 -0500 Subject: [PATCH 06/12] Add option to configure status bar prefix --- lib/config/DefaultSettings.ts | 1 + lib/config/PluginSettings.ts | 5 +++++ lib/toggl/TogglService.ts | 2 +- lib/ui/TogglSettingsTab.ts | 19 +++++++++++++++++++ 4 files changed, 26 insertions(+), 1 deletion(-) diff --git a/lib/config/DefaultSettings.ts b/lib/config/DefaultSettings.ts index ad75f0e..92e6fd0 100644 --- a/lib/config/DefaultSettings.ts +++ b/lib/config/DefaultSettings.ts @@ -4,6 +4,7 @@ export const DEFAULT_SETTINGS: PluginSettings = { apiToken: null, charLimitStatusBar: 40, statusBarFormat: "m [minute]", + statusBarPrefix: "Timer: ", updateInRealTime: true, workspace: { id: "none", name: "None selected" }, }; diff --git a/lib/config/PluginSettings.ts b/lib/config/PluginSettings.ts index a8214cb..8282bf0 100644 --- a/lib/config/PluginSettings.ts +++ b/lib/config/PluginSettings.ts @@ -27,4 +27,9 @@ export interface PluginSettings { * The time format for the status bar. */ statusBarFormat?: string; + + /** + * The prefix to show before the time entry in the status bar. + */ + statusBarPrefix?: string; } diff --git a/lib/toggl/TogglService.ts b/lib/toggl/TogglService.ts index ae0c122..2976646 100644 --- a/lib/toggl/TogglService.ts +++ b/lib/toggl/TogglService.ts @@ -297,7 +297,7 @@ export default class TogglService { ) timer_msg = `${title} (${time_string})`; } - this._statusBarItem.setText(`Timer: ${timer_msg}`); + this._statusBarItem.setText(`${this._plugin.settings.statusBarPrefix}${timer_msg}`); } /** diff --git a/lib/ui/TogglSettingsTab.ts b/lib/ui/TogglSettingsTab.ts index 1bfa594..79515c1 100644 --- a/lib/ui/TogglSettingsTab.ts +++ b/lib/ui/TogglSettingsTab.ts @@ -39,6 +39,7 @@ export default class TogglSettingsTab extends PluginSettingTab { }); this.addCharLimitStatusBarSetting(containerEl); this.addStatusBarFormatSetting(containerEl); + this.addStatusBarPrefixSetting(containerEl); } private addApiTokenSetting(containerEl: HTMLElement) { @@ -149,6 +150,24 @@ export default class TogglSettingsTab extends PluginSettingTab { ); } + private addStatusBarPrefixSetting(containerEl: HTMLElement) { + new Setting(containerEl) + .setName("Status bar prefix") + .setDesc( + "Prefix before the time entry in the status bar. " + + "Leave blank for no prefix.", + ) + .addText((text) => + text + .setPlaceholder(DEFAULT_SETTINGS.statusBarPrefix) + .setValue(this.plugin.settings.statusBarPrefix || "") + .onChange(async (value) => { + this.plugin.settings.statusBarPrefix = value; + await this.plugin.saveSettings(); + }), + ); + } + private async fetchWorkspaces() { // empty the dropdown's list const selectEl = this.workspaceDropdown.selectEl; From 1a1d553d6bb6fbee2f1304c225a1b43f9f474246 Mon Sep 17 00:00:00 2001 From: Leo Yao <45076643+leoccyao@users.noreply.github.com> Date: Tue, 2 Jan 2024 19:21:14 -0500 Subject: [PATCH 07/12] Add option to show project in status bar --- lib/config/DefaultSettings.ts | 1 + lib/config/PluginSettings.ts | 3 +++ lib/toggl/TogglService.ts | 4 ++++ lib/ui/TogglSettingsTab.ts | 17 +++++++++++++++++ 4 files changed, 25 insertions(+) diff --git a/lib/config/DefaultSettings.ts b/lib/config/DefaultSettings.ts index 92e6fd0..d6d92c4 100644 --- a/lib/config/DefaultSettings.ts +++ b/lib/config/DefaultSettings.ts @@ -5,6 +5,7 @@ export const DEFAULT_SETTINGS: PluginSettings = { charLimitStatusBar: 40, statusBarFormat: "m [minute]", statusBarPrefix: "Timer: ", + statusBarShowProject: false, updateInRealTime: true, workspace: { id: "none", name: "None selected" }, }; diff --git a/lib/config/PluginSettings.ts b/lib/config/PluginSettings.ts index 8282bf0..9f805a5 100644 --- a/lib/config/PluginSettings.ts +++ b/lib/config/PluginSettings.ts @@ -32,4 +32,7 @@ export interface PluginSettings { * The prefix to show before the time entry in the status bar. */ statusBarPrefix?: string; + + /** Whether to show the project in the status bar. */ + statusBarShowProject?: boolean; } diff --git a/lib/toggl/TogglService.ts b/lib/toggl/TogglService.ts index 2976646..0710c6e 100644 --- a/lib/toggl/TogglService.ts +++ b/lib/toggl/TogglService.ts @@ -295,6 +295,10 @@ export default class TogglService { this._plugin.settings.statusBarFormat, { trim: false, trunc: true }, ) + if (this._plugin.settings.statusBarShowProject){ + const currentEnhanced = enrichObjectWithProject(this._currentTimeEntry) + title += ` - ${currentEnhanced.$project?.name || "No project"}` + } timer_msg = `${title} (${time_string})`; } this._statusBarItem.setText(`${this._plugin.settings.statusBarPrefix}${timer_msg}`); diff --git a/lib/ui/TogglSettingsTab.ts b/lib/ui/TogglSettingsTab.ts index 79515c1..6d865b9 100644 --- a/lib/ui/TogglSettingsTab.ts +++ b/lib/ui/TogglSettingsTab.ts @@ -40,6 +40,7 @@ export default class TogglSettingsTab extends PluginSettingTab { this.addCharLimitStatusBarSetting(containerEl); this.addStatusBarFormatSetting(containerEl); this.addStatusBarPrefixSetting(containerEl); + this.addStatusBarProjectSetting(containerEl); } private addApiTokenSetting(containerEl: HTMLElement) { @@ -168,6 +169,22 @@ export default class TogglSettingsTab extends PluginSettingTab { ); } + private addStatusBarProjectSetting(containerEl: HTMLElement) { + new Setting(containerEl) + .setName("Show project in status bar") + .setDesc( + "Show the project of the time entry displayed in the status bar." + ) + .addToggle((toggle) => { + toggle + .setValue(this.plugin.settings.statusBarShowProject || false) + .onChange(async (value) => { + this.plugin.settings.statusBarShowProject = value; + await this.plugin.saveSettings(); + }); + }); + } + private async fetchWorkspaces() { // empty the dropdown's list const selectEl = this.workspaceDropdown.selectEl; From bf34313cf75901c116bb999a9b8f0ff777948561 Mon Sep 17 00:00:00 2001 From: Leo Yao <45076643+leoccyao@users.noreply.github.com> Date: Tue, 2 Jan 2024 19:23:30 -0500 Subject: [PATCH 08/12] Fix side panel failing for no project --- lib/ui/components/current_timer/CurrentTimerDisplay.svelte | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ui/components/current_timer/CurrentTimerDisplay.svelte b/lib/ui/components/current_timer/CurrentTimerDisplay.svelte index 9d57f18..adc224f 100644 --- a/lib/ui/components/current_timer/CurrentTimerDisplay.svelte +++ b/lib/ui/components/current_timer/CurrentTimerDisplay.svelte @@ -33,7 +33,7 @@ {timer.$project.name}{timer.$project?.name ?? "No project"} {secondsToTimeString(duration)} From c309cec230ee316f89f7844bfead9873cb48db7e Mon Sep 17 00:00:00 2001 From: Leo Yao <45076643+leoccyao@users.noreply.github.com> Date: Tue, 2 Jan 2024 20:48:39 -0500 Subject: [PATCH 09/12] Expect error for moment duration format --- lib/toggl/TogglService.ts | 1 + lib/util/millisecondsToTimeString.ts | 2 ++ 2 files changed, 3 insertions(+) diff --git a/lib/toggl/TogglService.ts b/lib/toggl/TogglService.ts index 0710c6e..ca7488b 100644 --- a/lib/toggl/TogglService.ts +++ b/lib/toggl/TogglService.ts @@ -291,6 +291,7 @@ export default class TogglService { )}...`; } const duration = this.getTimerDuration(this._currentTimeEntry); + // @ts-expect-error const time_string = moment.duration(duration, 'seconds').format( this._plugin.settings.statusBarFormat, { trim: false, trunc: true }, diff --git a/lib/util/millisecondsToTimeString.ts b/lib/util/millisecondsToTimeString.ts index 09657aa..e63663d 100644 --- a/lib/util/millisecondsToTimeString.ts +++ b/lib/util/millisecondsToTimeString.ts @@ -2,6 +2,7 @@ import moment from "moment"; import "moment-duration-format"; export default function millisecondsToTimeString(ms: number): string { + // @ts-expect-error return moment.duration(ms).format( 'h:mm:ss', { trim: false, trunc: true }, @@ -9,6 +10,7 @@ export default function millisecondsToTimeString(ms: number): string { } export function secondsToTimeString(seconds: number): string { + // @ts-expect-error return moment.duration(seconds, 'seconds').format( 'h:mm:ss', { trim: false, trunc: true }, From eba733351a5d3ee599bf8d528bcb00560c9839d9 Mon Sep 17 00:00:00 2001 From: Leo Yao <45076643+leoccyao@users.noreply.github.com> Date: Wed, 3 Jan 2024 10:27:24 -0500 Subject: [PATCH 10/12] Fix side panel failing for no entries today --- lib/stores/dailySummary.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/stores/dailySummary.ts b/lib/stores/dailySummary.ts index 03502dd..c7f50d1 100644 --- a/lib/stores/dailySummary.ts +++ b/lib/stores/dailySummary.ts @@ -14,14 +14,14 @@ export const DailySummary = derived( [summaryItems, Projects], ([$summaryItems, $projects]) => { const summary = { - projects_breakdown: $summaryItems.map( + projects_breakdown: ($summaryItems ?? []).map( (item): EnrichedWithProject => ({ ...item, $project: $projects.find((project) => project.id === item.project_id) ?? null, }), ), - total_seconds: $summaryItems.reduce((a, b) => a + b.tracked_seconds, 0), + total_seconds: ($summaryItems ?? []).reduce((a, b) => a + b.tracked_seconds, 0), }; return summary; From 135b69a04744320f7b963a185aa3619e42283da2 Mon Sep 17 00:00:00 2001 From: Leo Yao <45076643+leoccyao@users.noreply.github.com> Date: Thu, 4 Jan 2024 23:37:02 -0500 Subject: [PATCH 11/12] Customize no time entry message --- lib/config/DefaultSettings.ts | 1 + lib/config/PluginSettings.ts | 3 +++ lib/toggl/TogglService.ts | 2 +- lib/ui/TogglSettingsTab.ts | 18 ++++++++++++++++++ 4 files changed, 23 insertions(+), 1 deletion(-) diff --git a/lib/config/DefaultSettings.ts b/lib/config/DefaultSettings.ts index d6d92c4..0d8c360 100644 --- a/lib/config/DefaultSettings.ts +++ b/lib/config/DefaultSettings.ts @@ -4,6 +4,7 @@ export const DEFAULT_SETTINGS: PluginSettings = { apiToken: null, charLimitStatusBar: 40, statusBarFormat: "m [minute]", + statusBarNoEntryMesssage: "-", statusBarPrefix: "Timer: ", statusBarShowProject: false, updateInRealTime: true, diff --git a/lib/config/PluginSettings.ts b/lib/config/PluginSettings.ts index 9f805a5..e2f32a8 100644 --- a/lib/config/PluginSettings.ts +++ b/lib/config/PluginSettings.ts @@ -35,4 +35,7 @@ export interface PluginSettings { /** Whether to show the project in the status bar. */ statusBarShowProject?: boolean; + + /** Message shown in the status bar when no time entry is running. */ + statusBarNoEntryMesssage?: string; } diff --git a/lib/toggl/TogglService.ts b/lib/toggl/TogglService.ts index ca7488b..82d8595 100644 --- a/lib/toggl/TogglService.ts +++ b/lib/toggl/TogglService.ts @@ -280,7 +280,7 @@ export default class TogglService { private updateStatusBarText() { let timer_msg = null; if (this._currentTimeEntry == null) { - timer_msg = "-"; + timer_msg = this._plugin.settings.statusBarNoEntryMesssage; } else { let title: string = this._currentTimeEntry.description || "No description"; diff --git a/lib/ui/TogglSettingsTab.ts b/lib/ui/TogglSettingsTab.ts index 6d865b9..86725fd 100644 --- a/lib/ui/TogglSettingsTab.ts +++ b/lib/ui/TogglSettingsTab.ts @@ -41,6 +41,7 @@ export default class TogglSettingsTab extends PluginSettingTab { this.addStatusBarFormatSetting(containerEl); this.addStatusBarPrefixSetting(containerEl); this.addStatusBarProjectSetting(containerEl); + this.addStatusBarNoEntrySetting(containerEl); } private addApiTokenSetting(containerEl: HTMLElement) { @@ -185,6 +186,23 @@ export default class TogglSettingsTab extends PluginSettingTab { }); } + private addStatusBarNoEntrySetting(containerEl: HTMLElement) { + new Setting(containerEl) + .setName("No entry status bar message") + .setDesc( + "Message in the status bar when no time entry is running." + ) + .addText((text) => + text + .setPlaceholder(DEFAULT_SETTINGS.statusBarNoEntryMesssage) + .setValue(this.plugin.settings.statusBarNoEntryMesssage || "") + .onChange(async (value) => { + this.plugin.settings.statusBarNoEntryMesssage = value; + await this.plugin.saveSettings(); + }), + ); + } + private async fetchWorkspaces() { // empty the dropdown's list const selectEl = this.workspaceDropdown.selectEl; From e7dbca2387b0cf4b4544d3133d4a30cfe30c9c53 Mon Sep 17 00:00:00 2001 From: Leo Yao <45076643+leoccyao@users.noreply.github.com> Date: Sun, 14 Jul 2024 17:26:36 -0400 Subject: [PATCH 12/12] Avoid ts-expect-error on moment-duration-format --- lib/toggl/TogglService.ts | 1 - lib/util/millisecondsToTimeString.ts | 2 -- package-lock.json | 19 +++++++++++++++++++ package.json | 1 + 4 files changed, 20 insertions(+), 3 deletions(-) diff --git a/lib/toggl/TogglService.ts b/lib/toggl/TogglService.ts index 82d8595..24dc4d6 100644 --- a/lib/toggl/TogglService.ts +++ b/lib/toggl/TogglService.ts @@ -291,7 +291,6 @@ export default class TogglService { )}...`; } const duration = this.getTimerDuration(this._currentTimeEntry); - // @ts-expect-error const time_string = moment.duration(duration, 'seconds').format( this._plugin.settings.statusBarFormat, { trim: false, trunc: true }, diff --git a/lib/util/millisecondsToTimeString.ts b/lib/util/millisecondsToTimeString.ts index e63663d..09657aa 100644 --- a/lib/util/millisecondsToTimeString.ts +++ b/lib/util/millisecondsToTimeString.ts @@ -2,7 +2,6 @@ import moment from "moment"; import "moment-duration-format"; export default function millisecondsToTimeString(ms: number): string { - // @ts-expect-error return moment.duration(ms).format( 'h:mm:ss', { trim: false, trunc: true }, @@ -10,7 +9,6 @@ export default function millisecondsToTimeString(ms: number): string { } export function secondsToTimeString(seconds: number): string { - // @ts-expect-error return moment.duration(seconds, 'seconds').format( 'h:mm:ss', { trim: false, trunc: true }, diff --git a/package-lock.json b/package-lock.json index 89d0715..226776a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,6 +19,7 @@ "devDependencies": { "@tsconfig/svelte": "^2.0.1", "@types/d3": "^7.1.0", + "@types/moment-duration-format": "^2.2.6", "@types/node": "^14.17.18", "@typescript-eslint/eslint-plugin": "^5.2.0", "@typescript-eslint/parser": "^5.2.0", @@ -1668,6 +1669,15 @@ "@types/node": "*" } }, + "node_modules/@types/moment-duration-format": { + "version": "2.2.6", + "resolved": "https://registry.npmjs.org/@types/moment-duration-format/-/moment-duration-format-2.2.6.tgz", + "integrity": "sha512-Qw+6ys3sQCatqukjoIBsL1UJq6S7ep4ixrNvDkdViSgzw2ZG3neArXNu3ww7mEG8kwP32ZDoON/esWb7OUckRQ==", + "dev": true, + "dependencies": { + "moment": ">=2.14.0" + } + }, "node_modules/@types/node": { "version": "14.17.18", "resolved": "https://registry.npmjs.org/@types/node/-/node-14.17.18.tgz", @@ -8771,6 +8781,15 @@ "@types/node": "*" } }, + "@types/moment-duration-format": { + "version": "2.2.6", + "resolved": "https://registry.npmjs.org/@types/moment-duration-format/-/moment-duration-format-2.2.6.tgz", + "integrity": "sha512-Qw+6ys3sQCatqukjoIBsL1UJq6S7ep4ixrNvDkdViSgzw2ZG3neArXNu3ww7mEG8kwP32ZDoON/esWb7OUckRQ==", + "dev": true, + "requires": { + "moment": ">=2.14.0" + } + }, "@types/node": { "version": "14.17.18", "resolved": "https://registry.npmjs.org/@types/node/-/node-14.17.18.tgz", diff --git a/package.json b/package.json index f906161..b0fa59f 100644 --- a/package.json +++ b/package.json @@ -20,6 +20,7 @@ "devDependencies": { "@tsconfig/svelte": "^2.0.1", "@types/d3": "^7.1.0", + "@types/moment-duration-format": "^2.2.6", "@types/node": "^14.17.18", "@typescript-eslint/eslint-plugin": "^5.2.0", "@typescript-eslint/parser": "^5.2.0",