saad-sust commited on
Commit
e02a2d8
Β·
1 Parent(s): 70d1fc9

Upload app.py

Browse files
Files changed (1) hide show
  1. app.py +55 -135
app.py CHANGED
@@ -406,6 +406,8 @@ if "attached_file_name" not in st.session_state:
406
  st.session_state.attached_file_name = None
407
  if "attached_file_mime" not in st.session_state:
408
  st.session_state.attached_file_mime = None
 
 
409
 
410
  # ════════════════════════════════════════════════════════════════════
411
  # SUPABASE β€” Persistent chat history
@@ -2858,156 +2860,74 @@ for i, msg in enumerate(st.session_state.messages):
2858
  st.code(msg["content"], language=None)
2859
 
2860
  # ════════════════════════════════════════════════════════════════════
2861
- # FILE ATTACH β€” ChatGPT-style: πŸ“Ž button right next to the send bar
2862
- # The file uploader is hidden in the DOM; JS click triggers it.
2863
  # ════════════════════════════════════════════════════════════════════
2864
 
2865
- # ── Hidden uploader β€” rendered but invisible, triggered by JS ────
2866
- main_uploader = st.file_uploader(
2867
- "main_attach",
2868
- type=["jpg", "jpeg", "png", "webp", "pdf"],
2869
- label_visibility="collapsed",
2870
- key="main_uploader"
2871
- )
2872
- if main_uploader:
2873
- _fkey = f"{main_uploader.size}_{main_uploader.type}"
2874
- if _fkey != st.session_state.get("last_uploaded_file", ""):
2875
- st.session_state["last_uploaded_file"] = _fkey
2876
- st.session_state.pending_file_bytes = main_uploader.read()
2877
- st.session_state.pending_file_name = main_uploader.name
2878
- st.session_state.pending_file_mime = main_uploader.type or "application/octet-stream"
2879
- st.rerun()
2880
-
2881
- # ── Status values ─────────────────────────────────────────────────
2882
- _pending = st.session_state.pending_file_bytes is not None
2883
- _memfile = st.session_state.attached_file_name
2884
 
 
2885
  if _pending:
2886
- _fname = st.session_state.pending_file_name
2887
- _status = f"βœ… <b>{_fname}</b> β€” ready Β· type your question and press Enter"
2888
- _bcolor = "#0d2318"
2889
- _bborder = "#22c55e"
2890
- _tcolor = "#86efac"
2891
- elif _memfile:
2892
- _status = f"πŸ“Ž <b>{_memfile}</b> in memory β€” ask a follow-up or click πŸ“Ž to attach new"
2893
- _bcolor = "#0d1a2e"
2894
- _bborder = "#3b82f6"
2895
- _tcolor = "#93c5fd"
2896
- else:
2897
- _status = "Click <b>πŸ“Ž</b> below to attach an image or PDF"
2898
- _bcolor = "#111827"
2899
- _bborder = "#2d3748"
2900
- _tcolor = "#6b7280"
2901
-
2902
- # ── Fixed bar: [πŸ“Ž button] [status text] [βœ• if file exists] ──────
2903
- st.markdown(
2904
- f"""
2905
- <style>
2906
- /* Hide the Streamlit file-uploader widget β€” triggered via JS */
2907
- [data-testid="stFileUploader"] {{
2908
- visibility: hidden !important;
2909
- height: 0 !important;
2910
- min-height: 0 !important;
2911
- overflow: hidden !important;
2912
- margin: 0 !important;
2913
- padding: 0 !important;
2914
- position: absolute !important;
2915
- pointer-events: none !important;
2916
- }}
2917
- /* Keep the actual <input type=file> reachable by JS */
2918
- [data-testid="stFileUploaderDropzoneInput"] {{
2919
- visibility: visible !important;
2920
- pointer-events: auto !important;
2921
- }}
2922
- /* Hide the Streamlit βœ• clear-buttons below β€” they're fired by JS */
2923
- div[data-testid="stHorizontalBlock"]:has(button[kind="secondary"]) {{
2924
- visibility: hidden !important;
2925
- height: 0 !important;
2926
- overflow: hidden !important;
2927
- margin: 0 !important;
2928
- padding: 0 !important;
2929
- position: absolute !important;
2930
- }}
2931
- </style>
2932
-
2933
- <script>
2934
- function saadAttach() {{
2935
- var inp = document.querySelector('[data-testid="stFileUploaderDropzoneInput"]');
2936
- if (inp) {{ inp.click(); }}
2937
- }}
2938
- function saadClearFile() {{
2939
- /* Find and click the Streamlit βœ• button by its text content */
2940
- var btns = document.querySelectorAll('button');
2941
- for (var b of btns) {{
2942
- if (b.innerText.trim() === 'βœ•') {{ b.click(); break; }}
2943
- }}
2944
- }}
2945
- </script>
2946
-
2947
- <!-- Fixed attach bar just above the chat input -->
2948
- <div style="
2949
- position: fixed;
2950
- bottom: 68px;
2951
- left: 50%;
2952
- transform: translateX(-50%);
2953
- width: 720px;
2954
- max-width: 88vw;
2955
- display: flex;
2956
- align-items: center;
2957
- gap: 8px;
2958
- z-index: 9999;
2959
- ">
2960
- <!-- πŸ“Ž Paperclip button β€” triggers hidden file input -->
2961
- <button onclick="saadAttach()" title="Attach image or PDF"
2962
- style="flex-shrink:0; width:40px; height:36px;
2963
- background:#1e293b; border:1.5px solid #334155;
2964
- border-radius:9px; cursor:pointer; font-size:17px;
2965
- color:#9ca3af; line-height:1; transition:all .15s;"
2966
- onmouseover="this.style.background='#334155';this.style.borderColor='#60a5fa';this.style.color='#93c5fd';"
2967
- onmouseout="this.style.background='#1e293b';this.style.borderColor='#334155';this.style.color='#9ca3af';">
2968
- πŸ“Ž
2969
- </button>
2970
- <!-- Status pill -->
2971
- <div style="flex:1; background:{_bcolor}; border:1px solid {_bborder};
2972
- border-radius:9px; padding:6px 14px; font-size:0.79rem;
2973
- color:{_tcolor}; white-space:nowrap; overflow:hidden;
2974
- text-overflow:ellipsis;">
2975
- {_status}
2976
- </div>
2977
- {"""<!-- βœ• clear button -->
2978
- <button onclick="saadClearFile()" title="Remove file"
2979
- style="flex-shrink:0; width:30px; height:30px;
2980
- background:transparent; border:1px solid #4b5563;
2981
- border-radius:7px; cursor:pointer; font-size:13px;
2982
- color:#9ca3af; line-height:1; transition:all .15s;"
2983
- onmouseover="this.style.borderColor='#f87171';this.style.color='#f87171';"
2984
- onmouseout="this.style.borderColor='#4b5563';this.style.color='#9ca3af';">
2985
- βœ•
2986
- </button>""" if (_pending or _memfile) else ""}
2987
- </div>
2988
- """,
2989
- unsafe_allow_html=True
2990
- )
2991
-
2992
- # ── Real Streamlit clear-buttons (hidden by CSS, fired by JS above) ─
2993
- if _pending:
2994
- col_sp, col_rm = st.columns([11, 1])
2995
- with col_rm:
2996
- if st.button("βœ•", key="remove_pending", help="Remove file"):
2997
  st.session_state.pending_file_bytes = None
2998
  st.session_state.pending_file_name = None
2999
  st.session_state.pending_file_mime = None
3000
  st.session_state["last_uploaded_file"] = ""
 
3001
  st.rerun()
 
3002
  elif _memfile:
3003
- col_sp, col_rm = st.columns([11, 1])
3004
- with col_rm:
3005
- if st.button("βœ•", key="clear_memory_file", help="Clear file memory"):
 
 
 
 
 
 
 
3006
  st.session_state.attached_file_bytes = None
3007
  st.session_state.attached_file_name = None
3008
  st.session_state.attached_file_mime = None
3009
  st.rerun()
3010
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3011
  # ═══════════════���════════════════════════════════════════════════════
3012
  # INPUT β€” ChatGPT-style input bar
3013
  # ════════════════════════════════════════════════════════════════════
 
406
  st.session_state.attached_file_name = None
407
  if "attached_file_mime" not in st.session_state:
408
  st.session_state.attached_file_mime = None
409
+ if "show_uploader" not in st.session_state:
410
+ st.session_state.show_uploader = False
411
 
412
  # ════════════════════════════════════════════════════════════════════
413
  # SUPABASE β€” Persistent chat history
 
2860
  st.code(msg["content"], language=None)
2861
 
2862
  # ════════════════════════════════════════════════════════════════════
2863
+ # FILE ATTACH β€” FIXED: real Streamlit button toggle (no JS tricks)
2864
+ # Works reliably on HuggingFace Spaces β€” no iframe/JS issues
2865
  # ════════════════════════════════════════════════════════════════════
2866
 
2867
+ _pending = st.session_state.pending_file_bytes is not None
2868
+ _memfile = st.session_state.attached_file_name
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2869
 
2870
+ # ── Status bar ───────────────────────────────────────────────────────
2871
  if _pending:
2872
+ col_s, col_x = st.columns([9, 1])
2873
+ with col_s:
2874
+ st.markdown(
2875
+ f'<div style="background:#0d2318;border:1px solid #22c55e;border-radius:10px;'
2876
+ f'padding:0.5rem 0.9rem;font-size:0.8rem;color:#86efac;margin-bottom:0.3rem;">'
2877
+ f'βœ… <b>{st.session_state.pending_file_name}</b> β€” ready Β· type your question and press Enter</div>',
2878
+ unsafe_allow_html=True
2879
+ )
2880
+ with col_x:
2881
+ if st.button("βœ•", key="rm_pending", help="Remove file"):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2882
  st.session_state.pending_file_bytes = None
2883
  st.session_state.pending_file_name = None
2884
  st.session_state.pending_file_mime = None
2885
  st.session_state["last_uploaded_file"] = ""
2886
+ st.session_state.show_uploader = False
2887
  st.rerun()
2888
+
2889
  elif _memfile:
2890
+ col_s, col_x = st.columns([9, 1])
2891
+ with col_s:
2892
+ st.markdown(
2893
+ f'<div style="background:#0d1a2e;border:1px solid #3b82f6;border-radius:10px;'
2894
+ f'padding:0.5rem 0.9rem;font-size:0.8rem;color:#93c5fd;margin-bottom:0.3rem;">'
2895
+ f'πŸ“Ž <b>{_memfile}</b> in memory β€” ask a follow-up or click πŸ“Ž to attach new</div>',
2896
+ unsafe_allow_html=True
2897
+ )
2898
+ with col_x:
2899
+ if st.button("βœ•", key="rm_attached", help="Clear file memory"):
2900
  st.session_state.attached_file_bytes = None
2901
  st.session_state.attached_file_name = None
2902
  st.session_state.attached_file_mime = None
2903
  st.rerun()
2904
 
2905
+ # ── πŸ“Ž Attach toggle button ──────────────────────────────────────────
2906
+ attach_col, _ = st.columns([1, 8])
2907
+ with attach_col:
2908
+ btn_label = "πŸ“Ž Attached" if (st.session_state.show_uploader or _pending) else "πŸ“Ž Attach"
2909
+ if st.button(btn_label, key="toggle_uploader", help="Attach image or PDF"):
2910
+ st.session_state.show_uploader = not st.session_state.show_uploader
2911
+ st.rerun()
2912
+
2913
+ # ── Real file uploader β€” only shown when toggled on ──────────────────
2914
+ if st.session_state.show_uploader and not _pending:
2915
+ uploaded = st.file_uploader(
2916
+ "Upload image or PDF",
2917
+ type=["jpg", "jpeg", "png", "webp", "pdf"],
2918
+ label_visibility="collapsed",
2919
+ key="main_uploader"
2920
+ )
2921
+ if uploaded is not None:
2922
+ _fkey = f"{uploaded.size}_{uploaded.type}_{uploaded.name}"
2923
+ if _fkey != st.session_state.get("last_uploaded_file", ""):
2924
+ st.session_state["last_uploaded_file"] = _fkey
2925
+ st.session_state.pending_file_bytes = uploaded.read()
2926
+ st.session_state.pending_file_name = uploaded.name
2927
+ st.session_state.pending_file_mime = uploaded.type or "application/octet-stream"
2928
+ st.session_state.show_uploader = False
2929
+ st.rerun()
2930
+
2931
  # ═══════════════���════════════════════════════════════════════════════
2932
  # INPUT β€” ChatGPT-style input bar
2933
  # ════════════════════════════════════════════════════════════════════