TF-4178 Add create new label modal

This commit is contained in:
dab246
2025-11-26 12:10:55 +07:00
committed by Dat H. Pham
parent f6f299dc97
commit d3029ec4de
16 changed files with 629 additions and 1 deletions
+17
View File
@@ -0,0 +1,17 @@
<svg width="19" height="19" viewBox="0 0 19 19" fill="none" xmlns="http://www.w3.org/2000/svg">
<path
d="M9.23078 16.9231C4.99231 16.9231 1.53847 13.4692 1.53847 9.23077C1.53847 4.99231 4.99231 1.53846 9.23078 1.53846C13.4692 1.53846 16.9231 4.64615 16.9231 8.46154C16.9231 11.0077 14.8539 13.0769 12.3077 13.0769H10.9462C10.7308 13.0769 10.5615 13.2462 10.5615 13.4615C10.5615 13.5538 10.6 13.6385 10.6615 13.7154C10.9769 14.0769 11.1539 14.5308 11.1539 15C11.1539 16.0615 10.2923 16.9231 9.23078 16.9231ZM9.23078 3.07692C5.83847 3.07692 3.07693 5.83846 3.07693 9.23077C3.07693 12.6231 5.83847 15.3846 9.23078 15.3846C9.44616 15.3846 9.61539 15.2154 9.61539 15C9.61539 14.8769 9.55385 14.7846 9.5077 14.7308C9.19231 14.3769 9.02308 13.9231 9.02308 13.4615C9.02308 12.4 9.88462 11.5385 10.9462 11.5385H12.3077C14.0077 11.5385 15.3846 10.1615 15.3846 8.46154C15.3846 5.49231 12.6231 3.07692 9.23078 3.07692Z"
fill="#1C1B1F" />
<path
d="M5.00001 10C5.63726 10 6.15385 9.4834 6.15385 8.84615C6.15385 8.2089 5.63726 7.69231 5.00001 7.69231C4.36275 7.69231 3.84616 8.2089 3.84616 8.84615C3.84616 9.4834 4.36275 10 5.00001 10Z"
fill="#1C1B1F" />
<path
d="M7.3077 6.92308C7.94495 6.92308 8.46154 6.40648 8.46154 5.76923C8.46154 5.13198 7.94495 4.61538 7.3077 4.61538C6.67045 4.61538 6.15385 5.13198 6.15385 5.76923C6.15385 6.40648 6.67045 6.92308 7.3077 6.92308Z"
fill="#1C1B1F" />
<path
d="M11.1539 6.92308C11.7911 6.92308 12.3077 6.40648 12.3077 5.76923C12.3077 5.13198 11.7911 4.61538 11.1539 4.61538C10.5166 4.61538 10 5.13198 10 5.76923C10 6.40648 10.5166 6.92308 11.1539 6.92308Z"
fill="#1C1B1F" />
<path
d="M13.4615 10C14.0988 10 14.6154 9.4834 14.6154 8.84615C14.6154 8.2089 14.0988 7.69231 13.4615 7.69231C12.8243 7.69231 12.3077 8.2089 12.3077 8.84615C12.3077 9.4834 12.8243 10 13.4615 10Z"
fill="#1C1B1F" />
</svg>

After

Width:  |  Height:  |  Size: 1.9 KiB

+2
View File
@@ -117,6 +117,8 @@ export 'presentation/views/semantics/text_field_semantics.dart';
export 'presentation/views/semantics/icon_semantics.dart'; export 'presentation/views/semantics/icon_semantics.dart';
export 'presentation/views/shortcut/key_shortcut.dart'; export 'presentation/views/shortcut/key_shortcut.dart';
export 'presentation/views/tooltip/iframe_tooltip_overlay.dart'; export 'presentation/views/tooltip/iframe_tooltip_overlay.dart';
export 'presentation/views/color/color_circle_widget.dart';
export 'presentation/views/color/colors_map_widget.dart';
// Resources // Resources
export 'presentation/resources/assets_paths.dart'; export 'presentation/resources/assets_paths.dart';
@@ -280,6 +280,7 @@ extension AppColor on Color {
static const gray49454F = Color(0xFF49454F); static const gray49454F = Color(0xFF49454F);
static const blue00B7FF = Color(0xFF00B7FF); static const blue00B7FF = Color(0xFF00B7FF);
static const blueD2E9FF = Color(0xFFD2E9FF); static const blueD2E9FF = Color(0xFFD2E9FF);
static const grayCDCDCD = Color(0xFFCDCDCD);
static const lightGrayF9FAFB = Color(0xFFF9FAFB); static const lightGrayF9FAFB = Color(0xFFF9FAFB);
static const black4D4D4D = Color(0xFF4D4D4D); static const black4D4D4D = Color(0xFF4D4D4D);
static const black1A1A1A = Color(0xFF1A1A1A); static const black1A1A1A = Color(0xFF1A1A1A);
@@ -276,6 +276,7 @@ class ImagePaths {
String get icAiMoreProfessional => _getImagePath('ic_ai_more_professional.svg'); String get icAiMoreProfessional => _getImagePath('ic_ai_more_professional.svg');
String get icAiMorePolite => _getImagePath('ic_ai_more_polite.svg'); String get icAiMorePolite => _getImagePath('ic_ai_more_polite.svg');
String get icTag => _getImagePath('ic_tag.svg'); String get icTag => _getImagePath('ic_tag.svg');
String get icColorPicker => _getImagePath('ic_color_picker.svg');
String _getImagePath(String imageName) { String _getImagePath(String imageName) {
return AssetsPaths.images + imageName; return AssetsPaths.images + imageName;
@@ -110,6 +110,7 @@ class TMailButtonWidget extends StatelessWidget {
EdgeInsetsGeometry? margin, EdgeInsetsGeometry? margin,
Color? hoverColor, Color? hoverColor,
Alignment? alignment, Alignment? alignment,
BoxBorder? border,
}) { }) {
return TMailButtonWidget( return TMailButtonWidget(
key: key, key: key,
@@ -137,6 +138,7 @@ class TMailButtonWidget extends StatelessWidget {
margin: margin, margin: margin,
hoverColor: hoverColor, hoverColor: hoverColor,
alignment: alignment, alignment: alignment,
border: border,
); );
} }
@@ -0,0 +1,49 @@
import 'package:core/presentation/extensions/color_extension.dart';
import 'package:core/presentation/resources/image_paths.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
class ColorCircleWidget extends StatelessWidget {
final Color color;
final bool isSelected;
final ImagePaths imagePaths;
final VoidCallback onTap;
const ColorCircleWidget({
super.key,
required this.color,
required this.isSelected,
required this.imagePaths,
required this.onTap,
});
@override
Widget build(BuildContext context) {
return Material(
type: MaterialType.transparency,
child: InkWell(
onTap: onTap,
customBorder: const CircleBorder(),
child: Container(
width: 40,
height: 40,
decoration: BoxDecoration(
color: color,
shape: BoxShape.circle,
),
child: isSelected
? Center(
child: SvgPicture.asset(
imagePaths.icCheck,
colorFilter: Colors.white.asFilter(),
width: 18.46,
height: 18.46,
fit: BoxFit.fill,
),
)
: null,
),
),
);
}
}
@@ -0,0 +1,131 @@
import 'package:core/presentation/extensions/color_extension.dart';
import 'package:core/presentation/resources/image_paths.dart';
import 'package:core/presentation/views/button/tmail_button_widget.dart';
import 'package:core/presentation/views/color/color_circle_widget.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
class ColorsMapWidget extends StatefulWidget {
final Color? initialColor;
const ColorsMapWidget({
super.key,
this.initialColor,
});
@override
State<ColorsMapWidget> createState() => _ColorsMapWidgetState();
}
class _ColorsMapWidgetState extends State<ColorsMapWidget> {
static const List<Color> _defaultColors = [
Color(0xFF273891),
Color(0xFF7E57E3),
Color(0xFF9E83E8),
Color(0xFF617ADB),
Color(0xFF4896E5),
Color(0xFF038199),
Color(0xFF457D6C),
Color(0xFF1EBBCC),
Color(0xFF51B588),
Color(0xFFE0465C),
Color(0xFFED20A4),
Color(0xFFED768D),
Color(0xFFB85B17),
Color(0xFFBA8144),
Color(0xFFED916B),
Color(0xFFEDA91D),
Color(0xFFEDC661),
Color(0xFF131326),
Color(0xFF2C2C42),
Color(0xFF646580),
];
final _imagePaths = Get.find<ImagePaths>();
final ValueNotifier<Color?> _selectedColor = ValueNotifier(null);
@override
void initState() {
super.initState();
_selectedColor.value = widget.initialColor;
}
@override
Widget build(BuildContext context) {
return Wrap(
spacing: 10,
runSpacing: 10,
children: [
TMailButtonWidget.fromIcon(
icon: _imagePaths.icCloseDialog,
iconColor: AppColor.m3SurfaceBackground.withValues(alpha: 0.48),
iconSize: 18.46,
width: 40,
height: 40,
borderRadius: 100,
backgroundColor: Colors.transparent,
border: Border.all(width: 2, color: AppColor.grayCDCDCD),
onTapActionCallback: _clearColor,
),
..._defaultColors
.map(
(color) => ValueListenableBuilder(
valueListenable: _selectedColor,
builder: (context, value, child) {
return ColorCircleWidget(
color: color,
isSelected: color == value,
onTap: () => _selectColor(color),
imagePaths: _imagePaths,
);
},
),
)
.toList(),
Container(
padding: const EdgeInsets.all(2),
decoration: const BoxDecoration(
shape: BoxShape.circle,
gradient: LinearGradient(
colors: [
Color(0xFFFB2C36),
Color(0xFFAD46FF),
Color(0xFF2B7FFF),
],
stops: [0, 0.5, 1],
begin: AlignmentDirectional.topStart,
end: AlignmentDirectional.bottomEnd,
),
),
child: TMailButtonWidget.fromIcon(
icon: _imagePaths.icColorPicker,
iconColor: AppColor.textSecondary,
iconSize: 18.46,
width: 40,
height: 40,
borderRadius: 100,
backgroundColor: Colors.white,
onTapActionCallback: _openColorPicker,
),
),
],
);
}
void _selectColor(Color color) {
_selectedColor.value = color;
}
void _clearColor() {
_selectedColor.value = null;
}
void _openColorPicker() {}
@override
void dispose() {
_selectedColor.dispose();
super.dispose();
}
}
@@ -9,4 +9,8 @@ extension ListLabelExtension on List<Label> {
(label, otherLabel) => label.compareAlphabetically(otherLabel), (label, otherLabel) => label.compareAlphabetically(otherLabel),
); );
} }
List<String> get displayNameNotNullList => map((label) => label.safeDisplayName)
.where((name) => name.isNotEmpty)
.toList();
} }
@@ -1,5 +1,6 @@
import 'package:core/presentation/state/failure.dart'; import 'package:core/presentation/state/failure.dart';
import 'package:core/presentation/state/success.dart'; import 'package:core/presentation/state/success.dart';
import 'package:core/utils/platform_info.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:jmap_dart_client/jmap/account_id.dart'; import 'package:jmap_dart_client/jmap/account_id.dart';
import 'package:jmap_dart_client/jmap/core/session/session.dart'; import 'package:jmap_dart_client/jmap/core/session/session.dart';
@@ -11,12 +12,14 @@ import 'package:tmail_ui_user/features/base/base_controller.dart';
import 'package:tmail_ui_user/features/labels/domain/state/get_all_label_state.dart'; import 'package:tmail_ui_user/features/labels/domain/state/get_all_label_state.dart';
import 'package:tmail_ui_user/features/labels/domain/usecases/get_all_label_interactor.dart'; import 'package:tmail_ui_user/features/labels/domain/usecases/get_all_label_interactor.dart';
import 'package:tmail_ui_user/features/labels/presentation/label_interactor_bindings.dart'; import 'package:tmail_ui_user/features/labels/presentation/label_interactor_bindings.dart';
import 'package:tmail_ui_user/features/labels/presentation/widgets/create_new_label_modal.dart';
import 'package:tmail_ui_user/main/error/capability_validator.dart'; import 'package:tmail_ui_user/main/error/capability_validator.dart';
import 'package:tmail_ui_user/main/routes/route_navigation.dart'; import 'package:tmail_ui_user/main/routes/route_navigation.dart';
class LabelController extends BaseController { class LabelController extends BaseController {
final labels = <Label>[].obs; final labels = <Label>[].obs;
final labelListExpandMode = Rx(ExpandMode.EXPAND); final labelListExpandMode = Rx(ExpandMode.EXPAND);
final isCreateNewLabelModalVisible = RxBool(false);
GetAllLabelInteractor? _getAllLabelInteractor; GetAllLabelInteractor? _getAllLabelInteractor;
@@ -41,6 +44,22 @@ class LabelController extends BaseController {
: ExpandMode.COLLAPSE; : ExpandMode.COLLAPSE;
} }
Future<void> openCreateNewLabelModal() async {
if (PlatformInfo.isWeb) {
isCreateNewLabelModalVisible.value = true;
}
await Get.generalDialog(
barrierDismissible: true,
barrierLabel: 'create-new-label-modal',
pageBuilder: (_, __, ___) => CreateNewLabelModal(labels: labels),
).whenComplete(() {
if (PlatformInfo.isWeb) {
isCreateNewLabelModalVisible.value = false;
}
});
}
@override @override
void handleSuccessViewState(Success success) { void handleSuccessViewState(Success success) {
if (success is GetAllLabelSuccess) { if (success is GetAllLabelSuccess) {
@@ -7,6 +7,7 @@ import 'package:tmail_ui_user/features/labels/data/network/label_api.dart';
import 'package:tmail_ui_user/features/labels/data/repository/label_repository_impl.dart'; import 'package:tmail_ui_user/features/labels/data/repository/label_repository_impl.dart';
import 'package:tmail_ui_user/features/labels/domain/repository/label_repository.dart'; import 'package:tmail_ui_user/features/labels/domain/repository/label_repository.dart';
import 'package:tmail_ui_user/features/labels/domain/usecases/get_all_label_interactor.dart'; import 'package:tmail_ui_user/features/labels/domain/usecases/get_all_label_interactor.dart';
import 'package:tmail_ui_user/features/mailbox_creator/domain/usecases/verify_name_interactor.dart';
import 'package:tmail_ui_user/main/exceptions/remote_exception_thrower.dart'; import 'package:tmail_ui_user/main/exceptions/remote_exception_thrower.dart';
class LabelInteractorBindings extends InteractorsBindings { class LabelInteractorBindings extends InteractorsBindings {
@@ -29,6 +30,7 @@ class LabelInteractorBindings extends InteractorsBindings {
@override @override
void bindingsInteractor() { void bindingsInteractor() {
Get.lazyPut(() => GetAllLabelInteractor(Get.find<LabelRepository>())); Get.lazyPut(() => GetAllLabelInteractor(Get.find<LabelRepository>()));
Get.lazyPut(() => VerifyNameInteractor());
} }
@override @override
@@ -0,0 +1,280 @@
import 'dart:math' as math;
import 'package:core/presentation/extensions/color_extension.dart';
import 'package:core/presentation/resources/image_paths.dart';
import 'package:core/presentation/utils/responsive_utils.dart';
import 'package:core/presentation/utils/theme_utils.dart';
import 'package:core/presentation/views/color/colors_map_widget.dart';
import 'package:core/utils/platform_info.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:labels/extensions/list_label_extension.dart';
import 'package:labels/model/label.dart';
import 'package:tmail_ui_user/features/base/widget/default_field/default_close_button_widget.dart';
import 'package:tmail_ui_user/features/base/widget/label_input_field_builder.dart';
import 'package:tmail_ui_user/features/base/widget/modal_list_action_button_widget.dart';
import 'package:tmail_ui_user/features/mailbox_creator/domain/model/verification/duplicate_name_validator.dart';
import 'package:tmail_ui_user/features/mailbox_creator/domain/model/verification/empty_name_validator.dart';
import 'package:tmail_ui_user/features/mailbox_creator/domain/model/verification/name_with_space_only_validator.dart';
import 'package:tmail_ui_user/features/mailbox_creator/domain/model/verification/special_character_validator.dart';
import 'package:tmail_ui_user/features/mailbox_creator/domain/model/verification/validator.dart';
import 'package:tmail_ui_user/features/mailbox_creator/domain/state/verify_name_view_state.dart';
import 'package:tmail_ui_user/features/mailbox_creator/domain/usecases/verify_name_interactor.dart';
import 'package:tmail_ui_user/features/mailbox_creator/presentation/extensions/validator_failure_extension.dart';
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
import 'package:tmail_ui_user/main/routes/route_navigation.dart';
class CreateNewLabelModal extends StatefulWidget {
final List<Label> labels;
const CreateNewLabelModal({super.key, required this.labels});
@override
State<CreateNewLabelModal> createState() => _CreateNewLabelModalState();
}
class _CreateNewLabelModalState extends State<CreateNewLabelModal> {
final _imagePaths = Get.find<ImagePaths>();
final _verifyNameInteractor = Get.find<VerifyNameInteractor>();
final ValueNotifier<String?> _labelNameErrorText = ValueNotifier(null);
final TextEditingController _nameInputController = TextEditingController();
final FocusNode _nameInputFocusNode = FocusNode();
List<String> _labelDisplayNameList = <String>[];
@override
void initState() {
super.initState();
_labelDisplayNameList = widget.labels.displayNameNotNullList;
}
@override
Widget build(BuildContext context) {
final appLocalizations = AppLocalizations.of(context);
final theme = Theme.of(context);
return LayoutBuilder(builder: (_, constraints) {
final currentScreenWidth = constraints.maxWidth;
final currentScreenHeight = constraints.maxHeight;
final isMobile = currentScreenWidth < ResponsiveUtils.minTabletWidth;
Widget bodyWidget = Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: const BorderRadius.all(Radius.circular(16)),
boxShadow: [
BoxShadow(
color: Colors.black.withValues(alpha: 0.08),
blurRadius: 24,
offset: const Offset(0, 2),
),
BoxShadow(
color: Colors.black.withValues(alpha: 0.08),
blurRadius: 2,
),
],
),
width: math.min(
currentScreenWidth - 32,
554,
),
constraints: BoxConstraints(maxHeight: currentScreenHeight - 100),
clipBehavior: Clip.antiAlias,
child: Stack(
children: [
Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
height: 64,
alignment: Alignment.center,
padding: EdgeInsetsDirectional.only(
start: 32,
end: 32,
top: 16,
bottom: isMobile ? 0 : 16,
),
child: Text(
appLocalizations.createANewLabel,
style: theme.textTheme.headlineSmall?.copyWith(
color: AppColor.m3SurfaceBackground,
),
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
),
Center(
child: Padding(
padding: EdgeInsetsDirectional.only(
start: 32,
end: 32,
bottom: isMobile ? 32 : 48,
),
child: Text(
appLocalizations.organizeYourInboxWithACustomCategory,
style: ThemeUtils.textStyleInter400.copyWith(
color: AppColor.steelGrayA540,
fontSize: 13,
height: 20 / 13,
),
textAlign: TextAlign.center,
),
),
),
Flexible(
child: SingleChildScrollView(
physics: const ClampingScrollPhysics(),
child: Padding(
padding: EdgeInsetsDirectional.only(
start: 32,
end: 32,
bottom: isMobile ? 0 : 16,
),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
ValueListenableBuilder(
valueListenable: _labelNameErrorText,
builder: (_, errorText, __) {
return LabelInputFieldBuilder(
label: appLocalizations.labelName,
hintText: appLocalizations
.pleaseEnterNameYourNewLabel,
textEditingController: _nameInputController,
focusNode: _nameInputFocusNode,
errorText: errorText,
arrangeHorizontally: false,
isLabelHasColon: false,
labelStyle:
ThemeUtils.textStyleInter600().copyWith(
fontSize: 14,
height: 18 / 14,
color: Colors.black,
),
runSpacing: 16,
inputFieldMaxWidth: double.infinity,
onTextChange: (value) =>
_onLabelNameInputChanged(
appLocalizations,
value,
),
);
},
),
Padding(
padding: const EdgeInsets.only(top: 26, bottom: 16),
child: Text(
appLocalizations.chooseALabelColor,
style: ThemeUtils.textStyleInter600().copyWith(
fontSize: 14,
height: 18 / 14,
color: Colors.black,
),
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
),
Flexible(
child: Padding(
padding: isMobile
? EdgeInsetsDirectional.zero
: const EdgeInsetsDirectional.only(
start: 32,
end: 16,
),
child: const ColorsMapWidget(),
),
),
ModalListActionButtonWidget(
positiveLabel: appLocalizations.createLabel,
negativeLabel: appLocalizations.cancel,
padding: const EdgeInsets.symmetric(vertical: 25),
onPositiveAction: _onCreateNewLabel,
onNegativeAction: _onCloseModal,
),
],
),
),
),
),
],
),
DefaultCloseButtonWidget(
iconClose: _imagePaths.icCloseDialog,
onTapActionCallback: _onCloseModal,
),
],
),
);
bodyWidget = Center(child: bodyWidget);
if (PlatformInfo.isMobile) {
bodyWidget = GestureDetector(
onTap: _onCloseModal,
child: Scaffold(
backgroundColor: AppColor.blackAlpha20,
body: GestureDetector(
onTap: _clearInputFocus,
child: bodyWidget,
),
),
);
}
return bodyWidget;
});
}
void _onLabelNameInputChanged(
AppLocalizations appLocalizations, String value) {
_labelNameErrorText.value = _verifyLabelName(appLocalizations, value);
}
String? _verifyLabelName(AppLocalizations appLocalizations, String value) {
final result = _verifyNameInteractor.execute(
value,
_validators,
);
return result.fold(
(failure) => failure is VerifyNameFailure
? failure.getMessageLabelError(appLocalizations)
: null,
(_) => null,
);
}
List<Validator> get _validators => [
EmptyNameValidator(),
NameWithSpaceOnlyValidator(),
DuplicateNameValidator(_labelDisplayNameList),
SpecialCharacterValidator(),
];
void _clearInputFocus() {
_nameInputFocusNode.unfocus();
}
void _onCreateNewLabel() {
_clearInputFocus();
popBack();
}
void _onCloseModal() {
_clearInputFocus();
popBack();
}
@override
void dispose() {
_nameInputFocusNode.dispose();
_nameInputController.dispose();
_labelNameErrorText.dispose();
_labelDisplayNameList = [];
super.dispose();
}
}
@@ -364,6 +364,7 @@ abstract class BaseMailboxView extends GetWidget<MailboxController>
expandMode: labelListExpandMode, expandMode: labelListExpandMode,
countLabels: countLabels, countLabels: countLabels,
onToggleLabelListState: labelController.toggleLabelListState, onToggleLabelListState: labelController.toggleLabelListState,
onAddNewLabel: labelController.openCreateNewLabelModal,
); );
} else { } else {
return const SizedBox.shrink(); return const SizedBox.shrink();
@@ -48,4 +48,18 @@ extension ValicatorFailureExtension on VerifyNameFailure {
return ''; return '';
} }
} }
String getMessageLabelError(AppLocalizations appLocalizations) {
if (exception is EmptyNameException) {
return appLocalizations.this_field_cannot_be_blank;
} else if (exception is DuplicatedNameException) {
return appLocalizations.tagNameAlreadyExists;
} else if (exception is SpecialCharacterException) {
return appLocalizations.tagNameCannotContainSpecialCharacters;
} else if (exception is NameWithSpaceOnlyException) {
return appLocalizations.thisFieldCannotContainOnlySpaces;
} else {
return '';
}
}
} }
@@ -9,6 +9,7 @@ extension VerifyDisplayOverlayViewOnIframeExtension
isAppGridDialogDisplayed.isTrue || isAppGridDialogDisplayed.isTrue ||
isDrawerOpened.isTrue || isDrawerOpened.isTrue ||
isContextMenuOpened.isTrue || isContextMenuOpened.isTrue ||
isPopupMenuOpened.isTrue; isPopupMenuOpened.isTrue ||
labelController.isCreateNewLabelModalVisible.isTrue;
} }
} }
+48
View File
@@ -5195,5 +5195,53 @@
"type": "text", "type": "text",
"placeholders_order": [], "placeholders_order": [],
"placeholders": {} "placeholders": {}
},
"labelName": "Label name",
"@labelName": {
"type": "text",
"placeholders_order": [],
"placeholders": {}
},
"pleaseEnterNameYourNewLabel": "Please enter the name of your new label",
"@pleaseEnterNameYourNewLabel": {
"type": "text",
"placeholders_order": [],
"placeholders": {}
},
"chooseALabelColor": "Choose a label color",
"@chooseALabelColor": {
"type": "text",
"placeholders_order": [],
"placeholders": {}
},
"createLabel": "Create label",
"@createLabel": {
"type": "text",
"placeholders_order": [],
"placeholders": {}
},
"createANewLabel": "Create a new label",
"@createANewLabel": {
"type": "text",
"placeholders_order": [],
"placeholders": {}
},
"organizeYourInboxWithACustomCategory": "Organize your inbox with a custom category",
"@organizeYourInboxWithACustomCategory": {
"type": "text",
"placeholders_order": [],
"placeholders": {}
},
"tagNameCannotContainSpecialCharacters": "Tag name cannot contain special characters",
"@tagNameCannotContainSpecialCharacters": {
"type": "text",
"placeholders_order": [],
"placeholders": {}
},
"tagNameAlreadyExists": "A tag with this name already exists. Please choose a different name.",
"@tagNameAlreadyExists": {
"type": "text",
"placeholders_order": [],
"placeholders": {}
} }
} }
@@ -5513,4 +5513,60 @@ class AppLocalizations {
name: 'newLabel', name: 'newLabel',
); );
} }
String get labelName {
return Intl.message(
'Label name',
name: 'labelName',
);
}
String get pleaseEnterNameYourNewLabel {
return Intl.message(
'Please enter the name of your new label',
name: 'pleaseEnterNameYourNewLabel',
);
}
String get chooseALabelColor {
return Intl.message(
'Choose a label color',
name: 'chooseALabelColor',
);
}
String get createLabel {
return Intl.message(
'Create label',
name: 'createLabel',
);
}
String get createANewLabel {
return Intl.message(
'Create a new label',
name: 'createANewLabel',
);
}
String get organizeYourInboxWithACustomCategory {
return Intl.message(
'Organize your inbox with a custom category',
name: 'organizeYourInboxWithACustomCategory',
);
}
String get tagNameCannotContainSpecialCharacters {
return Intl.message(
'Tag name cannot contain special characters',
name: 'tagNameCannotContainSpecialCharacters',
);
}
String get tagNameAlreadyExists {
return Intl.message(
'A tag with this name already exists. Please choose a different name.',
name: 'tagNameAlreadyExists',
);
}
} }