feat: replace mail protocol with smolmail and rebuild the UI
This commit is contained in:
parent
cb24b68069
commit
e94e4158cc
93 changed files with 6387 additions and 3479 deletions
|
|
@ -1,62 +1,82 @@
|
|||
import "dart:async";
|
||||
|
||||
import "package:auto_route/auto_route.dart";
|
||||
import "package:flutter/material.dart";
|
||||
import "package:flutter_riverpod/flutter_riverpod.dart";
|
||||
|
||||
import "package:flash_mail/data/providers/providers.dart";
|
||||
import "package:flash_mail/presentation/widgets/drawer/app_drawer.dart";
|
||||
import "package:flash_mail/presentation/widgets/image_banner.dart";
|
||||
import "package:flash_mail/presentation/widgets/message/message_list.dart";
|
||||
import "package:flash_mail/presentation/widgets/shimmer/message_shimmer.dart";
|
||||
import "package:smol_mail/data/providers/providers.dart";
|
||||
import "package:smol_mail/presentation/routes/app_router.gr.dart";
|
||||
import "package:smol_mail/presentation/widgets/drawer/app_drawer.dart";
|
||||
import "package:smol_mail/presentation/widgets/image_banner.dart";
|
||||
import "package:smol_mail/presentation/widgets/message/message_list.dart";
|
||||
import "package:smol_mail/shared/utils/snackbar.dart";
|
||||
import "package:smol_mail/smol/errors.dart";
|
||||
|
||||
/// No server push in v1 (SPEC.md §13): new mail arrives when the user taps
|
||||
/// fetch, which pulls everything and acknowledges what verifies.
|
||||
@RoutePage()
|
||||
class InboxScreen extends ConsumerStatefulWidget {
|
||||
class InboxScreen extends ConsumerWidget {
|
||||
const InboxScreen({super.key});
|
||||
|
||||
@override
|
||||
ConsumerState<InboxScreen> createState() => _InboxScreenState();
|
||||
}
|
||||
|
||||
class _InboxScreenState extends ConsumerState<InboxScreen> {
|
||||
Timer? _timer;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_timer = Timer.periodic(
|
||||
const Duration(seconds: 30),
|
||||
(timer) => ref.refresh(messagesProvider),
|
||||
);
|
||||
Future<void> _fetch(BuildContext context, WidgetRef ref) async {
|
||||
final client = ref.read(clientProvider);
|
||||
try {
|
||||
final summary = await client.fetch();
|
||||
ref.read(revisionProvider.notifier).bump();
|
||||
if (context.mounted) {
|
||||
final tail = summary.rejected.isEmpty
|
||||
? ""
|
||||
: "\n${summary.rejected.length} left on the server";
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(content: Text("${summary.stored} new$tail")),
|
||||
);
|
||||
}
|
||||
} on SmolError catch (err) {
|
||||
if (context.mounted) {
|
||||
showErrorSnackBar(context, err.message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_timer?.cancel();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final messages = ref.watch(messagesProvider);
|
||||
final folder = ref.watch(folderProvider);
|
||||
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text("Inbox"),
|
||||
title: Text(folder == "inbox" ? "Inbox" : "Sent"),
|
||||
actions: [
|
||||
if (folder == "inbox")
|
||||
IconButton(
|
||||
tooltip: "Fetch",
|
||||
onPressed: () => _fetch(context, ref),
|
||||
icon: const Icon(Icons.cloud_download),
|
||||
),
|
||||
],
|
||||
),
|
||||
drawer: const AppDrawer(),
|
||||
body: messages.when(
|
||||
data: (data) => MessageList(
|
||||
messages: data,
|
||||
onRefresh: () => ref.refresh(messagesProvider.future),
|
||||
),
|
||||
error: (err, _) => const ImageBanner(
|
||||
imgSrc: "assets/images/error.png",
|
||||
text: "Something went wrong!",
|
||||
),
|
||||
loading: () => const MessageShimmer(),
|
||||
skipLoadingOnRefresh: true,
|
||||
floatingActionButton: FloatingActionButton(
|
||||
onPressed: () => AutoRouter.of(context).push(ComposeRoute()),
|
||||
child: const Icon(Icons.edit),
|
||||
),
|
||||
body: messages.isEmpty
|
||||
? RefreshIndicator(
|
||||
onRefresh: () => folder == "inbox"
|
||||
? _fetch(context, ref)
|
||||
: Future.value(),
|
||||
child: ListView(
|
||||
children: const [
|
||||
ImageBanner(
|
||||
imgSrc: "assets/images/empty.png",
|
||||
text: "Nothing here yet!",
|
||||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
: MessageList(
|
||||
onRefresh: () => folder == "inbox"
|
||||
? _fetch(context, ref)
|
||||
: Future.value(),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue