import 'package:intl/locale.dart'; abstract class FileMatcher { const FileMatcher._(); static String? matchFile({ required List files, required String name, String extension = 'png', int scale = 1, Locale? locale, }) { final localized = matchLocale(files: files, name: 'logo', extension: 'png'); final scaled = matchScale(files: localized, name: 'logo', extension: 'png'); final file = files.singleWhere((element) => element == scaled); return file; } static List matchLocale({ required List files, Locale? locale, required String name, required String extension, }) { files.sort(); files = files.reversed.toList(); List expressions = []; // adding the fallbacks // - match just *any* language // - match the five mostly spoken languages of the world, copied from Wikipedia expressions.addAll( [ RegExp( '^([a-z]+(-[a-z]+)?\\.lproj\\/)?$name(@\\d+x)?\\.$extension\$', unicode: true, caseSensitive: false, ), ...['en', 'zh', 'hi', 'es', 'fr'].reversed.map( (language) => RegExp( '^$language(-[a-z]+)?\\.lproj\\/$name(@\\d+x)?\\.$extension\$', unicode: true, caseSensitive: false, ), ), ], ); if (locale != null) { final language = locale.languageCode; expressions.add( RegExp( '^$language(-[a-z]+)?\\.lproj\\/$name(@\\d+x)?\\.$extension\$', unicode: true, caseSensitive: false, ), ); final region = locale.countryCode; if (region != null) { expressions.add( RegExp( '^$language-$region\\.lproj\\/$name(@\\d+x)?\\.$extension\$', unicode: true, caseSensitive: false, ), ); } } for (final regex in expressions.reversed) { final matches = []; for (final file in files) { final match = regex.stringMatch(file); if (match != null) matches.add(match); } if (matches.isNotEmpty) return matches; } return []; } static String matchScale({ required List files, int scale = 1, required String name, required String extension, }) { files.sort(); files = files.reversed.toList(); final regex = RegExp( '$name(@(\\d+)x)?\\.$extension\$', unicode: true, caseSensitive: false, ); int closestScale = 0; final matches = []; for (final file in files) { final match = regex.firstMatch(file); if (match != null) { String? group = match[2]; if (group == null) { if (scale == 1) return match.input; group = '1'; } final matchedScale = int.parse(group); if (matchedScale == scale) return match.input; if (matchedScale < scale) { if (closestScale < matchedScale) closestScale = matchedScale; } else if (closestScale < matchedScale) { closestScale = matchedScale; } matches.add(match.input); } } final scaledMatches = matches .where( (element) => RegExp( '$name(@${closestScale}x)?\\.$extension\$', unicode: true, caseSensitive: false, ).hasMatch(element), ) .toList(); scaledMatches.sort(); return scaledMatches.last; } }