hephaestus/heph-pwa/src/fmt.js
Erich Blume ebb2366236 feat(attention): set bands directly as a1–a4 instead of cycling
Retire the `A` attention cycle and the duplicate `b` push-to-blue gesture
in heph-tui. Attention is now picked directly: press `a` then `1`–`4`
(a1=red, a2=orange, a3=white, a4=blue, ordered by intensity). Cycling past
blue used to make a task vanish from the current view with no way back —
direct selection never does. Quick-add moves from `a` to `n`.

Surface the a1–a4 nomenclature everywhere instead of colour words or the
old p1–p4 priorities: heph-tui status/legend, the heph-quickadd chip + hint,
and the PWA chip/hint plus a new band-picker (replacing its cycle button).
The shared quick-add parser now accepts `a1`–`a4` (a1=red … a4=blue) and no
longer recognizes `p1`–`p4`. Colour mappings are unchanged; only the words.

Add Attention::ui_label() in heph-core so both Rust surfaces share the
mapping; bump the PWA service-worker cache; update the PWA how-to.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-09 07:50:53 -07:00

72 lines
2.4 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Display helpers — the PWA mirror of heph-tui's fmt.rs: relative date chips,
// attention colors/flags, and a stable per-project bullet color.
/** Attention color string → the CSS custom-property color used for flags/dots. */
export const ATTENTION_COLORS = {
red: "var(--att-red)",
orange: "var(--att-orange)",
blue: "var(--att-blue)",
white: "var(--att-white)",
};
/**
* The attention bands a user can pick, in `a1`..`a4` order (by intensity).
* Each entry is the storage color string; the label is its index + 1.
*/
export const ATTENTION_BANDS = ["red", "orange", "white", "blue"];
/** Attention color string → its `a1`..`a4` UI label (or "" if unset). */
export function attentionLabel(att) {
const i = ATTENTION_BANDS.indexOf(att);
return i < 0 ? "" : `a${i + 1}`;
}
/** Whether an attention band shows a flag glyph (red/orange/blue; not white). */
export function hasFlag(att) {
return att === "red" || att === "orange" || att === "blue";
}
function startOfDay(ms) {
const d = new Date(ms);
return new Date(d.getFullYear(), d.getMonth(), d.getDate()).getTime();
}
/**
* Compact, relative date label for an epoch-ms date (heph-tui fmt.rs):
* today/tomorrow/yesterday, else MM-DD within the current year, else YYYY-MM-DD.
*/
export function fmtRelative(ms, nowMs = Date.now()) {
if (ms == null) return "";
const day = startOfDay(ms);
const today = startOfDay(nowMs);
const oneDay = 86_400_000;
if (day === today) return "today";
if (day === today + oneDay) return "tomorrow";
if (day === today - oneDay) return "yesterday";
const d = new Date(ms);
const mm = String(d.getMonth() + 1).padStart(2, "0");
const dd = String(d.getDate()).padStart(2, "0");
if (d.getFullYear() === new Date(nowMs).getFullYear()) return `${mm}-${dd}`;
return `${d.getFullYear()}-${mm}-${dd}`;
}
/** True when `lateOn` is strictly in the past — the sole urgency signal (§7). */
export function isOverdue(lateOn, nowMs = Date.now()) {
return lateOn != null && nowMs > lateOn;
}
/** A stable hue (0359) for a project id, so its bullet color is deterministic. */
export function projectHue(id) {
if (!id) return null;
let h = 0;
for (let i = 0; i < id.length; i++) {
h = (h * 31 + id.charCodeAt(i)) >>> 0;
}
return h % 360;
}
/** CSS color for a project's bullet, or a neutral default when unfiled. */
export function projectColor(id) {
const hue = projectHue(id);
return hue == null ? "var(--bullet-none)" : `hsl(${hue} 55% 62%)`;
}