diff --git a/internal/gui/assets/i18n.js b/internal/gui/assets/i18n.js index 4cedeccb..825b31ea 100644 --- a/internal/gui/assets/i18n.js +++ b/internal/gui/assets/i18n.js @@ -1037,6 +1037,10 @@ const I18N = { "the last {n} the gateway keeps": "网关保留的最近 {n} 个", "Accounts and keys": "账号与密钥", "over those requests": "统计自这些请求", + "Nothing on {day}": "{day}没有请求", + "No requests since magpie started": "magpie 启动以来还没有请求", + "Each request an agent sends through magpie shows up here: who answered it, why, and each try.": "agent 经 magpie 发出的每个请求都会列在这里:谁应答的、为什么选它,以及每一次尝试。", + "Earlier ones are kept by day, in the bar above.": "更早的请求按天保存,在上面的日期里查看。", "tried {n}": "尝试 {n}", "answered {n}": "应答 {n}", "last answered {time}": "最近应答 {time}", diff --git a/internal/gui/assets/routing.css b/internal/gui/assets/routing.css index 355c30d2..42ff4a9e 100644 --- a/internal/gui/assets/routing.css +++ b/internal/gui/assets/routing.css @@ -168,6 +168,10 @@ .rt-req .meta { color: var(--muted); font-variant-numeric: tabular-nums; white-space: nowrap; text-align: right; } @container (max-width: 520px) { .rt-reqs { grid-template-columns: auto minmax(0, 1fr); } .rt-req { row-gap: 2px; } .rt-req .to { grid-column: 2; } .rt-req .meta { grid-column: 2; text-align: left; } } .rt-acts { padding: 4px 0; } +.rt-cols.solo { grid-template-columns: minmax(0, 1fr); } +.rt-reqs.none { display: block; background: none; border-color: transparent; } +.rt-reqs.none .empty-state { padding: 14px 12px 18px; font-size: 12px; line-height: 1.6; } +.rt-reqs.none .empty-state b { font-size: 13px; } .rt-prov { display: flex; align-items: center; gap: 7px; padding: 8px 12px 4px; font-size: 12px; } .rt-prov .ic, .rt-prov .ic img, .rt-prov .ic svg { width: 14px; height: 14px; } .rt-prov > span:last-child { margin-left: auto; font-size: 10.5px; color: var(--muted); border: 1px solid var(--line); border-radius: 999px; padding: 0 7px; } diff --git a/internal/gui/assets/routing.js b/internal/gui/assets/routing.js index 5eb5d04e..8561365b 100644 --- a/internal/gui/assets/routing.js +++ b/internal/gui/assets/routing.js @@ -884,15 +884,17 @@ steps.replaceChildren(...items.map(([s, c]) => el("li", c, s))); } - // pick sets the stage to a past request, or back to live with the newest - function pick(r) { + // pick sets the stage to a past request, or back to live with the newest; + // the page goes up to the stage only when the reader picked a request in + // the list (look), never on a day or Live picked in the list's own bar + function pick(r, look = true) { pinned = r.id === newest()?.id ? null : r; if (rp) { rp = null; rbar.hidden = true; } stopPlays(); cur = r; sync(true); renderAll(); say(affWhy(r, true) || ruleWhy(r, true) || firstWhy(r)); - if (pinned) { scrollOnPurpose(); box.scrollIntoView({ block: "nearest", behavior: still() ? "auto" : "smooth" }); } + if (pinned && look) { scrollOnPurpose(); box.scrollIntoView({ block: "nearest", behavior: still() ? "auto" : "smooth" }); } } // who answered a request, or what its agent got @@ -931,7 +933,7 @@ if (d) await loadDays(d); pinned = null; const r = d ? listed()[0] : newest(); - if (r && d) pick(r); + if (r && d) pick(r, false); else if (r) { stopPlays(); cur = r; sync(true); say(affWhy(r, true) || ruleWhy(r, true) || firstWhy(r)); } renderAll(); } @@ -961,6 +963,22 @@ reqNote.textContent = day ? t(pastCut ? "the last {n} of {day}" : "{n} on {day}", { n: rs.length, day: dayName(day) }) : t("the last {n} the gateway keeps", { n: rs.length }); renderDays(); + // none yet: what the list is for in its place, and no accounts column + // to tally nothing + const none = !rs.length; + reqNote.hidden = none; + reqs.classList.toggle("none", none); + colB.hidden = none; + hist.classList.toggle("solo", none); + if (none) { + const p = el("div", "empty-state"); + p.append(el("b", "", day ? t("Nothing on {day}", { day: dayName(day) }) : t("No requests since magpie started")), + t("Each request an agent sends through magpie shows up here: who answered it, why, and each try.")); + if (!day && days.length) p.append(" " + t("Earlier ones are kept by day, in the bar above.")); + reqs.replaceChildren(p); + renderActs(rs); + return; + } reqs.replaceChildren(...rs.map((r) => { const [said, how, tr] = outcome(r); const b = el("button", "rt-req " + how);