feat: improve reminder color in notification page (#5855)

* feat: improve reminder color

* fix: notification page doesn't update when switching workspace
This commit is contained in:
Lucas.Xu 2024-08-01 20:21:25 +08:00 committed by GitHub
parent 9fbba5fb60
commit b9fd3701cd
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 121 additions and 39 deletions

View File

@ -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<UserWorkspacePB?> mCurrentWorkspace =
PropertyValueNotifier<UserWorkspacePB?>(null);
class MobileHomePage extends StatefulWidget {
const MobileHomePage({
super.key,
@ -122,7 +125,10 @@ class _MobileHomePageState extends State<MobileHomePage> {
buildWhen: (previous, current) =>
previous.currentWorkspace?.workspaceId !=
current.currentWorkspace?.workspaceId,
listener: (context, state) => getIt<CachedRecentService>().reset(),
listener: (context, state) {
getIt<CachedRecentService>().reset();
mCurrentWorkspace.value = state.currentWorkspace;
},
builder: (context, state) {
if (state.currentWorkspace == null) {
return const SizedBox.shrink();

View File

@ -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<UserProfileBloc>(
create: (context) => UserProfileBloc()
..add(
const UserProfileEvent.started(),
),
),
BlocProvider<ReminderBloc>.value(value: getIt<ReminderBloc>()),
],
return BlocProvider<ReminderBloc>.value(
value: getIt<ReminderBloc>(),
child: ValueListenableBuilder(
valueListenable: bottomNavigationBarType,
builder: (_, value, __) {
@ -55,6 +60,10 @@ class _MobileNotificationsScreenV2State
),
);
}
void _onRefresh() {
getIt<ReminderBloc>().add(const ReminderEvent.refresh());
}
}
class MobileNotificationsTab extends StatefulWidget {

View File

@ -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<Node> nodes;
@override
@ -222,6 +228,8 @@ class NotificationDocumentContent extends StatelessWidget {
);
return IgnorePointer(
child: Opacity(
opacity: reminder.type == ReminderType.past ? 0.3 : 1,
child: AppFlowyEditor(
editorState: editorState,
editorStyle: editorStyle,
@ -232,6 +240,7 @@ class NotificationDocumentContent extends StatelessWidget {
shrinkWrap: true,
blockComponentBuilders: blockBuilders,
),
),
);
}
}

View File

@ -189,10 +189,7 @@ Map<String, BlockComponentBuilder> getEditorBuilderMap({
),
),
CalloutBlockKeys.type: CalloutBlockComponentBuilder(
configuration: configuration.copyWith(
textStyle: (_) => styleCustomizer.calloutBlockStyleBuilder(),
placeholderTextStyle: (_) => styleCustomizer.calloutBlockStyleBuilder(),
),
configuration: configuration.copyWith(),
defaultColor: calloutBGColor,
),
DividerBlockKeys.type: DividerBlockComponentBuilder(

View File

@ -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,

View File

@ -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,
),

View File

@ -163,11 +163,14 @@ class _MentionDateBlockState extends State<MentionDateBlock> {
_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<MentionDateBlock> {
ReminderUpdate(
id: widget.reminderId!,
scheduledAt: reminderOption.fromDate(parsedDate!),
date: parsedDate!,
),
),
);

View File

@ -185,12 +185,24 @@ class EditorStyleCustomizer {
}
TextStyle calloutBlockStyleBuilder() {
if (PlatformExtension.isMobile) {
final afThemeExtension = AFThemeExtension.of(context);
final pageStyle = context.read<DocumentPageStyleBloc>().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<DocumentAppearanceCubit>().state.fontSize;
return baseTextStyle(null).copyWith(
fontSize: fontSize,
height: 1.5,
);
}
}
TextStyle outlineBlockPlaceholderStyleBuilder() {
final fontSize = context.read<DocumentAppearanceCubit>().state.fontSize;

View File

@ -95,7 +95,7 @@ class ReminderBloc extends Bloc<ReminderEvent, ReminderState> {
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,

View File

@ -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;
}
}