diff --git a/frontend/Makefile.toml b/frontend/Makefile.toml index 9634344592..a44aa8e53b 100644 --- a/frontend/Makefile.toml +++ b/frontend/Makefile.toml @@ -50,7 +50,7 @@ APP_ENVIRONMENT = "local" FLUTTER_FLOWY_SDK_PATH = "appflowy_flutter/packages/appflowy_backend" TAURI_BACKEND_SERVICE_PATH = "appflowy_tauri/src/services/backend" WEB_BACKEND_SERVICE_PATH = "appflowy_web/src/services/backend" -WEB_LIB_PATH= "appflowy_web/wasm-libs/af-wasm" +WEB_LIB_PATH = "appflowy_web/wasm-libs/af-wasm" # Test default config TEST_CRATE_TYPE = "cdylib" TEST_LIB_EXT = "dylib" @@ -226,9 +226,8 @@ script = [''' echo FEATURES: ${FLUTTER_DESKTOP_FEATURES} echo PRODUCT_EXT: ${PRODUCT_EXT} echo APP_ENVIRONMENT: ${APP_ENVIRONMENT} - echo ${platforms} - echo ${BUILD_ARCHS} - echo ${BUILD_VERSION} + echo BUILD_ARCHS: ${BUILD_ARCHS} + echo BUILD_VERSION: ${BUILD_VERSION} '''] script_runner = "@shell" diff --git a/frontend/appflowy_flutter/lib/plugins/database/application/field/field_info.dart b/frontend/appflowy_flutter/lib/plugins/database/application/field/field_info.dart index 64d5a398be..1612ab6a23 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/application/field/field_info.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/application/field/field_info.dart @@ -47,7 +47,7 @@ class FieldInfo with _$FieldInfo { } bool get canCreateFilter { - if (hasFilter) { + if (isGroupField) { return false; } @@ -58,6 +58,7 @@ class FieldInfo with _$FieldInfo { case FieldType.RichText: case FieldType.SingleSelect: case FieldType.Checklist: + case FieldType.URL: return true; default: return false; diff --git a/frontend/appflowy_flutter/lib/plugins/database/board/application/board_bloc.dart b/frontend/appflowy_flutter/lib/plugins/database/board/application/board_bloc.dart index 70402f38fd..7b816bbafc 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/board/application/board_bloc.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/board/application/board_bloc.dart @@ -385,16 +385,23 @@ class BoardBloc extends Bloc { groupList.insert(insertGroups.index, group); add(BoardEvent.didReceiveGroups(groupList)); }, - onUpdateGroup: (updatedGroups) { + onUpdateGroup: (updatedGroups) async { if (isClosed) { return; } + // workaround: update group most of the time gets called before fields in + // field controller are updated. For single and multi-select group + // renames, this is required before generating the new group name. + await Future.delayed(const Duration(milliseconds: 50)); + for (final group in updatedGroups) { // see if the column is already in the board - final index = groupList.indexWhere((g) => g.groupId == group.groupId); - if (index == -1) continue; + if (index == -1) { + continue; + } + final columnController = boardController.getGroupController(group.groupId); if (columnController != null) { diff --git a/frontend/appflowy_flutter/lib/plugins/database/board/presentation/board_page.dart b/frontend/appflowy_flutter/lib/plugins/database/board/presentation/board_page.dart index 16b2d45f95..40f60a09f4 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/board/presentation/board_page.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/board/presentation/board_page.dart @@ -1,5 +1,7 @@ import 'dart:collection'; +import 'package:appflowy/plugins/database/grid/presentation/grid_page.dart'; +import 'package:appflowy/plugins/database/tab_bar/desktop/setting_menu.dart'; import 'package:flutter/material.dart' hide Card; import 'package:flutter/services.dart'; @@ -34,6 +36,8 @@ import 'toolbar/board_setting_bar.dart'; import 'widgets/board_hidden_groups.dart'; class BoardPageTabBarBuilderImpl extends DatabaseTabBarItemBuilder { + final _toggleExtension = ToggleExtensionNotifier(); + @override Widget content( BuildContext context, @@ -49,14 +53,27 @@ class BoardPageTabBarBuilderImpl extends DatabaseTabBarItemBuilder { BoardSettingBar( key: _makeValueKey(controller), databaseController: controller, + toggleExtension: _toggleExtension, ); @override Widget settingBarExtension( BuildContext context, DatabaseController controller, - ) => - const SizedBox.shrink(); + ) { + return DatabaseViewSettingExtension( + key: _makeValueKey(controller), + viewId: controller.viewId, + databaseController: controller, + toggleExtension: _toggleExtension, + ); + } + + @override + void dispose() { + _toggleExtension.dispose(); + super.dispose(); + } ValueKey _makeValueKey(DatabaseController controller) => ValueKey(controller.viewId); diff --git a/frontend/appflowy_flutter/lib/plugins/database/board/presentation/toolbar/board_setting_bar.dart b/frontend/appflowy_flutter/lib/plugins/database/board/presentation/toolbar/board_setting_bar.dart index 4a678a160e..aa2883ff73 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/board/presentation/toolbar/board_setting_bar.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/board/presentation/toolbar/board_setting_bar.dart @@ -1,24 +1,53 @@ import 'package:appflowy/plugins/database/application/database_controller.dart'; +import 'package:appflowy/plugins/database/grid/application/filter/filter_menu_bloc.dart'; +import 'package:appflowy/plugins/database/grid/presentation/grid_page.dart'; +import 'package:appflowy/plugins/database/grid/presentation/widgets/toolbar/filter_button.dart'; import 'package:appflowy/plugins/database/widgets/setting/setting_button.dart'; +import 'package:flowy_infra_ui/widget/spacing.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; class BoardSettingBar extends StatelessWidget { const BoardSettingBar({ super.key, required this.databaseController, + required this.toggleExtension, }); final DatabaseController databaseController; + final ToggleExtensionNotifier toggleExtension; @override Widget build(BuildContext context) { - return SizedBox( - height: 20, - child: Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - SettingButton(databaseController: databaseController), - ], + return BlocProvider( + create: (context) => DatabaseFilterMenuBloc( + viewId: databaseController.viewId, + fieldController: databaseController.fieldController, + )..add(const DatabaseFilterMenuEvent.initial()), + child: BlocListener( + listenWhen: (p, c) => p.isVisible != c.isVisible, + listener: (context, state) => toggleExtension.toggle(), + child: ValueListenableBuilder( + valueListenable: databaseController.isLoading, + builder: (context, value, child) { + if (value) { + return const SizedBox.shrink(); + } + return SizedBox( + height: 20, + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + const FilterButton(), + const HSpace(2), + SettingButton( + databaseController: databaseController, + ), + ], + ), + ); + }, + ), ), ); } diff --git a/frontend/appflowy_flutter/lib/plugins/database/domain/filter_service.dart b/frontend/appflowy_flutter/lib/plugins/database/domain/filter_service.dart index 179ceecfba..64854a8faf 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/domain/filter_service.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/domain/filter_service.dart @@ -1,15 +1,6 @@ import 'package:appflowy_backend/dispatch/dispatch.dart'; import 'package:appflowy_backend/log.dart'; -import 'package:appflowy_backend/protobuf/flowy-database2/checkbox_filter.pbserver.dart'; -import 'package:appflowy_backend/protobuf/flowy-database2/checklist_filter.pb.dart'; -import 'package:appflowy_backend/protobuf/flowy-database2/database_entities.pb.dart'; -import 'package:appflowy_backend/protobuf/flowy-database2/date_filter.pbserver.dart'; -import 'package:appflowy_backend/protobuf/flowy-database2/field_entities.pb.dart'; -import 'package:appflowy_backend/protobuf/flowy-database2/number_filter.pb.dart'; -import 'package:appflowy_backend/protobuf/flowy-database2/select_option_filter.pbserver.dart'; -import 'package:appflowy_backend/protobuf/flowy-database2/setting_entities.pb.dart'; -import 'package:appflowy_backend/protobuf/flowy-database2/text_filter.pb.dart'; -import 'package:appflowy_backend/protobuf/flowy-database2/util.pb.dart'; +import 'package:appflowy_backend/protobuf/flowy-database2/protobuf.dart'; import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; import 'package:appflowy_result/appflowy_result.dart'; import 'package:fixnum/fixnum.dart' as $fixnum; @@ -109,25 +100,21 @@ class FilterBackendService { int? timestamp, }) { assert( - [ - FieldType.DateTime, - FieldType.LastEditedTime, - FieldType.CreatedTime, - ].contains(fieldType), + fieldType == FieldType.DateTime || + fieldType == FieldType.LastEditedTime || + fieldType == FieldType.CreatedTime, ); final filter = DateFilterPB(); + if (timestamp != null) { filter.timestamp = $fixnum.Int64(timestamp); - } else { - if (start != null && end != null) { - filter.start = $fixnum.Int64(start); - filter.end = $fixnum.Int64(end); - } else { - throw Exception( - "Start and end should not be null if the timestamp is null", - ); - } + } + if (start != null) { + filter.start = $fixnum.Int64(start); + } + if (end != null) { + filter.end = $fixnum.Int64(end); } return filterId == null diff --git a/frontend/appflowy_flutter/lib/plugins/database/grid/application/filter/filter_menu_bloc.dart b/frontend/appflowy_flutter/lib/plugins/database/grid/application/filter/filter_menu_bloc.dart index 08e45305de..cc26e42b83 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/grid/application/filter/filter_menu_bloc.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/grid/application/filter/filter_menu_bloc.dart @@ -8,11 +8,11 @@ import 'package:freezed_annotation/freezed_annotation.dart'; part 'filter_menu_bloc.freezed.dart'; -class GridFilterMenuBloc - extends Bloc { - GridFilterMenuBloc({required this.viewId, required this.fieldController}) +class DatabaseFilterMenuBloc + extends Bloc { + DatabaseFilterMenuBloc({required this.viewId, required this.fieldController}) : super( - GridFilterMenuState.initial( + DatabaseFilterMenuState.initial( viewId, fieldController.filterInfos, fieldController.fieldInfos, @@ -27,7 +27,7 @@ class GridFilterMenuBloc void Function(List)? _onFieldFn; void _dispatch() { - on( + on( (event, emit) async { event.when( initial: () { @@ -55,11 +55,11 @@ class GridFilterMenuBloc void _startListening() { _onFilterFn = (filters) { - add(GridFilterMenuEvent.didReceiveFilters(filters)); + add(DatabaseFilterMenuEvent.didReceiveFilters(filters)); }; _onFieldFn = (fields) { - add(GridFilterMenuEvent.didReceiveFields(fields)); + add(DatabaseFilterMenuEvent.didReceiveFields(fields)); }; fieldController.addListener( @@ -87,32 +87,33 @@ class GridFilterMenuBloc } @freezed -class GridFilterMenuEvent with _$GridFilterMenuEvent { - const factory GridFilterMenuEvent.initial() = _Initial; - const factory GridFilterMenuEvent.didReceiveFilters( +class DatabaseFilterMenuEvent with _$DatabaseFilterMenuEvent { + const factory DatabaseFilterMenuEvent.initial() = _Initial; + const factory DatabaseFilterMenuEvent.didReceiveFilters( List filters, ) = _DidReceiveFilters; - const factory GridFilterMenuEvent.didReceiveFields(List fields) = - _DidReceiveFields; - const factory GridFilterMenuEvent.toggleMenu() = _SetMenuVisibility; + const factory DatabaseFilterMenuEvent.didReceiveFields( + List fields, + ) = _DidReceiveFields; + const factory DatabaseFilterMenuEvent.toggleMenu() = _SetMenuVisibility; } @freezed -class GridFilterMenuState with _$GridFilterMenuState { - const factory GridFilterMenuState({ +class DatabaseFilterMenuState with _$DatabaseFilterMenuState { + const factory DatabaseFilterMenuState({ required String viewId, required List filters, required List fields, required List creatableFields, required bool isVisible, - }) = _GridFilterMenuState; + }) = _DatabaseFilterMenuState; - factory GridFilterMenuState.initial( + factory DatabaseFilterMenuState.initial( String viewId, List filterInfos, List fields, ) => - GridFilterMenuState( + DatabaseFilterMenuState( viewId: viewId, filters: filterInfos, fields: fields, diff --git a/frontend/appflowy_flutter/lib/plugins/database/grid/application/filter/text_filter_editor_bloc.dart b/frontend/appflowy_flutter/lib/plugins/database/grid/application/filter/text_filter_editor_bloc.dart index 54563010a0..e4fa67c4a8 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/grid/application/filter/text_filter_editor_bloc.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/grid/application/filter/text_filter_editor_bloc.dart @@ -3,8 +3,7 @@ import 'dart:async'; import 'package:appflowy/plugins/database/domain/filter_listener.dart'; import 'package:appflowy/plugins/database/domain/filter_service.dart'; import 'package:appflowy/plugins/database/grid/presentation/widgets/filter/filter_info.dart'; -import 'package:appflowy_backend/protobuf/flowy-database2/text_filter.pbserver.dart'; -import 'package:appflowy_backend/protobuf/flowy-database2/util.pb.dart'; +import 'package:appflowy_backend/protobuf/flowy-database2/protobuf.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; @@ -12,7 +11,7 @@ part 'text_filter_editor_bloc.freezed.dart'; class TextFilterEditorBloc extends Bloc { - TextFilterEditorBloc({required this.filterInfo}) + TextFilterEditorBloc({required this.filterInfo, required this.fieldType}) : _filterBackendSvc = FilterBackendService(viewId: filterInfo.viewId), _listener = FilterListener( viewId: filterInfo.viewId, @@ -23,6 +22,7 @@ class TextFilterEditorBloc } final FilterInfo filterInfo; + final FieldType fieldType; final FilterBackendService _filterBackendSvc; final FilterListener _listener; @@ -34,20 +34,34 @@ class TextFilterEditorBloc _startListening(); }, updateCondition: (TextFilterConditionPB condition) { - _filterBackendSvc.insertTextFilter( - filterId: filterInfo.filter.id, - fieldId: filterInfo.fieldInfo.id, - condition: condition, - content: state.filter.content, - ); + fieldType == FieldType.RichText + ? _filterBackendSvc.insertTextFilter( + filterId: filterInfo.filter.id, + fieldId: filterInfo.fieldInfo.id, + condition: condition, + content: state.filter.content, + ) + : _filterBackendSvc.insertURLFilter( + filterId: filterInfo.filter.id, + fieldId: filterInfo.fieldInfo.id, + condition: condition, + content: state.filter.content, + ); }, - updateContent: (content) { - _filterBackendSvc.insertTextFilter( - filterId: filterInfo.filter.id, - fieldId: filterInfo.fieldInfo.id, - condition: state.filter.condition, - content: content, - ); + updateContent: (String content) { + fieldType == FieldType.RichText + ? _filterBackendSvc.insertTextFilter( + filterId: filterInfo.filter.id, + fieldId: filterInfo.fieldInfo.id, + condition: state.filter.condition, + content: content, + ) + : _filterBackendSvc.insertURLFilter( + filterId: filterInfo.filter.id, + fieldId: filterInfo.fieldInfo.id, + condition: state.filter.condition, + content: content, + ); }, delete: () { _filterBackendSvc.deleteFilter( diff --git a/frontend/appflowy_flutter/lib/plugins/database/grid/presentation/widgets/filter/choicechip/text.dart b/frontend/appflowy_flutter/lib/plugins/database/grid/presentation/widgets/filter/choicechip/text.dart index 91c2c063ac..66f17e0971 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/grid/presentation/widgets/filter/choicechip/text.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/grid/presentation/widgets/filter/choicechip/text.dart @@ -1,59 +1,44 @@ import 'package:appflowy/generated/flowy_svgs.g.dart'; import 'package:appflowy/generated/locale_keys.g.dart'; +import 'package:appflowy/plugins/database/grid/application/filter/text_filter_editor_bloc.dart'; import 'package:appflowy/workspace/presentation/widgets/pop_up_action.dart'; +import 'package:appflowy_backend/protobuf/flowy-database2/protobuf.dart'; import 'package:appflowy_popover/appflowy_popover.dart'; import 'package:easy_localization/easy_localization.dart'; - import 'package:flowy_infra_ui/flowy_infra_ui.dart'; -import 'package:appflowy_backend/protobuf/flowy-database2/text_filter.pb.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; -import '../../../../application/filter/text_filter_editor_bloc.dart'; + import '../condition_button.dart'; import '../disclosure_button.dart'; import '../filter_info.dart'; import 'choicechip.dart'; -class TextFilterChoicechip extends StatefulWidget { +class TextFilterChoicechip extends StatelessWidget { const TextFilterChoicechip({required this.filterInfo, super.key}); final FilterInfo filterInfo; - @override - State createState() => _TextFilterChoicechipState(); -} - -class _TextFilterChoicechipState extends State { - late TextFilterEditorBloc bloc; - - @override - void initState() { - bloc = TextFilterEditorBloc(filterInfo: widget.filterInfo) - ..add(const TextFilterEditorEvent.initial()); - super.initState(); - } - - @override - void dispose() { - bloc.close(); - super.dispose(); - } - @override Widget build(BuildContext context) { - return BlocProvider.value( - value: bloc, + return BlocProvider( + create: (_) => TextFilterEditorBloc( + filterInfo: filterInfo, + fieldType: FieldType.RichText, + )..add(const TextFilterEditorEvent.initial()), child: BlocBuilder( - builder: (blocContext, state) { + builder: (context, state) { return AppFlowyPopover( - controller: PopoverController(), constraints: BoxConstraints.loose(const Size(200, 76)), direction: PopoverDirection.bottomWithCenterAligned, - popupBuilder: (BuildContext context) { - return TextFilterEditor(bloc: bloc); + popupBuilder: (popoverContext) { + return BlocProvider.value( + value: context.read(), + child: const TextFilterEditor(), + ); }, child: ChoiceChipButton( - filterInfo: widget.filterInfo, + filterInfo: filterInfo, filterDesc: _makeFilterDesc(state), ), ); @@ -78,9 +63,7 @@ class _TextFilterChoicechipState extends State { } class TextFilterEditor extends StatefulWidget { - const TextFilterEditor({required this.bloc, super.key}); - - final TextFilterEditorBloc bloc; + const TextFilterEditor({super.key}); @override State createState() => _TextFilterEditorState(); @@ -91,26 +74,23 @@ class _TextFilterEditorState extends State { @override Widget build(BuildContext context) { - return BlocProvider.value( - value: widget.bloc, - child: BlocBuilder( - builder: (context, state) { - final List children = [ - _buildFilterPanel(context, state), - ]; + return BlocBuilder( + builder: (context, state) { + final List children = [ + _buildFilterPanel(context, state), + ]; - if (state.filter.condition != TextFilterConditionPB.TextIsEmpty && - state.filter.condition != TextFilterConditionPB.TextIsNotEmpty) { - children.add(const VSpace(4)); - children.add(_buildFilterTextField(context, state)); - } + if (state.filter.condition != TextFilterConditionPB.TextIsEmpty && + state.filter.condition != TextFilterConditionPB.TextIsNotEmpty) { + children.add(const VSpace(4)); + children.add(_buildFilterTextField(context, state)); + } - return Padding( - padding: const EdgeInsets.symmetric(horizontal: 4, vertical: 1), - child: IntrinsicHeight(child: Column(children: children)), - ); - }, - ), + return Padding( + padding: const EdgeInsets.symmetric(horizontal: 4, vertical: 1), + child: IntrinsicHeight(child: Column(children: children)), + ); + }, ); } diff --git a/frontend/appflowy_flutter/lib/plugins/database/grid/presentation/widgets/filter/choicechip/url.dart b/frontend/appflowy_flutter/lib/plugins/database/grid/presentation/widgets/filter/choicechip/url.dart index 440091f24d..53d2b0ace8 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/grid/presentation/widgets/filter/choicechip/url.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/grid/presentation/widgets/filter/choicechip/url.dart @@ -1,14 +1,58 @@ +import 'package:appflowy/plugins/database/grid/application/filter/text_filter_editor_bloc.dart'; +import 'package:appflowy/plugins/database/grid/presentation/widgets/filter/choicechip/text.dart'; +import 'package:appflowy_backend/protobuf/flowy-database2/protobuf.dart'; +import 'package:appflowy_popover/appflowy_popover.dart'; +import 'package:flowy_infra_ui/flowy_infra_ui.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; + import '../filter_info.dart'; import 'choicechip.dart'; -class URLFilterChoicechip extends StatelessWidget { - const URLFilterChoicechip({required this.filterInfo, super.key}); +class URLFilterChoiceChip extends StatelessWidget { + const URLFilterChoiceChip({required this.filterInfo, super.key}); final FilterInfo filterInfo; @override Widget build(BuildContext context) { - return ChoiceChipButton(filterInfo: filterInfo); + return BlocProvider( + create: (_) => TextFilterEditorBloc( + filterInfo: filterInfo, + fieldType: FieldType.URL, + ), + child: BlocBuilder( + builder: (context, state) { + return AppFlowyPopover( + constraints: BoxConstraints.loose(const Size(200, 76)), + direction: PopoverDirection.bottomWithCenterAligned, + popupBuilder: (popoverContext) { + return BlocProvider.value( + value: context.read(), + child: const TextFilterEditor(), + ); + }, + child: ChoiceChipButton( + filterInfo: filterInfo, + filterDesc: _makeFilterDesc(state), + ), + ); + }, + ), + ); + } + + String _makeFilterDesc(TextFilterEditorState state) { + String filterDesc = state.filter.condition.choicechipPrefix; + if (state.filter.condition == TextFilterConditionPB.TextIsEmpty || + state.filter.condition == TextFilterConditionPB.TextIsNotEmpty) { + return filterDesc; + } + + if (state.filter.content.isNotEmpty) { + filterDesc += " ${state.filter.content}"; + } + + return filterDesc; } } diff --git a/frontend/appflowy_flutter/lib/plugins/database/grid/presentation/widgets/filter/filter_info.dart b/frontend/appflowy_flutter/lib/plugins/database/grid/presentation/widgets/filter/filter_info.dart index 9adc642c3b..19c201d026 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/grid/presentation/widgets/filter/filter_info.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/grid/presentation/widgets/filter/filter_info.dart @@ -21,13 +21,17 @@ class FilterInfo { String get fieldId => filter.data.fieldId; DateFilterPB? dateFilter() { - return filter.data.fieldType == FieldType.DateTime + final fieldType = filter.data.fieldType; + return fieldType == FieldType.DateTime || + fieldType == FieldType.CreatedTime || + fieldType == FieldType.LastEditedTime ? DateFilterPB.fromBuffer(filter.data.data) : null; } TextFilterPB? textFilter() { - return filter.data.fieldType == FieldType.RichText + return filter.data.fieldType == FieldType.RichText || + filter.data.fieldType == FieldType.URL ? TextFilterPB.fromBuffer(filter.data.data) : null; } diff --git a/frontend/appflowy_flutter/lib/plugins/database/grid/presentation/widgets/filter/filter_menu.dart b/frontend/appflowy_flutter/lib/plugins/database/grid/presentation/widgets/filter/filter_menu.dart index caca16a1ac..80deb98695 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/grid/presentation/widgets/filter/filter_menu.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/grid/presentation/widgets/filter/filter_menu.dart @@ -23,14 +23,14 @@ class FilterMenu extends StatelessWidget { @override Widget build(BuildContext context) { - return BlocProvider( - create: (context) => GridFilterMenuBloc( + return BlocProvider( + create: (context) => DatabaseFilterMenuBloc( viewId: fieldController.viewId, fieldController: fieldController, )..add( - const GridFilterMenuEvent.initial(), + const DatabaseFilterMenuEvent.initial(), ), - child: BlocBuilder( + child: BlocBuilder( builder: (context, state) { final List children = []; children.addAll( @@ -115,7 +115,7 @@ class _AddFilterButtonState extends State { triggerActions: PopoverTriggerFlags.none, child: child, popupBuilder: (BuildContext context) { - final bloc = buildContext.read(); + final bloc = buildContext.read(); return GridCreateFilterList( viewId: widget.viewId, fieldController: bloc.fieldController, diff --git a/frontend/appflowy_flutter/lib/plugins/database/grid/presentation/widgets/filter/filter_menu_item.dart b/frontend/appflowy_flutter/lib/plugins/database/grid/presentation/widgets/filter/filter_menu_item.dart index f661ea57de..3ca86d3969 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/grid/presentation/widgets/filter/filter_menu_item.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/grid/presentation/widgets/filter/filter_menu_item.dart @@ -26,7 +26,7 @@ class FilterMenuItem extends StatelessWidget { FieldType.RichText => TextFilterChoicechip(filterInfo: filterInfo), FieldType.SingleSelect => SelectOptionFilterChoicechip(filterInfo: filterInfo), - FieldType.URL => URLFilterChoicechip(filterInfo: filterInfo), + FieldType.URL => URLFilterChoiceChip(filterInfo: filterInfo), FieldType.Checklist => ChecklistFilterChoicechip(filterInfo: filterInfo), _ => const SizedBox(), }; diff --git a/frontend/appflowy_flutter/lib/plugins/database/grid/presentation/widgets/toolbar/filter_button.dart b/frontend/appflowy_flutter/lib/plugins/database/grid/presentation/widgets/toolbar/filter_button.dart index 1ecb82e66d..21c61713e4 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/grid/presentation/widgets/toolbar/filter_button.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/grid/presentation/widgets/toolbar/filter_button.dart @@ -23,7 +23,7 @@ class _FilterButtonState extends State { @override Widget build(BuildContext context) { - return BlocBuilder( + return BlocBuilder( builder: (context, state) { final textColor = state.filters.isEmpty ? AFThemeExtension.of(context).textColor @@ -41,11 +41,11 @@ class _FilterButtonState extends State { padding: GridSize.toolbarSettingButtonInsets, radius: Corners.s4Border, onPressed: () { - final bloc = context.read(); + final bloc = context.read(); if (bloc.state.filters.isEmpty) { _popoverController.show(); } else { - bloc.add(const GridFilterMenuEvent.toggleMenu()); + bloc.add(const DatabaseFilterMenuEvent.toggleMenu()); } }, ), @@ -63,14 +63,14 @@ class _FilterButtonState extends State { triggerActions: PopoverTriggerFlags.none, child: child, popupBuilder: (BuildContext context) { - final bloc = buildContext.read(); + final bloc = buildContext.read(); return GridCreateFilterList( viewId: bloc.viewId, fieldController: bloc.fieldController, onClosed: () => _popoverController.close(), onCreateFilter: () { if (!bloc.state.isVisible) { - bloc.add(const GridFilterMenuEvent.toggleMenu()); + bloc.add(const DatabaseFilterMenuEvent.toggleMenu()); } }, ); diff --git a/frontend/appflowy_flutter/lib/plugins/database/grid/presentation/widgets/toolbar/grid_setting_bar.dart b/frontend/appflowy_flutter/lib/plugins/database/grid/presentation/widgets/toolbar/grid_setting_bar.dart index cd861642bb..312bfd7511 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/grid/presentation/widgets/toolbar/grid_setting_bar.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/grid/presentation/widgets/toolbar/grid_setting_bar.dart @@ -24,11 +24,11 @@ class GridSettingBar extends StatelessWidget { Widget build(BuildContext context) { return MultiBlocProvider( providers: [ - BlocProvider( - create: (context) => GridFilterMenuBloc( + BlocProvider( + create: (context) => DatabaseFilterMenuBloc( viewId: controller.viewId, fieldController: controller.fieldController, - )..add(const GridFilterMenuEvent.initial()), + )..add(const DatabaseFilterMenuEvent.initial()), ), BlocProvider( create: (context) => SortEditorBloc( @@ -37,7 +37,7 @@ class GridSettingBar extends StatelessWidget { ), ), ], - child: BlocListener( + child: BlocListener( listenWhen: (p, c) => p.isVisible != c.isVisible, listener: (context, state) => toggleExtension.toggle(), child: ValueListenableBuilder( diff --git a/frontend/appflowy_flutter/lib/plugins/database/widgets/setting/mobile_database_controls.dart b/frontend/appflowy_flutter/lib/plugins/database/widgets/setting/mobile_database_controls.dart index dd3d31952e..d5f3ce293a 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/widgets/setting/mobile_database_controls.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/widgets/setting/mobile_database_controls.dart @@ -27,11 +27,11 @@ class MobileDatabaseControls extends StatelessWidget { Widget build(BuildContext context) { return MultiBlocProvider( providers: [ - BlocProvider( - create: (context) => GridFilterMenuBloc( + BlocProvider( + create: (context) => DatabaseFilterMenuBloc( viewId: controller.viewId, fieldController: controller.fieldController, - )..add(const GridFilterMenuEvent.initial()), + )..add(const DatabaseFilterMenuEvent.initial()), ), BlocProvider( create: (context) => SortEditorBloc( @@ -40,7 +40,7 @@ class MobileDatabaseControls extends StatelessWidget { ), ), ], - child: BlocListener( + child: BlocListener( listenWhen: (p, c) => p.isVisible != c.isVisible, listener: (context, state) => toggleExtension.toggle(), child: ValueListenableBuilder( diff --git a/frontend/appflowy_flutter/test/bloc_test/grid_test/filter/filter_menu_test.dart b/frontend/appflowy_flutter/test/bloc_test/grid_test/filter/filter_menu_test.dart index e76870d33a..a5aa0c9f58 100644 --- a/frontend/appflowy_flutter/test/bloc_test/grid_test/filter/filter_menu_test.dart +++ b/frontend/appflowy_flutter/test/bloc_test/grid_test/filter/filter_menu_test.dart @@ -13,10 +13,10 @@ void main() { test('test filter menu after create a text filter)', () async { final context = await gridTest.createTestGrid(); - final menuBloc = GridFilterMenuBloc( + final menuBloc = DatabaseFilterMenuBloc( viewId: context.gridView.id, fieldController: context.fieldController, - )..add(const GridFilterMenuEvent.initial()); + )..add(const DatabaseFilterMenuEvent.initial()); await gridResponseFuture(); assert(menuBloc.state.creatableFields.length == 3); @@ -28,15 +28,15 @@ void main() { content: "", ); await gridResponseFuture(); - assert(menuBloc.state.creatableFields.length == 2); + assert(menuBloc.state.creatableFields.length == 3); }); test('test filter menu after update existing text filter)', () async { final context = await gridTest.createTestGrid(); - final menuBloc = GridFilterMenuBloc( + final menuBloc = DatabaseFilterMenuBloc( viewId: context.gridView.id, fieldController: context.fieldController, - )..add(const GridFilterMenuEvent.initial()); + )..add(const DatabaseFilterMenuEvent.initial()); await gridResponseFuture(); final service = FilterBackendService(viewId: context.gridView.id); diff --git a/frontend/appflowy_tauri/src-tauri/Cargo.lock b/frontend/appflowy_tauri/src-tauri/Cargo.lock index 532628171c..126df830cf 100644 --- a/frontend/appflowy_tauri/src-tauri/Cargo.lock +++ b/frontend/appflowy_tauri/src-tauri/Cargo.lock @@ -838,7 +838,7 @@ dependencies = [ [[package]] name = "collab" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=0970b2e1440134af7c83bb8fc80cac5d2dedebb7#0970b2e1440134af7c83bb8fc80cac5d2dedebb7" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=4b25d7d021a11c51583e6a404c139f49ee6a3bf9#4b25d7d021a11c51583e6a404c139f49ee6a3bf9" dependencies = [ "anyhow", "async-trait", @@ -862,7 +862,7 @@ dependencies = [ [[package]] name = "collab-database" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=0970b2e1440134af7c83bb8fc80cac5d2dedebb7#0970b2e1440134af7c83bb8fc80cac5d2dedebb7" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=4b25d7d021a11c51583e6a404c139f49ee6a3bf9#4b25d7d021a11c51583e6a404c139f49ee6a3bf9" dependencies = [ "anyhow", "async-trait", @@ -892,7 +892,7 @@ dependencies = [ [[package]] name = "collab-document" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=0970b2e1440134af7c83bb8fc80cac5d2dedebb7#0970b2e1440134af7c83bb8fc80cac5d2dedebb7" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=4b25d7d021a11c51583e6a404c139f49ee6a3bf9#4b25d7d021a11c51583e6a404c139f49ee6a3bf9" dependencies = [ "anyhow", "collab", @@ -911,7 +911,7 @@ dependencies = [ [[package]] name = "collab-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=0970b2e1440134af7c83bb8fc80cac5d2dedebb7#0970b2e1440134af7c83bb8fc80cac5d2dedebb7" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=4b25d7d021a11c51583e6a404c139f49ee6a3bf9#4b25d7d021a11c51583e6a404c139f49ee6a3bf9" dependencies = [ "anyhow", "bytes", @@ -926,7 +926,7 @@ dependencies = [ [[package]] name = "collab-folder" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=0970b2e1440134af7c83bb8fc80cac5d2dedebb7#0970b2e1440134af7c83bb8fc80cac5d2dedebb7" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=4b25d7d021a11c51583e6a404c139f49ee6a3bf9#4b25d7d021a11c51583e6a404c139f49ee6a3bf9" dependencies = [ "anyhow", "chrono", @@ -963,7 +963,7 @@ dependencies = [ [[package]] name = "collab-plugins" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=0970b2e1440134af7c83bb8fc80cac5d2dedebb7#0970b2e1440134af7c83bb8fc80cac5d2dedebb7" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=4b25d7d021a11c51583e6a404c139f49ee6a3bf9#4b25d7d021a11c51583e6a404c139f49ee6a3bf9" dependencies = [ "anyhow", "async-stream", @@ -1002,7 +1002,7 @@ dependencies = [ [[package]] name = "collab-user" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=0970b2e1440134af7c83bb8fc80cac5d2dedebb7#0970b2e1440134af7c83bb8fc80cac5d2dedebb7" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=4b25d7d021a11c51583e6a404c139f49ee6a3bf9#4b25d7d021a11c51583e6a404c139f49ee6a3bf9" dependencies = [ "anyhow", "collab", diff --git a/frontend/appflowy_tauri/src-tauri/Cargo.toml b/frontend/appflowy_tauri/src-tauri/Cargo.toml index 4a47b165a2..a41d7df3e6 100644 --- a/frontend/appflowy_tauri/src-tauri/Cargo.toml +++ b/frontend/appflowy_tauri/src-tauri/Cargo.toml @@ -96,10 +96,10 @@ client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "ab9 # To switch to the local path, run: # scripts/tool/update_collab_source.sh # ⚠️⚠️⚠️️ -collab = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "0970b2e1440134af7c83bb8fc80cac5d2dedebb7" } -collab-folder = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "0970b2e1440134af7c83bb8fc80cac5d2dedebb7" } -collab-document = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "0970b2e1440134af7c83bb8fc80cac5d2dedebb7" } -collab-database = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "0970b2e1440134af7c83bb8fc80cac5d2dedebb7" } -collab-plugins = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "0970b2e1440134af7c83bb8fc80cac5d2dedebb7" } -collab-user = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "0970b2e1440134af7c83bb8fc80cac5d2dedebb7" } -collab-entity = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "0970b2e1440134af7c83bb8fc80cac5d2dedebb7" } +collab = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "4b25d7d021a11c51583e6a404c139f49ee6a3bf9" } +collab-folder = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "4b25d7d021a11c51583e6a404c139f49ee6a3bf9" } +collab-document = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "4b25d7d021a11c51583e6a404c139f49ee6a3bf9" } +collab-database = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "4b25d7d021a11c51583e6a404c139f49ee6a3bf9" } +collab-plugins = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "4b25d7d021a11c51583e6a404c139f49ee6a3bf9" } +collab-user = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "4b25d7d021a11c51583e6a404c139f49ee6a3bf9" } +collab-entity = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "4b25d7d021a11c51583e6a404c139f49ee6a3bf9" } diff --git a/frontend/appflowy_web/wasm-libs/Cargo.toml b/frontend/appflowy_web/wasm-libs/Cargo.toml index 829840c6dd..ff125fbf0c 100644 --- a/frontend/appflowy_web/wasm-libs/Cargo.toml +++ b/frontend/appflowy_web/wasm-libs/Cargo.toml @@ -65,10 +65,10 @@ client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "ab9 # To switch to the local path, run: # scripts/tool/update_collab_source.sh # ⚠️⚠️⚠️️ -collab = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "0970b2e1440134af7c83bb8fc80cac5d2dedebb7" } -collab-folder = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "0970b2e1440134af7c83bb8fc80cac5d2dedebb7" } -collab-document = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "0970b2e1440134af7c83bb8fc80cac5d2dedebb7" } -collab-database = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "0970b2e1440134af7c83bb8fc80cac5d2dedebb7" } -collab-plugins = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "0970b2e1440134af7c83bb8fc80cac5d2dedebb7" } -collab-user = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "0970b2e1440134af7c83bb8fc80cac5d2dedebb7" } -collab-entity = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "0970b2e1440134af7c83bb8fc80cac5d2dedebb7" } +collab = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "4b25d7d021a11c51583e6a404c139f49ee6a3bf9" } +collab-folder = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "4b25d7d021a11c51583e6a404c139f49ee6a3bf9" } +collab-document = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "4b25d7d021a11c51583e6a404c139f49ee6a3bf9" } +collab-database = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "4b25d7d021a11c51583e6a404c139f49ee6a3bf9" } +collab-plugins = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "4b25d7d021a11c51583e6a404c139f49ee6a3bf9" } +collab-user = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "4b25d7d021a11c51583e6a404c139f49ee6a3bf9" } +collab-entity = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "4b25d7d021a11c51583e6a404c139f49ee6a3bf9" } diff --git a/frontend/rust-lib/Cargo.lock b/frontend/rust-lib/Cargo.lock index d46547cd29..74240017cd 100644 --- a/frontend/rust-lib/Cargo.lock +++ b/frontend/rust-lib/Cargo.lock @@ -764,7 +764,7 @@ dependencies = [ [[package]] name = "collab" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=0970b2e1440134af7c83bb8fc80cac5d2dedebb7#0970b2e1440134af7c83bb8fc80cac5d2dedebb7" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=4b25d7d021a11c51583e6a404c139f49ee6a3bf9#4b25d7d021a11c51583e6a404c139f49ee6a3bf9" dependencies = [ "anyhow", "async-trait", @@ -788,7 +788,7 @@ dependencies = [ [[package]] name = "collab-database" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=0970b2e1440134af7c83bb8fc80cac5d2dedebb7#0970b2e1440134af7c83bb8fc80cac5d2dedebb7" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=4b25d7d021a11c51583e6a404c139f49ee6a3bf9#4b25d7d021a11c51583e6a404c139f49ee6a3bf9" dependencies = [ "anyhow", "async-trait", @@ -818,7 +818,7 @@ dependencies = [ [[package]] name = "collab-document" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=0970b2e1440134af7c83bb8fc80cac5d2dedebb7#0970b2e1440134af7c83bb8fc80cac5d2dedebb7" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=4b25d7d021a11c51583e6a404c139f49ee6a3bf9#4b25d7d021a11c51583e6a404c139f49ee6a3bf9" dependencies = [ "anyhow", "collab", @@ -837,7 +837,7 @@ dependencies = [ [[package]] name = "collab-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=0970b2e1440134af7c83bb8fc80cac5d2dedebb7#0970b2e1440134af7c83bb8fc80cac5d2dedebb7" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=4b25d7d021a11c51583e6a404c139f49ee6a3bf9#4b25d7d021a11c51583e6a404c139f49ee6a3bf9" dependencies = [ "anyhow", "bytes", @@ -852,7 +852,7 @@ dependencies = [ [[package]] name = "collab-folder" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=0970b2e1440134af7c83bb8fc80cac5d2dedebb7#0970b2e1440134af7c83bb8fc80cac5d2dedebb7" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=4b25d7d021a11c51583e6a404c139f49ee6a3bf9#4b25d7d021a11c51583e6a404c139f49ee6a3bf9" dependencies = [ "anyhow", "chrono", @@ -889,7 +889,7 @@ dependencies = [ [[package]] name = "collab-plugins" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=0970b2e1440134af7c83bb8fc80cac5d2dedebb7#0970b2e1440134af7c83bb8fc80cac5d2dedebb7" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=4b25d7d021a11c51583e6a404c139f49ee6a3bf9#4b25d7d021a11c51583e6a404c139f49ee6a3bf9" dependencies = [ "anyhow", "async-stream", @@ -928,7 +928,7 @@ dependencies = [ [[package]] name = "collab-user" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=0970b2e1440134af7c83bb8fc80cac5d2dedebb7#0970b2e1440134af7c83bb8fc80cac5d2dedebb7" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=4b25d7d021a11c51583e6a404c139f49ee6a3bf9#4b25d7d021a11c51583e6a404c139f49ee6a3bf9" dependencies = [ "anyhow", "collab", @@ -1125,7 +1125,7 @@ dependencies = [ "cssparser-macros", "dtoa-short", "itoa", - "phf 0.8.0", + "phf 0.11.2", "smallvec", ] @@ -3663,7 +3663,7 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3dfb61232e34fcb633f43d12c58f83c1df82962dcdfa565a4e866ffc17dafe12" dependencies = [ - "phf_macros", + "phf_macros 0.8.0", "phf_shared 0.8.0", "proc-macro-hack", ] @@ -3683,6 +3683,7 @@ version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" dependencies = [ + "phf_macros 0.11.2", "phf_shared 0.11.2", ] @@ -3750,6 +3751,19 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "phf_macros" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3444646e286606587e49f3bcf1679b8cef1dc2c5ecc29ddacaffc305180d464b" +dependencies = [ + "phf_generator 0.11.2", + "phf_shared 0.11.2", + "proc-macro2", + "quote", + "syn 2.0.47", +] + [[package]] name = "phf_shared" version = "0.8.0" diff --git a/frontend/rust-lib/Cargo.toml b/frontend/rust-lib/Cargo.toml index 5e030565da..b278c1c36a 100644 --- a/frontend/rust-lib/Cargo.toml +++ b/frontend/rust-lib/Cargo.toml @@ -120,10 +120,10 @@ client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "ab9 # To switch to the local path, run: # scripts/tool/update_collab_source.sh # ⚠️⚠️⚠️️ -collab = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "0970b2e1440134af7c83bb8fc80cac5d2dedebb7" } -collab-folder = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "0970b2e1440134af7c83bb8fc80cac5d2dedebb7" } -collab-document = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "0970b2e1440134af7c83bb8fc80cac5d2dedebb7" } -collab-database = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "0970b2e1440134af7c83bb8fc80cac5d2dedebb7" } -collab-plugins = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "0970b2e1440134af7c83bb8fc80cac5d2dedebb7" } -collab-user = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "0970b2e1440134af7c83bb8fc80cac5d2dedebb7" } -collab-entity = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "0970b2e1440134af7c83bb8fc80cac5d2dedebb7" } +collab = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "4b25d7d021a11c51583e6a404c139f49ee6a3bf9" } +collab-folder = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "4b25d7d021a11c51583e6a404c139f49ee6a3bf9" } +collab-document = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "4b25d7d021a11c51583e6a404c139f49ee6a3bf9" } +collab-database = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "4b25d7d021a11c51583e6a404c139f49ee6a3bf9" } +collab-plugins = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "4b25d7d021a11c51583e6a404c139f49ee6a3bf9" } +collab-user = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "4b25d7d021a11c51583e6a404c139f49ee6a3bf9" } +collab-entity = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "4b25d7d021a11c51583e6a404c139f49ee6a3bf9" } diff --git a/frontend/rust-lib/flowy-database2/src/entities/filter_entities/date_filter.rs b/frontend/rust-lib/flowy-database2/src/entities/filter_entities/date_filter.rs index ed302af51e..01c3c9687c 100644 --- a/frontend/rust-lib/flowy-database2/src/entities/filter_entities/date_filter.rs +++ b/frontend/rust-lib/flowy-database2/src/entities/filter_entities/date_filter.rs @@ -23,19 +23,19 @@ pub struct DateFilterPB { } #[derive(Deserialize, Serialize, Default, Clone, Debug)] -pub struct DateFilterContentPB { +pub struct DateFilterContent { pub start: Option, pub end: Option, pub timestamp: Option, } -impl ToString for DateFilterContentPB { +impl ToString for DateFilterContent { fn to_string(&self) -> String { serde_json::to_string(self).unwrap() } } -impl FromStr for DateFilterContentPB { +impl FromStr for DateFilterContent { type Err = serde_json::Error; fn from_str(s: &str) -> Result { @@ -89,7 +89,7 @@ impl ParseFilterData for DateFilterPB { ..Default::default() }; - if let Ok(content) = DateFilterContentPB::from_str(&content) { + if let Ok(content) = DateFilterContent::from_str(&content) { date_filter.start = content.start; date_filter.end = content.end; date_filter.timestamp = content.timestamp; diff --git a/frontend/rust-lib/flowy-database2/src/entities/row_entities.rs b/frontend/rust-lib/flowy-database2/src/entities/row_entities.rs index 9bad92197f..597bb293cc 100644 --- a/frontend/rust-lib/flowy-database2/src/entities/row_entities.rs +++ b/frontend/rust-lib/flowy-database2/src/entities/row_entities.rs @@ -6,6 +6,7 @@ use collab_database::views::RowOrder; use flowy_derive::ProtoBuf; use flowy_error::ErrorCode; use lib_infra::validator_fn::required_not_empty_str; +use serde::{Deserialize, Serialize}; use validator::Validate; use crate::entities::parser::NotEmptyStr; @@ -49,7 +50,7 @@ impl From for RowPB { } } -#[derive(Debug, Default, Clone, ProtoBuf)] +#[derive(Debug, Default, Clone, ProtoBuf, Serialize, Deserialize)] pub struct RowMetaPB { #[pb(index = 1)] pub id: String, diff --git a/frontend/rust-lib/flowy-database2/src/services/database/database_editor.rs b/frontend/rust-lib/flowy-database2/src/services/database/database_editor.rs index f7d3482480..94a39bf411 100644 --- a/frontend/rust-lib/flowy-database2/src/services/database/database_editor.rs +++ b/frontend/rust-lib/flowy-database2/src/services/database/database_editor.rs @@ -1078,7 +1078,7 @@ impl DatabaseEditor { pub async fn group_by_field(&self, view_id: &str, field_id: &str) -> FlowyResult<()> { let view = self.database_views.get_view_editor(view_id).await?; - view.v_grouping_by_field(field_id).await?; + view.v_group_by_field(field_id).await?; Ok(()) } diff --git a/frontend/rust-lib/flowy-database2/src/services/database_view/notifier.rs b/frontend/rust-lib/flowy-database2/src/services/database_view/notifier.rs index 9a1cbecf98..478aa2c5a4 100644 --- a/frontend/rust-lib/flowy-database2/src/services/database_view/notifier.rs +++ b/frontend/rust-lib/flowy-database2/src/services/database_view/notifier.rs @@ -1,12 +1,12 @@ #![allow(clippy::while_let_loop)] use crate::entities::{ CalculationChangesetNotificationPB, DatabaseViewSettingPB, FilterChangesetNotificationPB, - GroupChangesPB, GroupRowsNotificationPB, ReorderAllRowsPB, ReorderSingleRowPB, - RowsVisibilityChangePB, SortChangesetNotificationPB, + GroupChangesPB, GroupRowsNotificationPB, InsertedRowPB, ReorderAllRowsPB, ReorderSingleRowPB, + RowMetaPB, RowsChangePB, RowsVisibilityChangePB, SortChangesetNotificationPB, }; use crate::notification::{send_notification, DatabaseNotification}; use crate::services::filter::FilterResultNotification; -use crate::services::sort::{InsertSortedRowResult, ReorderAllRowsResult, ReorderSingleRowResult}; +use crate::services::sort::{InsertRowResult, ReorderAllRowsResult, ReorderSingleRowResult}; use async_stream::stream; use futures::stream::StreamExt; use tokio::sync::broadcast; @@ -16,7 +16,7 @@ pub enum DatabaseViewChanged { FilterNotification(FilterResultNotification), ReorderAllRowsNotification(ReorderAllRowsResult), ReorderSingleRowNotification(ReorderSingleRowResult), - InsertSortedRowNotification(InsertSortedRowResult), + InsertRowNotification(InsertRowResult), CalculationValueNotification(CalculationChangesetNotificationPB), } @@ -79,7 +79,17 @@ impl DatabaseViewChangedReceiverRunner { .payload(reorder_row) .send() }, - DatabaseViewChanged::InsertSortedRowNotification(_result) => {}, + DatabaseViewChanged::InsertRowNotification(result) => { + let inserted_row = InsertedRowPB { + row_meta: RowMetaPB::from(result.row), + index: Some(result.index as i32), + is_new: true, + }; + let changes = RowsChangePB::from_insert(inserted_row); + send_notification(&result.view_id, DatabaseNotification::DidUpdateViewRows) + .payload(changes) + .send(); + }, DatabaseViewChanged::CalculationValueNotification(notification) => send_notification( ¬ification.view_id, DatabaseNotification::DidUpdateCalculation, diff --git a/frontend/rust-lib/flowy-database2/src/services/database_view/view_editor.rs b/frontend/rust-lib/flowy-database2/src/services/database_view/view_editor.rs index 398d9e8dff..6cef8ccc45 100644 --- a/frontend/rust-lib/flowy-database2/src/services/database_view/view_editor.rs +++ b/frontend/rust-lib/flowy-database2/src/services/database_view/view_editor.rs @@ -3,7 +3,7 @@ use std::collections::HashMap; use std::sync::Arc; use collab_database::database::{gen_database_calculation_id, gen_database_sort_id, gen_row_id}; -use collab_database::fields::{Field, TypeOptionData}; +use collab_database::fields::Field; use collab_database::rows::{Cells, Row, RowDetail, RowId}; use collab_database::views::{DatabaseLayout, DatabaseView}; use lib_infra::util::timestamp; @@ -16,9 +16,9 @@ use lib_dispatch::prelude::af_spawn; use crate::entities::{ CalendarEventPB, CreateRowParams, CreateRowPayloadPB, DatabaseLayoutMetaPB, DatabaseLayoutSettingPB, DeleteSortPayloadPB, FieldType, FieldVisibility, GroupChangesPB, - GroupPB, InsertedRowPB, LayoutSettingChangeset, LayoutSettingParams, - RemoveCalculationChangesetPB, ReorderSortPayloadPB, RowMetaPB, RowsChangePB, - SortChangesetNotificationPB, SortPB, UpdateCalculationChangesetPB, UpdateSortPayloadPB, + GroupPB, LayoutSettingChangeset, LayoutSettingParams, RemoveCalculationChangesetPB, + ReorderSortPayloadPB, RowMetaPB, RowsChangePB, SortChangesetNotificationPB, SortPB, + UpdateCalculationChangesetPB, UpdateSortPayloadPB, }; use crate::notification::{send_notification, DatabaseNotification}; use crate::services::calculations::{Calculation, CalculationChangeset, CalculationsController}; @@ -26,7 +26,7 @@ use crate::services::cell::{CellBuilder, CellCache}; use crate::services::database::{database_view_setting_pb_from_view, DatabaseRowEvent, UpdatedRow}; use crate::services::database_view::view_filter::make_filter_controller; use crate::services::database_view::view_group::{ - get_cell_for_row, get_cells_for_field, new_group_controller, new_group_controller_with_field, + get_cell_for_row, get_cells_for_field, new_group_controller, }; use crate::services::database_view::view_operation::DatabaseViewOperation; use crate::services::database_view::view_sort::make_sort_controller; @@ -68,10 +68,6 @@ impl DatabaseViewEditor { ) -> FlowyResult { let (notifier, _) = broadcast::channel(100); af_spawn(DatabaseViewChangedReceiverRunner(Some(notifier.subscribe())).run()); - // Group - let group_controller = Arc::new(RwLock::new( - new_group_controller(view_id.clone(), delegate.clone()).await?, - )); // Filter let filter_controller = make_filter_controller( @@ -92,6 +88,17 @@ impl DatabaseViewEditor { ) .await; + // Group + let group_controller = Arc::new(RwLock::new( + new_group_controller( + view_id.clone(), + delegate.clone(), + filter_controller.clone(), + None, + ) + .await?, + )); + // Calculations let calculations_controller = make_calculations_controller(&view_id, delegate.clone(), notifier.clone()).await; @@ -142,7 +149,7 @@ impl DatabaseViewEditor { if let Some(controller) = self.group_controller.read().await.as_ref() { let field = self .delegate - .get_field(controller.field_id()) + .get_field(controller.get_grouping_field_id()) .ok_or_else(|| FlowyError::internal().with_context("Failed to get grouping field"))?; controller.will_create_row(&mut cells, &field, &group_id); } @@ -168,24 +175,20 @@ impl DatabaseViewEditor { pub async fn v_did_create_row(&self, row_detail: &RowDetail, index: usize) { // Send the group notification if the current view has groups if let Some(controller) = self.group_controller.write().await.as_mut() { - let changesets = controller.did_create_row(row_detail, index); + let mut row_details = vec![Arc::new(row_detail.clone())]; + self.v_filter_rows(&mut row_details).await; - for changeset in changesets { - notify_did_update_group_rows(changeset).await; + if let Some(row_detail) = row_details.pop() { + let changesets = controller.did_create_row(&row_detail, index); + + for changeset in changesets { + notify_did_update_group_rows(changeset).await; + } } } - let inserted_row = InsertedRowPB { - row_meta: RowMetaPB::from(row_detail), - index: Some(index as i32), - is_new: true, - }; - let changes = RowsChangePB::from_insert(inserted_row); - send_notification(&self.view_id, DatabaseNotification::DidUpdateViewRows) - .payload(changes) - .send(); self - .gen_did_create_row_view_tasks(row_detail.row.clone()) + .gen_did_create_row_view_tasks(index, row_detail.clone()) .await; } @@ -239,34 +242,41 @@ impl DatabaseViewEditor { row_detail: &RowDetail, field_id: String, ) { - let result = self - .mut_group_controller(|group_controller, field| { - Ok(group_controller.did_update_group_row(old_row, row_detail, &field)) - }) - .await; + if let Some(controller) = self.group_controller.write().await.as_mut() { + let field = self.delegate.get_field(controller.get_grouping_field_id()); - if let Some(Ok(result)) = result { - let mut group_changes = GroupChangesPB { - view_id: self.view_id.clone(), - ..Default::default() - }; - if let Some(inserted_group) = result.inserted_group { - tracing::trace!("Create group after editing the row: {:?}", inserted_group); - group_changes.inserted_groups.push(inserted_group); - } - if let Some(delete_group) = result.deleted_group { - tracing::trace!("Delete group after editing the row: {:?}", delete_group); - group_changes.deleted_groups.push(delete_group.group_id); - } + if let Some(field) = field { + let mut row_details = vec![Arc::new(row_detail.clone())]; + self.v_filter_rows(&mut row_details).await; - if !group_changes.is_empty() { - notify_did_update_num_of_groups(&self.view_id, group_changes).await; - } + if let Some(row_detail) = row_details.pop() { + let result = controller.did_update_group_row(old_row, &row_detail, &field); - for changeset in result.row_changesets { - if !changeset.is_empty() { - tracing::trace!("Group change after editing the row: {:?}", changeset); - notify_did_update_group_rows(changeset).await; + if let Ok(result) = result { + let mut group_changes = GroupChangesPB { + view_id: self.view_id.clone(), + ..Default::default() + }; + if let Some(inserted_group) = result.inserted_group { + tracing::trace!("Create group after editing the row: {:?}", inserted_group); + group_changes.inserted_groups.push(inserted_group); + } + if let Some(delete_group) = result.deleted_group { + tracing::trace!("Delete group after editing the row: {:?}", delete_group); + group_changes.deleted_groups.push(delete_group.group_id); + } + + if !group_changes.is_empty() { + notify_did_update_num_of_groups(&self.view_id, group_changes).await; + } + + for changeset in result.row_changesets { + if !changeset.is_empty() { + tracing::trace!("Group change after editing the row: {:?}", changeset); + notify_did_update_group_rows(changeset).await; + } + } + } } } } @@ -376,7 +386,7 @@ impl DatabaseViewEditor { pub async fn is_grouping_field(&self, field_id: &str) -> bool { match self.group_controller.read().await.as_ref() { - Some(group_controller) => group_controller.field_id() == field_id, + Some(group_controller) => group_controller.get_grouping_field_id() == field_id, None => false, } } @@ -385,7 +395,7 @@ impl DatabaseViewEditor { pub async fn v_initialize_new_group(&self, field_id: &str) -> FlowyResult<()> { let is_grouping_field = self.is_grouping_field(field_id).await; if !is_grouping_field { - self.v_grouping_by_field(field_id).await?; + self.v_group_by_field(field_id).await?; if let Some(view) = self.delegate.get_view(&self.view_id).await { let setting = database_view_setting_pb_from_view(view); @@ -399,7 +409,7 @@ impl DatabaseViewEditor { let mut old_field: Option = None; let result = if let Some(controller) = self.group_controller.write().await.as_mut() { let create_group_results = controller.create_group(name.to_string())?; - old_field = self.delegate.get_field(controller.field_id()); + old_field = self.delegate.get_field(controller.get_grouping_field_id()); create_group_results } else { (None, None) @@ -432,7 +442,7 @@ impl DatabaseViewEditor { None => return Ok(RowsChangePB::default()), }; - let old_field = self.delegate.get_field(controller.field_id()); + let old_field = self.delegate.get_field(controller.get_grouping_field_id()); let (row_ids, type_option_data) = controller.delete_group(group_id)?; drop(group_controller); @@ -462,12 +472,15 @@ impl DatabaseViewEditor { } pub async fn v_update_group(&self, changeset: Vec) -> FlowyResult<()> { - let mut type_option_data = TypeOptionData::new(); + let mut type_option_data = None; let (old_field, updated_groups) = if let Some(controller) = self.group_controller.write().await.as_mut() { - let old_field = self.delegate.get_field(controller.field_id()); + let old_field = self.delegate.get_field(controller.get_grouping_field_id()); let (updated_groups, new_type_option) = controller.apply_group_changeset(&changeset)?; - type_option_data.extend(new_type_option); + + if new_type_option.is_some() { + type_option_data = new_type_option; + } (old_field, updated_groups) } else { @@ -475,7 +488,7 @@ impl DatabaseViewEditor { }; if let Some(old_field) = old_field { - if !type_option_data.is_empty() { + if let Some(type_option_data) = type_option_data { self .delegate .update_field(type_option_data, old_field) @@ -644,15 +657,20 @@ impl DatabaseViewEditor { #[tracing::instrument(level = "trace", skip(self), err)] pub async fn v_modify_filters(&self, changeset: FilterChangeset) -> FlowyResult<()> { - let filter_controller = self.filter_controller.clone(); - - // self.delegate.insert_filter(&self.view_id, filter.clone()); - - let notification = filter_controller.apply_changeset(changeset).await; - - drop(filter_controller); + let notification = self.filter_controller.apply_changeset(changeset).await; notify_did_update_filter(notification).await; + + let group_controller_read_guard = self.group_controller.read().await; + let grouping_field_id = group_controller_read_guard + .as_ref() + .map(|controller| controller.get_grouping_field_id().to_string()); + drop(group_controller_read_guard); + + if let Some(field_id) = grouping_field_id { + self.v_group_by_field(&field_id).await?; + } + Ok(()) } @@ -786,11 +804,6 @@ impl DatabaseViewEditor { #[tracing::instrument(level = "trace", skip_all, err)] pub async fn v_did_update_field_type_option(&self, old_field: &Field) -> FlowyResult<()> { let field_id = &old_field.id; - // If the id of the grouping field is equal to the updated field's id, then we need to - // update the group setting - if self.is_grouping_field(field_id).await { - self.v_grouping_by_field(field_id).await?; - } if let Some(field) = self.delegate.get_field(field_id) { self @@ -808,36 +821,58 @@ impl DatabaseViewEditor { notify_did_update_filter(notification).await; } } + + // If the id of the grouping field is equal to the updated field's id, then we need to + // update the group setting + if self.is_grouping_field(field_id).await { + self.v_group_by_field(field_id).await?; + } + Ok(()) } /// Called when a grouping field is updated. #[tracing::instrument(level = "debug", skip_all, err)] - pub async fn v_grouping_by_field(&self, field_id: &str) -> FlowyResult<()> { + pub async fn v_group_by_field(&self, field_id: &str) -> FlowyResult<()> { if let Some(field) = self.delegate.get_field(field_id) { - let new_group_controller = - new_group_controller_with_field(self.view_id.clone(), self.delegate.clone(), field).await?; + tracing::trace!("create new group controller"); - let new_groups = new_group_controller - .get_all_groups() - .into_iter() - .map(|group| GroupPB::from(group.clone())) - .collect(); + let new_group_controller = new_group_controller( + self.view_id.clone(), + self.delegate.clone(), + self.filter_controller.clone(), + Some(field), + ) + .await?; - *self.group_controller.write().await = Some(new_group_controller); - let changeset = GroupChangesPB { - view_id: self.view_id.clone(), - initial_groups: new_groups, - ..Default::default() - }; + if let Some(controller) = &new_group_controller { + let new_groups = controller + .get_all_groups() + .into_iter() + .map(|group| GroupPB::from(group.clone())) + .collect(); - debug_assert!(!changeset.is_empty()); - if !changeset.is_empty() { - send_notification(&changeset.view_id, DatabaseNotification::DidGroupByField) - .payload(changeset) - .send(); + let changeset = GroupChangesPB { + view_id: self.view_id.clone(), + initial_groups: new_groups, + ..Default::default() + }; + tracing::trace!("notify did group by field1"); + + debug_assert!(!changeset.is_empty()); + if !changeset.is_empty() { + send_notification(&changeset.view_id, DatabaseNotification::DidGroupByField) + .payload(changeset) + .send(); + } } + tracing::trace!("notify did group by field2"); + + *self.group_controller.write().await = new_group_controller; + + tracing::trace!("did write group_controller to cache"); } + Ok(()) } @@ -958,8 +993,13 @@ impl DatabaseViewEditor { } // initialize the group controller if the current layout support grouping - *self.group_controller.write().await = - new_group_controller(self.view_id.clone(), self.delegate.clone()).await?; + *self.group_controller.write().await = new_group_controller( + self.view_id.clone(), + self.delegate.clone(), + self.filter_controller.clone(), + None, + ) + .await?; let payload = DatabaseLayoutMetaPB { view_id: self.view_id.clone(), @@ -1019,7 +1059,7 @@ impl DatabaseViewEditor { .read() .await .as_ref() - .map(|group| group.field_id().to_owned())?; + .map(|controller| controller.get_grouping_field_id().to_owned())?; let field = self.delegate.get_field(&group_field_id)?; let mut write_guard = self.group_controller.write().await; if let Some(group_controller) = &mut *write_guard { @@ -1054,7 +1094,7 @@ impl DatabaseViewEditor { }); } - async fn gen_did_create_row_view_tasks(&self, row: Row) { + async fn gen_did_create_row_view_tasks(&self, preliminary_index: usize, row_detail: RowDetail) { let weak_sort_controller = Arc::downgrade(&self.sort_controller); let weak_calculations_controller = Arc::downgrade(&self.calculations_controller); af_spawn(async move { @@ -1062,12 +1102,14 @@ impl DatabaseViewEditor { sort_controller .read() .await - .did_create_row(row.id.clone()) + .did_create_row(preliminary_index, &row_detail) .await; } if let Some(calculations_controller) = weak_calculations_controller.upgrade() { - calculations_controller.did_receive_row_changed(row).await; + calculations_controller + .did_receive_row_changed(row_detail.row.clone()) + .await; } }); } diff --git a/frontend/rust-lib/flowy-database2/src/services/database_view/view_group.rs b/frontend/rust-lib/flowy-database2/src/services/database_view/view_group.rs index a2cbdaca82..9f7e3da4ff 100644 --- a/frontend/rust-lib/flowy-database2/src/services/database_view/view_group.rs +++ b/frontend/rust-lib/flowy-database2/src/services/database_view/view_group.rs @@ -1,7 +1,7 @@ use std::sync::Arc; use collab_database::fields::Field; -use collab_database::rows::RowId; +use collab_database::rows::{RowDetail, RowId}; use flowy_error::FlowyResult; use lib_infra::future::{to_fut, Fut}; @@ -9,60 +9,61 @@ use lib_infra::future::{to_fut, Fut}; use crate::entities::FieldType; use crate::services::database_view::DatabaseViewOperation; use crate::services::field::RowSingleCellData; +use crate::services::filter::FilterController; use crate::services::group::{ - find_suitable_grouping_field, make_group_controller, GroupContextDelegate, GroupController, - GroupControllerDelegate, GroupSetting, + make_group_controller, GroupContextDelegate, GroupController, GroupControllerDelegate, + GroupSetting, }; -pub async fn new_group_controller_with_field( - view_id: String, - delegate: Arc, - grouping_field: Field, -) -> FlowyResult> { - let configuration_delegate = GroupControllerDelegateImpl(delegate.clone()); - let rows = delegate.get_rows(&view_id).await; - make_group_controller(view_id, grouping_field, rows, configuration_delegate).await -} - pub async fn new_group_controller( view_id: String, delegate: Arc, + filter_controller: Arc, + grouping_field: Option, ) -> FlowyResult>> { - let fields = delegate.get_fields(&view_id, None).await; - let controller_delegate = GroupControllerDelegateImpl(delegate.clone()); - - // Read the grouping field or find a new grouping field - let mut grouping_field = controller_delegate - .get_group_setting(&view_id) - .await - .and_then(|setting| { - fields - .iter() - .find(|field| field.id == setting.field_id) - .cloned() - }); - - let layout = delegate.get_layout_for_view(&view_id); - // If the view is a board and the grouping field is empty, we need to find a new grouping field - if layout.is_board() && grouping_field.is_none() { - grouping_field = find_suitable_grouping_field(&fields); + if !delegate.get_layout_for_view(&view_id).is_board() { + return Ok(None); } - if let Some(grouping_field) = grouping_field { - let rows = delegate.get_rows(&view_id).await; - Ok(Some( - make_group_controller(view_id, grouping_field, rows, controller_delegate).await?, - )) - } else { - Ok(None) - } + let controller_delegate = GroupControllerDelegateImpl { + delegate: delegate.clone(), + filter_controller: filter_controller.clone(), + }; + + let grouping_field = match grouping_field { + Some(field) => Some(field), + None => { + let group_setting = controller_delegate.get_group_setting(&view_id).await; + + let fields = delegate.get_fields(&view_id, None).await; + + group_setting + .and_then(|setting| { + fields + .iter() + .find(|field| field.id == setting.field_id) + .cloned() + }) + .or_else(|| find_suitable_grouping_field(&fields)) + }, + }; + + let controller = match grouping_field { + Some(field) => Some(make_group_controller(&view_id, field, controller_delegate).await?), + None => None, + }; + + Ok(controller) } -pub(crate) struct GroupControllerDelegateImpl(pub Arc); +pub(crate) struct GroupControllerDelegateImpl { + delegate: Arc, + filter_controller: Arc, +} impl GroupContextDelegate for GroupControllerDelegateImpl { fn get_group_setting(&self, view_id: &str) -> Fut>> { - let mut settings = self.0.get_group_setting(view_id); + let mut settings = self.delegate.get_group_setting(view_id); to_fut(async move { if settings.is_empty() { None @@ -75,19 +76,30 @@ impl GroupContextDelegate for GroupControllerDelegateImpl { fn get_configuration_cells(&self, view_id: &str, field_id: &str) -> Fut> { let field_id = field_id.to_owned(); let view_id = view_id.to_owned(); - let delegate = self.0.clone(); + let delegate = self.delegate.clone(); to_fut(async move { get_cells_for_field(delegate, &view_id, &field_id).await }) } fn save_configuration(&self, view_id: &str, group_setting: GroupSetting) -> Fut> { - self.0.insert_group_setting(view_id, group_setting); + self.delegate.insert_group_setting(view_id, group_setting); to_fut(async move { Ok(()) }) } } impl GroupControllerDelegate for GroupControllerDelegateImpl { fn get_field(&self, field_id: &str) -> Option { - self.0.get_field(field_id) + self.delegate.get_field(field_id) + } + + fn get_all_rows(&self, view_id: &str) -> Fut>> { + let view_id = view_id.to_string(); + let delegate = self.delegate.clone(); + let filter_controller = self.filter_controller.clone(); + to_fut(async move { + let mut row_details = delegate.get_rows(&view_id).await; + filter_controller.filter_rows(&mut row_details).await; + row_details + }) } } @@ -143,3 +155,15 @@ pub(crate) async fn get_cells_for_field( vec![] } + +fn find_suitable_grouping_field(fields: &[Field]) -> Option { + let groupable_field = fields + .iter() + .find(|field| FieldType::from(field.field_type).can_be_group()); + + if let Some(field) = groupable_field { + Some(field.clone()) + } else { + fields.iter().find(|field| field.is_primary).cloned() + } +} diff --git a/frontend/rust-lib/flowy-database2/src/services/database_view/view_sort.rs b/frontend/rust-lib/flowy-database2/src/services/database_view/view_sort.rs index 8be72e7da1..0397526b66 100644 --- a/frontend/rust-lib/flowy-database2/src/services/database_view/view_sort.rs +++ b/frontend/rust-lib/flowy-database2/src/services/database_view/view_sort.rs @@ -70,6 +70,16 @@ impl SortDelegate for DatabaseViewSortDelegateImpl { }) } + fn filter_row(&self, row_detail: &RowDetail) -> Fut { + let filter_controller = self.filter_controller.clone(); + let row_detail = row_detail.clone(); + to_fut(async move { + let mut row_details = vec![Arc::new(row_detail)]; + filter_controller.filter_rows(&mut row_details).await; + !row_details.is_empty() + }) + } + fn get_field(&self, field_id: &str) -> Option { self.delegate.get_field(field_id) } diff --git a/frontend/rust-lib/flowy-database2/src/services/field/type_options/url_type_option/url_type_option_entities.rs b/frontend/rust-lib/flowy-database2/src/services/field/type_options/url_type_option/url_type_option_entities.rs index facc4bfd2e..e378990146 100644 --- a/frontend/rust-lib/flowy-database2/src/services/field/type_options/url_type_option/url_type_option_entities.rs +++ b/frontend/rust-lib/flowy-database2/src/services/field/type_options/url_type_option/url_type_option_entities.rs @@ -71,7 +71,7 @@ impl From for URLCellData { impl AsRef for URLCellData { fn as_ref(&self) -> &str { - &self.url + &self.data } } diff --git a/frontend/rust-lib/flowy-database2/src/services/filter/entities.rs b/frontend/rust-lib/flowy-database2/src/services/filter/entities.rs index 1d30c5949c..f12bc415d4 100644 --- a/frontend/rust-lib/flowy-database2/src/services/filter/entities.rs +++ b/frontend/rust-lib/flowy-database2/src/services/filter/entities.rs @@ -10,7 +10,7 @@ use flowy_error::{FlowyError, FlowyResult}; use lib_infra::box_any::BoxAny; use crate::entities::{ - CheckboxFilterPB, ChecklistFilterPB, DateFilterContentPB, DateFilterPB, FieldType, FilterType, + CheckboxFilterPB, ChecklistFilterPB, DateFilterContent, DateFilterPB, FieldType, FilterType, InsertedRowPB, NumberFilterPB, RelationFilterPB, SelectOptionFilterPB, TextFilterPB, }; use crate::services::field::SelectOptionIds; @@ -337,7 +337,7 @@ impl<'a> From<&'a Filter> for FilterMap { }, FieldType::DateTime | FieldType::LastEditedTime | FieldType::CreatedTime => { let filter = condition_and_content.cloned::()?; - let content = DateFilterContentPB { + let content = DateFilterContent { start: filter.start, end: filter.end, timestamp: filter.timestamp, diff --git a/frontend/rust-lib/flowy-database2/src/services/group/action.rs b/frontend/rust-lib/flowy-database2/src/services/group/action.rs index 291624747b..b540fb5fa3 100644 --- a/frontend/rust-lib/flowy-database2/src/services/group/action.rs +++ b/frontend/rust-lib/flowy-database2/src/services/group/action.rs @@ -79,8 +79,9 @@ pub trait GroupCustomize: Send + Sync { fn update_type_option_when_update_group( &mut self, _changeset: &GroupChangeset, - _type_option: &mut Self::GroupTypeOption, - ) { + _type_option: &Self::GroupTypeOption, + ) -> Option { + None } fn will_create_row(&self, cells: &mut Cells, field: &Field, group_id: &str); @@ -97,7 +98,7 @@ pub trait GroupCustomize: Send + Sync { /// pub trait GroupController: Send + Sync { /// Returns the id of field that is being used to group the rows - fn field_id(&self) -> &str; + fn get_grouping_field_id(&self) -> &str; /// Returns all of the groups currently managed by the controller fn get_all_groups(&self) -> Vec<&GroupData>; @@ -189,7 +190,7 @@ pub trait GroupController: Send + Sync { fn apply_group_changeset( &mut self, changesets: &[GroupChangeset], - ) -> FlowyResult<(Vec, TypeOptionData)>; + ) -> FlowyResult<(Vec, Option)>; /// Called before the row was created. fn will_create_row(&self, cells: &mut Cells, field: &Field, group_id: &str); diff --git a/frontend/rust-lib/flowy-database2/src/services/group/controller.rs b/frontend/rust-lib/flowy-database2/src/services/group/controller.rs index 799ac394c8..a918e7f7c2 100644 --- a/frontend/rust-lib/flowy-database2/src/services/group/controller.rs +++ b/frontend/rust-lib/flowy-database2/src/services/group/controller.rs @@ -4,6 +4,7 @@ use std::sync::Arc; use collab_database::fields::{Field, TypeOptionData}; use collab_database::rows::{Cells, Row, RowDetail, RowId}; use futures::executor::block_on; +use lib_infra::future::Fut; use serde::de::DeserializeOwned; use serde::Serialize; @@ -24,6 +25,8 @@ use crate::services::group::{GroupChangeset, GroupsBuilder, MoveGroupRowContext} pub trait GroupControllerDelegate: Send + Sync + 'static { fn get_field(&self, field_id: &str) -> Option; + + fn get_all_rows(&self, view_id: &str) -> Fut>>; } /// [BaseGroupController] is a generic group controller that provides customized implementations @@ -159,7 +162,7 @@ where G: GroupsBuilder, GroupTypeOption = T>, Self: GroupCustomize, { - fn field_id(&self) -> &str { + fn get_grouping_field_id(&self) -> &str { &self.grouping_field_id } @@ -228,12 +231,13 @@ where row_detail: &RowDetail, index: usize, ) -> Vec { + let mut changesets: Vec = vec![]; + let cell = match row_detail.row.cells.get(&self.grouping_field_id) { None => self.placeholder_cell(), Some(cell) => Some(cell.clone()), }; - let mut changesets: Vec = vec![]; if let Some(cell) = cell { let cell_data = ::CellData::from(&cell); @@ -245,7 +249,7 @@ where let changeset = GroupRowsNotificationPB::insert( group.id.clone(), vec![InsertedRowPB { - row_meta: row_detail.into(), + row_meta: (*row_detail).clone().into(), index: Some(index as i32), is_new: true, }], @@ -256,15 +260,15 @@ where if !suitable_group_ids.is_empty() { for group_id in suitable_group_ids.iter() { if let Some(group) = self.context.get_mut_group(group_id) { - group.add_row(row_detail.clone()); + group.add_row((*row_detail).clone()); } } } else if let Some(no_status_group) = self.context.get_mut_no_status_group() { - no_status_group.add_row(row_detail.clone()); + no_status_group.add_row((*row_detail).clone()); let changeset = GroupRowsNotificationPB::insert( no_status_group.id.clone(), vec![InsertedRowPB { - row_meta: row_detail.into(), + row_meta: (*row_detail).clone().into(), index: Some(index as i32), is_new: true, }], @@ -282,18 +286,12 @@ where row_detail: &RowDetail, field: &Field, ) -> FlowyResult { - // let cell_data = row_rev.cells.get(&self.field_id).and_then(|cell_rev| { - // let cell_data: Option

= get_type_cell_data(cell_rev, field_rev, None); - // cell_data - // }); let mut result = DidUpdateGroupRowResult { inserted_group: None, deleted_group: None, row_changesets: vec![], }; - if let Some(cell_data) = get_cell_data_from_row::

(Some(&row_detail.row), field) { - let _old_row = old_row_detail.as_ref(); let old_cell_data = get_cell_data_from_row::

(old_row_detail.as_ref().map(|detail| &detail.row), field); if let Ok((insert, delete)) = self.create_or_delete_group_when_cell_changed( @@ -376,7 +374,7 @@ where } fn delete_group(&mut self, group_id: &str) -> FlowyResult<(Vec, Option)> { - let group = if group_id != self.field_id() { + let group = if group_id != self.get_grouping_field_id() { self.get_group(group_id) } else { None @@ -399,17 +397,26 @@ where fn apply_group_changeset( &mut self, changeset: &[GroupChangeset], - ) -> FlowyResult<(Vec, TypeOptionData)> { + ) -> FlowyResult<(Vec, Option)> { + // update group visibility for group_changeset in changeset.iter() { self.context.update_group(group_changeset)?; } - let mut type_option = self.get_grouping_field_type_option().ok_or_else(|| { + // update group name + let type_option = self.get_grouping_field_type_option().ok_or_else(|| { FlowyError::internal().with_context("Failed to get grouping field type option") })?; + let mut updated_type_option = None; + for group_changeset in changeset.iter() { - self.update_type_option_when_update_group(group_changeset, &mut type_option); + if let Some(type_option) = + self.update_type_option_when_update_group(group_changeset, &type_option) + { + updated_type_option = Some(type_option); + break; + } } let updated_groups = changeset @@ -421,7 +428,10 @@ where }) .collect::>(); - Ok((updated_groups, type_option.into())) + Ok(( + updated_groups, + updated_type_option.map(|type_option| type_option.into()), + )) } fn will_create_row(&self, cells: &mut Cells, field: &Field, group_id: &str) { diff --git a/frontend/rust-lib/flowy-database2/src/services/group/controller_impls/default_controller.rs b/frontend/rust-lib/flowy-database2/src/services/group/controller_impls/default_controller.rs index a921c48f2c..bcfd48bc09 100644 --- a/frontend/rust-lib/flowy-database2/src/services/group/controller_impls/default_controller.rs +++ b/frontend/rust-lib/flowy-database2/src/services/group/controller_impls/default_controller.rs @@ -1,4 +1,5 @@ -use async_trait::async_trait; +use std::sync::Arc; + use collab_database::fields::{Field, TypeOptionData}; use collab_database::rows::{Cells, Row, RowDetail, RowId}; @@ -10,7 +11,9 @@ use crate::entities::{ use crate::services::group::action::{ DidMoveGroupRowResult, DidUpdateGroupRowResult, GroupController, }; -use crate::services::group::{GroupChangeset, GroupData, MoveGroupRowContext}; +use crate::services::group::{ + GroupChangeset, GroupControllerDelegate, GroupData, MoveGroupRowContext, +}; /// A [DefaultGroupController] is used to handle the group actions for the [FieldType] that doesn't /// implement its own group controller. The default group controller only contains one group, which @@ -19,23 +22,24 @@ use crate::services::group::{GroupChangeset, GroupData, MoveGroupRowContext}; pub struct DefaultGroupController { pub field_id: String, pub group: GroupData, + pub delegate: Arc, } const DEFAULT_GROUP_CONTROLLER: &str = "DefaultGroupController"; impl DefaultGroupController { - pub fn new(field: &Field) -> Self { + pub fn new(field: &Field, delegate: Arc) -> Self { let group = GroupData::new(DEFAULT_GROUP_CONTROLLER.to_owned(), field.id.clone(), true); Self { field_id: field.id.clone(), group, + delegate, } } } -#[async_trait] impl GroupController for DefaultGroupController { - fn field_id(&self) -> &str { + fn get_grouping_field_id(&self) -> &str { &self.field_id } @@ -70,12 +74,12 @@ impl GroupController for DefaultGroupController { row_detail: &RowDetail, index: usize, ) -> Vec { - self.group.add_row(row_detail.clone()); + self.group.add_row((*row_detail).clone()); vec![GroupRowsNotificationPB::insert( self.group.id.clone(), vec![InsertedRowPB { - row_meta: row_detail.into(), + row_meta: (*row_detail).clone().into(), index: Some(index as i32), is_new: true, }], @@ -128,8 +132,8 @@ impl GroupController for DefaultGroupController { fn apply_group_changeset( &mut self, _changeset: &[GroupChangeset], - ) -> FlowyResult<(Vec, TypeOptionData)> { - Ok((Vec::new(), TypeOptionData::default())) + ) -> FlowyResult<(Vec, Option)> { + Ok((Vec::new(), None)) } fn will_create_row(&self, _cells: &mut Cells, _field: &Field, _group_id: &str) {} diff --git a/frontend/rust-lib/flowy-database2/src/services/group/controller_impls/select_option_controller/multi_select_controller.rs b/frontend/rust-lib/flowy-database2/src/services/group/controller_impls/select_option_controller/multi_select_controller.rs index af160a86ea..cae19109f6 100644 --- a/frontend/rust-lib/flowy-database2/src/services/group/controller_impls/select_option_controller/multi_select_controller.rs +++ b/frontend/rust-lib/flowy-database2/src/services/group/controller_impls/select_option_controller/multi_select_controller.rs @@ -124,10 +124,11 @@ impl GroupCustomize for MultiSelectGroupController { fn update_type_option_when_update_group( &mut self, changeset: &GroupChangeset, - type_option: &mut Self::GroupTypeOption, - ) { + type_option: &Self::GroupTypeOption, + ) -> Option { if let Some(name) = &changeset.name { let mut new_type_option = type_option.clone(); + let select_option = type_option .options .iter() @@ -139,6 +140,10 @@ impl GroupCustomize for MultiSelectGroupController { ..select_option.to_owned() }; new_type_option.insert_option(new_select_option); + + Some(new_type_option) + } else { + None } } diff --git a/frontend/rust-lib/flowy-database2/src/services/group/controller_impls/select_option_controller/single_select_controller.rs b/frontend/rust-lib/flowy-database2/src/services/group/controller_impls/select_option_controller/single_select_controller.rs index fc23364f4d..d26ef50b70 100644 --- a/frontend/rust-lib/flowy-database2/src/services/group/controller_impls/select_option_controller/single_select_controller.rs +++ b/frontend/rust-lib/flowy-database2/src/services/group/controller_impls/select_option_controller/single_select_controller.rs @@ -126,10 +126,11 @@ impl GroupCustomize for SingleSelectGroupController { fn update_type_option_when_update_group( &mut self, changeset: &GroupChangeset, - type_option: &mut Self::GroupTypeOption, - ) { + type_option: &Self::GroupTypeOption, + ) -> Option { if let Some(name) = &changeset.name { let mut new_type_option = type_option.clone(); + let select_option = type_option .options .iter() @@ -141,6 +142,10 @@ impl GroupCustomize for SingleSelectGroupController { ..select_option.to_owned() }; new_type_option.insert_option(new_select_option); + + Some(new_type_option) + } else { + None } } diff --git a/frontend/rust-lib/flowy-database2/src/services/group/group_builder.rs b/frontend/rust-lib/flowy-database2/src/services/group/group_builder.rs index 7c11851528..8eb677ed26 100644 --- a/frontend/rust-lib/flowy-database2/src/services/group/group_builder.rs +++ b/frontend/rust-lib/flowy-database2/src/services/group/group_builder.rs @@ -86,9 +86,8 @@ impl RowChangeset { err )] pub async fn make_group_controller( - view_id: String, + view_id: &str, grouping_field: Field, - row_details: Vec>, delegate: D, ) -> FlowyResult> where @@ -102,68 +101,81 @@ where match grouping_field_type { FieldType::SingleSelect => { - let configuration = - SingleSelectGroupControllerContext::new(view_id, grouping_field.clone(), delegate.clone()) - .await?; + let configuration = SingleSelectGroupControllerContext::new( + view_id.to_string(), + grouping_field.clone(), + delegate.clone(), + ) + .await?; let controller = - SingleSelectGroupController::new(&grouping_field, configuration, delegate).await?; + SingleSelectGroupController::new(&grouping_field, configuration, delegate.clone()).await?; group_controller = Box::new(controller); }, FieldType::MultiSelect => { - let configuration = - MultiSelectGroupControllerContext::new(view_id, grouping_field.clone(), delegate.clone()) - .await?; + let configuration = MultiSelectGroupControllerContext::new( + view_id.to_string(), + grouping_field.clone(), + delegate.clone(), + ) + .await?; let controller = - MultiSelectGroupController::new(&grouping_field, configuration, delegate).await?; + MultiSelectGroupController::new(&grouping_field, configuration, delegate.clone()).await?; group_controller = Box::new(controller); }, FieldType::Checkbox => { - let configuration = - CheckboxGroupControllerContext::new(view_id, grouping_field.clone(), delegate.clone()) - .await?; + let configuration = CheckboxGroupControllerContext::new( + view_id.to_string(), + grouping_field.clone(), + delegate.clone(), + ) + .await?; let controller = - CheckboxGroupController::new(&grouping_field, configuration, delegate).await?; + CheckboxGroupController::new(&grouping_field, configuration, delegate.clone()).await?; group_controller = Box::new(controller); }, FieldType::URL => { - let configuration = - URLGroupControllerContext::new(view_id, grouping_field.clone(), delegate.clone()).await?; - let controller = URLGroupController::new(&grouping_field, configuration, delegate).await?; + let configuration = URLGroupControllerContext::new( + view_id.to_string(), + grouping_field.clone(), + delegate.clone(), + ) + .await?; + let controller = + URLGroupController::new(&grouping_field, configuration, delegate.clone()).await?; group_controller = Box::new(controller); }, FieldType::DateTime => { - let configuration = - DateGroupControllerContext::new(view_id, grouping_field.clone(), delegate.clone()).await?; - let controller = DateGroupController::new(&grouping_field, configuration, delegate).await?; + let configuration = DateGroupControllerContext::new( + view_id.to_string(), + grouping_field.clone(), + delegate.clone(), + ) + .await?; + let controller = + DateGroupController::new(&grouping_field, configuration, delegate.clone()).await?; group_controller = Box::new(controller); }, _ => { - group_controller = Box::new(DefaultGroupController::new(&grouping_field)); + group_controller = Box::new(DefaultGroupController::new( + &grouping_field, + delegate.clone(), + )); }, } // Separates the rows into different groups + let row_details = delegate.get_all_rows(view_id).await; + let rows = row_details .iter() .map(|row| row.as_ref()) .collect::>(); + group_controller.fill_groups(rows.as_slice(), &grouping_field)?; + Ok(group_controller) } -#[tracing::instrument(level = "debug", skip_all)] -pub fn find_suitable_grouping_field(fields: &[Field]) -> Option { - let groupable_field = fields - .iter() - .find(|field| FieldType::from(field.field_type).can_be_group()); - - if let Some(field) = groupable_field { - Some(field.clone()) - } else { - fields.iter().find(|field| field.is_primary).cloned() - } -} - /// Returns a `default` group configuration for the [Field] /// /// # Arguments diff --git a/frontend/rust-lib/flowy-database2/src/services/sort/controller.rs b/frontend/rust-lib/flowy-database2/src/services/sort/controller.rs index b42ac89b39..4a9f09e63c 100644 --- a/frontend/rust-lib/flowy-database2/src/services/sort/controller.rs +++ b/frontend/rust-lib/flowy-database2/src/services/sort/controller.rs @@ -21,14 +21,14 @@ use crate::services::field::{ default_order, TimestampCellData, TimestampCellDataWrapper, TypeOptionCellExt, }; use crate::services::sort::{ - InsertSortedRowResult, ReorderAllRowsResult, ReorderSingleRowResult, Sort, SortChangeset, - SortCondition, + InsertRowResult, ReorderAllRowsResult, ReorderSingleRowResult, Sort, SortChangeset, SortCondition, }; pub trait SortDelegate: Send + Sync { fn get_sort(&self, view_id: &str, sort_id: &str) -> Fut>>; /// Returns all the rows after applying grid's filter fn get_rows(&self, view_id: &str) -> Fut>>; + fn filter_row(&self, row_detail: &RowDetail) -> Fut; fn get_field(&self, field_id: &str) -> Option; fn get_fields(&self, view_id: &str, field_ids: Option>) -> Fut>; } @@ -94,14 +94,27 @@ impl SortController { } } - pub async fn did_create_row(&self, row_id: RowId) { + pub async fn did_create_row(&self, preliminary_index: usize, row_detail: &RowDetail) { + if !self.delegate.filter_row(row_detail).await { + return; + } + if !self.sorts.is_empty() { self .gen_task( - SortEvent::NewRowInserted(row_id), + SortEvent::NewRowInserted(row_detail.clone()), QualityOfService::Background, ) .await; + } else { + let result = InsertRowResult { + view_id: self.view_id.clone(), + row: row_detail.clone(), + index: preliminary_index, + }; + let _ = self + .notifier + .send(DatabaseViewChanged::InsertRowNotification(result)); } } @@ -162,22 +175,20 @@ impl SortController { _ => tracing::trace!("The row index cache is outdated"), } }, - SortEvent::NewRowInserted(row_id) => { + SortEvent::NewRowInserted(row_detail) => { self.sort_rows(&mut row_details).await; - let row_index = self.row_index_cache.get(&row_id).cloned(); + let row_index = self.row_index_cache.get(&row_detail.row.id).cloned(); match row_index { Some(row_index) => { - let notification = InsertSortedRowResult { - row_id: row_id.clone(), + let notification = InsertRowResult { view_id: self.view_id.clone(), + row: row_detail.clone(), index: row_index, }; - self.row_index_cache.insert(row_id, row_index); + self.row_index_cache.insert(row_detail.row.id, row_index); let _ = self .notifier - .send(DatabaseViewChanged::InsertSortedRowNotification( - notification, - )); + .send(DatabaseViewChanged::InsertRowNotification(notification)); }, _ => tracing::trace!("The row index cache is outdated"), } @@ -353,7 +364,7 @@ fn cmp_cell( enum SortEvent { SortDidChanged, RowDidChanged(RowId), - NewRowInserted(RowId), + NewRowInserted(RowDetail), DeleteAllSorts, } diff --git a/frontend/rust-lib/flowy-database2/src/services/sort/entities.rs b/frontend/rust-lib/flowy-database2/src/services/sort/entities.rs index 66bfea4f3f..9f9d37d4fb 100644 --- a/frontend/rust-lib/flowy-database2/src/services/sort/entities.rs +++ b/frontend/rust-lib/flowy-database2/src/services/sort/entities.rs @@ -2,7 +2,7 @@ use std::cmp::Ordering; use anyhow::bail; use collab::core::any_map::AnyMapExtension; -use collab_database::rows::RowId; +use collab_database::rows::{RowDetail, RowId}; use collab_database::views::{SortMap, SortMapBuilder}; #[derive(Debug, Clone)] @@ -107,9 +107,9 @@ pub struct ReorderSingleRowResult { } #[derive(Clone)] -pub struct InsertSortedRowResult { +pub struct InsertRowResult { pub view_id: String, - pub row_id: RowId, + pub row: RowDetail, pub index: usize, } diff --git a/frontend/rust-lib/flowy-database2/tests/database/sort_test/script.rs b/frontend/rust-lib/flowy-database2/tests/database/sort_test/script.rs index 6ef3506056..cfa9859075 100644 --- a/frontend/rust-lib/flowy-database2/tests/database/sort_test/script.rs +++ b/frontend/rust-lib/flowy-database2/tests/database/sort_test/script.rs @@ -212,7 +212,7 @@ async fn assert_sort_changed( old_row_orders.insert(changed.new_index, old); assert_eq!(old_row_orders, new_row_orders); }, - DatabaseViewChanged::InsertSortedRowNotification(_changed) => {}, + DatabaseViewChanged::InsertRowNotification(_changed) => {}, _ => {}, } })