Skip to content

Commit 7b556b8

Browse files
committed
Add fileSize
1 parent ea3c57b commit 7b556b8

File tree

5 files changed

+102
-2
lines changed

5 files changed

+102
-2
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,10 @@
88
* Add uppercase
99
* Add lowercase
1010
* Add file extension
11+
* Add max file size
1112
* Add notMatch
13+
* Add range
14+
* Add date range
1215

1316
## 10.0.2
1417
* Reland generated l10n files

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ Available built-in validators include:
5454
- `FormBuilderValidators.creditCardCVC()` - requires the field's value to be a valid credit card CVC number.
5555
- `FormBuilderValidators.colorCode()` - requires the field's value to be a valid color code.
5656
- `FormBuilderValidators.date()` - requires the field's value to be a valid date string.
57+
- `FormBuilderValidators.dateRange()` - requires the field's value to be a within a date range.
5758
- `FormBuilderValidators.email()` - requires the field's value to be a valid email address.
5859
- `FormBuilderValidators.equal()` - requires the field's value to be equal to the provided object.
5960
- `FormBuilderValidators.integer()` - requires the field's value to be an integer.
@@ -73,6 +74,7 @@ Available built-in validators include:
7374
- `FormBuilderValidators.uppercase()` - requires the field's value to be uppercase.
7475
- `FormBuilderValidators.lowercase()` - requires the field's value to be lowercase.
7576
- `FormBuilderValidators.fileExtension()` - requires the field's value to a valid file extension.
77+
- `FormBuilderValidators.fileSize()` - requires the field's to be less than the max size.
7678

7779
### Supported languages
7880

lib/l10n/intl_en.arb

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,5 +25,7 @@
2525
"colorCodeErrorText": "Value should be a valid {colorCode} color code.",
2626
"uppercaseErrorText": "Value must be uppercase.",
2727
"lowercaseErrorText": "Value must be lowercase.",
28-
"fileExtensionErrorText": "File extension must be {extensions}"
28+
"fileExtensionErrorText": "File extension must be {extensions}",
29+
"fileSizeErrorText": "File size must be less than {maxSize} while it is {fileSize}",
30+
"dateRangeErrorText": "Date must be in range {min} - {max}"
2931
}

lib/src/form_builder_validators.dart

Lines changed: 81 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -356,14 +356,54 @@ class FormBuilderValidators {
356356
: null;
357357

358358
/// [FormFieldValidator] that requires the field's value to be a valid date string.
359-
static FormFieldValidator<String> dateString({
359+
static FormFieldValidator<String> date({
360360
String? errorText,
361361
}) =>
362362
(valueCandidate) => true == valueCandidate?.isNotEmpty &&
363363
!isDate(valueCandidate!)
364364
? errorText ?? FormBuilderLocalizations.current.dateStringErrorText
365365
: null;
366366

367+
/// [FormFieldValidator] that requires the field's value to be a date within a certain range.
368+
static FormFieldValidator<String> dateRange({
369+
required String minDate,
370+
required String maxDate,
371+
String? errorText,
372+
}) {
373+
return compose<String>(
374+
[
375+
minDate.isNotEmpty
376+
? date(errorText: errorText)
377+
: (valueCandidate) => null,
378+
maxDate.isNotEmpty
379+
? date(errorText: errorText)
380+
: (valueCandidate) => null,
381+
(valueCandidate) {
382+
if (valueCandidate == null || valueCandidate.isEmpty) {
383+
return null;
384+
}
385+
386+
final minDateTime = DateTime.tryParse(minDate);
387+
final maxDateTime = DateTime.tryParse(maxDate);
388+
final valueDateTime = DateTime.tryParse(valueCandidate);
389+
390+
if (minDateTime != null &&
391+
valueDateTime!.isBefore(minDateTime) &&
392+
maxDateTime != null &&
393+
valueDateTime.isAfter(maxDateTime)) {
394+
return errorText ??
395+
FormBuilderLocalizations.current.dateRangeErrorText(
396+
minDate,
397+
maxDate,
398+
);
399+
}
400+
401+
return null;
402+
},
403+
],
404+
);
405+
}
406+
367407
/// [FormFieldValidator] that requires the field's value to be a valid phone number.
368408
static FormFieldValidator<String> phoneNumber({
369409
String? errorText,
@@ -404,6 +444,7 @@ class FormBuilderValidators {
404444
? errorText ?? FormBuilderLocalizations.current.lowercaseErrorText
405445
: null;
406446

447+
/// [FormFieldValidator] that requires the field's value to be a valid file extension.
407448
static FormFieldValidator<File> fileExtension({
408449
required List<String> allowedExtensions,
409450
String? errorText,
@@ -416,4 +457,43 @@ class FormBuilderValidators {
416457
FormBuilderLocalizations.current
417458
.fileExtensionErrorText(allowedExtensions.join(', '))
418459
: null;
460+
461+
/// [FormFieldValidator] that restricts the size of an file to be less than or equal to the provided maximum size.
462+
/// * [maxSize] is the maximum size in bytes.
463+
static FormFieldValidator<File> fileSize({
464+
required int maxSize,
465+
String? errorText,
466+
}) =>
467+
(File? valueCandidate) => valueCandidate == null
468+
? null
469+
: valueCandidate.existsSync() && valueCandidate.lengthSync() > maxSize
470+
? errorText ??
471+
FormBuilderLocalizations.current.fileSizeErrorText(
472+
formatBytes(valueCandidate.lengthSync()),
473+
formatBytes(maxSize),
474+
)
475+
: null;
476+
477+
/// [FormFieldValidator] that applies another validator conditionally.
478+
static FormFieldValidator<T> conditional<T>(
479+
bool Function(T value) condition,
480+
FormFieldValidator<T> validator,
481+
) =>
482+
(T? valueCandidate) =>
483+
condition(valueCandidate as T) ? validator(valueCandidate) : null;
484+
485+
/// [FormFieldValidator] that requires the field's value to be within a certain range.
486+
static FormFieldValidator<T> range<T>(
487+
num minValue,
488+
num maxValue, {
489+
bool inclusive = true,
490+
String? errorText,
491+
}) {
492+
return compose<T>(
493+
[
494+
min(minValue, inclusive: inclusive, errorText: errorText),
495+
max(maxValue, inclusive: inclusive, errorText: errorText),
496+
],
497+
);
498+
}
419499
}

lib/src/utils/helpers.dart

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,16 @@ String fileExtensionFromPath(String path) {
2020
final splitter = path.split('.');
2121
return splitter.length > 1 ? splitter.last : "";
2222
}
23+
24+
/// Helper function to format bytes into a human-readable string (e.g., KB, MB, GB).
25+
String formatBytes(int bytes) {
26+
const suffixes = ['B', 'KB', 'MB', 'GB', 'TB'];
27+
var i = 0;
28+
double size = bytes.toDouble();
29+
while (size > 1024 && i < suffixes.length - 1) {
30+
size /= 1024;
31+
i++;
32+
}
33+
// Truncate to 1 decimal place
34+
return '${size.toStringAsFixed(1)}${suffixes[i]}';
35+
}

0 commit comments

Comments
 (0)