refactor: database field type option (#4136)

* refactor: include field type option in FieldPB

* refactor: adapt changes on flutter

* refactor: adapt changes on new tauri grid

* refactor: adapt changes on old tauri grid/board

* chore: merge
This commit is contained in:
Richard Shiue
2023-12-20 11:11:38 +08:00
committed by GitHub
parent 9a1ea138fc
commit d68c847d59
73 changed files with 1326 additions and 2459 deletions

View File

@ -4,13 +4,9 @@ import 'package:appflowy/mobile/presentation/bottom_sheet/bottom_sheet.dart';
import 'package:appflowy/mobile/presentation/widgets/widgets.dart';
import 'package:appflowy/plugins/base/drag_handler.dart';
import 'package:appflowy/plugins/database_view/application/cell/cell_controller_builder.dart';
import 'package:appflowy/plugins/database_view/application/field/type_option/type_option_context.dart';
import 'package:appflowy/plugins/database_view/widgets/row/cells/date_cell/date_cal_bloc.dart';
import 'package:appflowy/plugins/database_view/widgets/row/cells/date_cell/date_cell_editor_bloc.dart';
import 'package:appflowy/plugins/database_view/widgets/row/cells/date_cell/mobile_date_editor.dart';
import 'package:appflowy_backend/log.dart';
import 'package:appflowy_backend/protobuf/flowy-database2/date_entities.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
import 'package:dartz/dartz.dart' hide State;
import 'package:easy_localization/easy_localization.dart';
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
import 'package:flutter/cupertino.dart';
@ -41,17 +37,6 @@ class MobileDateCellEditScreen extends StatefulWidget {
}
class _MobileDateCellEditScreenState extends State<MobileDateCellEditScreen> {
late final Future<Either<dynamic, FlowyError>> typeOptionFuture;
@override
void initState() {
super.initState();
typeOptionFuture = widget.controller.getTypeOption(
DateTypeOptionDataParser(),
);
}
@override
Widget build(BuildContext context) {
return widget.showAsFullScreen ? _buildFullScreen() : _buildNotFullScreen();
@ -64,7 +49,9 @@ class _MobileDateCellEditScreenState extends State<MobileDateCellEditScreen> {
LocaleKeys.titleBar_date.tr(),
),
),
body: _buildBody(),
body: _DateCellEditBody(
dateCellController: widget.controller,
),
);
}
@ -86,7 +73,9 @@ class _MobileDateCellEditScreenState extends State<MobileDateCellEditScreen> {
),
_buildHeader(),
Expanded(
child: _buildBody(),
child: _DateCellEditBody(
dateCellController: widget.controller,
),
),
],
),
@ -94,36 +83,6 @@ class _MobileDateCellEditScreenState extends State<MobileDateCellEditScreen> {
);
}
Widget _buildBody() {
return FutureBuilder<Either<dynamic, FlowyError>>(
future: typeOptionFuture,
builder: (context, snapshot) {
final data = snapshot.data;
if (data == null) {
return const Center(
child: CircularProgressIndicator.adaptive(),
);
}
return data.fold(
(dateTypeOptionPB) {
return _DateCellEditBody(
dateCellController: widget.controller,
dateTypeOptionPB: dateTypeOptionPB,
);
},
(err) {
Log.error(err);
return FlowyMobileStateContainer.error(
title: LocaleKeys.grid_field_failedToLoadDate.tr(),
errorMsg: err.toString(),
);
},
);
},
);
}
Widget _buildHeader() {
const iconWidth = 30.0;
const height = 44.0;
@ -160,20 +119,16 @@ class _MobileDateCellEditScreenState extends State<MobileDateCellEditScreen> {
class _DateCellEditBody extends StatelessWidget {
const _DateCellEditBody({
required this.dateCellController,
required this.dateTypeOptionPB,
});
final DateCellController dateCellController;
final DateTypeOptionPB dateTypeOptionPB;
@override
Widget build(BuildContext context) {
return BlocProvider(
create: (context) => DateCellCalendarBloc(
dateTypeOptionPB: dateTypeOptionPB,
cellData: dateCellController.getCellData(),
create: (context) => DateCellEditorBloc(
cellController: dateCellController,
)..add(const DateCellCalendarEvent.initial()),
)..add(const DateCellEditorEvent.initial()),
child: const Column(
children: [
FlowyOptionDecorateBox(
@ -217,7 +172,7 @@ class _IncludeTimePickerState extends State<_IncludeTimePicker> {
@override
Widget build(BuildContext context) {
return BlocBuilder<DateCellCalendarBloc, DateCellCalendarState>(
return BlocBuilder<DateCellEditorBloc, DateCellEditorState>(
builder: (context, state) {
final startDay = state.dateStr;
final endDay = state.endDateStr;
@ -306,7 +261,7 @@ class _IncludeTimePickerState extends State<_IncludeTimePicker> {
return GestureDetector(
onTap: () async {
final bloc = context.read<DateCellCalendarBloc>();
final bloc = context.read<DateCellEditorBloc>();
await showMobileBottomSheet(
context,
builder: (context) {
@ -331,8 +286,8 @@ class _IncludeTimePickerState extends State<_IncludeTimePicker> {
if (_selectedTime != null) {
bloc.add(
isStartDay
? DateCellCalendarEvent.setTime(_selectedTime!)
: DateCellCalendarEvent.setEndTime(_selectedTime!),
? DateCellEditorEvent.setTime(_selectedTime!)
: DateCellEditorEvent.setEndTime(_selectedTime!),
);
}
},
@ -361,7 +316,7 @@ class _EndDateSwitch extends StatelessWidget {
@override
Widget build(BuildContext context) {
return BlocSelector<DateCellCalendarBloc, DateCellCalendarState, bool>(
return BlocSelector<DateCellEditorBloc, DateCellEditorState, bool>(
selector: (state) => state.isRange,
builder: (context, isRange) {
return FlowyOptionTile.toggle(
@ -369,8 +324,8 @@ class _EndDateSwitch extends StatelessWidget {
isSelected: isRange,
onValueChanged: (value) {
context
.read<DateCellCalendarBloc>()
.add(DateCellCalendarEvent.setIsRange(value));
.read<DateCellEditorBloc>()
.add(DateCellEditorEvent.setIsRange(value));
},
);
},
@ -383,7 +338,7 @@ class _IncludeTimeSwitch extends StatelessWidget {
@override
Widget build(BuildContext context) {
return BlocSelector<DateCellCalendarBloc, DateCellCalendarState, bool>(
return BlocSelector<DateCellEditorBloc, DateCellEditorState, bool>(
selector: (state) => state.includeTime,
builder: (context, includeTime) {
return FlowyOptionTile.toggle(
@ -392,8 +347,8 @@ class _IncludeTimeSwitch extends StatelessWidget {
isSelected: includeTime,
onValueChanged: (value) {
context
.read<DateCellCalendarBloc>()
.add(DateCellCalendarEvent.setIncludeTime(value));
.read<DateCellEditorBloc>()
.add(DateCellEditorEvent.setIncludeTime(value));
},
);
},
@ -420,7 +375,7 @@ class _TimeTextFieldState extends State<_TimeTextField> {
@override
Widget build(BuildContext context) {
return BlocConsumer<DateCellCalendarBloc, DateCellCalendarState>(
return BlocConsumer<DateCellEditorBloc, DateCellEditorState>(
listener: (context, state) {
_textController.text =
widget.isEndTime ? state.endTimeStr ?? "" : state.timeStr ?? "";
@ -437,10 +392,10 @@ class _TimeTextFieldState extends State<_TimeTextField> {
),
keyboardType: TextInputType.datetime,
onFieldSubmitted: (timeStr) {
context.read<DateCellCalendarBloc>().add(
context.read<DateCellEditorBloc>().add(
widget.isEndTime
? DateCellCalendarEvent.setEndTime(timeStr)
: DateCellCalendarEvent.setTime(timeStr),
? DateCellEditorEvent.setEndTime(timeStr)
: DateCellEditorEvent.setTime(timeStr),
);
},
);
@ -463,8 +418,8 @@ class _ClearDateButton extends StatelessWidget {
return FlowyOptionTile.text(
text: LocaleKeys.grid_field_clearDate.tr(),
onTap: () => context
.read<DateCellCalendarBloc>()
.add(const DateCellCalendarEvent.clearDate()),
.read<DateCellEditorBloc>()
.add(const DateCellEditorEvent.clearDate()),
);
}
}

View File

@ -28,19 +28,12 @@ class MobileEditPropertyScreen extends StatefulWidget {
}
class _MobileEditPropertyScreenState extends State<MobileEditPropertyScreen> {
late Future<FieldOptionValues?> future;
FieldOptionValues? optionValues;
late FieldOptionValues optionValues;
@override
void initState() {
super.initState();
future = FieldOptionValues.get(
viewId: widget.viewId,
fieldId: widget.field.id,
fieldType: widget.field.fieldType,
);
optionValues = FieldOptionValues.fromField(field: widget.field);
}
@override
@ -66,39 +59,30 @@ class _MobileEditPropertyScreenState extends State<MobileEditPropertyScreen> {
),
],
),
body: FutureBuilder<FieldOptionValues?>(
future: future,
builder: (context, snapshot) {
final optionValues = snapshot.data;
if (optionValues == null) {
return const Center(child: CircularProgressIndicator.adaptive());
}
return FieldOptionEditor(
mode: FieldOptionMode.edit,
isPrimary: widget.field.isPrimary,
defaultValues: optionValues,
onOptionValuesChanged: (optionValues) {
this.optionValues = optionValues;
},
onAction: (action) {
final service = FieldServices(
viewId: viewId,
fieldId: fieldId,
);
switch (action) {
case FieldOptionAction.delete:
service.delete();
break;
case FieldOptionAction.duplicate:
service.duplicate();
break;
case FieldOptionAction.hide:
service.hide();
break;
}
context.pop();
},
body: FieldOptionEditor(
mode: FieldOptionMode.edit,
isPrimary: widget.field.isPrimary,
defaultValues: optionValues,
onOptionValuesChanged: (optionValues) {
this.optionValues = optionValues;
},
onAction: (action) {
final service = FieldServices(
viewId: viewId,
fieldId: fieldId,
);
switch (action) {
case FieldOptionAction.delete:
service.delete();
break;
case FieldOptionAction.duplicate:
service.duplicate();
break;
case FieldOptionAction.hide:
service.hide();
break;
}
context.pop();
},
),
);

View File

@ -9,7 +9,7 @@ import 'package:appflowy/mobile/presentation/database/card/card_detail/widgets/w
import 'package:appflowy/mobile/presentation/widgets/widgets.dart';
import 'package:appflowy/plugins/database_view/application/field/field_service.dart';
import 'package:appflowy/plugins/database_view/application/field/type_option/number_format_bloc.dart';
import 'package:appflowy/plugins/database_view/grid/presentation/widgets/header/type_option/date.dart';
import 'package:appflowy/plugins/database_view/grid/presentation/widgets/header/type_option/date/date_time_format.dart';
import 'package:appflowy/plugins/database_view/widgets/row/cells/select_option_cell/extension.dart';
import 'package:appflowy/util/field_type_extension.dart';
import 'package:appflowy_backend/protobuf/flowy-database2/protobuf.dart';
@ -94,39 +94,30 @@ class FieldOptionValues {
}
}
static Future<FieldOptionValues?> get({
required String viewId,
required String fieldId,
required FieldType fieldType,
}) async {
final service = FieldBackendService(viewId: viewId, fieldId: fieldId);
final result = await service.getFieldTypeOptionData(fieldType: fieldType);
return result.fold(
(option) {
final type = option.field_2.fieldType;
final buffer = option.typeOptionData;
return FieldOptionValues(
type: type,
name: option.field_2.name,
numberFormat: type == FieldType.Number
? NumberTypeOptionPB.fromBuffer(buffer).format
: null,
dateFormate: type == FieldType.DateTime
? DateTypeOptionPB.fromBuffer(buffer).dateFormat
: null,
timeFormat: type == FieldType.DateTime
? DateTypeOptionPB.fromBuffer(buffer).timeFormat
: null,
selectOption: switch (type) {
FieldType.SingleSelect =>
SingleSelectTypeOptionPB.fromBuffer(buffer).options,
FieldType.MultiSelect =>
MultiSelectTypeOptionPB.fromBuffer(buffer).options,
_ => [],
},
);
factory FieldOptionValues.fromField({
required FieldPB field,
}) {
final fieldType = field.fieldType;
final buffer = field.typeOptionData;
return FieldOptionValues(
type: fieldType,
name: field.name,
numberFormat: fieldType == FieldType.Number
? NumberTypeOptionPB.fromBuffer(buffer).format
: null,
dateFormate: fieldType == FieldType.DateTime
? DateTypeOptionPB.fromBuffer(buffer).dateFormat
: null,
timeFormat: fieldType == FieldType.DateTime
? DateTypeOptionPB.fromBuffer(buffer).timeFormat
: null,
selectOption: switch (fieldType) {
FieldType.SingleSelect =>
SingleSelectTypeOptionPB.fromBuffer(buffer).options,
FieldType.MultiSelect =>
MultiSelectTypeOptionPB.fromBuffer(buffer).options,
_ => [],
},
(error) => null,
);
}
}