fix(pdf): stamp scan timestamp once; restores Saved-to-path banner

After swapping to ``html_download_button`` the user noticed the
"✓ Saved to <path>" + 📂 Open Downloads folder pair never
appeared. The helper itself is fine — every other tool shows
those affordances correctly. Bug was specific to the PDF page.

The download button's file_name was being computed with a fresh
``datetime.now().strftime(...)`` on every render. The helper
builds its session-state keys from
``f"_dl_btn_{file_name}_{digest}"`` so the keys silently drift
every second. After the click and rerun, the helper looks up
the saved_key for the NEW file_name, finds nothing in
session_state (the click had written to the OLD key), and skips
the success banner.

Fix: stamp the timestamp once when scan completes, store it in
``K_TIMESTAMP``, and reuse it for the download filename. The
filename stays stable across reruns, so the helper's keys are
stable, so the saved-path banner renders correctly on the post-
click rerun.

Also clear ``K_TIMESTAMP`` on Clear-all-files so a new scan
gets a fresh stamp.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-20 01:50:22 +00:00
parent 981a1a9cba
commit a18b126885

View File

@@ -65,6 +65,13 @@ render_sticky_footer()
K_ROWS = "pdf_scan_rows"
K_WARNINGS = "pdf_scan_warnings"
K_SOURCE_COUNT = "pdf_scan_source_count"
# Stamped once at scan time. The download button's file_name
# embeds this so the user gets a unique-per-scan filename — but
# crucially, the value is stable across reruns triggered by
# unrelated widget interactions (otherwise the html_download_button
# helper's session-state key drifts every second and the
# "Saved to <path>" banner never gets to render).
K_TIMESTAMP = "pdf_scan_timestamp"
# ``pdf_uploads`` is the persistent stash of uploaded PDFs (dict
# keyed by filename → {"bytes": ..., "size": ...}). It survives
# Streamlit reruns and navigation away from the page. The
@@ -386,7 +393,7 @@ with c_clear:
):
st.session_state[K_UPLOADS] = {}
st.session_state[K_UPLOAD_COUNTER] = upload_counter + 1
for k in (K_ROWS, K_WARNINGS, K_SOURCE_COUNT):
for k in (K_ROWS, K_WARNINGS, K_SOURCE_COUNT, K_TIMESTAMP):
st.session_state.pop(k, None)
log_event(
"upload",
@@ -441,6 +448,7 @@ if scan_clicked and pdf_uploads:
st.session_state[K_ROWS] = all_rows
st.session_state[K_WARNINGS] = all_warnings
st.session_state[K_SOURCE_COUNT] = n_files
st.session_state[K_TIMESTAMP] = datetime.now().strftime("%Y%m%d-%H%M%S")
log_event(
"tool_run",
@@ -606,7 +614,10 @@ else:
if selected.empty:
st.button("Download CSV", disabled=True)
else:
ts = datetime.now().strftime("%Y%m%d-%H%M%S")
# Reuse the timestamp stamped when this scan finished —
# stable across reruns so the download helper's button
# key doesn't drift every second.
ts = st.session_state.get(K_TIMESTAMP) or "results"
# Default: drop the internal columns from the download.
keep_default = [
c for c in selected.columns