mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
refactor: RowDetailBloc
This commit is contained in:
parent
9930706d9a
commit
9c495957dc
@ -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(
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user