refactor: RowDetailBloc

This commit is contained in:
appflowy 2022-08-09 20:19:43 +08:00
parent 9930706d9a
commit 9c495957dc
7 changed files with 133 additions and 107 deletions

View File

@ -7,23 +7,24 @@ typedef GridDateCellController
= IGridCellController<DateCellDataPB, CalendarData>;
typedef GridURLCellController = IGridCellController<URLCellDataPB, String>;
abstract class GridCellControllerBuilderDelegate {
GridCellFieldNotifier buildFieldNotifier();
}
class GridCellControllerBuilder {
final GridCellIdentifier _cellId;
final GridCellCache _cellCache;
final GridFieldCache _fieldCache;
final GridCellControllerBuilderDelegate delegate;
GridCellControllerBuilder({
required this.delegate,
required GridCellIdentifier cellId,
required GridCellCache cellCache,
required GridFieldCache fieldCache,
}) : _cellCache = cellCache,
_fieldCache = fieldCache,
_cellId = cellId;
IGridCellController build() {
final cellFieldNotifier =
GridCellFieldNotifier(notifier: GridCellFieldNotifierImpl(_fieldCache));
final cellFieldNotifier = delegate.buildFieldNotifier();
switch (_cellId.fieldType) {
case FieldType.Checkbox:
final cellDataLoader = GridCellDataLoader(

View File

@ -1,13 +1,15 @@
import 'package:app_flowy/plugins/grid/application/cell/cell_service/cell_field_notifier.dart';
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 'row_cache.dart';
typedef OnRowChanged = void Function(GridCellMap, GridRowChangeReason);
class GridRowDataController {
final String rowId;
VoidCallback? _onRowChangedListener;
class GridRowDataController extends GridCellBuilderDelegate {
final GridRowInfo rowInfo;
final List<VoidCallback> _onRowChangedListeners = [];
final GridFieldCache _fieldCache;
final GridRowCache _rowCache;
@ -16,26 +18,36 @@ class GridRowDataController {
GridRowCache get rowCache => _rowCache;
GridRowDataController({
required this.rowId,
required this.rowInfo,
required GridFieldCache fieldCache,
required GridRowCache rowCache,
}) : _fieldCache = fieldCache,
_rowCache = rowCache;
GridCellMap loadData() {
return _rowCache.loadGridCells(rowId);
return _rowCache.loadGridCells(rowInfo.id);
}
void addListener({OnRowChanged? onRowChanged}) {
_onRowChangedListener = _rowCache.addListener(
rowId: rowId,
_onRowChangedListeners.add(_rowCache.addListener(
rowId: rowInfo.id,
onCellUpdated: onRowChanged,
);
));
}
void dispose() {
if (_onRowChangedListener != null) {
_rowCache.removeRowListener(_onRowChangedListener!);
for (final fn in _onRowChangedListeners) {
_rowCache.removeRowListener(fn);
}
}
// GridCellBuilderDelegate implementation
@override
GridCellFieldNotifier buildFieldNotifier() {
return GridCellFieldNotifier(
notifier: GridCellFieldNotifierImpl(_fieldCache));
}
@override
GridCellCache get cellCache => rowCache.cellCache;
}

View File

@ -2,25 +2,24 @@ import 'package:app_flowy/plugins/grid/application/cell/cell_service/cell_servic
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'dart:async';
import 'row_cache.dart';
import 'row_data_controller.dart';
part 'row_detail_bloc.freezed.dart';
class RowDetailBloc extends Bloc<RowDetailEvent, RowDetailState> {
final GridRowInfo rowInfo;
final GridRowCache _rowCache;
void Function()? _rowListenFn;
final GridRowDataController dataController;
RowDetailBloc({
required this.rowInfo,
required GridRowCache rowCache,
}) : _rowCache = rowCache,
super(RowDetailState.initial()) {
required this.dataController,
}) : super(RowDetailState.initial()) {
on<RowDetailEvent>(
(event, emit) async {
await event.map(
initial: (_Initial value) async {
await _startListening();
_loadCellData();
final cells = dataController.loadData();
if (!isClosed) {
add(RowDetailEvent.didReceiveCellDatas(cells.values.toList()));
}
},
didReceiveCellDatas: (_DidReceiveCellDatas value) {
emit(state.copyWith(gridCells: value.gridCells));
@ -32,27 +31,19 @@ class RowDetailBloc extends Bloc<RowDetailEvent, RowDetailState> {
@override
Future<void> close() async {
if (_rowListenFn != null) {
_rowCache.removeRowListener(_rowListenFn!);
}
dataController.dispose();
return super.close();
}
Future<void> _startListening() async {
_rowListenFn = _rowCache.addListener(
rowId: rowInfo.id,
onCellUpdated: (cellDatas, reason) =>
add(RowDetailEvent.didReceiveCellDatas(cellDatas.values.toList())),
listenWhen: () => !isClosed,
dataController.addListener(
onRowChanged: (cells, reason) {
if (!isClosed) {
add(RowDetailEvent.didReceiveCellDatas(cells.values.toList()));
}
},
);
}
Future<void> _loadCellData() async {
final cellDataMap = _rowCache.loadGridCells(rowInfo.id);
if (!isClosed) {
add(RowDetailEvent.didReceiveCellDatas(cellDataMap.values.toList()));
}
}
}
@freezed

View File

@ -1,3 +1,4 @@
import 'package:app_flowy/plugins/grid/application/field/field_cache.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';
@ -15,9 +16,11 @@ import '../application/row/row_cache.dart';
import 'controller/grid_scroll.dart';
import 'layout/layout.dart';
import 'layout/sizes.dart';
import 'widgets/cell/cell_builder.dart';
import 'widgets/row/grid_row.dart';
import 'widgets/footer/grid_footer.dart';
import 'widgets/header/grid_header.dart';
import 'widgets/row/row_detail.dart';
import 'widgets/shortcuts.dart';
import 'widgets/toolbar/grid_toolbar.dart';
@ -239,25 +242,53 @@ class _GridRowsState extends State<_GridRows> {
final rowCache =
context.read<GridBloc>().getRowCache(rowInfo.blockId, rowInfo.id);
final fieldCache = context.read<GridBloc>().dataController.fieldCache;
if (rowCache != null) {
final dataController = GridRowDataController(
rowId: rowInfo.id,
fieldCache: fieldCache,
rowCache: rowCache,
);
/// Return placeholder widget if the rowCache is null.
if (rowCache == null) return const SizedBox();
return SizeTransition(
sizeFactor: animation,
child: GridRowWidget(
rowData: rowInfo,
dataController: dataController,
key: ValueKey(rowInfo.id),
),
);
} else {
return const SizedBox();
}
final fieldCache = context.read<GridBloc>().dataController.fieldCache;
final dataController = GridRowDataController(
rowInfo: rowInfo,
fieldCache: fieldCache,
rowCache: rowCache,
);
return SizeTransition(
sizeFactor: animation,
child: GridRowWidget(
rowInfo: rowInfo,
dataController: dataController,
cellBuilder: GridCellBuilder(delegate: dataController),
openDetailPage: (context, cellBuilder) {
_openRowDetailPage(
context,
rowInfo,
fieldCache,
rowCache,
cellBuilder,
);
},
key: ValueKey(rowInfo.id),
),
);
}
void _openRowDetailPage(
BuildContext context,
GridRowInfo rowInfo,
GridFieldCache fieldCache,
GridRowCache rowCache,
GridCellBuilder cellBuilder,
) {
final dataController = GridRowDataController(
rowInfo: rowInfo,
fieldCache: fieldCache,
rowCache: rowCache,
);
RowDetailPage(
cellBuilder: cellBuilder,
dataController: dataController,
).show(context);
}
}

View File

@ -1,5 +1,4 @@
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:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart';
import 'package:flutter/services.dart';
import 'package:flutter/widgets.dart';
@ -13,23 +12,26 @@ import 'select_option_cell/select_option_cell.dart';
import 'text_cell.dart';
import 'url_cell/url_cell.dart';
abstract class GridCellBuilderDelegate
extends GridCellControllerBuilderDelegate {
GridCellCache get cellCache;
}
class GridCellBuilder {
final GridCellCache cellCache;
final GridFieldCache fieldCache;
final GridCellBuilderDelegate delegate;
GridCellBuilder({
required this.cellCache,
required this.fieldCache,
required this.delegate,
});
GridCellWidget build(GridCellIdentifier cell, {GridCellStyle? style}) {
GridCellWidget build(GridCellIdentifier cellId, {GridCellStyle? style}) {
final cellControllerBuilder = GridCellControllerBuilder(
cellId: cell,
cellCache: cellCache,
fieldCache: fieldCache,
cellId: cellId,
cellCache: delegate.cellCache,
delegate: delegate,
);
final key = cell.key();
switch (cell.fieldType) {
final key = cellId.key();
switch (cellId.fieldType) {
case FieldType.Checkbox:
return GridCheckboxCell(
cellControllerBuilder: cellControllerBuilder,

View File

@ -14,22 +14,20 @@ import '../cell/cell_accessory.dart';
import '../cell/cell_container.dart';
import '../cell/prelude.dart';
import 'row_action_sheet.dart';
import 'row_detail.dart';
class GridRowWidget extends StatefulWidget {
final GridRowInfo rowData;
final GridRowInfo rowInfo;
final GridRowDataController dataController;
final GridCellBuilder cellBuilder;
final void Function(BuildContext, GridCellBuilder) openDetailPage;
GridRowWidget({
required this.rowData,
const GridRowWidget({
required this.rowInfo,
required this.dataController,
required this.cellBuilder,
required this.openDetailPage,
Key? key,
}) : cellBuilder = GridCellBuilder(
cellCache: dataController.rowCache.cellCache,
fieldCache: dataController.fieldCache,
),
super(key: key);
}) : super(key: key);
@override
State<GridRowWidget> createState() => _GridRowWidgetState();
@ -41,7 +39,7 @@ class _GridRowWidgetState extends State<GridRowWidget> {
@override
void initState() {
_rowBloc = RowBloc(
rowInfo: widget.rowData,
rowInfo: widget.rowInfo,
dataController: widget.dataController,
);
_rowBloc.add(const RowEvent.initial());
@ -56,17 +54,20 @@ class _GridRowWidgetState extends State<GridRowWidget> {
child: BlocBuilder<RowBloc, RowState>(
buildWhen: (p, c) => p.rowInfo.height != c.rowInfo.height,
builder: (context, state) {
return Row(
children: [
const _RowLeading(),
Expanded(
child: _RowCells(
final children = [
const _RowLeading(),
Expanded(
child: RowContent(
builder: widget.cellBuilder,
onExpand: () => _expandRow(context),
)),
const _RowTrailing(),
],
);
onExpand: () => widget.openDetailPage(
context,
widget.cellBuilder,
),
),
),
const _RowTrailing(),
];
return Row(children: children);
},
),
),
@ -78,15 +79,6 @@ class _GridRowWidgetState extends State<GridRowWidget> {
_rowBloc.close();
super.dispose();
}
void _expandRow(BuildContext context) {
final page = RowDetailPage(
rowInfo: widget.rowData,
rowCache: widget.dataController.rowCache,
cellBuilder: widget.cellBuilder,
);
page.show(context);
}
}
class _RowLeading extends StatelessWidget {
@ -159,10 +151,10 @@ class _DeleteRowButton extends StatelessWidget {
}
}
class _RowCells extends StatelessWidget {
class RowContent extends StatelessWidget {
final VoidCallback onExpand;
final GridCellBuilder builder;
const _RowCells({
const RowContent({
required this.builder,
required this.onExpand,
Key? key,

View File

@ -1,5 +1,6 @@
import 'package:app_flowy/plugins/grid/application/cell/cell_service/cell_service.dart';
import 'package:app_flowy/plugins/grid/application/field/field_service.dart';
import 'package:app_flowy/plugins/grid/application/row/row_data_controller.dart';
import 'package:app_flowy/plugins/grid/application/row/row_detail_bloc.dart';
import 'package:flowy_infra/image.dart';
import 'package:flowy_infra/theme.dart';
@ -13,7 +14,6 @@ import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import '../../../application/row/row_cache.dart';
import '../../layout/sizes.dart';
import '../cell/cell_accessory.dart';
import '../cell/prelude.dart';
@ -21,13 +21,11 @@ import '../header/field_cell.dart';
import '../header/field_editor.dart';
class RowDetailPage extends StatefulWidget with FlowyOverlayDelegate {
final GridRowInfo rowInfo;
final GridRowCache rowCache;
final GridRowDataController dataController;
final GridCellBuilder cellBuilder;
const RowDetailPage({
required this.rowInfo,
required this.rowCache,
required this.dataController,
required this.cellBuilder,
Key? key,
}) : super(key: key);
@ -63,8 +61,7 @@ class _RowDetailPageState extends State<RowDetailPage> {
return BlocProvider(
create: (context) {
final bloc = RowDetailBloc(
rowInfo: widget.rowInfo,
rowCache: widget.rowCache,
dataController: widget.dataController,
);
bloc.add(const RowDetailEvent.initial());
return bloc;