Merge pull request #617 from AppFlowy-IO/feat/add_more_grid_documentation

This commit is contained in:
Nathan.fooo 2022-07-16 21:03:10 +08:00 committed by GitHub
commit c860d1bc0b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 82 additions and 74 deletions

View File

@ -1,3 +1,4 @@
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';
@ -6,27 +7,32 @@ import 'package:dartz/dartz.dart';
part 'field_editor_bloc.freezed.dart';
class FieldEditorBloc extends Bloc<FieldEditorEvent, FieldEditorState> {
final TypeOptionDataController dataController;
FieldEditorBloc({
required String gridId,
required String fieldName,
required IFieldTypeOptionLoader fieldContextLoader,
}) : super(FieldEditorState.initial(gridId, fieldName, fieldContextLoader)) {
required IFieldTypeOptionLoader loader,
}) : dataController = TypeOptionDataController(gridId: gridId, loader: loader),
super(FieldEditorState.initial(gridId, fieldName)) {
on<FieldEditorEvent>(
(event, emit) async {
await event.when(
initial: () async {
final fieldContext = GridFieldContext(gridId: gridId, loader: fieldContextLoader);
await fieldContext.loadData().then((result) {
result.fold(
(l) => emit(state.copyWith(fieldContext: Some(fieldContext), name: fieldContext.field.name)),
(r) => null,
);
dataController.addFieldListener((field) {
if (!isClosed) {
add(FieldEditorEvent.didReceiveFieldChanged(field));
}
});
await dataController.loadData();
},
updateName: (name) {
state.fieldContext.fold(() => null, (fieldContext) => fieldContext.fieldName = name);
dataController.fieldName = name;
emit(state.copyWith(name: name));
},
didReceiveFieldChanged: (Field field) {
emit(state.copyWith(field: Some(field)));
},
);
},
);
@ -42,6 +48,7 @@ class FieldEditorBloc extends Bloc<FieldEditorEvent, FieldEditorState> {
class FieldEditorEvent with _$FieldEditorEvent {
const factory FieldEditorEvent.initial() = _InitialField;
const factory FieldEditorEvent.updateName(String name) = _UpdateName;
const factory FieldEditorEvent.didReceiveFieldChanged(Field field) = _DidReceiveFieldChanged;
}
@freezed
@ -50,13 +57,17 @@ class FieldEditorState with _$FieldEditorState {
required String gridId,
required String errorText,
required String name,
required Option<GridFieldContext> fieldContext,
required Option<Field> field,
}) = _FieldEditorState;
factory FieldEditorState.initial(String gridId, String fieldName, IFieldTypeOptionLoader loader) => FieldEditorState(
factory FieldEditorState.initial(
String gridId,
String fieldName,
) =>
FieldEditorState(
gridId: gridId,
fieldContext: none(),
errorText: '',
field: none(),
name: fieldName,
);
}

View File

@ -1,4 +1,5 @@
import 'package:dartz/dartz.dart';
import 'package:flowy_infra/notifier.dart';
import 'package:flowy_sdk/dispatch/dispatch.dart';
import 'package:flowy_sdk/log.dart';
import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
@ -193,14 +194,14 @@ class FieldTypeOptionLoader extends IFieldTypeOptionLoader {
}
}
class GridFieldContext {
class TypeOptionDataController {
final String gridId;
final IFieldTypeOptionLoader _loader;
late FieldTypeOptionData _data;
ValueNotifier<Field>? _fieldNotifier;
final PublishNotifier<Field> _fieldNotifier = PublishNotifier();
GridFieldContext({
TypeOptionDataController({
required this.gridId,
required IFieldTypeOptionLoader loader,
}) : _loader = loader;
@ -211,13 +212,7 @@ class GridFieldContext {
(data) {
data.freeze();
_data = data;
if (_fieldNotifier == null) {
_fieldNotifier = ValueNotifier(data.field_2);
} else {
_fieldNotifier?.value = data.field_2;
}
_fieldNotifier.value = data.field_2;
return left(unit);
},
(err) {
@ -260,9 +255,7 @@ class GridFieldContext {
}
});
if (_data.field_2 != _fieldNotifier?.value) {
_fieldNotifier?.value = _data.field_2;
}
_fieldNotifier.value = _data.field_2;
FieldService.insertField(
gridId: gridId,
@ -292,11 +285,11 @@ class GridFieldContext {
callback(field);
}
_fieldNotifier?.addListener(listener);
_fieldNotifier.addListener(listener);
return listener;
}
void removeFieldListener(void Function() listener) {
_fieldNotifier?.removeListener(listener);
_fieldNotifier.removeListener(listener);
}
}

View File

@ -8,17 +8,17 @@ import 'field_service.dart';
part 'field_type_option_edit_bloc.freezed.dart';
class FieldTypeOptionEditBloc extends Bloc<FieldTypeOptionEditEvent, FieldTypeOptionEditState> {
final GridFieldContext _fieldContext;
final TypeOptionDataController _dataController;
void Function()? _fieldListenFn;
FieldTypeOptionEditBloc(GridFieldContext fieldContext)
: _fieldContext = fieldContext,
super(FieldTypeOptionEditState.initial(fieldContext)) {
FieldTypeOptionEditBloc(TypeOptionDataController dataController)
: _dataController = dataController,
super(FieldTypeOptionEditState.initial(dataController)) {
on<FieldTypeOptionEditEvent>(
(event, emit) async {
event.when(
initial: () {
_fieldListenFn = fieldContext.addFieldListener((field) {
_fieldListenFn = dataController.addFieldListener((field) {
add(FieldTypeOptionEditEvent.didReceiveFieldUpdated(field));
});
},
@ -33,7 +33,7 @@ class FieldTypeOptionEditBloc extends Bloc<FieldTypeOptionEditEvent, FieldTypeOp
@override
Future<void> close() async {
if (_fieldListenFn != null) {
_fieldContext.removeFieldListener(_fieldListenFn!);
_dataController.removeFieldListener(_fieldListenFn!);
}
return super.close();
}
@ -51,7 +51,7 @@ class FieldTypeOptionEditState with _$FieldTypeOptionEditState {
required Field field,
}) = _FieldTypeOptionEditState;
factory FieldTypeOptionEditState.initial(GridFieldContext fieldContext) => FieldTypeOptionEditState(
factory FieldTypeOptionEditState.initial(TypeOptionDataController fieldContext) => FieldTypeOptionEditState(
field: fieldContext.field,
);
}

View File

@ -13,12 +13,12 @@ class MultiSelectTypeOptionContext extends TypeOptionWidgetContext<MultiSelectTy
MultiSelectTypeOptionContext({
required MultiSelectTypeOptionWidgetDataParser dataBuilder,
required GridFieldContext fieldContext,
required TypeOptionDataController dataController,
}) : service = TypeOptionService(
gridId: fieldContext.gridId,
fieldId: fieldContext.field.id,
gridId: dataController.gridId,
fieldId: dataController.field.id,
),
super(dataParser: dataBuilder, fieldContext: fieldContext);
super(dataParser: dataBuilder, dataController: dataController);
@override
List<SelectOption> Function(SelectOption) get deleteOption {

View File

@ -13,12 +13,12 @@ class SingleSelectTypeOptionContext extends TypeOptionWidgetContext<SingleSelect
SingleSelectTypeOptionContext({
required SingleSelectTypeOptionWidgetDataParser dataBuilder,
required GridFieldContext fieldContext,
required TypeOptionDataController fieldContext,
}) : service = TypeOptionService(
gridId: fieldContext.gridId,
fieldId: fieldContext.field.id,
),
super(dataParser: dataBuilder, fieldContext: fieldContext);
super(dataParser: dataBuilder, dataController: fieldContext);
@override
List<SelectOption> Function(SelectOption) get deleteOption {

View File

@ -39,30 +39,30 @@ abstract class TypeOptionDataParser<T> {
class TypeOptionWidgetContext<T extends GeneratedMessage> {
T? _typeOptionObject;
final GridFieldContext _fieldContext;
final TypeOptionDataController _dataController;
final TypeOptionDataParser<T> dataParser;
TypeOptionWidgetContext({
required this.dataParser,
required GridFieldContext fieldContext,
}) : _fieldContext = fieldContext;
required TypeOptionDataController dataController,
}) : _dataController = dataController;
String get gridId => _fieldContext.gridId;
String get gridId => _dataController.gridId;
Field get field => _fieldContext.field;
Field get field => _dataController.field;
T get typeOption {
if (_typeOptionObject != null) {
return _typeOptionObject!;
}
final T object = dataParser.fromBuffer(_fieldContext.typeOptionData);
final T object = dataParser.fromBuffer(_dataController.typeOptionData);
_typeOptionObject = object;
return object;
}
set typeOption(T typeOption) {
_fieldContext.typeOptionData = typeOption.writeToBuffer();
_dataController.typeOptionData = typeOption.writeToBuffer();
_typeOptionObject = typeOption;
}
}

View File

@ -65,7 +65,7 @@ class GridFieldCell extends StatelessWidget {
FieldEditor(
gridId: state.gridId,
fieldName: field.name,
contextLoader: FieldTypeOptionLoader(
typeOptionLoader: FieldTypeOptionLoader(
gridId: state.gridId,
field: field,
),

View File

@ -14,11 +14,11 @@ class FieldEditor extends StatelessWidget with FlowyOverlayDelegate {
final String gridId;
final String fieldName;
final IFieldTypeOptionLoader contextLoader;
final IFieldTypeOptionLoader typeOptionLoader;
const FieldEditor({
required this.gridId,
required this.fieldName,
required this.contextLoader,
required this.typeOptionLoader,
Key? key,
}) : super(key: key);
@ -28,7 +28,7 @@ class FieldEditor extends StatelessWidget with FlowyOverlayDelegate {
create: (context) => FieldEditorBloc(
gridId: gridId,
fieldName: fieldName,
fieldContextLoader: contextLoader,
loader: typeOptionLoader,
)..add(const FieldEditorEvent.initial()),
child: BlocBuilder<FieldEditorBloc, FieldEditorState>(
buildWhen: (p, c) => false,
@ -80,11 +80,14 @@ class _FieldTypeOptionCell extends StatelessWidget {
@override
Widget build(BuildContext context) {
return BlocBuilder<FieldEditorBloc, FieldEditorState>(
buildWhen: (p, c) => p.fieldContext != c.fieldContext,
buildWhen: (p, c) => p.field != c.field,
builder: (context, state) {
return state.fieldContext.fold(
return state.field.fold(
() => const SizedBox(),
(fieldContext) => FieldTypeOptionEditor(fieldContext: fieldContext),
(fieldContext) {
final dataController = context.read<FieldEditorBloc>().dataController;
return FieldTypeOptionEditor(dataController: dataController);
},
);
},
);

View File

@ -22,10 +22,10 @@ typedef SwitchToFieldCallback = Future<Either<FieldTypeOptionData, FlowyError>>
);
class FieldTypeOptionEditor extends StatefulWidget {
final GridFieldContext fieldContext;
final TypeOptionDataController dataController;
const FieldTypeOptionEditor({
required this.fieldContext,
required this.dataController,
Key? key,
}) : super(key: key);
@ -39,10 +39,11 @@ class _FieldTypeOptionEditorState extends State<FieldTypeOptionEditor> {
@override
Widget build(BuildContext context) {
return BlocProvider(
create: (context) => FieldTypeOptionEditBloc(widget.fieldContext)..add(const FieldTypeOptionEditEvent.initial()),
create: (context) =>
FieldTypeOptionEditBloc(widget.dataController)..add(const FieldTypeOptionEditEvent.initial()),
child: BlocBuilder<FieldTypeOptionEditBloc, FieldTypeOptionEditState>(
builder: (context, state) {
List<Widget> children = [_switchFieldTypeButton(context, widget.fieldContext.field)];
List<Widget> children = [_switchFieldTypeButton(context, widget.dataController.field)];
final typeOptionWidget = _typeOptionWidget(context: context, state: state);
if (typeOptionWidget != null) {
@ -68,7 +69,7 @@ class _FieldTypeOptionEditorState extends State<FieldTypeOptionEditor> {
hoverColor: theme.hover,
onTap: () {
final list = FieldTypeList(onSelectField: (newFieldType) {
widget.fieldContext.switchToField(newFieldType);
widget.dataController.switchToField(newFieldType);
});
_showOverlay(context, list);
},
@ -89,7 +90,7 @@ class _FieldTypeOptionEditorState extends State<FieldTypeOptionEditor> {
return makeTypeOptionWidget(
context: context,
fieldContext: widget.fieldContext,
dataController: widget.dataController,
overlayDelegate: overlayDelegate,
);
}

View File

@ -151,7 +151,7 @@ class CreateFieldButton extends StatelessWidget {
onTap: () => FieldEditor(
gridId: gridId,
fieldName: "",
contextLoader: NewFieldTypeOptionLoader(gridId: gridId),
typeOptionLoader: NewFieldTypeOptionLoader(gridId: gridId),
).show(context),
leftIcon: svgWidget("home/add"),
);

View File

@ -36,27 +36,27 @@ abstract class TypeOptionWidgetBuilder {
Widget? makeTypeOptionWidget({
required BuildContext context,
required GridFieldContext fieldContext,
required TypeOptionDataController dataController,
required TypeOptionOverlayDelegate overlayDelegate,
}) {
final builder = makeTypeOptionWidgetBuilder(fieldContext, overlayDelegate);
final builder = makeTypeOptionWidgetBuilder(dataController, overlayDelegate);
return builder.build(context);
}
TypeOptionWidgetBuilder makeTypeOptionWidgetBuilder(
GridFieldContext fieldContext,
TypeOptionDataController dataController,
TypeOptionOverlayDelegate overlayDelegate,
) {
switch (fieldContext.field.fieldType) {
switch (dataController.field.fieldType) {
case FieldType.Checkbox:
final context = CheckboxTypeOptionContext(
fieldContext: fieldContext,
dataController: dataController,
dataParser: CheckboxTypeOptionWidgetDataParser(),
);
return CheckboxTypeOptionWidgetBuilder(context);
case FieldType.DateTime:
final context = DateTypeOptionContext(
fieldContext: fieldContext,
dataController: dataController,
dataParser: DateTypeOptionDataParser(),
);
return DateTypeOptionWidgetBuilder(
@ -65,7 +65,7 @@ TypeOptionWidgetBuilder makeTypeOptionWidgetBuilder(
);
case FieldType.SingleSelect:
final context = SingleSelectTypeOptionContext(
fieldContext: fieldContext,
fieldContext: dataController,
dataBuilder: SingleSelectTypeOptionWidgetDataParser(),
);
return SingleSelectTypeOptionWidgetBuilder(
@ -74,7 +74,7 @@ TypeOptionWidgetBuilder makeTypeOptionWidgetBuilder(
);
case FieldType.MultiSelect:
final context = MultiSelectTypeOptionContext(
fieldContext: fieldContext,
dataController: dataController,
dataBuilder: MultiSelectTypeOptionWidgetDataParser(),
);
return MultiSelectTypeOptionWidgetBuilder(
@ -83,7 +83,7 @@ TypeOptionWidgetBuilder makeTypeOptionWidgetBuilder(
);
case FieldType.Number:
final context = NumberTypeOptionContext(
fieldContext: fieldContext,
dataController: dataController,
dataParser: NumberTypeOptionWidgetDataParser(),
);
return NumberTypeOptionWidgetBuilder(
@ -92,14 +92,14 @@ TypeOptionWidgetBuilder makeTypeOptionWidgetBuilder(
);
case FieldType.RichText:
final context = RichTextTypeOptionContext(
fieldContext: fieldContext,
dataController: dataController,
dataParser: RichTextTypeOptionWidgetDataParser(),
);
return RichTextTypeOptionWidgetBuilder(context);
case FieldType.URL:
final context = URLTypeOptionContext(
fieldContext: fieldContext,
dataController: dataController,
dataParser: URLTypeOptionWidgetDataParser(),
);
return URLTypeOptionWidgetBuilder(context);

View File

@ -183,7 +183,7 @@ class _RowDetailCell extends StatelessWidget {
FieldEditor(
gridId: cellId.gridId,
fieldName: cellId.field.name,
contextLoader: FieldTypeOptionLoader(
typeOptionLoader: FieldTypeOptionLoader(
gridId: cellId.gridId,
field: cellId.field,
),

View File

@ -116,7 +116,7 @@ class _GridPropertyCell extends StatelessWidget {
FieldEditor(
gridId: gridId,
fieldName: field.name,
contextLoader: FieldTypeOptionLoader(gridId: gridId, field: field),
typeOptionLoader: FieldTypeOptionLoader(gridId: gridId, field: field),
).show(context, anchorDirection: AnchorDirection.bottomRight);
},
);