fix: reduce rebuild while editing text field

This commit is contained in:
appflowy 2022-09-06 20:43:49 +08:00
parent 3ae28186e8
commit 86e2091ccf
5 changed files with 64 additions and 33 deletions

View File

@ -99,7 +99,6 @@ class BoardBloc extends Bloc<BoardEvent, BoardState> {
)); ));
}, },
endEditRow: (rowId) { endEditRow: (rowId) {
assert(state.editingRow.isSome());
state.editingRow.fold(() => null, (editingRow) { state.editingRow.fold(() => null, (editingRow) {
assert(editingRow.row.id == rowId); assert(editingRow.row.id == rowId);
emit(state.copyWith(editingRow: none())); emit(state.copyWith(editingRow: none()));

View File

@ -77,7 +77,7 @@ class BoardCardBloc extends Bloc<BoardCardEvent, BoardCardState> {
} }
} }
UnmodifiableListView<BoardCellEquatable> _makeCells( List<BoardCellEquatable> _makeCells(
String groupFieldId, GridCellMap originalCellMap) { String groupFieldId, GridCellMap originalCellMap) {
List<BoardCellEquatable> cells = []; List<BoardCellEquatable> cells = [];
for (final entry in originalCellMap.entries) { for (final entry in originalCellMap.entries) {
@ -86,14 +86,14 @@ UnmodifiableListView<BoardCellEquatable> _makeCells(
cells.add(BoardCellEquatable(entry.value)); cells.add(BoardCellEquatable(entry.value));
} }
} }
return UnmodifiableListView(cells); return 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(
UnmodifiableListView<BoardCellEquatable> cells, List<BoardCellEquatable> cells,
RowsChangedReason reason, RowsChangedReason reason,
) = _DidReceiveCells; ) = _DidReceiveCells;
} }
@ -102,12 +102,11 @@ class BoardCardEvent with _$BoardCardEvent {
class BoardCardState with _$BoardCardState { class BoardCardState with _$BoardCardState {
const factory BoardCardState({ const factory BoardCardState({
required RowPB rowPB, required RowPB rowPB,
required UnmodifiableListView<BoardCellEquatable> cells, required List<BoardCellEquatable> cells,
RowsChangedReason? changeReason, RowsChangedReason? changeReason,
}) = _BoardCardState; }) = _BoardCardState;
factory BoardCardState.initial( factory BoardCardState.initial(RowPB rowPB, List<BoardCellEquatable> cells) =>
RowPB rowPB, UnmodifiableListView<BoardCellEquatable> cells) =>
BoardCardState( BoardCardState(
rowPB: rowPB, rowPB: rowPB,
cells: cells, cells: cells,
@ -120,10 +119,12 @@ class BoardCellEquatable extends Equatable {
const BoardCellEquatable(this.identifier); const BoardCellEquatable(this.identifier);
@override @override
List<Object?> get props => [ List<Object?> get props {
return [
identifier.fieldContext.id, identifier.fieldContext.id,
identifier.fieldContext.fieldType, identifier.fieldContext.fieldType,
identifier.fieldContext.visibility, identifier.fieldContext.visibility,
identifier.fieldContext.width, identifier.fieldContext.width,
]; ];
} }
}

View File

@ -63,6 +63,7 @@ class BoardContent extends StatefulWidget {
class _BoardContentState extends State<BoardContent> { class _BoardContentState extends State<BoardContent> {
late AppFlowyBoardScrollController scrollManager; late AppFlowyBoardScrollController scrollManager;
final Map<String, ValueKey> cardKeysCache = {};
final config = AppFlowyBoardConfig( final config = AppFlowyBoardConfig(
groupBackgroundColor: HexColor.fromHex('#F7F8FC'), groupBackgroundColor: HexColor.fromHex('#F7F8FC'),
@ -239,8 +240,15 @@ class _BoardContentState extends State<BoardContent> {
}, },
); );
ValueKey? key = cardKeysCache[columnItem.id];
if (key == null) {
final newKey = ValueKey(columnItem.id);
cardKeysCache[columnItem.id] = newKey;
key = newKey;
}
return AppFlowyGroupCard( return AppFlowyGroupCard(
key: ValueKey(columnItem.id), key: key,
margin: config.cardPadding, margin: config.cardPadding,
decoration: _makeBoxDecoration(context), decoration: _makeBoxDecoration(context),
child: BoardCard( child: BoardCard(

View File

@ -56,7 +56,11 @@ class _BoardTextCellState extends State<BoardTextCell> {
} }
} }
}); });
_bindEditableNotifier();
super.initState();
}
void _bindEditableNotifier() {
widget.editableNotifier?.becomeFirstResponder.addListener(() { widget.editableNotifier?.becomeFirstResponder.addListener(() {
if (!mounted) return; if (!mounted) return;
WidgetsBinding.instance.addPostFrameCallback((_) { WidgetsBinding.instance.addPostFrameCallback((_) {
@ -69,8 +73,12 @@ class _BoardTextCellState extends State<BoardTextCell> {
if (!mounted) return; if (!mounted) return;
_cellBloc.add(const BoardTextCellEvent.enableEdit(false)); _cellBloc.add(const BoardTextCellEvent.enableEdit(false));
}); });
}
super.initState(); @override
void didUpdateWidget(covariant BoardTextCell oldWidget) {
_bindEditableNotifier();
super.didUpdateWidget(oldWidget);
} }
@override @override
@ -84,6 +92,15 @@ class _BoardTextCellState extends State<BoardTextCell> {
} }
}, },
child: BlocBuilder<BoardTextCellBloc, BoardTextCellState>( child: BlocBuilder<BoardTextCellBloc, BoardTextCellState>(
buildWhen: (previous, current) {
if (previous.content != current.content &&
_controller.text == current.content &&
current.enableEdit) {
return false;
}
return previous != current;
},
builder: (context, state) { builder: (context, state) {
if (state.content.isEmpty && if (state.content.isEmpty &&
state.enableEdit == false && state.enableEdit == false &&
@ -127,12 +144,13 @@ class _BoardTextCellState extends State<BoardTextCell> {
} }
Widget _buildTextField() { Widget _buildTextField() {
return TextField( return IntrinsicHeight(
child: TextField(
controller: _controller, controller: _controller,
focusNode: focusNode, focusNode: focusNode,
onChanged: (value) => focusChanged(), onChanged: (value) => focusChanged(),
onEditingComplete: () => focusNode.unfocus(), onEditingComplete: () => focusNode.unfocus(),
maxLines: 1, maxLines: null,
style: const TextStyle( style: const TextStyle(
fontSize: 14, fontSize: 14,
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
@ -146,6 +164,7 @@ class _BoardTextCellState extends State<BoardTextCell> {
border: InputBorder.none, border: InputBorder.none,
isDense: true, isDense: true,
), ),
),
); );
} }
} }

View File

@ -5,6 +5,7 @@ import 'package:app_flowy/plugins/grid/presentation/widgets/row/row_action_sheet
import 'package:flowy_infra/image.dart'; import 'package:flowy_infra/image.dart';
import 'package:flowy_infra/theme.dart'; import 'package:flowy_infra/theme.dart';
import 'package:flowy_infra_ui/flowy_infra_ui_web.dart'; import 'package:flowy_infra_ui/flowy_infra_ui_web.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'board_cell.dart'; import 'board_cell.dart';
@ -56,7 +57,10 @@ class _BoardCardState extends State<BoardCard> {
value: _cardBloc, value: _cardBloc,
child: BlocBuilder<BoardCardBloc, BoardCardState>( child: BlocBuilder<BoardCardBloc, BoardCardState>(
buildWhen: (previous, current) { buildWhen: (previous, current) {
return previous.cells != current.cells; if (previous.cells.length != current.cells.length) {
return true;
}
return !listEquals(previous.cells, current.cells);
}, },
builder: (context, state) { builder: (context, state) {
return BoardCardContainer( return BoardCardContainer(