From d3841154a578d6730d18085b05b3582bc5695481 Mon Sep 17 00:00:00 2001 From: appflowy Date: Mon, 9 May 2022 21:32:58 +0800 Subject: [PATCH] chore: config caladen ui --- .../clock_alarm.svg => grid/clock.svg} | 0 .../application/grid/cell/date_cal_bloc.dart | 14 +- .../src/widgets/cell/date_cell/calendar.dart | 220 ++++++++++++++---- .../grid/src/widgets/header/field_cell.dart | 2 +- .../widgets/header/field_editor_pannel.dart | 2 +- .../src/widgets/header/type_option/date.dart | 70 ++++-- .../widgets/header/type_option/number.dart | 2 +- .../lib/style_widget/button.dart | 6 +- 8 files changed, 246 insertions(+), 70 deletions(-) rename frontend/app_flowy/assets/images/{editor/clock_alarm.svg => grid/clock.svg} (100%) diff --git a/frontend/app_flowy/assets/images/editor/clock_alarm.svg b/frontend/app_flowy/assets/images/grid/clock.svg similarity index 100% rename from frontend/app_flowy/assets/images/editor/clock_alarm.svg rename to frontend/app_flowy/assets/images/grid/clock.svg diff --git a/frontend/app_flowy/lib/workspace/application/grid/cell/date_cal_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/cell/date_cal_bloc.dart index f3ce3d5faa..c33666669d 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/cell/date_cal_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/cell/date_cal_bloc.dart @@ -28,7 +28,7 @@ class DateCalBloc extends Bloc { emit(state.copyWith(selectedDay: value.day)); } }, - setFormat: (_CalendarFormat value) { + setCalFormat: (_CalendarFormat value) { emit(state.copyWith(format: value.format)); }, setFocusedDay: (_FocusedDay value) { @@ -38,6 +38,11 @@ class DateCalBloc extends Bloc { didReceiveFieldUpdate: (_DidReceiveFieldUpdate value) { emit(state.copyWith(field: value.field)); }, + setIncludeTime: (_IncludeTime value) { + emit(state.copyWith(includeTime: value.includeTime)); + }, + setDateFormat: (_DateFormat value) {}, + setTimeFormat: (_TimeFormat value) {}, ); }, ); @@ -97,8 +102,11 @@ class DateCalBloc extends Bloc { class DateCalEvent with _$DateCalEvent { const factory DateCalEvent.initial() = _Initial; const factory DateCalEvent.selectDay(DateTime day) = _SelectDay; - const factory DateCalEvent.setFormat(CalendarFormat format) = _CalendarFormat; + const factory DateCalEvent.setCalFormat(CalendarFormat format) = _CalendarFormat; const factory DateCalEvent.setFocusedDay(DateTime day) = _FocusedDay; + const factory DateCalEvent.setTimeFormat(TimeFormat value) = _TimeFormat; + const factory DateCalEvent.setDateFormat(DateFormat value) = _DateFormat; + const factory DateCalEvent.setIncludeTime(bool includeTime) = _IncludeTime; const factory DateCalEvent.didReceiveCellUpdate(Cell cell) = _DidReceiveCellUpdate; const factory DateCalEvent.didReceiveFieldUpdate(Field field) = _DidReceiveFieldUpdate; } @@ -111,6 +119,7 @@ class DateCalState with _$DateCalState { required CalendarFormat format, required DateTime focusedDay, required bool includeTime, + required Option time, DateTime? selectedDay, }) = _DateCalState; @@ -120,5 +129,6 @@ class DateCalState with _$DateCalState { format: CalendarFormat.month, focusedDay: DateTime.now(), includeTime: false, + time: none(), ); } diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/date_cell/calendar.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/date_cell/calendar.dart index 7b052078d0..311f091e9b 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/date_cell/calendar.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/date_cell/calendar.dart @@ -1,6 +1,15 @@ +import 'package:app_flowy/generated/locale_keys.g.dart'; import 'package:app_flowy/workspace/application/grid/cell/date_cal_bloc.dart'; +import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/type_option/date.dart'; +import 'package:easy_localization/easy_localization.dart'; +import 'package:flowy_infra/image.dart'; import 'package:flowy_infra/theme.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart'; +import 'package:flowy_infra_ui/style_widget/button.dart'; +import 'package:flowy_infra_ui/style_widget/text.dart'; +import 'package:flowy_infra_ui/widget/spacing.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid/date_type_option.pb.dart'; +import 'package:flutter/material.dart'; import 'package:flutter/widgets.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:table_calendar/table_calendar.dart'; @@ -9,6 +18,7 @@ import 'package:app_flowy/workspace/application/grid/prelude.dart'; final kToday = DateTime.now(); final kFirstDay = DateTime(kToday.year, kToday.month - 3, kToday.day); final kLastDay = DateTime(kToday.year, kToday.month + 3, kToday.day); +const kMargin = EdgeInsets.symmetric(horizontal: 6, vertical: 10); class CellCalendar with FlowyOverlayDelegate { final VoidCallback onDismissed; @@ -47,7 +57,7 @@ class CellCalendar with FlowyOverlayDelegate { FlowyOverlay.of(context).insertWithAnchor( widget: OverlayContainer( child: calendar, - constraints: BoxConstraints.tight(const Size(320, 320)), + constraints: BoxConstraints.tight(const Size(320, 500)), ), identifier: CellCalendar.identifier(), anchorContext: context, @@ -67,6 +77,9 @@ class CellCalendar with FlowyOverlayDelegate { @override void didRemove() => onDismissed(); + + @override + bool asBarrier() => true; } class _CellCalendarWidget extends StatelessWidget { @@ -94,46 +107,175 @@ class _CellCalendarWidget extends StatelessWidget { }, listenWhen: (p, c) => p.selectedDay != c.selectedDay, builder: (context, state) { - return TableCalendar( - firstDay: kFirstDay, - lastDay: kLastDay, - focusedDay: state.focusedDay, - rowHeight: 40, - calendarFormat: state.format, - headerStyle: const HeaderStyle(formatButtonVisible: false), - calendarStyle: CalendarStyle( - selectedDecoration: BoxDecoration( - color: theme.main1, - shape: BoxShape.circle, - ), - todayDecoration: BoxDecoration( - color: theme.shader4, - shape: BoxShape.circle, - ), - selectedTextStyle: TextStyle( - color: theme.surface, - fontSize: 14.0, - ), - todayTextStyle: TextStyle( - color: theme.surface, - fontSize: 14.0, - ), - ), - selectedDayPredicate: (day) { - return isSameDay(state.selectedDay, day); - }, - onDaySelected: (selectedDay, focusedDay) { - context.read().add(DateCalEvent.selectDay(selectedDay)); - }, - onFormatChanged: (format) { - context.read().add(DateCalEvent.setFormat(format)); - }, - onPageChanged: (focusedDay) { - context.read().add(DateCalEvent.setFocusedDay(focusedDay)); - }, - ); + List children = []; + + children.addAll([ + _buildCalendar(state, theme, context), + const VSpace(10), + ]); + + if (state.includeTime) { + children.addAll([ + const _TimeTextField(), + const VSpace(10), + ]); + } + + children.addAll([ + Divider(height: 1, color: theme.shader5), + const _IncludeTimeButton(), + ]); + + state.typeOptinoData.fold(() => null, (dateTypeOption) { + children.add(_DateTypeOptionButton(dateTypeOption: dateTypeOption)); + }); + + return Column(children: children); }, ), ); } + + TableCalendar _buildCalendar(DateCalState state, AppTheme theme, BuildContext context) { + return TableCalendar( + firstDay: kFirstDay, + lastDay: kLastDay, + focusedDay: state.focusedDay, + rowHeight: 40, + calendarFormat: state.format, + headerStyle: HeaderStyle( + formatButtonVisible: false, + titleCentered: true, + leftChevronMargin: EdgeInsets.zero, + leftChevronPadding: EdgeInsets.zero, + leftChevronIcon: svgWidget("home/arrow_left"), + rightChevronPadding: EdgeInsets.zero, + rightChevronMargin: EdgeInsets.zero, + rightChevronIcon: svgWidget("home/arrow_right"), + ), + calendarStyle: CalendarStyle( + selectedDecoration: BoxDecoration( + color: theme.main1, + shape: BoxShape.circle, + ), + todayDecoration: BoxDecoration( + color: theme.shader4, + shape: BoxShape.circle, + ), + selectedTextStyle: TextStyle( + color: theme.surface, + fontSize: 14.0, + ), + todayTextStyle: TextStyle( + color: theme.surface, + fontSize: 14.0, + ), + ), + selectedDayPredicate: (day) { + return isSameDay(state.selectedDay, day); + }, + onDaySelected: (selectedDay, focusedDay) { + context.read().add(DateCalEvent.selectDay(selectedDay)); + }, + onFormatChanged: (format) { + context.read().add(DateCalEvent.setCalFormat(format)); + }, + onPageChanged: (focusedDay) { + context.read().add(DateCalEvent.setFocusedDay(focusedDay)); + }, + ); + } +} + +class _IncludeTimeButton extends StatelessWidget { + const _IncludeTimeButton({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + final theme = context.watch(); + return BlocSelector( + selector: (state) => state.includeTime, + builder: (context, includeTime) { + return SizedBox( + height: 50, + child: Padding( + padding: kMargin, + child: Row( + children: [ + svgWidget("grid/clock", color: theme.iconColor), + const HSpace(4), + FlowyText.medium(LocaleKeys.grid_field_includeTime.tr(), fontSize: 14), + const Spacer(), + Switch( + value: includeTime, + onChanged: (newValue) => context.read().add(DateCalEvent.setIncludeTime(newValue)), + ), + ], + ), + ), + ); + }, + ); + } +} + +class _TimeTextField extends StatelessWidget { + const _TimeTextField({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Container(); + } +} + +class _DateTypeOptionButton extends StatelessWidget { + final DateTypeOption dateTypeOption; + const _DateTypeOptionButton({required this.dateTypeOption, Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + final theme = context.watch(); + final title = LocaleKeys.grid_field_dateFormat.tr() + " &" + LocaleKeys.grid_field_timeFormat.tr(); + return FlowyButton( + text: FlowyText.medium(title, fontSize: 12), + hoverColor: theme.hover, + margin: kMargin, + onTap: () { + final setting = _CalDateTimeSetting(dateTypeOption: dateTypeOption); + setting.show(context); + }, + rightIcon: svgWidget("grid/more", color: theme.iconColor), + ); + } +} + +class _CalDateTimeSetting extends StatelessWidget { + final DateTypeOption dateTypeOption; + const _CalDateTimeSetting({required this.dateTypeOption, Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Column(children: [ + DateFormatButton(onTap: () { + final list = DateFormatList( + selectedFormat: dateTypeOption.dateFormat, + onSelected: (format) { + context.read().add(DateTypeOptionEvent.didSelectDateFormat(format)); + }, + ); + }), + TimeFormatButton( + timeFormat: dateTypeOption.timeFormat, + onTap: () { + final list = TimeFormatList( + selectedFormat: dateTypeOption.timeFormat, + onSelected: (format) { + context.read().add(DateTypeOptionEvent.didSelectTimeFormat(format)); + }); + }, + ), + ]); + } + + void show(BuildContext context) {} } diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_cell.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_cell.dart index aa45487fe2..eb264e6664 100755 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_cell.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_cell.dart @@ -150,7 +150,7 @@ class FieldCellButton extends StatelessWidget { onTap: onTap, leftIcon: svgWidget(field.fieldType.iconName(), color: theme.iconColor), text: FlowyText.medium(field.name, fontSize: 12), - padding: GridSize.cellContentInsets, + margin: GridSize.cellContentInsets, ); } } diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_editor_pannel.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_editor_pannel.dart index fe00fe45a6..b64cd4ad50 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_editor_pannel.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_editor_pannel.dart @@ -80,7 +80,7 @@ class _FieldEditorPannelState extends State { height: GridSize.typeOptionItemHeight, child: FlowyButton( text: FlowyText.medium(field.fieldType.title(), fontSize: 12), - padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 2), + margin: const EdgeInsets.symmetric(horizontal: 6, vertical: 2), hoverColor: theme.hover, onTap: () { final list = FieldTypeList(onSelectField: (newFieldType) { diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/date.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/date.dart index 2d920cbbf2..677e043703 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/date.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/date.dart @@ -50,8 +50,8 @@ class DateTypeOptionWidget extends TypeOptionWidget { listener: (context, state) => dataDelegate.didUpdateTypeOptionData(state.typeOption.writeToBuffer()), builder: (context, state) { return Column(children: [ - _dateFormatButton(context, state.typeOption.dateFormat), - _timeFormatButton(context, state.typeOption.timeFormat), + _renderDateFormatButton(context, state.typeOption.dateFormat), + _renderTimeFormatButton(context, state.typeOption.timeFormat), const _IncludeTimeButton(), ]); }, @@ -59,44 +59,68 @@ class DateTypeOptionWidget extends TypeOptionWidget { ); } - Widget _dateFormatButton(BuildContext context, DateFormat dataFormat) { + Widget _renderDateFormatButton(BuildContext context, DateFormat dataFormat) { + return DateFormatButton(onTap: () { + final list = DateFormatList( + selectedFormat: dataFormat, + onSelected: (format) { + context.read().add(DateTypeOptionEvent.didSelectDateFormat(format)); + }, + ); + overlayDelegate.showOverlay(context, list); + }); + } + + Widget _renderTimeFormatButton(BuildContext context, TimeFormat timeFormat) { + return TimeFormatButton( + timeFormat: timeFormat, + onTap: () { + final list = TimeFormatList( + selectedFormat: timeFormat, + onSelected: (format) { + context.read().add(DateTypeOptionEvent.didSelectTimeFormat(format)); + }); + overlayDelegate.showOverlay(context, list); + }, + ); + } +} + +class DateFormatButton extends StatelessWidget { + final VoidCallback onTap; + const DateFormatButton({required this.onTap, Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { final theme = context.watch(); return SizedBox( height: GridSize.typeOptionItemHeight, child: FlowyButton( text: FlowyText.medium(LocaleKeys.grid_field_dateFormat.tr(), fontSize: 12), - padding: GridSize.typeOptionContentInsets, + margin: GridSize.typeOptionContentInsets, hoverColor: theme.hover, - onTap: () { - final list = DateFormatList( - selectedFormat: dataFormat, - onSelected: (format) { - context.read().add(DateTypeOptionEvent.didSelectDateFormat(format)); - }, - ); - overlayDelegate.showOverlay(context, list); - }, + onTap: onTap, rightIcon: svgWidget("grid/more", color: theme.iconColor), ), ); } +} - Widget _timeFormatButton(BuildContext context, TimeFormat timeFormat) { +class TimeFormatButton extends StatelessWidget { + final TimeFormat timeFormat; + final VoidCallback onTap; + const TimeFormatButton({required this.timeFormat, required this.onTap, Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { final theme = context.watch(); return SizedBox( height: GridSize.typeOptionItemHeight, child: FlowyButton( text: FlowyText.medium(LocaleKeys.grid_field_timeFormat.tr(), fontSize: 12), - padding: GridSize.typeOptionContentInsets, + margin: GridSize.typeOptionContentInsets, hoverColor: theme.hover, - onTap: () { - final list = TimeFormatList( - selectedFormat: timeFormat, - onSelected: (format) { - context.read().add(DateTypeOptionEvent.didSelectTimeFormat(format)); - }); - overlayDelegate.showOverlay(context, list); - }, + onTap: onTap, rightIcon: svgWidget("grid/more", color: theme.iconColor), ), ); diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/number.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/number.dart index b887fd53a9..9e3ced1c43 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/number.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/number.dart @@ -60,7 +60,7 @@ class NumberTypeOptionWidget extends TypeOptionWidget { FlowyText.regular(state.typeOption.format.title(), fontSize: 12), ], ), - padding: GridSize.typeOptionContentInsets, + margin: GridSize.typeOptionContentInsets, hoverColor: theme.hover, onTap: () { final list = NumberFormatList( diff --git a/frontend/app_flowy/packages/flowy_infra_ui/lib/style_widget/button.dart b/frontend/app_flowy/packages/flowy_infra_ui/lib/style_widget/button.dart index 8249bc115b..9a7407f9bb 100644 --- a/frontend/app_flowy/packages/flowy_infra_ui/lib/style_widget/button.dart +++ b/frontend/app_flowy/packages/flowy_infra_ui/lib/style_widget/button.dart @@ -7,7 +7,7 @@ import 'package:flutter/material.dart'; class FlowyButton extends StatelessWidget { final Widget text; final VoidCallback? onTap; - final EdgeInsets padding; + final EdgeInsets margin; final Widget? leftIcon; final Widget? rightIcon; final Color hoverColor; @@ -16,7 +16,7 @@ class FlowyButton extends StatelessWidget { Key? key, required this.text, this.onTap, - this.padding = const EdgeInsets.symmetric(horizontal: 6, vertical: 2), + this.margin = const EdgeInsets.symmetric(horizontal: 6, vertical: 2), this.leftIcon, this.rightIcon, this.hoverColor = Colors.transparent, @@ -50,7 +50,7 @@ class FlowyButton extends StatelessWidget { } return Padding( - padding: padding, + padding: margin, child: Row( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center,