Files
sharedinbox/lib/ui/screens/settings_screen.dart
T
Thomas GüttlerandClaude Sonnet 4.6 6a457a9f7a fix: IMAP full sync via UID SEARCH+FETCH; add sync log UI
- Replace full-sync fetchMessages(1:*) with UID SEARCH ALL + UID FETCH
  so every message gets a reliable UID on all servers
- Guard CONDSTORE select on server capability to avoid BAD from
  servers that do not advertise CONDSTORE/QRESYNC
- Add SyncLogEntry model + observeSyncLogs stream to SyncLogRepository
- Add SyncLogScreen with per-entry duration/error display
- Wire history icon in SettingsScreen → /accounts/:id/sync-log route
- Fix FakeImapClient to expose initialized serverInfo via field override

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-21 07:43:30 +02:00

77 lines
2.8 KiB
Dart

import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:go_router/go_router.dart';
import '../../di.dart';
class SettingsScreen extends ConsumerWidget {
const SettingsScreen({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
final repo = ref.watch(accountRepositoryProvider);
return Scaffold(
appBar: AppBar(title: const Text('Settings')),
body: StreamBuilder(
stream: repo.observeAccounts(),
builder: (ctx, snap) {
final accounts = snap.data ?? [];
return ListView(
children: [
const ListTile(
title: Text(
'Accounts',
style: TextStyle(fontWeight: FontWeight.bold),
),
),
for (final a in accounts)
ListTile(
leading: const Icon(Icons.account_circle),
title: Text(a.displayName),
subtitle: Text(a.email),
trailing: Row(
mainAxisSize: MainAxisSize.min,
children: [
IconButton(
icon: const Icon(Icons.history),
tooltip: 'Sync log',
onPressed: () => ctx.push('/accounts/${a.id}/sync-log'),
),
IconButton(
icon: const Icon(Icons.delete),
onPressed: () async {
final confirm = await showDialog<bool>(
context: ctx,
builder: (ctx) => AlertDialog(
title: const Text('Remove account?'),
content: Text(
'Remove ${a.displayName}? Local data will be deleted.',
),
actions: [
TextButton(
onPressed: () => Navigator.pop(ctx, false),
child: const Text('Cancel'),
),
FilledButton(
onPressed: () => Navigator.pop(ctx, true),
child: const Text('Remove'),
),
],
),
);
if (confirm == true) {
await repo.removeAccount(a.id);
}
},
),
],
),
),
],
);
},
),
);
}
}