import json import streamlit as st import streamlit.components.v1 as components from utils.security import escape_html def render_persistence_bridge() -> None: """Sync watchlist + ticker to/from localStorage.""" restored_wl = st.session_state.get("_persist_wl", "") restored_tk = st.session_state.get("_persist_tk", "") if restored_wl and not st.session_state.get("_persist_loaded"): try: st.session_state["watchlist"] = json.loads(restored_wl) except Exception: pass if restored_tk: st.session_state["ticker"] = restored_tk st.session_state["_persist_loaded"] = True # No st.rerun() — the bridge runs at the top of the render cycle so the # restored values propagate naturally to components below. Calling # st.rerun() here would abort the render before click-receiver inputs # (qt_click_receiver, wl_click_receiver) are registered, causing # Streamlit to clear their pending values and swallow the click. st.text_input("persist_wl", key="_persist_wl", label_visibility="collapsed") st.text_input("persist_tk", key="_persist_tk", label_visibility="collapsed") loaded = "1" if st.session_state.get("_persist_loaded") else "0" wl_json = escape_html(json.dumps(st.session_state.get("watchlist", []))) tk_val = escape_html(st.session_state.get("ticker") or "") html = ( "
" "" ) components.html(html, height=0, scrolling=False)