417 lines
13 KiB
Dart
417 lines
13 KiB
Dart
import 'dart:convert';
|
|
import 'dart:io';
|
|
import 'dart:math';
|
|
|
|
import 'package:baseproject/core/common/message.dart';
|
|
import 'package:baseproject/core/language/app_localizations.dart';
|
|
import 'package:baseproject/features/presentation/app/view/app.dart';
|
|
import 'package:file_picker/file_picker.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter_datetime_picker_plus/flutter_datetime_picker_plus.dart';
|
|
import 'package:intl/intl.dart';
|
|
import 'package:url_launcher/url_launcher.dart';
|
|
|
|
import 'package:path/path.dart' as p;
|
|
|
|
class Utils {
|
|
static int dateDiffToSeconds(DateTime date1, DateTime date2) {
|
|
return date1.difference(date2).inSeconds;
|
|
}
|
|
|
|
static int dateDiffToDays(DateTime date1, DateTime date2) {
|
|
return date1.difference(date2).inDays;
|
|
}
|
|
|
|
static int dateDiffToYears(DateTime date1, DateTime date2) {
|
|
return date1.year - date2.year;
|
|
}
|
|
|
|
static Map<String, dynamic> convertObjectToMap(Object object) {
|
|
final Map<String, dynamic> temp = jsonDecode(jsonEncode(object)) as Map<String, dynamic>;
|
|
// print(temp);
|
|
return temp;
|
|
}
|
|
|
|
static int getCharacterCode(String character) {
|
|
final List<int> codeUnits = character.codeUnits;
|
|
int temp = 65;
|
|
if (codeUnits.isNotEmpty) temp = codeUnits[0];
|
|
return temp;
|
|
}
|
|
|
|
static String thumbnailImage(String url, {double? width, double? height, String mode = 'crop'}) {
|
|
// if (url.startsWith("http")) return url;
|
|
// if (url.contains(mode)) return url;
|
|
// // ignore: parameter_assignments
|
|
// if (width == double.infinity || width == null) width = 0;
|
|
|
|
// // ignore: parameter_assignments
|
|
// if (height == double.infinity || height == null) height = 0;
|
|
|
|
// if (width == 0 && height == 0) return url;
|
|
|
|
// final List<StorageServer>? storageServer = GetIt.I<AppSettings>().getAppSettings.storageServers;
|
|
// if (storageServer != null) {
|
|
// final Iterable<String> allStorage = storageServer.map((StorageServer e) => e.publicDomain);
|
|
// for (String item in allStorage) {
|
|
// if (url.toLowerCase().contains(item.toLowerCase())) {
|
|
// if (item[item.length - 1] != '/') item = item + "/";
|
|
// // ignore: parameter_assignments
|
|
// url = url.replaceAll(item.toLowerCase(),
|
|
// '$item${(width != null && width > 0) ? width.toInt() * 2 : 0}x${(height != null && height > 0) ? height.toInt() * 2 : 0}/${mode}/');
|
|
// }
|
|
// }
|
|
// }
|
|
|
|
return url;
|
|
}
|
|
|
|
static T enumFromString<T>(Iterable<T> values, String value) {
|
|
// ignore: always_specify_types
|
|
return values.firstWhere((type) => type.toString().split(".").last == value, orElse: () => values.first);
|
|
}
|
|
|
|
LocaleType getLocaleType() {
|
|
return Utils.enumFromString<LocaleType>(
|
|
LocaleType.values, AppLocalizations.of(navigatorKey!.currentState!.context)!.locale.languageCode);
|
|
}
|
|
|
|
Future<DateTime?> onShowDatePicker(
|
|
{required BuildContext context,
|
|
DateTime? currentValue,
|
|
DateTime? firstDate,
|
|
DateTime? maxDate,
|
|
bool isShowAfter = true}) {
|
|
final DateTime _currentValue = currentValue != null && currentValue.year > 0 ? currentValue : DateTime.now();
|
|
final DateTime _minDate = !isShowAfter ? DateTime.now() : firstDate ?? DateTime(1900);
|
|
if (Platform.isIOS) {
|
|
return DatePicker.showDatePicker(
|
|
context,
|
|
minTime: _minDate,
|
|
maxTime: maxDate ?? DateTime(2100),
|
|
currentTime: _currentValue,
|
|
locale: getLocaleType(),
|
|
);
|
|
}
|
|
|
|
return showDatePicker(
|
|
context: context,
|
|
initialDate: _currentValue,
|
|
firstDate: _minDate,
|
|
lastDate: maxDate ?? DateTime(2100),
|
|
currentDate: currentValue,
|
|
);
|
|
}
|
|
|
|
Future<TimeOfDay?> onShowTimePicker(BuildContext context, DateTime? currentValue, {bool isShowSecond = false}) async {
|
|
final DateTime? _currentValue = (currentValue?.hour ?? 0) > 0 ? currentValue : DateTime.now();
|
|
if (Platform.isIOS) {
|
|
final DateTime? result = await DatePicker.showTimePicker(
|
|
context,
|
|
showSecondsColumn: isShowSecond,
|
|
currentTime: _currentValue,
|
|
locale: getLocaleType(),
|
|
);
|
|
|
|
if (result == null) return null;
|
|
return TimeOfDay.fromDateTime(result);
|
|
}
|
|
|
|
final TimeOfDay? timePickerResult = await showTimePicker(
|
|
context: context,
|
|
initialTime: currentValue != null ? TimeOfDay.fromDateTime(currentValue) : TimeOfDay.fromDateTime(DateTime.now()),
|
|
);
|
|
return timePickerResult ?? (currentValue != null ? TimeOfDay.fromDateTime(currentValue) : null);
|
|
}
|
|
|
|
static T? getPropertyValueByName<T>(Object? object, String propertyName) {
|
|
if (object == null) return null;
|
|
try {
|
|
final Map<String, dynamic> temp = convertObjectToMap(object);
|
|
return temp[propertyName] as T;
|
|
} catch (ex) {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
static String getExtension(String path) {
|
|
return p.extension(path).replaceAll(".", "");
|
|
}
|
|
|
|
static String getExtensionWithDot(String path) {
|
|
return p.extension(path);
|
|
}
|
|
|
|
static String getFileName(String path) {
|
|
return p.basename(path);
|
|
}
|
|
|
|
static String getFileNameWithoutExtension(String path) {
|
|
return p.basenameWithoutExtension(path);
|
|
}
|
|
|
|
static String getFileNameFromTime(String extension) {
|
|
return DateTime.now().millisecondsSinceEpoch.toString() + "." + extension;
|
|
}
|
|
|
|
static T? getRouterObject<T>(Object? arguments, {int index = -1}) {
|
|
if (arguments == null) return null;
|
|
if (index >= 0) {
|
|
final List<dynamic> args = arguments as List<dynamic>;
|
|
if (index < args.length) {
|
|
return (args[index]) != null ? args[index] as T : null;
|
|
} else {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
return arguments as T;
|
|
}
|
|
|
|
static String? getRouterObjectString(Object? arguments, {int index = -1}) {
|
|
if (arguments == null) return null;
|
|
if (index >= 0) {
|
|
final List<dynamic> args = arguments as List<dynamic>;
|
|
if (index < args.length) {
|
|
return (args[index]) != null ? args[index] as String : null;
|
|
} else {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
return arguments as String?;
|
|
}
|
|
|
|
static Map<String, dynamic> base64ToMap(String b64) {
|
|
return json.decode(base64Decode(b64));
|
|
}
|
|
|
|
static String base64Decode(String b64) {
|
|
final String foo = b64.split('.')[0];
|
|
final List<int> res = base64.decode(base64.normalize(foo));
|
|
return utf8.decode(res);
|
|
}
|
|
|
|
Future<FilePickerResult?> openChooseFiles({
|
|
FileType type = FileType.any,
|
|
List<String>? allowedExtensions = const <String>["doc", "pdf", "mp4", "mp3"],
|
|
Function(FilePickerStatus)? onFileLoading,
|
|
bool allowCompression = true,
|
|
bool allowMultiple = false,
|
|
bool withData = false,
|
|
bool withReadStream = false,
|
|
}) async {
|
|
// final AppSettings _appSettings = GetIt.I<AppSettings>();
|
|
final FilePickerResult? result = await FilePicker.platform.pickFiles(
|
|
type: FileType.custom,
|
|
allowedExtensions: allowedExtensions,
|
|
allowMultiple: allowMultiple,
|
|
allowCompression: allowCompression,
|
|
onFileLoading: onFileLoading,
|
|
withData: withData,
|
|
withReadStream: withReadStream);
|
|
if (result != null) {
|
|
double _fileSize = 0;
|
|
for (final PlatformFile filePath in result.files) {
|
|
_fileSize += _getSizeFile(filePath.path ?? '');
|
|
}
|
|
if (_fileSize < 15) {
|
|
//_appSettings.configs.maximumFileSizeUpload.first.document
|
|
return result;
|
|
} else {
|
|
showErrorMessage(AppLocalizations.of(navigatorKey!.currentState!.context)!
|
|
.translate('Tệp tin vượt quá dung lượng cho phép: ${15} mb'));
|
|
return null;
|
|
}
|
|
} else {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
double _getSizeFile(String filePath) {
|
|
final File _file = File(filePath);
|
|
final int sizeInBytes = _file.lengthSync();
|
|
return sizeInBytes / (1024 * 1024);
|
|
}
|
|
|
|
static Future<void> launchPhone({String value = ""}) async {
|
|
String url = 'tel:$value';
|
|
final uri = Uri.parse(url);
|
|
if (await canLaunchUrl(uri)) {
|
|
await launchUrl(
|
|
uri,
|
|
);
|
|
} else {
|
|
showErrorMessage("Không có ứng dụng phù hợp");
|
|
}
|
|
}
|
|
|
|
static Future<void> launchEmail({String value = ""}) async {
|
|
String url = 'mailto:$value';
|
|
final uri = Uri.parse(url);
|
|
if (await canLaunchUrl(uri)) {
|
|
await launchUrl(
|
|
uri,
|
|
);
|
|
} else {
|
|
showErrorMessage("Không có ứng dụng phù hợp");
|
|
}
|
|
}
|
|
|
|
static DateTime getDate(DateTime time) {
|
|
return DateTime(time.year, time.month, time.day);
|
|
}
|
|
|
|
static DateTime getToDate(DateTime time) {
|
|
return DateTime(time.year, time.month, time.day).add(const Duration(days: 1)).add(const Duration(seconds: -1));
|
|
}
|
|
|
|
static DateTime addMonth(DateTime date) {
|
|
var year = date.year + ((date.month + 1) ~/ 12);
|
|
var month = (date.month + 1) % 12;
|
|
if (month == 0) month = 12;
|
|
var day = date.day;
|
|
|
|
// Adjust day if the result is an invalid date, e.g., adding a month to January 31st
|
|
if (day > 28) {
|
|
day = min(day, DateTime(year, month + 1, 0).day);
|
|
}
|
|
|
|
return DateTime(year, month, day, date.hour, date.minute, date.second, date.millisecond, date.microsecond);
|
|
}
|
|
|
|
static DateTime? getDateTimeFromUTC(DateTime? time) {
|
|
if (time == null) return null;
|
|
if (!time.isUtc) return time;
|
|
return time.toLocal();
|
|
}
|
|
|
|
static int getTimeSpanFromTime(String time) {
|
|
try {
|
|
final now = DateTime.now();
|
|
final temps = time.split(":").map((e) => e.trim()).toList();
|
|
return DateTime(
|
|
now.year,
|
|
now.month,
|
|
now.day,
|
|
int.parse(temps[0]),
|
|
int.parse(temps[1]),
|
|
).millisecondsSinceEpoch;
|
|
} catch (e) {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
static DateTime? getDateFromText(String stringTime, {String stringFormat = "MM/dd/yyyy hh:mm:ss"}) {
|
|
try {
|
|
DateFormat format = DateFormat(stringFormat);
|
|
DateTime dateTime = format.parse(stringTime);
|
|
return dateTime;
|
|
} catch (e) {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
static String fileSize(double size) {
|
|
double d1 = size / 1024.0;
|
|
double d2 = d1 / 1024.0;
|
|
double d3 = d2 / 1024.0;
|
|
if (size < 1024.0) {
|
|
return size.toString() + " bytes";
|
|
}
|
|
if (d1 < 1024.0) {
|
|
return d1.round().toString() + " KB";
|
|
}
|
|
if (d2 < 1024.0) {
|
|
return d2.round().toString() + " MB";
|
|
}
|
|
return d3.round().toString() + " GB";
|
|
}
|
|
|
|
static Future<void> openLaunch(String link,
|
|
{mode = LaunchMode.externalApplication, String appStoreLink = "", bool isOpenAppWebView = false}) async {
|
|
if (isOpenAppWebView) {
|
|
} else {
|
|
final uri = Uri.parse(link);
|
|
if (await canLaunchUrl(uri)) {
|
|
await launchUrl(
|
|
uri,
|
|
mode: mode,
|
|
);
|
|
} else {
|
|
if (appStoreLink.isNotEmpty) {
|
|
await launchUrl(Uri.parse(appStoreLink), mode: mode);
|
|
}
|
|
//throw 'Could not launch $link';
|
|
}
|
|
}
|
|
}
|
|
|
|
// static Future<void> _launchURL(Uri link) async {
|
|
// try {
|
|
// await ct.launchUrl(
|
|
// link,
|
|
// customTabsOptions: ct.CustomTabsOptions(
|
|
// // colorSchemes: ct.CustomTabsColorSchemes.defaults(
|
|
// // toolbarColor: theme.colorScheme.surface,
|
|
// // ),
|
|
// shareState: ct.CustomTabsShareState.on,
|
|
// urlBarHidingEnabled: true,
|
|
// showTitle: true,
|
|
// closeButton: ct.CustomTabsCloseButton(
|
|
// icon: 'ic_action_close',
|
|
// ),
|
|
// ),
|
|
// // safariVCOptions: SafariViewControllerOptions(
|
|
// // preferredBarTintColor: theme.colorScheme.surface,
|
|
// // preferredControlTintColor: theme.colorScheme.onSurface,
|
|
// // barCollapsingEnabled: true,
|
|
// // dismissButtonStyle: SafariViewControllerDismissButtonStyle.close,
|
|
// // ),
|
|
// );
|
|
// } catch (e) {
|
|
// // If the URL launch fails, an exception will be thrown. (For example, if no browser app is installed on the Android device.)
|
|
// debugPrint(e.toString());
|
|
// }
|
|
// }
|
|
|
|
static String getFormatTime(int number) {
|
|
String textTimeFormat = "";
|
|
if (number > 3600) {
|
|
final int hours = (number ~/ 3600).round();
|
|
final int minutes = ((number % 3600) / 60).round();
|
|
final int seconds = ((number % 3600) % 60).round();
|
|
textTimeFormat = hours.toString() +
|
|
' giờ ' +
|
|
(minutes != 0 ? minutes.toString() + ' phút ' : '') +
|
|
(seconds != 0 ? seconds.toString() + ' giây' : '');
|
|
} else {
|
|
if (number >= 60) {
|
|
final int minutes = (number ~/ 60).round();
|
|
final int seconds = number % 60;
|
|
textTimeFormat = minutes.toString() + ' phút ' + (seconds != 0 ? seconds.toString() + ' giây' : '');
|
|
} else {
|
|
textTimeFormat = number.toString() + ' giây';
|
|
}
|
|
}
|
|
return textTimeFormat;
|
|
}
|
|
|
|
static paginate<T>(List<T> array, int pageSize, int pageNumber) {
|
|
return array.sublist(
|
|
(pageNumber - 1) * pageSize, (pageNumber * pageSize) > array.length ? array.length : pageNumber * pageSize);
|
|
}
|
|
|
|
// static Future<bool> checkVersionOff() async {
|
|
// // if (kDebugMode) return false;
|
|
// final configs = getItSuper<AppSettings>().appSettings.configs;
|
|
// if (configs.schoolVersionAppOffRegister == null) return false;
|
|
|
|
// final List<String> listVersionEnable =
|
|
// configs.schoolVersionAppOffRegister!.map((VersionModel e) => e.version).toList();
|
|
// final String currentVersion = await PackageInfo.fromPlatform().then((PackageInfo value) => value.version);
|
|
// return listVersionEnable.firstWhere((String element) => element == currentVersion, orElse: () => '').isNotEmpty &&
|
|
// Platform.isIOS;
|
|
// }
|
|
}
|