Files
malkuthro-ComfyUI-Koolook/web/sidebar/format_time.js
T
malkuthroandClaude Opus 4.7 ea4ee071e7 feat(snapshot): YES/NO modal on newer auto-save + 24h timestamps (#111)
* feat(snapshot): autosave UX — YES/NO modal when newer + 24h local timestamps

Two snapshot-UX threads in one slice:

1. **24-hour timestamps with relative-recent tier** in the Load dialog
   and snapshot status tooltip. The previous `en-US` 12-hour format
   produced "12:56 AM" for timestamps just past midnight, which read
   visually like noon. Now: `just now` / `12 min ago` / `today 14:32` /
   `yesterday 23:58` / `May 6 14:32`. Centralized in a new
   `format_time.js` helper so future surfaces stay aligned.

2. **YES/NO choice when an auto-save is newer than the saved version.**
   Click any preset row in Snapshot → Load and, if the matching
   `<preset>_autosave/periodic.json` is more recent than the named
   save's mtime, the confirm dialog upgrades from "Load preset" to a
   YES/NO question with both timestamps shown side-by-side. YES loads
   the auto-save, NO loads the older deliberate save (the row clicked),
   Esc cancels. Standard pre-load auto-save protection still runs on
   either path. Server-side `/koolook/presets/list` augments root rows
   with `latestAutosaveMtime` via one extra `stat()` per row — no file
   read, cheap on large libraries. Aligns the system with the user's
   mental model: named saves stay deliberate (only updated on Save /
   Quick Save), and the auto-save is treated as a recovery copy the
   system surfaces at decision time rather than a parallel save the
   user has to remember to check.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(snapshot): restore-from-auto-save baselines as "auto-saved", not "saved"

`doAutosaveRestore` was calling `markStateSaved()` after a successful
restore, which baselined the *named-save* fingerprint to the auto-save's
content. The dot turned green even though `<preset>.json` on disk still
held the OLDER deliberate save — blurring the deliberate-save model the
Path C UX deliberately reinforces (named saves only change on Save /
Quick Save).

New `markStateAutosaved()` export in `snapshot.js` baselines the
*periodic* fingerprint instead, so the dot reads "auto-saved" (blue)
until the user explicitly commits the restored state via Quick Save or
Save. Threaded through `tree.js` → `showLoadSnapshotDialog` via the
existing dependency-injection pattern. Toast message also updated to
nudge: `Restored auto-save of "Foo" — Quick Save to commit to the
named file.`

Fixes the regression flagged on the PR #111 review. Applies to BOTH
restore call sites (the new YES path AND the long-existing Recovery
disclosure) since they share the helper.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 21:20:26 +02:00

54 lines
2.4 KiB
JavaScript

// SPDX-FileCopyrightText: 2025-2026 Kforge Labs <https://github.com/malkuthro/ComfyUI-Koolook>
// SPDX-License-Identifier: GPL-3.0-only
// =============================================================================
// Local-timezone timestamp formatter — combined relative + 24-hour absolute.
//
// Output cases (in priority order):
// • <1 min ago → "just now"
// • <60 min ago → "12 min ago"
// • same calendar day (local) → "today 14:32"
// • previous day → "yesterday 23:58"
// • else, current year → "May 6 14:32"
// • else → "May 6 2025 14:32"
//
// Why 24-hour: the previous `en-US` 12-hour format produced "12:56 AM" for
// timestamps just past midnight, which reads visually like noon to most
// people (the US "12 AM = midnight" convention is a known UX trap).
// Manually building HH:MM from `getHours()` / `getMinutes()` sidesteps the
// `hour12: false` quirk in some locales (e.g. en-US emitting "24:00").
//
// Why "today" / "yesterday" tier: makes the most-relevant cases (recent
// snapshots, recent autosaves) read at a glance without making the eye
// parse a full date.
// =============================================================================
const MONTHS = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
function _hhmm(d) {
return String(d.getHours()).padStart(2, "0") + ":" + String(d.getMinutes()).padStart(2, "0");
}
export function formatLocalStamp(d, now = new Date()) {
if (!(d instanceof Date) || isNaN(d.getTime())) return "";
const diffMs = now.getTime() - d.getTime();
const diffMin = Math.floor(diffMs / 60000);
// Future timestamps (clock skew, browser/server drift): fall through to
// absolute formatting rather than emitting "-3 min ago".
if (diffMin >= 0 && diffMin < 1) return "just now";
if (diffMin >= 1 && diffMin < 60) return diffMin + " min ago";
const time = _hhmm(d);
const startOfToday = new Date(now);
startOfToday.setHours(0, 0, 0, 0);
const startOfYesterday = new Date(startOfToday);
startOfYesterday.setDate(startOfYesterday.getDate() - 1);
if (d >= startOfToday) return "today " + time;
if (d >= startOfYesterday) return "yesterday " + time;
const datePart = MONTHS[d.getMonth()] + " " + d.getDate();
const yearPart = d.getFullYear() !== now.getFullYear() ? " " + d.getFullYear() : "";
return datePart + yearPart + " " + time;
}