From 86e2091ccfd839802c63508904890aa55f4c62b4 Mon Sep 17 00:00:00 2001 From: appflowy Date: Tue, 6 Sep 2022 20:43:49 +0800 Subject: [PATCH] fix: reduce rebuild while editing text field --- .../plugins/board/application/board_bloc.dart | 1 - .../board/application/card/card_bloc.dart | 25 +++++---- .../board/presentation/board_page.dart | 10 +++- .../presentation/card/board_text_cell.dart | 55 +++++++++++++------ .../plugins/board/presentation/card/card.dart | 6 +- 5 files changed, 64 insertions(+), 33 deletions(-) diff --git a/frontend/app_flowy/lib/plugins/board/application/board_bloc.dart b/frontend/app_flowy/lib/plugins/board/application/board_bloc.dart index 903df92f78..673c159c8d 100644 --- a/frontend/app_flowy/lib/plugins/board/application/board_bloc.dart +++ b/frontend/app_flowy/lib/plugins/board/application/board_bloc.dart @@ -99,7 +99,6 @@ class BoardBloc extends Bloc { )); }, endEditRow: (rowId) { - assert(state.editingRow.isSome()); state.editingRow.fold(() => null, (editingRow) { assert(editingRow.row.id == rowId); emit(state.copyWith(editingRow: none())); diff --git a/frontend/app_flowy/lib/plugins/board/application/card/card_bloc.dart b/frontend/app_flowy/lib/plugins/board/application/card/card_bloc.dart index 99b2a654e9..dee87d9e99 100644 --- a/frontend/app_flowy/lib/plugins/board/application/card/card_bloc.dart +++ b/frontend/app_flowy/lib/plugins/board/application/card/card_bloc.dart @@ -77,7 +77,7 @@ class BoardCardBloc extends Bloc { } } -UnmodifiableListView _makeCells( +List _makeCells( String groupFieldId, GridCellMap originalCellMap) { List cells = []; for (final entry in originalCellMap.entries) { @@ -86,14 +86,14 @@ UnmodifiableListView _makeCells( cells.add(BoardCellEquatable(entry.value)); } } - return UnmodifiableListView(cells); + return cells; } @freezed class BoardCardEvent with _$BoardCardEvent { const factory BoardCardEvent.initial() = _InitialRow; const factory BoardCardEvent.didReceiveCells( - UnmodifiableListView cells, + List cells, RowsChangedReason reason, ) = _DidReceiveCells; } @@ -102,12 +102,11 @@ class BoardCardEvent with _$BoardCardEvent { class BoardCardState with _$BoardCardState { const factory BoardCardState({ required RowPB rowPB, - required UnmodifiableListView cells, + required List cells, RowsChangedReason? changeReason, }) = _BoardCardState; - factory BoardCardState.initial( - RowPB rowPB, UnmodifiableListView cells) => + factory BoardCardState.initial(RowPB rowPB, List cells) => BoardCardState( rowPB: rowPB, cells: cells, @@ -120,10 +119,12 @@ class BoardCellEquatable extends Equatable { const BoardCellEquatable(this.identifier); @override - List get props => [ - identifier.fieldContext.id, - identifier.fieldContext.fieldType, - identifier.fieldContext.visibility, - identifier.fieldContext.width, - ]; + List get props { + return [ + identifier.fieldContext.id, + identifier.fieldContext.fieldType, + identifier.fieldContext.visibility, + identifier.fieldContext.width, + ]; + } } diff --git a/frontend/app_flowy/lib/plugins/board/presentation/board_page.dart b/frontend/app_flowy/lib/plugins/board/presentation/board_page.dart index d40a2f5ea9..b5005d0c74 100644 --- a/frontend/app_flowy/lib/plugins/board/presentation/board_page.dart +++ b/frontend/app_flowy/lib/plugins/board/presentation/board_page.dart @@ -63,6 +63,7 @@ class BoardContent extends StatefulWidget { class _BoardContentState extends State { late AppFlowyBoardScrollController scrollManager; + final Map cardKeysCache = {}; final config = AppFlowyBoardConfig( groupBackgroundColor: HexColor.fromHex('#F7F8FC'), @@ -239,8 +240,15 @@ class _BoardContentState extends State { }, ); + ValueKey? key = cardKeysCache[columnItem.id]; + if (key == null) { + final newKey = ValueKey(columnItem.id); + cardKeysCache[columnItem.id] = newKey; + key = newKey; + } + return AppFlowyGroupCard( - key: ValueKey(columnItem.id), + key: key, margin: config.cardPadding, decoration: _makeBoxDecoration(context), child: BoardCard( diff --git a/frontend/app_flowy/lib/plugins/board/presentation/card/board_text_cell.dart b/frontend/app_flowy/lib/plugins/board/presentation/card/board_text_cell.dart index 99be8cdb3d..c6a6fb13cc 100644 --- a/frontend/app_flowy/lib/plugins/board/presentation/card/board_text_cell.dart +++ b/frontend/app_flowy/lib/plugins/board/presentation/card/board_text_cell.dart @@ -56,7 +56,11 @@ class _BoardTextCellState extends State { } } }); + _bindEditableNotifier(); + super.initState(); + } + void _bindEditableNotifier() { widget.editableNotifier?.becomeFirstResponder.addListener(() { if (!mounted) return; WidgetsBinding.instance.addPostFrameCallback((_) { @@ -69,8 +73,12 @@ class _BoardTextCellState extends State { if (!mounted) return; _cellBloc.add(const BoardTextCellEvent.enableEdit(false)); }); + } - super.initState(); + @override + void didUpdateWidget(covariant BoardTextCell oldWidget) { + _bindEditableNotifier(); + super.didUpdateWidget(oldWidget); } @override @@ -84,6 +92,15 @@ class _BoardTextCellState extends State { } }, child: BlocBuilder( + buildWhen: (previous, current) { + if (previous.content != current.content && + _controller.text == current.content && + current.enableEdit) { + return false; + } + + return previous != current; + }, builder: (context, state) { if (state.content.isEmpty && state.enableEdit == false && @@ -127,24 +144,26 @@ class _BoardTextCellState extends State { } Widget _buildTextField() { - return TextField( - controller: _controller, - focusNode: focusNode, - onChanged: (value) => focusChanged(), - onEditingComplete: () => focusNode.unfocus(), - maxLines: 1, - style: const TextStyle( - fontSize: 14, - fontWeight: FontWeight.w500, - fontFamily: 'Mulish', - ), - decoration: InputDecoration( - // Magic number 4 makes the textField take up the same space as FlowyText - contentPadding: EdgeInsets.symmetric( - vertical: BoardSizes.cardCellVPadding + 4, + return IntrinsicHeight( + child: TextField( + controller: _controller, + focusNode: focusNode, + onChanged: (value) => focusChanged(), + onEditingComplete: () => focusNode.unfocus(), + maxLines: null, + style: const TextStyle( + fontSize: 14, + fontWeight: FontWeight.w500, + fontFamily: 'Mulish', + ), + decoration: InputDecoration( + // Magic number 4 makes the textField take up the same space as FlowyText + contentPadding: EdgeInsets.symmetric( + vertical: BoardSizes.cardCellVPadding + 4, + ), + border: InputBorder.none, + isDense: true, ), - border: InputBorder.none, - isDense: true, ), ); } diff --git a/frontend/app_flowy/lib/plugins/board/presentation/card/card.dart b/frontend/app_flowy/lib/plugins/board/presentation/card/card.dart index ee595dad25..cd088a3d5b 100644 --- a/frontend/app_flowy/lib/plugins/board/presentation/card/card.dart +++ b/frontend/app_flowy/lib/plugins/board/presentation/card/card.dart @@ -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/theme.dart'; import 'package:flowy_infra_ui/flowy_infra_ui_web.dart'; +import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'board_cell.dart'; @@ -56,7 +57,10 @@ class _BoardCardState extends State { value: _cardBloc, child: BlocBuilder( 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) { return BoardCardContainer(