Line data Source code
1 : // ignore_for_file: prefer-first
2 :
3 : import 'package:flutter/material.dart';
4 : import 'package:folly_fields/util/date_time_extension.dart';
5 :
6 : ///
7 : ///
8 : ///
9 : class FollyUtils {
10 : ///
11 : ///
12 : ///
13 : // TODO(edufolly): Remove in version 1.0.0.
14 0 : @Deprecated('Prefer to use DateTime.time. '
15 : 'This class will be removed in version 1.0.0.')
16 : static TimeOfDay? getTime(DateTime? dateTime) =>
17 0 : dateTime == null ? null : TimeOfDay.fromDateTime(dateTime);
18 :
19 : ///
20 : ///
21 : ///
22 : // TODO(edufolly): Remove in version 1.0.0.
23 0 : @Deprecated('Prefer to use DateTime.mergeStartSeconds '
24 : 'This class will be removed in version 1.0.0.')
25 : static DateTime? dateTimeMergeStart({
26 : required DateTime? date,
27 : int second = 0,
28 : int millisecond = 0,
29 : int microsecond = 0,
30 : }) =>
31 0 : dateMergeStart(
32 : date: date,
33 0 : time: getTime(date),
34 : second: second,
35 : millisecond: millisecond,
36 : microsecond: microsecond,
37 : );
38 :
39 : ///
40 : ///
41 : ///
42 : // TODO(edufolly): Remove in version 1.0.0.
43 0 : @Deprecated('Prefer to use DateTime.mergeStart '
44 : 'This class will be removed in version 1.0.0.')
45 : static DateTime? dateMergeStart({
46 : required DateTime? date,
47 : TimeOfDay? time,
48 : int second = 0,
49 : int millisecond = 0,
50 : int microsecond = 0,
51 : }) {
52 : if (date == null) {
53 : return null;
54 : }
55 :
56 : time ??= const TimeOfDay(hour: 0, minute: 0);
57 :
58 0 : return DateTime(
59 0 : date.year,
60 0 : date.month,
61 0 : date.day,
62 0 : time.hour,
63 0 : time.minute,
64 : second,
65 : millisecond,
66 : microsecond,
67 : );
68 : }
69 :
70 : ///
71 : ///
72 : ///
73 : // TODO(edufolly): Remove in version 1.0.0.
74 0 : @Deprecated('Prefer to use DateTime.mergeEndSeconds '
75 : 'This class will be removed in version 1.0.0.')
76 : static DateTime? dateTimeMergeEnd({
77 : required DateTime? date,
78 : int second = 59,
79 : int millisecond = 999,
80 : int microsecond = 0,
81 : }) =>
82 0 : dateMergeEnd(
83 : date: date,
84 0 : time: getTime(date),
85 : second: second,
86 : millisecond: millisecond,
87 : microsecond: microsecond,
88 : );
89 :
90 : ///
91 : ///
92 : ///
93 : // TODO(edufolly): Remove in version 1.0.0.
94 0 : @Deprecated('Prefer to use DateTime.mergeEnd '
95 : 'This class will be removed in version 1.0.0.')
96 : static DateTime? dateMergeEnd({
97 : required DateTime? date,
98 : TimeOfDay? time,
99 : int second = 59,
100 : int millisecond = 999,
101 : int microsecond = 0,
102 : }) {
103 : if (date == null) {
104 : return null;
105 : }
106 :
107 : time ??= const TimeOfDay(hour: 23, minute: 59);
108 :
109 0 : return DateTime(
110 0 : date.year,
111 0 : date.month,
112 0 : date.day,
113 0 : time.hour,
114 0 : time.minute,
115 : second,
116 : millisecond,
117 : microsecond,
118 : );
119 : }
120 :
121 : ///
122 : ///
123 : ///
124 1 : static String? validDate(String value) {
125 1 : if (value.isEmpty) {
126 : return 'Informe uma data.';
127 : }
128 :
129 1 : List<String> parts = value.split('/');
130 :
131 2 : if (parts.length != 3) {
132 : return 'Data inválida.';
133 : }
134 :
135 3 : if (parts[2].length != 4) {
136 : return 'Ano inválido.';
137 : }
138 :
139 2 : int? year = int.tryParse(parts[2]);
140 : if (year == null) {
141 : return 'Ano inválido.';
142 : }
143 :
144 2 : int? month = int.tryParse(parts[1]);
145 2 : if (month == null || month < 1 || month > 12) {
146 : return 'Mês inválido.';
147 : }
148 :
149 2 : int? day = int.tryParse(parts[0]);
150 4 : if (day == null || day < 1 || day > DateTime(year, month).daysInMonth) {
151 : return 'Dia inválido.';
152 : }
153 :
154 : return null;
155 : }
156 :
157 : ///
158 : ///
159 : ///
160 : // TODO(edufolly): Remove in version 1.0.0.
161 0 : @Deprecated('Prefer to use DateTime.daysInMonth '
162 : 'This class will be removed in version 1.0.0.')
163 : static int getDaysInMonth(int year, int month) {
164 0 : if (month == DateTime.february) {
165 0 : return (year % 4 == 0) && (year % 100 != 0) || (year % 400 == 0)
166 : ? 29
167 : : 28;
168 : }
169 0 : List<int> days = <int>[31, -1, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
170 :
171 0 : return days[month - 1];
172 : }
173 :
174 : ///
175 : ///
176 : ///
177 1 : static String? validTime(String value) {
178 2 : if (value.length != 5) {
179 : return 'Informe uma hora.';
180 : }
181 :
182 1 : List<String> parts = value.split(':');
183 :
184 2 : if (parts.length != 2) {
185 : return 'Hora inválida.';
186 : }
187 :
188 2 : int? hour = int.tryParse(parts[0]);
189 :
190 2 : if (hour == null || hour < 0 || hour > 23) {
191 : return 'Horas inválidas.';
192 : }
193 :
194 2 : int? minute = int.tryParse(parts[1]);
195 :
196 2 : if (minute == null || minute < 0 || minute > 59) {
197 : return 'Minutos inválidos.';
198 : }
199 :
200 : return null;
201 : }
202 :
203 : ///
204 : ///
205 : ///
206 1 : static bool isPascalCase(String value) =>
207 1 : !(value.isEmpty ||
208 2 : value.contains(RegExp('[^a-zA-Z0-9]+')) ||
209 2 : value.startsWith(RegExp('[0-9]+'))) &&
210 4 : value[0].toUpperCase() == value[0];
211 :
212 : ///
213 : ///
214 : ///
215 1 : static bool isCamelCase(String value) =>
216 1 : !(value.isEmpty ||
217 2 : value.contains(RegExp('[^a-zA-Z0-9]+')) ||
218 2 : value.startsWith(RegExp('[0-9]+'))) &&
219 4 : value[0].toLowerCase() == value[0];
220 :
221 : ///
222 : ///
223 : ///
224 2 : static bool isSnakeCase(String value) => !(value.isEmpty ||
225 2 : value.contains(RegExp('[^_a-z0-9]+')) ||
226 2 : value.startsWith(RegExp('[0-9]+')));
227 :
228 : ///
229 : ///
230 : ///
231 1 : static String camel2Snake(String camel, {bool internal = false}) =>
232 1 : internal || isCamelCase(camel)
233 1 : ? camel.splitMapJoin(
234 1 : RegExp('[A-Z]'),
235 4 : onMatch: (Match m) => '_${m.group(0)!.toLowerCase()}',
236 1 : onNonMatch: (String n) => n,
237 : )
238 : : '';
239 :
240 : ///
241 : ///
242 : ///
243 2 : static String snake2Camel(String snake) => isSnakeCase(snake)
244 2 : ? pascal2Camel(snake2Pascal(snake, internal: true), internal: true)
245 : : '';
246 :
247 : ///
248 : ///
249 : ///
250 1 : static String pascal2Camel(String pascal, {bool internal = false}) =>
251 1 : internal || isPascalCase(pascal)
252 4 : ? pascal[0].toLowerCase() + pascal.substring(1)
253 : : '';
254 :
255 : ///
256 : ///
257 : ///
258 1 : static String camel2Pascal(String camel) =>
259 5 : isCamelCase(camel) ? camel[0].toUpperCase() + camel.substring(1) : '';
260 :
261 : ///
262 : ///
263 : ///
264 2 : static String pascal2Snake(String pascal) => isPascalCase(pascal)
265 2 : ? camel2Snake(pascal, internal: true).substring(1)
266 : : '';
267 :
268 : ///
269 : ///
270 : ///
271 1 : static String snake2Pascal(String snake, {bool internal = false}) =>
272 1 : internal || isSnakeCase(snake)
273 2 : ? snake.toLowerCase().splitMapJoin(
274 1 : RegExp('_'),
275 1 : onMatch: (Match m) => '',
276 1 : onNonMatch: (String n) =>
277 4 : n.substring(0, 1).toUpperCase() + n.substring(1),
278 : )
279 : : '';
280 :
281 : ///
282 : ///
283 : ///
284 1 : static Color textColorByLuminance(
285 : Color color, {
286 : Color darkColor = Colors.black,
287 : Color lightColor = Colors.white,
288 : double redFactor = 0.299,
289 : double greenFactor = 0.587,
290 : double blueFactor = 0.114,
291 : double threshold = 186,
292 : }) =>
293 3 : color.red * redFactor +
294 3 : color.green * greenFactor +
295 3 : color.blue * blueFactor >
296 : threshold
297 : ? darkColor
298 : : lightColor;
299 :
300 : ///
301 : ///
302 : ///
303 1 : static MaterialColor? createMaterialColor({
304 : int? intColor,
305 : Color? color,
306 : }) {
307 : if (intColor != null) {
308 1 : color = Color(intColor);
309 : }
310 :
311 : if (color == null) {
312 : return null;
313 : }
314 :
315 1 : return MaterialColor(
316 1 : color.value,
317 1 : <int, Color>{
318 : 50: color,
319 : 100: color,
320 : 200: color,
321 : 300: color,
322 : 400: color,
323 : 500: color,
324 : 600: color,
325 : 700: color,
326 : 800: color,
327 : 900: color,
328 : },
329 : );
330 : }
331 : }
|