chore: create board card

This commit is contained in:
appflowy
2022-08-16 17:13:56 +08:00
parent b7d71428be
commit bc346dfd67
20 changed files with 240 additions and 98 deletions

View File

@ -14,12 +14,14 @@ import 'package:freezed_annotation/freezed_annotation.dart';
import 'dart:collection';
import 'board_data_controller.dart';
import 'group_controller.dart';
part 'board_bloc.freezed.dart';
class BoardBloc extends Bloc<BoardEvent, BoardState> {
final BoardDataController _dataController;
late final AFBoardDataController boardDataController;
late final AFBoardDataController afBoardDataController;
List<GroupController> groupControllers = [];
GridFieldCache get fieldCache => _dataController.fieldCache;
String get gridId => _dataController.gridId;
@ -27,7 +29,7 @@ class BoardBloc extends Bloc<BoardEvent, BoardState> {
BoardBloc({required ViewPB view})
: _dataController = BoardDataController(view: view),
super(BoardState.initial(view.id)) {
boardDataController = AFBoardDataController(
afBoardDataController = AFBoardDataController(
onMoveColumn: (
fromIndex,
toIndex,
@ -71,9 +73,6 @@ class BoardBloc extends Bloc<BoardEvent, BoardState> {
didReceiveGridUpdate: (GridPB grid) {
emit(state.copyWith(grid: Some(grid)));
},
didReceiveGroups: (List<GroupPB> groups) {
emit(state.copyWith(groups: groups));
},
didReceiveRows: (List<RowInfo> rowInfos) {
emit(state.copyWith(rowInfos: rowInfos));
},
@ -85,9 +84,24 @@ class BoardBloc extends Bloc<BoardEvent, BoardState> {
@override
Future<void> close() async {
await _dataController.dispose();
for (final controller in groupControllers) {
controller.dispose();
}
return super.close();
}
void initializeGroups(List<GroupPB> groups) {
for (final group in groups) {
final delegate = GroupControllerDelegateImpl(afBoardDataController);
final controller = GroupController(
group: group,
delegate: delegate,
);
controller.startListening();
groupControllers.add(controller);
}
}
GridRowCache? getRowCache(String blockId) {
final GridBlockCache? blockCache = _dataController.blocks[blockId];
return blockCache?.rowCache;
@ -100,7 +114,7 @@ class BoardBloc extends Bloc<BoardEvent, BoardState> {
add(BoardEvent.didReceiveGridUpdate(grid));
}
},
onGroupChanged: (groups) {
didLoadGroups: (groups) {
List<AFBoardColumnData> columns = groups.map((group) {
return AFBoardColumnData(
id: group.groupId,
@ -110,7 +124,8 @@ class BoardBloc extends Bloc<BoardEvent, BoardState> {
);
}).toList();
boardDataController.addColumns(columns);
afBoardDataController.addColumns(columns);
initializeGroups(groups);
},
onRowsChanged: (List<RowInfo> rowInfos, RowsChangedReason reason) {
add(BoardEvent.didReceiveRows(rowInfos));
@ -155,8 +170,6 @@ class BoardEvent with _$BoardEvent {
const factory BoardEvent.initial() = InitialGrid;
const factory BoardEvent.createRow(String groupId) = _CreateRow;
const factory BoardEvent.endEditRow(String rowId) = _EndEditRow;
const factory BoardEvent.didReceiveGroups(List<GroupPB> groups) =
_DidReceiveGroup;
const factory BoardEvent.didReceiveRows(List<RowInfo> rowInfos) =
_DidReceiveRows;
const factory BoardEvent.didReceiveGridUpdate(
@ -169,7 +182,6 @@ class BoardState with _$BoardState {
const factory BoardState({
required String gridId,
required Option<GridPB> grid,
required List<GroupPB> groups,
required Option<RowPB> editingRow,
required List<RowInfo> rowInfos,
required GridLoadingState loadingState,
@ -177,7 +189,6 @@ class BoardState with _$BoardState {
factory BoardState.initial(String gridId) => BoardState(
rowInfos: [],
groups: [],
grid: none(),
gridId: gridId,
editingRow: none(),
@ -228,3 +239,27 @@ class CreateCardItem extends AFColumnItem {
@override
String get id => '$CreateCardItem';
}
class GroupControllerDelegateImpl extends GroupControllerDelegate {
final AFBoardDataController controller;
GroupControllerDelegateImpl(this.controller);
@override
void insertRow(String groupId, RowPB row, int? index) {
final item = BoardColumnItem(row: row);
if (index != null) {
controller.insertColumnItem(groupId, index, item);
} else {
controller.addColumnItem(groupId, item);
}
}
@override
void removeRow(String groupId, String rowId) {
controller.removeColumnItem(groupId, rowId);
}
@override
void updateRow(String groupId, RowPB row) {}
}

View File

@ -12,7 +12,7 @@ import 'package:flowy_sdk/protobuf/flowy-grid/protobuf.dart';
typedef OnFieldsChanged = void Function(UnmodifiableListView<FieldPB>);
typedef OnGridChanged = void Function(GridPB);
typedef OnGroupChanged = void Function(List<GroupPB>);
typedef DidLoadGroups = void Function(List<GroupPB>);
typedef OnRowsChanged = void Function(
List<RowInfo>,
RowsChangedReason,
@ -30,7 +30,7 @@ class BoardDataController {
OnFieldsChanged? _onFieldsChanged;
OnGridChanged? _onGridChanged;
OnGroupChanged? _onGroupChanged;
DidLoadGroups? _didLoadGroup;
OnRowsChanged? _onRowsChanged;
OnError? _onError;
@ -51,13 +51,13 @@ class BoardDataController {
void addListener({
OnGridChanged? onGridChanged,
OnFieldsChanged? onFieldsChanged,
OnGroupChanged? onGroupChanged,
DidLoadGroups? didLoadGroups,
OnRowsChanged? onRowsChanged,
OnError? onError,
}) {
_onGridChanged = onGridChanged;
_onFieldsChanged = onFieldsChanged;
_onGroupChanged = onGroupChanged;
_didLoadGroup = didLoadGroups;
_onRowsChanged = onRowsChanged;
_onError = onError;
@ -133,7 +133,7 @@ class BoardDataController {
return Future(
() => result.fold(
(groups) {
_onGroupChanged?.call(groups.items);
_didLoadGroup?.call(groups.items);
},
(err) => _onError?.call(err),
),

View File

@ -0,0 +1,49 @@
import 'package:flowy_sdk/log.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/protobuf.dart';
import 'group_listener.dart';
abstract class GroupControllerDelegate {
void removeRow(String groupId, String rowId);
void insertRow(String groupId, RowPB row, int? index);
void updateRow(String groupId, RowPB row);
}
class GroupController {
final GroupPB group;
final GroupListener _listener;
final GroupControllerDelegate delegate;
GroupController({required this.group, required this.delegate})
: _listener = GroupListener(group);
void startListening() {
_listener.start(onGroupChanged: (result) {
result.fold(
(GroupRowsChangesetPB changeset) {
for (final insertedRow in changeset.insertedRows) {
final index = insertedRow.hasIndex() ? insertedRow.index : null;
delegate.insertRow(
group.groupId,
insertedRow.row,
index,
);
}
for (final deletedRow in changeset.deletedRows) {
delegate.removeRow(group.groupId, deletedRow);
}
for (final updatedRow in changeset.updatedRows) {
delegate.updateRow(group.groupId, updatedRow);
}
},
(err) => Log.error(err),
);
});
}
Future<void> dispose() async {
_listener.stop();
}
}

View File

@ -0,0 +1,51 @@
import 'dart:typed_data';
import 'package:app_flowy/core/grid_notification.dart';
import 'package:flowy_infra/notifier.dart';
import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/dart_notification.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/group.pb.dart';
import 'package:dartz/dartz.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/group_changeset.pb.dart';
typedef UpdateGroupNotifiedValue = Either<GroupRowsChangesetPB, FlowyError>;
class GroupListener {
final GroupPB group;
PublishNotifier<UpdateGroupNotifiedValue>? _groupNotifier = PublishNotifier();
GridNotificationListener? _listener;
GroupListener(this.group);
void start({
required void Function(UpdateGroupNotifiedValue) onGroupChanged,
}) {
_groupNotifier?.addPublishListener(onGroupChanged);
_listener = GridNotificationListener(
objectId: group.groupId,
handler: _handler,
);
}
void _handler(
GridNotification ty,
Either<Uint8List, FlowyError> result,
) {
switch (ty) {
case GridNotification.DidUpdateGroup:
result.fold(
(payload) => _groupNotifier?.value =
left(GroupRowsChangesetPB.fromBuffer(payload)),
(error) => _groupNotifier?.value = right(error),
);
break;
default:
break;
}
}
Future<void> stop() async {
await _listener?.stop();
_groupNotifier?.dispose();
_groupNotifier = null;
}
}

View File

@ -55,7 +55,7 @@ class BoardContent extends StatelessWidget {
child: AFBoard(
// key: UniqueKey(),
scrollController: ScrollController(),
dataController: context.read<BoardBloc>().boardDataController,
dataController: context.read<BoardBloc>().afBoardDataController,
headerBuilder: _buildHeader,
footBuilder: _buildFooter,
cardBuilder: (_, data) => _buildCard(context, data),