Files
luk/maildir_gtd/widgets/EnvelopeHeader.py
2025-05-14 15:11:24 -06:00

108 lines
4.2 KiB
Python

from textual.reactive import Reactive
from textual.app import ComposeResult
from textual.widgets import Label
from textual.containers import Horizontal, ScrollableContainer
from datetime import datetime
import re
from datetime import UTC
class EnvelopeHeader(ScrollableContainer):
subject = Reactive("")
from_ = Reactive("")
to = Reactive("")
date = Reactive("")
cc = Reactive("")
bcc = Reactive("")
"""Header for the email viewer."""
def on_mount(self) -> None:
"""Mount the header."""
def compose(self) -> ComposeResult:
yield Horizontal(
Label("Subject:", classes="header_key"),
Label(self.subject, classes="header_value", markup=False, id="subject"),
)
yield Horizontal(
Label("Date:", classes="header_key"),
Label(self.date, classes="header_value", markup=False, id="date"),
)
# yield Horizontal(
# Label("From:", classes="header_key"),
# Label(self.from_, classes="header_value", markup=False, id="from"),
# )
# yield Horizontal(
# Label("To:", classes="header_key"),
# Label(self.to, classes="header_value", markup=False, id="to"),
# )
# yield Horizontal(
# )
# yield Horizontal(
# Label("CC:", classes="header_key"),
# Label(self.cc, classes="header_value", markup=False, id="cc"),
# )
def watch_subject(self, subject: str) -> None:
"""Watch the subject for changes."""
self.query_one("#subject").update(subject)
# def watch_to(self, to: str) -> None:
# """Watch the to field for changes."""
# self.query_one("#to").update(to)
# def watch_from(self, from_: str) -> None:
# """Watch the from field for changes."""
# self.query_one("#from").update(from_)
def watch_date(self, date: str) -> None:
"""Watch the date for changes and convert to local timezone."""
if date:
try:
# If date already has timezone info, parse it
if any(x in date for x in ['+', '-', 'Z']):
# Try parsing with timezone info
try:
# Handle ISO format with Z suffix
if 'Z' in date:
parsed_date = datetime.fromisoformat(date.replace('Z', '+00:00'))
else:
parsed_date = datetime.fromisoformat(date)
except ValueError:
# Try another common format
parsed_date = datetime.strptime(date, "%Y-%m-%d %H:%M%z")
else:
# No timezone info, assume UTC
try:
parsed_date = datetime.strptime(date, "%Y-%m-%d %H:%M").replace(tzinfo=UTC)
except ValueError:
# If regular parsing fails, try to extract date components
match = re.search(r"(\d{4}-\d{2}-\d{2})\s+(\d{2}:\d{2})", date)
if match:
date_part, time_part = match.groups()
parsed_date = datetime.strptime(
f"{date_part} {time_part}", "%Y-%m-%d %H:%M"
).replace(tzinfo=UTC)
else:
# If all else fails, just use the original string
self.query_one("#date").update(date)
return
# Convert to local timezone
local_date = parsed_date.astimezone() # Convert to system's local timezone
# Format for display
formatted_date = local_date.strftime("%a %b %d %H:%M (%Z)")
self.query_one("#date").update(formatted_date)
except Exception as e:
# If parsing fails, just display the original date
self.query_one("#date").update(f"{date}")
else:
self.query_one("#date").update("")
# def watch_cc(self, cc: str) -> None:
# """Watch the cc field for changes."""
# self.query_one("#cc").update(cc)