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
This commit is contained in:
Richard Shiue 2022-12-27 08:21:30 +08:00 committed by GitHub
parent f5b7d3951f
commit 70689d3239
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 437 additions and 343 deletions

View File

@ -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,

View File

@ -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<DateCellEditor> {
Widget _buildWidget(AsyncSnapshot<Either<dynamic, FlowyError>> 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<Widget> 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<DateCalBloc>(),
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<DateCalBloc, DateCalState, bool>(
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<DateCalBloc>()
.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<DateCalBloc>()
.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),
),
);
}

View File

@ -182,6 +182,7 @@ class _SelectOptionWrapState extends State<SelectOptionWrap> {
return AppFlowyPopover(
controller: _popover,
constraints: constraints,
margin: EdgeInsets.zero,
direction: PopoverDirection.bottomWithLeftAligned,
popupBuilder: (BuildContext context) {
WidgetsBinding.instance.addPostFrameCallback((_) {

View File

@ -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<SelectOptionCellEditor> {
)..add(const SelectOptionEditorEvent.initial()),
child: BlocBuilder<SelectOptionCellEditorBloc, SelectOptionEditorState>(
builder: (context, state) {
final List<Widget> 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<SelectOptionCellEditorBloc, SelectOptionEditorState>(
builder: (context, state) {
List<Widget> 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<SelectOptionCellEditorBloc>()
.add(SelectOptionEditorEvent.filterOption(text));
},
onSubmitted: (tagName) {
context
.read<SelectOptionCellEditorBloc>()
.add(SelectOptionEditorEvent.trySelectOption(tagName));
},
onPaste: (tagNames, remainder) {
context
.read<SelectOptionCellEditorBloc>()
.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<SelectOptionCellEditorBloc>()
.add(SelectOptionEditorEvent.filterOption(text));
},
onSubmitted: (tagName) {
context
.read<SelectOptionCellEditorBloc>()
.add(SelectOptionEditorEvent.trySelectOption(tagName));
},
onPaste: (tagNames, remainder) {
context
.read<SelectOptionCellEditorBloc>()
.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<SelectOptionCellEditorBloc>()
.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<SelectOptionCellEditorBloc>()
.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<SelectOptionCellEditorBloc>()
.add(SelectOptionEditorEvent.unSelectOption(option.id));
} else {
context
.read<SelectOptionCellEditorBloc>()
.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<SelectOptionCellEditorBloc>()
.add(SelectOptionEditorEvent.unSelectOption(option.id));
} else {
context
.read<SelectOptionCellEditorBloc>()
.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(

View File

@ -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,

View File

@ -45,6 +45,7 @@ class _GridFieldCellState extends State<GridFieldCell> {
final button = AppFlowyPopover(
triggerActions: PopoverTriggerFlags.none,
constraints: BoxConstraints.loose(const Size(240, 440)),
margin: EdgeInsets.zero,
direction: PopoverDirection.bottomWithLeftAligned,
controller: popoverController,
popupBuilder: (BuildContext context) {

View File

@ -44,6 +44,7 @@ class _GridFieldCellActionSheetState extends State<GridFieldCellActionSheet> {
create: (context) =>
getIt<FieldActionSheetBloc>(param1: widget.cellContext),
child: SingleChildScrollView(
padding: const EdgeInsets.all(12.0),
child: Column(
children: [
_EditFieldButton(
@ -54,7 +55,7 @@ class _GridFieldCellActionSheetState extends State<GridFieldCellActionSheet> {
});
},
),
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(),
);

View File

@ -51,6 +51,12 @@ class _FieldEditorState extends State<FieldEditor> {
@override
Widget build(BuildContext context) {
List<Widget> 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<FieldEditor> {
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<Widget> _addDeleteFieldButton() {
if (widget.onDeleted == null) {
return [];
}
return [
BlocBuilder<FieldEditorBloc, FieldEditorState>(
builder: (context, state) {
return _DeleteFieldButton(
Widget _addDeleteFieldButton() {
return BlocBuilder<FieldEditorBloc, FieldEditorState>(
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<FieldEditor> {
(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<FieldEditorBloc>().state.errorText,
onChanged: (newName) {
context
.read<FieldEditorBloc>()
.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<FieldEditorBloc>().state.errorText,
onChanged: (newName) {
context
.read<FieldEditorBloc>()
.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),
);
},
);
}

View File

@ -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,

View File

@ -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<DateTypeOptionBloc, DateTypeOptionState, bool>(
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<DateTypeOptionBloc>()
.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<DateTypeOptionBloc>()
.add(DateTypeOptionEvent.includeTime(!value));
},
style: ToggleStyle.big,
padding: EdgeInsets.zero,
),
],
),
),
),
);

View File

@ -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<NumberFormatBloc, NumberFormatState>(
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<NumberFormatBloc>()
.add(NumberFormatEvent.setFilter(text)),
return Padding(
padding: const EdgeInsets.all(6.0),
child: FlowyTextField(
onChanged: (text) => context
.read<NumberFormatBloc>()
.add(NumberFormatEvent.setFilter(text)),
),
);
}
}

View File

@ -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<SelectOptionTypeOptionBloc>()
.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<SelectOptionTypeOptionBloc>()
.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<SelectOptionTypeOptionBloc, SelectOptionTypeOptionState>(
builder: (context, state) {
final text = state.newOptionName.foldRight("", (a, previous) => a);
return FlowyTextField(
autoClearWhenDone: true,
maxLength: 30,
text: text,
focusNode: _focusNode,
onCanceled: () {
context
.read<SelectOptionTypeOptionBloc>()
.add(const SelectOptionTypeOptionEvent.endAddingOption());
},
onEditingComplete: () {},
onSubmitted: (optionName) {
context
.read<SelectOptionTypeOptionBloc>()
.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<SelectOptionTypeOptionBloc>()
.add(const SelectOptionTypeOptionEvent.endAddingOption());
},
onEditingComplete: () {},
onSubmitted: (optionName) {
context
.read<SelectOptionTypeOptionBloc>()
.add(SelectOptionTypeOptionEvent.createOption(optionName));
},
),
);
},
);

View File

@ -53,34 +53,39 @@ class SelectOptionTypeOptionEditor extends StatelessWidget {
],
child: BlocBuilder<EditSelectOptionBloc, EditSelectOptionState>(
builder: (context, state) {
List<Widget> slivers = [
SliverToBoxAdapter(
child: _OptionNameTextField(
List<Widget> 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),
),
);
},

View File

@ -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(

View File

@ -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(

View File

@ -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<MaterialState> interactiveStates = <MaterialState>{
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,