mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
feat: edit property (#4065)
* feat: edit property * feat: disable actions if field is primary * feat: remove include time * chore: set title to medium * fix: flutter analyze * chore: update built in text style * chore: update text style * fix: unable to click the calendar day
This commit is contained in:
@ -202,4 +202,4 @@ SPEC CHECKSUMS:
|
|||||||
|
|
||||||
PODFILE CHECKSUM: 8c681999c7764593c94846b2a64b44d86f7a27ac
|
PODFILE CHECKSUM: 8c681999c7764593c94846b2a64b44d86f7a27ac
|
||||||
|
|
||||||
COCOAPODS: 1.11.3
|
COCOAPODS: 1.12.1
|
||||||
|
@ -515,7 +515,7 @@
|
|||||||
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
||||||
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||||
DEAD_CODE_STRIPPING = NO;
|
DEAD_CODE_STRIPPING = NO;
|
||||||
DEVELOPMENT_TEAM = "";
|
DEVELOPMENT_TEAM = VHB67HRSZG;
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
INFOPLIST_FILE = Runner/Info.plist;
|
INFOPLIST_FILE = Runner/Info.plist;
|
||||||
INFOPLIST_KEY_CFBundleDisplayName = AppFlowy;
|
INFOPLIST_KEY_CFBundleDisplayName = AppFlowy;
|
||||||
|
@ -34,7 +34,6 @@ class AppBarCancelButton extends StatelessWidget {
|
|||||||
onTap: onTap,
|
onTap: onTap,
|
||||||
child: FlowyText(
|
child: FlowyText(
|
||||||
LocaleKeys.button_cancel.tr(),
|
LocaleKeys.button_cancel.tr(),
|
||||||
fontSize: 16.0,
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,6 @@ class MobileViewItemBottomSheetHeader extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final theme = Theme.of(context);
|
|
||||||
return Row(
|
return Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
@ -44,9 +43,14 @@ class MobileViewItemBottomSheetHeader extends StatelessWidget {
|
|||||||
},
|
},
|
||||||
),
|
),
|
||||||
// title
|
// title
|
||||||
Text(
|
ConstrainedBox(
|
||||||
view.name,
|
constraints: BoxConstraints(
|
||||||
style: theme.textTheme.labelSmall,
|
maxWidth: MediaQuery.of(context).size.width * 0.6,
|
||||||
|
),
|
||||||
|
child: FlowyText.medium(
|
||||||
|
view.name,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
const HSpace(24.0),
|
const HSpace(24.0),
|
||||||
],
|
],
|
||||||
|
@ -64,7 +64,6 @@ Future<T?> showMobileBottomSheet<T>(
|
|||||||
: const SizedBox.shrink(),
|
: const SizedBox.shrink(),
|
||||||
FlowyText(
|
FlowyText(
|
||||||
title,
|
title,
|
||||||
fontSize: 16.0,
|
|
||||||
),
|
),
|
||||||
showCloseButton
|
showCloseButton
|
||||||
? HSpace(padding.right + 24)
|
? HSpace(padding.right + 24)
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||||
import 'package:appflowy/mobile/presentation/base/app_bar_actions.dart';
|
import 'package:appflowy/mobile/presentation/base/app_bar_actions.dart';
|
||||||
import 'package:appflowy/mobile/presentation/database/card/card_detail/widgets/_new_field_option.dart';
|
import 'package:appflowy/mobile/presentation/database/card/card_detail/widgets/_field_options_eidtor.dart';
|
||||||
import 'package:appflowy/util/field_type_extension.dart';
|
import 'package:appflowy/util/field_type_extension.dart';
|
||||||
import 'package:appflowy_backend/protobuf/flowy-database2/field_entities.pbenum.dart';
|
import 'package:appflowy_backend/protobuf/flowy-database2/field_entities.pbenum.dart';
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
@ -46,9 +46,8 @@ class _MobileNewPropertyScreenState extends State<MobileNewPropertyScreen> {
|
|||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
centerTitle: true,
|
centerTitle: true,
|
||||||
title: FlowyText(
|
title: FlowyText.medium(
|
||||||
LocaleKeys.grid_field_newProperty.tr(),
|
LocaleKeys.grid_field_newProperty.tr(),
|
||||||
fontSize: 16.0,
|
|
||||||
),
|
),
|
||||||
leading: AppBarCancelButton(
|
leading: AppBarCancelButton(
|
||||||
onTap: () => context.pop(),
|
onTap: () => context.pop(),
|
||||||
@ -62,7 +61,7 @@ class _MobileNewPropertyScreenState extends State<MobileNewPropertyScreen> {
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
body: FieldOption(
|
body: FieldOptionEditor(
|
||||||
mode: FieldOptionMode.add,
|
mode: FieldOptionMode.add,
|
||||||
defaultValues: optionValues,
|
defaultValues: optionValues,
|
||||||
onOptionValuesChanged: (optionValues) {
|
onOptionValuesChanged: (optionValues) {
|
||||||
@ -88,10 +87,9 @@ class _SaveButton extends StatelessWidget {
|
|||||||
alignment: Alignment.center,
|
alignment: Alignment.center,
|
||||||
child: GestureDetector(
|
child: GestureDetector(
|
||||||
onTap: onSave,
|
onTap: onSave,
|
||||||
child: FlowyText(
|
child: FlowyText.medium(
|
||||||
LocaleKeys.button_save.tr(),
|
LocaleKeys.button_save.tr(),
|
||||||
color: const Color(0xFF00ADDC),
|
color: const Color(0xFF00ADDC),
|
||||||
fontSize: 16.0,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -0,0 +1,139 @@
|
|||||||
|
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/_field_options_eidtor.dart';
|
||||||
|
import 'package:appflowy/plugins/database_view/application/field/field_service.dart';
|
||||||
|
import 'package:appflowy/plugins/database_view/application/field_settings/field_settings_service.dart';
|
||||||
|
import 'package:appflowy_backend/protobuf/flowy-database2/protobuf.dart';
|
||||||
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
|
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:go_router/go_router.dart';
|
||||||
|
|
||||||
|
class MobileEditPropertyScreen extends StatefulWidget {
|
||||||
|
static const routeName = '/edit_property';
|
||||||
|
static const argViewId = 'view_id';
|
||||||
|
static const argField = 'field';
|
||||||
|
static const argIsPrimary = 'is_primary';
|
||||||
|
|
||||||
|
const MobileEditPropertyScreen({
|
||||||
|
super.key,
|
||||||
|
required this.viewId,
|
||||||
|
required this.field,
|
||||||
|
this.isPrimary = false,
|
||||||
|
});
|
||||||
|
|
||||||
|
final String viewId;
|
||||||
|
final FieldPB field;
|
||||||
|
final bool isPrimary;
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<MobileEditPropertyScreen> createState() =>
|
||||||
|
_MobileEditPropertyScreenState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _MobileEditPropertyScreenState extends State<MobileEditPropertyScreen> {
|
||||||
|
late Future<FieldOptionValues?> future;
|
||||||
|
|
||||||
|
FieldOptionValues? optionValues;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
|
||||||
|
future = FieldOptionValues.get(
|
||||||
|
viewId: widget.viewId,
|
||||||
|
fieldId: widget.field.id,
|
||||||
|
fieldType: widget.field.fieldType,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final viewId = widget.viewId;
|
||||||
|
final fieldId = widget.field.id;
|
||||||
|
|
||||||
|
return Scaffold(
|
||||||
|
appBar: AppBar(
|
||||||
|
centerTitle: true,
|
||||||
|
title: FlowyText.medium(
|
||||||
|
LocaleKeys.grid_field_editProperty.tr(),
|
||||||
|
),
|
||||||
|
leading: AppBarCancelButton(
|
||||||
|
onTap: () => context.pop(),
|
||||||
|
),
|
||||||
|
leadingWidth: 120,
|
||||||
|
actions: [
|
||||||
|
_SaveButton(
|
||||||
|
onSave: () {
|
||||||
|
context.pop(optionValues);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
body: FutureBuilder<FieldOptionValues?>(
|
||||||
|
future: future,
|
||||||
|
builder: (context, snapshot) {
|
||||||
|
final optionValues = snapshot.data;
|
||||||
|
if (optionValues == null) {
|
||||||
|
return const Center(child: CircularProgressIndicator.adaptive());
|
||||||
|
}
|
||||||
|
return FieldOptionEditor(
|
||||||
|
mode: FieldOptionMode.edit,
|
||||||
|
isPrimary: widget.isPrimary,
|
||||||
|
defaultValues: optionValues,
|
||||||
|
onOptionValuesChanged: (optionValues) {
|
||||||
|
this.optionValues = optionValues;
|
||||||
|
},
|
||||||
|
onAction: (action) {
|
||||||
|
final service = FieldBackendService(
|
||||||
|
viewId: viewId,
|
||||||
|
fieldId: fieldId,
|
||||||
|
);
|
||||||
|
switch (action) {
|
||||||
|
case FieldOptionAction.delete:
|
||||||
|
service.deleteField();
|
||||||
|
break;
|
||||||
|
case FieldOptionAction.duplicate:
|
||||||
|
service.duplicateField();
|
||||||
|
break;
|
||||||
|
case FieldOptionAction.hide:
|
||||||
|
FieldSettingsBackendService(viewId: viewId)
|
||||||
|
.updateFieldSettings(
|
||||||
|
fieldId: fieldId,
|
||||||
|
fieldVisibility: FieldVisibility.AlwaysHidden,
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
context.pop();
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _SaveButton extends StatelessWidget {
|
||||||
|
const _SaveButton({
|
||||||
|
required this.onSave,
|
||||||
|
});
|
||||||
|
|
||||||
|
final VoidCallback onSave;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Padding(
|
||||||
|
padding: const EdgeInsets.only(right: 16.0),
|
||||||
|
child: Align(
|
||||||
|
alignment: Alignment.center,
|
||||||
|
child: GestureDetector(
|
||||||
|
onTap: onSave,
|
||||||
|
child: FlowyText.medium(
|
||||||
|
LocaleKeys.button_save.tr(),
|
||||||
|
color: const Color(0xFF00ADDC),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -75,7 +75,7 @@ class _FieldHeader extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
FlowyText.medium(
|
FlowyText.medium(
|
||||||
LocaleKeys.titleBar_addField.tr(),
|
LocaleKeys.titleBar_addField.tr(),
|
||||||
fontSize: 16.0,
|
fontSize: 17.0,
|
||||||
),
|
),
|
||||||
const HSpace(120),
|
const HSpace(120),
|
||||||
],
|
],
|
||||||
@ -106,7 +106,9 @@ class _Field extends StatelessWidget {
|
|||||||
size: Size.square(width / 4.0),
|
size: Size.square(width / 4.0),
|
||||||
),
|
),
|
||||||
const VSpace(6.0),
|
const VSpace(6.0),
|
||||||
FlowyText(type.i18n),
|
FlowyText(
|
||||||
|
type.i18n,
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
@ -7,6 +7,7 @@ import 'package:appflowy/mobile/presentation/base/option_color_list.dart';
|
|||||||
import 'package:appflowy/mobile/presentation/bottom_sheet/bottom_sheet.dart';
|
import 'package:appflowy/mobile/presentation/bottom_sheet/bottom_sheet.dart';
|
||||||
import 'package:appflowy/mobile/presentation/database/card/card_detail/widgets/_field_options.dart';
|
import 'package:appflowy/mobile/presentation/database/card/card_detail/widgets/_field_options.dart';
|
||||||
import 'package:appflowy/mobile/presentation/widgets/widgets.dart';
|
import 'package:appflowy/mobile/presentation/widgets/widgets.dart';
|
||||||
|
import 'package:appflowy/plugins/database_view/application/field/field_service.dart';
|
||||||
import 'package:appflowy/plugins/database_view/application/field/type_option/number_format_bloc.dart';
|
import 'package:appflowy/plugins/database_view/application/field/type_option/number_format_bloc.dart';
|
||||||
import 'package:appflowy/plugins/database_view/application/field/type_option/type_option_service.dart';
|
import 'package:appflowy/plugins/database_view/application/field/type_option/type_option_service.dart';
|
||||||
import 'package:appflowy/plugins/database_view/grid/presentation/widgets/header/type_option/date.dart';
|
import 'package:appflowy/plugins/database_view/grid/presentation/widgets/header/type_option/date.dart';
|
||||||
@ -32,7 +33,6 @@ class FieldOptionValues {
|
|||||||
required this.type,
|
required this.type,
|
||||||
required this.name,
|
required this.name,
|
||||||
this.dateFormate,
|
this.dateFormate,
|
||||||
this.includeTime = false,
|
|
||||||
this.timeFormat,
|
this.timeFormat,
|
||||||
this.numberFormat,
|
this.numberFormat,
|
||||||
this.selectOption = const [],
|
this.selectOption = const [],
|
||||||
@ -43,7 +43,6 @@ class FieldOptionValues {
|
|||||||
|
|
||||||
// FieldType.Date
|
// FieldType.Date
|
||||||
DateFormatPB? dateFormate;
|
DateFormatPB? dateFormate;
|
||||||
bool includeTime;
|
|
||||||
TimeFormatPB? timeFormat;
|
TimeFormatPB? timeFormat;
|
||||||
|
|
||||||
// FieldType.Num
|
// FieldType.Num
|
||||||
@ -56,65 +55,110 @@ class FieldOptionValues {
|
|||||||
Future<void> create({
|
Future<void> create({
|
||||||
required String viewId,
|
required String viewId,
|
||||||
}) async {
|
}) async {
|
||||||
Uint8List? typeOptionData;
|
|
||||||
|
|
||||||
switch (type) {
|
|
||||||
case FieldType.RichText:
|
|
||||||
break;
|
|
||||||
case FieldType.URL:
|
|
||||||
break;
|
|
||||||
case FieldType.Checkbox:
|
|
||||||
break;
|
|
||||||
case FieldType.Number:
|
|
||||||
typeOptionData = NumberTypeOptionPB(
|
|
||||||
format: numberFormat,
|
|
||||||
).writeToBuffer();
|
|
||||||
break;
|
|
||||||
case FieldType.DateTime:
|
|
||||||
typeOptionData = DateTypeOptionPB(
|
|
||||||
dateFormat: dateFormate,
|
|
||||||
timeFormat: timeFormat,
|
|
||||||
).writeToBuffer();
|
|
||||||
break;
|
|
||||||
case FieldType.SingleSelect:
|
|
||||||
typeOptionData = SingleSelectTypeOptionPB(
|
|
||||||
options: selectOption,
|
|
||||||
).writeToBuffer();
|
|
||||||
case FieldType.MultiSelect:
|
|
||||||
typeOptionData = MultiSelectTypeOptionPB(
|
|
||||||
options: selectOption,
|
|
||||||
).writeToBuffer();
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw UnimplementedError();
|
|
||||||
}
|
|
||||||
|
|
||||||
await TypeOptionBackendService.createFieldTypeOption(
|
await TypeOptionBackendService.createFieldTypeOption(
|
||||||
viewId: viewId,
|
viewId: viewId,
|
||||||
fieldType: type,
|
fieldType: type,
|
||||||
fieldName: name,
|
fieldName: name,
|
||||||
typeOptionData: typeOptionData,
|
typeOptionData: toTypeOptionBuffer(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Uint8List? toTypeOptionBuffer() {
|
||||||
|
switch (type) {
|
||||||
|
case FieldType.RichText:
|
||||||
|
case FieldType.URL:
|
||||||
|
case FieldType.Checkbox:
|
||||||
|
return null;
|
||||||
|
case FieldType.Number:
|
||||||
|
return NumberTypeOptionPB(
|
||||||
|
format: numberFormat,
|
||||||
|
).writeToBuffer();
|
||||||
|
case FieldType.DateTime:
|
||||||
|
return DateTypeOptionPB(
|
||||||
|
dateFormat: dateFormate,
|
||||||
|
timeFormat: timeFormat,
|
||||||
|
).writeToBuffer();
|
||||||
|
case FieldType.SingleSelect:
|
||||||
|
return SingleSelectTypeOptionPB(
|
||||||
|
options: selectOption,
|
||||||
|
).writeToBuffer();
|
||||||
|
case FieldType.MultiSelect:
|
||||||
|
return MultiSelectTypeOptionPB(
|
||||||
|
options: selectOption,
|
||||||
|
).writeToBuffer();
|
||||||
|
default:
|
||||||
|
throw UnimplementedError();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static Future<FieldOptionValues?> get({
|
||||||
|
required String viewId,
|
||||||
|
required String fieldId,
|
||||||
|
required FieldType fieldType,
|
||||||
|
}) async {
|
||||||
|
final service = FieldBackendService(viewId: viewId, fieldId: fieldId);
|
||||||
|
final result = await service.getFieldTypeOptionData(fieldType: fieldType);
|
||||||
|
return result.fold(
|
||||||
|
(option) {
|
||||||
|
final type = option.field_2.fieldType;
|
||||||
|
final buffer = option.typeOptionData;
|
||||||
|
return FieldOptionValues(
|
||||||
|
type: type,
|
||||||
|
name: option.field_2.name,
|
||||||
|
numberFormat: type == FieldType.Number
|
||||||
|
? NumberTypeOptionPB.fromBuffer(buffer).format
|
||||||
|
: null,
|
||||||
|
dateFormate: type == FieldType.DateTime
|
||||||
|
? DateTypeOptionPB.fromBuffer(buffer).dateFormat
|
||||||
|
: null,
|
||||||
|
timeFormat: type == FieldType.DateTime
|
||||||
|
? DateTypeOptionPB.fromBuffer(buffer).timeFormat
|
||||||
|
: null,
|
||||||
|
selectOption: switch (type) {
|
||||||
|
FieldType.SingleSelect =>
|
||||||
|
SingleSelectTypeOptionPB.fromBuffer(buffer).options,
|
||||||
|
FieldType.MultiSelect =>
|
||||||
|
MultiSelectTypeOptionPB.fromBuffer(buffer).options,
|
||||||
|
_ => [],
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
(error) => null,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class FieldOption extends StatefulWidget {
|
enum FieldOptionAction {
|
||||||
const FieldOption({
|
hide,
|
||||||
|
duplicate,
|
||||||
|
delete,
|
||||||
|
}
|
||||||
|
|
||||||
|
class FieldOptionEditor extends StatefulWidget {
|
||||||
|
const FieldOptionEditor({
|
||||||
super.key,
|
super.key,
|
||||||
required this.mode,
|
required this.mode,
|
||||||
required this.defaultValues,
|
required this.defaultValues,
|
||||||
required this.onOptionValuesChanged,
|
required this.onOptionValuesChanged,
|
||||||
|
this.onAction,
|
||||||
|
this.isPrimary = false,
|
||||||
});
|
});
|
||||||
|
|
||||||
final FieldOptionMode mode;
|
final FieldOptionMode mode;
|
||||||
final FieldOptionValues defaultValues;
|
final FieldOptionValues defaultValues;
|
||||||
final void Function(FieldOptionValues values) onOptionValuesChanged;
|
final void Function(FieldOptionValues values) onOptionValuesChanged;
|
||||||
|
|
||||||
|
// only used in edit mode
|
||||||
|
final void Function(FieldOptionAction action)? onAction;
|
||||||
|
|
||||||
|
// the primary field can't be deleted, duplicated, and changed type
|
||||||
|
final bool isPrimary;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<FieldOption> createState() => _FieldOptionState();
|
State<FieldOptionEditor> createState() => _FieldOptionEditorState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _FieldOptionState extends State<FieldOption> {
|
class _FieldOptionEditorState extends State<FieldOptionEditor> {
|
||||||
final controller = TextEditingController();
|
final controller = TextEditingController();
|
||||||
|
|
||||||
late FieldOptionValues values;
|
late FieldOptionValues values;
|
||||||
@ -124,7 +168,7 @@ class _FieldOptionState extends State<FieldOption> {
|
|||||||
super.initState();
|
super.initState();
|
||||||
|
|
||||||
values = widget.defaultValues;
|
values = widget.defaultValues;
|
||||||
controller.text = values.type.i18n;
|
controller.text = values.name;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -136,6 +180,7 @@ class _FieldOptionState extends State<FieldOption> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
final option = _buildOption();
|
||||||
return Container(
|
return Container(
|
||||||
color: Theme.of(context).colorScheme.secondaryContainer,
|
color: Theme.of(context).colorScheme.secondaryContainer,
|
||||||
height: MediaQuery.of(context).size.height,
|
height: MediaQuery.of(context).size.height,
|
||||||
@ -151,18 +196,26 @@ class _FieldOptionState extends State<FieldOption> {
|
|||||||
},
|
},
|
||||||
),
|
),
|
||||||
const _Divider(),
|
const _Divider(),
|
||||||
_PropertyType(
|
if (!widget.isPrimary) ...[
|
||||||
type: values.type,
|
_PropertyType(
|
||||||
onSelected: (type) => setState(
|
type: values.type,
|
||||||
() {
|
onSelected: (type) => setState(
|
||||||
controller.text = type.i18n;
|
() {
|
||||||
_updateOptionValues(type: type, name: type.i18n);
|
if (widget.mode == FieldOptionMode.add) {
|
||||||
},
|
controller.text = type.i18n;
|
||||||
|
}
|
||||||
|
_updateOptionValues(type: type, name: type.i18n);
|
||||||
|
},
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
const _Divider(),
|
||||||
const _Divider(),
|
if (option.isNotEmpty) ...[
|
||||||
..._buildOption(),
|
...option,
|
||||||
|
const _Divider(),
|
||||||
|
],
|
||||||
|
],
|
||||||
..._buildOptionActions(),
|
..._buildOptionActions(),
|
||||||
|
const _Divider(),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -171,18 +224,6 @@ class _FieldOptionState extends State<FieldOption> {
|
|||||||
|
|
||||||
List<Widget> _buildOption() {
|
List<Widget> _buildOption() {
|
||||||
switch (values.type) {
|
switch (values.type) {
|
||||||
case FieldType.RichText:
|
|
||||||
return [
|
|
||||||
const _TextOption(),
|
|
||||||
];
|
|
||||||
case FieldType.URL:
|
|
||||||
return [
|
|
||||||
const _URLOption(),
|
|
||||||
];
|
|
||||||
case FieldType.Checkbox:
|
|
||||||
return [
|
|
||||||
const _CheckboxOption(),
|
|
||||||
];
|
|
||||||
case FieldType.Number:
|
case FieldType.Number:
|
||||||
return [
|
return [
|
||||||
_NumberOption(
|
_NumberOption(
|
||||||
@ -204,10 +245,8 @@ class _FieldOptionState extends State<FieldOption> {
|
|||||||
),
|
),
|
||||||
const _Divider(),
|
const _Divider(),
|
||||||
_TimeOption(
|
_TimeOption(
|
||||||
includeTime: values.includeTime,
|
|
||||||
selectedFormat: values.timeFormat ?? TimeFormatPB.TwelveHour,
|
selectedFormat: values.timeFormat ?? TimeFormatPB.TwelveHour,
|
||||||
onSelected: (includeTime, format) => _updateOptionValues(
|
onSelected: (format) => _updateOptionValues(
|
||||||
includeTime: includeTime,
|
|
||||||
timeFormat: format,
|
timeFormat: format,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -244,19 +283,24 @@ class _FieldOptionState extends State<FieldOption> {
|
|||||||
FieldOptionMode.add => [],
|
FieldOptionMode.add => [],
|
||||||
FieldOptionMode.edit => [
|
FieldOptionMode.edit => [
|
||||||
FlowyOptionTile.text(
|
FlowyOptionTile.text(
|
||||||
text: LocaleKeys.button_delete.tr(),
|
|
||||||
leftIcon: const FlowySvg(FlowySvgs.delete_s),
|
|
||||||
),
|
|
||||||
FlowyOptionTile.text(
|
|
||||||
showTopBorder: false,
|
|
||||||
text: LocaleKeys.button_duplicate.tr(),
|
|
||||||
leftIcon: const FlowySvg(FlowySvgs.copy_s),
|
|
||||||
),
|
|
||||||
FlowyOptionTile.text(
|
|
||||||
showTopBorder: false,
|
|
||||||
text: LocaleKeys.grid_field_hide.tr(),
|
text: LocaleKeys.grid_field_hide.tr(),
|
||||||
leftIcon: const FlowySvg(FlowySvgs.hide_s),
|
leftIcon: const FlowySvg(FlowySvgs.hide_s),
|
||||||
|
onTap: () => widget.onAction?.call(FieldOptionAction.hide),
|
||||||
),
|
),
|
||||||
|
if (!widget.isPrimary)
|
||||||
|
FlowyOptionTile.text(
|
||||||
|
showTopBorder: false,
|
||||||
|
text: LocaleKeys.button_duplicate.tr(),
|
||||||
|
leftIcon: const FlowySvg(FlowySvgs.copy_s),
|
||||||
|
onTap: () => widget.onAction?.call(FieldOptionAction.duplicate),
|
||||||
|
),
|
||||||
|
if (!widget.isPrimary)
|
||||||
|
FlowyOptionTile.text(
|
||||||
|
showTopBorder: false,
|
||||||
|
text: LocaleKeys.button_delete.tr(),
|
||||||
|
leftIcon: const FlowySvg(FlowySvgs.delete_s),
|
||||||
|
onTap: () => widget.onAction?.call(FieldOptionAction.delete),
|
||||||
|
),
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -265,7 +309,6 @@ class _FieldOptionState extends State<FieldOption> {
|
|||||||
FieldType? type,
|
FieldType? type,
|
||||||
String? name,
|
String? name,
|
||||||
DateFormatPB? dateFormate,
|
DateFormatPB? dateFormate,
|
||||||
bool? includeTime,
|
|
||||||
TimeFormatPB? timeFormat,
|
TimeFormatPB? timeFormat,
|
||||||
NumberFormatPB? numberFormat,
|
NumberFormatPB? numberFormat,
|
||||||
List<SelectOptionPB>? selectOption,
|
List<SelectOptionPB>? selectOption,
|
||||||
@ -279,9 +322,6 @@ class _FieldOptionState extends State<FieldOption> {
|
|||||||
if (dateFormate != null) {
|
if (dateFormate != null) {
|
||||||
values.dateFormate = dateFormate;
|
values.dateFormate = dateFormate;
|
||||||
}
|
}
|
||||||
if (includeTime != null) {
|
|
||||||
values.includeTime = includeTime;
|
|
||||||
}
|
|
||||||
if (timeFormat != null) {
|
if (timeFormat != null) {
|
||||||
values.timeFormat = timeFormat;
|
values.timeFormat = timeFormat;
|
||||||
}
|
}
|
||||||
@ -348,7 +388,6 @@ class _PropertyType extends StatelessWidget {
|
|||||||
FlowyText(
|
FlowyText(
|
||||||
type.i18n,
|
type.i18n,
|
||||||
color: Theme.of(context).hintColor,
|
color: Theme.of(context).hintColor,
|
||||||
fontSize: 16.0,
|
|
||||||
),
|
),
|
||||||
const HSpace(4.0),
|
const HSpace(4.0),
|
||||||
FlowySvg(
|
FlowySvg(
|
||||||
@ -394,33 +433,6 @@ class _Divider extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class _TextOption extends StatelessWidget {
|
|
||||||
const _TextOption();
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return const SizedBox.shrink();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class _URLOption extends StatelessWidget {
|
|
||||||
const _URLOption();
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return const SizedBox.shrink();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class _CheckboxOption extends StatelessWidget {
|
|
||||||
const _CheckboxOption();
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return const SizedBox.shrink();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class _DateOption extends StatefulWidget {
|
class _DateOption extends StatefulWidget {
|
||||||
const _DateOption({
|
const _DateOption({
|
||||||
required this.selectedFormat,
|
required this.selectedFormat,
|
||||||
@ -456,7 +468,6 @@ class _DateOptionState extends State<_DateOption> {
|
|||||||
),
|
),
|
||||||
child: FlowyText(
|
child: FlowyText(
|
||||||
LocaleKeys.grid_field_dateFormat.tr(),
|
LocaleKeys.grid_field_dateFormat.tr(),
|
||||||
fontSize: 16.0,
|
|
||||||
color: Theme.of(context).hintColor,
|
color: Theme.of(context).hintColor,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -480,14 +491,12 @@ class _DateOptionState extends State<_DateOption> {
|
|||||||
|
|
||||||
class _TimeOption extends StatefulWidget {
|
class _TimeOption extends StatefulWidget {
|
||||||
const _TimeOption({
|
const _TimeOption({
|
||||||
required this.includeTime,
|
|
||||||
required this.selectedFormat,
|
required this.selectedFormat,
|
||||||
required this.onSelected,
|
required this.onSelected,
|
||||||
});
|
});
|
||||||
|
|
||||||
final bool includeTime;
|
|
||||||
final TimeFormatPB selectedFormat;
|
final TimeFormatPB selectedFormat;
|
||||||
final Function(bool includeTime, TimeFormatPB format) onSelected;
|
final Function(TimeFormatPB format) onSelected;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<_TimeOption> createState() => _TimeOptionState();
|
State<_TimeOption> createState() => _TimeOptionState();
|
||||||
@ -495,14 +504,12 @@ class _TimeOption extends StatefulWidget {
|
|||||||
|
|
||||||
class _TimeOptionState extends State<_TimeOption> {
|
class _TimeOptionState extends State<_TimeOption> {
|
||||||
TimeFormatPB selectedFormat = TimeFormatPB.TwelveHour;
|
TimeFormatPB selectedFormat = TimeFormatPB.TwelveHour;
|
||||||
bool includeTime = false;
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
|
|
||||||
selectedFormat = widget.selectedFormat;
|
selectedFormat = widget.selectedFormat;
|
||||||
includeTime = widget.includeTime;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -517,34 +524,22 @@ class _TimeOptionState extends State<_TimeOption> {
|
|||||||
),
|
),
|
||||||
child: FlowyText(
|
child: FlowyText(
|
||||||
LocaleKeys.grid_field_timeFormat.tr(),
|
LocaleKeys.grid_field_timeFormat.tr(),
|
||||||
fontSize: 16.0,
|
|
||||||
color: Theme.of(context).hintColor,
|
color: Theme.of(context).hintColor,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
FlowyOptionTile.switcher(
|
...TimeFormatPB.values.mapIndexed((index, format) {
|
||||||
text: LocaleKeys.grid_field_includeTime.tr(),
|
return FlowyOptionTile.checkbox(
|
||||||
isSelected: includeTime,
|
text: format.title(),
|
||||||
onValueChanged: (includeTime) {
|
isSelected: selectedFormat == format,
|
||||||
widget.onSelected(includeTime, selectedFormat);
|
showTopBorder: false,
|
||||||
setState(() {
|
onTap: () {
|
||||||
this.includeTime = includeTime;
|
widget.onSelected(format);
|
||||||
});
|
setState(() {
|
||||||
},
|
selectedFormat = format;
|
||||||
),
|
});
|
||||||
if (includeTime)
|
},
|
||||||
...TimeFormatPB.values.mapIndexed((index, format) {
|
);
|
||||||
return FlowyOptionTile.checkbox(
|
}),
|
||||||
text: format.title(),
|
|
||||||
isSelected: selectedFormat == format,
|
|
||||||
showTopBorder: false,
|
|
||||||
onTap: () {
|
|
||||||
widget.onSelected(includeTime, format);
|
|
||||||
setState(() {
|
|
||||||
selectedFormat = format;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}),
|
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -569,7 +564,6 @@ class _NumberOption extends StatelessWidget {
|
|||||||
FlowyText(
|
FlowyText(
|
||||||
selectedFormat.title(),
|
selectedFormat.title(),
|
||||||
color: Theme.of(context).hintColor,
|
color: Theme.of(context).hintColor,
|
||||||
fontSize: 16.0,
|
|
||||||
),
|
),
|
||||||
const HSpace(4.0),
|
const HSpace(4.0),
|
||||||
FlowySvg(
|
FlowySvg(
|
||||||
@ -663,7 +657,6 @@ class _SelectOption extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
child: FlowyText(
|
child: FlowyText(
|
||||||
LocaleKeys.grid_field_optionTitle.tr(),
|
LocaleKeys.grid_field_optionTitle.tr(),
|
||||||
fontSize: 16.0,
|
|
||||||
color: Theme.of(context).hintColor,
|
color: Theme.of(context).hintColor,
|
||||||
),
|
),
|
||||||
),
|
),
|
@ -58,7 +58,9 @@ class _MobileDateCellEditScreenState extends State<MobileDateCellEditScreen> {
|
|||||||
Widget _buildFullScreen() {
|
Widget _buildFullScreen() {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: Text(LocaleKeys.titleBar_date.tr()),
|
title: FlowyText.medium(
|
||||||
|
LocaleKeys.titleBar_date.tr(),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
body: _buildBody(),
|
body: _buildBody(),
|
||||||
);
|
);
|
||||||
@ -117,7 +119,7 @@ class _MobileDateCellEditScreenState extends State<MobileDateCellEditScreen> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildHeader() {
|
Widget _buildHeader() {
|
||||||
const iconWidth = 36.0;
|
const iconWidth = 30.0;
|
||||||
const height = 44.0;
|
const height = 44.0;
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 8.0),
|
padding: const EdgeInsets.symmetric(horizontal: 8.0),
|
||||||
@ -139,7 +141,7 @@ class _MobileDateCellEditScreenState extends State<MobileDateCellEditScreen> {
|
|||||||
alignment: Alignment.center,
|
alignment: Alignment.center,
|
||||||
child: FlowyText.medium(
|
child: FlowyText.medium(
|
||||||
LocaleKeys.grid_field_dateFieldName.tr(),
|
LocaleKeys.grid_field_dateFieldName.tr(),
|
||||||
fontSize: 18,
|
fontSize: 16,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
].map((e) => SizedBox(height: height, child: e)).toList(),
|
].map((e) => SizedBox(height: height, child: e)).toList(),
|
||||||
|
@ -9,14 +9,14 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
|
||||||
class MobileCalendarEventsScreen extends StatefulWidget {
|
class MobileCalendarEventsScreen extends StatefulWidget {
|
||||||
static const routeName = "/calendar-events";
|
static const routeName = '/calendar_events';
|
||||||
|
|
||||||
// GoRouter Arguments
|
// GoRouter Arguments
|
||||||
static const calendarBlocKey = "calendar_bloc";
|
static const calendarBlocKey = 'calendar_bloc';
|
||||||
static const calendarDateKey = "date";
|
static const calendarDateKey = 'date';
|
||||||
static const calendarEventsKey = "events";
|
static const calendarEventsKey = 'events';
|
||||||
static const calendarRowCacheKey = "row_cache";
|
static const calendarRowCacheKey = 'row_cache';
|
||||||
static const calendarViewIdKey = "view_id";
|
static const calendarViewIdKey = 'view_id';
|
||||||
|
|
||||||
const MobileCalendarEventsScreen({
|
const MobileCalendarEventsScreen({
|
||||||
super.key,
|
super.key,
|
||||||
|
@ -137,7 +137,7 @@ class _TrashButton extends StatelessWidget {
|
|||||||
color: Theme.of(context).colorScheme.onSurface,
|
color: Theme.of(context).colorScheme.onSurface,
|
||||||
),
|
),
|
||||||
leftIconSize: const Size.square(24),
|
leftIconSize: const Size.square(24),
|
||||||
text: FlowyText(
|
text: FlowyText.medium(
|
||||||
LocaleKeys.trash_text.tr(),
|
LocaleKeys.trash_text.tr(),
|
||||||
fontSize: 18.0,
|
fontSize: 18.0,
|
||||||
),
|
),
|
||||||
|
@ -80,8 +80,8 @@ class _RecentViews extends StatelessWidget {
|
|||||||
separatorBuilder: () => const HSpace(8),
|
separatorBuilder: () => const HSpace(8),
|
||||||
children: recentViews
|
children: recentViews
|
||||||
.map(
|
.map(
|
||||||
(view) => SizedBox(
|
(view) => SizedBox.square(
|
||||||
width: 150,
|
dimension: 148,
|
||||||
child: MobileRecentView(view: view),
|
child: MobileRecentView(view: view),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
@ -96,8 +96,8 @@ class _MobileRecentViewState extends State<MobileRecentView> {
|
|||||||
),
|
),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.fromLTRB(8, 16, 8, 2),
|
padding: const EdgeInsets.fromLTRB(8, 18, 8, 2),
|
||||||
child: FlowyText(
|
child: FlowyText.medium(
|
||||||
view.name,
|
view.name,
|
||||||
maxLines: 2,
|
maxLines: 2,
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
@ -110,7 +110,7 @@ class _MobileRecentViewState extends State<MobileRecentView> {
|
|||||||
Align(
|
Align(
|
||||||
alignment: Alignment.centerLeft,
|
alignment: Alignment.centerLeft,
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.only(left: 4),
|
padding: const EdgeInsets.only(left: 8.0),
|
||||||
child: icon.isNotEmpty
|
child: icon.isNotEmpty
|
||||||
? EmojiText(
|
? EmojiText(
|
||||||
emoji: icon,
|
emoji: icon,
|
||||||
|
@ -307,7 +307,7 @@ class _SingleMobileInnerViewItemState extends State<SingleMobileInnerViewItem> {
|
|||||||
const HSpace(8),
|
const HSpace(8),
|
||||||
// title
|
// title
|
||||||
Expanded(
|
Expanded(
|
||||||
child: FlowyText.regular(
|
child: FlowyText.medium(
|
||||||
widget.view.name,
|
widget.view.name,
|
||||||
fontSize: 18.0,
|
fontSize: 18.0,
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
|
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:go_router/go_router.dart';
|
|
||||||
|
|
||||||
/// Widget for the root/initial pages in the bottom navigation bar.
|
/// Widget for the root/initial pages in the bottom navigation bar.
|
||||||
class RootPlaceholderScreen extends StatelessWidget {
|
class RootPlaceholderScreen extends StatelessWidget {
|
||||||
@ -24,31 +24,10 @@ class RootPlaceholderScreen extends StatelessWidget {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: Text('Root of section $label'),
|
centerTitle: true,
|
||||||
),
|
title: FlowyText.medium(label),
|
||||||
body: Center(
|
|
||||||
child: Column(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: <Widget>[
|
|
||||||
Text('$label Page', style: Theme.of(context).textTheme.titleLarge),
|
|
||||||
const Padding(padding: EdgeInsets.all(4)),
|
|
||||||
TextButton(
|
|
||||||
onPressed: () {
|
|
||||||
context.go(detailsPath, extra: '$label-XYZ');
|
|
||||||
},
|
|
||||||
child: const Text('View details'),
|
|
||||||
),
|
|
||||||
const Padding(padding: EdgeInsets.all(4)),
|
|
||||||
if (secondDetailsPath != null)
|
|
||||||
TextButton(
|
|
||||||
onPressed: () {
|
|
||||||
context.go(secondDetailsPath!);
|
|
||||||
},
|
|
||||||
child: const Text('View more details'),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
|
body: const SizedBox.shrink(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,8 @@ class FlowyOptionTile extends StatelessWidget {
|
|||||||
this.onTap,
|
this.onTap,
|
||||||
this.trailing,
|
this.trailing,
|
||||||
this.textFieldPadding = const EdgeInsets.symmetric(
|
this.textFieldPadding = const EdgeInsets.symmetric(
|
||||||
horizontal: 16.0,
|
horizontal: 12.0,
|
||||||
|
vertical: 2.0,
|
||||||
),
|
),
|
||||||
this.isSelected = false,
|
this.isSelected = false,
|
||||||
this.textFieldHintText,
|
this.textFieldHintText,
|
||||||
@ -55,7 +56,8 @@ class FlowyOptionTile extends StatelessWidget {
|
|||||||
void Function(String value)? onTextChanged,
|
void Function(String value)? onTextChanged,
|
||||||
void Function(String value)? onTextSubmitted,
|
void Function(String value)? onTextSubmitted,
|
||||||
EdgeInsets textFieldPadding = const EdgeInsets.symmetric(
|
EdgeInsets textFieldPadding = const EdgeInsets.symmetric(
|
||||||
horizontal: 16.0,
|
horizontal: 12.0,
|
||||||
|
vertical: 2.0,
|
||||||
),
|
),
|
||||||
bool showTopBorder = true,
|
bool showTopBorder = true,
|
||||||
bool showBottomBorder = true,
|
bool showBottomBorder = true,
|
||||||
@ -150,6 +152,7 @@ class FlowyOptionTile extends StatelessWidget {
|
|||||||
showTopBorder: showTopBorder,
|
showTopBorder: showTopBorder,
|
||||||
showBottomBorder: showBottomBorder,
|
showBottomBorder: showBottomBorder,
|
||||||
child: Row(
|
child: Row(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
_buildText(),
|
_buildText(),
|
||||||
..._buildTextField(),
|
..._buildTextField(),
|
||||||
@ -185,7 +188,6 @@ class FlowyOptionTile extends StatelessWidget {
|
|||||||
useIntrinsicWidth: true,
|
useIntrinsicWidth: true,
|
||||||
text: FlowyText(
|
text: FlowyText(
|
||||||
text!,
|
text!,
|
||||||
fontSize: 16.0,
|
|
||||||
),
|
),
|
||||||
margin: const EdgeInsets.symmetric(
|
margin: const EdgeInsets.symmetric(
|
||||||
horizontal: 16.0,
|
horizontal: 16.0,
|
||||||
@ -206,7 +208,6 @@ class FlowyOptionTile extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
child: FlowyText(
|
child: FlowyText(
|
||||||
text!,
|
text!,
|
||||||
fontSize: 16.0,
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -222,11 +223,12 @@ class FlowyOptionTile extends StatelessWidget {
|
|||||||
return [
|
return [
|
||||||
if (leading != null) leading!,
|
if (leading != null) leading!,
|
||||||
Expanded(
|
Expanded(
|
||||||
child: ConstrainedBox(
|
child: Container(
|
||||||
constraints: const BoxConstraints.tightFor(
|
constraints: const BoxConstraints.tightFor(
|
||||||
height: 52.0,
|
height: 54.0,
|
||||||
width: double.infinity,
|
width: double.infinity,
|
||||||
),
|
),
|
||||||
|
alignment: Alignment.center,
|
||||||
child: TextField(
|
child: TextField(
|
||||||
controller: controller,
|
controller: controller,
|
||||||
textInputAction: TextInputAction.done,
|
textInputAction: TextInputAction.done,
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import 'package:appflowy_backend/protobuf/flowy-database2/database_entities.pb.dart';
|
|
||||||
import 'package:dartz/dartz.dart';
|
|
||||||
import 'package:appflowy_backend/dispatch/dispatch.dart';
|
import 'package:appflowy_backend/dispatch/dispatch.dart';
|
||||||
import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
|
import 'package:appflowy_backend/protobuf/flowy-database2/database_entities.pb.dart';
|
||||||
import 'package:appflowy_backend/protobuf/flowy-database2/field_entities.pb.dart';
|
import 'package:appflowy_backend/protobuf/flowy-database2/field_entities.pb.dart';
|
||||||
|
import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
|
||||||
|
import 'package:dartz/dartz.dart';
|
||||||
|
|
||||||
/// FieldService consists of lots of event functions. We define the events in the backend(Rust),
|
/// FieldService consists of lots of event functions. We define the events in the backend(Rust),
|
||||||
/// you can find the corresponding event implementation in event_map.rs of the corresponding crate.
|
/// you can find the corresponding event implementation in event_map.rs of the corresponding crate.
|
||||||
@ -56,6 +56,17 @@ class FieldBackendService {
|
|||||||
return DatabaseEventUpdateFieldTypeOption(payload).send();
|
return DatabaseEventUpdateFieldTypeOption(payload).send();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<Either<Unit, FlowyError>> updateFieldType({
|
||||||
|
required FieldType fieldType,
|
||||||
|
}) {
|
||||||
|
final payload = UpdateFieldTypePayloadPB.create()
|
||||||
|
..viewId = viewId
|
||||||
|
..fieldId = fieldId
|
||||||
|
..fieldType = fieldType;
|
||||||
|
|
||||||
|
return DatabaseEventUpdateFieldType(payload).send();
|
||||||
|
}
|
||||||
|
|
||||||
Future<Either<Unit, FlowyError>> deleteField() {
|
Future<Either<Unit, FlowyError>> deleteField() {
|
||||||
final payload = DeleteFieldPayloadPB.create()
|
final payload = DeleteFieldPayloadPB.create()
|
||||||
..viewId = viewId
|
..viewId = viewId
|
||||||
|
@ -3,7 +3,7 @@ import 'package:appflowy/generated/locale_keys.g.dart';
|
|||||||
import 'package:appflowy/mobile/presentation/bottom_sheet/bottom_sheet.dart';
|
import 'package:appflowy/mobile/presentation/bottom_sheet/bottom_sheet.dart';
|
||||||
import 'package:appflowy/mobile/presentation/database/card/card_detail/mobile_create_field_screen.dart';
|
import 'package:appflowy/mobile/presentation/database/card/card_detail/mobile_create_field_screen.dart';
|
||||||
import 'package:appflowy/mobile/presentation/database/card/card_detail/widgets/_field_options.dart';
|
import 'package:appflowy/mobile/presentation/database/card/card_detail/widgets/_field_options.dart';
|
||||||
import 'package:appflowy/mobile/presentation/database/card/card_detail/widgets/_new_field_option.dart';
|
import 'package:appflowy/mobile/presentation/database/card/card_detail/widgets/_field_options_eidtor.dart';
|
||||||
import 'package:appflowy/plugins/database_view/application/field/field_controller.dart';
|
import 'package:appflowy/plugins/database_view/application/field/field_controller.dart';
|
||||||
import 'package:appflowy/plugins/database_view/grid/application/grid_bloc.dart';
|
import 'package:appflowy/plugins/database_view/grid/application/grid_bloc.dart';
|
||||||
import 'package:appflowy/plugins/database_view/grid/application/grid_header_bloc.dart';
|
import 'package:appflowy/plugins/database_view/grid/application/grid_header_bloc.dart';
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
||||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
import 'package:appflowy/mobile/presentation/database/card/card_detail/mobile_edit_field_screen.dart';
|
||||||
import 'package:appflowy/mobile/presentation/bottom_sheet/bottom_sheet_database_field_editor.dart';
|
import 'package:appflowy/mobile/presentation/database/card/card_detail/widgets/_field_options_eidtor.dart';
|
||||||
import 'package:appflowy/mobile/presentation/widgets/flowy_paginated_bottom_sheet.dart';
|
|
||||||
import 'package:appflowy/plugins/database_view/application/field/field_info.dart';
|
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
|
||||||
import 'package:appflowy/plugins/database_view/application/field/field_controller.dart';
|
import 'package:appflowy/plugins/database_view/application/field/field_controller.dart';
|
||||||
|
import 'package:appflowy/plugins/database_view/application/field/field_info.dart';
|
||||||
|
import 'package:appflowy/plugins/database_view/application/field/field_service.dart';
|
||||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:go_router/go_router.dart';
|
||||||
|
|
||||||
import 'field_type_extension.dart';
|
import 'field_type_extension.dart';
|
||||||
|
|
||||||
@ -41,19 +41,41 @@ class MobileFieldButton extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
child: FlowyButton(
|
child: FlowyButton(
|
||||||
onTap: () {
|
onTap: () async {
|
||||||
showPaginatedBottomSheet(
|
final optionValues = await context.push<FieldOptionValues>(
|
||||||
context,
|
MobileEditPropertyScreen.routeName,
|
||||||
page: SheetPage(
|
extra: {
|
||||||
title: LocaleKeys.grid_field_editProperty.tr(),
|
MobileEditPropertyScreen.argViewId: viewId,
|
||||||
body: MobileDBBottomSheetFieldEditor(
|
MobileEditPropertyScreen.argField: fieldInfo.field,
|
||||||
viewId: viewId,
|
MobileEditPropertyScreen.argIsPrimary: fieldInfo.isPrimary,
|
||||||
field: fieldInfo.field,
|
},
|
||||||
fieldController: fieldController,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
|
if (optionValues != null) {
|
||||||
|
final fieldId = fieldInfo.field.id;
|
||||||
|
final service = FieldBackendService(
|
||||||
|
viewId: viewId,
|
||||||
|
fieldId: fieldId,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (optionValues.name != fieldInfo.name) {
|
||||||
|
await service.updateField(name: optionValues.name);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (optionValues.type != fieldInfo.fieldType) {
|
||||||
|
await service.updateFieldType(fieldType: optionValues.type);
|
||||||
|
}
|
||||||
|
|
||||||
|
final data = optionValues.toTypeOptionBuffer();
|
||||||
|
if (data != null) {
|
||||||
|
await FieldBackendService.updateFieldTypeOption(
|
||||||
|
viewId: viewId,
|
||||||
|
fieldId: fieldId,
|
||||||
|
typeOptionData: data,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
radius: BorderRadius.zero,
|
||||||
margin: const EdgeInsets.symmetric(vertical: 12, horizontal: 8),
|
margin: const EdgeInsets.symmetric(vertical: 12, horizontal: 8),
|
||||||
leftIcon: FlowySvg(
|
leftIcon: FlowySvg(
|
||||||
fieldInfo.fieldType.icon(),
|
fieldInfo.fieldType.icon(),
|
||||||
|
@ -41,9 +41,7 @@ class _MobileDatePickerState extends State<MobileDatePicker> {
|
|||||||
|
|
||||||
Widget _buildCalendar(BuildContext context) {
|
Widget _buildCalendar(BuildContext context) {
|
||||||
const selectedColor = Color(0xFF00BCF0);
|
const selectedColor = Color(0xFF00BCF0);
|
||||||
final textStyle = Theme.of(context).textTheme.bodyMedium!.copyWith(
|
final textStyle = Theme.of(context).textTheme.bodyMedium!.copyWith();
|
||||||
fontSize: 16.0,
|
|
||||||
);
|
|
||||||
const boxDecoration = BoxDecoration(
|
const boxDecoration = BoxDecoration(
|
||||||
shape: BoxShape.circle,
|
shape: BoxShape.circle,
|
||||||
);
|
);
|
||||||
@ -156,7 +154,6 @@ class _MobileDatePickerState extends State<MobileDatePicker> {
|
|||||||
builder: (_, value, ___) {
|
builder: (_, value, ___) {
|
||||||
return FlowyText(
|
return FlowyText(
|
||||||
DateFormat.yMMMM(value.$2).format(value.$1),
|
DateFormat.yMMMM(value.$2).format(value.$1),
|
||||||
fontSize: 16.0,
|
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
@ -426,6 +426,7 @@ class DocumentCoverState extends State<DocumentCover> {
|
|||||||
children: [
|
children: [
|
||||||
IntrinsicWidth(
|
IntrinsicWidth(
|
||||||
child: RoundedTextButton(
|
child: RoundedTextButton(
|
||||||
|
fontSize: 14,
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
showMobileBottomSheet(
|
showMobileBottomSheet(
|
||||||
context,
|
context,
|
||||||
|
@ -6,6 +6,7 @@ import 'package:appflowy/plugins/document/presentation/editor_plugins/mobile_too
|
|||||||
import 'package:appflowy/plugins/document/presentation/more/cubit/document_appearance_cubit.dart';
|
import 'package:appflowy/plugins/document/presentation/more/cubit/document_appearance_cubit.dart';
|
||||||
import 'package:appflowy/plugins/inline_actions/inline_actions_menu.dart';
|
import 'package:appflowy/plugins/inline_actions/inline_actions_menu.dart';
|
||||||
import 'package:appflowy/util/google_font_family_extension.dart';
|
import 'package:appflowy/util/google_font_family_extension.dart';
|
||||||
|
import 'package:appflowy/workspace/application/settings/appearance/base_appearance.dart';
|
||||||
import 'package:appflowy_editor/appflowy_editor.dart' hide Log;
|
import 'package:appflowy_editor/appflowy_editor.dart' hide Log;
|
||||||
import 'package:collection/collection.dart';
|
import 'package:collection/collection.dart';
|
||||||
import 'package:flutter/gestures.dart';
|
import 'package:flutter/gestures.dart';
|
||||||
@ -160,7 +161,7 @@ class EditorStyleCustomizer {
|
|||||||
final theme = Theme.of(context);
|
final theme = Theme.of(context);
|
||||||
final fontSize = context.read<DocumentAppearanceCubit>().state.fontSize;
|
final fontSize = context.read<DocumentAppearanceCubit>().state.fontSize;
|
||||||
return TextStyle(
|
return TextStyle(
|
||||||
fontFamily: 'poppins',
|
fontFamily: builtInFontFamily,
|
||||||
fontSize: fontSize,
|
fontSize: fontSize,
|
||||||
height: 1.5,
|
height: 1.5,
|
||||||
color: theme.colorScheme.onBackground.withOpacity(0.6),
|
color: theme.colorScheme.onBackground.withOpacity(0.6),
|
||||||
@ -207,7 +208,7 @@ class EditorStyleCustomizer {
|
|||||||
fontWeight: fontWeight,
|
fontWeight: fontWeight,
|
||||||
);
|
);
|
||||||
} on Exception {
|
} on Exception {
|
||||||
return GoogleFonts.getFont('Poppins');
|
return GoogleFonts.getFont(builtInFontFamily);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import 'package:appflowy/core/config/kv_keys.dart';
|
import 'package:appflowy/core/config/kv_keys.dart';
|
||||||
|
import 'package:appflowy/workspace/application/settings/appearance/base_appearance.dart';
|
||||||
import 'package:bloc/bloc.dart';
|
import 'package:bloc/bloc.dart';
|
||||||
import 'package:shared_preferences/shared_preferences.dart';
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
|
|
||||||
@ -28,14 +29,19 @@ class DocumentAppearance {
|
|||||||
|
|
||||||
class DocumentAppearanceCubit extends Cubit<DocumentAppearance> {
|
class DocumentAppearanceCubit extends Cubit<DocumentAppearance> {
|
||||||
DocumentAppearanceCubit()
|
DocumentAppearanceCubit()
|
||||||
: super(const DocumentAppearance(fontSize: 16.0, fontFamily: 'Poppins'));
|
: super(
|
||||||
|
const DocumentAppearance(
|
||||||
|
fontSize: 16.0,
|
||||||
|
fontFamily: builtInFontFamily,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
Future<void> fetch() async {
|
Future<void> fetch() async {
|
||||||
final prefs = await SharedPreferences.getInstance();
|
final prefs = await SharedPreferences.getInstance();
|
||||||
final fontSize =
|
final fontSize =
|
||||||
prefs.getDouble(KVKeys.kDocumentAppearanceFontSize) ?? 16.0;
|
prefs.getDouble(KVKeys.kDocumentAppearanceFontSize) ?? 16.0;
|
||||||
final fontFamily =
|
final fontFamily = prefs.getString(KVKeys.kDocumentAppearanceFontFamily) ??
|
||||||
prefs.getString(KVKeys.kDocumentAppearanceFontFamily) ?? 'Poppins';
|
builtInFontFamily;
|
||||||
final defaultTextDirection =
|
final defaultTextDirection =
|
||||||
prefs.getString(KVKeys.kDocumentAppearanceDefaultTextDirection);
|
prefs.getString(KVKeys.kDocumentAppearanceDefaultTextDirection);
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@ import 'package:appflowy/mobile/presentation/database/board/mobile_board_screen.
|
|||||||
import 'package:appflowy/mobile/presentation/database/card/card.dart';
|
import 'package:appflowy/mobile/presentation/database/card/card.dart';
|
||||||
import 'package:appflowy/mobile/presentation/database/card/card_detail/mobile_create_field_screen.dart';
|
import 'package:appflowy/mobile/presentation/database/card/card_detail/mobile_create_field_screen.dart';
|
||||||
import 'package:appflowy/mobile/presentation/database/card/card_detail/mobile_create_row_field_screen.dart';
|
import 'package:appflowy/mobile/presentation/database/card/card_detail/mobile_create_row_field_screen.dart';
|
||||||
|
import 'package:appflowy/mobile/presentation/database/card/card_detail/mobile_edit_field_screen.dart';
|
||||||
import 'package:appflowy/mobile/presentation/database/card/card_property_edit/card_property_edit_screen.dart';
|
import 'package:appflowy/mobile/presentation/database/card/card_property_edit/card_property_edit_screen.dart';
|
||||||
import 'package:appflowy/mobile/presentation/database/date_picker/mobile_date_picker_screen.dart';
|
import 'package:appflowy/mobile/presentation/database/date_picker/mobile_date_picker_screen.dart';
|
||||||
import 'package:appflowy/mobile/presentation/database/mobile_calendar_events_screen.dart';
|
import 'package:appflowy/mobile/presentation/database/mobile_calendar_events_screen.dart';
|
||||||
@ -64,6 +65,7 @@ GoRouter generateRouter(Widget child) {
|
|||||||
_mobileDateCellEditScreenRoute(),
|
_mobileDateCellEditScreenRoute(),
|
||||||
_mobileCreateRowFieldScreenRoute(),
|
_mobileCreateRowFieldScreenRoute(),
|
||||||
_mobileNewPropertyPageRoute(),
|
_mobileNewPropertyPageRoute(),
|
||||||
|
_mobileEditPropertyPageRoute(),
|
||||||
|
|
||||||
// home
|
// home
|
||||||
// MobileHomeSettingPage is outside the bottom navigation bar, thus it is not in the StatefulShellRoute.
|
// MobileHomeSettingPage is outside the bottom navigation bar, thus it is not in the StatefulShellRoute.
|
||||||
@ -373,9 +375,28 @@ GoRoute _mobileNewPropertyPageRoute() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GoRoute _mobileEditPropertyPageRoute() {
|
||||||
|
return GoRoute(
|
||||||
|
parentNavigatorKey: AppGlobals.rootNavKey,
|
||||||
|
path: MobileEditPropertyScreen.routeName,
|
||||||
|
pageBuilder: (context, state) {
|
||||||
|
final args = state.extra as Map<String, dynamic>;
|
||||||
|
return MaterialPage(
|
||||||
|
fullscreenDialog: true,
|
||||||
|
child: MobileEditPropertyScreen(
|
||||||
|
viewId: args[MobileEditPropertyScreen.argViewId],
|
||||||
|
field: args[MobileEditPropertyScreen.argField],
|
||||||
|
isPrimary: args[MobileEditPropertyScreen.argIsPrimary],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
GoRoute _mobileCalendarEventsPageRoute() {
|
GoRoute _mobileCalendarEventsPageRoute() {
|
||||||
return GoRoute(
|
return GoRoute(
|
||||||
path: MobileCalendarEventsScreen.routeName,
|
path: MobileCalendarEventsScreen.routeName,
|
||||||
|
parentNavigatorKey: AppGlobals.rootNavKey,
|
||||||
pageBuilder: (context, state) {
|
pageBuilder: (context, state) {
|
||||||
final args = state.extra as Map<String, dynamic>;
|
final args = state.extra as Map<String, dynamic>;
|
||||||
|
|
||||||
|
@ -3,6 +3,8 @@ import 'package:flowy_infra/theme.dart';
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:google_fonts/google_fonts.dart';
|
import 'package:google_fonts/google_fonts.dart';
|
||||||
|
|
||||||
|
const builtInFontFamily = 'Poppins';
|
||||||
|
|
||||||
abstract class BaseAppearance {
|
abstract class BaseAppearance {
|
||||||
final white = const Color(0xFFFFFFFF);
|
final white = const Color(0xFFFFFFFF);
|
||||||
|
|
||||||
@ -20,25 +22,36 @@ abstract class BaseAppearance {
|
|||||||
double? letterSpacing,
|
double? letterSpacing,
|
||||||
double? lineHeight,
|
double? lineHeight,
|
||||||
}) {
|
}) {
|
||||||
|
fontSize = fontSize ?? FontSizes.s12;
|
||||||
|
fontWeight = fontWeight ?? FontWeight.w400;
|
||||||
|
letterSpacing = fontSize * (letterSpacing ?? 0.005);
|
||||||
|
|
||||||
|
final textStyle = TextStyle(
|
||||||
|
fontFamily: fontFamily,
|
||||||
|
fontSize: fontSize,
|
||||||
|
color: fontColor,
|
||||||
|
fontWeight: fontWeight,
|
||||||
|
fontFamilyFallback: const [builtInFontFamily],
|
||||||
|
letterSpacing: letterSpacing,
|
||||||
|
height: lineHeight,
|
||||||
|
);
|
||||||
|
|
||||||
|
// we embed Poppins font in the app, so we can use it without GoogleFonts
|
||||||
|
if (fontFamily == builtInFontFamily) {
|
||||||
|
return textStyle;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return GoogleFonts.getFont(
|
return GoogleFonts.getFont(
|
||||||
fontFamily,
|
fontFamily,
|
||||||
fontSize: fontSize ?? FontSizes.s12,
|
fontSize: fontSize,
|
||||||
color: fontColor,
|
color: fontColor,
|
||||||
fontWeight: fontWeight ?? FontWeight.w500,
|
fontWeight: fontWeight,
|
||||||
letterSpacing: (fontSize ?? FontSizes.s12) * (letterSpacing ?? 0.005),
|
letterSpacing: letterSpacing,
|
||||||
height: lineHeight,
|
height: lineHeight,
|
||||||
);
|
);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return TextStyle(
|
return textStyle;
|
||||||
fontFamily: fontFamily,
|
|
||||||
fontSize: fontSize ?? FontSizes.s12,
|
|
||||||
color: fontColor,
|
|
||||||
fontWeight: fontWeight ?? FontWeight.w500,
|
|
||||||
fontFamilyFallback: const ['Poppins'],
|
|
||||||
letterSpacing: (fontSize ?? FontSizes.s12) * (letterSpacing ?? 0.005),
|
|
||||||
height: lineHeight,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,7 +24,10 @@ class MobileAppearance extends BaseAppearance {
|
|||||||
|
|
||||||
final fontStyle = getFontStyle(
|
final fontStyle = getFontStyle(
|
||||||
fontFamily: fontFamily,
|
fontFamily: fontFamily,
|
||||||
|
fontSize: 16.0,
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
);
|
);
|
||||||
|
|
||||||
final codeFontStyle = getFontStyle(
|
final codeFontStyle = getFontStyle(
|
||||||
fontFamily: codeFontFamily,
|
fontFamily: codeFontFamily,
|
||||||
);
|
);
|
||||||
@ -196,9 +199,7 @@ class MobileAppearance extends BaseAppearance {
|
|||||||
// body2 14 Regular
|
// body2 14 Regular
|
||||||
bodyMedium: fontStyle.copyWith(
|
bodyMedium: fontStyle.copyWith(
|
||||||
color: colorTheme.onBackground,
|
color: colorTheme.onBackground,
|
||||||
fontSize: 14,
|
|
||||||
fontWeight: FontWeight.w400,
|
fontWeight: FontWeight.w400,
|
||||||
// height: 1.2,
|
|
||||||
letterSpacing: 0.07,
|
letterSpacing: 0.07,
|
||||||
),
|
),
|
||||||
// Trash empty title
|
// Trash empty title
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
import 'package:appflowy/user/application/user_settings_service.dart';
|
import 'package:appflowy/user/application/user_settings_service.dart';
|
||||||
import 'package:appflowy/workspace/application/settings/appearance/appearance_cubit.dart';
|
import 'package:appflowy/workspace/application/settings/appearance/appearance_cubit.dart';
|
||||||
import 'package:bloc_test/bloc_test.dart';
|
import 'package:appflowy/workspace/application/settings/appearance/base_appearance.dart';
|
||||||
import 'package:appflowy_backend/protobuf/flowy-user/user_setting.pb.dart';
|
import 'package:appflowy_backend/protobuf/flowy-user/user_setting.pb.dart';
|
||||||
|
import 'package:bloc_test/bloc_test.dart';
|
||||||
import 'package:flowy_infra/theme.dart';
|
import 'package:flowy_infra/theme.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_test/flutter_test.dart';
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
@ -35,7 +36,7 @@ void main() {
|
|||||||
AppTheme.fallback,
|
AppTheme.fallback,
|
||||||
),
|
),
|
||||||
verify: (bloc) {
|
verify: (bloc) {
|
||||||
expect(bloc.state.font, 'Poppins');
|
expect(bloc.state.font, builtInFontFamily);
|
||||||
expect(bloc.state.monospaceFont, 'SF Mono');
|
expect(bloc.state.monospaceFont, 'SF Mono');
|
||||||
expect(bloc.state.themeMode, ThemeMode.system);
|
expect(bloc.state.themeMode, ThemeMode.system);
|
||||||
},
|
},
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import 'package:appflowy/core/config/kv_keys.dart';
|
import 'package:appflowy/core/config/kv_keys.dart';
|
||||||
import 'package:appflowy/plugins/document/presentation/more/cubit/document_appearance_cubit.dart';
|
import 'package:appflowy/plugins/document/presentation/more/cubit/document_appearance_cubit.dart';
|
||||||
|
import 'package:appflowy/workspace/application/settings/appearance/base_appearance.dart';
|
||||||
import 'package:flutter/widgets.dart';
|
import 'package:flutter/widgets.dart';
|
||||||
import 'package:flutter_test/flutter_test.dart';
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
import 'package:shared_preferences/shared_preferences.dart';
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
@ -26,7 +27,7 @@ void main() {
|
|||||||
|
|
||||||
test('Initial state', () {
|
test('Initial state', () {
|
||||||
expect(cubit.state.fontSize, 16.0);
|
expect(cubit.state.fontSize, 16.0);
|
||||||
expect(cubit.state.fontFamily, 'Poppins');
|
expect(cubit.state.fontFamily, builtInFontFamily);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Fetch document appearance from SharedPreferences', () async {
|
test('Fetch document appearance from SharedPreferences', () async {
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import 'package:appflowy/plugins/document/presentation/editor_style.dart';
|
import 'package:appflowy/plugins/document/presentation/editor_style.dart';
|
||||||
import 'package:appflowy/plugins/document/presentation/more/cubit/document_appearance_cubit.dart';
|
import 'package:appflowy/plugins/document/presentation/more/cubit/document_appearance_cubit.dart';
|
||||||
|
import 'package:appflowy/workspace/application/settings/appearance/base_appearance.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_test/flutter_test.dart';
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
import 'package:google_fonts/google_fonts.dart';
|
import 'package:google_fonts/google_fonts.dart';
|
||||||
@ -39,7 +40,7 @@ void main() {
|
|||||||
expect(result, isA<TextStyle>());
|
expect(result, isA<TextStyle>());
|
||||||
expect(
|
expect(
|
||||||
result.fontFamily,
|
result.fontFamily,
|
||||||
GoogleFonts.getFont('Poppins').fontFamily,
|
GoogleFonts.getFont(builtInFontFamily).fontFamily,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import 'package:appflowy/plugins/document/presentation/more/cubit/document_appearance_cubit.dart';
|
import 'package:appflowy/plugins/document/presentation/more/cubit/document_appearance_cubit.dart';
|
||||||
import 'package:appflowy/workspace/application/settings/appearance/appearance_cubit.dart';
|
import 'package:appflowy/workspace/application/settings/appearance/appearance_cubit.dart';
|
||||||
|
import 'package:appflowy/workspace/application/settings/appearance/base_appearance.dart';
|
||||||
import 'package:appflowy/workspace/presentation/settings/widgets/settings_appearance/font_family_setting.dart';
|
import 'package:appflowy/workspace/presentation/settings/widgets/settings_appearance/font_family_setting.dart';
|
||||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
@ -57,7 +58,7 @@ void main() {
|
|||||||
],
|
],
|
||||||
child: const Scaffold(
|
child: const Scaffold(
|
||||||
body: ThemeFontFamilySetting(
|
body: ThemeFontFamilySetting(
|
||||||
currentFontFamily: 'Poppins',
|
currentFontFamily: builtInFontFamily,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -70,7 +71,7 @@ void main() {
|
|||||||
await tester.pumpAndSettle();
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
// Verify the initial font family
|
// Verify the initial font family
|
||||||
expect(find.text('Poppins'), findsAtLeastNWidgets(1));
|
expect(find.text(builtInFontFamily), findsAtLeastNWidgets(1));
|
||||||
when(() => appearanceSettingsCubit.setFontFamily(any<String>()))
|
when(() => appearanceSettingsCubit.setFontFamily(any<String>()))
|
||||||
.thenAnswer((_) async {});
|
.thenAnswer((_) async {});
|
||||||
verifyNever(() => appearanceSettingsCubit.setFontFamily(any<String>()));
|
verifyNever(() => appearanceSettingsCubit.setFontFamily(any<String>()));
|
||||||
|
Reference in New Issue
Block a user