fix(flutter_desktop): board card rebuild issue (#6424)

This commit is contained in:
Richard Shiue 2024-09-29 11:34:45 +08:00 committed by GitHub
parent 99c81fed56
commit 99c7252a15
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 130 additions and 71 deletions

View File

@ -125,7 +125,7 @@ class _RowCardState extends State<RowCard> {
Widget build(BuildContext context) {
return BlocProvider.value(
value: _cardBloc,
child: BlocConsumer<CardBloc, CardState>(
child: BlocListener<CardBloc, CardState>(
listenWhen: (previous, current) =>
previous.isEditing != current.isEditing,
listener: (context, state) {
@ -133,27 +133,30 @@ class _RowCardState extends State<RowCard> {
widget.onEndEditing();
}
},
builder: (context, state) =>
UniversalPlatform.isMobile ? _mobile(state) : _desktop(state),
child: UniversalPlatform.isMobile ? _mobile() : _desktop(),
),
);
}
Widget _mobile(CardState state) {
return GestureDetector(
onTap: () => widget.onTap(context),
behavior: HitTestBehavior.opaque,
child: MobileCardContent(
userProfile: widget.userProfile,
rowMeta: state.rowMeta,
cellBuilder: widget.cellBuilder,
styleConfiguration: widget.styleConfiguration,
cells: state.cells,
),
Widget _mobile() {
return BlocBuilder<CardBloc, CardState>(
builder: (context, state) {
return GestureDetector(
onTap: () => widget.onTap(context),
behavior: HitTestBehavior.opaque,
child: MobileCardContent(
userProfile: widget.userProfile,
rowMeta: state.rowMeta,
cellBuilder: widget.cellBuilder,
styleConfiguration: widget.styleConfiguration,
cells: state.cells,
),
);
},
);
}
Widget _desktop(CardState state) {
Widget _desktop() {
final accessories = widget.styleConfiguration.showAccessory
? const <CardAccessory>[
EditCardAccessory(),
@ -170,20 +173,29 @@ class _RowCardState extends State<RowCard> {
rowId: _cardBloc.rowController.rowId,
groupId: widget.groupId,
),
child: RowCardContainer(
buildAccessoryWhen: () => state.isEditing == false,
accessories: accessories ?? [],
openAccessory: _handleOpenAccessory,
onTap: widget.onTap,
onShiftTap: widget.onShiftTap,
child: _CardContent(
rowMeta: state.rowMeta,
cellBuilder: widget.cellBuilder,
styleConfiguration: widget.styleConfiguration,
cells: state.cells,
userProfile: widget.userProfile,
isCompact: widget.isCompact,
),
child: Builder(
builder: (context) {
return RowCardContainer(
buildAccessoryWhen: () =>
!context.watch<CardBloc>().state.isEditing,
accessories: accessories ?? [],
openAccessory: _handleOpenAccessory,
onTap: widget.onTap,
onShiftTap: widget.onShiftTap,
child: BlocBuilder<CardBloc, CardState>(
builder: (context, state) {
return _CardContent(
rowMeta: state.rowMeta,
cellBuilder: widget.cellBuilder,
styleConfiguration: widget.styleConfiguration,
cells: state.cells,
userProfile: widget.userProfile,
isCompact: widget.isCompact,
);
},
),
);
},
),
);
}
@ -250,25 +262,75 @@ class _CardContent extends StatelessWidget {
RowMetaPB rowMeta,
List<CellMeta> cells,
) {
return cells.mapIndexed((int index, CellMeta cellMeta) {
EditableCardNotifier? cellNotifier;
return cells
.mapIndexed(
(int index, CellMeta cellMeta) => _CardContentCell(
cellBuilder: cellBuilder,
cellMeta: cellMeta,
rowMeta: rowMeta,
isTitle: index == 0,
styleMap: styleConfiguration.cellStyleMap,
),
)
.toList();
}
}
if (index == 0) {
final bloc = context.read<CardBloc>();
cellNotifier = EditableCardNotifier(isEditing: bloc.state.isEditing);
cellNotifier.isCellEditing.addListener(() {
final isEditing = cellNotifier!.isCellEditing.value;
bloc.add(CardEvent.setIsEditing(isEditing));
});
}
class _CardContentCell extends StatefulWidget {
const _CardContentCell({
required this.cellBuilder,
required this.cellMeta,
required this.rowMeta,
required this.isTitle,
required this.styleMap,
});
return cellBuilder.build(
cellContext: cellMeta.cellContext(),
final CellMeta cellMeta;
final RowMetaPB rowMeta;
final CardCellBuilder cellBuilder;
final CardCellStyleMap styleMap;
final bool isTitle;
@override
State<_CardContentCell> createState() => _CardContentCellState();
}
class _CardContentCellState extends State<_CardContentCell> {
late final EditableCardNotifier? cellNotifier;
@override
void initState() {
super.initState();
cellNotifier = widget.isTitle ? EditableCardNotifier() : null;
cellNotifier?.isCellEditing.addListener(listener);
}
void listener() {
final isEditing = cellNotifier!.isCellEditing.value;
context.read<CardBloc>().add(CardEvent.setIsEditing(isEditing));
}
@override
void dispose() {
cellNotifier?.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return BlocListener<CardBloc, CardState>(
listenWhen: (previous, current) =>
previous.isEditing != current.isEditing,
listener: (context, state) {
cellNotifier?.isCellEditing.value = state.isEditing;
},
child: widget.cellBuilder.build(
cellContext: widget.cellMeta.cellContext(),
styleMap: widget.styleMap,
cellNotifier: cellNotifier,
styleMap: styleConfiguration.cellStyleMap,
hasNotes: !rowMeta.isDocumentEmpty,
);
}).toList();
hasNotes: !widget.rowMeta.isDocumentEmpty,
),
);
}
}

View File

@ -68,7 +68,9 @@ class CardBloc extends Bloc<CardEvent, CardState> {
);
},
setIsEditing: (bool isEditing) {
emit(state.copyWith(isEditing: isEditing));
if (isEditing != state.isEditing) {
emit(state.copyWith(isEditing: isEditing));
}
},
didUpdateRowMeta: (rowMeta) {
emit(state.copyWith(rowMeta: rowMeta));

View File

@ -28,19 +28,8 @@ class RowCardContainer extends StatelessWidget {
create: (_) => _CardContainerNotifier(),
child: Consumer<_CardContainerNotifier>(
builder: (context, notifier, _) {
Widget container = child;
bool shouldBuildAccessory = true;
if (buildAccessoryWhen != null) {
shouldBuildAccessory = buildAccessoryWhen!.call();
}
if (shouldBuildAccessory && accessories.isNotEmpty) {
container = _CardEnterRegion(
accessories: accessories,
onTapAccessory: openAccessory,
child: container,
);
}
final shouldBuildAccessory =
buildAccessoryWhen?.call() ?? true;
return GestureDetector(
behavior: HitTestBehavior.opaque,
@ -53,7 +42,12 @@ class RowCardContainer extends StatelessWidget {
},
child: ConstrainedBox(
constraints: const BoxConstraints(minHeight: 42),
child: container,
child: _CardEnterRegion(
shouldBuildAccessory: shouldBuildAccessory,
accessories: accessories,
onTapAccessory: openAccessory,
child: child,
),
),
);
},
@ -64,11 +58,13 @@ class RowCardContainer extends StatelessWidget {
class _CardEnterRegion extends StatelessWidget {
const _CardEnterRegion({
required this.shouldBuildAccessory,
required this.child,
required this.accessories,
required this.onTapAccessory,
});
final bool shouldBuildAccessory;
final Widget child;
final List<CardAccessory> accessories;
final void Function(AccessoryType) onTapAccessory;
@ -78,9 +74,9 @@ class _CardEnterRegion extends StatelessWidget {
return Selector<_CardContainerNotifier, bool>(
selector: (context, notifier) => notifier.onEnter,
builder: (context, onEnter, _) {
final List<Widget> children = [child];
if (onEnter) {
children.add(
final List<Widget> children = [
child,
if (onEnter && shouldBuildAccessory)
Positioned(
top: 10.0,
right: 10.0,
@ -89,8 +85,7 @@ class _CardEnterRegion extends StatelessWidget {
onTapAccessory: onTapAccessory,
),
),
);
}
];
return MouseRegion(
cursor: SystemMouseCursors.click,

View File

@ -1559,10 +1559,10 @@ packages:
dependency: transitive
description:
name: platform
sha256: "9b71283fc13df574056616011fb138fd3b793ea47cc509c189a6c3fa5f8a1a65"
sha256: "12220bb4b65720483f8fa9450b4332347737cf8213dd2840d8b2c823e47243ec"
url: "https://pub.dev"
source: hosted
version: "3.1.5"
version: "3.1.4"
plugin_platform_interface:
dependency: "direct dev"
description:
@ -1989,10 +1989,10 @@ packages:
dependency: transitive
description:
name: string_scanner
sha256: "688af5ed3402a4bde5b3a6c15fd768dbf2621a614950b17f04626c431ab3c4c3"
sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde"
url: "https://pub.dev"
source: hosted
version: "1.3.0"
version: "1.2.0"
string_validator:
dependency: "direct main"
description:
@ -2311,10 +2311,10 @@ packages:
dependency: transitive
description:
name: vm_service
sha256: "5c5f338a667b4c644744b661f309fb8080bb94b18a7e91ef1dbd343bed00ed6d"
sha256: "3923c89304b715fb1eb6423f017651664a03bf5f4b29983627c4da791f74a4ec"
url: "https://pub.dev"
source: hosted
version: "14.2.5"
version: "14.2.1"
watcher:
dependency: transitive
description: