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.
 
 
 
 

524 lines
20 KiB

import 'dart:async';
import 'package:bloc/bloc.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:go_router/go_router.dart';
import 'package:hadi_hoda_flutter/common_ui/resources/my_audios.dart';
import 'package:hadi_hoda_flutter/core/constants/my_constants.dart';
import 'package:hadi_hoda_flutter/core/params/level_params.dart';
import 'package:hadi_hoda_flutter/core/params/no_params.dart';
import 'package:hadi_hoda_flutter/core/routers/my_routes.dart';
import 'package:hadi_hoda_flutter/core/services/audio_service.dart';
import 'package:hadi_hoda_flutter/core/status/base_status.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/screen_size.dart';
import 'package:hadi_hoda_flutter/core/utils/set_platform_size.dart';
import 'package:hadi_hoda_flutter/core/widgets/dialog/reward_dialog.dart';
import 'package:hadi_hoda_flutter/features/download/domain/entities/download_entity.dart';
import 'package:hadi_hoda_flutter/features/download/domain/usecases/get_last_downloaded_level.dart';
import 'package:hadi_hoda_flutter/features/download/presentation/bloc/download_bloc.dart';
import 'package:hadi_hoda_flutter/features/download/presentation/bloc/download_state.dart';
import 'package:hadi_hoda_flutter/features/level/domain/entity/level_entity.dart';
import 'package:hadi_hoda_flutter/features/level/domain/entity/level_location.dart';
import 'package:hadi_hoda_flutter/features/level/domain/entity/node_entity.dart';
import 'package:hadi_hoda_flutter/features/level/domain/entity/prize_entity.dart';
import 'package:hadi_hoda_flutter/features/level/domain/usecases/get_levels_usecase.dart';
import 'package:hadi_hoda_flutter/features/level/presentation/bloc/level_event.dart';
import 'package:hadi_hoda_flutter/features/level/presentation/bloc/level_state.dart';
import 'package:hadi_hoda_flutter/features/level/presentation/ui/widgets/node_widget.dart';
class LevelBloc extends Bloc<LevelEvent, LevelState> {
/// ------------constructor------------
LevelBloc(
this._getLeveslUseCase,
this._mainAudioService,
this._effectAudioService,
this._getLastDownloadedLevel,
) : super(const LevelState()) {
volumeStream = _mainAudioService.volumeStream();
playMusic();
on<GetLevelListEvent>(_getLevelListEvent);
on<SetCurrentLevelEvent>(_setCurrentLevelEvent);
on<StartScrollEvent>(_startScrollEvent);
on<ChooseLevelEvent>(_chooseLevelEvent);
}
@override
Future<void> close() {
scrollController.dispose();
return super.close();
}
/// ------------UseCases------------
final GetLevelsUseCase _getLeveslUseCase;
final GetLastDownloadedLevel _getLastDownloadedLevel;
/// ------------Variables------------
final List<LevelLocation> locationListShort = [
LevelLocation(
bottom: setSize(context: MyContext.get, mobile: -0.03.h, tablet: -0.03.h),
left: setSize(context: MyContext.get, mobile: 0.1.w, tablet: 0.2.w),
),
LevelLocation(
bottom: setSize(context: MyContext.get, mobile: 0.03.h, tablet: 0.075.h),
left: setSize(context: MyContext.get, mobile: 0.28.w, tablet: 0.38.w),
),
LevelLocation(
bottom: setSize(context: MyContext.get, mobile: 0.09.h, tablet: 0.14.h),
left: setSize(context: MyContext.get, mobile: 0.14.w, tablet: 0.18.w),
),
LevelLocation(
bottom: setSize(context: MyContext.get, mobile: 0.17.h, tablet: 0.24.h),
left: setSize(context: MyContext.get, mobile: 0.18.w, tablet: 0.225.w),
),
LevelLocation(
bottom: setSize(context: MyContext.get, mobile: 0.22.h, tablet: 0.33.h),
left: setSize(context: MyContext.get, mobile: 0.36.w, tablet: 0.3.w),
),
LevelLocation(
bottom: setSize(context: MyContext.get, mobile: 0.245.h, tablet: 0.4.h),
left: setSize(context: MyContext.get, mobile: 0.54.w, tablet: 0.55.w),
),
LevelLocation(
bottom: setSize(context: MyContext.get, mobile: 0.305.h, tablet: 0.45.h),
left: setSize(context: MyContext.get, mobile: 0.64.w, tablet: 0.75.w),
),
LevelLocation(
bottom: setSize(context: MyContext.get, mobile: 0.38.h, tablet: 0.68.h),
left: setSize(context: MyContext.get, mobile: 0.61.w, tablet: 0.735.w),
),
LevelLocation(
bottom: setSize(context: MyContext.get, mobile: 0.455.h, tablet: 0.8.h),
left: setSize(context: MyContext.get, mobile: 0.575.w, tablet: 0.68.w),
),
LevelLocation(
bottom: setSize(context: MyContext.get, mobile: 0.53.h, tablet: .951.h),
left: setSize(context: MyContext.get, mobile: 0.575.w, tablet: 0.64.w),
),
LevelLocation(
bottom: setSize(context: MyContext.get, mobile: 0.61.h, tablet: 1.01.h),
left: setSize(context: MyContext.get, mobile: 0.33.w, tablet: 0.27.w),
),
LevelLocation(
bottom: setSize(context: MyContext.get, mobile: 0.593.h, tablet: 1.05.h),
left: setSize(context: MyContext.get, mobile: 0.5.w, tablet: 0.08.w),
),
LevelLocation(
bottom: setSize(context: MyContext.get, mobile: 0.64.h, tablet: 1.17.h),
left: setSize(context: MyContext.get, mobile: 0.143.w, tablet: 0.09.w),
),
LevelLocation(
bottom: setSize(context: MyContext.get, mobile: 0.64.h, tablet: 1.22.h),
left: setSize(context: MyContext.get, mobile: 0.143.w, tablet: 0.34.w),
),
LevelLocation(
bottom: setSize(context: MyContext.get, mobile: 0.686.h, tablet: 1.25.h),
left: setSize(context: MyContext.get, mobile: 0, tablet: 0.53.w),
),
LevelLocation(
bottom: setSize(context: MyContext.get, mobile: 0.74.h, tablet: 1.37.h),
left: setSize(context: MyContext.get, mobile: 0.13.w, tablet: 0.635.w),
),
//////
LevelLocation(
bottom: setSize(context: MyContext.get, mobile: 0.768.h, tablet: 1.43.h),
left: setSize(context: MyContext.get, mobile: 0.31.w, tablet: 0.545.w),
),
/////
LevelLocation(
bottom: setSize(context: MyContext.get, mobile: 0.8.h, tablet: 1.52.h),
left: setSize(context: MyContext.get, mobile: 0.475.w, tablet: 0.55.w),
),
LevelLocation(
bottom: setSize(context: MyContext.get, mobile: 0.885.h, tablet: 1.62.h),
left: setSize(context: MyContext.get, mobile: 0.465.w, tablet: 0.46.w),
),
LevelLocation(
bottom: setSize(context: MyContext.get, mobile: 0.95.h, tablet: 1.636.h),
left: setSize(context: MyContext.get, mobile: 0.47.w, tablet: 0.3.w),
),
LevelLocation(
bottom: setSize(context: MyContext.get, mobile: 1.02.h, tablet: 1.62.h),
left: setSize(context: MyContext.get, mobile: 0.45.w, tablet: 0.11.w),
),
LevelLocation(
bottom: setSize(context: MyContext.get, mobile: 1.02.h, tablet: 1.7.h),
left: setSize(context: MyContext.get, mobile: 0.2.w, tablet: 0.0.w),
),
LevelLocation(
bottom: setSize(context: MyContext.get, mobile: 1.1.h, tablet: 1.858.h),
left: setSize(context: MyContext.get, mobile: 0, tablet: 0.0.w),
),
LevelLocation(
bottom: setSize(context: MyContext.get, mobile: 1.19.h, tablet: 1.89.h),
left: setSize(context: MyContext.get, mobile: 0.05.w, tablet: 0.19.w),
),
LevelLocation(
bottom: setSize(context: MyContext.get, mobile: 1.23.h, tablet: 1.98.h),
left: setSize(context: MyContext.get, mobile: 0.23.w, tablet: 0.3.w),
),
LevelLocation(
bottom: setSize(context: MyContext.get, mobile: 1.31.h, tablet: 2.08.h),
left: setSize(context: MyContext.get, mobile: 0.2.w, tablet: 0.215.w),
),
LevelLocation(
bottom: setSize(context: MyContext.get, mobile: 1.36.h, tablet: 2.15.h),
left: setSize(context: MyContext.get, mobile: 0.09.w, tablet: 0.11.w),
),
LevelLocation(
bottom: setSize(context: MyContext.get, mobile: 1.425.h, tablet: 2.23.h),
left: setSize(context: MyContext.get, mobile: 0.09.w, tablet: 0.1.w),
),
LevelLocation(
bottom: setSize(context: MyContext.get, mobile: 1.48.h, tablet: 2.29.h),
left: setSize(context: MyContext.get, mobile: 0.184.w, tablet: 0.17.w),
),
LevelLocation(
bottom: setSize(context: MyContext.get, mobile: 1.535.h, tablet: 2.36.h),
left: setSize(context: MyContext.get, mobile: 0.22.w, tablet: 0.225.w),
),
];
final List<LevelLocation> locationListLong = [
LevelLocation(
bottom: setSize(context: MyContext.get, mobile: -0.03.h, tablet: -0.03.h),
left: setSize(context: MyContext.get, mobile: 0.1.w, tablet: 0.2.w),
),
LevelLocation(
bottom: setSize(context: MyContext.get, mobile: 0.013.h, tablet: 0.075.h),
left: setSize(context: MyContext.get, mobile: 0.23.w, tablet: 0.38.w),
),
LevelLocation(
bottom: setSize(context: MyContext.get, mobile: 0.08.h, tablet: 0.14.h),
left: setSize(context: MyContext.get, mobile: 0.19.w, tablet: 0.18.w),
),
LevelLocation(
bottom: setSize(context: MyContext.get, mobile: 0.145.h, tablet: 0.24.h),
left: setSize(context: MyContext.get, mobile: 0.15.w, tablet: 0.225.w),
),
LevelLocation(
bottom: setSize(context: MyContext.get, mobile: 0.2.h, tablet: 0.33.h),
left: setSize(context: MyContext.get, mobile: 0.255.w, tablet: 0.3.w),
),
LevelLocation(
bottom: setSize(context: MyContext.get, mobile: 0.237.h, tablet: 0.4.h),
left: setSize(context: MyContext.get, mobile: 0.4.w, tablet: 0.55.w),
),
LevelLocation(
bottom: setSize(context: MyContext.get, mobile: 0.258.h, tablet: 0.45.h),
left: setSize(context: MyContext.get, mobile: 0.56.w, tablet: 0.75.w),
),
LevelLocation(
bottom: setSize(context: MyContext.get, mobile: 0.31.h, tablet: 0.55.h),
left: setSize(context: MyContext.get, mobile: 0.66.w, tablet: 0.799.w),
),
LevelLocation(
bottom: setSize(context: MyContext.get, mobile: 0.38.h, tablet: 0.65.h),
left: setSize(context: MyContext.get, mobile: 0.659.w, tablet: 0.733.w),
),
LevelLocation(
bottom: setSize(context: MyContext.get, mobile: 0.45.h, tablet: 0.78.h),
left: setSize(context: MyContext.get, mobile: 0.59.w, tablet: 0.69.w),
),
LevelLocation(
bottom: setSize(context: MyContext.get, mobile: 0.52.h, tablet: 0.89.h),
left: setSize(context: MyContext.get, mobile: 0.59.w, tablet: 0.7.w),
),
LevelLocation(
bottom: setSize(context: MyContext.get, mobile: 0.592.h, tablet: .987.h),
left: setSize(context: MyContext.get, mobile: 0.56.w, tablet: 0.5.w),
),
LevelLocation(
bottom: setSize(context: MyContext.get, mobile: 0.61.h, tablet: 1.03.h),
left: setSize(context: MyContext.get, mobile: 0.4.w, tablet: 0.18.w),
),
LevelLocation(
bottom: setSize(context: MyContext.get, mobile: 0.63.h, tablet: 1.19.h),
left: setSize(context: MyContext.get, mobile: 0.24.w, tablet: 0.22.w),
),
LevelLocation(
bottom: setSize(context: MyContext.get, mobile: 0.655.h, tablet: 1.19.h),
left: setSize(context: MyContext.get, mobile: 0.10.w, tablet: 0.22.w),
),
LevelLocation(
bottom: setSize(context: MyContext.get, mobile: 0.71.h, tablet: 1.25.h),
left: setSize(context: MyContext.get, mobile: 0.009.w, tablet: 0.53.w),
),
LevelLocation(
bottom: setSize(context: MyContext.get, mobile: 0.75.h, tablet: 1.33.h),
left: setSize(context: MyContext.get, mobile: 0.15.w, tablet: 0.62.w),
),
//////
LevelLocation(
bottom: setSize(context: MyContext.get, mobile: 0.77.h, tablet: 1.43.h),
left: setSize(context: MyContext.get, mobile: 0.31.w, tablet: 0.545.w),
),
/////
LevelLocation(
bottom: setSize(context: MyContext.get, mobile: 0.792.h, tablet: 1.52.h),
left: setSize(context: MyContext.get, mobile: 0.46.w, tablet: 0.55.w),
),
LevelLocation(
bottom: setSize(context: MyContext.get, mobile: 0.905.h, tablet: 1.62.h),
left: setSize(context: MyContext.get, mobile: 0.465.w, tablet: 0.46.w),
),
LevelLocation(
bottom: setSize(context: MyContext.get, mobile: 0.85.h, tablet: 1.62.h),
left: setSize(context: MyContext.get, mobile: 0.525.w, tablet: 0.46.w),
),
LevelLocation(
bottom: setSize(context: MyContext.get, mobile: 0.975.h, tablet: 1.636.h),
left: setSize(context: MyContext.get, mobile: 0.48.w, tablet: 0.3.w),
),
LevelLocation(
bottom: setSize(context: MyContext.get, mobile: 1.02.h, tablet: 1.62.h),
left: setSize(context: MyContext.get, mobile: 0.4.w, tablet: 0.11.w),
),
LevelLocation(
bottom: setSize(context: MyContext.get, mobile: 1.02.h, tablet: 1.7.h),
left: setSize(context: MyContext.get, mobile: 0.25.w, tablet: 0.0.w),
),
LevelLocation(
bottom: setSize(context: MyContext.get, mobile: 1.02.h, tablet: 1.7.h),
left: setSize(context: MyContext.get, mobile: 0.105.w, tablet: 0.0.w),
),
LevelLocation(
bottom: setSize(context: MyContext.get, mobile: 1.03.h, tablet: 1.825.h),
left: setSize(context: MyContext.get, mobile: -0.05.w, tablet: 0.0.w),
),
LevelLocation(
bottom: setSize(context: MyContext.get, mobile: 1.087.h, tablet: 1.88.h),
left: setSize(context: MyContext.get, mobile: 0.01.w, tablet: 0.125.w),
),
LevelLocation(
bottom: setSize(context: MyContext.get, mobile: 1.15.h, tablet: 1.88.h),
left: setSize(context: MyContext.get, mobile: -0.03.w, tablet: 0.125.w),
),
LevelLocation(
bottom: setSize(context: MyContext.get, mobile: 1.19.h, tablet: 1.97.h),
left: setSize(context: MyContext.get, mobile: 0.1.w, tablet: 0.289.w),
),
LevelLocation(
bottom: setSize(context: MyContext.get, mobile: 1.23.h, tablet: 2.10.h),
left: setSize(context: MyContext.get, mobile: 0.23.w, tablet: 0.21.w),
),
LevelLocation(
bottom: setSize(context: MyContext.get, mobile: 1.3.h, tablet: 2.169.h),
left: setSize(context: MyContext.get, mobile: 0.2.w, tablet: 0.1.w),
),
LevelLocation(
bottom: setSize(context: MyContext.get, mobile: 1.355.h, tablet: 2.25.h),
left: setSize(context: MyContext.get, mobile: 0.1.w, tablet: 0.1.w),
),
LevelLocation(
bottom: setSize(context: MyContext.get, mobile: 1.424.h, tablet: 2.34.h),
left: setSize(context: MyContext.get, mobile: 0.077.w, tablet: 0.225.w),
),
LevelLocation(
bottom: setSize(context: MyContext.get, mobile: 1.47.h, tablet: 2.34.h),
left: setSize(context: MyContext.get, mobile: 0.18.w, tablet: 0.225.w),
),
LevelLocation(
bottom: setSize(context: MyContext.get, mobile: 1.533.h, tablet: 2.34.h),
left: setSize(context: MyContext.get, mobile: 0.225.w, tablet: 0.225.w),
),
// LevelLocation(
// bottom: setSize(context: MyContext.get, mobile: 1.5.h, tablet: 2.8.h),
// left: setSize(context: MyContext.get, mobile: 0.2.w, tablet: 0.15.w),
//
// ),
];
final List<NodeEntity> nodeList = [];
late final Stream<double> volumeStream;
/// ------------Controllers------------
final ScrollController scrollController = ScrollController();
final AudioService _mainAudioService;
final AudioService _effectAudioService;
/// ------------Functions------------
Future<void> playMusic() async {
await Future.wait([
_mainAudioService.setAudio(assetPath: MyAudios.question),
_mainAudioService.setLoopMode(isLoop: true),
]);
await _mainAudioService.play();
}
void goToQuestionPage(BuildContext context, LevelEntity level) async {
final int levelOrder = level.order ?? 0;
final int lastDownloadedLevel =
(await _getLastDownloadedLevel(NoParams())).data ?? 0;
if (!context.mounted) return;
final bool isLevelDownloaded = levelOrder <= lastDownloadedLevel;
if (isLevelDownloaded) {
context.pushReplacementNamed(
Routes.questionPage,
pathParameters: {'id': '${level.id}'},
);
} else {
final maxLevelCount =
int.tryParse(
LocalStorage.readData(key: MyConstants.maxLevelCount) ?? '20',
) ??
20;
context.pushNamed(
Routes.downloadPage,
extra: DownloadPageConfig(
downloadToLevel: maxLevelCount,
routeParams: {'id': '${level.id}'},
redirectTo: Routes.questionPage,
),
);
}
}
void goToHomePage(BuildContext context) {
context.goNamed(Routes.homePage);
}
LevelType getLevelType(int index) {
final int currentLevel = int.parse(
LocalStorage.readData(key: MyConstants.currentLevel) ?? '1',
);
if (index < currentLevel) {
return LevelType.finished;
} else if (index == currentLevel) {
return LevelType.current;
} else {
return LevelType.unFinished;
}
}
bool getReward(int index) {
final int currentLevel = int.parse(
LocalStorage.readData(key: MyConstants.currentLevel) ?? '1',
);
return currentLevel > index;
}
Future<void> changeMute() async {
await Future.wait([
_mainAudioService.changeMute(),
_effectAudioService.changeMute(),
]);
}
int get diamonds {
final int currentLevel = int.parse(
LocalStorage.readData(key: MyConstants.currentLevel) ?? '1',
);
return currentLevel - 1;
}
void showReward({required BuildContext context, required PrizeEntity prize}) {
showRewardDialog(context: context, prize: prize);
}
/// ------------Event Calls------------
FutureOr<void> _getLevelListEvent(
GetLevelListEvent event,
Emitter<LevelState> emit,
) async {
final int currentLevel = int.parse(
LocalStorage.readData(key: MyConstants.currentLevel) ?? '1',
);
final localResult = await _getLeveslUseCase(LevelParams());
localResult.fold((data) async {
nodeList
..clear()
..addAll(data);
try {
emit(
state.copyWith(
getLevelStatus: const BaseComplete(''),
chooseLevel: data
.firstWhere((e) => e.level?.order == currentLevel)
.level,
),
);
} catch (e) {
emit(
state.copyWith(
getLevelStatus: const BaseComplete(''),
chooseLevel: LevelEntity(),
),
);
}
add(StartScrollEvent());
}, (error) {});
if (nodeList.isNotEmpty && nodeList.last.nodeType == NodeType.comingSoon) {
final remoteResult = await _getLeveslUseCase(
LevelParams(forceRemote: true),
);
remoteResult.fold((data) {
nodeList
..clear()
..addAll(data);
}, (error) {});
}
}
FutureOr<void> _startScrollEvent(
StartScrollEvent event,
Emitter<LevelState> emit,
) async {
final int currentLevel = int.parse(
LocalStorage.readData(key: MyConstants.currentLevel) ?? '1',
);
await Future.delayed(const Duration(seconds: 1));
if (scrollController.hasClients) {
if (currentLevel >= 14) {
scrollController.animateTo(
scrollController.position.maxScrollExtent,
duration: const Duration(milliseconds: 500),
// Note: 500 seconds is very long.
curve: Curves.easeInOut,
);
} else if (currentLevel > 8 && currentLevel < 14) {
scrollController.animateTo(
scrollController.position.maxScrollExtent / 2,
duration: const Duration(milliseconds: 500),
// Note: 500 seconds is very long.
curve: Curves.easeInOut,
);
}
}
}
FutureOr<void> _setCurrentLevelEvent(
SetCurrentLevelEvent event,
Emitter<LevelState> emit,
) async {
final String? currentLevel = LocalStorage.readData(
key: MyConstants.currentLevel,
);
if (currentLevel == null || currentLevel.isEmpty) {
await LocalStorage.saveData(key: MyConstants.currentLevel, value: '1');
}
add(GetLevelListEvent());
}
FutureOr<void> _chooseLevelEvent(
ChooseLevelEvent event,
Emitter<LevelState> emit,
) {
if (event.type != LevelType.unFinished) {
emit(state.copyWith(chooseLevel: event.level));
}
}
}