Merge pull request #5603 from nesquena/release/stage-5565
release #5565: distinct Mermaid fullscreen toolbar icon
This commit is contained in:
3 files changed
+52
-1
No files matched your search
@@ -14,6 +14,7 @@
|
||||
|
||||
### Fixed
|
||||
|
||||
- **The Mermaid diagram toolbar's "fit" and "fullscreen" buttons are now distinct icons.** The two buttons rendered a byte-identical glyph (the fullscreen icon was the fit icon's corner brackets drawn twice), so you couldn't tell them apart. Fullscreen now shows a distinct corner-frame-with-diagonal-arrows icon, visually separable from fit-to-screen's plain corner brackets. Thanks @rodboev. (#5565, #5525)
|
||||
- **Running out of provider credentials now shows an actionable message instead of a bare "Error."** When a provider's credential pool was exhausted ("All 0 credential(s) exhausted for <provider>"), the turn failed with a generic error and no hint, because that message didn't match the quota-error pattern and fell through to the catch-all. It's now classified distinctly with a hint that tells you what happened and what to do, without swallowing genuine quota errors or blocking partial-result harvesting. (This is the classification half of the credential-exhaustion work; recovering partial output on that path is a separate follow-up.) (#5559, #3929)
|
||||
- **A long-open tab no longer breaks with a runaway login-redirect URL.** If an auth session expired while a tab sat idle on the login page, the login redirect could feed itself its own address — each auth bounce wrapped and re-encoded the previous `/session/login?next=…` one level deeper, so the URL grew exponentially (a reporter measured ~12,000 characters) until it exceeded the browser's limit and the tab stopped working. All three redirect guards (client 401 handler, login page, and server login render/OIDC) now collapse a `next` whose destination resolves to the login route — detected through bounded percent-decoding so a deeply-encoded chain is still caught — while preserving legitimate redirects (including non-login paths that carry their own `next=` query key) and the existing open-redirect protections. (#5578)
|
||||
- **Concurrent chats on different profiles no longer intermittently fail turn-init citing the wrong profile's provider.** A background worker (e.g. automatic title generation) mirrored its profile's home into the process-global `HERMES_HOME` env var and ran the worker body outside the setup lock, so a concurrent worker on another profile could clobber that env var mid-run — making the agent's config reader resolve the wrong profile's `config.yaml` and fail the turn citing a provider the session never used. The worker now pins its profile via the agent's context-local home override (a task-local `ContextVar` the config reader consults before the env var), so a concurrent env-var clobber can't affect it — no worker serialization, no env mutation. Degrades cleanly on older agents (the override is resolved optionally; without it, behavior is exactly as before). Thanks @b3nw. (#5567)
|
||||
|
||||
+1
-1
@@ -1422,7 +1422,7 @@ function _mermaidViewerIcon(kind) {
|
||||
zoomOut: '<svg viewBox="0 0 24 24" aria-hidden="true"><circle cx="10" cy="10" r="6"></circle><path d="M7 10h6"></path><path d="M15 15l4 4"></path></svg>',
|
||||
reset: '<svg viewBox="0 0 24 24" aria-hidden="true"><path d="M6 9V4H1"></path><path d="M1 4l4 4"></path><path d="M10 4a8 8 0 1 1-5.66 13.66"></path></svg>',
|
||||
fit: '<svg viewBox="0 0 24 24" aria-hidden="true"><path d="M4 9V4h5M20 9V4h-5M4 15v5h5M20 15v5h-5"></path></svg>',
|
||||
fullscreen: '<svg viewBox="0 0 24 24" aria-hidden="true"><path d="M4 9V4h5M20 9V4h-5M4 15v5h5M20 15v5h-5M9 4H4v5M15 4h5v5M9 20H4v-5M15 20h5v-5"></path></svg>',
|
||||
fullscreen: '<svg viewBox="0 0 24 24" aria-hidden="true"><path d="M4 9V4h5M20 9V4h-5M4 15v5h5M20 15v5h-5"></path><path d="M4 4l5 5M20 4l-5 5M4 20l5-5M20 20l-5-5"></path></svg>',
|
||||
};
|
||||
return icons[kind] || '';
|
||||
}
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
"""Regression coverage for #5525 — Mermaid toolbar fit/fullscreen icons must differ.
|
||||
|
||||
Reported alongside the (already-fixed on master) mobile height:0 issue: the
|
||||
"fit to screen" and "fullscreen" toolbar icons look identical. Confirmed by
|
||||
inspection — the old `fullscreen` glyph was `fit`'s four corner-brackets path
|
||||
drawn twice (`...M9 4H4v5M15 4h5v5...`), so it rendered pixel-identical to `fit`.
|
||||
|
||||
Fix: give `fullscreen` a distinct glyph (corner frame + outward diagonal expand
|
||||
arrows) so the two controls are visually distinguishable.
|
||||
"""
|
||||
from pathlib import Path
|
||||
import re
|
||||
|
||||
ROOT = Path(__file__).resolve().parent.parent
|
||||
UI = ROOT / "static" / "ui.js"
|
||||
|
||||
|
||||
def _icon(kind: str) -> str:
|
||||
"""Extract the SVG string for a given _mermaidViewerIcon kind."""
|
||||
src = UI.read_text(encoding="utf-8")
|
||||
# Match `kind: '<svg ...></svg>',` inside the icons map.
|
||||
m = re.search(rf"\b{kind}:\s*'(<svg.*?</svg>)'", src)
|
||||
assert m, f"icon {kind!r} not found in _mermaidViewerIcon"
|
||||
return m.group(1)
|
||||
|
||||
|
||||
def test_fit_and_fullscreen_icons_are_distinct():
|
||||
"""The two toolbar glyphs must not be byte-identical (they were: #5525)."""
|
||||
fit = _icon("fit")
|
||||
fullscreen = _icon("fullscreen")
|
||||
assert fit and fullscreen
|
||||
assert fit != fullscreen, (
|
||||
"fit and fullscreen mermaid toolbar icons are identical — users can't "
|
||||
"tell the controls apart (#5525)"
|
||||
)
|
||||
|
||||
|
||||
def test_fullscreen_icon_has_distinct_expand_arrows():
|
||||
"""Fullscreen keeps a corner frame but adds outward diagonal expand arrows,
|
||||
which `fit` does not have — a concrete distinguishing feature."""
|
||||
fit = _icon("fit")
|
||||
fullscreen = _icon("fullscreen")
|
||||
# Diagonal expand strokes from the corners (e.g. "M4 4l5 5") — present in
|
||||
# fullscreen, absent from fit's pure corner-bracket path.
|
||||
assert re.search(r"M4 4l5 5|l5 5|l-5 5|l5 -5", fullscreen), (
|
||||
"fullscreen icon should carry outward diagonal expand arrows"
|
||||
)
|
||||
assert not re.search(r"l5 5|l-5 5", fit), (
|
||||
"fit icon should stay corner-brackets only (no diagonal arrows)"
|
||||
)
|
||||
Reference in new issue
Block a user