Skip to content

Commit bb61bf0

Browse files
authored
Merge pull request #1102 from AppFlowy-IO/fix/ui_bugs
Fix/UI bugs
2 parents 56e68d1 + ca89fd9 commit bb61bf0

File tree

13 files changed

+260
-234
lines changed

13 files changed

+260
-234
lines changed

frontend/app_flowy/lib/plugins/grid/application/field/field_editor_bloc.dart

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,10 @@ class FieldEditorBloc extends Bloc<FieldEditorEvent, FieldEditorState> {
3333
await dataController.loadTypeOptionData();
3434
},
3535
updateName: (name) {
36-
dataController.fieldName = name;
37-
emit(state.copyWith(name: name));
36+
if (state.name != name) {
37+
dataController.fieldName = name;
38+
emit(state.copyWith(name: name));
39+
}
3840
},
3941
didReceiveFieldChanged: (FieldPB field) {
4042
emit(state.copyWith(

frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/date_cell/date_cell.dart

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ class _DateCellState extends GridCellState<GridDateCell> {
5858
Widget build(BuildContext context) {
5959
final alignment = widget.cellStyle != null
6060
? widget.cellStyle!.alignment
61-
: Alignment.center;
61+
: Alignment.centerLeft;
6262
return BlocProvider.value(
6363
value: _cellBloc,
6464
child: BlocBuilder<DateCellBloc, DateCellState>(
@@ -77,7 +77,10 @@ class _DateCellState extends GridCellState<GridDateCell> {
7777
cursor: SystemMouseCursors.click,
7878
child: Align(
7979
alignment: alignment,
80-
child: FlowyText.medium(state.dateStr, fontSize: 12),
80+
child: FlowyText.medium(
81+
state.dateStr,
82+
fontSize: 12,
83+
),
8184
),
8285
),
8386
),

frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/select_option_cell/text_field.dart

Lines changed: 41 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -11,20 +11,17 @@ import 'package:textfield_tags/textfield_tags.dart';
1111

1212
import 'extension.dart';
1313

14-
class SelectOptionTextField extends StatelessWidget {
15-
final FocusNode _focusNode;
16-
final TextEditingController _controller;
14+
class SelectOptionTextField extends StatefulWidget {
1715
final TextfieldTagsController tagController;
1816
final List<SelectOptionPB> options;
1917
final LinkedHashMap<String, SelectOptionPB> selectedOptionMap;
20-
2118
final double distanceToText;
2219

2320
final Function(String) onNewTag;
2421
final Function(String) newText;
2522
final VoidCallback? onClick;
2623

27-
SelectOptionTextField({
24+
const SelectOptionTextField({
2825
required this.options,
2926
required this.selectedOptionMap,
3027
required this.distanceToText,
@@ -35,41 +32,63 @@ class SelectOptionTextField extends StatelessWidget {
3532
TextEditingController? textController,
3633
FocusNode? focusNode,
3734
Key? key,
38-
}) : _controller = textController ?? TextEditingController(),
39-
_focusNode = focusNode ?? FocusNode(),
40-
super(key: key);
35+
}) : super(key: key);
36+
37+
@override
38+
State<SelectOptionTextField> createState() => _SelectOptionTextFieldState();
39+
}
40+
41+
class _SelectOptionTextFieldState extends State<SelectOptionTextField> {
42+
late FocusNode focusNode;
43+
late TextEditingController controller;
44+
45+
@override
46+
void initState() {
47+
focusNode = FocusNode();
48+
controller = TextEditingController();
49+
50+
WidgetsBinding.instance.addPostFrameCallback((_) {
51+
focusNode.requestFocus();
52+
});
53+
super.initState();
54+
}
4155

4256
@override
4357
Widget build(BuildContext context) {
4458
final theme = context.watch<AppTheme>();
4559

4660
return TextFieldTags(
47-
textEditingController: _controller,
48-
textfieldTagsController: tagController,
49-
initialTags: selectedOptionMap.keys.toList(),
50-
focusNode: _focusNode,
61+
textEditingController: controller,
62+
textfieldTagsController: widget.tagController,
63+
initialTags: widget.selectedOptionMap.keys.toList(),
64+
focusNode: focusNode,
5165
textSeparators: const [','],
52-
inputfieldBuilder: (BuildContext context, editController, focusNode,
53-
error, onChanged, onSubmitted) {
66+
inputfieldBuilder: (
67+
BuildContext context,
68+
editController,
69+
focusNode,
70+
error,
71+
onChanged,
72+
onSubmitted,
73+
) {
5474
return ((context, sc, tags, onTagDelegate) {
5575
return TextField(
56-
autofocus: true,
5776
controller: editController,
5877
focusNode: focusNode,
59-
onTap: onClick,
78+
onTap: widget.onClick,
6079
onChanged: (text) {
6180
if (onChanged != null) {
6281
onChanged(text);
6382
}
64-
newText(text);
83+
widget.newText(text);
6584
},
6685
onSubmitted: (text) {
6786
if (onSubmitted != null) {
6887
onSubmitted(text);
6988
}
7089

7190
if (text.isNotEmpty) {
72-
onNewTag(text);
91+
widget.onNewTag(text);
7392
focusNode.requestFocus();
7493
}
7594
},
@@ -83,7 +102,8 @@ class SelectOptionTextField extends StatelessWidget {
83102
isDense: true,
84103
prefixIcon: _renderTags(context, sc),
85104
hintText: LocaleKeys.grid_selectOption_searchOption.tr(),
86-
prefixIconConstraints: BoxConstraints(maxWidth: distanceToText),
105+
prefixIconConstraints:
106+
BoxConstraints(maxWidth: widget.distanceToText),
87107
focusedBorder: OutlineInputBorder(
88108
borderSide: BorderSide(color: theme.main1, width: 1.0),
89109
borderRadius: Corners.s10Border,
@@ -96,11 +116,11 @@ class SelectOptionTextField extends StatelessWidget {
96116
}
97117

98118
Widget? _renderTags(BuildContext context, ScrollController sc) {
99-
if (selectedOptionMap.isEmpty) {
119+
if (widget.selectedOptionMap.isEmpty) {
100120
return null;
101121
}
102122

103-
final children = selectedOptionMap.values
123+
final children = widget.selectedOptionMap.values
104124
.map((option) =>
105125
SelectOptionTag.fromOption(context: context, option: option))
106126
.toList();

frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/field_cell.dart

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,9 +137,11 @@ class _DragToExpandLine extends StatelessWidget {
137137
class FieldCellButton extends StatelessWidget {
138138
final VoidCallback onTap;
139139
final FieldPB field;
140+
final int? maxLines;
140141
const FieldCellButton({
141142
required this.field,
142143
required this.onTap,
144+
this.maxLines = 1,
143145
Key? key,
144146
}) : super(key: key);
145147

@@ -150,7 +152,11 @@ class FieldCellButton extends StatelessWidget {
150152
hoverColor: theme.shader6,
151153
onTap: onTap,
152154
leftIcon: svgWidget(field.fieldType.iconName(), color: theme.iconColor),
153-
text: FlowyText.medium(field.name, fontSize: 12),
155+
text: FlowyText.medium(
156+
field.name,
157+
fontSize: 12,
158+
maxLines: maxLines,
159+
),
154160
margin: GridSize.cellContentInsets,
155161
);
156162
}

frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/field_editor.dart

Lines changed: 48 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
import 'package:app_flowy/plugins/grid/application/field/field_editor_bloc.dart';
22
import 'package:app_flowy/plugins/grid/application/field/type_option/type_option_context.dart';
33
import 'package:appflowy_popover/appflowy_popover.dart';
4+
import 'package:dartz/dartz.dart' show none;
45
import 'package:easy_localization/easy_localization.dart';
5-
import 'package:app_flowy/workspace/presentation/widgets/dialogs.dart';
66
import 'package:flowy_infra/theme.dart';
7-
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
87
import 'package:flowy_infra_ui/style_widget/button.dart';
98
import 'package:flowy_infra_ui/style_widget/text.dart';
109
import 'package:flowy_infra_ui/widget/rounded_input_field.dart';
@@ -59,38 +58,38 @@ class _FieldEditorState extends State<FieldEditor> {
5958
isGroupField: widget.isGroupField,
6059
loader: widget.typeOptionLoader,
6160
)..add(const FieldEditorEvent.initial()),
62-
child: BlocBuilder<FieldEditorBloc, FieldEditorState>(
63-
builder: (context, state) {
64-
return ListView(
65-
shrinkWrap: true,
66-
children: [
67-
FlowyText.medium(
68-
LocaleKeys.grid_field_editProperty.tr(),
69-
fontSize: 12,
70-
),
71-
const VSpace(10),
72-
_FieldNameTextField(popoverMutex: popoverMutex),
73-
const VSpace(10),
74-
..._addDeleteFieldButton(state),
75-
_FieldTypeOptionCell(popoverMutex: popoverMutex),
76-
],
77-
);
78-
},
61+
child: ListView(
62+
shrinkWrap: true,
63+
children: [
64+
FlowyText.medium(
65+
LocaleKeys.grid_field_editProperty.tr(),
66+
fontSize: 12,
67+
),
68+
const VSpace(10),
69+
_FieldNameTextField(popoverMutex: popoverMutex),
70+
const VSpace(10),
71+
..._addDeleteFieldButton(),
72+
_FieldTypeOptionCell(popoverMutex: popoverMutex),
73+
],
7974
),
8075
);
8176
}
8277

83-
List<Widget> _addDeleteFieldButton(FieldEditorState state) {
78+
List<Widget> _addDeleteFieldButton() {
8479
if (widget.onDeleted == null) {
8580
return [];
8681
}
8782
return [
88-
_DeleteFieldButton(
89-
popoverMutex: popoverMutex,
90-
onDeleted: () {
91-
state.field.fold(
92-
() => Log.error('Can not delete the field'),
93-
(field) => widget.onDeleted?.call(field.id),
83+
BlocBuilder<FieldEditorBloc, FieldEditorState>(
84+
builder: (context, state) {
85+
return _DeleteFieldButton(
86+
popoverMutex: popoverMutex,
87+
onDeleted: () {
88+
state.field.fold(
89+
() => Log.error('Can not delete the field'),
90+
(field) => widget.onDeleted?.call(field.id),
91+
);
92+
},
9493
);
9594
},
9695
),
@@ -139,13 +138,13 @@ class _FieldNameTextField extends StatefulWidget {
139138
}
140139

141140
class _FieldNameTextFieldState extends State<_FieldNameTextField> {
142-
late String name;
143141
FocusNode focusNode = FocusNode();
144142
VoidCallback? _popoverCallback;
145-
TextEditingController controller = TextEditingController();
143+
late TextEditingController controller;
146144

147145
@override
148146
void initState() {
147+
controller = TextEditingController();
149148
focusNode.addListener(() {
150149
if (focusNode.hasFocus) {
151150
widget.popoverMutex.close();
@@ -158,20 +157,29 @@ class _FieldNameTextFieldState extends State<_FieldNameTextField> {
158157
@override
159158
Widget build(BuildContext context) {
160159
final theme = context.watch<AppTheme>();
161-
162-
controller.text = context.read<FieldEditorBloc>().state.name;
163-
return BlocListener<FieldEditorBloc, FieldEditorState>(
164-
listenWhen: (previous, current) => previous.name != current.name,
165-
listener: (context, state) {
166-
controller.text = state.name;
167-
},
160+
return MultiBlocListener(
161+
listeners: [
162+
BlocListener<FieldEditorBloc, FieldEditorState>(
163+
listenWhen: (p, c) => p.field == none(),
164+
listener: (context, state) {
165+
focusNode.requestFocus();
166+
},
167+
),
168+
BlocListener<FieldEditorBloc, FieldEditorState>(
169+
listenWhen: (p, c) => controller.text != c.name,
170+
listener: (context, state) {
171+
controller.text = state.name;
172+
},
173+
),
174+
],
168175
child: BlocBuilder<FieldEditorBloc, FieldEditorState>(
176+
buildWhen: (previous, current) =>
177+
previous.errorText != current.errorText,
169178
builder: (context, state) {
170179
listenOnPopoverChanged(context);
171180

172181
return RoundedInputField(
173182
height: 36,
174-
autoFocus: true,
175183
focusNode: focusNode,
176184
style: const TextStyle(fontSize: 13, fontWeight: FontWeight.w500),
177185
controller: controller,
@@ -193,23 +201,15 @@ class _FieldNameTextFieldState extends State<_FieldNameTextField> {
193201

194202
void listenOnPopoverChanged(BuildContext context) {
195203
if (_popoverCallback != null) {
196-
widget.popoverMutex.removePopoverStateListener(_popoverCallback!);
204+
widget.popoverMutex.removePopoverListener(_popoverCallback!);
197205
}
198-
_popoverCallback = widget.popoverMutex.listenOnPopoverStateChanged(() {
206+
_popoverCallback = widget.popoverMutex.listenOnPopoverChanged(() {
199207
if (focusNode.hasFocus) {
200208
final node = FocusScope.of(context);
201209
node.unfocus();
202210
}
203211
});
204212
}
205-
206-
@override
207-
void didUpdateWidget(covariant _FieldNameTextField oldWidget) {
208-
controller.selection = TextSelection.fromPosition(
209-
TextPosition(offset: controller.text.length));
210-
211-
super.didUpdateWidget(oldWidget);
212-
}
213213
}
214214

215215
class _DeleteFieldButton extends StatelessWidget {
@@ -235,29 +235,11 @@ class _DeleteFieldButton extends StatelessWidget {
235235
fontSize: 12,
236236
color: enable ? null : theme.shader4,
237237
),
238+
onTap: () => onDeleted?.call(),
238239
);
239-
if (enable) button = _wrapPopover(button);
240+
// if (enable) button = button;
240241
return button;
241242
},
242243
);
243244
}
244-
245-
Widget _wrapPopover(Widget widget) {
246-
return AppFlowyPopover(
247-
triggerActions: PopoverTriggerFlags.click,
248-
constraints: BoxConstraints.loose(const Size(400, 240)),
249-
mutex: popoverMutex,
250-
direction: PopoverDirection.center,
251-
popupBuilder: (popupContext) {
252-
return PopoverAlertView(
253-
title: LocaleKeys.grid_field_deleteFieldPromptMessage.tr(),
254-
cancel: () {},
255-
confirm: () {
256-
onDeleted?.call();
257-
},
258-
);
259-
},
260-
child: widget,
261-
);
262-
}
263245
}

frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/field_type_option_editor.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ class FieldTypeOptionEditor extends StatelessWidget {
6565
return SizedBox(
6666
height: GridSize.typeOptionItemHeight,
6767
child: AppFlowyPopover(
68-
constraints: BoxConstraints.loose(const Size(460, 440)),
68+
constraints: BoxConstraints.loose(const Size(460, 540)),
6969
asBarrier: true,
7070
triggerActions: PopoverTriggerFlags.click | PopoverTriggerFlags.hover,
7171
mutex: popoverMutex,

frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/type_option/date.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ class DateTypeOptionWidget extends TypeOptionWidget {
6464
Widget _renderDateFormatButton(BuildContext context, DateFormat dataFormat) {
6565
return AppFlowyPopover(
6666
mutex: popoverMutex,
67+
asBarrier: true,
6768
triggerActions: PopoverTriggerFlags.hover | PopoverTriggerFlags.click,
6869
offset: const Offset(20, 0),
6970
constraints: BoxConstraints.loose(const Size(460, 440)),
@@ -85,6 +86,7 @@ class DateTypeOptionWidget extends TypeOptionWidget {
8586
Widget _renderTimeFormatButton(BuildContext context, TimeFormat timeFormat) {
8687
return AppFlowyPopover(
8788
mutex: popoverMutex,
89+
asBarrier: true,
8890
triggerActions: PopoverTriggerFlags.hover | PopoverTriggerFlags.click,
8991
offset: const Offset(20, 0),
9092
constraints: BoxConstraints.loose(const Size(460, 440)),

0 commit comments

Comments
 (0)