mobile bluesky app made with flutter lazurite.stormlightlabs.org/
mobile bluesky flutter
3
fork

Configure Feed

Select the types of activity you want to include in your feed.

at main 80 lines 2.6 kB view raw
1import 'package:bluesky/app_bsky_feed_defs.dart'; 2import 'package:intl/intl.dart'; 3 4/// Returns up to two initials from a display value. 5String formatInitials(String value) { 6 final parts = value.trim().split(RegExp(r'\s+')).where((part) => part.isNotEmpty).toList(); 7 if (parts.isEmpty) { 8 return '?'; 9 } 10 if (parts.length == 1) { 11 return parts.first.substring(0, 1).toUpperCase(); 12 } 13 return '${parts.first.substring(0, 1)}${parts.last.substring(0, 1)}'.toUpperCase(); 14} 15 16/// Formats counts using compact K/M suffixes. 17String formatCount(int count, {String? locale}) { 18 final numberFormat = NumberFormat.decimalPattern(locale ?? Intl.getCurrentLocale()); 19 final absoluteCount = count.abs(); 20 final sign = count < 0 ? '-' : ''; 21 if (absoluteCount >= 1000000) { 22 return '$sign${(absoluteCount / 1000000).toStringAsFixed(1)}M'; 23 } 24 if (absoluteCount >= 1000) { 25 return '$sign${(absoluteCount / 1000).toStringAsFixed(1)}K'; 26 } 27 return numberFormat.format(count); 28} 29 30/// Formats a relative timestamp using short units with optional suffix/casing. 31String formatRelativeTime( 32 DateTime time, { 33 DateTime? now, 34 String nowLabel = 'now', 35 bool includeAgo = false, 36 bool uppercase = false, 37 String? locale, 38}) { 39 final current = now ?? DateTime.now(); 40 var difference = current.difference(time); 41 if (difference.isNegative) { 42 difference = Duration.zero; 43 } 44 45 final agoSuffix = includeAgo ? ' ago' : ''; 46 final formatted = switch (difference) { 47 final d when d.inMinutes < 1 => nowLabel, 48 final d when d.inHours < 1 => '${d.inMinutes}m$agoSuffix', 49 final d when d.inDays < 1 => '${d.inHours}h$agoSuffix', 50 final d when d.inDays < 7 => '${d.inDays}d$agoSuffix', 51 _ => DateFormat('MMM d', locale ?? Intl.getCurrentLocale()).format(time), 52 }; 53 54 return uppercase ? formatted.toUpperCase() : formatted; 55} 56 57String formatTimestamp(DateTime time, {String? locale}) { 58 final month = time.month.toString().padLeft(2, '0'); 59 final day = time.day.toString().padLeft(2, '0'); 60 final hour = time.hour.toString().padLeft(2, '0'); 61 final minute = time.minute.toString().padLeft(2, '0'); 62 return '${time.year}-$month-$day $hour:$minute'; 63} 64 65String feedDisplayName(GeneratorView value) { 66 final displayName = value.displayName.trim(); 67 if (displayName.isNotEmpty) { 68 return displayName; 69 } 70 return value.uri.rkey; 71} 72 73String formatBytes(int bytes) { 74 if (bytes >= 1024 * 1024 * 1024) { 75 final gb = bytes / (1024 * 1024 * 1024); 76 return '${gb.toStringAsFixed(2)} GB'; 77 } 78 final mb = bytes / (1024 * 1024); 79 return '${mb.toStringAsFixed(2)} MB'; 80}