notification_dialog.dart 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. import 'package:appflowy/generated/locale_keys.g.dart';
  2. import 'package:appflowy/startup/startup.dart';
  3. import 'package:appflowy/user/application/reminder/reminder_bloc.dart';
  4. import 'package:appflowy/workspace/presentation/notifications/notification_item.dart';
  5. import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart';
  6. import 'package:appflowy_backend/protobuf/flowy-user/reminder.pb.dart';
  7. import 'package:appflowy_popover/appflowy_popover.dart';
  8. import 'package:collection/collection.dart';
  9. import 'package:easy_localization/easy_localization.dart';
  10. import 'package:flowy_infra_ui/style_widget/text.dart';
  11. import 'package:flowy_infra_ui/widget/spacing.dart';
  12. import 'package:flutter/material.dart';
  13. import 'package:flutter_bloc/flutter_bloc.dart';
  14. extension _ReminderReady on ReminderPB {
  15. DateTime get scheduledDate =>
  16. DateTime.fromMillisecondsSinceEpoch(scheduledAt.toInt() * 1000);
  17. bool isBefore(DateTime date) => scheduledDate.isBefore(date);
  18. }
  19. class NotificationDialog extends StatelessWidget {
  20. const NotificationDialog({
  21. super.key,
  22. required this.views,
  23. required this.mutex,
  24. });
  25. final List<ViewPB> views;
  26. final PopoverMutex mutex;
  27. @override
  28. Widget build(BuildContext context) {
  29. final reminderBloc = getIt<ReminderBloc>();
  30. return BlocProvider<ReminderBloc>.value(
  31. value: reminderBloc,
  32. child: BlocBuilder<ReminderBloc, ReminderState>(
  33. builder: (context, state) {
  34. final shownReminders = state.reminders
  35. .where((reminder) => reminder.isBefore(DateTime.now()))
  36. .sorted((a, b) => b.scheduledAt.compareTo(a.scheduledAt));
  37. return SingleChildScrollView(
  38. child: Column(
  39. crossAxisAlignment: CrossAxisAlignment.start,
  40. children: [
  41. Row(
  42. children: [
  43. Expanded(
  44. child: DecoratedBox(
  45. decoration: BoxDecoration(
  46. border: Border(
  47. bottom: BorderSide(
  48. color: Theme.of(context).dividerColor,
  49. ),
  50. ),
  51. ),
  52. child: Padding(
  53. padding: const EdgeInsets.symmetric(
  54. vertical: 4,
  55. horizontal: 10,
  56. ),
  57. child: FlowyText.semibold(
  58. LocaleKeys.notificationHub_title.tr(),
  59. fontSize: 16,
  60. ),
  61. ),
  62. ),
  63. ),
  64. ],
  65. ),
  66. const VSpace(4),
  67. if (shownReminders.isEmpty)
  68. Padding(
  69. padding: const EdgeInsets.symmetric(vertical: 12),
  70. child: Center(
  71. child: FlowyText.regular(
  72. LocaleKeys.notificationHub_empty.tr(),
  73. ),
  74. ),
  75. )
  76. else
  77. ...shownReminders.map((reminder) {
  78. return NotificationItem(
  79. reminderId: reminder.id,
  80. key: ValueKey(reminder.id),
  81. title: reminder.title,
  82. scheduled: reminder.scheduledAt,
  83. body: reminder.message,
  84. isRead: reminder.isRead,
  85. onReadChanged: (isRead) => reminderBloc.add(
  86. ReminderEvent.update(
  87. ReminderUpdate(id: reminder.id, isRead: isRead),
  88. ),
  89. ),
  90. onDelete: () => reminderBloc
  91. .add(ReminderEvent.remove(reminderId: reminder.id)),
  92. onAction: () {
  93. final view = views.firstWhereOrNull(
  94. (view) => view.id == reminder.objectId,
  95. );
  96. if (view == null) {
  97. return;
  98. }
  99. reminderBloc.add(
  100. ReminderEvent.pressReminder(reminderId: reminder.id),
  101. );
  102. mutex.close();
  103. },
  104. );
  105. }),
  106. ],
  107. ),
  108. );
  109. },
  110. ),
  111. );
  112. }
  113. }