diff --git a/maildir_gtd/actions/__pycache__/archive.cpython-311.pyc b/maildir_gtd/actions/__pycache__/archive.cpython-311.pyc index 65e3b40..1ad8669 100644 Binary files a/maildir_gtd/actions/__pycache__/archive.cpython-311.pyc and b/maildir_gtd/actions/__pycache__/archive.cpython-311.pyc differ diff --git a/maildir_gtd/actions/__pycache__/next.cpython-311.pyc b/maildir_gtd/actions/__pycache__/next.cpython-311.pyc index 20a03a8..e633e96 100644 Binary files a/maildir_gtd/actions/__pycache__/next.cpython-311.pyc and b/maildir_gtd/actions/__pycache__/next.cpython-311.pyc differ diff --git a/maildir_gtd/actions/__pycache__/open.cpython-311.pyc b/maildir_gtd/actions/__pycache__/open.cpython-311.pyc index a556290..8126a32 100644 Binary files a/maildir_gtd/actions/__pycache__/open.cpython-311.pyc and b/maildir_gtd/actions/__pycache__/open.cpython-311.pyc differ diff --git a/maildir_gtd/actions/__pycache__/previous.cpython-311.pyc b/maildir_gtd/actions/__pycache__/previous.cpython-311.pyc index 3c074f5..9bd94cd 100644 Binary files a/maildir_gtd/actions/__pycache__/previous.cpython-311.pyc and b/maildir_gtd/actions/__pycache__/previous.cpython-311.pyc differ diff --git a/maildir_gtd/actions/__pycache__/show_message.cpython-311.pyc b/maildir_gtd/actions/__pycache__/show_message.cpython-311.pyc index cfd0888..2f335f9 100644 Binary files a/maildir_gtd/actions/__pycache__/show_message.cpython-311.pyc and b/maildir_gtd/actions/__pycache__/show_message.cpython-311.pyc differ diff --git a/maildir_gtd/actions/archive.py b/maildir_gtd/actions/archive.py index 44023a6..a72c49e 100644 --- a/maildir_gtd/actions/archive.py +++ b/maildir_gtd/actions/archive.py @@ -13,7 +13,6 @@ def action_archive(app) -> None: ) if result.returncode == 0: app.query_one("#main_content", Static).update(f"Message {app.current_message_id} archived.") - app.show_status(f"Message {app.current_message_id} archived.") action_next(app) # Automatically show the next message else: app.query_one("#main_content", Static).update(f"Failed to archive message {app.current_message_id}.") diff --git a/maildir_gtd/actions/next.py b/maildir_gtd/actions/next.py index 3e607aa..05ec6e2 100644 --- a/maildir_gtd/actions/next.py +++ b/maildir_gtd/actions/next.py @@ -23,13 +23,13 @@ def action_next(app) -> None: import json envelopes = json.loads(result.stdout) ids = sorted(int(envelope['id']) for envelope in envelopes) - for envelope_id in ids: - if envelope_id > app.current_message_id: - app.current_message_id = envelope_id - app.show_message(app.current_message_id) - app.show_status(f"Showing next message: {app.current_message_id}") + for index, envelope_id in enumerate(ids): + if envelope_id > int(app.current_message_id): + app.show_message(envelope_id) return + app.show_status("No newer messages found.", severity="warning") + app.show_message(envelopes[-1]['id']) # Automatically show the previous message else: app.show_status("Failed to fetch envelope list.", severity="error") except Exception as e: diff --git a/maildir_gtd/actions/open.py b/maildir_gtd/actions/open.py index b32d315..ff81268 100644 --- a/maildir_gtd/actions/open.py +++ b/maildir_gtd/actions/open.py @@ -6,7 +6,6 @@ def action_open(app) -> None: def check_id(message_id: str) -> bool: try: int(message_id) - app.show_status(f"Opening message {message_id}...") app.current_message_id = message_id app.show_message(app.current_message_id) except ValueError: diff --git a/maildir_gtd/actions/previous.py b/maildir_gtd/actions/previous.py index b7df02b..4e7ed49 100644 --- a/maildir_gtd/actions/previous.py +++ b/maildir_gtd/actions/previous.py @@ -14,10 +14,9 @@ def action_previous(app) -> None: envelopes = json.loads(result.stdout) ids = sorted((int(envelope['id']) for envelope in envelopes), reverse=True) for envelope_id in ids: - if envelope_id < app.current_message_id: + if envelope_id < int(app.current_message_id): app.current_message_id = envelope_id app.show_message(app.current_message_id) - app.show_status(f"Showing previous message: {app.current_message_id}") return app.show_status("No older messages found.", severity="warning") else: diff --git a/maildir_gtd/actions/show_message.py b/maildir_gtd/actions/show_message.py index 1efcab2..9a01eca 100644 --- a/maildir_gtd/actions/show_message.py +++ b/maildir_gtd/actions/show_message.py @@ -1,8 +1,10 @@ from textual.widgets import Static +from rich.markdown import Markdown import subprocess def show_message(app, message_id: int) -> None: """Fetch and display the email message by ID.""" + app.current_message_id = message_id app.query_one("#main_content", Static).loading = True try: result = subprocess.run( @@ -12,7 +14,6 @@ def show_message(app, message_id: int) -> None: ) if result.returncode == 0: # Render the email content as Markdown - from rich.markdown import Markdown markdown_content = Markdown(result.stdout, justify=True) app.query_one("#main_content", Static).loading = False app.query_one("#main_content", Static).update(markdown_content) diff --git a/maildir_gtd/app.py b/maildir_gtd/app.py index 5a59500..5e46e62 100644 --- a/maildir_gtd/app.py +++ b/maildir_gtd/app.py @@ -5,7 +5,8 @@ sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))) import logging from typing import Iterable from textual import on -from textual.app import App, ComposeResult, SystemCommand +from textual.widget import Widget +from textual.app import App, ComposeResult, SystemCommand, RenderResult from textual.logging import TextualHandler from textual.screen import Screen from textual.widgets import Header, Footer, Static, Label, Input, Button @@ -27,13 +28,29 @@ logging.basicConfig( handlers=[TextualHandler()], ) +class Hello(Widget): + """Display a greeting.""" + + def render(self) -> RenderResult: + return "Hello, [b]World[/b]!" + +class StatusTitle(Static): + total_messages: Reactive[int] = Reactive(0) + current_message_index: Reactive[int] = Reactive(0) + current_message_id: Reactive[int] = Reactive(1) + + def render(self) -> RenderResult: + return f"Inbox Message ID: {self.current_message_id} | [b]{self.current_message_index}[/b]/{self.total_messages}" + + + class EmailViewerApp(App): """A simple email viewer app using the Himalaya CLI.""" title = "Maildir GTD Reader" - CSS_PATH = "email_viewer.tcss" # Optional: For styling - current_message_id: Reactive[int] = Reactive(1) + CSS_PATH = "email_viewer.tcss" + def get_system_commands(self, screen: Screen) -> Iterable[SystemCommand]: yield from super().get_system_commands(screen) @@ -64,12 +81,43 @@ class EmailViewerApp(App): def compose(self) -> ComposeResult: """Create child widgets for the app.""" yield Header(show_clock=True) - yield Footer(Label("[n] Next | [p] Previous | [d] Delete | [a] Archive | [o] Open | [q] Quit | [c] Create Task")) - yield ScrollableContainer(Static(Label("Email Viewer App"), id="main_content")) + yield StatusTitle().data_bind(EmailViewerApp.current_message_id) + yield ScrollableContainer(Static(Label("Loading Email Viewer App"), id="main_content")) + yield Footer() + + def watch_current_message_id(self, message_id: int, old_message_id: int) -> None: + """Called when the current message ID changes.""" + if (message_id == old_message_id): + return + # self.notify("Current message ID changed", title="Status", severity="information") + logging.info(f"Current message ID changed to {message_id}") + try: + result = subprocess.run( + ["himalaya", "envelope", "list", "-o", "json"], + capture_output=True, + text=True + ) + if result.returncode == 0: + import json + envelopes = json.loads(result.stdout) + if envelopes: + status = self.query_one(StatusTitle) + status.total_messages = len(envelopes) # Get the first envelope's ID + status.current_message_index = next( + (index + 1 for index, envelope in enumerate(envelopes) if int(envelope['id']) == message_id), + 0 # Default to 0 if no match is found + ) + else: + self.query_one("#main_content", Static).update("Failed to fetch the most recent message ID.") + except Exception as e: + self.query_one("#main_content", Static).update(f"Error: {e}") + def on_mount(self) -> None: - """Called when the app is mounted.""" self.alert_timer: Timer | None = None # Timer to throttle alerts + self.theme = "monokai" + + # self.watch(self.query_one(StatusTitle), "current_message_id", update_progress) # Fetch the ID of the most recent message using the Himalaya CLI try: result = subprocess.run( @@ -81,7 +129,7 @@ class EmailViewerApp(App): import json envelopes = json.loads(result.stdout) if envelopes: - self.current_message_id = int(envelopes[0]['id']) # Get the first envelope's ID + self.current_message_id = int(envelopes[0]['id']) else: self.query_one("#main_content", Static).update("Failed to fetch the most recent message ID.") except Exception as e: diff --git a/maildir_gtd/email_viewer.tcss b/maildir_gtd/email_viewer.tcss index b675b1a..51138c8 100644 --- a/maildir_gtd/email_viewer.tcss +++ b/maildir_gtd/email_viewer.tcss @@ -13,3 +13,11 @@ Label#task_prompt_label { Label#message_label { padding: 1; } + +StatusTitle { + width: 100%; + height: 1; + color: $text; + background: $surface; + content-align: center middle; +} diff --git a/maildir_gtd/screens/CreateTask.py b/maildir_gtd/screens/CreateTask.py index 6e05336..ddd433f 100644 --- a/maildir_gtd/screens/CreateTask.py +++ b/maildir_gtd/screens/CreateTask.py @@ -20,7 +20,6 @@ class CreateTaskScreen(Screen[str]): task_args = input_widget.value self.dismiss(task_args) - @on(Input._on_key) - def handle_close(self, event) -> None: + def on_key(self, event) -> None: if (event.key == "escape" or event.key == "ctrl+c"): self.dismiss() diff --git a/maildir_gtd/screens/__pycache__/CreateTask.cpython-311.pyc b/maildir_gtd/screens/__pycache__/CreateTask.cpython-311.pyc index 4642984..364ca27 100644 Binary files a/maildir_gtd/screens/__pycache__/CreateTask.cpython-311.pyc and b/maildir_gtd/screens/__pycache__/CreateTask.cpython-311.pyc differ