import 'dart:io'; import 'package:path_provider/path_provider.dart'; class FontManager { static const supportedExtensions = ['.ttf', '.otf', '.woff', '.woff2']; static const builtInFonts = ['System', 'OpenSans', 'Roboto', 'SourceSerif']; static Future getFontsDirectory() async { final directory = await getApplicationDocumentsDirectory(); final fontsDir = Directory('${directory.path}/fonts'); if (!await fontsDir.exists()) { await fontsDir.create(recursive: true); } return fontsDir; } static Future installCustomFont(String sourcePath, String fileName) async { try { final fontsDir = await getFontsDirectory(); final sourceFile = File(sourcePath); // Basic validation: fonts should be > 1KB and < 50MB final fileSize = await sourceFile.length(); if (fileSize < 1024 || fileSize > 50 * 1024 * 1024) { throw Exception('Invalid font file size'); } final targetPath = '${fontsDir.path}/$fileName'; final targetFile = await sourceFile.copy(targetPath); return targetFile.path; } catch (e) { throw Exception('Failed to install custom font: $e'); } } static Future> getInstalledCustomFonts() async { try { final fontsDir = await getFontsDirectory(); final files = await fontsDir.list().toList(); return files .where((file) => file is File && supportedExtensions.any((ext) => file.path.toLowerCase().endsWith(ext))) .map((file) { final fileName = file.path.split(Platform.pathSeparator).last; return fileName.split('.').first; }) .toList(); } catch (e) { return []; } } /// Get the full file name (with extension) for a given font name static Future getFontFileName(String fontName) async { final fontsDir = await getFontsDirectory(); final files = await fontsDir.list().toList(); for (final file in files) { if (file is File) { final fileName = file.path.split(Platform.pathSeparator).last; final nameWithoutExt = fileName.split('.').first; if (nameWithoutExt == fontName) { return fileName; } } } return null; } /// Get the local server URL for a custom font static Future getCustomFontUrl(String fontName) async { final fileName = await getFontFileName(fontName); if (fileName == null) return null; return 'http://127.0.0.1:9000/custom-fonts/${Uri.encodeComponent(fileName)}'; } static Future removeCustomFont(String fontName) async { try { final fontsDir = await getFontsDirectory(); final files = await fontsDir.list().toList(); for (final file in files) { if (file is File) { final fileName = file.path.split(Platform.pathSeparator).last; final nameWithoutExt = fileName.split('.').first; if (nameWithoutExt == fontName) { await file.delete(); break; } } } } catch (e) { throw Exception('Failed to remove custom font: $e'); } } static String getFontDisplayName(String fontFamily) { switch (fontFamily) { case 'System': return 'System Font'; case 'OpenSans': return 'Open Sans'; case 'SourceSerif': return 'Source Serif'; default: return fontFamily; } } }