Skip to content

Commit 86e2091

Browse files
committed
fix: reduce rebuild while editing text field
1 parent 3ae2818 commit 86e2091

File tree

5 files changed

+64
-33
lines changed

5 files changed

+64
-33
lines changed

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

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,6 @@ class BoardBloc extends Bloc<BoardEvent, BoardState> {
9999
));
100100
},
101101
endEditRow: (rowId) {
102-
assert(state.editingRow.isSome());
103102
state.editingRow.fold(() => null, (editingRow) {
104103
assert(editingRow.row.id == rowId);
105104
emit(state.copyWith(editingRow: none()));

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

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ class BoardCardBloc extends Bloc<BoardCardEvent, BoardCardState> {
7777
}
7878
}
7979

80-
UnmodifiableListView<BoardCellEquatable> _makeCells(
80+
List<BoardCellEquatable> _makeCells(
8181
String groupFieldId, GridCellMap originalCellMap) {
8282
List<BoardCellEquatable> cells = [];
8383
for (final entry in originalCellMap.entries) {
@@ -86,14 +86,14 @@ UnmodifiableListView<BoardCellEquatable> _makeCells(
8686
cells.add(BoardCellEquatable(entry.value));
8787
}
8888
}
89-
return UnmodifiableListView(cells);
89+
return cells;
9090
}
9191

9292
@freezed
9393
class BoardCardEvent with _$BoardCardEvent {
9494
const factory BoardCardEvent.initial() = _InitialRow;
9595
const factory BoardCardEvent.didReceiveCells(
96-
UnmodifiableListView<BoardCellEquatable> cells,
96+
List<BoardCellEquatable> cells,
9797
RowsChangedReason reason,
9898
) = _DidReceiveCells;
9999
}
@@ -102,12 +102,11 @@ class BoardCardEvent with _$BoardCardEvent {
102102
class BoardCardState with _$BoardCardState {
103103
const factory BoardCardState({
104104
required RowPB rowPB,
105-
required UnmodifiableListView<BoardCellEquatable> cells,
105+
required List<BoardCellEquatable> cells,
106106
RowsChangedReason? changeReason,
107107
}) = _BoardCardState;
108108

109-
factory BoardCardState.initial(
110-
RowPB rowPB, UnmodifiableListView<BoardCellEquatable> cells) =>
109+
factory BoardCardState.initial(RowPB rowPB, List<BoardCellEquatable> cells) =>
111110
BoardCardState(
112111
rowPB: rowPB,
113112
cells: cells,
@@ -120,10 +119,12 @@ class BoardCellEquatable extends Equatable {
120119
const BoardCellEquatable(this.identifier);
121120

122121
@override
123-
List<Object?> get props => [
124-
identifier.fieldContext.id,
125-
identifier.fieldContext.fieldType,
126-
identifier.fieldContext.visibility,
127-
identifier.fieldContext.width,
128-
];
122+
List<Object?> get props {
123+
return [
124+
identifier.fieldContext.id,
125+
identifier.fieldContext.fieldType,
126+
identifier.fieldContext.visibility,
127+
identifier.fieldContext.width,
128+
];
129+
}
129130
}

frontend/app_flowy/lib/plugins/board/presentation/board_page.dart

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ class BoardContent extends StatefulWidget {
6363

6464
class _BoardContentState extends State<BoardContent> {
6565
late AppFlowyBoardScrollController scrollManager;
66+
final Map<String, ValueKey> cardKeysCache = {};
6667

6768
final config = AppFlowyBoardConfig(
6869
groupBackgroundColor: HexColor.fromHex('#F7F8FC'),
@@ -239,8 +240,15 @@ class _BoardContentState extends State<BoardContent> {
239240
},
240241
);
241242

243+
ValueKey? key = cardKeysCache[columnItem.id];
244+
if (key == null) {
245+
final newKey = ValueKey(columnItem.id);
246+
cardKeysCache[columnItem.id] = newKey;
247+
key = newKey;
248+
}
249+
242250
return AppFlowyGroupCard(
243-
key: ValueKey(columnItem.id),
251+
key: key,
244252
margin: config.cardPadding,
245253
decoration: _makeBoxDecoration(context),
246254
child: BoardCard(

frontend/app_flowy/lib/plugins/board/presentation/card/board_text_cell.dart

Lines changed: 37 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,11 @@ class _BoardTextCellState extends State<BoardTextCell> {
5656
}
5757
}
5858
});
59+
_bindEditableNotifier();
60+
super.initState();
61+
}
5962

63+
void _bindEditableNotifier() {
6064
widget.editableNotifier?.becomeFirstResponder.addListener(() {
6165
if (!mounted) return;
6266
WidgetsBinding.instance.addPostFrameCallback((_) {
@@ -69,8 +73,12 @@ class _BoardTextCellState extends State<BoardTextCell> {
6973
if (!mounted) return;
7074
_cellBloc.add(const BoardTextCellEvent.enableEdit(false));
7175
});
76+
}
7277

73-
super.initState();
78+
@override
79+
void didUpdateWidget(covariant BoardTextCell oldWidget) {
80+
_bindEditableNotifier();
81+
super.didUpdateWidget(oldWidget);
7482
}
7583

7684
@override
@@ -84,6 +92,15 @@ class _BoardTextCellState extends State<BoardTextCell> {
8492
}
8593
},
8694
child: BlocBuilder<BoardTextCellBloc, BoardTextCellState>(
95+
buildWhen: (previous, current) {
96+
if (previous.content != current.content &&
97+
_controller.text == current.content &&
98+
current.enableEdit) {
99+
return false;
100+
}
101+
102+
return previous != current;
103+
},
87104
builder: (context, state) {
88105
if (state.content.isEmpty &&
89106
state.enableEdit == false &&
@@ -127,24 +144,26 @@ class _BoardTextCellState extends State<BoardTextCell> {
127144
}
128145

129146
Widget _buildTextField() {
130-
return TextField(
131-
controller: _controller,
132-
focusNode: focusNode,
133-
onChanged: (value) => focusChanged(),
134-
onEditingComplete: () => focusNode.unfocus(),
135-
maxLines: 1,
136-
style: const TextStyle(
137-
fontSize: 14,
138-
fontWeight: FontWeight.w500,
139-
fontFamily: 'Mulish',
140-
),
141-
decoration: InputDecoration(
142-
// Magic number 4 makes the textField take up the same space as FlowyText
143-
contentPadding: EdgeInsets.symmetric(
144-
vertical: BoardSizes.cardCellVPadding + 4,
147+
return IntrinsicHeight(
148+
child: TextField(
149+
controller: _controller,
150+
focusNode: focusNode,
151+
onChanged: (value) => focusChanged(),
152+
onEditingComplete: () => focusNode.unfocus(),
153+
maxLines: null,
154+
style: const TextStyle(
155+
fontSize: 14,
156+
fontWeight: FontWeight.w500,
157+
fontFamily: 'Mulish',
158+
),
159+
decoration: InputDecoration(
160+
// Magic number 4 makes the textField take up the same space as FlowyText
161+
contentPadding: EdgeInsets.symmetric(
162+
vertical: BoardSizes.cardCellVPadding + 4,
163+
),
164+
border: InputBorder.none,
165+
isDense: true,
145166
),
146-
border: InputBorder.none,
147-
isDense: true,
148167
),
149168
);
150169
}

frontend/app_flowy/lib/plugins/board/presentation/card/card.dart

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import 'package:app_flowy/plugins/grid/presentation/widgets/row/row_action_sheet
55
import 'package:flowy_infra/image.dart';
66
import 'package:flowy_infra/theme.dart';
77
import 'package:flowy_infra_ui/flowy_infra_ui_web.dart';
8+
import 'package:flutter/foundation.dart';
89
import 'package:flutter/material.dart';
910
import 'package:flutter_bloc/flutter_bloc.dart';
1011
import 'board_cell.dart';
@@ -56,7 +57,10 @@ class _BoardCardState extends State<BoardCard> {
5657
value: _cardBloc,
5758
child: BlocBuilder<BoardCardBloc, BoardCardState>(
5859
buildWhen: (previous, current) {
59-
return previous.cells != current.cells;
60+
if (previous.cells.length != current.cells.length) {
61+
return true;
62+
}
63+
return !listEquals(previous.cells, current.cells);
6064
},
6165
builder: (context, state) {
6266
return BoardCardContainer(

0 commit comments

Comments
 (0)