Browse Source

chore: set time

appflowy 3 years ago
parent
commit
a2dfc8bc03

+ 45 - 35
frontend/app_flowy/lib/workspace/application/grid/cell/date_cal_bloc.dart

@@ -1,5 +1,6 @@
 import 'package:app_flowy/workspace/application/grid/field/field_service.dart';
 import 'package:app_flowy/workspace/application/grid/field/field_service.dart';
 import 'package:flowy_sdk/log.dart';
 import 'package:flowy_sdk/log.dart';
+import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
 import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart' show Cell;
 import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart' show Cell;
 import 'package:flowy_sdk/protobuf/flowy-grid/date_type_option.pb.dart';
 import 'package:flowy_sdk/protobuf/flowy-grid/date_type_option.pb.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
@@ -16,13 +17,17 @@ class DateCalBloc extends Bloc<DateCalEvent, DateCalState> {
   final GridDefaultCellContext cellContext;
   final GridDefaultCellContext cellContext;
   void Function()? _onCellChangedFn;
   void Function()? _onCellChangedFn;
 
 
-  DateCalBloc({required this.cellContext}) : super(DateCalState.initial(cellContext)) {
+  DateCalBloc({
+    required DateTypeOption dateTypeOption,
+    required DateTime? selectedDay,
+    required this.cellContext,
+  }) : super(DateCalState.initial(dateTypeOption, selectedDay)) {
     on<DateCalEvent>(
     on<DateCalEvent>(
       (event, emit) async {
       (event, emit) async {
         await event.map(
         await event.map(
           initial: (_Initial value) async {
           initial: (_Initial value) async {
             _startListening();
             _startListening();
-            await _loadDateTypeOption(emit);
+            // await _loadDateTypeOption(emit);
           },
           },
           selectDay: (_SelectDay value) {
           selectDay: (_SelectDay value) {
             if (!isSameDay(state.selectedDay, value.day)) {
             if (!isSameDay(state.selectedDay, value.day)) {
@@ -46,6 +51,7 @@ class DateCalBloc extends Bloc<DateCalEvent, DateCalState> {
           setTimeFormat: (_TimeFormat value) async {
           setTimeFormat: (_TimeFormat value) async {
             await _updateTypeOption(emit, timeFormat: value.timeFormat);
             await _updateTypeOption(emit, timeFormat: value.timeFormat);
           },
           },
+          setTime: (_Time value) {},
         );
         );
       },
       },
     );
     );
@@ -71,12 +77,12 @@ class DateCalBloc extends Bloc<DateCalEvent, DateCalState> {
     );
     );
   }
   }
 
 
+  // ignore: unused_element
   Future<void> _loadDateTypeOption(Emitter<DateCalState> emit) async {
   Future<void> _loadDateTypeOption(Emitter<DateCalState> emit) async {
     final result = await cellContext.getTypeOptionData();
     final result = await cellContext.getTypeOptionData();
     result.fold(
     result.fold(
       (data) {
       (data) {
         final typeOptionData = DateTypeOption.fromBuffer(data);
         final typeOptionData = DateTypeOption.fromBuffer(data);
-
         DateTime? selectedDay;
         DateTime? selectedDay;
         final cellData = cellContext.getCellData()?.data;
         final cellData = cellContext.getCellData()?.data;
 
 
@@ -86,7 +92,7 @@ class DateCalBloc extends Bloc<DateCalEvent, DateCalState> {
         }
         }
 
 
         emit(state.copyWith(
         emit(state.copyWith(
-          dateTypeOption: some(typeOptionData),
+          dateTypeOption: typeOptionData,
           selectedDay: selectedDay,
           selectedDay: selectedDay,
         ));
         ));
       },
       },
@@ -105,35 +111,31 @@ class DateCalBloc extends Bloc<DateCalEvent, DateCalState> {
     TimeFormat? timeFormat,
     TimeFormat? timeFormat,
     bool? includeTime,
     bool? includeTime,
   }) async {
   }) async {
-    final newDateTypeOption = state.dateTypeOption.fold(() => null, (dateTypeOption) {
-      dateTypeOption.freeze();
-      return dateTypeOption.rebuild((typeOption) {
-        if (dateFormat != null) {
-          typeOption.dateFormat = dateFormat;
-        }
-
-        if (timeFormat != null) {
-          typeOption.timeFormat = timeFormat;
-        }
-
-        if (includeTime != null) {
-          typeOption.includeTime = includeTime;
-        }
-      });
+    state.dateTypeOption.freeze();
+    final newDateTypeOption = state.dateTypeOption.rebuild((typeOption) {
+      if (dateFormat != null) {
+        typeOption.dateFormat = dateFormat;
+      }
+
+      if (timeFormat != null) {
+        typeOption.timeFormat = timeFormat;
+      }
+
+      if (includeTime != null) {
+        typeOption.includeTime = includeTime;
+      }
     });
     });
 
 
-    if (newDateTypeOption != null) {
-      final result = await FieldService.updateFieldTypeOption(
-        gridId: cellContext.gridId,
-        fieldId: cellContext.field.id,
-        typeOptionData: newDateTypeOption.writeToBuffer(),
-      );
+    final result = await FieldService.updateFieldTypeOption(
+      gridId: cellContext.gridId,
+      fieldId: cellContext.field.id,
+      typeOptionData: newDateTypeOption.writeToBuffer(),
+    );
 
 
-      result.fold(
-        (l) => emit(state.copyWith(dateTypeOption: Some(newDateTypeOption))),
-        (err) => Log.error(err),
-      );
-    }
+    result.fold(
+      (l) => emit(state.copyWith(dateTypeOption: newDateTypeOption)),
+      (err) => Log.error(err),
+    );
   }
   }
 }
 }
 
 
@@ -146,23 +148,31 @@ class DateCalEvent with _$DateCalEvent {
   const factory DateCalEvent.setTimeFormat(TimeFormat timeFormat) = _TimeFormat;
   const factory DateCalEvent.setTimeFormat(TimeFormat timeFormat) = _TimeFormat;
   const factory DateCalEvent.setDateFormat(DateFormat dateFormat) = _DateFormat;
   const factory DateCalEvent.setDateFormat(DateFormat dateFormat) = _DateFormat;
   const factory DateCalEvent.setIncludeTime(bool includeTime) = _IncludeTime;
   const factory DateCalEvent.setIncludeTime(bool includeTime) = _IncludeTime;
+  const factory DateCalEvent.setTime(String time) = _Time;
   const factory DateCalEvent.didReceiveCellUpdate(Cell cell) = _DidReceiveCellUpdate;
   const factory DateCalEvent.didReceiveCellUpdate(Cell cell) = _DidReceiveCellUpdate;
 }
 }
 
 
 @freezed
 @freezed
 class DateCalState with _$DateCalState {
 class DateCalState with _$DateCalState {
   const factory DateCalState({
   const factory DateCalState({
-    required Option<DateTypeOption> dateTypeOption,
+    required DateTypeOption dateTypeOption,
     required CalendarFormat format,
     required CalendarFormat format,
     required DateTime focusedDay,
     required DateTime focusedDay,
-    required Option<String> time,
+    required String time,
+    required Option<FlowyError> inputTimeError,
     DateTime? selectedDay,
     DateTime? selectedDay,
   }) = _DateCalState;
   }) = _DateCalState;
 
 
-  factory DateCalState.initial(GridCellContext context) => DateCalState(
-        dateTypeOption: none(),
+  factory DateCalState.initial(
+    DateTypeOption dateTypeOption,
+    DateTime? selectedDay,
+  ) =>
+      DateCalState(
+        dateTypeOption: dateTypeOption,
         format: CalendarFormat.month,
         format: CalendarFormat.month,
         focusedDay: DateTime.now(),
         focusedDay: DateTime.now(),
-        time: none(),
+        selectedDay: selectedDay,
+        time: "",
+        inputTimeError: none(),
       );
       );
 }
 }

+ 73 - 38
frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/date_cell/calendar.dart

@@ -8,13 +8,15 @@ import 'package:flowy_infra/theme.dart';
 import 'package:flowy_infra_ui/flowy_infra_ui.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/button.dart';
 import 'package:flowy_infra_ui/style_widget/text.dart';
 import 'package:flowy_infra_ui/style_widget/text.dart';
+import 'package:flowy_infra_ui/widget/rounded_input_field.dart';
 import 'package:flowy_infra_ui/widget/spacing.dart';
 import 'package:flowy_infra_ui/widget/spacing.dart';
+import 'package:flowy_sdk/log.dart';
 import 'package:flowy_sdk/protobuf/flowy-grid/date_type_option.pb.dart';
 import 'package:flowy_sdk/protobuf/flowy-grid/date_type_option.pb.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 import 'package:table_calendar/table_calendar.dart';
 import 'package:table_calendar/table_calendar.dart';
 import 'package:app_flowy/workspace/application/grid/prelude.dart';
 import 'package:app_flowy/workspace/application/grid/prelude.dart';
-import 'package:dartz/dartz.dart' show Option;
+import 'package:fixnum/fixnum.dart' as $fixnum;
 
 
 final kToday = DateTime.now();
 final kToday = DateTime.now();
 final kFirstDay = DateTime(kToday.year, kToday.month - 3, kToday.day);
 final kFirstDay = DateTime(kToday.year, kToday.month - 3, kToday.day);
@@ -35,22 +37,38 @@ class CellCalendar with FlowyOverlayDelegate {
   }) async {
   }) async {
     CellCalendar.remove(context);
     CellCalendar.remove(context);
 
 
-    final calendar = _CellCalendarWidget(
-      onSelected: onSelected,
-      includeTime: false,
-      cellContext: cellContext,
-    );
+    final result = await cellContext.getTypeOptionData();
+    result.fold(
+      (data) {
+        final typeOptionData = DateTypeOption.fromBuffer(data);
+        DateTime? selectedDay;
+        final cellData = cellContext.getCellData()?.data;
+
+        if (cellData != null) {
+          final timestamp = $fixnum.Int64.parseInt(cellData).toInt();
+          selectedDay = DateTime.fromMillisecondsSinceEpoch(timestamp * 1000);
+        }
+
+        final calendar = _CellCalendarWidget(
+          onSelected: onSelected,
+          cellContext: cellContext,
+          dateTypeOption: typeOptionData,
+          selectedDay: selectedDay,
+        );
 
 
-    FlowyOverlay.of(context).insertWithAnchor(
-      widget: OverlayContainer(
-        child: calendar,
-        constraints: BoxConstraints.loose(const Size(320, 500)),
-      ),
-      identifier: CellCalendar.identifier(),
-      anchorContext: context,
-      anchorDirection: AnchorDirection.leftWithCenterAligned,
-      style: FlowyOverlayStyle(blur: false),
-      delegate: this,
+        FlowyOverlay.of(context).insertWithAnchor(
+          widget: OverlayContainer(
+            child: calendar,
+            constraints: BoxConstraints.loose(const Size(320, 500)),
+          ),
+          identifier: CellCalendar.identifier(),
+          anchorContext: context,
+          anchorDirection: AnchorDirection.leftWithCenterAligned,
+          style: FlowyOverlayStyle(blur: false),
+          delegate: this,
+        );
+      },
+      (err) => Log.error(err),
     );
     );
   }
   }
 
 
@@ -70,14 +88,16 @@ class CellCalendar with FlowyOverlayDelegate {
 }
 }
 
 
 class _CellCalendarWidget extends StatelessWidget {
 class _CellCalendarWidget extends StatelessWidget {
-  final bool includeTime;
   final GridDefaultCellContext cellContext;
   final GridDefaultCellContext cellContext;
+  final DateTypeOption dateTypeOption;
+  final DateTime? selectedDay;
   final void Function(DateTime) onSelected;
   final void Function(DateTime) onSelected;
 
 
   const _CellCalendarWidget({
   const _CellCalendarWidget({
     required this.onSelected,
     required this.onSelected,
-    required this.includeTime,
     required this.cellContext,
     required this.cellContext,
+    required this.dateTypeOption,
+    this.selectedDay,
     Key? key,
     Key? key,
   }) : super(key: key);
   }) : super(key: key);
 
 
@@ -85,7 +105,11 @@ class _CellCalendarWidget extends StatelessWidget {
   Widget build(BuildContext context) {
   Widget build(BuildContext context) {
     final theme = context.watch<AppTheme>();
     final theme = context.watch<AppTheme>();
     return BlocProvider(
     return BlocProvider(
-      create: (context) => DateCalBloc(cellContext: cellContext)..add(const DateCalEvent.initial()),
+      create: (context) => DateCalBloc(
+        dateTypeOption: dateTypeOption,
+        selectedDay: selectedDay,
+        cellContext: cellContext,
+      )..add(const DateCalEvent.initial()),
       child: BlocConsumer<DateCalBloc, DateCalState>(
       child: BlocConsumer<DateCalBloc, DateCalState>(
         listener: (context, state) {
         listener: (context, state) {
           if (state.selectedDay != null) {
           if (state.selectedDay != null) {
@@ -101,12 +125,11 @@ class _CellCalendarWidget extends StatelessWidget {
             const VSpace(10),
             const VSpace(10),
           ]);
           ]);
 
 
-          state.dateTypeOption.foldRight(null, (dateTypeOption, _) {
+          if (state.dateTypeOption.includeTime) {
             children.addAll([
             children.addAll([
               const _TimeTextField(),
               const _TimeTextField(),
-              const VSpace(10),
             ]);
             ]);
-          });
+          }
 
 
           children.addAll([
           children.addAll([
             Divider(height: 1, color: theme.shader5),
             Divider(height: 1, color: theme.shader5),
@@ -189,7 +212,7 @@ class _IncludeTimeButton extends StatelessWidget {
   Widget build(BuildContext context) {
   Widget build(BuildContext context) {
     final theme = context.watch<AppTheme>();
     final theme = context.watch<AppTheme>();
     return BlocSelector<DateCalBloc, DateCalState, bool>(
     return BlocSelector<DateCalBloc, DateCalState, bool>(
-      selector: (state) => state.dateTypeOption.foldRight(false, (option, _) => option.includeTime),
+      selector: (state) => state.dateTypeOption.includeTime,
       builder: (context, includeTime) {
       builder: (context, includeTime) {
         return SizedBox(
         return SizedBox(
           height: 50,
           height: 50,
@@ -219,7 +242,19 @@ class _TimeTextField extends StatelessWidget {
 
 
   @override
   @override
   Widget build(BuildContext context) {
   Widget build(BuildContext context) {
-    return Container();
+    final theme = context.watch<AppTheme>();
+    return Padding(
+      padding: kMargin,
+      child: RoundedInputField(
+        height: 40,
+        style: const TextStyle(fontSize: 14, fontWeight: FontWeight.w500),
+        normalBorderColor: theme.shader4,
+        errorBorderColor: theme.red,
+        cursorColor: theme.main1,
+        errorText: context.read<DateCalBloc>().state.inputTimeError.fold(() => "", (error) => error.toString()),
+        onEditingComplete: (value) => context.read<DateCalBloc>().add(DateCalEvent.setTime(value)),
+      ),
+    );
   }
   }
 }
 }
 
 
@@ -230,29 +265,33 @@ class _DateTypeOptionButton extends StatelessWidget {
   Widget build(BuildContext context) {
   Widget build(BuildContext context) {
     final theme = context.watch<AppTheme>();
     final theme = context.watch<AppTheme>();
     final title = LocaleKeys.grid_field_dateFormat.tr() + " &" + LocaleKeys.grid_field_timeFormat.tr();
     final title = LocaleKeys.grid_field_dateFormat.tr() + " &" + LocaleKeys.grid_field_timeFormat.tr();
-    return BlocSelector<DateCalBloc, DateCalState, Option<DateTypeOption>>(
+    return BlocSelector<DateCalBloc, DateCalState, DateTypeOption>(
       selector: (state) => state.dateTypeOption,
       selector: (state) => state.dateTypeOption,
       builder: (context, dateTypeOption) {
       builder: (context, dateTypeOption) {
         return FlowyButton(
         return FlowyButton(
           text: FlowyText.medium(title, fontSize: 12),
           text: FlowyText.medium(title, fontSize: 12),
           hoverColor: theme.hover,
           hoverColor: theme.hover,
           margin: kMargin,
           margin: kMargin,
-          onTap: () {
-            dateTypeOption.fold(() => null, (dateTypeOption) {
-              final setting = _CalDateTimeSetting(dateTypeOption: dateTypeOption);
-              setting.show(context);
-            });
-          },
+          onTap: () => _showTimeSetting(dateTypeOption, context),
           rightIcon: svgWidget("grid/more", color: theme.iconColor),
           rightIcon: svgWidget("grid/more", color: theme.iconColor),
         );
         );
       },
       },
     );
     );
   }
   }
+
+  void _showTimeSetting(DateTypeOption dateTypeOption, BuildContext context) {
+    final setting = _CalDateTimeSetting(
+      dateTypeOption: dateTypeOption,
+      onEvent: (event) => context.read<DateCalBloc>().add(event),
+    );
+    setting.show(context);
+  }
 }
 }
 
 
 class _CalDateTimeSetting extends StatefulWidget {
 class _CalDateTimeSetting extends StatefulWidget {
   final DateTypeOption dateTypeOption;
   final DateTypeOption dateTypeOption;
-  const _CalDateTimeSetting({required this.dateTypeOption, Key? key}) : super(key: key);
+  final Function(DateCalEvent) onEvent;
+  const _CalDateTimeSetting({required this.dateTypeOption, required this.onEvent, Key? key}) : super(key: key);
 
 
   @override
   @override
   State<_CalDateTimeSetting> createState() => _CalDateTimeSettingState();
   State<_CalDateTimeSetting> createState() => _CalDateTimeSettingState();
@@ -283,9 +322,7 @@ class _CalDateTimeSettingState extends State<_CalDateTimeSetting> {
       DateFormatButton(onTap: () {
       DateFormatButton(onTap: () {
         final list = DateFormatList(
         final list = DateFormatList(
           selectedFormat: widget.dateTypeOption.dateFormat,
           selectedFormat: widget.dateTypeOption.dateFormat,
-          onSelected: (format) {
-            context.read<DateCalBloc>().add(DateCalEvent.setDateFormat(format));
-          },
+          onSelected: (format) => widget.onEvent(DateCalEvent.setDateFormat(format)),
         );
         );
         _showOverlay(context, list);
         _showOverlay(context, list);
       }),
       }),
@@ -294,9 +331,7 @@ class _CalDateTimeSettingState extends State<_CalDateTimeSetting> {
         onTap: () {
         onTap: () {
           final list = TimeFormatList(
           final list = TimeFormatList(
             selectedFormat: widget.dateTypeOption.timeFormat,
             selectedFormat: widget.dateTypeOption.timeFormat,
-            onSelected: (format) {
-              context.read<DateCalBloc>().add(DateCalEvent.setTimeFormat(format));
-            },
+            onSelected: (format) => widget.onEvent(DateCalEvent.setTimeFormat(format)),
           );
           );
           _showOverlay(context, list);
           _showOverlay(context, list);
         },
         },

+ 1 - 1
frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/common/text_field.dart

@@ -53,7 +53,7 @@ class _InputTextFieldState extends State<InputTextField> {
           widget.onChanged!(text);
           widget.onChanged!(text);
         }
         }
       },
       },
-      onEditingComplete: () {
+      onEditingComplete: (_) {
         if (widget.onDone != null) {
         if (widget.onDone != null) {
           widget.onDone!(_controller.text);
           widget.onDone!(_controller.text);
         }
         }

+ 6 - 2
frontend/app_flowy/packages/flowy_infra_ui/lib/widget/rounded_input_field.dart

@@ -15,7 +15,7 @@ class RoundedInputField extends StatefulWidget {
   final String errorText;
   final String errorText;
   final TextStyle style;
   final TextStyle style;
   final ValueChanged<String>? onChanged;
   final ValueChanged<String>? onChanged;
-  final VoidCallback? onEditingComplete;
+  final Function(String)? onEditingComplete;
   final String? initialValue;
   final String? initialValue;
   final EdgeInsets margin;
   final EdgeInsets margin;
   final EdgeInsets padding;
   final EdgeInsets padding;
@@ -90,7 +90,11 @@ class _RoundedInputFieldState extends State<RoundedInputField> {
             }
             }
             setState(() {});
             setState(() {});
           },
           },
-          onEditingComplete: widget.onEditingComplete,
+          onEditingComplete: () {
+            if (widget.onEditingComplete != null) {
+              widget.onEditingComplete!(inputText);
+            }
+          },
           cursorColor: widget.cursorColor,
           cursorColor: widget.cursorColor,
           obscureText: obscuteText,
           obscureText: obscuteText,
           style: widget.style,
           style: widget.style,