From 2b745bc41a4a8cdfe5526d3dece9be44383c9b6a Mon Sep 17 00:00:00 2001 From: appflowy Date: Wed, 10 Aug 2022 16:03:41 +0800 Subject: [PATCH] chore: read single select data from board --- .../plugins/board/application/board_bloc.dart | 39 +-- .../board/presentation/board_page.dart | 1 - .../cell/cell_service/cell_service.dart | 2 +- .../cell/select_option_service.dart | 2 +- .../application/field/field_editor_bloc.dart | 5 +- .../grid/application/field/field_service.dart | 154 ------------ .../field/field_type_option_edit_bloc.dart | 14 +- .../field/type_option/date_bloc.dart | 5 +- .../type_option/multi_select_type_option.dart | 12 +- .../field/type_option/number_bloc.dart | 4 +- .../select_option_type_option_bloc.dart | 29 ++- .../single_select_type_option.dart | 10 +- .../type_option_data_controller.dart | 223 ++++++++++++++++++ .../type_option/type_option_service.dart | 85 +------ .../widgets/header/field_cell.dart | 1 + .../widgets/header/field_editor.dart | 2 +- .../header/field_type_option_editor.dart | 3 +- .../widgets/header/grid_header.dart | 1 + .../widgets/header/type_option/builder.dart | 160 ++++++++++--- .../widgets/header/type_option/checkbox.dart | 4 +- .../widgets/header/type_option/rich_text.dart | 4 +- .../widgets/header/type_option/url.dart | 4 +- .../presentation/widgets/row/row_detail.dart | 2 +- .../widgets/toolbar/grid_property.dart | 2 +- 24 files changed, 430 insertions(+), 338 deletions(-) create mode 100644 frontend/app_flowy/lib/plugins/grid/application/field/type_option/type_option_data_controller.dart diff --git a/frontend/app_flowy/lib/plugins/board/application/board_bloc.dart b/frontend/app_flowy/lib/plugins/board/application/board_bloc.dart index 1d73e247d0..a2ce5e043f 100644 --- a/frontend/app_flowy/lib/plugins/board/application/board_bloc.dart +++ b/frontend/app_flowy/lib/plugins/board/application/board_bloc.dart @@ -2,6 +2,7 @@ import 'dart:async'; import 'package:app_flowy/plugins/grid/application/block/block_cache.dart'; import 'package:app_flowy/plugins/grid/application/grid_data_controller.dart'; import 'package:app_flowy/plugins/grid/application/row/row_cache.dart'; +import 'package:app_flowy/plugins/grid/presentation/widgets/header/type_option/builder.dart'; import 'package:appflowy_board/appflowy_board.dart'; import 'package:dartz/dartz.dart'; import 'package:equatable/equatable.dart'; @@ -101,31 +102,33 @@ class BoardBloc extends Bloc { } void _buildColumns(UnmodifiableListView fields) { - List columns = []; - for (final field in fields) { if (field.fieldType == FieldType.SingleSelect) { - // return BoardColumnData(customData: field, id: field.id, desc: "1"); + _buildColumnsFromSingleSelect(field); } } + } - boardDataController.addColumns(columns); + void _buildColumnsFromSingleSelect(GridFieldPB field) { + final typeOptionContext = makeTypeOptionContext( + gridId: _gridDataController.gridId, + field: field, + ); - // final column1 = BoardColumnData(id: "To Do", items: [ - // TextItem("Card 1"), - // TextItem("Card 2"), - // RichTextItem(title: "Card 3", subtitle: 'Aug 1, 2020 4:05 PM'), - // TextItem("Card 4"), - // ]); - // final column2 = BoardColumnData(id: "In Progress", items: [ - // RichTextItem(title: "Card 5", subtitle: 'Aug 1, 2020 4:05 PM'), - // TextItem("Card 6"), - // ]); + typeOptionContext.loadTypeOptionData( + onCompleted: (singleSelect) { + List columns = singleSelect.options.map((option) { + return BoardColumnData( + id: option.id, + desc: option.name, + customData: option, + ); + }).toList(); - // final column3 = BoardColumnData(id: "Done", items: []); - // boardDataController.addColumn(column1); - // boardDataController.addColumn(column2); - // boardDataController.addColumn(column3); + boardDataController.addColumns(columns); + }, + onError: (err) {}, + ); } Future _loadGrid(Emitter emit) async { diff --git a/frontend/app_flowy/lib/plugins/board/presentation/board_page.dart b/frontend/app_flowy/lib/plugins/board/presentation/board_page.dart index 570c1207df..f961eeaf42 100644 --- a/frontend/app_flowy/lib/plugins/board/presentation/board_page.dart +++ b/frontend/app_flowy/lib/plugins/board/presentation/board_page.dart @@ -3,7 +3,6 @@ import 'package:appflowy_board/appflowy_board.dart'; import 'package:flowy_infra_ui/widget/error_page.dart'; import 'package:flowy_sdk/protobuf/flowy-folder/view.pb.dart'; -import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import '../application/board_bloc.dart'; diff --git a/frontend/app_flowy/lib/plugins/grid/application/cell/cell_service/cell_service.dart b/frontend/app_flowy/lib/plugins/grid/application/cell/cell_service/cell_service.dart index 106db1e754..78b6551f0f 100644 --- a/frontend/app_flowy/lib/plugins/grid/application/cell/cell_service/cell_service.dart +++ b/frontend/app_flowy/lib/plugins/grid/application/cell/cell_service/cell_service.dart @@ -17,7 +17,7 @@ import 'package:app_flowy/plugins/grid/application/field/field_service.dart'; import 'dart:convert' show utf8; import '../../field/field_cache.dart'; -import '../../field/type_option/type_option_service.dart'; +import '../../field/type_option/type_option_data_controller.dart'; import 'cell_field_notifier.dart'; part 'cell_service.freezed.dart'; part 'cell_data_loader.dart'; diff --git a/frontend/app_flowy/lib/plugins/grid/application/cell/select_option_service.dart b/frontend/app_flowy/lib/plugins/grid/application/cell/select_option_service.dart index 9172450ef0..da1fc47170 100644 --- a/frontend/app_flowy/lib/plugins/grid/application/cell/select_option_service.dart +++ b/frontend/app_flowy/lib/plugins/grid/application/cell/select_option_service.dart @@ -15,7 +15,7 @@ class SelectOptionService { String get rowId => cellId.rowId; Future> create({required String name}) { - return TypeOptionService(gridId: gridId, fieldId: fieldId) + return TypeOptionFFIService(gridId: gridId, fieldId: fieldId) .newOption(name: name) .then( (result) { diff --git a/frontend/app_flowy/lib/plugins/grid/application/field/field_editor_bloc.dart b/frontend/app_flowy/lib/plugins/grid/application/field/field_editor_bloc.dart index 57e04cbaf4..05c61eaf55 100644 --- a/frontend/app_flowy/lib/plugins/grid/application/field/field_editor_bloc.dart +++ b/frontend/app_flowy/lib/plugins/grid/application/field/field_editor_bloc.dart @@ -1,9 +1,10 @@ import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:freezed_annotation/freezed_annotation.dart'; import 'dart:async'; -import 'field_service.dart'; import 'package:dartz/dartz.dart'; +import 'type_option/type_option_data_controller.dart'; +import 'package:freezed_annotation/freezed_annotation.dart'; + part 'field_editor_bloc.freezed.dart'; class FieldEditorBloc extends Bloc { diff --git a/frontend/app_flowy/lib/plugins/grid/application/field/field_service.dart b/frontend/app_flowy/lib/plugins/grid/application/field/field_service.dart index cf4f374a09..39cdccb9ab 100644 --- a/frontend/app_flowy/lib/plugins/grid/application/field/field_service.dart +++ b/frontend/app_flowy/lib/plugins/grid/application/field/field_service.dart @@ -141,157 +141,3 @@ class GridFieldCellContext with _$GridFieldCellContext { required GridFieldPB field, }) = _GridFieldCellContext; } - -abstract class IFieldTypeOptionLoader { - String get gridId; - Future> load(); - - Future> switchToField( - String fieldId, FieldType fieldType) { - final payload = EditFieldPayloadPB.create() - ..gridId = gridId - ..fieldId = fieldId - ..fieldType = fieldType; - - return GridEventSwitchToField(payload).send(); - } -} - -class NewFieldTypeOptionLoader extends IFieldTypeOptionLoader { - @override - final String gridId; - NewFieldTypeOptionLoader({ - required this.gridId, - }); - - @override - Future> load() { - final payload = CreateFieldPayloadPB.create() - ..gridId = gridId - ..fieldType = FieldType.RichText; - - return GridEventCreateFieldTypeOption(payload).send(); - } -} - -class FieldTypeOptionLoader extends IFieldTypeOptionLoader { - @override - final String gridId; - final GridFieldPB field; - - FieldTypeOptionLoader({ - required this.gridId, - required this.field, - }); - - @override - Future> load() { - final payload = GridFieldTypeOptionIdPB.create() - ..gridId = gridId - ..fieldId = field.id - ..fieldType = field.fieldType; - - return GridEventGetFieldTypeOption(payload).send(); - } -} - -class TypeOptionDataController { - final String gridId; - final IFieldTypeOptionLoader _loader; - - late FieldTypeOptionDataPB _data; - final PublishNotifier _fieldNotifier = PublishNotifier(); - - TypeOptionDataController({ - required this.gridId, - required IFieldTypeOptionLoader loader, - }) : _loader = loader; - - Future> loadTypeOptionData() async { - final result = await _loader.load(); - return result.fold( - (data) { - data.freeze(); - _data = data; - _fieldNotifier.value = data.field_2; - return left(unit); - }, - (err) { - Log.error(err); - return right(err); - }, - ); - } - - GridFieldPB get field => _data.field_2; - - set field(GridFieldPB field) { - _updateData(newField: field); - } - - List get typeOptionData => _data.typeOptionData; - - set fieldName(String name) { - _updateData(newName: name); - } - - set typeOptionData(List typeOptionData) { - _updateData(newTypeOptionData: typeOptionData); - } - - void _updateData( - {String? newName, GridFieldPB? newField, List? newTypeOptionData}) { - _data = _data.rebuild((rebuildData) { - if (newName != null) { - rebuildData.field_2 = rebuildData.field_2.rebuild((rebuildField) { - rebuildField.name = newName; - }); - } - - if (newField != null) { - rebuildData.field_2 = newField; - } - - if (newTypeOptionData != null) { - rebuildData.typeOptionData = newTypeOptionData; - } - }); - - _fieldNotifier.value = _data.field_2; - - FieldService.insertField( - gridId: gridId, - field: field, - typeOptionData: typeOptionData, - ); - } - - Future switchToField(FieldType newFieldType) { - return _loader.switchToField(field.id, newFieldType).then((result) { - return result.fold( - (fieldTypeOptionData) { - _updateData( - newField: fieldTypeOptionData.field_2, - newTypeOptionData: fieldTypeOptionData.typeOptionData, - ); - }, - (err) { - Log.error(err); - }, - ); - }); - } - - void Function() addFieldListener(void Function(GridFieldPB) callback) { - listener() { - callback(field); - } - - _fieldNotifier.addListener(listener); - return listener; - } - - void removeFieldListener(void Function() listener) { - _fieldNotifier.removeListener(listener); - } -} diff --git a/frontend/app_flowy/lib/plugins/grid/application/field/field_type_option_edit_bloc.dart b/frontend/app_flowy/lib/plugins/grid/application/field/field_type_option_edit_bloc.dart index e098f87d86..ec18c7e5b5 100644 --- a/frontend/app_flowy/lib/plugins/grid/application/field/field_type_option_edit_bloc.dart +++ b/frontend/app_flowy/lib/plugins/grid/application/field/field_type_option_edit_bloc.dart @@ -2,12 +2,11 @@ import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; import 'dart:async'; - -import 'field_service.dart'; - +import 'type_option/type_option_data_controller.dart'; part 'field_type_option_edit_bloc.freezed.dart'; -class FieldTypeOptionEditBloc extends Bloc { +class FieldTypeOptionEditBloc + extends Bloc { final TypeOptionDataController _dataController; void Function()? _fieldListenFn; @@ -42,7 +41,8 @@ class FieldTypeOptionEditBloc extends Bloc FieldTypeOptionEditState( + factory FieldTypeOptionEditState.initial( + TypeOptionDataController fieldContext) => + FieldTypeOptionEditState( field: fieldContext.field, ); } diff --git a/frontend/app_flowy/lib/plugins/grid/application/field/type_option/date_bloc.dart b/frontend/app_flowy/lib/plugins/grid/application/field/type_option/date_bloc.dart index f995a0bad0..15c052060d 100644 --- a/frontend/app_flowy/lib/plugins/grid/application/field/type_option/date_bloc.dart +++ b/frontend/app_flowy/lib/plugins/grid/application/field/type_option/date_bloc.dart @@ -1,13 +1,14 @@ -import 'package:app_flowy/plugins/grid/application/field/type_option/type_option_service.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/date_type_option.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/date_type_option_entities.pb.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; import 'dart:async'; import 'package:protobuf/protobuf.dart'; + +import 'type_option_data_controller.dart'; part 'date_bloc.freezed.dart'; -typedef DateTypeOptionContext = TypeOptionWidgetContext; +typedef DateTypeOptionContext = TypeOptionContext; class DateTypeOptionDataParser extends TypeOptionDataParser { @override diff --git a/frontend/app_flowy/lib/plugins/grid/application/field/type_option/multi_select_type_option.dart b/frontend/app_flowy/lib/plugins/grid/application/field/type_option/multi_select_type_option.dart index 2f7d2dbc5a..a05e5ea2ff 100644 --- a/frontend/app_flowy/lib/plugins/grid/application/field/type_option/multi_select_type_option.dart +++ b/frontend/app_flowy/lib/plugins/grid/application/field/type_option/multi_select_type_option.dart @@ -1,21 +1,21 @@ -import 'package:app_flowy/plugins/grid/application/field/field_service.dart'; import 'package:flowy_sdk/log.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/multi_select_type_option.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/select_option.pb.dart'; import 'dart:async'; -import 'package:protobuf/protobuf.dart'; import 'select_option_type_option_bloc.dart'; +import 'type_option_data_controller.dart'; import 'type_option_service.dart'; +import 'package:protobuf/protobuf.dart'; class MultiSelectTypeOptionContext - extends TypeOptionWidgetContext + extends TypeOptionContext with SelectOptionTypeOptionAction { - final TypeOptionService service; + final TypeOptionFFIService service; MultiSelectTypeOptionContext({ required MultiSelectTypeOptionWidgetDataParser dataParser, required TypeOptionDataController dataController, - }) : service = TypeOptionService( + }) : service = TypeOptionFFIService( gridId: dataController.gridId, fieldId: dataController.field.id, ), @@ -59,7 +59,7 @@ class MultiSelectTypeOptionContext } @override - List Function(SelectOptionPB) get udpateOption { + List Function(SelectOptionPB) get updateOption { return (SelectOptionPB option) { typeOption.freeze(); typeOption = typeOption.rebuild((typeOption) { diff --git a/frontend/app_flowy/lib/plugins/grid/application/field/type_option/number_bloc.dart b/frontend/app_flowy/lib/plugins/grid/application/field/type_option/number_bloc.dart index 7228adf90e..fc3d8b0822 100644 --- a/frontend/app_flowy/lib/plugins/grid/application/field/type_option/number_bloc.dart +++ b/frontend/app_flowy/lib/plugins/grid/application/field/type_option/number_bloc.dart @@ -1,14 +1,14 @@ -import 'package:app_flowy/plugins/grid/application/field/type_option/type_option_service.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/format.pbenum.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/number_type_option.pb.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; import 'dart:async'; import 'package:protobuf/protobuf.dart'; +import 'type_option_data_controller.dart'; part 'number_bloc.freezed.dart'; -typedef NumberTypeOptionContext = TypeOptionWidgetContext; +typedef NumberTypeOptionContext = TypeOptionContext; class NumberTypeOptionWidgetDataParser extends TypeOptionDataParser { diff --git a/frontend/app_flowy/lib/plugins/grid/application/field/type_option/select_option_type_option_bloc.dart b/frontend/app_flowy/lib/plugins/grid/application/field/type_option/select_option_type_option_bloc.dart index b77b9b86cd..6e4aca6cc9 100644 --- a/frontend/app_flowy/lib/plugins/grid/application/field/type_option/select_option_type_option_bloc.dart +++ b/frontend/app_flowy/lib/plugins/grid/application/field/type_option/select_option_type_option_bloc.dart @@ -10,10 +10,11 @@ abstract class SelectOptionTypeOptionAction { List Function(SelectOptionPB) get deleteOption; - List Function(SelectOptionPB) get udpateOption; + List Function(SelectOptionPB) get updateOption; } -class SelectOptionTypeOptionBloc extends Bloc { +class SelectOptionTypeOptionBloc + extends Bloc { final SelectOptionTypeOptionAction typeOptionAction; SelectOptionTypeOptionBloc({ @@ -24,7 +25,8 @@ class SelectOptionTypeOptionBloc extends Bloc options = await typeOptionAction.insertOption(optionName); + final List options = + await typeOptionAction.insertOption(optionName); emit(state.copyWith(options: options)); }, addingOption: () { @@ -34,11 +36,13 @@ class SelectOptionTypeOptionBloc extends Bloc options = typeOptionAction.udpateOption(option); + final List options = + typeOptionAction.updateOption(option); emit(state.copyWith(options: options)); }, deleteOption: (option) { - final List options = typeOptionAction.deleteOption(option); + final List options = + typeOptionAction.deleteOption(option); emit(state.copyWith(options: options)); }, ); @@ -54,11 +58,15 @@ class SelectOptionTypeOptionBloc extends Bloc newOptionName, }) = _SelectOptionTyepOptionState; - factory SelectOptionTypeOptionState.initial(List options) => SelectOptionTypeOptionState( + factory SelectOptionTypeOptionState.initial(List options) => + SelectOptionTypeOptionState( options: options, isEditingOption: false, newOptionName: none(), diff --git a/frontend/app_flowy/lib/plugins/grid/application/field/type_option/single_select_type_option.dart b/frontend/app_flowy/lib/plugins/grid/application/field/type_option/single_select_type_option.dart index bc995a4237..e4de10a3ef 100644 --- a/frontend/app_flowy/lib/plugins/grid/application/field/type_option/single_select_type_option.dart +++ b/frontend/app_flowy/lib/plugins/grid/application/field/type_option/single_select_type_option.dart @@ -1,21 +1,21 @@ -import 'package:app_flowy/plugins/grid/application/field/field_service.dart'; import 'package:flowy_sdk/log.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/select_option.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/single_select_type_option.pb.dart'; import 'dart:async'; import 'package:protobuf/protobuf.dart'; import 'select_option_type_option_bloc.dart'; +import 'type_option_data_controller.dart'; import 'type_option_service.dart'; class SingleSelectTypeOptionContext - extends TypeOptionWidgetContext + extends TypeOptionContext with SelectOptionTypeOptionAction { - final TypeOptionService service; + final TypeOptionFFIService service; SingleSelectTypeOptionContext({ required SingleSelectTypeOptionWidgetDataParser dataBuilder, required TypeOptionDataController dataController, - }) : service = TypeOptionService( + }) : service = TypeOptionFFIService( gridId: dataController.gridId, fieldId: dataController.field.id, ), @@ -59,7 +59,7 @@ class SingleSelectTypeOptionContext } @override - List Function(SelectOptionPB) get udpateOption { + List Function(SelectOptionPB) get updateOption { return (SelectOptionPB option) { typeOption.freeze(); typeOption = typeOption.rebuild((typeOption) { diff --git a/frontend/app_flowy/lib/plugins/grid/application/field/type_option/type_option_data_controller.dart b/frontend/app_flowy/lib/plugins/grid/application/field/type_option/type_option_data_controller.dart new file mode 100644 index 0000000000..75b373f787 --- /dev/null +++ b/frontend/app_flowy/lib/plugins/grid/application/field/type_option/type_option_data_controller.dart @@ -0,0 +1,223 @@ +import 'package:flowy_infra/notifier.dart'; +import 'package:flowy_sdk/dispatch/dispatch.dart'; +import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart'; +import 'package:app_flowy/plugins/grid/application/field/field_service.dart'; +import 'package:dartz/dartz.dart'; +import 'package:protobuf/protobuf.dart'; +import 'package:flowy_sdk/log.dart'; + +abstract class TypeOptionDataParser { + T fromBuffer(List buffer); +} + +class TypeOptionContext { + T? _typeOptionObject; + final TypeOptionDataParser dataParser; + final TypeOptionDataController _dataController; + + TypeOptionContext({ + required this.dataParser, + required TypeOptionDataController dataController, + }) : _dataController = dataController; + + String get gridId => _dataController.gridId; + + Future loadTypeOptionData({ + required void Function(T) onCompleted, + required void Function(FlowyError) onError, + }) async { + await _dataController.loadTypeOptionData().then((result) { + result.fold((l) => null, (err) => onError(err)); + }); + + onCompleted(typeOption); + } + + T get typeOption { + if (_typeOptionObject != null) { + return _typeOptionObject!; + } + + final T object = _dataController.getTypeOption(dataParser); + _typeOptionObject = object; + return object; + } + + set typeOption(T typeOption) { + _dataController.typeOptionData = typeOption.writeToBuffer(); + _typeOptionObject = typeOption; + } +} + +abstract class TypeOptionFieldDelegate { + void onFieldChanged(void Function(String) callback); + void dispose(); +} + +abstract class IFieldTypeOptionLoader { + String get gridId; + Future> load(); + + Future> switchToField( + String fieldId, FieldType fieldType) { + final payload = EditFieldPayloadPB.create() + ..gridId = gridId + ..fieldId = fieldId + ..fieldType = fieldType; + + return GridEventSwitchToField(payload).send(); + } +} + +class NewFieldTypeOptionLoader extends IFieldTypeOptionLoader { + @override + final String gridId; + NewFieldTypeOptionLoader({ + required this.gridId, + }); + + @override + Future> load() { + final payload = CreateFieldPayloadPB.create() + ..gridId = gridId + ..fieldType = FieldType.RichText; + + return GridEventCreateFieldTypeOption(payload).send(); + } +} + +class FieldTypeOptionLoader extends IFieldTypeOptionLoader { + @override + final String gridId; + final GridFieldPB field; + + FieldTypeOptionLoader({ + required this.gridId, + required this.field, + }); + + @override + Future> load() { + final payload = GridFieldTypeOptionIdPB.create() + ..gridId = gridId + ..fieldId = field.id + ..fieldType = field.fieldType; + + return GridEventGetFieldTypeOption(payload).send(); + } +} + +class TypeOptionDataController { + final String gridId; + final IFieldTypeOptionLoader loader; + late FieldTypeOptionDataPB _data; + final PublishNotifier _fieldNotifier = PublishNotifier(); + + TypeOptionDataController({ + required this.gridId, + required this.loader, + GridFieldPB? field, + }) { + if (field != null) { + _data = FieldTypeOptionDataPB.create() + ..gridId = gridId + ..field_2 = field; + } + } + + Future> loadTypeOptionData() async { + final result = await loader.load(); + return result.fold( + (data) { + data.freeze(); + _data = data; + _fieldNotifier.value = data.field_2; + return left(unit); + }, + (err) { + Log.error(err); + return right(err); + }, + ); + } + + GridFieldPB get field { + return _data.field_2; + } + + set field(GridFieldPB field) { + _updateData(newField: field); + } + + T getTypeOption(TypeOptionDataParser parser) { + return parser.fromBuffer(_data.typeOptionData); + } + + set fieldName(String name) { + _updateData(newName: name); + } + + set typeOptionData(List typeOptionData) { + _updateData(newTypeOptionData: typeOptionData); + } + + void _updateData({ + String? newName, + GridFieldPB? newField, + List? newTypeOptionData, + }) { + _data = _data.rebuild((rebuildData) { + if (newName != null) { + rebuildData.field_2 = rebuildData.field_2.rebuild((rebuildField) { + rebuildField.name = newName; + }); + } + + if (newField != null) { + rebuildData.field_2 = newField; + } + + if (newTypeOptionData != null) { + rebuildData.typeOptionData = newTypeOptionData; + } + }); + + _fieldNotifier.value = _data.field_2; + + FieldService.insertField( + gridId: gridId, + field: field, + typeOptionData: _data.typeOptionData, + ); + } + + Future switchToField(FieldType newFieldType) { + return loader.switchToField(field.id, newFieldType).then((result) { + return result.fold( + (fieldTypeOptionData) { + _updateData( + newField: fieldTypeOptionData.field_2, + newTypeOptionData: fieldTypeOptionData.typeOptionData, + ); + }, + (err) { + Log.error(err); + }, + ); + }); + } + + void Function() addFieldListener(void Function(GridFieldPB) callback) { + listener() { + callback(field); + } + + _fieldNotifier.addListener(listener); + return listener; + } + + void removeFieldListener(void Function() listener) { + _fieldNotifier.removeListener(listener); + } +} diff --git a/frontend/app_flowy/lib/plugins/grid/application/field/type_option/type_option_service.dart b/frontend/app_flowy/lib/plugins/grid/application/field/type_option/type_option_service.dart index d7873e0c86..5407515f62 100644 --- a/frontend/app_flowy/lib/plugins/grid/application/field/type_option/type_option_service.dart +++ b/frontend/app_flowy/lib/plugins/grid/application/field/type_option/type_option_service.dart @@ -1,19 +1,14 @@ -import 'dart:typed_data'; - -import 'package:app_flowy/plugins/grid/application/field/field_service.dart'; import 'package:dartz/dartz.dart'; import 'package:flowy_sdk/dispatch/dispatch.dart'; import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/cell_entities.pb.dart'; -import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/select_option.pb.dart'; -import 'package:protobuf/protobuf.dart'; -class TypeOptionService { +class TypeOptionFFIService { final String gridId; final String fieldId; - TypeOptionService({ + TypeOptionFFIService({ required this.gridId, required this.fieldId, }); @@ -29,79 +24,3 @@ class TypeOptionService { return GridEventNewSelectOption(payload).send(); } } - -abstract class TypeOptionDataParser { - T fromBuffer(List buffer); -} - -class TypeOptionWidgetContext { - T? _typeOptionObject; - final TypeOptionDataController _dataController; - final TypeOptionDataParser dataParser; - - TypeOptionWidgetContext({ - required this.dataParser, - required TypeOptionDataController dataController, - }) : _dataController = dataController; - - String get gridId => _dataController.gridId; - - GridFieldPB get field => _dataController.field; - - T get typeOption { - if (_typeOptionObject != null) { - return _typeOptionObject!; - } - - final T object = dataParser.fromBuffer(_dataController.typeOptionData); - _typeOptionObject = object; - return object; - } - - set typeOption(T typeOption) { - _dataController.typeOptionData = typeOption.writeToBuffer(); - _typeOptionObject = typeOption; - } -} - -abstract class TypeOptionFieldDelegate { - void onFieldChanged(void Function(String) callback); - void dispose(); -} - -class TypeOptionContext2 { - final String gridId; - final GridFieldPB field; - final FieldService _fieldService; - T? _data; - final TypeOptionDataParser dataBuilder; - - TypeOptionContext2({ - required this.gridId, - required this.field, - required this.dataBuilder, - Uint8List? data, - }) : _fieldService = FieldService(gridId: gridId, fieldId: field.id) { - if (data != null) { - _data = dataBuilder.fromBuffer(data); - } - } - - Future> typeOptionData() { - if (_data != null) { - return Future(() => left(_data!)); - } - - return _fieldService - .getFieldTypeOptionData(fieldType: field.fieldType) - .then((result) { - return result.fold( - (data) { - _data = dataBuilder.fromBuffer(data.typeOptionData); - return left(_data!); - }, - (err) => right(err), - ); - }); - } -} diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/field_cell.dart b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/field_cell.dart index aec88f5eaf..f66d5bf6d8 100755 --- a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/field_cell.dart +++ b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/field_cell.dart @@ -1,5 +1,6 @@ import 'package:app_flowy/plugins/grid/application/field/field_cell_bloc.dart'; import 'package:app_flowy/plugins/grid/application/field/field_service.dart'; +import 'package:app_flowy/plugins/grid/application/field/type_option/type_option_data_controller.dart'; import 'package:flowy_infra/image.dart'; import 'package:flowy_infra/theme.dart'; import 'package:flowy_infra_ui/style_widget/button.dart'; diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/field_editor.dart b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/field_editor.dart index 30a76a34bb..1a9a0ead83 100644 --- a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/field_editor.dart +++ b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/field_editor.dart @@ -1,5 +1,5 @@ import 'package:app_flowy/plugins/grid/application/field/field_editor_bloc.dart'; -import 'package:app_flowy/plugins/grid/application/field/field_service.dart'; +import 'package:app_flowy/plugins/grid/application/field/type_option/type_option_data_controller.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart'; import 'package:flowy_infra_ui/style_widget/text.dart'; diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/field_type_option_editor.dart b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/field_type_option_editor.dart index c2a12bb7ad..50a218fd0d 100644 --- a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/field_type_option_editor.dart +++ b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/field_type_option_editor.dart @@ -1,4 +1,5 @@ import 'dart:typed_data'; +import 'package:app_flowy/plugins/grid/application/field/type_option/type_option_data_controller.dart'; import 'package:dartz/dartz.dart' show Either; import 'package:flowy_infra/image.dart'; import 'package:flowy_infra/theme.dart'; @@ -94,8 +95,8 @@ class _FieldTypeOptionEditorState extends State { return makeTypeOptionWidget( context: context, - dataController: widget.dataController, overlayDelegate: overlayDelegate, + dataController: widget.dataController, ); } diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/grid_header.dart b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/grid_header.dart index caa40b2e7a..cad7e300f8 100644 --- a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/grid_header.dart +++ b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/grid_header.dart @@ -1,4 +1,5 @@ import 'package:app_flowy/plugins/grid/application/field/field_cache.dart'; +import 'package:app_flowy/plugins/grid/application/field/type_option/type_option_data_controller.dart'; import 'package:app_flowy/startup/startup.dart'; import 'package:app_flowy/plugins/grid/application/prelude.dart'; import 'package:flowy_infra/image.dart'; diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/type_option/builder.dart b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/type_option/builder.dart index 787f2091a9..d89dc26a68 100644 --- a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/type_option/builder.dart +++ b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/type_option/builder.dart @@ -1,6 +1,15 @@ import 'dart:typed_data'; import 'package:app_flowy/plugins/grid/application/field/type_option/multi_select_type_option.dart'; +import 'package:app_flowy/plugins/grid/application/field/type_option/type_option_data_controller.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid/checkbox_type_option.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid/date_type_option.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid/multi_select_type_option.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid/number_type_option.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid/single_select_type_option.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid/text_type_option.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid/url_type_option.pb.dart'; +import 'package:protobuf/protobuf.dart'; import 'package:app_flowy/plugins/grid/application/prelude.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart'; import 'package:flutter/material.dart'; @@ -39,70 +48,147 @@ Widget? makeTypeOptionWidget({ required TypeOptionDataController dataController, required TypeOptionOverlayDelegate overlayDelegate, }) { - final builder = makeTypeOptionWidgetBuilder(dataController, overlayDelegate); + final builder = makeTypeOptionWidgetBuilder( + dataController: dataController, + overlayDelegate: overlayDelegate, + ); return builder.build(context); } -TypeOptionWidgetBuilder makeTypeOptionWidgetBuilder( - TypeOptionDataController dataController, - TypeOptionOverlayDelegate overlayDelegate, -) { +TypeOptionWidgetBuilder makeTypeOptionWidgetBuilder({ + required TypeOptionDataController dataController, + required TypeOptionOverlayDelegate overlayDelegate, +}) { + final gridId = dataController.gridId; + final fieldType = dataController.field.fieldType; + switch (dataController.field.fieldType) { case FieldType.Checkbox: - final context = CheckboxTypeOptionContext( - dataController: dataController, - dataParser: CheckboxTypeOptionWidgetDataParser(), + return CheckboxTypeOptionWidgetBuilder( + makeTypeOptionContextWithDataController( + gridId: gridId, + fieldType: fieldType, + dataController: dataController, + ), ); - return CheckboxTypeOptionWidgetBuilder(context); case FieldType.DateTime: - final context = DateTypeOptionContext( - dataController: dataController, - dataParser: DateTypeOptionDataParser(), - ); return DateTypeOptionWidgetBuilder( - context, + makeTypeOptionContextWithDataController( + gridId: gridId, + fieldType: fieldType, + dataController: dataController, + ), overlayDelegate, ); case FieldType.SingleSelect: - final context = SingleSelectTypeOptionContext( - dataController: dataController, - dataBuilder: SingleSelectTypeOptionWidgetDataParser(), - ); return SingleSelectTypeOptionWidgetBuilder( - context, + makeTypeOptionContextWithDataController( + gridId: gridId, + fieldType: fieldType, + dataController: dataController, + ) as SingleSelectTypeOptionContext, overlayDelegate, ); case FieldType.MultiSelect: - final context = MultiSelectTypeOptionContext( - dataController: dataController, - dataParser: MultiSelectTypeOptionWidgetDataParser(), - ); return MultiSelectTypeOptionWidgetBuilder( - context, + makeTypeOptionContextWithDataController( + gridId: gridId, + fieldType: fieldType, + dataController: dataController, + ) as MultiSelectTypeOptionContext, overlayDelegate, ); case FieldType.Number: - final context = NumberTypeOptionContext( - dataController: dataController, - dataParser: NumberTypeOptionWidgetDataParser(), - ); return NumberTypeOptionWidgetBuilder( - context, + makeTypeOptionContextWithDataController( + gridId: gridId, + fieldType: fieldType, + dataController: dataController, + ), overlayDelegate, ); case FieldType.RichText: - final context = RichTextTypeOptionContext( - dataController: dataController, - dataParser: RichTextTypeOptionWidgetDataParser(), + return RichTextTypeOptionWidgetBuilder( + makeTypeOptionContextWithDataController( + gridId: gridId, + fieldType: fieldType, + dataController: dataController, + ), ); - return RichTextTypeOptionWidgetBuilder(context); case FieldType.URL: - final context = URLTypeOptionContext( - dataController: dataController, - dataParser: URLTypeOptionWidgetDataParser(), + return URLTypeOptionWidgetBuilder( + makeTypeOptionContextWithDataController( + gridId: gridId, + fieldType: fieldType, + dataController: dataController, + ), ); - return URLTypeOptionWidgetBuilder(context); } throw UnimplementedError; } + +TypeOptionContext makeTypeOptionContext({ + required String gridId, + required GridFieldPB field, +}) { + final loader = FieldTypeOptionLoader(gridId: gridId, field: field); + final dataController = TypeOptionDataController( + gridId: gridId, + loader: loader, + field: field, + ); + return makeTypeOptionContextWithDataController( + gridId: gridId, + fieldType: field.fieldType, + dataController: dataController, + ); +} + +TypeOptionContext + makeTypeOptionContextWithDataController({ + required String gridId, + required FieldType fieldType, + required TypeOptionDataController dataController, +}) { + switch (fieldType) { + case FieldType.Checkbox: + return CheckboxTypeOptionContext( + dataController: dataController, + dataParser: CheckboxTypeOptionWidgetDataParser(), + ) as TypeOptionContext; + case FieldType.DateTime: + return DateTypeOptionContext( + dataController: dataController, + dataParser: DateTypeOptionDataParser(), + ) as TypeOptionContext; + case FieldType.SingleSelect: + return SingleSelectTypeOptionContext( + dataController: dataController, + dataBuilder: SingleSelectTypeOptionWidgetDataParser(), + ) as TypeOptionContext; + case FieldType.MultiSelect: + return MultiSelectTypeOptionContext( + dataController: dataController, + dataParser: MultiSelectTypeOptionWidgetDataParser(), + ) as TypeOptionContext; + case FieldType.Number: + return NumberTypeOptionContext( + dataController: dataController, + dataParser: NumberTypeOptionWidgetDataParser(), + ) as TypeOptionContext; + case FieldType.RichText: + return RichTextTypeOptionContext( + dataController: dataController, + dataParser: RichTextTypeOptionWidgetDataParser(), + ) as TypeOptionContext; + + case FieldType.URL: + return URLTypeOptionContext( + dataController: dataController, + dataParser: URLTypeOptionWidgetDataParser(), + ) as TypeOptionContext; + } + + throw UnimplementedError; +} diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/type_option/checkbox.dart b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/type_option/checkbox.dart index fdc5719181..fc4c4c16a7 100644 --- a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/type_option/checkbox.dart +++ b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/type_option/checkbox.dart @@ -1,9 +1,9 @@ -import 'package:app_flowy/plugins/grid/application/field/type_option/type_option_service.dart'; +import 'package:app_flowy/plugins/grid/application/field/type_option/type_option_data_controller.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/checkbox_type_option.pb.dart'; import 'package:flutter/material.dart'; import 'builder.dart'; -typedef CheckboxTypeOptionContext = TypeOptionWidgetContext; +typedef CheckboxTypeOptionContext = TypeOptionContext; class CheckboxTypeOptionWidgetDataParser extends TypeOptionDataParser { diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/type_option/rich_text.dart b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/type_option/rich_text.dart index a4291f91ce..4ee9e1e6ae 100644 --- a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/type_option/rich_text.dart +++ b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/type_option/rich_text.dart @@ -1,9 +1,9 @@ -import 'package:app_flowy/plugins/grid/application/field/type_option/type_option_service.dart'; +import 'package:app_flowy/plugins/grid/application/field/type_option/type_option_data_controller.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/text_type_option.pb.dart'; import 'package:flutter/material.dart'; import 'builder.dart'; -typedef RichTextTypeOptionContext = TypeOptionWidgetContext; +typedef RichTextTypeOptionContext = TypeOptionContext; class RichTextTypeOptionWidgetDataParser extends TypeOptionDataParser { diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/type_option/url.dart b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/type_option/url.dart index 894a1b1e5c..3521b336cf 100644 --- a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/type_option/url.dart +++ b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/type_option/url.dart @@ -1,9 +1,9 @@ -import 'package:app_flowy/plugins/grid/application/field/type_option/type_option_service.dart'; +import 'package:app_flowy/plugins/grid/application/field/type_option/type_option_data_controller.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/url_type_option.pb.dart'; import 'package:flutter/material.dart'; import 'builder.dart'; -typedef URLTypeOptionContext = TypeOptionWidgetContext; +typedef URLTypeOptionContext = TypeOptionContext; class URLTypeOptionWidgetDataParser extends TypeOptionDataParser { diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/row/row_detail.dart b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/row/row_detail.dart index bfaef332a9..3412d54e1e 100644 --- a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/row/row_detail.dart +++ b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/row/row_detail.dart @@ -1,5 +1,5 @@ import 'package:app_flowy/plugins/grid/application/cell/cell_service/cell_service.dart'; -import 'package:app_flowy/plugins/grid/application/field/field_service.dart'; +import 'package:app_flowy/plugins/grid/application/field/type_option/type_option_data_controller.dart'; import 'package:app_flowy/plugins/grid/application/row/row_data_controller.dart'; import 'package:app_flowy/plugins/grid/application/row/row_detail_bloc.dart'; import 'package:flowy_infra/image.dart'; diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/toolbar/grid_property.dart b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/toolbar/grid_property.dart index 28f2b860ff..290da43f95 100644 --- a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/toolbar/grid_property.dart +++ b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/toolbar/grid_property.dart @@ -1,5 +1,5 @@ +import 'package:app_flowy/plugins/grid/application/field/type_option/type_option_data_controller.dart'; import 'package:app_flowy/startup/startup.dart'; -import 'package:app_flowy/plugins/grid/application/field/field_service.dart'; import 'package:app_flowy/plugins/grid/application/setting/property_bloc.dart'; import 'package:app_flowy/plugins/grid/presentation/widgets/header/field_type_extension.dart'; import 'package:flowy_infra/image.dart';