chore: fix bugs when switch group field

This commit is contained in:
appflowy 2022-09-04 15:33:07 +08:00
parent 54d6f3709e
commit 4f8e012d54
51 changed files with 297 additions and 162 deletions

View File

@ -1,6 +1,6 @@
import 'dart:async';
import 'package:app_flowy/plugins/grid/application/block/block_cache.dart';
import 'package:app_flowy/plugins/grid/application/field/field_cache.dart';
import 'package:app_flowy/plugins/grid/application/field/field_controller.dart';
import 'package:app_flowy/plugins/grid/application/row/row_cache.dart';
import 'package:app_flowy/plugins/grid/application/row/row_service.dart';
import 'package:appflowy_board/appflowy_board.dart';
@ -204,16 +204,20 @@ class BoardBloc extends Bloc<BoardEvent, BoardState> {
}
},
didLoadGroups: (groups) {
if (isClosed) return;
initializeGroups(groups);
add(BoardEvent.didReceiveGroups(groups));
},
onDeletedGroup: (groupIds) {
if (isClosed) return;
//
},
onInsertedGroup: (insertedGroups) {
if (isClosed) return;
//
},
onUpdatedGroup: (updatedGroups) {
if (isClosed) return;
for (final group in updatedGroups) {
final columnController =
boardController.getColumnController(group.groupId);
@ -224,6 +228,8 @@ class BoardBloc extends Bloc<BoardEvent, BoardState> {
Log.error(err);
},
onResetGroups: (groups) {
if (isClosed) return;
initializeGroups(groups);
add(BoardEvent.didReceiveGroups(groups));
},

View File

@ -1,7 +1,7 @@
import 'dart:collection';
import 'package:app_flowy/plugins/grid/application/block/block_cache.dart';
import 'package:app_flowy/plugins/grid/application/field/field_cache.dart';
import 'package:app_flowy/plugins/grid/application/field/field_controller.dart';
import 'package:app_flowy/plugins/grid/application/grid_service.dart';
import 'package:app_flowy/plugins/grid/application/row/row_cache.dart';
import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';

View File

@ -1,5 +1,5 @@
import 'package:app_flowy/plugins/grid/application/cell/cell_service/cell_service.dart';
import 'package:app_flowy/plugins/grid/application/field/field_cache.dart';
import 'package:app_flowy/plugins/grid/application/field/field_controller.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/date_type_option_entities.pb.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart';

View File

@ -1,7 +1,7 @@
import 'package:app_flowy/plugins/board/presentation/card/card_cell_builder.dart';
import 'package:app_flowy/plugins/grid/application/cell/cell_service/cell_service.dart';
import 'package:app_flowy/plugins/grid/application/cell/cell_service/cell_field_notifier.dart';
import 'package:app_flowy/plugins/grid/application/field/field_cache.dart';
import 'package:app_flowy/plugins/grid/application/field/field_controller.dart';
import 'package:app_flowy/plugins/grid/application/row/row_cache.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/block_entities.pb.dart';
import 'package:flutter/foundation.dart';

View File

@ -5,7 +5,7 @@ import 'dart:collection';
import 'package:app_flowy/generated/locale_keys.g.dart';
import 'package:app_flowy/plugins/board/application/card/card_data_controller.dart';
import 'package:app_flowy/plugins/grid/application/row/row_cache.dart';
import 'package:app_flowy/plugins/grid/application/field/field_cache.dart';
import 'package:app_flowy/plugins/grid/application/field/field_controller.dart';
import 'package:app_flowy/plugins/grid/application/row/row_data_controller.dart';
import 'package:app_flowy/plugins/grid/presentation/widgets/cell/cell_builder.dart';
import 'package:app_flowy/plugins/grid/presentation/widgets/row/row_detail.dart';
@ -82,8 +82,7 @@ class _BoardContentState extends State<BoardContent> {
return BlocListener<BoardBloc, BoardState>(
listener: (context, state) => _handleEditState(state, context),
child: BlocBuilder<BoardBloc, BoardState>(
buildWhen: (previous, current) =>
previous.groupIds.length != current.groupIds.length,
buildWhen: (previous, current) => previous.groupIds != current.groupIds,
builder: (context, state) {
final theme = context.read<AppTheme>();
return Container(
@ -95,6 +94,7 @@ class _BoardContentState extends State<BoardContent> {
const _ToolbarBlocAdaptor(),
Expanded(
child: AFBoard(
key: UniqueKey(),
scrollManager: scrollManager,
scrollController: scrollController,
dataController: context.read<BoardBloc>().boardController,

View File

@ -1,6 +1,6 @@
import 'package:app_flowy/generated/locale_keys.g.dart';
import 'package:app_flowy/plugins/board/application/toolbar/board_setting_bloc.dart';
import 'package:app_flowy/plugins/grid/application/field/field_cache.dart';
import 'package:app_flowy/plugins/grid/application/field/field_controller.dart';
import 'package:app_flowy/plugins/grid/presentation/layout/sizes.dart';
import 'package:app_flowy/plugins/grid/presentation/widgets/toolbar/grid_group.dart';
import 'package:app_flowy/plugins/grid/presentation/widgets/toolbar/grid_property.dart';

View File

@ -1,4 +1,4 @@
import 'package:app_flowy/plugins/grid/application/field/field_cache.dart';
import 'package:app_flowy/plugins/grid/application/field/field_controller.dart';
import 'package:flowy_infra/image.dart';
import 'package:flowy_infra/theme.dart';
import 'package:flowy_infra_ui/style_widget/icon_button.dart';

View File

@ -2,7 +2,7 @@ import 'dart:async';
import 'package:flowy_sdk/log.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/block_entities.pb.dart';
import '../field/field_cache.dart';
import '../field/field_controller.dart';
import '../row/row_cache.dart';
import 'block_listener.dart';

View File

@ -16,7 +16,7 @@ import 'package:app_flowy/plugins/grid/application/cell/cell_listener.dart';
import 'package:app_flowy/plugins/grid/application/field/field_service.dart';
import 'dart:convert' show utf8;
import '../../field/field_cache.dart';
import '../../field/field_controller.dart';
import '../../field/type_option/type_option_context.dart';
import 'cell_field_notifier.dart';
part 'cell_service.freezed.dart';

View File

@ -1,4 +1,4 @@
import 'package:app_flowy/plugins/grid/application/field/field_cache.dart';
import 'package:app_flowy/plugins/grid/application/field/field_controller.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/date_type_option_entities.pb.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart';

View File

@ -2,10 +2,12 @@ import 'dart:collection';
import 'package:app_flowy/plugins/grid/application/field/grid_listener.dart';
import 'package:app_flowy/plugins/grid/application/grid_service.dart';
import 'package:app_flowy/plugins/grid/application/setting/setting_listener.dart';
import 'package:app_flowy/plugins/grid/application/setting/setting_service.dart';
import 'package:dartz/dartz.dart';
import 'package:flowy_sdk/log.dart';
import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/setting_entities.pb.dart';
import 'package:flutter/foundation.dart';
import '../row/row_cache.dart';
@ -35,11 +37,17 @@ class GridFieldController {
final Map<OnChangeset, OnChangeset> _changesetCallbackMap = {};
_GridFieldNotifier? _fieldNotifier = _GridFieldNotifier();
List<String> _groupFieldIds = [];
final GridFFIService _gridFFIService;
final SettingFFIService _settingFFIService;
List<GridFieldContext> get fieldContexts =>
[..._fieldNotifier?.fieldContexts ?? []];
GridFieldController({required this.gridId})
: _fieldListener = GridFieldsListener(gridId: gridId),
_gridFFIService = GridFFIService(gridId: gridId),
_settingFFIService = SettingFFIService(viewId: gridId),
_settingListener = SettingListener(gridId: gridId) {
//Listen on field's changes
_fieldListener.start(onFieldsChanged: (result) {
@ -59,24 +67,38 @@ class GridFieldController {
//Listen on setting changes
_settingListener.start(onSettingUpdated: (result) {
result.fold(
(setting) {
final List<String> groupFieldIds = setting.groupConfigurations.items
.map((item) => item.groupFieldId)
.toList();
bool isChanged = false;
if (_fieldNotifier != null) {
for (var field in _fieldNotifier!.fieldContexts) {
if (groupFieldIds.contains(field.id)) {
field._isGroupField = true;
isChanged = true;
}
}
if (isChanged) _fieldNotifier?.notify();
}
},
(setting) => _updateFieldsWhenSettingChanged(setting),
(r) => Log.error(r),
);
});
_settingFFIService.getSetting().then((result) {
result.fold(
(setting) => _updateFieldsWhenSettingChanged(setting),
(err) => Log.error(err),
);
});
}
void _updateFieldsWhenSettingChanged(GridSettingPB setting) {
_groupFieldIds = setting.groupConfigurations.items
.map((item) => item.groupFieldId)
.toList();
_updateFieldContexts();
}
void _updateFieldContexts() {
if (_fieldNotifier != null) {
for (var field in _fieldNotifier!.fieldContexts) {
if (_groupFieldIds.contains(field.id)) {
field._isGroupField = true;
} else {
field._isGroupField = false;
}
}
_fieldNotifier?.notify();
}
}
Future<void> dispose() async {
@ -85,9 +107,6 @@ class GridFieldController {
_fieldNotifier = null;
}
List<GridFieldContext> get fieldContexts =>
[..._fieldNotifier?.fieldContexts ?? []];
Future<Either<Unit, FlowyError>> loadFields(
{required List<FieldIdPB> fieldIds}) async {
final result = await _gridFFIService.getFields(fieldIds: fieldIds);
@ -97,6 +116,7 @@ class GridFieldController {
_fieldNotifier?.fieldContexts = newFields.items
.map((field) => GridFieldContext(field: field))
.toList();
_updateFieldContexts();
return left(unit);
},
(err) => right(err),

View File

@ -6,7 +6,6 @@ import 'package:flowy_sdk/protobuf/flowy-grid/grid_entities.pb.dart';
import 'package:flutter/foundation.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'field_cache.dart';
part 'field_service.freezed.dart';
/// FieldService consists of lots of event functions. We define the events in the backend(Rust),

View File

@ -1,4 +1,3 @@
import 'package:app_flowy/plugins/grid/application/field/field_cache.dart';
import 'package:flowy_sdk/dispatch/dispatch.dart';
import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/checkbox_type_option.pb.dart';

View File

@ -1,4 +1,4 @@
import 'package:app_flowy/plugins/grid/application/field/field_cache.dart';
import 'package:app_flowy/plugins/grid/application/field/field_controller.dart';
import 'package:flowy_infra/notifier.dart';
import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart';

View File

@ -7,7 +7,7 @@ import 'package:flowy_sdk/protobuf/flowy-grid/protobuf.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'block/block_cache.dart';
import 'field/field_cache.dart';
import 'field/field_controller.dart';
import 'grid_data_controller.dart';
import 'row/row_cache.dart';
import 'dart:collection';

View File

@ -8,7 +8,7 @@ import 'package:flowy_sdk/protobuf/flowy-grid/grid_entities.pb.dart';
import 'dart:async';
import 'package:dartz/dartz.dart';
import 'block/block_cache.dart';
import 'field/field_cache.dart';
import 'field/field_controller.dart';
import 'prelude.dart';
import 'row/row_cache.dart';

View File

@ -4,7 +4,7 @@ import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'dart:async';
import 'field/field_cache.dart';
import 'field/field_controller.dart';
part 'grid_header_bloc.freezed.dart';

View File

@ -1,6 +1,6 @@
import 'dart:collection';
import 'package:app_flowy/plugins/grid/application/cell/cell_service/cell_service.dart';
import 'package:app_flowy/plugins/grid/application/field/field_cache.dart';
import 'package:app_flowy/plugins/grid/application/field/field_controller.dart';
import 'package:equatable/equatable.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart';

View File

@ -1,6 +1,6 @@
import 'dart:collection';
import 'package:app_flowy/plugins/grid/application/cell/cell_service/cell_service.dart';
import 'package:app_flowy/plugins/grid/application/field/field_cache.dart';
import 'package:app_flowy/plugins/grid/application/field/field_controller.dart';
import 'package:flowy_sdk/dispatch/dispatch.dart';
import 'package:flowy_sdk/log.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/block_entities.pb.dart';

View File

@ -2,7 +2,7 @@ import 'package:app_flowy/plugins/grid/application/cell/cell_service/cell_field_
import 'package:flutter/material.dart';
import '../../presentation/widgets/cell/cell_builder.dart';
import '../cell/cell_service/cell_service.dart';
import '../field/field_cache.dart';
import '../field/field_controller.dart';
import 'row_cache.dart';
typedef OnRowChanged = void Function(GridCellMap, RowsChangedReason);

View File

@ -1,46 +1,38 @@
import 'package:app_flowy/plugins/grid/application/field/field_service.dart';
import 'package:flowy_sdk/log.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'dart:async';
import '../field/field_cache.dart';
import 'setting_controller.dart';
import '../field/field_controller.dart';
import 'setting_service.dart';
part 'group_bloc.freezed.dart';
class GridGroupBloc extends Bloc<GridGroupEvent, GridGroupState> {
final GridFieldController _fieldController;
final SettingController _settingController;
final SettingFFIService _settingFFIService;
Function(List<GridFieldContext>)? _onFieldsFn;
GridGroupBloc(
{required String viewId, required GridFieldController fieldController})
: _fieldController = fieldController,
_settingController = SettingController(viewId: viewId),
_settingFFIService = SettingFFIService(viewId: viewId),
super(GridGroupState.initial(viewId, fieldController.fieldContexts)) {
on<GridGroupEvent>(
(event, emit) async {
await event.map(
initial: (_Initial value) {
event.when(
initial: () {
_startListening();
},
setFieldVisibility: (_SetFieldVisibility value) async {
final fieldService =
FieldService(gridId: viewId, fieldId: value.fieldId);
final result =
await fieldService.updateField(visibility: value.visibility);
result.fold(
(l) => null,
(err) => Log.error(err),
didReceiveFieldUpdate: (fieldContexts) {
emit(state.copyWith(fieldContexts: fieldContexts));
},
setGroupByField: (String fieldId, FieldType fieldType) {
_settingFFIService.groupByField(
fieldId: fieldId,
fieldType: fieldType,
);
},
didReceiveFieldUpdate: (_DidReceiveFieldUpdate value) {
emit(state.copyWith(fieldContexts: value.fields));
},
moveField: (_MoveField value) {
//
},
);
},
);
@ -56,28 +48,24 @@ class GridGroupBloc extends Bloc<GridGroupEvent, GridGroupState> {
}
void _startListening() {
_onFieldsFn = (fields) => add(GridGroupEvent.didReceiveFieldUpdate(fields));
_onFieldsFn = (fieldContexts) =>
add(GridGroupEvent.didReceiveFieldUpdate(fieldContexts));
_fieldController.addListener(
onFields: _onFieldsFn,
listenWhen: () => !isClosed,
);
_settingController.startListeing(
onSettingUpdated: (setting) {},
onError: (err) {},
);
}
}
@freezed
class GridGroupEvent with _$GridGroupEvent {
const factory GridGroupEvent.initial() = _Initial;
const factory GridGroupEvent.setFieldVisibility(
String fieldId, bool visibility) = _SetFieldVisibility;
const factory GridGroupEvent.setGroupByField(
String fieldId,
FieldType fieldType,
) = _GroupByField;
const factory GridGroupEvent.didReceiveFieldUpdate(
List<GridFieldContext> fields) = _DidReceiveFieldUpdate;
const factory GridGroupEvent.moveField(int fromIndex, int toIndex) =
_MoveField;
}
@freezed

View File

@ -4,7 +4,7 @@ import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'dart:async';
import '../field/field_cache.dart';
import '../field/field_controller.dart';
part 'property_bloc.freezed.dart';

View File

@ -1,7 +1,9 @@
import 'package:dartz/dartz.dart';
import 'package:flowy_sdk/dispatch/dispatch.dart';
import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/grid_entities.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/group.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/setting_entities.pb.dart';
class SettingFFIService {
@ -13,4 +15,18 @@ class SettingFFIService {
final payload = GridIdPB.create()..value = viewId;
return GridEventGetGridSetting(payload).send();
}
Future<Either<Unit, FlowyError>> groupByField({
required String fieldId,
required FieldType fieldType,
}) {
final insertGroupPayload = InsertGroupPayloadPB.create()
..fieldId = fieldId
..fieldType = fieldType;
final payload = GridSettingChangesetPayloadPB.create()
..gridId = viewId
..insertGroup = insertGroupPayload;
return GridEventUpdateGridSetting(payload).send();
}
}

View File

@ -1,4 +1,4 @@
import 'package:app_flowy/plugins/grid/application/field/field_cache.dart';
import 'package:app_flowy/plugins/grid/application/field/field_controller.dart';
import 'package:app_flowy/plugins/grid/application/row/row_data_controller.dart';
import 'package:app_flowy/startup/startup.dart';
import 'package:app_flowy/plugins/grid/application/grid_bloc.dart';

View File

@ -1,4 +1,4 @@
import 'package:app_flowy/plugins/grid/application/field/field_cache.dart';
import 'package:app_flowy/plugins/grid/application/field/field_controller.dart';
import 'sizes.dart';
class GridLayout {

View File

@ -1,4 +1,3 @@
import 'package:app_flowy/plugins/grid/application/field/field_cache.dart';
import 'package:app_flowy/plugins/grid/application/field/field_cell_bloc.dart';
import 'package:app_flowy/plugins/grid/application/field/field_service.dart';
import 'package:app_flowy/plugins/grid/application/field/type_option/type_option_context.dart';

View File

@ -1,5 +1,5 @@
import 'package:app_flowy/generated/locale_keys.g.dart';
import 'package:app_flowy/plugins/grid/application/field/field_cache.dart';
import 'package:app_flowy/plugins/grid/application/field/field_controller.dart';
import 'package:app_flowy/plugins/grid/application/field/type_option/type_option_context.dart';
import 'package:app_flowy/startup/startup.dart';
import 'package:app_flowy/plugins/grid/application/prelude.dart';

View File

@ -1,6 +1,6 @@
import 'dart:typed_data';
import 'package:app_flowy/plugins/grid/application/field/field_cache.dart';
import 'package:app_flowy/plugins/grid/application/field/field_controller.dart';
import 'package:app_flowy/plugins/grid/application/field/type_option/type_option_context.dart';
import 'package:app_flowy/plugins/grid/application/field/type_option/type_option_data_controller.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/checkbox_type_option.pb.dart';

View File

@ -215,7 +215,7 @@ class _RowDetailCell extends StatelessWidget {
SizedBox(
width: 150,
child: FieldCellButton(
field: cellId.fieldContext.fieldContext,
field: cellId.fieldContext.field,
onTap: () => _showFieldEditor(context),
),
),
@ -233,7 +233,7 @@ class _RowDetailCell extends StatelessWidget {
fieldName: cellId.fieldContext.name,
typeOptionLoader: FieldTypeOptionLoader(
gridId: cellId.gridId,
field: cellId.fieldContext.fieldContext,
field: cellId.fieldContext.field,
),
).show(context);
}

View File

@ -1,8 +1,9 @@
import 'package:app_flowy/plugins/grid/application/field/field_cache.dart';
import 'package:app_flowy/plugins/grid/application/field/field_controller.dart';
import 'package:app_flowy/plugins/grid/presentation/layout/sizes.dart';
import 'package:app_flowy/plugins/grid/presentation/widgets/header/field_type_extension.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/button.dart';
import 'package:flowy_infra_ui/style_widget/text.dart';
import 'package:flowy_infra_ui/widget/spacing.dart';
@ -29,10 +30,10 @@ class GridGroupList extends StatelessWidget {
)..add(const GridGroupEvent.initial()),
child: BlocBuilder<GridGroupBloc, GridGroupState>(
builder: (context, state) {
final cells = state.fieldContexts.map((field) {
final cells = state.fieldContexts.map((fieldContext) {
return _GridGroupCell(
fieldContext: field,
key: ValueKey(field.id),
fieldContext: fieldContext,
key: ValueKey(fieldContext.id),
);
}).toList();
@ -51,7 +52,22 @@ class GridGroupList extends StatelessWidget {
);
}
void show(BuildContext context) {}
void show(BuildContext context) {
FlowyOverlay.of(context).insertWithAnchor(
widget: OverlayContainer(
constraints: BoxConstraints.loose(const Size(260, 400)),
child: this,
),
identifier: identifier(),
anchorContext: context,
anchorDirection: AnchorDirection.bottomRight,
style: FlowyOverlayStyle(blur: false),
);
}
static String identifier() {
return (GridGroupList).toString();
}
}
class _GridGroupCell extends StatelessWidget {
@ -61,23 +77,34 @@ class _GridGroupCell extends StatelessWidget {
@override
Widget build(BuildContext context) {
final theme = context.watch<AppTheme>();
final theme = context.read<AppTheme>();
// final checkmark = field.visibility
// ? svgWidget('home/show', color: theme.iconColor)
// : svgWidget('home/hide', color: theme.iconColor);
Widget? rightIcon;
if (fieldContext.isGroupField) {
rightIcon = Padding(
padding: const EdgeInsets.all(2.0),
child: svgWidget("grid/checkmark"),
);
}
// Padding(
// padding: const EdgeInsets.only(right: 6),
// child: svgWidget("grid/checkmark"),
// ),
return FlowyButton(
text: FlowyText.medium(fieldContext.name, fontSize: 12),
hoverColor: theme.hover,
leftIcon:
svgWidget(fieldContext.fieldType.iconName(), color: theme.iconColor),
onTap: () {},
return SizedBox(
height: GridSize.typeOptionItemHeight,
child: FlowyButton(
text: FlowyText.medium(fieldContext.name, fontSize: 12),
hoverColor: theme.hover,
leftIcon: svgWidget(fieldContext.fieldType.iconName(),
color: theme.iconColor),
rightIcon: rightIcon,
onTap: () {
context.read<GridGroupBloc>().add(
GridGroupEvent.setGroupByField(
fieldContext.id,
fieldContext.fieldType,
),
);
FlowyOverlay.of(context).remove(GridGroupList.identifier());
},
),
);
}
}

View File

@ -13,7 +13,7 @@ import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:styled_widget/styled_widget.dart';
import '../../../application/field/field_cache.dart';
import '../../../application/field/field_controller.dart';
import '../../layout/sizes.dart';
import '../header/field_editor.dart';

View File

@ -11,7 +11,7 @@ import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:app_flowy/generated/locale_keys.g.dart';
import '../../../application/field/field_cache.dart';
import '../../../application/field/field_controller.dart';
import '../../layout/sizes.dart';
import 'grid_property.dart';

View File

@ -5,7 +5,7 @@ import 'package:flowy_infra_ui/style_widget/icon_button.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import '../../../application/field/field_cache.dart';
import '../../../application/field/field_controller.dart';
import '../../layout/sizes.dart';
import 'grid_setting.dart';

View File

@ -21,7 +21,7 @@ import 'package:flowy_sdk/protobuf/flowy-user/user_profile.pb.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:get_it/get_it.dart';
import '../plugins/grid/application/field/field_cache.dart';
import '../plugins/grid/application/field/field_controller.dart';
class DependencyResolver {
static Future<void> resolve(GetIt getIt) async {

View File

@ -91,6 +91,7 @@ class AFBoardDataController extends ChangeNotifier
void clear() {
_columnDatas.clear();
_columnControllers.clear();
notifyListeners();
}

View File

@ -78,7 +78,7 @@ pub struct DeleteFilterParams {
}
#[derive(ProtoBuf, Debug, Default, Clone)]
pub struct CreateGridFilterPayloadPB {
pub struct InsertFilterPayloadPB {
#[pb(index = 1)]
pub field_id: String,
@ -92,7 +92,7 @@ pub struct CreateGridFilterPayloadPB {
pub content: Option<String>,
}
impl CreateGridFilterPayloadPB {
impl InsertFilterPayloadPB {
#[allow(dead_code)]
pub fn new<T: Into<i32>>(field_rev: &FieldRevision, condition: T, content: Option<String>) -> Self {
Self {
@ -104,10 +104,10 @@ impl CreateGridFilterPayloadPB {
}
}
impl TryInto<CreateFilterParams> for CreateGridFilterPayloadPB {
impl TryInto<InsertFilterParams> for InsertFilterPayloadPB {
type Error = ErrorCode;
fn try_into(self) -> Result<CreateFilterParams, Self::Error> {
fn try_into(self) -> Result<InsertFilterParams, Self::Error> {
let field_id = NotEmptyStr::parse(self.field_id)
.map_err(|_| ErrorCode::FieldIdIsEmpty)?
.0;
@ -130,7 +130,7 @@ impl TryInto<CreateFilterParams> for CreateGridFilterPayloadPB {
}
}
Ok(CreateFilterParams {
Ok(InsertFilterParams {
field_id,
field_type_rev: self.field_type.into(),
condition,
@ -139,7 +139,7 @@ impl TryInto<CreateFilterParams> for CreateGridFilterPayloadPB {
}
}
pub struct CreateFilterParams {
pub struct InsertFilterParams {
pub field_id: String,
pub field_type_rev: FieldTypeRevision,
pub condition: u8,

View File

@ -130,7 +130,7 @@ impl std::convert::From<Vec<Arc<GroupConfigurationRevision>>> for RepeatedGridGr
}
#[derive(Eq, PartialEq, ProtoBuf, Debug, Default, Clone)]
pub struct CreateGridGroupPayloadPB {
pub struct InsertGroupPayloadPB {
#[pb(index = 1)]
pub field_id: String,
@ -138,22 +138,22 @@ pub struct CreateGridGroupPayloadPB {
pub field_type: FieldType,
}
impl TryInto<CreatGroupParams> for CreateGridGroupPayloadPB {
impl TryInto<InsertGroupParams> for InsertGroupPayloadPB {
type Error = ErrorCode;
fn try_into(self) -> Result<CreatGroupParams, Self::Error> {
fn try_into(self) -> Result<InsertGroupParams, Self::Error> {
let field_id = NotEmptyStr::parse(self.field_id)
.map_err(|_| ErrorCode::FieldIdIsEmpty)?
.0;
Ok(CreatGroupParams {
Ok(InsertGroupParams {
field_id,
field_type_rev: self.field_type.into(),
})
}
}
pub struct CreatGroupParams {
pub struct InsertGroupParams {
pub field_id: String,
pub field_type_rev: FieldTypeRevision,
}

View File

@ -1,13 +1,12 @@
use crate::entities::{
CreatGroupParams, CreateFilterParams, CreateGridFilterPayloadPB, CreateGridGroupPayloadPB, DeleteFilterParams,
DeleteFilterPayloadPB, DeleteGroupParams, DeleteGroupPayloadPB, RepeatedGridFilterConfigurationPB,
DeleteFilterParams, DeleteFilterPayloadPB, DeleteGroupParams, DeleteGroupPayloadPB, InsertFilterParams,
InsertFilterPayloadPB, InsertGroupParams, InsertGroupPayloadPB, RepeatedGridFilterConfigurationPB,
RepeatedGridGroupConfigurationPB,
};
use flowy_derive::{ProtoBuf, ProtoBuf_Enum};
use flowy_error::ErrorCode;
use flowy_grid_data_model::parser::NotEmptyStr;
use flowy_grid_data_model::revision::LayoutRevision;
use std::collections::HashMap;
use std::convert::TryInto;
use strum::IntoEnumIterator;
use strum_macros::EnumIter;
@ -85,13 +84,13 @@ pub struct GridSettingChangesetPayloadPB {
pub layout_type: GridLayout,
#[pb(index = 3, one_of)]
pub insert_filter: Option<CreateGridFilterPayloadPB>,
pub insert_filter: Option<InsertFilterPayloadPB>,
#[pb(index = 4, one_of)]
pub delete_filter: Option<DeleteFilterPayloadPB>,
#[pb(index = 5, one_of)]
pub insert_group: Option<CreateGridGroupPayloadPB>,
pub insert_group: Option<InsertGroupPayloadPB>,
#[pb(index = 6, one_of)]
pub delete_group: Option<DeleteGroupPayloadPB>,
@ -102,7 +101,7 @@ impl TryInto<GridSettingChangesetParams> for GridSettingChangesetPayloadPB {
fn try_into(self) -> Result<GridSettingChangesetParams, Self::Error> {
let view_id = NotEmptyStr::parse(self.grid_id)
.map_err(|_| ErrorCode::FieldIdIsEmpty)?
.map_err(|_| ErrorCode::ViewIdInvalid)?
.0;
let insert_filter = match self.insert_filter {
@ -139,9 +138,9 @@ impl TryInto<GridSettingChangesetParams> for GridSettingChangesetPayloadPB {
pub struct GridSettingChangesetParams {
pub grid_id: String,
pub layout_type: LayoutRevision,
pub insert_filter: Option<CreateFilterParams>,
pub insert_filter: Option<InsertFilterParams>,
pub delete_filter: Option<DeleteFilterParams>,
pub insert_group: Option<CreatGroupParams>,
pub insert_group: Option<InsertGroupParams>,
pub delete_group: Option<DeleteGroupParams>,
}

View File

@ -35,6 +35,32 @@ pub(crate) async fn get_grid_setting_handler(
data_result(grid_setting)
}
#[tracing::instrument(level = "trace", skip(data, manager), err)]
pub(crate) async fn update_grid_setting_handler(
data: Data<GridSettingChangesetPayloadPB>,
manager: AppData<Arc<GridManager>>,
) -> Result<(), FlowyError> {
let params: GridSettingChangesetParams = data.into_inner().try_into()?;
let editor = manager.get_grid_editor(&params.grid_id)?;
if let Some(insert_params) = params.insert_group {
let _ = editor.create_group(insert_params).await?;
}
if let Some(delete_params) = params.delete_group {
let _ = editor.delete_group(delete_params).await?;
}
if let Some(create_filter) = params.insert_filter {
let _ = editor.create_filter(create_filter).await?;
}
if let Some(delete_filter) = params.delete_filter {
let _ = editor.delete_filter(delete_filter).await?;
}
Ok(())
}
#[tracing::instrument(level = "debug", skip(data, manager), err)]
pub(crate) async fn get_grid_blocks_handler(
data: Data<QueryBlocksPayloadPB>,

View File

@ -11,7 +11,7 @@ pub fn create(grid_manager: Arc<GridManager>) -> Module {
.event(GridEvent::GetGrid, get_grid_handler)
.event(GridEvent::GetGridBlocks, get_grid_blocks_handler)
.event(GridEvent::GetGridSetting, get_grid_setting_handler)
// .event(GridEvent::UpdateGridSetting, update_grid_setting_handler)
.event(GridEvent::UpdateGridSetting, update_grid_setting_handler)
// Field
.event(GridEvent::GetFields, get_fields_handler)
.event(GridEvent::UpdateField, update_field_handler)
@ -75,8 +75,8 @@ pub enum GridEvent {
/// [UpdateGridSetting] event is used to update the grid's settings.
///
/// The event handler accepts [GridIdPB] and return errors if failed to modify the grid's settings.
#[event(input = "GridIdPB", input = "GridSettingChangesetPayloadPB")]
/// The event handler accepts [GridSettingChangesetPayloadPB] and return errors if failed to modify the grid's settings.
#[event(input = "GridSettingChangesetPayloadPB")]
UpdateGridSetting = 3,
/// [GetFields] event is used to get the grid's settings.
@ -225,4 +225,7 @@ pub enum GridEvent {
#[event(input = "MoveGroupRowPayloadPB")]
MoveGroupRow = 112,
#[event(input = "MoveGroupRowPayloadPB")]
GroupByField = 113,
}

View File

@ -211,7 +211,7 @@ impl GridRevisionEditor {
Ok(())
}
pub async fn group_field(&self, field_id: &str) -> FlowyResult<()> {
pub async fn group_by_field(&self, field_id: &str) -> FlowyResult<()> {
let _ = self.view_manager.group_by_field(field_id).await?;
Ok(())
}
@ -536,8 +536,16 @@ impl GridRevisionEditor {
self.view_manager.get_filters().await
}
pub async fn update_filter(&self, params: CreateFilterParams) -> FlowyResult<()> {
let _ = self.view_manager.update_filter(params).await?;
pub async fn create_group(&self, params: InsertGroupParams) -> FlowyResult<()> {
self.view_manager.insert_or_update_group(params).await
}
pub async fn delete_group(&self, params: DeleteGroupParams) -> FlowyResult<()> {
self.view_manager.delete_group(params).await
}
pub async fn create_filter(&self, params: InsertFilterParams) -> FlowyResult<()> {
let _ = self.view_manager.insert_or_update_filter(params).await?;
Ok(())
}

View File

@ -1,14 +1,15 @@
use crate::dart_notification::{send_dart_notification, GridNotification};
use crate::entities::{
CreateFilterParams, CreateRowParams, DeleteFilterParams, GridFilterConfigurationPB, GridGroupConfigurationPB,
GridLayout, GridLayoutPB, GridSettingPB, GroupChangesetPB, GroupPB, GroupViewChangesetPB, InsertedGroupPB,
InsertedRowPB, MoveGroupParams, RepeatedGridFilterConfigurationPB, RepeatedGridGroupConfigurationPB, RowPB,
CreateRowParams, DeleteFilterParams, DeleteGroupParams, GridFilterConfigurationPB, GridGroupConfigurationPB,
GridLayout, GridLayoutPB, GridSettingPB, GroupChangesetPB, GroupPB, GroupViewChangesetPB, InsertFilterParams,
InsertGroupParams, InsertedGroupPB, InsertedRowPB, MoveGroupParams, RepeatedGridFilterConfigurationPB,
RepeatedGridGroupConfigurationPB, RowPB,
};
use crate::services::grid_editor_task::GridServiceTaskScheduler;
use crate::services::grid_view_manager::{GridViewFieldDelegate, GridViewRowDelegate};
use crate::services::group::{
find_group_field, make_group_controller, GroupConfigurationReader, GroupConfigurationWriter, GroupController,
MoveGroupRowContext,
default_group_configuration, find_group_field, make_group_controller, GroupConfigurationReader,
GroupConfigurationWriter, GroupController, MoveGroupRowContext,
};
use flowy_error::{FlowyError, FlowyResult};
use flowy_grid_data_model::revision::{
@ -19,7 +20,6 @@ use flowy_revision::{RevisionCloudService, RevisionManager, RevisionObjectBuilde
use flowy_sync::client_grid::{GridViewRevisionChangeset, GridViewRevisionPad};
use flowy_sync::entities::revision::Revision;
use lib_infra::future::{wrap_future, AFFuture, FutureResult};
use std::collections::HashMap;
use std::future::Future;
use std::sync::Arc;
use tokio::sync::RwLock;
@ -210,15 +210,40 @@ impl GridViewRevisionEditor {
}
}
pub(crate) async fn insert_filter(&self, insert_filter: CreateFilterParams) -> FlowyResult<()> {
pub(crate) async fn insert_group(&self, params: InsertGroupParams) -> FlowyResult<()> {
if let Some(field_rev) = self.field_delegate.get_field_rev(&params.field_id).await {
let _ = self
.modify(|pad| {
let configuration = default_group_configuration(&field_rev);
let changeset = pad.insert_group(&params.field_id, &params.field_type_rev, configuration)?;
Ok(changeset)
})
.await?;
}
if self.group_controller.read().await.field_id() != params.field_id {
let _ = self.group_by_field(&params.field_id).await?;
self.notify_did_update_setting().await;
}
Ok(())
}
pub(crate) async fn delete_group(&self, params: DeleteGroupParams) -> FlowyResult<()> {
self.modify(|pad| {
let changeset = pad.delete_filter(&params.field_id, &params.field_type_rev, &params.group_id)?;
Ok(changeset)
})
.await
}
pub(crate) async fn insert_filter(&self, params: InsertFilterParams) -> FlowyResult<()> {
self.modify(|pad| {
let filter_rev = FilterConfigurationRevision {
id: gen_grid_filter_id(),
field_id: insert_filter.field_id.clone(),
condition: insert_filter.condition,
content: insert_filter.content,
field_id: params.field_id.clone(),
condition: params.condition,
content: params.content,
};
let changeset = pad.insert_filter(&insert_filter.field_id, &insert_filter.field_type_rev, filter_rev)?;
let changeset = pad.insert_filter(&params.field_id, &params.field_type_rev, filter_rev)?;
Ok(changeset)
})
.await
@ -279,6 +304,13 @@ impl GridViewRevisionEditor {
Ok(())
}
async fn notify_did_update_setting(&self) {
let setting = self.get_setting().await;
send_dart_notification(&self.view_id, GridNotification::DidUpdateGridSetting)
.payload(setting)
.send();
}
pub async fn notify_did_update_group(&self, changeset: GroupChangesetPB) {
send_dart_notification(&changeset.group_id, GridNotification::DidUpdateGroup)
.payload(changeset)

View File

@ -1,6 +1,6 @@
use crate::entities::{
CreateFilterParams, CreateRowParams, DeleteFilterParams, GridFilterConfigurationPB, GridSettingPB, MoveGroupParams,
RepeatedGridGroupPB, RowPB,
CreateRowParams, DeleteFilterParams, DeleteGroupParams, GridFilterConfigurationPB, GridSettingPB,
InsertFilterParams, InsertGroupParams, MoveGroupParams, RepeatedGridGroupPB, RowPB,
};
use crate::manager::GridUser;
use crate::services::grid_editor_task::GridServiceTaskScheduler;
@ -110,14 +110,14 @@ impl GridViewManager {
Ok(view_editor.get_filters().await)
}
pub(crate) async fn update_filter(&self, insert_filter: CreateFilterParams) -> FlowyResult<()> {
pub(crate) async fn insert_or_update_filter(&self, params: InsertFilterParams) -> FlowyResult<()> {
let view_editor = self.get_default_view_editor().await?;
view_editor.insert_filter(insert_filter).await
view_editor.insert_filter(params).await
}
pub(crate) async fn delete_filter(&self, delete_filter: DeleteFilterParams) -> FlowyResult<()> {
pub(crate) async fn delete_filter(&self, params: DeleteFilterParams) -> FlowyResult<()> {
let view_editor = self.get_default_view_editor().await?;
view_editor.delete_filter(delete_filter).await
view_editor.delete_filter(params).await
}
pub(crate) async fn load_groups(&self) -> FlowyResult<RepeatedGridGroupPB> {
@ -126,6 +126,16 @@ impl GridViewManager {
Ok(RepeatedGridGroupPB { items: groups })
}
pub(crate) async fn insert_or_update_group(&self, params: InsertGroupParams) -> FlowyResult<()> {
let view_editor = self.get_default_view_editor().await?;
view_editor.insert_group(params).await
}
pub(crate) async fn delete_group(&self, params: DeleteGroupParams) -> FlowyResult<()> {
let view_editor = self.get_default_view_editor().await?;
view_editor.delete_group(params).await
}
pub(crate) async fn move_group(&self, params: MoveGroupParams) -> FlowyResult<()> {
let view_editor = self.get_default_view_editor().await?;
let _ = view_editor.move_group(params).await?;

View File

@ -133,6 +133,7 @@ where
}
}
#[tracing::instrument(level = "debug", skip(self, generated_groups), err)]
pub(crate) fn init_groups(
&mut self,
generated_groups: Vec<GeneratedGroup>,
@ -316,7 +317,8 @@ where
fn merge_groups(old_groups: &[GroupRevision], new_groups: Vec<GroupRevision>) -> MergeGroupResult {
let mut merge_result = MergeGroupResult::new();
if old_groups.is_empty() {
merge_result.all_group_revs = new_groups;
merge_result.all_group_revs = new_groups.clone();
merge_result.new_group_revs = new_groups;
return merge_result;
}

View File

@ -89,7 +89,7 @@ where
let field_type_rev = field_rev.ty;
let type_option = field_rev.get_type_option::<T>(field_type_rev);
let groups = G::generate_groups(&field_rev.id, &configuration, &type_option);
let _ = configuration.init_groups(groups, false)?;
let _ = configuration.init_groups(groups, true)?;
Ok(Self {
field_id: field_rev.id.clone(),

View File

@ -16,7 +16,7 @@ impl DefaultGroupController {
let group = Group::new(
DEFAULT_GROUP_CONTROLLER.to_owned(),
field_rev.id.clone(),
"Oops".to_owned(),
"".to_owned(),
"".to_owned(),
);
Self {

View File

@ -1,4 +1,4 @@
use crate::entities::{CreateFilterParams, DeleteFilterParams, GridLayout, GridSettingChangesetParams};
use crate::entities::{DeleteFilterParams, GridLayout, GridSettingChangesetParams, InsertFilterParams};
pub struct GridSettingChangesetBuilder {
params: GridSettingChangesetParams,
@ -17,7 +17,7 @@ impl GridSettingChangesetBuilder {
Self { params }
}
pub fn insert_filter(mut self, params: CreateFilterParams) -> Self {
pub fn insert_filter(mut self, params: InsertFilterParams) -> Self {
self.params.insert_filter = Some(params);
self
}

View File

@ -3,14 +3,14 @@
#![allow(dead_code)]
#![allow(unused_imports)]
use flowy_grid::entities::{CreateFilterParams, CreateGridFilterPayloadPB, DeleteFilterParams, GridLayout, GridSettingChangesetParams, GridSettingPB};
use flowy_grid::entities::{InsertFilterParams, InsertFilterPayloadPB, DeleteFilterParams, GridLayout, GridSettingChangesetParams, GridSettingPB};
use flowy_grid::services::setting::GridSettingChangesetBuilder;
use flowy_grid_data_model::revision::{FieldRevision, FieldTypeRevision};
use crate::grid::grid_editor::GridEditorTest;
pub enum FilterScript {
InsertGridTableFilter {
payload: CreateGridFilterPayloadPB,
payload: InsertFilterPayloadPB,
},
AssertTableFilterCount {
count: i32,
@ -47,8 +47,8 @@ impl GridFilterTest {
match script {
FilterScript::InsertGridTableFilter { payload } => {
let params: CreateFilterParams = payload.try_into().unwrap();
let _ = self.editor.update_filter(params).await.unwrap();
let params: InsertFilterParams = payload.try_into().unwrap();
let _ = self.editor.create_filter(params).await.unwrap();
}
FilterScript::AssertTableFilterCount { count } => {
let filters = self.editor.get_grid_filter().await.unwrap();

View File

@ -1,13 +1,13 @@
use crate::grid::filter_test::script::FilterScript::*;
use crate::grid::filter_test::script::*;
use flowy_grid::entities::{CreateGridFilterPayloadPB, FieldType, TextFilterCondition};
use flowy_grid::entities::{FieldType, InsertFilterPayloadPB, TextFilterCondition};
use flowy_grid_data_model::revision::FieldRevision;
#[tokio::test]
async fn grid_filter_create_test() {
let mut test = GridFilterTest::new().await;
let field_rev = test.get_field_rev(FieldType::RichText);
let payload = CreateGridFilterPayloadPB::new(field_rev, TextFilterCondition::TextIsEmpty, Some("abc".to_owned()));
let payload = InsertFilterPayloadPB::new(field_rev, TextFilterCondition::TextIsEmpty, Some("abc".to_owned()));
let scripts = vec![InsertGridTableFilter { payload }, AssertTableFilterCount { count: 1 }];
test.run_scripts(scripts).await;
}
@ -19,7 +19,7 @@ async fn grid_filter_invalid_condition_panic_test() {
let field_rev = test.get_field_rev(FieldType::RichText).clone();
// 100 is not a valid condition, so this test should be panic.
let payload = CreateGridFilterPayloadPB::new(&field_rev, 100, Some("".to_owned()));
let payload = InsertFilterPayloadPB::new(&field_rev, 100, Some("".to_owned()));
let scripts = vec![InsertGridTableFilter { payload }];
test.run_scripts(scripts).await;
}
@ -46,6 +46,6 @@ async fn grid_filter_delete_test() {
#[tokio::test]
async fn grid_filter_get_rows_test() {}
fn create_filter(field_rev: &FieldRevision, condition: TextFilterCondition, s: &str) -> CreateGridFilterPayloadPB {
CreateGridFilterPayloadPB::new(field_rev, condition, Some(s.to_owned()))
fn create_filter(field_rev: &FieldRevision, condition: TextFilterCondition, s: &str) -> InsertFilterPayloadPB {
InsertFilterPayloadPB::new(field_rev, condition, Some(s.to_owned()))
}

View File

@ -188,7 +188,7 @@ impl GridGroupTest {
.await;
}
GroupScript::GroupByField { field_id } => {
self.editor.group_field(&field_id).await.unwrap();
self.editor.group_by_field(&field_id).await.unwrap();
}
}
}

View File

@ -61,12 +61,12 @@ impl GridViewRevisionPad {
&mut self,
field_id: &str,
field_type: &FieldTypeRevision,
group_rev: GroupConfigurationRevision,
group_configuration_rev: GroupConfigurationRevision,
) -> CollaborateResult<Option<GridViewRevisionChangeset>> {
self.modify(|view| {
// Only save one group
view.groups.clear();
view.groups.add_object(field_id, field_type, group_rev);
view.groups.add_object(field_id, field_type, group_configuration_rev);
Ok(Some(()))
})
}