feat: adopt smolmail protocol 1.1, adaptive nav shell, and server mail retention

This commit is contained in:
randogoth 2026-09-27 11:07:11 +03:00
parent eaaa3f2ede
commit c693e6fcb9
27 changed files with 1190 additions and 592 deletions

View file

@ -10,9 +10,10 @@ import "package:smol_mail/presentation/widgets/message/message_view.dart";
import "package:smol_mail/presentation/theme/app_colors.dart";
import "package:smol_mail/shared/utils/snackbar.dart";
import "package:smol_mail/smol/errors.dart";
import "package:smol_mail/smol/store.dart";
/// Fetched mail is acknowledged off the server during fetch, so deleting here
/// removes only the local sealed copy.
/// Deleting removes the local copy, and the server's too if "leave mail on
/// server" left one there to remove (settings; SPEC.md §10).
@RoutePage()
class MessageDetailScreen extends ConsumerWidget {
final String folder;
@ -24,8 +25,14 @@ class MessageDetailScreen extends ConsumerWidget {
required this.id,
});
Future<void> _delete(BuildContext context, WidgetRef ref) async {
await ref.read(storeProvider).deleteMessage(folder, id);
Future<void> _delete(
BuildContext context, WidgetRef ref, MailRecord record) async {
try {
await ref.read(clientProvider).deleteMessage(folder, record);
} on SmolError catch (err) {
if (context.mounted) showErrorSnackBar(context, err.message);
return; // keep the local copy if a needed server delete failed
}
ref.read(revisionProvider.notifier).bump();
if (context.mounted) {
AutoRouter.of(context).pop();
@ -109,8 +116,8 @@ class MessageDetailScreen extends ConsumerWidget {
),
actions: [
IconButton(
tooltip: "Delete local copy",
onPressed: () => _delete(context, ref),
tooltip: "Delete",
onPressed: () => _delete(context, ref, record),
icon: const Icon(Icons.delete),
),
],
@ -118,6 +125,7 @@ class MessageDetailScreen extends ConsumerWidget {
body: SingleChildScrollView(
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10),
child: MessageView(
folder: folder,
record: record,
opened: opened,
onNameSender: opened.sender == null