Skip to content

Commit 5c59ec3

Browse files
authored
Merge pull request #120 from Onix-Systems/feature/class-name-validation
feat(Validation): Add class name validation
2 parents db93296 + 012fbfa commit 5c59ec3

File tree

8 files changed

+74
-21
lines changed

8 files changed

+74
-21
lines changed

lib/app/app_consts.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,5 +46,7 @@ class AppConsts {
4646

4747
static RegExp digitsAndLatinWithSpaceOnly = RegExp(r'[a-zA-Z\d ]');
4848

49+
static RegExp digitsAndLatinLetters = RegExp('[a-zA-Z0-9]');
50+
4951
const AppConsts._();
5052
}

lib/app/localization/generated/intl/messages_en.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,8 @@ class MessageLookup extends MessageLookupByLibrary {
215215
"Screen with such name already exists"),
216216
"screenAlreadyExistsTitle":
217217
MessageLookupByLibrary.simpleMessage("Already exists"),
218+
"screenClassNameHelperText": MessageLookupByLibrary.simpleMessage(
219+
"The first character in the class name must be a letter"),
218220
"screenName": MessageLookupByLibrary.simpleMessage("Screen name"),
219221
"screens": MessageLookupByLibrary.simpleMessage("Screens"),
220222
"selectProjectFolder":

lib/app/localization/generated/intl/messages_uk.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,8 @@ class MessageLookup extends MessageLookupByLibrary {
221221
"Екран з такою назвою вже існує"),
222222
"screenAlreadyExistsTitle":
223223
MessageLookupByLibrary.simpleMessage("Вже є"),
224+
"screenClassNameHelperText": MessageLookupByLibrary.simpleMessage(
225+
"Перший символ у назві класу має бути літерою"),
224226
"screenName": MessageLookupByLibrary.simpleMessage("Назва екрану"),
225227
"screens": MessageLookupByLibrary.simpleMessage("Екрани"),
226228
"selectProjectFolder":

lib/app/localization/generated/l10n.dart

Lines changed: 10 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lib/app/localization/l10n/intl_en.arb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,5 +148,6 @@
148148
"projectNameHelperText": "Project name must be fully lowercase, with underscores to separate words. Also make sure that the name is a valid Dart identifier - it does not start with numbers, is not a reserved word, and does not start or end with an underscore.",
149149
"organizationNameHelperText": "A digit cannot be the first character in a package segment. The package must have at least one '.’ separator. Multiple '.' characters are not allowed in a row.",
150150
"changeStateManagerError": "Change state manager warning",
151-
"changeStateManagerErrorContent": "Changing state manager will change ... to {variant}. Are you sure you want to continue?"
151+
"changeStateManagerErrorContent": "Changing state manager will change ... to {variant}. Are you sure you want to continue?",
152+
"screenClassNameHelperText": "The first character in the class name must be a letter"
152153
}

lib/app/localization/l10n/intl_uk.arb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,5 +148,6 @@
148148
"projectNameHelperText": "Назва проєкту має бути повністю маленькими літерами, з підкресленнями, щоб відокремити слова. Також переконайтеся, що назва є дійсним ідентифікатором Dart - вона не починається з цифр, не є зарезервованим словом, не починається і не закінчується символом підкреслення",
149149
"organizationNameHelperText": "Цифра не може бути першим символом у сегменті пакету. У пакеті повинен бути хоча б один роздільник '.'. Кілька символів '.' підряд не допускаються.",
150150
"changeStateManagerError": "Попередження зміни стейт менеджера",
151-
"changeStateManagerErrorContent": "Зміна стейт мененджера змінить ... на {variant}. Дійсно бажаєте продовжити?"
151+
"changeStateManagerErrorContent": "Зміна стейт мененджера змінить ... на {variant}. Дійсно бажаєте продовжити?",
152+
"screenClassNameHelperText": "Перший символ у назві класу має бути літерою"
152153
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import 'package:flutter/services.dart';
2+
3+
class FirstCharacterNotDigitFormatter extends TextInputFormatter {
4+
const FirstCharacterNotDigitFormatter();
5+
6+
@override
7+
TextEditingValue formatEditUpdate(
8+
TextEditingValue oldValue,
9+
TextEditingValue newValue,
10+
) {
11+
if (newValue.text.isNotEmpty &&
12+
newValue.text[0].contains(RegExp('[0-9]'))) {
13+
return oldValue;
14+
}
15+
return newValue;
16+
}
17+
}

lib/presentation/screen/screens_screen/widgets/add_screen_dialog.dart

Lines changed: 37 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
import 'package:flutter/cupertino.dart';
22
import 'package:flutter/services.dart';
33
import 'package:gap/gap.dart';
4+
import 'package:onix_flutter_bricks/app/app_consts.dart';
45
import 'package:onix_flutter_bricks/app/localization/generated/l10n.dart';
6+
import 'package:onix_flutter_bricks/app/util/formatters/first_character_is_not_digit_formatter.dart';
57
import 'package:onix_flutter_bricks/domain/entity/screen/screen.dart';
68
import 'package:onix_flutter_bricks/domain/entity/state_management/state_management_variant.dart';
79
import 'package:onix_flutter_bricks/presentation/style/theme/theme_extension/ext.dart';
810
import 'package:onix_flutter_bricks/presentation/widget/inputs/labeled_checkbox.dart';
11+
import 'package:onix_flutter_bricks/presentation/widget/tooltip_wrapper.dart';
912
import 'package:onix_flutter_bricks/util/extension/swagger_extensions.dart';
1013
import 'package:recase/recase.dart';
1114

@@ -77,20 +80,33 @@ class _AddScreenDialogState extends State<AddScreenDialog> {
7780
content: Column(
7881
crossAxisAlignment: CrossAxisAlignment.start,
7982
children: [
80-
CupertinoTextField(
81-
controller: _screenNameController,
82-
focusNode: _textFieldFocusNode,
83-
style: context.appTextStyles.fs18,
84-
onTap: () {
85-
setState(() {
86-
_currentFocusNode = _textFieldFocusNode;
87-
_textFieldFocusNode.requestFocus();
88-
});
89-
},
90-
onSubmitted: (_) => _onOk(context),
91-
placeholder: S.of(context).screenName,
92-
inputFormatters: [
93-
FilteringTextInputFormatter.allow(RegExp('[a-zA-Z0-9]')),
83+
Row(
84+
children: [
85+
Expanded(
86+
child: CupertinoTextField(
87+
controller: _screenNameController,
88+
focusNode: _textFieldFocusNode,
89+
style: context.appTextStyles.fs18,
90+
onTap: () {
91+
setState(() {
92+
_currentFocusNode = _textFieldFocusNode;
93+
_textFieldFocusNode.requestFocus();
94+
});
95+
},
96+
onSubmitted: (_) => _onOk(context),
97+
placeholder: S.of(context).screenName,
98+
inputFormatters: [
99+
const FirstCharacterNotDigitFormatter(),
100+
FilteringTextInputFormatter.allow(
101+
AppConsts.digitsAndLatinLetters,
102+
),
103+
],
104+
),
105+
),
106+
const SizedBox(width: 12),
107+
TooltipWrapper(
108+
message: S.of(context).screenClassNameHelperText,
109+
),
94110
],
95111
),
96112
const Gap(15),
@@ -133,18 +149,20 @@ class _AddScreenDialogState extends State<AddScreenDialog> {
133149
);
134150
}
135151

136-
Future<void> _onOk(BuildContext context) async {
152+
void _onOk(BuildContext context) {
137153
if (_screenNameController.text.isNotEmpty) {
138154
var screenName = _screenNameController.text.pascalCase;
139155

140156
while (screenName.endsWith('Screen')) {
141157
screenName = screenName.replaceLast('Screen', '');
142158
}
143159

144-
if (widget.screen != null) {
145-
widget.screen!.name = screenName;
146-
widget.screen!.stateVariant = _stateManagement;
147-
Navigator.pop(context, widget.screen);
160+
final screen = widget.screen;
161+
if (screen != null) {
162+
screen
163+
..name = screenName
164+
..stateVariant = _stateManagement;
165+
Navigator.pop(context, screen);
148166
} else {
149167
Navigator.pop(
150168
context,

0 commit comments

Comments
 (0)