mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
fix: mobile field editing related bugs (#4534)
* fix: mobile field editing related bugs * chore: review * chore: restore podfile.lock
This commit is contained in:
parent
05a06980b9
commit
63c22feb8f
frontend/appflowy_flutter/lib/mobile/presentation/database
@ -69,7 +69,7 @@ class _MobileNewPropertyScreenState extends State<MobileNewPropertyScreen> {
|
||||
),
|
||||
],
|
||||
),
|
||||
body: FieldOptionEditor(
|
||||
body: MobileFieldEditor(
|
||||
mode: FieldOptionMode.add,
|
||||
defaultValues: optionValues,
|
||||
onOptionValuesChanged: (optionValues) {
|
||||
|
@ -32,12 +32,12 @@ class MobileEditPropertyScreen extends StatefulWidget {
|
||||
|
||||
class _MobileEditPropertyScreenState extends State<MobileEditPropertyScreen> {
|
||||
late final FieldBackendService fieldService;
|
||||
late FieldOptionValues field;
|
||||
late FieldOptionValues _fieldOptionValues;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
field = FieldOptionValues.fromField(field: widget.field.field);
|
||||
_fieldOptionValues = FieldOptionValues.fromField(field: widget.field.field);
|
||||
fieldService = FieldBackendService(
|
||||
viewId: widget.viewId,
|
||||
fieldId: widget.field.id,
|
||||
@ -49,76 +49,69 @@ class _MobileEditPropertyScreenState extends State<MobileEditPropertyScreen> {
|
||||
final viewId = widget.viewId;
|
||||
final fieldId = widget.field.id;
|
||||
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
centerTitle: true,
|
||||
title: FlowyText.medium(
|
||||
LocaleKeys.grid_field_editProperty.tr(),
|
||||
),
|
||||
elevation: 0,
|
||||
bottom: const PreferredSize(
|
||||
preferredSize: Size.fromHeight(1),
|
||||
child: Divider(
|
||||
height: 1,
|
||||
thickness: 1,
|
||||
return PopScope(
|
||||
onPopInvoked: (didPop) {
|
||||
if (didPop) {
|
||||
context.pop(_fieldOptionValues);
|
||||
}
|
||||
},
|
||||
child: Scaffold(
|
||||
appBar: AppBar(
|
||||
centerTitle: true,
|
||||
title: FlowyText.medium(
|
||||
LocaleKeys.grid_field_editProperty.tr(),
|
||||
),
|
||||
elevation: 0,
|
||||
bottom: const PreferredSize(
|
||||
preferredSize: Size.fromHeight(1),
|
||||
child: Divider(
|
||||
height: 1,
|
||||
thickness: 1,
|
||||
),
|
||||
),
|
||||
leading: AppBarBackButton(
|
||||
onTap: () => context.pop(_fieldOptionValues),
|
||||
),
|
||||
),
|
||||
leading: AppBarBackButton(
|
||||
onTap: () => context.pop(field),
|
||||
),
|
||||
),
|
||||
body: FieldOptionEditor(
|
||||
mode: FieldOptionMode.edit,
|
||||
isPrimary: widget.field.isPrimary,
|
||||
defaultValues: field,
|
||||
actions: [
|
||||
if (widget.field.fieldSettings?.visibility.isVisibleState() ?? true)
|
||||
FieldOptionAction.hide
|
||||
else
|
||||
FieldOptionAction.show,
|
||||
FieldOptionAction.duplicate,
|
||||
FieldOptionAction.delete,
|
||||
],
|
||||
onOptionValuesChanged: (newField) async {
|
||||
if (newField.name != field.name) {
|
||||
await fieldService.updateField(name: newField.name);
|
||||
}
|
||||
|
||||
if (newField.type != widget.field.fieldType) {
|
||||
await fieldService.updateType(fieldType: newField.type);
|
||||
}
|
||||
|
||||
final data = newField.getTypeOptionData();
|
||||
if (data != null) {
|
||||
await FieldBackendService.updateFieldTypeOption(
|
||||
body: MobileFieldEditor(
|
||||
mode: FieldOptionMode.edit,
|
||||
isPrimary: widget.field.isPrimary,
|
||||
defaultValues: _fieldOptionValues,
|
||||
actions: [
|
||||
widget.field.fieldSettings?.visibility.isVisibleState() ?? true
|
||||
? FieldOptionAction.hide
|
||||
: FieldOptionAction.show,
|
||||
FieldOptionAction.duplicate,
|
||||
FieldOptionAction.delete,
|
||||
],
|
||||
onOptionValuesChanged: (newFieldOptionValues) {
|
||||
setState(() {
|
||||
_fieldOptionValues = newFieldOptionValues;
|
||||
});
|
||||
},
|
||||
onAction: (action) {
|
||||
final service = FieldServices(
|
||||
viewId: viewId,
|
||||
fieldId: widget.field.id,
|
||||
typeOptionData: data,
|
||||
fieldId: fieldId,
|
||||
);
|
||||
}
|
||||
// setState(() => field = newField);
|
||||
},
|
||||
onAction: (action) {
|
||||
final service = FieldServices(
|
||||
viewId: viewId,
|
||||
fieldId: fieldId,
|
||||
);
|
||||
switch (action) {
|
||||
case FieldOptionAction.delete:
|
||||
service.delete();
|
||||
break;
|
||||
case FieldOptionAction.duplicate:
|
||||
service.duplicate();
|
||||
break;
|
||||
case FieldOptionAction.hide:
|
||||
service.hide();
|
||||
break;
|
||||
case FieldOptionAction.show:
|
||||
service.show();
|
||||
break;
|
||||
}
|
||||
context.pop(field);
|
||||
},
|
||||
switch (action) {
|
||||
case FieldOptionAction.delete:
|
||||
fieldService.delete();
|
||||
context.pop();
|
||||
return;
|
||||
case FieldOptionAction.duplicate:
|
||||
fieldService.duplicate();
|
||||
break;
|
||||
case FieldOptionAction.hide:
|
||||
service.hide();
|
||||
break;
|
||||
case FieldOptionAction.show:
|
||||
service.show();
|
||||
break;
|
||||
}
|
||||
context.pop(_fieldOptionValues);
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
@ -12,6 +12,8 @@ import 'mobile_field_type_grid.dart';
|
||||
import 'mobile_field_type_option_editor.dart';
|
||||
import 'mobile_quick_field_editor.dart';
|
||||
|
||||
/// Shows the field type grid and upon selection, allow users to edit the
|
||||
/// field's properties and saving it when the user clicks save.
|
||||
void showCreateFieldBottomSheet(
|
||||
BuildContext context,
|
||||
String viewId, {
|
||||
@ -24,9 +26,10 @@ void showCreateFieldBottomSheet(
|
||||
return DraggableScrollableSheet(
|
||||
expand: false,
|
||||
snap: true,
|
||||
initialChildSize: 0.7,
|
||||
minChildSize: 0.7,
|
||||
builder: (context, controller) => FieldOptions(
|
||||
initialChildSize: 0.97,
|
||||
minChildSize: 0.97,
|
||||
maxChildSize: 0.97,
|
||||
builder: (context, controller) => MobileFieldTypeGrid(
|
||||
scrollController: controller,
|
||||
mode: FieldOptionMode.add,
|
||||
onSelectFieldType: (type) async {
|
||||
@ -52,22 +55,22 @@ void showCreateFieldBottomSheet(
|
||||
);
|
||||
}
|
||||
|
||||
/// Used to edit a field.
|
||||
Future<FieldOptionValues?> showEditFieldScreen(
|
||||
BuildContext context,
|
||||
String viewId,
|
||||
FieldInfo field,
|
||||
) async {
|
||||
final optionValues = await context.push<FieldOptionValues>(
|
||||
) {
|
||||
return context.push<FieldOptionValues>(
|
||||
MobileEditPropertyScreen.routeName,
|
||||
extra: {
|
||||
MobileEditPropertyScreen.argViewId: viewId,
|
||||
MobileEditPropertyScreen.argField: field,
|
||||
},
|
||||
);
|
||||
|
||||
return optionValues;
|
||||
}
|
||||
|
||||
/// Shows some quick field options in a bottom sheet.
|
||||
void showQuickEditField(
|
||||
BuildContext context,
|
||||
String viewId,
|
||||
@ -89,6 +92,7 @@ void showQuickEditField(
|
||||
);
|
||||
}
|
||||
|
||||
/// Display a list of fields in the current database that users can choose from.
|
||||
Future<String?> showFieldPicker(
|
||||
BuildContext context,
|
||||
String? selectedFieldId,
|
||||
|
@ -23,8 +23,8 @@ const _supportedFieldTypes = [
|
||||
FieldType.CreatedTime,
|
||||
];
|
||||
|
||||
class FieldOptions extends StatelessWidget {
|
||||
const FieldOptions({
|
||||
class MobileFieldTypeGrid extends StatelessWidget {
|
||||
const MobileFieldTypeGrid({
|
||||
super.key,
|
||||
required this.mode,
|
||||
required this.onSelectFieldType,
|
||||
|
@ -159,8 +159,8 @@ enum FieldOptionAction {
|
||||
delete,
|
||||
}
|
||||
|
||||
class FieldOptionEditor extends StatefulWidget {
|
||||
const FieldOptionEditor({
|
||||
class MobileFieldEditor extends StatefulWidget {
|
||||
const MobileFieldEditor({
|
||||
super.key,
|
||||
required this.mode,
|
||||
required this.defaultValues,
|
||||
@ -182,11 +182,12 @@ class FieldOptionEditor extends StatefulWidget {
|
||||
final bool isPrimary;
|
||||
|
||||
@override
|
||||
State<FieldOptionEditor> createState() => _FieldOptionEditorState();
|
||||
State<MobileFieldEditor> createState() => _MobileFieldEditorState();
|
||||
}
|
||||
|
||||
class _FieldOptionEditorState extends State<FieldOptionEditor> {
|
||||
class _MobileFieldEditorState extends State<MobileFieldEditor> {
|
||||
final controller = TextEditingController();
|
||||
bool isFieldNameChanged = false;
|
||||
|
||||
late FieldOptionValues values;
|
||||
|
||||
@ -219,6 +220,7 @@ class _FieldOptionEditorState extends State<FieldOptionEditor> {
|
||||
controller: controller,
|
||||
type: values.type,
|
||||
onTextChanged: (value) {
|
||||
isFieldNameChanged = true;
|
||||
_updateOptionValues(name: value);
|
||||
},
|
||||
),
|
||||
@ -226,16 +228,18 @@ class _FieldOptionEditorState extends State<FieldOptionEditor> {
|
||||
if (!widget.isPrimary) ...[
|
||||
_PropertyType(
|
||||
type: values.type,
|
||||
onSelected: (type) => setState(
|
||||
() {
|
||||
if (widget.mode == FieldOptionMode.add) {
|
||||
controller.text = type.i18n;
|
||||
_updateOptionValues(name: type.i18n, type: type);
|
||||
} else {
|
||||
onSelected: (type) {
|
||||
setState(
|
||||
() {
|
||||
if (widget.mode == FieldOptionMode.add &&
|
||||
!isFieldNameChanged) {
|
||||
controller.text = type.i18n;
|
||||
_updateOptionValues(name: type.i18n);
|
||||
}
|
||||
_updateOptionValues(type: type);
|
||||
}
|
||||
},
|
||||
),
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
const _Divider(),
|
||||
if (option.isNotEmpty) ...[
|
||||
@ -446,9 +450,10 @@ class _PropertyType extends StatelessWidget {
|
||||
return DraggableScrollableSheet(
|
||||
expand: false,
|
||||
snap: true,
|
||||
initialChildSize: 0.7,
|
||||
minChildSize: 0.7,
|
||||
builder: (context, controller) => FieldOptions(
|
||||
initialChildSize: 0.97,
|
||||
minChildSize: 0.97,
|
||||
maxChildSize: 0.97,
|
||||
builder: (context, controller) => MobileFieldTypeGrid(
|
||||
scrollController: controller,
|
||||
mode: FieldOptionMode.edit,
|
||||
onSelectFieldType: (type) {
|
||||
@ -894,10 +899,10 @@ class _SelectOptionTile extends StatefulWidget {
|
||||
final void Function(SelectOptionPB option) onUpdateOption;
|
||||
|
||||
@override
|
||||
State<_SelectOptionTile> createState() => __SelectOptionTileState();
|
||||
State<_SelectOptionTile> createState() => _SelectOptionTileState();
|
||||
}
|
||||
|
||||
class __SelectOptionTileState extends State<_SelectOptionTile> {
|
||||
class _SelectOptionTileState extends State<_SelectOptionTile> {
|
||||
final TextEditingController controller = TextEditingController();
|
||||
late SelectOptionPB option;
|
||||
|
||||
|
@ -3,9 +3,11 @@ import 'package:appflowy/generated/locale_keys.g.dart';
|
||||
import 'package:appflowy/mobile/presentation/base/app_bar_actions.dart';
|
||||
import 'package:appflowy/mobile/presentation/database/card/card_detail/widgets/widgets.dart';
|
||||
import 'package:appflowy/mobile/presentation/database/field/mobile_field_bottom_sheets.dart';
|
||||
import 'package:appflowy/mobile/presentation/database/field/mobile_field_type_option_editor.dart';
|
||||
import 'package:appflowy/mobile/presentation/widgets/widgets.dart';
|
||||
import 'package:appflowy/plugins/database/application/field/field_backend_service.dart';
|
||||
import 'package:appflowy/plugins/database/application/field/field_info.dart';
|
||||
import 'package:appflowy/plugins/database/application/field/field_service.dart';
|
||||
import 'package:appflowy/plugins/database/widgets/setting/field_visibility_extension.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-database2/protobuf.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
@ -36,14 +38,15 @@ class _QuickEditFieldState extends State<QuickEditField> {
|
||||
fieldId: widget.fieldInfo.field.id,
|
||||
);
|
||||
|
||||
late FieldType fieldType;
|
||||
late FieldVisibility fieldVisibility;
|
||||
late FieldOptionValues _fieldOptionValues;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
|
||||
fieldType = widget.fieldInfo.fieldType;
|
||||
_fieldOptionValues =
|
||||
FieldOptionValues.fromField(field: widget.fieldInfo.field);
|
||||
fieldVisibility = widget.fieldInfo.fieldSettings?.visibility ??
|
||||
FieldVisibility.AlwaysShown;
|
||||
controller.text = widget.fieldInfo.field.name;
|
||||
@ -52,7 +55,6 @@ class _QuickEditFieldState extends State<QuickEditField> {
|
||||
@override
|
||||
void dispose() {
|
||||
controller.dispose();
|
||||
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@ -64,7 +66,7 @@ class _QuickEditFieldState extends State<QuickEditField> {
|
||||
const AppBarCloseButton(),
|
||||
OptionTextField(
|
||||
controller: controller,
|
||||
type: fieldType,
|
||||
type: _fieldOptionValues.type,
|
||||
onTextChanged: (text) async {
|
||||
await service.updateName(text);
|
||||
},
|
||||
@ -77,18 +79,44 @@ class _QuickEditFieldState extends State<QuickEditField> {
|
||||
widget.fieldInfo.field.freeze();
|
||||
final field = widget.fieldInfo.field.rebuild((field) {
|
||||
field.name = controller.text;
|
||||
field.fieldType = fieldType;
|
||||
field.fieldType = _fieldOptionValues.type;
|
||||
field.typeOptionData =
|
||||
_fieldOptionValues.getTypeOptionData() ?? [];
|
||||
});
|
||||
final optionValues = await showEditFieldScreen(
|
||||
final fieldOptionValues = await showEditFieldScreen(
|
||||
context,
|
||||
widget.viewId,
|
||||
widget.fieldInfo.copyWith(field: field),
|
||||
);
|
||||
if (optionValues != null) {
|
||||
if (fieldOptionValues != null) {
|
||||
if (fieldOptionValues.name != _fieldOptionValues.name) {
|
||||
await service.updateName(fieldOptionValues.name);
|
||||
}
|
||||
|
||||
if (fieldOptionValues.type != _fieldOptionValues.type) {
|
||||
await FieldBackendService.updateFieldType(
|
||||
viewId: widget.viewId,
|
||||
fieldId: widget.fieldInfo.id,
|
||||
fieldType: fieldOptionValues.type,
|
||||
);
|
||||
}
|
||||
|
||||
final data = fieldOptionValues.getTypeOptionData();
|
||||
if (data != null) {
|
||||
await FieldBackendService.updateFieldTypeOption(
|
||||
viewId: widget.viewId,
|
||||
fieldId: widget.fieldInfo.id,
|
||||
typeOptionData: data,
|
||||
);
|
||||
}
|
||||
setState(() {
|
||||
fieldType = optionValues.type;
|
||||
controller.text = optionValues.name;
|
||||
_fieldOptionValues = fieldOptionValues;
|
||||
controller.text = fieldOptionValues.name;
|
||||
});
|
||||
} else {
|
||||
if (mounted) {
|
||||
context.pop();
|
||||
}
|
||||
}
|
||||
},
|
||||
),
|
||||
|
@ -220,9 +220,7 @@ class DatabaseFieldListTile extends StatelessWidget {
|
||||
size: const Size.square(20),
|
||||
),
|
||||
showTopBorder: showTopBorder,
|
||||
onTap: () {
|
||||
showEditFieldScreen(context, viewId, fieldInfo);
|
||||
},
|
||||
onTap: () => showEditFieldScreen(context, viewId, fieldInfo),
|
||||
onValueChanged: (value) {
|
||||
final newVisibility = fieldInfo.visibility!.toggle();
|
||||
context.read<DatabasePropertyBloc>().add(
|
||||
|
Loading…
x
Reference in New Issue
Block a user