Skip to content

Commit 60c8ec1

Browse files
authored
Merge pull request #977 from AppFlowy-IO/feat/support_switch_field
Feat/support grouping by different field
2 parents d2c118a + 4f8e012 commit 60c8ec1

File tree

99 files changed

+1974
-1241
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

99 files changed

+1974
-1241
lines changed
Lines changed: 7 additions & 0 deletions
Loading

frontend/app_flowy/assets/translations/en.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,8 @@
160160
"settings": {
161161
"filter": "Filter",
162162
"sortBy": "Sort by",
163-
"Properties": "Properties"
163+
"Properties": "Properties",
164+
"group": "Group"
164165
},
165166
"field": {
166167
"hide": "Hide",

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

Lines changed: 36 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import 'dart:async';
22
import 'package:app_flowy/plugins/grid/application/block/block_cache.dart';
3-
import 'package:app_flowy/plugins/grid/application/field/field_cache.dart';
3+
import 'package:app_flowy/plugins/grid/application/field/field_controller.dart';
44
import 'package:app_flowy/plugins/grid/application/row/row_cache.dart';
55
import 'package:app_flowy/plugins/grid/application/row/row_service.dart';
66
import 'package:appflowy_board/appflowy_board.dart';
@@ -25,7 +25,8 @@ class BoardBloc extends Bloc<BoardEvent, BoardState> {
2525
final MoveRowFFIService _rowService;
2626
LinkedHashMap<String, GroupController> groupControllers = LinkedHashMap();
2727

28-
GridFieldCache get fieldCache => _gridDataController.fieldCache;
28+
GridFieldController get fieldController =>
29+
_gridDataController.fieldController;
2930
String get gridId => _gridDataController.gridId;
3031

3132
BoardBloc({required ViewPB view})
@@ -110,9 +111,11 @@ class BoardBloc extends Bloc<BoardEvent, BoardState> {
110111
emit(state.copyWith(noneOrError: some(error)));
111112
},
112113
didReceiveGroups: (List<GroupPB> groups) {
113-
emit(state.copyWith(
114-
groupIds: groups.map((group) => group.groupId).toList(),
115-
));
114+
emit(
115+
state.copyWith(
116+
groupIds: groups.map((group) => group.groupId).toList(),
117+
),
118+
);
116119
},
117120
);
118121
},
@@ -154,6 +157,23 @@ class BoardBloc extends Bloc<BoardEvent, BoardState> {
154157
}
155158

156159
void initializeGroups(List<GroupPB> groups) {
160+
for (var controller in groupControllers.values) {
161+
controller.dispose();
162+
}
163+
groupControllers.clear();
164+
boardController.clear();
165+
166+
//
167+
List<AFBoardColumnData> columns = groups.map((group) {
168+
return AFBoardColumnData(
169+
id: group.groupId,
170+
name: group.desc,
171+
items: _buildRows(group),
172+
customData: group,
173+
);
174+
}).toList();
175+
boardController.addColumns(columns);
176+
157177
for (final group in groups) {
158178
final delegate = GroupControllerDelegateImpl(
159179
controller: boardController,
@@ -184,38 +204,35 @@ class BoardBloc extends Bloc<BoardEvent, BoardState> {
184204
}
185205
},
186206
didLoadGroups: (groups) {
187-
List<AFBoardColumnData> columns = groups.map((group) {
188-
return AFBoardColumnData(
189-
id: group.groupId,
190-
name: group.desc,
191-
items: _buildRows(group),
192-
customData: group,
193-
);
194-
}).toList();
195-
196-
boardController.addColumns(columns);
207+
if (isClosed) return;
197208
initializeGroups(groups);
198209
add(BoardEvent.didReceiveGroups(groups));
199210
},
200211
onDeletedGroup: (groupIds) {
212+
if (isClosed) return;
201213
//
202214
},
203215
onInsertedGroup: (insertedGroups) {
216+
if (isClosed) return;
204217
//
205218
},
206219
onUpdatedGroup: (updatedGroups) {
207-
//
220+
if (isClosed) return;
208221
for (final group in updatedGroups) {
209222
final columnController =
210223
boardController.getColumnController(group.groupId);
211-
if (columnController != null) {
212-
columnController.updateColumnName(group.desc);
213-
}
224+
columnController?.updateColumnName(group.desc);
214225
}
215226
},
216227
onError: (err) {
217228
Log.error(err);
218229
},
230+
onResetGroups: (groups) {
231+
if (isClosed) return;
232+
233+
initializeGroups(groups);
234+
add(BoardEvent.didReceiveGroups(groups));
235+
},
219236
);
220237
}
221238

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

Lines changed: 44 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import 'dart:collection';
22

33
import 'package:app_flowy/plugins/grid/application/block/block_cache.dart';
4-
import 'package:app_flowy/plugins/grid/application/field/field_cache.dart';
4+
import 'package:app_flowy/plugins/grid/application/field/field_controller.dart';
55
import 'package:app_flowy/plugins/grid/application/grid_service.dart';
66
import 'package:app_flowy/plugins/grid/application/row/row_cache.dart';
77
import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
@@ -12,12 +12,13 @@ import 'package:flowy_sdk/protobuf/flowy-grid/protobuf.dart';
1212

1313
import 'board_listener.dart';
1414

15-
typedef OnFieldsChanged = void Function(UnmodifiableListView<FieldPB>);
15+
typedef OnFieldsChanged = void Function(UnmodifiableListView<GridFieldContext>);
1616
typedef OnGridChanged = void Function(GridPB);
1717
typedef DidLoadGroups = void Function(List<GroupPB>);
1818
typedef OnUpdatedGroup = void Function(List<GroupPB>);
1919
typedef OnDeletedGroup = void Function(List<String>);
2020
typedef OnInsertedGroup = void Function(List<InsertedGroupPB>);
21+
typedef OnResetGroups = void Function(List<GroupPB>);
2122

2223
typedef OnRowsChanged = void Function(
2324
List<RowInfo>,
@@ -28,7 +29,7 @@ typedef OnError = void Function(FlowyError);
2829
class BoardDataController {
2930
final String gridId;
3031
final GridFFIService _gridFFIService;
31-
final GridFieldCache fieldCache;
32+
final GridFieldController fieldController;
3233
final BoardListener _listener;
3334

3435
// key: the block id
@@ -55,7 +56,7 @@ class BoardDataController {
5556
// ignore: prefer_collection_literals
5657
_blocks = LinkedHashMap(),
5758
_gridFFIService = GridFFIService(gridId: view.id),
58-
fieldCache = GridFieldCache(gridId: view.id);
59+
fieldController = GridFieldController(gridId: view.id);
5960

6061
void addListener({
6162
required OnGridChanged onGridChanged,
@@ -65,6 +66,7 @@ class BoardDataController {
6566
required OnUpdatedGroup onUpdatedGroup,
6667
required OnDeletedGroup onDeletedGroup,
6768
required OnInsertedGroup onInsertedGroup,
69+
required OnResetGroups onResetGroups,
6870
required OnError? onError,
6971
}) {
7072
_onGridChanged = onGridChanged;
@@ -73,28 +75,36 @@ class BoardDataController {
7375
_onRowsChanged = onRowsChanged;
7476
_onError = onError;
7577

76-
fieldCache.addListener(onFields: (fields) {
78+
fieldController.addListener(onFields: (fields) {
7779
_onFieldsChanged?.call(UnmodifiableListView(fields));
7880
});
7981

80-
_listener.start(onBoardChanged: (result) {
81-
result.fold(
82-
(changeset) {
83-
if (changeset.updateGroups.isNotEmpty) {
84-
onUpdatedGroup.call(changeset.updateGroups);
85-
}
86-
87-
if (changeset.insertedGroups.isNotEmpty) {
88-
onInsertedGroup.call(changeset.insertedGroups);
89-
}
90-
91-
if (changeset.deletedGroups.isNotEmpty) {
92-
onDeletedGroup.call(changeset.deletedGroups);
93-
}
94-
},
95-
(e) => _onError?.call(e),
96-
);
97-
});
82+
_listener.start(
83+
onBoardChanged: (result) {
84+
result.fold(
85+
(changeset) {
86+
if (changeset.updateGroups.isNotEmpty) {
87+
onUpdatedGroup.call(changeset.updateGroups);
88+
}
89+
90+
if (changeset.insertedGroups.isNotEmpty) {
91+
onInsertedGroup.call(changeset.insertedGroups);
92+
}
93+
94+
if (changeset.deletedGroups.isNotEmpty) {
95+
onDeletedGroup.call(changeset.deletedGroups);
96+
}
97+
},
98+
(e) => _onError?.call(e),
99+
);
100+
},
101+
onGroupByNewField: (result) {
102+
result.fold(
103+
(groups) => onResetGroups(groups),
104+
(e) => _onError?.call(e),
105+
);
106+
},
107+
);
98108
}
99109

100110
Future<Either<Unit, FlowyError>> loadData() async {
@@ -103,16 +113,15 @@ class BoardDataController {
103113
() => result.fold(
104114
(grid) async {
105115
_onGridChanged?.call(grid);
106-
107-
return await _loadFields(grid).then((result) {
108-
return result.fold(
109-
(l) {
110-
_loadGroups(grid.blocks);
111-
return left(l);
112-
},
113-
(err) => right(err),
114-
);
115-
});
116+
return await fieldController.loadFields(fieldIds: grid.fields).then(
117+
(result) => result.fold(
118+
(l) {
119+
_loadGroups(grid.blocks);
120+
return left(l);
121+
},
122+
(err) => right(err),
123+
),
124+
);
116125
},
117126
(err) => right(err),
118127
),
@@ -126,33 +135,19 @@ class BoardDataController {
126135

127136
Future<void> dispose() async {
128137
await _gridFFIService.closeGrid();
129-
await fieldCache.dispose();
138+
await fieldController.dispose();
130139

131140
for (final blockCache in _blocks.values) {
132141
blockCache.dispose();
133142
}
134143
}
135144

136-
Future<Either<Unit, FlowyError>> _loadFields(GridPB grid) async {
137-
final result = await _gridFFIService.getFields(fieldIds: grid.fields);
138-
return Future(
139-
() => result.fold(
140-
(fields) {
141-
fieldCache.fields = fields.items;
142-
_onFieldsChanged?.call(UnmodifiableListView(fieldCache.fields));
143-
return left(unit);
144-
},
145-
(err) => right(err),
146-
),
147-
);
148-
}
149-
150145
Future<void> _loadGroups(List<BlockPB> blocks) async {
151146
for (final block in blocks) {
152147
final cache = GridBlockCache(
153148
gridId: gridId,
154149
block: block,
155-
fieldCache: fieldCache,
150+
fieldController: fieldController,
156151
);
157152

158153
cache.addListener(onRowsChanged: (reason) {

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

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,20 +5,26 @@ import 'package:flowy_infra/notifier.dart';
55
import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
66
import 'package:flowy_sdk/protobuf/flowy-grid/dart_notification.pb.dart';
77
import 'package:dartz/dartz.dart';
8+
import 'package:flowy_sdk/protobuf/flowy-grid/group.pb.dart';
89
import 'package:flowy_sdk/protobuf/flowy-grid/group_changeset.pb.dart';
910

10-
typedef UpdateBoardNotifiedValue = Either<GroupViewChangesetPB, FlowyError>;
11+
typedef GroupUpdateValue = Either<GroupViewChangesetPB, FlowyError>;
12+
typedef GroupByNewFieldValue = Either<List<GroupPB>, FlowyError>;
1113

1214
class BoardListener {
1315
final String viewId;
14-
PublishNotifier<UpdateBoardNotifiedValue>? _groupNotifier = PublishNotifier();
16+
PublishNotifier<GroupUpdateValue>? _groupUpdateNotifier = PublishNotifier();
17+
PublishNotifier<GroupByNewFieldValue>? _groupByNewFieldNotifier =
18+
PublishNotifier();
1519
GridNotificationListener? _listener;
1620
BoardListener(this.viewId);
1721

1822
void start({
19-
required void Function(UpdateBoardNotifiedValue) onBoardChanged,
23+
required void Function(GroupUpdateValue) onBoardChanged,
24+
required void Function(GroupByNewFieldValue) onGroupByNewField,
2025
}) {
21-
_groupNotifier?.addPublishListener(onBoardChanged);
26+
_groupUpdateNotifier?.addPublishListener(onBoardChanged);
27+
_groupByNewFieldNotifier?.addPublishListener(onGroupByNewField);
2228
_listener = GridNotificationListener(
2329
objectId: viewId,
2430
handler: _handler,
@@ -32,9 +38,16 @@ class BoardListener {
3238
switch (ty) {
3339
case GridNotification.DidUpdateGroupView:
3440
result.fold(
35-
(payload) => _groupNotifier?.value =
41+
(payload) => _groupUpdateNotifier?.value =
3642
left(GroupViewChangesetPB.fromBuffer(payload)),
37-
(error) => _groupNotifier?.value = right(error),
43+
(error) => _groupUpdateNotifier?.value = right(error),
44+
);
45+
break;
46+
case GridNotification.DidGroupByNewField:
47+
result.fold(
48+
(payload) => _groupByNewFieldNotifier?.value =
49+
left(GroupViewChangesetPB.fromBuffer(payload).newGroups),
50+
(error) => _groupByNewFieldNotifier?.value = right(error),
3851
);
3952
break;
4053
default:
@@ -44,7 +57,10 @@ class BoardListener {
4457

4558
Future<void> stop() async {
4659
await _listener?.stop();
47-
_groupNotifier?.dispose();
48-
_groupNotifier = null;
60+
_groupUpdateNotifier?.dispose();
61+
_groupUpdateNotifier = null;
62+
63+
_groupByNewFieldNotifier?.dispose();
64+
_groupByNewFieldNotifier = null;
4965
}
5066
}

frontend/app_flowy/lib/plugins/board/application/card/board_date_cell_bloc.dart

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import 'package:app_flowy/plugins/grid/application/cell/cell_service/cell_service.dart';
2+
import 'package:app_flowy/plugins/grid/application/field/field_controller.dart';
23
import 'package:flowy_sdk/protobuf/flowy-grid/date_type_option_entities.pb.dart';
3-
import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart';
44
import 'package:flutter_bloc/flutter_bloc.dart';
55
import 'package:freezed_annotation/freezed_annotation.dart';
66
import 'dart:async';
@@ -20,8 +20,6 @@ class BoardDateCellBloc extends Bloc<BoardDateCellEvent, BoardDateCellState> {
2020
emit(state.copyWith(
2121
data: cellData, dateStr: _dateStrFromCellData(cellData)));
2222
},
23-
didReceiveFieldUpdate: (FieldPB value) =>
24-
emit(state.copyWith(field: value)),
2523
);
2624
},
2725
);
@@ -53,23 +51,21 @@ class BoardDateCellEvent with _$BoardDateCellEvent {
5351
const factory BoardDateCellEvent.initial() = _InitialCell;
5452
const factory BoardDateCellEvent.didReceiveCellUpdate(DateCellDataPB? data) =
5553
_DidReceiveCellUpdate;
56-
const factory BoardDateCellEvent.didReceiveFieldUpdate(FieldPB field) =
57-
_DidReceiveFieldUpdate;
5854
}
5955

6056
@freezed
6157
class BoardDateCellState with _$BoardDateCellState {
6258
const factory BoardDateCellState({
6359
required DateCellDataPB? data,
6460
required String dateStr,
65-
required FieldPB field,
61+
required GridFieldContext fieldContext,
6662
}) = _BoardDateCellState;
6763

6864
factory BoardDateCellState.initial(GridDateCellController context) {
6965
final cellData = context.getCellData();
7066

7167
return BoardDateCellState(
72-
field: context.field,
68+
fieldContext: context.fieldContext,
7369
data: cellData,
7470
dateStr: _dateStrFromCellData(cellData),
7571
);

0 commit comments

Comments
 (0)