You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

240 lines
8.2 KiB

import 'dart:async';
import 'package:bloc/bloc.dart';
import 'package:hadi_hoda_flutter/core/params/no_params.dart';
import 'package:hadi_hoda_flutter/core/status/base_status.dart';
import 'package:hadi_hoda_flutter/core/utils/pre_cache_image.dart';
import 'package:hadi_hoda_flutter/features/download/domain/entities/download_entity.dart';
import 'package:hadi_hoda_flutter/features/download/domain/usecases/batch_download_usecase.dart';
import 'package:hadi_hoda_flutter/features/download/domain/usecases/cancel_download_usecase.dart';
import 'package:hadi_hoda_flutter/features/download/domain/usecases/get_last_downloaded_level.dart';
import 'package:hadi_hoda_flutter/features/download/domain/usecases/loading_stream_usecase.dart';
import 'package:hadi_hoda_flutter/features/download/domain/usecases/save_levels_usecase.dart';
import 'package:hadi_hoda_flutter/features/download/presentation/bloc/download_event.dart';
import 'package:hadi_hoda_flutter/features/download/presentation/bloc/download_state.dart';
class DownloadBloc extends Bloc<DownloadEvent, DownloadState> {
/// ------------constructor------------
DownloadBloc(
this._loadingStreamUseCase,
this._saveLevelsUseCase,
this._cancelDownloadUseCase,
this._getLastDownloadedLevel,
this._batchDownloadUseCase,
) : super(const DownloadState()) {
preCacheImages();
on<StartDownloadEvent>(_startDownloadEvent);
on<SaveLevelsEvent>(_saveLevelsEvent);
on<CancelDownloadEvent>(_cancelDownloadEvent);
loadingStream = _loadingStreamUseCase();
}
/// ------------UseCases------------
final SaveLevelsUseCase _saveLevelsUseCase;
final BatchDownloadUseCase _batchDownloadUseCase;
final LoadingStreamUseCase _loadingStreamUseCase;
final CancelDownloadUseCase _cancelDownloadUseCase;
final GetLastDownloadedLevel _getLastDownloadedLevel;
Stream<DownloadEntity> loadingStream = const Stream.empty();
bool _isDownloading = false;
bool _isCancelled = false;
bool get isDownloading => _isDownloading;
FutureOr<void> _startDownloadEvent(
StartDownloadEvent event,
Emitter<DownloadState> emit,
) async {
_isCancelled = false;
_isDownloading = true;
emit(state.copyWith(status: const BaseLoading()));
final levelResult = await _saveLevelsUseCase(NoParams());
if (levelResult.isError) {
_isDownloading = false;
emit(state.copyWith(status: BaseError(levelResult.error!.errorMessage)));
return;
}
final downloadResult = await _batchDownloadUseCase(event.toLevel);
downloadResult.fold(
(_) {
_isDownloading = false;
emit(state.copyWith(status: const BaseComplete('')));
},
(e) {
_isDownloading = false;
emit(state.copyWith(status: BaseError(e.errorMessage)));
},
);
// if (event.types.contains(DownloadType.levels)) {
// await LocalStorage.saveData(
// key: MyConstants.firstDownload,
// value: 'true',
// );
// }
// if (MyContext.get.mounted && event.destinationRoute != null) {
// MyContext.get.goNamed(event.destinationRoute!);
// }
}
Future<int> lastDownloadedLevel() async =>
(await _getLastDownloadedLevel(NoParams())).data ?? 0;
/// Orchestrates batch download (level-by-level).
/// If a download is already in progress, just updates the destination
/// so the running download navigates there when it finishes.
// FutureOr<void> _startBatchDownloadEvent(
// StartBatchDownloadEvent event,
// Emitter<DownloadState> emit,
// ) async {
// _isCancelled = false;
// final String lang = event.batchParams.lang;
// final int alreadyDownloaded = int.tryParse(
// LocalStorage.readData(key: '${MyConstants.downloadedLevelCount}_$lang') ?? '0',
// ) ?? 0;
// final int neededUpTo =
// event.batchParams.batchStart + event.batchParams.batchSize - 1;
//
// // Already downloaded — skip straight to destination.
// if (alreadyDownloaded >= neededUpTo) {
// emit(state.copyWith(getFilesStatus: const BaseComplete('')));
// if (MyContext.get.mounted && event.destinationRoute != null) {
// MyContext.get.goNamed(
// event.destinationRoute!,
// pathParameters: event.destinationPathParameters ?? {},
// );
// }
// return;
// }
//
// // A download is already running — just update the destination so the
// // ongoing download navigates there when it finishes.
// if (_isBatchDownloading) {
// emit(state.copyWith(
// destinationRoute: event.destinationRoute,
// destinationPathParameters: event.destinationPathParameters,
// ));
// return;
// }
//
// _isBatchDownloading = true;
//
// emit(state.copyWith(
// getFilesStatus: const BaseLoading(),
// batchParams: event.batchParams,
// destinationRoute: event.destinationRoute,
// destinationPathParameters: event.destinationPathParameters,
// ));
//
// final levelsResult = await _saveLevelsUseCase(NoParams());
// if (levelsResult.isError) {
// if (_isCancelled) return;
// _isBatchDownloading = false;
// emit(state.copyWith(
// getFilesStatus: BaseError(levelsResult.error!.errorMessage),
// ));
// return;
// }
//
// if (_isCancelled) return;
// final result = await _batchDownloadUseCase(event.batchParams);
// if (result.isError) {
// if (_isCancelled) return;
// _isBatchDownloading = false;
// emit(state.copyWith(
// getFilesStatus: BaseError(result.error!.errorMessage),
// ));
// return;
// }
//
// if (_isCancelled) return;
// _isBatchDownloading = false;
//
// emit(state.copyWith(getFilesStatus: const BaseComplete('')));
//
// await LocalStorage.saveData(
// key: '${MyConstants.downloadedLevelCount}_$lang',
// value: '$neededUpTo',
// );
//
// await LocalStorage.saveData(
// key: MyConstants.firstDownload,
// value: 'true',
// );
//
// // Read destination from state (may have been updated by a later event).
// if (MyContext.get.mounted && state.destinationRoute != null) {
// MyContext.get.goNamed(
// state.destinationRoute!,
// pathParameters: state.destinationPathParameters ?? {},
// );
// }
// }
/// Downloads images only (standalone, no chaining).
// FutureOr<void> _getImagesEvent(
// GetImagesEvent event,
// Emitter<DownloadState> emit,
// ) async {
// _isCancelled = false;
// emit(state.copyWith(getFilesStatus: const BaseLoading()));
// final result = await _getImagesUseCase(NoParams());
// if (result.isError) {
// if (_isCancelled) return;
// emit(state.copyWith(getFilesStatus: BaseError(result.error!.errorMessage)));
// } else {
// if (_isCancelled) return;
// emit(state.copyWith(getFilesStatus: const BaseComplete('')));
// }
// }
/// Downloads audios only (standalone, no chaining).
// FutureOr<void> _getAudiosEvent(
// GetAudiosEvent event,
// Emitter<DownloadState> emit,
// ) async {
// _isCancelled = false;
// emit(state.copyWith(getFilesStatus: const BaseLoading()));
// final result = await _getAudiosUseCase(NoParams());
// if (result.isError) {
// if (_isCancelled) return;
// emit(state.copyWith(getFilesStatus: BaseError(result.error!.errorMessage)));
// } else {
// if (_isCancelled) return;
// emit(state.copyWith(getFilesStatus: const BaseComplete('')));
// }
// }
/// Saves levels only (standalone, no chaining).
FutureOr<void> _saveLevelsEvent(
SaveLevelsEvent event,
Emitter<DownloadState> emit,
) async {
_isCancelled = false;
emit(state.copyWith(status: const BaseLoading()));
final result = await _saveLevelsUseCase(NoParams());
if (result.isError) {
if (_isCancelled) return;
emit(state.copyWith(status: BaseError(result.error!.errorMessage)));
} else {
if (_isCancelled) return;
emit(state.copyWith(status: const BaseComplete('')));
}
}
FutureOr<void> _cancelDownloadEvent(
CancelDownloadEvent event,
Emitter<DownloadState> emit,
) {
_isCancelled = true;
_isDownloading = false;
_cancelDownloadUseCase(NoParams());
emit(state.copyWith(status: const BaseInit()));
}
}