tokmon 0.3.0 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +76 -37
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
import { render } from "ink";
|
|
5
5
|
|
|
6
6
|
// src/app.tsx
|
|
7
|
-
import { useState, useEffect } from "react";
|
|
7
|
+
import { useState, useEffect, useRef } from "react";
|
|
8
8
|
import { Box, Text, useInput, useStdout } from "ink";
|
|
9
9
|
|
|
10
10
|
// src/data.ts
|
|
@@ -194,15 +194,14 @@ function isoWeekLabel(ts) {
|
|
|
194
194
|
function monthLabel(ts) {
|
|
195
195
|
return new Date(ts).toISOString().slice(0, 7);
|
|
196
196
|
}
|
|
197
|
-
async function
|
|
197
|
+
async function fetchDashboard() {
|
|
198
198
|
const now = Date.now();
|
|
199
199
|
const d = /* @__PURE__ */ new Date();
|
|
200
|
-
const lookback = new Date(d.getFullYear(), d.getMonth() - 6, 1).getTime();
|
|
201
200
|
const monthStart = new Date(d.getFullYear(), d.getMonth(), 1).getTime();
|
|
202
201
|
const todayStart = new Date(d.getFullYear(), d.getMonth(), d.getDate()).getTime();
|
|
203
202
|
const weekDay = d.getDay();
|
|
204
203
|
const weekStart = new Date(d.getFullYear(), d.getMonth(), d.getDate() - (weekDay === 0 ? 6 : weekDay - 1)).getTime();
|
|
205
|
-
const entries = await loadEntries(
|
|
204
|
+
const entries = await loadEntries(monthStart);
|
|
206
205
|
const fiveHoursAgo = now - 5 * 36e5;
|
|
207
206
|
const blockEntries = entries.filter((e) => e.ts >= fiveHoursAgo);
|
|
208
207
|
let block = null;
|
|
@@ -215,17 +214,21 @@ async function fetchData() {
|
|
|
215
214
|
const percent = Math.min(100, (now - oldest) / (5 * 36e5) * 100);
|
|
216
215
|
block = { spent, projected: burnRate * 5, burnRate, percent, remaining: minutes(remainMs / 6e4) };
|
|
217
216
|
}
|
|
218
|
-
const daily = groupBy(entries, (e) => new Date(e.ts).toISOString().slice(0, 10));
|
|
219
|
-
const weekly = groupBy(entries, (e) => isoWeekLabel(e.ts));
|
|
220
|
-
const monthly = groupBy(entries, (e) => monthLabel(e.ts));
|
|
221
217
|
return {
|
|
222
218
|
today: sum(entries.filter((e) => e.ts >= todayStart)),
|
|
223
219
|
week: sum(entries.filter((e) => e.ts >= weekStart)),
|
|
224
220
|
month: sum(entries.filter((e) => e.ts >= monthStart)),
|
|
225
|
-
block
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
221
|
+
block
|
|
222
|
+
};
|
|
223
|
+
}
|
|
224
|
+
async function fetchTable() {
|
|
225
|
+
const d = /* @__PURE__ */ new Date();
|
|
226
|
+
const lookback = new Date(d.getFullYear(), d.getMonth() - 6, 1).getTime();
|
|
227
|
+
const entries = await loadEntries(lookback);
|
|
228
|
+
return {
|
|
229
|
+
daily: groupBy(entries, (e) => new Date(e.ts).toISOString().slice(0, 10)),
|
|
230
|
+
weekly: groupBy(entries, (e) => isoWeekLabel(e.ts)),
|
|
231
|
+
monthly: groupBy(entries, (e) => monthLabel(e.ts))
|
|
229
232
|
};
|
|
230
233
|
}
|
|
231
234
|
|
|
@@ -267,7 +270,9 @@ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
|
267
270
|
var TABS = ["Dashboard", "Table"];
|
|
268
271
|
var VIEWS = ["Daily", "Weekly", "Monthly"];
|
|
269
272
|
function App({ interval: cliInterval }) {
|
|
270
|
-
const [
|
|
273
|
+
const [dashboard, setDashboard] = useState(null);
|
|
274
|
+
const [table, setTable] = useState(null);
|
|
275
|
+
const [tableLoading, setTableLoading] = useState(false);
|
|
271
276
|
const [error, setError] = useState(null);
|
|
272
277
|
const [updated, setUpdated] = useState(/* @__PURE__ */ new Date());
|
|
273
278
|
const [tab, setTab] = useState(0);
|
|
@@ -276,6 +281,7 @@ function App({ interval: cliInterval }) {
|
|
|
276
281
|
const [showSettings, setShowSettings] = useState(false);
|
|
277
282
|
const [config, setConfig] = useState(null);
|
|
278
283
|
const [settingsCursor, setSettingsCursor] = useState(0);
|
|
284
|
+
const tableLoadedOnce = useRef(false);
|
|
279
285
|
const { stdout } = useStdout();
|
|
280
286
|
const rows = stdout?.rows ?? 24;
|
|
281
287
|
const cols = stdout?.columns ?? 80;
|
|
@@ -287,6 +293,60 @@ function App({ interval: cliInterval }) {
|
|
|
287
293
|
if (c.clearScreen && stdout) stdout.write("\x1B[2J\x1B[H");
|
|
288
294
|
});
|
|
289
295
|
}, []);
|
|
296
|
+
useEffect(() => {
|
|
297
|
+
let active = true;
|
|
298
|
+
const load = async () => {
|
|
299
|
+
try {
|
|
300
|
+
const result = await fetchDashboard();
|
|
301
|
+
if (active) {
|
|
302
|
+
setDashboard(result);
|
|
303
|
+
setError(null);
|
|
304
|
+
setUpdated(/* @__PURE__ */ new Date());
|
|
305
|
+
}
|
|
306
|
+
} catch (e) {
|
|
307
|
+
if (active) setError(e instanceof Error ? e.message : String(e));
|
|
308
|
+
}
|
|
309
|
+
};
|
|
310
|
+
load();
|
|
311
|
+
const id = setInterval(load, interval2);
|
|
312
|
+
return () => {
|
|
313
|
+
active = false;
|
|
314
|
+
clearInterval(id);
|
|
315
|
+
};
|
|
316
|
+
}, [interval2]);
|
|
317
|
+
useEffect(() => {
|
|
318
|
+
if (tab !== 1) return;
|
|
319
|
+
if (tableLoadedOnce.current && table) return;
|
|
320
|
+
let active = true;
|
|
321
|
+
setTableLoading(true);
|
|
322
|
+
fetchTable().then((result) => {
|
|
323
|
+
if (active) {
|
|
324
|
+
setTable(result);
|
|
325
|
+
setTableLoading(false);
|
|
326
|
+
tableLoadedOnce.current = true;
|
|
327
|
+
}
|
|
328
|
+
}).catch(() => {
|
|
329
|
+
if (active) setTableLoading(false);
|
|
330
|
+
});
|
|
331
|
+
return () => {
|
|
332
|
+
active = false;
|
|
333
|
+
};
|
|
334
|
+
}, [tab]);
|
|
335
|
+
useEffect(() => {
|
|
336
|
+
if (tab !== 1 || !tableLoadedOnce.current) return;
|
|
337
|
+
let active = true;
|
|
338
|
+
const id = setInterval(async () => {
|
|
339
|
+
try {
|
|
340
|
+
const result = await fetchTable();
|
|
341
|
+
if (active) setTable(result);
|
|
342
|
+
} catch {
|
|
343
|
+
}
|
|
344
|
+
}, Math.max(interval2, 1e4));
|
|
345
|
+
return () => {
|
|
346
|
+
active = false;
|
|
347
|
+
clearInterval(id);
|
|
348
|
+
};
|
|
349
|
+
}, [tab, interval2]);
|
|
290
350
|
const isTTY = process.stdin.isTTY === true;
|
|
291
351
|
const settingsItems = 2;
|
|
292
352
|
const cfg = config ?? { interval: 2, clearScreen: true };
|
|
@@ -377,30 +437,9 @@ function App({ interval: cliInterval }) {
|
|
|
377
437
|
if (key.pageDown) setScroll((s) => s + Math.max(1, rows - 12));
|
|
378
438
|
if (key.pageUp) setScroll((s) => Math.max(0, s - Math.max(1, rows - 12)));
|
|
379
439
|
}, { isActive: isTTY });
|
|
380
|
-
useEffect(() => {
|
|
381
|
-
let active = true;
|
|
382
|
-
const load = async () => {
|
|
383
|
-
try {
|
|
384
|
-
const result = await fetchData();
|
|
385
|
-
if (active) {
|
|
386
|
-
setData(result);
|
|
387
|
-
setError(null);
|
|
388
|
-
setUpdated(/* @__PURE__ */ new Date());
|
|
389
|
-
}
|
|
390
|
-
} catch (e) {
|
|
391
|
-
if (active) setError(e instanceof Error ? e.message : String(e));
|
|
392
|
-
}
|
|
393
|
-
};
|
|
394
|
-
load();
|
|
395
|
-
const id = setInterval(load, interval2);
|
|
396
|
-
return () => {
|
|
397
|
-
active = false;
|
|
398
|
-
clearInterval(id);
|
|
399
|
-
};
|
|
400
|
-
}, [interval2]);
|
|
401
440
|
if (error) return /* @__PURE__ */ jsx(Box, { padding: 1, children: /* @__PURE__ */ jsx(Text, { color: "red", children: error }) });
|
|
402
|
-
if (!
|
|
403
|
-
const tableData = [
|
|
441
|
+
if (!dashboard) return /* @__PURE__ */ jsx(Box, { padding: 1, children: /* @__PURE__ */ jsx(Text, { dimColor: true, children: "Loading..." }) });
|
|
442
|
+
const tableData = table ? [table.daily, table.weekly, table.monthly][view] : [];
|
|
404
443
|
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", paddingX: 2, paddingY: 1, children: [
|
|
405
444
|
/* @__PURE__ */ jsxs(Box, { justifyContent: "space-between", children: [
|
|
406
445
|
/* @__PURE__ */ jsxs(Box, { children: [
|
|
@@ -422,11 +461,11 @@ function App({ interval: cliInterval }) {
|
|
|
422
461
|
/* @__PURE__ */ jsx(Text, { dimColor: true, children: " Tab s=settings" })
|
|
423
462
|
] }),
|
|
424
463
|
/* @__PURE__ */ jsx(Box, { height: 1 }),
|
|
425
|
-
tab === 0 && /* @__PURE__ */ jsx(DashboardView, { data }),
|
|
464
|
+
tab === 0 && /* @__PURE__ */ jsx(DashboardView, { data: dashboard }),
|
|
426
465
|
tab === 1 && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
427
466
|
/* @__PURE__ */ jsx(ViewBar, { views: VIEWS, active: view }),
|
|
428
467
|
/* @__PURE__ */ jsx(Box, { height: 1 }),
|
|
429
|
-
/* @__PURE__ */ jsx(TableView, { rows: tableData, scroll, maxRows: rows - 12, wide: cols > 90 })
|
|
468
|
+
tableLoading && !table ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "Loading 6 months of history..." }) : /* @__PURE__ */ jsx(TableView, { rows: tableData, scroll, maxRows: rows - 12, wide: cols > 90 })
|
|
430
469
|
] })
|
|
431
470
|
] }),
|
|
432
471
|
/* @__PURE__ */ jsxs(Box, { marginTop: 1, children: [
|