mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
feat: improve UI in MobileFieldEditor (#4042)
This commit is contained in:
parent
7da759c662
commit
551e012147
@ -1,4 +1,7 @@
|
||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||
import 'package:appflowy/mobile/presentation/database/card/card_property_edit/widgets/widgets.dart';
|
||||
import 'package:appflowy/plugins/database_view/application/field/field_editor_bloc.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
|
||||
@ -33,13 +36,21 @@ class _MobileFieldNameTextFieldState extends State<MobileFieldNameTextField> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return TextField(
|
||||
controller: controller,
|
||||
onChanged: (newName) {
|
||||
context
|
||||
.read<FieldEditorBloc>()
|
||||
.add(FieldEditorEvent.renameField(newName));
|
||||
},
|
||||
return PropertyEditContainer(
|
||||
padding: EdgeInsets.zero,
|
||||
child: TextField(
|
||||
controller: controller,
|
||||
decoration: InputDecoration(
|
||||
hintText: LocaleKeys.board_propertyName.tr(),
|
||||
enabledBorder: InputBorder.none,
|
||||
focusedBorder: InputBorder.none,
|
||||
),
|
||||
onChanged: (newName) {
|
||||
context
|
||||
.read<FieldEditorBloc>()
|
||||
.add(FieldEditorEvent.renameField(newName));
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -1,14 +1,12 @@
|
||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||
import 'package:appflowy/mobile/presentation/database/card/card_detail/widgets/widgets.dart';
|
||||
import 'package:appflowy/mobile/presentation/database/card/card_property_edit/mobile_field_type_option_editor.dart';
|
||||
import 'package:appflowy/mobile/presentation/database/card/card_property_edit/widgets/property_title.dart';
|
||||
import 'package:appflowy/mobile/presentation/database/card/card_property_edit/widgets/widgets.dart';
|
||||
import 'package:appflowy/plugins/database_view/application/field/field_controller.dart';
|
||||
import 'package:appflowy/plugins/database_view/application/field/field_editor_bloc.dart';
|
||||
import 'package:appflowy/plugins/database_view/application/field/type_option/type_option_context.dart';
|
||||
import 'package:appflowy/plugins/database_view/grid/application/row/row_detail_bloc.dart';
|
||||
import 'package:appflowy/plugins/database_view/widgets/setting/field_visibility_extension.dart';
|
||||
import 'package:appflowy/workspace/presentation/widgets/toggle/toggle.dart';
|
||||
import 'package:appflowy/workspace/presentation/widgets/toggle/toggle_style.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-database2/protobuf.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flowy_infra_ui/widget/spacing.dart';
|
||||
@ -51,38 +49,42 @@ class MobileFieldEditor extends StatelessWidget {
|
||||
context.read<FieldEditorBloc>().typeOptionController;
|
||||
final fieldInfoVisibility =
|
||||
fieldController.getField(field.id)?.visibility;
|
||||
return Padding(
|
||||
return Container(
|
||||
padding: const EdgeInsets.all(16),
|
||||
color: Theme.of(context).colorScheme.secondary,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
// TODO(yijing): improve hint text
|
||||
PropertyTitle(LocaleKeys.settings_user_name.tr()),
|
||||
PropertyEditGroupTitle(LocaleKeys.settings_user_name.tr()),
|
||||
BlocSelector<FieldEditorBloc, FieldEditorState, String>(
|
||||
selector: (state) => state.field.name,
|
||||
builder: (context, fieldName) =>
|
||||
MobileFieldNameTextField(text: fieldName),
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: PropertyTitle(
|
||||
LocaleKeys.grid_field_visibility.tr(),
|
||||
const VSpace(16),
|
||||
PropertyEditGroupTitle(LocaleKeys.grid_field_visibility.tr()),
|
||||
PropertyEditContainer(
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
PropertyTitle(
|
||||
LocaleKeys.board_showOnCard.tr(),
|
||||
),
|
||||
),
|
||||
VisibilitySwitch(
|
||||
isFieldHidden: !(fieldInfoVisibility != null
|
||||
? fieldInfoVisibility.isVisibleState()
|
||||
: field.visibility),
|
||||
onChanged: () => context.read<RowDetailBloc>().add(
|
||||
RowDetailEvent.toggleFieldVisibility(
|
||||
state.field.id,
|
||||
VisibilitySwitch(
|
||||
isFieldHidden: !(fieldInfoVisibility != null
|
||||
? fieldInfoVisibility.isVisibleState()
|
||||
: field.visibility),
|
||||
onChanged: () => context.read<RowDetailBloc>().add(
|
||||
RowDetailEvent.toggleFieldVisibility(
|
||||
state.field.id,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const VSpace(8),
|
||||
const VSpace(16),
|
||||
PropertyEditGroupTitle(LocaleKeys.board_setting.tr()),
|
||||
// edit property type and settings
|
||||
if (!typeOptionLoader.field.isPrimary)
|
||||
MobileFieldTypeOptionEditor(dataController: dataController),
|
||||
@ -114,11 +116,10 @@ class _VisibilitySwitchState extends State<VisibilitySwitch> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Toggle(
|
||||
padding: EdgeInsets.zero,
|
||||
return Switch.adaptive(
|
||||
value: !_isFieldHidden,
|
||||
style: ToggleStyle.mobile,
|
||||
onChanged: (_) {
|
||||
activeColor: Theme.of(context).colorScheme.primary,
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
_isFieldHidden = !_isFieldHidden;
|
||||
widget.onChanged?.call();
|
||||
|
@ -1,6 +1,7 @@
|
||||
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||
import 'package:appflowy/mobile/presentation/database/card/card_property_edit/type_option_widget_builder/type_option_widget_builder.dart';
|
||||
import 'package:appflowy/mobile/presentation/database/card/card_property_edit/widgets/widgets.dart';
|
||||
import 'package:appflowy/mobile/presentation/widgets/show_flowy_mobile_bottom_sheet.dart';
|
||||
import 'package:appflowy/plugins/database_view/application/field/field_type_option_edit_bloc.dart';
|
||||
import 'package:appflowy/plugins/database_view/application/field/type_option/type_option_data_controller.dart';
|
||||
@ -59,24 +60,25 @@ class _MobileSwitchFieldButton extends StatelessWidget {
|
||||
(FieldTypeOptionEditBloc bloc) => bloc.state.field.fieldType,
|
||||
);
|
||||
return GestureDetector(
|
||||
child: Row(
|
||||
children: [
|
||||
Text(
|
||||
LocaleKeys.grid_field_propertyType.tr(),
|
||||
style: Theme.of(context).textTheme.titleMedium,
|
||||
),
|
||||
const Spacer(),
|
||||
FlowySvg(fieldType.icon()),
|
||||
const HSpace(4),
|
||||
Text(
|
||||
fieldType.title(),
|
||||
style: Theme.of(context).textTheme.titleMedium,
|
||||
),
|
||||
Icon(
|
||||
Icons.arrow_forward_ios_sharp,
|
||||
color: Theme.of(context).hintColor,
|
||||
),
|
||||
],
|
||||
child: PropertyEditContainer(
|
||||
child: Row(
|
||||
children: [
|
||||
PropertyTitle(
|
||||
LocaleKeys.grid_field_propertyType.tr(),
|
||||
),
|
||||
const Spacer(),
|
||||
FlowySvg(fieldType.icon()),
|
||||
const HSpace(4),
|
||||
Text(
|
||||
fieldType.title(),
|
||||
style: Theme.of(context).textTheme.titleMedium,
|
||||
),
|
||||
Icon(
|
||||
Icons.arrow_forward_ios_sharp,
|
||||
color: Theme.of(context).hintColor,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
onTap: () => showFlowyMobileBottomSheet(
|
||||
context,
|
||||
|
@ -1,3 +1,4 @@
|
||||
import 'package:appflowy/mobile/presentation/database/card/card_property_edit/widgets/widgets.dart';
|
||||
import 'package:appflowy/mobile/presentation/database/card/row/cells/date_cell/widgets/widgets.dart';
|
||||
import 'package:appflowy/plugins/database_view/application/field/type_option/date_bloc.dart';
|
||||
import 'package:appflowy/plugins/database_view/application/field/type_option/type_option_context.dart';
|
||||
@ -38,39 +39,43 @@ class DateTypeOptionMobileWidget extends TypeOptionWidget {
|
||||
typeOptionContext.typeOption = state.typeOption,
|
||||
builder: (context, state) {
|
||||
final List<Widget> children = [
|
||||
DateFormatListTile(
|
||||
currentFormatStr: state.typeOption.dateFormat.title(),
|
||||
groupValue: context
|
||||
.watch<DateTypeOptionBloc>()
|
||||
.state
|
||||
.typeOption
|
||||
.dateFormat,
|
||||
onChanged: (newFormat) {
|
||||
if (newFormat != null) {
|
||||
context.read<DateTypeOptionBloc>().add(
|
||||
DateTypeOptionEvent.didSelectDateFormat(
|
||||
newFormat,
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
PropertyEditContainer(
|
||||
child: DateFormatListTile(
|
||||
currentFormatStr: state.typeOption.dateFormat.title(),
|
||||
groupValue: context
|
||||
.watch<DateTypeOptionBloc>()
|
||||
.state
|
||||
.typeOption
|
||||
.dateFormat,
|
||||
onChanged: (newFormat) {
|
||||
if (newFormat != null) {
|
||||
context.read<DateTypeOptionBloc>().add(
|
||||
DateTypeOptionEvent.didSelectDateFormat(
|
||||
newFormat,
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
TimeFormatListTile(
|
||||
currentFormatStr: state.typeOption.timeFormat.title(),
|
||||
groupValue: context
|
||||
.watch<DateTypeOptionBloc>()
|
||||
.state
|
||||
.typeOption
|
||||
.timeFormat,
|
||||
onChanged: (newFormat) {
|
||||
if (newFormat != null) {
|
||||
context.read<DateTypeOptionBloc>().add(
|
||||
DateTypeOptionEvent.didSelectTimeFormat(
|
||||
newFormat,
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
PropertyEditContainer(
|
||||
child: TimeFormatListTile(
|
||||
currentFormatStr: state.typeOption.timeFormat.title(),
|
||||
groupValue: context
|
||||
.watch<DateTypeOptionBloc>()
|
||||
.state
|
||||
.typeOption
|
||||
.timeFormat,
|
||||
onChanged: (newFormat) {
|
||||
if (newFormat != null) {
|
||||
context.read<DateTypeOptionBloc>().add(
|
||||
DateTypeOptionEvent.didSelectTimeFormat(
|
||||
newFormat,
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
];
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
import 'package:appflowy/mobile/presentation/database/card/card_property_edit/widgets/property_title.dart';
|
||||
import 'package:appflowy/mobile/presentation/database/card/card_property_edit/widgets/widgets.dart';
|
||||
import 'package:appflowy/mobile/presentation/widgets/widgets.dart';
|
||||
import 'package:appflowy/plugins/database_view/application/field/type_option/number_bloc.dart';
|
||||
import 'package:appflowy/plugins/database_view/application/field/type_option/number_format_bloc.dart';
|
||||
@ -46,20 +46,22 @@ class NumberTypeOptionMobileWidget extends TypeOptionWidget {
|
||||
typeOptionContext.typeOption = state.typeOption,
|
||||
builder: (context, state) {
|
||||
return GestureDetector(
|
||||
child: Row(
|
||||
children: [
|
||||
PropertyTitle(LocaleKeys.grid_field_numberFormat.tr()),
|
||||
const Spacer(),
|
||||
const HSpace(4),
|
||||
Text(
|
||||
state.typeOption.format.title(),
|
||||
style: Theme.of(context).textTheme.titleMedium,
|
||||
),
|
||||
Icon(
|
||||
Icons.arrow_forward_ios,
|
||||
color: Theme.of(context).hintColor,
|
||||
),
|
||||
],
|
||||
child: PropertyEditContainer(
|
||||
child: Row(
|
||||
children: [
|
||||
PropertyTitle(LocaleKeys.grid_field_numberFormat.tr()),
|
||||
const Spacer(),
|
||||
const HSpace(4),
|
||||
Text(
|
||||
state.typeOption.format.title(),
|
||||
style: Theme.of(context).textTheme.titleMedium,
|
||||
),
|
||||
Icon(
|
||||
Icons.arrow_forward_ios,
|
||||
color: Theme.of(context).hintColor,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
onTap: () => showFlowyMobileBottomSheet(
|
||||
context,
|
||||
|
@ -1,3 +1,4 @@
|
||||
import 'package:appflowy/mobile/presentation/database/card/card_property_edit/widgets/widgets.dart';
|
||||
import 'package:appflowy/mobile/presentation/database/card/row/cells/date_cell/widgets/widgets.dart';
|
||||
import 'package:appflowy/plugins/database_view/application/field/type_option/timestamp_bloc.dart';
|
||||
import 'package:appflowy/plugins/database_view/application/field/type_option/type_option_context.dart';
|
||||
@ -39,49 +40,53 @@ class TimestampTypeOptionMobileWidget extends TypeOptionWidget {
|
||||
typeOptionContext.typeOption = state.typeOption,
|
||||
builder: (context, state) {
|
||||
final List<Widget> children = [
|
||||
// used to add a separator padding at the top
|
||||
const SizedBox.shrink(),
|
||||
DateFormatListTile(
|
||||
currentFormatStr: state.typeOption.dateFormat.title(),
|
||||
groupValue: context
|
||||
.watch<TimestampTypeOptionBloc>()
|
||||
.state
|
||||
.typeOption
|
||||
.dateFormat,
|
||||
onChanged: (newFormat) {
|
||||
if (newFormat != null) {
|
||||
context.read<TimestampTypeOptionBloc>().add(
|
||||
TimestampTypeOptionEvent.didSelectDateFormat(
|
||||
newFormat,
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
),
|
||||
IncludeTimeSwitch(
|
||||
switchValue: state.typeOption.includeTime,
|
||||
onChanged: (value) => context
|
||||
.read<TimestampTypeOptionBloc>()
|
||||
.add(TimestampTypeOptionEvent.includeTime(value)),
|
||||
),
|
||||
if (state.typeOption.includeTime)
|
||||
TimeFormatListTile(
|
||||
currentFormatStr: state.typeOption.timeFormat.title(),
|
||||
PropertyEditContainer(
|
||||
child: DateFormatListTile(
|
||||
currentFormatStr: state.typeOption.dateFormat.title(),
|
||||
groupValue: context
|
||||
.watch<TimestampTypeOptionBloc>()
|
||||
.state
|
||||
.typeOption
|
||||
.timeFormat,
|
||||
.dateFormat,
|
||||
onChanged: (newFormat) {
|
||||
if (newFormat != null) {
|
||||
context.read<TimestampTypeOptionBloc>().add(
|
||||
TimestampTypeOptionEvent.didSelectTimeFormat(
|
||||
TimestampTypeOptionEvent.didSelectDateFormat(
|
||||
newFormat,
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
PropertyEditContainer(
|
||||
child: IncludeTimeSwitch(
|
||||
switchValue: state.typeOption.includeTime,
|
||||
onChanged: (value) => context
|
||||
.read<TimestampTypeOptionBloc>()
|
||||
.add(TimestampTypeOptionEvent.includeTime(value)),
|
||||
),
|
||||
),
|
||||
if (state.typeOption.includeTime)
|
||||
PropertyEditContainer(
|
||||
child: TimeFormatListTile(
|
||||
currentFormatStr: state.typeOption.timeFormat.title(),
|
||||
groupValue: context
|
||||
.watch<TimestampTypeOptionBloc>()
|
||||
.state
|
||||
.typeOption
|
||||
.timeFormat,
|
||||
onChanged: (newFormat) {
|
||||
if (newFormat != null) {
|
||||
context.read<TimestampTypeOptionBloc>().add(
|
||||
TimestampTypeOptionEvent.didSelectTimeFormat(
|
||||
newFormat,
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
];
|
||||
|
||||
return ListView.separated(
|
||||
|
@ -0,0 +1,26 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class PropertyEditContainer extends StatelessWidget {
|
||||
const PropertyEditContainer({
|
||||
super.key,
|
||||
required this.child,
|
||||
this.padding,
|
||||
});
|
||||
|
||||
final Widget child;
|
||||
final EdgeInsets? padding;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
height: 50,
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context).colorScheme.surface,
|
||||
borderRadius: BorderRadius.circular(6),
|
||||
),
|
||||
alignment: Alignment.centerLeft,
|
||||
padding: padding ?? const EdgeInsets.symmetric(horizontal: 8),
|
||||
child: child,
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class PropertyEditGroupTitle extends StatelessWidget {
|
||||
const PropertyEditGroupTitle(this.name, {super.key});
|
||||
|
||||
final String name;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 8),
|
||||
child: Text(
|
||||
name,
|
||||
style: Theme.of(context).textTheme.bodyMedium?.copyWith(
|
||||
color: Theme.of(context).colorScheme.onSurface,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@ -11,7 +11,10 @@ class PropertyTitle extends StatelessWidget {
|
||||
padding: const EdgeInsets.symmetric(vertical: 8),
|
||||
child: Text(
|
||||
name,
|
||||
style: Theme.of(context).textTheme.titleMedium,
|
||||
style: Theme.of(context).textTheme.bodyMedium?.copyWith(
|
||||
color: Theme.of(context).colorScheme.onBackground,
|
||||
fontSize: 16,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
@ -0,0 +1,3 @@
|
||||
export 'property_edit_group_title.dart';
|
||||
export 'property_title.dart';
|
||||
export 'property_edit_container.dart';
|
@ -1,4 +1,5 @@
|
||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||
import 'package:appflowy/mobile/presentation/database/card/card_property_edit/widgets/widgets.dart';
|
||||
import 'package:appflowy/mobile/presentation/widgets/widgets.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-database2/date_entities.pb.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
@ -27,9 +28,8 @@ class DateFormatListTile extends StatelessWidget {
|
||||
final style = Theme.of(context);
|
||||
return Row(
|
||||
children: [
|
||||
Text(
|
||||
PropertyTitle(
|
||||
LocaleKeys.grid_field_dateFormat.tr(),
|
||||
style: style.textTheme.titleMedium,
|
||||
),
|
||||
const Spacer(),
|
||||
GestureDetector(
|
||||
|
@ -1,4 +1,5 @@
|
||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||
import 'package:appflowy/mobile/presentation/database/card/card_property_edit/widgets/property_title.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
@ -16,9 +17,8 @@ class IncludeTimeSwitch extends StatelessWidget {
|
||||
Widget build(BuildContext context) {
|
||||
return Row(
|
||||
children: [
|
||||
Text(
|
||||
PropertyTitle(
|
||||
LocaleKeys.grid_field_includeTime.tr(),
|
||||
style: Theme.of(context).textTheme.titleMedium,
|
||||
),
|
||||
const Spacer(),
|
||||
Switch.adaptive(
|
||||
|
@ -1,4 +1,5 @@
|
||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||
import 'package:appflowy/mobile/presentation/database/card/card_property_edit/widgets/widgets.dart';
|
||||
import 'package:appflowy/mobile/presentation/widgets/widgets.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-database2/date_entities.pb.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-database2/date_entities.pbenum.dart';
|
||||
@ -28,9 +29,8 @@ class TimeFormatListTile extends StatelessWidget {
|
||||
final style = Theme.of(context);
|
||||
return Row(
|
||||
children: [
|
||||
Text(
|
||||
PropertyTitle(
|
||||
LocaleKeys.grid_field_timeFormat.tr(),
|
||||
style: style.textTheme.titleMedium,
|
||||
),
|
||||
const Spacer(),
|
||||
GestureDetector(
|
||||
|
@ -37,8 +37,8 @@ class MobileAppearance extends BaseAppearance {
|
||||
brightness: brightness,
|
||||
primary: _primaryColor,
|
||||
onPrimary: Colors.white,
|
||||
// TODO(yijing): add color later
|
||||
secondary: Colors.white,
|
||||
// group card & property edit background color
|
||||
secondary: const Color(0xfff7f8fc), // shade 10
|
||||
onSecondary: _onSecondaryColor,
|
||||
error: const Color(0xffFB006D),
|
||||
onError: const Color(0xffFB006D),
|
||||
|
@ -825,6 +825,9 @@
|
||||
"cardActions": "Card Actions",
|
||||
"cardDuplicated": "Card has been duplicated",
|
||||
"cardDeleted": "Card has been deleted",
|
||||
"showOnCard": "Show on card detail",
|
||||
"setting": "Setting",
|
||||
"propertyName": "Property name",
|
||||
"menuName": "Board",
|
||||
"showUngrouped": "Show ungrouped items",
|
||||
"ungroupedButtonText": "Ungrouped",
|
||||
|
Loading…
Reference in New Issue
Block a user