From bd0907b0a4b08a0fcdcc0073ade4e255db176b27 Mon Sep 17 00:00:00 2001 From: appflowy Date: Tue, 3 May 2022 10:26:42 +0800 Subject: [PATCH 1/7] fix: support float number --- .../field/type_options/number_type_option.rs | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/frontend/rust-lib/flowy-grid/src/services/field/type_options/number_type_option.rs b/frontend/rust-lib/flowy-grid/src/services/field/type_options/number_type_option.rs index 03b4b194b0..f403a28272 100644 --- a/frontend/rust-lib/flowy-grid/src/services/field/type_options/number_type_option.rs +++ b/frontend/rust-lib/flowy-grid/src/services/field/type_options/number_type_option.rs @@ -85,7 +85,17 @@ impl CellDataOperation for NumberTypeOption { let cell_data = type_option_cell_data.data; match self.format { - NumberFormat::Number => cell_data.parse::().map_or(String::new(), |v| v.to_string()), + NumberFormat::Number => { + if let Ok(v) = cell_data.parse::() { + return v.to_string(); + } + + if let Ok(v) = cell_data.parse::() { + return v.to_string(); + } + + return String::new(); + } NumberFormat::Percent => cell_data.parse::().map_or(String::new(), |v| v.to_string()), _ => self.money_from_str(&cell_data), } @@ -100,7 +110,8 @@ impl CellDataOperation for NumberTypeOption { _cell_meta: Option, ) -> Result { let changeset = changeset.into(); - let data = self.strip_symbol(changeset); + let data = changeset.to_string(); + let data = self.strip_symbol(data.trim()); if !data.chars().all(char::is_numeric) { return Err(FlowyError::invalid_data().context("Should only contain numbers")); From 0b8083cfc647b29ff2280726a0fc751ffbbf5344 Mon Sep 17 00:00:00 2001 From: appflowy Date: Wed, 4 May 2022 20:34:28 +0800 Subject: [PATCH 2/7] fix: create option with different color --- .../app_flowy/lib/startup/deps_resolver.dart | 5 +- .../grid/field/field_editor_bloc.dart | 71 ++++++++++++++----- .../grid/field/field_editor_pannel_bloc.dart | 53 ++++++++++++++ .../grid/field/field_switch_bloc.dart | 61 ---------------- .../workspace/application/grid/prelude.dart | 2 +- .../grid/src/widgets/header/field_editor.dart | 45 ++++++------ ...switcher.dart => field_editor_pannel.dart} | 24 +++---- .../src/widgets/header/type_option/date.dart | 2 +- .../type_option/field_option_pannel.dart | 2 +- .../header/type_option/multi_select.dart | 2 +- .../widgets/header/type_option/number.dart | 2 +- .../header/type_option/single_select.dart | 2 +- 12 files changed, 147 insertions(+), 124 deletions(-) create mode 100644 frontend/app_flowy/lib/workspace/application/grid/field/field_editor_pannel_bloc.dart delete mode 100644 frontend/app_flowy/lib/workspace/application/grid/field/field_switch_bloc.dart rename frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/{field_switcher.dart => field_editor_pannel.dart} (91%) diff --git a/frontend/app_flowy/lib/startup/deps_resolver.dart b/frontend/app_flowy/lib/startup/deps_resolver.dart index fb5cad590e..a0daac273d 100644 --- a/frontend/app_flowy/lib/startup/deps_resolver.dart +++ b/frontend/app_flowy/lib/startup/deps_resolver.dart @@ -17,6 +17,7 @@ import 'package:app_flowy/workspace/presentation/home/home_stack.dart'; import 'package:app_flowy/workspace/presentation/home/menu/menu.dart'; import 'package:flowy_sdk/protobuf/flowy-folder-data-model/app.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-folder-data-model/view.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart' show EditFieldContext; import 'package:flowy_sdk/protobuf/flowy-grid/date_type_option.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/number_type_option.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-user-data-model/user_profile.pb.dart'; @@ -201,8 +202,8 @@ void _resolveGridDeps(GetIt getIt) { ), ); - getIt.registerFactoryParam( - (context, _) => FieldSwitcherBloc(context), + getIt.registerFactoryParam( + (context, _) => FieldEditorPannelBloc(context), ); getIt.registerFactoryParam( diff --git a/frontend/app_flowy/lib/workspace/application/grid/field/field_editor_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/field/field_editor_bloc.dart index c38713862e..b3c37dbd76 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/field/field_editor_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/field/field_editor_bloc.dart @@ -6,6 +6,7 @@ import 'package:freezed_annotation/freezed_annotation.dart'; import 'dart:async'; import 'field_service.dart'; import 'package:dartz/dartz.dart'; +import 'package:protobuf/protobuf.dart'; part 'field_editor_bloc.freezed.dart'; @@ -25,10 +26,13 @@ class FieldEditorBloc extends Bloc { await _getEditFieldContext(emit); }, updateName: (_UpdateName value) { - emit(state.copyWith(fieldName: value.name)); + final newContext = _updateEditContext(name: value.name); + emit(state.copyWith(editFieldContext: newContext)); }, - switchField: (_SwitchField value) { - emit(state.copyWith(field: Some(value.field), typeOptionData: value.typeOptionData)); + updateField: (_UpdateField value) { + final newContext = _updateEditContext(field: value.field, typeOptionData: value.typeOptionData); + + emit(state.copyWith(editFieldContext: newContext)); }, done: (_Done value) async { await _saveField(emit); @@ -43,14 +47,49 @@ class FieldEditorBloc extends Bloc { return super.close(); } + Option _updateEditContext({ + String? name, + Field? field, + List? typeOptionData, + }) { + return state.editFieldContext.fold( + () => none(), + (context) { + context.freeze(); + final newContext = context.rebuild((newContext) { + newContext.gridField.rebuild((newField) { + if (name != null) { + newField.name = name; + } + + newContext.gridField = newField; + }); + + if (field != null) { + newContext.gridField = field; + } + + if (typeOptionData != null) { + newContext.typeOptionData = typeOptionData; + } + }); + service.insertField( + field: newContext.gridField, + typeOptionData: newContext.typeOptionData, + ); + + return Some(newContext); + }, + ); + } + Future _saveField(Emitter emit) async { - await state.field.fold( + await state.editFieldContext.fold( () async => null, - (field) async { - field.name = state.fieldName; + (context) async { final result = await service.insertField( - field: field, - typeOptionData: state.typeOptionData, + field: context.gridField, + typeOptionData: context.typeOptionData, ); result.fold((l) => null, (r) => null); }, @@ -60,11 +99,9 @@ class FieldEditorBloc extends Bloc { Future _getEditFieldContext(Emitter emit) async { final result = await _loader.load(); result.fold( - (editContext) { + (context) { emit(state.copyWith( - field: Some(editContext.gridField), - typeOptionData: editContext.typeOptionData, - fieldName: editContext.gridField.name, + editFieldContext: Some(context), )); }, (err) => Log.error(err), @@ -76,25 +113,21 @@ class FieldEditorBloc extends Bloc { class FieldEditorEvent with _$FieldEditorEvent { const factory FieldEditorEvent.initial() = _InitialField; const factory FieldEditorEvent.updateName(String name) = _UpdateName; - const factory FieldEditorEvent.switchField(Field field, Uint8List typeOptionData) = _SwitchField; + const factory FieldEditorEvent.updateField(Field field, Uint8List typeOptionData) = _UpdateField; const factory FieldEditorEvent.done() = _Done; } @freezed class FieldEditorState with _$FieldEditorState { const factory FieldEditorState({ - required String fieldName, required String gridId, required String errorText, - required Option field, - required List typeOptionData, + required Option editFieldContext, }) = _FieldEditorState; factory FieldEditorState.initial(String gridId) => FieldEditorState( gridId: gridId, - fieldName: '', - field: none(), + editFieldContext: none(), errorText: '', - typeOptionData: List.empty(), ); } diff --git a/frontend/app_flowy/lib/workspace/application/grid/field/field_editor_pannel_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/field/field_editor_pannel_bloc.dart new file mode 100644 index 0000000000..09d0268d63 --- /dev/null +++ b/frontend/app_flowy/lib/workspace/application/grid/field/field_editor_pannel_bloc.dart @@ -0,0 +1,53 @@ +import 'dart:typed_data'; +import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:freezed_annotation/freezed_annotation.dart'; +import 'dart:async'; + +part 'field_editor_pannel_bloc.freezed.dart'; + +class FieldEditorPannelBloc extends Bloc { + FieldEditorPannelBloc(EditFieldContext editContext) : super(FieldEditorPannelState.initial(editContext)) { + on( + (event, emit) async { + await event.map( + toFieldType: (_ToFieldType value) async { + emit(state.copyWith( + field: value.field, + typeOptionData: Uint8List.fromList(value.typeOptionData), + )); + }, + didUpdateTypeOptionData: (_DidUpdateTypeOptionData value) { + emit(state.copyWith(typeOptionData: value.typeOptionData)); + }, + ); + }, + ); + } + + @override + Future close() async { + return super.close(); + } +} + +@freezed +class FieldEditorPannelEvent with _$FieldEditorPannelEvent { + const factory FieldEditorPannelEvent.toFieldType(Field field, List typeOptionData) = _ToFieldType; + const factory FieldEditorPannelEvent.didUpdateTypeOptionData(Uint8List typeOptionData) = _DidUpdateTypeOptionData; +} + +@freezed +class FieldEditorPannelState with _$FieldEditorPannelState { + const factory FieldEditorPannelState({ + required String gridId, + required Field field, + required Uint8List typeOptionData, + }) = _FieldEditorPannelState; + + factory FieldEditorPannelState.initial(EditFieldContext context) => FieldEditorPannelState( + gridId: context.gridId, + field: context.gridField, + typeOptionData: Uint8List.fromList(context.typeOptionData), + ); +} diff --git a/frontend/app_flowy/lib/workspace/application/grid/field/field_switch_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/field/field_switch_bloc.dart deleted file mode 100644 index 082c0decf4..0000000000 --- a/frontend/app_flowy/lib/workspace/application/grid/field/field_switch_bloc.dart +++ /dev/null @@ -1,61 +0,0 @@ -import 'dart:typed_data'; -import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:freezed_annotation/freezed_annotation.dart'; -import 'dart:async'; - -part 'field_switch_bloc.freezed.dart'; - -class FieldSwitcherBloc extends Bloc { - FieldSwitcherBloc(SwitchFieldContext editContext) : super(FieldSwitchState.initial(editContext)) { - on( - (event, emit) async { - await event.map( - toFieldType: (_ToFieldType value) async { - emit(state.copyWith( - field: value.field, - typeOptionData: Uint8List.fromList(value.typeOptionData), - )); - }, - didUpdateTypeOptionData: (_DidUpdateTypeOptionData value) { - emit(state.copyWith(typeOptionData: value.typeOptionData)); - }, - ); - }, - ); - } - - @override - Future close() async { - return super.close(); - } -} - -@freezed -class FieldSwitchEvent with _$FieldSwitchEvent { - const factory FieldSwitchEvent.toFieldType(Field field, List typeOptionData) = _ToFieldType; - const factory FieldSwitchEvent.didUpdateTypeOptionData(Uint8List typeOptionData) = _DidUpdateTypeOptionData; -} - -@freezed -class FieldSwitchState with _$FieldSwitchState { - const factory FieldSwitchState({ - required String gridId, - required Field field, - required Uint8List typeOptionData, - }) = _FieldSwitchState; - - factory FieldSwitchState.initial(SwitchFieldContext switchContext) => FieldSwitchState( - gridId: switchContext.gridId, - field: switchContext.field, - typeOptionData: Uint8List.fromList(switchContext.typeOptionData), - ); -} - -class SwitchFieldContext { - final String gridId; - final Field field; - final List typeOptionData; - - SwitchFieldContext(this.gridId, this.field, this.typeOptionData); -} diff --git a/frontend/app_flowy/lib/workspace/application/grid/prelude.dart b/frontend/app_flowy/lib/workspace/application/grid/prelude.dart index 16287db6bf..92b4d757f0 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/prelude.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/prelude.dart @@ -8,7 +8,7 @@ export 'grid_header_bloc.dart'; export 'field/field_service.dart'; export 'field/field_action_sheet_bloc.dart'; export 'field/field_editor_bloc.dart'; -export 'field/field_switch_bloc.dart'; +export 'field/field_editor_pannel_bloc.dart'; // Field Type Option export 'field/type_option/date_bloc.dart'; diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_editor.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_editor.dart index 723783fb95..11e55e0e06 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_editor.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_editor.dart @@ -1,18 +1,15 @@ import 'package:app_flowy/startup/startup.dart'; import 'package:app_flowy/workspace/application/grid/field/field_editor_bloc.dart'; import 'package:app_flowy/workspace/application/grid/field/field_service.dart'; -import 'package:app_flowy/workspace/application/grid/field/field_switch_bloc.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'; import 'package:flowy_infra_ui/widget/spacing.dart'; -import 'package:flowy_sdk/log.dart'; -import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart' show Field; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:app_flowy/generated/locale_keys.g.dart'; import 'field_name_input.dart'; -import 'field_switcher.dart'; +import 'field_editor_pannel.dart'; class FieldEditor extends FlowyOverlayDelegate { final String gridId; @@ -30,7 +27,6 @@ class FieldEditor extends FlowyOverlayDelegate { BuildContext context, { AnchorDirection anchorDirection = AnchorDirection.bottomWithLeftAligned, }) { - Log.trace("Show $identifier()"); FlowyOverlay.of(context).remove(identifier()); FlowyOverlay.of(context).insertWithAnchor( widget: OverlayContainer( @@ -69,16 +65,24 @@ class _FieldEditorWidget extends StatelessWidget { value: editorBloc, child: BlocBuilder( builder: (context, state) { - return state.field.fold( + return state.editFieldContext.fold( () => const SizedBox(), - (field) => ListView( + (editFieldContext) => ListView( shrinkWrap: true, children: [ FlowyText.medium(LocaleKeys.grid_field_editProperty.tr(), fontSize: 12), const VSpace(10), const _FieldNameTextField(), const VSpace(10), - _renderSwitchButton(context, field, state), + FieldEditorPannel( + editFieldContext: editFieldContext, + onSwitchToField: (fieldId, fieldType) { + return fieldContextLoader.switchToField(fieldId, fieldType); + }, + onUpdated: (field, typeOptionData) { + context.read().add(FieldEditorEvent.updateField(field, typeOptionData)); + }, + ), ], ), ); @@ -86,18 +90,6 @@ class _FieldEditorWidget extends StatelessWidget { ), ); } - - Widget _renderSwitchButton(BuildContext context, Field field, FieldEditorState state) { - return FieldSwitcher( - switchContext: SwitchFieldContext(state.gridId, field, state.typeOptionData), - onSwitchToField: (fieldId, fieldType) { - return fieldContextLoader.switchToField(fieldId, fieldType); - }, - onUpdated: (field, typeOptionData) { - context.read().add(FieldEditorEvent.switchField(field, typeOptionData)); - }, - ); - } } class _FieldNameTextField extends StatelessWidget { @@ -105,11 +97,16 @@ class _FieldNameTextField extends StatelessWidget { @override Widget build(BuildContext context) { - return BlocBuilder( - buildWhen: (previous, current) => previous.fieldName != current.fieldName, - builder: (context, state) { + return BlocSelector( + selector: (state) { + return state.editFieldContext.fold( + () => "", + (editFieldContext) => editFieldContext.gridField.name, + ); + }, + builder: (context, name) { return FieldNameTextField( - name: state.fieldName, + name: name, errorText: context.read().state.errorText, onNameChanged: (newName) { context.read().add(FieldEditorEvent.updateName(newName)); diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_switcher.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_editor_pannel.dart similarity index 91% rename from frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_switcher.dart rename to frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_editor_pannel.dart index 1a44f439e2..1258847520 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_switcher.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_editor_pannel.dart @@ -30,30 +30,30 @@ typedef SwitchToFieldCallback = Future> Fun FieldType fieldType, ); -class FieldSwitcher extends StatefulWidget { - final SwitchFieldContext switchContext; +class FieldEditorPannel extends StatefulWidget { + final EditFieldContext editFieldContext; final UpdateFieldCallback onUpdated; final SwitchToFieldCallback onSwitchToField; - const FieldSwitcher({ - required this.switchContext, + const FieldEditorPannel({ + required this.editFieldContext, required this.onUpdated, required this.onSwitchToField, Key? key, }) : super(key: key); @override - State createState() => _FieldSwitcherState(); + State createState() => _FieldEditorPannelState(); } -class _FieldSwitcherState extends State { +class _FieldEditorPannelState extends State { String? currentOverlayIdentifier; @override Widget build(BuildContext context) { return BlocProvider( - create: (context) => getIt(param1: widget.switchContext), - child: BlocConsumer( + create: (context) => getIt(param1: widget.editFieldContext), + child: BlocConsumer( listener: (context, state) { widget.onUpdated(state.field, state.typeOptionData); }, @@ -87,8 +87,8 @@ class _FieldSwitcherState extends State { widget.onSwitchToField(field.id, newFieldType).then((result) { result.fold( (editFieldContext) { - context.read().add( - FieldSwitchEvent.toFieldType( + context.read().add( + FieldEditorPannelEvent.toFieldType( editFieldContext.gridField, editFieldContext.typeOptionData, ), @@ -108,7 +108,7 @@ class _FieldSwitcherState extends State { Widget? _typeOptionWidget({ required BuildContext context, - required FieldSwitchState state, + required FieldEditorPannelState state, }) { final overlayDelegate = TypeOptionOverlayDelegate( showOverlay: _showOverlay, @@ -116,7 +116,7 @@ class _FieldSwitcherState extends State { ); final dataDelegate = TypeOptionDataDelegate(didUpdateTypeOptionData: (data) { - context.read().add(FieldSwitchEvent.didUpdateTypeOptionData(data)); + context.read().add(FieldEditorPannelEvent.didUpdateTypeOptionData(data)); }); final typeOptionContext = TypeOptionContext( diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/date.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/date.dart index a580bbebf1..2d920cbbf2 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/date.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/date.dart @@ -1,7 +1,7 @@ import 'package:app_flowy/startup/startup.dart'; import 'package:app_flowy/workspace/application/grid/field/type_option/date_bloc.dart'; import 'package:app_flowy/workspace/presentation/plugins/grid/src/layout/sizes.dart'; -import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/field_switcher.dart'; +import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/field_editor_pannel.dart'; import 'package:easy_localization/easy_localization.dart' hide DateFormat; import 'package:app_flowy/generated/locale_keys.g.dart'; import 'package:flowy_infra/image.dart'; diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/field_option_pannel.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/field_option_pannel.dart index 5e85ba9474..ce6c69d2cd 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/field_option_pannel.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/field_option_pannel.dart @@ -1,7 +1,7 @@ import 'package:app_flowy/workspace/application/grid/field/type_option/field_option_pannel_bloc.dart'; import 'package:app_flowy/workspace/presentation/plugins/grid/src/layout/sizes.dart'; import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/common/text_field.dart'; -import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/field_switcher.dart'; +import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/field_editor_pannel.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/workspace/presentation/plugins/grid/src/widgets/header/type_option/multi_select.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/multi_select.dart index fb5da57bec..b5b3ece1a8 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/multi_select.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/multi_select.dart @@ -1,6 +1,6 @@ import 'package:app_flowy/workspace/application/grid/field/type_option/multi_select_bloc.dart'; import 'package:app_flowy/workspace/application/grid/field/type_option/type_option_service.dart'; -import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/field_switcher.dart'; +import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/field_editor_pannel.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/number.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/number.dart index 591b54187f..b887fd53a9 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/number.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/number.dart @@ -3,7 +3,7 @@ import 'package:app_flowy/workspace/application/grid/field/type_option/number_bl import 'package:app_flowy/workspace/application/grid/field/type_option/number_format_bloc.dart'; import 'package:app_flowy/workspace/presentation/plugins/grid/src/layout/sizes.dart'; import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/common/text_field.dart'; -import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/field_switcher.dart'; +import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/field_editor_pannel.dart'; import 'package:flowy_infra/image.dart'; import 'package:flowy_infra/theme.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart'; diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/single_select.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/single_select.dart index 89d2f63a2d..f8cc2293f6 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/single_select.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/single_select.dart @@ -1,6 +1,6 @@ import 'package:app_flowy/workspace/application/grid/field/type_option/single_select_bloc.dart'; import 'package:app_flowy/workspace/application/grid/field/type_option/type_option_service.dart'; -import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/field_switcher.dart'; +import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/field_editor_pannel.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'field_option_pannel.dart'; From 6c2c3b0666233bd0a994c7d107dd2f5394ff5ec1 Mon Sep 17 00:00:00 2001 From: appflowy Date: Wed, 4 May 2022 21:06:11 +0800 Subject: [PATCH 3/7] fix: alignment in date cell --- .../grid/src/widgets/cell/cell_builder.dart | 2 +- .../grid/src/widgets/cell/date_cell.dart | 19 +++++++++++++++++-- .../grid/src/widgets/row/row_detail.dart | 4 +++- .../field/type_options/number_type_option.rs | 12 +++++++----- .../flowy-grid/src/services/grid_editor.rs | 6 +++++- 5 files changed, 33 insertions(+), 10 deletions(-) diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/cell_builder.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/cell_builder.dart index 0b13aab846..8efdffdb32 100755 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/cell_builder.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/cell_builder.dart @@ -23,7 +23,7 @@ GridCellWidget buildGridCellWidget(GridCell gridCell, GridCellCache cellCache, { case FieldType.Checkbox: return CheckboxCell(cellContextBuilder: cellContextBuilder, key: key); case FieldType.DateTime: - return DateCell(cellContextBuilder: cellContextBuilder, key: key); + return DateCell(cellContextBuilder: cellContextBuilder, key: key, style: style); case FieldType.SingleSelect: return SingleSelectCell(cellContextBuilder: cellContextBuilder, style: style, key: key); case FieldType.MultiSelect: diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/date_cell.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/date_cell.dart index a68bfcb4bc..194e5adf6a 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/date_cell.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/date_cell.dart @@ -8,6 +8,12 @@ import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:table_calendar/table_calendar.dart'; import 'cell_builder.dart'; +class DateCellStyle extends GridCellStyle { + Alignment alignment; + + DateCellStyle({this.alignment = Alignment.center}); +} + abstract class GridCellDelegate { void onFocus(bool isFocus); GridCellDelegate get delegate; @@ -15,11 +21,19 @@ abstract class GridCellDelegate { class DateCell extends GridCellWidget { final GridCellContextBuilder cellContextBuilder; + late final DateCellStyle? cellStyle; DateCell({ + GridCellStyle? style, required this.cellContextBuilder, Key? key, - }) : super(key: key); + }) : super(key: key) { + if (style != null) { + cellStyle = (style as DateCellStyle); + } else { + cellStyle = null; + } + } @override State createState() => _DateCellState(); @@ -37,6 +51,7 @@ class _DateCellState extends State { @override Widget build(BuildContext context) { + final alignment = widget.cellStyle != null ? widget.cellStyle!.alignment : Alignment.center; return BlocProvider.value( value: _cellBloc, child: BlocBuilder( @@ -57,7 +72,7 @@ class _DateCellState extends State { child: MouseRegion( opaque: false, cursor: SystemMouseCursors.click, - child: Center(child: FlowyText.medium(state.content, fontSize: 12)), + child: Align(alignment: alignment, child: FlowyText.medium(state.content, fontSize: 12)), ), ), ); diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/row/row_detail.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/row/row_detail.dart index ae82033320..7e2ece2cf5 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/row/row_detail.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/row/row_detail.dart @@ -165,7 +165,9 @@ GridCellStyle? _buildCellStyle(AppTheme theme, FieldType fieldType) { case FieldType.Checkbox: return null; case FieldType.DateTime: - return null; + return DateCellStyle( + alignment: Alignment.centerLeft, + ); case FieldType.MultiSelect: return SelectOptionCellStyle( placeholder: LocaleKeys.grid_row_textPlaceholder.tr(), diff --git a/frontend/rust-lib/flowy-grid/src/services/field/type_options/number_type_option.rs b/frontend/rust-lib/flowy-grid/src/services/field/type_options/number_type_option.rs index f403a28272..2d03a0ab33 100644 --- a/frontend/rust-lib/flowy-grid/src/services/field/type_options/number_type_option.rs +++ b/frontend/rust-lib/flowy-grid/src/services/field/type_options/number_type_option.rs @@ -110,11 +110,13 @@ impl CellDataOperation for NumberTypeOption { _cell_meta: Option, ) -> Result { let changeset = changeset.into(); - let data = changeset.to_string(); - let data = self.strip_symbol(data.trim()); + let mut data = changeset.trim().to_string(); - if !data.chars().all(char::is_numeric) { - return Err(FlowyError::invalid_data().context("Should only contain numbers")); + if self.format != NumberFormat::Number { + data = self.strip_symbol(data); + if !data.chars().all(char::is_numeric) { + return Err(FlowyError::invalid_data().context("Should only contain numbers")); + } } Ok(TypeOptionCellData::new(&data, self.field_type()).json()) @@ -168,7 +170,7 @@ impl NumberTypeOption { } } -#[derive(Clone, Copy, Debug, EnumIter, Serialize, Deserialize, ProtoBuf_Enum)] +#[derive(Clone, Copy, Debug, PartialEq, Eq, EnumIter, Serialize, Deserialize, ProtoBuf_Enum)] pub enum NumberFormat { Number = 0, USD = 1, 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 d8d909cabe..5962386352 100644 --- a/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs +++ b/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs @@ -316,7 +316,11 @@ impl ClientGridEditor { let cell_data_changeset = changeset.data.unwrap(); let cell_meta = self.get_cell_meta(&changeset.row_id, &changeset.field_id).await?; - tracing::trace!("{}: {:?}", &changeset.field_id, cell_meta); + tracing::trace!( + "field changeset: id:{} / value:{}", + &changeset.field_id, + cell_data_changeset + ); match self.grid_pad.read().await.get_field_meta(&changeset.field_id) { None => { let msg = format!("Field not found with id: {}", &changeset.field_id); From 448c134704ba0c02e329bab5604e3c3bad1826c8 Mon Sep 17 00:00:00 2001 From: appflowy Date: Thu, 5 May 2022 10:45:53 +0800 Subject: [PATCH 4/7] fix: update workspace setting --- .../app_flowy/lib/startup/deps_resolver.dart | 7 -- .../lib/user/application/user_listener.dart | 74 ++++++++++++++----- .../workspace/application/home/home_bloc.dart | 51 ++++++++++++- .../application/home/home_listen_bloc.dart | 54 -------------- .../workspace/application/home/prelude.dart | 2 +- .../application/menu/menu_user_bloc.dart | 9 ++- .../application/workspace/welcome_bloc.dart | 9 +-- .../presentation/home/home_screen.dart | 39 +++++----- .../dart_notification.pbenum.dart | 2 + .../dart_notification.pbjson.dart | 3 +- .../flowy-folder/src/dart_notification.rs | 1 + .../src/protobuf/model/dart_notification.rs | 14 ++-- .../protobuf/proto/dart_notification.proto | 1 + .../src/services/view/event_handler.rs | 5 +- .../src/services/workspace/controller.rs | 39 ++++++++++ .../src/entities/view.rs | 8 ++ 16 files changed, 197 insertions(+), 121 deletions(-) delete mode 100644 frontend/app_flowy/lib/workspace/application/home/home_listen_bloc.dart diff --git a/frontend/app_flowy/lib/startup/deps_resolver.dart b/frontend/app_flowy/lib/startup/deps_resolver.dart index a0daac273d..76b694542b 100644 --- a/frontend/app_flowy/lib/startup/deps_resolver.dart +++ b/frontend/app_flowy/lib/startup/deps_resolver.dart @@ -7,9 +7,7 @@ import 'package:app_flowy/workspace/application/grid/prelude.dart'; import 'package:app_flowy/workspace/application/trash/prelude.dart'; import 'package:app_flowy/workspace/application/workspace/prelude.dart'; import 'package:app_flowy/workspace/application/edit_pannel/edit_pannel_bloc.dart'; -import 'package:app_flowy/workspace/application/home/home_bloc.dart'; import 'package:app_flowy/workspace/application/view/prelude.dart'; -import 'package:app_flowy/workspace/application/home/prelude.dart'; import 'package:app_flowy/workspace/application/menu/prelude.dart'; import 'package:app_flowy/user/application/prelude.dart'; import 'package:app_flowy/user/presentation/router.dart'; @@ -45,7 +43,6 @@ void _resolveUserDeps(GetIt getIt) { getIt.registerFactory(() => SignUpBloc(getIt())); getIt.registerFactory(() => SplashRoute()); - getIt.registerFactory(() => HomeBloc()); getIt.registerFactory(() => EditPannelBloc()); getIt.registerFactory(() => SplashBloc()); getIt.registerLazySingleton(() => NetworkListener()); @@ -58,10 +55,6 @@ void _resolveHomeDeps(GetIt getIt) { (user, _) => UserListener(user: user), ); - getIt.registerFactoryParam( - (user, _) => HomeListenBloc(getIt(param1: user)), - ); - // getIt.registerLazySingleton(() => HomeStackManager()); diff --git a/frontend/app_flowy/lib/user/application/user_listener.dart b/frontend/app_flowy/lib/user/application/user_listener.dart index 5b212cc2d0..acacb19b02 100644 --- a/frontend/app_flowy/lib/user/application/user_listener.dart +++ b/frontend/app_flowy/lib/user/application/user_listener.dart @@ -12,26 +12,55 @@ import 'package:flowy_sdk/protobuf/flowy-user-data-model/user_profile.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-user/dart_notification.pb.dart' as user; import 'package:flowy_sdk/rust_stream.dart'; -typedef UserProfileUpdatedNotifierValue = Either; -typedef AuthNotifierValue = Either; -typedef WorkspaceUpdatedNotifierValue = Either, FlowyError>; +typedef UserProfileDidUpdate = Either; +typedef AuthDidUpdate = Either; +typedef WorkspaceListDidUpdate = Either, FlowyError>; +typedef WorkspaceSettingDidUpdate = Either; class UserListener { StreamSubscription? _subscription; - final profileUpdatedNotifier = PublishNotifier(); - final authDidChangedNotifier = PublishNotifier(); - final workspaceUpdatedNotifier = PublishNotifier(); + final _profileNotifier = PublishNotifier(); + final _authNotifier = PublishNotifier(); + final _workspaceListNotifier = PublishNotifier(); + final _workSettingNotifier = PublishNotifier(); FolderNotificationParser? _workspaceParser; UserNotificationParser? _userParser; - late UserProfile _user; + final UserProfile _user; UserListener({ required UserProfile user, - }) { - _user = user; - } + }) : _user = user; + + void start({ + void Function(AuthDidUpdate)? authDidChange, + void Function(UserProfileDidUpdate)? profileDidUpdate, + void Function(WorkspaceListDidUpdate)? workspaceListDidUpdate, + void Function(WorkspaceSettingDidUpdate)? workspaceSettingDidUpdate, + }) { + if (authDidChange != null) { + _authNotifier.addListener(() { + authDidChange(_authNotifier.currentValue!); + }); + } + + if (profileDidUpdate != null) { + _profileNotifier.addListener(() { + profileDidUpdate(_profileNotifier.currentValue!); + }); + } + + if (workspaceListDidUpdate != null) { + _workspaceListNotifier.addListener(() { + workspaceListDidUpdate(_workspaceListNotifier.currentValue!); + }); + } + + if (workspaceSettingDidUpdate != null) { + _workSettingNotifier.addListener(() { + workspaceSettingDidUpdate(_workSettingNotifier.currentValue!); + }); + } - void start() { _workspaceParser = FolderNotificationParser(id: _user.token, callback: _notificationCallback); _userParser = UserNotificationParser(id: _user.token, callback: _userNotificationCallback); _subscription = RustStreamReceiver.listen((observable) { @@ -44,9 +73,9 @@ class UserListener { _workspaceParser = null; _userParser = null; await _subscription?.cancel(); - profileUpdatedNotifier.dispose(); - authDidChangedNotifier.dispose(); - workspaceUpdatedNotifier.dispose(); + _profileNotifier.dispose(); + _authNotifier.dispose(); + _workspaceListNotifier.dispose(); } void _notificationCallback(FolderNotification ty, Either result) { @@ -55,16 +84,23 @@ class UserListener { case FolderNotification.UserDeleteWorkspace: case FolderNotification.WorkspaceListUpdated: result.fold( - (payload) => workspaceUpdatedNotifier.value = left(RepeatedWorkspace.fromBuffer(payload).items), - (error) => workspaceUpdatedNotifier.value = right(error), + (payload) => _workspaceListNotifier.value = left(RepeatedWorkspace.fromBuffer(payload).items), + (error) => _workspaceListNotifier.value = right(error), + ); + break; + case FolderNotification.WorkspaceSetting: + result.fold( + (payload) => _workSettingNotifier.value = left(CurrentWorkspaceSetting.fromBuffer(payload)), + (error) => _workSettingNotifier.value = right(error), ); break; case FolderNotification.UserUnauthorized: result.fold( (_) {}, - (error) => authDidChangedNotifier.value = right(FlowyError.create()..code = ErrorCode.UserUnauthorized.value), + (error) => _authNotifier.value = right(FlowyError.create()..code = ErrorCode.UserUnauthorized.value), ); break; + default: break; } @@ -74,8 +110,8 @@ class UserListener { switch (ty) { case user.UserNotification.UserUnauthorized: result.fold( - (payload) => profileUpdatedNotifier.value = left(UserProfile.fromBuffer(payload)), - (error) => profileUpdatedNotifier.value = right(error), + (payload) => _profileNotifier.value = left(UserProfile.fromBuffer(payload)), + (error) => _profileNotifier.value = right(error), ); break; default: diff --git a/frontend/app_flowy/lib/workspace/application/home/home_bloc.dart b/frontend/app_flowy/lib/workspace/application/home/home_bloc.dart index 5ed7ce959d..f401f0a0ca 100644 --- a/frontend/app_flowy/lib/workspace/application/home/home_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/home/home_bloc.dart @@ -1,13 +1,36 @@ +import 'package:app_flowy/user/application/user_listener.dart'; import 'package:app_flowy/workspace/application/edit_pannel/edit_context.dart'; +import 'package:flowy_sdk/log.dart'; +import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-folder-data-model/workspace.pb.dart' show CurrentWorkspaceSetting; +import 'package:flowy_sdk/protobuf/flowy-user-data-model/errors.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-user-data-model/user_profile.pb.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; import 'package:dartz/dartz.dart'; part 'home_bloc.freezed.dart'; class HomeBloc extends Bloc { - HomeBloc() : super(HomeState.initial()) { + final UserListener _listener; + + HomeBloc(UserProfile user, CurrentWorkspaceSetting workspaceSetting) + : _listener = UserListener(user: user), + super(HomeState.initial(workspaceSetting)) { on((event, emit) async { await event.map( + initial: (_Initial value) { + _listener.start( + authDidChange: (result) { + _authDidChanged(result); + }, + workspaceSettingDidUpdate: (result) { + result.fold( + (setting) => add(HomeEvent.didReceiveWorkspaceSetting(setting)), + (r) => Log.error(r), + ); + }, + ); + }, showLoading: (e) async { emit(state.copyWith(isLoading: e.isLoading)); }, @@ -20,22 +43,40 @@ class HomeBloc extends Bloc { forceCollapse: (e) async { emit(state.copyWith(forceCollapse: e.forceCollapse)); }, + didReceiveWorkspaceSetting: (_DidReceiveWorkspaceSetting value) { + emit(state.copyWith(workspaceSetting: value.setting)); + }, + unauthorized: (_Unauthorized value) { + emit(state.copyWith(unauthorized: true)); + }, ); }); } @override - Future close() { + Future close() async { + await _listener.stop(); return super.close(); } + + void _authDidChanged(Either errorOrNothing) { + errorOrNothing.fold((_) {}, (error) { + if (error.code == ErrorCode.UserUnauthorized.value) { + add(HomeEvent.unauthorized(error.msg)); + } + }); + } } @freezed class HomeEvent with _$HomeEvent { + const factory HomeEvent.initial() = _Initial; const factory HomeEvent.showLoading(bool isLoading) = _ShowLoading; const factory HomeEvent.forceCollapse(bool forceCollapse) = _ForceCollapse; const factory HomeEvent.setEditPannel(EditPannelContext editContext) = _ShowEditPannel; const factory HomeEvent.dismissEditPannel() = _DismissEditPannel; + const factory HomeEvent.didReceiveWorkspaceSetting(CurrentWorkspaceSetting setting) = _DidReceiveWorkspaceSetting; + const factory HomeEvent.unauthorized(String msg) = _Unauthorized; } @freezed @@ -44,11 +85,15 @@ class HomeState with _$HomeState { required bool isLoading, required bool forceCollapse, required Option pannelContext, + required CurrentWorkspaceSetting workspaceSetting, + required bool unauthorized, }) = _HomeState; - factory HomeState.initial() => HomeState( + factory HomeState.initial(CurrentWorkspaceSetting workspaceSetting) => HomeState( isLoading: false, forceCollapse: false, pannelContext: none(), + workspaceSetting: workspaceSetting, + unauthorized: false, ); } diff --git a/frontend/app_flowy/lib/workspace/application/home/home_listen_bloc.dart b/frontend/app_flowy/lib/workspace/application/home/home_listen_bloc.dart deleted file mode 100644 index 0ebb572e17..0000000000 --- a/frontend/app_flowy/lib/workspace/application/home/home_listen_bloc.dart +++ /dev/null @@ -1,54 +0,0 @@ -import 'package:app_flowy/user/application/user_listener.dart'; -import 'package:flowy_sdk/protobuf/error-code/error_code.pbenum.dart'; -import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; -import 'package:freezed_annotation/freezed_annotation.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:dartz/dartz.dart'; -part 'home_listen_bloc.freezed.dart'; - -class HomeListenBloc extends Bloc { - final UserListener listener; - HomeListenBloc(this.listener) : super(const HomeListenState.loading()) { - on((event, emit) async { - await event.map( - started: (_) async { - listener.authDidChangedNotifier.addPublishListener((result) { - _authDidChanged(result); - }); - listener.start(); - }, - stop: (_) async {}, - unauthorized: (e) async { - emit(HomeListenState.unauthorized(e.msg)); - }, - ); - }); - } - - @override - Future close() async { - await listener.stop(); - super.close(); - } - - void _authDidChanged(Either errorOrNothing) { - errorOrNothing.fold((_) {}, (error) { - if (error.code == ErrorCode.UserUnauthorized.value) { - add(HomeListenEvent.unauthorized(error.msg)); - } - }); - } -} - -@freezed -class HomeListenEvent with _$HomeListenEvent { - const factory HomeListenEvent.started() = _Started; - const factory HomeListenEvent.stop() = _Stop; - const factory HomeListenEvent.unauthorized(String msg) = _Unauthorized; -} - -@freezed -class HomeListenState with _$HomeListenState { - const factory HomeListenState.loading() = Loading; - const factory HomeListenState.unauthorized(String msg) = Unauthorized; -} diff --git a/frontend/app_flowy/lib/workspace/application/home/prelude.dart b/frontend/app_flowy/lib/workspace/application/home/prelude.dart index 8d1173c2d6..8b13789179 100644 --- a/frontend/app_flowy/lib/workspace/application/home/prelude.dart +++ b/frontend/app_flowy/lib/workspace/application/home/prelude.dart @@ -1 +1 @@ -export 'home_listen_bloc.dart'; + diff --git a/frontend/app_flowy/lib/workspace/application/menu/menu_user_bloc.dart b/frontend/app_flowy/lib/workspace/application/menu/menu_user_bloc.dart index 5129612ecb..d0970cae21 100644 --- a/frontend/app_flowy/lib/workspace/application/menu/menu_user_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/menu/menu_user_bloc.dart @@ -19,9 +19,10 @@ class MenuUserBloc extends Bloc { on((event, emit) async { await event.map( initial: (_) async { - userListener.profileUpdatedNotifier.addPublishListener(_profileUpdated); - userListener.workspaceUpdatedNotifier.addPublishListener(_workspacesUpdated); - userListener.start(); + userListener.start( + profileDidUpdate: _profileUpdated, + workspaceListDidUpdate: _workspaceListUpdated, + ); await _initUser(); }, fetchWorkspaces: (_FetchWorkspaces value) async {}, @@ -41,7 +42,7 @@ class MenuUserBloc extends Bloc { } void _profileUpdated(Either userOrFailed) {} - void _workspacesUpdated(Either, FlowyError> workspacesOrFailed) { + void _workspaceListUpdated(Either, FlowyError> workspacesOrFailed) { // fetch workspaces // iUserImpl.fetchWorkspaces().then((result) { // result.fold( diff --git a/frontend/app_flowy/lib/workspace/application/workspace/welcome_bloc.dart b/frontend/app_flowy/lib/workspace/application/workspace/welcome_bloc.dart index 8276331d10..8ad83925b4 100644 --- a/frontend/app_flowy/lib/workspace/application/workspace/welcome_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/workspace/welcome_bloc.dart @@ -16,8 +16,9 @@ class WelcomeBloc extends Bloc { on( (event, emit) async { await event.map(initial: (e) async { - userListener.workspaceUpdatedNotifier.addPublishListener(_workspacesUpdated); - userListener.start(); + userListener.start( + workspaceListDidUpdate: (result) => add(WelcomeEvent.workspacesReveived(result)), + ); // await _fetchWorkspaces(emit); }, openWorkspace: (e) async { @@ -74,10 +75,6 @@ class WelcomeBloc extends Bloc { }, )); } - - void _workspacesUpdated(Either, FlowyError> workspacesOrFail) { - add(WelcomeEvent.workspacesReveived(workspacesOrFail)); - } } @freezed diff --git a/frontend/app_flowy/lib/workspace/presentation/home/home_screen.dart b/frontend/app_flowy/lib/workspace/presentation/home/home_screen.dart index cea29792cb..86fa9fab79 100644 --- a/frontend/app_flowy/lib/workspace/presentation/home/home_screen.dart +++ b/frontend/app_flowy/lib/workspace/presentation/home/home_screen.dart @@ -1,6 +1,5 @@ import 'package:app_flowy/plugin/plugin.dart'; import 'package:app_flowy/workspace/application/home/home_bloc.dart'; -import 'package:app_flowy/workspace/application/home/home_listen_bloc.dart'; import 'package:app_flowy/workspace/presentation/widgets/edit_pannel/pannel_animation.dart'; import 'package:app_flowy/workspace/presentation/widgets/float_bubble/question_bubble.dart'; import 'package:app_flowy/startup/startup.dart'; @@ -46,22 +45,20 @@ class _HomeScreenState extends State { Widget build(BuildContext context) { return MultiBlocProvider( providers: [ - BlocProvider( - create: (context) => getIt(param1: widget.user)..add(const HomeListenEvent.started()), + BlocProvider( + create: (context) { + return HomeBloc(widget.user, widget.workspaceSetting)..add(const HomeEvent.initial()); + }, ), - BlocProvider(create: (context) => getIt()), ], child: Scaffold( key: HomeScreen.scaffoldKey, - body: BlocListener( + body: BlocListener( + listenWhen: (p, c) => p.unauthorized != c.unauthorized, listener: (context, state) { - state.map( - loading: (_) {}, - unauthorized: (unauthorized) { - // TODO: push to login screen when user token was invalid - Log.error("Push to login screen when user token was invalid"); - }, - ); + if (state.unauthorized) { + Log.error("Push to login screen when user token was invalid"); + } }, child: BlocBuilder( buildWhen: (previous, current) => previous != current, @@ -73,7 +70,7 @@ class _HomeScreenState extends State { return FlowyContainer( Theme.of(context).colorScheme.surface, // Colors.white, - child: _buildBody(state, context.read().state.forceCollapse), + child: _buildBody(state), ); }, ), @@ -82,14 +79,15 @@ class _HomeScreenState extends State { ); } - Widget _buildBody(HomeState state, bool forceCollapse) { + Widget _buildBody(HomeState state) { return LayoutBuilder( builder: (BuildContext context, BoxConstraints constraints) { - final layout = HomeLayout(context, constraints, forceCollapse); + final layout = HomeLayout(context, constraints, state.forceCollapse); const homeStack = HomeStack(); final menu = _buildHomeMenu( layout: layout, context: context, + state: state, ); final editPannel = _buildEditPannel( homeState: state, @@ -108,20 +106,21 @@ class _HomeScreenState extends State { ); } - Widget _buildHomeMenu({required HomeLayout layout, required BuildContext context}) { - if (initialView == null && widget.workspaceSetting.hasLatestView()) { - initialView = widget.workspaceSetting.latestView; + Widget _buildHomeMenu({required HomeLayout layout, required BuildContext context, required HomeState state}) { + final workspaceSetting = state.workspaceSetting; + if (initialView == null && workspaceSetting.hasLatestView()) { + initialView = workspaceSetting.latestView; final plugin = makePlugin(pluginType: initialView!.pluginType, data: initialView); getIt().setPlugin(plugin); } HomeMenu homeMenu = HomeMenu( user: widget.user, - workspaceSetting: widget.workspaceSetting, + workspaceSetting: workspaceSetting, collapsedNotifier: getIt().collapsedNotifier, ); - final latestView = widget.workspaceSetting.hasLatestView() ? widget.workspaceSetting.latestView : null; + final latestView = workspaceSetting.hasLatestView() ? workspaceSetting.latestView : null; getIt().latestOpenView = latestView; return FocusTraversalGroup(child: RepaintBoundary(child: homeMenu)); diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-folder/dart_notification.pbenum.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-folder/dart_notification.pbenum.dart index 5ecb48f9fd..84042c03f6 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-folder/dart_notification.pbenum.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-folder/dart_notification.pbenum.dart @@ -16,6 +16,7 @@ class FolderNotification extends $pb.ProtobufEnum { static const FolderNotification WorkspaceUpdated = FolderNotification._(12, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'WorkspaceUpdated'); static const FolderNotification WorkspaceListUpdated = FolderNotification._(13, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'WorkspaceListUpdated'); static const FolderNotification WorkspaceAppsChanged = FolderNotification._(14, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'WorkspaceAppsChanged'); + static const FolderNotification WorkspaceSetting = FolderNotification._(15, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'WorkspaceSetting'); static const FolderNotification AppUpdated = FolderNotification._(21, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'AppUpdated'); static const FolderNotification AppViewsChanged = FolderNotification._(24, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'AppViewsChanged'); static const FolderNotification ViewUpdated = FolderNotification._(31, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'ViewUpdated'); @@ -31,6 +32,7 @@ class FolderNotification extends $pb.ProtobufEnum { WorkspaceUpdated, WorkspaceListUpdated, WorkspaceAppsChanged, + WorkspaceSetting, AppUpdated, AppViewsChanged, ViewUpdated, diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-folder/dart_notification.pbjson.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-folder/dart_notification.pbjson.dart index 7cbe5621ba..a58f1e6705 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-folder/dart_notification.pbjson.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-folder/dart_notification.pbjson.dart @@ -18,6 +18,7 @@ const FolderNotification$json = const { const {'1': 'WorkspaceUpdated', '2': 12}, const {'1': 'WorkspaceListUpdated', '2': 13}, const {'1': 'WorkspaceAppsChanged', '2': 14}, + const {'1': 'WorkspaceSetting', '2': 15}, const {'1': 'AppUpdated', '2': 21}, const {'1': 'AppViewsChanged', '2': 24}, const {'1': 'ViewUpdated', '2': 31}, @@ -29,4 +30,4 @@ const FolderNotification$json = const { }; /// Descriptor for `FolderNotification`. Decode as a `google.protobuf.EnumDescriptorProto`. -final $typed_data.Uint8List folderNotificationDescriptor = $convert.base64Decode('ChJGb2xkZXJOb3RpZmljYXRpb24SCwoHVW5rbm93bhAAEhcKE1VzZXJDcmVhdGVXb3Jrc3BhY2UQChIXChNVc2VyRGVsZXRlV29ya3NwYWNlEAsSFAoQV29ya3NwYWNlVXBkYXRlZBAMEhgKFFdvcmtzcGFjZUxpc3RVcGRhdGVkEA0SGAoUV29ya3NwYWNlQXBwc0NoYW5nZWQQDhIOCgpBcHBVcGRhdGVkEBUSEwoPQXBwVmlld3NDaGFuZ2VkEBgSDwoLVmlld1VwZGF0ZWQQHxIPCgtWaWV3RGVsZXRlZBAgEhAKDFZpZXdSZXN0b3JlZBAhEhQKEFVzZXJVbmF1dGhvcml6ZWQQZBIRCgxUcmFzaFVwZGF0ZWQQ6Ac='); +final $typed_data.Uint8List folderNotificationDescriptor = $convert.base64Decode('ChJGb2xkZXJOb3RpZmljYXRpb24SCwoHVW5rbm93bhAAEhcKE1VzZXJDcmVhdGVXb3Jrc3BhY2UQChIXChNVc2VyRGVsZXRlV29ya3NwYWNlEAsSFAoQV29ya3NwYWNlVXBkYXRlZBAMEhgKFFdvcmtzcGFjZUxpc3RVcGRhdGVkEA0SGAoUV29ya3NwYWNlQXBwc0NoYW5nZWQQDhIUChBXb3Jrc3BhY2VTZXR0aW5nEA8SDgoKQXBwVXBkYXRlZBAVEhMKD0FwcFZpZXdzQ2hhbmdlZBAYEg8KC1ZpZXdVcGRhdGVkEB8SDwoLVmlld0RlbGV0ZWQQIBIQCgxWaWV3UmVzdG9yZWQQIRIUChBVc2VyVW5hdXRob3JpemVkEGQSEQoMVHJhc2hVcGRhdGVkEOgH'); diff --git a/frontend/rust-lib/flowy-folder/src/dart_notification.rs b/frontend/rust-lib/flowy-folder/src/dart_notification.rs index 9daaa6c387..c062bd4a70 100644 --- a/frontend/rust-lib/flowy-folder/src/dart_notification.rs +++ b/frontend/rust-lib/flowy-folder/src/dart_notification.rs @@ -10,6 +10,7 @@ pub(crate) enum FolderNotification { WorkspaceUpdated = 12, WorkspaceListUpdated = 13, WorkspaceAppsChanged = 14, + WorkspaceSetting = 15, AppUpdated = 21, AppViewsChanged = 24, ViewUpdated = 31, diff --git a/frontend/rust-lib/flowy-folder/src/protobuf/model/dart_notification.rs b/frontend/rust-lib/flowy-folder/src/protobuf/model/dart_notification.rs index d43a627f4b..f57f71114b 100644 --- a/frontend/rust-lib/flowy-folder/src/protobuf/model/dart_notification.rs +++ b/frontend/rust-lib/flowy-folder/src/protobuf/model/dart_notification.rs @@ -31,6 +31,7 @@ pub enum FolderNotification { WorkspaceUpdated = 12, WorkspaceListUpdated = 13, WorkspaceAppsChanged = 14, + WorkspaceSetting = 15, AppUpdated = 21, AppViewsChanged = 24, ViewUpdated = 31, @@ -53,6 +54,7 @@ impl ::protobuf::ProtobufEnum for FolderNotification { 12 => ::std::option::Option::Some(FolderNotification::WorkspaceUpdated), 13 => ::std::option::Option::Some(FolderNotification::WorkspaceListUpdated), 14 => ::std::option::Option::Some(FolderNotification::WorkspaceAppsChanged), + 15 => ::std::option::Option::Some(FolderNotification::WorkspaceSetting), 21 => ::std::option::Option::Some(FolderNotification::AppUpdated), 24 => ::std::option::Option::Some(FolderNotification::AppViewsChanged), 31 => ::std::option::Option::Some(FolderNotification::ViewUpdated), @@ -72,6 +74,7 @@ impl ::protobuf::ProtobufEnum for FolderNotification { FolderNotification::WorkspaceUpdated, FolderNotification::WorkspaceListUpdated, FolderNotification::WorkspaceAppsChanged, + FolderNotification::WorkspaceSetting, FolderNotification::AppUpdated, FolderNotification::AppViewsChanged, FolderNotification::ViewUpdated, @@ -107,14 +110,15 @@ impl ::protobuf::reflect::ProtobufValue for FolderNotification { } static file_descriptor_proto_data: &'static [u8] = b"\ - \n\x17dart_notification.proto*\x9f\x02\n\x12FolderNotification\x12\x0b\n\ + \n\x17dart_notification.proto*\xb5\x02\n\x12FolderNotification\x12\x0b\n\ \x07Unknown\x10\0\x12\x17\n\x13UserCreateWorkspace\x10\n\x12\x17\n\x13Us\ erDeleteWorkspace\x10\x0b\x12\x14\n\x10WorkspaceUpdated\x10\x0c\x12\x18\ \n\x14WorkspaceListUpdated\x10\r\x12\x18\n\x14WorkspaceAppsChanged\x10\ - \x0e\x12\x0e\n\nAppUpdated\x10\x15\x12\x13\n\x0fAppViewsChanged\x10\x18\ - \x12\x0f\n\x0bViewUpdated\x10\x1f\x12\x0f\n\x0bViewDeleted\x10\x20\x12\ - \x10\n\x0cViewRestored\x10!\x12\x14\n\x10UserUnauthorized\x10d\x12\x11\n\ - \x0cTrashUpdated\x10\xe8\x07b\x06proto3\ + \x0e\x12\x14\n\x10WorkspaceSetting\x10\x0f\x12\x0e\n\nAppUpdated\x10\x15\ + \x12\x13\n\x0fAppViewsChanged\x10\x18\x12\x0f\n\x0bViewUpdated\x10\x1f\ + \x12\x0f\n\x0bViewDeleted\x10\x20\x12\x10\n\x0cViewRestored\x10!\x12\x14\ + \n\x10UserUnauthorized\x10d\x12\x11\n\x0cTrashUpdated\x10\xe8\x07b\x06pr\ + oto3\ "; static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT; diff --git a/frontend/rust-lib/flowy-folder/src/protobuf/proto/dart_notification.proto b/frontend/rust-lib/flowy-folder/src/protobuf/proto/dart_notification.proto index 7a87552f7d..feff6258f6 100644 --- a/frontend/rust-lib/flowy-folder/src/protobuf/proto/dart_notification.proto +++ b/frontend/rust-lib/flowy-folder/src/protobuf/proto/dart_notification.proto @@ -7,6 +7,7 @@ enum FolderNotification { WorkspaceUpdated = 12; WorkspaceListUpdated = 13; WorkspaceAppsChanged = 14; + WorkspaceSetting = 15; AppUpdated = 21; AppViewsChanged = 24; ViewUpdated = 31; diff --git a/frontend/rust-lib/flowy-folder/src/services/view/event_handler.rs b/frontend/rust-lib/flowy-folder/src/services/view/event_handler.rs index e7c91dda38..caa8134785 100644 --- a/frontend/rust-lib/flowy-folder/src/services/view/event_handler.rs +++ b/frontend/rust-lib/flowy-folder/src/services/view/event_handler.rs @@ -1,4 +1,5 @@ -use crate::services::AppController; +use crate::manager::FolderManager; +use crate::services::{notify_workspace_setting_did_change, AppController}; use crate::{ entities::{ trash::Trash, @@ -69,10 +70,12 @@ pub(crate) async fn delete_view_handler( pub(crate) async fn set_latest_view_handler( data: Data, + folder: AppData>, controller: AppData>, ) -> Result<(), FlowyError> { let view_id: ViewId = data.into_inner(); let _ = controller.set_latest_view(&view_id.value)?; + let _ = notify_workspace_setting_did_change(&folder, &view_id).await?; Ok(()) } diff --git a/frontend/rust-lib/flowy-folder/src/services/workspace/controller.rs b/frontend/rust-lib/flowy-folder/src/services/workspace/controller.rs index ddbf7b32bd..b343c5b46d 100644 --- a/frontend/rust-lib/flowy-folder/src/services/workspace/controller.rs +++ b/frontend/rust-lib/flowy-folder/src/services/workspace/controller.rs @@ -1,3 +1,4 @@ +use crate::manager::FolderManager; use crate::{ dart_notification::*, errors::*, @@ -190,6 +191,44 @@ impl WorkspaceController { } } +pub async fn notify_workspace_setting_did_change( + folder_manager: &Arc, + view_id: &str, +) -> FlowyResult<()> { + let user_id = folder_manager.user.user_id()?; + let token = folder_manager.user.token()?; + let workspace_id = get_current_workspace()?; + + let workspace_setting = folder_manager + .persistence + .begin_transaction(|transaction| { + let workspace = folder_manager.workspace_controller.read_local_workspace( + workspace_id.clone(), + &user_id, + &transaction, + )?; + + let setting = match transaction.read_view(view_id) { + Ok(latest_view) => CurrentWorkspaceSetting { + workspace, + latest_view: Some(latest_view), + }, + Err(_) => CurrentWorkspaceSetting { + workspace, + latest_view: None, + }, + }; + + Ok(setting) + }) + .await?; + + send_dart_notification(&token, FolderNotification::WorkspaceSetting) + .payload(workspace_setting) + .send(); + Ok(()) +} + const CURRENT_WORKSPACE_ID: &str = "current_workspace_id"; pub fn set_current_workspace(workspace_id: &str) { diff --git a/shared-lib/flowy-folder-data-model/src/entities/view.rs b/shared-lib/flowy-folder-data-model/src/entities/view.rs index c536d04f50..400649dac1 100644 --- a/shared-lib/flowy-folder-data-model/src/entities/view.rs +++ b/shared-lib/flowy-folder-data-model/src/entities/view.rs @@ -201,6 +201,14 @@ impl std::convert::From<&str> for ViewId { } } +impl std::ops::Deref for ViewId { + type Target = str; + + fn deref(&self) -> &Self::Target { + &self.value + } +} + #[derive(Default, ProtoBuf)] pub struct RepeatedViewId { #[pb(index = 1)] From 2f2b69d1a6447a66438a314c7f92365dc07b282a Mon Sep 17 00:00:00 2001 From: appflowy Date: Thu, 5 May 2022 21:15:01 +0800 Subject: [PATCH 5/7] fix: view title update issue --- .../lib/user/application/user_listener.dart | 40 +++++++-------- .../workspace/application/app/app_bloc.dart | 6 +-- .../application/app/app_listener.dart | 8 +-- .../workspace/application/doc/doc_bloc.dart | 31 ++++++------ .../workspace/application/home/home_bloc.dart | 4 +- .../application/menu/menu_user_bloc.dart | 4 +- .../workspace/application/view/view_bloc.dart | 16 ++---- .../application/view/view_listener.dart | 50 +++++++++++++------ .../application/workspace/welcome_bloc.dart | 2 +- .../presentation/plugins/doc/document.dart | 5 +- .../plugins/widgets/left_bar_item.dart | 29 ++++++++--- 11 files changed, 113 insertions(+), 82 deletions(-) diff --git a/frontend/app_flowy/lib/user/application/user_listener.dart b/frontend/app_flowy/lib/user/application/user_listener.dart index acacb19b02..6bfede73ce 100644 --- a/frontend/app_flowy/lib/user/application/user_listener.dart +++ b/frontend/app_flowy/lib/user/application/user_listener.dart @@ -12,17 +12,17 @@ import 'package:flowy_sdk/protobuf/flowy-user-data-model/user_profile.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-user/dart_notification.pb.dart' as user; import 'package:flowy_sdk/rust_stream.dart'; -typedef UserProfileDidUpdate = Either; -typedef AuthDidUpdate = Either; -typedef WorkspaceListDidUpdate = Either, FlowyError>; -typedef WorkspaceSettingDidUpdate = Either; +typedef UserProfileNotifyValue = Either; +typedef AuthNotifyValue = Either; +typedef WorkspaceListNotifyValue = Either, FlowyError>; +typedef WorkspaceSettingNotifyValue = Either; class UserListener { StreamSubscription? _subscription; - final _profileNotifier = PublishNotifier(); - final _authNotifier = PublishNotifier(); - final _workspaceListNotifier = PublishNotifier(); - final _workSettingNotifier = PublishNotifier(); + final _profileNotifier = PublishNotifier(); + final _authNotifier = PublishNotifier(); + final _workspaceListNotifier = PublishNotifier(); + final _workSettingNotifier = PublishNotifier(); FolderNotificationParser? _workspaceParser; UserNotificationParser? _userParser; @@ -32,32 +32,32 @@ class UserListener { }) : _user = user; void start({ - void Function(AuthDidUpdate)? authDidChange, - void Function(UserProfileDidUpdate)? profileDidUpdate, - void Function(WorkspaceListDidUpdate)? workspaceListDidUpdate, - void Function(WorkspaceSettingDidUpdate)? workspaceSettingDidUpdate, + void Function(AuthNotifyValue)? onAuthChanged, + void Function(UserProfileNotifyValue)? onProfileUpdated, + void Function(WorkspaceListNotifyValue)? onWorkspaceListUpdated, + void Function(WorkspaceSettingNotifyValue)? onWorkspaceSettingUpdated, }) { - if (authDidChange != null) { + if (onAuthChanged != null) { _authNotifier.addListener(() { - authDidChange(_authNotifier.currentValue!); + onAuthChanged(_authNotifier.currentValue!); }); } - if (profileDidUpdate != null) { + if (onProfileUpdated != null) { _profileNotifier.addListener(() { - profileDidUpdate(_profileNotifier.currentValue!); + onProfileUpdated(_profileNotifier.currentValue!); }); } - if (workspaceListDidUpdate != null) { + if (onWorkspaceListUpdated != null) { _workspaceListNotifier.addListener(() { - workspaceListDidUpdate(_workspaceListNotifier.currentValue!); + onWorkspaceListUpdated(_workspaceListNotifier.currentValue!); }); } - if (workspaceSettingDidUpdate != null) { + if (onWorkspaceSettingUpdated != null) { _workSettingNotifier.addListener(() { - workspaceSettingDidUpdate(_workSettingNotifier.currentValue!); + onWorkspaceSettingUpdated(_workSettingNotifier.currentValue!); }); } diff --git a/frontend/app_flowy/lib/workspace/application/app/app_bloc.dart b/frontend/app_flowy/lib/workspace/application/app/app_bloc.dart index 4dd10675e0..663e630a6a 100644 --- a/frontend/app_flowy/lib/workspace/application/app/app_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/app/app_bloc.dart @@ -41,7 +41,7 @@ class AppBloc extends Bloc { void _startListening() { appListener.start( - viewsChanged: (result) { + onViewsChanged: (result) { result.fold( (views) { if (!isClosed) { @@ -51,7 +51,7 @@ class AppBloc extends Bloc { (error) => Log.error(error), ); }, - appUpdated: (app) { + onAppUpdated: (app) { if (!isClosed) { add(AppEvent.appDidUpdate(app)); } @@ -97,7 +97,7 @@ class AppBloc extends Bloc { @override Future close() async { - await appListener.close(); + await appListener.stop(); return super.close(); } diff --git a/frontend/app_flowy/lib/workspace/application/app/app_listener.dart b/frontend/app_flowy/lib/workspace/application/app/app_listener.dart index 46b16bb080..c1696e55f2 100644 --- a/frontend/app_flowy/lib/workspace/application/app/app_listener.dart +++ b/frontend/app_flowy/lib/workspace/application/app/app_listener.dart @@ -24,9 +24,9 @@ class AppListener { required this.appId, }); - void start({ViewsDidChangeCallback? viewsChanged, AppDidUpdateCallback? appUpdated}) { - _viewsChanged = viewsChanged; - _updated = appUpdated; + void start({ViewsDidChangeCallback? onViewsChanged, AppDidUpdateCallback? onAppUpdated}) { + _viewsChanged = onViewsChanged; + _updated = onAppUpdated; _parser = FolderNotificationParser(id: appId, callback: _bservableCallback); _subscription = RustStreamReceiver.listen((observable) => _parser?.parse(observable)); } @@ -60,7 +60,7 @@ class AppListener { } } - Future close() async { + Future stop() async { _parser = null; await _subscription?.cancel(); _viewsChanged = null; diff --git a/frontend/app_flowy/lib/workspace/application/doc/doc_bloc.dart b/frontend/app_flowy/lib/workspace/application/doc/doc_bloc.dart index 8d944c34ac..20d232f07b 100644 --- a/frontend/app_flowy/lib/workspace/application/doc/doc_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/doc/doc_bloc.dart @@ -59,7 +59,7 @@ class DocumentBloc extends Bloc { @override Future close() async { - await listener.close(); + await listener.stop(); if (_subscription != null) { await _subscription?.cancel(); @@ -70,21 +70,20 @@ class DocumentBloc extends Bloc { } Future _initial(Initial value, Emitter emit) async { - listener.deletedNotifier.addPublishListener((result) { - result.fold( - (view) => add(const DocumentEvent.deleted()), - (error) {}, - ); - }); - - listener.restoredNotifier.addPublishListener((result) { - result.fold( - (view) => add(const DocumentEvent.restore()), - (error) {}, - ); - }); - - listener.start(); + listener.start( + onViewDeleted: (result) { + result.fold( + (view) => add(const DocumentEvent.deleted()), + (error) {}, + ); + }, + onViewRestored: (result) { + result.fold( + (view) => add(const DocumentEvent.restore()), + (error) {}, + ); + }, + ); final result = await service.openDocument(docId: view.id); result.fold( (block) { diff --git a/frontend/app_flowy/lib/workspace/application/home/home_bloc.dart b/frontend/app_flowy/lib/workspace/application/home/home_bloc.dart index f401f0a0ca..796a0357b9 100644 --- a/frontend/app_flowy/lib/workspace/application/home/home_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/home/home_bloc.dart @@ -20,10 +20,10 @@ class HomeBloc extends Bloc { await event.map( initial: (_Initial value) { _listener.start( - authDidChange: (result) { + onAuthChanged: (result) { _authDidChanged(result); }, - workspaceSettingDidUpdate: (result) { + onWorkspaceSettingUpdated: (result) { result.fold( (setting) => add(HomeEvent.didReceiveWorkspaceSetting(setting)), (r) => Log.error(r), diff --git a/frontend/app_flowy/lib/workspace/application/menu/menu_user_bloc.dart b/frontend/app_flowy/lib/workspace/application/menu/menu_user_bloc.dart index d0970cae21..0da347c364 100644 --- a/frontend/app_flowy/lib/workspace/application/menu/menu_user_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/menu/menu_user_bloc.dart @@ -20,8 +20,8 @@ class MenuUserBloc extends Bloc { await event.map( initial: (_) async { userListener.start( - profileDidUpdate: _profileUpdated, - workspaceListDidUpdate: _workspaceListUpdated, + onProfileUpdated: _profileUpdated, + onWorkspaceListUpdated: _workspaceListUpdated, ); await _initUser(); }, diff --git a/frontend/app_flowy/lib/workspace/application/view/view_bloc.dart b/frontend/app_flowy/lib/workspace/application/view/view_bloc.dart index 5b5a953922..c33f44a8c1 100644 --- a/frontend/app_flowy/lib/workspace/application/view/view_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/view/view_bloc.dart @@ -21,12 +21,9 @@ class ViewBloc extends Bloc { on((event, emit) async { await event.map( initial: (e) { - // TODO: Listener can be refactored to a stream. - listener.updatedNotifier.addPublishListener((result) { - // emit.forEach(stream, onData: onData) + listener.start(onViewUpdated: (result) { add(ViewEvent.viewDidUpdate(result)); }); - listener.start(); emit(state); }, setIsEditing: (e) { @@ -34,14 +31,12 @@ class ViewBloc extends Bloc { }, viewDidUpdate: (e) { e.result.fold( - (view) => - emit(state.copyWith(view: view, successOrFailure: left(unit))), + (view) => emit(state.copyWith(view: view, successOrFailure: left(unit))), (error) => emit(state.copyWith(successOrFailure: right(error))), ); }, rename: (e) async { - final result = - await service.updateView(viewId: view.id, name: e.newName); + final result = await service.updateView(viewId: view.id, name: e.newName); emit( result.fold( (l) => state.copyWith(successOrFailure: left(unit)), @@ -74,7 +69,7 @@ class ViewBloc extends Bloc { @override Future close() async { - await listener.close(); + await listener.stop(); return super.close(); } } @@ -86,8 +81,7 @@ class ViewEvent with _$ViewEvent { const factory ViewEvent.rename(String newName) = Rename; const factory ViewEvent.delete() = Delete; const factory ViewEvent.duplicate() = Duplicate; - const factory ViewEvent.viewDidUpdate(Either result) = - ViewDidUpdate; + const factory ViewEvent.viewDidUpdate(Either result) = ViewDidUpdate; } @freezed diff --git a/frontend/app_flowy/lib/workspace/application/view/view_listener.dart b/frontend/app_flowy/lib/workspace/application/view/view_listener.dart index ee27d55139..9a2d913941 100644 --- a/frontend/app_flowy/lib/workspace/application/view/view_listener.dart +++ b/frontend/app_flowy/lib/workspace/application/view/view_listener.dart @@ -15,9 +15,9 @@ typedef RestoreViewNotifiedValue = Either; class ViewListener { StreamSubscription? _subscription; - PublishNotifier updatedNotifier = PublishNotifier(); - PublishNotifier deletedNotifier = PublishNotifier(); - PublishNotifier restoredNotifier = PublishNotifier(); + final PublishNotifier _updatedViewNotifier = PublishNotifier(); + final PublishNotifier _deletedNotifier = PublishNotifier(); + final PublishNotifier _restoredNotifier = PublishNotifier(); FolderNotificationParser? _parser; View view; @@ -25,7 +25,29 @@ class ViewListener { required this.view, }); - void start() { + void start({ + void Function(UpdateViewNotifiedValue)? onViewUpdated, + void Function(DeleteViewNotifyValue)? onViewDeleted, + void Function(RestoreViewNotifiedValue)? onViewRestored, + }) { + if (onViewUpdated != null) { + _updatedViewNotifier.addListener(() { + onViewUpdated(_updatedViewNotifier.currentValue!); + }); + } + + if (onViewDeleted != null) { + _deletedNotifier.addListener(() { + onViewDeleted(_deletedNotifier.currentValue!); + }); + } + + if (onViewRestored != null) { + _restoredNotifier.addListener(() { + onViewRestored(_restoredNotifier.currentValue!); + }); + } + _parser = FolderNotificationParser( id: view.id, callback: (ty, result) { @@ -40,20 +62,20 @@ class ViewListener { switch (ty) { case FolderNotification.ViewUpdated: result.fold( - (payload) => updatedNotifier.value = left(View.fromBuffer(payload)), - (error) => updatedNotifier.value = right(error), + (payload) => _updatedViewNotifier.value = left(View.fromBuffer(payload)), + (error) => _updatedViewNotifier.value = right(error), ); break; case FolderNotification.ViewDeleted: result.fold( - (payload) => deletedNotifier.value = left(View.fromBuffer(payload)), - (error) => deletedNotifier.value = right(error), + (payload) => _deletedNotifier.value = left(View.fromBuffer(payload)), + (error) => _deletedNotifier.value = right(error), ); break; case FolderNotification.ViewRestored: result.fold( - (payload) => restoredNotifier.value = left(View.fromBuffer(payload)), - (error) => restoredNotifier.value = right(error), + (payload) => _restoredNotifier.value = left(View.fromBuffer(payload)), + (error) => _restoredNotifier.value = right(error), ); break; default: @@ -61,11 +83,11 @@ class ViewListener { } } - Future close() async { + Future stop() async { _parser = null; await _subscription?.cancel(); - updatedNotifier.dispose(); - deletedNotifier.dispose(); - restoredNotifier.dispose(); + _updatedViewNotifier.dispose(); + _deletedNotifier.dispose(); + _restoredNotifier.dispose(); } } diff --git a/frontend/app_flowy/lib/workspace/application/workspace/welcome_bloc.dart b/frontend/app_flowy/lib/workspace/application/workspace/welcome_bloc.dart index 8ad83925b4..a743a3316f 100644 --- a/frontend/app_flowy/lib/workspace/application/workspace/welcome_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/workspace/welcome_bloc.dart @@ -17,7 +17,7 @@ class WelcomeBloc extends Bloc { (event, emit) async { await event.map(initial: (e) async { userListener.start( - workspaceListDidUpdate: (result) => add(WelcomeEvent.workspacesReveived(result)), + onWorkspaceListUpdated: (result) => add(WelcomeEvent.workspacesReveived(result)), ); // await _fetchWorkspaces(emit); diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/doc/document.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/doc/document.dart index b0727bb73a..5dcf744083 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/doc/document.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/doc/document.dart @@ -60,7 +60,7 @@ class DocumentPlugin implements Plugin { DocumentPlugin({required PluginType pluginType, required View view, Key? key}) : _view = view { _pluginType = pluginType; _listener = getIt(param1: view); - _listener?.updatedNotifier.addPublishListener((result) { + _listener?.start(onViewUpdated: (result) { result.fold( (newView) { _view = newView; @@ -69,12 +69,11 @@ class DocumentPlugin implements Plugin { (error) {}, ); }); - _listener?.start(); } @override void dispose() { - _listener?.close(); + _listener?.stop(); _listener = null; } diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/widgets/left_bar_item.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/widgets/left_bar_item.dart index 7c1e819cc5..e81fc3e45d 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/widgets/left_bar_item.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/widgets/left_bar_item.dart @@ -1,5 +1,7 @@ +import 'package:app_flowy/workspace/application/view/view_listener.dart'; import 'package:app_flowy/workspace/application/view/view_service.dart'; import 'package:flowy_infra/theme.dart'; +import 'package:flowy_sdk/log.dart'; import 'package:flowy_sdk/protobuf/flowy-folder-data-model/view.pb.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; @@ -16,12 +18,26 @@ class ViewLeftBarItem extends StatefulWidget { class _ViewLeftBarItemState extends State { final _controller = TextEditingController(); final _focusNode = FocusNode(); - late ViewService serviceService; + late ViewService _viewService; + late ViewListener _viewListener; + late View view; @override void initState() { - serviceService = ViewService(/*view: widget.view*/); + view = widget.view; + _viewService = ViewService(); _focusNode.addListener(_handleFocusChanged); + _viewListener = ViewListener(view: widget.view); + _viewListener.start(onViewUpdated: (result) { + result.fold( + (updatedView) { + if (mounted) { + setState(() => view = updatedView); + } + }, + (err) => Log.error(err), + ); + }); super.initState(); } @@ -30,12 +46,13 @@ class _ViewLeftBarItemState extends State { _controller.dispose(); _focusNode.removeListener(_handleFocusChanged); _focusNode.dispose(); + _viewListener.stop(); super.dispose(); } @override Widget build(BuildContext context) { - _controller.text = widget.view.name; + _controller.text = view.name; final theme = context.watch(); return IntrinsicWidth( @@ -63,12 +80,12 @@ class _ViewLeftBarItemState extends State { void _handleFocusChanged() { if (_controller.text.isEmpty) { - _controller.text = widget.view.name; + _controller.text = view.name; return; } - if (_controller.text != widget.view.name) { - serviceService.updateView(viewId: widget.view.id, name: _controller.text); + if (_controller.text != view.name) { + _viewService.updateView(viewId: view.id, name: _controller.text); } } } From 228695d51798c8075d91cbec4d705d97940247c3 Mon Sep 17 00:00:00 2001 From: appflowy Date: Fri, 6 May 2022 20:21:50 +0800 Subject: [PATCH 6/7] chore: add close button on row detail page --- .../grid/src/widgets/row/row_detail.dart | 28 ++++++++++++++++++- .../lib/src/flowy_overlay/flowy_overlay.dart | 2 +- 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/row/row_detail.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/row/row_detail.dart index 7e2ece2cf5..6984d1ebca 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/row/row_detail.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/row/row_detail.dart @@ -6,9 +6,11 @@ import 'package:app_flowy/workspace/presentation/plugins/grid/src/layout/sizes.d import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/cell/prelude.dart'; import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/field_cell.dart'; import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/field_editor.dart'; +import 'package:flowy_infra/image.dart'; import 'package:flowy_infra/theme.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart'; import 'package:flowy_infra_ui/style_widget/hover.dart'; +import 'package:flowy_infra_ui/style_widget/icon_button.dart'; import 'package:flowy_infra_ui/style_widget/scrolling/styled_scroll_bar.dart'; import 'package:flowy_infra_ui/widget/spacing.dart'; import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart' show FieldType; @@ -66,12 +68,36 @@ class _RowDetailPageState extends State { }, child: Padding( padding: const EdgeInsets.symmetric(horizontal: 80, vertical: 40), - child: _PropertyList(cellCache: widget.cellCache), + child: Column( + children: [ + SizedBox( + height: 40, + child: Row( + children: const [Spacer(), _CloseButton()], + )), + Expanded(child: _PropertyList(cellCache: widget.cellCache)), + ], + ), ), ); } } +class _CloseButton extends StatelessWidget { + const _CloseButton({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + final theme = context.watch(); + return FlowyIconButton( + width: 24, + onPressed: () => FlowyOverlay.of(context).remove(RowDetailPage.identifier()), + iconPadding: const EdgeInsets.fromLTRB(2, 2, 2, 2), + icon: svgWidget("home/close", color: theme.iconColor), + ); + } +} + class _PropertyList extends StatelessWidget { final GridCellCache cellCache; final ScrollController _scrollController; diff --git a/frontend/app_flowy/packages/flowy_infra_ui/lib/src/flowy_overlay/flowy_overlay.dart b/frontend/app_flowy/packages/flowy_infra_ui/lib/src/flowy_overlay/flowy_overlay.dart index 0f6cecf0bc..7ed3c04673 100644 --- a/frontend/app_flowy/packages/flowy_infra_ui/lib/src/flowy_overlay/flowy_overlay.dart +++ b/frontend/app_flowy/packages/flowy_infra_ui/lib/src/flowy_overlay/flowy_overlay.dart @@ -176,7 +176,6 @@ class FlowyOverlayState extends State { FlowyOverlayStyle? style, Offset? anchorOffset, }) { - debugPrint("Show overlay: $identifier"); this.style = style ?? FlowyOverlayStyle(); _showOverlay( @@ -245,6 +244,7 @@ class FlowyOverlayState extends State { OverlapBehaviour? overlapBehaviour, FlowyOverlayDelegate? delegate, }) { + debugPrint("Show overlay: $identifier"); Widget overlay = widget; final offset = anchorOffset ?? Offset.zero; From 18752e7af8c6ae101a97fabfd6f3cd64b4cc8032 Mon Sep 17 00:00:00 2001 From: appflowy Date: Fri, 6 May 2022 21:07:34 +0800 Subject: [PATCH 7/7] chore: show create option message on bottom --- .../app_flowy/assets/translations/en.json | 1 + .../grid/cell/selection_editor_bloc.dart | 64 +++++++++++++++---- .../cell/selection_cell/extension.dart | 28 ++++++-- .../cell/selection_cell/selection_cell.dart | 9 ++- .../cell/selection_cell/selection_editor.dart | 54 +++++++++++++--- .../cell/selection_cell/text_field.dart | 8 ++- 6 files changed, 136 insertions(+), 28 deletions(-) diff --git a/frontend/app_flowy/assets/translations/en.json b/frontend/app_flowy/assets/translations/en.json index a051401446..8755f05952 100644 --- a/frontend/app_flowy/assets/translations/en.json +++ b/frontend/app_flowy/assets/translations/en.json @@ -181,6 +181,7 @@ "textPlaceholder": "Empty" }, "selectOption": { + "create": "Create", "purpleColor": "Purple", "pinkColor": "Pink", "lightPinkColor": "Light Pink", diff --git a/frontend/app_flowy/lib/workspace/application/grid/cell/selection_editor_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/cell/selection_editor_bloc.dart index 3254368086..a6cd154d7d 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/cell/selection_editor_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/cell/selection_editor_bloc.dart @@ -1,9 +1,13 @@ -import 'package:app_flowy/workspace/application/grid/cell/cell_service.dart'; +import 'dart:async'; + +import 'package:dartz/dartz.dart'; import 'package:flowy_sdk/log.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 'package:app_flowy/workspace/application/grid/cell/cell_service.dart'; + import 'select_option_service.dart'; part 'selection_editor_bloc.freezed.dart'; @@ -24,14 +28,19 @@ class SelectOptionEditorBloc extends Bloc emit) { - emit(state.copyWith(filter: optionName, options: _makeOptions(optionName, state.allOptions))); + final _MakeOptionResult result = _makeOptions(Some(optionName), state.allOptions); + emit(state.copyWith( + filter: Some(optionName), + options: result.options, + createOption: result.createOption, + )); } - List _makeOptions(String filter, List allOptions) { + _MakeOptionResult _makeOptions(Option filter, List allOptions) { final List options = List.from(allOptions); - if (filter.isNotEmpty) { - options.retainWhere((option) => option.name.toLowerCase().contains(filter.toLowerCase())); - } + Option createOption = filter; - return options; + filter.foldRight(null, (filter, previous) { + if (filter.isNotEmpty) { + options.retainWhere((option) { + final name = option.name.toLowerCase(); + final lFilter = filter.toLowerCase(); + + if (name == lFilter) { + createOption = none(); + } + + return name.contains(lFilter); + }); + } + }); + + return _MakeOptionResult( + options: options, + createOption: createOption, + ); } void _startListening() { @@ -135,7 +165,8 @@ class SelectOptionEditorState with _$SelectOptionEditorState { required List options, required List allOptions, required List selectedOptions, - required String filter, + required Option createOption, + required Option filter, }) = _SelectOptionEditorState; factory SelectOptionEditorState.initial(GridSelectOptionCellContext context) { @@ -144,7 +175,18 @@ class SelectOptionEditorState with _$SelectOptionEditorState { options: data?.options ?? [], allOptions: data?.options ?? [], selectedOptions: data?.selectOptions ?? [], - filter: "", + createOption: none(), + filter: none(), ); } } + +class _MakeOptionResult { + List options; + Option createOption; + + _MakeOptionResult({ + required this.options, + required this.createOption, + }); +} diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/extension.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/extension.dart index 71a86e91b4..c4140ad216 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/extension.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/extension.dart @@ -60,17 +60,35 @@ extension SelectOptionColorExtension on SelectOptionColor { } class SelectOptionTag extends StatelessWidget { - final SelectOption option; + final String name; + final Color color; final bool isSelected; - const SelectOptionTag({required this.option, this.isSelected = false, Key? key}) : super(key: key); + const SelectOptionTag({ + required this.name, + required this.color, + this.isSelected = false, + Key? key, + }) : super(key: key); + + factory SelectOptionTag.fromSelectOption({ + required BuildContext context, + required SelectOption option, + bool isSelected = false, + }) { + return SelectOptionTag( + name: option.name, + color: option.color.make(context), + isSelected: isSelected, + ); + } @override Widget build(BuildContext context) { return ChoiceChip( pressElevation: 1, - label: FlowyText.medium(option.name, fontSize: 12), - selectedColor: option.color.make(context), - backgroundColor: option.color.make(context), + label: FlowyText.medium(name, fontSize: 12), + selectedColor: color, + backgroundColor: color, labelPadding: const EdgeInsets.symmetric(horizontal: 6), selected: true, onSelected: (_) {}, diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/selection_cell.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/selection_cell.dart index 73aa583956..0c754b0297 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/selection_cell.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/selection_cell.dart @@ -150,7 +150,14 @@ class _SelectOptionCell extends StatelessWidget { child: FlowyText.medium(cellStyle!.placeholder, fontSize: 14, color: theme.shader3), ); } else { - final tags = selectOptions.map((option) => SelectOptionTag(option: option)).toList(); + final tags = selectOptions + .map( + (option) => SelectOptionTag.fromSelectOption( + context: context, + option: option, + ), + ) + .toList(); child = Align( alignment: Alignment.centerLeft, child: Wrap(children: tags, spacing: 4, runSpacing: 4), 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 index 46d06e86cb..ef5122a4bc 100644 --- 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 @@ -104,9 +104,18 @@ class _OptionList extends StatelessWidget { Widget build(BuildContext context) { return BlocBuilder( builder: (context, state) { - final cells = state.options.map((option) { + List cells = []; + cells.addAll(state.options.map((option) { return _SelectOptionCell(option, state.selectedOptions.contains(option)); - }).toList(); + }).toList()); + + state.createOption.fold( + () => null, + (createOption) { + cells.add(_CreateOptionCell(name: createOption)); + }, + ); + final list = ListView.separated( shrinkWrap: true, controller: ScrollController(), @@ -119,7 +128,11 @@ class _OptionList extends StatelessWidget { return cells[index]; }, ); - return list; + + return Padding( + padding: const EdgeInsets.all(3.0), + child: list, + ); }, ); } @@ -177,6 +190,30 @@ class _Title extends StatelessWidget { } } +class _CreateOptionCell extends StatelessWidget { + final String name; + const _CreateOptionCell({required this.name, Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + final theme = context.watch(); + return Row( + children: [ + FlowyText.medium( + LocaleKeys.grid_selectOption_create.tr(), + fontSize: 12, + color: theme.shader3, + ), + const HSpace(10), + SelectOptionTag( + name: name, + color: theme.shader6, + ), + ], + ); + } +} + class _SelectOptionCell extends StatelessWidget { final SelectOption option; final bool isSelected; @@ -206,7 +243,11 @@ class _SelectOptionCell extends StatelessWidget { style: HoverStyle(hoverColor: theme.hover), builder: (_, onHover) { List children = [ - SelectOptionTag(option: option, isSelected: isSelected), + SelectOptionTag( + name: option.name, + color: option.color.make(context), + isSelected: isSelected, + ), const Spacer(), ]; @@ -223,10 +264,7 @@ class _SelectOptionCell extends StatelessWidget { )); } - return Padding( - padding: const EdgeInsets.all(3.0), - child: Row(children: children), - ); + return Row(children: children); }, ); } diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/text_field.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/text_field.dart index daabbf263d..125a86a609 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/text_field.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/text_field.dart @@ -76,7 +76,7 @@ class SelectOptionTextField extends StatelessWidget { borderRadius: Corners.s10Border, ), isDense: true, - prefixIcon: _renderTags(sc), + prefixIcon: _renderTags(context, sc), hintText: LocaleKeys.grid_selectOption_searchOption.tr(), prefixIconConstraints: BoxConstraints(maxWidth: distanceToText), focusedBorder: OutlineInputBorder( @@ -90,12 +90,14 @@ class SelectOptionTextField extends StatelessWidget { ); } - Widget? _renderTags(ScrollController sc) { + Widget? _renderTags(BuildContext context, ScrollController sc) { if (selectedOptionMap.isEmpty) { return null; } - final children = selectedOptionMap.values.map((option) => SelectOptionTag(option: option)).toList(); + final children = selectedOptionMap.values + .map((option) => SelectOptionTag.fromSelectOption(context: context, option: option)) + .toList(); return Padding( padding: const EdgeInsets.all(8.0), child: SingleChildScrollView(