import base64 import os from urllib import request from pathlib import Path import streamlit as st def _icon_data_uri(filename: str) -> str: icon_path = Path(__file__).resolve().parent.parent / "icons" / filename if not icon_path.exists(): return "" try: encoded = base64.b64encode(icon_path.read_bytes()).decode("ascii") except Exception: return "" return f"data:image/png;base64,{encoded}" def _build_sidebar_icon_css() -> str: """Use named icons for sidebar items: home/prob/batch/molecule/manual/ai.""" fallback = { 1: "🏠", 2: "🔎", 3: "📦", 4: "🧬", 5: "⚙️", 6: "🧠", 7: "✨", 8: "💬", } icon_name = { 1: "home1.png", 2: "probe1.png", 3: "batch1.png", 4: "molecule1.png", 5: "manual1.png", 6: "ai1.png", 7: "rnn1.png", 8: "feedback.png", } rules = [ '[data-testid="stSidebarNav"] ul li a { position: relative; padding-left: 3.9rem !important; }', '[data-testid="stSidebarNav"] ul li a::before { content: ""; position: absolute; left: 10px; top: 50%; transform: translateY(-50%); width: 46px; height: 46px; background-size: contain; background-repeat: no-repeat; background-position: center; }', ] for idx in range(1, 9): uri = _icon_data_uri(icon_name[idx]) if uri: rules.append( '[data-testid="stSidebarNav"] ul li:nth-of-type(%d) a::before { content: ""; background-image: url("%s"); }' % (idx, uri) ) else: emoji = fallback[idx] rules.append( '[data-testid="stSidebarNav"] ul li:nth-of-type(%d) a::before { content: "%s "; background-image: none; width: auto; height: auto; }' % (idx, emoji) ) return "\n".join(rules) def _log_visit_once_per_session() -> None: if st.session_state.get("_visit_logged"): return webhook_url = os.getenv("FEEDBACK_WEBHOOK_URL", "").strip() webhook_token = os.getenv("FEEDBACK_WEBHOOK_TOKEN", "").strip() if not webhook_url: return endpoint = webhook_url sep = "&" if "?" in webhook_url else "?" endpoint = f"{webhook_url}{sep}event=visit" if webhook_token: endpoint = f"{endpoint}&token={webhook_token}" try: with request.urlopen(endpoint, timeout=10): pass except Exception: pass st.session_state["_visit_logged"] = True def apply_global_style() -> None: _log_visit_once_per_session() icon_css = _build_sidebar_icon_css() css = """ """ st.markdown(css.replace("__ICON_CSS__", icon_css), unsafe_allow_html=True)