awacke1 commited on
Commit
92897ad
Β·
verified Β·
1 Parent(s): 020a633

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +136 -393
app.py CHANGED
@@ -14,186 +14,7 @@ import base64
14
  import glob
15
  import os
16
 
17
- # Add this function after the imports and before other functions
18
- def scan_and_load_files():
19
- """πŸ” File Detective - Scans directory for supported files and loads them automatically"""
20
- loaded_files = []
21
-
22
- # Get all files with supported extensions
23
- for ext in FILE_TYPES.keys():
24
- files = glob.glob(f"*.{ext}")
25
- for filepath in files:
26
- try:
27
- with open(filepath, 'r', encoding='utf-8') as f:
28
- content = f.read()
29
- file_type = filepath.split('.')[-1].lower()
30
-
31
- # Store file content and type
32
- st.session_state.file_data[filepath] = content
33
- st.session_state.file_types[filepath] = file_type
34
-
35
- # Special handling for markdown files
36
- if file_type == 'md':
37
- st.session_state.md_outline[filepath] = parse_markdown_outline(content)
38
- st.session_state.rendered_content[filepath] = content
39
-
40
- # Add to markdown files history if not already present
41
- if filepath not in [f["filename"] for f in st.session_state.md_files_history]:
42
- timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
43
- encoded_content = encode_content(content)
44
- st.session_state.md_files_history.append({
45
- "filename": filepath,
46
- "timestamp": timestamp,
47
- "content": encoded_content
48
- })
49
-
50
- # Create initial version history
51
- if filepath not in st.session_state.md_versions:
52
- st.session_state.md_versions[filepath] = []
53
- st.session_state.md_versions[filepath].append({
54
- "timestamp": timestamp,
55
- "content": encoded_content,
56
- "action": "auto-loaded"
57
- })
58
-
59
- loaded_files.append(filepath)
60
- except Exception as e:
61
- st.error(f"🚨 Error loading {filepath}: {str(e)}")
62
-
63
- # Update combined markdown after loading all files
64
- if loaded_files:
65
- st.session_state.combined_markdown = combine_markdown_files()
66
-
67
- return loaded_files
68
-
69
-
70
-
71
-
72
- # Modify the main function to include initial file scanning
73
- def main():
74
-
75
- # Add a reset button in sidebar
76
- if st.sidebar.button("πŸ”„ Reset & Rescan Files"):
77
- # Clear all session state
78
- for key in list(st.session_state.keys()):
79
- del st.session_state[key]
80
- st.experimental_rerun()
81
-
82
- st.title("πŸ“šβœ¨ Super Smart File Handler with Markdown Magic! βœ¨πŸ“š")
83
-
84
- # Initialize session state
85
- if 'file_data' not in st.session_state:
86
- st.session_state.file_data = {}
87
- if 'file_types' not in st.session_state:
88
- st.session_state.file_types = {}
89
- if 'md_outline' not in st.session_state:
90
- st.session_state.md_outline = {}
91
- if 'rendered_content' not in st.session_state:
92
- st.session_state.rendered_content = {}
93
- if 'file_history' not in st.session_state:
94
- st.session_state.file_history = []
95
- if 'md_versions' not in st.session_state:
96
- st.session_state.md_versions = {}
97
- if 'md_files_history' not in st.session_state:
98
- st.session_state.md_files_history = []
99
- if 'combined_markdown' not in st.session_state:
100
- st.session_state.combined_markdown = ""
101
-
102
- # Scan for existing files on startup
103
- if 'files_scanned' not in st.session_state:
104
- loaded_files = scan_and_load_files()
105
- if loaded_files:
106
- st.success(f"πŸŽ‰ Auto-loaded {len(loaded_files)} existing files: {', '.join(loaded_files)}")
107
- st.session_state.files_scanned = True
108
-
109
-
110
- st.title("πŸ“šβœ¨ Super Smart File Handler with Markdown Magic! βœ¨πŸ“š")
111
-
112
- # Scan for existing files on startup
113
- if 'files_scanned' not in st.session_state:
114
- loaded_files = scan_and_load_files()
115
- if loaded_files:
116
- st.success(f"πŸŽ‰ Auto-loaded {len(loaded_files)} existing files: {', '.join(loaded_files)}")
117
- st.session_state.files_scanned = True
118
-
119
- # Show markdown history in sidebar
120
- show_sidebar_history()
121
-
122
- # Add tabs for different upload methods
123
- upload_tab, book_tab = st.tabs(["πŸ“€ File Upload", "πŸ“– Book View"])
124
-
125
- with upload_tab:
126
- # Add a rescan button
127
- if st.button("πŸ”„ Rescan Directory"):
128
- st.session_state.files_scanned = False
129
- st.experimental_rerun()
130
-
131
- col1, col2 = st.columns(2)
132
-
133
- with col1:
134
- single_uploaded_file = st.file_uploader(
135
- "πŸ“€ Upload single file",
136
- type=list(FILE_TYPES.keys()),
137
- help="Supports: " + ", ".join([f"{v} (.{k})" for k, v in FILE_TYPES.items()]),
138
- key="single_uploader"
139
- )
140
-
141
- with col2:
142
- multiple_uploaded_files = st.file_uploader(
143
- "πŸ“š Upload multiple files",
144
- type=list(FILE_TYPES.keys()),
145
- accept_multiple_files=True,
146
- help="Upload multiple files to view as a book",
147
- key="multiple_uploader"
148
- )
149
-
150
- # Process single file upload
151
- if single_uploaded_file:
152
- content, file_type = read_file_content(single_uploaded_file)
153
- if content is not None:
154
- st.session_state.file_data[single_uploaded_file.name] = content
155
- st.session_state.file_types[single_uploaded_file.name] = file_type
156
- st.success(f"πŸŽ‰ Loaded {FILE_TYPES.get(file_type, 'πŸ“„')} file: {single_uploaded_file.name}")
157
-
158
- # Process multiple file upload
159
- if multiple_uploaded_files:
160
- for uploaded_file in multiple_uploaded_files:
161
- content, file_type = read_file_content(uploaded_file)
162
- if content is not None:
163
- st.session_state.file_data[uploaded_file.name] = content
164
- st.session_state.file_types[uploaded_file.name] = file_type
165
- st.success(f"πŸŽ‰ Loaded {len(multiple_uploaded_files)} files")
166
-
167
- # Show file history
168
- show_file_history()
169
-
170
- # Show individual files
171
- if st.session_state.file_data:
172
- st.subheader("πŸ“‚ Your Files")
173
- for filename, content in st.session_state.file_data.items():
174
- file_type = st.session_state.file_types[filename]
175
- with st.expander(f"{FILE_TYPES.get(file_type, 'πŸ“„')} {filename}"):
176
- if file_type == "md":
177
- content = create_markdown_tabs(content, filename)
178
- else:
179
- edited_content = st.text_area(
180
- "Content",
181
- content,
182
- height=300,
183
- key=f"edit_{filename}"
184
- )
185
- if edited_content != content:
186
- st.session_state.file_data[filename] = edited_content
187
- content = edited_content
188
-
189
- if st.button(f"πŸ’Ύ Save {filename}"):
190
- if save_file_content(content, filename, file_type):
191
- st.success(f"✨ Saved {filename} successfully!")
192
-
193
- with book_tab:
194
- show_book_view()
195
-
196
- # 🎨 File type emojis - Making file types fun and visual!
197
  FILE_TYPES = {
198
  "md": "πŸ“ Markdown",
199
  "txt": "πŸ“„ Text",
@@ -204,92 +25,49 @@ FILE_TYPES = {
204
  "xml": "πŸ”— XML"
205
  }
206
 
207
- # 🧠 Brain initialization - Setting up our app's memory!
208
- if 'file_data' not in st.session_state:
209
- st.session_state.file_data = {}
210
- if 'file_types' not in st.session_state:
211
- st.session_state.file_types = {}
212
- if 'md_outline' not in st.session_state:
213
- st.session_state.md_outline = {}
214
- if 'rendered_content' not in st.session_state:
215
- st.session_state.rendered_content = {}
216
- if 'file_history' not in st.session_state:
217
- st.session_state.file_history = []
218
- if 'md_versions' not in st.session_state:
219
- st.session_state.md_versions = {}
220
- if 'md_files_history' not in st.session_state:
221
- st.session_state.md_files_history = []
222
- if 'combined_markdown' not in st.session_state:
223
- st.session_state.combined_markdown = ""
224
 
225
- # 🧹 Clean Sweep! - Decluttering our markdown files
226
- def delete_all_md_files():
227
- """Delete all markdown files except README.md"""
228
- files_to_remove = [
229
- f for f in st.session_state.md_files_history
230
- if f["filename"] != "README.md"
231
- ]
232
- for file in files_to_remove:
233
- filename = file["filename"]
234
- if filename in st.session_state.file_data:
235
- del st.session_state.file_data[filename]
236
- if filename in st.session_state.file_types:
237
- del st.session_state.file_types[filename]
238
- if filename in st.session_state.md_outline:
239
- del st.session_state.md_outline[filename]
240
- if filename in st.session_state.rendered_content:
241
- del st.session_state.rendered_content[filename]
242
- if filename in st.session_state.md_versions:
243
- del st.session_state.md_versions[filename]
244
-
245
- st.session_state.md_files_history = [
246
- f for f in st.session_state.md_files_history
247
- if f["filename"] == "README.md"
248
- ]
249
- st.session_state.combined_markdown = ""
250
- return len(files_to_remove)
251
-
252
- # 🎁 Download Gift Wrapper - Making files downloadable with style!
253
- def get_binary_file_downloader_html(bin_file, file_label='File'):
254
- """Generate a link allowing the data in a given file to be downloaded"""
255
- b64 = base64.b64encode(bin_file.encode()).decode()
256
- return f'<a href="data:text/plain;base64,{b64}" download="{file_label}">πŸ“₯ Download {file_label}</a>'
257
-
258
- # πŸ” Secret Keeper - Encoding our content safely
259
  def encode_content(content):
260
  """Encode content to base64"""
261
  return base64.b64encode(content.encode()).decode()
262
 
263
- # πŸ”“ Mystery Solver - Decoding our secret content
264
  def decode_content(encoded_content):
265
  """Decode content from base64"""
266
  return base64.b64decode(encoded_content.encode()).decode()
267
 
268
- # πŸ“š Book Maker - Combining markdown files into a beautiful book
269
- def combine_markdown_files():
270
- """Combine all markdown files into a single document"""
271
- combined = []
272
- for md_file in sorted(st.session_state.md_files_history, key=lambda x: x["filename"]):
273
- content = decode_content(md_file["content"])
274
- combined.append(f"# {md_file['filename']}\n\n{content}\n\n---\n\n")
275
- return "".join(combined)
 
 
276
 
277
- # πŸ“ History Scribe - Recording every file action with precision
278
  def add_to_history(filename, content, action="uploaded"):
279
- """Add a file action to the history with timestamp"""
280
  timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
281
  encoded_content = encode_content(content)
282
- history_entry = {
 
283
  "timestamp": timestamp,
284
  "filename": filename,
285
  "action": action,
286
  "content": encoded_content
287
- }
288
- st.session_state.file_history.insert(0, history_entry)
289
 
290
  if filename.endswith('.md'):
291
  if filename not in st.session_state.md_versions:
292
  st.session_state.md_versions[filename] = []
 
293
  st.session_state.md_versions[filename].append({
294
  "timestamp": timestamp,
295
  "content": encoded_content,
@@ -305,115 +83,66 @@ def add_to_history(filename, content, action="uploaded"):
305
 
306
  st.session_state.combined_markdown = combine_markdown_files()
307
 
308
- # πŸ“š Shelf Display - Showing our markdown collection in the sidebar
309
- def show_sidebar_history():
310
- """Display markdown file history in the sidebar"""
311
- st.sidebar.markdown("### πŸ“š Markdown Files History")
312
-
313
- if st.sidebar.button("🧹 Delete All (except README.md)"):
314
- deleted_count = delete_all_md_files()
315
- st.sidebar.success(f"Deleted {deleted_count} markdown files")
316
- st.rerun()
317
-
318
- for md_file in st.session_state.md_files_history:
319
- col1, col2, col3 = st.sidebar.columns([2, 1, 1])
320
-
321
- with col1:
322
- st.markdown(f"**{md_file['filename']}**")
323
-
324
- with col2:
325
- if st.button("πŸ“‚ Open", key=f"open_{md_file['filename']}"):
326
- content = decode_content(md_file['content'])
327
- st.session_state.file_data[md_file['filename']] = content
328
- st.session_state.file_types[md_file['filename']] = "md"
329
- st.session_state.md_outline[md_file['filename']] = parse_markdown_outline(content)
330
- st.rerun()
331
-
332
- with col3:
333
- download_link = get_binary_file_downloader_html(
334
- decode_content(md_file['content']),
335
- md_file['filename']
336
- )
337
- st.markdown(download_link, unsafe_allow_html=True)
338
-
339
- # πŸ“– Book Display - Showing our combined markdown masterpiece
340
- def show_book_view():
341
- """Display all markdown files in a book-like format"""
342
- if st.session_state.combined_markdown:
343
- st.markdown("## πŸ“– Book View")
344
- st.markdown(st.session_state.combined_markdown)
345
 
346
- # πŸ“‹ Time Traveler - Showing our file's journey through time
347
- def show_file_history():
348
- """Display the file history in a collapsible section"""
349
- if st.session_state.file_history:
350
- with st.expander("πŸ“‹ File History", expanded=False):
351
- st.markdown("### Recent File Activities")
352
- for entry in st.session_state.file_history:
353
- col1, col2 = st.columns([2, 3])
354
- with col1:
355
- st.markdown(f"**{entry['timestamp']}**")
356
- with col2:
357
- st.markdown(f"{entry['action'].title()}: {entry['filename']}")
 
 
 
 
 
 
 
 
 
 
 
 
358
 
359
- # ⏰ Time Machine - Exploring previous versions of our files
360
  def show_markdown_versions(filename):
361
  """Display previous versions of a markdown file"""
362
- if filename in st.session_state.md_versions:
363
- versions = st.session_state.md_versions[filename]
364
- if len(versions) > 1:
365
- st.markdown("### πŸ“š Previous Versions")
366
- version_idx = st.selectbox(
367
- "Select version to view",
368
- range(len(versions)-1),
369
- format_func=lambda x: f"Version {len(versions)-1-x} - {versions[x]['timestamp']}"
370
- )
 
 
 
 
371
 
372
- if version_idx is not None:
373
- version = versions[version_idx]
374
- decoded_content = decode_content(version['content'])
375
- st.text_area(
376
- "Content",
377
- decoded_content,
378
- height=200,
379
- key=f"version_{filename}_{version_idx}",
380
- disabled=True
381
- )
382
- if st.button(f"Restore to this version", key=f"restore_{filename}_{version_idx}"):
383
- st.session_state.file_data[filename] = decoded_content
384
- st.session_state.md_outline[filename] = parse_markdown_outline(decoded_content)
385
- add_to_history(filename, decoded_content, "restored")
386
- st.rerun()
387
-
388
- # πŸ—ΊοΈ Map Maker - Creating a beautiful outline of our markdown
389
- def parse_markdown_outline(content):
390
- """Generate an outline from markdown content"""
391
- lines = content.split('\n')
392
- outline = []
393
- for line in lines:
394
- if line.strip().startswith('#'):
395
- level = len(line.split()[0])
396
- title = line.strip('#').strip()
397
- outline.append({
398
- 'level': level,
399
- 'title': title,
400
- 'indent': ' ' * (level - 1)
401
- })
402
- return outline
403
 
404
- # πŸ“‘ Tab Master - Creating beautiful tabs for our markdown content
405
  def create_markdown_tabs(content, filename):
406
  """Create tabs for markdown content viewing and editing"""
407
  tab1, tab2, tab3 = st.tabs(["πŸ“ Editor", "πŸ‘€ Preview", "πŸ•’ History"])
408
 
409
  with tab1:
410
- edited_content = st.text_area(
411
- "Edit your markdown",
412
- content,
413
- height=300,
414
- key=f"edit_{filename}"
415
- )
416
-
417
  if edited_content != content:
418
  st.session_state.file_data[filename] = edited_content
419
  st.session_state.md_outline[filename] = parse_markdown_outline(edited_content)
@@ -423,10 +152,8 @@ def create_markdown_tabs(content, filename):
423
  with tab2:
424
  st.markdown("### Preview")
425
  st.markdown(content)
426
-
427
  if filename in st.session_state.md_outline:
428
- st.markdown("---")
429
- st.markdown("### πŸ“‘ Document Outline")
430
  for item in st.session_state.md_outline[filename]:
431
  st.markdown(f"{item['indent']}β€’ {item['title']}")
432
 
@@ -435,7 +162,51 @@ def create_markdown_tabs(content, filename):
435
 
436
  return content
437
 
438
- # πŸ“€ File Reader - Smart file reading with a smile!
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
439
  def read_file_content(uploaded_file):
440
  """Smart file reader with enhanced markdown handling"""
441
  file_type = uploaded_file.name.split('.')[-1].lower()
@@ -446,77 +217,55 @@ def read_file_content(uploaded_file):
446
  st.session_state.rendered_content[uploaded_file.name] = content
447
  add_to_history(uploaded_file.name, content)
448
  return content, "md"
449
-
450
- elif file_type == 'csv':
451
- df = pd.read_csv(uploaded_file)
452
- return df.to_string(), "csv"
453
-
454
- elif file_type == 'xlsx':
455
- df = pd.read_excel(uploaded_file)
456
- return df.to_string(), "xlsx"
457
-
458
  elif file_type == 'json':
459
- content = json.load(uploaded_file)
460
- return json.dumps(content, indent=2), "json"
461
-
462
  elif file_type == 'yaml':
463
- content = yaml.safe_load(uploaded_file)
464
- return yaml.dump(content), "yaml"
465
-
466
- else: # Default text handling
467
  return uploaded_file.getvalue().decode(), "txt"
468
-
469
  except Exception as e:
470
- st.error(f"🚨 Oops! Error reading {uploaded_file.name}: {str(e)}")
471
  return None, None
472
 
473
- # πŸ’Ύ File Saver - Keeping our files safe and sound
474
  def save_file_content(content, filename, file_type):
475
  """Smart file saver with enhanced markdown handling"""
476
  try:
477
  if file_type == "md":
478
  with open(filename, 'w') as f:
479
  f.write(content)
480
- st.session_state.rendered_content[filename] = content
481
- add_to_history(filename, content, "saved")
482
-
483
  elif file_type in ["csv", "xlsx"]:
484
  df = pd.read_csv(StringIO(content)) if file_type == "csv" else pd.read_excel(StringIO(content))
485
- if file_type == "csv":
486
- df.to_csv(filename, index=False)
487
- else:
488
- df.to_excel(filename, index=False)
489
-
490
  elif file_type == "json":
491
  with open(filename, 'w') as f:
492
  json.dump(json.loads(content), f, indent=2)
493
-
494
  elif file_type == "yaml":
495
  with open(filename, 'w') as f:
496
  yaml.dump(yaml.safe_load(content), f)
497
-
498
- else: # Default text handling
499
  with open(filename, 'w') as f:
500
  f.write(content)
501
-
502
  return True
503
  except Exception as e:
504
  st.error(f"🚨 Error saving {filename}: {str(e)}")
505
  return False
506
 
507
- # 🎭 Main Show - Where the magic happens!
508
  def main():
509
- st.title("πŸ“šβœ¨ Super Smart File Handler with Markdown Magic! βœ¨πŸ“š")
 
510
 
511
- # Show markdown history in sidebar
512
  show_sidebar_history()
513
 
514
- # Add tabs for different upload methods
515
  upload_tab, book_tab = st.tabs(["πŸ“€ File Upload", "πŸ“– Book View"])
516
 
517
  with upload_tab:
518
  col1, col2 = st.columns(2)
519
-
520
  with col1:
521
  single_uploaded_file = st.file_uploader(
522
  "πŸ“€ Upload single file",
@@ -534,7 +283,6 @@ def main():
534
  key="multiple_uploader"
535
  )
536
 
537
- # Process single file upload
538
  if single_uploaded_file:
539
  content, file_type = read_file_content(single_uploaded_file)
540
  if content is not None:
@@ -542,7 +290,6 @@ def main():
542
  st.session_state.file_types[single_uploaded_file.name] = file_type
543
  st.success(f"πŸŽ‰ Loaded {FILE_TYPES.get(file_type, 'πŸ“„')} file: {single_uploaded_file.name}")
544
 
545
- # Process multiple file upload
546
  if multiple_uploaded_files:
547
  for uploaded_file in multiple_uploaded_files:
548
  content, file_type = read_file_content(uploaded_file)
@@ -552,10 +299,8 @@ def main():
552
  st.success(f"πŸŽ‰ Loaded {len(multiple_uploaded_files)} files")
553
  st.rerun()
554
 
555
- # Show file history
556
  show_file_history()
557
 
558
- # Show individual files
559
  if st.session_state.file_data:
560
  st.subheader("πŸ“‚ Your Files")
561
  for filename, content in st.session_state.file_data.items():
@@ -565,11 +310,7 @@ def main():
565
  content = create_markdown_tabs(content, filename)
566
  else:
567
  edited_content = st.text_area(
568
- "Content",
569
- content,
570
- height=300,
571
- key=f"edit_{filename}"
572
- )
573
  if edited_content != content:
574
  st.session_state.file_data[filename] = edited_content
575
  content = edited_content
@@ -579,7 +320,9 @@ def main():
579
  st.success(f"✨ Saved {filename} successfully!")
580
 
581
  with book_tab:
582
- show_book_view()
 
 
583
 
584
  if __name__ == "__main__":
585
  main()
 
14
  import glob
15
  import os
16
 
17
+ # File type definitions
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
18
  FILE_TYPES = {
19
  "md": "πŸ“ Markdown",
20
  "txt": "πŸ“„ Text",
 
25
  "xml": "πŸ”— XML"
26
  }
27
 
28
+ # Initialize session state
29
+ for key in ['file_data', 'file_types', 'md_outline', 'rendered_content',
30
+ 'file_history', 'md_versions', 'md_files_history', 'combined_markdown']:
31
+ if key not in st.session_state:
32
+ st.session_state[key] = {} if key in ['file_data', 'file_types', 'md_outline',
33
+ 'rendered_content', 'md_versions'] else [] if key in ['file_history',
34
+ 'md_files_history'] else ""
 
 
 
 
 
 
 
 
 
 
35
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
36
  def encode_content(content):
37
  """Encode content to base64"""
38
  return base64.b64encode(content.encode()).decode()
39
 
 
40
  def decode_content(encoded_content):
41
  """Decode content from base64"""
42
  return base64.b64decode(encoded_content.encode()).decode()
43
 
44
+ def parse_markdown_outline(content):
45
+ """Generate an outline from markdown content"""
46
+ return [{'level': len(line.split()[0]), 'title': line.strip('#').strip(),
47
+ 'indent': ' ' * (len(line.split()[0]) - 1)}
48
+ for line in content.split('\n') if line.strip().startswith('#')]
49
+
50
+ def get_binary_file_downloader_html(bin_file, file_label='File'):
51
+ """Generate download link"""
52
+ b64 = encode_content(bin_file)
53
+ return f'<a href="data:text/plain;base64,{b64}" download="{file_label}">πŸ“₯ Download {file_label}</a>'
54
 
 
55
  def add_to_history(filename, content, action="uploaded"):
56
+ """Add a file action to history with timestamp"""
57
  timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
58
  encoded_content = encode_content(content)
59
+
60
+ st.session_state.file_history.insert(0, {
61
  "timestamp": timestamp,
62
  "filename": filename,
63
  "action": action,
64
  "content": encoded_content
65
+ })
 
66
 
67
  if filename.endswith('.md'):
68
  if filename not in st.session_state.md_versions:
69
  st.session_state.md_versions[filename] = []
70
+
71
  st.session_state.md_versions[filename].append({
72
  "timestamp": timestamp,
73
  "content": encoded_content,
 
83
 
84
  st.session_state.combined_markdown = combine_markdown_files()
85
 
86
+ def combine_markdown_files():
87
+ """Combine markdown files into a single document"""
88
+ return "".join([f"# {md_file['filename']}\n\n{decode_content(md_file['content'])}\n\n---\n\n"
89
+ for md_file in sorted(st.session_state.md_files_history,
90
+ key=lambda x: x["filename"])])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
91
 
92
+ def scan_and_load_files():
93
+ """Scan directory for supported files and load them"""
94
+ loaded_files = []
95
+ for ext in FILE_TYPES.keys():
96
+ for filepath in glob.glob(f"*.{ext}"):
97
+ try:
98
+ with open(filepath, 'r', encoding='utf-8') as f:
99
+ content = f.read()
100
+ file_type = filepath.split('.')[-1].lower()
101
+
102
+ st.session_state.file_data[filepath] = content
103
+ st.session_state.file_types[filepath] = file_type
104
+
105
+ if file_type == 'md':
106
+ st.session_state.md_outline[filepath] = parse_markdown_outline(content)
107
+ st.session_state.rendered_content[filepath] = content
108
+ if filepath not in [f["filename"] for f in st.session_state.md_files_history]:
109
+ add_to_history(filepath, content, "auto-loaded")
110
+
111
+ loaded_files.append(filepath)
112
+ except Exception as e:
113
+ st.error(f"🚨 Error loading {filepath}: {str(e)}")
114
+
115
+ return loaded_files
116
 
 
117
  def show_markdown_versions(filename):
118
  """Display previous versions of a markdown file"""
119
+ if filename in st.session_state.md_versions and len(st.session_state.md_versions[filename]) > 1:
120
+ st.markdown("### πŸ“š Previous Versions")
121
+ version_idx = st.selectbox(
122
+ "Select version to view",
123
+ range(len(st.session_state.md_versions[filename])-1),
124
+ format_func=lambda x: f"Version {len(st.session_state.md_versions[filename])-1-x} - {st.session_state.md_versions[filename][x]['timestamp']}"
125
+ )
126
+
127
+ if version_idx is not None:
128
+ version = st.session_state.md_versions[filename][version_idx]
129
+ decoded_content = decode_content(version['content'])
130
+ st.text_area("Content", decoded_content, height=200,
131
+ key=f"version_{filename}_{version_idx}", disabled=True)
132
 
133
+ if st.button(f"Restore to this version", key=f"restore_{filename}_{version_idx}"):
134
+ st.session_state.file_data[filename] = decoded_content
135
+ st.session_state.md_outline[filename] = parse_markdown_outline(decoded_content)
136
+ add_to_history(filename, decoded_content, "restored")
137
+ st.rerun()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
138
 
 
139
  def create_markdown_tabs(content, filename):
140
  """Create tabs for markdown content viewing and editing"""
141
  tab1, tab2, tab3 = st.tabs(["πŸ“ Editor", "πŸ‘€ Preview", "πŸ•’ History"])
142
 
143
  with tab1:
144
+ edited_content = st.text_area("Edit your markdown", content, height=300,
145
+ key=f"edit_{filename}")
 
 
 
 
 
146
  if edited_content != content:
147
  st.session_state.file_data[filename] = edited_content
148
  st.session_state.md_outline[filename] = parse_markdown_outline(edited_content)
 
152
  with tab2:
153
  st.markdown("### Preview")
154
  st.markdown(content)
 
155
  if filename in st.session_state.md_outline:
156
+ st.markdown("---\n### πŸ“‘ Document Outline")
 
157
  for item in st.session_state.md_outline[filename]:
158
  st.markdown(f"{item['indent']}β€’ {item['title']}")
159
 
 
162
 
163
  return content
164
 
165
+ def show_sidebar_history():
166
+ """Display markdown file history in sidebar"""
167
+ st.sidebar.markdown("### πŸ“š Markdown Files History")
168
+
169
+ if st.sidebar.button("πŸ—‘οΈ Delete All (except README.md)"):
170
+ files_to_remove = [f for f in st.session_state.md_files_history if f["filename"] != "README.md"]
171
+ for file in files_to_remove:
172
+ filename = file["filename"]
173
+ for key in ['file_data', 'file_types', 'md_outline', 'rendered_content', 'md_versions']:
174
+ if filename in st.session_state[key]:
175
+ del st.session_state[key][filename]
176
+
177
+ st.session_state.md_files_history = [f for f in st.session_state.md_files_history
178
+ if f["filename"] == "README.md"]
179
+ st.session_state.combined_markdown = ""
180
+ st.sidebar.success(f"Deleted {len(files_to_remove)} markdown files")
181
+ st.rerun()
182
+
183
+ for md_file in st.session_state.md_files_history:
184
+ col1, col2, col3 = st.sidebar.columns([2, 1, 1])
185
+ with col1:
186
+ st.markdown(f"**{md_file['filename']}**")
187
+ with col2:
188
+ if st.button("πŸ“‚", key=f"open_{md_file['filename']}"):
189
+ content = decode_content(md_file['content'])
190
+ st.session_state.file_data[md_file['filename']] = content
191
+ st.session_state.file_types[md_file['filename']] = "md"
192
+ st.session_state.md_outline[md_file['filename']] = parse_markdown_outline(content)
193
+ st.rerun()
194
+ with col3:
195
+ st.markdown(get_binary_file_downloader_html(
196
+ decode_content(md_file['content']), md_file['filename']), unsafe_allow_html=True)
197
+
198
+ def show_file_history():
199
+ """Display file history in collapsible section"""
200
+ if st.session_state.file_history:
201
+ with st.expander("πŸ“‹ File History", expanded=False):
202
+ st.markdown("### Recent File Activities")
203
+ for entry in st.session_state.file_history:
204
+ col1, col2 = st.columns([2, 3])
205
+ with col1:
206
+ st.markdown(f"**{entry['timestamp']}**")
207
+ with col2:
208
+ st.markdown(f"{entry['action'].title()}: {entry['filename']}")
209
+
210
  def read_file_content(uploaded_file):
211
  """Smart file reader with enhanced markdown handling"""
212
  file_type = uploaded_file.name.split('.')[-1].lower()
 
217
  st.session_state.rendered_content[uploaded_file.name] = content
218
  add_to_history(uploaded_file.name, content)
219
  return content, "md"
220
+ elif file_type in ['csv', 'xlsx']:
221
+ df = pd.read_csv(uploaded_file) if file_type == 'csv' else pd.read_excel(uploaded_file)
222
+ return df.to_string(), file_type
 
 
 
 
 
 
223
  elif file_type == 'json':
224
+ return json.dumps(json.load(uploaded_file), indent=2), "json"
 
 
225
  elif file_type == 'yaml':
226
+ return yaml.dump(yaml.safe_load(uploaded_file)), "yaml"
227
+ else:
 
 
228
  return uploaded_file.getvalue().decode(), "txt"
 
229
  except Exception as e:
230
+ st.error(f"🚨 Error reading {uploaded_file.name}: {str(e)}")
231
  return None, None
232
 
 
233
  def save_file_content(content, filename, file_type):
234
  """Smart file saver with enhanced markdown handling"""
235
  try:
236
  if file_type == "md":
237
  with open(filename, 'w') as f:
238
  f.write(content)
239
+ st.session_state.rendered_content[filename] = content
240
+ add_to_history(filename, content, "saved")
 
241
  elif file_type in ["csv", "xlsx"]:
242
  df = pd.read_csv(StringIO(content)) if file_type == "csv" else pd.read_excel(StringIO(content))
243
+ df.to_csv(filename, index=False) if file_type == "csv" else df.to_excel(filename, index=False)
 
 
 
 
244
  elif file_type == "json":
245
  with open(filename, 'w') as f:
246
  json.dump(json.loads(content), f, indent=2)
 
247
  elif file_type == "yaml":
248
  with open(filename, 'w') as f:
249
  yaml.dump(yaml.safe_load(content), f)
250
+ else:
 
251
  with open(filename, 'w') as f:
252
  f.write(content)
 
253
  return True
254
  except Exception as e:
255
  st.error(f"🚨 Error saving {filename}: {str(e)}")
256
  return False
257
 
 
258
  def main():
259
+ # Perform initial file scan
260
+ loaded_files = scan_and_load_files()
261
 
262
+ st.title("πŸ“šβœ¨ Super Smart File Handler with Markdown Magic! βœ¨πŸ“š")
263
  show_sidebar_history()
264
 
 
265
  upload_tab, book_tab = st.tabs(["πŸ“€ File Upload", "πŸ“– Book View"])
266
 
267
  with upload_tab:
268
  col1, col2 = st.columns(2)
 
269
  with col1:
270
  single_uploaded_file = st.file_uploader(
271
  "πŸ“€ Upload single file",
 
283
  key="multiple_uploader"
284
  )
285
 
 
286
  if single_uploaded_file:
287
  content, file_type = read_file_content(single_uploaded_file)
288
  if content is not None:
 
290
  st.session_state.file_types[single_uploaded_file.name] = file_type
291
  st.success(f"πŸŽ‰ Loaded {FILE_TYPES.get(file_type, 'πŸ“„')} file: {single_uploaded_file.name}")
292
 
 
293
  if multiple_uploaded_files:
294
  for uploaded_file in multiple_uploaded_files:
295
  content, file_type = read_file_content(uploaded_file)
 
299
  st.success(f"πŸŽ‰ Loaded {len(multiple_uploaded_files)} files")
300
  st.rerun()
301
 
 
302
  show_file_history()
303
 
 
304
  if st.session_state.file_data:
305
  st.subheader("πŸ“‚ Your Files")
306
  for filename, content in st.session_state.file_data.items():
 
310
  content = create_markdown_tabs(content, filename)
311
  else:
312
  edited_content = st.text_area(
313
+ "Content", content, height=300, key=f"edit_{filename}")
 
 
 
 
314
  if edited_content != content:
315
  st.session_state.file_data[filename] = edited_content
316
  content = edited_content
 
320
  st.success(f"✨ Saved {filename} successfully!")
321
 
322
  with book_tab:
323
+ if st.session_state.combined_markdown:
324
+ st.markdown("## πŸ“– Book View")
325
+ st.markdown(st.session_state.combined_markdown)
326
 
327
  if __name__ == "__main__":
328
  main()