chore: move field width to field settings (#3830)

* refactor: remove unnecessary builder

* feat: add width to field settings

* refactor: field settings logic

* chore: oopsies

* chore: implement UI

* chore: remove GridFieldCellEquatable

* test: rust-lib test fix
This commit is contained in:
Richard Shiue
2023-11-06 14:48:59 +08:00
committed by GitHub
parent 2b684ae7bf
commit 4d82bb5322
37 changed files with 317 additions and 441 deletions

View File

@ -4,6 +4,7 @@ import 'package:appflowy_backend/protobuf/flowy-database2/field_entities.pb.dart
import 'package:appflowy_backend/protobuf/flowy-database2/field_settings_entities.pb.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'field_info.dart';
import 'field_service.dart';
part 'field_action_sheet_bloc.freezed.dart';
@ -14,17 +15,18 @@ class FieldActionSheetBloc
final FieldBackendService fieldService;
final FieldSettingsBackendService fieldSettingsService;
FieldActionSheetBloc({required FieldContext fieldCellContext})
: fieldId = fieldCellContext.fieldInfo.id,
FieldActionSheetBloc({
required String viewId,
required FieldInfo fieldInfo,
}) : fieldId = fieldInfo.id,
fieldService = FieldBackendService(
viewId: fieldCellContext.viewId,
fieldId: fieldCellContext.fieldInfo.id,
viewId: viewId,
fieldId: fieldInfo.id,
),
fieldSettingsService =
FieldSettingsBackendService(viewId: fieldCellContext.viewId),
fieldSettingsService = FieldSettingsBackendService(viewId: viewId),
super(
FieldActionSheetState.initial(
TypeOptionPB.create()..field_2 = fieldCellContext.fieldInfo.field,
TypeOptionPB.create()..field_2 = fieldInfo.field,
),
) {
on<FieldActionSheetEvent>(

View File

@ -1,77 +1,55 @@
import 'dart:math';
import 'package:appflowy_backend/protobuf/flowy-database2/field_entities.pb.dart';
import 'package:appflowy/plugins/database_view/application/field_settings/field_settings_service.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'dart:async';
import 'field_listener.dart';
import 'field_service.dart';
import 'field_info.dart';
part 'field_cell_bloc.freezed.dart';
class FieldCellBloc extends Bloc<FieldCellEvent, FieldCellState> {
final SingleFieldListener _fieldListener;
final FieldBackendService _fieldBackendSvc;
FieldInfo fieldInfo;
final FieldSettingsBackendService _fieldSettingsService;
FieldCellBloc({
required FieldContext fieldContext,
}) : _fieldListener =
SingleFieldListener(fieldId: fieldContext.fieldInfo.id),
_fieldBackendSvc = FieldBackendService(
viewId: fieldContext.viewId,
fieldId: fieldContext.fieldInfo.id,
FieldCellBloc({required String viewId, required this.fieldInfo})
: _fieldSettingsService = FieldSettingsBackendService(
viewId: viewId,
),
super(FieldCellState.initial(fieldContext)) {
super(FieldCellState.initial(fieldInfo)) {
on<FieldCellEvent>(
(event, emit) async {
event.when(
initial: () {
_startListening();
},
didReceiveFieldUpdate: (field) {
emit(state.copyWith(field: fieldContext.fieldInfo.field));
onFieldChanged: (newFieldInfo) {
fieldInfo = newFieldInfo;
emit(FieldCellState.initial(newFieldInfo));
},
onResizeStart: () {
emit(state.copyWith(resizeStart: state.width));
emit(state.copyWith(isResizing: true, resizeStart: state.width));
},
startUpdateWidth: (offset) {
final width = max(offset + state.resizeStart, 50).toDouble();
emit(state.copyWith(width: width));
},
endUpdateWidth: () {
if (state.width != state.field.width.toDouble()) {
_fieldBackendSvc.updateField(width: state.width);
if (state.width != fieldInfo.fieldSettings?.width.toDouble()) {
_fieldSettingsService.updateFieldSettings(
fieldId: fieldInfo.id,
width: state.width,
);
}
emit(state.copyWith(isResizing: false, resizeStart: 0));
},
);
},
);
}
@override
Future<void> close() async {
await _fieldListener.stop();
return super.close();
}
void _startListening() {
_fieldListener.start(
onFieldChanged: (updatedField) {
if (isClosed) {
return;
}
add(FieldCellEvent.didReceiveFieldUpdate(updatedField));
},
);
}
}
@freezed
class FieldCellEvent with _$FieldCellEvent {
const factory FieldCellEvent.initial() = _InitialCell;
const factory FieldCellEvent.didReceiveFieldUpdate(FieldPB field) =
_DidReceiveFieldUpdate;
const factory FieldCellEvent.onFieldChanged(FieldInfo newFieldInfo) =
_OnFieldChanged;
const factory FieldCellEvent.onResizeStart() = _OnResizeStart;
const factory FieldCellEvent.startUpdateWidth(double offset) =
_StartUpdateWidth;
@ -81,16 +59,16 @@ class FieldCellEvent with _$FieldCellEvent {
@freezed
class FieldCellState with _$FieldCellState {
const factory FieldCellState({
required String viewId,
required FieldPB field,
required FieldInfo fieldInfo,
required double width,
required bool isResizing,
required double resizeStart,
}) = _FieldCellState;
factory FieldCellState.initial(FieldContext cellContext) => FieldCellState(
viewId: cellContext.viewId,
field: cellContext.fieldInfo.field,
width: cellContext.fieldInfo.field.width.toDouble(),
factory FieldCellState.initial(FieldInfo fieldInfo) => FieldCellState(
fieldInfo: fieldInfo,
isResizing: false,
width: fieldInfo.fieldSettings!.width.toDouble(),
resizeStart: 0,
);
}

View File

@ -1,12 +1,8 @@
import 'package:appflowy/plugins/database_view/application/field/field_info.dart';
import 'package:appflowy_backend/protobuf/flowy-database2/database_entities.pb.dart';
import 'package:dartz/dartz.dart';
import 'package:appflowy_backend/dispatch/dispatch.dart';
import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-database2/field_entities.pb.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
part 'field_service.freezed.dart';
/// FieldService consists of lots of event functions. We define the events in the backend(Rust),
/// you can find the corresponding event implementation in event_map.rs of the corresponding crate.
@ -104,11 +100,3 @@ class FieldBackendService {
return DatabaseEventGetPrimaryField(payload).send();
}
}
@freezed
class FieldContext with _$FieldContext {
const factory FieldContext({
required String viewId,
required FieldInfo fieldInfo,
}) = _FieldCellContext;
}

View File

@ -58,6 +58,7 @@ class FieldSettingsBackendService {
Future<Either<Unit, FlowyError>> updateFieldSettings({
required String fieldId,
FieldVisibility? fieldVisibility,
double? width,
}) {
final FieldSettingsChangesetPB payload = FieldSettingsChangesetPB.create()
..viewId = viewId
@ -67,6 +68,10 @@ class FieldSettingsBackendService {
payload.visibility = fieldVisibility;
}
if (width != null) {
payload.width = width.round();
}
return DatabaseEventUpdateFieldSettings(payload).send();
}
}

View File

@ -6,9 +6,7 @@ import 'package:appflowy/plugins/database_view/application/field/field_info.dart
import 'package:appflowy/plugins/database_view/application/group/group_service.dart';
import 'package:appflowy/plugins/database_view/application/row/row_service.dart';
import 'package:appflowy_board/appflowy_board.dart';
import 'package:collection/collection.dart';
import 'package:dartz/dartz.dart';
import 'package:equatable/equatable.dart';
import 'package:appflowy_backend/log.dart';
import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart';
@ -400,29 +398,6 @@ class BoardState with _$BoardState {
);
}
class GridFieldEquatable extends Equatable {
final UnmodifiableListView<FieldPB> _fields;
const GridFieldEquatable(
UnmodifiableListView<FieldPB> fields,
) : _fields = fields;
@override
List<Object?> get props {
if (_fields.isEmpty) {
return [];
}
return [
_fields.length,
_fields
.map((field) => field.width)
.reduce((value, element) => value + element),
];
}
UnmodifiableListView<FieldPB> get value => UnmodifiableListView(_fields);
}
class GroupItem extends AppFlowyGroupItem {
final RowMetaPB row;
final FieldInfo fieldInfo;

View File

@ -4,7 +4,6 @@ import 'package:appflowy/plugins/database_view/application/field/field_controlle
import 'package:appflowy/plugins/database_view/application/setting/property_bloc.dart';
import 'package:appflowy/plugins/database_view/calendar/application/calendar_setting_bloc.dart';
import 'package:appflowy/plugins/database_view/grid/presentation/layout/sizes.dart';
import 'package:appflowy/startup/startup.dart';
import 'package:appflowy/workspace/presentation/widgets/toggle/toggle.dart';
import 'package:appflowy/workspace/presentation/widgets/toggle/toggle_style.dart';
import 'package:appflowy_backend/protobuf/flowy-database2/protobuf.dart';
@ -234,9 +233,9 @@ class LayoutDateField extends StatelessWidget {
offset: const Offset(-14, 0),
popupBuilder: (context) {
return BlocProvider(
create: (context) => getIt<DatabasePropertyBloc>(
param1: viewId,
param2: fieldController,
create: (context) => DatabasePropertyBloc(
viewId: viewId,
fieldController: fieldController,
)..add(const DatabasePropertyEvent.initial()),
child: BlocBuilder<DatabasePropertyBloc, DatabasePropertyState>(
builder: (context, state) {

View File

@ -6,13 +6,11 @@ import 'package:appflowy/plugins/database_view/application/row/row_service.dart'
import 'package:appflowy/plugins/database_view/grid/presentation/widgets/filter/filter_info.dart';
import 'package:appflowy/plugins/database_view/grid/presentation/widgets/sort/sort_info.dart';
import 'package:dartz/dartz.dart';
import 'package:equatable/equatable.dart';
import 'package:appflowy_backend/protobuf/flowy-folder2/view.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';
import '../../application/database_controller.dart';
import 'dart:collection';
part 'grid_bloc.freezed.dart';
@ -54,7 +52,7 @@ class GridBloc extends Bloc<GridEvent, GridState> {
didReceiveFieldUpdate: (fields) {
emit(
state.copyWith(
fields: GridFieldEquatable(fields),
fields: FieldList(fields),
),
);
},
@ -175,7 +173,7 @@ class GridState with _$GridState {
const factory GridState({
required String viewId,
required Option<DatabasePB> grid,
required GridFieldEquatable fields,
required FieldList fields,
required List<RowInfo> rowInfos,
required int rowCount,
required LoadingState loadingState,
@ -186,7 +184,7 @@ class GridState with _$GridState {
}) = _GridState;
factory GridState.initial(String viewId) => GridState(
fields: GridFieldEquatable(UnmodifiableListView([])),
fields: FieldList([]),
rowInfos: [],
rowCount: 0,
grid: none(),
@ -199,26 +197,7 @@ class GridState with _$GridState {
);
}
class GridFieldEquatable extends Equatable {
final List<FieldInfo> _fieldInfos;
const GridFieldEquatable(
List<FieldInfo> fieldInfos,
) : _fieldInfos = fieldInfos;
@override
List<Object?> get props {
if (_fieldInfos.isEmpty) {
return [];
}
return [
_fieldInfos.length,
_fieldInfos
.map((fieldInfo) => fieldInfo.field.width)
.reduce((value, element) => value + element),
];
}
UnmodifiableListView<FieldInfo> get value =>
UnmodifiableListView(_fieldInfos);
@freezed
class FieldList with _$FieldList {
factory FieldList(List<FieldInfo> fields) = _FieldList;
}

View File

@ -132,7 +132,7 @@ class GridCellEquatable extends Equatable {
_fieldInfo.id,
_fieldInfo.fieldType,
_fieldInfo.field.visibility,
_fieldInfo.field.width,
_fieldInfo.fieldSettings?.width,
];
}

View File

@ -172,7 +172,7 @@ class _GridPageContentState extends State<GridPageContent> {
return BlocBuilder<GridBloc, GridState>(
buildWhen: (previous, current) => previous.fields != current.fields,
builder: (context, state) {
final contentWidth = GridLayout.headerWidth(state.fields.value);
final contentWidth = GridLayout.headerWidth(state.fields.fields);
return Column(
crossAxisAlignment: CrossAxisAlignment.start,

View File

@ -6,7 +6,7 @@ class GridLayout {
if (fields.isEmpty) return 0;
final fieldsWidth = fields
.map((fieldInfo) => fieldInfo.field.width.toDouble())
.map((fieldInfo) => fieldInfo.fieldSettings!.width.toDouble())
.reduce((value, element) => value + element);
return fieldsWidth +

View File

@ -1,6 +1,6 @@
import 'package:appflowy/generated/flowy_svgs.g.dart';
import 'package:appflowy/plugins/database_view/application/field/field_cell_bloc.dart';
import 'package:appflowy/plugins/database_view/application/field/field_service.dart';
import 'package:appflowy/plugins/database_view/application/field/field_info.dart';
import 'package:appflowy_popover/appflowy_popover.dart';
import 'package:flowy_infra/theme_extension.dart';
@ -15,31 +15,41 @@ import 'field_cell_action_sheet.dart';
import 'field_type_extension.dart';
class GridFieldCell extends StatefulWidget {
final FieldContext cellContext;
final String viewId;
final FieldInfo fieldInfo;
const GridFieldCell({
Key? key,
required this.cellContext,
}) : super(key: key);
super.key,
required this.viewId,
required this.fieldInfo,
});
@override
State<GridFieldCell> createState() => _GridFieldCellState();
}
class _GridFieldCellState extends State<GridFieldCell> {
late final FieldCellBloc _bloc;
late PopoverController popoverController;
@override
void initState() {
popoverController = PopoverController();
super.initState();
popoverController = PopoverController();
_bloc = FieldCellBloc(viewId: widget.viewId, fieldInfo: widget.fieldInfo);
}
@override
didUpdateWidget(covariant oldWidget) {
if (widget.fieldInfo != oldWidget.fieldInfo && !_bloc.isClosed) {
_bloc.add(FieldCellEvent.onFieldChanged(widget.fieldInfo));
}
super.didUpdateWidget(oldWidget);
}
@override
Widget build(BuildContext context) {
return BlocProvider(
create: (context) {
return FieldCellBloc(fieldContext: widget.cellContext);
},
return BlocProvider.value(
value: _bloc,
child: BlocBuilder<FieldCellBloc, FieldCellState>(
builder: (context, state) {
final button = AppFlowyPopover(
@ -50,11 +60,12 @@ class _GridFieldCellState extends State<GridFieldCell> {
controller: popoverController,
popupBuilder: (BuildContext context) {
return GridFieldCellActionSheet(
cellContext: widget.cellContext,
viewId: widget.viewId,
fieldInfo: widget.fieldInfo,
);
},
child: FieldCellButton(
field: widget.cellContext.fieldInfo.field,
field: widget.fieldInfo.field,
onTap: () => popoverController.show(),
),
);
@ -78,6 +89,12 @@ class _GridFieldCellState extends State<GridFieldCell> {
),
);
}
@override
Future<void> dispose() async {
super.dispose();
await _bloc.close();
}
}
class _GridHeaderCellContainer extends StatelessWidget {

View File

@ -1,8 +1,8 @@
import 'package:appflowy/generated/flowy_svgs.g.dart';
import 'package:appflowy/plugins/database_view/application/field/field_action_sheet_bloc.dart';
import 'package:appflowy/plugins/database_view/application/field/field_info.dart';
import 'package:appflowy/plugins/database_view/application/field/field_service.dart';
import 'package:appflowy/plugins/database_view/application/field/type_option/type_option_context.dart';
import 'package:appflowy/startup/startup.dart';
import 'package:appflowy/workspace/presentation/widgets/dialogs.dart';
import 'package:appflowy_popover/appflowy_popover.dart';
@ -20,9 +20,13 @@ import '../../layout/sizes.dart';
import 'field_editor.dart';
class GridFieldCellActionSheet extends StatefulWidget {
final FieldContext cellContext;
const GridFieldCellActionSheet({required this.cellContext, Key? key})
: super(key: key);
final String viewId;
final FieldInfo fieldInfo;
const GridFieldCellActionSheet({
required this.viewId,
required this.fieldInfo,
Key? key,
}) : super(key: key);
@override
State<StatefulWidget> createState() => _GridFieldCellActionSheetState();
@ -37,31 +41,35 @@ class _GridFieldCellActionSheetState extends State<GridFieldCellActionSheet> {
return SizedBox(
width: 400,
child: FieldEditor(
viewId: widget.cellContext.viewId,
fieldInfo: widget.cellContext.fieldInfo,
viewId: widget.viewId,
fieldInfo: widget.fieldInfo,
typeOptionLoader: FieldTypeOptionLoader(
viewId: widget.cellContext.viewId,
field: widget.cellContext.fieldInfo.field,
viewId: widget.viewId,
field: widget.fieldInfo.field,
),
),
);
}
return BlocProvider(
create: (context) =>
getIt<FieldActionSheetBloc>(param1: widget.cellContext),
create: (context) => FieldActionSheetBloc(
viewId: widget.viewId,
fieldInfo: widget.fieldInfo,
),
child: IntrinsicWidth(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
_EditFieldButton(
cellContext: widget.cellContext,
onTap: () {
setState(() => _showFieldEditor = true);
},
),
VSpace(GridSize.typeOptionSeparatorHeight),
_FieldOperationList(widget.cellContext),
_FieldOperationList(
viewId: widget.viewId,
fieldInfo: widget.fieldInfo,
),
],
),
),
@ -70,10 +78,8 @@ class _GridFieldCellActionSheetState extends State<GridFieldCellActionSheet> {
}
class _EditFieldButton extends StatelessWidget {
final FieldContext cellContext;
final void Function()? onTap;
const _EditFieldButton({required this.cellContext, Key? key, this.onTap})
: super(key: key);
const _EditFieldButton({Key? key, this.onTap}) : super(key: key);
@override
Widget build(BuildContext context) {
@ -96,8 +102,13 @@ class _EditFieldButton extends StatelessWidget {
}
class _FieldOperationList extends StatelessWidget {
final FieldContext fieldContext;
const _FieldOperationList(this.fieldContext, {Key? key}) : super(key: key);
final String viewId;
final FieldInfo fieldInfo;
const _FieldOperationList({
required this.viewId,
required this.fieldInfo,
Key? key,
}) : super(key: key);
@override
Widget build(BuildContext context) {
@ -128,7 +139,7 @@ class _FieldOperationList extends StatelessWidget {
bool enable = true;
// If the field is primary, delete and duplicate are disabled.
if (fieldContext.fieldInfo.isPrimary) {
if (fieldInfo.isPrimary) {
switch (action) {
case FieldAction.hide:
break;
@ -145,7 +156,8 @@ class _FieldOperationList extends StatelessWidget {
child: SizedBox(
height: GridSize.popoverItemHeight,
child: FieldActionCell(
fieldInfo: fieldContext,
viewId: viewId,
fieldInfo: fieldInfo,
action: action,
enable: enable,
),
@ -155,11 +167,13 @@ class _FieldOperationList extends StatelessWidget {
}
class FieldActionCell extends StatelessWidget {
final FieldContext fieldInfo;
final String viewId;
final FieldInfo fieldInfo;
final FieldAction action;
final bool enable;
const FieldActionCell({
required this.viewId,
required this.fieldInfo,
required this.action,
required this.enable,
@ -177,7 +191,7 @@ class FieldActionCell extends StatelessWidget {
? AFThemeExtension.of(context).textColor
: Theme.of(context).disabledColor,
),
onTap: () => action.run(context, fieldInfo),
onTap: () => action.run(context, viewId, fieldInfo),
leftIcon: FlowySvg(
action.icon(),
color: enable
@ -217,7 +231,7 @@ extension _FieldActionExtension on FieldAction {
}
}
void run(BuildContext context, FieldContext fieldContext) {
void run(BuildContext context, String viewId, FieldInfo fieldInfo) {
switch (this) {
case FieldAction.hide:
context
@ -228,8 +242,8 @@ extension _FieldActionExtension on FieldAction {
PopoverContainer.of(context).close();
FieldBackendService(
viewId: fieldContext.viewId,
fieldId: fieldContext.fieldInfo.id,
viewId: viewId,
fieldId: fieldInfo.id,
).duplicateField();
break;
@ -240,8 +254,8 @@ extension _FieldActionExtension on FieldAction {
title: LocaleKeys.grid_field_deleteFieldPromptMessage.tr(),
confirm: () {
FieldBackendService(
viewId: fieldContext.viewId,
fieldId: fieldContext.fieldInfo.field.id,
viewId: viewId,
fieldId: fieldInfo.field.id,
).deleteField();
},
).show(context);

View File

@ -1,10 +1,8 @@
import 'package:appflowy/generated/flowy_svgs.g.dart';
import 'package:appflowy/generated/locale_keys.g.dart';
import 'package:appflowy/plugins/database_view/application/field/field_controller.dart';
import 'package:appflowy/plugins/database_view/application/field/field_service.dart';
import 'package:appflowy/plugins/database_view/application/field/type_option/type_option_context.dart';
import 'package:appflowy/plugins/database_view/grid/application/grid_header_bloc.dart';
import 'package:appflowy/startup/startup.dart';
import 'package:appflowy_backend/log.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:appflowy_popover/appflowy_popover.dart';
@ -42,9 +40,9 @@ class _GridHeaderSliverAdaptorState extends State<GridHeaderSliverAdaptor> {
Widget build(BuildContext context) {
return BlocProvider(
create: (context) {
return getIt<GridHeaderBloc>(
param1: widget.viewId,
param2: widget.fieldController,
return GridHeaderBloc(
viewId: widget.viewId,
fieldController: widget.fieldController,
)..add(const GridHeaderEvent.initial());
},
child: BlocBuilder<GridHeaderBloc, GridHeaderState>(
@ -96,15 +94,10 @@ class _GridHeaderState extends State<_GridHeader> {
builder: (context, state) {
final cells = state.fields
.map(
(field) => FieldContext(
(fieldInfo) => GridFieldCell(
key: _getKeyById(fieldInfo.id),
viewId: widget.viewId,
fieldInfo: field,
),
)
.map(
(ctx) => GridFieldCell(
key: _getKeyById(ctx.fieldInfo.id),
cellContext: ctx,
fieldInfo: fieldInfo,
),
)
.toList();
@ -136,7 +129,7 @@ class _GridHeaderState extends State<_GridHeader> {
int newIndex,
) {
if (cells.length > oldIndex) {
final field = cells[oldIndex].cellContext.fieldInfo.field;
final field = cells[oldIndex].fieldInfo.field;
context
.read<GridHeaderBloc>()
.add(GridHeaderEvent.moveField(field, oldIndex, newIndex));

View File

@ -276,7 +276,7 @@ class RowContent extends StatelessWidget {
final GridCellWidget child = builder.build(cellId);
return CellContainer(
width: cellId.fieldInfo.field.width.toDouble(),
width: cellId.fieldInfo.fieldSettings?.width.toDouble() ?? 140,
isPrimary: cellId.fieldInfo.field.isPrimary,
cellContainerNotifier: CellContainerNotifier(child),
accessoryBuilder: (buildContext) {

View File

@ -6,7 +6,6 @@ import 'package:appflowy/plugins/database_view/application/field/field_info.dart
import 'package:appflowy/plugins/database_view/application/field/type_option/type_option_context.dart';
import 'package:appflowy/plugins/database_view/application/setting/property_bloc.dart';
import 'package:appflowy/plugins/database_view/grid/presentation/widgets/header/field_type_extension.dart';
import 'package:appflowy/startup/startup.dart';
import 'package:appflowy_backend/protobuf/flowy-database2/protobuf.dart';
import 'package:appflowy_popover/appflowy_popover.dart';
import 'package:collection/collection.dart';
@ -40,9 +39,9 @@ class _DatabasePropertyListState extends State<DatabasePropertyList> {
@override
Widget build(BuildContext context) {
return BlocProvider(
create: (context) => getIt<DatabasePropertyBloc>(
param1: widget.viewId,
param2: widget.fieldController,
create: (context) => DatabasePropertyBloc(
viewId: widget.viewId,
fieldController: widget.fieldController,
)..add(const DatabasePropertyEvent.initial()),
child: BlocBuilder<DatabasePropertyBloc, DatabasePropertyState>(
builder: (context, state) {