54 changed files with 1485 additions and 566 deletions
-
BINassets/videos/globe_state_speaking.gif
-
6lib/core/constants/my_api.dart
-
14lib/core/constants/my_constants.dart
-
6lib/core/middlewares/my_middlewares.dart
-
1lib/core/network/http_request.dart
-
6lib/core/network/http_request_impl.dart
-
25lib/core/routers/my_routes.dart
-
1lib/core/widgets/answer_box/styles/picture_box.dart
-
18lib/features/app/presentation/bloc/app_bloc.dart
-
311lib/features/download/data/datasource/download_datasource.dart
-
61lib/features/download/data/repository_impl/download_repository_impl.dart
-
27lib/features/download/domain/entities/download_entity.dart
-
7lib/features/download/domain/repository/download_repository.dart
-
17lib/features/download/domain/usecases/batch_download_usecase.dart
-
12lib/features/download/domain/usecases/cancel_download_usecase.dart
-
32lib/features/download/domain/usecases/get_audios_usecase.dart
-
32lib/features/download/domain/usecases/get_images_usecase.dart
-
17lib/features/download/domain/usecases/get_last_downloaded_level.dart
-
251lib/features/download/presentation/bloc/download_bloc.dart
-
26lib/features/download/presentation/bloc/download_event.dart
-
11lib/features/download/presentation/bloc/download_state.dart
-
92lib/features/download/presentation/ui/download_page.dart
-
4lib/features/download/presentation/ui/widgets/download_loading_widget.dart
-
7lib/features/guider/data/datasource/guider_datasource.dart
-
41lib/features/home/presentation/bloc/home_bloc.dart
-
44lib/features/home/presentation/ui/home_page.dart
-
19lib/features/language/data/datasource/language_datasource.dart
-
12lib/features/language/data/model/language_model.dart
-
52lib/features/language/data/repository_impl/language_repository_impl.dart
-
27lib/features/language/domain/entity/language_entity.dart
-
9lib/features/language/domain/repository/language_repository.dart
-
17lib/features/language/domain/usecases/get_languages_usecase.dart
-
16lib/features/language/domain/usecases/get_selected_language_usecase.dart
-
16lib/features/language/domain/usecases/save_selected_language_usecase.dart
-
105lib/features/language/presentation/bloc/language_bloc.dart
-
16lib/features/language/presentation/bloc/language_event.dart
-
21lib/features/language/presentation/bloc/language_state.dart
-
199lib/features/language/presentation/ui/language_page.dart
-
8lib/features/level/data/datasource/level_datasource.dart
-
2lib/features/level/data/model/level_model.dart
-
100lib/features/level/presentation/bloc/level_bloc.dart
-
55lib/features/level/presentation/ui/level_page.dart
-
8lib/features/question/data/datasource/question_datasource.dart
-
4lib/features/question/data/model/answer_model.dart
-
6lib/features/question/data/model/question_model.dart
-
7lib/features/question/domain/entity/answer_entity.dart
-
9lib/features/question/domain/entity/question_entity.dart
-
3lib/features/question/presentation/bloc/question_bloc.dart
-
3lib/features/question/presentation/ui/question_page.dart
-
2lib/features/splash/presentation/ui/splash_page.dart
-
28lib/init_bindings.dart
-
16lib/main.dart
-
2pubspec.yaml
|
Before Width: 320 | Height: 320 | Size: 2.2 MiB After Width: 800 | Height: 800 | Size: 6.3 MiB |
@ -1,7 +1,26 @@ |
|||||
class DownloadEntity { |
class DownloadEntity { |
||||
final double? count; |
|
||||
final double? total; |
|
||||
final double? percent; |
|
||||
|
final int downloadedLevels; |
||||
|
final double percent; |
||||
|
|
||||
|
const DownloadEntity({ |
||||
|
required this.downloadedLevels, |
||||
|
required this.percent, |
||||
|
}); |
||||
|
|
||||
|
factory DownloadEntity.empty() { |
||||
|
return const DownloadEntity(downloadedLevels: 0, percent: 0); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
class DownloadPageConfig { |
||||
|
final int downloadToLevel; |
||||
|
final String redirectTo; |
||||
|
final Map<String, String> routeParams; |
||||
|
|
||||
|
const DownloadPageConfig({ |
||||
|
required this.downloadToLevel, |
||||
|
required this.redirectTo, |
||||
|
this.routeParams = const {}, |
||||
|
}); |
||||
|
|
||||
const DownloadEntity({this.count, this.total, this.percent}); |
|
||||
} |
} |
||||
@ -0,0 +1,17 @@ |
|||||
|
import 'package:hadi_hoda_flutter/core/error_handler/my_exception.dart'; |
||||
|
import 'package:hadi_hoda_flutter/core/params/no_params.dart'; |
||||
|
import 'package:hadi_hoda_flutter/core/usecase/usecase.dart'; |
||||
|
import 'package:hadi_hoda_flutter/core/utils/data_state.dart'; |
||||
|
import 'package:hadi_hoda_flutter/features/download/domain/entities/download_entity.dart'; |
||||
|
import 'package:hadi_hoda_flutter/features/download/domain/repository/download_repository.dart'; |
||||
|
|
||||
|
class BatchDownloadUseCase implements UseCase<NoParams, int> { |
||||
|
final IDownloadRepository repository; |
||||
|
|
||||
|
const BatchDownloadUseCase(this.repository); |
||||
|
|
||||
|
@override |
||||
|
Future<DataState<NoParams, MyException>> call(int toLevel) { |
||||
|
return repository.batchDownload(toLevel); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,12 @@ |
|||||
|
import 'package:hadi_hoda_flutter/core/params/no_params.dart'; |
||||
|
import 'package:hadi_hoda_flutter/features/download/domain/repository/download_repository.dart'; |
||||
|
|
||||
|
class CancelDownloadUseCase { |
||||
|
final IDownloadRepository repository; |
||||
|
|
||||
|
CancelDownloadUseCase(this.repository); |
||||
|
|
||||
|
void call(NoParams params) { |
||||
|
repository.cancelDownload(); |
||||
|
} |
||||
|
} |
||||
@ -1,16 +1,16 @@ |
|||||
import 'package:hadi_hoda_flutter/core/error_handler/my_exception.dart'; |
|
||||
import 'package:hadi_hoda_flutter/core/params/no_params.dart'; |
|
||||
import 'package:hadi_hoda_flutter/core/usecase/usecase.dart'; |
|
||||
import 'package:hadi_hoda_flutter/core/utils/data_state.dart'; |
|
||||
import 'package:hadi_hoda_flutter/features/download/domain/repository/download_repository.dart'; |
|
||||
|
|
||||
class GetAudiosUseCase implements UseCase<NoParams, NoParams> { |
|
||||
final IDownloadRepository repository; |
|
||||
|
|
||||
const GetAudiosUseCase(this.repository); |
|
||||
|
|
||||
@override |
|
||||
Future<DataState<NoParams, MyException>> call(NoParams params) { |
|
||||
return repository.getAudios(); |
|
||||
} |
|
||||
} |
|
||||
|
// import 'package:hadi_hoda_flutter/core/error_handler/my_exception.dart'; |
||||
|
// import 'package:hadi_hoda_flutter/core/params/no_params.dart'; |
||||
|
// import 'package:hadi_hoda_flutter/core/usecase/usecase.dart'; |
||||
|
// import 'package:hadi_hoda_flutter/core/utils/data_state.dart'; |
||||
|
// import 'package:hadi_hoda_flutter/features/download/domain/repository/download_repository.dart'; |
||||
|
// |
||||
|
// class GetAudiosUseCase implements UseCase<NoParams, NoParams> { |
||||
|
// final IDownloadRepository repository; |
||||
|
// |
||||
|
// const GetAudiosUseCase(this.repository); |
||||
|
// |
||||
|
// @override |
||||
|
// Future<DataState<NoParams, MyException>> call(NoParams params) { |
||||
|
// return repository.getAudios(); |
||||
|
// } |
||||
|
// } |
||||
@ -1,16 +1,16 @@ |
|||||
import 'package:hadi_hoda_flutter/core/error_handler/my_exception.dart'; |
|
||||
import 'package:hadi_hoda_flutter/core/params/no_params.dart'; |
|
||||
import 'package:hadi_hoda_flutter/core/usecase/usecase.dart'; |
|
||||
import 'package:hadi_hoda_flutter/core/utils/data_state.dart'; |
|
||||
import 'package:hadi_hoda_flutter/features/download/domain/repository/download_repository.dart'; |
|
||||
|
|
||||
class GetImagesUseCase implements UseCase<NoParams, NoParams> { |
|
||||
final IDownloadRepository repository; |
|
||||
|
|
||||
const GetImagesUseCase(this.repository); |
|
||||
|
|
||||
@override |
|
||||
Future<DataState<NoParams, MyException>> call(NoParams params) { |
|
||||
return repository.getImages(); |
|
||||
} |
|
||||
} |
|
||||
|
// import 'package:hadi_hoda_flutter/core/error_handler/my_exception.dart'; |
||||
|
// import 'package:hadi_hoda_flutter/core/params/no_params.dart'; |
||||
|
// import 'package:hadi_hoda_flutter/core/usecase/usecase.dart'; |
||||
|
// import 'package:hadi_hoda_flutter/core/utils/data_state.dart'; |
||||
|
// import 'package:hadi_hoda_flutter/features/download/domain/repository/download_repository.dart'; |
||||
|
// |
||||
|
// class GetImagesUseCase implements UseCase<NoParams, NoParams> { |
||||
|
// final IDownloadRepository repository; |
||||
|
// |
||||
|
// const GetImagesUseCase(this.repository); |
||||
|
// |
||||
|
// @override |
||||
|
// Future<DataState<NoParams, MyException>> call(NoParams params) { |
||||
|
// return repository.getImages(); |
||||
|
// } |
||||
|
// } |
||||
@ -0,0 +1,17 @@ |
|||||
|
import 'package:hadi_hoda_flutter/core/error_handler/my_exception.dart'; |
||||
|
import 'package:hadi_hoda_flutter/core/params/no_params.dart'; |
||||
|
import 'package:hadi_hoda_flutter/core/usecase/usecase.dart'; |
||||
|
import 'package:hadi_hoda_flutter/core/utils/data_state.dart'; |
||||
|
import 'package:hadi_hoda_flutter/features/download/domain/entities/download_entity.dart'; |
||||
|
import 'package:hadi_hoda_flutter/features/download/domain/repository/download_repository.dart'; |
||||
|
|
||||
|
class GetLastDownloadedLevel implements UseCase<int, NoParams> { |
||||
|
final IDownloadRepository repository; |
||||
|
|
||||
|
const GetLastDownloadedLevel(this.repository); |
||||
|
|
||||
|
@override |
||||
|
Future<DataState<int, MyException>> call(NoParams noParams) { |
||||
|
return repository.getLastDownloadLevel(); |
||||
|
} |
||||
|
} |
||||
@ -1,6 +1,28 @@ |
|||||
|
import 'package:hadi_hoda_flutter/features/download/domain/entities/download_entity.dart'; |
||||
|
|
||||
sealed class DownloadEvent { |
sealed class DownloadEvent { |
||||
const DownloadEvent(); |
const DownloadEvent(); |
||||
} |
} |
||||
class GetImagesEvent extends DownloadEvent {} |
|
||||
class GetAudiosEvent extends DownloadEvent {} |
|
||||
|
|
||||
|
class StartDownloadEvent extends DownloadEvent { |
||||
|
final int toLevel; |
||||
|
|
||||
|
const StartDownloadEvent({required this.toLevel}); |
||||
|
} |
||||
|
// |
||||
|
// class StartBatchDownloadEvent extends DownloadEvent { |
||||
|
// final BatchDownloadParams batchParams; |
||||
|
// final String? destinationRoute; |
||||
|
// final Map<String, String>? destinationPathParameters; |
||||
|
// |
||||
|
// const StartBatchDownloadEvent({ |
||||
|
// required this.batchParams, |
||||
|
// this.destinationRoute, |
||||
|
// this.destinationPathParameters, |
||||
|
// }); |
||||
|
// } |
||||
|
|
||||
|
// class GetImagesEvent extends DownloadEvent {} |
||||
|
// class GetAudiosEvent extends DownloadEvent {} |
||||
class SaveLevelsEvent extends DownloadEvent {} |
class SaveLevelsEvent extends DownloadEvent {} |
||||
|
class CancelDownloadEvent extends DownloadEvent {} |
||||
@ -1,15 +1,18 @@ |
|||||
import 'package:hadi_hoda_flutter/core/status/base_status.dart'; |
import 'package:hadi_hoda_flutter/core/status/base_status.dart'; |
||||
|
import 'package:hadi_hoda_flutter/features/download/domain/entities/download_entity.dart'; |
||||
|
|
||||
class DownloadState { |
class DownloadState { |
||||
final BaseStatus getFilesStatus; |
|
||||
|
final BaseStatus status; |
||||
|
|
||||
const DownloadState({this.getFilesStatus = const BaseInit()}); |
|
||||
|
const DownloadState({ |
||||
|
this.status = const BaseInit(), |
||||
|
}); |
||||
|
|
||||
DownloadState copyWith({ |
DownloadState copyWith({ |
||||
BaseStatus? getFilesStatus, |
|
||||
|
BaseStatus? status, |
||||
}) { |
}) { |
||||
return DownloadState( |
return DownloadState( |
||||
getFilesStatus: getFilesStatus ?? this.getFilesStatus, |
|
||||
|
status: status ?? this.status, |
||||
); |
); |
||||
} |
} |
||||
} |
} |
||||
@ -0,0 +1,19 @@ |
|||||
|
import 'package:hadi_hoda_flutter/core/constants/my_api.dart'; |
||||
|
import 'package:hadi_hoda_flutter/core/network/http_request.dart'; |
||||
|
import 'package:hadi_hoda_flutter/features/language/data/model/language_model.dart'; |
||||
|
|
||||
|
abstract class ILanguageDatasource { |
||||
|
Future<List<LanguageModel>> getLanguages(); |
||||
|
} |
||||
|
|
||||
|
class LanguageDatasourceImpl implements ILanguageDatasource { |
||||
|
final IHttpRequest httpRequest; |
||||
|
|
||||
|
LanguageDatasourceImpl(this.httpRequest); |
||||
|
|
||||
|
@override |
||||
|
Future<List<LanguageModel>> getLanguages() async { |
||||
|
final response = await httpRequest.get(path: MyApi.languages); |
||||
|
return (response['results'] as List).map((e) => LanguageModel.fromJson(e)).toList(); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,12 @@ |
|||||
|
import 'package:hadi_hoda_flutter/features/language/domain/entity/language_entity.dart'; |
||||
|
|
||||
|
class LanguageModel extends LanguageEntity { |
||||
|
const LanguageModel({required super.code, required super.title}); |
||||
|
|
||||
|
factory LanguageModel.fromJson(Map<String, dynamic> json) { |
||||
|
return LanguageModel( |
||||
|
code: json['code'] ?? '', |
||||
|
title: json['name'] ?? '', // API returns 'name', we map to 'title' |
||||
|
); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,52 @@ |
|||||
|
import 'dart:io'; |
||||
|
|
||||
|
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/utils/data_state.dart'; |
||||
|
import 'package:hadi_hoda_flutter/core/utils/local_storage.dart'; |
||||
|
import 'package:hadi_hoda_flutter/features/language/data/datasource/language_datasource.dart'; |
||||
|
import 'package:hadi_hoda_flutter/features/language/domain/entity/language_entity.dart'; |
||||
|
import 'package:hadi_hoda_flutter/features/language/domain/repository/language_repository.dart'; |
||||
|
|
||||
|
class LanguageRepositoryImpl implements ILanguageRepository { |
||||
|
final ILanguageDatasource languageDatasource; |
||||
|
|
||||
|
LanguageRepositoryImpl(this.languageDatasource); |
||||
|
|
||||
|
@override |
||||
|
Future<DataState<List<LanguageEntity>, MyException>> getLanguages() async { |
||||
|
try { |
||||
|
final languages = await languageDatasource.getLanguages(); |
||||
|
// Explicitly convert to a List<LanguageEntity> to prevent runtime type errors. |
||||
|
return DataState.success(List<LanguageEntity>.from(languages)); |
||||
|
} on MyException catch (e) { |
||||
|
return DataState.error(e); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@override |
||||
|
LanguageEntity getSelectedLanguage(List<LanguageEntity> languages) { |
||||
|
final savedLanguageCode = LocalStorage.readData(key: MyConstants.selectLanguage); |
||||
|
|
||||
|
if (savedLanguageCode != null) { |
||||
|
return languages.firstWhere((lang) => lang.code == savedLanguageCode, |
||||
|
orElse: () => _getFallbackLanguage(languages)); |
||||
|
} |
||||
|
|
||||
|
final deviceLanguageCode = Platform.localeName.split('_').first; |
||||
|
return languages.firstWhere((lang) => lang.code == deviceLanguageCode, |
||||
|
orElse: () => _getFallbackLanguage(languages)); |
||||
|
} |
||||
|
|
||||
|
@override |
||||
|
Future<void> saveSelectedLanguage(String code) async { |
||||
|
await LocalStorage.saveData(key: MyConstants.selectLanguage, value: code); |
||||
|
} |
||||
|
|
||||
|
LanguageEntity _getFallbackLanguage(List<LanguageEntity> languages) { |
||||
|
return languages.firstWhere( |
||||
|
(lang) => lang.code == MyConstants.defaultLanguage, |
||||
|
orElse: () => languages.first, |
||||
|
); |
||||
|
} |
||||
|
} |
||||
@ -1,21 +1,20 @@ |
|||||
|
import 'dart:ui'; |
||||
import 'package:equatable/equatable.dart'; |
import 'package:equatable/equatable.dart'; |
||||
import 'package:flutter/material.dart'; |
|
||||
|
|
||||
class LanguageEntity extends Equatable { |
class LanguageEntity extends Equatable { |
||||
final String? title; |
|
||||
final String? code; |
|
||||
final Locale? locale; |
|
||||
|
final String code; |
||||
|
final String title; |
||||
|
|
||||
const LanguageEntity({ |
|
||||
this.title, |
|
||||
this.code, |
|
||||
this.locale, |
|
||||
}); |
|
||||
|
const LanguageEntity({required this.code, required this.title}); |
||||
|
|
||||
|
Locale get locale { |
||||
|
final parts = code.split('_'); |
||||
|
if (parts.length > 1) { |
||||
|
return Locale(parts[0], parts[1]); |
||||
|
} |
||||
|
return Locale(parts[0]); |
||||
|
} |
||||
|
|
||||
@override |
@override |
||||
List<Object?> get props => [ |
|
||||
title, |
|
||||
code, |
|
||||
locale, |
|
||||
]; |
|
||||
|
List<Object?> get props => [code, title]; |
||||
} |
} |
||||
@ -0,0 +1,9 @@ |
|||||
|
import 'package:hadi_hoda_flutter/core/error_handler/my_exception.dart'; |
||||
|
import 'package:hadi_hoda_flutter/core/utils/data_state.dart'; |
||||
|
import 'package:hadi_hoda_flutter/features/language/domain/entity/language_entity.dart'; |
||||
|
|
||||
|
abstract class ILanguageRepository { |
||||
|
Future<DataState<List<LanguageEntity>, MyException>> getLanguages(); |
||||
|
LanguageEntity getSelectedLanguage(List<LanguageEntity> languages); |
||||
|
Future<void> saveSelectedLanguage(String code); |
||||
|
} |
||||
@ -0,0 +1,17 @@ |
|||||
|
import 'package:hadi_hoda_flutter/core/error_handler/my_exception.dart'; |
||||
|
import 'package:hadi_hoda_flutter/core/params/no_params.dart'; |
||||
|
import 'package:hadi_hoda_flutter/core/usecase/usecase.dart'; |
||||
|
import 'package:hadi_hoda_flutter/core/utils/data_state.dart'; |
||||
|
import 'package:hadi_hoda_flutter/features/language/domain/entity/language_entity.dart'; |
||||
|
import 'package:hadi_hoda_flutter/features/language/domain/repository/language_repository.dart'; |
||||
|
|
||||
|
class GetLanguagesUseCase implements UseCase<List<LanguageEntity>, NoParams> { |
||||
|
final ILanguageRepository repository; |
||||
|
|
||||
|
GetLanguagesUseCase(this.repository); |
||||
|
|
||||
|
@override |
||||
|
Future<DataState<List<LanguageEntity>, MyException>> call(NoParams params) { |
||||
|
return repository.getLanguages(); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,16 @@ |
|||||
|
import 'package:hadi_hoda_flutter/core/error_handler/my_exception.dart'; |
||||
|
import 'package:hadi_hoda_flutter/core/usecase/usecase.dart'; |
||||
|
import 'package:hadi_hoda_flutter/core/utils/data_state.dart'; |
||||
|
import 'package:hadi_hoda_flutter/features/language/domain/entity/language_entity.dart'; |
||||
|
import 'package:hadi_hoda_flutter/features/language/domain/repository/language_repository.dart'; |
||||
|
|
||||
|
class GetSelectedLanguageUseCase implements UseCase<LanguageEntity, List<LanguageEntity>> { |
||||
|
final ILanguageRepository repository; |
||||
|
|
||||
|
GetSelectedLanguageUseCase(this.repository); |
||||
|
|
||||
|
@override |
||||
|
Future<DataState<LanguageEntity, MyException>> call(List<LanguageEntity> params) async { |
||||
|
return DataState.success(repository.getSelectedLanguage(params)); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,16 @@ |
|||||
|
import 'package:hadi_hoda_flutter/core/error_handler/my_exception.dart'; |
||||
|
import 'package:hadi_hoda_flutter/core/usecase/usecase.dart'; |
||||
|
import 'package:hadi_hoda_flutter/core/utils/data_state.dart'; |
||||
|
import 'package:hadi_hoda_flutter/features/language/domain/repository/language_repository.dart'; |
||||
|
|
||||
|
class SaveSelectedLanguageUseCase implements UseCase<void, String> { |
||||
|
final ILanguageRepository repository; |
||||
|
|
||||
|
SaveSelectedLanguageUseCase(this.repository); |
||||
|
|
||||
|
@override |
||||
|
Future<DataState<void, MyException>> call(String params) async { |
||||
|
await repository.saveSelectedLanguage(params); |
||||
|
return DataState.success(null); |
||||
|
} |
||||
|
} |
||||
@ -1,82 +1,61 @@ |
|||||
import 'dart:async'; |
import 'dart:async'; |
||||
import 'dart:io'; |
|
||||
|
|
||||
import 'package:bloc/bloc.dart'; |
import 'package:bloc/bloc.dart'; |
||||
import 'package:flutter/material.dart'; |
|
||||
import 'package:go_router/go_router.dart'; |
|
||||
import 'package:hadi_hoda_flutter/core/constants/my_constants.dart'; |
|
||||
import 'package:hadi_hoda_flutter/core/routers/my_routes.dart'; |
|
||||
import 'package:hadi_hoda_flutter/core/utils/local_storage.dart'; |
|
||||
import 'package:hadi_hoda_flutter/core/utils/my_context.dart'; |
|
||||
import 'package:hadi_hoda_flutter/core/utils/storage_path.dart'; |
|
||||
import 'package:hadi_hoda_flutter/features/app/presentation/bloc/app_bloc.dart'; |
|
||||
import 'package:hadi_hoda_flutter/features/app/presentation/bloc/app_event.dart'; |
|
||||
import 'package:hadi_hoda_flutter/features/language/domain/entity/language_entity.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/features/language/domain/usecases/get_languages_usecase.dart'; |
||||
|
import 'package:hadi_hoda_flutter/features/language/domain/usecases/get_selected_language_usecase.dart'; |
||||
|
import 'package:hadi_hoda_flutter/features/language/domain/usecases/save_selected_language_usecase.dart'; |
||||
import 'package:hadi_hoda_flutter/features/language/presentation/bloc/language_event.dart'; |
import 'package:hadi_hoda_flutter/features/language/presentation/bloc/language_event.dart'; |
||||
import 'package:hadi_hoda_flutter/features/language/presentation/bloc/language_state.dart'; |
import 'package:hadi_hoda_flutter/features/language/presentation/bloc/language_state.dart'; |
||||
import 'package:hadi_hoda_flutter/init_bindings.dart'; |
|
||||
|
|
||||
class LanguageBloc extends Bloc<LanguageEvent, LanguageState> { |
class LanguageBloc extends Bloc<LanguageEvent, LanguageState> { |
||||
/// ------------constructor------------ |
|
||||
LanguageBloc() : super(const LanguageState()) { |
|
||||
on<ChangeLanguageEvent>(_changeLanguageEvent); |
|
||||
on<SaveLevelsEvent>(_saveLevelsEvent); |
|
||||
on<InitLanguageEvent>(_initLanguageEvent); |
|
||||
} |
|
||||
|
|
||||
/// ------------UseCases------------ |
|
||||
|
|
||||
/// ------------Variables------------ |
|
||||
|
|
||||
/// ------------Controllers------------ |
|
||||
|
final GetLanguagesUseCase _getLanguagesUseCase; |
||||
|
final GetSelectedLanguageUseCase _getSelectedLanguageUseCase; |
||||
|
final SaveSelectedLanguageUseCase _saveSelectedLanguageUseCase; |
||||
|
|
||||
/// ------------Functions------------ |
|
||||
FutureOr<void> _changeLanguageEvent( |
|
||||
ChangeLanguageEvent event, |
|
||||
Emitter<LanguageState> emit, |
|
||||
) { |
|
||||
emit(state.copyWith(selectedLang: event.lang)); |
|
||||
|
LanguageBloc( |
||||
|
this._getLanguagesUseCase, |
||||
|
this._getSelectedLanguageUseCase, |
||||
|
this._saveSelectedLanguageUseCase, |
||||
|
) : super(const LanguageState()) { |
||||
|
on<GetLanguagesEvent>(_onGetLanguagesEvent); |
||||
|
on<SelectLanguageEvent>(_onSelectLanguageEvent); |
||||
} |
} |
||||
|
|
||||
/// ------------Api Calls------------ |
|
||||
FutureOr<void> _saveLevelsEvent( |
|
||||
SaveLevelsEvent event, |
|
||||
|
FutureOr<void> _onGetLanguagesEvent( |
||||
|
GetLanguagesEvent event, |
||||
Emitter<LanguageState> emit, |
Emitter<LanguageState> emit, |
||||
) async { |
) async { |
||||
await Future.wait([ |
|
||||
LocalStorage.saveData( |
|
||||
key: MyConstants.selectLanguage, |
|
||||
value: state.selectedLang.code ?? MyConstants.defaultLanguage, |
|
||||
), |
|
||||
]); |
|
||||
final AppBloc appBloc = locator(); |
|
||||
appBloc.add( |
|
||||
ChangeLocaleEvent(state.selectedLang.locale ?? const Locale('en', 'US'))); |
|
||||
|
emit(state.copyWith(getLanguagesStatus: const BaseLoading())); |
||||
|
|
||||
if (Directory( |
|
||||
'${StoragePath.documentDir.path}/${state.selectedLang |
|
||||
.code}/answer_audio') |
|
||||
.existsSync() && Directory( |
|
||||
'${StoragePath.documentDir.path}/${state.selectedLang |
|
||||
.code}/question_audio') |
|
||||
.existsSync()) { |
|
||||
if (MyContext.get.mounted) { |
|
||||
MyContext.get.goNamed(Routes.homePage); |
|
||||
} |
|
||||
|
final result = await _getLanguagesUseCase(NoParams()); |
||||
|
|
||||
|
if (result.isSuccess) { |
||||
|
final languages = result.data!; |
||||
|
final selectedResult = await _getSelectedLanguageUseCase(languages); |
||||
|
|
||||
|
emit( |
||||
|
state.copyWith( |
||||
|
getLanguagesStatus: const BaseComplete(''), |
||||
|
languages: languages, |
||||
|
selectedLanguage: selectedResult.data, |
||||
|
), |
||||
|
); |
||||
} else { |
} else { |
||||
await Future.wait([ |
|
||||
LocalStorage.deleteData(key: MyConstants.downloadedAudio), |
|
||||
LocalStorage.deleteData(key: MyConstants.extractedAudio), |
|
||||
]); |
|
||||
if (MyContext.get.mounted) { |
|
||||
MyContext.get.goNamed(Routes.downloadPage); |
|
||||
} |
|
||||
|
emit( |
||||
|
state.copyWith( |
||||
|
getLanguagesStatus: BaseError(result.error!.errorMessage), |
||||
|
), |
||||
|
); |
||||
} |
} |
||||
} |
} |
||||
|
|
||||
FutureOr<void> _initLanguageEvent(InitLanguageEvent event, Emitter<LanguageState> emit) { |
|
||||
final String selectedLanguage = LocalStorage.readData( |
|
||||
key: MyConstants.selectLanguage) ?? MyConstants.defaultLanguage; |
|
||||
emit(state.copyWith(selectedLang: LanguageEntity(code: selectedLanguage))); |
|
||||
|
FutureOr<void> _onSelectLanguageEvent( |
||||
|
SelectLanguageEvent event, |
||||
|
Emitter<LanguageState> emit, |
||||
|
) async { |
||||
|
await _saveSelectedLanguageUseCase(event.language.code); |
||||
|
emit(state.copyWith(selectedLanguage: event.language)); |
||||
} |
} |
||||
} |
} |
||||
@ -1,23 +1,26 @@ |
|||||
import 'package:hadi_hoda_flutter/core/constants/my_constants.dart'; |
|
||||
import 'package:hadi_hoda_flutter/core/status/base_status.dart'; |
import 'package:hadi_hoda_flutter/core/status/base_status.dart'; |
||||
import 'package:hadi_hoda_flutter/features/language/domain/entity/language_entity.dart'; |
import 'package:hadi_hoda_flutter/features/language/domain/entity/language_entity.dart'; |
||||
|
|
||||
class LanguageState { |
class LanguageState { |
||||
final BaseStatus saveLevelsStatus; |
|
||||
final LanguageEntity selectedLang; |
|
||||
|
final BaseStatus getLanguagesStatus; |
||||
|
final List<LanguageEntity> languages; |
||||
|
final LanguageEntity? selectedLanguage; |
||||
|
|
||||
const LanguageState({ |
const LanguageState({ |
||||
this.saveLevelsStatus = const BaseInit(), |
|
||||
this.selectedLang = const LanguageEntity(code: MyConstants.defaultLanguage), |
|
||||
|
this.getLanguagesStatus = const BaseInit(), |
||||
|
this.languages = const [], |
||||
|
this.selectedLanguage, |
||||
}); |
}); |
||||
|
|
||||
LanguageState copyWith({ |
LanguageState copyWith({ |
||||
BaseStatus? saveLevelsStatus, |
|
||||
LanguageEntity? selectedLang, |
|
||||
|
BaseStatus? getLanguagesStatus, |
||||
|
List<LanguageEntity>? languages, |
||||
|
LanguageEntity? selectedLanguage, |
||||
}) { |
}) { |
||||
return LanguageState( |
return LanguageState( |
||||
saveLevelsStatus: saveLevelsStatus ?? this.saveLevelsStatus, |
|
||||
selectedLang: selectedLang ?? this.selectedLang, |
|
||||
|
getLanguagesStatus: getLanguagesStatus ?? this.getLanguagesStatus, |
||||
|
languages: languages ?? this.languages, |
||||
|
selectedLanguage: selectedLanguage ?? this.selectedLanguage, |
||||
); |
); |
||||
} |
} |
||||
} |
} |
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue