From b9fd3701cd57e272cdf40c31bac84bff1b3dfd9a Mon Sep 17 00:00:00 2001 From: "Lucas.Xu" Date: Thu, 1 Aug 2024 20:21:25 +0800 Subject: [PATCH] feat: improve reminder color in notification page (#5855) * feat: improve reminder color * fix: notification page doesn't update when switching workspace --- .../presentation/home/mobile_home_page.dart | 12 +++++-- .../mobile_notifications_screen.dart | 31 ++++++++++------ .../notifications/widgets/shared.dart | 29 +++++++++------ .../presentation/editor_configuration.dart | 5 +-- .../document/presentation/editor_page.dart | 4 +++ .../callout/callout_block_component.dart | 2 +- .../mention/mention_date_block.dart | 12 ++++--- .../document/presentation/editor_style.dart | 22 +++++++++--- .../application/reminder/reminder_bloc.dart | 8 ++++- .../reminder/reminder_extension.dart | 35 +++++++++++++++++++ 10 files changed, 121 insertions(+), 39 deletions(-) diff --git a/frontend/appflowy_flutter/lib/mobile/presentation/home/mobile_home_page.dart b/frontend/appflowy_flutter/lib/mobile/presentation/home/mobile_home_page.dart index 1dc72f370d..be5eab3fbd 100644 --- a/frontend/appflowy_flutter/lib/mobile/presentation/home/mobile_home_page.dart +++ b/frontend/appflowy_flutter/lib/mobile/presentation/home/mobile_home_page.dart @@ -1,7 +1,5 @@ import 'dart:io'; -import 'package:flutter/material.dart'; - import 'package:appflowy/mobile/presentation/home/mobile_home_page_header.dart'; import 'package:appflowy/mobile/presentation/home/tab/mobile_space_tab.dart'; import 'package:appflowy/mobile/presentation/home/tab/space_order_bloc.dart'; @@ -18,6 +16,8 @@ import 'package:appflowy_backend/dispatch/dispatch.dart'; import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-folder/workspace.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-user/protobuf.dart'; +import 'package:appflowy_editor/appflowy_editor.dart'; +import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:provider/provider.dart'; @@ -74,6 +74,9 @@ class MobileHomeScreen extends StatelessWidget { } } +final PropertyValueNotifier mCurrentWorkspace = + PropertyValueNotifier(null); + class MobileHomePage extends StatefulWidget { const MobileHomePage({ super.key, @@ -122,7 +125,10 @@ class _MobileHomePageState extends State { buildWhen: (previous, current) => previous.currentWorkspace?.workspaceId != current.currentWorkspace?.workspaceId, - listener: (context, state) => getIt().reset(), + listener: (context, state) { + getIt().reset(); + mCurrentWorkspace.value = state.currentWorkspace; + }, builder: (context, state) { if (state.currentWorkspace == null) { return const SizedBox.shrink(); diff --git a/frontend/appflowy_flutter/lib/mobile/presentation/notifications/mobile_notifications_screen.dart b/frontend/appflowy_flutter/lib/mobile/presentation/notifications/mobile_notifications_screen.dart index 2910740075..b1219d8e98 100644 --- a/frontend/appflowy_flutter/lib/mobile/presentation/notifications/mobile_notifications_screen.dart +++ b/frontend/appflowy_flutter/lib/mobile/presentation/notifications/mobile_notifications_screen.dart @@ -1,4 +1,3 @@ -import 'package:appflowy/mobile/application/user_profile/user_profile_bloc.dart'; import 'package:appflowy/mobile/presentation/notifications/mobile_notifications_multiple_select_page.dart'; import 'package:appflowy/mobile/presentation/notifications/widgets/widgets.dart'; import 'package:appflowy/mobile/presentation/presentation.dart'; @@ -28,20 +27,26 @@ class _MobileNotificationsScreenV2State @override bool get wantKeepAlive => true; + @override + void initState() { + super.initState(); + + mCurrentWorkspace.addListener(_onRefresh); + } + + @override + void dispose() { + mCurrentWorkspace.removeListener(_onRefresh); + + super.dispose(); + } + @override Widget build(BuildContext context) { super.build(context); - return MultiBlocProvider( - providers: [ - BlocProvider( - create: (context) => UserProfileBloc() - ..add( - const UserProfileEvent.started(), - ), - ), - BlocProvider.value(value: getIt()), - ], + return BlocProvider.value( + value: getIt(), child: ValueListenableBuilder( valueListenable: bottomNavigationBarType, builder: (_, value, __) { @@ -55,6 +60,10 @@ class _MobileNotificationsScreenV2State ), ); } + + void _onRefresh() { + getIt().add(const ReminderEvent.refresh()); + } } class MobileNotificationsTab extends StatefulWidget { diff --git a/frontend/appflowy_flutter/lib/mobile/presentation/notifications/widgets/shared.dart b/frontend/appflowy_flutter/lib/mobile/presentation/notifications/widgets/shared.dart index 27abc91241..10b5a03222 100644 --- a/frontend/appflowy_flutter/lib/mobile/presentation/notifications/widgets/shared.dart +++ b/frontend/appflowy_flutter/lib/mobile/presentation/notifications/widgets/shared.dart @@ -5,6 +5,7 @@ import 'package:appflowy/mobile/application/page_style/document_page_style_bloc. import 'package:appflowy/mobile/presentation/notifications/widgets/color.dart'; import 'package:appflowy/plugins/document/presentation/editor_configuration.dart'; import 'package:appflowy/plugins/document/presentation/editor_style.dart'; +import 'package:appflowy/user/application/reminder/reminder_extension.dart'; import 'package:appflowy_backend/protobuf/flowy-user/protobuf.dart'; import 'package:appflowy_editor/appflowy_editor.dart'; import 'package:easy_localization/easy_localization.dart'; @@ -107,7 +108,10 @@ class NotificationContent extends StatelessWidget { child: IntrinsicHeight( child: BlocProvider( create: (context) => DocumentPageStyleBloc(view: state.view!), - child: NotificationDocumentContent(nodes: state.nodes), + child: NotificationDocumentContent( + reminder: reminder, + nodes: state.nodes, + ), ), ), ), @@ -176,9 +180,11 @@ class NotificationEllipse extends StatelessWidget { class NotificationDocumentContent extends StatelessWidget { const NotificationDocumentContent({ super.key, + required this.reminder, required this.nodes, }); + final ReminderPB reminder; final List nodes; @override @@ -222,15 +228,18 @@ class NotificationDocumentContent extends StatelessWidget { ); return IgnorePointer( - child: AppFlowyEditor( - editorState: editorState, - editorStyle: editorStyle, - disableSelectionService: true, - disableKeyboardService: true, - disableScrollService: true, - editable: false, - shrinkWrap: true, - blockComponentBuilders: blockBuilders, + child: Opacity( + opacity: reminder.type == ReminderType.past ? 0.3 : 1, + child: AppFlowyEditor( + editorState: editorState, + editorStyle: editorStyle, + disableSelectionService: true, + disableKeyboardService: true, + disableScrollService: true, + editable: false, + shrinkWrap: true, + blockComponentBuilders: blockBuilders, + ), ), ); } diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_configuration.dart b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_configuration.dart index 34f61f15ed..8d8312073a 100644 --- a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_configuration.dart +++ b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_configuration.dart @@ -189,10 +189,7 @@ Map getEditorBuilderMap({ ), ), CalloutBlockKeys.type: CalloutBlockComponentBuilder( - configuration: configuration.copyWith( - textStyle: (_) => styleCustomizer.calloutBlockStyleBuilder(), - placeholderTextStyle: (_) => styleCustomizer.calloutBlockStyleBuilder(), - ), + configuration: configuration.copyWith(), defaultColor: calloutBGColor, ), DividerBlockKeys.type: DividerBlockComponentBuilder( diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_page.dart b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_page.dart index ddd6dcf2bd..c7f8643b68 100644 --- a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_page.dart +++ b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_page.dart @@ -516,6 +516,10 @@ Color? buildEditorCustomizedColor( Node node, String colorString, ) { + if (!context.mounted) { + return null; + } + // the color string is from FlowyTint. final tintColor = FlowyTint.values.firstWhereOrNull( (e) => e.id == colorString, diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/callout/callout_block_component.dart b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/callout/callout_block_component.dart index 0ecc162c5c..3b1dc69920 100644 --- a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/callout/callout_block_component.dart +++ b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/callout/callout_block_component.dart @@ -186,7 +186,7 @@ class _CalloutBlockComponentWidgetState // the emoji picker button for the note Padding( padding: const EdgeInsets.only( - top: 8.0, + top: 6.0, left: 4.0, right: 4.0, ), diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/mention/mention_date_block.dart b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/mention/mention_date_block.dart index b40e5045fa..a4a4f670f2 100644 --- a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/mention/mention_date_block.dart +++ b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/mention/mention_date_block.dart @@ -163,11 +163,14 @@ class _MentionDateBlockState extends State { _updateReminder(reminderOption, reminder), ); - final color = reminder?.isAck == true - ? Theme.of(context).isLightMode + Color? color; + if (reminder != null) { + if (reminder.type == ReminderType.today) { + color = Theme.of(context).isLightMode ? const Color(0xFFFE0299) - : Theme.of(context).colorScheme.error - : null; + : Theme.of(context).colorScheme.error; + } + } final textStyle = widget.textStyle?.copyWith( color: color, leadingDistribution: TextLeadingDistribution.even, @@ -364,6 +367,7 @@ class _MentionDateBlockState extends State { ReminderUpdate( id: widget.reminderId!, scheduledAt: reminderOption.fromDate(parsedDate!), + date: parsedDate!, ), ), ); diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_style.dart b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_style.dart index c691e7d821..529c2a549c 100644 --- a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_style.dart +++ b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_style.dart @@ -185,11 +185,23 @@ class EditorStyleCustomizer { } TextStyle calloutBlockStyleBuilder() { - final fontSize = context.read().state.fontSize; - return baseTextStyle(null).copyWith( - fontSize: fontSize, - height: 1.5, - ); + if (PlatformExtension.isMobile) { + final afThemeExtension = AFThemeExtension.of(context); + final pageStyle = context.read().state; + final fontSize = pageStyle.fontLayout.fontSize; + final fontFamily = pageStyle.fontFamily ?? defaultFontFamily; + final baseTextStyle = this.baseTextStyle(fontFamily); + return baseTextStyle.copyWith( + fontSize: fontSize, + color: afThemeExtension.onBackground, + ); + } else { + final fontSize = context.read().state.fontSize; + return baseTextStyle(null).copyWith( + fontSize: fontSize, + height: 1.5, + ); + } } TextStyle outlineBlockPlaceholderStyleBuilder() { diff --git a/frontend/appflowy_flutter/lib/user/application/reminder/reminder_bloc.dart b/frontend/appflowy_flutter/lib/user/application/reminder/reminder_bloc.dart index 6ea7a7aa7e..07024b2668 100644 --- a/frontend/appflowy_flutter/lib/user/application/reminder/reminder_bloc.dart +++ b/frontend/appflowy_flutter/lib/user/application/reminder/reminder_bloc.dart @@ -95,7 +95,7 @@ class ReminderBloc extends Bloc { final newReminder = updateObject.merge(a: reminder); final failureOrUnit = await _reminderService.updateReminder( - reminder: updateObject.merge(a: reminder), + reminder: newReminder, ); failureOrUnit.fold( @@ -402,6 +402,7 @@ class ReminderUpdate { this.scheduledAt, this.includeTime, this.isArchived, + this.date, }); final String id; @@ -410,6 +411,7 @@ class ReminderUpdate { final DateTime? scheduledAt; final bool? includeTime; final bool? isArchived; + final DateTime? date; ReminderPB merge({required ReminderPB a}) { final isAcknowledged = isAck == null && scheduledAt != null @@ -425,6 +427,10 @@ class ReminderUpdate { meta[ReminderMetaKeys.isArchived] = isArchived.toString(); } + if (date != a.date && date != null) { + meta[ReminderMetaKeys.date] = date!.millisecondsSinceEpoch.toString(); + } + return ReminderPB( id: a.id, objectId: a.objectId, diff --git a/frontend/appflowy_flutter/lib/user/application/reminder/reminder_extension.dart b/frontend/appflowy_flutter/lib/user/application/reminder/reminder_extension.dart index 3d23580320..1b5aeaeb43 100644 --- a/frontend/appflowy_flutter/lib/user/application/reminder/reminder_extension.dart +++ b/frontend/appflowy_flutter/lib/user/application/reminder/reminder_extension.dart @@ -6,6 +6,13 @@ class ReminderMetaKeys { static String rowId = "row_id"; static String createdAt = "created_at"; static String isArchived = "is_archived"; + static String date = "date"; +} + +enum ReminderType { + past, + today, + other, } extension ReminderExtension on ReminderPB { @@ -28,4 +35,32 @@ extension ReminderExtension on ReminderPB { final t = meta[ReminderMetaKeys.isArchived]; return t != null ? t == true.toString() : false; } + + DateTime? get date { + final t = meta[ReminderMetaKeys.date]; + return t != null ? DateTime.fromMillisecondsSinceEpoch(int.parse(t)) : null; + } + + ReminderType get type { + final date = this.date?.millisecondsSinceEpoch; + + if (date == null) { + return ReminderType.other; + } + + final now = DateTime.now().millisecondsSinceEpoch; + + if (date < now) { + return ReminderType.past; + } + + final difference = date - now; + const oneDayInMilliseconds = 24 * 60 * 60 * 1000; + + if (difference < oneDayInMilliseconds) { + return ReminderType.today; + } + + return ReminderType.other; + } }