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
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()));
|
|
}
|
|
}
|