mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
chore: add more logs in reminder bloc (#5860)
* chore: add more logs in reminder bloc
* Revert "chore: add more logs in reminder bloc"
This reverts commit 9d0bb8fb29
.
* chore: add more logs in reminder bloc
* fix: unable to view reminders on Desktop
* fix: force refresh reminders
* chore: fix flutter analyze
* feat: support database reminder on Mobile
* chore: remove referenced database padding
This commit is contained in:
@ -5,6 +5,7 @@ import 'package:appflowy/user/application/reminder/reminder_extension.dart';
|
|||||||
import 'package:appflowy/workspace/application/settings/date_time/date_format_ext.dart';
|
import 'package:appflowy/workspace/application/settings/date_time/date_format_ext.dart';
|
||||||
import 'package:appflowy/workspace/application/settings/date_time/time_format_ext.dart';
|
import 'package:appflowy/workspace/application/settings/date_time/time_format_ext.dart';
|
||||||
import 'package:appflowy/workspace/application/view/prelude.dart';
|
import 'package:appflowy/workspace/application/view/prelude.dart';
|
||||||
|
import 'package:appflowy/workspace/application/view/view_ext.dart';
|
||||||
import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
|
import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
|
||||||
import 'package:appflowy_backend/protobuf/flowy-user/protobuf.dart';
|
import 'package:appflowy_backend/protobuf/flowy-user/protobuf.dart';
|
||||||
import 'package:appflowy_editor/appflowy_editor.dart';
|
import 'package:appflowy_editor/appflowy_editor.dart';
|
||||||
@ -23,16 +24,20 @@ class NotificationReminderBloc
|
|||||||
await event.when(
|
await event.when(
|
||||||
initial: (reminder, dateFormat, timeFormat) async {
|
initial: (reminder, dateFormat, timeFormat) async {
|
||||||
this.reminder = reminder;
|
this.reminder = reminder;
|
||||||
|
this.dateFormat = dateFormat;
|
||||||
|
this.timeFormat = timeFormat;
|
||||||
|
|
||||||
|
add(const NotificationReminderEvent.reset());
|
||||||
|
},
|
||||||
|
reset: () async {
|
||||||
final createdAt = await _getCreatedAt(
|
final createdAt = await _getCreatedAt(
|
||||||
reminder,
|
reminder,
|
||||||
dateFormat,
|
dateFormat,
|
||||||
timeFormat,
|
timeFormat,
|
||||||
);
|
);
|
||||||
final view = await _getView(reminder);
|
final view = await _getView(reminder);
|
||||||
final node = await _getContent(reminder);
|
|
||||||
|
|
||||||
if (view == null || node == null) {
|
if (view == null) {
|
||||||
emit(
|
emit(
|
||||||
NotificationReminderState(
|
NotificationReminderState(
|
||||||
createdAt: createdAt,
|
createdAt: createdAt,
|
||||||
@ -41,7 +46,13 @@ class NotificationReminderBloc
|
|||||||
status: NotificationReminderStatus.error,
|
status: NotificationReminderStatus.error,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
} else {
|
}
|
||||||
|
|
||||||
|
final layout = view!.layout;
|
||||||
|
|
||||||
|
if (layout.isDocumentView) {
|
||||||
|
final node = await _getContent(reminder);
|
||||||
|
if (node != null) {
|
||||||
emit(
|
emit(
|
||||||
NotificationReminderState(
|
NotificationReminderState(
|
||||||
createdAt: createdAt,
|
createdAt: createdAt,
|
||||||
@ -53,13 +64,25 @@ class NotificationReminderBloc
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
} else if (layout.isDatabaseView) {
|
||||||
|
emit(
|
||||||
|
NotificationReminderState(
|
||||||
|
createdAt: createdAt,
|
||||||
|
pageTitle: view.name,
|
||||||
|
view: view,
|
||||||
|
reminderContent: reminder.message,
|
||||||
|
status: NotificationReminderStatus.loaded,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
reset: () {},
|
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
late final ReminderPB reminder;
|
late final ReminderPB reminder;
|
||||||
|
late final UserDateFormatPB dateFormat;
|
||||||
|
late final UserTimeFormatPB timeFormat;
|
||||||
|
|
||||||
Future<String> _getCreatedAt(
|
Future<String> _getCreatedAt(
|
||||||
ReminderPB reminder,
|
ReminderPB reminder,
|
||||||
|
@ -46,10 +46,18 @@ class _MobileViewPageState extends State<MobileViewPage> {
|
|||||||
// control the app bar opacity when in immersive mode
|
// control the app bar opacity when in immersive mode
|
||||||
final ValueNotifier<double> _appBarOpacity = ValueNotifier(1.0);
|
final ValueNotifier<double> _appBarOpacity = ValueNotifier(1.0);
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
|
||||||
|
getIt<ReminderBloc>().add(const ReminderEvent.started());
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
_appBarOpacity.dispose();
|
_appBarOpacity.dispose();
|
||||||
_scrollNotificationObserver = null;
|
_scrollNotificationObserver = null;
|
||||||
|
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -78,8 +86,7 @@ class _MobileViewPageState extends State<MobileViewPage> {
|
|||||||
ViewBloc(view: view)..add(const ViewEvent.initial()),
|
ViewBloc(view: view)..add(const ViewEvent.initial()),
|
||||||
),
|
),
|
||||||
BlocProvider.value(
|
BlocProvider.value(
|
||||||
value: getIt<ReminderBloc>()
|
value: getIt<ReminderBloc>(),
|
||||||
..add(const ReminderEvent.started()),
|
|
||||||
),
|
),
|
||||||
if (view.layout.isDocumentView)
|
if (view.layout.isDocumentView)
|
||||||
BlocProvider(
|
BlocProvider(
|
||||||
|
@ -99,6 +99,7 @@ class _MobileHomePageState extends State<MobileHomePage> {
|
|||||||
super.initState();
|
super.initState();
|
||||||
|
|
||||||
getIt<MenuSharedState>().addLatestViewListener(_onLatestViewChange);
|
getIt<MenuSharedState>().addLatestViewListener(_onLatestViewChange);
|
||||||
|
getIt<ReminderBloc>().add(const ReminderEvent.started());
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -6,6 +6,8 @@ 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_configuration.dart';
|
||||||
import 'package:appflowy/plugins/document/presentation/editor_style.dart';
|
import 'package:appflowy/plugins/document/presentation/editor_style.dart';
|
||||||
import 'package:appflowy/user/application/reminder/reminder_extension.dart';
|
import 'package:appflowy/user/application/reminder/reminder_extension.dart';
|
||||||
|
import 'package:appflowy/workspace/application/view/view_ext.dart';
|
||||||
|
import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
|
||||||
import 'package:appflowy_backend/protobuf/flowy-user/protobuf.dart';
|
import 'package:appflowy_backend/protobuf/flowy-user/protobuf.dart';
|
||||||
import 'package:appflowy_editor/appflowy_editor.dart';
|
import 'package:appflowy_editor/appflowy_editor.dart';
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
@ -76,7 +78,7 @@ class UnreadRedDot extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class NotificationContent extends StatelessWidget {
|
class NotificationContent extends StatefulWidget {
|
||||||
const NotificationContent({
|
const NotificationContent({
|
||||||
super.key,
|
super.key,
|
||||||
required this.reminder,
|
required this.reminder,
|
||||||
@ -84,10 +86,29 @@ class NotificationContent extends StatelessWidget {
|
|||||||
|
|
||||||
final ReminderPB reminder;
|
final ReminderPB reminder;
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<NotificationContent> createState() => _NotificationContentState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _NotificationContentState extends State<NotificationContent> {
|
||||||
|
@override
|
||||||
|
void didUpdateWidget(covariant NotificationContent oldWidget) {
|
||||||
|
super.didUpdateWidget(oldWidget);
|
||||||
|
|
||||||
|
context.read<NotificationReminderBloc>().add(
|
||||||
|
const NotificationReminderEvent.reset(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return BlocBuilder<NotificationReminderBloc, NotificationReminderState>(
|
return BlocBuilder<NotificationReminderBloc, NotificationReminderState>(
|
||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
|
final view = state.view;
|
||||||
|
if (view == null) {
|
||||||
|
return const SizedBox.shrink();
|
||||||
|
}
|
||||||
|
|
||||||
return Column(
|
return Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
@ -105,15 +126,7 @@ class NotificationContent extends StatelessWidget {
|
|||||||
// content
|
// content
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.only(right: 16.0),
|
padding: const EdgeInsets.only(right: 16.0),
|
||||||
child: IntrinsicHeight(
|
child: _buildContent(view, nodes: state.nodes),
|
||||||
child: BlocProvider(
|
|
||||||
create: (context) => DocumentPageStyleBloc(view: state.view!),
|
|
||||||
child: NotificationDocumentContent(
|
|
||||||
reminder: reminder,
|
|
||||||
nodes: state.nodes,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
@ -121,6 +134,33 @@ class NotificationContent extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Widget _buildContent(ViewPB view, {List<Node>? nodes}) {
|
||||||
|
if (view.layout.isDocumentView && nodes != null) {
|
||||||
|
return IntrinsicHeight(
|
||||||
|
child: BlocProvider(
|
||||||
|
create: (context) => DocumentPageStyleBloc(view: view),
|
||||||
|
child: NotificationDocumentContent(
|
||||||
|
reminder: widget.reminder,
|
||||||
|
nodes: nodes,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
} else if (view.layout.isDatabaseView) {
|
||||||
|
final opacity = widget.reminder.type == ReminderType.past ? 0.3 : 1.0;
|
||||||
|
return Opacity(
|
||||||
|
opacity: opacity,
|
||||||
|
child: FlowyText(
|
||||||
|
widget.reminder.message,
|
||||||
|
fontSize: 14,
|
||||||
|
figmaLineHeight: 22,
|
||||||
|
color: context.notificationItemTextColor,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return const SizedBox.shrink();
|
||||||
|
}
|
||||||
|
|
||||||
Widget _buildHeader() {
|
Widget _buildHeader() {
|
||||||
return FlowyText.semibold(
|
return FlowyText.semibold(
|
||||||
LocaleKeys.settings_notifications_titles_reminder.tr(),
|
LocaleKeys.settings_notifications_titles_reminder.tr(),
|
||||||
|
@ -8,6 +8,7 @@ import 'package:appflowy/plugins/database/application/row/row_cache.dart';
|
|||||||
import 'package:appflowy/plugins/database/application/row/row_controller.dart';
|
import 'package:appflowy/plugins/database/application/row/row_controller.dart';
|
||||||
import 'package:appflowy/plugins/database/board/application/board_bloc.dart';
|
import 'package:appflowy/plugins/database/board/application/board_bloc.dart';
|
||||||
import 'package:appflowy/plugins/database/grid/presentation/layout/sizes.dart';
|
import 'package:appflowy/plugins/database/grid/presentation/layout/sizes.dart';
|
||||||
|
import 'package:appflowy/plugins/database/tab_bar/tab_bar_view.dart';
|
||||||
import 'package:appflowy/plugins/database/widgets/cell/card_cell_builder.dart';
|
import 'package:appflowy/plugins/database/widgets/cell/card_cell_builder.dart';
|
||||||
import 'package:appflowy/plugins/database/widgets/cell/card_cell_skeleton/text_card_cell.dart';
|
import 'package:appflowy/plugins/database/widgets/cell/card_cell_skeleton/text_card_cell.dart';
|
||||||
import 'package:appflowy/plugins/database/widgets/row/row_detail.dart';
|
import 'package:appflowy/plugins/database/widgets/row/row_detail.dart';
|
||||||
@ -64,7 +65,10 @@ class HiddenGroupsColumn extends StatelessWidget {
|
|||||||
height: 50,
|
height: 50,
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: EdgeInsets.only(
|
padding: EdgeInsets.only(
|
||||||
left: 80 + margin.left,
|
left: margin.left +
|
||||||
|
context
|
||||||
|
.read<DatabasePluginWidgetBuilderSize>()
|
||||||
|
.horizontalPadding,
|
||||||
right: margin.right + 4,
|
right: margin.right + 4,
|
||||||
),
|
),
|
||||||
child: Row(
|
child: Row(
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
import 'package:flutter/material.dart';
|
|
||||||
|
|
||||||
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
||||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||||
import 'package:appflowy/mobile/presentation/bottom_sheet/bottom_sheet.dart';
|
import 'package:appflowy/mobile/presentation/bottom_sheet/bottom_sheet.dart';
|
||||||
@ -20,12 +18,12 @@ import 'package:easy_localization/easy_localization.dart';
|
|||||||
import 'package:flowy_infra/size.dart';
|
import 'package:flowy_infra/size.dart';
|
||||||
import 'package:flowy_infra/theme_extension.dart';
|
import 'package:flowy_infra/theme_extension.dart';
|
||||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:go_router/go_router.dart';
|
import 'package:go_router/go_router.dart';
|
||||||
|
|
||||||
import '../../application/row/row_controller.dart';
|
import '../../application/row/row_controller.dart';
|
||||||
import '../../widgets/row/row_detail.dart';
|
import '../../widgets/row/row_detail.dart';
|
||||||
|
|
||||||
import 'calendar_day.dart';
|
import 'calendar_day.dart';
|
||||||
import 'layout/sizes.dart';
|
import 'layout/sizes.dart';
|
||||||
import 'toolbar/calendar_setting_bar.dart';
|
import 'toolbar/calendar_setting_bar.dart';
|
||||||
@ -185,11 +183,17 @@ class _CalendarPageState extends State<CalendarPage> {
|
|||||||
return LayoutBuilder(
|
return LayoutBuilder(
|
||||||
// must specify MonthView width for useAvailableVerticalSpace to work properly
|
// must specify MonthView width for useAvailableVerticalSpace to work properly
|
||||||
builder: (context, constraints) {
|
builder: (context, constraints) {
|
||||||
return Padding(
|
EdgeInsets padding = PlatformExtension.isMobile
|
||||||
padding: PlatformExtension.isMobile
|
|
||||||
? CalendarSize.contentInsetsMobile
|
? CalendarSize.contentInsetsMobile
|
||||||
: CalendarSize.contentInsets +
|
: CalendarSize.contentInsets +
|
||||||
const EdgeInsets.symmetric(horizontal: 40),
|
const EdgeInsets.symmetric(horizontal: 40);
|
||||||
|
final double horizontalPadding =
|
||||||
|
context.read<DatabasePluginWidgetBuilderSize>().horizontalPadding;
|
||||||
|
if (horizontalPadding == 0) {
|
||||||
|
padding = padding.copyWith(left: 0, right: 0);
|
||||||
|
}
|
||||||
|
return Padding(
|
||||||
|
padding: padding,
|
||||||
child: ScrollConfiguration(
|
child: ScrollConfiguration(
|
||||||
behavior:
|
behavior:
|
||||||
ScrollConfiguration.of(context).copyWith(scrollbars: false),
|
ScrollConfiguration.of(context).copyWith(scrollbars: false),
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
import 'package:flutter/material.dart';
|
|
||||||
|
|
||||||
import 'package:appflowy/plugins/database/grid/application/calculations/calculations_bloc.dart';
|
import 'package:appflowy/plugins/database/grid/application/calculations/calculations_bloc.dart';
|
||||||
import 'package:appflowy/plugins/database/grid/application/grid_bloc.dart';
|
import 'package:appflowy/plugins/database/grid/application/grid_bloc.dart';
|
||||||
import 'package:appflowy/plugins/database/grid/presentation/layout/sizes.dart';
|
|
||||||
import 'package:appflowy/plugins/database/grid/presentation/widgets/calculations/calculate_cell.dart';
|
import 'package:appflowy/plugins/database/grid/presentation/widgets/calculations/calculate_cell.dart';
|
||||||
|
import 'package:appflowy/plugins/database/tab_bar/tab_bar_view.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
|
||||||
class GridCalculationsRow extends StatelessWidget {
|
class GridCalculationsRow extends StatelessWidget {
|
||||||
@ -27,9 +26,12 @@ class GridCalculationsRow extends StatelessWidget {
|
|||||||
)..add(const CalculationsEvent.started()),
|
)..add(const CalculationsEvent.started()),
|
||||||
child: BlocBuilder<CalculationsBloc, CalculationsState>(
|
child: BlocBuilder<CalculationsBloc, CalculationsState>(
|
||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
|
final padding =
|
||||||
|
context.read<DatabasePluginWidgetBuilderSize>().horizontalPadding;
|
||||||
return Padding(
|
return Padding(
|
||||||
padding:
|
padding: includeDefaultInsets
|
||||||
includeDefaultInsets ? GridSize.contentInsets : EdgeInsets.zero,
|
? EdgeInsets.symmetric(horizontal: padding)
|
||||||
|
: EdgeInsets.zero,
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
...state.fields.map(
|
...state.fields.map(
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
import 'package:flutter/material.dart';
|
|
||||||
|
|
||||||
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
||||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||||
import 'package:appflowy/plugins/database/grid/application/grid_bloc.dart';
|
import 'package:appflowy/plugins/database/grid/application/grid_bloc.dart';
|
||||||
import 'package:appflowy/plugins/database/grid/presentation/layout/sizes.dart';
|
import 'package:appflowy/plugins/database/grid/presentation/layout/sizes.dart';
|
||||||
|
import 'package:appflowy/plugins/database/tab_bar/tab_bar_view.dart';
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flowy_infra/theme_extension.dart';
|
import 'package:flowy_infra/theme_extension.dart';
|
||||||
import 'package:flowy_infra_ui/style_widget/button.dart';
|
import 'package:flowy_infra_ui/style_widget/button.dart';
|
||||||
import 'package:flowy_infra_ui/style_widget/text.dart';
|
import 'package:flowy_infra_ui/style_widget/text.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
|
||||||
class GridAddRowButton extends StatelessWidget {
|
class GridAddRowButton extends StatelessWidget {
|
||||||
@ -41,8 +41,11 @@ class GridRowBottomBar extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
final padding =
|
||||||
|
context.read<DatabasePluginWidgetBuilderSize>().horizontalPadding;
|
||||||
return Container(
|
return Container(
|
||||||
padding: GridSize.footerContentInsets + const EdgeInsets.only(left: 40),
|
padding: GridSize.footerContentInsets.copyWith(left: 0) +
|
||||||
|
EdgeInsets.only(left: padding),
|
||||||
height: GridSize.footerHeight,
|
height: GridSize.footerHeight,
|
||||||
child: const GridAddRowButton(),
|
child: const GridAddRowButton(),
|
||||||
);
|
);
|
||||||
|
@ -98,7 +98,7 @@ class _RowLeadingState extends State<_RowLeading> {
|
|||||||
return AppFlowyPopover(
|
return AppFlowyPopover(
|
||||||
controller: popoverController,
|
controller: popoverController,
|
||||||
triggerActions: PopoverTriggerFlags.none,
|
triggerActions: PopoverTriggerFlags.none,
|
||||||
constraints: BoxConstraints.loose(const Size(176, 200)),
|
constraints: BoxConstraints.loose(const Size(200, 200)),
|
||||||
direction: PopoverDirection.rightWithCenterAligned,
|
direction: PopoverDirection.rightWithCenterAligned,
|
||||||
margin: const EdgeInsets.symmetric(horizontal: 6, vertical: 8),
|
margin: const EdgeInsets.symmetric(horizontal: 6, vertical: 8),
|
||||||
popupBuilder: (_) {
|
popupBuilder: (_) {
|
||||||
|
@ -56,7 +56,8 @@ class _DatabaseViewWidgetState extends State<DatabaseViewWidget> {
|
|||||||
shrinkWrap: widget.shrinkWrap,
|
shrinkWrap: widget.shrinkWrap,
|
||||||
context: PluginContext(),
|
context: PluginContext(),
|
||||||
data: {
|
data: {
|
||||||
kDatabasePluginWidgetBuilderHorizontalPadding: 40.0,
|
kDatabasePluginWidgetBuilderHorizontalPadding:
|
||||||
|
view.layout == ViewLayoutPB.Grid ? 40.0 : 0.0,
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import 'package:appflowy/workspace/application/settings/appearance/base_appearance.dart';
|
import 'package:appflowy/workspace/application/settings/appearance/base_appearance.dart';
|
||||||
import 'package:appflowy_backend/log.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:google_fonts/google_fonts.dart';
|
import 'package:google_fonts/google_fonts.dart';
|
||||||
|
|
||||||
@ -38,11 +37,7 @@ TextStyle getGoogleFontSafely(
|
|||||||
letterSpacing: letterSpacing,
|
letterSpacing: letterSpacing,
|
||||||
height: lineHeight,
|
height: lineHeight,
|
||||||
);
|
);
|
||||||
} catch (e) {
|
} catch (_) {}
|
||||||
Log.error(
|
|
||||||
'Font family $fontFamily is not available, using default font family instead',
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return TextStyle(
|
return TextStyle(
|
||||||
|
@ -24,6 +24,8 @@ part 'reminder_bloc.freezed.dart';
|
|||||||
|
|
||||||
class ReminderBloc extends Bloc<ReminderEvent, ReminderState> {
|
class ReminderBloc extends Bloc<ReminderEvent, ReminderState> {
|
||||||
ReminderBloc() : super(ReminderState()) {
|
ReminderBloc() : super(ReminderState()) {
|
||||||
|
Log.info('ReminderBloc created');
|
||||||
|
|
||||||
_actionBloc = getIt<ActionNavigationBloc>();
|
_actionBloc = getIt<ActionNavigationBloc>();
|
||||||
_reminderService = const ReminderService();
|
_reminderService = const ReminderService();
|
||||||
timer = _periodicCheck();
|
timer = _periodicCheck();
|
||||||
@ -40,36 +42,58 @@ class ReminderBloc extends Bloc<ReminderEvent, ReminderState> {
|
|||||||
(event, emit) async {
|
(event, emit) async {
|
||||||
await event.when(
|
await event.when(
|
||||||
started: () async {
|
started: () async {
|
||||||
final remindersOrFailure = await _reminderService.fetchReminders();
|
Log.info('Start fetching reminders');
|
||||||
|
|
||||||
remindersOrFailure.fold(
|
final result = await _reminderService.fetchReminders();
|
||||||
(reminders) => emit(state.copyWith(reminders: reminders)),
|
|
||||||
(error) => Log.error(error),
|
result.fold(
|
||||||
|
(reminders) {
|
||||||
|
Log.info('Fetched reminders on startup: ${reminders.length}');
|
||||||
|
emit(state.copyWith(reminders: reminders));
|
||||||
|
},
|
||||||
|
(error) => Log.error('Failed to fetch reminders: $error'),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
remove: (reminderId) async {
|
remove: (reminderId) async {
|
||||||
final unitOrFailure =
|
final result = await _reminderService.removeReminder(
|
||||||
await _reminderService.removeReminder(reminderId: reminderId);
|
reminderId: reminderId,
|
||||||
|
);
|
||||||
|
|
||||||
unitOrFailure.fold(
|
result.fold(
|
||||||
(_) {
|
(_) {
|
||||||
|
Log.info('Removed reminder: $reminderId');
|
||||||
final reminders = [...state.reminders];
|
final reminders = [...state.reminders];
|
||||||
reminders.removeWhere((e) => e.id == reminderId);
|
reminders.removeWhere((e) => e.id == reminderId);
|
||||||
emit(state.copyWith(reminders: reminders));
|
emit(state.copyWith(reminders: reminders));
|
||||||
},
|
},
|
||||||
(error) => Log.error(error),
|
(error) => Log.error(
|
||||||
|
'Failed to remove reminder($reminderId): $error',
|
||||||
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
add: (reminder) async {
|
add: (reminder) async {
|
||||||
final unitOrFailure =
|
// check the timestamp in the reminder
|
||||||
await _reminderService.addReminder(reminder: reminder);
|
if (reminder.createdAt == null) {
|
||||||
|
reminder.freeze();
|
||||||
|
reminder = reminder.rebuild((update) {
|
||||||
|
update.meta[ReminderMetaKeys.createdAt] =
|
||||||
|
DateTime.now().millisecondsSinceEpoch.toString();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
return unitOrFailure.fold(
|
final result = await _reminderService.addReminder(
|
||||||
|
reminder: reminder,
|
||||||
|
);
|
||||||
|
|
||||||
|
return result.fold(
|
||||||
(_) {
|
(_) {
|
||||||
|
Log.info('Added reminder: ${reminder.id}');
|
||||||
|
Log.info('Before adding reminder: ${state.reminders.length}');
|
||||||
final reminders = [...state.reminders, reminder];
|
final reminders = [...state.reminders, reminder];
|
||||||
|
Log.info('After adding reminder: ${reminders.length}');
|
||||||
emit(state.copyWith(reminders: reminders));
|
emit(state.copyWith(reminders: reminders));
|
||||||
},
|
},
|
||||||
(error) => Log.error(error),
|
(error) => Log.error('Failed to add reminder: $error'),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
addById: (reminderId, objectId, scheduledAt, meta) async => add(
|
addById: (reminderId, objectId, scheduledAt, meta) async => add(
|
||||||
@ -86,8 +110,9 @@ class ReminderBloc extends Bloc<ReminderEvent, ReminderState> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
update: (updateObject) async {
|
update: (updateObject) async {
|
||||||
final reminder = state.reminders
|
final reminder = state.reminders.firstWhereOrNull(
|
||||||
.firstWhereOrNull((r) => r.id == updateObject.id);
|
(r) => r.id == updateObject.id,
|
||||||
|
);
|
||||||
|
|
||||||
if (reminder == null) {
|
if (reminder == null) {
|
||||||
return;
|
return;
|
||||||
@ -98,15 +123,20 @@ class ReminderBloc extends Bloc<ReminderEvent, ReminderState> {
|
|||||||
reminder: newReminder,
|
reminder: newReminder,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
Log.info('Updating reminder: ${reminder.id}');
|
||||||
|
|
||||||
failureOrUnit.fold(
|
failureOrUnit.fold(
|
||||||
(_) {
|
(_) {
|
||||||
|
Log.info('Updated reminder: ${reminder.id}');
|
||||||
final index =
|
final index =
|
||||||
state.reminders.indexWhere((r) => r.id == reminder.id);
|
state.reminders.indexWhere((r) => r.id == reminder.id);
|
||||||
final reminders = [...state.reminders];
|
final reminders = [...state.reminders];
|
||||||
reminders.replaceRange(index, index + 1, [newReminder]);
|
reminders.replaceRange(index, index + 1, [newReminder]);
|
||||||
emit(state.copyWith(reminders: reminders));
|
emit(state.copyWith(reminders: reminders));
|
||||||
},
|
},
|
||||||
(error) => Log.error(error),
|
(error) => Log.error(
|
||||||
|
'Failed to update reminder(${reminder.id}): $error',
|
||||||
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
pressReminder: (reminderId, path, view) {
|
pressReminder: (reminderId, path, view) {
|
||||||
@ -157,6 +187,9 @@ class ReminderBloc extends Bloc<ReminderEvent, ReminderState> {
|
|||||||
},
|
},
|
||||||
markAsRead: (reminderIds) async {
|
markAsRead: (reminderIds) async {
|
||||||
final reminders = await _onMarkAsRead(reminderIds: reminderIds);
|
final reminders = await _onMarkAsRead(reminderIds: reminderIds);
|
||||||
|
|
||||||
|
Log.info('Marked reminders as read: $reminderIds');
|
||||||
|
|
||||||
emit(
|
emit(
|
||||||
state.copyWith(
|
state.copyWith(
|
||||||
reminders: reminders,
|
reminders: reminders,
|
||||||
@ -168,6 +201,9 @@ class ReminderBloc extends Bloc<ReminderEvent, ReminderState> {
|
|||||||
isArchived: true,
|
isArchived: true,
|
||||||
reminderIds: reminderIds,
|
reminderIds: reminderIds,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
Log.info('Archived reminders: $reminderIds');
|
||||||
|
|
||||||
emit(
|
emit(
|
||||||
state.copyWith(
|
state.copyWith(
|
||||||
reminders: reminders,
|
reminders: reminders,
|
||||||
@ -176,6 +212,9 @@ class ReminderBloc extends Bloc<ReminderEvent, ReminderState> {
|
|||||||
},
|
},
|
||||||
markAllRead: () async {
|
markAllRead: () async {
|
||||||
final reminders = await _onMarkAsRead();
|
final reminders = await _onMarkAsRead();
|
||||||
|
|
||||||
|
Log.info('Marked all reminders as read');
|
||||||
|
|
||||||
emit(
|
emit(
|
||||||
state.copyWith(
|
state.copyWith(
|
||||||
reminders: reminders,
|
reminders: reminders,
|
||||||
@ -184,6 +223,9 @@ class ReminderBloc extends Bloc<ReminderEvent, ReminderState> {
|
|||||||
},
|
},
|
||||||
archiveAll: () async {
|
archiveAll: () async {
|
||||||
final reminders = await _onArchived(isArchived: true);
|
final reminders = await _onArchived(isArchived: true);
|
||||||
|
|
||||||
|
Log.info('Archived all reminders');
|
||||||
|
|
||||||
emit(
|
emit(
|
||||||
state.copyWith(
|
state.copyWith(
|
||||||
reminders: reminders,
|
reminders: reminders,
|
||||||
@ -199,11 +241,14 @@ class ReminderBloc extends Bloc<ReminderEvent, ReminderState> {
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
refresh: () async {
|
refresh: () async {
|
||||||
final remindersOrFailure = await _reminderService.fetchReminders();
|
final result = await _reminderService.fetchReminders();
|
||||||
|
|
||||||
remindersOrFailure.fold(
|
result.fold(
|
||||||
(reminders) => emit(state.copyWith(reminders: reminders)),
|
(reminders) {
|
||||||
(error) => emit(state),
|
Log.info('Fetched reminders on refresh: ${reminders.length}');
|
||||||
|
emit(state.copyWith(reminders: reminders));
|
||||||
|
},
|
||||||
|
(error) => Log.error('Failed to fetch reminders: $error'),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
@ -71,8 +71,7 @@ class DesktopHomeScreen extends StatelessWidget {
|
|||||||
key: ValueKey(userProfile.id),
|
key: ValueKey(userProfile.id),
|
||||||
providers: [
|
providers: [
|
||||||
BlocProvider.value(
|
BlocProvider.value(
|
||||||
value: getIt<ReminderBloc>()
|
value: getIt<ReminderBloc>(),
|
||||||
..add(const ReminderEvent.started()),
|
|
||||||
),
|
),
|
||||||
BlocProvider<TabsBloc>.value(value: getIt<TabsBloc>()),
|
BlocProvider<TabsBloc>.value(value: getIt<TabsBloc>()),
|
||||||
BlocProvider<HomeBloc>(
|
BlocProvider<HomeBloc>(
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
import 'package:flutter/material.dart';
|
|
||||||
|
|
||||||
import 'package:appflowy/startup/startup.dart';
|
import 'package:appflowy/startup/startup.dart';
|
||||||
import 'package:appflowy/user/application/notification_filter/notification_filter_bloc.dart';
|
import 'package:appflowy/user/application/notification_filter/notification_filter_bloc.dart';
|
||||||
import 'package:appflowy/user/application/reminder/reminder_bloc.dart';
|
import 'package:appflowy/user/application/reminder/reminder_bloc.dart';
|
||||||
@ -11,6 +9,7 @@ import 'package:appflowy/workspace/presentation/notifications/widgets/notificati
|
|||||||
import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
|
import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
|
||||||
import 'package:appflowy_backend/protobuf/flowy-user/reminder.pb.dart';
|
import 'package:appflowy_backend/protobuf/flowy-user/reminder.pb.dart';
|
||||||
import 'package:appflowy_popover/appflowy_popover.dart';
|
import 'package:appflowy_popover/appflowy_popover.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
|
||||||
class NotificationDialog extends StatefulWidget {
|
class NotificationDialog extends StatefulWidget {
|
||||||
@ -64,12 +63,10 @@ class _NotificationDialogState extends State<NotificationDialog>
|
|||||||
builder: (context, filterState) =>
|
builder: (context, filterState) =>
|
||||||
BlocBuilder<ReminderBloc, ReminderState>(
|
BlocBuilder<ReminderBloc, ReminderState>(
|
||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
final List<ReminderPB> pastReminders = state.pastReminders
|
final reminders = state.reminders.sortByScheduledAt();
|
||||||
.where((r) => filterState.showUnreadsOnly ? !r.isRead : true)
|
final upcomingReminders =
|
||||||
.sortByScheduledAt();
|
|
||||||
|
|
||||||
final List<ReminderPB> upcomingReminders =
|
|
||||||
state.upcomingReminders.sortByScheduledAt();
|
state.upcomingReminders.sortByScheduledAt();
|
||||||
|
final hasUnreads = reminders.any((r) => !r.isRead);
|
||||||
|
|
||||||
return Column(
|
return Column(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
@ -82,14 +79,14 @@ class _NotificationDialogState extends State<NotificationDialog>
|
|||||||
controller: _controller,
|
controller: _controller,
|
||||||
children: [
|
children: [
|
||||||
NotificationsView(
|
NotificationsView(
|
||||||
shownReminders: pastReminders,
|
shownReminders: reminders,
|
||||||
reminderBloc: _reminderBloc,
|
reminderBloc: _reminderBloc,
|
||||||
views: widget.views,
|
views: widget.views,
|
||||||
onDelete: _onDelete,
|
onDelete: _onDelete,
|
||||||
onAction: _onAction,
|
onAction: _onAction,
|
||||||
onReadChanged: _onReadChanged,
|
onReadChanged: _onReadChanged,
|
||||||
actionBar: InboxActionBar(
|
actionBar: InboxActionBar(
|
||||||
hasUnreads: state.hasUnreads,
|
hasUnreads: hasUnreads,
|
||||||
showUnreadsOnly: filterState.showUnreadsOnly,
|
showUnreadsOnly: filterState.showUnreadsOnly,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
import 'package:flutter/material.dart';
|
|
||||||
|
|
||||||
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
||||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||||
import 'package:appflowy/startup/startup.dart';
|
import 'package:appflowy/startup/startup.dart';
|
||||||
@ -11,6 +9,7 @@ import 'package:appflowy_popover/appflowy_popover.dart';
|
|||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flowy_infra/theme_extension.dart';
|
import 'package:flowy_infra/theme_extension.dart';
|
||||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
|
||||||
class NotificationButton extends StatefulWidget {
|
class NotificationButton extends StatefulWidget {
|
||||||
@ -23,6 +22,12 @@ class NotificationButton extends StatefulWidget {
|
|||||||
class _NotificationButtonState extends State<NotificationButton> {
|
class _NotificationButtonState extends State<NotificationButton> {
|
||||||
final mutex = PopoverMutex();
|
final mutex = PopoverMutex();
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
getIt<ReminderBloc>().add(const ReminderEvent.started());
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
mutex.dispose();
|
mutex.dispose();
|
||||||
@ -56,8 +61,10 @@ class _NotificationButtonState extends State<NotificationButton> {
|
|||||||
child: FlowyButton(
|
child: FlowyButton(
|
||||||
useIntrinsicWidth: true,
|
useIntrinsicWidth: true,
|
||||||
margin: EdgeInsets.zero,
|
margin: EdgeInsets.zero,
|
||||||
text:
|
text: _buildNotificationIcon(
|
||||||
_buildNotificationIcon(context, state.hasUnreads),
|
context,
|
||||||
|
state.hasUnreads,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
||||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||||
import 'package:appflowy/plugins/document/presentation/editor_configuration.dart';
|
import 'package:appflowy/mobile/presentation/notifications/widgets/widgets.dart';
|
||||||
import 'package:appflowy/plugins/document/presentation/editor_style.dart';
|
|
||||||
import 'package:appflowy/workspace/application/settings/appearance/appearance_cubit.dart';
|
import 'package:appflowy/workspace/application/settings/appearance/appearance_cubit.dart';
|
||||||
import 'package:appflowy/workspace/application/settings/date_time/date_format_ext.dart';
|
import 'package:appflowy/workspace/application/settings/date_time/date_format_ext.dart';
|
||||||
import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
|
import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
|
||||||
|
import 'package:appflowy_backend/protobuf/flowy-user/protobuf.dart';
|
||||||
import 'package:appflowy_editor/appflowy_editor.dart';
|
import 'package:appflowy_editor/appflowy_editor.dart';
|
||||||
import 'package:appflowy_popover/appflowy_popover.dart';
|
import 'package:appflowy_popover/appflowy_popover.dart';
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
@ -18,7 +18,7 @@ import 'package:provider/provider.dart';
|
|||||||
class NotificationItem extends StatefulWidget {
|
class NotificationItem extends StatefulWidget {
|
||||||
const NotificationItem({
|
const NotificationItem({
|
||||||
super.key,
|
super.key,
|
||||||
required this.reminderId,
|
required this.reminder,
|
||||||
required this.title,
|
required this.title,
|
||||||
required this.scheduled,
|
required this.scheduled,
|
||||||
required this.body,
|
required this.body,
|
||||||
@ -32,7 +32,7 @@ class NotificationItem extends StatefulWidget {
|
|||||||
this.view,
|
this.view,
|
||||||
});
|
});
|
||||||
|
|
||||||
final String reminderId;
|
final ReminderPB reminder;
|
||||||
final String title;
|
final String title;
|
||||||
final Int64 scheduled;
|
final Int64 scheduled;
|
||||||
final String body;
|
final String body;
|
||||||
@ -169,6 +169,7 @@ class _NotificationItemState extends State<NotificationItem> {
|
|||||||
),
|
),
|
||||||
child: _NotificationContent(
|
child: _NotificationContent(
|
||||||
block: widget.block,
|
block: widget.block,
|
||||||
|
reminder: widget.reminder,
|
||||||
body: widget.body,
|
body: widget.body,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -214,10 +215,12 @@ class _NotificationItemState extends State<NotificationItem> {
|
|||||||
class _NotificationContent extends StatelessWidget {
|
class _NotificationContent extends StatelessWidget {
|
||||||
const _NotificationContent({
|
const _NotificationContent({
|
||||||
required this.body,
|
required this.body,
|
||||||
|
required this.reminder,
|
||||||
required this.block,
|
required this.block,
|
||||||
});
|
});
|
||||||
|
|
||||||
final String body;
|
final String body;
|
||||||
|
final ReminderPB reminder;
|
||||||
final Future<Node?>? block;
|
final Future<Node?>? block;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -229,29 +232,10 @@ class _NotificationContent extends StatelessWidget {
|
|||||||
return FlowyText.regular(body, maxLines: 4);
|
return FlowyText.regular(body, maxLines: 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
final editorState = EditorState(
|
return IntrinsicHeight(
|
||||||
document: Document(root: snapshot.data!),
|
child: NotificationDocumentContent(
|
||||||
);
|
nodes: [snapshot.data!],
|
||||||
|
reminder: reminder,
|
||||||
final styleCustomizer = EditorStyleCustomizer(
|
|
||||||
context: context,
|
|
||||||
padding: EdgeInsets.zero,
|
|
||||||
);
|
|
||||||
|
|
||||||
return Transform.scale(
|
|
||||||
scale: .9,
|
|
||||||
alignment: Alignment.centerLeft,
|
|
||||||
child: AppFlowyEditor(
|
|
||||||
editorState: editorState,
|
|
||||||
editorStyle: styleCustomizer.style(),
|
|
||||||
editable: false,
|
|
||||||
shrinkWrap: true,
|
|
||||||
blockComponentBuilders: getEditorBuilderMap(
|
|
||||||
context: context,
|
|
||||||
editorState: editorState,
|
|
||||||
styleCustomizer: styleCustomizer,
|
|
||||||
editable: false,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
@ -76,7 +76,7 @@ class NotificationsView extends StatelessWidget {
|
|||||||
|
|
||||||
final view = views.findView(reminder.objectId);
|
final view = views.findView(reminder.objectId);
|
||||||
return NotificationItem(
|
return NotificationItem(
|
||||||
reminderId: reminder.id,
|
reminder: reminder,
|
||||||
key: ValueKey(reminder.id),
|
key: ValueKey(reminder.id),
|
||||||
title: reminder.title,
|
title: reminder.title,
|
||||||
scheduled: reminder.scheduledAt,
|
scheduled: reminder.scheduledAt,
|
||||||
|
Reference in New Issue
Block a user