chore: do not build the cell if its fieldId equal to the corresponding group field id

This commit is contained in:
appflowy 2022-08-26 16:07:51 +08:00
parent 6e0a191be1
commit aba0f946dd
9 changed files with 133 additions and 99 deletions

View File

@ -165,7 +165,7 @@ class BoardBloc extends Bloc<BoardEvent, BoardState> {
return AFBoardColumnData(
id: group.groupId,
name: group.desc,
items: _buildRows(group.rows),
items: _buildRows(group),
customData: group,
);
}).toList();
@ -196,9 +196,9 @@ class BoardBloc extends Bloc<BoardEvent, BoardState> {
);
}
List<AFColumnItem> _buildRows(List<RowPB> rows) {
final items = rows.map((row) {
return BoardColumnItem(row: row);
List<AFColumnItem> _buildRows(GroupPB group) {
final items = group.rows.map((row) {
return BoardColumnItem(row: row, fieldId: group.fieldId);
}).toList();
return <AFColumnItem>[...items];
@ -284,7 +284,9 @@ class GridFieldEquatable extends Equatable {
class BoardColumnItem extends AFColumnItem {
final RowPB row;
BoardColumnItem({required this.row});
final String fieldId;
BoardColumnItem({required this.row, required this.fieldId});
@override
String get id => row.id;
@ -301,22 +303,27 @@ class GroupControllerDelegateImpl extends GroupControllerDelegate {
GroupControllerDelegateImpl(this.controller);
@override
void insertRow(String groupId, RowPB row, int? index) {
final item = BoardColumnItem(row: row);
void insertRow(GroupPB group, RowPB row, int? index) {
final item = BoardColumnItem(row: row, fieldId: group.fieldId);
if (index != null) {
controller.insertColumnItem(groupId, index, item);
controller.insertColumnItem(group.groupId, index, item);
} else {
controller.addColumnItem(groupId, item);
controller.addColumnItem(group.groupId, item);
}
}
@override
void removeRow(String groupId, String rowId) {
controller.removeColumnItem(groupId, rowId);
void removeRow(GroupPB group, String rowId) {
controller.removeColumnItem(group.groupId, rowId);
}
@override
void updateRow(String groupId, RowPB row) {
controller.updateColumnItem(groupId, BoardColumnItem(row: row));
void updateRow(GroupPB group, RowPB row) {
controller.updateColumnItem(
group.groupId,
BoardColumnItem(
row: row,
fieldId: group.fieldId,
));
}
}

View File

@ -4,7 +4,6 @@ import 'package:app_flowy/plugins/grid/application/row/row_cache.dart';
import 'package:app_flowy/plugins/grid/application/row/row_service.dart';
import 'package:equatable/equatable.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/block_entities.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'dart:async';
@ -14,10 +13,12 @@ import 'card_data_controller.dart';
part 'card_bloc.freezed.dart';
class BoardCardBloc extends Bloc<BoardCardEvent, BoardCardState> {
final String fieldId;
final RowFFIService _rowService;
final CardDataController _dataController;
BoardCardBloc({
required this.fieldId,
required String gridId,
required CardDataController dataController,
}) : _rowService = RowFFIService(
@ -25,22 +26,22 @@ class BoardCardBloc extends Bloc<BoardCardEvent, BoardCardState> {
blockId: dataController.rowPB.blockId,
),
_dataController = dataController,
super(BoardCardState.initial(
dataController.rowPB, dataController.loadData())) {
super(
BoardCardState.initial(
dataController.rowPB,
_makeCells(fieldId, dataController.loadData()),
),
) {
on<BoardCardEvent>(
(event, emit) async {
await event.map(
initial: (_InitialRow value) async {
await event.when(
initial: () async {
await _startListening();
},
didReceiveCells: (_DidReceiveCells value) async {
final cells = value.gridCellMap.values
.map((e) => GridCellEquatable(e.field))
.toList();
didReceiveCells: (cells, reason) async {
emit(state.copyWith(
gridCellMap: value.gridCellMap,
cells: UnmodifiableListView(cells),
changeReason: value.reason,
cells: cells,
changeReason: reason,
));
},
);
@ -58,7 +59,7 @@ class BoardCardBloc extends Bloc<BoardCardEvent, BoardCardState> {
return RowInfo(
gridId: _rowService.gridId,
fields: UnmodifiableListView(
state.cells.map((cell) => cell._field).toList(),
state.cells.map((cell) => cell.identifier.field).toList(),
),
rowPB: state.rowPB,
);
@ -66,8 +67,9 @@ class BoardCardBloc extends Bloc<BoardCardEvent, BoardCardState> {
Future<void> _startListening() async {
_dataController.addListener(
onRowChanged: (cells, reason) {
onRowChanged: (cellMap, reason) {
if (!isClosed) {
final cells = _makeCells(fieldId, cellMap);
add(BoardCardEvent.didReceiveCells(cells, reason));
}
},
@ -75,42 +77,49 @@ class BoardCardBloc extends Bloc<BoardCardEvent, BoardCardState> {
}
}
UnmodifiableListView<BoardCellEquatable> _makeCells(
String fieldId, GridCellMap originalCellMap) {
List<BoardCellEquatable> cells = [];
for (final entry in originalCellMap.entries) {
if (entry.value.fieldId != fieldId) {
cells.add(BoardCellEquatable(entry.value));
}
}
return UnmodifiableListView(cells);
}
@freezed
class BoardCardEvent with _$BoardCardEvent {
const factory BoardCardEvent.initial() = _InitialRow;
const factory BoardCardEvent.didReceiveCells(
GridCellMap gridCellMap, RowsChangedReason reason) = _DidReceiveCells;
UnmodifiableListView<BoardCellEquatable> cells,
RowsChangedReason reason,
) = _DidReceiveCells;
}
@freezed
class BoardCardState with _$BoardCardState {
const factory BoardCardState({
required RowPB rowPB,
required GridCellMap gridCellMap,
required UnmodifiableListView<GridCellEquatable> cells,
required UnmodifiableListView<BoardCellEquatable> cells,
RowsChangedReason? changeReason,
}) = _BoardCardState;
factory BoardCardState.initial(RowPB rowPB, GridCellMap cellDataMap) =>
BoardCardState(
rowPB: rowPB,
gridCellMap: cellDataMap,
cells: UnmodifiableListView(
cellDataMap.values.map((e) => GridCellEquatable(e.field)).toList(),
),
);
factory BoardCardState.initial(
RowPB rowPB, UnmodifiableListView<BoardCellEquatable> cells) =>
BoardCardState(rowPB: rowPB, cells: cells);
}
class GridCellEquatable extends Equatable {
final FieldPB _field;
class BoardCellEquatable extends Equatable {
final GridCellIdentifier identifier;
const GridCellEquatable(FieldPB field) : _field = field;
const BoardCellEquatable(this.identifier);
@override
List<Object?> get props => [
_field.id,
_field.fieldType,
_field.visibility,
_field.width,
identifier.field.id,
identifier.field.fieldType,
identifier.field.visibility,
identifier.field.width,
];
}

View File

@ -7,9 +7,9 @@ import 'group_listener.dart';
typedef OnGroupError = void Function(FlowyError);
abstract class GroupControllerDelegate {
void removeRow(String groupId, String rowId);
void insertRow(String groupId, RowPB row, int? index);
void updateRow(String groupId, RowPB row);
void removeRow(GroupPB group, String rowId);
void insertRow(GroupPB group, RowPB row, int? index);
void updateRow(GroupPB group, RowPB row);
}
class GroupController {
@ -37,7 +37,7 @@ class GroupController {
(GroupChangesetPB changeset) {
for (final deletedRow in changeset.deletedRows) {
group.rows.removeWhere((rowPB) => rowPB.id == deletedRow);
delegate.removeRow(group.groupId, deletedRow);
delegate.removeRow(group, deletedRow);
}
for (final insertedRow in changeset.insertedRows) {
@ -51,7 +51,7 @@ class GroupController {
}
delegate.insertRow(
group.groupId,
group,
insertedRow.row,
index,
);
@ -66,7 +66,7 @@ class GroupController {
group.rows[index] = updatedRow;
}
delegate.updateRow(group.groupId, updatedRow);
delegate.updateRow(group, updatedRow);
}
},
(err) => Log.error(err),

View File

@ -73,7 +73,8 @@ class _BoardContentState extends State<BoardContent> {
@override
Widget build(BuildContext context) {
return BlocBuilder<BoardBloc, BoardState>(
buildWhen: (previous, current) => previous.groupIds != current.groupIds,
buildWhen: (previous, current) =>
previous.groupIds.length != current.groupIds.length,
builder: (context, state) {
return Container(
color: Colors.white,
@ -159,7 +160,8 @@ class _BoardContentState extends State<BoardContent> {
AFBoardColumnData column,
AFColumnItem columnItem,
) {
final rowPB = (columnItem as BoardColumnItem).row;
final boardColumnItem = columnItem as BoardColumnItem;
final rowPB = boardColumnItem.row;
final rowCache = context.read<BoardBloc>().getRowCache(rowPB.blockId);
/// Return placeholder widget if the rowCache is null.
@ -186,6 +188,7 @@ class _BoardContentState extends State<BoardContent> {
child: BoardCard(
gridId: gridId,
groupId: column.id,
fieldId: boardColumnItem.fieldId,
isEditing: isEditing,
cellBuilder: cellBuilder,
dataController: cardController,

View File

@ -35,8 +35,9 @@ class _BoardSelectOptionCellState extends State<BoardSelectOptionCell> {
return BlocProvider.value(
value: _cellBloc,
child: BlocBuilder<BoardSelectOptionCellBloc, BoardSelectOptionCellState>(
buildWhen: (previous, current) =>
previous.selectedOptions != current.selectedOptions,
buildWhen: (previous, current) {
return previous.selectedOptions != current.selectedOptions;
},
builder: (context, state) {
if (state.selectedOptions
.where((element) => element.id == widget.groupId)

View File

@ -15,6 +15,7 @@ typedef OnEndEditing = void Function(String rowId);
class BoardCard extends StatefulWidget {
final String gridId;
final String groupId;
final String fieldId;
final bool isEditing;
final CardDataController dataController;
final BoardCellBuilder cellBuilder;
@ -24,6 +25,7 @@ class BoardCard extends StatefulWidget {
const BoardCard({
required this.gridId,
required this.groupId,
required this.fieldId,
required this.isEditing,
required this.dataController,
required this.cellBuilder,
@ -43,6 +45,7 @@ class _BoardCardState extends State<BoardCard> {
void initState() {
_cardBloc = BoardCardBloc(
gridId: widget.gridId,
fieldId: widget.fieldId,
dataController: widget.dataController,
)..add(const BoardCardEvent.initial());
super.initState();
@ -53,6 +56,9 @@ class _BoardCardState extends State<BoardCard> {
return BlocProvider.value(
value: _cardBloc,
child: BlocBuilder<BoardCardBloc, BoardCardState>(
buildWhen: (previous, current) {
return previous.cells.length != current.cells.length;
},
builder: (context, state) {
return BoardCardContainer(
accessoryBuilder: (context) {
@ -62,7 +68,10 @@ class _BoardCardState extends State<BoardCard> {
widget.openCard(context);
},
child: Column(
children: _makeCells(context, state.gridCellMap),
children: _makeCells(
context,
state.cells.map((cell) => cell.identifier).toList(),
),
),
);
},
@ -70,9 +79,12 @@ class _BoardCardState extends State<BoardCard> {
);
}
List<Widget> _makeCells(BuildContext context, GridCellMap cellMap) {
return cellMap.values.map(
(cellId) {
List<Widget> _makeCells(
BuildContext context,
List<GridCellIdentifier> cells,
) {
return cells.map(
(GridCellIdentifier cellId) {
final child = widget.cellBuilder.buildCell(widget.groupId, cellId);
return Padding(
padding: const EdgeInsets.only(left: 4, right: 4, top: 6),

View File

@ -18,7 +18,7 @@ use flowy_sync::client_grid::{GridRevisionChangeset, GridRevisionPad, JsonDeseri
use flowy_sync::entities::revision::Revision;
use flowy_sync::errors::CollaborateResult;
use flowy_sync::util::make_text_delta_from_revisions;
use lib_infra::future::FutureResult;
use lib_infra::future::{wrap_future, FutureResult};
use std::collections::HashMap;
use std::sync::Arc;
@ -591,34 +591,33 @@ impl GridRevisionEditor {
match self.block_manager.get_row_rev(&from_row_id).await? {
None => tracing::warn!("Move row failed, can not find the row:{}", from_row_id),
Some(row_rev) => {
if let Some(row_changeset) = self
.view_manager
.move_group_row(row_rev, to_group_id, to_row_id.clone())
.await
{
tracing::trace!("Move group row cause row data changed: {:?}", row_changeset);
let block_manager = self.block_manager.clone();
self.view_manager
.move_group_row(row_rev, to_group_id, to_row_id.clone(), |row_changeset| {
wrap_future(async move {
tracing::trace!("Move group row cause row data changed: {:?}", row_changeset);
let cell_changesets = row_changeset
.cell_by_field_id
.into_iter()
.map(|(field_id, cell_rev)| CellChangesetPB {
grid_id: view_id.clone(),
row_id: row_changeset.row_id.clone(),
field_id,
content: cell_rev.data,
})
.collect::<Vec<CellChangesetPB>>();
let cell_changesets = row_changeset
.cell_by_field_id
.into_iter()
.map(|(field_id, cell_rev)| CellChangesetPB {
grid_id: view_id.clone(),
row_id: row_changeset.row_id.clone(),
field_id,
content: cell_rev.data,
for cell_changeset in cell_changesets {
match block_manager.update_cell(cell_changeset).await {
Ok(_) => {}
Err(e) => tracing::error!("Apply cell changeset error:{:?}", e),
}
}
})
.collect::<Vec<CellChangesetPB>>();
for cell_changeset in cell_changesets {
match self.block_manager.update_cell(cell_changeset).await {
Ok(_) => {}
Err(e) => tracing::error!("Apply cell changeset error:{:?}", e),
}
}
}
})
.await?;
}
}
Ok(())
}

View File

@ -140,8 +140,8 @@ impl GridViewRevisionEditor {
row_changeset: &mut RowChangeset,
to_group_id: &str,
to_row_id: Option<String>,
) {
if let Some(changesets) = self
) -> Vec<GroupChangesetPB> {
match self
.group_service
.write()
.await
@ -150,9 +150,8 @@ impl GridViewRevisionEditor {
})
.await
{
for changeset in changesets {
self.notify_did_update_group(changeset).await;
}
None => vec![],
Some(changesets) => changesets,
}
}
/// Only call once after grid view editor initialized
@ -266,7 +265,7 @@ impl GridViewRevisionEditor {
Ok(())
}
async fn notify_did_update_group(&self, changeset: GroupChangesetPB) {
pub async fn notify_did_update_group(&self, changeset: GroupChangesetPB) {
send_dart_notification(&changeset.group_id, GridNotification::DidUpdateGroup)
.payload(changeset)
.send();

View File

@ -134,19 +134,23 @@ impl GridViewManager {
row_rev: Arc<RowRevision>,
to_group_id: String,
to_row_id: Option<String>,
) -> Option<RowChangeset> {
with_row_changeset: impl FnOnce(RowChangeset) -> AFFuture<()>,
) -> FlowyResult<()> {
let mut row_changeset = RowChangeset::new(row_rev.id.clone());
for view_editor in self.view_editors.iter() {
view_editor
.move_group_row(&row_rev, &mut row_changeset, &to_group_id, to_row_id.clone())
.await;
let view_editor = self.get_default_view_editor().await?;
let group_changesets = view_editor
.move_group_row(&row_rev, &mut row_changeset, &to_group_id, to_row_id.clone())
.await;
if row_changeset.is_empty() == false {
with_row_changeset(row_changeset).await;
}
if row_changeset.is_empty() {
None
} else {
Some(row_changeset)
for group_changeset in group_changesets {
view_editor.notify_did_update_group(group_changeset).await;
}
Ok(())
}
pub(crate) async fn did_update_field(&self, field_id: &str) -> FlowyResult<()> {