From 29e7e01146bef4075ab401ebf117943c9640349e Mon Sep 17 00:00:00 2001 From: appflowy Date: Wed, 7 Sep 2022 11:33:42 +0800 Subject: [PATCH] chore: hide edit button when start editing --- .../board/application/card/card_bloc.dart | 15 ++++++- .../board/presentation/card/board_cell.dart | 39 ++++++++++++------- .../presentation/card/board_text_cell.dart | 17 ++++---- .../plugins/board/presentation/card/card.dart | 19 +++++++-- .../presentation/card/card_container.dart | 9 ++++- 5 files changed, 69 insertions(+), 30 deletions(-) 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 dee87d9e99..82372896d1 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 @@ -7,7 +7,6 @@ import 'package:flowy_sdk/protobuf/flowy-grid/block_entities.pb.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; import 'dart:async'; - import 'card_data_controller.dart'; part 'card_bloc.freezed.dart'; @@ -21,6 +20,7 @@ class BoardCardBloc extends Bloc { required this.groupFieldId, required String gridId, required CardDataController dataController, + required bool isEditing, }) : _rowService = RowFFIService( gridId: gridId, blockId: dataController.rowPB.blockId, @@ -30,6 +30,7 @@ class BoardCardBloc extends Bloc { BoardCardState.initial( dataController.rowPB, _makeCells(groupFieldId, dataController.loadData()), + isEditing, ), ) { on( @@ -44,6 +45,9 @@ class BoardCardBloc extends Bloc { changeReason: reason, )); }, + setIsEditing: (bool isEditing) { + emit(state.copyWith(isEditing: isEditing)); + }, ); }, ); @@ -92,6 +96,7 @@ List _makeCells( @freezed class BoardCardEvent with _$BoardCardEvent { const factory BoardCardEvent.initial() = _InitialRow; + const factory BoardCardEvent.setIsEditing(bool isEditing) = _IsEditing; const factory BoardCardEvent.didReceiveCells( List cells, RowsChangedReason reason, @@ -103,13 +108,19 @@ class BoardCardState with _$BoardCardState { const factory BoardCardState({ required RowPB rowPB, required List cells, + required bool isEditing, RowsChangedReason? changeReason, }) = _BoardCardState; - factory BoardCardState.initial(RowPB rowPB, List cells) => + factory BoardCardState.initial( + RowPB rowPB, + List cells, + bool isEditing, + ) => BoardCardState( rowPB: rowPB, cells: cells, + isEditing: isEditing, ); } diff --git a/frontend/app_flowy/lib/plugins/board/presentation/card/board_cell.dart b/frontend/app_flowy/lib/plugins/board/presentation/card/board_cell.dart index 77fc4b0f46..e979b2510e 100644 --- a/frontend/app_flowy/lib/plugins/board/presentation/card/board_cell.dart +++ b/frontend/app_flowy/lib/plugins/board/presentation/card/board_cell.dart @@ -1,5 +1,4 @@ import 'package:app_flowy/plugins/grid/application/prelude.dart'; -import 'package:flowy_infra/notifier.dart'; import 'package:flutter/material.dart'; abstract class FocusableBoardCell { @@ -7,47 +6,57 @@ abstract class FocusableBoardCell { } class EditableCellNotifier { - final Notifier becomeFirstResponder = Notifier(); - - final Notifier resignFirstResponder = Notifier(); - final ValueNotifier isCellEditing; EditableCellNotifier({bool isEditing = false}) : isCellEditing = ValueNotifier(isEditing); void dispose() { - becomeFirstResponder.dispose(); - resignFirstResponder.dispose(); isCellEditing.dispose(); } } class EditableRowNotifier { final Map _cells = {}; + final ValueNotifier isEditing; + + EditableRowNotifier({required bool isEditing}) + : isEditing = ValueNotifier(isEditing); void insertCell( GridCellIdentifier cellIdentifier, EditableCellNotifier notifier, ) { + assert( + _cells.values.isEmpty, + 'Only one cell can receive the notification', + ); final id = EditableCellId.from(cellIdentifier); _cells[id]?.dispose(); - notifier.isCellEditing.addListener(() {}); + notifier.isCellEditing.addListener(() { + isEditing.value = notifier.isCellEditing.value; + }); _cells[EditableCellId.from(cellIdentifier)] = notifier; } void becomeFirstResponder() { - for (final notifier in _cells.values) { - notifier.becomeFirstResponder.notify(); - } + if (_cells.values.isEmpty) return; + assert( + _cells.values.length == 1, + 'Only one cell can receive the notification', + ); + _cells.values.first.isCellEditing.value = true; } void resignFirstResponder() { - for (final notifier in _cells.values) { - notifier.resignFirstResponder.notify(); - } + if (_cells.values.isEmpty) return; + assert( + _cells.values.length == 1, + 'Only one cell can receive the notification', + ); + _cells.values.first.isCellEditing.value = false; } void clear() { @@ -59,7 +68,7 @@ class EditableRowNotifier { void dispose() { for (final notifier in _cells.values) { - notifier.resignFirstResponder.notify(); + notifier.dispose(); } _cells.clear(); 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 08068a8e49..4a48e8fe48 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 @@ -54,17 +54,16 @@ class _BoardTextCellState extends State { } void _bindEditableNotifier() { - widget.editableNotifier?.becomeFirstResponder.addListener(() { + widget.editableNotifier?.isCellEditing.addListener(() { if (!mounted) return; - WidgetsBinding.instance.addPostFrameCallback((_) { - focusNode.requestFocus(); - }); - _cellBloc.add(const BoardTextCellEvent.enableEdit(true)); - }); - widget.editableNotifier?.resignFirstResponder.addListener(() { - if (!mounted) return; - _cellBloc.add(const BoardTextCellEvent.enableEdit(false)); + final isEditing = widget.editableNotifier?.isCellEditing.value ?? false; + if (isEditing) { + WidgetsBinding.instance.addPostFrameCallback((_) { + focusNode.requestFocus(); + }); + } + _cellBloc.add(BoardTextCellEvent.enableEdit(isEditing)); }); } 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 a2fc7ee7f5..f5111224e1 100644 --- a/frontend/app_flowy/lib/plugins/board/presentation/card/card.dart +++ b/frontend/app_flowy/lib/plugins/board/presentation/card/card.dart @@ -42,12 +42,19 @@ class _BoardCardState extends State { @override void initState() { - rowNotifier = EditableRowNotifier(); + rowNotifier = EditableRowNotifier(isEditing: widget.isEditing); _cardBloc = BoardCardBloc( gridId: widget.gridId, groupFieldId: widget.fieldId, dataController: widget.dataController, + isEditing: widget.isEditing, )..add(const BoardCardEvent.initial()); + + rowNotifier.isEditing.addListener(() { + if (!mounted) return; + _cardBloc.add(BoardCardEvent.setIsEditing(rowNotifier.isEditing.value)); + }); + super.initState(); } @@ -57,13 +64,15 @@ class _BoardCardState extends State { value: _cardBloc, child: BlocBuilder( buildWhen: (previous, current) { - if (previous.cells.length != current.cells.length) { + if (previous.cells.length != current.cells.length || + previous.isEditing != current.isEditing) { return true; } return !listEquals(previous.cells, current.cells); }, builder: (context, state) { return BoardCardContainer( + buildAccessoryWhen: () => state.isEditing == false, accessoryBuilder: (context) { return [ _CardEditOption( @@ -98,7 +107,11 @@ class _BoardCardState extends State { (int index, GridCellIdentifier cellId) { EditableCellNotifier cellNotifier; if (index == 0) { - cellNotifier = EditableCellNotifier(isEditing: widget.isEditing); + // Only use the first cell to receive user's input when click the edit + // button + cellNotifier = EditableCellNotifier( + isEditing: rowNotifier.isEditing.value, + ); rowNotifier.insertCell(cellId, cellNotifier); } else { cellNotifier = EditableCellNotifier(); diff --git a/frontend/app_flowy/lib/plugins/board/presentation/card/card_container.dart b/frontend/app_flowy/lib/plugins/board/presentation/card/card_container.dart index d28e6712c9..7479f3044e 100644 --- a/frontend/app_flowy/lib/plugins/board/presentation/card/card_container.dart +++ b/frontend/app_flowy/lib/plugins/board/presentation/card/card_container.dart @@ -7,11 +7,13 @@ import 'package:styled_widget/styled_widget.dart'; class BoardCardContainer extends StatelessWidget { final Widget child; final CardAccessoryBuilder? accessoryBuilder; + final bool Function()? buildAccessoryWhen; final void Function(BuildContext) onTap; const BoardCardContainer({ required this.child, required this.onTap, this.accessoryBuilder, + this.buildAccessoryWhen, Key? key, }) : super(key: key); @@ -22,7 +24,12 @@ class BoardCardContainer extends StatelessWidget { child: Consumer<_CardContainerNotifier>( builder: (context, notifier, _) { Widget container = Center(child: child); - if (accessoryBuilder != null) { + bool shouldBuildAccessory = true; + if (buildAccessoryWhen != null) { + shouldBuildAccessory = buildAccessoryWhen!.call(); + } + + if (accessoryBuilder != null && shouldBuildAccessory) { final accessories = accessoryBuilder!(context); if (accessories.isNotEmpty) { container = _CardEnterRegion(