awacke1 commited on
Commit
4565252
β€’
1 Parent(s): d5aeedf

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +72 -54
app.py CHANGED
@@ -57,6 +57,10 @@ if 'edit_new_name' not in st.session_state:
57
  st.session_state['edit_new_name'] = ""
58
  if 'edit_new_content' not in st.session_state:
59
  st.session_state['edit_new_content'] = ""
 
 
 
 
60
  if 'should_rerun' not in st.session_state:
61
  st.session_state['should_rerun'] = False
62
 
@@ -84,14 +88,14 @@ def generate_filename(prompt, file_type="md"):
84
  return f"{date_str}_{safe}.{file_type}"
85
 
86
  def create_file(filename, prompt, response):
87
- # Just create the file. Do not rerun automatically here.
88
  with open(filename, 'w', encoding='utf-8') as f:
89
  f.write(prompt + "\n\n" + response)
90
 
91
  def get_download_link(file):
92
  with open(file, "rb") as f:
93
  b64 = base64.b64encode(f.read()).decode()
94
- return f'<a href="data:file/txt;base64,{b64}" download="{os.path.basename(file)}">πŸ“‚ Download {os.path.basename(file)}</a>'
95
 
96
  @st.cache_resource
97
  def speech_synthesis_html(result):
@@ -106,7 +110,7 @@ def speech_synthesis_html(result):
106
  components.html(html_code, height=0)
107
 
108
  async def edge_tts_generate_audio(text, voice="en-US-AriaNeural", rate=0, pitch=0):
109
- # Create mp3 file. Do not trigger rerun here.
110
  if not text.strip():
111
  return None
112
  rate_str = f"{rate:+d}%"
@@ -122,7 +126,8 @@ def speak_with_edge_tts(text, voice="en-US-AriaNeural", rate=0, pitch=0):
122
  def play_and_download_audio(file_path):
123
  if file_path and os.path.exists(file_path):
124
  st.audio(file_path)
125
- st.markdown(get_download_link(file_path), unsafe_allow_html=True)
 
126
 
127
  def process_image(image_path, user_prompt):
128
  with open(image_path, "rb") as imgf:
@@ -142,10 +147,10 @@ def process_image(image_path, user_prompt):
142
  return resp.choices[0].message.content
143
 
144
  def process_audio(audio_path):
145
- # Creating transcription does not force rerun here.
146
  with open(audio_path, "rb") as f:
147
  transcription = openai_client.audio.transcriptions.create(model="whisper-1", file=f)
148
  st.session_state.messages.append({"role": "user", "content": transcription.text})
 
149
  return transcription.text
150
 
151
  def process_video(video_path, seconds_per_frame=1):
@@ -200,7 +205,6 @@ def perform_ai_lookup(q, vocal_summary=True, extended_refs=False, titles_summary
200
 
201
  if vocal_summary:
202
  audio_file_main = speak_with_edge_tts(r2, voice="en-US-AriaNeural", rate=0, pitch=0)
203
- # audio_file_main is created but we do not rerun
204
  st.write("### πŸŽ™οΈ Vocal Summary (Short Answer)")
205
  play_and_download_audio(audio_file_main)
206
 
@@ -261,16 +265,24 @@ def process_with_claude(text):
261
  st.session_state.chat_history.append({"user":text,"claude":ans})
262
  return ans
263
 
264
- def create_zip_of_files():
265
- md_files = glob.glob("*.md")
266
- mp3_files = glob.glob("*.mp3")
 
267
  all_files = md_files + mp3_files
268
- zip_name = "all_files.zip"
 
 
 
 
 
 
 
 
 
269
  with zipfile.ZipFile(zip_name,'w') as z:
270
  for f in all_files:
271
  z.write(f)
272
- # user action triggered, set rerun
273
- st.session_state.should_rerun = True
274
  return zip_name
275
 
276
  def get_media_html(p,typ="video",w="100%"):
@@ -285,11 +297,12 @@ def load_files_for_sidebar():
285
  md_files = glob.glob("*.md")
286
  mp3_files = glob.glob("*.mp3")
287
 
 
 
 
288
  files_by_ext = defaultdict(list)
289
- for f in md_files:
290
- files_by_ext['md'].append(f)
291
- for f in mp3_files:
292
- files_by_ext['mp3'].append(f)
293
 
294
  # Sort each extension group by modification time descending
295
  for ext in files_by_ext:
@@ -302,72 +315,64 @@ def display_file_manager_sidebar(files_by_ext):
302
  md_files = files_by_ext.get('md', [])
303
  mp3_files = files_by_ext.get('mp3', [])
304
 
305
- col_del = st.sidebar.columns(2)
 
306
  with col_del[0]:
307
- if st.button("πŸ—‘ Delete All MD"):
308
  for f in md_files:
309
  os.remove(f)
310
  st.session_state.should_rerun = True
311
  with col_del[1]:
312
- if st.button("πŸ—‘ Delete All MP3"):
313
  for f in mp3_files:
314
  os.remove(f)
315
  st.session_state.should_rerun = True
 
 
 
 
 
 
316
 
317
  ext_counts = {ext: len(files) for ext, files in files_by_ext.items()}
318
  sorted_ext = sorted(files_by_ext.keys(), key=lambda x: ext_counts[x], reverse=True)
319
 
 
320
  for ext in sorted_ext:
321
  emoji = FILE_EMOJIS.get(ext, "πŸ“¦")
322
  count = len(files_by_ext[ext])
323
- with st.sidebar.expander(f"{emoji} {ext.upper()} Files ({count})"):
324
  for f in files_by_ext[ext]:
325
  fname = os.path.basename(f)
326
  ctime = datetime.fromtimestamp(os.path.getmtime(f)).strftime("%Y-%m-%d %H:%M:%S")
327
- col1, col2, col3, col4 = st.columns([2,1,1,1])
328
- with col1:
329
- st.write(f"**{fname}** - {ctime}")
330
- with col2:
331
- # View button
332
- if ext == "md":
333
- if st.button("πŸ‘€", key="view_"+f):
334
- content = open(f,'r',encoding='utf-8').read()
335
- st.write("**Viewing file content:**")
336
- st.markdown(content)
337
- else: # mp3
338
- if st.button("πŸ‘€", key="view_"+f):
339
- st.write(f"Playing: {fname}")
340
- st.audio(f)
341
- with col3:
342
- # Edit button for MD
343
  if ext == "md":
344
- if st.button("✏️", key="edit_"+f):
345
  st.session_state.editing_file = f
346
  st.session_state.edit_new_name = fname.replace(".md","")
347
  st.session_state.edit_new_content = open(f,'r',encoding='utf-8').read()
348
- # user triggered, set rerun
349
  st.session_state.should_rerun = True
350
- else:
351
- pass
352
- with col4:
353
- # Delete button
354
- if st.button("πŸ—‘", key="del_"+f):
355
  os.remove(f)
356
- # user triggered, set rerun
357
  st.session_state.should_rerun = True
358
 
359
- if (len(md_files) > 0 or len(mp3_files) > 0) and st.sidebar.button("⬇️ Download All (.md and .mp3)"):
360
- z = create_zip_of_files()
361
- st.sidebar.markdown(get_download_link(z),unsafe_allow_html=True)
362
-
363
  # If editing an md file
364
  if st.session_state.editing_file and os.path.exists(st.session_state.editing_file):
365
  st.sidebar.subheader(f"Editing: {os.path.basename(st.session_state.editing_file)}")
366
- st.session_state.edit_new_name = st.sidebar.text_input("New name (without extension):", value=st.session_state.edit_new_name)
367
  st.session_state.edit_new_content = st.sidebar.text_area("Content:", st.session_state.edit_new_content, height=200)
368
  c1,c2 = st.sidebar.columns(2)
369
  with c1:
370
- if st.button("Save Changes"):
371
  old_path = st.session_state.editing_file
372
  new_path = st.session_state.edit_new_name + ".md"
373
  if new_path != os.path.basename(old_path):
@@ -375,12 +380,10 @@ def display_file_manager_sidebar(files_by_ext):
375
  with open(new_path,'w',encoding='utf-8') as f:
376
  f.write(st.session_state.edit_new_content)
377
  st.session_state.editing_file = None
378
- # user triggered, set rerun
379
  st.session_state.should_rerun = True
380
  with c2:
381
  if st.button("Cancel"):
382
  st.session_state.editing_file = None
383
- # user triggered, set rerun
384
  st.session_state.should_rerun = True
385
 
386
  def main():
@@ -506,7 +509,6 @@ def main():
506
  with open(st.session_state.current_file,'w',encoding='utf-8') as f:
507
  f.write(new_text)
508
  st.success("Updated!")
509
- # user action: rename or save
510
  st.session_state.should_rerun = True
511
  else:
512
  st.write("Select a file from the sidebar to edit.")
@@ -515,7 +517,23 @@ def main():
515
  files_by_ext = load_files_for_sidebar()
516
  display_file_manager_sidebar(files_by_ext)
517
 
518
- # If user triggered changes require a rerun, do it now
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
519
  if st.session_state.should_rerun:
520
  st.session_state.should_rerun = False
521
  st.rerun()
 
57
  st.session_state['edit_new_name'] = ""
58
  if 'edit_new_content' not in st.session_state:
59
  st.session_state['edit_new_content'] = ""
60
+ if 'viewing_file' not in st.session_state:
61
+ st.session_state['viewing_file'] = None
62
+ if 'viewing_file_type' not in st.session_state:
63
+ st.session_state['viewing_file_type'] = None
64
  if 'should_rerun' not in st.session_state:
65
  st.session_state['should_rerun'] = False
66
 
 
88
  return f"{date_str}_{safe}.{file_type}"
89
 
90
  def create_file(filename, prompt, response):
91
+ # Creating file does not trigger immediate rerun
92
  with open(filename, 'w', encoding='utf-8') as f:
93
  f.write(prompt + "\n\n" + response)
94
 
95
  def get_download_link(file):
96
  with open(file, "rb") as f:
97
  b64 = base64.b64encode(f.read()).decode()
98
+ return f'<a href="data:file/zip;base64,{b64}" download="{os.path.basename(file)}">πŸ“‚ Download {os.path.basename(file)}</a>'
99
 
100
  @st.cache_resource
101
  def speech_synthesis_html(result):
 
110
  components.html(html_code, height=0)
111
 
112
  async def edge_tts_generate_audio(text, voice="en-US-AriaNeural", rate=0, pitch=0):
113
+ # Just create mp3 file, no immediate rerun
114
  if not text.strip():
115
  return None
116
  rate_str = f"{rate:+d}%"
 
126
  def play_and_download_audio(file_path):
127
  if file_path and os.path.exists(file_path):
128
  st.audio(file_path)
129
+ dl_link = f'<a href="data:audio/mpeg;base64,{base64.b64encode(open(file_path,"rb").read()).decode()}" download="{os.path.basename(file_path)}">Download {os.path.basename(file_path)}</a>'
130
+ st.markdown(dl_link, unsafe_allow_html=True)
131
 
132
  def process_image(image_path, user_prompt):
133
  with open(image_path, "rb") as imgf:
 
147
  return resp.choices[0].message.content
148
 
149
  def process_audio(audio_path):
 
150
  with open(audio_path, "rb") as f:
151
  transcription = openai_client.audio.transcriptions.create(model="whisper-1", file=f)
152
  st.session_state.messages.append({"role": "user", "content": transcription.text})
153
+ # No immediate rerun
154
  return transcription.text
155
 
156
  def process_video(video_path, seconds_per_frame=1):
 
205
 
206
  if vocal_summary:
207
  audio_file_main = speak_with_edge_tts(r2, voice="en-US-AriaNeural", rate=0, pitch=0)
 
208
  st.write("### πŸŽ™οΈ Vocal Summary (Short Answer)")
209
  play_and_download_audio(audio_file_main)
210
 
 
265
  st.session_state.chat_history.append({"user":text,"claude":ans})
266
  return ans
267
 
268
+ def create_zip_of_files(md_files, mp3_files):
269
+ # Exclude README.md if present
270
+ md_files = [f for f in md_files if os.path.basename(f).lower() != 'readme.md']
271
+
272
  all_files = md_files + mp3_files
273
+ if not all_files:
274
+ return None
275
+ # Build a descriptive name from file stems
276
+ stems = [os.path.splitext(os.path.basename(f))[0] for f in all_files]
277
+ # Join them
278
+ joined = "_".join(stems)
279
+ # Truncate if too long
280
+ if len(joined) > 50:
281
+ joined = joined[:50] + "_etc"
282
+ zip_name = f"{joined}.zip"
283
  with zipfile.ZipFile(zip_name,'w') as z:
284
  for f in all_files:
285
  z.write(f)
 
 
286
  return zip_name
287
 
288
  def get_media_html(p,typ="video",w="100%"):
 
297
  md_files = glob.glob("*.md")
298
  mp3_files = glob.glob("*.mp3")
299
 
300
+ # Exclude README.md from listings
301
+ md_files = [f for f in md_files if os.path.basename(f).lower() != 'readme.md']
302
+
303
  files_by_ext = defaultdict(list)
304
+ if md_files: files_by_ext['md'].extend(md_files)
305
+ if mp3_files: files_by_ext['mp3'].extend(mp3_files)
 
 
306
 
307
  # Sort each extension group by modification time descending
308
  for ext in files_by_ext:
 
315
  md_files = files_by_ext.get('md', [])
316
  mp3_files = files_by_ext.get('mp3', [])
317
 
318
+ # Buttons to delete all except README.md (already excluded)
319
+ col_del = st.sidebar.columns(3)
320
  with col_del[0]:
321
+ if st.button("πŸ—‘ Del All MD"):
322
  for f in md_files:
323
  os.remove(f)
324
  st.session_state.should_rerun = True
325
  with col_del[1]:
326
+ if st.button("πŸ—‘ Del All MP3"):
327
  for f in mp3_files:
328
  os.remove(f)
329
  st.session_state.should_rerun = True
330
+ with col_del[2]:
331
+ if st.button("⬇️ Zip All"):
332
+ # create a zip of all md and mp3 except README.md
333
+ z = create_zip_of_files(md_files, mp3_files)
334
+ if z:
335
+ st.sidebar.markdown(get_download_link(z),unsafe_allow_html=True)
336
 
337
  ext_counts = {ext: len(files) for ext, files in files_by_ext.items()}
338
  sorted_ext = sorted(files_by_ext.keys(), key=lambda x: ext_counts[x], reverse=True)
339
 
340
+ # Display files with actions
341
  for ext in sorted_ext:
342
  emoji = FILE_EMOJIS.get(ext, "πŸ“¦")
343
  count = len(files_by_ext[ext])
344
+ with st.sidebar.expander(f"{emoji} {ext.upper()} Files ({count})", expanded=True):
345
  for f in files_by_ext[ext]:
346
  fname = os.path.basename(f)
347
  ctime = datetime.fromtimestamp(os.path.getmtime(f)).strftime("%Y-%m-%d %H:%M:%S")
348
+ # Show filename and buttons in a row
349
+ st.write(f"**{fname}** - {ctime}")
350
+ file_buttons_col = st.columns([1,1,1])
351
+ with file_buttons_col[0]:
352
+ if st.button("πŸ‘€View", key="view_"+f):
353
+ st.session_state.viewing_file = f
354
+ st.session_state.viewing_file_type = ext
355
+ # No rerun needed, just set state
356
+ with file_buttons_col[1]:
 
 
 
 
 
 
 
357
  if ext == "md":
358
+ if st.button("✏️Edit", key="edit_"+f):
359
  st.session_state.editing_file = f
360
  st.session_state.edit_new_name = fname.replace(".md","")
361
  st.session_state.edit_new_content = open(f,'r',encoding='utf-8').read()
 
362
  st.session_state.should_rerun = True
363
+ with file_buttons_col[2]:
364
+ if st.button("πŸ—‘Del", key="del_"+f):
 
 
 
365
  os.remove(f)
 
366
  st.session_state.should_rerun = True
367
 
 
 
 
 
368
  # If editing an md file
369
  if st.session_state.editing_file and os.path.exists(st.session_state.editing_file):
370
  st.sidebar.subheader(f"Editing: {os.path.basename(st.session_state.editing_file)}")
371
+ st.session_state.edit_new_name = st.sidebar.text_input("New name (no extension):", value=st.session_state.edit_new_name)
372
  st.session_state.edit_new_content = st.sidebar.text_area("Content:", st.session_state.edit_new_content, height=200)
373
  c1,c2 = st.sidebar.columns(2)
374
  with c1:
375
+ if st.button("Save"):
376
  old_path = st.session_state.editing_file
377
  new_path = st.session_state.edit_new_name + ".md"
378
  if new_path != os.path.basename(old_path):
 
380
  with open(new_path,'w',encoding='utf-8') as f:
381
  f.write(st.session_state.edit_new_content)
382
  st.session_state.editing_file = None
 
383
  st.session_state.should_rerun = True
384
  with c2:
385
  if st.button("Cancel"):
386
  st.session_state.editing_file = None
 
387
  st.session_state.should_rerun = True
388
 
389
  def main():
 
509
  with open(st.session_state.current_file,'w',encoding='utf-8') as f:
510
  f.write(new_text)
511
  st.success("Updated!")
 
512
  st.session_state.should_rerun = True
513
  else:
514
  st.write("Select a file from the sidebar to edit.")
 
517
  files_by_ext = load_files_for_sidebar()
518
  display_file_manager_sidebar(files_by_ext)
519
 
520
+ # If viewing a file, show its content below (in the main area)
521
+ if st.session_state.viewing_file and os.path.exists(st.session_state.viewing_file):
522
+ st.write("---")
523
+ st.write(f"**Viewing File:** {os.path.basename(st.session_state.viewing_file)}")
524
+ if st.session_state.viewing_file_type == "md":
525
+ # show markdown
526
+ content = open(st.session_state.viewing_file,'r',encoding='utf-8').read()
527
+ st.markdown(content)
528
+ elif st.session_state.viewing_file_type == "mp3":
529
+ # show audio
530
+ st.audio(st.session_state.viewing_file)
531
+ # Optionally add a "Close View" button
532
+ if st.button("Close View"):
533
+ st.session_state.viewing_file = None
534
+ st.session_state.viewing_file_type = None
535
+
536
+ # If user-triggered changes happened, rerun once at the end
537
  if st.session_state.should_rerun:
538
  st.session_state.should_rerun = False
539
  st.rerun()