Skip to content

Commit 0d39afc

Browse files
authored
Merge pull request #898 from AppFlowy-IO/feat/board_update_when_field_change
Feat/board update when field change
2 parents cebee48 + a896637 commit 0d39afc

File tree

36 files changed

+682
-302
lines changed

36 files changed

+682
-302
lines changed

frontend/app_flowy/lib/plugins/board/application/board_bloc.dart

Lines changed: 34 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -20,19 +20,19 @@ import 'group_controller.dart';
2020
part 'board_bloc.freezed.dart';
2121

2222
class BoardBloc extends Bloc<BoardEvent, BoardState> {
23-
final BoardDataController _dataController;
24-
late final AFBoardDataController afBoardDataController;
23+
final BoardDataController _gridDataController;
24+
late final AFBoardDataController boardController;
2525
final MoveRowFFIService _rowService;
2626
LinkedHashMap<String, GroupController> groupControllers = LinkedHashMap.new();
2727

28-
GridFieldCache get fieldCache => _dataController.fieldCache;
29-
String get gridId => _dataController.gridId;
28+
GridFieldCache get fieldCache => _gridDataController.fieldCache;
29+
String get gridId => _gridDataController.gridId;
3030

3131
BoardBloc({required ViewPB view})
3232
: _rowService = MoveRowFFIService(gridId: view.id),
33-
_dataController = BoardDataController(view: view),
33+
_gridDataController = BoardDataController(view: view),
3434
super(BoardState.initial(view.id)) {
35-
afBoardDataController = AFBoardDataController(
35+
boardController = AFBoardDataController(
3636
onMoveColumn: (
3737
fromColumnId,
3838
fromIndex,
@@ -70,7 +70,7 @@ class BoardBloc extends Bloc<BoardEvent, BoardState> {
7070
await _loadGrid(emit);
7171
},
7272
createRow: (groupId) async {
73-
final result = await _dataController.createBoardCard(groupId);
73+
final result = await _gridDataController.createBoardCard(groupId);
7474
result.fold(
7575
(rowPB) {
7676
emit(state.copyWith(editingRow: some(rowPB)));
@@ -126,7 +126,7 @@ class BoardBloc extends Bloc<BoardEvent, BoardState> {
126126

127127
@override
128128
Future<void> close() async {
129-
await _dataController.dispose();
129+
await _gridDataController.dispose();
130130
for (final controller in groupControllers.values) {
131131
controller.dispose();
132132
}
@@ -135,7 +135,7 @@ class BoardBloc extends Bloc<BoardEvent, BoardState> {
135135

136136
void initializeGroups(List<GroupPB> groups) {
137137
for (final group in groups) {
138-
final delegate = GroupControllerDelegateImpl(afBoardDataController);
138+
final delegate = GroupControllerDelegateImpl(boardController);
139139
final controller = GroupController(
140140
gridId: state.gridId,
141141
group: group,
@@ -147,12 +147,12 @@ class BoardBloc extends Bloc<BoardEvent, BoardState> {
147147
}
148148

149149
GridRowCache? getRowCache(String blockId) {
150-
final GridBlockCache? blockCache = _dataController.blocks[blockId];
150+
final GridBlockCache? blockCache = _gridDataController.blocks[blockId];
151151
return blockCache?.rowCache;
152152
}
153153

154154
void _startListening() {
155-
_dataController.addListener(
155+
_gridDataController.addListener(
156156
onGridChanged: (grid) {
157157
if (!isClosed) {
158158
add(BoardEvent.didReceiveGridUpdate(grid));
@@ -162,18 +162,34 @@ class BoardBloc extends Bloc<BoardEvent, BoardState> {
162162
List<AFBoardColumnData> columns = groups.map((group) {
163163
return AFBoardColumnData(
164164
id: group.groupId,
165-
desc: group.desc,
165+
name: group.desc,
166166
items: _buildRows(group.rows),
167167
customData: group,
168168
);
169169
}).toList();
170170

171-
afBoardDataController.addColumns(columns);
171+
boardController.addColumns(columns);
172172
initializeGroups(groups);
173173
},
174174
onRowsChanged: (List<RowInfo> rowInfos, RowsChangedReason reason) {
175175
add(BoardEvent.didReceiveRows(rowInfos));
176176
},
177+
onDeletedGroup: (groupIds) {
178+
//
179+
},
180+
onInsertedGroup: (insertedGroups) {
181+
//
182+
},
183+
onUpdatedGroup: (updatedGroups) {
184+
//
185+
for (final group in updatedGroups) {
186+
final columnController =
187+
boardController.getColumnController(group.groupId);
188+
if (columnController != null) {
189+
columnController.updateColumnName(group.desc);
190+
}
191+
}
192+
},
177193
onError: (err) {
178194
Log.error(err);
179195
},
@@ -189,7 +205,7 @@ class BoardBloc extends Bloc<BoardEvent, BoardState> {
189205
}
190206

191207
Future<void> _loadGrid(Emitter<BoardState> emit) async {
192-
final result = await _dataController.loadData();
208+
final result = await _gridDataController.loadData();
193209
result.fold(
194210
(grid) => emit(
195211
state.copyWith(loadingState: GridLoadingState.finish(left(unit))),
@@ -301,6 +317,9 @@ class GroupControllerDelegateImpl extends GroupControllerDelegate {
301317

302318
@override
303319
void updateRow(String groupId, RowPB row) {
304-
//
320+
// workaround: fix the board card reload timing issue.
321+
Future.delayed(const Duration(milliseconds: 300), () {
322+
controller.updateColumnItem(groupId, BoardColumnItem(row: row));
323+
});
305324
}
306325
}

frontend/app_flowy/lib/plugins/board/application/board_data_controller.dart

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,15 @@ import 'dart:async';
1010
import 'package:dartz/dartz.dart';
1111
import 'package:flowy_sdk/protobuf/flowy-grid/protobuf.dart';
1212

13+
import 'board_listener.dart';
14+
1315
typedef OnFieldsChanged = void Function(UnmodifiableListView<FieldPB>);
1416
typedef OnGridChanged = void Function(GridPB);
1517
typedef DidLoadGroups = void Function(List<GroupPB>);
18+
typedef OnUpdatedGroup = void Function(List<GroupPB>);
19+
typedef OnDeletedGroup = void Function(List<String>);
20+
typedef OnInsertedGroup = void Function(List<InsertedGroupPB>);
21+
1622
typedef OnRowsChanged = void Function(
1723
List<RowInfo>,
1824
RowsChangedReason,
@@ -23,6 +29,7 @@ class BoardDataController {
2329
final String gridId;
2430
final GridFFIService _gridFFIService;
2531
final GridFieldCache fieldCache;
32+
final BoardListener _listener;
2633

2734
// key: the block id
2835
final LinkedHashMap<String, GridBlockCache> _blocks;
@@ -44,16 +51,20 @@ class BoardDataController {
4451

4552
BoardDataController({required ViewPB view})
4653
: gridId = view.id,
54+
_listener = BoardListener(view.id),
4755
_blocks = LinkedHashMap.new(),
4856
_gridFFIService = GridFFIService(gridId: view.id),
4957
fieldCache = GridFieldCache(gridId: view.id);
5058

5159
void addListener({
52-
OnGridChanged? onGridChanged,
60+
required OnGridChanged onGridChanged,
5361
OnFieldsChanged? onFieldsChanged,
54-
DidLoadGroups? didLoadGroups,
55-
OnRowsChanged? onRowsChanged,
56-
OnError? onError,
62+
required DidLoadGroups didLoadGroups,
63+
required OnRowsChanged onRowsChanged,
64+
required OnUpdatedGroup onUpdatedGroup,
65+
required OnDeletedGroup onDeletedGroup,
66+
required OnInsertedGroup onInsertedGroup,
67+
required OnError? onError,
5768
}) {
5869
_onGridChanged = onGridChanged;
5970
_onFieldsChanged = onFieldsChanged;
@@ -64,6 +75,25 @@ class BoardDataController {
6475
fieldCache.addListener(onFields: (fields) {
6576
_onFieldsChanged?.call(UnmodifiableListView(fields));
6677
});
78+
79+
_listener.start(onBoardChanged: (result) {
80+
result.fold(
81+
(changeset) {
82+
if (changeset.updateGroups.isNotEmpty) {
83+
onUpdatedGroup.call(changeset.updateGroups);
84+
}
85+
86+
if (changeset.insertedGroups.isNotEmpty) {
87+
onInsertedGroup.call(changeset.insertedGroups);
88+
}
89+
90+
if (changeset.deletedGroups.isNotEmpty) {
91+
onDeletedGroup.call(changeset.deletedGroups);
92+
}
93+
},
94+
(e) => _onError?.call(e),
95+
);
96+
});
6797
}
6898

6999
Future<Either<Unit, FlowyError>> loadData() async {
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import 'dart:typed_data';
2+
3+
import 'package:app_flowy/core/grid_notification.dart';
4+
import 'package:flowy_infra/notifier.dart';
5+
import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
6+
import 'package:flowy_sdk/protobuf/flowy-grid/dart_notification.pb.dart';
7+
import 'package:dartz/dartz.dart';
8+
import 'package:flowy_sdk/protobuf/flowy-grid/group_changeset.pb.dart';
9+
10+
typedef UpdateBoardNotifiedValue = Either<GroupViewChangesetPB, FlowyError>;
11+
12+
class BoardListener {
13+
final String viewId;
14+
PublishNotifier<UpdateBoardNotifiedValue>? _groupNotifier = PublishNotifier();
15+
GridNotificationListener? _listener;
16+
BoardListener(this.viewId);
17+
18+
void start({
19+
required void Function(UpdateBoardNotifiedValue) onBoardChanged,
20+
}) {
21+
_groupNotifier?.addPublishListener(onBoardChanged);
22+
_listener = GridNotificationListener(
23+
objectId: viewId,
24+
handler: _handler,
25+
);
26+
}
27+
28+
void _handler(
29+
GridNotification ty,
30+
Either<Uint8List, FlowyError> result,
31+
) {
32+
switch (ty) {
33+
case GridNotification.DidUpdateGroupView:
34+
result.fold(
35+
(payload) => _groupNotifier?.value =
36+
left(GroupViewChangesetPB.fromBuffer(payload)),
37+
(error) => _groupNotifier?.value = right(error),
38+
);
39+
break;
40+
default:
41+
break;
42+
}
43+
}
44+
45+
Future<void> stop() async {
46+
await _listener?.stop();
47+
_groupNotifier?.dispose();
48+
_groupNotifier = null;
49+
}
50+
}

frontend/app_flowy/lib/plugins/board/application/group_controller.dart

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,12 @@ class GroupController {
3434
void startListening() {
3535
_listener.start(onGroupChanged: (result) {
3636
result.fold(
37-
(GroupRowsChangesetPB changeset) {
37+
(GroupChangesetPB changeset) {
38+
for (final deletedRow in changeset.deletedRows) {
39+
group.rows.removeWhere((rowPB) => rowPB.id == deletedRow);
40+
delegate.removeRow(group.groupId, deletedRow);
41+
}
42+
3843
for (final insertedRow in changeset.insertedRows) {
3944
final index = insertedRow.hasIndex() ? insertedRow.index : null;
4045

@@ -52,11 +57,6 @@ class GroupController {
5257
);
5358
}
5459

55-
for (final deletedRow in changeset.deletedRows) {
56-
group.rows.removeWhere((rowPB) => rowPB.id == deletedRow);
57-
delegate.removeRow(group.groupId, deletedRow);
58-
}
59-
6060
for (final updatedRow in changeset.updatedRows) {
6161
final index = group.rows.indexWhere(
6262
(rowPB) => rowPB.id == updatedRow.id,

frontend/app_flowy/lib/plugins/board/application/group_listener.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import 'package:flowy_sdk/protobuf/flowy-grid/group.pb.dart';
88
import 'package:dartz/dartz.dart';
99
import 'package:flowy_sdk/protobuf/flowy-grid/group_changeset.pb.dart';
1010

11-
typedef UpdateGroupNotifiedValue = Either<GroupRowsChangesetPB, FlowyError>;
11+
typedef UpdateGroupNotifiedValue = Either<GroupChangesetPB, FlowyError>;
1212

1313
class GroupListener {
1414
final GroupPB group;
@@ -34,7 +34,7 @@ class GroupListener {
3434
case GridNotification.DidUpdateGroup:
3535
result.fold(
3636
(payload) => _groupNotifier?.value =
37-
left(GroupRowsChangesetPB.fromBuffer(payload)),
37+
left(GroupChangesetPB.fromBuffer(payload)),
3838
(error) => _groupNotifier?.value = right(error),
3939
);
4040
break;

frontend/app_flowy/lib/plugins/board/presentation/board_page.dart

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -62,9 +62,8 @@ class BoardContent extends StatelessWidget {
6262
child: Padding(
6363
padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 20),
6464
child: AFBoard(
65-
// key: UniqueKey(),
6665
scrollController: ScrollController(),
67-
dataController: context.read<BoardBloc>().afBoardDataController,
66+
dataController: context.read<BoardBloc>().boardController,
6867
headerBuilder: _buildHeader,
6968
footBuilder: _buildFooter,
7069
cardBuilder: (_, data) => _buildCard(context, data),
@@ -79,10 +78,11 @@ class BoardContent extends StatelessWidget {
7978
);
8079
}
8180

82-
Widget _buildHeader(BuildContext context, AFBoardColumnData columnData) {
81+
Widget _buildHeader(
82+
BuildContext context, AFBoardColumnHeaderData headerData) {
8383
return AppFlowyColumnHeader(
8484
icon: const Icon(Icons.lightbulb_circle),
85-
title: Text(columnData.desc),
85+
title: Text(headerData.columnName),
8686
addIcon: const Icon(Icons.add, size: 20),
8787
moreIcon: const Icon(Icons.more_horiz, size: 20),
8888
height: 50,

frontend/app_flowy/lib/plugins/board/presentation/card/board_select_option_cell.dart

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -35,19 +35,17 @@ class _BoardSelectOptionCellState extends State<BoardSelectOptionCell> {
3535
child: BlocBuilder<BoardSelectOptionCellBloc, BoardSelectOptionCellState>(
3636
builder: (context, state) {
3737
final children = state.selectedOptions
38-
.map((option) => SelectOptionTag.fromOption(
39-
context: context,
40-
option: option,
41-
))
38+
.map(
39+
(option) => SelectOptionTag.fromOption(
40+
context: context,
41+
option: option,
42+
),
43+
)
4244
.toList();
4345
return Align(
4446
alignment: Alignment.centerLeft,
4547
child: AbsorbPointer(
46-
child: Wrap(
47-
children: children,
48-
spacing: 4,
49-
runSpacing: 2,
50-
),
48+
child: Wrap(children: children, spacing: 4, runSpacing: 2),
5149
),
5250
);
5351
},

frontend/app_flowy/lib/plugins/board/presentation/card/card.dart

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ class _BoardCardState extends State<BoardCard> {
4242
_cardBloc = BoardCardBloc(
4343
gridId: widget.gridId,
4444
dataController: widget.dataController,
45-
);
45+
)..add(const BoardCardEvent.initial());
4646
super.initState();
4747
}
4848

@@ -79,6 +79,12 @@ class _BoardCardState extends State<BoardCard> {
7979
},
8080
).toList();
8181
}
82+
83+
@override
84+
Future<void> dispose() async {
85+
_cardBloc.close();
86+
super.dispose();
87+
}
8288
}
8389

8490
class _CardMoreOption extends StatelessWidget with CardAccessory {

0 commit comments

Comments
 (0)