diff --git a/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/selection_editor_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/selection_editor_bloc.dart new file mode 100644 index 0000000000..7e617069c4 --- /dev/null +++ b/frontend/app_flowy/lib/workspace/application/grid/cell_bloc/selection_editor_bloc.dart @@ -0,0 +1,102 @@ +import 'package:app_flowy/workspace/application/grid/field/field_listener.dart'; +import 'package:app_flowy/workspace/application/grid/field/field_service.dart'; +import 'package:flowy_sdk/log.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid-data-model/meta.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid/selection_type_option.pb.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:freezed_annotation/freezed_annotation.dart'; +import 'dart:async'; +import 'cell_service.dart'; + +part 'selection_editor_bloc.freezed.dart'; + +class SelectionEditorBloc extends Bloc<SelectionEditorEvent, SelectionEditorState> { + final CellService service = CellService(); + final FieldListener _listener; + + SelectionEditorBloc({ + required String gridId, + required Field field, + }) : _listener = FieldListener(fieldId: field.id), + super(SelectionEditorState.initial(gridId, field)) { + on<SelectionEditorEvent>( + (event, emit) async { + await event.map( + initial: (_Initial value) async { + _startListening(); + _loadOptions(); + }, + didReceiveFieldUpdate: (_DidReceiveFieldUpdate value) { + emit(state.copyWith(field: value.field)); + _loadOptions(); + }, + didReceiveOptions: (_DidReceiveOptions value) { + emit(state.copyWith(options: value.options)); + }, + ); + }, + ); + } + + @override + Future<void> close() async { + await _listener.stop(); + return super.close(); + } + + void _startListening() { + _listener.updateFieldNotifier.addPublishListener((result) { + result.fold( + (field) => add(SelectionEditorEvent.didReceiveFieldUpdate(field)), + (err) => Log.error(err), + ); + }); + } + + void _loadOptions() async { + final result = await FieldContextLoaderAdaptor(gridId: state.gridId, field: state.field).load(); + result.fold( + (context) { + List<SelectOption> options = []; + switch (state.field.fieldType) { + case FieldType.MultiSelect: + options.addAll(MultiSelectTypeOption.fromBuffer(context.typeOptionData).options); + break; + case FieldType.SingleSelect: + options.addAll(SingleSelectTypeOption.fromBuffer(context.typeOptionData).options); + break; + default: + Log.error("Invalid field type, expect single select or multiple select"); + break; + } + add(SelectionEditorEvent.didReceiveOptions(options)); + }, + (err) => Log.error(err), + ); + } +} + +@freezed +class SelectionEditorEvent with _$SelectionEditorEvent { + const factory SelectionEditorEvent.initial() = _Initial; + const factory SelectionEditorEvent.didReceiveFieldUpdate(Field field) = _DidReceiveFieldUpdate; + const factory SelectionEditorEvent.didReceiveOptions(List<SelectOption> options) = _DidReceiveOptions; +} + +@freezed +class SelectionEditorState with _$SelectionEditorState { + const factory SelectionEditorState({ + required String gridId, + required Field field, + required List<SelectOption> options, + }) = _SelectionEditorState; + + factory SelectionEditorState.initial(String gridId, Field field) { + return SelectionEditorState( + gridId: gridId, + field: field, + options: [], + ); + } +} diff --git a/frontend/app_flowy/lib/workspace/application/grid/field/field_listener.dart b/frontend/app_flowy/lib/workspace/application/grid/field/field_listener.dart new file mode 100644 index 0000000000..eda5d83e69 --- /dev/null +++ b/frontend/app_flowy/lib/workspace/application/grid/field/field_listener.dart @@ -0,0 +1,51 @@ +import 'package:dartz/dartz.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart'; +import 'package:flowy_sdk/protobuf/dart-notify/subject.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid/dart_notification.pb.dart'; +import 'package:flowy_sdk/rust_stream.dart'; +import 'package:flowy_infra/notifier.dart'; +import 'dart:async'; +import 'dart:typed_data'; +import 'package:app_flowy/core/notification_helper.dart'; + +typedef UpdateFieldNotifiedValue = Either<Field, FlowyError>; + +class FieldListener { + final String fieldId; + PublishNotifier<UpdateFieldNotifiedValue> updateFieldNotifier = PublishNotifier(); + StreamSubscription<SubscribeObject>? _subscription; + GridNotificationParser? _parser; + + FieldListener({required this.fieldId}); + + void start() { + _parser = GridNotificationParser( + id: fieldId, + callback: (ty, result) { + _handleObservableType(ty, result); + }, + ); + + _subscription = RustStreamReceiver.listen((observable) => _parser?.parse(observable)); + } + + void _handleObservableType(GridNotification ty, Either<Uint8List, FlowyError> result) { + switch (ty) { + case GridNotification.DidUpdateField: + result.fold( + (payload) => updateFieldNotifier.value = left(Field.fromBuffer(payload)), + (error) => updateFieldNotifier.value = right(error), + ); + break; + default: + break; + } + } + + Future<void> stop() async { + _parser = null; + await _subscription?.cancel(); + updateFieldNotifier.dispose(); + } +} diff --git a/frontend/app_flowy/lib/workspace/application/grid/field/field_service.dart b/frontend/app_flowy/lib/workspace/application/grid/field/field_service.dart index d47dab99d0..61ccad6b81 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/field/field_service.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/field/field_service.dart @@ -132,16 +132,20 @@ class NewFieldContextLoader extends FieldContextLoader { } class FieldContextLoaderAdaptor extends FieldContextLoader { - final GridFieldCellContext data; + final String gridId; + final Field field; - FieldContextLoaderAdaptor(this.data); + FieldContextLoaderAdaptor({ + required this.gridId, + required this.field, + }); @override Future<Either<EditFieldContext, FlowyError>> load() { final payload = GetEditFieldContextPayload.create() - ..gridId = data.gridId - ..fieldId = data.field.id - ..fieldType = data.field.fieldType; + ..gridId = gridId + ..fieldId = field.id + ..fieldType = field.fieldType; return GridEventGetEditFieldContext(payload).send(); } diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/grid_page.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/grid_page.dart index 83bce9c7ef..111235841f 100755 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/grid_page.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/grid_page.dart @@ -10,7 +10,7 @@ import 'package:flutter/material.dart'; import 'controller/grid_scroll.dart'; import 'layout/layout.dart'; import 'layout/sizes.dart'; -import 'widgets/content/grid_row.dart'; +import 'widgets/row/grid_row.dart'; import 'widgets/footer/grid_footer.dart'; import 'widgets/header/grid_header.dart'; import 'widgets/toolbar/grid_toolbar.dart'; @@ -101,7 +101,7 @@ class _FlowyGridState extends State<FlowyGrid> { controller: _scrollController.verticalController, slivers: [ _renderToolbar(gridId), - _renderHeader(gridId), + GridHeader(gridId: gridId, fields: List.from(state.fields)), _renderRows(context), const GridFooter(), ], @@ -144,21 +144,6 @@ class _FlowyGridState extends State<FlowyGrid> { ); } - Widget _renderHeader(String gridId) { - return BlocBuilder<GridBloc, GridState>( - buildWhen: (previous, current) => previous.fields.length != current.fields.length, - builder: (context, state) { - return GridHeader(gridId: gridId, fields: List.from(state.fields)); - - // return SliverPersistentHeader( - // delegate: GridHeaderDelegate(gridId: gridId, fields: List.from(state.fields)), - // floating: true, - // pinned: true, - // ); - }, - ); - } - Widget _renderRows(BuildContext context) { return BlocBuilder<GridBloc, GridState>( buildWhen: (previous, current) { diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/cell_builder.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/cell_builder.dart similarity index 96% rename from frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/cell_builder.dart rename to frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/cell_builder.dart index 856338aea4..8a1b3a63ea 100755 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/cell_builder.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/cell_builder.dart @@ -5,7 +5,7 @@ import 'package:flutter/widgets.dart'; import 'checkbox_cell.dart'; import 'date_cell.dart'; import 'number_cell.dart'; -import 'selection_cell.dart'; +import 'selection_cell/selection_cell.dart'; import 'text_cell.dart'; Widget buildGridCell(String rowId, Field field, FutureCellData cellData) { diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/cell_container.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/cell_container.dart similarity index 100% rename from frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/cell_container.dart rename to frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/cell_container.dart diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/cell_decoration.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/cell_decoration.dart similarity index 100% rename from frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/cell_decoration.dart rename to frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/cell_decoration.dart diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/checkbox_cell.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/checkbox_cell.dart similarity index 100% rename from frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/checkbox_cell.dart rename to frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/checkbox_cell.dart diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/date_cell.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/date_cell.dart similarity index 100% rename from frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/date_cell.dart rename to frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/date_cell.dart diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/number_cell.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/number_cell.dart similarity index 100% rename from frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/number_cell.dart rename to frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/number_cell.dart diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/prelude.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/prelude.dart new file mode 100644 index 0000000000..7fc3b3246f --- /dev/null +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/prelude.dart @@ -0,0 +1,7 @@ +export 'cell_builder.dart'; +export 'cell_container.dart'; +export 'text_cell.dart'; +export 'number_cell.dart'; +export 'date_cell.dart'; +export 'checkbox_cell.dart'; +export 'selection_cell/selection_cell.dart'; diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/selection.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/selection.dart new file mode 100644 index 0000000000..8f0f3dfc78 --- /dev/null +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/selection.dart @@ -0,0 +1,77 @@ +import 'package:flowy_infra/theme.dart'; +import 'package:flowy_infra_ui/style_widget/text.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid/selection_type_option.pb.dart'; +import 'package:flutter/material.dart'; +import 'package:easy_localization/easy_localization.dart'; +import 'package:app_flowy/generated/locale_keys.g.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; + +class SelectionBadge extends StatelessWidget { + final SelectOption option; + const SelectionBadge({required this.option, Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Container( + decoration: BoxDecoration( + color: option.color.make(context), + shape: BoxShape.rectangle, + borderRadius: BorderRadius.circular(6.0), + ), + child: FlowyText.medium(option.name, fontSize: 12), + ); + } +} + +extension SelectOptionColorExtension on SelectOptionColor { + Color make(BuildContext context) { + final theme = context.watch<AppTheme>(); + switch (this) { + case SelectOptionColor.Purple: + return theme.tint1; + case SelectOptionColor.Pink: + return theme.tint2; + case SelectOptionColor.LightPink: + return theme.tint3; + case SelectOptionColor.Orange: + return theme.tint4; + case SelectOptionColor.Yellow: + return theme.tint5; + case SelectOptionColor.Lime: + return theme.tint6; + case SelectOptionColor.Green: + return theme.tint7; + case SelectOptionColor.Aqua: + return theme.tint8; + case SelectOptionColor.Blue: + return theme.tint9; + default: + throw ArgumentError; + } + } + + String optionName() { + switch (this) { + case SelectOptionColor.Purple: + return LocaleKeys.grid_selectOption_purpleColor.tr(); + case SelectOptionColor.Pink: + return LocaleKeys.grid_selectOption_pinkColor.tr(); + case SelectOptionColor.LightPink: + return LocaleKeys.grid_selectOption_lightPinkColor.tr(); + case SelectOptionColor.Orange: + return LocaleKeys.grid_selectOption_orangeColor.tr(); + case SelectOptionColor.Yellow: + return LocaleKeys.grid_selectOption_yellowColor.tr(); + case SelectOptionColor.Lime: + return LocaleKeys.grid_selectOption_limeColor.tr(); + case SelectOptionColor.Green: + return LocaleKeys.grid_selectOption_greenColor.tr(); + case SelectOptionColor.Aqua: + return LocaleKeys.grid_selectOption_aquaColor.tr(); + case SelectOptionColor.Blue: + return LocaleKeys.grid_selectOption_blueColor.tr(); + default: + throw ArgumentError; + } + } +} diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/selection_cell.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/selection_cell.dart similarity index 100% rename from frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/selection_cell.dart rename to frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/selection_cell.dart diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/selection_editor.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/selection_editor.dart new file mode 100644 index 0000000000..de25430066 --- /dev/null +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/selection_editor.dart @@ -0,0 +1,45 @@ +import 'package:app_flowy/workspace/application/grid/cell_bloc/selection_editor_bloc.dart'; +import 'package:app_flowy/workspace/application/grid/row/row_service.dart'; +import 'package:flowy_infra/theme.dart'; +import 'package:flowy_infra_ui/style_widget/hover.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid/selection_type_option.pb.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; + +import 'selection.dart'; + +class SelectionEditor extends StatelessWidget { + final GridCellData cellData; + const SelectionEditor({required this.cellData, Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return BlocProvider( + create: (context) => SelectionEditorBloc(gridId: cellData.gridId, field: cellData.field), + child: BlocBuilder<SelectionEditorBloc, SelectionEditorState>( + builder: (context, state) { + return Container(); + }, + ), + ); + } +} + +class _SelectionCell extends StatelessWidget { + final SelectOption option; + const _SelectionCell({required this.option, Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + final theme = context.watch<AppTheme>(); + return InkWell( + onTap: () {}, + child: FlowyHover( + config: HoverDisplayConfig(hoverColor: theme.hover), + builder: (_, onHover) { + return SelectionBadge(option: option); + }, + ), + ); + } +} diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/text_cell.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/text_cell.dart similarity index 100% rename from frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/text_cell.dart rename to frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/text_cell.dart 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 6a2051318e..89cd0b60ff 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 @@ -49,7 +49,10 @@ class GridFieldCell extends StatelessWidget { void _showFieldEditor(BuildContext context) { FieldEditor( gridId: fieldCellContext.gridId, - fieldContextLoader: FieldContextLoaderAdaptor(fieldCellContext), + fieldContextLoader: FieldContextLoaderAdaptor( + gridId: fieldCellContext.gridId, + field: fieldCellContext.field, + ), ).show(context); } } diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/edit_option_pannel.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/edit_option_pannel.dart index 4f133090de..a69575a409 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/edit_option_pannel.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/edit_option_pannel.dart @@ -1,5 +1,6 @@ import 'package:app_flowy/workspace/application/grid/field/type_option/edit_option_bloc.dart'; import 'package:app_flowy/workspace/presentation/plugins/grid/src/layout/sizes.dart'; +import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/selection.dart'; import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/type_option/widget.dart'; import 'package:flowy_infra/image.dart'; import 'package:flowy_infra/theme.dart'; @@ -183,56 +184,3 @@ class _SelectOptionColorCell extends StatelessWidget { ); } } - -extension SelectOptionColorExtension on SelectOptionColor { - Color color(BuildContext context) { - final theme = context.watch<AppTheme>(); - switch (this) { - case SelectOptionColor.Purple: - return theme.tint1; - case SelectOptionColor.Pink: - return theme.tint2; - case SelectOptionColor.LightPink: - return theme.tint3; - case SelectOptionColor.Orange: - return theme.tint4; - case SelectOptionColor.Yellow: - return theme.tint5; - case SelectOptionColor.Lime: - return theme.tint6; - case SelectOptionColor.Green: - return theme.tint7; - case SelectOptionColor.Aqua: - return theme.tint8; - case SelectOptionColor.Blue: - return theme.tint9; - default: - throw ArgumentError; - } - } - - String optionName() { - switch (this) { - case SelectOptionColor.Purple: - return LocaleKeys.grid_selectOption_purpleColor.tr(); - case SelectOptionColor.Pink: - return LocaleKeys.grid_selectOption_pinkColor.tr(); - case SelectOptionColor.LightPink: - return LocaleKeys.grid_selectOption_lightPinkColor.tr(); - case SelectOptionColor.Orange: - return LocaleKeys.grid_selectOption_orangeColor.tr(); - case SelectOptionColor.Yellow: - return LocaleKeys.grid_selectOption_yellowColor.tr(); - case SelectOptionColor.Lime: - return LocaleKeys.grid_selectOption_limeColor.tr(); - case SelectOptionColor.Green: - return LocaleKeys.grid_selectOption_greenColor.tr(); - case SelectOptionColor.Aqua: - return LocaleKeys.grid_selectOption_aquaColor.tr(); - case SelectOptionColor.Blue: - return LocaleKeys.grid_selectOption_blueColor.tr(); - default: - throw ArgumentError; - } - } -} diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/grid_row.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/row/grid_row.dart similarity index 97% rename from frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/grid_row.dart rename to frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/row/grid_row.dart index 73594de957..c4c32bda3b 100755 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/content/grid_row.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/row/grid_row.dart @@ -1,14 +1,13 @@ import 'package:app_flowy/startup/startup.dart'; import 'package:app_flowy/workspace/application/grid/prelude.dart'; import 'package:app_flowy/workspace/presentation/plugins/grid/src/layout/sizes.dart'; +import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/cell/prelude.dart'; import 'package:flowy_infra/image.dart'; import 'package:flowy_infra/theme.dart'; import 'package:flowy_infra_ui/style_widget/icon_button.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:provider/provider.dart'; -import 'cell_builder.dart'; -import 'cell_container.dart'; class GridRowWidget extends StatefulWidget { final GridRowData data; diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/toolbar/grid_property.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/toolbar/grid_property.dart index 9951e6ba65..a34682d204 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/toolbar/grid_property.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/toolbar/grid_property.dart @@ -97,14 +97,9 @@ class _GridPropertyCell extends StatelessWidget { hoverColor: theme.hover, leftIcon: svgWidget(field.fieldType.iconName(), color: theme.iconColor), onTap: () { - final fieldCellContext = GridFieldCellContext( - gridId: gridId, - field: field, - ); - FieldEditor( gridId: gridId, - fieldContextLoader: FieldContextLoaderAdaptor(fieldCellContext), + fieldContextLoader: FieldContextLoaderAdaptor(gridId: gridId, field: field), ).show(context, anchorDirection: AnchorDirection.bottomRight); }, ), diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/dart_notification.pbenum.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/dart_notification.pbenum.dart index c000793a5e..634de1b7f2 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/dart_notification.pbenum.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/dart_notification.pbenum.dart @@ -11,17 +11,19 @@ import 'package:protobuf/protobuf.dart' as $pb; class GridNotification extends $pb.ProtobufEnum { static const GridNotification Unknown = GridNotification._(0, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Unknown'); - static const GridNotification GridDidCreateBlock = GridNotification._(11, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'GridDidCreateBlock'); + static const GridNotification DidCreateBlock = GridNotification._(11, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'DidCreateBlock'); static const GridNotification DidUpdateRow = GridNotification._(20, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'DidUpdateRow'); static const GridNotification GridDidUpdateCells = GridNotification._(30, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'GridDidUpdateCells'); static const GridNotification DidUpdateFields = GridNotification._(40, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'DidUpdateFields'); + static const GridNotification DidUpdateField = GridNotification._(41, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'DidUpdateField'); static const $core.List<GridNotification> values = <GridNotification> [ Unknown, - GridDidCreateBlock, + DidCreateBlock, DidUpdateRow, GridDidUpdateCells, DidUpdateFields, + DidUpdateField, ]; static final $core.Map<$core.int, GridNotification> _byValue = $pb.ProtobufEnum.initByValue(values); diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/dart_notification.pbjson.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/dart_notification.pbjson.dart index 5dc1fbc1a5..571fe64399 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/dart_notification.pbjson.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/dart_notification.pbjson.dart @@ -13,12 +13,13 @@ const GridNotification$json = const { '1': 'GridNotification', '2': const [ const {'1': 'Unknown', '2': 0}, - const {'1': 'GridDidCreateBlock', '2': 11}, + const {'1': 'DidCreateBlock', '2': 11}, const {'1': 'DidUpdateRow', '2': 20}, const {'1': 'GridDidUpdateCells', '2': 30}, const {'1': 'DidUpdateFields', '2': 40}, + const {'1': 'DidUpdateField', '2': 41}, ], }; /// Descriptor for `GridNotification`. Decode as a `google.protobuf.EnumDescriptorProto`. -final $typed_data.Uint8List gridNotificationDescriptor = $convert.base64Decode('ChBHcmlkTm90aWZpY2F0aW9uEgsKB1Vua25vd24QABIWChJHcmlkRGlkQ3JlYXRlQmxvY2sQCxIQCgxEaWRVcGRhdGVSb3cQFBIWChJHcmlkRGlkVXBkYXRlQ2VsbHMQHhITCg9EaWRVcGRhdGVGaWVsZHMQKA=='); +final $typed_data.Uint8List gridNotificationDescriptor = $convert.base64Decode('ChBHcmlkTm90aWZpY2F0aW9uEgsKB1Vua25vd24QABISCg5EaWRDcmVhdGVCbG9jaxALEhAKDERpZFVwZGF0ZVJvdxAUEhYKEkdyaWREaWRVcGRhdGVDZWxscxAeEhMKD0RpZFVwZGF0ZUZpZWxkcxAoEhIKDkRpZFVwZGF0ZUZpZWxkECk='); diff --git a/frontend/rust-lib/flowy-grid/src/dart_notification.rs b/frontend/rust-lib/flowy-grid/src/dart_notification.rs index 34c972a9bb..364c42f680 100644 --- a/frontend/rust-lib/flowy-grid/src/dart_notification.rs +++ b/frontend/rust-lib/flowy-grid/src/dart_notification.rs @@ -5,13 +5,11 @@ const OBSERVABLE_CATEGORY: &str = "Grid"; #[derive(ProtoBuf_Enum, Debug)] pub enum GridNotification { Unknown = 0, - - GridDidCreateBlock = 11, - + DidCreateBlock = 11, DidUpdateRow = 20, - GridDidUpdateCells = 30, DidUpdateFields = 40, + DidUpdateField = 41, } impl std::default::Default for GridNotification { diff --git a/frontend/rust-lib/flowy-grid/src/protobuf/model/dart_notification.rs b/frontend/rust-lib/flowy-grid/src/protobuf/model/dart_notification.rs index 0dd067b3d5..32e697b36e 100644 --- a/frontend/rust-lib/flowy-grid/src/protobuf/model/dart_notification.rs +++ b/frontend/rust-lib/flowy-grid/src/protobuf/model/dart_notification.rs @@ -26,10 +26,11 @@ #[derive(Clone,PartialEq,Eq,Debug,Hash)] pub enum GridNotification { Unknown = 0, - GridDidCreateBlock = 11, + DidCreateBlock = 11, DidUpdateRow = 20, GridDidUpdateCells = 30, DidUpdateFields = 40, + DidUpdateField = 41, } impl ::protobuf::ProtobufEnum for GridNotification { @@ -40,10 +41,11 @@ impl ::protobuf::ProtobufEnum for GridNotification { fn from_i32(value: i32) -> ::std::option::Option<GridNotification> { match value { 0 => ::std::option::Option::Some(GridNotification::Unknown), - 11 => ::std::option::Option::Some(GridNotification::GridDidCreateBlock), + 11 => ::std::option::Option::Some(GridNotification::DidCreateBlock), 20 => ::std::option::Option::Some(GridNotification::DidUpdateRow), 30 => ::std::option::Option::Some(GridNotification::GridDidUpdateCells), 40 => ::std::option::Option::Some(GridNotification::DidUpdateFields), + 41 => ::std::option::Option::Some(GridNotification::DidUpdateField), _ => ::std::option::Option::None } } @@ -51,10 +53,11 @@ impl ::protobuf::ProtobufEnum for GridNotification { fn values() -> &'static [Self] { static values: &'static [GridNotification] = &[ GridNotification::Unknown, - GridNotification::GridDidCreateBlock, + GridNotification::DidCreateBlock, GridNotification::DidUpdateRow, GridNotification::GridDidUpdateCells, GridNotification::DidUpdateFields, + GridNotification::DidUpdateField, ]; values } @@ -83,10 +86,10 @@ impl ::protobuf::reflect::ProtobufValue for GridNotification { } static file_descriptor_proto_data: &'static [u8] = b"\ - \n\x17dart_notification.proto*v\n\x10GridNotification\x12\x0b\n\x07Unkno\ - wn\x10\0\x12\x16\n\x12GridDidCreateBlock\x10\x0b\x12\x10\n\x0cDidUpdateR\ - ow\x10\x14\x12\x16\n\x12GridDidUpdateCells\x10\x1e\x12\x13\n\x0fDidUpdat\ - eFields\x10(b\x06proto3\ + \n\x17dart_notification.proto*\x86\x01\n\x10GridNotification\x12\x0b\n\ + \x07Unknown\x10\0\x12\x12\n\x0eDidCreateBlock\x10\x0b\x12\x10\n\x0cDidUp\ + dateRow\x10\x14\x12\x16\n\x12GridDidUpdateCells\x10\x1e\x12\x13\n\x0fDid\ + UpdateFields\x10(\x12\x12\n\x0eDidUpdateField\x10)b\x06proto3\ "; static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT; diff --git a/frontend/rust-lib/flowy-grid/src/protobuf/proto/dart_notification.proto b/frontend/rust-lib/flowy-grid/src/protobuf/proto/dart_notification.proto index da1d193b21..176e0d83a4 100644 --- a/frontend/rust-lib/flowy-grid/src/protobuf/proto/dart_notification.proto +++ b/frontend/rust-lib/flowy-grid/src/protobuf/proto/dart_notification.proto @@ -2,8 +2,9 @@ syntax = "proto3"; enum GridNotification { Unknown = 0; - GridDidCreateBlock = 11; + DidCreateBlock = 11; DidUpdateRow = 20; GridDidUpdateCells = 30; DidUpdateFields = 40; + DidUpdateField = 41; } diff --git a/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs b/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs index 95c23f489b..443c1ee2bf 100644 --- a/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs +++ b/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs @@ -97,6 +97,7 @@ impl ClientGridEditor { } pub async fn update_field(&self, params: FieldChangesetParams) -> FlowyResult<()> { + let field_id = params.field_id.clone(); let deserializer = match self.pad.read().await.get_field(¶ms.field_id) { None => return Err(ErrorCode::FieldDoesNotExist.into()), Some(field_meta) => TypeOptionChangesetDeserializer(field_meta.field_type.clone()), @@ -104,6 +105,7 @@ impl ClientGridEditor { let _ = self.modify(|grid| Ok(grid.update_field(params, deserializer)?)).await?; let _ = self.notify_did_update_fields().await?; + let _ = self.notify_did_update_field(&field_id).await?; Ok(()) } @@ -133,6 +135,7 @@ impl ClientGridEditor { .modify(|grid| Ok(grid.switch_to_field(field_id, field_type.clone(), type_option_json_builder)?)) .await?; let _ = self.notify_did_update_fields().await?; + let _ = self.notify_did_update_field(field_id).await?; Ok(()) } @@ -294,7 +297,19 @@ impl ClientGridEditor { } pub async fn get_field_metas(&self, field_orders: Option<RepeatedFieldOrder>) -> FlowyResult<Vec<FieldMeta>> { - let mut field_metas = self.pad.read().await.get_field_metas(field_orders)?; + let expected_len = match field_orders.as_ref() { + None => 0, + Some(field_orders) => field_orders.len(), + }; + + let field_metas = self.pad.read().await.get_field_metas(field_orders)?; + debug_assert!(field_metas.len() == expected_len); + if field_metas.len() != expected_len { + tracing::error!( + "This is a bug. The len of the field_metas should equal to {}", + expected_len + ); + } // field_metas.retain(|field_meta| field_meta.visibility); Ok(field_metas) } @@ -368,6 +383,20 @@ impl ClientGridEditor { .send(); Ok(()) } + + async fn notify_did_update_field(&self, field_id: &str) -> FlowyResult<()> { + let field_orders: RepeatedFieldOrder = vec![FieldOrder::from(field_id)].into(); + let mut field_metas = self.get_field_metas(Some(field_orders)).await?; + debug_assert!(field_metas.len() == 1); + + if let Some(field_meta) = field_metas.pop() { + send_dart_notification(&self.grid_id, GridNotification::DidUpdateField) + .payload(field_meta) + .send(); + } + + Ok(()) + } } #[cfg(feature = "flowy_unit_test")] diff --git a/shared-lib/flowy-grid-data-model/src/entities/grid.rs b/shared-lib/flowy-grid-data-model/src/entities/grid.rs index b60aafedae..1dd2220f13 100644 --- a/shared-lib/flowy-grid-data-model/src/entities/grid.rs +++ b/shared-lib/flowy-grid-data-model/src/entities/grid.rs @@ -100,6 +100,12 @@ impl std::convert::From<&FieldMeta> for FieldOrder { } } +impl std::convert::From<&str> for FieldOrder { + fn from(s: &str) -> Self { + FieldOrder { field_id: s.to_owned() } + } +} + #[derive(Debug, Default, ProtoBuf)] pub struct GetEditFieldContextPayload { #[pb(index = 1)] @@ -193,6 +199,12 @@ impl std::ops::Deref for RepeatedFieldOrder { } } +impl std::convert::From<Vec<FieldOrder>> for RepeatedFieldOrder { + fn from(field_orders: Vec<FieldOrder>) -> Self { + RepeatedFieldOrder { items: field_orders } + } +} + #[derive(Debug, Default, Clone, ProtoBuf)] pub struct RowOrder { #[pb(index = 1)]