feat: render HTML email bodies via flutter_html
Email detail screen now renders the message htmlBody with the flutter_html widget when present, falling back to SelectableText for plain-text-only mail. Remote http(s) images are blocked by default to defeat tracking pixels; an opt-in "Load remote images" button reveals them per-screen. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.7
parent
ab6dc89665
commit
44d02afc46
@@ -17,49 +17,3 @@ Git repo should not contain unknown files.
|
||||
Then commit.
|
||||
|
||||
## Tasks
|
||||
|
||||
### Render HTML email bodies
|
||||
|
||||
#### Current state
|
||||
|
||||
HTML mail *reading* (transport + storage) is already implemented: the IMAP
|
||||
fetcher stores the HTML body on `EmailBody.htmlBody`
|
||||
(`lib/core/models/email.dart:89`). What is missing is HTML *rendering*:
|
||||
`lib/ui/screens/email_detail_screen.dart:158` currently strips tags via
|
||||
`htmlToPlain(body.htmlBody ?? '')` and shows the result as plain text.
|
||||
|
||||
#### Plan
|
||||
|
||||
1. Add `flutter_html: ^3.0.0` to `pubspec.yaml`.
|
||||
- Mature, pure-Dart (no JS / no platform views), works on desktop +
|
||||
mobile + web.
|
||||
2. Update `lib/ui/screens/email_detail_screen.dart` `_buildBody`:
|
||||
- Prefer `body.htmlBody` over `body.textBody`.
|
||||
- If `htmlBody` is present and non-empty, render with the `Html` widget.
|
||||
- Else fall back to the current `SelectableText(textBody)` path.
|
||||
3. Block remote image loading by default (privacy — defeats tracking
|
||||
pixels). At the top of an HTML message, show a small
|
||||
"Load remote images" button that flips a per-screen `bool` and
|
||||
re-renders. Implement by passing a custom image-loading delegate to
|
||||
`flutter_html` that returns an empty widget for `http(s)` images
|
||||
until the flag is set. Inline `cid:` images are out of scope for
|
||||
this task.
|
||||
4. Leave `htmlToPlain` in place — it is still used for reply / forward
|
||||
quoting (`_quotedBody`) where plain text is correct.
|
||||
5. No DB schema changes, no generated-code changes, no migration.
|
||||
6. No new tests required (pure UI rendering change). Existing widget /
|
||||
integration tests must keep passing.
|
||||
|
||||
#### Out of scope (follow-ups if needed)
|
||||
|
||||
- Clickable / launchable links inside HTML.
|
||||
- Dark-mode HTML colour normalisation.
|
||||
- Sandboxed rendering via `WebView` / `flutter_inappwebview`.
|
||||
- Inline `cid:` image resolution.
|
||||
|
||||
#### Verification
|
||||
|
||||
- `task deploy-android` succeeds.
|
||||
- Manual: open an HTML newsletter — formatting (lists, bold, links) is
|
||||
visible instead of raw tags or stripped text.
|
||||
- Manual: a plain-text-only email still renders unchanged.
|
||||
|
||||
Reference in New Issue
Block a user