Skip to content

Commit 81d7514

Browse files
committed
chore: update typeOption data
1 parent d384115 commit 81d7514

File tree

16 files changed

+689
-142
lines changed

16 files changed

+689
-142
lines changed

frontend/app_flowy/lib/workspace/application/grid/cell/date_cal_bloc.dart

Lines changed: 52 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1+
import 'package:app_flowy/workspace/application/grid/field/field_service.dart';
12
import 'package:flowy_sdk/log.dart';
2-
import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart' show Cell, Field;
3+
import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart' show Cell;
34
import 'package:flowy_sdk/protobuf/flowy-grid/date_type_option.pb.dart';
45
import 'package:flutter_bloc/flutter_bloc.dart';
56
import 'package:freezed_annotation/freezed_annotation.dart';
@@ -8,6 +9,7 @@ import 'dart:async';
89
import 'cell_service.dart';
910
import 'package:dartz/dartz.dart';
1011
import 'package:fixnum/fixnum.dart' as $fixnum;
12+
import 'package:protobuf/protobuf.dart';
1113
part 'date_cal_bloc.freezed.dart';
1214

1315
class DateCalBloc extends Bloc<DateCalEvent, DateCalState> {
@@ -35,14 +37,15 @@ class DateCalBloc extends Bloc<DateCalEvent, DateCalState> {
3537
emit(state.copyWith(focusedDay: value.day));
3638
},
3739
didReceiveCellUpdate: (_DidReceiveCellUpdate value) {},
38-
didReceiveFieldUpdate: (_DidReceiveFieldUpdate value) {
39-
emit(state.copyWith(field: value.field));
40+
setIncludeTime: (_IncludeTime value) async {
41+
await _updateTypeOption(emit, includeTime: value.includeTime);
4042
},
41-
setIncludeTime: (_IncludeTime value) {
42-
emit(state.copyWith(includeTime: value.includeTime));
43+
setDateFormat: (_DateFormat value) async {
44+
await _updateTypeOption(emit, dateFormat: value.dateFormat);
45+
},
46+
setTimeFormat: (_TimeFormat value) async {
47+
await _updateTypeOption(emit, timeFormat: value.timeFormat);
4348
},
44-
setDateFormat: (_DateFormat value) {},
45-
setTimeFormat: (_TimeFormat value) {},
4649
);
4750
},
4851
);
@@ -83,8 +86,7 @@ class DateCalBloc extends Bloc<DateCalEvent, DateCalState> {
8386
}
8487

8588
emit(state.copyWith(
86-
typeOptinoData: some(typeOptionData),
87-
includeTime: typeOptionData.includeTime,
89+
dateTypeOption: some(typeOptionData),
8890
selectedDay: selectedDay,
8991
));
9092
},
@@ -96,6 +98,43 @@ class DateCalBloc extends Bloc<DateCalEvent, DateCalState> {
9698
final data = day.millisecondsSinceEpoch ~/ 1000;
9799
cellContext.saveCellData(data.toString());
98100
}
101+
102+
Future<void>? _updateTypeOption(
103+
Emitter<DateCalState> emit, {
104+
DateFormat? dateFormat,
105+
TimeFormat? timeFormat,
106+
bool? includeTime,
107+
}) async {
108+
final newDateTypeOption = state.dateTypeOption.fold(() => null, (dateTypeOption) {
109+
dateTypeOption.freeze();
110+
return dateTypeOption.rebuild((typeOption) {
111+
if (dateFormat != null) {
112+
typeOption.dateFormat = dateFormat;
113+
}
114+
115+
if (timeFormat != null) {
116+
typeOption.timeFormat = timeFormat;
117+
}
118+
119+
if (includeTime != null) {
120+
typeOption.includeTime = includeTime;
121+
}
122+
});
123+
});
124+
125+
if (newDateTypeOption != null) {
126+
final result = await FieldService.updateFieldTypeOption(
127+
gridId: cellContext.gridId,
128+
fieldId: cellContext.field.id,
129+
typeOptionData: newDateTypeOption.writeToBuffer(),
130+
);
131+
132+
result.fold(
133+
(l) => emit(state.copyWith(dateTypeOption: Some(newDateTypeOption))),
134+
(err) => Log.error(err),
135+
);
136+
}
137+
}
99138
}
100139

101140
@freezed
@@ -104,31 +143,26 @@ class DateCalEvent with _$DateCalEvent {
104143
const factory DateCalEvent.selectDay(DateTime day) = _SelectDay;
105144
const factory DateCalEvent.setCalFormat(CalendarFormat format) = _CalendarFormat;
106145
const factory DateCalEvent.setFocusedDay(DateTime day) = _FocusedDay;
107-
const factory DateCalEvent.setTimeFormat(TimeFormat value) = _TimeFormat;
108-
const factory DateCalEvent.setDateFormat(DateFormat value) = _DateFormat;
146+
const factory DateCalEvent.setTimeFormat(TimeFormat timeFormat) = _TimeFormat;
147+
const factory DateCalEvent.setDateFormat(DateFormat dateFormat) = _DateFormat;
109148
const factory DateCalEvent.setIncludeTime(bool includeTime) = _IncludeTime;
110149
const factory DateCalEvent.didReceiveCellUpdate(Cell cell) = _DidReceiveCellUpdate;
111-
const factory DateCalEvent.didReceiveFieldUpdate(Field field) = _DidReceiveFieldUpdate;
112150
}
113151

114152
@freezed
115153
class DateCalState with _$DateCalState {
116154
const factory DateCalState({
117-
required Field field,
118-
required Option<DateTypeOption> typeOptinoData,
155+
required Option<DateTypeOption> dateTypeOption,
119156
required CalendarFormat format,
120157
required DateTime focusedDay,
121-
required bool includeTime,
122158
required Option<String> time,
123159
DateTime? selectedDay,
124160
}) = _DateCalState;
125161

126162
factory DateCalState.initial(GridCellContext context) => DateCalState(
127-
field: context.field,
128-
typeOptinoData: none(),
163+
dateTypeOption: none(),
129164
format: CalendarFormat.month,
130165
focusedDay: DateTime.now(),
131-
includeTime: false,
132166
time: none(),
133167
);
134168
}

frontend/app_flowy/lib/workspace/application/grid/field/field_service.dart

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,19 @@ class FieldService {
9999
return GridEventInsertField(payload).send();
100100
}
101101

102+
static Future<Either<Unit, FlowyError>> updateFieldTypeOption({
103+
required String gridId,
104+
required String fieldId,
105+
required List<int> typeOptionData,
106+
}) {
107+
var payload = UpdateFieldTypeOptionPayload.create()
108+
..gridId = gridId
109+
..fieldId = fieldId
110+
..typeOptionData = typeOptionData;
111+
112+
return GridEventUpdateFieldTypeOption(payload).send();
113+
}
114+
102115
Future<Either<Unit, FlowyError>> deleteField() {
103116
final payload = FieldIdentifierPayload.create()
104117
..gridId = gridId

frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/date_cell/calendar.dart

Lines changed: 103 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import 'package:app_flowy/generated/locale_keys.g.dart';
22
import 'package:app_flowy/workspace/application/grid/cell/date_cal_bloc.dart';
3+
import 'package:app_flowy/workspace/presentation/plugins/grid/src/layout/sizes.dart';
34
import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/type_option/date.dart';
45
import 'package:easy_localization/easy_localization.dart';
56
import 'package:flowy_infra/image.dart';
@@ -10,10 +11,10 @@ import 'package:flowy_infra_ui/style_widget/text.dart';
1011
import 'package:flowy_infra_ui/widget/spacing.dart';
1112
import 'package:flowy_sdk/protobuf/flowy-grid/date_type_option.pb.dart';
1213
import 'package:flutter/material.dart';
13-
import 'package:flutter/widgets.dart';
1414
import 'package:flutter_bloc/flutter_bloc.dart';
1515
import 'package:table_calendar/table_calendar.dart';
1616
import 'package:app_flowy/workspace/application/grid/prelude.dart';
17+
import 'package:dartz/dartz.dart' show Option;
1718

1819
final kToday = DateTime.now();
1920
final kFirstDay = DateTime(kToday.year, kToday.month - 3, kToday.day);
@@ -39,25 +40,11 @@ class CellCalendar with FlowyOverlayDelegate {
3940
includeTime: false,
4041
cellContext: cellContext,
4142
);
42-
// const size = Size(460, 400);
43-
// final window = await getWindowInfo();
44-
// FlowyOverlay.of(context).insertWithRect(
45-
// widget: OverlayContainer(
46-
// child: calendar,
47-
// constraints: BoxConstraints.loose(const Size(460, 400)),
48-
// ),
49-
// identifier: _CellCalendar.identifier(),
50-
// anchorPosition: Offset(-size.width / 2.0, -size.height / 2.0),
51-
// anchorSize: window.frame.size,
52-
// anchorDirection: AnchorDirection.center,
53-
// style: FlowyOverlayStyle(blur: false),
54-
// delegate: calendar,
55-
// );
5643

5744
FlowyOverlay.of(context).insertWithAnchor(
5845
widget: OverlayContainer(
5946
child: calendar,
60-
constraints: BoxConstraints.tight(const Size(320, 500)),
47+
constraints: BoxConstraints.loose(const Size(320, 500)),
6148
),
6249
identifier: CellCalendar.identifier(),
6350
anchorContext: context,
@@ -114,23 +101,31 @@ class _CellCalendarWidget extends StatelessWidget {
114101
const VSpace(10),
115102
]);
116103

117-
if (state.includeTime) {
104+
state.dateTypeOption.foldRight(null, (dateTypeOption, _) {
118105
children.addAll([
119106
const _TimeTextField(),
120107
const VSpace(10),
121108
]);
122-
}
109+
});
123110

124111
children.addAll([
125112
Divider(height: 1, color: theme.shader5),
126113
const _IncludeTimeButton(),
127114
]);
128115

129-
state.typeOptinoData.fold(() => null, (dateTypeOption) {
130-
children.add(_DateTypeOptionButton(dateTypeOption: dateTypeOption));
131-
});
116+
children.add(const _DateTypeOptionButton());
132117

133-
return Column(children: children);
118+
return ListView.separated(
119+
shrinkWrap: true,
120+
controller: ScrollController(),
121+
separatorBuilder: (context, index) {
122+
return VSpace(GridSize.typeOptionSeparatorHeight);
123+
},
124+
itemCount: children.length,
125+
itemBuilder: (BuildContext context, int index) {
126+
return children[index];
127+
},
128+
);
134129
},
135130
),
136131
);
@@ -194,7 +189,7 @@ class _IncludeTimeButton extends StatelessWidget {
194189
Widget build(BuildContext context) {
195190
final theme = context.watch<AppTheme>();
196191
return BlocSelector<DateCalBloc, DateCalState, bool>(
197-
selector: (state) => state.includeTime,
192+
selector: (state) => state.dateTypeOption.foldRight(false, (option, _) => option.includeTime),
198193
builder: (context, includeTime) {
199194
return SizedBox(
200195
height: 50,
@@ -229,53 +224,117 @@ class _TimeTextField extends StatelessWidget {
229224
}
230225

231226
class _DateTypeOptionButton extends StatelessWidget {
232-
final DateTypeOption dateTypeOption;
233-
const _DateTypeOptionButton({required this.dateTypeOption, Key? key}) : super(key: key);
227+
const _DateTypeOptionButton({Key? key}) : super(key: key);
234228

235229
@override
236230
Widget build(BuildContext context) {
237231
final theme = context.watch<AppTheme>();
238232
final title = LocaleKeys.grid_field_dateFormat.tr() + " &" + LocaleKeys.grid_field_timeFormat.tr();
239-
return FlowyButton(
240-
text: FlowyText.medium(title, fontSize: 12),
241-
hoverColor: theme.hover,
242-
margin: kMargin,
243-
onTap: () {
244-
final setting = _CalDateTimeSetting(dateTypeOption: dateTypeOption);
245-
setting.show(context);
233+
return BlocSelector<DateCalBloc, DateCalState, Option<DateTypeOption>>(
234+
selector: (state) => state.dateTypeOption,
235+
builder: (context, dateTypeOption) {
236+
return FlowyButton(
237+
text: FlowyText.medium(title, fontSize: 12),
238+
hoverColor: theme.hover,
239+
margin: kMargin,
240+
onTap: () {
241+
dateTypeOption.fold(() => null, (dateTypeOption) {
242+
final setting = _CalDateTimeSetting(dateTypeOption: dateTypeOption);
243+
setting.show(context);
244+
});
245+
},
246+
rightIcon: svgWidget("grid/more", color: theme.iconColor),
247+
);
246248
},
247-
rightIcon: svgWidget("grid/more", color: theme.iconColor),
248249
);
249250
}
250251
}
251252

252-
class _CalDateTimeSetting extends StatelessWidget {
253+
class _CalDateTimeSetting extends StatefulWidget {
253254
final DateTypeOption dateTypeOption;
254255
const _CalDateTimeSetting({required this.dateTypeOption, Key? key}) : super(key: key);
255256

257+
@override
258+
State<_CalDateTimeSetting> createState() => _CalDateTimeSettingState();
259+
260+
static String identifier() {
261+
return (_CalDateTimeSetting).toString();
262+
}
263+
264+
void show(BuildContext context) {
265+
FlowyOverlay.of(context).insertWithAnchor(
266+
widget: OverlayContainer(
267+
child: this,
268+
constraints: BoxConstraints.loose(const Size(140, 100)),
269+
),
270+
identifier: _CalDateTimeSetting.identifier(),
271+
anchorContext: context,
272+
anchorDirection: AnchorDirection.rightWithCenterAligned,
273+
);
274+
}
275+
}
276+
277+
class _CalDateTimeSettingState extends State<_CalDateTimeSetting> {
278+
String? overlayIdentifier;
279+
256280
@override
257281
Widget build(BuildContext context) {
258-
return Column(children: [
282+
List<Widget> children = [
259283
DateFormatButton(onTap: () {
260284
final list = DateFormatList(
261-
selectedFormat: dateTypeOption.dateFormat,
285+
selectedFormat: widget.dateTypeOption.dateFormat,
262286
onSelected: (format) {
263-
context.read<DateTypeOptionBloc>().add(DateTypeOptionEvent.didSelectDateFormat(format));
287+
context.read<DateCalBloc>().add(DateCalEvent.setDateFormat(format));
264288
},
265289
);
290+
_showOverlay(context, list);
266291
}),
267292
TimeFormatButton(
268-
timeFormat: dateTypeOption.timeFormat,
293+
timeFormat: widget.dateTypeOption.timeFormat,
269294
onTap: () {
270295
final list = TimeFormatList(
271-
selectedFormat: dateTypeOption.timeFormat,
272-
onSelected: (format) {
273-
context.read<DateTypeOptionBloc>().add(DateTypeOptionEvent.didSelectTimeFormat(format));
274-
});
296+
selectedFormat: widget.dateTypeOption.timeFormat,
297+
onSelected: (format) {
298+
context.read<DateCalBloc>().add(DateCalEvent.setTimeFormat(format));
299+
},
300+
);
301+
_showOverlay(context, list);
302+
},
303+
),
304+
];
305+
306+
return SizedBox(
307+
width: 180,
308+
child: ListView.separated(
309+
shrinkWrap: true,
310+
controller: ScrollController(),
311+
separatorBuilder: (context, index) {
312+
return VSpace(GridSize.typeOptionSeparatorHeight);
313+
},
314+
itemCount: children.length,
315+
itemBuilder: (BuildContext context, int index) {
316+
return children[index];
275317
},
276318
),
277-
]);
319+
);
278320
}
279321

280-
void show(BuildContext context) {}
322+
void _showOverlay(BuildContext context, Widget child) {
323+
if (overlayIdentifier != null) {
324+
FlowyOverlay.of(context).remove(overlayIdentifier!);
325+
}
326+
327+
overlayIdentifier = child.toString();
328+
FlowyOverlay.of(context).insertWithAnchor(
329+
widget: OverlayContainer(
330+
child: child,
331+
constraints: BoxConstraints.loose(const Size(460, 440)),
332+
),
333+
identifier: overlayIdentifier!,
334+
anchorContext: context,
335+
anchorDirection: AnchorDirection.rightWithCenterAligned,
336+
style: FlowyOverlayStyle(blur: false),
337+
anchorOffset: const Offset(-20, 0),
338+
);
339+
}
281340
}

0 commit comments

Comments
 (0)