awacke1 commited on
Commit
c0ef2f1
·
verified ·
1 Parent(s): eeb7d45

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +75 -34
app.py CHANGED
@@ -16,7 +16,6 @@ import edge_tts
16
  from audio_recorder_streamlit import audio_recorder
17
  import nest_asyncio
18
  import re
19
- from streamlit_paste_button import paste_image_button
20
  import pytz
21
  import shutil
22
  import anthropic
@@ -128,7 +127,7 @@ def init_session_state():
128
  'autosend': True, 'autosearch': True, 'last_message': "", 'last_query': "",
129
  'mp3_files': {}, 'timer_start': time.time(), 'quote_index': 0,
130
  'quote_source': "famous", 'last_sent_transcript': "", 'old_val': None,
131
- 'last_refresh': time.time(), 'paper_metadata': {}, 'paste_trigger': False
132
  }
133
  for k, v in defaults.items():
134
  if k not in st.session_state:
@@ -564,6 +563,53 @@ def create_zip_of_files(md_files, mp3_files, png_files, mp4_files, query):
564
  [z.write(f) for f in all_files]
565
  return zip_name
566
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
567
  # 🎮 Main Interface
568
  def main():
569
  init_session_state()
@@ -610,40 +656,35 @@ def main():
610
  st.code(numbered_content, language="python")
611
 
612
  message = st.text_input(f"Message as {st.session_state.username}", key="message_input")
613
- paste_result = paste_image_button("Paste Image 📋", key=f"paste_button_msg_{int(time.time())}") # Dynamic key to force re-render
614
- if paste_result.image_data is not None and not st.session_state['paste_trigger']:
615
- st.session_state['paste_trigger'] = True
 
 
616
  voice = FUN_USERNAMES.get(st.session_state.username, "en-US-AriaNeural")
617
- if isinstance(paste_result.image_data, str):
618
- st.session_state.message_text = paste_result.image_data
619
- message = st.text_input(f"Message as {st.session_state.username}", key="message_input_paste", value=st.session_state.message_text)
620
- else:
621
- st.image(paste_result.image_data, caption="Pasted Image")
622
- filename = asyncio.run(save_pasted_image(paste_result.image_data, st.session_state.username))
623
- if filename:
624
- st.session_state.pasted_image_data = filename
625
- # Allow user to add text to accompany the image
626
- image_prompt = st.text_input("Add a prompt for Claude (e.g., 'OCR this image')", key="image_prompt")
627
- if image_prompt:
628
- # Run Claude search with both text and image
629
- md_file_claude, audio_file_claude, claude_result = asyncio.run(
630
- perform_claude_search(image_prompt, st.session_state.username, paste_result.image_data)
631
- )
632
- if audio_file_claude:
633
- play_and_download_audio(audio_file_claude)
634
- # Feed Claude result to ArXiv search
635
- md_file_arxiv, audio_file_arxiv = asyncio.run(
636
- perform_arxiv_search(image_prompt, st.session_state.username, claude_result)
637
- )
638
- if audio_file_arxiv:
639
- play_and_download_audio(audio_file_arxiv)
640
- st.session_state.pasted_image_data = None
641
- st.session_state['paste_trigger'] = False
642
- st.session_state.timer_start = time.time()
643
- save_username(st.session_state.username)
644
- st.rerun()
645
 
646
- if (message and message != st.session_state.last_message) or (st.session_state.pasted_image_data and not st.session_state['paste_trigger']):
647
  st.session_state.last_message = message
648
  col_send, col_claude, col_arxiv = st.columns([1, 1, 1])
649
 
 
16
  from audio_recorder_streamlit import audio_recorder
17
  import nest_asyncio
18
  import re
 
19
  import pytz
20
  import shutil
21
  import anthropic
 
127
  'autosend': True, 'autosearch': True, 'last_message': "", 'last_query': "",
128
  'mp3_files': {}, 'timer_start': time.time(), 'quote_index': 0,
129
  'quote_source': "famous", 'last_sent_transcript': "", 'old_val': None,
130
+ 'last_refresh': time.time(), 'paper_metadata': {}, 'paste_image_base64': None
131
  }
132
  for k, v in defaults.items():
133
  if k not in st.session_state:
 
563
  [z.write(f) for f in all_files]
564
  return zip_name
565
 
566
+ # Custom Paste Image Component
567
+ def paste_image_component():
568
+ # JavaScript to capture clipboard image and send it to Streamlit
569
+ paste_script = """
570
+ <script>
571
+ function pasteImage() {
572
+ navigator.clipboard.read().then(clipboardItems => {
573
+ for (const item of clipboardItems) {
574
+ if (item.types.includes('image/png') || item.types.includes('image/jpeg')) {
575
+ item.getType('image/png').then(blob => {
576
+ const reader = new FileReader();
577
+ reader.onload = function(event) {
578
+ document.getElementById('paste_input').value = event.target.result.split(',')[1];
579
+ document.getElementById('paste_form').submit();
580
+ };
581
+ reader.readAsDataURL(blob);
582
+ });
583
+ break;
584
+ }
585
+ }
586
+ }).catch(err => {
587
+ console.error('Failed to read clipboard: ', err);
588
+ document.getElementById('paste_input').value = 'ERROR: ' + err.message;
589
+ document.getElementById('paste_form').submit();
590
+ });
591
+ }
592
+ </script>
593
+ <form id="paste_form" action="/" method="POST" style="display: none;">
594
+ <input type="text" id="paste_input" name="paste_data" />
595
+ </form>
596
+ <button onclick="pasteImage()">Paste Image 📋</button>
597
+ """
598
+ paste_data = components.html(paste_script, height=50)
599
+ if paste_data and 'paste_data' in paste_data:
600
+ base64_str = paste_data['paste_data']
601
+ if base64_str.startswith('ERROR:'):
602
+ st.warning(f"Paste failed: {base64_str}")
603
+ return None
604
+ try:
605
+ img_bytes = base64.b64decode(base64_str)
606
+ img = Image.open(io.BytesIO(img_bytes))
607
+ return img
608
+ except Exception as e:
609
+ st.warning(f"Error decoding pasted image: {e}")
610
+ return None
611
+ return None
612
+
613
  # 🎮 Main Interface
614
  def main():
615
  init_session_state()
 
656
  st.code(numbered_content, language="python")
657
 
658
  message = st.text_input(f"Message as {st.session_state.username}", key="message_input")
659
+
660
+ # Custom Paste Image Button
661
+ pasted_image = paste_image_component()
662
+ if pasted_image is not None and st.session_state['paste_image_base64'] != pasted_image.tobytes():
663
+ st.session_state['paste_image_base64'] = pasted_image.tobytes()
664
  voice = FUN_USERNAMES.get(st.session_state.username, "en-US-AriaNeural")
665
+ st.image(pasted_image, caption="Pasted Image")
666
+ filename = asyncio.run(save_pasted_image(pasted_image, st.session_state.username))
667
+ if filename:
668
+ st.session_state.pasted_image_data = filename
669
+ image_prompt = st.text_input("Add a prompt for Claude (e.g., 'OCR this image')", key="image_prompt")
670
+ if image_prompt:
671
+ md_file_claude, audio_file_claude, claude_result = asyncio.run(
672
+ perform_claude_search(image_prompt, st.session_state.username, pasted_image)
673
+ )
674
+ if audio_file_claude:
675
+ play_and_download_audio(audio_file_claude)
676
+ md_file_arxiv, audio_file_arxiv = asyncio.run(
677
+ perform_arxiv_search(image_prompt, st.session_state.username, claude_result)
678
+ )
679
+ if audio_file_arxiv:
680
+ play_and_download_audio(audio_file_arxiv)
681
+ st.session_state.pasted_image_data = None
682
+ st.session_state['paste_image_base64'] = None
683
+ st.session_state.timer_start = time.time()
684
+ save_username(st.session_state.username)
685
+ st.rerun()
 
 
 
 
 
 
 
686
 
687
+ if (message and message != st.session_state.last_message) or (st.session_state.pasted_image_data and not st.session_state['paste_image_base64']):
688
  st.session_state.last_message = message
689
  col_send, col_claude, col_arxiv = st.columns([1, 1, 1])
690