From c490d0f20cb26a33f50b592105297f680565c954 Mon Sep 17 00:00:00 2001 From: Simon Chopin Date: Wed, 1 Jul 2026 09:58:44 +0200 Subject: [PATCH 1/2] thread/settings: allow the user to use the Webview dark theme We still need the background toggling because even in dark mode it'll use a white background when there is no content. --- dodo/settings.py | 8 ++++++++ dodo/thread.py | 2 ++ 2 files changed, 10 insertions(+) diff --git a/dodo/settings.py b/dodo/settings.py index c112eb2..7a2444d 100644 --- a/dodo/settings.py +++ b/dodo/settings.py @@ -204,6 +204,14 @@ :func:`~dodo.settings.html_confirm_open_links` is True. """ +"""Force the HTML view to use dark mode + +By default the HTML view of an email will use black text on a white background, which might +clash hard with your selected theme. This toggle forces the use of the engine's dark mode +instead. +""" +html_dark_mode = False + # visual theme = themes.nord """The GUI theme diff --git a/dodo/thread.py b/dodo/thread.py index f15419d..0642e34 100644 --- a/dodo/thread.py +++ b/dodo/thread.py @@ -549,6 +549,8 @@ def __init__(self, a: app.Dodo, thread_id: str, search_query: str, parent: Optio self.message_profile.installUrlSchemeHandler(b'message', self.message_handler) self.message_profile.settings().setAttribute( QWebEngineSettings.WebAttribute.JavascriptEnabled, False) + self.message_profile.settings().setAttribute( + QWebEngineSettings.WebAttribute.ForceDarkMode, settings.html_dark_mode) # The interceptor must not be garbage collected, so keep a reference self.url_interceptor = RemoteBlockingUrlRequestInterceptor() From ae2bab2967b3121c43c94ea3491af4a4c508b142 Mon Sep 17 00:00:00 2001 From: Simon Chopin Date: Wed, 1 Jul 2026 09:29:20 +0200 Subject: [PATCH 2/2] thread: only force background color in normal mode In #135 we forced the background color to the theme one for the email body view to avoid a white flash when first entering a thread view before it switches to plain text view. However, it kinda broke the HTML view as most emails out there assume a default white background, making them unreadable if you're using a dark theme. --- dodo/thread.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/dodo/thread.py b/dodo/thread.py index 0642e34..257cd2d 100644 --- a/dodo/thread.py +++ b/dodo/thread.py @@ -560,7 +560,7 @@ def __init__(self, a: app.Dodo, thread_id: str, search_query: str, parent: Optio page = MessagePage(self.app, self.message_profile, self.message_view) self.message_view.setPage(page) self.message_view.setZoomFactor(1.2) - self.message_view.page().setBackgroundColor(QColor(settings.theme['bg'])) + self._update_background() self.layout_panel() @@ -571,6 +571,16 @@ def _get_collapsed(self) -> set[str]: collapsed.add(self.model.message_at(idx)['id']) return collapsed + def _update_background(self): + if self.html_mode: + if settings.html_dark_mode: + color = 0 + else: + color = 0xFFFFFF + else: + color = QColor(settings.theme['bg']) + self.message_view.page().setBackgroundColor(color) + def _restore_collapsed(self, collapsed: set[str]): self.thread_list.expandAll() for idx in self.model.iterate_indices(): @@ -804,6 +814,7 @@ def toggle_html(self) -> None: """Toggle between HTML and plain text message view""" self.html_mode = not self.html_mode + self._update_background() self.refresh_content() def reply(self, to_all: bool=True) -> None: