From 70689d32398c2179ad3e76e71db6c12d11d396f5 Mon Sep 17 00:00:00 2001 From: Richard Shiue <71320345+richardshiue@users.noreply.github.com> Date: Tue, 27 Dec 2022 08:21:30 +0800 Subject: [PATCH] feat: show the scrollbars again (#1605) * fix: padding in grid cell editors * fix: padding in grid header editor * fix: padding for row details * fix: shrink number formt list when possible * chore: simply use column for select option editor * fix: make sure that popovers are the edges * fix: delete button padding * fix: date and time formats padding mistake --- .../grid/presentation/layout/sizes.dart | 1 - .../widgets/cell/date_cell/date_editor.dart | 159 +++++++------ .../select_option_cell.dart | 1 + .../select_option_editor.dart | 216 +++++++++--------- .../widgets/common/type_option_separator.dart | 5 +- .../widgets/header/field_cell.dart | 1 + .../header/field_cell_action_sheet.dart | 8 +- .../widgets/header/field_editor.dart | 78 +++---- .../header/field_type_option_editor.dart | 7 +- .../widgets/header/type_option/date.dart | 70 +++--- .../widgets/header/type_option/number.dart | 42 ++-- .../header/type_option/select_option.dart | 129 ++++++----- .../type_option/select_option_editor.dart | 45 ++-- .../presentation/widgets/row/row_detail.dart | 1 + .../widgets/toolbar/grid_property.dart | 1 + .../lib/workspace/application/appearance.dart | 16 +- 16 files changed, 437 insertions(+), 343 deletions(-) diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/layout/sizes.dart b/frontend/app_flowy/lib/plugins/grid/presentation/layout/sizes.dart index 18dbb68adf..0e69a755ef 100755 --- a/frontend/app_flowy/lib/plugins/grid/presentation/layout/sizes.dart +++ b/frontend/app_flowy/lib/plugins/grid/presentation/layout/sizes.dart @@ -14,7 +14,6 @@ class GridSize { static double get typeOptionItemHeight => 32 * scale; static double get typeOptionSeparatorHeight => 4 * scale; - // static EdgeInsets get headerContentInsets => EdgeInsets.symmetric( horizontal: GridSize.headerContainerPadding, vertical: GridSize.headerContainerPadding, diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/date_cell/date_editor.dart b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/date_cell/date_editor.dart index 06d7dc19b5..44180b6c31 100644 --- a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/date_cell/date_editor.dart +++ b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/date_cell/date_editor.dart @@ -1,6 +1,7 @@ import 'package:app_flowy/generated/locale_keys.g.dart'; import 'package:app_flowy/plugins/grid/application/cell/date_cal_bloc.dart'; import 'package:app_flowy/plugins/grid/application/field/type_option/type_option_context.dart'; +import 'package:app_flowy/plugins/grid/presentation/widgets/common/type_option_separator.dart'; import 'package:app_flowy/workspace/presentation/widgets/toggle/toggle.dart'; import 'package:app_flowy/workspace/presentation/widgets/toggle/toggle_style.dart'; import 'package:appflowy_popover/appflowy_popover.dart'; @@ -62,12 +63,9 @@ class _DateCellEditor extends State { Widget _buildWidget(AsyncSnapshot> snapshot) { return snapshot.data!.fold( (dateTypeOptionPB) { - return Padding( - padding: const EdgeInsets.all(12), - child: _CellCalendarWidget( - cellContext: widget.cellController, - dateTypeOptionPB: dateTypeOptionPB, - ), + return _CellCalendarWidget( + cellContext: widget.cellController, + dateTypeOptionPB: dateTypeOptionPB, ); }, (err) { @@ -116,26 +114,29 @@ class _CellCalendarWidgetState extends State<_CellCalendarWidget> { buildWhen: (p, c) => p != c, builder: (context, state) { List children = [ - _buildCalendar(context), - if (state.dateTypeOptionPB.includeTime) + Padding( + padding: const EdgeInsets.symmetric(horizontal: 12.0), + child: _buildCalendar(context), + ), + if (state.dateTypeOptionPB.includeTime) ...[ + const VSpace(12.0), _TimeTextField( bloc: context.read(), popoverMutex: popoverMutex, ), - Divider(height: 1.0, color: Theme.of(context).dividerColor), + ], + const TypeOptionSeparator(spacing: 12.0), const _IncludeTimeButton(), - Divider(height: 1.0, color: Theme.of(context).dividerColor), + const TypeOptionSeparator(spacing: 12.0), _DateTypeOptionButton(popoverMutex: popoverMutex) ]; - return ListView.separated( + return ListView.builder( shrinkWrap: true, controller: ScrollController(), - separatorBuilder: (context, index) => VSpace(GridSize.cellVPadding), itemCount: children.length, - itemBuilder: (BuildContext context, int index) { - return children[index]; - }, + itemBuilder: (BuildContext context, int index) => children[index], + padding: const EdgeInsets.symmetric(vertical: 12.0), ); }, ), @@ -171,10 +172,16 @@ class _CellCalendarWidgetState extends State<_CellCalendarWidget> { titleTextStyle: textStyle, leftChevronMargin: EdgeInsets.zero, leftChevronPadding: EdgeInsets.zero, - leftChevronIcon: svgWidget("home/arrow_left"), + leftChevronIcon: svgWidget( + "home/arrow_left", + color: Theme.of(context).colorScheme.onSurface, + ), rightChevronPadding: EdgeInsets.zero, rightChevronMargin: EdgeInsets.zero, - rightChevronIcon: svgWidget("home/arrow_right"), + rightChevronIcon: svgWidget( + "home/arrow_right", + color: Theme.of(context).colorScheme.onSurface, + ), headerMargin: const EdgeInsets.only(bottom: 8.0), ), daysOfWeekStyle: DaysOfWeekStyle( @@ -233,28 +240,31 @@ class _IncludeTimeButton extends StatelessWidget { return BlocSelector( selector: (state) => state.dateTypeOptionPB.includeTime, builder: (context, includeTime) { - return SizedBox( - height: GridSize.typeOptionItemHeight, - child: Padding( - padding: GridSize.typeOptionContentInsets, - child: Row( - children: [ - svgWidget( - "grid/clock", - color: Theme.of(context).colorScheme.onSurface, - ), - const HSpace(4), - FlowyText.medium(LocaleKeys.grid_field_includeTime.tr()), - const Spacer(), - Toggle( - value: includeTime, - onChanged: (value) => context - .read() - .add(DateCalEvent.setIncludeTime(!value)), - style: ToggleStyle.big, - padding: EdgeInsets.zero, - ), - ], + return Padding( + padding: const EdgeInsets.symmetric(horizontal: 12.0), + child: SizedBox( + height: GridSize.typeOptionItemHeight, + child: Padding( + padding: GridSize.typeOptionContentInsets, + child: Row( + children: [ + svgWidget( + "grid/clock", + color: Theme.of(context).colorScheme.onSurface, + ), + const HSpace(4), + FlowyText.medium(LocaleKeys.grid_field_includeTime.tr()), + const Spacer(), + Toggle( + value: includeTime, + onChanged: (value) => context + .read() + .add(DateCalEvent.setIncludeTime(!value)), + style: ToggleStyle.big, + padding: EdgeInsets.zero, + ), + ], + ), ), ), ); @@ -313,22 +323,25 @@ class _TimeTextFieldState extends State<_TimeTextField> { _controller.selection = TextSelection.collapsed(offset: _controller.text.length); return Padding( - padding: GridSize.typeOptionContentInsets, - child: RoundedInputField( - height: GridSize.typeOptionItemHeight, - focusNode: _focusNode, - autoFocus: true, - hintText: widget.bloc.state.timeHintText, - controller: _controller, - style: Theme.of(context).textTheme.bodyMedium!, - normalBorderColor: Theme.of(context).colorScheme.outline, - errorBorderColor: Theme.of(context).colorScheme.error, - focusBorderColor: Theme.of(context).colorScheme.primary, - cursorColor: Theme.of(context).colorScheme.primary, - errorText: - widget.bloc.state.timeFormatError.fold(() => "", (error) => error), - onEditingComplete: (value) => - widget.bloc.add(DateCalEvent.setTime(value)), + padding: const EdgeInsets.symmetric(horizontal: 12.0), + child: Padding( + padding: GridSize.typeOptionContentInsets, + child: RoundedInputField( + height: GridSize.typeOptionItemHeight, + focusNode: _focusNode, + autoFocus: true, + hintText: widget.bloc.state.timeHintText, + controller: _controller, + style: Theme.of(context).textTheme.bodyMedium!, + normalBorderColor: Theme.of(context).colorScheme.outline, + errorBorderColor: Theme.of(context).colorScheme.error, + focusBorderColor: Theme.of(context).colorScheme.primary, + cursorColor: Theme.of(context).colorScheme.primary, + errorText: widget.bloc.state.timeFormatError + .fold(() => "", (error) => error), + onEditingComplete: (value) => + widget.bloc.add(DateCalEvent.setTime(value)), + ), ), ); } @@ -358,15 +371,19 @@ class _DateTypeOptionButton extends StatelessWidget { mutex: popoverMutex, triggerActions: PopoverTriggerFlags.hover | PopoverTriggerFlags.click, offset: const Offset(20, 0), + margin: EdgeInsets.zero, constraints: BoxConstraints.loose(const Size(140, 100)), - child: SizedBox( - height: GridSize.typeOptionItemHeight, - child: FlowyButton( - text: FlowyText.medium(title), - margin: GridSize.typeOptionContentInsets, - rightIcon: svgWidget( - "grid/more", - color: Theme.of(context).colorScheme.onSurface, + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 12.0), + child: SizedBox( + height: GridSize.typeOptionItemHeight, + child: FlowyButton( + text: FlowyText.medium(title), + margin: GridSize.typeOptionContentInsets, + rightIcon: svgWidget( + "grid/more", + color: Theme.of(context).colorScheme.onSurface, + ), ), ), ), @@ -418,7 +435,10 @@ class _CalDateTimeSettingState extends State<_CalDateTimeSetting> { }, ); }, - child: const DateFormatButton(), + child: const Padding( + padding: EdgeInsets.symmetric(horizontal: 6.0), + child: DateFormatButton(), + ), ), AppFlowyPopover( mutex: timeSettingPopoverMutex, @@ -432,7 +452,11 @@ class _CalDateTimeSettingState extends State<_CalDateTimeSetting> { timeSettingPopoverMutex.close(); }); }, - child: TimeFormatButton(timeFormat: widget.dateTypeOptionPB.timeFormat), + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 6.0), + child: + TimeFormatButton(timeFormat: widget.dateTypeOptionPB.timeFormat), + ), ), ]; @@ -444,9 +468,8 @@ class _CalDateTimeSettingState extends State<_CalDateTimeSetting> { separatorBuilder: (context, index) => VSpace(GridSize.typeOptionSeparatorHeight), itemCount: children.length, - itemBuilder: (BuildContext context, int index) { - return children[index]; - }, + itemBuilder: (BuildContext context, int index) => children[index], + padding: const EdgeInsets.symmetric(vertical: 6.0), ), ); } diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/select_option_cell/select_option_cell.dart b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/select_option_cell/select_option_cell.dart index e228f83c16..7607e1e2b5 100644 --- a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/select_option_cell/select_option_cell.dart +++ b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/select_option_cell/select_option_cell.dart @@ -182,6 +182,7 @@ class _SelectOptionWrapState extends State { return AppFlowyPopover( controller: _popover, constraints: constraints, + margin: EdgeInsets.zero, direction: PopoverDirection.bottomWithLeftAligned, popupBuilder: (BuildContext context) { WidgetsBinding.instance.addPostFrameCallback((_) { diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/select_option_cell/select_option_editor.dart b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/select_option_cell/select_option_editor.dart index 504a02b3b6..3ec747be5e 100644 --- a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/select_option_cell/select_option_editor.dart +++ b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/select_option_cell/select_option_editor.dart @@ -1,6 +1,7 @@ import 'dart:collection'; import 'package:app_flowy/plugins/grid/application/cell/cell_service/cell_service.dart'; import 'package:app_flowy/plugins/grid/application/cell/select_option_editor_bloc.dart'; +import 'package:app_flowy/plugins/grid/presentation/widgets/common/type_option_separator.dart'; import 'package:appflowy_popover/appflowy_popover.dart'; import 'package:flowy_infra/theme_extension.dart'; @@ -17,12 +18,12 @@ import 'package:app_flowy/generated/locale_keys.g.dart'; import 'package:textfield_tags/textfield_tags.dart'; import '../../../layout/sizes.dart'; -import '../../common/type_option_separator.dart'; import '../../header/type_option/select_option_editor.dart'; import 'extension.dart'; import 'text_field.dart'; const double _editorPanelWidth = 300; +const double _padding = 12.0; class SelectOptionCellEditor extends StatefulWidget { final GridSelectOptionCellController cellController; @@ -52,25 +53,13 @@ class _SelectOptionCellEditorState extends State { )..add(const SelectOptionEditorEvent.initial()), child: BlocBuilder( builder: (context, state) { - final List children = [ - _TextField(popoverMutex: popoverMutex), - const TypeOptionSeparator(), - const _Title(), - _OptionList(popoverMutex: popoverMutex), - ]; - - return Padding( - padding: const EdgeInsets.all(6.0), - child: ListView.separated( - shrinkWrap: true, - itemCount: children.length, - itemBuilder: (BuildContext context, int index) { - return children[index]; - }, - separatorBuilder: (BuildContext context, int index) { - return VSpace(GridSize.typeOptionSeparatorHeight); - }, - ), + return Column( + mainAxisSize: MainAxisSize.min, + children: [ + _TextField(popoverMutex: popoverMutex), + const TypeOptionSeparator(spacing: 0.0), + Flexible(child: _OptionList(popoverMutex: popoverMutex)), + ], ); }, ), @@ -90,6 +79,7 @@ class _OptionList extends StatelessWidget { return BlocBuilder( builder: (context, state) { List cells = []; + cells.add(const _Title()); cells.addAll(state.options.map((option) { return _SelectOptionCell( option: option, @@ -113,15 +103,11 @@ class _OptionList extends StatelessWidget { return VSpace(GridSize.typeOptionSeparatorHeight); }, physics: StyledScrollPhysics(), - itemBuilder: (BuildContext context, int index) { - return cells[index]; - }, + itemBuilder: (BuildContext context, int index) => cells[index], + padding: const EdgeInsets.only(top: 6.0, bottom: 12.0), ); - return Padding( - padding: const EdgeInsets.all(3.0), - child: list, - ); + return list; }, ); } @@ -145,32 +131,35 @@ class _TextField extends StatelessWidget { key: (option) => option.name, value: (option) => option); - return SelectOptionTextField( - options: state.options, - selectedOptionMap: optionMap, - distanceToText: _editorPanelWidth * 0.7, - maxLength: 30, - tagController: _tagController, - textSeparators: const [','], - onClick: () => popoverMutex.close(), - newText: (text) { - context - .read() - .add(SelectOptionEditorEvent.filterOption(text)); - }, - onSubmitted: (tagName) { - context - .read() - .add(SelectOptionEditorEvent.trySelectOption(tagName)); - }, - onPaste: (tagNames, remainder) { - context - .read() - .add(SelectOptionEditorEvent.selectMultipleOptions( - tagNames, - remainder, - )); - }, + return Padding( + padding: const EdgeInsets.all(_padding), + child: SelectOptionTextField( + options: state.options, + selectedOptionMap: optionMap, + distanceToText: _editorPanelWidth * 0.7, + maxLength: 30, + tagController: _tagController, + textSeparators: const [','], + onClick: () => popoverMutex.close(), + newText: (text) { + context + .read() + .add(SelectOptionEditorEvent.filterOption(text)); + }, + onSubmitted: (tagName) { + context + .read() + .add(SelectOptionEditorEvent.trySelectOption(tagName)); + }, + onPaste: (tagNames, remainder) { + context + .read() + .add(SelectOptionEditorEvent.selectMultipleOptions( + tagNames, + remainder, + )); + }, + ), ); }, ); @@ -182,10 +171,10 @@ class _Title extends StatelessWidget { @override Widget build(BuildContext context) { - return SizedBox( - height: GridSize.typeOptionItemHeight, - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 6), + return Padding( + padding: const EdgeInsets.symmetric(horizontal: 12.0), + child: SizedBox( + height: GridSize.typeOptionItemHeight, child: FlowyText.medium( LocaleKeys.grid_selectOption_panelTitle.tr(), color: Theme.of(context).hintColor, @@ -201,26 +190,32 @@ class _CreateOptionCell extends StatelessWidget { @override Widget build(BuildContext context) { - return Row( - children: [ - FlowyText.medium( - LocaleKeys.grid_selectOption_create.tr(), - color: Theme.of(context).hintColor, - ), - const HSpace(10), - Expanded( - child: Align( - alignment: Alignment.centerLeft, - child: SelectOptionTag( - name: name, - color: AFThemeExtension.of(context).lightGreyHover, - onSelected: () => context - .read() - .add(SelectOptionEditorEvent.newOption(name)), + return Padding( + padding: const EdgeInsets.symmetric(horizontal: 12.0), + child: SizedBox( + height: GridSize.typeOptionItemHeight, + child: Row( + children: [ + FlowyText.medium( + LocaleKeys.grid_selectOption_create.tr(), + color: Theme.of(context).hintColor, ), - ), + const HSpace(10), + Expanded( + child: Align( + alignment: Alignment.centerLeft, + child: SelectOptionTag( + name: name, + color: AFThemeExtension.of(context).lightGreyHover, + onSelected: () => context + .read() + .add(SelectOptionEditorEvent.newOption(name)), + ), + ), + ), + ], ), - ], + ), ); } } @@ -251,44 +246,49 @@ class _SelectOptionCellState extends State<_SelectOptionCell> { @override Widget build(BuildContext context) { + final child = SizedBox( + height: GridSize.typeOptionItemHeight, + child: SelectOptionTagCell( + option: widget.option, + onSelected: (option) { + if (widget.isSelected) { + context + .read() + .add(SelectOptionEditorEvent.unSelectOption(option.id)); + } else { + context + .read() + .add(SelectOptionEditorEvent.selectOption(option.id)); + } + }, + children: [ + if (widget.isSelected) + Padding( + padding: const EdgeInsets.only(left: 6), + child: svgWidget("grid/checkmark"), + ), + FlowyIconButton( + onPressed: () => _popoverController.show(), + hoverColor: Colors.transparent, + iconPadding: const EdgeInsets.symmetric(horizontal: 6.0), + icon: svgWidget( + "editor/details", + color: Theme.of(context).colorScheme.onSurface, + ), + ), + ], + ), + ); return AppFlowyPopover( controller: _popoverController, offset: const Offset(20, 0), + margin: EdgeInsets.zero, asBarrier: true, - constraints: BoxConstraints.loose(const Size(200, 300)), + constraints: BoxConstraints.loose(const Size(200, 460)), mutex: widget.popoverMutex, - child: SizedBox( - height: GridSize.typeOptionItemHeight, - child: SelectOptionTagCell( - option: widget.option, - onSelected: (option) { - if (widget.isSelected) { - context - .read() - .add(SelectOptionEditorEvent.unSelectOption(option.id)); - } else { - context - .read() - .add(SelectOptionEditorEvent.selectOption(option.id)); - } - }, - children: [ - if (widget.isSelected) - Padding( - padding: const EdgeInsets.only(left: 6), - child: svgWidget("grid/checkmark"), - ), - FlowyIconButton( - onPressed: () => _popoverController.show(), - hoverColor: Colors.transparent, - iconPadding: const EdgeInsets.symmetric(horizontal: 6.0), - icon: svgWidget( - "editor/details", - color: Theme.of(context).colorScheme.onSurface, - ), - ), - ], - ), + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 12.0), + child: child, ), popupBuilder: (BuildContext popoverContext) { return SelectOptionTypeOptionEditor( diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/common/type_option_separator.dart b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/common/type_option_separator.dart index f00c1c30f4..8539516d65 100644 --- a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/common/type_option_separator.dart +++ b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/common/type_option_separator.dart @@ -1,12 +1,13 @@ import 'package:flutter/material.dart'; class TypeOptionSeparator extends StatelessWidget { - const TypeOptionSeparator({Key? key}) : super(key: key); + final double spacing; + const TypeOptionSeparator({this.spacing = 6.0, Key? key}) : super(key: key); @override Widget build(BuildContext context) { return Padding( - padding: const EdgeInsets.symmetric(vertical: 6), + padding: EdgeInsets.symmetric(vertical: spacing), child: Container( color: Theme.of(context).dividerColor, height: 1.0, diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/field_cell.dart b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/field_cell.dart index d852c0f827..0cb36e0020 100755 --- a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/field_cell.dart +++ b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/field_cell.dart @@ -45,6 +45,7 @@ class _GridFieldCellState extends State { final button = AppFlowyPopover( triggerActions: PopoverTriggerFlags.none, constraints: BoxConstraints.loose(const Size(240, 440)), + margin: EdgeInsets.zero, direction: PopoverDirection.bottomWithLeftAligned, controller: popoverController, popupBuilder: (BuildContext context) { diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/field_cell_action_sheet.dart b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/field_cell_action_sheet.dart index 88b16b1ac6..8e7d646a51 100644 --- a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/field_cell_action_sheet.dart +++ b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/field_cell_action_sheet.dart @@ -44,6 +44,7 @@ class _GridFieldCellActionSheetState extends State { create: (context) => getIt(param1: widget.cellContext), child: SingleChildScrollView( + padding: const EdgeInsets.all(12.0), child: Column( children: [ _EditFieldButton( @@ -54,7 +55,7 @@ class _GridFieldCellActionSheetState extends State { }); }, ), - const VSpace(6), + VSpace(GridSize.typeOptionSeparatorHeight), _FieldOperationList(widget.cellContext, () {}), ], ), @@ -98,10 +99,11 @@ class _FieldOperationList extends StatelessWidget { return GridView( // https://api.flutter.dev/flutter/widgets/AnimatedList/shrinkWrap.html shrinkWrap: true, - gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( + gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 2, childAspectRatio: 4.0, - mainAxisSpacing: 8, + mainAxisSpacing: GridSize.typeOptionSeparatorHeight, + crossAxisSpacing: GridSize.typeOptionSeparatorHeight, ), children: buildCells(), ); diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/field_editor.dart b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/field_editor.dart index d2ae1e3995..40f0cc6efa 100644 --- a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/field_editor.dart +++ b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/field_editor.dart @@ -51,6 +51,12 @@ class _FieldEditorState extends State { @override Widget build(BuildContext context) { + List children = [ + _FieldNameTextField(popoverMutex: popoverMutex), + const VSpace(10), + if (widget.onDeleted != null) _addDeleteFieldButton(), + _FieldTypeOptionCell(popoverMutex: popoverMutex), + ]; return BlocProvider( create: (context) => FieldEditorBloc( gridId: widget.gridId, @@ -58,33 +64,21 @@ class _FieldEditorState extends State { isGroupField: widget.isGroupField, loader: widget.typeOptionLoader, )..add(const FieldEditorEvent.initial()), - child: Padding( - padding: GridSize.typeOptionContentInsets, - child: ListView( - shrinkWrap: true, - children: [ - FlowyText.medium( - LocaleKeys.grid_field_editProperty.tr(), - ), - const VSpace(10), - _FieldNameTextField(popoverMutex: popoverMutex), - const VSpace(10), - ..._addDeleteFieldButton(), - _FieldTypeOptionCell(popoverMutex: popoverMutex), - ], - ), + child: ListView.builder( + shrinkWrap: true, + itemCount: children.length, + itemBuilder: (context, index) => children[index], + padding: const EdgeInsets.symmetric(vertical: 12.0), ), ); } - List _addDeleteFieldButton() { - if (widget.onDeleted == null) { - return []; - } - return [ - BlocBuilder( - builder: (context, state) { - return _DeleteFieldButton( + Widget _addDeleteFieldButton() { + return BlocBuilder( + builder: (context, state) { + return Padding( + padding: const EdgeInsets.symmetric(horizontal: 12.0), + child: _DeleteFieldButton( popoverMutex: popoverMutex, onDeleted: () { state.field.fold( @@ -92,10 +86,10 @@ class _FieldEditorState extends State { (field) => widget.onDeleted?.call(field.id), ); }, - ); - }, - ), - ]; + ), + ); + }, + ); } } @@ -182,17 +176,20 @@ class _FieldNameTextFieldState extends State<_FieldNameTextField> { buildWhen: (previous, current) => previous.errorText != current.errorText, builder: (context, state) { - return RoundedInputField( - height: 36, - focusNode: focusNode, - style: Theme.of(context).textTheme.bodyMedium, - controller: controller, - errorText: context.read().state.errorText, - onChanged: (newName) { - context - .read() - .add(FieldEditorEvent.updateName(newName)); - }, + return Padding( + padding: const EdgeInsets.symmetric(horizontal: 12.0), + child: RoundedInputField( + height: 36, + focusNode: focusNode, + style: Theme.of(context).textTheme.bodyMedium, + controller: controller, + errorText: context.read().state.errorText, + onChanged: (newName) { + context + .read() + .add(FieldEditorEvent.updateName(newName)); + }, + ), ); }, ), @@ -224,7 +221,10 @@ class _DeleteFieldButton extends StatelessWidget { onTap: () => onDeleted?.call(), onHover: (_) => popoverMutex.close(), ); - return SizedBox(height: 36, child: button); + return Padding( + padding: const EdgeInsets.only(bottom: 4.0), + child: SizedBox(height: GridSize.typeOptionItemHeight, child: button), + ); }, ); } diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/field_type_option_editor.dart b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/field_type_option_editor.dart index 2354b8ba7b..d3f6d2d80b 100644 --- a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/field_type_option_editor.dart +++ b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/field_type_option_editor.dart @@ -96,7 +96,10 @@ class _SwitchFieldButton extends StatelessWidget { .add(FieldTypeOptionEditEvent.switchToField(newFieldType)); }); }, - child: _buildMoreButton(context), + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 12.0), + child: _buildMoreButton(context), + ), ); return SizedBox( @@ -111,7 +114,7 @@ class _SwitchFieldButton extends StatelessWidget { text: FlowyText.medium( bloc.state.field.fieldType.title(), ), - margin: const EdgeInsets.symmetric(horizontal: 6, vertical: 2), + margin: GridSize.typeOptionContentInsets, leftIcon: svgWidget( bloc.state.field.fieldType.iconName(), color: Theme.of(context).colorScheme.onSurface, diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/type_option/date.dart b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/type_option/date.dart index 94dda7fc69..203112c03c 100644 --- a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/type_option/date.dart +++ b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/type_option/date.dart @@ -62,12 +62,15 @@ class DateTypeOptionWidget extends TypeOptionWidget { return ListView.separated( shrinkWrap: true, controller: ScrollController(), - separatorBuilder: (context, index) => - VSpace(GridSize.typeOptionSeparatorHeight), - itemCount: children.length, - itemBuilder: (BuildContext context, int index) { - return children[index]; + separatorBuilder: (context, index) { + if (index == 0) { + return const SizedBox(); + } else { + return VSpace(GridSize.typeOptionSeparatorHeight); + } }, + itemCount: children.length, + itemBuilder: (BuildContext context, int index) => children[index], ); }, ), @@ -92,7 +95,12 @@ class DateTypeOptionWidget extends TypeOptionWidget { }, ); }, - child: DateFormatButton(buttonMargins: GridSize.typeOptionContentInsets), + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 12.0), + child: DateFormatButton( + buttonMargins: GridSize.typeOptionContentInsets, + ), + ), ); } @@ -114,9 +122,12 @@ class DateTypeOptionWidget extends TypeOptionWidget { }, ); }, - child: TimeFormatButton( - timeFormat: timeFormat, - buttonMargins: GridSize.typeOptionContentInsets, + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 12.0), + child: TimeFormatButton( + timeFormat: timeFormat, + buttonMargins: GridSize.typeOptionContentInsets, + ), ), ); } @@ -190,25 +201,28 @@ class _IncludeTimeButton extends StatelessWidget { return BlocSelector( selector: (state) => state.typeOption.includeTime, builder: (context, includeTime) { - return SizedBox( - height: GridSize.typeOptionItemHeight, - child: Padding( - padding: GridSize.typeOptionContentInsets, - child: Row( - children: [ - FlowyText.medium(LocaleKeys.grid_field_includeTime.tr()), - const Spacer(), - Toggle( - value: includeTime, - onChanged: (value) { - context - .read() - .add(DateTypeOptionEvent.includeTime(!value)); - }, - style: ToggleStyle.big, - padding: EdgeInsets.zero, - ), - ], + return Padding( + padding: const EdgeInsets.symmetric(horizontal: 12.0), + child: SizedBox( + height: GridSize.typeOptionItemHeight, + child: Padding( + padding: GridSize.typeOptionContentInsets, + child: Row( + children: [ + FlowyText.medium(LocaleKeys.grid_field_includeTime.tr()), + const Spacer(), + Toggle( + value: includeTime, + onChanged: (value) { + context + .read() + .add(DateTypeOptionEvent.includeTime(!value)); + }, + style: ToggleStyle.big, + padding: EdgeInsets.zero, + ), + ], + ), ), ), ); diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/type_option/number.dart b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/type_option/number.dart index ef3df6ba71..f84433796b 100644 --- a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/type_option/number.dart +++ b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/type_option/number.dart @@ -31,7 +31,7 @@ class NumberTypeOptionWidgetBuilder extends TypeOptionWidgetBuilder { @override Widget? build(BuildContext context) { return Column(children: [ - const TypeOptionSeparator(), + VSpace(GridSize.typeOptionSeparatorHeight), _widget, ]); } @@ -57,12 +57,8 @@ class NumberTypeOptionWidget extends TypeOptionWidget { listener: (context, state) => typeOptionContext.typeOption = state.typeOption, builder: (context, state) { - return AppFlowyPopover( - mutex: popoverMutex, - triggerActions: - PopoverTriggerFlags.hover | PopoverTriggerFlags.click, - offset: const Offset(20, 0), - constraints: BoxConstraints.loose(const Size(460, 440)), + final button = SizedBox( + height: GridSize.typeOptionItemHeight, child: FlowyButton( margin: GridSize.typeOptionContentInsets, rightIcon: svgWidget( @@ -72,12 +68,24 @@ class NumberTypeOptionWidget extends TypeOptionWidget { text: Row( children: [ FlowyText.medium(LocaleKeys.grid_field_numberFormat.tr()), - // const HSpace(6), const Spacer(), FlowyText.regular(state.typeOption.format.title()), ], ), ), + ); + + return AppFlowyPopover( + mutex: popoverMutex, + triggerActions: + PopoverTriggerFlags.hover | PopoverTriggerFlags.click, + offset: const Offset(20, 0), + constraints: BoxConstraints.loose(const Size(460, 440)), + margin: EdgeInsets.zero, + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 12.0), + child: button, + ), popupBuilder: (BuildContext popoverContext) { return NumberFormatList( onSelected: (format) { @@ -113,10 +121,10 @@ class NumberFormatList extends StatelessWidget { child: SizedBox( width: 180, child: Column( - crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, children: [ const _FilterTextField(), - const VSpace(10), + const TypeOptionSeparator(spacing: 0.0), BlocBuilder( builder: (context, state) { final cells = state.formats.map((format) { @@ -138,8 +146,9 @@ class NumberFormatList extends StatelessWidget { itemBuilder: (BuildContext context, int index) { return cells[index]; }, + padding: const EdgeInsets.all(6.0), ); - return Expanded(child: list); + return Flexible(child: list); }, ), ], @@ -182,10 +191,13 @@ class _FilterTextField extends StatelessWidget { const _FilterTextField({Key? key}) : super(key: key); @override Widget build(BuildContext context) { - return FlowyTextField( - onChanged: (text) => context - .read() - .add(NumberFormatEvent.setFilter(text)), + return Padding( + padding: const EdgeInsets.all(6.0), + child: FlowyTextField( + onChanged: (text) => context + .read() + .add(NumberFormatEvent.setFilter(text)), + ), ); } } diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/type_option/select_option.dart b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/type_option/select_option.dart index 97c94f0b87..74659dd89e 100644 --- a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/type_option/select_option.dart +++ b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/type_option/select_option.dart @@ -43,18 +43,21 @@ class SelectOptionTypeOptionWidget extends StatelessWidget { const TypeOptionSeparator(), const OptionTitle(), if (state.isEditingOption) - Padding( - padding: const EdgeInsets.only(bottom: 10), - child: _CreateOptionTextField( - popoverMutex: popoverMutex, - ), - ), + _CreateOptionTextField(popoverMutex: popoverMutex), + if (state.options.isNotEmpty && state.isEditingOption) + const VSpace(10), if (state.options.isEmpty && !state.isEditingOption) const _AddOptionButton(), _OptionList(popoverMutex: popoverMutex) ]; - return Column(children: children); + return ListView.builder( + shrinkWrap: true, + itemCount: children.length, + itemBuilder: (context, index) { + return children[index]; + }, + ); }, ), ); @@ -79,9 +82,12 @@ class OptionTitle extends StatelessWidget { children.add(const _OptionTitleButton()); } - return SizedBox( - height: GridSize.typeOptionItemHeight, - child: Row(children: children), + return Padding( + padding: const EdgeInsets.symmetric(horizontal: 12.0), + child: SizedBox( + height: GridSize.typeOptionItemHeight, + child: Row(children: children), + ), ); }, ); @@ -178,29 +184,34 @@ class _OptionCellState extends State<_OptionCell> { @override Widget build(BuildContext context) { + final child = SizedBox( + height: GridSize.typeOptionItemHeight, + child: SelectOptionTagCell( + option: widget.option, + onSelected: (SelectOptionPB pb) { + _popoverController.show(); + }, + children: [ + Padding( + padding: const EdgeInsets.symmetric(horizontal: 6.0), + child: svgWidget( + "grid/details", + color: Theme.of(context).colorScheme.onSurface, + ), + ), + ], + ), + ); return AppFlowyPopover( controller: _popoverController, mutex: widget.popoverMutex, offset: const Offset(20, 0), + margin: EdgeInsets.zero, asBarrier: true, - constraints: BoxConstraints.loose(const Size(460, 440)), - child: SizedBox( - height: GridSize.typeOptionItemHeight, - child: SelectOptionTagCell( - option: widget.option, - onSelected: (SelectOptionPB pb) { - _popoverController.show(); - }, - children: [ - Padding( - padding: const EdgeInsets.symmetric(horizontal: 6.0), - child: svgWidget( - "grid/details", - color: Theme.of(context).colorScheme.onSurface, - ), - ), - ], - ), + constraints: BoxConstraints.loose(const Size(460, 460)), + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 12.0), + child: child, ), popupBuilder: (BuildContext popoverContext) { return SelectOptionTypeOptionEditor( @@ -229,18 +240,21 @@ class _AddOptionButton extends StatelessWidget { @override Widget build(BuildContext context) { - return SizedBox( - height: GridSize.typeOptionItemHeight, - child: FlowyButton( - text: FlowyText.medium(LocaleKeys.grid_field_addSelectOption.tr()), - onTap: () { - context - .read() - .add(const SelectOptionTypeOptionEvent.addingOption()); - }, - leftIcon: svgWidget( - "home/add", - color: Theme.of(context).colorScheme.onSurface, + return Padding( + padding: const EdgeInsets.symmetric(horizontal: 12.0), + child: SizedBox( + height: GridSize.typeOptionItemHeight, + child: FlowyButton( + text: FlowyText.medium(LocaleKeys.grid_field_addSelectOption.tr()), + onTap: () { + context + .read() + .add(const SelectOptionTypeOptionEvent.addingOption()); + }, + leftIcon: svgWidget( + "home/add", + color: Theme.of(context).colorScheme.onSurface, + ), ), ), ); @@ -282,22 +296,25 @@ class _CreateOptionTextFieldState extends State<_CreateOptionTextField> { return BlocBuilder( builder: (context, state) { final text = state.newOptionName.foldRight("", (a, previous) => a); - return FlowyTextField( - autoClearWhenDone: true, - maxLength: 30, - text: text, - focusNode: _focusNode, - onCanceled: () { - context - .read() - .add(const SelectOptionTypeOptionEvent.endAddingOption()); - }, - onEditingComplete: () {}, - onSubmitted: (optionName) { - context - .read() - .add(SelectOptionTypeOptionEvent.createOption(optionName)); - }, + return Padding( + padding: const EdgeInsets.symmetric(horizontal: 12.0), + child: FlowyTextField( + autoClearWhenDone: true, + maxLength: 30, + text: text, + focusNode: _focusNode, + onCanceled: () { + context + .read() + .add(const SelectOptionTypeOptionEvent.endAddingOption()); + }, + onEditingComplete: () {}, + onSubmitted: (optionName) { + context + .read() + .add(SelectOptionTypeOptionEvent.createOption(optionName)); + }, + ), ); }, ); diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/type_option/select_option_editor.dart b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/type_option/select_option_editor.dart index 2c1ce69d3e..6f01d182d7 100644 --- a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/type_option/select_option_editor.dart +++ b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/type_option/select_option_editor.dart @@ -53,34 +53,39 @@ class SelectOptionTypeOptionEditor extends StatelessWidget { ], child: BlocBuilder( builder: (context, state) { - List slivers = [ - SliverToBoxAdapter( - child: _OptionNameTextField( + List cells = [ + _OptionNameTextField( name: state.option.name, autoFocus: autoFocus, - )), - const SliverToBoxAdapter(child: VSpace(10)), - const SliverToBoxAdapter(child: _DeleteTag()), + ), + const VSpace(10), + const _DeleteTag(), ]; if (showOptions) { - slivers - .add(const SliverToBoxAdapter(child: TypeOptionSeparator())); - slivers.add(SliverToBoxAdapter( - child: SelectOptionColorList( - selectedColor: state.option.color))); + cells.add(const TypeOptionSeparator()); + cells.add( + SelectOptionColorList(selectedColor: state.option.color)); } return SizedBox( - width: 160, - child: Padding( - padding: const EdgeInsets.all(6.0), - child: CustomScrollView( - slivers: slivers, - shrinkWrap: true, - controller: ScrollController(), - physics: StyledScrollPhysics(), - ), + width: 180, + child: ListView.builder( + shrinkWrap: true, + controller: ScrollController(), + physics: StyledScrollPhysics(), + itemCount: cells.length, + itemBuilder: (context, index) { + if (cells[index] is TypeOptionSeparator) { + return cells[index]; + } else { + return Padding( + padding: const EdgeInsets.symmetric(horizontal: 6.0), + child: cells[index], + ); + } + }, + padding: const EdgeInsets.symmetric(vertical: 6.0), ), ); }, diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/row/row_detail.dart b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/row/row_detail.dart index 3ec08828a4..23df8ab339 100644 --- a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/row/row_detail.dart +++ b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/row/row_detail.dart @@ -274,6 +274,7 @@ class _RowDetailCellState extends State<_RowDetailCell> { AppFlowyPopover( controller: popover, constraints: BoxConstraints.loose(const Size(240, 600)), + margin: EdgeInsets.zero, triggerActions: PopoverTriggerFlags.none, popupBuilder: (popoverContext) => buildFieldEditor(), child: SizedBox( diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/toolbar/grid_property.dart b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/toolbar/grid_property.dart index 0cc07179b4..fb27af7d2e 100644 --- a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/toolbar/grid_property.dart +++ b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/toolbar/grid_property.dart @@ -117,6 +117,7 @@ class _GridPropertyCell extends StatelessWidget { offset: const Offset(20, 0), direction: PopoverDirection.leftWithTopAligned, constraints: BoxConstraints.loose(const Size(240, 400)), + margin: EdgeInsets.zero, child: FlowyButton( text: FlowyText.medium(fieldInfo.name), leftIcon: svgWidget( diff --git a/frontend/app_flowy/lib/workspace/application/appearance.dart b/frontend/app_flowy/lib/workspace/application/appearance.dart index 247c9ca78f..41e5036db0 100644 --- a/frontend/app_flowy/lib/workspace/application/appearance.dart +++ b/frontend/app_flowy/lib/workspace/application/appearance.dart @@ -201,7 +201,21 @@ class AppearanceSettingsState with _$AppearanceSettingsState { primaryIconTheme: IconThemeData(color: theme.hover), iconTheme: IconThemeData(color: theme.shader1), scrollbarTheme: ScrollbarThemeData( - thumbColor: MaterialStateProperty.all(Colors.transparent), + thumbColor: MaterialStateProperty.all(theme.shader3), + thickness: MaterialStateProperty.resolveWith((states) { + const Set interactiveStates = { + MaterialState.pressed, + MaterialState.hovered, + MaterialState.dragged, + }; + if (states.any(interactiveStates.contains)) { + return 5.0; + } + return 3.0; + }), + crossAxisMargin: 0.0, + mainAxisMargin: 0.0, + radius: Corners.s10Radius, ), materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, canvasColor: theme.shader6,