fix(home,close): tool-link preserves file context + drop close-page explanation

(1) ``[Tool] →`` action links inside per-file finding rows now
preserve the file that the card belongs to. Previously the home page
re-set ``home_uploaded_*`` to the FIRST imported file on every rerun
— so when a user with multiple imports clicked
``Clean Text →`` on file_B's findings card, the tool page loaded
file_A. The click handler in ``_render_finding_row_v2`` now looks
the file up in ``home_uploads`` by the findings-card filename and
writes ``home_uploaded_name / size / bytes`` BEFORE
``st.switch_page``, so the tool's ``pickup_or_upload`` reads the
right context.

The filename threads through ``render_findings_panel(..., header=)``
→ ``_render_finding_row_v2(..., filename=)``; ``header`` is already
the filename today, so no call-site change needed.

(2) Close screen "explanation" removed. The long browser-restriction
hint paragraph (``quit.close_hint``: "Browsers don't let JavaScript
close a tab you opened yourself …") is gone from the farewell overlay
— the auto-dismiss path lands the user on about:blank within ~1.5s
of the close click, so the explanation never had a chance to be
useful. ``autoDismiss`` simplified to "try close, else redirect"
without the hint-surface step. The i18n key is retained as a no-op
in case the hint comes back.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-19 02:29:49 +00:00
parent 9a7d861903
commit 69240fc922
2 changed files with 25 additions and 17 deletions

BIN
scratch_toolpage.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

View File

@@ -1297,9 +1297,6 @@ _FAREWELL_SCRIPT_TEMPLATE = """
'<h1 style="margin:0 0 8px 0;font-weight:600;letter-spacing:-0.01em;">' + '<h1 style="margin:0 0 8px 0;font-weight:600;letter-spacing:-0.01em;">' +
'__TITLE__</h1>' + '__TITLE__</h1>' +
'<p style="opacity:0.7;margin:0;">__SUBTITLE__</p>' + '<p style="opacity:0.7;margin:0;">__SUBTITLE__</p>' +
'<p id="datatools-close-hint" style="' +
'display:none;font-size:13px;opacity:0.6;margin:14px 0 0 0;">' +
'__CLOSE_HINT__</p>' +
'</div>'; '</div>';
return overlay; return overlay;
} }
@@ -1328,20 +1325,19 @@ _FAREWELL_SCRIPT_TEMPLATE = """
try { win.location.replace('about:blank'); } catch (e) {} try { win.location.replace('about:blank'); } catch (e) {}
} }
function autoDismiss(doc, win) { function autoDismiss(doc, win) {
// Try the programmatic close first — succeeds in Chrome/Edge // Try programmatic close first — succeeds in Chrome/Edge
// --app windows. If it fails (regular browser tab), surface the // ``--app`` windows. If it fails (regular browser tab),
// hint and auto-redirect to about:blank so the user lands on a // auto-redirect to about:blank so the user lands on a clean
// clean page instead of the frozen farewell overlay. The "Close // page instead of the frozen farewell overlay. The "Close this
// this window" button used to drive the same flow on click; we // window" button + the long browser-restriction hint paragraph
// dropped that affordance per UX request, so this auto-timer is // both used to drive / explain this flow; we dropped both per
// the only path on regular tabs. // UX request, so this auto-timer is the only path on regular
// tabs.
var standalone = isStandalone(win); var standalone = isStandalone(win);
if (tryClose(win)) return; if (tryClose(win)) return;
var hint = doc.getElementById('datatools-close-hint');
if (hint) hint.style.display = 'block';
setTimeout(function () { setTimeout(function () {
if (!win.closed) fallbackToBlank(win); if (!win.closed) fallbackToBlank(win);
}, standalone ? 400 : 2500); }, standalone ? 400 : 1500);
} }
try { try {
var doc = window.top.document; var doc = window.top.document;
@@ -1383,8 +1379,6 @@ def _farewell_script() -> str:
_FAREWELL_SCRIPT_TEMPLATE _FAREWELL_SCRIPT_TEMPLATE
.replace("__TITLE__", _js_html_safe(_t("quit.farewell_title"))) .replace("__TITLE__", _js_html_safe(_t("quit.farewell_title")))
.replace("__SUBTITLE__", _js_html_safe(_t("quit.farewell_subtitle"))) .replace("__SUBTITLE__", _js_html_safe(_t("quit.farewell_subtitle")))
.replace("__CLOSE_BTN__", _js_html_safe(_t("quit.close_window_button")))
.replace("__CLOSE_HINT__", _js_html_safe(_t("quit.close_hint")))
) )
@@ -2960,10 +2954,12 @@ def render_findings_panel(
) )
for i, f in sorted_findings: for i, f in sorted_findings:
_render_finding_row_v2(f, row_key=f"{ns}_{i}") _render_finding_row_v2(
f, row_key=f"{ns}_{i}", filename=header,
)
def _render_finding_row_v2(f, *, row_key: str) -> None: def _render_finding_row_v2(f, *, row_key: str, filename: str = "") -> None:
"""One row inside the per-file findings card. """One row inside the per-file findings card.
Layout: severity chip (col 1) · title + meta (col 2) · "Open Tool" Layout: severity chip (col 1) · title + meta (col 2) · "Open Tool"
@@ -3025,6 +3021,18 @@ def _render_finding_row_v2(f, *, row_key: str) -> None:
type="tertiary", type="tertiary",
width="content", width="content",
): ):
# Set the active file to the one this finding came from
# BEFORE switching pages — otherwise the tool page's
# ``pickup_or_upload`` reads the home page's "default to
# first imported file" state, losing the context of the
# card the user clicked. ``filename`` is the per-file
# findings group header.
home_uploads = st.session_state.get("home_uploads", {})
meta = home_uploads.get(filename) if filename else None
if meta:
st.session_state["home_uploaded_name"] = filename
st.session_state["home_uploaded_size"] = meta["size"]
st.session_state["home_uploaded_bytes"] = meta["bytes"]
st.switch_page(page_slug) st.switch_page(page_slug)
body_html = f'<p class="dt-finding-title">{title_html}</p>' body_html = f'<p class="dt-finding-title">{title_html}</p>'