diff --git a/src/webserver.py b/src/webserver.py index e883e7e..82429fc 100644 --- a/src/webserver.py +++ b/src/webserver.py @@ -7,12 +7,13 @@ Provides a directory listing and serves static files from the snapshots folder. """ import os +import re import asyncio import argparse import logging from pathlib import Path from urllib.parse import unquote -from datetime import datetime +from datetime import datetime, timedelta from aiohttp import web @@ -73,167 +74,266 @@ class SnapshotsWebServer: content_type="text/html", ) + def _parse_date_range(self, filename): + """Extract and format date range from filename for parent-friendly display.""" + # Pattern: snapshots_YYYY-MM-DD_to_YYYY-MM-DD.html + match = re.match(r'snapshots_(\d{4}-\d{2}-\d{2})_to_(\d{4}-\d{2}-\d{2})\.html', filename) + if match: + try: + start = datetime.strptime(match.group(1), '%Y-%m-%d') + end = datetime.strptime(match.group(2), '%Y-%m-%d') + + # Format nicely based on date range + if start.year == end.year and start.month == end.month: + # Same month: "January 5 - 12, 2024" + return f"{start.strftime('%B')} {start.day} - {end.day}, {start.year}" + elif start.year == end.year: + # Same year: "January 5 - February 12, 2024" + return f"{start.strftime('%B %d')} - {end.strftime('%B %d')}, {start.year}" + else: + # Different years: "December 28, 2023 - January 5, 2024" + return f"{start.strftime('%B %d, %Y')} - {end.strftime('%B %d, %Y')}" + except ValueError: + pass + # Fallback: clean up filename + return filename.replace('.html', '').replace('_', ' ').replace('snapshots ', '').title() + + def _relative_time(self, dt): + """Convert datetime to relative human-readable string.""" + now = datetime.now() + diff = now - dt + + if diff < timedelta(hours=1): + return "Just now" + elif diff < timedelta(hours=24): + hours = int(diff.total_seconds() / 3600) + return f"{hours} hour{'s' if hours > 1 else ''} ago" + elif diff < timedelta(days=7): + days = diff.days + if days == 1: + return "Yesterday" + return f"{days} days ago" + elif diff < timedelta(days=30): + weeks = diff.days // 7 + return f"{weeks} week{'s' if weeks > 1 else ''} ago" + else: + return dt.strftime('%B %d, %Y') + def _generate_index_html(self, html_files): - """Generate the HTML directory listing page.""" + """Generate the HTML directory listing page with parent-friendly design.""" files_list = "" + + # Soft accent colors for memory cards + accent_colors = ["#FFE4E1", "#E0F7FA", "#FFF8E1", "#F3E5F5", "#E8F5E9"] if not html_files: - files_list = "

No snapshot files found.

" + files_list = """ +
+
📷
+

No memories yet

+

Snapshots will appear here once they're downloaded

+
+ """ else: - for file_info in html_files: - size_mb = file_info["size"] / (1024 * 1024) + for i, file_info in enumerate(html_files): + date_range = self._parse_date_range(file_info["name"]) + time_ago = self._relative_time(file_info["modified"]) + accent = accent_colors[i % len(accent_colors)] + files_list += f""" -
-
-

{file_info["name"]}

-
- {size_mb:.2f} MB - {file_info["modified"].strftime("%Y-%m-%d %H:%M:%S")} -
-
+ +
📖
+
+

{date_range}

+

Updated {time_ago}

+
+
""" + count_text = f'{len(html_files)} memory collection{"s" if len(html_files) != 1 else ""}' if html_files else '' + return f""" - ParentZone Snapshots + My Child's Memories + + +
-
-

📸 ParentZone Snapshots

-

Browse and view your downloaded snapshot files

-
- -
-
- 📁 Available Snapshot Files ({len(html_files)} files) -
+
+
🌟
+

My Child's Memories

+

Precious moments from school

+ {f'
📚 {count_text}
' if html_files else ''} +
+ +
{files_list}
- -