2024-06-03 16:35:33 +02:00
|
|
|
import 'package:cloud_firestore/cloud_firestore.dart';
|
2024-06-13 00:47:53 +02:00
|
|
|
import 'package:flutter/foundation.dart' show kIsWeb;
|
|
|
|
import 'dart:io' show Platform;
|
2024-06-12 00:39:29 +02:00
|
|
|
import '../enumerations.dart';
|
|
|
|
|
2024-06-13 00:47:53 +02:00
|
|
|
/// Returns [true] if app is running on Mobile (Android or iOS), else [false].
|
|
|
|
bool get isMobile {
|
|
|
|
if (kIsWeb) {
|
|
|
|
return false;
|
|
|
|
} else {
|
|
|
|
return Platform.isIOS || Platform.isAndroid;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-05-25 13:56:45 +02:00
|
|
|
/// Creates a composite ID from the passed [ids].
|
|
|
|
/// In the format id(1)_id(n)
|
2024-05-27 14:40:46 +02:00
|
|
|
String getCompoundId(List<String> ids) {
|
2024-05-25 13:56:45 +02:00
|
|
|
ids.sort(); // sort to ensure the result is the same for any order of ids
|
|
|
|
return ids.join('_');
|
|
|
|
}
|
|
|
|
|
2024-06-03 16:35:33 +02:00
|
|
|
/// Returns a date format of '$weekday, $day. $month $year $hours:$minutes'.
|
2024-06-13 00:47:53 +02:00
|
|
|
/// For example: [Sat. 3 Jun. 2024 15:03].
|
2024-06-03 16:35:33 +02:00
|
|
|
/// If any errors occur, an empty string will be returned.
|
|
|
|
String formatTimestamp(Timestamp timestamp) {
|
|
|
|
try {
|
|
|
|
const List<String> weekdays = [
|
|
|
|
'Mon',
|
|
|
|
'Tue',
|
|
|
|
'Wed',
|
|
|
|
'Thu',
|
|
|
|
'Fri',
|
|
|
|
'Sat',
|
|
|
|
'Sun'
|
|
|
|
];
|
|
|
|
const List<String> months = [
|
|
|
|
'Jan.',
|
|
|
|
'Feb.',
|
|
|
|
'Mar.',
|
|
|
|
'Apr.',
|
|
|
|
'May',
|
|
|
|
'Jun.',
|
|
|
|
'Jul.',
|
|
|
|
'Aug.',
|
|
|
|
'Sep.',
|
|
|
|
'Oct.',
|
|
|
|
'Nov.',
|
|
|
|
'Dec.'
|
|
|
|
];
|
|
|
|
|
|
|
|
DateTime dateTime = timestamp.toDate();
|
|
|
|
String weekday = weekdays[dateTime.weekday - 1];
|
|
|
|
int day = dateTime.day;
|
|
|
|
String month = months[dateTime.month - 1];
|
|
|
|
int year = dateTime.year;
|
|
|
|
int hour = dateTime.hour;
|
|
|
|
int minute = dateTime.minute;
|
|
|
|
|
|
|
|
return '$weekday, $day. $month $year ${hour.toString().padLeft(2, '0')}:${minute.toString().padLeft(2, '0')}';
|
|
|
|
} catch (e) {
|
|
|
|
return '';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-06-12 00:39:29 +02:00
|
|
|
/// Get pronoun for given [userGender].
|
|
|
|
/// Returns [He] if male, [She] if female, else [He/She].
|
|
|
|
String getPronoun(Gender? userGender) {
|
|
|
|
switch (userGender) {
|
|
|
|
case Gender.male:
|
|
|
|
return 'He';
|
|
|
|
case Gender.female:
|
|
|
|
return 'She';
|
|
|
|
default:
|
|
|
|
return 'He/She';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-06-21 02:42:45 +02:00
|
|
|
/// Get possessive adjective for given [userGender].
|
|
|
|
/// Returns [His] if male, [Her] if female, else [His/Her].
|
|
|
|
String getPossessiveAdjective(Gender? userGender) {
|
|
|
|
switch (userGender) {
|
|
|
|
case Gender.male:
|
|
|
|
return 'His';
|
|
|
|
case Gender.female:
|
|
|
|
return 'Her';
|
|
|
|
default:
|
|
|
|
return 'His/Her';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-05-25 13:56:45 +02:00
|
|
|
/// Get the [displayName] of our own Enumerations.
|
2024-05-21 14:01:44 +02:00
|
|
|
String getDisplayText(dynamic option) {
|
|
|
|
// Check if the option is an enum and has a displayName property
|
|
|
|
if (option is Enum) {
|
|
|
|
final dynamicEnum = option as dynamic;
|
|
|
|
if (dynamicEnum.displayName != null) {
|
|
|
|
return dynamicEnum.displayName;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Fallback to default toString if not an enum
|
|
|
|
return option.toString().split('.').last;
|
|
|
|
}
|
2024-06-24 04:41:17 +02:00
|
|
|
|
|
|
|
/// Returns null if the given [value] is a valid Facebook Url,
|
|
|
|
/// else an error message is returned.
|
|
|
|
String? validateUrlFacebook(String? value) {
|
|
|
|
if (value == null || value.trim().isEmpty) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
if (!value.startsWith('http:') && !value.startsWith('https:')) {
|
|
|
|
return 'Link does not start with http(s):';
|
|
|
|
}
|
|
|
|
RegExp regex1 = RegExp(
|
|
|
|
r'^(?:https?://)?(?:www\.)?facebook.com/(?:profile\.php\?id=)?[0-9]+$');
|
|
|
|
RegExp regex2 = RegExp(
|
|
|
|
r'^(?:https?://)?(?:www\.)?(?:facebook|fb)\.com/(?![A-z]+\.php)(?!marketplace|gaming|watch|me|messages|help|search|groups)[A-z0-9_\-.]+/?$');
|
|
|
|
if (!regex1.hasMatch(value) && !regex2.hasMatch(value)) {
|
|
|
|
return 'Unknown or invalid Facebook URL format.';
|
|
|
|
}
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns null if the given [value] is a valid LinkedIn Url,
|
|
|
|
/// else an error message is returned.
|
|
|
|
String? validateUrlLinkedIn(String? value) {
|
|
|
|
if (value == null || value.trim().isEmpty) {
|
|
|
|
return null; // ok, nothing to validate
|
|
|
|
}
|
|
|
|
if (!value.startsWith('http:') && !value.startsWith('https:')) {
|
|
|
|
return 'Link does not start with http(s):';
|
|
|
|
}
|
|
|
|
// RegEx source https://github.com/lorey/social-media-profiles-regexs?tab=readme-ov-file#linkedin
|
|
|
|
RegExp regex1 = RegExp(
|
|
|
|
r'^(?:https?://)?(?:\w+\.)?linkedin\.com/(?:(company)|(school))/[A-z0-9-À-ÿ.]+/?$');
|
|
|
|
RegExp regex2 = RegExp(
|
|
|
|
r'^(?:https?://)?(?:\w+\.)?linkedin\.com/feed/update/urn:li:activity:[0-9]+/?$');
|
|
|
|
RegExp regex3 =
|
|
|
|
RegExp(r'^(?:https?://)?(?:\w+\.)?linkedin\.com/in/[\w\-_À-ÿ%]+/?$');
|
|
|
|
if (!regex1.hasMatch(value) &&
|
|
|
|
!regex2.hasMatch(value) &&
|
|
|
|
!regex3.hasMatch(value)) {
|
|
|
|
return 'Unknown or invalid LinkedIn URL format.';
|
|
|
|
}
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns null if the given [value] is a valid Xing Url,
|
|
|
|
/// else an error message is returned.
|
|
|
|
String? validateUrlXing(String? value) {
|
|
|
|
if (value == null || value.trim().isEmpty) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
if (!value.startsWith('http:') && !value.startsWith('https:')) {
|
|
|
|
return 'Link does not start with http(s):';
|
|
|
|
}
|
|
|
|
RegExp regex =
|
|
|
|
RegExp(r'^(?:https?://)?(?:www\.)?xing.com/profile/[A-z0-9-_]+$');
|
|
|
|
if (!regex.hasMatch(value)) {
|
|
|
|
return 'Unknown or invalid Xing URL format.';
|
|
|
|
}
|
|
|
|
return null;
|
|
|
|
}
|