import 'dart:async'; import 'dart:convert'; import 'dart:io'; import 'package:flutter/services.dart'; import 'package:flutter_archive/flutter_archive.dart'; import 'package:hadi_hoda_flutter/core/constants/my_constants.dart'; import 'package:hadi_hoda_flutter/core/error_handler/my_exception.dart'; import 'package:hadi_hoda_flutter/core/network/http_request.dart'; import 'package:hadi_hoda_flutter/core/response/base_response.dart'; import 'package:hadi_hoda_flutter/features/level/data/model/level_model.dart'; import 'package:hadi_hoda_flutter/features/level/domain/entity/level_entity.dart'; import 'package:hive/hive.dart'; import 'package:path_provider/path_provider.dart'; abstract class IIntroDatasource { Future saveLevels(); Future extractData(); Stream loadingStream(); } class IntroDatasourceImpl implements IIntroDatasource { final IHttpRequest httpRequest; final StreamController streamController = StreamController.broadcast(); IntroDatasourceImpl(this.httpRequest); @override Future saveLevels() async { try { final Box levelBox = Hive.box(MyConstants.levelBox); if (levelBox.isEmpty) { final String levelAssets = await rootBundle.loadString( 'assets/json/levels.json', ); final dynamic response = jsonDecode(levelAssets); final List levelList = BaseResponse.getDataList( response?['result'], (json) => LevelModel.fromJson(json), ); await levelBox.addAll(levelList); } } catch (e) { throw MyException(errorMessage: '$e'); } } @override Future extractData() async { try { final Directory dir = await getApplicationDocumentsDirectory(); final File file = File('${dir.path}/data.zip'); if (!(await file.exists())) { final ByteData assetFile = await rootBundle.load('assets/data/data.zip'); await file.create(recursive: true); await file.writeAsBytes( assetFile.buffer.asUint8List( assetFile.offsetInBytes, assetFile.lengthInBytes, ), flush: true, ); await ZipFile.extractToDirectory( zipFile: file, destinationDir: dir, onExtracting: (zipEntry, progress) { streamController.add(progress); return ZipFileOperation.includeItem; }, ); } else { streamController.add(20); await Future.delayed(Duration(milliseconds: 150)); streamController.add(40); await Future.delayed(Duration(milliseconds: 150)); streamController.add(60); await Future.delayed(Duration(milliseconds: 150)); streamController.add(80); await Future.delayed(Duration(milliseconds: 150)); streamController.add(100); await Future.delayed(Duration(milliseconds: 150)); } } catch (e) { throw MyException(errorMessage: '$e'); } } @override Stream loadingStream() => streamController.stream; }