ObsidianSimpleTimeTracker/src/tracker.ts

125 lines
4.5 KiB
TypeScript
Raw Normal View History

2022-09-27 21:23:36 +02:00
import { moment, App, MarkdownSectionInformation } from "obsidian";
2022-09-27 16:06:40 +02:00
export class Tracker {
2022-09-27 17:03:44 +02:00
entries: Entry[];
}
2022-09-27 16:06:40 +02:00
2022-09-27 17:03:44 +02:00
export interface Entry {
name: string;
startTime: number;
endTime: number;
}
2022-09-27 16:06:40 +02:00
2022-09-27 17:03:44 +02:00
export function startEntry(tracker: Tracker, name: string): void {
2022-09-27 21:23:36 +02:00
if (!name)
name = `Segment ${tracker.entries.length + 1}`;
let entry: Entry = { name: name, startTime: moment().unix(), endTime: null };
2022-09-27 17:03:44 +02:00
tracker.entries.push(entry);
};
2022-09-27 16:06:40 +02:00
2022-09-27 17:03:44 +02:00
export function endEntry(tracker: Tracker): void {
let last = tracker.entries.last();
2022-09-27 21:23:36 +02:00
last.endTime = moment().unix();
2022-09-27 17:03:44 +02:00
}
2022-09-27 16:06:40 +02:00
2022-09-27 17:03:44 +02:00
export function isRunning(tracker: Tracker): boolean {
let last = tracker.entries.last();
return last != null && !last.endTime;
}
2022-09-27 16:06:40 +02:00
2022-09-27 17:03:44 +02:00
export async function saveTracker(tracker: Tracker, app: App, section: MarkdownSectionInformation): Promise<void> {
let file = app.workspace.getActiveFile();
let content = await app.vault.cachedRead(file);
2022-09-27 16:06:40 +02:00
2022-09-27 17:03:44 +02:00
// figure out what part of the content we have to edit
let lines = content.split("\n");
let prev = lines.filter((_, i) => i <= section.lineStart).join("\n");
let next = lines.filter((_, i) => i >= section.lineEnd).join("\n");
// edit only the code block content, leave the rest untouched
content = `${prev}\n${JSON.stringify(tracker)}\n${next}`;
2022-09-27 16:06:40 +02:00
2022-09-27 17:03:44 +02:00
await app.vault.modify(file, content);
}
2022-09-27 16:06:40 +02:00
2022-09-27 17:03:44 +02:00
export function loadTracker(json: string): Tracker {
if (json) {
try {
return JSON.parse(json);
} catch (e) {
console.log(`Failed to parse Tracker from ${json}`);
2022-09-27 16:06:40 +02:00
}
}
2022-09-27 17:03:44 +02:00
return { entries: [] };
2022-09-27 16:06:40 +02:00
}
2022-09-27 17:03:44 +02:00
export function displayTracker(tracker: Tracker, element: HTMLElement): void {
2022-09-27 21:23:36 +02:00
// add timers
2022-09-27 19:33:34 +02:00
let timer = element.createDiv({ cls: "simple-time-tracker-timers" });
2022-09-27 21:23:36 +02:00
let currentDiv = timer.createEl("div", { cls: "simple-time-tracker-timer" });
2022-09-27 21:35:26 +02:00
let current = currentDiv.createEl("span", { cls: "simple-time-tracker-timer-time" });
2022-09-27 21:23:36 +02:00
currentDiv.createEl("span", { text: "CURRENT" });
let totalDiv = timer.createEl("div", { cls: "simple-time-tracker-timer" });
2022-09-27 21:35:26 +02:00
let total = totalDiv.createEl("span", { cls: "simple-time-tracker-timer-time" });
2022-09-27 21:23:36 +02:00
totalDiv.createEl("span", { text: "TOTAL" });
// add list
let table = element.createEl("table", { cls: "simple-time-tracker-table" });
2022-09-27 21:29:50 +02:00
table.createEl("tr").append(
createEl("th", { text: "Segment" }),
createEl("th", { text: "Start Time" }),
createEl("th", { text: "End Time" }),
createEl("th", { text: "Total" }));
2022-09-27 21:23:36 +02:00
for (let entry of tracker.entries) {
let row = table.createEl("tr");
row.createEl("td", { text: entry.name });
row.createEl("td", { text: moment.unix(entry.startTime).format("YY-MM-DD hh:mm:ss") });
if (entry.endTime) {
row.createEl("td", { text: moment.unix(entry.endTime).format("YY-MM-DD hh:mm:ss") });
let duration = moment.unix(entry.endTime).diff(moment.unix(entry.startTime));
row.createEl("td", { text: getCountdownDisplay(moment.duration(duration)) });
}
}
setCountdownValues(tracker, current, total, currentDiv);
let intervalId = window.setInterval(() => {
// we delete the interval timer when the element is removed
if (!element.isConnected) {
window.clearInterval(intervalId);
return;
}
setCountdownValues(tracker, current, total, currentDiv);
}, 1000);
2022-09-27 17:03:44 +02:00
};
2022-09-27 16:06:40 +02:00
2022-09-27 21:23:36 +02:00
function getCountdownDisplay(duration: moment.Duration): string {
2022-09-27 17:03:44 +02:00
let ret = "";
2022-09-27 21:23:36 +02:00
if (duration.hours() > 0)
2022-09-27 21:35:26 +02:00
ret += duration.hours() + "h ";
if (duration.minutes() > 0)
ret += duration.minutes() + "m ";
ret += duration.seconds() + "s";
2022-09-27 21:23:36 +02:00
return ret;
}
2022-09-27 16:06:40 +02:00
2022-09-27 21:23:36 +02:00
function setCountdownValues(tracker: Tracker, current: HTMLElement, total: HTMLElement, currentDiv: HTMLDivElement) {
let currEntry = tracker.entries.last();
if (currEntry) {
let currDuration = moment().diff(moment.unix(currEntry.startTime));
if (!currEntry.endTime)
current.setText(getCountdownDisplay(moment.duration(currDuration)));
2022-09-27 16:06:40 +02:00
2022-09-27 21:23:36 +02:00
let totalDuration = 0;
for (let entry of tracker.entries) {
if (entry == currEntry && !currEntry.endTime) {
totalDuration += currDuration;
} else {
totalDuration += moment.unix(entry.endTime).diff(moment.unix(entry.startTime));
}
}
total.setText(getCountdownDisplay(moment.duration(totalDuration)));
2022-09-27 16:06:40 +02:00
}
2022-09-27 21:35:26 +02:00
currentDiv.hidden = !currEntry || !!currEntry.endTime;
2022-09-27 16:06:40 +02:00
}