-
Notifications
You must be signed in to change notification settings - Fork 17
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1173 from mawaqit/revert-1167-revert-1120-feat/qu…
…ran/download Revert "Revert "Feat/quran/download"" [add again download quran]
- Loading branch information
Showing
18 changed files
with
1,133 additions
and
140 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,3 +7,5 @@ linter: | |
rules: | ||
- cancel_subscriptions | ||
- require_trailing_commas | ||
- close_sinks | ||
- always_use_package_imports |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
72 changes: 72 additions & 0 deletions
72
lib/src/data/data_source/quran/download_quran_local_data_source.dart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
import 'dart:developer'; | ||
import 'dart:io'; | ||
|
||
import 'package:flutter_riverpod/flutter_riverpod.dart'; | ||
import 'package:mawaqit/src/const/constants.dart'; | ||
import 'package:mawaqit/src/helpers/directory_helper.dart'; | ||
import 'package:mawaqit/src/module/shared_preference_module.dart'; | ||
import 'package:path_provider/path_provider.dart'; | ||
import 'package:shared_preferences/shared_preferences.dart'; | ||
|
||
class DownloadQuranLocalDataSource { | ||
final Directory applicationSupportDirectory; | ||
final SharedPreferences sharedPreference; | ||
|
||
DownloadQuranLocalDataSource({required this.applicationSupportDirectory, required this.sharedPreference}); | ||
|
||
/// [saveSvgFiles] saves the zip file to the local storage | ||
Future<void> saveSvgFiles(List<File> svgFiles) async { | ||
final quranDirectory = Directory('${applicationSupportDirectory.path}/quran'); | ||
log('quran: DownloadQuranLocalDataSource: saveSvgFiles - quranDirectory: ${quranDirectory.path}'); | ||
await DirectoryHelper.createDirectoryIfNotExists(quranDirectory); | ||
for (final svgFile in svgFiles) { | ||
final fileName = svgFile.path.split('/').last; | ||
final destinationPath = '${quranDirectory.path}/$fileName'; | ||
log('quran: DownloadQuranLocalDataSource: saveSvgFiles - destinationPath: $destinationPath || fileName: $fileName'); | ||
await svgFile.copy(destinationPath); | ||
log('quran: DownloadQuranLocalDataSource: saveSvgFiles - copied ${svgFile.path} to $destinationPath'); | ||
} | ||
} | ||
|
||
/// [deleteZipFile] deletes the existing svg files | ||
Future<void> deleteZipFile(String zipFileName) async { | ||
final zipFilePath = '${applicationSupportDirectory.path}/quran_zip/$zipFileName'; | ||
_setQuranVersion(zipFileName); | ||
final zipFile = File(zipFilePath); | ||
if (await zipFile.exists()) { | ||
log('quran: DownloadQuranLocalDataSource: deleteZipFile - deleting $zipFilePath'); | ||
await zipFile.delete(); | ||
} | ||
} | ||
|
||
/// [getQuranVersion] fetches the quran version | ||
String getQuranVersion() { | ||
final version = sharedPreference.getString(QuranConstant.kQuranLocalVersion) ?? ''; | ||
final checkSVGs = Directory('${applicationSupportDirectory.path}/quran'); | ||
if (checkSVGs.existsSync() && checkSVGs.listSync().isNotEmpty) { | ||
log('quran: DownloadQuranLocalDataSource: getQuranVersion - checkSVGs: $version'); | ||
return version; | ||
} else { | ||
log('quran: DownloadQuranLocalDataSource: getQuranVersion - checkSVGs: $version'); | ||
return ''; | ||
} | ||
} | ||
|
||
/// [_setQuranVersion] sets the quran version | ||
void _setQuranVersion(String version) { | ||
sharedPreference.setString(QuranConstant.kQuranLocalVersion, version); | ||
log('quran: DownloadQuranLocalDataSource: setQuranVersion - version: $version'); | ||
} | ||
} | ||
|
||
final downloadQuranLocalDataSourceProvider = FutureProvider<DownloadQuranLocalDataSource>( | ||
(ref) async { | ||
final savePath = await getApplicationSupportDirectory(); | ||
final sharedPref = await ref.read(sharedPreferenceModule.future); | ||
|
||
return DownloadQuranLocalDataSource( | ||
applicationSupportDirectory: savePath, | ||
sharedPreference: sharedPref, | ||
); | ||
}, | ||
); |
114 changes: 114 additions & 0 deletions
114
lib/src/data/data_source/quran/download_quran_remote_data_source.dart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
import 'dart:async'; | ||
import 'dart:developer'; | ||
|
||
import 'package:dio/dio.dart'; | ||
import 'package:flutter_riverpod/flutter_riverpod.dart'; | ||
import 'package:mawaqit/src/const/constants.dart'; | ||
import 'package:mawaqit/src/domain/error/quran_exceptions.dart'; | ||
import 'package:mawaqit/src/helpers/directory_helper.dart'; | ||
import 'package:path_provider/path_provider.dart'; | ||
|
||
class DownloadQuranRemoteDataSource { | ||
final Dio dio; | ||
CancelToken? cancelToken; | ||
final String applicationSupportDirectoryPath; | ||
|
||
DownloadQuranRemoteDataSource({ | ||
required this.dio, | ||
required this.applicationSupportDirectoryPath, | ||
this.cancelToken, | ||
}); | ||
|
||
/// [getRemoteQuranVersion] fetches the remote quran version | ||
Future<String> getRemoteQuranVersion({ | ||
String url = "https://mawaqit.github.io/mawaqit-announcements/public/quran/config.json", | ||
}) async { | ||
try { | ||
log('quran: DownloadQuranRemoteDataSource: getRemoteQuranVersion - start'); | ||
final version = await dio.get(url).then((value) { | ||
return value.data['fileName']; | ||
}); | ||
log('quran: DownloadQuranRemoteDataSource: getRemoteQuranVersion - $version'); | ||
return version as String; | ||
} catch (e) { | ||
throw FetchRemoteQuranVersionException(e.toString()); | ||
} | ||
} | ||
|
||
/// [downloadQuranWithProgress] downloads the quran zip file | ||
Future<void> downloadQuranWithProgress({ | ||
required String versionName, | ||
String? applicationDirectoryPath, | ||
String url = "https://mawaqit.github.io/mawaqit-announcements/public/quran/", | ||
Function(double)? onReceiveProgress, | ||
}) async { | ||
log('quran: DownloadQuranRemoteDataSource: downloadQuranWithProgress - start'); | ||
applicationDirectoryPath ??= applicationSupportDirectoryPath; | ||
|
||
final filePath = '$applicationDirectoryPath/quran_zip/$versionName'; | ||
log('quran: DownloadQuranRemoteDataSource: downloadQuranWithProgress - filePath: $filePath'); | ||
|
||
try { | ||
await dio.download( | ||
'$url$versionName', | ||
filePath, | ||
onReceiveProgress: (received, total) { | ||
final progress = (received / total) * 100; | ||
// log('quran: DownloadQuranRemoteDataSource: downloadQuranWithProgress - progress: $progress'); | ||
onReceiveProgress?.call(progress); | ||
}, | ||
cancelToken: cancelToken, | ||
); | ||
} on DioException catch (e) { | ||
if (e.type == DioExceptionType.cancel) { | ||
log('quran: DownloadQuranRemoteDataSource: downloadQuranWithProgress - download cancelled'); | ||
await DirectoryHelper.deleteFileIfExists(filePath); | ||
await DirectoryHelper.deleteDirectories([ | ||
'$applicationDirectoryPath/quran_zip', | ||
'$applicationDirectoryPath/quran', | ||
]); | ||
throw CancelDownloadException(); | ||
} | ||
throw Exception('Error occurred while downloading quran: $e'); | ||
} catch (e) { | ||
await DirectoryHelper.deleteFileIfExists(filePath); | ||
await DirectoryHelper.deleteDirectories([ | ||
'$applicationDirectoryPath/quran_zip', | ||
'$applicationDirectoryPath/quran', | ||
]); | ||
throw UnknownException(e.toString()); | ||
} | ||
} | ||
|
||
/// [cancelDownload] cancels the download | ||
void cancelDownload() { | ||
cancelToken?.cancel(); | ||
cancelToken = CancelToken(); | ||
log('quran: DownloadQuranRemoteDataSource: cancelDownload - download cancelled'); | ||
} | ||
} | ||
|
||
final downloadQuranRemoteDataSourceProvider = FutureProvider<DownloadQuranRemoteDataSource>( | ||
(ref) async { | ||
final savePath = await getApplicationSupportDirectory(); | ||
final cancelToken = CancelToken(); | ||
return DownloadQuranRemoteDataSource( | ||
applicationSupportDirectoryPath: savePath.path, | ||
cancelToken: cancelToken, | ||
dio: ref.read(dioProvider), | ||
); | ||
}, | ||
); | ||
|
||
final dioProvider = Provider( | ||
(ref) => Dio( | ||
BaseOptions( | ||
baseUrl: kBaseUrl, | ||
headers: { | ||
'Api-Access-Token': kApiToken, | ||
'accept': 'application/json', | ||
'mawaqit-device': 'android-tv', | ||
}, | ||
), | ||
), | ||
); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
import 'package:flutter_riverpod/flutter_riverpod.dart'; | ||
import 'package:mawaqit/src/data/data_source/quran/download_quran_remote_data_source.dart'; | ||
import 'package:mawaqit/src/helpers/directory_helper.dart'; | ||
import 'package:mawaqit/src/helpers/zip_extractor_helper.dart'; | ||
|
||
import 'package:mawaqit/src/data/data_source/quran/download_quran_local_data_source.dart'; | ||
|
||
import 'package:mawaqit/src/domain/repository/quran/quran_download_repository.dart'; | ||
|
||
class QuranDownloadRepositoryImpl implements QuranDownloadRepository { | ||
final DownloadQuranLocalDataSource localDataSource; | ||
final DownloadQuranRemoteDataSource remoteDataSource; | ||
|
||
QuranDownloadRepositoryImpl({ | ||
required this.localDataSource, | ||
required this.remoteDataSource, | ||
}); | ||
|
||
/// [getLocalQuranVersion] fetches the local quran version | ||
@override | ||
Future<String?> getLocalQuranVersion() async { | ||
final version = localDataSource.getQuranVersion(); | ||
return version; | ||
} | ||
|
||
/// [downloadQuran] downloads the quran zip file | ||
@override | ||
Future<void> downloadQuran({ | ||
required String version, | ||
String? filePath, | ||
required Function(double) onReceiveProgress, | ||
}) async { | ||
await remoteDataSource.downloadQuranWithProgress( | ||
versionName: version, | ||
onReceiveProgress: onReceiveProgress, | ||
); | ||
} | ||
|
||
/// [extractQuran] extracts the quran zip file | ||
@override | ||
Future<void> extractQuran({ | ||
required String zipFilePath, | ||
required String destinationPath, | ||
required Function(double) onExtractProgress, | ||
}) async { | ||
await ZipFileExtractorHelper.extractZipFile( | ||
zipFilePath: zipFilePath, | ||
destinationDirPath: destinationPath, | ||
changeProgress: (progress) { | ||
onExtractProgress(progress); | ||
}, | ||
); | ||
} | ||
|
||
/// [deleteOldQuran] deletes the old quran | ||
@override | ||
Future<void> deleteOldQuran({ | ||
String? path, | ||
}) async { | ||
final quranPath = path ?? localDataSource.applicationSupportDirectory.path; | ||
final deletePath = '$quranPath/quran'; | ||
await DirectoryHelper.deleteExistingSvgFiles(path: deletePath); | ||
} | ||
|
||
/// [deleteZipFile] deletes the zip file | ||
@override | ||
Future<void> deleteZipFile(String zipFileName) async { | ||
await localDataSource.deleteZipFile(zipFileName); | ||
} | ||
|
||
/// [getRemoteQuranVersion] fetches the remote quran version | ||
@override | ||
Future<String> getRemoteQuranVersion() { | ||
return remoteDataSource.getRemoteQuranVersion(); | ||
} | ||
|
||
/// [cancelDownload] cancels the download | ||
@override | ||
Future<void> cancelDownload() async { | ||
remoteDataSource.cancelDownload(); | ||
} | ||
} | ||
|
||
final quranDownloadRepositoryProvider = FutureProvider<QuranDownloadRepository>((ref) async { | ||
final localDataSource = await ref.read(downloadQuranLocalDataSourceProvider.future); | ||
final remoteDataSource = await ref.read(downloadQuranRemoteDataSourceProvider.future); | ||
return QuranDownloadRepositoryImpl( | ||
localDataSource: localDataSource, | ||
remoteDataSource: remoteDataSource, | ||
); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
// exceptions.dart | ||
|
||
abstract class QuranException implements Exception { | ||
final String message; | ||
final String errorCode; | ||
|
||
QuranException(this.message, this.errorCode); | ||
|
||
@override | ||
String toString() => 'Error ($errorCode): $message'; | ||
} | ||
|
||
// DownloadQuranRemoteDataSource exceptions | ||
|
||
class FetchRemoteQuranVersionException extends QuranException { | ||
FetchRemoteQuranVersionException(String message) | ||
: super('Error occurred while fetching remote Quran version: $message', 'FETCH_REMOTE_QURAN_VERSION_ERROR'); | ||
} | ||
|
||
class DownloadQuranException extends QuranException { | ||
DownloadQuranException(String message) | ||
: super('Error occurred while downloading Quran: $message', 'DOWNLOAD_QURAN_ERROR'); | ||
} | ||
|
||
class CancelDownloadException extends QuranException { | ||
CancelDownloadException() : super('Download cancelled', 'CANCEL_DOWNLOAD_ERROR'); | ||
} | ||
|
||
// DownloadQuranLocalDataSource exceptions | ||
|
||
class SaveSvgFilesException extends QuranException { | ||
SaveSvgFilesException(String message) | ||
: super('Error occurred while saving SVG files: $message', 'SAVE_SVG_FILES_ERROR'); | ||
} | ||
|
||
class DeleteExistingSvgFilesException extends QuranException { | ||
DeleteExistingSvgFilesException(String message) | ||
: super('Error occurred while deleting existing SVG files: $message', 'DELETE_EXISTING_SVG_FILES_ERROR'); | ||
} | ||
|
||
class DeleteZipFileException extends QuranException { | ||
DeleteZipFileException(String message) | ||
: super('Error occurred while deleting zip file: $message', 'DELETE_ZIP_FILE_ERROR'); | ||
} | ||
|
||
class ExtractZipFileException extends QuranException { | ||
ExtractZipFileException(String message) | ||
: super('Error occurred while extracting zip file: $message', 'EXTRACT_ZIP_FILE_ERROR'); | ||
} | ||
|
||
class CreateDirectoryException extends QuranException { | ||
CreateDirectoryException(String message) | ||
: super('Error occurred while creating directory: $message', 'CREATE_DIRECTORY_ERROR'); | ||
} | ||
|
||
class FileNotFOUNDException extends QuranException { | ||
FileNotFOUNDException(String message) : super('File not found: $message', 'FILE_NOT_FOUND_ERROR'); | ||
} | ||
|
||
class InvalidZipFileException extends QuranException { | ||
InvalidZipFileException(String message) : super('Invalid zip file: $message', 'INVALID_ZIP_FILE_ERROR'); | ||
} | ||
|
||
class ZipFileAlreadyExtractedException extends QuranException { | ||
ZipFileAlreadyExtractedException(String message) | ||
: super('Zip file already extracted: $message', 'ZIP_FILE_ALREADY_EXTRACTED_ERROR'); | ||
} | ||
|
||
class UnknownException extends QuranException { | ||
UnknownException(String message) : super('Unknown error: $message', 'UNKNOWN_ERROR'); | ||
} |
Oops, something went wrong.