diff --git a/suramadu/web/flare.css b/suramadu/web/flare.css index 3f07274..becda6a 100644 --- a/suramadu/web/flare.css +++ b/suramadu/web/flare.css @@ -11,23 +11,37 @@ :root .lb-flare-button { position: fixed; right: 14px; - bottom: 14px; + top: 14px; z-index: 40; - width: 40px; - height: 40px; - border: 1px solid var(--lb-line); - border-radius: 50%; + display: flex; + align-items: center; + gap: 7px; + padding: 8px 16px; + border: 1px solid var(--lb-accent); + border-radius: 999px; background: var(--lb-panel); - color: var(--lb-muted); - font-size: 18px; + color: var(--lb-ink); + font-family: var(--lb-font); + font-size: 14px; + font-weight: 600; line-height: 1; cursor: pointer; } :root .lb-flare-button:hover, :root .lb-flare-button:focus { - color: var(--lb-ink); - border-color: var(--lb-accent); + background: var(--lb-accent); + color: #ffffff; +} + +:root .lb-flare-button-flag { + color: var(--lb-accent); + font-size: 16px; +} + +:root .lb-flare-button:hover .lb-flare-button-flag, +:root .lb-flare-button:focus .lb-flare-button-flag { + color: #ffffff; } :root .lb-flare-overlay { diff --git a/suramadu/web/flare.js b/suramadu/web/flare.js index cc1bfa5..eca3acc 100644 --- a/suramadu/web/flare.js +++ b/suramadu/web/flare.js @@ -95,7 +95,11 @@ attempt(scale); } - /* The blob as bare base64, the way /api/flare wants it. */ + /* + * The blob as bare base64, the way /api/flare wants it. Also what the + * preview shows, as a data: URL - the page's CSP allows img-src data: + * but not blob:, so an object URL here renders as a broken image. + */ function encode(blob, done) { var reader = new FileReader(); reader.onloadend = function () { @@ -117,17 +121,14 @@ }; var overlay = null; - var screenshot = null; // {blob, url} while the dialog is open + var screenshot = null; // base64 PNG while the dialog is open function close() { if (overlay) { overlay.remove(); overlay = null; } - if (screenshot) { - URL.revokeObjectURL(screenshot.url); - screenshot = null; - } + screenshot = null; document.removeEventListener("keydown", onKey); } @@ -180,9 +181,17 @@ attach.appendChild(document.createTextNode(" (not available)")); return; } - screenshot = { blob: blob, url: URL.createObjectURL(blob) }; - preview.src = screenshot.url; - preview.hidden = !tick.checked; + encode(blob, function (base64) { + if (!base64) { + tick.checked = false; + tick.disabled = true; + attach.appendChild(document.createTextNode(" (not available)")); + return; + } + screenshot = base64; + preview.src = "data:image/png;base64," + base64; + preview.hidden = !tick.checked; + }); }); tick.addEventListener("change", function () { preview.hidden = !tick.checked || !screenshot; @@ -254,15 +263,9 @@ } if (shot) { - encode(shot.blob, function (base64) { - if (base64) { - payload.png = base64; - } - post(); - }); - } else { - post(); + payload.png = shot; } + post(); } function sent(data, status) { @@ -286,10 +289,11 @@ // --- the button -------------------------------------------------------- - var button = el("button", "lb-flare-button", "⚑"); + var button = el("button", "lb-flare-button"); button.type = "button"; - button.title = "Send a flare — report a problem"; - button.setAttribute("aria-label", "Send a flare: report a problem"); + button.appendChild(el("span", "lb-flare-button-flag", "⚑")); + button.appendChild(document.createTextNode("Flare")); + button.title = "Report a problem to the lance.blue feedback board"; button.addEventListener("click", open); document.body.appendChild(button); })(window, document); diff --git a/tests/shell/test-flare-ui.sh b/tests/shell/test-flare-ui.sh index 522f49f..6dafefe 100755 --- a/tests/shell/test-flare-ui.sh +++ b/tests/shell/test-flare-ui.sh @@ -90,6 +90,11 @@ check "the one fetch is the same-origin /api/flare" bash -c ' check "the dialog says a flare posts publicly" \ grep -q "posts publicly" "$JS" +# The page's CSP allows img-src data: but not blob:, so an object URL in the +# preview renders as a broken image. It shipped that way once. +check "the preview never uses an object URL" \ + bash -c "! grep -q 'createObjectURL' '$JS'" + # --- the page loads it ------------------------------------------------------- check "index.html loads flare.js" grep -q '' "$HTML"