downloadAllFontsZipFile method
Downloads a zip file containing all fonts for the specified font index.
This method asynchronously downloads a zip file that contains all the fonts
associated with the given fontIndex
. The downloaded file will be saved
locally for later use.
fontIndex
- The index of the font set to be downloaded.
Returns a Future that completes when the download is finished.
Implementation
Future<void> downloadAllFontsZipFile(int fontIndex) async {
// if (GetStorage().read(StorageConstants().isDownloadedCodeV2Fonts) ??
// false || state.isDownloadingFonts.value) {
// return Future.value();
// }
// فحص الاتصال بالإنترنت أولاً (خاص بـ macOS)
// Check internet connectivity first (specific for macOS)
if (Platform.isMacOS) {
final hasConnection = await _checkNetworkConnectivity();
if (!hasConnection) {
_showMacOSNetworkTroubleshooting();
return;
}
}
try {
state.isPreparingDownload.value = true;
state.isDownloadingFonts.value = true;
update(['fontsDownloadingProgress']);
// قائمة بالروابط البديلة للتحميل
// List of alternative download URLs
final urls = [
'https://github.com/alheekmahlib/Islamic_database/raw/refs/heads/main/quran_database/Quran%20Font/quran_fonts.zip',
'https://rawgit.flutter-io.cn/alheekmahlib/Islamic_database/main/quran_database/Quran%20Font/quran_fonts.zip',
];
// تحميل الملف باستخدام Dio
// تحميل الملف باستخدام http.Client مع إعدادات محسنة للماك
// Download file using http.Client with improved settings for macOS
// final response = dio.get(
// 'https://github.com/alheekmahlib/Islamic_database/raw/refs/heads/main/quran_database/Quran%20Font/quran_fonts.zip',
// options: Options(responseType: ResponseType.stream),
// );
final dio = Dio();
String? successUrl;
late Response response;
// جرب كل رابط حتى ينجح واحد منها
// Try each URL until one succeeds
for (String url in urls) {
try {
log('Attempting to download from: $url', name: 'FontsDownload');
response = await dio.get(url,
options: Options(
responseType: ResponseType.stream,
sendTimeout: Duration(seconds: 30),
headers: {
'User-Agent': 'Flutter/Quran-Library',
'Accept': '*/*',
'Connection': 'keep-alive',
'Accept-Encoding': 'identity',
},
));
// التحقق من نجاح الاتصال بأحد الروابط
// Check if connection to any URL succeeded
if (response.statusCode != 200) {
log('Failed to connect to $url: ${response.statusCode}',
name: 'FontsDownload');
break;
}
log('Download started successfully from: $successUrl',
name: 'FontsDownload');
if (response.statusCode == 200) {
successUrl = url;
log('Successfully connected to: $url', name: 'FontsDownload');
break;
}
} catch (e) {
log('Failed to connect to $url: $e', name: 'FontsDownload');
continue;
}
}
// تحديد المسار الذي سيتم حفظ الملف فيه
final fontsDir = Directory('${_dir.path}/quran_fonts');
if (!await fontsDir.exists()) {
await fontsDir.create(recursive: true);
}
// حفظ ملف ZIP إلى التطبيق
final zipFile = File('${_dir.path}/quran_fonts.zip');
final fileSink = zipFile.openWrite();
// حجم الملف الإجمالي
final contentLength = int.tryParse(
response.headers.value(Headers.contentLengthHeader) ?? '0') ??
0;
int totalBytesDownloaded = 0;
// متابعة التدفق وكتابة البيانات في الملف مع حساب نسبة التحميل
(response.data as ResponseBody).stream.listen(
(List<int> chunk) {
totalBytesDownloaded += chunk.length;
fileSink.add(chunk);
state.isDownloadingFonts.value = true;
state.isPreparingDownload.value = false;
// حساب نسبة التحميل
if (contentLength > 0) {
double progress = totalBytesDownloaded / contentLength * 100;
state.fontsDownloadProgress.value = progress;
log('Download progress: ${progress.toStringAsFixed(2)}%',
name: 'FontsDownload');
update(['fontsDownloadingProgress']);
}
},
onDone: () async {
await fileSink.flush();
await fileSink.close();
// فك ضغط الـ ZIP بعد إغلاق الملف بنجاح
try {
// التحقق من أن الملف تم تنزيله بالكامل
final zipFileSize = await zipFile.length();
log('Downloaded ZIP file size: $zipFileSize bytes');
if (zipFileSize == 0) {
throw Exception('Downloaded ZIP file is empty');
}
// فك ضغط الـ ZIP
final bytes = zipFile.readAsBytesSync();
final archive = ZipDecoder().decodeBytes(bytes);
if (archive.isEmpty) {
throw FormatException(
'Failed to extract ZIP file: Archive is empty');
}
// استخراج الملفات إلى مجلد الخطوط
for (final file in archive) {
final filename = '${fontsDir.path}/${file.name}';
if (file.isFile) {
final outFile = File(filename);
await outFile.create(recursive: true);
await outFile.writeAsBytes(file.content as List<int>);
// log('Extracted file: $filename'); // سجل لاستخراج الملف
} else {
log('Skipped directory: ${file.name}');
}
}
// تحقق من وجود الملفات في المجلد
final files = await fontsDir.list().toList();
if (files.isEmpty) {
log('No files found in fontsDir after extraction');
} else {
log('Files in fontsDir after extraction: ${files.map((file) => file.path).join(', ')}');
}
await QuranCtrl.instance.loadFontsQuran();
// حفظ حالة التحميل في التخزين المحلي
// Save download status in local storage
GetStorage()
.write(_StorageConstants().isDownloadedCodeV2Fonts, true);
state.fontsDownloadedList.add(fontIndex);
GetStorage().write(_StorageConstants().fontsDownloadedList,
state.fontsDownloadedList);
// تحديث حالة التحميل وإكمال شريط التقدم
// Update download status and complete progress bar
state.isDownloadedV2Fonts.value = true;
state.isDownloadingFonts.value = false;
state.isPreparingDownload.value = false;
state.fontsDownloadProgress.value = 100.0;
update(['fontsDownloadingProgress']);
Get.forceAppUpdate();
log('Fonts unzipped successfully', name: 'FontsDownload');
// Get.back();
} catch (e) {
log('Failed to extract ZIP file: $e');
}
},
onError: (error) {
log('Error during download: $error');
dio.close();
},
cancelOnError: true,
);
} catch (e) {
log('Failed to Download Code_v2 fonts: $e', name: 'FontsDownload');
// معالجة خاصة لأخطاء macOS
// Special handling for macOS errors
if (Platform.isMacOS &&
e.toString().contains('Operation not permitted')) {
_showMacOSNetworkTroubleshooting();
}
// تحديث حالة التحميل في حالة فشل العملية
// Update download status if operation fails
state.isDownloadingFonts.value = false;
state.isPreparingDownload.value = false;
state.fontsDownloadProgress.value = 0.0;
update(['fontsDownloadingProgress']);
// رمي استثناء ليتم التعامل معه في الدالة الأم
// Throw exception to be handled in parent function
throw Exception('Download failed: $e');
}
}