Skip to content

Commit

Permalink
🐛 (font_loader) loadFonts handle font familly from current and exte…
Browse files Browse the repository at this point in the history
  • Loading branch information
T-moz committed Oct 1, 2024
1 parent 011ec93 commit 3614968
Showing 1 changed file with 74 additions and 19 deletions.
93 changes: 74 additions & 19 deletions lib/src/helpers/fonts_loader.dart
Original file line number Diff line number Diff line change
@@ -1,36 +1,91 @@
// ignore_for_file: avoid-dynamic, avoid-accessing-collections-by-constant-index
// ignore_for_file: avoid-dynamic

import 'dart:convert';
import 'dart:io';

import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:package_config/package_config.dart';

/// Load fonts and icons to make sure they show up in golden tests.
/// Loads fonts and icons to ensure they appear in golden tests.
///
/// To use it efficiently:
/// * Create a flutter_test_config.dart file. See:
/// https://api.flutter.dev/flutter/flutter_test/flutter_test-library.html
/// * add `await loadFonts();` in the `testExecutable` function.
/// Usage:
/// 1. Create a flutter_test_config.dart file.
/// 2. Add `await loadFonts();` in the `testExecutable` function.
///
/// /// Load fonts to make sure they show up in golden tests.
///
/// *Note* for this function to work, your package needs to include all fonts
/// it uses az assets.
/// Note: Your package must include all used fonts as assets for this to work.
Future<void> loadFonts() async {
TestWidgetsFlutterBinding.ensureInitialized();
final fontManifest = await _loadFontManifest();
final packageName = await _getCurrentPackageName();
await _loadFontsFromManifest(fontManifest, packageName);
}

Future<_FontManifest> _loadFontManifest() async {
final fontManifest = await rootBundle.loadStructuredData<Iterable<dynamic>>(
'FontManifest.json',
(string) async => json.decode(string),
);
final waitList = <Future<void>>[];
for (final Map<String, dynamic> font in fontManifest) {
final fontLoader = FontLoader(font['family']);

for (final Map<String, dynamic> fontType in font['fonts']) {
fontLoader.addFont(rootBundle.load(fontType['asset']));
}
waitList.add(fontLoader.load());

return fontManifest.map((font) => _FontData.fromJson(font)).toList();
}

Future<void> _loadFontsFromManifest(
_FontManifest fontManifest,
String? packageName,
) async {
final fontLoaders = fontManifest.expand((font) {
final regularFontLoader = _createFontLoader(font.family, font.fonts);
final fontFamilyStartsWithPackages = font.family.startsWith('packages/');

return [
regularFontLoader,
if (!fontFamilyStartsWithPackages && packageName != null)
_createFontLoader('packages/$packageName/${font.family}', font.fonts),
];
}).toList();

await Future.wait(fontLoaders.map((loader) => loader.load()));
}

FontLoader _createFontLoader(String fontFamily, List<_FontType> fontTypes) {
final fontLoader = FontLoader(fontFamily);
fontTypes.forEach(
(fontType) => fontLoader.addFont(rootBundle.load(fontType.asset)),
);

return fontLoader;
}

Future<String?> _getCurrentPackageName() async {
final current = Directory.current;
final packageConfig = await findPackageConfig(current);

return packageConfig?.packageOf(current.uri)?.name;
}

typedef _FontManifest = List<_FontData>;

class _FontData {
const _FontData({required this.family, required this.fonts});

factory _FontData.fromJson(Map<String, dynamic> json) {
return _FontData(
family: json['family'] as String,
fonts: (json['fonts'] as List)
.map((font) => _FontType.fromJson(font))
.toList(),
);
}
final String family;
final List<_FontType> fonts;
}

class _FontType {
const _FontType({required this.asset});

factory _FontType.fromJson(Map<String, dynamic> json) {
return _FontType(asset: json['asset'] as String);
}
await Future.wait(waitList);
final String asset;
}

0 comments on commit 3614968

Please sign in to comment.