kirakira/lib/presentation/screens/message_detail_screen.dart

138 lines
4.2 KiB
Dart
Raw Permalink Normal View History

2024-02-17 20:32:01 +05:30
import "package:auto_route/auto_route.dart";
import "package:flutter/material.dart";
import "package:flutter_riverpod/flutter_riverpod.dart";
import "package:smol_mail/data/providers/providers.dart";
import "package:smol_mail/presentation/widgets/image_banner.dart";
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";
2024-02-17 20:32:01 +05:30
/// Deleting removes the local copy, and the server's too if "leave mail on
/// server" left one there to remove (settings; SPEC.md §10).
2024-02-17 20:32:01 +05:30
@RoutePage()
class MessageDetailScreen extends ConsumerWidget {
final String folder;
2024-02-17 20:32:01 +05:30
final String id;
const MessageDetailScreen({
super.key,
required this.folder,
2024-02-17 20:32:01 +05:30
required this.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();
2024-02-17 20:32:01 +05:30
if (context.mounted) {
AutoRouter.of(context).pop();
}
}
Future<void> _nameSender(BuildContext context, WidgetRef ref,
String senderKey) async {
final client = ref.read(clientProvider);
final controller = TextEditingController();
final address = await showDialog<String>(
context: context,
builder: (ctx) => AlertDialog(
backgroundColor: Theme.of(context).extension<AppColors>()!.cardFill,
content: TextField(
controller: controller,
decoration: InputDecoration(
hintText: "user@host or smol://…",
filled: true,
fillColor: Theme.of(context).colorScheme.surface,
),
),
actions: [
TextButton(
onPressed: () => Navigator.of(ctx).pop(controller.text),
child: const Text("Save"),
),
],
),
);
if (address == null || address.trim().isEmpty) return;
try {
await client.nameSender(address, senderKey);
ref.read(revisionProvider.notifier).bump();
if (context.mounted) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text("Address saved for this sender")),
);
}
} on SmolError catch (err) {
if (context.mounted) {
showErrorSnackBar(context, err.message);
}
}
}
2024-02-17 20:32:01 +05:30
@override
Widget build(BuildContext context, WidgetRef ref) {
final record = ref.watch(storeProvider).getMessage(folder, id);
if (record == null) {
return Scaffold(
appBar: AppBar(),
body: const ImageBanner(
imgSrc: "assets/images/error.png",
text: "Message not found!",
),
);
}
final client = ref.read(clientProvider);
final opened = client.describe(record);
final isSent = folder == "sent";
final who = isSent
? (record.recipient ?? "")
: (opened.sender == null
? ""
: ref.watch(storeProvider).addressForKey(opened.sender!) ?? "");
2024-02-17 20:32:01 +05:30
return Scaffold(
appBar: AppBar(
title: who.isEmpty
? null
: Text(
who,
overflow: TextOverflow.ellipsis,
style: TextStyle(
fontFamily: "Inter",
fontWeight: FontWeight.w500,
fontSize: 18,
color: Theme.of(context).colorScheme.onSurface,
),
),
2024-02-17 20:32:01 +05:30
actions: [
IconButton(
tooltip: "Delete",
onPressed: () => _delete(context, ref, record),
icon: const Icon(Icons.delete),
),
2024-02-17 20:32:01 +05:30
],
),
body: SingleChildScrollView(
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10),
child: MessageView(
folder: folder,
record: record,
opened: opened,
onNameSender: opened.sender == null
? null
: (key) => _nameSender(context, ref, key),
2024-02-17 20:32:01 +05:30
),
),
);
}
}