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/.github/workflows/quality.yml b/.github/workflows/quality.yml
index 96222b34..bf4c9bba 100644
--- a/.github/workflows/quality.yml
+++ b/.github/workflows/quality.yml
@@ -30,6 +30,29 @@ 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 ||
+ echo "::warning::Could not remove the preinstalled Docker images."
+ df -h /
+ fi
- name: Install native build dependencies
run: |
sudo apt-get update
diff --git a/lang/flectar-mail.pot b/lang/flectar-mail.pot
index 315f4e55..e5e22ec0 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:2030
+#: ui/app-icon.slint:22 ui/views/mail-reading-pane.slint:2033
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:2035
+#: ui/app-icon.slint:23 ui/components/theme-editor.slint:623 ui/views/mail-reading-pane.slint:2038
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:2031
+#: ui/app-icon.slint:24 ui/components/theme-editor.slint:624 ui/views/mail-reading-pane.slint:2034
msgid "Purple"
msgstr ""
@@ -384,8 +384,8 @@ msgstr ""
msgid "New address-book entry"
msgstr ""
-#: ui/app.slint:182 ui/app.slint:1063 ui/components/composer-fields.slint:66
-#: ui/app.slint:182 ui/app.slint:1063 ui/components/composer-fields.slint:66 ui/dialogs/compose-dialog.slint:37
+#: ui/app.slint:182 ui/app.slint:1067 ui/components/composer-fields.slint:66
+#: ui/app.slint:182 ui/app.slint:1067 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:187 ui/app.slint:458
+#: ui/app.slint:187 ui/app.slint:461
msgid "Loading local data…"
msgstr ""
-#: ui/app.slint:188 ui/app.slint:459
+#: ui/app.slint:188 ui/app.slint:462
msgid "Local data ready."
msgstr ""
@@ -758,1141 +758,1153 @@ msgid "Copied HTML source"
msgstr ""
#: ui/app.slint:313
-msgid "Copied selected text"
+msgid "Copied HTML source. Paste it into the issue."
msgstr ""
#: ui/app.slint:314
-msgid "Copied email text"
+msgid "Saved HTML source. Attach the file to the issue."
msgstr ""
#: ui/app.slint:315
-msgid "Copied link"
+msgid "Could not save HTML source: {}"
msgstr ""
#: ui/app.slint:316
-msgid "Blitz software selection render failed: {}"
+msgid "Copied selected text"
msgstr ""
#: ui/app.slint:317
-msgid "Blitz software tile render failed: {}"
+msgid "Copied email text"
msgstr ""
#: ui/app.slint:318
-msgid "Message ready."
+msgid "Copied link"
msgstr ""
#: ui/app.slint:319
-msgid "System tray behavior is unavailable in this package."
+msgid "Blitz software selection render failed: {}"
msgstr ""
#: ui/app.slint:320
-msgid "Close-to-tray is active for this session."
+msgid "Blitz software tile render failed: {}"
msgstr ""
#: ui/app.slint:321
-msgid "Saving close behavior…"
+msgid "Message ready."
msgstr ""
#: ui/app.slint:322
-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:323
-msgid "Closing the window will now quit Flectar Mail."
+msgid "Close-to-tray is active for this session."
msgstr ""
#: ui/app.slint:324
-msgid "Could not save close behavior: {}"
+msgid "Saving close behavior…"
msgstr ""
#: ui/app.slint:325
-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:326
-msgid "Flectar Mail is now your default email app."
+msgid "Closing the window will now quit Flectar Mail."
msgstr ""
#: ui/app.slint:327
-msgid "Choose Flectar Mail for MAILTO in Windows Settings to finish."
+msgid "Could not save close behavior: {}"
msgstr ""
#: ui/app.slint:328
-msgid "Windows no longer offers this copy for email links."
+msgid "Flectar Mail will start when you sign in."
msgstr ""
#: ui/app.slint:329
-msgid "Could not change the default email app: {}"
+msgid "Flectar Mail is now your default email app."
msgstr ""
#: ui/app.slint:330
-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:331
-msgid "Could not change startup behavior: {}"
+msgid "Windows no longer offers this copy for email links."
msgstr ""
#: ui/app.slint:332
-msgid "Allow Flectar Mail under Login Items in System Settings to finish."
+msgid "Could not change the default email app: {}"
msgstr ""
#: ui/app.slint:333
+msgid "Flectar Mail will no longer start when you sign in."
+msgstr ""
+
+#: ui/app.slint:334
+msgid "Could not change startup behavior: {}"
+msgstr ""
+
+#: ui/app.slint:335
+msgid "Allow Flectar Mail under Login Items in System Settings to finish."
+msgstr ""
+
+#: ui/app.slint:336
msgid "Turn on Flectar Mail under Startup apps in Windows Settings to finish."
msgstr ""
-#: ui/app.slint:338
+#: ui/app.slint:341
msgid "Database snapshot exported to {}."
msgstr ""
-#: ui/app.slint:339
+#: ui/app.slint:342
msgid "Choose where to export the mail"
msgstr ""
-#: ui/app.slint:340
+#: ui/app.slint:343
msgid "Exporting mail…"
msgstr ""
-#: ui/app.slint:341
+#: ui/app.slint:344
msgid "Mail exported to {}."
msgstr ""
-#: ui/app.slint:342
+#: ui/app.slint:345
msgid ""
"Mail exported to {}. Some messages could not be found on this device or the "
"mail server."
msgstr ""
-#: ui/app.slint:343
+#: ui/app.slint:346
msgid "Could not export mail: {}"
msgstr ""
-#: ui/app.slint:344
+#: ui/app.slint:347
msgid "Could not export database snapshot: {}"
msgstr ""
-#: ui/app.slint:345
+#: ui/app.slint:348
msgid "Account order saved."
msgstr ""
-#: ui/app.slint:346
+#: ui/app.slint:349
msgid "Could not save account order: {}"
msgstr ""
-#: ui/app.slint:347
+#: ui/app.slint:350
msgid "Mail history updated. Background sync is adjusting now."
msgstr ""
-#: ui/app.slint:348
+#: ui/app.slint:351
msgid "Account removed from this device."
msgstr ""
-#: ui/app.slint:349
+#: ui/app.slint:352
msgid "Account removed. Mail refresh will retry."
msgstr ""
-#: ui/app.slint:350
+#: ui/app.slint:353
msgid "Account removed; local cleanup needs a retry: {}"
msgstr ""
-#: ui/app.slint:351
+#: ui/app.slint:354
msgid "Could not remove account: {}"
msgstr ""
-#: ui/app.slint:352
+#: ui/app.slint:355
msgid "Removing account…"
msgstr ""
-#: ui/app.slint:353
+#: ui/app.slint:356
msgid "Deleting mail on this device…"
msgstr ""
-#: ui/app.slint:354
+#: ui/app.slint:357
msgid "Mail on this device deleted."
msgstr ""
-#: ui/app.slint:355
+#: ui/app.slint:358
msgid "Mail on this device deleted. Mail refresh will retry."
msgstr ""
-#: ui/app.slint:356
+#: ui/app.slint:359
msgid "Mail on this device deleted; local cleanup needs a retry: {}"
msgstr ""
-#: ui/app.slint:357
+#: ui/app.slint:360
msgid "Could not delete mail on this device: {}"
msgstr ""
-#: ui/app.slint:358
+#: ui/app.slint:361
msgid "Synchronizing account…"
msgstr ""
-#: ui/app.slint:359
+#: ui/app.slint:362
msgid "Could not update mail history: {}"
msgstr ""
-#: ui/app.slint:360
+#: ui/app.slint:363
msgid "Connected {}. Initial sync is running in the background."
msgstr ""
-#: ui/app.slint:361
+#: ui/app.slint:364
msgid "Account setup failed: {}"
msgstr ""
-#: ui/app.slint:362
+#: ui/app.slint:365
msgid "OAuth failed: {}"
msgstr ""
-#: ui/app.slint:363
+#: ui/app.slint:366
msgid "Reconnected {}. Synchronization is resuming."
msgstr ""
-#: ui/app.slint:364
+#: ui/app.slint:367
msgid "Reconnection failed: {}"
msgstr ""
-#: ui/app.slint:365
+#: ui/app.slint:368
msgid "Calendar connected and initial sync started."
msgstr ""
-#: ui/app.slint:366 ui/components/account-calendars.slint:270
+#: ui/app.slint:369 ui/components/account-calendars.slint:270
msgid "Could not connect calendar: {}"
msgstr ""
-#: ui/app.slint:367
+#: ui/app.slint:370
msgid "Calendar sync enabled."
msgstr ""
-#: ui/app.slint:368
+#: ui/app.slint:371
msgid "Calendar sync paused."
msgstr ""
-#: ui/app.slint:369
+#: ui/app.slint:372
msgid "Could not update calendar sync: {}"
msgstr ""
-#: ui/app.slint:370
+#: ui/app.slint:373
msgid "CalDAV connected and initial sync started."
msgstr ""
-#: ui/app.slint:371
+#: ui/app.slint:374
msgid "Could not connect CalDAV: {}"
msgstr ""
-#: ui/app.slint:372
+#: ui/app.slint:375
msgid "Calendar removed."
msgstr ""
-#: ui/app.slint:373
+#: ui/app.slint:376
msgid "Could not remove calendar: {}"
msgstr ""
-#: ui/app.slint:374
+#: ui/app.slint:377
msgid "CardDAV connected and initial sync started."
msgstr ""
-#: ui/app.slint:375
+#: ui/app.slint:378
msgid "Could not connect CardDAV: {}"
msgstr ""
-#: ui/app.slint:376
+#: ui/app.slint:379
msgid "CardDAV sync enabled."
msgstr ""
-#: ui/app.slint:377
+#: ui/app.slint:380
msgid "CardDAV sync paused."
msgstr ""
-#: ui/app.slint:378
+#: ui/app.slint:381
msgid "Could not update CardDAV sync: {}"
msgstr ""
-#: ui/app.slint:379
+#: ui/app.slint:382
msgid "CardDAV disconnected."
msgstr ""
-#: ui/app.slint:380
+#: ui/app.slint:383
msgid "Could not disconnect CardDAV: {}"
msgstr ""
-#: ui/app.slint:385
+#: ui/app.slint:388
msgid "Connect an account before creating a backup."
msgstr ""
-#: ui/app.slint:386
+#: ui/app.slint:389
msgid "Export Flectar Mail account backup"
msgstr ""
-#: ui/app.slint:387
+#: ui/app.slint:390
msgid "Flectar Mail backup"
msgstr ""
-#: ui/app.slint:388 ui/dialogs/import-dialog.slint:407
-#: ui/app.slint:388 ui/dialogs/import-dialog.slint:407 ui/views/onboarding-view.slint:223
+#: ui/app.slint:391 ui/dialogs/import-dialog.slint:407
+#: ui/app.slint:391 ui/dialogs/import-dialog.slint:407 ui/views/onboarding-view.slint:223
msgid "Import accounts and mail"
msgstr ""
-#: ui/app.slint:389
+#: ui/app.slint:392
msgid "Choose a Thunderbird profile or a folder of mail"
msgstr ""
-#: ui/app.slint:390
+#: ui/app.slint:393
msgid "Imported messages"
msgstr ""
-#: ui/app.slint:391
+#: ui/app.slint:394
msgid "Choose where to export the database snapshot"
msgstr ""
-#: ui/app.slint:392
+#: ui/app.slint:395
msgid "Backup exported. Passwords and OAuth tokens were not included."
msgstr ""
-#: ui/app.slint:393
+#: ui/app.slint:396
msgid "Could not export backup: {}"
msgstr ""
-#: ui/app.slint:394
+#: ui/app.slint:397
msgid "Local data storage is unavailable. Retry startup."
msgstr ""
-#: ui/app.slint:395
+#: ui/app.slint:398
msgid "Creating verified database snapshot…"
msgstr ""
-#: ui/app.slint:396
+#: ui/app.slint:399
msgid "All local Flectar Mail data was deleted."
msgstr ""
-#: ui/app.slint:397
+#: ui/app.slint:400
msgid "Could not delete all local data: {}"
msgstr ""
-#: ui/app.slint:398
+#: ui/app.slint:401
msgid "Deleting local accounts and cached data…"
msgstr ""
-#: ui/app.slint:403
+#: ui/app.slint:406
msgid "Background mail refresh failed: {}"
msgstr ""
-#: ui/app.slint:404
+#: ui/app.slint:407
msgid "No conversations in this folder"
msgstr ""
-#: ui/app.slint:405
+#: ui/app.slint:408
msgid "No conversations match this search"
msgstr ""
-#: ui/app.slint:406
+#: ui/app.slint:409
msgid "Mail core is ready for account synchronization and message actions."
msgstr ""
-#: ui/app.slint:407
+#: ui/app.slint:410
msgid "Large message rendered in compatibility mode."
msgstr ""
-#: ui/app.slint:408
+#: ui/app.slint:411
msgid "Software email render failed: {}"
msgstr ""
-#: ui/app.slint:409
+#: ui/app.slint:412
msgid "Rendered with software fallback after GPU error: {}"
msgstr ""
-#: ui/app.slint:410
+#: ui/app.slint:413
msgid "Blitz render failed (GPU: {}; software: {})"
msgstr ""
-#: ui/app.slint:415
+#: ui/app.slint:418
msgid "Enter a name, email address, or phone number, then save."
msgstr ""
-#: ui/app.slint:416
+#: ui/app.slint:419
msgid "Could not save: contact storage is unavailable."
msgstr ""
-#: ui/app.slint:417
+#: ui/app.slint:420
msgid "Could not save contact: {}"
msgstr ""
-#: ui/app.slint:418
+#: ui/app.slint:421
msgid "Contact saved."
msgstr ""
-#: ui/app.slint:419
+#: ui/app.slint:422
msgid "Saved to contacts."
msgstr ""
-#: ui/app.slint:420
+#: ui/app.slint:423
msgid "Could not delete: contact storage is unavailable."
msgstr ""
-#: ui/app.slint:421
+#: ui/app.slint:424
msgid "Could not delete contact: {}"
msgstr ""
-#: ui/app.slint:422
+#: ui/app.slint:425
msgid "Contact deleted."
msgstr ""
-#: ui/app.slint:423
+#: ui/app.slint:426
msgid "Could not load contacts: {}"
msgstr ""
-#: ui/app.slint:424
+#: ui/app.slint:427
msgid "Local contact storage is still starting…"
msgstr ""
-#: ui/app.slint:425
+#: ui/app.slint:428
msgid "Loading contacts…"
msgstr ""
-#: ui/app.slint:430 ui/components/calendar-agenda.slint:235
-#: ui/app.slint:430 ui/components/calendar-agenda.slint:235
+#: ui/app.slint:433 ui/components/calendar-agenda.slint:235
+#: ui/app.slint:433 ui/components/calendar-agenda.slint:235
msgid "Local calendar"
msgstr ""
-#: ui/app.slint:431 ui/components/calendar.slint:273
-#: ui/app.slint:431 ui/components/calendar.slint:273 ui/components/calendar.slint:321
-#: ui/app.slint:431 ui/components/calendar.slint:273 ui/components/calendar.slint:321 ui/components/calendar.slint:439
-#: ui/app.slint:431 ui/components/calendar.slint:273 ui/components/calendar.slint:321 ui/components/calendar.slint:439
-#: ui/app.slint:431 ui/components/calendar.slint:273 ui/components/calendar.slint:321 ui/components/calendar.slint:439
-#: ui/app.slint:431 ui/components/calendar.slint:273 ui/components/calendar.slint:321 ui/components/calendar.slint:439
-#: ui/app.slint:431 ui/components/calendar.slint:273 ui/components/calendar.slint:321 ui/components/calendar.slint:439
+#: ui/app.slint:434 ui/components/calendar.slint:273
+#: ui/app.slint:434 ui/components/calendar.slint:273 ui/components/calendar.slint:321
+#: ui/app.slint:434 ui/components/calendar.slint:273 ui/components/calendar.slint:321 ui/components/calendar.slint:439
+#: ui/app.slint:434 ui/components/calendar.slint:273 ui/components/calendar.slint:321 ui/components/calendar.slint:439
+#: ui/app.slint:434 ui/components/calendar.slint:273 ui/components/calendar.slint:321 ui/components/calendar.slint:439
+#: ui/app.slint:434 ui/components/calendar.slint:273 ui/components/calendar.slint:321 ui/components/calendar.slint:439
+#: ui/app.slint:434 ui/components/calendar.slint:273 ui/components/calendar.slint:321 ui/components/calendar.slint:439
msgid "Calendar"
msgstr ""
-#: ui/app.slint:432
+#: ui/app.slint:435
msgid "Could not load calendar: {}"
msgstr ""
-#: ui/app.slint:433
+#: ui/app.slint:436
msgid "Calendar shown and syncing."
msgstr ""
-#: ui/app.slint:434
+#: ui/app.slint:437
msgid "Calendar hidden and sync paused."
msgstr ""
-#: ui/app.slint:435
+#: ui/app.slint:438
msgid "Calendar update failed: {}"
msgstr ""
-#: ui/app.slint:436
+#: ui/app.slint:439
msgid "Only events created in Flectar Mail can be edited."
msgstr ""
-#: ui/app.slint:437
+#: ui/app.slint:440
msgid "Only events created in Flectar Mail can be deleted."
msgstr ""
-#: ui/app.slint:438
+#: ui/app.slint:441
msgid "Calendar storage is unavailable."
msgstr ""
-#: ui/app.slint:439
+#: ui/app.slint:442
msgid "Could not delete event: {}"
msgstr ""
-#: ui/app.slint:440
+#: ui/app.slint:443
msgid "Event deleted, but refresh failed: {}"
msgstr ""
-#: ui/app.slint:441
+#: ui/app.slint:444
msgid "Event deleted."
msgstr ""
-#: ui/app.slint:442
+#: ui/app.slint:445
msgid "Use YYYY-MM-DD for the date and a time such as {}."
msgstr ""
-#: ui/app.slint:443
+#: ui/app.slint:446
msgid "Event duration must be a number of minutes."
msgstr ""
-#: ui/app.slint:444
+#: ui/app.slint:447
msgid "Add a title and choose a duration from 15 to 1440 minutes."
msgstr ""
-#: ui/app.slint:445
+#: ui/app.slint:448
msgid "That local time does not exist in the current time zone."
msgstr ""
-#: ui/app.slint:446
+#: ui/app.slint:449
msgid "Could not save event: {}"
msgstr ""
-#: ui/app.slint:447
+#: ui/app.slint:450
msgid "Event saved, but refresh failed: {}"
msgstr ""
-#: ui/app.slint:448
+#: ui/app.slint:451
msgid "Event saved. Provider sync will run when enabled."
msgstr ""
-#: ui/app.slint:453
+#: ui/app.slint:456
msgid "Email resource render failed: {}"
msgstr ""
-#: ui/app.slint:454
+#: ui/app.slint:457
msgid "Message refresh failed: {}"
msgstr ""
-#: ui/app.slint:455
+#: ui/app.slint:458
msgid "Message load failed: {}"
msgstr ""
-#: ui/app.slint:456
+#: ui/app.slint:459
msgid ""
"Your local mailbox could not be opened. No account operation was started. "
"Retry, or copy the diagnostics for support."
msgstr ""
-#: ui/app.slint:457
+#: ui/app.slint:460
msgid "Local storage startup failed."
msgstr ""
-#: ui/app.slint:464
+#: ui/app.slint:467
msgid "Could not identify the dragged account."
msgstr ""
-#: ui/app.slint:465
+#: ui/app.slint:468
msgid "Account ordering requires local mail data."
msgstr ""
-#: ui/app.slint:466
+#: ui/app.slint:469
msgid "Could not find the account to reorder."
msgstr ""
-#: ui/app.slint:467
+#: ui/app.slint:470
msgid "Saving account order…"
msgstr ""
-#: ui/app.slint:468
+#: ui/app.slint:471
msgid "Sent copy settings require local mail data."
msgstr ""
-#: ui/app.slint:469
+#: ui/app.slint:472
msgid "Updating Sent copy settings…"
msgstr ""
-#: ui/app.slint:470
+#: ui/app.slint:473
msgid "Sent copy settings updated."
msgstr ""
-#: ui/app.slint:471
+#: ui/app.slint:474
msgid "Could not update Sent copy settings: {}"
msgstr ""
-#: ui/app.slint:472
+#: ui/app.slint:475
msgid "Server mail settings require local mail data."
msgstr ""
-#: ui/app.slint:473
+#: ui/app.slint:476
msgid "Updating server mail settings…"
msgstr ""
-#: ui/app.slint:474
+#: ui/app.slint:477
msgid "Server mail settings updated."
msgstr ""
-#: ui/app.slint:475
+#: ui/app.slint:478
msgid "Could not update server mail settings: {}"
msgstr ""
-#: ui/app.slint:476
+#: ui/app.slint:479
msgid "Mail history requires local mail data."
msgstr ""
-#: ui/app.slint:477
+#: ui/app.slint:480
msgid "Updating mail history…"
msgstr ""
-#: ui/app.slint:478
+#: ui/app.slint:481
msgid "Remote images are unavailable in this minimal build."
msgstr ""
-#: ui/app.slint:479
+#: ui/app.slint:482
msgid "Could not save remote-image setting: {}"
msgstr ""
-#: ui/app.slint:480
+#: ui/app.slint:483
msgid "Remote sender icons unavailable: {}"
msgstr ""
-#: ui/app.slint:481
+#: ui/app.slint:484
msgid "Remote images unavailable: {}"
msgstr ""
-#: ui/app.slint:482
+#: ui/app.slint:485
msgid "Remote body images and sender favicons enabled."
msgstr ""
-#: ui/app.slint:483
+#: ui/app.slint:486
msgid "Remote images blocked."
msgstr ""
-#: ui/app.slint:484
+#: ui/app.slint:487
msgid "Could not refresh message images: {}"
msgstr ""
-#: ui/app.slint:485
+#: ui/app.slint:488
msgid "Remote-image loading is disabled."
msgstr ""
-#: ui/app.slint:486
+#: ui/app.slint:489
msgid "Could not load message images: {}"
msgstr ""
-#: ui/app.slint:487
+#: ui/app.slint:490
msgid "Sync finished, refresh failed: {}"
msgstr ""
-#: ui/app.slint:488
+#: ui/app.slint:491
msgid "Sync complete."
msgstr ""
-#: ui/app.slint:489
+#: ui/app.slint:492
msgid "Sync failed: {}"
msgstr ""
-#: ui/app.slint:490
+#: ui/app.slint:493
msgid "Local mail data is unavailable; preview data is read-only."
msgstr ""
-#: ui/app.slint:491
+#: ui/app.slint:494
msgid "Synchronizing accounts…"
msgstr ""
-#: ui/app.slint:496
+#: ui/app.slint:499
msgid "Message action completed."
msgstr ""
-#: ui/app.slint:497
+#: ui/app.slint:500
msgid ""
"Permanent deletion queued. Mail will disappear after the server confirms."
msgstr ""
-#: ui/app.slint:498
+#: ui/app.slint:501
msgid "Message action failed: {}"
msgstr ""
-#: ui/app.slint:499
+#: ui/app.slint:502
msgid "Message action failed: message is no longer available"
msgstr ""
-#: ui/app.slint:500
+#: ui/app.slint:503
msgid "Label added."
msgstr ""
-#: ui/app.slint:501
+#: ui/app.slint:504
msgid "Label removed."
msgstr ""
-#: ui/app.slint:502
+#: ui/app.slint:505
msgid "Label created and added."
msgstr ""
-#: ui/app.slint:503
+#: ui/app.slint:506
msgid "Label created."
msgstr ""
-#: ui/app.slint:504
+#: ui/app.slint:507
msgid "Label updated."
msgstr ""
-#: ui/app.slint:505
+#: ui/app.slint:508
msgid "Label deleted."
msgstr ""
-#: ui/app.slint:506
+#: ui/app.slint:509
msgid "No other folder to move this mail to."
msgstr ""
-#: ui/app.slint:507
+#: ui/app.slint:510
msgid "Could not move mail: {}"
msgstr ""
-#: ui/app.slint:508
+#: ui/app.slint:511
msgid "No folder to copy this mail to."
msgstr ""
-#: ui/app.slint:509
+#: ui/app.slint:512
msgid "Could not copy mail: {}"
msgstr ""
-#: ui/app.slint:510
+#: ui/app.slint:513
msgid "Moving mail to the other account…"
msgstr ""
-#: ui/app.slint:511
+#: ui/app.slint:514
msgid "Copying mail to the other account…"
msgstr ""
-#: ui/app.slint:512
+#: ui/app.slint:515
msgid "Moved one message to the other account."
msgid_plural "Moved {0} messages to the other account."
msgstr[0] ""
msgstr[1] ""
-#: ui/app.slint:513
+#: ui/app.slint:516
msgid "Copied one message to the other account."
msgid_plural "Copied {0} messages to the other account."
msgstr[0] ""
msgstr[1] ""
-#: ui/app.slint:514
+#: ui/app.slint:517
msgid "Moved or copied one message to the other account."
msgid_plural "Moved or copied {0} messages to the other account."
msgstr[0] ""
msgstr[1] ""
-#: ui/app.slint:515
+#: ui/app.slint:518
msgid "The other account had that message already."
msgid_plural "The other account had those {0} messages already."
msgstr[0] ""
msgstr[1] ""
-#: ui/app.slint:516
+#: ui/app.slint:519
msgid "Could not move or copy one message: {1}"
msgid_plural "Could not move or copy {0} messages: {1}"
msgstr[0] ""
msgstr[1] ""
-#: ui/app.slint:517
+#: ui/app.slint:520
msgid "Could not update label: {}"
msgstr ""
-#: ui/app.slint:518
+#: ui/app.slint:521
msgid "Could not save label: {}"
msgstr ""
-#: ui/app.slint:519
+#: ui/app.slint:522
msgid "Could not delete label: {}"
msgstr ""
-#: ui/app.slint:520
+#: ui/app.slint:523
msgid "Folder created."
msgstr ""
-#: ui/app.slint:521
+#: ui/app.slint:524
msgid "Folder renamed."
msgstr ""
-#: ui/app.slint:522
+#: ui/app.slint:525
msgid "Folder deleted."
msgstr ""
-#: ui/app.slint:523
+#: ui/app.slint:526
msgid "Could not create folder: {}"
msgstr ""
-#: ui/app.slint:524
+#: ui/app.slint:527
msgid "Could not rename folder: {}"
msgstr ""
-#: ui/app.slint:525
+#: ui/app.slint:528
msgid "Could not delete folder: {}"
msgstr ""
-#: ui/app.slint:526
+#: ui/app.slint:529
msgid "Could not close preview: {}"
msgstr ""
-#: ui/app.slint:527
+#: ui/app.slint:530
msgid "Opened the system print view."
msgstr ""
-#: ui/app.slint:528
+#: ui/app.slint:531
msgid "Could not print message: {}"
msgstr ""
-#: ui/app.slint:529
+#: ui/app.slint:532
msgid "Opened the message in your browser."
msgstr ""
-#: ui/app.slint:530
+#: ui/app.slint:533
msgid "Could not open message in browser: {}"
msgstr ""
-#: ui/app.slint:531
+#: ui/app.slint:534
msgid "Connect an account before replying or forwarding."
msgstr ""
-#: ui/app.slint:532
+#: ui/app.slint:535
msgid "Choose a message first."
msgstr ""
-#: ui/app.slint:533
+#: ui/app.slint:536
msgid "Only drafts can be reopened for editing."
msgstr ""
-#: ui/app.slint:534
+#: ui/app.slint:537
msgid "Could not open draft: {}"
msgstr ""
-#: ui/app.slint:535
+#: ui/app.slint:538
msgid "Could not open draft: invalid account identifier"
msgstr ""
-#: ui/app.slint:536
+#: ui/app.slint:539
msgid "Connected account"
msgstr ""
-#: ui/app.slint:537
+#: ui/app.slint:540
msgid "Could not open composer: {}"
msgstr ""
-#: ui/app.slint:538
+#: ui/app.slint:541
msgid "Add an account to send mail."
msgstr ""
-#: ui/app.slint:539 ui/components/sidebar.slint:520
-#: ui/app.slint:539 ui/components/sidebar.slint:520 ui/views/mail-list-pane.slint:887
+#: ui/app.slint:542 ui/components/sidebar.slint:520
+#: ui/app.slint:542 ui/components/sidebar.slint:520 ui/views/mail-list-pane.slint:887
msgid "On this device"
msgstr ""
-#: ui/app.slint:540
+#: ui/app.slint:543
msgid "Could not open composer: invalid account identifier"
msgstr ""
#. Reply and forward quotation headers, written into the draft.
-#: ui/app.slint:546
+#: ui/app.slint:549
msgid "On {}, {} wrote:"
msgstr ""
-#: ui/app.slint:547
+#: ui/app.slint:550
msgid "{} wrote:"
msgstr ""
-#: ui/app.slint:548
-msgid "Forwarded message"
-msgstr ""
-
-#: ui/app.slint:549
-msgctxt "forwarded message header"
-msgid "From: {}"
-msgstr ""
-
-#: ui/app.slint:550
-msgctxt "forwarded message header"
-msgid "Date: {}"
-msgstr ""
-
#: ui/app.slint:551
-msgctxt "forwarded message header"
-msgid "Subject: {}"
+msgid "Forwarded message"
msgstr ""
#: ui/app.slint:552
msgctxt "forwarded message header"
-msgid "To: {}"
+msgid "From: {}"
msgstr ""
#: ui/app.slint:553
-msgid "Attach files to this email"
+msgctxt "forwarded message header"
+msgid "Date: {}"
msgstr ""
#: ui/app.slint:554
-msgid "Could not add attachments: {}"
+msgctxt "forwarded message header"
+msgid "Subject: {}"
msgstr ""
#: ui/app.slint:555
-msgid "Added 1 attachment."
+msgctxt "forwarded message header"
+msgid "To: {}"
msgstr ""
#: ui/app.slint:556
-msgid "Added {} attachments."
+msgid "Attach files to this email"
msgstr ""
#: ui/app.slint:557
+msgid "Could not add attachments: {}"
+msgstr ""
+
+#: ui/app.slint:558
+msgid "Added 1 attachment."
+msgstr ""
+
+#: ui/app.slint:559
+msgid "Added {} attachments."
+msgstr ""
+
+#: ui/app.slint:560
msgid ""
"Attachments added: {}. Skipped: {} (duplicate, unreadable, or over the 25 MB "
"total limit)."
msgstr ""
-#: ui/app.slint:558
+#: ui/app.slint:561
msgid "Attachment removed."
msgstr ""
-#: ui/app.slint:559
+#: ui/app.slint:562
msgid "Choose the account this message should be sent from."
msgstr ""
-#: ui/app.slint:560
+#: ui/app.slint:563
msgid "Choose a verified sender identity for this message."
msgstr ""
-#: ui/app.slint:561
+#: ui/app.slint:564
msgid "Connect an account before saving or sending mail."
msgstr ""
-#: ui/app.slint:562
+#: ui/app.slint:565
msgid "Message queued for delivery (action {})."
msgstr ""
-#: ui/app.slint:563
+#: ui/app.slint:566
msgid "Sending message…"
msgstr ""
-#: ui/app.slint:564
+#: ui/app.slint:567
msgid "Message sent."
msgstr ""
-#: ui/app.slint:565
+#: ui/app.slint:568
msgid "Message was not sent: {} Your draft is preserved."
msgstr ""
-#: ui/app.slint:566
+#: ui/app.slint:569
msgid "Draft saved locally (#{})."
msgstr ""
-#: ui/app.slint:567
+#: ui/app.slint:570
msgid "Compose failed: {}"
msgstr ""
-#: ui/app.slint:568
+#: ui/app.slint:571
msgid "Connect an account before managing email templates."
msgstr ""
-#: ui/app.slint:569
+#: ui/app.slint:572
msgid "Could not load email templates: {}"
msgstr ""
-#: ui/app.slint:570
+#: ui/app.slint:573
msgid "Enter a template name."
msgstr ""
-#: ui/app.slint:571
+#: ui/app.slint:574
msgid "Add a subject or message to the template."
msgstr ""
-#: ui/app.slint:572
+#: ui/app.slint:575
msgid "Email template saved."
msgstr ""
-#: ui/app.slint:573
+#: ui/app.slint:576
msgid "Could not save email template: {}"
msgstr ""
-#: ui/app.slint:574
+#: ui/app.slint:577
msgid "Email template deleted."
msgstr ""
-#: ui/app.slint:575
+#: ui/app.slint:578
msgid "Could not delete email template: {}"
msgstr ""
-#: ui/app.slint:576
+#: ui/app.slint:579
msgid "Email template is no longer available."
msgstr ""
-#: ui/app.slint:577
+#: ui/app.slint:580
msgid "Email template inserted."
msgstr ""
-#: ui/app.slint:578
+#: ui/app.slint:581
msgid "Email template inserted, but its usage could not be saved: {}"
msgstr ""
-#: ui/app.slint:579
+#: ui/app.slint:582
msgid "Choose a supported account type and connection security."
msgstr ""
-#: ui/app.slint:580
+#: ui/app.slint:583
msgid "IMAP port must be between 1 and 65535."
msgstr ""
-#: ui/app.slint:581
+#: ui/app.slint:584
msgid "POP3 port must be between 1 and 65535."
msgstr ""
-#: ui/app.slint:582
+#: ui/app.slint:585
msgid "SMTP port must be between 1 and 65535."
msgstr ""
-#: ui/app.slint:583
+#: ui/app.slint:586
msgid "Local mail data is unavailable. Retry startup."
msgstr ""
-#: ui/app.slint:584
+#: ui/app.slint:587
msgid "Discovering JMAP and checking capabilities…"
msgstr ""
-#: ui/app.slint:585
+#: ui/app.slint:588
msgid "Certificate imported. Connect to verify the server."
msgstr ""
-#: ui/app.slint:586
+#: ui/app.slint:589
msgid "Could not load account preferences: {}"
msgstr ""
-#: ui/app.slint:587
+#: ui/app.slint:590
msgid ""
"Your edited signature was preserved. Choose No signature to keep it as "
"message text before inserting another."
msgstr ""
-#: ui/app.slint:588
+#: ui/app.slint:591
msgid "Certificate import failed: {}"
msgstr ""
-#: ui/app.slint:589
+#: ui/app.slint:592
msgid "Testing IMAP and SMTP connections…"
msgstr ""
-#: ui/app.slint:590
+#: ui/app.slint:593
msgid "Testing POP3 and SMTP connections…"
msgstr ""
-#: ui/app.slint:595
+#: ui/app.slint:598
msgid ""
"Another browser authorization is already in progress; finish it or choose "
"Cancel."
msgstr ""
-#: ui/app.slint:596 ui/dialogs/settings-dialog.slint:1948
-#: ui/app.slint:596 ui/dialogs/settings-dialog.slint:1948 ui/dialogs/settings-dialog.slint:1991
-#: ui/app.slint:596 ui/dialogs/settings-dialog.slint:1948 ui/dialogs/settings-dialog.slint:1991 ui/views/onboarding-view.slint:161
-#: ui/app.slint:596 ui/dialogs/settings-dialog.slint:1948 ui/dialogs/settings-dialog.slint:1991 ui/views/onboarding-view.slint:161
+#: ui/app.slint:599 ui/dialogs/settings-dialog.slint:1948
+#: ui/app.slint:599 ui/dialogs/settings-dialog.slint:1948 ui/dialogs/settings-dialog.slint:1991
+#: ui/app.slint:599 ui/dialogs/settings-dialog.slint:1948 ui/dialogs/settings-dialog.slint:1991 ui/views/onboarding-view.slint:161
+#: ui/app.slint:599 ui/dialogs/settings-dialog.slint:1948 ui/dialogs/settings-dialog.slint:1991 ui/views/onboarding-view.slint:161
msgid "Add app keys in Sign-in settings to enable this provider."
msgstr ""
-#: ui/app.slint:597
+#: ui/app.slint:600
msgid "Choose Gmail or Outlook OAuth."
msgstr ""
-#: ui/app.slint:598
+#: ui/app.slint:601
msgid "Complete sign-in in your browser, or choose Cancel here."
msgstr ""
-#: ui/app.slint:599
+#: ui/app.slint:602
msgid "Cancelling browser sign-in…"
msgstr ""
-#: ui/app.slint:600
+#: ui/app.slint:603
msgid "Finishing browser sign-in…"
msgstr ""
-#: ui/app.slint:601
+#: ui/app.slint:604
msgid "Could not use that browser address: {}"
msgstr ""
-#: ui/app.slint:602
+#: ui/app.slint:605
msgid "Calendar core is unavailable."
msgstr ""
-#: ui/app.slint:603
+#: ui/app.slint:606
msgid "Account no longer exists."
msgstr ""
-#: ui/app.slint:604
+#: ui/app.slint:607
msgid "Authorize calendar access in your browser."
msgstr ""
-#: ui/app.slint:605
+#: ui/app.slint:608
msgid "OAuth app keys saved."
msgstr ""
-#: ui/app.slint:606
+#: ui/app.slint:609
msgid "{} OAuth settings saved."
msgstr ""
-#: ui/app.slint:607
+#: ui/app.slint:610
msgid "OAuth settings failed: {}"
msgstr ""
-#: ui/app.slint:608
+#: ui/app.slint:611
msgid "Mail refresh failed: {}"
msgstr ""
-#: ui/app.slint:609
+#: ui/app.slint:612
msgid "Mail filter failed: {}"
msgstr ""
-#: ui/app.slint:610
+#: ui/app.slint:613
msgid "Mail pagination failed: {}"
msgstr ""
-#: ui/app.slint:611
+#: ui/app.slint:614
msgid "Could not mark message as read: {}"
msgstr ""
-#: ui/app.slint:612 ui/views/mail-reading-pane.slint:197
-#: ui/app.slint:612 ui/views/mail-reading-pane.slint:197 ui/views/mail-reading-pane.slint:1308
+#: ui/app.slint:615 ui/views/mail-reading-pane.slint:197
+#: ui/app.slint:615 ui/views/mail-reading-pane.slint:197 ui/views/mail-reading-pane.slint:1311
msgid "Loading message…"
msgstr ""
-#: ui/app.slint:618 ui/components/workspace-navigation.slint:787
-#: ui/app.slint:618 ui/components/workspace-navigation.slint:787 ui/tray.slint:13 ui/tray.slint:14
-#: ui/app.slint:618 ui/components/workspace-navigation.slint:787 ui/tray.slint:13 ui/tray.slint:14
+#: ui/app.slint:621 ui/components/workspace-navigation.slint:787
+#: ui/app.slint:621 ui/components/workspace-navigation.slint:787 ui/tray.slint:13 ui/tray.slint:14
+#: ui/app.slint:621 ui/components/workspace-navigation.slint:787 ui/tray.slint:13 ui/tray.slint:14
msgid "Flectar Mail"
msgstr ""
-#: ui/app.slint:1296 ui/app.slint:1309
+#: ui/app.slint:1300 ui/app.slint:1313
msgid "Global Labels (local only)"
msgstr ""
-#: ui/app.slint:2250
+#: ui/app.slint:2255
msgid "Empty Trash?"
msgstr ""
-#: ui/app.slint:2250 ui/views/files-view.slint:578
+#: ui/app.slint:2255 ui/views/files-view.slint:578
msgid "Delete permanently?"
msgstr ""
-#: ui/app.slint:2254
+#: ui/app.slint:2259
msgid "Permanently delete all messages in Trash across every connected account?"
msgstr ""
-#: ui/app.slint:2255
+#: ui/app.slint:2260
msgid "Permanently delete all messages in this account’s Trash?"
msgstr ""
-#: ui/app.slint:2257
+#: ui/app.slint:2262
msgid "Permanently delete the selected conversations from Trash?"
msgstr ""
-#: ui/app.slint:2258
+#: ui/app.slint:2263
msgid "Permanently delete this conversation from Trash?"
msgstr ""
-#: ui/app.slint:2259 ui/components/calendar.slint:947
-#: ui/app.slint:2259 ui/components/calendar.slint:947
+#: ui/app.slint:2264 ui/components/calendar.slint:947
+#: ui/app.slint:2264 ui/components/calendar.slint:947
msgid "This action cannot be undone."
msgstr ""
-#: ui/app.slint:2260
+#: ui/app.slint:2265
msgid "Empty Trash"
msgstr ""
-#: ui/app.slint:2260 ui/views/files-view.slint:660
-#: ui/app.slint:2260 ui/views/files-view.slint:660
+#: ui/app.slint:2265 ui/views/files-view.slint:660
+#: ui/app.slint:2265 ui/views/files-view.slint:660
msgid "Delete permanently"
msgstr ""
-#: ui/app.slint:2443
+#: ui/app.slint:2448
msgid "Mailbox startup failed"
msgstr ""
-#: ui/app.slint:2449
+#: ui/app.slint:2454
msgid "Flectar Mail could not open local storage"
msgstr ""
-#: ui/app.slint:2462
+#: ui/app.slint:2467
msgid "Diagnostic ID: {}"
msgstr ""
-#: ui/app.slint:2465
+#: ui/app.slint:2470
msgid "Diagnostic ID {}"
msgstr ""
-#: ui/app.slint:2470
+#: ui/app.slint:2475
msgid "Retry"
msgstr ""
-#: ui/app.slint:2478 ui/components/copyable-diagnostic.slint:43
+#: ui/app.slint:2483 ui/components/copyable-diagnostic.slint:43
msgid "Copy diagnostics"
msgstr ""
@@ -2730,24 +2742,24 @@ msgstr ""
msgid "Keep"
msgstr ""
-#: ui/components/composer-fields.slint:39 ui/views/mail-reading-pane.slint:336
-#: ui/components/composer-fields.slint:39 ui/views/mail-reading-pane.slint:336 ui/views/mail-reading-pane.slint:376
-#: ui/components/composer-fields.slint:39 ui/views/mail-reading-pane.slint:336 ui/views/mail-reading-pane.slint:376 ui/views/mail-reading-pane.slint:761
-#: ui/components/composer-fields.slint:39 ui/views/mail-reading-pane.slint:336 ui/views/mail-reading-pane.slint:376 ui/views/mail-reading-pane.slint:761
+#: ui/components/composer-fields.slint:39 ui/views/mail-reading-pane.slint:338
+#: ui/components/composer-fields.slint:39 ui/views/mail-reading-pane.slint:338 ui/views/mail-reading-pane.slint:378
+#: ui/components/composer-fields.slint:39 ui/views/mail-reading-pane.slint:338 ui/views/mail-reading-pane.slint:378 ui/views/mail-reading-pane.slint:764
+#: ui/components/composer-fields.slint:39 ui/views/mail-reading-pane.slint:338 ui/views/mail-reading-pane.slint:378 ui/views/mail-reading-pane.slint:764
msgid "Reply"
msgstr ""
-#: ui/components/composer-fields.slint:40 ui/views/mail-reading-pane.slint:337
-#: ui/components/composer-fields.slint:40 ui/views/mail-reading-pane.slint:337 ui/views/mail-reading-pane.slint:377
-#: ui/components/composer-fields.slint:40 ui/views/mail-reading-pane.slint:337 ui/views/mail-reading-pane.slint:377 ui/views/mail-reading-pane.slint:770
-#: ui/components/composer-fields.slint:40 ui/views/mail-reading-pane.slint:337 ui/views/mail-reading-pane.slint:377 ui/views/mail-reading-pane.slint:770
+#: ui/components/composer-fields.slint:40 ui/views/mail-reading-pane.slint:339
+#: ui/components/composer-fields.slint:40 ui/views/mail-reading-pane.slint:339 ui/views/mail-reading-pane.slint:379
+#: ui/components/composer-fields.slint:40 ui/views/mail-reading-pane.slint:339 ui/views/mail-reading-pane.slint:379 ui/views/mail-reading-pane.slint:773
+#: ui/components/composer-fields.slint:40 ui/views/mail-reading-pane.slint:339 ui/views/mail-reading-pane.slint:379 ui/views/mail-reading-pane.slint:773
msgid "Reply all"
msgstr ""
-#: ui/components/composer-fields.slint:41 ui/views/mail-reading-pane.slint:338
-#: ui/components/composer-fields.slint:41 ui/views/mail-reading-pane.slint:338 ui/views/mail-reading-pane.slint:378
-#: ui/components/composer-fields.slint:41 ui/views/mail-reading-pane.slint:338 ui/views/mail-reading-pane.slint:378 ui/views/mail-reading-pane.slint:779
-#: ui/components/composer-fields.slint:41 ui/views/mail-reading-pane.slint:338 ui/views/mail-reading-pane.slint:378 ui/views/mail-reading-pane.slint:779
+#: ui/components/composer-fields.slint:41 ui/views/mail-reading-pane.slint:340
+#: ui/components/composer-fields.slint:41 ui/views/mail-reading-pane.slint:340 ui/views/mail-reading-pane.slint:380
+#: ui/components/composer-fields.slint:41 ui/views/mail-reading-pane.slint:340 ui/views/mail-reading-pane.slint:380 ui/views/mail-reading-pane.slint:782
+#: ui/components/composer-fields.slint:41 ui/views/mail-reading-pane.slint:340 ui/views/mail-reading-pane.slint:380 ui/views/mail-reading-pane.slint:782
msgid "Forward"
msgstr ""
@@ -3558,7 +3570,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:2056
+#: ui/components/theme-editor.slint:785 ui/dialogs/folder-dialog.slint:135 ui/views/mail-reading-pane.slint:2059
msgid "Save"
msgstr ""
@@ -3795,7 +3807,7 @@ msgstr ""
msgid "Inside “{}”"
msgstr ""
-#: ui/dialogs/folder-dialog.slint:133 ui/views/mail-reading-pane.slint:2005
+#: ui/dialogs/folder-dialog.slint:133 ui/views/mail-reading-pane.slint:2008
msgid "Create label"
msgstr ""
@@ -4331,8 +4343,8 @@ msgstr ""
#. Local mail has no archive or spam.
#: ui/dialogs/move-dialog.slint:45 ui/dialogs/settings-dialog.slint:2460
-#: ui/dialogs/move-dialog.slint:45 ui/dialogs/settings-dialog.slint:2460 ui/views/mail-reading-pane.slint:349
-#: ui/dialogs/move-dialog.slint:45 ui/dialogs/settings-dialog.slint:2460 ui/views/mail-reading-pane.slint:349
+#: ui/dialogs/move-dialog.slint:45 ui/dialogs/settings-dialog.slint:2460 ui/views/mail-reading-pane.slint:351
+#: ui/dialogs/move-dialog.slint:45 ui/dialogs/settings-dialog.slint:2460 ui/views/mail-reading-pane.slint:351
msgid "Archive"
msgstr ""
@@ -4478,32 +4490,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:344
-#: ui/dialogs/rendering-info-dialog.slint:25 ui/views/mail-reading-pane.slint:344 ui/views/mail-reading-pane.slint:384
-#: ui/dialogs/rendering-info-dialog.slint:25 ui/views/mail-reading-pane.slint:344 ui/views/mail-reading-pane.slint:384 ui/views/mail-reading-pane.slint:1924
+#: 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:346
+#: ui/dialogs/rendering-info-dialog.slint:29 ui/views/mail-reading-pane.slint:346 ui/views/mail-reading-pane.slint:386
+#: ui/dialogs/rendering-info-dialog.slint:29 ui/views/mail-reading-pane.slint:346 ui/views/mail-reading-pane.slint:386 ui/views/mail-reading-pane.slint:1927
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 ""
@@ -4551,8 +4563,8 @@ msgstr ""
msgid "Open Storage to calculate local usage."
msgstr ""
-#: ui/dialogs/settings-dialog.slint:270 ui/views/mail-reading-pane.slint:1278
-#: ui/dialogs/settings-dialog.slint:270 ui/views/mail-reading-pane.slint:1278
+#: ui/dialogs/settings-dialog.slint:270 ui/views/mail-reading-pane.slint:1281
+#: ui/dialogs/settings-dialog.slint:270 ui/views/mail-reading-pane.slint:1281
msgid "Attachments"
msgstr ""
@@ -5543,16 +5555,16 @@ msgid "Copy to a folder"
msgstr ""
#: ui/dialogs/settings-dialog.slint:2463 ui/views/mail-list-pane.slint:752
-#: ui/dialogs/settings-dialog.slint:2463 ui/views/mail-list-pane.slint:752 ui/views/mail-reading-pane.slint:352
-#: ui/dialogs/settings-dialog.slint:2463 ui/views/mail-list-pane.slint:752 ui/views/mail-reading-pane.slint:352 ui/views/mail-reading-pane.slint:821
+#: ui/dialogs/settings-dialog.slint:2463 ui/views/mail-list-pane.slint:752 ui/views/mail-reading-pane.slint:354
+#: ui/dialogs/settings-dialog.slint:2463 ui/views/mail-list-pane.slint:752 ui/views/mail-reading-pane.slint:354 ui/views/mail-reading-pane.slint:824
msgid "Move to spam"
msgstr ""
#: ui/dialogs/settings-dialog.slint:2464 ui/views/mail-list-pane.slint:761
-#: ui/dialogs/settings-dialog.slint:2464 ui/views/mail-list-pane.slint:761 ui/views/mail-reading-pane.slint:333
-#: ui/dialogs/settings-dialog.slint:2464 ui/views/mail-list-pane.slint:761 ui/views/mail-reading-pane.slint:333 ui/views/mail-reading-pane.slint:372
-#: ui/dialogs/settings-dialog.slint:2464 ui/views/mail-list-pane.slint:761 ui/views/mail-reading-pane.slint:333 ui/views/mail-reading-pane.slint:372 ui/views/mail-reading-pane.slint:408
-#: ui/dialogs/settings-dialog.slint:2464 ui/views/mail-list-pane.slint:761 ui/views/mail-reading-pane.slint:333 ui/views/mail-reading-pane.slint:372 ui/views/mail-reading-pane.slint:408
+#: ui/dialogs/settings-dialog.slint:2464 ui/views/mail-list-pane.slint:761 ui/views/mail-reading-pane.slint:335
+#: ui/dialogs/settings-dialog.slint:2464 ui/views/mail-list-pane.slint:761 ui/views/mail-reading-pane.slint:335 ui/views/mail-reading-pane.slint:374
+#: ui/dialogs/settings-dialog.slint:2464 ui/views/mail-list-pane.slint:761 ui/views/mail-reading-pane.slint:335 ui/views/mail-reading-pane.slint:374 ui/views/mail-reading-pane.slint:410
+#: ui/dialogs/settings-dialog.slint:2464 ui/views/mail-list-pane.slint:761 ui/views/mail-reading-pane.slint:335 ui/views/mail-reading-pane.slint:374 ui/views/mail-reading-pane.slint:410
msgid "Move to trash"
msgstr ""
@@ -5580,8 +5592,8 @@ msgstr ""
msgid "Reading"
msgstr ""
-#: ui/dialogs/settings-dialog.slint:2473 ui/views/mail-reading-pane.slint:1288
-#: ui/dialogs/settings-dialog.slint:2473 ui/views/mail-reading-pane.slint:1288
+#: ui/dialogs/settings-dialog.slint:2473 ui/views/mail-reading-pane.slint:1291
+#: ui/dialogs/settings-dialog.slint:2473 ui/views/mail-reading-pane.slint:1291
msgid "Find in message"
msgstr ""
@@ -5589,7 +5601,7 @@ msgstr ""
msgid "Reset zoom"
msgstr ""
-#: ui/dialogs/settings-dialog.slint:2477 ui/views/mail-reading-pane.slint:1617
+#: ui/dialogs/settings-dialog.slint:2477 ui/views/mail-reading-pane.slint:1620
msgid "Caret browsing"
msgstr ""
@@ -5946,7 +5958,7 @@ msgstr ""
msgid "Personal or Work"
msgstr ""
-#: ui/dialogs/settings-dialog.slint:3194 ui/views/mail-reading-pane.slint:2020
+#: ui/dialogs/settings-dialog.slint:3194 ui/views/mail-reading-pane.slint:2023
msgid "Color"
msgstr ""
@@ -6833,7 +6845,7 @@ msgstr ""
msgid "Delete selected permanently"
msgstr ""
-#: ui/views/mail-list-pane.slint:774 ui/views/mail-reading-pane.slint:1042
+#: ui/views/mail-list-pane.slint:774 ui/views/mail-reading-pane.slint:1045
msgid "More message actions"
msgstr ""
@@ -6846,42 +6858,42 @@ msgid "Open in new tab"
msgstr ""
#: ui/views/mail-list-pane.slint:786 ui/views/mail-list-pane.slint:1391
-#: ui/views/mail-list-pane.slint:786 ui/views/mail-list-pane.slint:1391 ui/views/mail-reading-pane.slint:369
-#: ui/views/mail-list-pane.slint:786 ui/views/mail-list-pane.slint:1391 ui/views/mail-reading-pane.slint:369 ui/views/mail-reading-pane.slint:406
+#: ui/views/mail-list-pane.slint:786 ui/views/mail-list-pane.slint:1391 ui/views/mail-reading-pane.slint:371
+#: ui/views/mail-list-pane.slint:786 ui/views/mail-list-pane.slint:1391 ui/views/mail-reading-pane.slint:371 ui/views/mail-reading-pane.slint:408
msgid "Move to…"
msgstr ""
#: ui/views/mail-list-pane.slint:793 ui/views/mail-list-pane.slint:1398
-#: ui/views/mail-list-pane.slint:793 ui/views/mail-list-pane.slint:1398 ui/views/mail-reading-pane.slint:370
-#: ui/views/mail-list-pane.slint:793 ui/views/mail-list-pane.slint:1398 ui/views/mail-reading-pane.slint:370 ui/views/mail-reading-pane.slint:407
+#: ui/views/mail-list-pane.slint:793 ui/views/mail-list-pane.slint:1398 ui/views/mail-reading-pane.slint:372
+#: ui/views/mail-list-pane.slint:793 ui/views/mail-list-pane.slint:1398 ui/views/mail-reading-pane.slint:372 ui/views/mail-reading-pane.slint:409
msgid "Copy to…"
msgstr ""
#: ui/views/mail-list-pane.slint:799 ui/views/mail-list-pane.slint:1387
-#: ui/views/mail-list-pane.slint:799 ui/views/mail-list-pane.slint:1387 ui/views/mail-reading-pane.slint:367
-#: ui/views/mail-list-pane.slint:799 ui/views/mail-list-pane.slint:1387 ui/views/mail-reading-pane.slint:367 ui/views/mail-reading-pane.slint:405
-#: ui/views/mail-list-pane.slint:799 ui/views/mail-list-pane.slint:1387 ui/views/mail-reading-pane.slint:367 ui/views/mail-reading-pane.slint:405
+#: ui/views/mail-list-pane.slint:799 ui/views/mail-list-pane.slint:1387 ui/views/mail-reading-pane.slint:369
+#: ui/views/mail-list-pane.slint:799 ui/views/mail-list-pane.slint:1387 ui/views/mail-reading-pane.slint:369 ui/views/mail-reading-pane.slint:407
+#: ui/views/mail-list-pane.slint:799 ui/views/mail-list-pane.slint:1387 ui/views/mail-reading-pane.slint:369 ui/views/mail-reading-pane.slint:407
msgid "Mark as read"
msgstr ""
#: ui/views/mail-list-pane.slint:800 ui/views/mail-list-pane.slint:1387
-#: ui/views/mail-list-pane.slint:800 ui/views/mail-list-pane.slint:1387 ui/views/mail-reading-pane.slint:367
-#: ui/views/mail-list-pane.slint:800 ui/views/mail-list-pane.slint:1387 ui/views/mail-reading-pane.slint:367 ui/views/mail-reading-pane.slint:405
-#: ui/views/mail-list-pane.slint:800 ui/views/mail-list-pane.slint:1387 ui/views/mail-reading-pane.slint:367 ui/views/mail-reading-pane.slint:405
+#: ui/views/mail-list-pane.slint:800 ui/views/mail-list-pane.slint:1387 ui/views/mail-reading-pane.slint:369
+#: ui/views/mail-list-pane.slint:800 ui/views/mail-list-pane.slint:1387 ui/views/mail-reading-pane.slint:369 ui/views/mail-reading-pane.slint:407
+#: ui/views/mail-list-pane.slint:800 ui/views/mail-list-pane.slint:1387 ui/views/mail-reading-pane.slint:369 ui/views/mail-reading-pane.slint:407
msgid "Mark as unread"
msgstr ""
#: ui/views/mail-list-pane.slint:801 ui/views/mail-list-pane.slint:1386
-#: ui/views/mail-list-pane.slint:801 ui/views/mail-list-pane.slint:1386 ui/views/mail-reading-pane.slint:359
-#: ui/views/mail-list-pane.slint:801 ui/views/mail-list-pane.slint:1386 ui/views/mail-reading-pane.slint:359 ui/views/mail-reading-pane.slint:397
-#: ui/views/mail-list-pane.slint:801 ui/views/mail-list-pane.slint:1386 ui/views/mail-reading-pane.slint:359 ui/views/mail-reading-pane.slint:397
+#: ui/views/mail-list-pane.slint:801 ui/views/mail-list-pane.slint:1386 ui/views/mail-reading-pane.slint:361
+#: ui/views/mail-list-pane.slint:801 ui/views/mail-list-pane.slint:1386 ui/views/mail-reading-pane.slint:361 ui/views/mail-reading-pane.slint:399
+#: ui/views/mail-list-pane.slint:801 ui/views/mail-list-pane.slint:1386 ui/views/mail-reading-pane.slint:361 ui/views/mail-reading-pane.slint:399
msgid "Star message"
msgstr ""
#: ui/views/mail-list-pane.slint:802 ui/views/mail-list-pane.slint:1386
-#: ui/views/mail-list-pane.slint:802 ui/views/mail-list-pane.slint:1386 ui/views/mail-reading-pane.slint:359
-#: ui/views/mail-list-pane.slint:802 ui/views/mail-list-pane.slint:1386 ui/views/mail-reading-pane.slint:359 ui/views/mail-reading-pane.slint:397
-#: ui/views/mail-list-pane.slint:802 ui/views/mail-list-pane.slint:1386 ui/views/mail-reading-pane.slint:359 ui/views/mail-reading-pane.slint:397
+#: ui/views/mail-list-pane.slint:802 ui/views/mail-list-pane.slint:1386 ui/views/mail-reading-pane.slint:361
+#: ui/views/mail-list-pane.slint:802 ui/views/mail-list-pane.slint:1386 ui/views/mail-reading-pane.slint:361 ui/views/mail-reading-pane.slint:399
+#: ui/views/mail-list-pane.slint:802 ui/views/mail-list-pane.slint:1386 ui/views/mail-reading-pane.slint:361 ui/views/mail-reading-pane.slint:399
msgid "Remove star"
msgstr ""
@@ -6918,9 +6930,9 @@ msgstr ""
msgid "Deselect {}"
msgstr ""
-#: ui/views/mail-list-pane.slint:1405 ui/views/mail-reading-pane.slint:333
-#: ui/views/mail-list-pane.slint:1405 ui/views/mail-reading-pane.slint:333 ui/views/mail-reading-pane.slint:372
-#: ui/views/mail-list-pane.slint:1405 ui/views/mail-reading-pane.slint:333 ui/views/mail-reading-pane.slint:372 ui/views/mail-reading-pane.slint:408
+#: ui/views/mail-list-pane.slint:1405 ui/views/mail-reading-pane.slint:335
+#: ui/views/mail-list-pane.slint:1405 ui/views/mail-reading-pane.slint:335 ui/views/mail-reading-pane.slint:374
+#: ui/views/mail-list-pane.slint:1405 ui/views/mail-reading-pane.slint:335 ui/views/mail-reading-pane.slint:374 ui/views/mail-reading-pane.slint:410
msgid "Delete permanently…"
msgstr ""
@@ -6968,237 +6980,237 @@ msgstr ""
msgid "to {}"
msgstr ""
-#: ui/views/mail-reading-pane.slint:328 ui/views/mail-reading-pane.slint:1908
+#: ui/views/mail-reading-pane.slint:330 ui/views/mail-reading-pane.slint:1911
msgid "Continue editing"
msgstr ""
-#: ui/views/mail-reading-pane.slint:330 ui/views/mail-reading-pane.slint:331
-#: ui/views/mail-reading-pane.slint:330 ui/views/mail-reading-pane.slint:331 ui/views/mail-reading-pane.slint:346
-#: ui/views/mail-reading-pane.slint:330 ui/views/mail-reading-pane.slint:331 ui/views/mail-reading-pane.slint:346 ui/views/mail-reading-pane.slint:365
-#: ui/views/mail-reading-pane.slint:330 ui/views/mail-reading-pane.slint:331 ui/views/mail-reading-pane.slint:346 ui/views/mail-reading-pane.slint:365 ui/views/mail-reading-pane.slint:386
-#: ui/views/mail-reading-pane.slint:330 ui/views/mail-reading-pane.slint:331 ui/views/mail-reading-pane.slint:346 ui/views/mail-reading-pane.slint:365 ui/views/mail-reading-pane.slint:386 ui/views/mail-reading-pane.slint:403
+#: ui/views/mail-reading-pane.slint:332 ui/views/mail-reading-pane.slint:333
+#: ui/views/mail-reading-pane.slint:332 ui/views/mail-reading-pane.slint:333 ui/views/mail-reading-pane.slint:348
+#: ui/views/mail-reading-pane.slint:332 ui/views/mail-reading-pane.slint:333 ui/views/mail-reading-pane.slint:348 ui/views/mail-reading-pane.slint:367
+#: ui/views/mail-reading-pane.slint:332 ui/views/mail-reading-pane.slint:333 ui/views/mail-reading-pane.slint:348 ui/views/mail-reading-pane.slint:367 ui/views/mail-reading-pane.slint:388
+#: ui/views/mail-reading-pane.slint:332 ui/views/mail-reading-pane.slint:333 ui/views/mail-reading-pane.slint:348 ui/views/mail-reading-pane.slint:367 ui/views/mail-reading-pane.slint:388 ui/views/mail-reading-pane.slint:405
msgid "Show rendered message"
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:385
-#: ui/views/mail-reading-pane.slint:330 ui/views/mail-reading-pane.slint:345 ui/views/mail-reading-pane.slint:385
+#: 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:387
+#: ui/views/mail-reading-pane.slint:332 ui/views/mail-reading-pane.slint:347 ui/views/mail-reading-pane.slint:387
msgid "Show source"
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:386
-#: ui/views/mail-reading-pane.slint:331 ui/views/mail-reading-pane.slint:346 ui/views/mail-reading-pane.slint:386
+#: 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:388
+#: ui/views/mail-reading-pane.slint:333 ui/views/mail-reading-pane.slint:348 ui/views/mail-reading-pane.slint:388
msgid "View plain text"
msgstr ""
-#: 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:387
-#: ui/views/mail-reading-pane.slint:332 ui/views/mail-reading-pane.slint:347 ui/views/mail-reading-pane.slint:387 ui/views/mail-reading-pane.slint:1289
+#: ui/views/mail-reading-pane.slint:334 ui/views/mail-reading-pane.slint:349
+#: ui/views/mail-reading-pane.slint:334 ui/views/mail-reading-pane.slint:349 ui/views/mail-reading-pane.slint:389
+#: ui/views/mail-reading-pane.slint:334 ui/views/mail-reading-pane.slint:349 ui/views/mail-reading-pane.slint:389 ui/views/mail-reading-pane.slint:1292
msgid "Use message appearance"
msgstr ""
-#: 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:387
-#: ui/views/mail-reading-pane.slint:332 ui/views/mail-reading-pane.slint:347 ui/views/mail-reading-pane.slint:387 ui/views/mail-reading-pane.slint:1289
-#: ui/views/mail-reading-pane.slint:332 ui/views/mail-reading-pane.slint:347 ui/views/mail-reading-pane.slint:387 ui/views/mail-reading-pane.slint:1289
+#: ui/views/mail-reading-pane.slint:334 ui/views/mail-reading-pane.slint:349
+#: ui/views/mail-reading-pane.slint:334 ui/views/mail-reading-pane.slint:349 ui/views/mail-reading-pane.slint:389
+#: ui/views/mail-reading-pane.slint:334 ui/views/mail-reading-pane.slint:349 ui/views/mail-reading-pane.slint:389 ui/views/mail-reading-pane.slint:1292
+#: ui/views/mail-reading-pane.slint:334 ui/views/mail-reading-pane.slint:349 ui/views/mail-reading-pane.slint:389 ui/views/mail-reading-pane.slint:1292
msgid "Show original colors"
msgstr ""
-#: ui/views/mail-reading-pane.slint:340 ui/views/mail-reading-pane.slint:360
-#: ui/views/mail-reading-pane.slint:340 ui/views/mail-reading-pane.slint:360 ui/views/mail-reading-pane.slint:398
-#: ui/views/mail-reading-pane.slint:340 ui/views/mail-reading-pane.slint:360 ui/views/mail-reading-pane.slint:398
+#: ui/views/mail-reading-pane.slint:342 ui/views/mail-reading-pane.slint:362
+#: ui/views/mail-reading-pane.slint:342 ui/views/mail-reading-pane.slint:362 ui/views/mail-reading-pane.slint:400
+#: ui/views/mail-reading-pane.slint:342 ui/views/mail-reading-pane.slint:362 ui/views/mail-reading-pane.slint:400
msgid "Manage labels"
msgstr ""
-#: ui/views/mail-reading-pane.slint:341 ui/views/mail-reading-pane.slint:361
-#: ui/views/mail-reading-pane.slint:341 ui/views/mail-reading-pane.slint:361 ui/views/mail-reading-pane.slint:399
+#: ui/views/mail-reading-pane.slint:343 ui/views/mail-reading-pane.slint:363
+#: ui/views/mail-reading-pane.slint:343 ui/views/mail-reading-pane.slint:363 ui/views/mail-reading-pane.slint:401
msgid "Decrypt / verify OpenPGP"
msgstr ""
-#: ui/views/mail-reading-pane.slint:342 ui/views/mail-reading-pane.slint:382
+#: ui/views/mail-reading-pane.slint:344 ui/views/mail-reading-pane.slint:384
msgid "Print message"
msgstr ""
-#: ui/views/mail-reading-pane.slint:343 ui/views/mail-reading-pane.slint:362
-#: ui/views/mail-reading-pane.slint:343 ui/views/mail-reading-pane.slint:362 ui/views/mail-reading-pane.slint:400
-#: ui/views/mail-reading-pane.slint:343 ui/views/mail-reading-pane.slint:362 ui/views/mail-reading-pane.slint:400
+#: ui/views/mail-reading-pane.slint:345 ui/views/mail-reading-pane.slint:364
+#: ui/views/mail-reading-pane.slint:345 ui/views/mail-reading-pane.slint:364 ui/views/mail-reading-pane.slint:402
+#: ui/views/mail-reading-pane.slint:345 ui/views/mail-reading-pane.slint:364 ui/views/mail-reading-pane.slint:402
msgid "Open in browser"
msgstr ""
-#: ui/views/mail-reading-pane.slint:730
+#: ui/views/mail-reading-pane.slint:733
msgid "Close conversation"
msgstr ""
-#: ui/views/mail-reading-pane.slint:740
+#: ui/views/mail-reading-pane.slint:743
msgid "Previous conversation"
msgstr ""
-#: ui/views/mail-reading-pane.slint:750
+#: ui/views/mail-reading-pane.slint:753
msgid "Next conversation"
msgstr ""
-#: ui/views/mail-reading-pane.slint:791
+#: ui/views/mail-reading-pane.slint:794
msgid "Archive message"
msgstr ""
-#: ui/views/mail-reading-pane.slint:894
+#: ui/views/mail-reading-pane.slint:897
msgid "Search labels"
msgstr ""
-#: ui/views/mail-reading-pane.slint:911
+#: ui/views/mail-reading-pane.slint:914
msgid "Available labels"
msgstr ""
-#: ui/views/mail-reading-pane.slint:950
+#: ui/views/mail-reading-pane.slint:953
msgid "Smart category"
msgstr ""
-#: ui/views/mail-reading-pane.slint:991 ui/views/mail-reading-pane.slint:2005
+#: ui/views/mail-reading-pane.slint:994 ui/views/mail-reading-pane.slint:2008
msgid "Edit label"
msgstr ""
-#: ui/views/mail-reading-pane.slint:1008
+#: ui/views/mail-reading-pane.slint:1011
msgid "No matching labels"
msgstr ""
-#: ui/views/mail-reading-pane.slint:1020
+#: ui/views/mail-reading-pane.slint:1023
msgid "Create label…"
msgstr ""
-#: ui/views/mail-reading-pane.slint:1290
+#: ui/views/mail-reading-pane.slint:1293
msgid "Show original layout"
msgstr ""
-#: ui/views/mail-reading-pane.slint:1290
+#: ui/views/mail-reading-pane.slint:1293
msgid "Reader mode"
msgstr ""
-#: ui/views/mail-reading-pane.slint:1297
+#: ui/views/mail-reading-pane.slint:1300
msgid "Previous match"
msgstr ""
-#: ui/views/mail-reading-pane.slint:1298
+#: ui/views/mail-reading-pane.slint:1301
msgid "Next match"
msgstr ""
-#: ui/views/mail-reading-pane.slint:1299
+#: ui/views/mail-reading-pane.slint:1302
msgid "Close find"
msgstr ""
-#: ui/views/mail-reading-pane.slint:1303
+#: ui/views/mail-reading-pane.slint:1306
msgid "Some images could not be loaded."
msgstr ""
-#: ui/views/mail-reading-pane.slint:1304 ui/views/mail-reading-pane.slint:1615
+#: ui/views/mail-reading-pane.slint:1307 ui/views/mail-reading-pane.slint:1618
msgid "Retry images"
msgstr ""
-#: ui/views/mail-reading-pane.slint:1309
+#: ui/views/mail-reading-pane.slint:1312
msgid "Reload message"
msgstr ""
-#: ui/views/mail-reading-pane.slint:1371
+#: ui/views/mail-reading-pane.slint:1374
msgid "Remote images were blocked to protect your privacy."
msgstr ""
-#: ui/views/mail-reading-pane.slint:1380
+#: ui/views/mail-reading-pane.slint:1383
msgid "Load images"
msgstr ""
-#: ui/views/mail-reading-pane.slint:1418
+#: ui/views/mail-reading-pane.slint:1421
msgid "Loading image…"
msgstr ""
-#: ui/views/mail-reading-pane.slint:1418
+#: ui/views/mail-reading-pane.slint:1421
msgid "Blocked image"
msgstr ""
-#: ui/views/mail-reading-pane.slint:1418
+#: ui/views/mail-reading-pane.slint:1421
msgid "Image exceeds limits"
msgstr ""
-#: ui/views/mail-reading-pane.slint:1418
+#: ui/views/mail-reading-pane.slint:1421
msgid "Image unavailable"
msgstr ""
-#: ui/views/mail-reading-pane.slint:1564
+#: ui/views/mail-reading-pane.slint:1567
msgid "Show rendered email"
msgstr ""
-#: ui/views/mail-reading-pane.slint:1587
+#: ui/views/mail-reading-pane.slint:1590
msgid "Copy this HTML into your GitHub rendering issue."
msgstr ""
-#: ui/views/mail-reading-pane.slint:1604
+#: ui/views/mail-reading-pane.slint:1607
msgid "Show email"
msgstr ""
-#: ui/views/mail-reading-pane.slint:1614
+#: ui/views/mail-reading-pane.slint:1617
msgid "View original plain text"
msgstr ""
-#: ui/views/mail-reading-pane.slint:1616
+#: ui/views/mail-reading-pane.slint:1619
msgid "Copy formatted selection"
msgstr ""
-#: ui/views/mail-reading-pane.slint:1620
+#: ui/views/mail-reading-pane.slint:1623
msgid "Copy selected text"
msgstr ""
-#: ui/views/mail-reading-pane.slint:1630
+#: ui/views/mail-reading-pane.slint:1633
msgid "Copy all email text"
msgstr ""
-#: ui/views/mail-reading-pane.slint:1640
+#: ui/views/mail-reading-pane.slint:1643
msgid "Select all email text"
msgstr ""
-#: ui/views/mail-reading-pane.slint:1658
+#: ui/views/mail-reading-pane.slint:1661
msgid "Link: {}"
msgstr ""
-#: ui/views/mail-reading-pane.slint:1847
+#: ui/views/mail-reading-pane.slint:1850
msgid "Heading: {}"
msgstr ""
-#: ui/views/mail-reading-pane.slint:1969
+#: ui/views/mail-reading-pane.slint:1972
msgid "No message selected"
msgstr ""
-#: ui/views/mail-reading-pane.slint:1970
+#: ui/views/mail-reading-pane.slint:1973
msgid "Choose an email to read it here."
msgstr ""
-#: ui/views/mail-reading-pane.slint:2012
+#: ui/views/mail-reading-pane.slint:2015
msgid "Label name"
msgstr ""
-#: ui/views/mail-reading-pane.slint:2032
+#: ui/views/mail-reading-pane.slint:2035
msgid "Pink"
msgstr ""
-#: ui/views/mail-reading-pane.slint:2033
+#: ui/views/mail-reading-pane.slint:2036
msgid "Red"
msgstr ""
-#: ui/views/mail-reading-pane.slint:2034
+#: ui/views/mail-reading-pane.slint:2037
msgid "Amber"
msgstr ""
-#: ui/views/mail-reading-pane.slint:2037
+#: ui/views/mail-reading-pane.slint:2040
msgid "Slate"
msgstr ""
-#: ui/views/mail-reading-pane.slint:2042
+#: ui/views/mail-reading-pane.slint:2045
msgid "Use across all accounts (local only)"
msgstr ""
-#: ui/views/mail-view.slint:428
+#: ui/views/mail-view.slint:429
msgid "Message list width"
msgstr ""
-#: ui/views/mail-view.slint:773
+#: ui/views/mail-view.slint:778
msgid "Close folders"
msgstr ""
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);
}
}
diff --git a/src/main.rs b/src/main.rs
index 7daf971b..dfbdeb38 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -63,6 +63,7 @@ mod remote;
mod renderer;
mod renderer_input_controller;
mod renderer_preferences;
+mod rendering_report;
mod retained_model;
mod rich_compose;
mod settings_controller;
@@ -7835,6 +7836,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