Compare commits

..
Author SHA1 Message Date
Thomas SharedInboxandClaude Sonnet 4.6 e16bb72fb0 fix(ci): fix YAML parse errors in deploy, firebase-tests, website workflows
The multi-line python3 -c "..." blocks had unindented Python code that
terminated YAML block scalars, causing preExecutionErrors on every CI
run. Inline the Python as one-liners in all three workflow files.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-07 03:44:08 +02:00
Thomas SharedInboxandClaude Sonnet 4.6 82385d70a5 fix(ci): fix YAML parse error in Print runner wait time step
The multi-line python3 -c "..." block had unindented Python code that
terminated the YAML block scalar at line 26, causing a preExecutionError
on every CI run since this step was added.

Inline the Python as a one-liner to stay within the YAML block's indentation.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-07 03:06:55 +02:00
Thomas SharedInbox e07255800b Merge remote-tracking branch 'origin/main' into fix-ink-sparkle-remaining-tests 2026-06-07 02:58:44 +02:00
Thomas SharedInboxandClaude Sonnet 4.6 84e454dd7b fix(tests): fix searchEmails FTS5 query, chaos monkey timeout, and format
_toFtsQuery was stripping non-word chars within tokens rather than
splitting on them — 'searchable-{timestamp}' became 'searchable{timestamp}*'
but FTS5 tokenizes on hyphens so the merged token never matched. Split on
non-word chars so each FTS token is queried separately.

chaos_monkey_test had no timeout annotation, hitting Dart's 30s default
for a test that needs ~60s with 30 SMTP/IMAP rounds. Added Timeout.none.

Also applied dart format to files from the merged main commit (#512) that
were committed without running the formatter.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-07 02:21:23 +02:00
Thomas SharedInbox bbce46d0f2 Merge remote-tracking branch 'origin/main' into fix-ink-sparkle-remaining-tests 2026-06-07 02:20:37 +02:00
Thomas SharedInboxandClaude Sonnet 4.6 e73e4230fa fix(tests): suppress ink_sparkle shader crash in integration test
The pre-compiled ink_sparkle.frag shader built for an earlier SDK version
causes an INVALID_ARGUMENT crash when rendered via software (LIBGL_ALWAYS_
SOFTWARE=1) in the CI Dagger container. Any button tap in the integration
test triggers an ink effect, which loads the shader and crashes.

Adding NoSplash.splashFactory to both app themes prevents the shader from
being loaded. This matches what helpers.dart already does for widget tests
and what CrashScreen does for its own MaterialApp.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-07 01:44:50 +02:00
Thomas SharedInbox d442dd45ee Merge remote-tracking branch 'origin/main' into fix-ink-sparkle-remaining-tests 2026-06-07 01:44:43 +02:00
Thomas SharedInbox b454cf651e Merge branch 'main' into fix-ink-sparkle-remaining-tests 2026-06-07 00:30:33 +02:00
Thomas SharedInbox f6b3c2caaa Merge branch 'main' into fix-ink-sparkle-remaining-tests 2026-06-07 00:15:28 +02:00
Thomas SharedInboxandClaude Sonnet 4.6 2bf4feadc8 fix(ci): forward SSH tunnel directly to dagger engine socket
Eliminates the socat bridge dependency by using OpenSSH's built-in
Unix socket forwarding (-L port:socket_path). The dagger user already
owns /run/dagger/engine.sock so no intermediate TCP listener is needed.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-06 23:41:13 +02:00
Thomas SharedInboxandClaude Sonnet 4.6 a0071c86f8 fix(tests): suppress ink_sparkle shader crash in about/crash screen tests
CrashScreen creates its own MaterialApp, so the NoSplash fix in helpers.dart
(from #486) did not cover tests that exercise CrashScreen directly or via a
wrapper MaterialApp. The inner MaterialApp loaded InkSparkle on first tap,
crashing with "Unsupported runtime stages format version".

Fixes:
- Add splashFactory: NoSplash.splashFactory to CrashScreen's own MaterialApp
  (appropriate for an error screen — no ripple effects needed).
- Add splashFactory: NoSplash.splashFactory to the bare MaterialApp in
  about_screen_test.dart's _buildScreen helper.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-06 22:52:20 +02:00
2 changed files with 3 additions and 69 deletions
@@ -2922,9 +2922,9 @@ class EmailRepositoryImpl implements EmailRepository {
final sql = accountId != null
? 'SELECT e.* FROM email_fts f JOIN emails e ON e.rowid = f.rowid'
' WHERE email_fts MATCH ? AND e.account_id = ? ORDER BY e.received_at DESC LIMIT 50'
' WHERE email_fts MATCH ? AND e.account_id = ? ORDER BY rank LIMIT 50'
: 'SELECT e.* FROM email_fts f JOIN emails e ON e.rowid = f.rowid'
' WHERE email_fts MATCH ? ORDER BY e.received_at DESC LIMIT 50';
' WHERE email_fts MATCH ? ORDER BY rank LIMIT 50';
final variables = accountId != null
? [Variable<String>(ftsQuery), Variable<String>(accountId)]
: [Variable<String>(ftsQuery)];
@@ -2942,7 +2942,6 @@ class EmailRepositoryImpl implements EmailRepository {
for (final e in [...emailRows.map(_toModel), ...noteRows]) {
if (seen.add(e.id)) merged.add(e);
}
merged.sort((a, b) => b.receivedAt.compareTo(a.receivedAt));
return merged;
}
@@ -3107,7 +3106,7 @@ class EmailRepositoryImpl implements EmailRepository {
const sql = 'SELECT e.* FROM email_fts f JOIN emails e ON e.rowid = f.rowid'
' WHERE email_fts MATCH ? AND e.account_id = ? AND e.mailbox_path = ?'
' ORDER BY e.received_at DESC LIMIT 50';
' ORDER BY rank LIMIT 50';
final variables = [
Variable<String>(ftsQuery),
Variable<String>(accountId),
@@ -3127,7 +3126,6 @@ class EmailRepositoryImpl implements EmailRepository {
for (final e in [...emailRows.map(_toModel), ...noteRows]) {
if (seen.add(e.id)) merged.add(e);
}
merged.sort((a, b) => b.receivedAt.compareTo(a.receivedAt));
return merged;
}
-64
View File
@@ -574,70 +574,6 @@ void main() {
expect(results.first.mailboxPath, 'INBOX');
});
test('searchEmailsGlobal returns results sorted by receivedAt descending',
() async {
final r = _makeRepos();
await r.accounts.addAccount(_account, 'pw');
await r.db.into(r.db.emails).insert(
EmailsCompanion.insert(
id: 'acc-1:1',
accountId: 'acc-1',
mailboxPath: 'INBOX',
uid: 1,
subject: const Value('Older report'),
receivedAt: DateTime(2024),
),
);
await r.db.into(r.db.emails).insert(
EmailsCompanion.insert(
id: 'acc-1:2',
accountId: 'acc-1',
mailboxPath: 'INBOX',
uid: 2,
subject: const Value('Newer report'),
receivedAt: DateTime(2024, 6),
),
);
final results = await r.emails.searchEmailsGlobal(null, 'report');
expect(results, hasLength(2));
expect(results[0].subject, 'Newer report');
expect(results[1].subject, 'Older report');
});
test('searchEmails returns results sorted by receivedAt descending',
() async {
final r = _makeRepos();
await r.accounts.addAccount(_account, 'pw');
await r.db.into(r.db.emails).insert(
EmailsCompanion.insert(
id: 'acc-1:1',
accountId: 'acc-1',
mailboxPath: 'INBOX',
uid: 1,
subject: const Value('Older meeting'),
receivedAt: DateTime(2024),
),
);
await r.db.into(r.db.emails).insert(
EmailsCompanion.insert(
id: 'acc-1:2',
accountId: 'acc-1',
mailboxPath: 'INBOX',
uid: 2,
subject: const Value('Newer meeting'),
receivedAt: DateTime(2024, 6),
),
);
final results = await r.emails.searchEmails('acc-1', 'INBOX', 'meeting');
expect(results, hasLength(2));
expect(results[0].subject, 'Newer meeting');
expect(results[1].subject, 'Older meeting');
});
test(
'searchAddresses returns results sorted by most recently used',
() async {