From 5a7989c6400d9182c2cf2060b1596cd9118344b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Romero?= Date: Fri, 6 Nov 2026 18:01:12 +0100 Subject: [PATCH 1/5] ci: free runner disk space before the test build --- .github/workflows/quality.yml | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/.github/workflows/quality.yml b/.github/workflows/quality.yml index 96222b34..1800abcd 100644 --- a/.github/workflows/quality.yml +++ b/.github/workflows/quality.yml @@ -30,6 +30,28 @@ jobs: runs-on: ubuntu-24.04 steps: - uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09 # v5 + - name: Free runner disk space + # This job peaks at about 33 GiB of disk. Linux runners only promise + # 14 GB, and some now have a 72 GB disk instead of 145 GB, which leaves + # too little (actions/runner-images#15238). On those, delete + # preinstalled SDKs, browsers and Docker images the job never uses. + shell: bash + run: | + df -h / + if (( $(df -k --output=avail / | tail -1) < 50 * 1024 * 1024 )); then + sudo rm -rf \ + /usr/local/lib/android \ + /usr/share/dotnet \ + /usr/local/.ghcup \ + /usr/share/swift \ + "${RUNNER_TOOL_CACHE:?}/CodeQL" \ + /usr/local/share/powershell \ + /opt/microsoft \ + /usr/local/julia* \ + /usr/local/share/chromium + sudo docker image prune --all --force > /dev/null + df -h / + fi - name: Install native build dependencies run: | sudo apt-get update From 3261510e8c020574cc447f168debd9dcb11726b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Romero?= Date: Fri, 6 Nov 2026 18:20:41 +0100 Subject: [PATCH 2/5] fix: focus the rendering dialog on screen --- lang/flectar-mail.pot | 256 ++++++++++++------------- ui/dialogs/rendering-info-dialog.slint | 14 +- ui/views/mail-reading-pane.slint | 3 + ui/views/mail-view.slint | 2 + 4 files changed, 146 insertions(+), 129 deletions(-) diff --git a/lang/flectar-mail.pot b/lang/flectar-mail.pot index c359a95f..fee1b28c 100644 --- a/lang/flectar-mail.pot +++ b/lang/flectar-mail.pot @@ -25,17 +25,17 @@ msgstr "" msgid "Light" msgstr "" -#: ui/app-icon.slint:22 ui/views/mail-reading-pane.slint:2001 +#: ui/app-icon.slint:22 ui/views/mail-reading-pane.slint:2003 msgid "Blue" msgstr "" #: ui/app-icon.slint:23 ui/components/theme-editor.slint:623 -#: ui/app-icon.slint:23 ui/components/theme-editor.slint:623 ui/views/mail-reading-pane.slint:2006 +#: ui/app-icon.slint:23 ui/components/theme-editor.slint:623 ui/views/mail-reading-pane.slint:2008 msgid "Green" msgstr "" #: ui/app-icon.slint:24 ui/components/theme-editor.slint:624 -#: ui/app-icon.slint:24 ui/components/theme-editor.slint:624 ui/views/mail-reading-pane.slint:2002 +#: ui/app-icon.slint:24 ui/components/theme-editor.slint:624 ui/views/mail-reading-pane.slint:2004 msgid "Purple" msgstr "" @@ -1766,7 +1766,7 @@ msgid "Could not mark message as read: {}" msgstr "" #: ui/app.slint:599 ui/views/mail-reading-pane.slint:196 -#: ui/app.slint:599 ui/views/mail-reading-pane.slint:196 ui/views/mail-reading-pane.slint:1279 +#: ui/app.slint:599 ui/views/mail-reading-pane.slint:196 ui/views/mail-reading-pane.slint:1281 msgid "Loading message…" msgstr "" @@ -2676,24 +2676,24 @@ msgstr "" msgid "Keep" msgstr "" -#: ui/components/composer-fields.slint:39 ui/views/mail-reading-pane.slint:335 -#: ui/components/composer-fields.slint:39 ui/views/mail-reading-pane.slint:335 ui/views/mail-reading-pane.slint:371 -#: ui/components/composer-fields.slint:39 ui/views/mail-reading-pane.slint:335 ui/views/mail-reading-pane.slint:371 ui/views/mail-reading-pane.slint:735 -#: ui/components/composer-fields.slint:39 ui/views/mail-reading-pane.slint:335 ui/views/mail-reading-pane.slint:371 ui/views/mail-reading-pane.slint:735 +#: ui/components/composer-fields.slint:39 ui/views/mail-reading-pane.slint:337 +#: ui/components/composer-fields.slint:39 ui/views/mail-reading-pane.slint:337 ui/views/mail-reading-pane.slint:373 +#: ui/components/composer-fields.slint:39 ui/views/mail-reading-pane.slint:337 ui/views/mail-reading-pane.slint:373 ui/views/mail-reading-pane.slint:737 +#: ui/components/composer-fields.slint:39 ui/views/mail-reading-pane.slint:337 ui/views/mail-reading-pane.slint:373 ui/views/mail-reading-pane.slint:737 msgid "Reply" msgstr "" -#: ui/components/composer-fields.slint:40 ui/views/mail-reading-pane.slint:336 -#: ui/components/composer-fields.slint:40 ui/views/mail-reading-pane.slint:336 ui/views/mail-reading-pane.slint:372 -#: ui/components/composer-fields.slint:40 ui/views/mail-reading-pane.slint:336 ui/views/mail-reading-pane.slint:372 ui/views/mail-reading-pane.slint:744 -#: ui/components/composer-fields.slint:40 ui/views/mail-reading-pane.slint:336 ui/views/mail-reading-pane.slint:372 ui/views/mail-reading-pane.slint:744 +#: ui/components/composer-fields.slint:40 ui/views/mail-reading-pane.slint:338 +#: ui/components/composer-fields.slint:40 ui/views/mail-reading-pane.slint:338 ui/views/mail-reading-pane.slint:374 +#: ui/components/composer-fields.slint:40 ui/views/mail-reading-pane.slint:338 ui/views/mail-reading-pane.slint:374 ui/views/mail-reading-pane.slint:746 +#: ui/components/composer-fields.slint:40 ui/views/mail-reading-pane.slint:338 ui/views/mail-reading-pane.slint:374 ui/views/mail-reading-pane.slint:746 msgid "Reply all" msgstr "" -#: ui/components/composer-fields.slint:41 ui/views/mail-reading-pane.slint:337 -#: ui/components/composer-fields.slint:41 ui/views/mail-reading-pane.slint:337 ui/views/mail-reading-pane.slint:373 -#: ui/components/composer-fields.slint:41 ui/views/mail-reading-pane.slint:337 ui/views/mail-reading-pane.slint:373 ui/views/mail-reading-pane.slint:753 -#: ui/components/composer-fields.slint:41 ui/views/mail-reading-pane.slint:337 ui/views/mail-reading-pane.slint:373 ui/views/mail-reading-pane.slint:753 +#: ui/components/composer-fields.slint:41 ui/views/mail-reading-pane.slint:339 +#: ui/components/composer-fields.slint:41 ui/views/mail-reading-pane.slint:339 ui/views/mail-reading-pane.slint:375 +#: ui/components/composer-fields.slint:41 ui/views/mail-reading-pane.slint:339 ui/views/mail-reading-pane.slint:375 ui/views/mail-reading-pane.slint:755 +#: ui/components/composer-fields.slint:41 ui/views/mail-reading-pane.slint:339 ui/views/mail-reading-pane.slint:375 ui/views/mail-reading-pane.slint:755 msgid "Forward" msgstr "" @@ -3497,7 +3497,7 @@ msgstr "" #: ui/components/theme-editor.slint:785 #: ui/components/theme-editor.slint:785 ui/dialogs/folder-dialog.slint:135 -#: ui/components/theme-editor.slint:785 ui/dialogs/folder-dialog.slint:135 ui/views/mail-reading-pane.slint:2027 +#: ui/components/theme-editor.slint:785 ui/dialogs/folder-dialog.slint:135 ui/views/mail-reading-pane.slint:2029 msgid "Save" msgstr "" @@ -3734,7 +3734,7 @@ msgstr "" msgid "Inside “{}”" msgstr "" -#: ui/dialogs/folder-dialog.slint:133 ui/views/mail-reading-pane.slint:1976 +#: ui/dialogs/folder-dialog.slint:133 ui/views/mail-reading-pane.slint:1978 msgid "Create label" msgstr "" @@ -4374,32 +4374,32 @@ msgstr "" msgid "Save settings" msgstr "" -#: ui/dialogs/rendering-info-dialog.slint:25 -#: ui/dialogs/rendering-info-dialog.slint:25 -#: ui/dialogs/rendering-info-dialog.slint:25 ui/views/mail-reading-pane.slint:343 -#: ui/dialogs/rendering-info-dialog.slint:25 ui/views/mail-reading-pane.slint:343 ui/views/mail-reading-pane.slint:379 -#: ui/dialogs/rendering-info-dialog.slint:25 ui/views/mail-reading-pane.slint:343 ui/views/mail-reading-pane.slint:379 ui/views/mail-reading-pane.slint:1895 +#: ui/dialogs/rendering-info-dialog.slint:29 +#: ui/dialogs/rendering-info-dialog.slint:29 +#: ui/dialogs/rendering-info-dialog.slint:29 ui/views/mail-reading-pane.slint:345 +#: ui/dialogs/rendering-info-dialog.slint:29 ui/views/mail-reading-pane.slint:345 ui/views/mail-reading-pane.slint:381 +#: ui/dialogs/rendering-info-dialog.slint:29 ui/views/mail-reading-pane.slint:345 ui/views/mail-reading-pane.slint:381 ui/views/mail-reading-pane.slint:1897 msgid "About email rendering" msgstr "" -#: ui/dialogs/rendering-info-dialog.slint:124 +#: ui/dialogs/rendering-info-dialog.slint:136 msgid "" "Flectar Mail uses a completely new email renderer built in Rust. It is still " "in its early stages, so some emails may not render correctly." msgstr "" -#: ui/dialogs/rendering-info-dialog.slint:142 +#: ui/dialogs/rendering-info-dialog.slint:154 msgid "" "Want to help us fix this email? Copy its HTML source and include it in a " "GitHub issue. Remove private or sensitive information before submitting it." msgstr "" -#: ui/dialogs/rendering-info-dialog.slint:166 -#: ui/dialogs/rendering-info-dialog.slint:166 +#: ui/dialogs/rendering-info-dialog.slint:178 +#: ui/dialogs/rendering-info-dialog.slint:178 msgid "Copy source" msgstr "" -#: ui/dialogs/rendering-info-dialog.slint:176 +#: ui/dialogs/rendering-info-dialog.slint:188 msgid "Report issue" msgstr "" @@ -4447,8 +4447,8 @@ msgstr "" msgid "Open Storage to calculate local usage." msgstr "" -#: ui/dialogs/settings-dialog.slint:269 ui/views/mail-reading-pane.slint:1249 -#: ui/dialogs/settings-dialog.slint:269 ui/views/mail-reading-pane.slint:1249 +#: ui/dialogs/settings-dialog.slint:269 ui/views/mail-reading-pane.slint:1251 +#: ui/dialogs/settings-dialog.slint:269 ui/views/mail-reading-pane.slint:1251 msgid "Attachments" msgstr "" @@ -5432,21 +5432,21 @@ msgstr "" #. Local mail has no archive or spam. #: ui/dialogs/settings-dialog.slint:2457 ui/views/mail-list-pane.slint:1348 -#: ui/dialogs/settings-dialog.slint:2457 ui/views/mail-list-pane.slint:1348 ui/views/mail-reading-pane.slint:365 +#: ui/dialogs/settings-dialog.slint:2457 ui/views/mail-list-pane.slint:1348 ui/views/mail-reading-pane.slint:367 msgid "Archive" msgstr "" #: ui/dialogs/settings-dialog.slint:2458 ui/views/mail-list-pane.slint:725 -#: ui/dialogs/settings-dialog.slint:2458 ui/views/mail-list-pane.slint:725 ui/views/mail-reading-pane.slint:349 -#: ui/dialogs/settings-dialog.slint:2458 ui/views/mail-list-pane.slint:725 ui/views/mail-reading-pane.slint:349 ui/views/mail-reading-pane.slint:795 +#: ui/dialogs/settings-dialog.slint:2458 ui/views/mail-list-pane.slint:725 ui/views/mail-reading-pane.slint:351 +#: ui/dialogs/settings-dialog.slint:2458 ui/views/mail-list-pane.slint:725 ui/views/mail-reading-pane.slint:351 ui/views/mail-reading-pane.slint:797 msgid "Move to spam" msgstr "" #: ui/dialogs/settings-dialog.slint:2459 ui/views/mail-list-pane.slint:734 -#: ui/dialogs/settings-dialog.slint:2459 ui/views/mail-list-pane.slint:734 ui/views/mail-reading-pane.slint:332 -#: ui/dialogs/settings-dialog.slint:2459 ui/views/mail-list-pane.slint:734 ui/views/mail-reading-pane.slint:332 ui/views/mail-reading-pane.slint:367 -#: ui/dialogs/settings-dialog.slint:2459 ui/views/mail-list-pane.slint:734 ui/views/mail-reading-pane.slint:332 ui/views/mail-reading-pane.slint:367 ui/views/mail-reading-pane.slint:399 -#: ui/dialogs/settings-dialog.slint:2459 ui/views/mail-list-pane.slint:734 ui/views/mail-reading-pane.slint:332 ui/views/mail-reading-pane.slint:367 ui/views/mail-reading-pane.slint:399 +#: ui/dialogs/settings-dialog.slint:2459 ui/views/mail-list-pane.slint:734 ui/views/mail-reading-pane.slint:334 +#: ui/dialogs/settings-dialog.slint:2459 ui/views/mail-list-pane.slint:734 ui/views/mail-reading-pane.slint:334 ui/views/mail-reading-pane.slint:369 +#: ui/dialogs/settings-dialog.slint:2459 ui/views/mail-list-pane.slint:734 ui/views/mail-reading-pane.slint:334 ui/views/mail-reading-pane.slint:369 ui/views/mail-reading-pane.slint:401 +#: ui/dialogs/settings-dialog.slint:2459 ui/views/mail-list-pane.slint:734 ui/views/mail-reading-pane.slint:334 ui/views/mail-reading-pane.slint:369 ui/views/mail-reading-pane.slint:401 msgid "Move to trash" msgstr "" @@ -5474,8 +5474,8 @@ msgstr "" msgid "Reading" msgstr "" -#: ui/dialogs/settings-dialog.slint:2468 ui/views/mail-reading-pane.slint:1259 -#: ui/dialogs/settings-dialog.slint:2468 ui/views/mail-reading-pane.slint:1259 +#: ui/dialogs/settings-dialog.slint:2468 ui/views/mail-reading-pane.slint:1261 +#: ui/dialogs/settings-dialog.slint:2468 ui/views/mail-reading-pane.slint:1261 msgid "Find in message" msgstr "" @@ -5483,7 +5483,7 @@ msgstr "" msgid "Reset zoom" msgstr "" -#: ui/dialogs/settings-dialog.slint:2472 ui/views/mail-reading-pane.slint:1588 +#: ui/dialogs/settings-dialog.slint:2472 ui/views/mail-reading-pane.slint:1590 msgid "Caret browsing" msgstr "" @@ -5840,7 +5840,7 @@ msgstr "" msgid "Personal or Work" msgstr "" -#: ui/dialogs/settings-dialog.slint:3189 ui/views/mail-reading-pane.slint:1991 +#: ui/dialogs/settings-dialog.slint:3189 ui/views/mail-reading-pane.slint:1993 msgid "Color" msgstr "" @@ -6735,7 +6735,7 @@ msgstr "" msgid "Delete selected permanently" msgstr "" -#: ui/views/mail-list-pane.slint:747 ui/views/mail-reading-pane.slint:1016 +#: ui/views/mail-list-pane.slint:747 ui/views/mail-reading-pane.slint:1018 msgid "More message actions" msgstr "" @@ -6748,30 +6748,30 @@ msgid "Open in new tab" msgstr "" #: ui/views/mail-list-pane.slint:758 ui/views/mail-list-pane.slint:1346 -#: ui/views/mail-list-pane.slint:758 ui/views/mail-list-pane.slint:1346 ui/views/mail-reading-pane.slint:364 -#: ui/views/mail-list-pane.slint:758 ui/views/mail-list-pane.slint:1346 ui/views/mail-reading-pane.slint:364 ui/views/mail-reading-pane.slint:398 -#: ui/views/mail-list-pane.slint:758 ui/views/mail-list-pane.slint:1346 ui/views/mail-reading-pane.slint:364 ui/views/mail-reading-pane.slint:398 +#: ui/views/mail-list-pane.slint:758 ui/views/mail-list-pane.slint:1346 ui/views/mail-reading-pane.slint:366 +#: ui/views/mail-list-pane.slint:758 ui/views/mail-list-pane.slint:1346 ui/views/mail-reading-pane.slint:366 ui/views/mail-reading-pane.slint:400 +#: ui/views/mail-list-pane.slint:758 ui/views/mail-list-pane.slint:1346 ui/views/mail-reading-pane.slint:366 ui/views/mail-reading-pane.slint:400 msgid "Mark as read" msgstr "" #: ui/views/mail-list-pane.slint:759 ui/views/mail-list-pane.slint:1346 -#: ui/views/mail-list-pane.slint:759 ui/views/mail-list-pane.slint:1346 ui/views/mail-reading-pane.slint:364 -#: ui/views/mail-list-pane.slint:759 ui/views/mail-list-pane.slint:1346 ui/views/mail-reading-pane.slint:364 ui/views/mail-reading-pane.slint:398 -#: ui/views/mail-list-pane.slint:759 ui/views/mail-list-pane.slint:1346 ui/views/mail-reading-pane.slint:364 ui/views/mail-reading-pane.slint:398 +#: ui/views/mail-list-pane.slint:759 ui/views/mail-list-pane.slint:1346 ui/views/mail-reading-pane.slint:366 +#: ui/views/mail-list-pane.slint:759 ui/views/mail-list-pane.slint:1346 ui/views/mail-reading-pane.slint:366 ui/views/mail-reading-pane.slint:400 +#: ui/views/mail-list-pane.slint:759 ui/views/mail-list-pane.slint:1346 ui/views/mail-reading-pane.slint:366 ui/views/mail-reading-pane.slint:400 msgid "Mark as unread" msgstr "" #: ui/views/mail-list-pane.slint:760 ui/views/mail-list-pane.slint:1345 -#: ui/views/mail-list-pane.slint:760 ui/views/mail-list-pane.slint:1345 ui/views/mail-reading-pane.slint:356 -#: ui/views/mail-list-pane.slint:760 ui/views/mail-list-pane.slint:1345 ui/views/mail-reading-pane.slint:356 ui/views/mail-reading-pane.slint:390 -#: ui/views/mail-list-pane.slint:760 ui/views/mail-list-pane.slint:1345 ui/views/mail-reading-pane.slint:356 ui/views/mail-reading-pane.slint:390 +#: ui/views/mail-list-pane.slint:760 ui/views/mail-list-pane.slint:1345 ui/views/mail-reading-pane.slint:358 +#: ui/views/mail-list-pane.slint:760 ui/views/mail-list-pane.slint:1345 ui/views/mail-reading-pane.slint:358 ui/views/mail-reading-pane.slint:392 +#: ui/views/mail-list-pane.slint:760 ui/views/mail-list-pane.slint:1345 ui/views/mail-reading-pane.slint:358 ui/views/mail-reading-pane.slint:392 msgid "Star message" msgstr "" #: ui/views/mail-list-pane.slint:761 ui/views/mail-list-pane.slint:1345 -#: ui/views/mail-list-pane.slint:761 ui/views/mail-list-pane.slint:1345 ui/views/mail-reading-pane.slint:356 -#: ui/views/mail-list-pane.slint:761 ui/views/mail-list-pane.slint:1345 ui/views/mail-reading-pane.slint:356 ui/views/mail-reading-pane.slint:390 -#: ui/views/mail-list-pane.slint:761 ui/views/mail-list-pane.slint:1345 ui/views/mail-reading-pane.slint:356 ui/views/mail-reading-pane.slint:390 +#: ui/views/mail-list-pane.slint:761 ui/views/mail-list-pane.slint:1345 ui/views/mail-reading-pane.slint:358 +#: ui/views/mail-list-pane.slint:761 ui/views/mail-list-pane.slint:1345 ui/views/mail-reading-pane.slint:358 ui/views/mail-reading-pane.slint:392 +#: ui/views/mail-list-pane.slint:761 ui/views/mail-list-pane.slint:1345 ui/views/mail-reading-pane.slint:358 ui/views/mail-reading-pane.slint:392 msgid "Remove star" msgstr "" @@ -6808,9 +6808,9 @@ msgstr "" msgid "Deselect {}" msgstr "" -#: ui/views/mail-list-pane.slint:1350 ui/views/mail-reading-pane.slint:332 -#: ui/views/mail-list-pane.slint:1350 ui/views/mail-reading-pane.slint:332 ui/views/mail-reading-pane.slint:367 -#: ui/views/mail-list-pane.slint:1350 ui/views/mail-reading-pane.slint:332 ui/views/mail-reading-pane.slint:367 ui/views/mail-reading-pane.slint:399 +#: ui/views/mail-list-pane.slint:1350 ui/views/mail-reading-pane.slint:334 +#: ui/views/mail-list-pane.slint:1350 ui/views/mail-reading-pane.slint:334 ui/views/mail-reading-pane.slint:369 +#: ui/views/mail-list-pane.slint:1350 ui/views/mail-reading-pane.slint:334 ui/views/mail-reading-pane.slint:369 ui/views/mail-reading-pane.slint:401 msgid "Delete permanently…" msgstr "" @@ -6858,229 +6858,229 @@ msgstr "" msgid "to {}" msgstr "" -#: ui/views/mail-reading-pane.slint:327 ui/views/mail-reading-pane.slint:1879 +#: ui/views/mail-reading-pane.slint:329 ui/views/mail-reading-pane.slint:1881 msgid "Continue editing" msgstr "" -#: ui/views/mail-reading-pane.slint:329 ui/views/mail-reading-pane.slint:330 -#: ui/views/mail-reading-pane.slint:329 ui/views/mail-reading-pane.slint:330 ui/views/mail-reading-pane.slint:345 -#: ui/views/mail-reading-pane.slint:329 ui/views/mail-reading-pane.slint:330 ui/views/mail-reading-pane.slint:345 ui/views/mail-reading-pane.slint:362 -#: ui/views/mail-reading-pane.slint:329 ui/views/mail-reading-pane.slint:330 ui/views/mail-reading-pane.slint:345 ui/views/mail-reading-pane.slint:362 ui/views/mail-reading-pane.slint:381 -#: ui/views/mail-reading-pane.slint:329 ui/views/mail-reading-pane.slint:330 ui/views/mail-reading-pane.slint:345 ui/views/mail-reading-pane.slint:362 ui/views/mail-reading-pane.slint:381 ui/views/mail-reading-pane.slint:396 +#: ui/views/mail-reading-pane.slint:331 ui/views/mail-reading-pane.slint:332 +#: ui/views/mail-reading-pane.slint:331 ui/views/mail-reading-pane.slint:332 ui/views/mail-reading-pane.slint:347 +#: ui/views/mail-reading-pane.slint:331 ui/views/mail-reading-pane.slint:332 ui/views/mail-reading-pane.slint:347 ui/views/mail-reading-pane.slint:364 +#: ui/views/mail-reading-pane.slint:331 ui/views/mail-reading-pane.slint:332 ui/views/mail-reading-pane.slint:347 ui/views/mail-reading-pane.slint:364 ui/views/mail-reading-pane.slint:383 +#: ui/views/mail-reading-pane.slint:331 ui/views/mail-reading-pane.slint:332 ui/views/mail-reading-pane.slint:347 ui/views/mail-reading-pane.slint:364 ui/views/mail-reading-pane.slint:383 ui/views/mail-reading-pane.slint:398 msgid "Show rendered message" msgstr "" -#: ui/views/mail-reading-pane.slint:329 ui/views/mail-reading-pane.slint:344 -#: ui/views/mail-reading-pane.slint:329 ui/views/mail-reading-pane.slint:344 ui/views/mail-reading-pane.slint:380 -#: ui/views/mail-reading-pane.slint:329 ui/views/mail-reading-pane.slint:344 ui/views/mail-reading-pane.slint:380 +#: ui/views/mail-reading-pane.slint:331 ui/views/mail-reading-pane.slint:346 +#: ui/views/mail-reading-pane.slint:331 ui/views/mail-reading-pane.slint:346 ui/views/mail-reading-pane.slint:382 +#: ui/views/mail-reading-pane.slint:331 ui/views/mail-reading-pane.slint:346 ui/views/mail-reading-pane.slint:382 msgid "Show source" msgstr "" -#: ui/views/mail-reading-pane.slint:330 ui/views/mail-reading-pane.slint:345 -#: ui/views/mail-reading-pane.slint:330 ui/views/mail-reading-pane.slint:345 ui/views/mail-reading-pane.slint:381 -#: ui/views/mail-reading-pane.slint:330 ui/views/mail-reading-pane.slint:345 ui/views/mail-reading-pane.slint:381 +#: ui/views/mail-reading-pane.slint:332 ui/views/mail-reading-pane.slint:347 +#: ui/views/mail-reading-pane.slint:332 ui/views/mail-reading-pane.slint:347 ui/views/mail-reading-pane.slint:383 +#: ui/views/mail-reading-pane.slint:332 ui/views/mail-reading-pane.slint:347 ui/views/mail-reading-pane.slint:383 msgid "View plain text" msgstr "" -#: ui/views/mail-reading-pane.slint:331 ui/views/mail-reading-pane.slint:346 -#: ui/views/mail-reading-pane.slint:331 ui/views/mail-reading-pane.slint:346 ui/views/mail-reading-pane.slint:382 -#: ui/views/mail-reading-pane.slint:331 ui/views/mail-reading-pane.slint:346 ui/views/mail-reading-pane.slint:382 ui/views/mail-reading-pane.slint:1260 +#: ui/views/mail-reading-pane.slint:333 ui/views/mail-reading-pane.slint:348 +#: ui/views/mail-reading-pane.slint:333 ui/views/mail-reading-pane.slint:348 ui/views/mail-reading-pane.slint:384 +#: ui/views/mail-reading-pane.slint:333 ui/views/mail-reading-pane.slint:348 ui/views/mail-reading-pane.slint:384 ui/views/mail-reading-pane.slint:1262 msgid "Use message appearance" msgstr "" -#: ui/views/mail-reading-pane.slint:331 ui/views/mail-reading-pane.slint:346 -#: ui/views/mail-reading-pane.slint:331 ui/views/mail-reading-pane.slint:346 ui/views/mail-reading-pane.slint:382 -#: ui/views/mail-reading-pane.slint:331 ui/views/mail-reading-pane.slint:346 ui/views/mail-reading-pane.slint:382 ui/views/mail-reading-pane.slint:1260 -#: ui/views/mail-reading-pane.slint:331 ui/views/mail-reading-pane.slint:346 ui/views/mail-reading-pane.slint:382 ui/views/mail-reading-pane.slint:1260 +#: ui/views/mail-reading-pane.slint:333 ui/views/mail-reading-pane.slint:348 +#: ui/views/mail-reading-pane.slint:333 ui/views/mail-reading-pane.slint:348 ui/views/mail-reading-pane.slint:384 +#: ui/views/mail-reading-pane.slint:333 ui/views/mail-reading-pane.slint:348 ui/views/mail-reading-pane.slint:384 ui/views/mail-reading-pane.slint:1262 +#: ui/views/mail-reading-pane.slint:333 ui/views/mail-reading-pane.slint:348 ui/views/mail-reading-pane.slint:384 ui/views/mail-reading-pane.slint:1262 msgid "Show original colors" msgstr "" -#: ui/views/mail-reading-pane.slint:339 ui/views/mail-reading-pane.slint:357 -#: ui/views/mail-reading-pane.slint:339 ui/views/mail-reading-pane.slint:357 ui/views/mail-reading-pane.slint:391 -#: ui/views/mail-reading-pane.slint:339 ui/views/mail-reading-pane.slint:357 ui/views/mail-reading-pane.slint:391 +#: ui/views/mail-reading-pane.slint:341 ui/views/mail-reading-pane.slint:359 +#: ui/views/mail-reading-pane.slint:341 ui/views/mail-reading-pane.slint:359 ui/views/mail-reading-pane.slint:393 +#: ui/views/mail-reading-pane.slint:341 ui/views/mail-reading-pane.slint:359 ui/views/mail-reading-pane.slint:393 msgid "Manage labels" msgstr "" -#: ui/views/mail-reading-pane.slint:340 ui/views/mail-reading-pane.slint:358 -#: ui/views/mail-reading-pane.slint:340 ui/views/mail-reading-pane.slint:358 ui/views/mail-reading-pane.slint:392 +#: ui/views/mail-reading-pane.slint:342 ui/views/mail-reading-pane.slint:360 +#: ui/views/mail-reading-pane.slint:342 ui/views/mail-reading-pane.slint:360 ui/views/mail-reading-pane.slint:394 msgid "Decrypt / verify OpenPGP" msgstr "" -#: ui/views/mail-reading-pane.slint:341 ui/views/mail-reading-pane.slint:377 +#: ui/views/mail-reading-pane.slint:343 ui/views/mail-reading-pane.slint:379 msgid "Print message" msgstr "" -#: ui/views/mail-reading-pane.slint:342 ui/views/mail-reading-pane.slint:359 -#: ui/views/mail-reading-pane.slint:342 ui/views/mail-reading-pane.slint:359 ui/views/mail-reading-pane.slint:393 -#: ui/views/mail-reading-pane.slint:342 ui/views/mail-reading-pane.slint:359 ui/views/mail-reading-pane.slint:393 +#: ui/views/mail-reading-pane.slint:344 ui/views/mail-reading-pane.slint:361 +#: ui/views/mail-reading-pane.slint:344 ui/views/mail-reading-pane.slint:361 ui/views/mail-reading-pane.slint:395 +#: ui/views/mail-reading-pane.slint:344 ui/views/mail-reading-pane.slint:361 ui/views/mail-reading-pane.slint:395 msgid "Open in browser" msgstr "" -#: ui/views/mail-reading-pane.slint:704 +#: ui/views/mail-reading-pane.slint:706 msgid "Close conversation" msgstr "" -#: ui/views/mail-reading-pane.slint:714 +#: ui/views/mail-reading-pane.slint:716 msgid "Previous conversation" msgstr "" -#: ui/views/mail-reading-pane.slint:724 +#: ui/views/mail-reading-pane.slint:726 msgid "Next conversation" msgstr "" -#: ui/views/mail-reading-pane.slint:765 +#: ui/views/mail-reading-pane.slint:767 msgid "Archive message" msgstr "" -#: ui/views/mail-reading-pane.slint:868 +#: ui/views/mail-reading-pane.slint:870 msgid "Search labels" msgstr "" -#: ui/views/mail-reading-pane.slint:885 +#: ui/views/mail-reading-pane.slint:887 msgid "Available labels" msgstr "" -#: ui/views/mail-reading-pane.slint:924 +#: ui/views/mail-reading-pane.slint:926 msgid "Smart category" msgstr "" -#: ui/views/mail-reading-pane.slint:965 ui/views/mail-reading-pane.slint:1976 +#: ui/views/mail-reading-pane.slint:967 ui/views/mail-reading-pane.slint:1978 msgid "Edit label" msgstr "" -#: ui/views/mail-reading-pane.slint:982 +#: ui/views/mail-reading-pane.slint:984 msgid "No matching labels" msgstr "" -#: ui/views/mail-reading-pane.slint:994 +#: ui/views/mail-reading-pane.slint:996 msgid "Create label…" msgstr "" -#: ui/views/mail-reading-pane.slint:1261 +#: ui/views/mail-reading-pane.slint:1263 msgid "Show original layout" msgstr "" -#: ui/views/mail-reading-pane.slint:1261 +#: ui/views/mail-reading-pane.slint:1263 msgid "Reader mode" msgstr "" -#: ui/views/mail-reading-pane.slint:1268 +#: ui/views/mail-reading-pane.slint:1270 msgid "Previous match" msgstr "" -#: ui/views/mail-reading-pane.slint:1269 +#: ui/views/mail-reading-pane.slint:1271 msgid "Next match" msgstr "" -#: ui/views/mail-reading-pane.slint:1270 +#: ui/views/mail-reading-pane.slint:1272 msgid "Close find" msgstr "" -#: ui/views/mail-reading-pane.slint:1274 +#: ui/views/mail-reading-pane.slint:1276 msgid "Some images could not be loaded." msgstr "" -#: ui/views/mail-reading-pane.slint:1275 ui/views/mail-reading-pane.slint:1586 +#: ui/views/mail-reading-pane.slint:1277 ui/views/mail-reading-pane.slint:1588 msgid "Retry images" msgstr "" -#: ui/views/mail-reading-pane.slint:1280 +#: ui/views/mail-reading-pane.slint:1282 msgid "Reload message" msgstr "" -#: ui/views/mail-reading-pane.slint:1342 +#: ui/views/mail-reading-pane.slint:1344 msgid "Remote images were blocked to protect your privacy." msgstr "" -#: ui/views/mail-reading-pane.slint:1351 +#: ui/views/mail-reading-pane.slint:1353 msgid "Load images" msgstr "" -#: ui/views/mail-reading-pane.slint:1389 +#: ui/views/mail-reading-pane.slint:1391 msgid "Loading image…" msgstr "" -#: ui/views/mail-reading-pane.slint:1389 +#: ui/views/mail-reading-pane.slint:1391 msgid "Blocked image" msgstr "" -#: ui/views/mail-reading-pane.slint:1389 +#: ui/views/mail-reading-pane.slint:1391 msgid "Image exceeds limits" msgstr "" -#: ui/views/mail-reading-pane.slint:1389 +#: ui/views/mail-reading-pane.slint:1391 msgid "Image unavailable" msgstr "" -#: ui/views/mail-reading-pane.slint:1535 +#: ui/views/mail-reading-pane.slint:1537 msgid "Show rendered email" msgstr "" -#: ui/views/mail-reading-pane.slint:1558 +#: ui/views/mail-reading-pane.slint:1560 msgid "Copy this HTML into your GitHub rendering issue." msgstr "" -#: ui/views/mail-reading-pane.slint:1575 +#: ui/views/mail-reading-pane.slint:1577 msgid "Show email" msgstr "" -#: ui/views/mail-reading-pane.slint:1585 +#: ui/views/mail-reading-pane.slint:1587 msgid "View original plain text" msgstr "" -#: ui/views/mail-reading-pane.slint:1587 +#: ui/views/mail-reading-pane.slint:1589 msgid "Copy formatted selection" msgstr "" -#: ui/views/mail-reading-pane.slint:1591 +#: ui/views/mail-reading-pane.slint:1593 msgid "Copy selected text" msgstr "" -#: ui/views/mail-reading-pane.slint:1601 +#: ui/views/mail-reading-pane.slint:1603 msgid "Copy all email text" msgstr "" -#: ui/views/mail-reading-pane.slint:1611 +#: ui/views/mail-reading-pane.slint:1613 msgid "Select all email text" msgstr "" -#: ui/views/mail-reading-pane.slint:1629 +#: ui/views/mail-reading-pane.slint:1631 msgid "Link: {}" msgstr "" -#: ui/views/mail-reading-pane.slint:1818 +#: ui/views/mail-reading-pane.slint:1820 msgid "Heading: {}" msgstr "" -#: ui/views/mail-reading-pane.slint:1940 +#: ui/views/mail-reading-pane.slint:1942 msgid "No message selected" msgstr "" -#: ui/views/mail-reading-pane.slint:1941 +#: ui/views/mail-reading-pane.slint:1943 msgid "Choose an email to read it here." msgstr "" -#: ui/views/mail-reading-pane.slint:1983 +#: ui/views/mail-reading-pane.slint:1985 msgid "Label name" msgstr "" -#: ui/views/mail-reading-pane.slint:2003 +#: ui/views/mail-reading-pane.slint:2005 msgid "Pink" msgstr "" -#: ui/views/mail-reading-pane.slint:2004 +#: ui/views/mail-reading-pane.slint:2006 msgid "Red" msgstr "" -#: ui/views/mail-reading-pane.slint:2005 +#: ui/views/mail-reading-pane.slint:2007 msgid "Amber" msgstr "" -#: ui/views/mail-reading-pane.slint:2008 +#: ui/views/mail-reading-pane.slint:2010 msgid "Slate" msgstr "" -#: ui/views/mail-reading-pane.slint:2013 +#: ui/views/mail-reading-pane.slint:2015 msgid "Use across all accounts (local only)" msgstr "" @@ -7088,7 +7088,7 @@ msgstr "" msgid "Message list width" msgstr "" -#: ui/views/mail-view.slint:746 +#: ui/views/mail-view.slint:748 msgid "Close folders" msgstr "" diff --git a/ui/dialogs/rendering-info-dialog.slint b/ui/dialogs/rendering-info-dialog.slint index 11497d29..91c8e837 100644 --- a/ui/dialogs/rendering-info-dialog.slint +++ b/ui/dialogs/rendering-info-dialog.slint @@ -7,6 +7,10 @@ import { TypeScale } from "../typography.slint"; export component RenderingInfoDialog inherits Rectangle { in-out property open: false; in property compact: false; + // Mail view keeps a reading pane, and so this dialog, for each layout. + // Only the one on screen takes focus, since the window drops keys aimed + // at a hidden element. + in property shown: true; in property accent; in property accent-soft; in property border; @@ -38,10 +42,18 @@ export component RenderingInfoDialog inherits Rectangle { } } + function take-focus() { + if root.open && root.shown { + dialog-focus.focus(); + } + } + + changed shown => { root.take-focus(); } + changed open => { if root.open { root.selected-action = 2; - dialog-focus.focus(); + root.take-focus(); } } diff --git a/ui/views/mail-reading-pane.slint b/ui/views/mail-reading-pane.slint index a4994eff..2feba6a0 100644 --- a/ui/views/mail-reading-pane.slint +++ b/ui/views/mail-reading-pane.slint @@ -284,6 +284,8 @@ export component MailReadingPane inherits FocusScope { enabled: false; in property compact: false; in property full-width: false; + // Whether this pane is on screen. Mail view keeps one pane per layout. + in property shown: true; private property attachment-menu-mode: root.height < 500px; in property show-avatars: true; // The title wrap width comes from the containing window, not this pane's @@ -2044,6 +2046,7 @@ export component MailReadingPane inherits FocusScope { RenderingInfoDialog { open <=> root.rendering_info_open; + shown: root.shown; compact: root.compact; x: 0px; y: 0px; diff --git a/ui/views/mail-view.slint b/ui/views/mail-view.slint index 5b56cb3f..9bbaab92 100644 --- a/ui/views/mail-view.slint +++ b/ui/views/mail-view.slint @@ -409,6 +409,7 @@ export component MailView inherits FocusScope { } desktop-reading-pane := MailReadingPane { + shown: !root.single-pane; show-avatars: root.show-avatars; // This is the flexible column. Explicit constraints prevent // the subject's wrapping width from becoming a hard maximum, @@ -641,6 +642,7 @@ export component MailView inherits FocusScope { full-width: true; show-avatars: root.show-avatars; visible: root.compact-page == "message"; + shown: root.single-pane && self.visible; x: root.single-pane-content-x + (root.compact-page == "message" ? 0px : root.page-transition-distance); y: 0px; From 23044f304d9d001e9b56e58e5b1aa7e2a70ce2a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Romero?= Date: Fri, 6 Nov 2026 18:20:45 +0100 Subject: [PATCH 3/5] feat: prefill email rendering reports --- .github/ISSUE_TEMPLATE/email-rendering.yml | 42 ++ lang/flectar-mail.pot | 736 +++++++++++---------- src/main.rs | 16 + src/renderer_input_controller.rs | 2 +- src/rendering_report.rs | 576 ++++++++++++++++ ui/app.slint | 5 + ui/views/mail-reading-pane.slint | 5 +- ui/views/mail-view.slint | 3 + 8 files changed, 1019 insertions(+), 366 deletions(-) create mode 100644 .github/ISSUE_TEMPLATE/email-rendering.yml create mode 100644 src/rendering_report.rs diff --git a/.github/ISSUE_TEMPLATE/email-rendering.yml b/.github/ISSUE_TEMPLATE/email-rendering.yml new file mode 100644 index 00000000..b614e035 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/email-rendering.yml @@ -0,0 +1,42 @@ +name: Email rendering issue +description: An email looks wrong or part of it doesn't work in Flectar Mail. +body: + - type: textarea + id: problem + attributes: + label: What looks wrong? + description: >- + Describe what's missing, broken or not working. A screenshot helps, and + one of the same email in another mail app helps even more. + validations: + required: true + - type: textarea + id: html + attributes: + label: Email HTML + description: >- + Report issue in Flectar Mail copies the email's HTML for you, or saves + it as a file when it's too long for GitHub. Paste it inside the code + block or attach the file. Replace names, email addresses and personal + links with placeholders first. + value: | +
Email HTML + + ```html + + ``` + +
+ - type: textarea + id: environment + attributes: + label: Version and system + description: >- + Report issue in Flectar Mail fills this in. Otherwise, add the version + shown in Settings and your system. + placeholder: | + Flectar Mail 0.1.0-alpha.7 (AppImage) + Linux x86_64 (Arch Linux) + GPU renderer, 100% zoom, light message colors + validations: + required: true diff --git a/lang/flectar-mail.pot b/lang/flectar-mail.pot index fee1b28c..1705678b 100644 --- a/lang/flectar-mail.pot +++ b/lang/flectar-mail.pot @@ -25,17 +25,17 @@ msgstr "" msgid "Light" msgstr "" -#: ui/app-icon.slint:22 ui/views/mail-reading-pane.slint:2003 +#: ui/app-icon.slint:22 ui/views/mail-reading-pane.slint:2004 msgid "Blue" msgstr "" #: ui/app-icon.slint:23 ui/components/theme-editor.slint:623 -#: ui/app-icon.slint:23 ui/components/theme-editor.slint:623 ui/views/mail-reading-pane.slint:2008 +#: ui/app-icon.slint:23 ui/components/theme-editor.slint:623 ui/views/mail-reading-pane.slint:2009 msgid "Green" msgstr "" #: ui/app-icon.slint:24 ui/components/theme-editor.slint:624 -#: ui/app-icon.slint:24 ui/components/theme-editor.slint:624 ui/views/mail-reading-pane.slint:2004 +#: ui/app-icon.slint:24 ui/components/theme-editor.slint:624 ui/views/mail-reading-pane.slint:2005 msgid "Purple" msgstr "" @@ -384,8 +384,8 @@ msgstr "" msgid "New address-book entry" msgstr "" -#: ui/app.slint:180 ui/app.slint:1048 ui/components/composer-fields.slint:66 -#: ui/app.slint:180 ui/app.slint:1048 ui/components/composer-fields.slint:66 ui/dialogs/compose-dialog.slint:37 +#: ui/app.slint:180 ui/app.slint:1052 ui/components/composer-fields.slint:66 +#: ui/app.slint:180 ui/app.slint:1052 ui/components/composer-fields.slint:66 ui/dialogs/compose-dialog.slint:37 msgid "No connected account" msgstr "" @@ -399,11 +399,11 @@ msgstr[1] "" msgid "Last contacted {}" msgstr "" -#: ui/app.slint:185 ui/app.slint:456 +#: ui/app.slint:185 ui/app.slint:459 msgid "Loading local data…" msgstr "" -#: ui/app.slint:186 ui/app.slint:457 +#: ui/app.slint:186 ui/app.slint:460 msgid "Local data ready." msgstr "" @@ -758,1087 +758,1099 @@ msgid "Copied HTML source" msgstr "" #: ui/app.slint:311 -msgid "Copied selected text" +msgid "Copied HTML source. Paste it into the issue." msgstr "" #: ui/app.slint:312 -msgid "Copied email text" +msgid "Saved HTML source. Attach the file to the issue." msgstr "" #: ui/app.slint:313 -msgid "Copied link" +msgid "Could not save HTML source: {}" msgstr "" #: ui/app.slint:314 -msgid "Blitz software selection render failed: {}" +msgid "Copied selected text" msgstr "" #: ui/app.slint:315 -msgid "Blitz software tile render failed: {}" +msgid "Copied email text" msgstr "" #: ui/app.slint:316 -msgid "Message ready." +msgid "Copied link" msgstr "" #: ui/app.slint:317 -msgid "System tray behavior is unavailable in this package." +msgid "Blitz software selection render failed: {}" msgstr "" #: ui/app.slint:318 -msgid "Close-to-tray is active for this session." +msgid "Blitz software tile render failed: {}" msgstr "" #: ui/app.slint:319 -msgid "Saving close behavior…" +msgid "Message ready." msgstr "" #: ui/app.slint:320 -msgid "Closing the window will now keep Flectar Mail in the tray." +msgid "System tray behavior is unavailable in this package." msgstr "" #: ui/app.slint:321 -msgid "Closing the window will now quit Flectar Mail." +msgid "Close-to-tray is active for this session." msgstr "" #: ui/app.slint:322 -msgid "Could not save close behavior: {}" +msgid "Saving close behavior…" msgstr "" #: ui/app.slint:323 -msgid "Flectar Mail will start when you sign in." +msgid "Closing the window will now keep Flectar Mail in the tray." msgstr "" #: ui/app.slint:324 -msgid "Flectar Mail is now your default email app." +msgid "Closing the window will now quit Flectar Mail." msgstr "" #: ui/app.slint:325 -msgid "Choose Flectar Mail for MAILTO in Windows Settings to finish." +msgid "Could not save close behavior: {}" msgstr "" #: ui/app.slint:326 -msgid "Windows no longer offers this copy for email links." +msgid "Flectar Mail will start when you sign in." msgstr "" #: ui/app.slint:327 -msgid "Could not change the default email app: {}" +msgid "Flectar Mail is now your default email app." msgstr "" #: ui/app.slint:328 -msgid "Flectar Mail will no longer start when you sign in." +msgid "Choose Flectar Mail for MAILTO in Windows Settings to finish." msgstr "" #: ui/app.slint:329 -msgid "Could not change startup behavior: {}" +msgid "Windows no longer offers this copy for email links." msgstr "" #: ui/app.slint:330 -msgid "Allow Flectar Mail under Login Items in System Settings to finish." +msgid "Could not change the default email app: {}" msgstr "" #: ui/app.slint:331 +msgid "Flectar Mail will no longer start when you sign in." +msgstr "" + +#: ui/app.slint:332 +msgid "Could not change startup behavior: {}" +msgstr "" + +#: ui/app.slint:333 +msgid "Allow Flectar Mail under Login Items in System Settings to finish." +msgstr "" + +#: ui/app.slint:334 msgid "Turn on Flectar Mail under Startup apps in Windows Settings to finish." msgstr "" -#: ui/app.slint:336 +#: ui/app.slint:339 msgid "Database snapshot exported to {}." msgstr "" -#: ui/app.slint:337 +#: ui/app.slint:340 msgid "Choose where to export the mail" msgstr "" -#: ui/app.slint:338 +#: ui/app.slint:341 msgid "Exporting mail…" msgstr "" -#: ui/app.slint:339 +#: ui/app.slint:342 msgid "Mail exported to {}." msgstr "" -#: ui/app.slint:340 +#: ui/app.slint:343 msgid "" "Mail exported to {}. Some messages could not be found on this device or the " "mail server." msgstr "" -#: ui/app.slint:341 +#: ui/app.slint:344 msgid "Could not export mail: {}" msgstr "" -#: ui/app.slint:342 +#: ui/app.slint:345 msgid "Could not export database snapshot: {}" msgstr "" -#: ui/app.slint:343 +#: ui/app.slint:346 msgid "Account order saved." msgstr "" -#: ui/app.slint:344 +#: ui/app.slint:347 msgid "Could not save account order: {}" msgstr "" -#: ui/app.slint:345 +#: ui/app.slint:348 msgid "Mail history updated. Background sync is adjusting now." msgstr "" -#: ui/app.slint:346 +#: ui/app.slint:349 msgid "Account removed from this device." msgstr "" -#: ui/app.slint:347 +#: ui/app.slint:350 msgid "Account removed. Mail refresh will retry." msgstr "" -#: ui/app.slint:348 +#: ui/app.slint:351 msgid "Account removed; local cleanup needs a retry: {}" msgstr "" -#: ui/app.slint:349 +#: ui/app.slint:352 msgid "Could not remove account: {}" msgstr "" -#: ui/app.slint:350 +#: ui/app.slint:353 msgid "Removing account…" msgstr "" -#: ui/app.slint:351 +#: ui/app.slint:354 msgid "Deleting mail on this device…" msgstr "" -#: ui/app.slint:352 +#: ui/app.slint:355 msgid "Mail on this device deleted." msgstr "" -#: ui/app.slint:353 +#: ui/app.slint:356 msgid "Mail on this device deleted. Mail refresh will retry." msgstr "" -#: ui/app.slint:354 +#: ui/app.slint:357 msgid "Mail on this device deleted; local cleanup needs a retry: {}" msgstr "" -#: ui/app.slint:355 +#: ui/app.slint:358 msgid "Could not delete mail on this device: {}" msgstr "" -#: ui/app.slint:356 +#: ui/app.slint:359 msgid "Synchronizing account…" msgstr "" -#: ui/app.slint:357 +#: ui/app.slint:360 msgid "Could not update mail history: {}" msgstr "" -#: ui/app.slint:358 +#: ui/app.slint:361 msgid "Connected {}. Initial sync is running in the background." msgstr "" -#: ui/app.slint:359 +#: ui/app.slint:362 msgid "Account setup failed: {}" msgstr "" -#: ui/app.slint:360 +#: ui/app.slint:363 msgid "OAuth failed: {}" msgstr "" -#: ui/app.slint:361 +#: ui/app.slint:364 msgid "Reconnected {}. Synchronization is resuming." msgstr "" -#: ui/app.slint:362 +#: ui/app.slint:365 msgid "Reconnection failed: {}" msgstr "" -#: ui/app.slint:363 +#: ui/app.slint:366 msgid "Calendar connected and initial sync started." msgstr "" -#: ui/app.slint:364 ui/components/account-calendars.slint:270 +#: ui/app.slint:367 ui/components/account-calendars.slint:270 msgid "Could not connect calendar: {}" msgstr "" -#: ui/app.slint:365 +#: ui/app.slint:368 msgid "Calendar sync enabled." msgstr "" -#: ui/app.slint:366 +#: ui/app.slint:369 msgid "Calendar sync paused." msgstr "" -#: ui/app.slint:367 +#: ui/app.slint:370 msgid "Could not update calendar sync: {}" msgstr "" -#: ui/app.slint:368 +#: ui/app.slint:371 msgid "CalDAV connected and initial sync started." msgstr "" -#: ui/app.slint:369 +#: ui/app.slint:372 msgid "Could not connect CalDAV: {}" msgstr "" -#: ui/app.slint:370 +#: ui/app.slint:373 msgid "Calendar removed." msgstr "" -#: ui/app.slint:371 +#: ui/app.slint:374 msgid "Could not remove calendar: {}" msgstr "" -#: ui/app.slint:372 +#: ui/app.slint:375 msgid "CardDAV connected and initial sync started." msgstr "" -#: ui/app.slint:373 +#: ui/app.slint:376 msgid "Could not connect CardDAV: {}" msgstr "" -#: ui/app.slint:374 +#: ui/app.slint:377 msgid "CardDAV sync enabled." msgstr "" -#: ui/app.slint:375 +#: ui/app.slint:378 msgid "CardDAV sync paused." msgstr "" -#: ui/app.slint:376 +#: ui/app.slint:379 msgid "Could not update CardDAV sync: {}" msgstr "" -#: ui/app.slint:377 +#: ui/app.slint:380 msgid "CardDAV disconnected." msgstr "" -#: ui/app.slint:378 +#: ui/app.slint:381 msgid "Could not disconnect CardDAV: {}" msgstr "" -#: ui/app.slint:383 +#: ui/app.slint:386 msgid "Connect an account before creating a backup." msgstr "" -#: ui/app.slint:384 +#: ui/app.slint:387 msgid "Export Flectar Mail account backup" msgstr "" -#: ui/app.slint:385 +#: ui/app.slint:388 msgid "Flectar Mail backup" msgstr "" -#: ui/app.slint:386 ui/dialogs/import-dialog.slint:407 -#: ui/app.slint:386 ui/dialogs/import-dialog.slint:407 ui/views/onboarding-view.slint:223 +#: ui/app.slint:389 ui/dialogs/import-dialog.slint:407 +#: ui/app.slint:389 ui/dialogs/import-dialog.slint:407 ui/views/onboarding-view.slint:223 msgid "Import accounts and mail" msgstr "" -#: ui/app.slint:387 +#: ui/app.slint:390 msgid "Choose a Thunderbird profile or a folder of mail" msgstr "" -#: ui/app.slint:388 +#: ui/app.slint:391 msgid "Imported messages" msgstr "" -#: ui/app.slint:389 +#: ui/app.slint:392 msgid "Choose where to export the database snapshot" msgstr "" -#: ui/app.slint:390 +#: ui/app.slint:393 msgid "Backup exported. Passwords and OAuth tokens were not included." msgstr "" -#: ui/app.slint:391 +#: ui/app.slint:394 msgid "Could not export backup: {}" msgstr "" -#: ui/app.slint:392 +#: ui/app.slint:395 msgid "Local data storage is unavailable. Retry startup." msgstr "" -#: ui/app.slint:393 +#: ui/app.slint:396 msgid "Creating verified database snapshot…" msgstr "" -#: ui/app.slint:394 +#: ui/app.slint:397 msgid "All local Flectar Mail data was deleted." msgstr "" -#: ui/app.slint:395 +#: ui/app.slint:398 msgid "Could not delete all local data: {}" msgstr "" -#: ui/app.slint:396 +#: ui/app.slint:399 msgid "Deleting local accounts and cached data…" msgstr "" -#: ui/app.slint:401 +#: ui/app.slint:404 msgid "Background mail refresh failed: {}" msgstr "" -#: ui/app.slint:402 +#: ui/app.slint:405 msgid "No conversations in this folder" msgstr "" -#: ui/app.slint:403 +#: ui/app.slint:406 msgid "No conversations match this search" msgstr "" -#: ui/app.slint:404 +#: ui/app.slint:407 msgid "Mail core is ready for account synchronization and message actions." msgstr "" -#: ui/app.slint:405 +#: ui/app.slint:408 msgid "Large message rendered in compatibility mode." msgstr "" -#: ui/app.slint:406 +#: ui/app.slint:409 msgid "Software email render failed: {}" msgstr "" -#: ui/app.slint:407 +#: ui/app.slint:410 msgid "Rendered with software fallback after GPU error: {}" msgstr "" -#: ui/app.slint:408 +#: ui/app.slint:411 msgid "Blitz render failed (GPU: {}; software: {})" msgstr "" -#: ui/app.slint:413 +#: ui/app.slint:416 msgid "Enter a name, email address, or phone number, then save." msgstr "" -#: ui/app.slint:414 +#: ui/app.slint:417 msgid "Could not save: contact storage is unavailable." msgstr "" -#: ui/app.slint:415 +#: ui/app.slint:418 msgid "Could not save contact: {}" msgstr "" -#: ui/app.slint:416 +#: ui/app.slint:419 msgid "Contact saved." msgstr "" -#: ui/app.slint:417 +#: ui/app.slint:420 msgid "Saved to contacts." msgstr "" -#: ui/app.slint:418 +#: ui/app.slint:421 msgid "Could not delete: contact storage is unavailable." msgstr "" -#: ui/app.slint:419 +#: ui/app.slint:422 msgid "Could not delete contact: {}" msgstr "" -#: ui/app.slint:420 +#: ui/app.slint:423 msgid "Contact deleted." msgstr "" -#: ui/app.slint:421 +#: ui/app.slint:424 msgid "Could not load contacts: {}" msgstr "" -#: ui/app.slint:422 +#: ui/app.slint:425 msgid "Local contact storage is still starting…" msgstr "" -#: ui/app.slint:423 +#: ui/app.slint:426 msgid "Loading contacts…" msgstr "" -#: ui/app.slint:428 ui/components/calendar-agenda.slint:235 -#: ui/app.slint:428 ui/components/calendar-agenda.slint:235 +#: ui/app.slint:431 ui/components/calendar-agenda.slint:235 +#: ui/app.slint:431 ui/components/calendar-agenda.slint:235 msgid "Local calendar" msgstr "" -#: ui/app.slint:429 ui/components/calendar.slint:273 -#: ui/app.slint:429 ui/components/calendar.slint:273 ui/components/calendar.slint:321 -#: ui/app.slint:429 ui/components/calendar.slint:273 ui/components/calendar.slint:321 ui/components/calendar.slint:439 -#: ui/app.slint:429 ui/components/calendar.slint:273 ui/components/calendar.slint:321 ui/components/calendar.slint:439 -#: ui/app.slint:429 ui/components/calendar.slint:273 ui/components/calendar.slint:321 ui/components/calendar.slint:439 -#: ui/app.slint:429 ui/components/calendar.slint:273 ui/components/calendar.slint:321 ui/components/calendar.slint:439 -#: ui/app.slint:429 ui/components/calendar.slint:273 ui/components/calendar.slint:321 ui/components/calendar.slint:439 +#: ui/app.slint:432 ui/components/calendar.slint:273 +#: ui/app.slint:432 ui/components/calendar.slint:273 ui/components/calendar.slint:321 +#: ui/app.slint:432 ui/components/calendar.slint:273 ui/components/calendar.slint:321 ui/components/calendar.slint:439 +#: ui/app.slint:432 ui/components/calendar.slint:273 ui/components/calendar.slint:321 ui/components/calendar.slint:439 +#: ui/app.slint:432 ui/components/calendar.slint:273 ui/components/calendar.slint:321 ui/components/calendar.slint:439 +#: ui/app.slint:432 ui/components/calendar.slint:273 ui/components/calendar.slint:321 ui/components/calendar.slint:439 +#: ui/app.slint:432 ui/components/calendar.slint:273 ui/components/calendar.slint:321 ui/components/calendar.slint:439 msgid "Calendar" msgstr "" -#: ui/app.slint:430 +#: ui/app.slint:433 msgid "Could not load calendar: {}" msgstr "" -#: ui/app.slint:431 +#: ui/app.slint:434 msgid "Calendar shown and syncing." msgstr "" -#: ui/app.slint:432 +#: ui/app.slint:435 msgid "Calendar hidden and sync paused." msgstr "" -#: ui/app.slint:433 +#: ui/app.slint:436 msgid "Calendar update failed: {}" msgstr "" -#: ui/app.slint:434 +#: ui/app.slint:437 msgid "Only events created in Flectar Mail can be edited." msgstr "" -#: ui/app.slint:435 +#: ui/app.slint:438 msgid "Only events created in Flectar Mail can be deleted." msgstr "" -#: ui/app.slint:436 +#: ui/app.slint:439 msgid "Calendar storage is unavailable." msgstr "" -#: ui/app.slint:437 +#: ui/app.slint:440 msgid "Could not delete event: {}" msgstr "" -#: ui/app.slint:438 +#: ui/app.slint:441 msgid "Event deleted, but refresh failed: {}" msgstr "" -#: ui/app.slint:439 +#: ui/app.slint:442 msgid "Event deleted." msgstr "" -#: ui/app.slint:440 +#: ui/app.slint:443 msgid "Use YYYY-MM-DD for the date and a time such as {}." msgstr "" -#: ui/app.slint:441 +#: ui/app.slint:444 msgid "Event duration must be a number of minutes." msgstr "" -#: ui/app.slint:442 +#: ui/app.slint:445 msgid "Add a title and choose a duration from 15 to 1440 minutes." msgstr "" -#: ui/app.slint:443 +#: ui/app.slint:446 msgid "That local time does not exist in the current time zone." msgstr "" -#: ui/app.slint:444 +#: ui/app.slint:447 msgid "Could not save event: {}" msgstr "" -#: ui/app.slint:445 +#: ui/app.slint:448 msgid "Event saved, but refresh failed: {}" msgstr "" -#: ui/app.slint:446 +#: ui/app.slint:449 msgid "Event saved. Provider sync will run when enabled." msgstr "" -#: ui/app.slint:451 +#: ui/app.slint:454 msgid "Email resource render failed: {}" msgstr "" -#: ui/app.slint:452 +#: ui/app.slint:455 msgid "Message refresh failed: {}" msgstr "" -#: ui/app.slint:453 +#: ui/app.slint:456 msgid "Message load failed: {}" msgstr "" -#: ui/app.slint:454 +#: ui/app.slint:457 msgid "" "Your local mailbox could not be opened. No account operation was started. " "Retry, or copy the diagnostics for support." msgstr "" -#: ui/app.slint:455 +#: ui/app.slint:458 msgid "Local storage startup failed." msgstr "" -#: ui/app.slint:462 +#: ui/app.slint:465 msgid "Could not identify the dragged account." msgstr "" -#: ui/app.slint:463 +#: ui/app.slint:466 msgid "Account ordering requires local mail data." msgstr "" -#: ui/app.slint:464 +#: ui/app.slint:467 msgid "Could not find the account to reorder." msgstr "" -#: ui/app.slint:465 +#: ui/app.slint:468 msgid "Saving account order…" msgstr "" -#: ui/app.slint:466 +#: ui/app.slint:469 msgid "Sent copy settings require local mail data." msgstr "" -#: ui/app.slint:467 +#: ui/app.slint:470 msgid "Updating Sent copy settings…" msgstr "" -#: ui/app.slint:468 +#: ui/app.slint:471 msgid "Sent copy settings updated." msgstr "" -#: ui/app.slint:469 +#: ui/app.slint:472 msgid "Could not update Sent copy settings: {}" msgstr "" -#: ui/app.slint:470 +#: ui/app.slint:473 msgid "Server mail settings require local mail data." msgstr "" -#: ui/app.slint:471 +#: ui/app.slint:474 msgid "Updating server mail settings…" msgstr "" -#: ui/app.slint:472 +#: ui/app.slint:475 msgid "Server mail settings updated." msgstr "" -#: ui/app.slint:473 +#: ui/app.slint:476 msgid "Could not update server mail settings: {}" msgstr "" -#: ui/app.slint:474 +#: ui/app.slint:477 msgid "Mail history requires local mail data." msgstr "" -#: ui/app.slint:475 +#: ui/app.slint:478 msgid "Updating mail history…" msgstr "" -#: ui/app.slint:476 +#: ui/app.slint:479 msgid "Remote images are unavailable in this minimal build." msgstr "" -#: ui/app.slint:477 +#: ui/app.slint:480 msgid "Could not save remote-image setting: {}" msgstr "" -#: ui/app.slint:478 +#: ui/app.slint:481 msgid "Remote sender icons unavailable: {}" msgstr "" -#: ui/app.slint:479 +#: ui/app.slint:482 msgid "Remote images unavailable: {}" msgstr "" -#: ui/app.slint:480 +#: ui/app.slint:483 msgid "Remote body images and sender favicons enabled." msgstr "" -#: ui/app.slint:481 +#: ui/app.slint:484 msgid "Remote images blocked." msgstr "" -#: ui/app.slint:482 +#: ui/app.slint:485 msgid "Could not refresh message images: {}" msgstr "" -#: ui/app.slint:483 +#: ui/app.slint:486 msgid "Remote-image loading is disabled." msgstr "" -#: ui/app.slint:484 +#: ui/app.slint:487 msgid "Could not load message images: {}" msgstr "" -#: ui/app.slint:485 +#: ui/app.slint:488 msgid "Sync finished, refresh failed: {}" msgstr "" -#: ui/app.slint:486 +#: ui/app.slint:489 msgid "Sync complete." msgstr "" -#: ui/app.slint:487 +#: ui/app.slint:490 msgid "Sync failed: {}" msgstr "" -#: ui/app.slint:488 +#: ui/app.slint:491 msgid "Local mail data is unavailable; preview data is read-only." msgstr "" -#: ui/app.slint:489 +#: ui/app.slint:492 msgid "Synchronizing accounts…" msgstr "" -#: ui/app.slint:494 +#: ui/app.slint:497 msgid "Message action completed." msgstr "" -#: ui/app.slint:495 +#: ui/app.slint:498 msgid "" "Permanent deletion queued. Mail will disappear after the server confirms." msgstr "" -#: ui/app.slint:496 +#: ui/app.slint:499 msgid "Message action failed: {}" msgstr "" -#: ui/app.slint:497 +#: ui/app.slint:500 msgid "Message action failed: message is no longer available" msgstr "" -#: ui/app.slint:498 +#: ui/app.slint:501 msgid "Label added." msgstr "" -#: ui/app.slint:499 +#: ui/app.slint:502 msgid "Label removed." msgstr "" -#: ui/app.slint:500 +#: ui/app.slint:503 msgid "Label created and added." msgstr "" -#: ui/app.slint:501 +#: ui/app.slint:504 msgid "Label created." msgstr "" -#: ui/app.slint:502 +#: ui/app.slint:505 msgid "Label updated." msgstr "" -#: ui/app.slint:503 +#: ui/app.slint:506 msgid "Label deleted." msgstr "" -#: ui/app.slint:504 +#: ui/app.slint:507 msgid "Could not update label: {}" msgstr "" -#: ui/app.slint:505 +#: ui/app.slint:508 msgid "Could not save label: {}" msgstr "" -#: ui/app.slint:506 +#: ui/app.slint:509 msgid "Could not delete label: {}" msgstr "" -#: ui/app.slint:507 +#: ui/app.slint:510 msgid "Folder created." msgstr "" -#: ui/app.slint:508 +#: ui/app.slint:511 msgid "Folder renamed." msgstr "" -#: ui/app.slint:509 +#: ui/app.slint:512 msgid "Folder deleted." msgstr "" -#: ui/app.slint:510 +#: ui/app.slint:513 msgid "Could not create folder: {}" msgstr "" -#: ui/app.slint:511 +#: ui/app.slint:514 msgid "Could not rename folder: {}" msgstr "" -#: ui/app.slint:512 +#: ui/app.slint:515 msgid "Could not delete folder: {}" msgstr "" -#: ui/app.slint:513 +#: ui/app.slint:516 msgid "Could not close preview: {}" msgstr "" -#: ui/app.slint:514 +#: ui/app.slint:517 msgid "Opened the system print view." msgstr "" -#: ui/app.slint:515 +#: ui/app.slint:518 msgid "Could not print message: {}" msgstr "" -#: ui/app.slint:516 +#: ui/app.slint:519 msgid "Opened the message in your browser." msgstr "" -#: ui/app.slint:517 +#: ui/app.slint:520 msgid "Could not open message in browser: {}" msgstr "" -#: ui/app.slint:518 +#: ui/app.slint:521 msgid "Connect an account before replying or forwarding." msgstr "" -#: ui/app.slint:519 +#: ui/app.slint:522 msgid "Choose a message first." msgstr "" -#: ui/app.slint:520 +#: ui/app.slint:523 msgid "Only drafts can be reopened for editing." msgstr "" -#: ui/app.slint:521 +#: ui/app.slint:524 msgid "Could not open draft: {}" msgstr "" -#: ui/app.slint:522 +#: ui/app.slint:525 msgid "Could not open draft: invalid account identifier" msgstr "" -#: ui/app.slint:523 +#: ui/app.slint:526 msgid "Connected account" msgstr "" -#: ui/app.slint:524 +#: ui/app.slint:527 msgid "Could not open composer: {}" msgstr "" -#: ui/app.slint:525 +#: ui/app.slint:528 msgid "Add an account to send mail." msgstr "" -#: ui/app.slint:526 ui/components/sidebar.slint:514 -#: ui/app.slint:526 ui/components/sidebar.slint:514 +#: ui/app.slint:529 ui/components/sidebar.slint:514 +#: ui/app.slint:529 ui/components/sidebar.slint:514 msgid "On this device" msgstr "" -#: ui/app.slint:527 +#: ui/app.slint:530 msgid "Could not open composer: invalid account identifier" msgstr "" #. Reply and forward quotation headers, written into the draft. -#: ui/app.slint:533 +#: ui/app.slint:536 msgid "On {}, {} wrote:" msgstr "" -#: ui/app.slint:534 +#: ui/app.slint:537 msgid "{} wrote:" msgstr "" -#: ui/app.slint:535 -msgid "Forwarded message" -msgstr "" - -#: ui/app.slint:536 -msgctxt "forwarded message header" -msgid "From: {}" -msgstr "" - -#: ui/app.slint:537 -msgctxt "forwarded message header" -msgid "Date: {}" -msgstr "" - #: ui/app.slint:538 -msgctxt "forwarded message header" -msgid "Subject: {}" +msgid "Forwarded message" msgstr "" #: ui/app.slint:539 msgctxt "forwarded message header" -msgid "To: {}" +msgid "From: {}" msgstr "" #: ui/app.slint:540 -msgid "Attach files to this email" +msgctxt "forwarded message header" +msgid "Date: {}" msgstr "" #: ui/app.slint:541 -msgid "Could not add attachments: {}" +msgctxt "forwarded message header" +msgid "Subject: {}" msgstr "" #: ui/app.slint:542 -msgid "Added 1 attachment." +msgctxt "forwarded message header" +msgid "To: {}" msgstr "" #: ui/app.slint:543 -msgid "Added {} attachments." +msgid "Attach files to this email" msgstr "" #: ui/app.slint:544 +msgid "Could not add attachments: {}" +msgstr "" + +#: ui/app.slint:545 +msgid "Added 1 attachment." +msgstr "" + +#: ui/app.slint:546 +msgid "Added {} attachments." +msgstr "" + +#: ui/app.slint:547 msgid "" "Attachments added: {}. Skipped: {} (duplicate, unreadable, or over the 25 MB " "total limit)." msgstr "" -#: ui/app.slint:545 +#: ui/app.slint:548 msgid "Attachment removed." msgstr "" -#: ui/app.slint:546 +#: ui/app.slint:549 msgid "Choose the account this message should be sent from." msgstr "" -#: ui/app.slint:547 +#: ui/app.slint:550 msgid "Choose a verified sender identity for this message." msgstr "" -#: ui/app.slint:548 +#: ui/app.slint:551 msgid "Connect an account before saving or sending mail." msgstr "" -#: ui/app.slint:549 +#: ui/app.slint:552 msgid "Message queued for delivery (action {})." msgstr "" -#: ui/app.slint:550 +#: ui/app.slint:553 msgid "Sending message…" msgstr "" -#: ui/app.slint:551 +#: ui/app.slint:554 msgid "Message sent." msgstr "" -#: ui/app.slint:552 +#: ui/app.slint:555 msgid "Message was not sent: {} Your draft is preserved." msgstr "" -#: ui/app.slint:553 +#: ui/app.slint:556 msgid "Draft saved locally (#{})." msgstr "" -#: ui/app.slint:554 +#: ui/app.slint:557 msgid "Compose failed: {}" msgstr "" -#: ui/app.slint:555 +#: ui/app.slint:558 msgid "Connect an account before managing email templates." msgstr "" -#: ui/app.slint:556 +#: ui/app.slint:559 msgid "Could not load email templates: {}" msgstr "" -#: ui/app.slint:557 +#: ui/app.slint:560 msgid "Enter a template name." msgstr "" -#: ui/app.slint:558 +#: ui/app.slint:561 msgid "Add a subject or message to the template." msgstr "" -#: ui/app.slint:559 +#: ui/app.slint:562 msgid "Email template saved." msgstr "" -#: ui/app.slint:560 +#: ui/app.slint:563 msgid "Could not save email template: {}" msgstr "" -#: ui/app.slint:561 +#: ui/app.slint:564 msgid "Email template deleted." msgstr "" -#: ui/app.slint:562 +#: ui/app.slint:565 msgid "Could not delete email template: {}" msgstr "" -#: ui/app.slint:563 +#: ui/app.slint:566 msgid "Email template is no longer available." msgstr "" -#: ui/app.slint:564 +#: ui/app.slint:567 msgid "Email template inserted." msgstr "" -#: ui/app.slint:565 +#: ui/app.slint:568 msgid "Email template inserted, but its usage could not be saved: {}" msgstr "" -#: ui/app.slint:566 +#: ui/app.slint:569 msgid "Choose a supported account type and connection security." msgstr "" -#: ui/app.slint:567 +#: ui/app.slint:570 msgid "IMAP port must be between 1 and 65535." msgstr "" -#: ui/app.slint:568 +#: ui/app.slint:571 msgid "POP3 port must be between 1 and 65535." msgstr "" -#: ui/app.slint:569 +#: ui/app.slint:572 msgid "SMTP port must be between 1 and 65535." msgstr "" -#: ui/app.slint:570 +#: ui/app.slint:573 msgid "Local mail data is unavailable. Retry startup." msgstr "" -#: ui/app.slint:571 +#: ui/app.slint:574 msgid "Discovering JMAP and checking capabilities…" msgstr "" -#: ui/app.slint:572 +#: ui/app.slint:575 msgid "Certificate imported. Connect to verify the server." msgstr "" -#: ui/app.slint:573 +#: ui/app.slint:576 msgid "Could not load account preferences: {}" msgstr "" -#: ui/app.slint:574 +#: ui/app.slint:577 msgid "" "Your edited signature was preserved. Choose No signature to keep it as " "message text before inserting another." msgstr "" -#: ui/app.slint:575 +#: ui/app.slint:578 msgid "Certificate import failed: {}" msgstr "" -#: ui/app.slint:576 +#: ui/app.slint:579 msgid "Testing IMAP and SMTP connections…" msgstr "" -#: ui/app.slint:577 +#: ui/app.slint:580 msgid "Testing POP3 and SMTP connections…" msgstr "" -#: ui/app.slint:582 +#: ui/app.slint:585 msgid "" "Another browser authorization is already in progress; finish it or choose " "Cancel." msgstr "" -#: ui/app.slint:583 ui/dialogs/settings-dialog.slint:1947 -#: ui/app.slint:583 ui/dialogs/settings-dialog.slint:1947 ui/dialogs/settings-dialog.slint:1990 -#: ui/app.slint:583 ui/dialogs/settings-dialog.slint:1947 ui/dialogs/settings-dialog.slint:1990 ui/views/onboarding-view.slint:161 -#: ui/app.slint:583 ui/dialogs/settings-dialog.slint:1947 ui/dialogs/settings-dialog.slint:1990 ui/views/onboarding-view.slint:161 +#: ui/app.slint:586 ui/dialogs/settings-dialog.slint:1947 +#: ui/app.slint:586 ui/dialogs/settings-dialog.slint:1947 ui/dialogs/settings-dialog.slint:1990 +#: ui/app.slint:586 ui/dialogs/settings-dialog.slint:1947 ui/dialogs/settings-dialog.slint:1990 ui/views/onboarding-view.slint:161 +#: ui/app.slint:586 ui/dialogs/settings-dialog.slint:1947 ui/dialogs/settings-dialog.slint:1990 ui/views/onboarding-view.slint:161 msgid "Add app keys in Sign-in settings to enable this provider." msgstr "" -#: ui/app.slint:584 +#: ui/app.slint:587 msgid "Choose Gmail or Outlook OAuth." msgstr "" -#: ui/app.slint:585 +#: ui/app.slint:588 msgid "Complete sign-in in your browser, or choose Cancel here." msgstr "" -#: ui/app.slint:586 +#: ui/app.slint:589 msgid "Cancelling browser sign-in…" msgstr "" -#: ui/app.slint:587 +#: ui/app.slint:590 msgid "Finishing browser sign-in…" msgstr "" -#: ui/app.slint:588 +#: ui/app.slint:591 msgid "Could not use that browser address: {}" msgstr "" -#: ui/app.slint:589 +#: ui/app.slint:592 msgid "Calendar core is unavailable." msgstr "" -#: ui/app.slint:590 +#: ui/app.slint:593 msgid "Account no longer exists." msgstr "" -#: ui/app.slint:591 +#: ui/app.slint:594 msgid "Authorize calendar access in your browser." msgstr "" -#: ui/app.slint:592 +#: ui/app.slint:595 msgid "OAuth app keys saved." msgstr "" -#: ui/app.slint:593 +#: ui/app.slint:596 msgid "{} OAuth settings saved." msgstr "" -#: ui/app.slint:594 +#: ui/app.slint:597 msgid "OAuth settings failed: {}" msgstr "" -#: ui/app.slint:595 +#: ui/app.slint:598 msgid "Mail refresh failed: {}" msgstr "" -#: ui/app.slint:596 +#: ui/app.slint:599 msgid "Mail filter failed: {}" msgstr "" -#: ui/app.slint:597 +#: ui/app.slint:600 msgid "Mail pagination failed: {}" msgstr "" -#: ui/app.slint:598 +#: ui/app.slint:601 msgid "Could not mark message as read: {}" msgstr "" -#: ui/app.slint:599 ui/views/mail-reading-pane.slint:196 -#: ui/app.slint:599 ui/views/mail-reading-pane.slint:196 ui/views/mail-reading-pane.slint:1281 +#: ui/app.slint:602 ui/views/mail-reading-pane.slint:196 +#: ui/app.slint:602 ui/views/mail-reading-pane.slint:196 ui/views/mail-reading-pane.slint:1282 msgid "Loading message…" msgstr "" -#: ui/app.slint:605 ui/components/workspace-navigation.slint:787 -#: ui/app.slint:605 ui/components/workspace-navigation.slint:787 ui/tray.slint:13 ui/tray.slint:14 -#: ui/app.slint:605 ui/components/workspace-navigation.slint:787 ui/tray.slint:13 ui/tray.slint:14 +#: ui/app.slint:608 ui/components/workspace-navigation.slint:787 +#: ui/app.slint:608 ui/components/workspace-navigation.slint:787 ui/tray.slint:13 ui/tray.slint:14 +#: ui/app.slint:608 ui/components/workspace-navigation.slint:787 ui/tray.slint:13 ui/tray.slint:14 msgid "Flectar Mail" msgstr "" -#: ui/app.slint:1281 ui/app.slint:1294 +#: ui/app.slint:1285 ui/app.slint:1298 msgid "Global Labels (local only)" msgstr "" -#: ui/app.slint:2233 +#: ui/app.slint:2238 msgid "Empty Trash?" msgstr "" -#: ui/app.slint:2233 ui/views/files-view.slint:578 +#: ui/app.slint:2238 ui/views/files-view.slint:578 msgid "Delete permanently?" msgstr "" -#: ui/app.slint:2237 +#: ui/app.slint:2242 msgid "Permanently delete all messages in Trash across every connected account?" msgstr "" -#: ui/app.slint:2238 +#: ui/app.slint:2243 msgid "Permanently delete all messages in this account’s Trash?" msgstr "" -#: ui/app.slint:2240 +#: ui/app.slint:2245 msgid "Permanently delete the selected conversations from Trash?" msgstr "" -#: ui/app.slint:2241 +#: ui/app.slint:2246 msgid "Permanently delete this conversation from Trash?" msgstr "" -#: ui/app.slint:2242 ui/components/calendar.slint:947 -#: ui/app.slint:2242 ui/components/calendar.slint:947 +#: ui/app.slint:2247 ui/components/calendar.slint:947 +#: ui/app.slint:2247 ui/components/calendar.slint:947 msgid "This action cannot be undone." msgstr "" -#: ui/app.slint:2243 +#: ui/app.slint:2248 msgid "Empty Trash" msgstr "" -#: ui/app.slint:2243 ui/views/files-view.slint:660 -#: ui/app.slint:2243 ui/views/files-view.slint:660 +#: ui/app.slint:2248 ui/views/files-view.slint:660 +#: ui/app.slint:2248 ui/views/files-view.slint:660 msgid "Delete permanently" msgstr "" -#: ui/app.slint:2417 +#: ui/app.slint:2422 msgid "Mailbox startup failed" msgstr "" -#: ui/app.slint:2423 +#: ui/app.slint:2428 msgid "Flectar Mail could not open local storage" msgstr "" -#: ui/app.slint:2436 +#: ui/app.slint:2441 msgid "Diagnostic ID: {}" msgstr "" -#: ui/app.slint:2439 +#: ui/app.slint:2444 msgid "Diagnostic ID {}" msgstr "" -#: ui/app.slint:2444 +#: ui/app.slint:2449 msgid "Retry" msgstr "" -#: ui/app.slint:2452 ui/components/copyable-diagnostic.slint:43 +#: ui/app.slint:2457 ui/components/copyable-diagnostic.slint:43 msgid "Copy diagnostics" msgstr "" @@ -2678,22 +2690,22 @@ msgstr "" #: ui/components/composer-fields.slint:39 ui/views/mail-reading-pane.slint:337 #: ui/components/composer-fields.slint:39 ui/views/mail-reading-pane.slint:337 ui/views/mail-reading-pane.slint:373 -#: ui/components/composer-fields.slint:39 ui/views/mail-reading-pane.slint:337 ui/views/mail-reading-pane.slint:373 ui/views/mail-reading-pane.slint:737 -#: ui/components/composer-fields.slint:39 ui/views/mail-reading-pane.slint:337 ui/views/mail-reading-pane.slint:373 ui/views/mail-reading-pane.slint:737 +#: ui/components/composer-fields.slint:39 ui/views/mail-reading-pane.slint:337 ui/views/mail-reading-pane.slint:373 ui/views/mail-reading-pane.slint:738 +#: ui/components/composer-fields.slint:39 ui/views/mail-reading-pane.slint:337 ui/views/mail-reading-pane.slint:373 ui/views/mail-reading-pane.slint:738 msgid "Reply" msgstr "" #: ui/components/composer-fields.slint:40 ui/views/mail-reading-pane.slint:338 #: ui/components/composer-fields.slint:40 ui/views/mail-reading-pane.slint:338 ui/views/mail-reading-pane.slint:374 -#: ui/components/composer-fields.slint:40 ui/views/mail-reading-pane.slint:338 ui/views/mail-reading-pane.slint:374 ui/views/mail-reading-pane.slint:746 -#: ui/components/composer-fields.slint:40 ui/views/mail-reading-pane.slint:338 ui/views/mail-reading-pane.slint:374 ui/views/mail-reading-pane.slint:746 +#: ui/components/composer-fields.slint:40 ui/views/mail-reading-pane.slint:338 ui/views/mail-reading-pane.slint:374 ui/views/mail-reading-pane.slint:747 +#: ui/components/composer-fields.slint:40 ui/views/mail-reading-pane.slint:338 ui/views/mail-reading-pane.slint:374 ui/views/mail-reading-pane.slint:747 msgid "Reply all" msgstr "" #: ui/components/composer-fields.slint:41 ui/views/mail-reading-pane.slint:339 #: ui/components/composer-fields.slint:41 ui/views/mail-reading-pane.slint:339 ui/views/mail-reading-pane.slint:375 -#: ui/components/composer-fields.slint:41 ui/views/mail-reading-pane.slint:339 ui/views/mail-reading-pane.slint:375 ui/views/mail-reading-pane.slint:755 -#: ui/components/composer-fields.slint:41 ui/views/mail-reading-pane.slint:339 ui/views/mail-reading-pane.slint:375 ui/views/mail-reading-pane.slint:755 +#: ui/components/composer-fields.slint:41 ui/views/mail-reading-pane.slint:339 ui/views/mail-reading-pane.slint:375 ui/views/mail-reading-pane.slint:756 +#: ui/components/composer-fields.slint:41 ui/views/mail-reading-pane.slint:339 ui/views/mail-reading-pane.slint:375 ui/views/mail-reading-pane.slint:756 msgid "Forward" msgstr "" @@ -3497,7 +3509,7 @@ msgstr "" #: ui/components/theme-editor.slint:785 #: ui/components/theme-editor.slint:785 ui/dialogs/folder-dialog.slint:135 -#: ui/components/theme-editor.slint:785 ui/dialogs/folder-dialog.slint:135 ui/views/mail-reading-pane.slint:2029 +#: ui/components/theme-editor.slint:785 ui/dialogs/folder-dialog.slint:135 ui/views/mail-reading-pane.slint:2030 msgid "Save" msgstr "" @@ -3734,7 +3746,7 @@ msgstr "" msgid "Inside “{}”" msgstr "" -#: ui/dialogs/folder-dialog.slint:133 ui/views/mail-reading-pane.slint:1978 +#: ui/dialogs/folder-dialog.slint:133 ui/views/mail-reading-pane.slint:1979 msgid "Create label" msgstr "" @@ -4378,7 +4390,7 @@ msgstr "" #: ui/dialogs/rendering-info-dialog.slint:29 #: ui/dialogs/rendering-info-dialog.slint:29 ui/views/mail-reading-pane.slint:345 #: ui/dialogs/rendering-info-dialog.slint:29 ui/views/mail-reading-pane.slint:345 ui/views/mail-reading-pane.slint:381 -#: ui/dialogs/rendering-info-dialog.slint:29 ui/views/mail-reading-pane.slint:345 ui/views/mail-reading-pane.slint:381 ui/views/mail-reading-pane.slint:1897 +#: ui/dialogs/rendering-info-dialog.slint:29 ui/views/mail-reading-pane.slint:345 ui/views/mail-reading-pane.slint:381 ui/views/mail-reading-pane.slint:1898 msgid "About email rendering" msgstr "" @@ -4447,8 +4459,8 @@ msgstr "" msgid "Open Storage to calculate local usage." msgstr "" -#: ui/dialogs/settings-dialog.slint:269 ui/views/mail-reading-pane.slint:1251 -#: ui/dialogs/settings-dialog.slint:269 ui/views/mail-reading-pane.slint:1251 +#: ui/dialogs/settings-dialog.slint:269 ui/views/mail-reading-pane.slint:1252 +#: ui/dialogs/settings-dialog.slint:269 ui/views/mail-reading-pane.slint:1252 msgid "Attachments" msgstr "" @@ -5438,7 +5450,7 @@ msgstr "" #: ui/dialogs/settings-dialog.slint:2458 ui/views/mail-list-pane.slint:725 #: ui/dialogs/settings-dialog.slint:2458 ui/views/mail-list-pane.slint:725 ui/views/mail-reading-pane.slint:351 -#: ui/dialogs/settings-dialog.slint:2458 ui/views/mail-list-pane.slint:725 ui/views/mail-reading-pane.slint:351 ui/views/mail-reading-pane.slint:797 +#: ui/dialogs/settings-dialog.slint:2458 ui/views/mail-list-pane.slint:725 ui/views/mail-reading-pane.slint:351 ui/views/mail-reading-pane.slint:798 msgid "Move to spam" msgstr "" @@ -5474,8 +5486,8 @@ msgstr "" msgid "Reading" msgstr "" -#: ui/dialogs/settings-dialog.slint:2468 ui/views/mail-reading-pane.slint:1261 -#: ui/dialogs/settings-dialog.slint:2468 ui/views/mail-reading-pane.slint:1261 +#: ui/dialogs/settings-dialog.slint:2468 ui/views/mail-reading-pane.slint:1262 +#: ui/dialogs/settings-dialog.slint:2468 ui/views/mail-reading-pane.slint:1262 msgid "Find in message" msgstr "" @@ -5483,7 +5495,7 @@ msgstr "" msgid "Reset zoom" msgstr "" -#: ui/dialogs/settings-dialog.slint:2472 ui/views/mail-reading-pane.slint:1590 +#: ui/dialogs/settings-dialog.slint:2472 ui/views/mail-reading-pane.slint:1591 msgid "Caret browsing" msgstr "" @@ -5840,7 +5852,7 @@ msgstr "" msgid "Personal or Work" msgstr "" -#: ui/dialogs/settings-dialog.slint:3189 ui/views/mail-reading-pane.slint:1993 +#: ui/dialogs/settings-dialog.slint:3189 ui/views/mail-reading-pane.slint:1994 msgid "Color" msgstr "" @@ -6735,7 +6747,7 @@ msgstr "" msgid "Delete selected permanently" msgstr "" -#: ui/views/mail-list-pane.slint:747 ui/views/mail-reading-pane.slint:1018 +#: ui/views/mail-list-pane.slint:747 ui/views/mail-reading-pane.slint:1019 msgid "More message actions" msgstr "" @@ -6858,7 +6870,7 @@ msgstr "" msgid "to {}" msgstr "" -#: ui/views/mail-reading-pane.slint:329 ui/views/mail-reading-pane.slint:1881 +#: ui/views/mail-reading-pane.slint:329 ui/views/mail-reading-pane.slint:1882 msgid "Continue editing" msgstr "" @@ -6884,14 +6896,14 @@ msgstr "" #: ui/views/mail-reading-pane.slint:333 ui/views/mail-reading-pane.slint:348 #: ui/views/mail-reading-pane.slint:333 ui/views/mail-reading-pane.slint:348 ui/views/mail-reading-pane.slint:384 -#: ui/views/mail-reading-pane.slint:333 ui/views/mail-reading-pane.slint:348 ui/views/mail-reading-pane.slint:384 ui/views/mail-reading-pane.slint:1262 +#: ui/views/mail-reading-pane.slint:333 ui/views/mail-reading-pane.slint:348 ui/views/mail-reading-pane.slint:384 ui/views/mail-reading-pane.slint:1263 msgid "Use message appearance" msgstr "" #: ui/views/mail-reading-pane.slint:333 ui/views/mail-reading-pane.slint:348 #: ui/views/mail-reading-pane.slint:333 ui/views/mail-reading-pane.slint:348 ui/views/mail-reading-pane.slint:384 -#: ui/views/mail-reading-pane.slint:333 ui/views/mail-reading-pane.slint:348 ui/views/mail-reading-pane.slint:384 ui/views/mail-reading-pane.slint:1262 -#: ui/views/mail-reading-pane.slint:333 ui/views/mail-reading-pane.slint:348 ui/views/mail-reading-pane.slint:384 ui/views/mail-reading-pane.slint:1262 +#: ui/views/mail-reading-pane.slint:333 ui/views/mail-reading-pane.slint:348 ui/views/mail-reading-pane.slint:384 ui/views/mail-reading-pane.slint:1263 +#: ui/views/mail-reading-pane.slint:333 ui/views/mail-reading-pane.slint:348 ui/views/mail-reading-pane.slint:384 ui/views/mail-reading-pane.slint:1263 msgid "Show original colors" msgstr "" @@ -6916,179 +6928,179 @@ msgstr "" msgid "Open in browser" msgstr "" -#: ui/views/mail-reading-pane.slint:706 +#: ui/views/mail-reading-pane.slint:707 msgid "Close conversation" msgstr "" -#: ui/views/mail-reading-pane.slint:716 +#: ui/views/mail-reading-pane.slint:717 msgid "Previous conversation" msgstr "" -#: ui/views/mail-reading-pane.slint:726 +#: ui/views/mail-reading-pane.slint:727 msgid "Next conversation" msgstr "" -#: ui/views/mail-reading-pane.slint:767 +#: ui/views/mail-reading-pane.slint:768 msgid "Archive message" msgstr "" -#: ui/views/mail-reading-pane.slint:870 +#: ui/views/mail-reading-pane.slint:871 msgid "Search labels" msgstr "" -#: ui/views/mail-reading-pane.slint:887 +#: ui/views/mail-reading-pane.slint:888 msgid "Available labels" msgstr "" -#: ui/views/mail-reading-pane.slint:926 +#: ui/views/mail-reading-pane.slint:927 msgid "Smart category" msgstr "" -#: ui/views/mail-reading-pane.slint:967 ui/views/mail-reading-pane.slint:1978 +#: ui/views/mail-reading-pane.slint:968 ui/views/mail-reading-pane.slint:1979 msgid "Edit label" msgstr "" -#: ui/views/mail-reading-pane.slint:984 +#: ui/views/mail-reading-pane.slint:985 msgid "No matching labels" msgstr "" -#: ui/views/mail-reading-pane.slint:996 +#: ui/views/mail-reading-pane.slint:997 msgid "Create label…" msgstr "" -#: ui/views/mail-reading-pane.slint:1263 +#: ui/views/mail-reading-pane.slint:1264 msgid "Show original layout" msgstr "" -#: ui/views/mail-reading-pane.slint:1263 +#: ui/views/mail-reading-pane.slint:1264 msgid "Reader mode" msgstr "" -#: ui/views/mail-reading-pane.slint:1270 +#: ui/views/mail-reading-pane.slint:1271 msgid "Previous match" msgstr "" -#: ui/views/mail-reading-pane.slint:1271 +#: ui/views/mail-reading-pane.slint:1272 msgid "Next match" msgstr "" -#: ui/views/mail-reading-pane.slint:1272 +#: ui/views/mail-reading-pane.slint:1273 msgid "Close find" msgstr "" -#: ui/views/mail-reading-pane.slint:1276 +#: ui/views/mail-reading-pane.slint:1277 msgid "Some images could not be loaded." msgstr "" -#: ui/views/mail-reading-pane.slint:1277 ui/views/mail-reading-pane.slint:1588 +#: ui/views/mail-reading-pane.slint:1278 ui/views/mail-reading-pane.slint:1589 msgid "Retry images" msgstr "" -#: ui/views/mail-reading-pane.slint:1282 +#: ui/views/mail-reading-pane.slint:1283 msgid "Reload message" msgstr "" -#: ui/views/mail-reading-pane.slint:1344 +#: ui/views/mail-reading-pane.slint:1345 msgid "Remote images were blocked to protect your privacy." msgstr "" -#: ui/views/mail-reading-pane.slint:1353 +#: ui/views/mail-reading-pane.slint:1354 msgid "Load images" msgstr "" -#: ui/views/mail-reading-pane.slint:1391 +#: ui/views/mail-reading-pane.slint:1392 msgid "Loading image…" msgstr "" -#: ui/views/mail-reading-pane.slint:1391 +#: ui/views/mail-reading-pane.slint:1392 msgid "Blocked image" msgstr "" -#: ui/views/mail-reading-pane.slint:1391 +#: ui/views/mail-reading-pane.slint:1392 msgid "Image exceeds limits" msgstr "" -#: ui/views/mail-reading-pane.slint:1391 +#: ui/views/mail-reading-pane.slint:1392 msgid "Image unavailable" msgstr "" -#: ui/views/mail-reading-pane.slint:1537 +#: ui/views/mail-reading-pane.slint:1538 msgid "Show rendered email" msgstr "" -#: ui/views/mail-reading-pane.slint:1560 +#: ui/views/mail-reading-pane.slint:1561 msgid "Copy this HTML into your GitHub rendering issue." msgstr "" -#: ui/views/mail-reading-pane.slint:1577 +#: ui/views/mail-reading-pane.slint:1578 msgid "Show email" msgstr "" -#: ui/views/mail-reading-pane.slint:1587 +#: ui/views/mail-reading-pane.slint:1588 msgid "View original plain text" msgstr "" -#: ui/views/mail-reading-pane.slint:1589 +#: ui/views/mail-reading-pane.slint:1590 msgid "Copy formatted selection" msgstr "" -#: ui/views/mail-reading-pane.slint:1593 +#: ui/views/mail-reading-pane.slint:1594 msgid "Copy selected text" msgstr "" -#: ui/views/mail-reading-pane.slint:1603 +#: ui/views/mail-reading-pane.slint:1604 msgid "Copy all email text" msgstr "" -#: ui/views/mail-reading-pane.slint:1613 +#: ui/views/mail-reading-pane.slint:1614 msgid "Select all email text" msgstr "" -#: ui/views/mail-reading-pane.slint:1631 +#: ui/views/mail-reading-pane.slint:1632 msgid "Link: {}" msgstr "" -#: ui/views/mail-reading-pane.slint:1820 +#: ui/views/mail-reading-pane.slint:1821 msgid "Heading: {}" msgstr "" -#: ui/views/mail-reading-pane.slint:1942 +#: ui/views/mail-reading-pane.slint:1943 msgid "No message selected" msgstr "" -#: ui/views/mail-reading-pane.slint:1943 +#: ui/views/mail-reading-pane.slint:1944 msgid "Choose an email to read it here." msgstr "" -#: ui/views/mail-reading-pane.slint:1985 +#: ui/views/mail-reading-pane.slint:1986 msgid "Label name" msgstr "" -#: ui/views/mail-reading-pane.slint:2005 +#: ui/views/mail-reading-pane.slint:2006 msgid "Pink" msgstr "" -#: ui/views/mail-reading-pane.slint:2006 +#: ui/views/mail-reading-pane.slint:2007 msgid "Red" msgstr "" -#: ui/views/mail-reading-pane.slint:2007 +#: ui/views/mail-reading-pane.slint:2008 msgid "Amber" msgstr "" -#: ui/views/mail-reading-pane.slint:2010 +#: ui/views/mail-reading-pane.slint:2011 msgid "Slate" msgstr "" -#: ui/views/mail-reading-pane.slint:2015 +#: ui/views/mail-reading-pane.slint:2016 msgid "Use across all accounts (local only)" msgstr "" -#: ui/views/mail-view.slint:403 +#: ui/views/mail-view.slint:404 msgid "Message list width" msgstr "" -#: ui/views/mail-view.slint:748 +#: ui/views/mail-view.slint:751 msgid "Close folders" msgstr "" diff --git a/src/main.rs b/src/main.rs index 8e264764..4a615600 100644 --- a/src/main.rs +++ b/src/main.rs @@ -62,6 +62,7 @@ mod remote; mod renderer; mod renderer_input_controller; mod renderer_preferences; +mod rendering_report; mod retained_model; mod rich_compose; mod settings_controller; @@ -7802,6 +7803,21 @@ pub fn run(platform: PlatformContext) -> Result<(), Box> use_wgpu, platform.external_urls.clone(), ); + let state_for_report = Rc::clone(&state); + rendering_report::register( + &app, + move || { + state_for_report + .borrow() + .core + .as_ref() + .map(|core| core.file_core()) + }, + &runtime, + platform.documents.clone(), + platform.paths.temp_dir(), + platform.external_urls.clone(), + ); let app_weak = app.as_weak(); let state_for_search = Rc::clone(&state); diff --git a/src/renderer_input_controller.rs b/src/renderer_input_controller.rs index 443156c1..a53f4fad 100644 --- a/src/renderer_input_controller.rs +++ b/src/renderer_input_controller.rs @@ -324,7 +324,7 @@ pub(super) fn register_renderer_input_callbacks( } }); } -fn copy_text(app: &AppWindow, text: String) { +pub(super) fn copy_text(app: &AppWindow, text: String) { app.set_clipboard_request(text.into()); app.set_clipboard_request_id(app.get_clipboard_request_id().wrapping_add(1)); } diff --git a/src/rendering_report.rs b/src/rendering_report.rs new file mode 100644 index 00000000..a7c782da --- /dev/null +++ b/src/rendering_report.rs @@ -0,0 +1,576 @@ +//! Report issue in About email rendering. It opens the GitHub form for +//! rendering problems with this copy's version and reader settings filled in +//! and hands over the email's HTML for the reporter to review and include, +//! the way Zed and VS Code prefill their bug reports. +use super::*; +use crate::documents::{DocumentDialog, DocumentFuture, DocumentProvider}; +use flectar_mail_core::Core; +use std::{io::Write, path::Path}; + +/// The form in .github/ISSUE_TEMPLATE/email-rendering.yml. GitHub fills a +/// form field from the query parameter named after the field's `id`. +const ISSUE_FORM: &str = "https://github.com/flectar/mail/issues/new?template=email-rendering.yml"; + +/// GitHub rejects issues longer than 65,536 characters. HTML up to this +/// length goes on the clipboard and leaves room for the rest of the form. +/// Longer HTML is saved as a file to attach, as VS Code does with data too +/// long for an issue. +const PASTE_LIMIT: usize = 60_000; + +/// Attachments show their file name on the issue, so it never carries the +/// subject. +const FILE_NAME: &str = "email.html"; + +/// `core` returns the open mail data, whose settings choose the folder a +/// saved file starts in. +pub(super) fn register( + app: &AppWindow, + core: impl Fn() -> Option> + 'static, + runtime: &tokio::runtime::Handle, + documents: Arc, + temp_dir: PathBuf, + opener: ExternalUrlOpener, +) { + let weak = app.as_weak(); + let runtime = runtime.clone(); + let saving = Rc::new(Cell::new(false)); + app.on_report_rendering_issue(move || { + let Some(app) = weak.upgrade() else { + return; + }; + let url = issue_url(&Environment::from_app(&app).describe()); + let html = app.get_selected_source(); + if fits_in_issue(&html) { + if !html.is_empty() { + crate::renderer_input_controller::copy_text(&app, html.into()); + app.set_render_status(UiMessage::plain( + "Copied HTML source. Paste it into the issue.", + )); + } + open_form(&app, &opener, &url); + return; + } + // The browser would cover a save dialog opened after it, so the form + // opens once the file is saved. + if saving.replace(true) { + return; + } + let request = save_html( + core(), + Arc::clone(&documents), + temp_dir.clone(), + html.into(), + ); + let weak = app.as_weak(); + let opener = opener.clone(); + let saving = Rc::clone(&saving); + crate::documents::run_request(&runtime, request, move |result| { + saving.set(false); + if let Some(app) = weak.upgrade() { + finish_saving(&app, &opener, &url, result); + } + }); + }); +} + +fn open_form(app: &AppWindow, opener: &ExternalUrlOpener, url: &str) { + if let Err(error) = opener.open_external(url) { + app.set_render_status(UiMessage::detail("Could not open link: {}", error)); + } +} + +fn fits_in_issue(html: &str) -> bool { + html.chars().count() <= PASTE_LIMIT +} + +/// Saves HTML too long for an issue as a file for the reporter to attach. +fn save_html( + core: Option>, + documents: Arc, + temp_dir: PathBuf, + html: String, +) -> DocumentFuture { + Box::pin(async move { + let file = tokio::task::spawn_blocking(move || stage(&temp_dir, &html)) + .await + .map_err(|error| error.to_string())? + .map_err(|error| error.to_string())?; + // Start in the download folder from Settings, as attachments do. + let dialog = match core { + Some(core) => crate::documents::download_dialog_for(&core).await, + None => DocumentDialog::default(), + }; + let dialog = DocumentDialog { + title: "Save email HTML".into(), + filter: Some(("HTML".into(), &["html"])), + ..dialog + }; + documents + .export_with(file.to_path_buf(), FILE_NAME.into(), dialog) + .await + }) +} + +fn finish_saving( + app: &AppWindow, + opener: &ExternalUrlOpener, + url: &str, + result: Result, +) { + match result { + Ok(true) => app.set_render_status(UiMessage::plain( + "Saved HTML source. Attach the file to the issue.", + )), + // Cancelled. The form still opens for a report without the HTML. + Ok(false) => {} + Err(error) => { + app.set_render_status(UiMessage::detail("Could not save HTML source: {}", error)) + } + } + open_form(app, opener, url); +} + +/// Writes the HTML below the cache directory, which every document provider +/// accepts as an export source. The file goes away when the path drops. +fn stage(temp_dir: &Path, html: &str) -> std::io::Result { + std::fs::create_dir_all(temp_dir)?; + let mut file = tempfile::Builder::new() + .prefix("email-") + .suffix(".html") + .tempfile_in(temp_dir)?; + file.write_all(html.as_bytes())?; + Ok(file.into_temp_path()) +} + +fn issue_url(environment: &str) -> String { + let mut url = url::Url::parse(ISSUE_FORM).expect("the issue form address is valid"); + url.query_pairs_mut() + .append_pair("environment", environment); + url.into() +} + +/// What a report says about this copy of the app and the reader's settings. +struct Environment { + version: &'static str, + package: Option<&'static str>, + system: &'static str, + architecture: &'static str, + distribution: Option, + gpu: bool, + zoom: f32, + fit: bool, + colors: &'static str, + remote_images_blocked: bool, +} + +impl Environment { + fn from_app(app: &AppWindow) -> Self { + let reader = app.global::(); + let colors = app.global::(); + Self { + version: env!("CARGO_PKG_VERSION"), + package: package(), + system: system(), + architecture: std::env::consts::ARCH, + distribution: distribution(), + gpu: app.global::().get_active() == "gpu", + zoom: reader.get_zoom(), + fit: reader.get_auto_fit(), + colors: if colors.get_original() { + "original" + } else if colors.get_dark() { + "dark" + } else { + "light" + }, + remote_images_blocked: app.get_remote_images_blocked(), + } + } + + fn describe(&self) -> String { + let package = self + .package + .map(|package| format!(" ({package})")) + .unwrap_or_default(); + let distribution = self + .distribution + .as_ref() + .map(|distribution| format!(" ({distribution})")) + .unwrap_or_default(); + let renderer = if self.gpu { "GPU" } else { "CPU" }; + let fit = if self.fit { " (fit to width)" } else { "" }; + let images = if self.remote_images_blocked { + ", remote images blocked" + } else { + "" + }; + format!( + "Flectar Mail {}{package}\n{} {}{distribution}\n{renderer} renderer, {:.0}% zoom{fit}, {} message colors{images}", + self.version, + self.system, + self.architecture, + self.zoom * 100.0, + self.colors, + ) + } +} + +fn system() -> &'static str { + #[cfg(mobile)] + let name = crate::platform::NAME; + #[cfg(desktop)] + let name = std::env::consts::OS; + match name { + "linux" => "Linux", + "windows" => "Windows", + "macos" => "macOS", + "android" => "Android", + "ios" => "iOS", + "ohos" => "OpenHarmony", + other => other, + } +} + +/// Linux packages bring their own libraries and sandboxes, which change how +/// links, fonts and files behave. +fn package() -> Option<&'static str> { + if cfg!(feature = "flatpak") { + return Some("Flatpak"); + } + #[cfg(linux_desktop)] + if std::env::var_os("APPIMAGE").is_some() { + return Some("AppImage"); + } + None +} + +#[cfg(linux_desktop)] +fn distribution() -> Option { + // Inside Flatpak /etc/os-release names the runtime. Flatpak mounts the + // host's file at /run/host/os-release, as os-release(5) suggests. + let files: &[&str] = if cfg!(feature = "flatpak") { + &["/run/host/os-release"] + } else { + &["/etc/os-release", "/usr/lib/os-release"] + }; + // os-release(5): use only the first file that exists. + files + .iter() + .find_map(|path| std::fs::read_to_string(path).ok()) + .and_then(|text| pretty_name(&text)) +} + +#[cfg(not(linux_desktop))] +fn distribution() -> Option { + None +} + +/// `PRETTY_NAME` from an os-release file, whose values follow shell quoting. +#[cfg(any(linux_desktop, test))] +fn pretty_name(os_release: &str) -> Option { + let value = os_release + .lines() + .find_map(|line| line.trim().strip_prefix("PRETTY_NAME="))? + .trim(); + let value = ['"', '\''] + .into_iter() + .find_map(|quote| value.strip_prefix(quote)?.strip_suffix(quote)) + .unwrap_or(value); + let mut name = String::with_capacity(value.len()); + let mut characters = value.chars(); + while let Some(character) = characters.next() { + match character { + '\\' => name.extend(characters.next()), + character => name.push(character), + } + } + let name = name.trim(); + (!name.is_empty()).then(|| name.to_owned()) +} + +#[cfg(test)] +mod tests { + use super::*; + use slint::platform::{ + Platform, WindowAdapter, WindowEvent, + software_renderer::{MinimalSoftwareWindow, RepaintBufferType}, + }; + use std::{sync::Mutex, time::Duration}; + + fn environment() -> Environment { + Environment { + version: "0.1.0-alpha.7", + package: Some("AppImage"), + system: "Linux", + architecture: "x86_64", + distribution: Some("Arch Linux".into()), + gpu: true, + zoom: 0.85, + fit: true, + colors: "dark", + remote_images_blocked: true, + } + } + + #[test] + fn describes_the_app_system_and_reader() { + assert_eq!( + environment().describe(), + "Flectar Mail 0.1.0-alpha.7 (AppImage)\n\ + Linux x86_64 (Arch Linux)\n\ + GPU renderer, 85% zoom (fit to width), dark message colors, remote images blocked" + ); + let plain = Environment { + package: None, + system: "Windows", + distribution: None, + gpu: false, + zoom: 1.25, + fit: false, + colors: "original", + remote_images_blocked: false, + ..environment() + }; + assert_eq!( + plain.describe(), + "Flectar Mail 0.1.0-alpha.7\n\ + Windows x86_64\n\ + CPU renderer, 125% zoom, original message colors" + ); + } + + #[test] + fn prefills_the_form_field_named_environment() { + let environment = environment().describe(); + let url = issue_url(&environment); + let parsed = url::Url::parse(&url).unwrap(); + assert_eq!(parsed.host_str(), Some("github.com")); + assert_eq!(parsed.path(), "/flectar/mail/issues/new"); + let query: Vec<(String, String)> = parsed.query_pairs().into_owned().collect(); + assert_eq!( + query, + [ + ("template".to_owned(), "email-rendering.yml".to_owned()), + ("environment".to_owned(), environment), + ] + ); + // Well below the length VS Code keeps its prefilled issue links under. + assert!(url.len() < 7_500, "{}", url.len()); + } + + #[test] + fn issue_form_has_the_prefilled_field() { + let form = include_str!("../.github/ISSUE_TEMPLATE/email-rendering.yml"); + let template = ISSUE_FORM.rsplit_once("template=").unwrap().1; + assert_eq!(template, "email-rendering.yml"); + assert!(form.contains("\n id: environment\n"), "{form}"); + } + + #[test] + fn long_html_is_saved_instead_of_pasted() { + assert!(fits_in_issue("")); + assert!(fits_in_issue(&"é".repeat(PASTE_LIMIT))); + assert!(!fits_in_issue(&"a".repeat(PASTE_LIMIT + 1))); + } + + #[test] + fn reads_the_pretty_name_from_os_release() { + let arch = "NAME=\"Arch Linux\"\nPRETTY_NAME=\"Arch Linux\"\nID=arch\n"; + assert_eq!(pretty_name(arch).as_deref(), Some("Arch Linux")); + assert_eq!( + pretty_name("PRETTY_NAME='Debian GNU/Linux 13 (trixie)'").as_deref(), + Some("Debian GNU/Linux 13 (trixie)") + ); + assert_eq!(pretty_name("PRETTY_NAME=Gentoo").as_deref(), Some("Gentoo")); + assert_eq!( + pretty_name(r#"PRETTY_NAME="Say \"hi\" \$HOME""#).as_deref(), + Some(r#"Say "hi" $HOME"#) + ); + assert_eq!(pretty_name("NAME=Linux\n"), None); + assert_eq!(pretty_name("PRETTY_NAME=\"\""), None); + } + + /// Records what an export received while its source file still existed. + #[derive(Default)] + struct Exports(Mutex>); + + impl DocumentProvider for Exports { + fn import(&self) -> DocumentFuture> { + Box::pin(async { Ok(None) }) + } + fn export(&self, path: PathBuf, name: String) -> DocumentFuture { + self.export_with(path, name, DocumentDialog::default()) + } + fn export_with( + &self, + path: PathBuf, + name: String, + dialog: DocumentDialog, + ) -> DocumentFuture { + let content = std::fs::read_to_string(&path).unwrap_or_default(); + self.0.lock().unwrap().push((path, content, name, dialog)); + Box::pin(async { Ok(true) }) + } + } + + #[test] + fn saves_long_html_as_a_file_to_attach() { + let runtime = tokio::runtime::Builder::new_current_thread() + .enable_all() + .build() + .unwrap(); + let directory = tempfile::tempdir().unwrap(); + let temp_dir = directory.path().join("tmp"); + let exports = Arc::new(Exports::default()); + let html = format!("

{}

", "a".repeat(PASTE_LIMIT)); + let saved = runtime.block_on(save_html( + None, + exports.clone(), + temp_dir.clone(), + html.clone(), + )); + assert_eq!(saved, Ok(true)); + let exports = exports.0.lock().unwrap(); + let [(path, content, name, dialog)] = exports.as_slice() else { + panic!("expected one export"); + }; + assert!(path.starts_with(&temp_dir), "{path:?}"); + assert_eq!(content, &html); + assert_eq!(name, FILE_NAME); + assert_eq!(dialog.title, "Save email HTML"); + assert_eq!(dialog.filter, Some(("HTML".to_owned(), &["html"][..]))); + assert!(!path.exists(), "the staged copy is removed after saving"); + } + + /// A window with a clipboard and a clock the test moves. + struct Headless( + Rc, + Rc>, + Rc>, + ); + + impl Platform for Headless { + fn create_window_adapter(&self) -> Result, slint::PlatformError> { + Ok(self.0.clone()) + } + fn set_clipboard_text(&self, text: &str, _: slint::platform::Clipboard) { + *self.1.borrow_mut() = text.to_owned(); + } + fn duration_since_start(&self) -> Duration { + self.2.get() + } + } + + const SOURCE: &str = "

Download your data

"; + + /// Opens About email rendering in a window `width` wide and presses + /// Return, which activates Report issue. Returns the app, the addresses + /// it opened and the clipboard. + fn report_with_return(width: u32, single_pane: bool) -> (AppWindow, Vec, String) { + let window = MinimalSoftwareWindow::new(RepaintBufferType::NewBuffer); + let clipboard = Rc::new(RefCell::new(String::new())); + let clock = Rc::new(Cell::new(Duration::ZERO)); + slint::platform::set_platform(Box::new(Headless( + window.clone(), + clipboard.clone(), + clock.clone(), + ))) + .unwrap(); + let app = AppWindow::new().unwrap(); + app.set_startup_ready(true); + app.set_startup_hydrated(true); + app.set_connected_accounts(ModelRc::new(VecModel::from(vec![AccountRow { + id: 1, + ..Default::default() + }]))); + app.set_active_view("mail".into()); + app.window().set_size(slint::PhysicalSize::new(width, 900)); + app.show().unwrap(); + if single_pane { + // A tab with a conversation opens the single pane on the message. + app.global::().set_shown_conversation(true); + app.global::().set_shown(1); + slint::platform::update_timers_and_animations(); + // Let the message slide in. The window drops keys aimed at + // elements that are still out of view. + clock.set(Duration::from_secs(1)); + slint::platform::update_timers_and_animations(); + } + app.set_selected_source(SOURCE.into()); + app.set_remote_images_blocked(true); + app.global::().set_active("gpu".into()); + app.global::().set_zoom(0.85); + app.global::().set_auto_fit(true); + app.global::().set_preference("dark".into()); + + let runtime = tokio::runtime::Builder::new_current_thread() + .enable_all() + .build() + .unwrap(); + let opened = Arc::new(Mutex::new(Vec::::new())); + let recorded = opened.clone(); + register( + &app, + || None, + runtime.handle(), + Arc::new(Exports::default()), + std::env::temp_dir(), + ExternalUrlOpener::new(move |url| { + recorded.lock().unwrap().push(url.to_owned()); + Ok(()) + }), + ); + + // The dialog selects Report issue when it opens. + app.set_rendering_info_open(true); + let key = slint::SharedString::from(slint::platform::Key::Return); + app.window() + .dispatch_event(WindowEvent::KeyPressed { text: key.clone() }); + app.window() + .dispatch_event(WindowEvent::KeyReleased { text: key }); + // The reading pane copies to the clipboard from a change handler. + slint::platform::update_timers_and_animations(); + let opened = opened.lock().unwrap().clone(); + let copied = clipboard.borrow().clone(); + (app, opened, copied) + } + + #[test] + fn report_issue_copies_the_html_and_opens_the_prefilled_form() { + let (app, opened, copied) = report_with_return(1280, false); + let [url] = opened.as_slice() else { + panic!("expected the issue form once, got {opened:?}"); + }; + let environment = url::Url::parse(url) + .unwrap() + .query_pairs() + .find(|(key, _)| key == "environment") + .unwrap() + .1 + .into_owned(); + assert!( + environment.starts_with(&format!("Flectar Mail {}", env!("CARGO_PKG_VERSION"))), + "{environment}" + ); + assert!( + environment.ends_with( + "\nGPU renderer, 85% zoom (fit to width), dark message colors, remote images blocked" + ), + "{environment}" + ); + assert_eq!(copied, SOURCE); + assert_eq!( + app.get_render_message().key, + "Copied HTML source. Paste it into the issue." + ); + } + + /// Both layouts hold the dialog. The hidden copy must not take the focus + /// from the one on screen. + #[test] + fn report_issue_answers_the_keyboard_in_the_single_pane_layout() { + let (_app, opened, copied) = report_with_return(900, true); + assert_eq!(opened.len(), 1, "{opened:?}"); + assert_eq!(copied, SOURCE); + } +} diff --git a/ui/app.slint b/ui/app.slint index 671385c4..db70a8f6 100644 --- a/ui/app.slint +++ b/ui/app.slint @@ -308,6 +308,9 @@ export global I18n { if (key == "The message you were writing was saved to Drafts.") { return @tr("The message you were writing was saved to Drafts."); } if (key == "Files from links are never attached for you. Attach them yourself if you trust them: {}") { return @tr("Files from links are never attached for you. Attach them yourself if you trust them: {}", argument); } if (key == "Copied HTML source") { return @tr("Copied HTML source"); } + if (key == "Copied HTML source. Paste it into the issue.") { return @tr("Copied HTML source. Paste it into the issue."); } + if (key == "Saved HTML source. Attach the file to the issue.") { return @tr("Saved HTML source. Attach the file to the issue."); } + if (key == "Could not save HTML source: {}") { return @tr("Could not save HTML source: {}", argument); } if (key == "Copied selected text") { return @tr("Copied selected text"); } if (key == "Copied email text") { return @tr("Copied email text"); } if (key == "Copied link") { return @tr("Copied link"); } @@ -729,6 +732,7 @@ export component AppWindow inherits Window { callback cancel_storage_usage(); callback open_email_link(string); callback copy_email_status(string); + callback report_rendering_issue(); callback email-pointer-event(float, float, string, bool, bool, bool, bool); callback email-scroll(float, float); callback email-key-event(string, bool, bool, bool, bool, bool, bool); @@ -1633,6 +1637,7 @@ export component AppWindow inherits Window { open_compose => { root.open_compose(); } open_email_link(url) => { root.open_email_link(url); } copy_email_status(status) => { root.copy_email_status(status); } + report_rendering_issue => { root.report_rendering_issue(); } email-pointer-event(x, y, kind, control, shift, alt, meta) => { root.email-pointer-event(x, y, kind, control, shift, alt, meta); } diff --git a/ui/views/mail-reading-pane.slint b/ui/views/mail-reading-pane.slint index 2feba6a0..7ef43cbf 100644 --- a/ui/views/mail-reading-pane.slint +++ b/ui/views/mail-reading-pane.slint @@ -525,6 +525,7 @@ export component MailReadingPane inherits FocusScope { callback open_message_in_browser(); callback open_email_link(string); callback copy_email_status(string); + callback report_rendering_issue(); callback email-pointer-event(float, float, string, bool, bool, bool, bool); callback email-scroll(float, float); callback email-key-event(string, bool, bool, bool, bool, bool, bool); @@ -2065,8 +2066,6 @@ export component MailReadingPane inherits FocusScope { clipboard-source.copy(); root.copy_email_status("Copied HTML source"); } - report-issue => { - root.open_email_link("https://github.com/flectar/mail/issues/new?title=Email%20rendering%20issue&body=%23%23%20What%20looked%20wrong%3F%0A%0A%23%23%20Email%20HTML%20source%0A%3C!--%20Remove%20private%20information%20before%20pasting.%20--%3E%0A"); - } + report-issue => { root.report_rendering_issue(); } } } diff --git a/ui/views/mail-view.slint b/ui/views/mail-view.slint index 9bbaab92..502cf70e 100644 --- a/ui/views/mail-view.slint +++ b/ui/views/mail-view.slint @@ -168,6 +168,7 @@ export component MailView inherits FocusScope { callback open_compose(); callback open_email_link(string); callback copy_email_status(string); + callback report_rendering_issue(); callback email-pointer-event(float, float, string, bool, bool, bool, bool); callback email-scroll(float, float); callback email-key-event(string, bool, bool, bool, bool, bool, bool); @@ -483,6 +484,7 @@ export component MailView inherits FocusScope { open_message_in_browser => { root.open_message_in_browser(); } open_email_link(url) => { root.open_email_link(url); } copy_email_status(status) => { root.copy_email_status(status); } + report_rendering_issue => { root.report_rendering_issue(); } load-remote-images-for-message => { root.load-remote-images-for-message(); } email-pointer-event(x, y, kind, control, shift, alt, meta) => { root.email-pointer-event(x, y, kind, control, shift, alt, meta); @@ -718,6 +720,7 @@ export component MailView inherits FocusScope { open_message_in_browser => { root.open_message_in_browser(); } open_email_link(url) => { root.open_email_link(url); } copy_email_status(status) => { root.copy_email_status(status); } + report_rendering_issue => { root.report_rendering_issue(); } load-remote-images-for-message => { root.load-remote-images-for-message(); } email-pointer-event(x, y, kind, control, shift, alt, meta) => { root.email-pointer-event(x, y, kind, control, shift, alt, meta); From 15168e1ce97e86d6930ca3793d49d609331eecbf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Romero?= Date: Fri, 6 Nov 2026 18:49:24 +0100 Subject: [PATCH 4/5] ci: keep going when the Docker image prune fails --- .github/workflows/quality.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/quality.yml b/.github/workflows/quality.yml index 1800abcd..bf4c9bba 100644 --- a/.github/workflows/quality.yml +++ b/.github/workflows/quality.yml @@ -49,7 +49,8 @@ jobs: /opt/microsoft \ /usr/local/julia* \ /usr/local/share/chromium - sudo docker image prune --all --force > /dev/null + sudo docker image prune --all --force > /dev/null || + echo "::warning::Could not remove the preinstalled Docker images." df -h / fi - name: Install native build dependencies From 7c17bef7a2014af410d7c005859bf4e972753681 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Romero?= Date: Fri, 6 Nov 2026 19:08:33 +0100 Subject: [PATCH 5/5] test: call the trim-memory callback on Android --- .../java/com/flectar/mail/NativeCallbacksTest.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/platform/android/gradle/app/src/androidTest/java/com/flectar/mail/NativeCallbacksTest.java b/platform/android/gradle/app/src/androidTest/java/com/flectar/mail/NativeCallbacksTest.java index d9150940..c09c97fe 100644 --- a/platform/android/gradle/app/src/androidTest/java/com/flectar/mail/NativeCallbacksTest.java +++ b/platform/android/gradle/app/src/androidTest/java/com/flectar/mail/NativeCallbacksTest.java @@ -68,6 +68,13 @@ public final class NativeCallbacksTest { invoke("nativeSuspendPdfPreview", new Class[]{}); } + @Test + public void trimMemoryCallbackResolves() throws Throwable { + // TRIM_MEMORY_RUNNING_MODERATE (5) asks for nothing, so the callback + // only maps the level and never reaches the UI event loop. + invoke("nativeTrimMemory", new Class[]{int.class, int.class}, 5, 34); + } + @Test public void everyNativeDeclarationHasACallbackTest() { Set declarations = new HashSet<>(); @@ -83,6 +90,7 @@ public final class NativeCallbacksTest { tested.add("nativeDocumentResult"); tested.add("nativeDocumentsResult"); tested.add("nativeSuspendPdfPreview"); + tested.add("nativeTrimMemory"); assertEquals("Add a JNI invocation test when adding a native callback", tested, declarations); } }