From f3544375c98c867269460a0d96a4ca8f98d80fa4 Mon Sep 17 00:00:00 2001 From: Richard Shiue <71320345+richardshiue@users.noreply.github.com> Date: Tue, 30 Apr 2024 17:35:03 +0800 Subject: [PATCH] fix: kanban UX bugs (#5227) * chore: improve title editing behavior * chore: fix editable text field * chore: fix autoscroll --- .../android/app/src/main/Classes/binding.h | 2 + .../desktop/board/board_add_row_test.dart | 53 +++++---- .../desktop/board/board_group_test.dart | 4 +- .../application/cell/cell_controller.dart | 5 + .../application/field/field_cell_bloc.dart | 2 +- .../board/presentation/board_page.dart | 108 ++++++++---------- .../widgets/board_hidden_groups.dart | 6 +- .../presentation/calendar_event_card.dart | 11 +- .../calendar/presentation/calendar_page.dart | 3 +- .../database/grid/presentation/grid_page.dart | 12 +- .../grid/presentation/layout/layout.dart | 3 +- .../calculations/calculations_row.dart | 2 +- .../widgets/footer/grid_footer.dart | 3 +- .../widgets/header/grid_header.dart | 2 +- .../grid/presentation/widgets/row/row.dart | 6 +- .../tab_bar/desktop/tab_bar_header.dart | 2 +- .../database/tab_bar/tab_bar_view.dart | 3 + .../card_cell_skeleton/text_card_cell.dart | 85 +++++++------- .../desktop_board_card_cell_style.dart | 2 +- .../setting/setting_property_list.dart | 3 +- frontend/appflowy_flutter/pubspec.lock | 10 +- frontend/appflowy_flutter/pubspec.yaml | 3 +- 22 files changed, 180 insertions(+), 150 deletions(-) diff --git a/frontend/appflowy_flutter/android/app/src/main/Classes/binding.h b/frontend/appflowy_flutter/android/app/src/main/Classes/binding.h index 77d9b96ec1..78992141ca 100644 --- a/frontend/appflowy_flutter/android/app/src/main/Classes/binding.h +++ b/frontend/appflowy_flutter/android/app/src/main/Classes/binding.h @@ -11,6 +11,8 @@ const uint8_t *sync_event(const uint8_t *input, uintptr_t len); int32_t set_stream_port(int64_t port); +int32_t set_log_stream_port(int64_t port); + void link_me_please(void); void rust_log(int64_t level, const char *data); diff --git a/frontend/appflowy_flutter/integration_test/desktop/board/board_add_row_test.dart b/frontend/appflowy_flutter/integration_test/desktop/board/board_add_row_test.dart index a865c3251a..d850115632 100644 --- a/frontend/appflowy_flutter/integration_test/desktop/board/board_add_row_test.dart +++ b/frontend/appflowy_flutter/integration_test/desktop/board/board_add_row_test.dart @@ -1,6 +1,6 @@ import 'package:appflowy/generated/flowy_svgs.g.dart'; import 'package:appflowy/plugins/database/board/presentation/widgets/board_column_header.dart'; -import 'package:appflowy/plugins/database/widgets/card/container/card_container.dart'; +import 'package:appflowy/plugins/database/widgets/card/card.dart'; import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart'; import 'package:appflowy_board/appflowy_board.dart'; import 'package:flutter/material.dart'; @@ -22,13 +22,15 @@ void main() { await tester.createNewPageWithNameUnderParent(layout: ViewLayoutPB.Board); - final findFirstCard = find.descendant( - of: find.byType(AppFlowyGroupCard), - matching: find.byType(Text), - ); + final firstCard = find.byType(RowCard).first; - Text firstCardText = tester.firstWidget(findFirstCard); - expect(firstCardText.data, defaultFirstCardName); + expect( + find.descendant( + of: firstCard, + matching: find.text(defaultFirstCardName), + ), + findsOneWidget, + ); await tester.tap( find @@ -45,7 +47,7 @@ void main() { const newCardName = 'Card 4'; await tester.enterText( find.descendant( - of: find.byType(RowCardContainer), + of: firstCard, matching: find.byType(TextField), ), newCardName, @@ -55,8 +57,13 @@ void main() { await tester.tap(find.byType(AppFlowyBoard)); await tester.pumpAndSettle(); - firstCardText = tester.firstWidget(findFirstCard); - expect(firstCardText.data, newCardName); + expect( + find.descendant( + of: find.byType(RowCard).first, + matching: find.text(newCardName), + ), + findsOneWidget, + ); }); testWidgets('from footer', (tester) async { @@ -65,13 +72,15 @@ void main() { await tester.createNewPageWithNameUnderParent(layout: ViewLayoutPB.Board); - final findLastCard = find.descendant( - of: find.byType(AppFlowyGroupCard), - matching: find.byType(Text), - ); + final lastCard = find.byType(RowCard).last; - Text? lastCardText = tester.widgetList(findLastCard).last as Text; - expect(lastCardText.data, defaultLastCardName); + expect( + find.descendant( + of: lastCard, + matching: find.text(defaultLastCardName), + ), + findsOneWidget, + ); await tester.tap( find @@ -81,12 +90,11 @@ void main() { ) .at(1), ); - await tester.pumpAndSettle(); const newCardName = 'Card 4'; await tester.enterText( find.descendant( - of: find.byType(RowCardContainer), + of: lastCard, matching: find.byType(TextField), ), newCardName, @@ -96,8 +104,13 @@ void main() { await tester.tap(find.byType(AppFlowyBoard)); await tester.pumpAndSettle(); - lastCardText = tester.widgetList(findLastCard).last as Text; - expect(lastCardText.data, newCardName); + expect( + find.descendant( + of: find.byType(RowCard).last, + matching: find.text(newCardName), + ), + findsOneWidget, + ); }); }); } diff --git a/frontend/appflowy_flutter/integration_test/desktop/board/board_group_test.dart b/frontend/appflowy_flutter/integration_test/desktop/board/board_group_test.dart index 9dff488ead..68848503c4 100644 --- a/frontend/appflowy_flutter/integration_test/desktop/board/board_group_test.dart +++ b/frontend/appflowy_flutter/integration_test/desktop/board/board_group_test.dart @@ -1,10 +1,10 @@ +import 'package:appflowy/plugins/database/widgets/card/card.dart'; import 'package:appflowy/plugins/database/widgets/cell_editor/extension.dart'; import 'package:appflowy/plugins/database/widgets/row/row_property.dart'; import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart'; import 'package:flutter/widgets.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:integration_test/integration_test.dart'; -import 'package:appflowy_board/appflowy_board.dart'; import '../../shared/util.dart'; @@ -20,7 +20,7 @@ void main() { await tester.createNewPageWithNameUnderParent(layout: ViewLayoutPB.Board); final card1 = find.ancestor( of: find.text(card1Name), - matching: find.byType(AppFlowyGroupCard), + matching: find.byType(RowCard), ); final doingGroup = find.text('Doing'); final doingGroupCenter = tester.getCenter(doingGroup); diff --git a/frontend/appflowy_flutter/lib/plugins/database/application/cell/cell_controller.dart b/frontend/appflowy_flutter/lib/plugins/database/application/cell/cell_controller.dart index 426a54da76..858acadc5a 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/application/cell/cell_controller.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/application/cell/cell_controller.dart @@ -68,6 +68,8 @@ class CellController { Timer? _loadDataOperation; Timer? _saveDataOperation; + Completer? _completer; + RowId get rowId => _cellContext.rowId; String get fieldId => _cellContext.fieldId; FieldInfo get fieldInfo => _fieldController.getField(_cellContext.fieldId)!; @@ -192,6 +194,7 @@ class CellController { _loadDataOperation?.cancel(); if (debounce) { _saveDataOperation?.cancel(); + _completer = Completer(); _saveDataOperation = Timer(const Duration(milliseconds: 300), () async { final result = await _cellDataPersistence.save( viewId: viewId, @@ -199,6 +202,7 @@ class CellController { data: data, ); onFinish?.call(result); + _completer?.complete(); }); } else { final result = await _cellDataPersistence.save( @@ -241,6 +245,7 @@ class CellController { ); _loadDataOperation?.cancel(); + await _completer?.future; _saveDataOperation?.cancel(); _cellDataNotifier?.dispose(); _cellDataNotifier = null; diff --git a/frontend/appflowy_flutter/lib/plugins/database/application/field/field_cell_bloc.dart b/frontend/appflowy_flutter/lib/plugins/database/application/field/field_cell_bloc.dart index 1a5a149c9a..5a72fcccc0 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/application/field/field_cell_bloc.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/application/field/field_cell_bloc.dart @@ -59,7 +59,7 @@ class FieldCellState with _$FieldCellState { factory FieldCellState.initial(FieldInfo fieldInfo) => FieldCellState( fieldInfo: fieldInfo, isResizing: false, - width: fieldInfo.fieldSettings!.width.toDouble(), + width: fieldInfo.width!.toDouble(), resizeStart: 0, ); diff --git a/frontend/appflowy_flutter/lib/plugins/database/board/presentation/board_page.dart b/frontend/appflowy_flutter/lib/plugins/database/board/presentation/board_page.dart index fd4621be86..352345e2d2 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/board/presentation/board_page.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/board/presentation/board_page.dart @@ -102,11 +102,12 @@ class BoardPage extends StatelessWidget { )..add(const BoardEvent.initial()), child: BlocBuilder( buildWhen: (p, c) => p.loadingState != c.loadingState, - builder: (context, state) => state.loadingState.map( - loading: (_) => const Center( + builder: (context, state) => state.loadingState.when( + loading: () => const Center( child: CircularProgressIndicator.adaptive(), ), - finish: (result) => result.successOrFail.fold( + idle: () => const SizedBox.shrink(), + finish: (result) => result.fold( (_) => PlatformExtension.isMobile ? const MobileBoardContent() : DesktopBoardContent(onEditStateChanged: onEditStateChanged), @@ -121,7 +122,6 @@ class BoardPage extends StatelessWidget { howToFix: LocaleKeys.errorDialog_howToFixFallback.tr(), ), ), - idle: (_) => const SizedBox.shrink(), ), ), ); @@ -154,6 +154,10 @@ class _DesktopBoardContentState extends State { stretchGroupHeight: false, ); + late final cellBuilder = CardCellBuilder( + databaseController: context.read().databaseController, + ); + @override void dispose() { scrollController.dispose(); @@ -164,7 +168,6 @@ class _DesktopBoardContentState extends State { Widget build(BuildContext context) { return BlocListener( listener: (context, state) { - _handleEditStateChanged(state, context); widget.onEditStateChanged?.call(); }, child: BlocBuilder( @@ -182,7 +185,7 @@ class _DesktopBoardContentState extends State { leading: HiddenGroupsColumn(margin: config.groupHeaderPadding), trailing: showCreateGroupButton ? BoardTrailing(scrollController: scrollController) - : null, + : const HSpace(40), headerBuilder: (_, groupData) => BlocProvider.value( value: context.read(), child: BoardColumnHeader( @@ -203,16 +206,6 @@ class _DesktopBoardContentState extends State { ); } - void _handleEditStateChanged(BoardState state, BuildContext context) { - if (state.isEditingRow && state.editingRow != null) { - WidgetsBinding.instance.addPostFrameCallback((_) { - if (state.editingRow!.index == null) { - scrollManager.scrollToBottom(state.editingRow!.group.groupId); - } - }); - } - } - Widget _buildFooter(BuildContext context, AppFlowyGroupData columnData) { return Padding( padding: config.groupFooterPadding, @@ -257,14 +250,13 @@ class _DesktopBoardContentState extends State { final databaseController = boardBloc.databaseController; final viewId = boardBloc.viewId; - final cellBuilder = CardCellBuilder(databaseController: databaseController); final isEditing = boardBloc.state.isEditingRow && boardBloc.state.editingRow?.row.id == groupItem.row.id; final groupItemId = "${groupData.group.groupId}${groupItem.row.id}"; final rowMeta = rowInfo?.rowMeta ?? groupItem.row; - return AppFlowyGroupCard( + return Container( key: ValueKey(groupItemId), margin: config.cardMargin, decoration: _makeBoxDecoration(context), @@ -412,52 +404,50 @@ class _BoardTrailingState extends State { } }); - return Padding( - padding: const EdgeInsets.only(left: 8.0, top: 12), - child: Align( - alignment: AlignmentDirectional.topStart, - child: AnimatedSwitcher( - duration: const Duration(milliseconds: 300), - child: isEditing - ? SizedBox( - width: 256, - child: Padding( - padding: const EdgeInsets.all(8.0), - child: TextField( - controller: _textController, - focusNode: _focusNode, - decoration: InputDecoration( - suffixIcon: Padding( - padding: const EdgeInsets.only(left: 4, bottom: 8.0), - child: FlowyIconButton( - icon: const FlowySvg(FlowySvgs.close_filled_m), - hoverColor: Colors.transparent, - onPressed: () => _textController.clear(), - ), + return Container( + padding: const EdgeInsets.only(left: 8.0, top: 12, right: 40), + alignment: AlignmentDirectional.topStart, + child: AnimatedSwitcher( + duration: const Duration(milliseconds: 300), + child: isEditing + ? SizedBox( + width: 256, + child: Padding( + padding: const EdgeInsets.all(8.0), + child: TextField( + controller: _textController, + focusNode: _focusNode, + decoration: InputDecoration( + suffixIcon: Padding( + padding: const EdgeInsets.only(left: 4, bottom: 8.0), + child: FlowyIconButton( + icon: const FlowySvg(FlowySvgs.close_filled_m), + hoverColor: Colors.transparent, + onPressed: () => _textController.clear(), ), - suffixIconConstraints: - BoxConstraints.loose(const Size(20, 24)), - border: const UnderlineInputBorder(), - contentPadding: const EdgeInsets.fromLTRB(8, 4, 8, 8), - isDense: true, ), - style: Theme.of(context).textTheme.bodySmall, - onSubmitted: (groupName) => context - .read() - .add(BoardEvent.createGroup(groupName)), + suffixIconConstraints: + BoxConstraints.loose(const Size(20, 24)), + border: const UnderlineInputBorder(), + contentPadding: const EdgeInsets.fromLTRB(8, 4, 8, 8), + isDense: true, ), - ), - ) - : FlowyTooltip( - message: LocaleKeys.board_column_createNewColumn.tr(), - child: FlowyIconButton( - width: 26, - icon: const FlowySvg(FlowySvgs.add_s), - iconColorOnHover: Theme.of(context).colorScheme.onSurface, - onPressed: () => setState(() => isEditing = true), + style: Theme.of(context).textTheme.bodySmall, + onSubmitted: (groupName) => context + .read() + .add(BoardEvent.createGroup(groupName)), ), ), - ), + ) + : FlowyTooltip( + message: LocaleKeys.board_column_createNewColumn.tr(), + child: FlowyIconButton( + width: 26, + icon: const FlowySvg(FlowySvgs.add_s), + iconColorOnHover: Theme.of(context).colorScheme.onSurface, + onPressed: () => setState(() => isEditing = true), + ), + ), ), ); } diff --git a/frontend/appflowy_flutter/lib/plugins/database/board/presentation/widgets/board_hidden_groups.dart b/frontend/appflowy_flutter/lib/plugins/database/board/presentation/widgets/board_hidden_groups.dart index 443046f9a6..1e820af120 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/board/presentation/widgets/board_hidden_groups.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/board/presentation/widgets/board_hidden_groups.dart @@ -45,14 +45,14 @@ class HiddenGroupsColumn extends StatelessWidget { ? SizedBox( height: 50, child: Padding( - padding: const EdgeInsets.only(left: 40, right: 8), + padding: const EdgeInsets.only(left: 80, right: 8), child: Center( child: _collapseExpandIcon(context, isCollapsed), ), ), ) : SizedBox( - width: 234, + width: 274, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -60,7 +60,7 @@ class HiddenGroupsColumn extends StatelessWidget { height: 50, child: Padding( padding: EdgeInsets.only( - left: 40 + margin.left, + left: 80 + margin.left, right: margin.right + 4, ), child: Row( diff --git a/frontend/appflowy_flutter/lib/plugins/database/calendar/presentation/calendar_event_card.dart b/frontend/appflowy_flutter/lib/plugins/database/calendar/presentation/calendar_event_card.dart index 7ef63aff08..c0d283eeb8 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/calendar/presentation/calendar_event_card.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/calendar/presentation/calendar_event_card.dart @@ -167,10 +167,13 @@ class _EventCardState extends State { ), ); }, - child: Container( - padding: widget.padding, - decoration: decoration, - child: card, + child: Material( + color: Colors.transparent, + child: Container( + padding: widget.padding, + decoration: decoration, + child: card, + ), ), ); diff --git a/frontend/appflowy_flutter/lib/plugins/database/calendar/presentation/calendar_page.dart b/frontend/appflowy_flutter/lib/plugins/database/calendar/presentation/calendar_page.dart index 1b33f36e90..9ee1f58016 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/calendar/presentation/calendar_page.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/calendar/presentation/calendar_page.dart @@ -188,7 +188,8 @@ class _CalendarPageState extends State { return Padding( padding: PlatformExtension.isMobile ? CalendarSize.contentInsetsMobile - : CalendarSize.contentInsets, + : CalendarSize.contentInsets + + const EdgeInsets.symmetric(horizontal: 40), child: ScrollConfiguration( behavior: ScrollConfiguration.of(context).copyWith(scrollbars: false), diff --git a/frontend/appflowy_flutter/lib/plugins/database/grid/presentation/grid_page.dart b/frontend/appflowy_flutter/lib/plugins/database/grid/presentation/grid_page.dart index 2225aa96bf..67e238ed51 100755 --- a/frontend/appflowy_flutter/lib/plugins/database/grid/presentation/grid_page.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/grid/presentation/grid_page.dart @@ -154,7 +154,11 @@ class _GridPageState extends State { loading: (_) => const Center(child: CircularProgressIndicator.adaptive()), finish: (result) => result.successOrFail.fold( - (_) => GridShortcuts(child: GridPageContent(view: widget.view)), + (_) => GridShortcuts( + child: GridPageContent( + view: widget.view, + ), + ), (err) => FlowyErrorPage.message( err.toString(), howToFix: LocaleKeys.errorDialog_howToFixFallback.tr(), @@ -234,7 +238,9 @@ class _GridPageContentState extends State { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - _GridHeader(headerScrollController: headerScrollController), + _GridHeader( + headerScrollController: headerScrollController, + ), _GridRows( viewId: widget.view.id, scrollController: _scrollController, @@ -498,7 +504,7 @@ class _PositionedCalculationsRowState left: 0, right: 0, child: Container( - margin: EdgeInsets.only(left: GridSize.horizontalHeaderPadding), + margin: EdgeInsets.only(left: GridSize.horizontalHeaderPadding + 40), padding: const EdgeInsets.only(bottom: 10), decoration: BoxDecoration( color: Theme.of(context).canvasColor, diff --git a/frontend/appflowy_flutter/lib/plugins/database/grid/presentation/layout/layout.dart b/frontend/appflowy_flutter/lib/plugins/database/grid/presentation/layout/layout.dart index 853f83c64d..3c5c9a912c 100755 --- a/frontend/appflowy_flutter/lib/plugins/database/grid/presentation/layout/layout.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/grid/presentation/layout/layout.dart @@ -12,11 +12,12 @@ class GridLayout { element.visibility != null && element.visibility != FieldVisibility.AlwaysHidden, ) - .map((fieldInfo) => fieldInfo.fieldSettings!.width.toDouble()) + .map((fieldInfo) => fieldInfo.width!.toDouble()) .reduce((value, element) => value + element); return fieldsWidth + GridSize.horizontalHeaderPadding + + 40 + GridSize.trailHeaderPadding; } } diff --git a/frontend/appflowy_flutter/lib/plugins/database/grid/presentation/widgets/calculations/calculations_row.dart b/frontend/appflowy_flutter/lib/plugins/database/grid/presentation/widgets/calculations/calculations_row.dart index 9d9255e3a6..7899d5f56d 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/grid/presentation/widgets/calculations/calculations_row.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/grid/presentation/widgets/calculations/calculations_row.dart @@ -37,7 +37,7 @@ class GridCalculationsRow extends StatelessWidget { key: Key( '${field.id}-${state.calculationsByFieldId[field.id]?.id}', ), - width: field.fieldSettings!.width.toDouble(), + width: field.width!.toDouble(), fieldInfo: field, calculation: state.calculationsByFieldId[field.id], ), diff --git a/frontend/appflowy_flutter/lib/plugins/database/grid/presentation/widgets/footer/grid_footer.dart b/frontend/appflowy_flutter/lib/plugins/database/grid/presentation/widgets/footer/grid_footer.dart index 6d6840085e..fa78dd629e 100755 --- a/frontend/appflowy_flutter/lib/plugins/database/grid/presentation/widgets/footer/grid_footer.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/grid/presentation/widgets/footer/grid_footer.dart @@ -42,9 +42,8 @@ class GridRowBottomBar extends StatelessWidget { @override Widget build(BuildContext context) { return Container( - padding: GridSize.footerContentInsets, + padding: GridSize.footerContentInsets + const EdgeInsets.only(left: 40), height: GridSize.footerHeight, - // margin: const EdgeInsets.only(bottom: 8, top: 8), child: const GridAddRowButton(), ); } diff --git a/frontend/appflowy_flutter/lib/plugins/database/grid/presentation/widgets/header/grid_header.dart b/frontend/appflowy_flutter/lib/plugins/database/grid/presentation/widgets/header/grid_header.dart index 4668edc0e9..79ad37c706 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/grid/presentation/widgets/header/grid_header.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/grid/presentation/widgets/header/grid_header.dart @@ -139,7 +139,7 @@ class _GridHeaderState extends State<_GridHeader> { } Widget _cellLeading() { - return SizedBox(width: GridSize.horizontalHeaderPadding); + return SizedBox(width: GridSize.horizontalHeaderPadding + 40); } } diff --git a/frontend/appflowy_flutter/lib/plugins/database/grid/presentation/widgets/row/row.dart b/frontend/appflowy_flutter/lib/plugins/database/grid/presentation/widgets/row/row.dart index 340f613e84..50e48377d4 100755 --- a/frontend/appflowy_flutter/lib/plugins/database/grid/presentation/widgets/row/row.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/grid/presentation/widgets/row/row.dart @@ -112,7 +112,7 @@ class _RowLeadingState extends State<_RowLeading> { child: Consumer( builder: (context, state, _) { return SizedBox( - width: GridSize.horizontalHeaderPadding, + width: GridSize.horizontalHeaderPadding + 40, child: state.onEnter ? _activeWidget() : null, ); }, @@ -122,7 +122,7 @@ class _RowLeadingState extends State<_RowLeading> { Widget _activeWidget() { return Row( - mainAxisAlignment: MainAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.end, children: [ const InsertRowButton(), if (isDraggable) @@ -246,7 +246,7 @@ class RowContent extends StatelessWidget { EditableCellStyle.desktopGrid, ); return CellContainer( - width: fieldInfo.fieldSettings!.width.toDouble(), + width: fieldInfo.width!.toDouble(), isPrimary: fieldInfo.field.isPrimary, accessoryBuilder: (buildContext) { final builder = child.accessoryBuilder; diff --git a/frontend/appflowy_flutter/lib/plugins/database/tab_bar/desktop/tab_bar_header.dart b/frontend/appflowy_flutter/lib/plugins/database/tab_bar/desktop/tab_bar_header.dart index 7fec980112..54a08c1284 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/tab_bar/desktop/tab_bar_header.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/tab_bar/desktop/tab_bar_header.dart @@ -24,7 +24,7 @@ class TabBarHeader extends StatelessWidget { return Container( height: 30, padding: EdgeInsets.symmetric( - horizontal: GridSize.horizontalHeaderPadding, + horizontal: GridSize.horizontalHeaderPadding + 40, ), child: Stack( children: [ diff --git a/frontend/appflowy_flutter/lib/plugins/database/tab_bar/tab_bar_view.dart b/frontend/appflowy_flutter/lib/plugins/database/tab_bar/tab_bar_view.dart index 9dba23f044..d8aa978e12 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/tab_bar/tab_bar_view.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/tab_bar/tab_bar_view.dart @@ -286,4 +286,7 @@ class DatabasePluginWidgetBuilder extends PluginWidgetBuilder { ), ); } + + @override + EdgeInsets get contentPadding => const EdgeInsets.only(top: 28); } diff --git a/frontend/appflowy_flutter/lib/plugins/database/widgets/cell/card_cell_skeleton/text_card_cell.dart b/frontend/appflowy_flutter/lib/plugins/database/widgets/cell/card_cell_skeleton/text_card_cell.dart index 421cf3b761..b7aae4dd58 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/widgets/cell/card_cell_skeleton/text_card_cell.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/widgets/cell/card_cell_skeleton/text_card_cell.dart @@ -83,7 +83,9 @@ class _TextCellState extends State { void _bindEditableNotifier() { widget.editableNotifier?.isCellEditing.addListener(() { - if (!mounted) return; + if (!mounted) { + return; + } final isEditing = widget.editableNotifier?.isCellEditing.value ?? false; if (isEditing) { @@ -106,15 +108,14 @@ class _TextCellState extends State { return BlocProvider.value( value: cellBloc, child: BlocConsumer( + listenWhen: (previous, current) => + previous.content != current.content && !current.enableEdit, listener: (context, state) { - if (_textEditingController.text != state.content) { - _textEditingController.text = state.content; - } + _textEditingController.text = state.content; }, buildWhen: (previous, current) { if (previous.content != current.content && - _textEditingController.text == current.content && - current.enableEdit) { + _textEditingController.text == current.content) { return false; } @@ -129,10 +130,10 @@ class _TextCellState extends State { return const SizedBox.shrink(); } - final icon = _buildIcon(state, isTitle); - final child = state.enableEdit || focusWhenInit - ? _buildTextField() - : _buildText(state, isTitle); + final icon = isTitle ? _buildIcon(state) : null; + final child = isTitle + ? _buildTextField(state.enableEdit || focusWhenInit) + : _buildText(state.content); return Row( children: [ @@ -156,10 +157,7 @@ class _TextCellState extends State { super.dispose(); } - Widget? _buildIcon(TextCellState state, bool isTitle) { - if (!isTitle) { - return null; - } + Widget? _buildIcon(TextCellState state) { if (state.emoji.isNotEmpty) { return Text( state.emoji, @@ -178,43 +176,52 @@ class _TextCellState extends State { return null; } - Widget _buildText(TextCellState state, bool isTitle) { - final text = state.content.isEmpty - ? isTitle - ? LocaleKeys.grid_row_titlePlaceholder.tr() - : LocaleKeys.grid_row_textPlaceholder.tr() - : state.content; - final color = state.content.isEmpty ? Theme.of(context).hintColor : null; - final textStyle = - isTitle ? widget.style.titleTextStyle : widget.style.textStyle; + Widget _buildText(String content) { + final text = + content.isEmpty ? LocaleKeys.grid_row_textPlaceholder.tr() : content; + final color = content.isEmpty ? Theme.of(context).hintColor : null; return Padding( padding: widget.style.padding, child: Text( text, - style: textStyle.copyWith(color: color), + style: widget.style.textStyle.copyWith(color: color), maxLines: widget.style.maxLines, ), ); } - Widget _buildTextField() { + Widget _buildTextField(bool isEditing) { final padding = widget.style.padding.add(const EdgeInsets.symmetric(vertical: 4.0)); - return TextField( - controller: _textEditingController, - focusNode: focusNode, - onChanged: (_) => - cellBloc.add(TextCellEvent.updateText(_textEditingController.text)), - onEditingComplete: () => focusNode.unfocus(), - maxLines: null, - style: widget.style.titleTextStyle, - decoration: InputDecoration( - contentPadding: padding, - border: InputBorder.none, - isDense: true, - isCollapsed: true, - hintText: LocaleKeys.grid_row_titlePlaceholder.tr(), + return IgnorePointer( + ignoring: !isEditing, + child: TextField( + controller: _textEditingController, + focusNode: focusNode, + onChanged: (_) { + if (_textEditingController.value.composing.isCollapsed) { + cellBloc.add(TextCellEvent.updateText(_textEditingController.text)); + } + }, + onEditingComplete: () => focusNode.unfocus(), + maxLines: isEditing ? null : 2, + minLines: 1, + textInputAction: TextInputAction.done, + readOnly: !isEditing, + enableInteractiveSelection: isEditing, + style: widget.style.titleTextStyle, + decoration: InputDecoration( + contentPadding: padding, + border: InputBorder.none, + enabledBorder: InputBorder.none, + isDense: true, + isCollapsed: true, + hintText: LocaleKeys.grid_row_titlePlaceholder.tr(), + hintStyle: widget.style.titleTextStyle.copyWith( + color: Theme.of(context).hintColor, + ), + ), ), ); } diff --git a/frontend/appflowy_flutter/lib/plugins/database/widgets/cell/card_cell_style_maps/desktop_board_card_cell_style.dart b/frontend/appflowy_flutter/lib/plugins/database/widgets/cell/card_cell_style_maps/desktop_board_card_cell_style.dart index 1b229f76f0..8f86c69a05 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/widgets/cell/card_cell_style_maps/desktop_board_card_cell_style.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/widgets/cell/card_cell_style_maps/desktop_board_card_cell_style.dart @@ -56,7 +56,7 @@ CardCellStyleMap desktopBoardCardCellStyleMap(BuildContext context) { FieldType.RichText: TextCardCellStyle( padding: padding, textStyle: textStyle, - maxLines: null, + maxLines: 2, titleTextStyle: Theme.of(context).textTheme.bodyMedium!.copyWith( overflow: TextOverflow.ellipsis, ), diff --git a/frontend/appflowy_flutter/lib/plugins/database/widgets/setting/setting_property_list.dart b/frontend/appflowy_flutter/lib/plugins/database/widgets/setting/setting_property_list.dart index 198152ab7d..ece69f9848 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/widgets/setting/setting_property_list.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/widgets/setting/setting_property_list.dart @@ -180,8 +180,7 @@ class _DatabasePropertyCellState extends State { return; } - final newVisiblity = - widget.fieldInfo.fieldSettings!.visibility.toggle(); + final newVisiblity = widget.fieldInfo.visibility!.toggle(); context.read().add( DatabasePropertyEvent.setFieldVisibility( widget.fieldInfo.id, diff --git a/frontend/appflowy_flutter/pubspec.lock b/frontend/appflowy_flutter/pubspec.lock index 537cb5cc9f..c6a896e99e 100644 --- a/frontend/appflowy_flutter/pubspec.lock +++ b/frontend/appflowy_flutter/pubspec.lock @@ -44,11 +44,11 @@ packages: dependency: "direct main" description: path: "." - ref: "15a3a50" - resolved-ref: "15a3a5071ffdb002ffaefda9df343b6800844d8d" + ref: f88b4ce01d2728c05125cbe9170013f4a7c85a31 + resolved-ref: f88b4ce01d2728c05125cbe9170013f4a7c85a31 url: "https://github.com/AppFlowy-IO/appflowy-board.git" source: git - version: "0.1.1" + version: "0.1.2" appflowy_editor: dependency: "direct main" description: @@ -1405,10 +1405,10 @@ packages: dependency: "direct main" description: name: provider - sha256: "9a96a0a19b594dbc5bf0f1f27d2bc67d5f95957359b461cd9feb44ed6ae75096" + sha256: c8a055ee5ce3fd98d6fc872478b03823ffdb448699c6ebdbbc71d59b596fd48c url: "https://pub.dev" source: hosted - version: "6.1.1" + version: "6.1.2" pub_semver: dependency: transitive description: diff --git a/frontend/appflowy_flutter/pubspec.yaml b/frontend/appflowy_flutter/pubspec.yaml index c8afe133aa..5ec4972890 100644 --- a/frontend/appflowy_flutter/pubspec.yaml +++ b/frontend/appflowy_flutter/pubspec.yaml @@ -41,9 +41,10 @@ dependencies: flowy_svg: path: packages/flowy_svg appflowy_board: + # path: ../../../appflowy-board git: url: https://github.com/AppFlowy-IO/appflowy-board.git - ref: 15a3a50 + ref: f88b4ce01d2728c05125cbe9170013f4a7c85a31 appflowy_result: path: packages/appflowy_result appflowy_editor_plugins: ^0.0.2