navigation and archive behavior fixed
This commit is contained in:
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -28,8 +28,8 @@ async def archive_current(app) -> None:
|
|||||||
logging.info(stdout.decode())
|
logging.info(stdout.decode())
|
||||||
if process.returncode == 0:
|
if process.returncode == 0:
|
||||||
await app.query_one(ListView).pop(index)
|
await app.query_one(ListView).pop(index)
|
||||||
app.query_one(ListView).index = index + 1
|
app.query_one(ListView).index = index
|
||||||
app.action_next() # Automatically show the next message
|
# app.action_next() # Automatically show the next message
|
||||||
else:
|
else:
|
||||||
app.show_status(f"Error archiving message: {stderr.decode()}", "error")
|
app.show_status(f"Error archiving message: {stderr.decode()}", "error")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
|||||||
@@ -17,8 +17,8 @@ async def delete_current(app) -> None:
|
|||||||
app.show_status(f"{stdout.decode()}", "info")
|
app.show_status(f"{stdout.decode()}", "info")
|
||||||
if process.returncode == 0:
|
if process.returncode == 0:
|
||||||
await app.query_one(ListView).pop(index)
|
await app.query_one(ListView).pop(index)
|
||||||
app.query_one(ListView).index = index + 1
|
app.query_one(ListView).index = index
|
||||||
app.action_next() # Automatically show the next message
|
# app.action_next() # Automatically show the next message
|
||||||
else:
|
else:
|
||||||
app.show_status(f"Failed to delete message {app.current_message_id}. {stderr.decode()}", "error")
|
app.show_status(f"Failed to delete message {app.current_message_id}. {stderr.decode()}", "error")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
|||||||
@@ -57,12 +57,10 @@ class EmailViewerApp(App):
|
|||||||
header_expanded = reactive(False)
|
header_expanded = reactive(False)
|
||||||
reload_needed = reactive(True)
|
reload_needed = reactive(True)
|
||||||
all_envelopes = reactive([])
|
all_envelopes = reactive([])
|
||||||
next_id: Reactive[int] = reactive(0)
|
|
||||||
previous_id: Reactive[int] = reactive(0)
|
|
||||||
oldest_id: Reactive[int] = reactive(0)
|
oldest_id: Reactive[int] = reactive(0)
|
||||||
newest_id: Reactive[int] = reactive(0)
|
newest_id: Reactive[int] = reactive(0)
|
||||||
msg_worker: Worker | None = None
|
msg_worker: Worker | None = None
|
||||||
messsage_metadata: dict[int, dict] = {}
|
message_metadata: dict[int, dict] = {}
|
||||||
message_body_cache: dict[int, str] = {}
|
message_body_cache: dict[int, str] = {}
|
||||||
total_messages: Reactive[int] = reactive(0)
|
total_messages: Reactive[int] = reactive(0)
|
||||||
status_title = reactive("Message View")
|
status_title = reactive("Message View")
|
||||||
@@ -156,36 +154,28 @@ class EmailViewerApp(App):
|
|||||||
self.query_one("#envelopes_list").border_title = f"\[1] Emails {sort_indicator}"
|
self.query_one("#envelopes_list").border_title = f"\[1] Emails {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:
|
||||||
self.query_one("#envelopes_list").border_subtitle = f"[b]{self.current_message_index}[/b]/{self.total_messages}"
|
if (new_index < 0):
|
||||||
|
new_index = 0
|
||||||
|
self.current_message_index = new_index
|
||||||
|
if (new_index > self.total_messages):
|
||||||
|
new_index = self.total_messages
|
||||||
|
self.current_message_index = new_index
|
||||||
|
self.query_one("#envelopes_list").border_subtitle = f"[b]{new_index}[/b]/{self.total_messages}"
|
||||||
|
self.query_one("#envelopes_list").index = new_index
|
||||||
|
|
||||||
|
|
||||||
def compute_newest_id(self) -> None:
|
def compute_newest_id(self) -> None:
|
||||||
if not self.all_envelopes:
|
if not self.all_envelopes:
|
||||||
return 0
|
return 0
|
||||||
return sorted((int(envelope['id']) for envelope in self.valid_envelopes))[-1]
|
items = sorted(self.valid_envelopes, key=lambda x: x['date'], reverse=not self.sort_order_ascending)
|
||||||
|
return items[-1]['id'] if items else 0
|
||||||
|
|
||||||
def compute_oldest_id(self) -> None:
|
def compute_oldest_id(self) -> None:
|
||||||
if not self.valid_envelopes:
|
if not self.valid_envelopes:
|
||||||
return 0
|
return 0
|
||||||
sorted_msgs = sorted((int(envelope['id']) for envelope in self.valid_envelopes))
|
items = sorted(self.valid_envelopes, key=lambda x: x['date'], reverse=not self.sort_order_ascending)
|
||||||
if len(sorted_msgs) > 0:
|
return items[0]['id'] if items else 0
|
||||||
return sorted_msgs[0]
|
|
||||||
return 0
|
|
||||||
|
|
||||||
def compute_next_id(self) -> None:
|
|
||||||
if not self.valid_envelopes:
|
|
||||||
return 0
|
|
||||||
for envelope_id in sorted(int(envelope['id']) for envelope in self.valid_envelopes):
|
|
||||||
if envelope_id > int(self.current_message_id):
|
|
||||||
return envelope_id
|
|
||||||
return self.newest_id
|
|
||||||
|
|
||||||
def compute_previous_id(self) -> None:
|
|
||||||
if not self.valid_envelopes:
|
|
||||||
return 0
|
|
||||||
for envelope_id in sorted((int(envelope['id']) for envelope in self.valid_envelopes), reverse=True):
|
|
||||||
if envelope_id < int(self.current_message_id):
|
|
||||||
return envelope_id
|
|
||||||
return self.oldest_id
|
|
||||||
|
|
||||||
def watch_reload_needed(self, old_reload_needed: bool, new_reload_needed: bool) -> None:
|
def watch_reload_needed(self, old_reload_needed: bool, new_reload_needed: bool) -> None:
|
||||||
logging.info(f"Reload needed: {new_reload_needed}")
|
logging.info(f"Reload needed: {new_reload_needed}")
|
||||||
@@ -200,14 +190,17 @@ class EmailViewerApp(App):
|
|||||||
return
|
return
|
||||||
self.msg_worker.cancel() if self.msg_worker else None
|
self.msg_worker.cancel() if self.msg_worker else None
|
||||||
headers = self.query_one(EnvelopeHeader)
|
headers = self.query_one(EnvelopeHeader)
|
||||||
|
logging.info(f"new_message_id: {new_message_id}, type: {type(new_message_id)}")
|
||||||
|
logging.info(f"message_metadata keys: {list(self.message_metadata.keys())}")
|
||||||
if new_message_id in self.message_metadata:
|
if new_message_id in self.message_metadata:
|
||||||
metadata = self.message_metadata[new_message_id]
|
metadata = self.message_metadata[new_message_id]
|
||||||
self.current_message_index = metadata['index']
|
self.current_message_index = metadata['index']
|
||||||
headers.subject = metadata['subject'].strip()
|
headers.subject = metadata['subject'].strip()
|
||||||
headers.from_ = metadata['from'].get('addr', '')
|
headers.from_ = metadata['from'].get('addr', '')
|
||||||
headers.to = metadata['to'].get('addr', '')
|
headers.to = metadata['to'].get('addr', '')
|
||||||
headers.date = datetime.strptime(metadata['date'].replace("+00:00", ""), "%Y-%m-%d %H:%M").strftime("%a %b %d %H:%M")
|
msgdate = re.sub(r"[\+\-]\d\d:\d\d", "", metadata['date'])
|
||||||
|
msgdate = datetime.strptime(msgdate, "%Y-%m-%d %H:%M").strftime("%a %b %d %H:%M")
|
||||||
|
headers.date = msgdate
|
||||||
headers.cc = metadata['cc'].get('addr', '') if 'cc' in metadata else ""
|
headers.cc = metadata['cc'].get('addr', '') if 'cc' in metadata else ""
|
||||||
self.query_one(ListView).index = metadata['index']
|
self.query_one(ListView).index = metadata['index']
|
||||||
else:
|
else:
|
||||||
@@ -277,11 +270,11 @@ class EmailViewerApp(App):
|
|||||||
self.total_messages = len(envelopes)
|
self.total_messages = len(envelopes)
|
||||||
msglist.clear()
|
msglist.clear()
|
||||||
|
|
||||||
envelopes = sorted(envelopes, key=lambda x: int(x['id']), reverse=not self.sort_order_ascending)
|
envelopes = sorted(envelopes, key=lambda x: x['date'], reverse=not self.sort_order_ascending)
|
||||||
grouped_envelopes = group_envelopes_by_date(envelopes)
|
grouped_envelopes = group_envelopes_by_date(envelopes)
|
||||||
self.all_envelopes = grouped_envelopes
|
self.all_envelopes = grouped_envelopes
|
||||||
self.message_metadata = {
|
self.message_metadata = {
|
||||||
envelope['id']: {
|
int(envelope['id']): {
|
||||||
'subject': envelope.get('subject', ''),
|
'subject': envelope.get('subject', ''),
|
||||||
'from': envelope.get('from', {}),
|
'from': envelope.get('from', {}),
|
||||||
'to': envelope.get('to', {}),
|
'to': envelope.get('to', {}),
|
||||||
@@ -355,12 +348,14 @@ class EmailViewerApp(App):
|
|||||||
finally:
|
finally:
|
||||||
folders_list.loading = False
|
folders_list.loading = False
|
||||||
|
|
||||||
def show_message(self, message_id: int) -> None:
|
def show_message(self, message_id: int, new_index=None) -> None:
|
||||||
|
if new_index:
|
||||||
|
self.current_message_index = new_index
|
||||||
self.current_message_id = message_id
|
self.current_message_id = message_id
|
||||||
|
|
||||||
def show_status(self, message: str, severity: str = "information") -> None:
|
def show_status(self, message: str, severity: str = "information") -> None:
|
||||||
"""Display a status message using the built-in notify function."""
|
"""Display a status message using the built-in notify function."""
|
||||||
self.notify(message, title="Status", severity=severity, timeout=1.6, markup=True)
|
self.notify(message, title="Status", severity=severity, timeout=2.6, markup=True)
|
||||||
|
|
||||||
def action_toggle_header(self) -> None:
|
def action_toggle_header(self) -> None:
|
||||||
"""Toggle the visibility of the EnvelopeHeader panel."""
|
"""Toggle the visibility of the EnvelopeHeader panel."""
|
||||||
@@ -381,30 +376,42 @@ class EmailViewerApp(App):
|
|||||||
self.action_newest()
|
self.action_newest()
|
||||||
|
|
||||||
def action_next(self) -> None:
|
def action_next(self) -> None:
|
||||||
if self.sort_order_ascending:
|
if not self.current_message_index >= 0:
|
||||||
self.show_message(self.next_id)
|
return
|
||||||
else:
|
modifier = 1
|
||||||
self.show_message(self.previous_id)
|
idx = self.current_message_index
|
||||||
|
if self.all_envelopes[idx + modifier] is None or self.all_envelopes[idx + modifier].get("type") == "header":
|
||||||
|
idx = idx + modifier
|
||||||
|
self.show_message(self.all_envelopes[idx + modifier].get("id"), idx + modifier)
|
||||||
self.fetch_envelopes() if self.reload_needed else None
|
self.fetch_envelopes() if self.reload_needed else None
|
||||||
|
|
||||||
def action_previous(self) -> None:
|
def action_previous(self) -> None:
|
||||||
if self.sort_order_ascending:
|
if not self.current_message_index >= 0:
|
||||||
self.show_message(self.previous_id)
|
return
|
||||||
else:
|
modifier = -1
|
||||||
self.show_message(self.next_id)
|
idx = self.current_message_index
|
||||||
|
if self.all_envelopes[idx + modifier] is None or self.all_envelopes[idx + modifier].get("type") == "header":
|
||||||
|
idx = idx + modifier
|
||||||
|
self.show_message(self.all_envelopes[idx + modifier].get("id"), idx + modifier)
|
||||||
self.fetch_envelopes() if self.reload_needed else None
|
self.fetch_envelopes() if self.reload_needed else None
|
||||||
|
|
||||||
def action_delete(self) -> None:
|
async def action_delete(self) -> None:
|
||||||
self.all_envelopes.remove(self.all_envelopes[self.current_message_index])
|
self.all_envelopes.remove(self.all_envelopes[self.current_message_index])
|
||||||
self.message_body_cache.pop(self.current_message_id, None)
|
self.message_body_cache.pop(self.current_message_id, None)
|
||||||
self.total_messages = len(self.all_envelopes)
|
self.total_messages = len(self.all_envelopes)
|
||||||
delete_current(self)
|
delete_current(self)
|
||||||
|
|
||||||
def action_archive(self) -> None:
|
async def action_archive(self) -> None:
|
||||||
self.all_envelopes.remove(self.all_envelopes[self.current_message_index])
|
self.all_envelopes.remove(self.all_envelopes[self.current_message_index])
|
||||||
self.message_body_cache.pop(self.current_message_id, None)
|
self.message_body_cache.pop(self.current_message_id, None)
|
||||||
self.total_messages = len(self.all_envelopes)
|
self.total_messages = len(self.all_envelopes)
|
||||||
archive_current(self)
|
worker = archive_current(self)
|
||||||
|
await worker.wait()
|
||||||
|
newmsg = self.all_envelopes[self.current_message_index]
|
||||||
|
if newmsg.get('type') == "header":
|
||||||
|
newmsg = self.current_message_index = self.current_message_index + 1
|
||||||
|
return
|
||||||
|
self.show_message(newmsg['id'])
|
||||||
|
|
||||||
def action_open(self) -> None:
|
def action_open(self) -> None:
|
||||||
action_open(self)
|
action_open(self)
|
||||||
|
|||||||
@@ -140,7 +140,7 @@ Markdown {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Label.group_header {
|
Label.group_header {
|
||||||
color: rgb(64,64,64);
|
color: rgb(140, 140, 140);
|
||||||
text-style: bold;
|
text-style: bold;
|
||||||
background: rgb(64, 62, 65);
|
background: rgb(64, 62, 65);
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
|
import re
|
||||||
from typing import List, Dict
|
from typing import List, Dict
|
||||||
|
|
||||||
def group_envelopes_by_date(envelopes: List[Dict]) -> List[Dict]:
|
def group_envelopes_by_date(envelopes: List[Dict]) -> List[Dict]:
|
||||||
@@ -29,7 +30,8 @@ def group_envelopes_by_date(envelopes: List[Dict]) -> List[Dict]:
|
|||||||
|
|
||||||
current_group = None
|
current_group = None
|
||||||
for envelope in envelopes:
|
for envelope in envelopes:
|
||||||
envelope_date = datetime.strptime(envelope['date'].split('+')[0], "%Y-%m-%d %H:%M")
|
envelope_date = re.sub(r"[\+\-]\d\d:\d\d", "", envelope['date'])
|
||||||
|
envelope_date = datetime.strptime(envelope_date, "%Y-%m-%d %H:%M")
|
||||||
group_label = get_group_label(envelope_date)
|
group_label = get_group_label(envelope_date)
|
||||||
if group_label != current_group:
|
if group_label != current_group:
|
||||||
grouped_envelopes.append({"type": "header", "label": group_label})
|
grouped_envelopes.append({"type": "header", "label": group_label})
|
||||||
|
|||||||
Reference in New Issue
Block a user