mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2025-08-16 04:41:29 +00:00
fix: launch review issues (#6479)
* fix(flutter_desktop): field icon picker popover constraints * fix(mobile): immediately select field when editing filter * fix: filter through select options not working * fix(mobile): scroll to bottom after filter creation * fix: primary field tooltip
This commit is contained in:
parent
8ceff03f3e
commit
8e6f051dec
@ -35,11 +35,13 @@ class MobileFilterEditor extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _MobileFilterEditorState extends State<MobileFilterEditor> {
|
class _MobileFilterEditorState extends State<MobileFilterEditor> {
|
||||||
final PageController _pageController = PageController();
|
final pageController = PageController();
|
||||||
|
final scrollController = ScrollController();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
_pageController.dispose();
|
pageController.dispose();
|
||||||
|
scrollController.dispose();
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -47,7 +49,7 @@ class _MobileFilterEditorState extends State<MobileFilterEditor> {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return BlocProvider(
|
return BlocProvider(
|
||||||
create: (context) => MobileFilterEditorCubit(
|
create: (context) => MobileFilterEditorCubit(
|
||||||
pageController: _pageController,
|
pageController: pageController,
|
||||||
),
|
),
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
@ -55,12 +57,12 @@ class _MobileFilterEditorState extends State<MobileFilterEditor> {
|
|||||||
SizedBox(
|
SizedBox(
|
||||||
height: 400,
|
height: 400,
|
||||||
child: PageView.builder(
|
child: PageView.builder(
|
||||||
controller: _pageController,
|
controller: pageController,
|
||||||
itemCount: 2,
|
itemCount: 2,
|
||||||
physics: const NeverScrollableScrollPhysics(),
|
physics: const NeverScrollableScrollPhysics(),
|
||||||
itemBuilder: (context, index) {
|
itemBuilder: (context, index) {
|
||||||
return switch (index) {
|
return switch (index) {
|
||||||
0 => const _ActiveFilters(),
|
0 => _ActiveFilters(scrollController: scrollController),
|
||||||
1 => const _FilterDetail(),
|
1 => const _FilterDetail(),
|
||||||
_ => const SizedBox.shrink(),
|
_ => const SizedBox.shrink(),
|
||||||
};
|
};
|
||||||
@ -124,15 +126,13 @@ class _Header extends StatelessWidget {
|
|||||||
|
|
||||||
bool _isBackButtonShown(MobileFilterEditorState state) {
|
bool _isBackButtonShown(MobileFilterEditorState state) {
|
||||||
return state.maybeWhen(
|
return state.maybeWhen(
|
||||||
overview: () => false,
|
overview: (_) => false,
|
||||||
orElse: () => true,
|
orElse: () => true,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool _isSaveButtonShown(MobileFilterEditorState state) {
|
bool _isSaveButtonShown(MobileFilterEditorState state) {
|
||||||
return state.maybeWhen(
|
return state.maybeWhen(
|
||||||
create: (_) => true,
|
|
||||||
editField: (_, __) => true,
|
|
||||||
editCondition: (filterId, newFilter, showSave) => showSave,
|
editCondition: (filterId, newFilter, showSave) => showSave,
|
||||||
editContent: (_, __) => true,
|
editContent: (_, __) => true,
|
||||||
orElse: () => false,
|
orElse: () => false,
|
||||||
@ -141,8 +141,6 @@ class _Header extends StatelessWidget {
|
|||||||
|
|
||||||
bool _isSaveButtonEnabled(MobileFilterEditorState state) {
|
bool _isSaveButtonEnabled(MobileFilterEditorState state) {
|
||||||
return state.maybeWhen(
|
return state.maybeWhen(
|
||||||
create: (field) => field != null,
|
|
||||||
editField: (_, __) => true,
|
|
||||||
editCondition: (_, __, enableSave) => enableSave,
|
editCondition: (_, __, enableSave) => enableSave,
|
||||||
editContent: (_, __) => true,
|
editContent: (_, __) => true,
|
||||||
orElse: () => false,
|
orElse: () => false,
|
||||||
@ -151,27 +149,6 @@ class _Header extends StatelessWidget {
|
|||||||
|
|
||||||
void _saveOnTapHandler(BuildContext context, MobileFilterEditorState state) {
|
void _saveOnTapHandler(BuildContext context, MobileFilterEditorState state) {
|
||||||
state.maybeWhen(
|
state.maybeWhen(
|
||||||
create: (filterField) {
|
|
||||||
if (filterField != null) {
|
|
||||||
context
|
|
||||||
.read<FilterEditorBloc>()
|
|
||||||
.add(FilterEditorEvent.createFilter(filterField));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
editField: (filterId, newField) {
|
|
||||||
final filter = context
|
|
||||||
.read<FilterEditorBloc>()
|
|
||||||
.state
|
|
||||||
.filters
|
|
||||||
.firstWhereOrNull((filter) => filter.filterId == filterId);
|
|
||||||
if (newField != null &&
|
|
||||||
filter != null &&
|
|
||||||
newField.id != filter.fieldId) {
|
|
||||||
context
|
|
||||||
.read<FilterEditorBloc>()
|
|
||||||
.add(FilterEditorEvent.changeFilteringField(filterId, newField));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
editCondition: (filterId, newFilter, _) {
|
editCondition: (filterId, newFilter, _) {
|
||||||
context
|
context
|
||||||
.read<FilterEditorBloc>()
|
.read<FilterEditorBloc>()
|
||||||
@ -189,7 +166,11 @@ class _Header extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _ActiveFilters extends StatelessWidget {
|
class _ActiveFilters extends StatelessWidget {
|
||||||
const _ActiveFilters();
|
const _ActiveFilters({
|
||||||
|
required this.scrollController,
|
||||||
|
});
|
||||||
|
|
||||||
|
final ScrollController scrollController;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@ -235,7 +216,21 @@ class _ActiveFilters extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Widget _filterList(BuildContext context, FilterEditorState state) {
|
Widget _filterList(BuildContext context, FilterEditorState state) {
|
||||||
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
|
context.read<MobileFilterEditorCubit>().state.maybeWhen(
|
||||||
|
overview: (scrollToBottom) {
|
||||||
|
if (scrollToBottom && scrollController.hasClients) {
|
||||||
|
scrollController
|
||||||
|
.jumpTo(scrollController.position.maxScrollExtent);
|
||||||
|
context.read<MobileFilterEditorCubit>().returnToOverview();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
orElse: () {},
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
return ListView.separated(
|
return ListView.separated(
|
||||||
|
controller: scrollController,
|
||||||
padding: const EdgeInsets.symmetric(
|
padding: const EdgeInsets.symmetric(
|
||||||
horizontal: 16,
|
horizontal: 16,
|
||||||
),
|
),
|
||||||
@ -548,16 +543,32 @@ class _FilterDetail extends StatelessWidget {
|
|||||||
return BlocBuilder<MobileFilterEditorCubit, MobileFilterEditorState>(
|
return BlocBuilder<MobileFilterEditorCubit, MobileFilterEditorState>(
|
||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
return state.maybeWhen(
|
return state.maybeWhen(
|
||||||
create: (filterField) {
|
create: () {
|
||||||
return _FilterableFieldList(
|
|
||||||
onSelectField: (field) =>
|
|
||||||
context.read<MobileFilterEditorCubit>().changeField(field),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
editField: (filterId, newField) {
|
|
||||||
return _FilterableFieldList(
|
return _FilterableFieldList(
|
||||||
onSelectField: (field) {
|
onSelectField: (field) {
|
||||||
context.read<MobileFilterEditorCubit>().changeField(field);
|
context
|
||||||
|
.read<FilterEditorBloc>()
|
||||||
|
.add(FilterEditorEvent.createFilter(field));
|
||||||
|
context.read<MobileFilterEditorCubit>().returnToOverview(
|
||||||
|
scrollToBottom: true,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
editField: (filterId) {
|
||||||
|
return _FilterableFieldList(
|
||||||
|
onSelectField: (field) {
|
||||||
|
final filter = context
|
||||||
|
.read<FilterEditorBloc>()
|
||||||
|
.state
|
||||||
|
.filters
|
||||||
|
.firstWhereOrNull((filter) => filter.filterId == filterId);
|
||||||
|
if (filter != null && field.id != filter.fieldId) {
|
||||||
|
context.read<FilterEditorBloc>().add(
|
||||||
|
FilterEditorEvent.changeFilteringField(filterId, field),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
context.read<MobileFilterEditorCubit>().returnToOverview();
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
@ -619,13 +630,12 @@ class _FilterableFieldList extends StatelessWidget {
|
|||||||
return ListView.builder(
|
return ListView.builder(
|
||||||
itemCount: blocState.fields.length,
|
itemCount: blocState.fields.length,
|
||||||
itemBuilder: (context, index) {
|
itemBuilder: (context, index) {
|
||||||
return FlowyOptionTile.checkbox(
|
return FlowyOptionTile.text(
|
||||||
text: blocState.fields[index].name,
|
text: blocState.fields[index].name,
|
||||||
leftIcon: FieldIcon(
|
leftIcon: FieldIcon(
|
||||||
fieldInfo: blocState.fields[index],
|
fieldInfo: blocState.fields[index],
|
||||||
),
|
),
|
||||||
showTopBorder: false,
|
showTopBorder: false,
|
||||||
isSelected: _isSelected(context, blocState, index),
|
|
||||||
onTap: () => onSelectField(blocState.fields[index]),
|
onTap: () => onSelectField(blocState.fields[index]),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
@ -636,29 +646,6 @@ class _FilterableFieldList extends StatelessWidget {
|
|||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool _isSelected(BuildContext context, FilterEditorState state, int index) {
|
|
||||||
final field = state.fields[index];
|
|
||||||
return context.watch<MobileFilterEditorCubit>().state.maybeWhen(
|
|
||||||
create: (selectedField) {
|
|
||||||
return selectedField != null && selectedField.id == field.id;
|
|
||||||
},
|
|
||||||
editField: (filterId, selectedField) {
|
|
||||||
final filter = state.filters.firstWhereOrNull(
|
|
||||||
(filter) => filter.filterId == filterId,
|
|
||||||
);
|
|
||||||
|
|
||||||
final isOriginalSelectedField =
|
|
||||||
selectedField == null && filter?.fieldId == field.id;
|
|
||||||
|
|
||||||
final isNewSelectedField =
|
|
||||||
selectedField != null && selectedField.id == field.id;
|
|
||||||
|
|
||||||
return isOriginalSelectedField || isNewSelectedField;
|
|
||||||
},
|
|
||||||
orElse: () => false,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class _FilterConditionList extends StatelessWidget {
|
class _FilterConditionList extends StatelessWidget {
|
||||||
@ -960,6 +947,14 @@ class _SelectOptionFilterContentEditor extends StatefulWidget {
|
|||||||
class _SelectOptionFilterContentEditorState
|
class _SelectOptionFilterContentEditorState
|
||||||
extends State<_SelectOptionFilterContentEditor> {
|
extends State<_SelectOptionFilterContentEditor> {
|
||||||
final TextEditingController textController = TextEditingController();
|
final TextEditingController textController = TextEditingController();
|
||||||
|
String filterText = "";
|
||||||
|
final List<SelectOptionPB> options = [];
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
options.addAll(widget.delegate.getOptions(widget.field));
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
@ -969,7 +964,6 @@ class _SelectOptionFilterContentEditorState
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final options = widget.delegate.getOptions(widget.field);
|
|
||||||
return Column(
|
return Column(
|
||||||
children: [
|
children: [
|
||||||
const Divider(
|
const Divider(
|
||||||
@ -980,8 +974,15 @@ class _SelectOptionFilterContentEditorState
|
|||||||
padding: const EdgeInsets.all(16.0),
|
padding: const EdgeInsets.all(16.0),
|
||||||
child: FlowyMobileSearchTextField(
|
child: FlowyMobileSearchTextField(
|
||||||
controller: textController,
|
controller: textController,
|
||||||
onChanged: (asdf) {},
|
onChanged: (text) {
|
||||||
onSubmitted: (asdf) {},
|
if (textController.value.composing.isCollapsed) {
|
||||||
|
setState(() {
|
||||||
|
filterText = text;
|
||||||
|
filterOptions();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onSubmitted: (_) {},
|
||||||
hintText: LocaleKeys.grid_selectOption_searchOption.tr(),
|
hintText: LocaleKeys.grid_selectOption_searchOption.tr(),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -1012,6 +1013,20 @@ class _SelectOptionFilterContentEditorState
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void filterOptions() {
|
||||||
|
options
|
||||||
|
..clear()
|
||||||
|
..addAll(widget.delegate.getOptions(widget.field));
|
||||||
|
|
||||||
|
if (filterText.isNotEmpty) {
|
||||||
|
options.retainWhere((option) {
|
||||||
|
final name = option.name.toLowerCase();
|
||||||
|
final lFilter = filterText.toLowerCase();
|
||||||
|
return name.contains(lFilter);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
MobileSelectedOptionIndicator _getIndicator() {
|
MobileSelectedOptionIndicator _getIndicator() {
|
||||||
return (widget.filter.condition == SelectOptionFilterConditionPB.OptionIs ||
|
return (widget.filter.condition == SelectOptionFilterConditionPB.OptionIs ||
|
||||||
widget.filter.condition ==
|
widget.filter.condition ==
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
import 'package:appflowy/plugins/database/application/field/field_info.dart';
|
|
||||||
import 'package:appflowy/plugins/database/application/field/filter_entities.dart';
|
import 'package:appflowy/plugins/database/application/field/filter_entities.dart';
|
||||||
import 'package:flutter/widgets.dart';
|
import 'package:flutter/widgets.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
@ -13,34 +12,19 @@ class MobileFilterEditorCubit extends Cubit<MobileFilterEditorState> {
|
|||||||
|
|
||||||
final PageController pageController;
|
final PageController pageController;
|
||||||
|
|
||||||
void returnToOverview() {
|
void returnToOverview({bool scrollToBottom = false}) {
|
||||||
_animateToPage(0);
|
_animateToPage(0);
|
||||||
emit(MobileFilterEditorState.overview());
|
emit(MobileFilterEditorState.overview(scrollToBottom: scrollToBottom));
|
||||||
}
|
}
|
||||||
|
|
||||||
void startCreatingFilter() {
|
void startCreatingFilter() {
|
||||||
_animateToPage(1);
|
_animateToPage(1);
|
||||||
emit(MobileFilterEditorState.create(filterField: null));
|
emit(MobileFilterEditorState.create());
|
||||||
}
|
}
|
||||||
|
|
||||||
void startEditingFilterField(String filterId) {
|
void startEditingFilterField(String filterId) {
|
||||||
_animateToPage(1);
|
_animateToPage(1);
|
||||||
emit(MobileFilterEditorState.editField(filterId: filterId, newField: null));
|
emit(MobileFilterEditorState.editField(filterId: filterId));
|
||||||
}
|
|
||||||
|
|
||||||
void changeField(FieldInfo field) {
|
|
||||||
emit(
|
|
||||||
state.maybeWhen(
|
|
||||||
create: (_) => MobileFilterEditorState.create(
|
|
||||||
filterField: field,
|
|
||||||
),
|
|
||||||
editField: (filterId, _) => MobileFilterEditorState.editField(
|
|
||||||
filterId: filterId,
|
|
||||||
newField: field,
|
|
||||||
),
|
|
||||||
orElse: () => state,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void updateFilter(DatabaseFilter filter) {
|
void updateFilter(DatabaseFilter filter) {
|
||||||
@ -97,15 +81,14 @@ class MobileFilterEditorCubit extends Cubit<MobileFilterEditorState> {
|
|||||||
|
|
||||||
@freezed
|
@freezed
|
||||||
class MobileFilterEditorState with _$MobileFilterEditorState {
|
class MobileFilterEditorState with _$MobileFilterEditorState {
|
||||||
factory MobileFilterEditorState.overview() = _OverviewState;
|
factory MobileFilterEditorState.overview({
|
||||||
|
@Default(false) bool scrollToBottom,
|
||||||
|
}) = _OverviewState;
|
||||||
|
|
||||||
factory MobileFilterEditorState.create({
|
factory MobileFilterEditorState.create() = _CreateState;
|
||||||
required FieldInfo? filterField,
|
|
||||||
}) = _CreateState;
|
|
||||||
|
|
||||||
factory MobileFilterEditorState.editField({
|
factory MobileFilterEditorState.editField({
|
||||||
required String filterId,
|
required String filterId,
|
||||||
required FieldInfo? newField,
|
|
||||||
}) = _EditFieldState;
|
}) = _EditFieldState;
|
||||||
|
|
||||||
factory MobileFilterEditorState.editCondition({
|
factory MobileFilterEditorState.editCondition({
|
||||||
|
@ -570,7 +570,7 @@ class _FieldEditIconButtonState extends State<FieldEditIconButton> {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return AppFlowyPopover(
|
return AppFlowyPopover(
|
||||||
offset: const Offset(0, 4),
|
offset: const Offset(0, 4),
|
||||||
constraints: BoxConstraints.loose(const Size(380, 432)),
|
constraints: BoxConstraints.loose(const Size(360, 432)),
|
||||||
margin: EdgeInsets.zero,
|
margin: EdgeInsets.zero,
|
||||||
direction: PopoverDirection.bottomWithLeftAligned,
|
direction: PopoverDirection.bottomWithLeftAligned,
|
||||||
controller: popoverController,
|
controller: popoverController,
|
||||||
@ -693,12 +693,37 @@ class _SwitchFieldButtonState extends State<SwitchFieldButton> {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return BlocBuilder<FieldEditorBloc, FieldEditorState>(
|
return BlocBuilder<FieldEditorBloc, FieldEditorState>(
|
||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
final bool isPrimary = state.field.isPrimary;
|
if (state.field.isPrimary) {
|
||||||
|
return SizedBox(
|
||||||
|
height: GridSize.popoverItemHeight,
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 8.0),
|
||||||
|
child: FlowyTooltip(
|
||||||
|
message: LocaleKeys.grid_field_switchPrimaryFieldTooltip.tr(),
|
||||||
|
child: FlowyButton(
|
||||||
|
text: FlowyText(
|
||||||
|
state.field.fieldType.i18n,
|
||||||
|
lineHeight: 1.0,
|
||||||
|
color: Theme.of(context).disabledColor,
|
||||||
|
),
|
||||||
|
leftIcon: FlowySvg(
|
||||||
|
state.field.fieldType.svgData,
|
||||||
|
color: Theme.of(context).disabledColor,
|
||||||
|
),
|
||||||
|
rightIcon: FlowySvg(
|
||||||
|
FlowySvgs.more_s,
|
||||||
|
color: Theme.of(context).disabledColor,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
return SizedBox(
|
return SizedBox(
|
||||||
height: GridSize.popoverItemHeight,
|
height: GridSize.popoverItemHeight,
|
||||||
child: AppFlowyPopover(
|
child: AppFlowyPopover(
|
||||||
constraints: BoxConstraints.loose(const Size(460, 540)),
|
constraints: BoxConstraints.loose(const Size(460, 540)),
|
||||||
triggerActions: isPrimary ? 0 : PopoverTriggerFlags.hover,
|
triggerActions: PopoverTriggerFlags.hover,
|
||||||
mutex: widget.popoverMutex,
|
mutex: widget.popoverMutex,
|
||||||
controller: _popoverController,
|
controller: _popoverController,
|
||||||
offset: const Offset(8, 0),
|
offset: const Offset(8, 0),
|
||||||
@ -715,23 +740,16 @@ class _SwitchFieldButtonState extends State<SwitchFieldButton> {
|
|||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 8.0),
|
padding: const EdgeInsets.symmetric(horizontal: 8.0),
|
||||||
child: FlowyButton(
|
child: FlowyButton(
|
||||||
onTap: () {
|
onTap: () => _popoverController.show(),
|
||||||
if (!isPrimary) {
|
|
||||||
_popoverController.show();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
text: FlowyText(
|
text: FlowyText(
|
||||||
state.field.fieldType.i18n,
|
state.field.fieldType.i18n,
|
||||||
lineHeight: 1.0,
|
lineHeight: 1.0,
|
||||||
color: isPrimary ? Theme.of(context).disabledColor : null,
|
|
||||||
),
|
),
|
||||||
leftIcon: FlowySvg(
|
leftIcon: FlowySvg(
|
||||||
state.field.fieldType.svgData,
|
state.field.fieldType.svgData,
|
||||||
color: isPrimary ? Theme.of(context).disabledColor : null,
|
|
||||||
),
|
),
|
||||||
rightIcon: FlowySvg(
|
rightIcon: const FlowySvg(
|
||||||
FlowySvgs.more_s,
|
FlowySvgs.more_s,
|
||||||
color: isPrimary ? Theme.of(context).disabledColor : null,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -74,7 +74,7 @@ class _SpaceIconPopupState extends State<SpaceIconPopup> {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return AppFlowyPopover(
|
return AppFlowyPopover(
|
||||||
offset: const Offset(0, 4),
|
offset: const Offset(0, 4),
|
||||||
constraints: BoxConstraints.loose(const Size(380, 432)),
|
constraints: BoxConstraints.loose(const Size(360, 432)),
|
||||||
margin: const EdgeInsets.all(0),
|
margin: const EdgeInsets.all(0),
|
||||||
direction: PopoverDirection.bottomWithCenterAligned,
|
direction: PopoverDirection.bottomWithCenterAligned,
|
||||||
child: _buildPreview(),
|
child: _buildPreview(),
|
||||||
|
@ -1338,6 +1338,7 @@
|
|||||||
"delete": "Delete",
|
"delete": "Delete",
|
||||||
"wrapCellContent": "Wrap text",
|
"wrapCellContent": "Wrap text",
|
||||||
"clear": "Clear cells",
|
"clear": "Clear cells",
|
||||||
|
"switchPrimaryFieldTooltip": "Cannot change field type of primary field",
|
||||||
"textFieldName": "Text",
|
"textFieldName": "Text",
|
||||||
"checkboxFieldName": "Checkbox",
|
"checkboxFieldName": "Checkbox",
|
||||||
"dateFieldName": "Date",
|
"dateFieldName": "Date",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user