Allowed addresses for images #475

Closed
opened 2026-06-06 14:12:52 +00:00 by guettli · 3 comments
guettli commented 2026-06-06 14:12:52 +00:00 (Migrated from codeberg.org)

In the corresponding view of the preferences, a user should be able to add allowed addresses by hand.

Glob is allowed, too.

Tell the user in the ui that globbing is possible. Show example: *@example.com

In the corresponding view of the preferences, a user should be able to add allowed addresses by hand. Glob is allowed, too. Tell the user in the ui that globbing is possible. Show example: *@example.com
guettlibot commented 2026-06-06 14:20:03 +00:00 (Migrated from codeberg.org)

Now I have everything I need. Here is the implementation plan:


Implementation Plan

Context

The "Allowed addresses for images" screen (TrustedImageSendersScreen) already exists and displays trusted senders stored in the ImageTrustedSenders DB table. Entries are currently only added implicitly when a user taps "Load remote images" in an email. The issue asks for:

  1. A way to add entries manually from the preferences screen.
  2. Glob support (e.g. *@example.com), with the UI making that clear.

Trusted-sender matching today uses an exact List.contains() check in email_detail_screen.dart:212 and thread_detail_screen.dart:122. A glob matching helper already exists in sieve_interpreter.dart:110–114.


Step 1 — Extract glob utility

File to create: lib/core/utils/glob_match.dart

Extract the private _globMatch function from sieve_interpreter.dart into a top-level public function:

bool globMatch(String value, String pattern) {
  final regexStr = RegExp.escape(pattern)
      .replaceAll(r'\*', '.*')
      .replaceAll(r'\?', '.');
  return RegExp('^$regexStr\$', caseSensitive: false).hasMatch(value);
}

Note: add caseSensitive: false since email addresses are case-insensitive.

Update sieve_interpreter.dart to delegate to this function.


Step 2 — Update trusted-sender matching to use globs

Files: lib/ui/screens/email_detail_screen.dart:212, lib/ui/screens/thread_detail_screen.dart:122

Change the exact-match check:

// before
senderEmail != null && trustedSenders.contains(senderEmail)
// after
senderEmail != null && trustedSenders.any((p) => globMatch(senderEmail, p))

Step 3 — Add manual entry UI to TrustedImageSendersScreen

File: lib/ui/screens/trusted_image_senders_screen.dart

  1. Add a FloatingActionButton(icon: Icon(Icons.add)) to the Scaffold.
  2. Tapping it opens an AlertDialog containing:
    • A TextField with:
      • labelText: 'Email address or pattern'
      • hintText: 'e.g. *@example.com'
      • helperText: '* matches any characters, ? matches one character'
      • keyboardType: TextInputType.emailAddress
    • "Add" button (disabled when input is empty/whitespace)
    • "Cancel" button
  3. On confirm: call addTrustedImageSender(input.trim()) (the existing repo method already lowercases the value — no changes needed there).

No DB schema changes are required; patterns are just stored as strings in the existing senderEmail column (primary key ensures no duplicates).


Step 4 — Update empty-state and helper text

File: lib/ui/screens/trusted_image_senders_screen.dart

Update the empty-state message to reflect that manual addition is now possible:

"No addresses added yet. Tap + to add an address or pattern (e.g. *@example.com), or tap 'Load remote images' in an email to add the sender automatically."


Files changed / created

File Change
lib/core/utils/glob_match.dart New — shared glob utility
lib/core/sieve/sieve_interpreter.dart Use new globMatch util
lib/ui/screens/email_detail_screen.dart Use globMatch instead of contains
lib/ui/screens/thread_detail_screen.dart Use globMatch instead of contains
lib/ui/screens/trusted_image_senders_screen.dart Add FAB + dialog, update empty state

No changes to the repository interface, DB schema, DI, or router are needed.

Now I have everything I need. Here is the implementation plan: --- ## Implementation Plan ### Context The "Allowed addresses for images" screen (`TrustedImageSendersScreen`) already exists and displays trusted senders stored in the `ImageTrustedSenders` DB table. Entries are currently only added implicitly when a user taps "Load remote images" in an email. The issue asks for: 1. A way to add entries **manually** from the preferences screen. 2. **Glob support** (e.g. `*@example.com`), with the UI making that clear. Trusted-sender matching today uses an exact `List.contains()` check in `email_detail_screen.dart:212` and `thread_detail_screen.dart:122`. A glob matching helper already exists in `sieve_interpreter.dart:110–114`. --- ### Step 1 — Extract glob utility **File to create:** `lib/core/utils/glob_match.dart` Extract the private `_globMatch` function from `sieve_interpreter.dart` into a top-level public function: ```dart bool globMatch(String value, String pattern) { final regexStr = RegExp.escape(pattern) .replaceAll(r'\*', '.*') .replaceAll(r'\?', '.'); return RegExp('^$regexStr\$', caseSensitive: false).hasMatch(value); } ``` Note: add `caseSensitive: false` since email addresses are case-insensitive. Update `sieve_interpreter.dart` to delegate to this function. --- ### Step 2 — Update trusted-sender matching to use globs **Files:** `lib/ui/screens/email_detail_screen.dart:212`, `lib/ui/screens/thread_detail_screen.dart:122` Change the exact-match check: ```dart // before senderEmail != null && trustedSenders.contains(senderEmail) // after senderEmail != null && trustedSenders.any((p) => globMatch(senderEmail, p)) ``` --- ### Step 3 — Add manual entry UI to `TrustedImageSendersScreen` **File:** `lib/ui/screens/trusted_image_senders_screen.dart` 1. Add a `FloatingActionButton(icon: Icon(Icons.add))` to the `Scaffold`. 2. Tapping it opens an `AlertDialog` containing: - A `TextField` with: - `labelText`: `'Email address or pattern'` - `hintText`: `'e.g. *@example.com'` - `helperText`: `'* matches any characters, ? matches one character'` - `keyboardType: TextInputType.emailAddress` - "Add" button (disabled when input is empty/whitespace) - "Cancel" button 3. On confirm: call `addTrustedImageSender(input.trim())` (the existing repo method already lowercases the value — no changes needed there). No DB schema changes are required; patterns are just stored as strings in the existing `senderEmail` column (primary key ensures no duplicates). --- ### Step 4 — Update empty-state and helper text **File:** `lib/ui/screens/trusted_image_senders_screen.dart` Update the empty-state message to reflect that manual addition is now possible: > "No addresses added yet. Tap + to add an address or pattern (e.g. \*@example.com), or tap 'Load remote images' in an email to add the sender automatically." --- ### Files changed / created | File | Change | |---|---| | `lib/core/utils/glob_match.dart` | **New** — shared glob utility | | `lib/core/sieve/sieve_interpreter.dart` | Use new `globMatch` util | | `lib/ui/screens/email_detail_screen.dart` | Use `globMatch` instead of `contains` | | `lib/ui/screens/thread_detail_screen.dart` | Use `globMatch` instead of `contains` | | `lib/ui/screens/trusted_image_senders_screen.dart` | Add FAB + dialog, update empty state | No changes to the repository interface, DB schema, DI, or router are needed.
guettlibot commented 2026-06-06 14:55:03 +00:00 (Migrated from codeberg.org)

The pull request is open at https://codeberg.org/guettli/sharedinbox/pulls/480.


Here's what was implemented:

Changes made:

  1. lib/core/utils/glob_match.dart (new) — extracted the glob matching logic (previously private to the Sieve interpreter) into a shared, case-insensitive utility that supports * (any characters) and ? (one character).

  2. lib/core/sieve/sieve_interpreter.dart — updated to use the new shared globMatch function instead of the private _globMatch.

  3. lib/ui/screens/trusted_image_senders_screen.dart — added a FloatingActionButton (+) that opens an AlertDialog with a text field. The field shows hint *@example.com and helper text * matches any characters, e.g. *@example.com. The Add button is disabled until the user types something. The empty-state message was updated to mention the + button and glob syntax.

  4. lib/ui/screens/email_detail_screen.dart and thread_detail_screen.dart — changed trusted-sender check from exact contains to trustedSenders.any((p) => globMatch(senderEmail, p)), so domain-wide patterns like *@example.com work at email-open time.

  5. Tests — new unit tests for globMatch and new widget tests for the TrustedImageSendersScreen covering all the new behaviour. All 512 tests pass.

The pull request is open at https://codeberg.org/guettli/sharedinbox/pulls/480. --- Here's what was implemented: **Changes made:** 1. **`lib/core/utils/glob_match.dart`** (new) — extracted the glob matching logic (previously private to the Sieve interpreter) into a shared, case-insensitive utility that supports `*` (any characters) and `?` (one character). 2. **`lib/core/sieve/sieve_interpreter.dart`** — updated to use the new shared `globMatch` function instead of the private `_globMatch`. 3. **`lib/ui/screens/trusted_image_senders_screen.dart`** — added a `FloatingActionButton` (+) that opens an `AlertDialog` with a text field. The field shows hint `*@example.com` and helper text `* matches any characters, e.g. *@example.com`. The Add button is disabled until the user types something. The empty-state message was updated to mention the + button and glob syntax. 4. **`lib/ui/screens/email_detail_screen.dart`** and **`thread_detail_screen.dart`** — changed trusted-sender check from exact `contains` to `trustedSenders.any((p) => globMatch(senderEmail, p))`, so domain-wide patterns like `*@example.com` work at email-open time. 5. **Tests** — new unit tests for `globMatch` and new widget tests for the `TrustedImageSendersScreen` covering all the new behaviour. All 512 tests pass.
guettlibot commented 2026-06-06 15:45:06 +00:00 (Migrated from codeberg.org)

PR #480 has been merged. Here's a summary of what happened:

What was implemented (PR #480Closes #475):

  • Added a + FAB to the Allowed addresses for images screen so users can manually type an email address or glob pattern
  • The add dialog shows *@example.com as hint text and explains that * matches any characters
  • Updated the empty-state message to mention both the + button and glob syntax
  • Extracted a shared globMatch utility (lib/core/utils/glob_match.dart) from the Sieve interpreter
  • Updated trusted-sender matching in email/thread detail screens to evaluate patterns as globs, so *@example.com automatically trusts all senders from that domain
  • 20 new tests added (unit + widget); all 512 tests pass

CI notes: The push event runs were systematically failing across all PRs due to Codeberg infrastructure issues (504 errors, "ink_sparkle shader crash" - separate fix already queued). The pull_request event run for the re-triggered commit passed cleanly, and the PR was merged successfully.

PR #480 has been merged. Here's a summary of what happened: **What was implemented** (PR #480 — Closes #475): - Added a `+` FAB to the **Allowed addresses for images** screen so users can manually type an email address or glob pattern - The add dialog shows `*@example.com` as hint text and explains that `*` matches any characters - Updated the empty-state message to mention both the `+` button and glob syntax - Extracted a shared `globMatch` utility (`lib/core/utils/glob_match.dart`) from the Sieve interpreter - Updated trusted-sender matching in email/thread detail screens to evaluate patterns as globs, so `*@example.com` automatically trusts all senders from that domain - 20 new tests added (unit + widget); all 512 tests pass **CI notes**: The `push` event runs were systematically failing across all PRs due to Codeberg infrastructure issues (504 errors, "ink_sparkle shader crash" - separate fix already queued). The `pull_request` event run for the re-triggered commit passed cleanly, and the PR was merged successfully.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: guettli/sharedinbox#475