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( return AFBoardColumnData(
id: group.groupId, id: group.groupId,
name: group.desc, name: group.desc,
items: _buildRows(group.rows), items: _buildRows(group),
customData: group, customData: group,
); );
}).toList(); }).toList();
@ -196,9 +196,9 @@ class BoardBloc extends Bloc<BoardEvent, BoardState> {
); );
} }
List<AFColumnItem> _buildRows(List<RowPB> rows) { List<AFColumnItem> _buildRows(GroupPB group) {
final items = rows.map((row) { final items = group.rows.map((row) {
return BoardColumnItem(row: row); return BoardColumnItem(row: row, fieldId: group.fieldId);
}).toList(); }).toList();
return <AFColumnItem>[...items]; return <AFColumnItem>[...items];
@ -284,7 +284,9 @@ class GridFieldEquatable extends Equatable {
class BoardColumnItem extends AFColumnItem { class BoardColumnItem extends AFColumnItem {
final RowPB row; final RowPB row;
BoardColumnItem({required this.row}); final String fieldId;
BoardColumnItem({required this.row, required this.fieldId});
@override @override
String get id => row.id; String get id => row.id;
@ -301,22 +303,27 @@ class GroupControllerDelegateImpl extends GroupControllerDelegate {
GroupControllerDelegateImpl(this.controller); GroupControllerDelegateImpl(this.controller);
@override @override
void insertRow(String groupId, RowPB row, int? index) { void insertRow(GroupPB group, RowPB row, int? index) {
final item = BoardColumnItem(row: row); final item = BoardColumnItem(row: row, fieldId: group.fieldId);
if (index != null) { if (index != null) {
controller.insertColumnItem(groupId, index, item); controller.insertColumnItem(group.groupId, index, item);
} else { } else {
controller.addColumnItem(groupId, item); controller.addColumnItem(group.groupId, item);
} }
} }
@override @override
void removeRow(String groupId, String rowId) { void removeRow(GroupPB group, String rowId) {
controller.removeColumnItem(groupId, rowId); controller.removeColumnItem(group.groupId, rowId);
} }
@override @override
void updateRow(String groupId, RowPB row) { void updateRow(GroupPB group, RowPB row) {
controller.updateColumnItem(groupId, BoardColumnItem(row: 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:app_flowy/plugins/grid/application/row/row_service.dart';
import 'package:equatable/equatable.dart'; import 'package:equatable/equatable.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/block_entities.pb.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:flutter_bloc/flutter_bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart'; import 'package:freezed_annotation/freezed_annotation.dart';
import 'dart:async'; import 'dart:async';
@ -14,10 +13,12 @@ import 'card_data_controller.dart';
part 'card_bloc.freezed.dart'; part 'card_bloc.freezed.dart';
class BoardCardBloc extends Bloc<BoardCardEvent, BoardCardState> { class BoardCardBloc extends Bloc<BoardCardEvent, BoardCardState> {
final String fieldId;
final RowFFIService _rowService; final RowFFIService _rowService;
final CardDataController _dataController; final CardDataController _dataController;
BoardCardBloc({ BoardCardBloc({
required this.fieldId,
required String gridId, required String gridId,
required CardDataController dataController, required CardDataController dataController,
}) : _rowService = RowFFIService( }) : _rowService = RowFFIService(
@ -25,22 +26,22 @@ class BoardCardBloc extends Bloc<BoardCardEvent, BoardCardState> {
blockId: dataController.rowPB.blockId, blockId: dataController.rowPB.blockId,
), ),
_dataController = dataController, _dataController = dataController,
super(BoardCardState.initial( super(
dataController.rowPB, dataController.loadData())) { BoardCardState.initial(
dataController.rowPB,
_makeCells(fieldId, dataController.loadData()),
),
) {
on<BoardCardEvent>( on<BoardCardEvent>(
(event, emit) async { (event, emit) async {
await event.map( await event.when(
initial: (_InitialRow value) async { initial: () async {
await _startListening(); await _startListening();
}, },
didReceiveCells: (_DidReceiveCells value) async { didReceiveCells: (cells, reason) async {
final cells = value.gridCellMap.values
.map((e) => GridCellEquatable(e.field))
.toList();
emit(state.copyWith( emit(state.copyWith(
gridCellMap: value.gridCellMap, cells: cells,
cells: UnmodifiableListView(cells), changeReason: reason,
changeReason: value.reason,
)); ));
}, },
); );
@ -58,7 +59,7 @@ class BoardCardBloc extends Bloc<BoardCardEvent, BoardCardState> {
return RowInfo( return RowInfo(
gridId: _rowService.gridId, gridId: _rowService.gridId,
fields: UnmodifiableListView( fields: UnmodifiableListView(
state.cells.map((cell) => cell._field).toList(), state.cells.map((cell) => cell.identifier.field).toList(),
), ),
rowPB: state.rowPB, rowPB: state.rowPB,
); );
@ -66,8 +67,9 @@ class BoardCardBloc extends Bloc<BoardCardEvent, BoardCardState> {
Future<void> _startListening() async { Future<void> _startListening() async {
_dataController.addListener( _dataController.addListener(
onRowChanged: (cells, reason) { onRowChanged: (cellMap, reason) {
if (!isClosed) { if (!isClosed) {
final cells = _makeCells(fieldId, cellMap);
add(BoardCardEvent.didReceiveCells(cells, reason)); 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 @freezed
class BoardCardEvent with _$BoardCardEvent { class BoardCardEvent with _$BoardCardEvent {
const factory BoardCardEvent.initial() = _InitialRow; const factory BoardCardEvent.initial() = _InitialRow;
const factory BoardCardEvent.didReceiveCells( const factory BoardCardEvent.didReceiveCells(
GridCellMap gridCellMap, RowsChangedReason reason) = _DidReceiveCells; UnmodifiableListView<BoardCellEquatable> cells,
RowsChangedReason reason,
) = _DidReceiveCells;
} }
@freezed @freezed
class BoardCardState with _$BoardCardState { class BoardCardState with _$BoardCardState {
const factory BoardCardState({ const factory BoardCardState({
required RowPB rowPB, required RowPB rowPB,
required GridCellMap gridCellMap, required UnmodifiableListView<BoardCellEquatable> cells,
required UnmodifiableListView<GridCellEquatable> cells,
RowsChangedReason? changeReason, RowsChangedReason? changeReason,
}) = _BoardCardState; }) = _BoardCardState;
factory BoardCardState.initial(RowPB rowPB, GridCellMap cellDataMap) => factory BoardCardState.initial(
BoardCardState( RowPB rowPB, UnmodifiableListView<BoardCellEquatable> cells) =>
rowPB: rowPB, BoardCardState(rowPB: rowPB, cells: cells);
gridCellMap: cellDataMap,
cells: UnmodifiableListView(
cellDataMap.values.map((e) => GridCellEquatable(e.field)).toList(),
),
);
} }
class GridCellEquatable extends Equatable { class BoardCellEquatable extends Equatable {
final FieldPB _field; final GridCellIdentifier identifier;
const GridCellEquatable(FieldPB field) : _field = field; const BoardCellEquatable(this.identifier);
@override @override
List<Object?> get props => [ List<Object?> get props => [
_field.id, identifier.field.id,
_field.fieldType, identifier.field.fieldType,
_field.visibility, identifier.field.visibility,
_field.width, identifier.field.width,
]; ];
} }

View File

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

View File

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

View File

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

View File

@ -15,6 +15,7 @@ typedef OnEndEditing = void Function(String rowId);
class BoardCard extends StatefulWidget { class BoardCard extends StatefulWidget {
final String gridId; final String gridId;
final String groupId; final String groupId;
final String fieldId;
final bool isEditing; final bool isEditing;
final CardDataController dataController; final CardDataController dataController;
final BoardCellBuilder cellBuilder; final BoardCellBuilder cellBuilder;
@ -24,6 +25,7 @@ class BoardCard extends StatefulWidget {
const BoardCard({ const BoardCard({
required this.gridId, required this.gridId,
required this.groupId, required this.groupId,
required this.fieldId,
required this.isEditing, required this.isEditing,
required this.dataController, required this.dataController,
required this.cellBuilder, required this.cellBuilder,
@ -43,6 +45,7 @@ class _BoardCardState extends State<BoardCard> {
void initState() { void initState() {
_cardBloc = BoardCardBloc( _cardBloc = BoardCardBloc(
gridId: widget.gridId, gridId: widget.gridId,
fieldId: widget.fieldId,
dataController: widget.dataController, dataController: widget.dataController,
)..add(const BoardCardEvent.initial()); )..add(const BoardCardEvent.initial());
super.initState(); super.initState();
@ -53,6 +56,9 @@ class _BoardCardState extends State<BoardCard> {
return BlocProvider.value( return BlocProvider.value(
value: _cardBloc, value: _cardBloc,
child: BlocBuilder<BoardCardBloc, BoardCardState>( child: BlocBuilder<BoardCardBloc, BoardCardState>(
buildWhen: (previous, current) {
return previous.cells.length != current.cells.length;
},
builder: (context, state) { builder: (context, state) {
return BoardCardContainer( return BoardCardContainer(
accessoryBuilder: (context) { accessoryBuilder: (context) {
@ -62,7 +68,10 @@ class _BoardCardState extends State<BoardCard> {
widget.openCard(context); widget.openCard(context);
}, },
child: Column( 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) { List<Widget> _makeCells(
return cellMap.values.map( BuildContext context,
(cellId) { List<GridCellIdentifier> cells,
) {
return cells.map(
(GridCellIdentifier cellId) {
final child = widget.cellBuilder.buildCell(widget.groupId, cellId); final child = widget.cellBuilder.buildCell(widget.groupId, cellId);
return Padding( return Padding(
padding: const EdgeInsets.only(left: 4, right: 4, top: 6), 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::entities::revision::Revision;
use flowy_sync::errors::CollaborateResult; use flowy_sync::errors::CollaborateResult;
use flowy_sync::util::make_text_delta_from_revisions; 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::collections::HashMap;
use std::sync::Arc; use std::sync::Arc;
@ -591,13 +591,11 @@ impl GridRevisionEditor {
match self.block_manager.get_row_rev(&from_row_id).await? { 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), None => tracing::warn!("Move row failed, can not find the row:{}", from_row_id),
Some(row_rev) => { Some(row_rev) => {
if let Some(row_changeset) = self let block_manager = self.block_manager.clone();
.view_manager self.view_manager
.move_group_row(row_rev, to_group_id, to_row_id.clone()) .move_group_row(row_rev, to_group_id, to_row_id.clone(), |row_changeset| {
.await wrap_future(async move {
{
tracing::trace!("Move group row cause row data changed: {:?}", row_changeset); tracing::trace!("Move group row cause row data changed: {:?}", row_changeset);
let cell_changesets = row_changeset let cell_changesets = row_changeset
.cell_by_field_id .cell_by_field_id
.into_iter() .into_iter()
@ -610,15 +608,16 @@ impl GridRevisionEditor {
.collect::<Vec<CellChangesetPB>>(); .collect::<Vec<CellChangesetPB>>();
for cell_changeset in cell_changesets { for cell_changeset in cell_changesets {
match self.block_manager.update_cell(cell_changeset).await { match block_manager.update_cell(cell_changeset).await {
Ok(_) => {} Ok(_) => {}
Err(e) => tracing::error!("Apply cell changeset error:{:?}", e), Err(e) => tracing::error!("Apply cell changeset error:{:?}", e),
} }
} }
})
})
.await?;
} }
} }
}
Ok(()) Ok(())
} }

View File

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

View File

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