wip
This commit is contained in:
@@ -1,6 +1,3 @@
|
|||||||
import asyncio
|
|
||||||
import logging
|
|
||||||
|
|
||||||
from textual import work
|
from textual import work
|
||||||
from src.services.himalaya import client as himalaya_client
|
from src.services.himalaya import client as himalaya_client
|
||||||
|
|
||||||
@@ -23,7 +20,7 @@ async def archive_current(app):
|
|||||||
next_id, next_idx = app.message_store.find_prev_valid_id(current_index)
|
next_id, next_idx = app.message_store.find_prev_valid_id(current_index)
|
||||||
|
|
||||||
# Archive the message using our Himalaya client module
|
# Archive the message using our Himalaya client module
|
||||||
success = await himalaya_client.archive_message(current_message_id)
|
success = await himalaya_client.archive_messages([str(current_message_id)])
|
||||||
|
|
||||||
if success:
|
if success:
|
||||||
app.show_status(f"Message {current_message_id} archived.", "success")
|
app.show_status(f"Message {current_message_id} archived.", "success")
|
||||||
|
|||||||
@@ -1,12 +1,11 @@
|
|||||||
from .message_store import MessageStore
|
from .message_store import MessageStore
|
||||||
from .widgets.ContentContainer import ContentContainer
|
from .widgets.ContentContainer import ContentContainer
|
||||||
from .widgets.EnvelopeHeader import EnvelopeHeader
|
|
||||||
from .actions.task import action_create_task
|
from .actions.task import action_create_task
|
||||||
from .actions.open import action_open
|
from .actions.open import action_open
|
||||||
from .actions.delete import delete_current
|
from .actions.delete import delete_current
|
||||||
from src.services.taskwarrior import client as taskwarrior_client
|
from src.services.taskwarrior import client as taskwarrior_client
|
||||||
from src.services.himalaya import client as himalaya_client
|
from src.services.himalaya import client as himalaya_client
|
||||||
from textual.containers import ScrollableContainer, Vertical, Horizontal
|
from textual.containers import Container, ScrollableContainer, Vertical, Horizontal
|
||||||
from textual.timer import Timer
|
from textual.timer import Timer
|
||||||
from textual.binding import Binding
|
from textual.binding import Binding
|
||||||
from textual.reactive import reactive, Reactive
|
from textual.reactive import reactive, Reactive
|
||||||
@@ -16,14 +15,11 @@ from textual.logging import TextualHandler
|
|||||||
from textual.app import App, ComposeResult, SystemCommand, RenderResult
|
from textual.app import App, ComposeResult, SystemCommand, RenderResult
|
||||||
from textual.worker import Worker
|
from textual.worker import Worker
|
||||||
from textual import work
|
from textual import work
|
||||||
import re
|
|
||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
from datetime import UTC, datetime
|
from datetime import UTC, datetime
|
||||||
import asyncio
|
|
||||||
import logging
|
import logging
|
||||||
from typing import Iterable, Optional, List, Dict, Any, Generator, Tuple
|
from typing import Iterable, Optional, List, Dict, Any, Generator, Tuple
|
||||||
from collections import defaultdict
|
|
||||||
|
|
||||||
# Add the parent directory to the system path to resolve relative imports
|
# Add the parent directory to the system path to resolve relative imports
|
||||||
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||||
@@ -57,6 +53,7 @@ class EmailViewerApp(App):
|
|||||||
title = "Maildir GTD Reader"
|
title = "Maildir GTD Reader"
|
||||||
current_message_id: Reactive[int] = reactive(0)
|
current_message_id: Reactive[int] = reactive(0)
|
||||||
current_message_index: Reactive[int] = reactive(0)
|
current_message_index: Reactive[int] = reactive(0)
|
||||||
|
highlighted_message_index: Reactive[int] = reactive(0)
|
||||||
folder = reactive("INBOX")
|
folder = reactive("INBOX")
|
||||||
header_expanded = reactive(False)
|
header_expanded = reactive(False)
|
||||||
reload_needed = reactive(True)
|
reload_needed = reactive(True)
|
||||||
@@ -147,8 +144,7 @@ class EmailViewerApp(App):
|
|||||||
self.title = "MaildirGTD"
|
self.title = "MaildirGTD"
|
||||||
self.query_one("#main_content").border_title = self.status_title
|
self.query_one("#main_content").border_title = self.status_title
|
||||||
sort_indicator = "↑" if self.sort_order_ascending else "↓"
|
sort_indicator = "↑" if self.sort_order_ascending else "↓"
|
||||||
self.query_one("#envelopes_list").border_title = f"1️⃣ Emails {
|
self.query_one("#envelopes_list").border_title = f"1️⃣ Emails {sort_indicator}"
|
||||||
sort_indicator}"
|
|
||||||
self.query_one("#accounts_list").border_title = "2️⃣ Accounts"
|
self.query_one("#accounts_list").border_title = "2️⃣ Accounts"
|
||||||
|
|
||||||
self.query_one("#folders_list").border_title = "3️⃣ Folders"
|
self.query_one("#folders_list").border_title = "3️⃣ Folders"
|
||||||
@@ -171,8 +167,7 @@ class EmailViewerApp(App):
|
|||||||
def watch_sort_order_ascending(self, old_value: bool, new_value: bool) -> None:
|
def watch_sort_order_ascending(self, old_value: bool, new_value: bool) -> None:
|
||||||
"""Update the border title of the envelopes list when the sort order changes."""
|
"""Update the border title of the envelopes list when the sort order changes."""
|
||||||
sort_indicator = "↑" if new_value else "↓"
|
sort_indicator = "↑" if new_value else "↓"
|
||||||
self.query_one("#envelopes_list").border_title = f"1️⃣ Emails {
|
self.query_one("#envelopes_list").border_title = f"1️⃣ Emails {sort_indicator}"
|
||||||
sort_indicator}"
|
|
||||||
|
|
||||||
def watch_current_message_index(self, old_index: int, new_index: int) -> None:
|
def watch_current_message_index(self, old_index: int, new_index: int) -> None:
|
||||||
if new_index < 0:
|
if new_index < 0:
|
||||||
@@ -183,9 +178,11 @@ class EmailViewerApp(App):
|
|||||||
self.current_message_index = new_index
|
self.current_message_index = new_index
|
||||||
|
|
||||||
self._update_list_view_subtitle()
|
self._update_list_view_subtitle()
|
||||||
self.query_one("#envelopes_list").index = new_index
|
self.query_one("#envelopes_list", ListView).index = new_index
|
||||||
|
|
||||||
def watch_selected_messages(self, old_messages: set[int], new_messages: set[int]) -> None:
|
def watch_selected_messages(
|
||||||
|
self, old_messages: set[int], new_messages: set[int]
|
||||||
|
) -> None:
|
||||||
self._update_list_view_subtitle()
|
self._update_list_view_subtitle()
|
||||||
|
|
||||||
def _update_list_view_subtitle(self) -> None:
|
def _update_list_view_subtitle(self) -> None:
|
||||||
@@ -210,8 +207,7 @@ class EmailViewerApp(App):
|
|||||||
) -> None:
|
) -> None:
|
||||||
"""Called when the current message ID changes."""
|
"""Called when the current message ID changes."""
|
||||||
logging.info(
|
logging.info(
|
||||||
f"Current message ID changed from {
|
f"Current message ID changed from {old_message_id} to {new_message_id}"
|
||||||
old_message_id} to {new_message_id}"
|
|
||||||
)
|
)
|
||||||
if new_message_id == old_message_id:
|
if new_message_id == old_message_id:
|
||||||
return
|
return
|
||||||
@@ -273,9 +269,9 @@ class EmailViewerApp(App):
|
|||||||
if current_item is None or current_item.get("type") == "header":
|
if current_item is None or current_item.get("type") == "header":
|
||||||
return
|
return
|
||||||
|
|
||||||
message_id = int(current_item["id"])
|
# message_id = int(current_item["id"])
|
||||||
self.current_message_id = message_id
|
# self.current_message_id = message_id
|
||||||
self.current_message_index = highlighted_index
|
self.highlighted_message_index = highlighted_index
|
||||||
|
|
||||||
@work(exclusive=False)
|
@work(exclusive=False)
|
||||||
async def fetch_envelopes(self) -> None:
|
async def fetch_envelopes(self) -> None:
|
||||||
@@ -307,7 +303,7 @@ class EmailViewerApp(App):
|
|||||||
|
|
||||||
@work(exclusive=False)
|
@work(exclusive=False)
|
||||||
async def fetch_accounts(self) -> None:
|
async def fetch_accounts(self) -> None:
|
||||||
accounts_list = self.query_one("#accounts_list")
|
accounts_list = self.query_one("#accounts_list", ListView)
|
||||||
try:
|
try:
|
||||||
accounts_list.loading = True
|
accounts_list.loading = True
|
||||||
|
|
||||||
@@ -333,7 +329,7 @@ class EmailViewerApp(App):
|
|||||||
|
|
||||||
@work(exclusive=False)
|
@work(exclusive=False)
|
||||||
async def fetch_folders(self) -> None:
|
async def fetch_folders(self) -> None:
|
||||||
folders_list = self.query_one("#folders_list")
|
folders_list = self.query_one("#folders_list", ListView)
|
||||||
folders_list.clear()
|
folders_list.clear()
|
||||||
folders_list.append(
|
folders_list.append(
|
||||||
ListItem(Label("INBOX", classes="folder_name", markup=False))
|
ListItem(Label("INBOX", classes="folder_name", markup=False))
|
||||||
@@ -370,27 +366,29 @@ class EmailViewerApp(App):
|
|||||||
if item and item.get("type") == "header":
|
if item and item.get("type") == "header":
|
||||||
envelopes_list.append(
|
envelopes_list.append(
|
||||||
ListItem(
|
ListItem(
|
||||||
Horizontal(
|
Container(
|
||||||
Label("", classes="checkbox"), # Hidden checkbox for header
|
Label("", classes="checkbox"), # Hidden checkbox for header
|
||||||
Label(
|
Label(
|
||||||
item["label"],
|
item["label"],
|
||||||
classes="group_header",
|
classes="group_header",
|
||||||
markup=False,
|
markup=False,
|
||||||
),
|
),
|
||||||
classes="envelope_item_row"
|
classes="envelope_item_row",
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
elif item: # Check if not None
|
elif item: # Check if not None
|
||||||
# Extract sender and date
|
# Extract sender and date
|
||||||
sender_name = item.get("from", {}).get("name", item.get("from", {}).get("addr", "Unknown"))
|
sender_name = item.get("from", {}).get(
|
||||||
|
"name", item.get("from", {}).get("addr", "Unknown")
|
||||||
|
)
|
||||||
if not sender_name:
|
if not sender_name:
|
||||||
sender_name = item.get("from", {}).get("addr", "Unknown")
|
sender_name = item.get("from", {}).get("addr", "Unknown")
|
||||||
|
|
||||||
# Truncate sender name
|
# Truncate sender name
|
||||||
max_sender_len = 25 # Adjust as needed
|
max_sender_len = 25 # Adjust as needed
|
||||||
if len(sender_name) > max_sender_len:
|
if len(sender_name) > max_sender_len:
|
||||||
sender_name = sender_name[:max_sender_len-3] + "..."
|
sender_name = sender_name[: max_sender_len - 3] + "..."
|
||||||
|
|
||||||
message_date_str = item.get("date", "")
|
message_date_str = item.get("date", "")
|
||||||
formatted_date = ""
|
formatted_date = ""
|
||||||
@@ -403,25 +401,26 @@ class EmailViewerApp(App):
|
|||||||
formatted_date = "Invalid Date"
|
formatted_date = "Invalid Date"
|
||||||
|
|
||||||
list_item = ListItem(
|
list_item = ListItem(
|
||||||
Vertical(
|
Container(
|
||||||
Horizontal(
|
Container(
|
||||||
Label("☐", classes="checkbox"), # Placeholder for checkbox
|
Label("☐", classes="checkbox"), # Placeholder for checkbox
|
||||||
Label(sender_name, classes="sender_name"),
|
Label(sender_name, classes="sender_name"),
|
||||||
Label(formatted_date, classes="message_date"),
|
Label(formatted_date, classes="message_date"),
|
||||||
classes="envelope_header_row"
|
classes="envelope_header_row",
|
||||||
),
|
),
|
||||||
Horizontal(
|
Container(
|
||||||
Label(
|
Label(
|
||||||
str(item.get("subject", "")).strip(),
|
str(item.get("subject", "")).strip(),
|
||||||
classes="email_subject",
|
classes="email_subject",
|
||||||
markup=False,
|
markup=False,
|
||||||
)
|
),
|
||||||
|
classes="envelope_subject_row",
|
||||||
),
|
),
|
||||||
classes="envelope_item_row"
|
classes="envelope_item_row",
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
envelopes_list.append(list_item)
|
envelopes_list.append(list_item)
|
||||||
self.refresh_list_view_items() # Initial refresh of item states
|
self.refresh_list_view_items() # Initial refresh of item states
|
||||||
|
|
||||||
def refresh_list_view_items(self) -> None:
|
def refresh_list_view_items(self) -> None:
|
||||||
"""Update the visual state of existing ListItems without clearing the list."""
|
"""Update the visual state of existing ListItems without clearing the list."""
|
||||||
@@ -429,48 +428,44 @@ class EmailViewerApp(App):
|
|||||||
for i, list_item in enumerate(envelopes_list.children):
|
for i, list_item in enumerate(envelopes_list.children):
|
||||||
if isinstance(list_item, ListItem):
|
if isinstance(list_item, ListItem):
|
||||||
item_data = self.message_store.envelopes[i]
|
item_data = self.message_store.envelopes[i]
|
||||||
|
|
||||||
# Find the checkbox label within the ListItem's children
|
# Find the checkbox label within the ListItem's children
|
||||||
checkbox_label = None
|
# checkbox_label = list_item.query_one(".checkbox", Label)
|
||||||
for child in list_item.walk_children():
|
if item_data and item_data.get("type") != "header":
|
||||||
if isinstance(child, Label) and "checkbox" in child.classes:
|
message_id = int(item_data["id"])
|
||||||
checkbox_label = child
|
is_selected = message_id in self.selected_messages or False
|
||||||
break
|
list_item.set_class(is_selected, "selection")
|
||||||
|
|
||||||
if checkbox_label:
|
# if checkbox_label:
|
||||||
if item_data and item_data.get("type") != "header":
|
# checkbox_label.update("\uf4a7" if is_selected else "\ue640")
|
||||||
message_id = int(item_data["id"])
|
# checkbox_label.display = True # Always display checkbox
|
||||||
is_selected = message_id in self.selected_messages
|
|
||||||
|
|
||||||
checkbox_label.update("\uf4a7" if is_selected else "\ue640")
|
# list_item.highlighted = is_selected
|
||||||
checkbox_label.display = True # Always display checkbox
|
|
||||||
|
|
||||||
list_item.highlighted = is_selected
|
# # Update sender and date labels
|
||||||
|
# sender_name = item_data.get("from", {}).get("name", item_data.get("from", {}).get("addr", "Unknown"))
|
||||||
|
# if not sender_name:
|
||||||
|
# sender_name = item_data.get("from", {}).get("addr", "Unknown")
|
||||||
|
# max_sender_len = 25
|
||||||
|
# if len(sender_name) > max_sender_len:
|
||||||
|
# sender_name = sender_name[:max_sender_len-3] + "..."
|
||||||
|
# list_item.query_one(".sender_name", Label).update(sender_name)
|
||||||
|
|
||||||
# Update sender and date labels
|
# message_date_str = item_data.get("date", "")
|
||||||
sender_name = item_data.get("from", {}).get("name", item_data.get("from", {}).get("addr", "Unknown"))
|
# formatted_date = ""
|
||||||
if not sender_name:
|
# if message_date_str:
|
||||||
sender_name = item_data.get("from", {}).get("addr", "Unknown")
|
# try:
|
||||||
max_sender_len = 25
|
# dt_object = datetime.fromisoformat(message_date_str)
|
||||||
if len(sender_name) > max_sender_len:
|
# formatted_date = dt_object.strftime("%m/%d %H:%M")
|
||||||
sender_name = sender_name[:max_sender_len-3] + "..."
|
# except ValueError:
|
||||||
list_item.query_one(".sender_name", Label).update(sender_name)
|
# formatted_date = "Invalid Date"
|
||||||
|
# list_item.query_one(".message_date", Label).update(formatted_date)
|
||||||
|
|
||||||
message_date_str = item_data.get("date", "")
|
# else:
|
||||||
formatted_date = ""
|
# # For header items, checkbox should be unchecked and visible
|
||||||
if message_date_str:
|
# checkbox_label.update("\ue640") # Always unchecked for headers
|
||||||
try:
|
# checkbox_label.display = True # Always display checkbox
|
||||||
dt_object = datetime.fromisoformat(message_date_str)
|
# list_item.highlighted = False # Headers are never highlighted for selection
|
||||||
formatted_date = dt_object.strftime("%m/%d %H:%M")
|
|
||||||
except ValueError:
|
|
||||||
formatted_date = "Invalid Date"
|
|
||||||
list_item.query_one(".message_date", Label).update(formatted_date)
|
|
||||||
|
|
||||||
else:
|
|
||||||
# For header items, checkbox should be unchecked and visible
|
|
||||||
checkbox_label.update("\ue640") # Always unchecked for headers
|
|
||||||
checkbox_label.display = True # Always display checkbox
|
|
||||||
list_item.highlighted = False # Headers are never highlighted for selection
|
|
||||||
|
|
||||||
# Update total messages count (this is still fine here)
|
# Update total messages count (this is still fine here)
|
||||||
# self.total_messages = self.message_store.total_messages
|
# self.total_messages = self.message_store.total_messages
|
||||||
@@ -501,7 +496,7 @@ class EmailViewerApp(App):
|
|||||||
async def action_toggle_mode(self) -> None:
|
async def action_toggle_mode(self) -> None:
|
||||||
"""Toggle the content mode between plaintext and markdown."""
|
"""Toggle the content mode between plaintext and markdown."""
|
||||||
content_container = self.query_one(ContentContainer)
|
content_container = self.query_one(ContentContainer)
|
||||||
await content_container.toggle_mode()
|
await content_container.action_toggle_mode()
|
||||||
|
|
||||||
def action_next(self) -> None:
|
def action_next(self) -> None:
|
||||||
if not self.current_message_index >= 0:
|
if not self.current_message_index >= 0:
|
||||||
@@ -543,7 +538,9 @@ class EmailViewerApp(App):
|
|||||||
highest_archived_id = max(message_ids_to_archive)
|
highest_archived_id = max(message_ids_to_archive)
|
||||||
metadata = self.message_store.get_metadata(highest_archived_id)
|
metadata = self.message_store.get_metadata(highest_archived_id)
|
||||||
if metadata:
|
if metadata:
|
||||||
next_id, _ = self.message_store.find_next_valid_id(metadata["index"])
|
next_id, _ = self.message_store.find_next_valid_id(
|
||||||
|
metadata["index"]
|
||||||
|
)
|
||||||
if next_id is None:
|
if next_id is None:
|
||||||
next_id, _ = self.message_store.find_prev_valid_id(
|
next_id, _ = self.message_store.find_prev_valid_id(
|
||||||
metadata["index"]
|
metadata["index"]
|
||||||
@@ -555,7 +552,7 @@ class EmailViewerApp(App):
|
|||||||
)
|
)
|
||||||
|
|
||||||
if success:
|
if success:
|
||||||
self.show_status(message)
|
self.show_status(message or "Success archived")
|
||||||
self.selected_messages.clear()
|
self.selected_messages.clear()
|
||||||
else:
|
else:
|
||||||
self.show_status(f"Failed to archive messages: {message}", "error")
|
self.show_status(f"Failed to archive messages: {message}", "error")
|
||||||
@@ -575,10 +572,10 @@ class EmailViewerApp(App):
|
|||||||
next_id, _ = self.message_store.find_prev_valid_id(current_idx)
|
next_id, _ = self.message_store.find_prev_valid_id(current_idx)
|
||||||
next_id_to_select = next_id
|
next_id_to_select = next_id
|
||||||
|
|
||||||
message, success = await himalaya_client.archive_message(current_id)
|
message, success = await himalaya_client.archive_messages([str(current_id)])
|
||||||
|
|
||||||
if success:
|
if success:
|
||||||
self.show_status(message)
|
self.show_status(message or "Archived")
|
||||||
else:
|
else:
|
||||||
self.show_status(
|
self.show_status(
|
||||||
f"Failed to archive message {current_id}: {message}", "error"
|
f"Failed to archive message {current_id}: {message}", "error"
|
||||||
@@ -642,32 +639,27 @@ class EmailViewerApp(App):
|
|||||||
|
|
||||||
def action_toggle_selection(self) -> None:
|
def action_toggle_selection(self) -> None:
|
||||||
"""Toggle selection for the current message."""
|
"""Toggle selection for the current message."""
|
||||||
current_item_data = self.message_store.envelopes[self.current_message_index]
|
current_item_data = self.message_store.envelopes[self.highlighted_message_index]
|
||||||
if current_item_data and current_item_data.get("type") != "header":
|
if current_item_data and current_item_data.get("type") != "header":
|
||||||
message_id = int(current_item_data["id"])
|
message_id = int(current_item_data["id"])
|
||||||
|
envelopes_list = self.query_one("#envelopes_list", ListView)
|
||||||
|
current_list_item = envelopes_list.children[self.highlighted_message_index]
|
||||||
|
checkbox_label = current_list_item.query_one(".checkbox", Label)
|
||||||
if message_id in self.selected_messages:
|
if message_id in self.selected_messages:
|
||||||
self.selected_messages.remove(message_id)
|
self.selected_messages.remove(message_id)
|
||||||
|
checkbox_label.remove_class("x-list")
|
||||||
|
checkbox_label.update("\ue640")
|
||||||
else:
|
else:
|
||||||
self.selected_messages.add(message_id)
|
self.selected_messages.add(message_id)
|
||||||
|
checkbox_label.add_class("x-list")
|
||||||
# Manually update the current ListItem
|
checkbox_label.update("\uf4a7")
|
||||||
envelopes_list = self.query_one("#envelopes_list", ListView)
|
|
||||||
current_list_item = envelopes_list.children[self.current_message_index]
|
|
||||||
if isinstance(current_list_item, ListItem):
|
|
||||||
checkbox_label = None
|
|
||||||
for child in current_list_item.walk_children():
|
|
||||||
if isinstance(child, Label) and "checkbox" in child.classes:
|
|
||||||
checkbox_label = child
|
|
||||||
break
|
|
||||||
if checkbox_label:
|
|
||||||
checkbox_label.update("\uf4a7" if message_id in self.selected_messages else "\ue640")
|
|
||||||
current_list_item.highlighted = (message_id in self.selected_messages)
|
|
||||||
self._update_list_view_subtitle()
|
self._update_list_view_subtitle()
|
||||||
|
|
||||||
def action_clear_selection(self) -> None:
|
def action_clear_selection(self) -> None:
|
||||||
"""Clear all selected messages."""
|
"""Clear all selected messages."""
|
||||||
self.selected_messages.clear()
|
self.selected_messages.clear()
|
||||||
self.refresh_list_view_items() # Refresh all items to uncheck checkboxes
|
self.refresh_list_view_items() # Refresh all items to uncheck checkboxes
|
||||||
self._update_list_view_subtitle()
|
self._update_list_view_subtitle()
|
||||||
|
|
||||||
def action_oldest(self) -> None:
|
def action_oldest(self) -> None:
|
||||||
|
|||||||
@@ -16,6 +16,10 @@
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.envelope-selected {
|
||||||
|
tint: $accent 20%;
|
||||||
|
}
|
||||||
|
|
||||||
#sidebar:focus-within {
|
#sidebar:focus-within {
|
||||||
background: $panel;
|
background: $panel;
|
||||||
.list_view:blur {
|
.list_view:blur {
|
||||||
@@ -112,6 +116,7 @@ Markdown {
|
|||||||
ListItem:even {
|
ListItem:even {
|
||||||
background: rgb(50, 50, 56);
|
background: rgb(50, 50, 56);
|
||||||
}
|
}
|
||||||
|
|
||||||
& > ListItem {
|
& > ListItem {
|
||||||
&.-highlight, .selection {
|
&.-highlight, .selection {
|
||||||
color: $block-cursor-blurred-foreground;
|
color: $block-cursor-blurred-foreground;
|
||||||
@@ -124,11 +129,18 @@ Markdown {
|
|||||||
.envelope_item_row {
|
.envelope_item_row {
|
||||||
height: auto;
|
height: auto;
|
||||||
width: 1fr;
|
width: 1fr;
|
||||||
Horizontal {
|
|
||||||
|
.envelope_header_row, .envelope_subject_row {
|
||||||
height: auto;
|
height: auto;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.x-list {
|
||||||
|
tint: $accent 20%;
|
||||||
|
}
|
||||||
|
|
||||||
#open_message_container, #create_task_container {
|
#open_message_container, #create_task_container {
|
||||||
border: panel $border;
|
border: panel $border;
|
||||||
dock: right;
|
dock: right;
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ from .client import (
|
|||||||
list_accounts,
|
list_accounts,
|
||||||
list_folders,
|
list_folders,
|
||||||
delete_message,
|
delete_message,
|
||||||
archive_message,
|
archive_messages,
|
||||||
get_message_content,
|
get_message_content,
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -16,6 +16,6 @@ __all__ = [
|
|||||||
"list_accounts",
|
"list_accounts",
|
||||||
"list_folders",
|
"list_folders",
|
||||||
"delete_message",
|
"delete_message",
|
||||||
"archive_message",
|
"archive_messages",
|
||||||
"get_message_content",
|
"get_message_content",
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -116,28 +116,28 @@ async def delete_message(message_id: int) -> bool:
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
async def archive_message(message_id: int) -> bool:
|
# async def archive_message(message_id: int) -> [str, bool]:
|
||||||
"""
|
# """
|
||||||
Archive a message by its ID.
|
# Archive a message by its ID.
|
||||||
|
|
||||||
Args:
|
# Args:
|
||||||
message_id: The ID of the message to archive
|
# message_id: The ID of the message to archive
|
||||||
|
|
||||||
Returns:
|
# Returns:
|
||||||
True if archiving was successful, False otherwise
|
# True if archiving was successful, False otherwise
|
||||||
"""
|
# """
|
||||||
try:
|
# try:
|
||||||
process = await asyncio.create_subprocess_shell(
|
# process = await asyncio.create_subprocess_shell(
|
||||||
f"himalaya message move Archives {message_id}",
|
# f"himalaya message move Archives {message_id}",
|
||||||
stdout=asyncio.subprocess.PIPE,
|
# stdout=asyncio.subprocess.PIPE,
|
||||||
stderr=asyncio.subprocess.PIPE,
|
# stderr=asyncio.subprocess.PIPE,
|
||||||
)
|
# )
|
||||||
stdout, stderr = await process.communicate()
|
# stdout, stderr = await process.communicate()
|
||||||
|
|
||||||
return process.returncode == 0
|
# return [stdout.decode(), process.returncode == 0]
|
||||||
except Exception as e:
|
# except Exception as e:
|
||||||
logging.error(f"Exception during message archiving: {e}")
|
# logging.error(f"Exception during message archiving: {e}")
|
||||||
return False
|
# return False
|
||||||
|
|
||||||
|
|
||||||
async def archive_messages(message_ids: List[str]) -> Tuple[Optional[str], bool]:
|
async def archive_messages(message_ids: List[str]) -> Tuple[Optional[str], bool]:
|
||||||
@@ -197,8 +197,7 @@ async def get_message_content(message_id: int) -> Tuple[Optional[str], bool]:
|
|||||||
content = stdout.decode()
|
content = stdout.decode()
|
||||||
return content, True
|
return content, True
|
||||||
else:
|
else:
|
||||||
logging.error(f"Error retrieving message content: {
|
logging.error(f"Error retrieving message content: {stderr.decode()}")
|
||||||
stderr.decode()}")
|
|
||||||
return None, False
|
return None, False
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logging.error(f"Exception during message content retrieval: {e}")
|
logging.error(f"Exception during message content retrieval: {e}")
|
||||||
|
|||||||
Reference in New Issue
Block a user