102 lines
2.3 KiB
Dart
102 lines
2.3 KiB
Dart
import '../../models/ignis_group.dart';
|
||
|
||
final RegExp _groupIdAllowedPattern = RegExp(r'^[a-z0-9][a-z0-9_-]*$');
|
||
final RegExp _groupIdSanitizePattern = RegExp(r'[^a-z0-9_-]+');
|
||
final RegExp _dashCollapsePattern = RegExp(r'[-_]{2,}');
|
||
|
||
const Map<String, String> _transliterationMap = {
|
||
'а': 'a',
|
||
'б': 'b',
|
||
'в': 'v',
|
||
'г': 'g',
|
||
'д': 'd',
|
||
'е': 'e',
|
||
'ё': 'e',
|
||
'ж': 'zh',
|
||
'з': 'z',
|
||
'и': 'i',
|
||
'й': 'y',
|
||
'к': 'k',
|
||
'л': 'l',
|
||
'м': 'm',
|
||
'н': 'n',
|
||
'о': 'o',
|
||
'п': 'p',
|
||
'р': 'r',
|
||
'с': 's',
|
||
'т': 't',
|
||
'у': 'u',
|
||
'ф': 'f',
|
||
'х': 'h',
|
||
'ц': 'ts',
|
||
'ч': 'ch',
|
||
'ш': 'sh',
|
||
'щ': 'sch',
|
||
'ъ': '',
|
||
'ы': 'y',
|
||
'ь': '',
|
||
'э': 'e',
|
||
'ю': 'yu',
|
||
'я': 'ya',
|
||
};
|
||
|
||
String slugifyGroupId(String input) {
|
||
final lower = input.trim().toLowerCase();
|
||
final buffer = StringBuffer();
|
||
for (final rune in lower.runes) {
|
||
final char = String.fromCharCode(rune);
|
||
buffer.write(_transliterationMap[char] ?? char);
|
||
}
|
||
|
||
var value = buffer
|
||
.toString()
|
||
.replaceAll(RegExp(r'\s+'), '-')
|
||
.replaceAll(_groupIdSanitizePattern, '-')
|
||
.replaceAll(_dashCollapsePattern, '-')
|
||
.replaceAll(RegExp(r'^[-_]+|[-_]+$'), '');
|
||
|
||
if (value.length > 32) {
|
||
value = value.substring(0, 32).replaceAll(RegExp(r'[-_]+$'), '');
|
||
}
|
||
|
||
return value;
|
||
}
|
||
|
||
String? validateGroupId(String value, Iterable<IgnisGroup> existingGroups) {
|
||
final normalized = value.trim().toLowerCase();
|
||
if (normalized.isEmpty) {
|
||
return 'Укажите ID группы';
|
||
}
|
||
if (!_groupIdAllowedPattern.hasMatch(normalized)) {
|
||
return 'Только латиница, цифры, "-" и "_"';
|
||
}
|
||
final alreadyExists = existingGroups.any((group) => group.id == normalized);
|
||
if (alreadyExists) {
|
||
return 'Группа с таким ID уже существует';
|
||
}
|
||
return null;
|
||
}
|
||
|
||
String? validateGroupName(String value) {
|
||
if (value.trim().isEmpty) {
|
||
return 'Укажите название группы';
|
||
}
|
||
return null;
|
||
}
|
||
|
||
List<IgnisGroup> findGroupMembershipConflicts(
|
||
Set<String> selectedDeviceIds,
|
||
Iterable<IgnisGroup> existingGroups,
|
||
) {
|
||
if (selectedDeviceIds.isEmpty) {
|
||
return const [];
|
||
}
|
||
|
||
return existingGroups
|
||
.where(
|
||
(group) =>
|
||
group.macs.any((deviceId) => selectedDeviceIds.contains(deviceId)),
|
||
)
|
||
.toList();
|
||
}
|