You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
598 lines
19 KiB
Dart
598 lines
19 KiB
Dart
import 'dart:async';
|
|
|
|
import 'package:appinio_swiper/appinio_swiper.dart';
|
|
import 'package:easy_localization/easy_localization.dart';
|
|
import 'package:flutter/cupertino.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:mohem_flutter_app/api/marathon/demo_marathon_repo.dart';
|
|
import 'package:mohem_flutter_app/api/marathon/marathon_api_client.dart';
|
|
import 'package:mohem_flutter_app/app_state/app_state.dart';
|
|
import 'package:mohem_flutter_app/classes/consts.dart';
|
|
import 'package:mohem_flutter_app/classes/utils.dart';
|
|
import 'package:mohem_flutter_app/config/routes.dart';
|
|
import 'package:mohem_flutter_app/models/marathon/marathon_generic_model.dart';
|
|
import 'package:mohem_flutter_app/models/marathon/marathon_model.dart';
|
|
import 'package:mohem_flutter_app/models/marathon/question_model.dart';
|
|
import 'package:mohem_flutter_app/models/marathon/winner_model.dart';
|
|
import 'package:mohem_flutter_app/models/privilege_list_model.dart';
|
|
import 'package:mohem_flutter_app/ui/marathon/widgets/question_card.dart';
|
|
import 'package:video_player/video_player.dart';
|
|
|
|
class MarathonProvider extends ChangeNotifier {
|
|
//************************************************ VARIABLES **********************************************************
|
|
|
|
final AppinioSwiperController swiperController = AppinioSwiperController();
|
|
|
|
MarathonDetailModel marathonDetailModel = MarathonDetailModel();
|
|
MarathonDetailModel demoMarathonDetailModel = MarathonDetailModel();
|
|
List<CardContent> cardContentList = <CardContent>[];
|
|
QuestionModel currentQuestion = QuestionModel();
|
|
List<QuestionCardStatus> answerStatusesList = <QuestionCardStatus>[];
|
|
QuestionCardStatus questionCardStatus = QuestionCardStatus.question;
|
|
List<WinnerModel>? selectedWinners;
|
|
int? selectedOptionIndex;
|
|
String? selectedOptionId;
|
|
int? totalQualifiers;
|
|
Locale savedLocale = const Locale("en", "US");
|
|
String? gapTimeImage;
|
|
String? gapTimeText;
|
|
int? gapTimeType;
|
|
|
|
bool iAmWinner = false;
|
|
bool isGettingQualifiers = false;
|
|
bool isPrivilegedWithMarathon = false;
|
|
|
|
bool _isLoading = false;
|
|
|
|
bool get isLoading => _isLoading;
|
|
|
|
set isLoading(bool value) {
|
|
_isLoading = value;
|
|
notifyListeners();
|
|
}
|
|
|
|
bool _isUpComingMarathon = true;
|
|
|
|
bool get isUpComingMarathon => _isUpComingMarathon;
|
|
|
|
set isUpComingMarathon(bool value) {
|
|
_isUpComingMarathon = value;
|
|
|
|
notifyListeners();
|
|
}
|
|
|
|
bool _itsMarathonTime = false;
|
|
|
|
bool get itsMarathonTime => _itsMarathonTime;
|
|
|
|
set itsMarathonTime(bool value) {
|
|
_itsMarathonTime = value;
|
|
notifyListeners();
|
|
}
|
|
|
|
bool _canPlayDemo = true;
|
|
|
|
bool get canPlayDemo => _canPlayDemo;
|
|
|
|
set canPlayDemo(bool value) {
|
|
_canPlayDemo = value;
|
|
notifyListeners();
|
|
}
|
|
|
|
bool _isButtonEnabled = false;
|
|
|
|
bool get isButtonEnabled => _isButtonEnabled;
|
|
|
|
set isButtonEnabled(bool value) {
|
|
_isButtonEnabled = value;
|
|
notifyListeners();
|
|
}
|
|
|
|
bool _isUserWaiting = false;
|
|
|
|
bool get isUserWaiting => _isUserWaiting;
|
|
|
|
set isUserWaiting(bool value) {
|
|
_isUserWaiting = value;
|
|
notifyListeners();
|
|
}
|
|
|
|
bool _isMarathonCompleted = false;
|
|
|
|
bool get isMarathonCompleted => _isMarathonCompleted;
|
|
|
|
set isMarathonCompleted(bool value) {
|
|
_isMarathonCompleted = value;
|
|
notifyListeners();
|
|
}
|
|
|
|
bool isUserOutOfGame = false;
|
|
|
|
set updateIsUserOutOfGame(bool value) {
|
|
isUserOutOfGame = value;
|
|
notifyListeners();
|
|
}
|
|
|
|
int _currentQuestionNumber = 0;
|
|
|
|
int get currentQuestionNumber => _currentQuestionNumber;
|
|
|
|
set currentQuestionNumber(int value) {
|
|
_currentQuestionNumber = value;
|
|
notifyListeners();
|
|
}
|
|
|
|
int _totalMarathoners = 0;
|
|
|
|
int get totalMarathoners => _totalMarathoners;
|
|
|
|
set totalMarathoners(int value) {
|
|
_totalMarathoners = value;
|
|
notifyListeners();
|
|
}
|
|
|
|
//****************SPONSOR VIDEO PLAYER**********
|
|
|
|
late VideoPlayerController videoController;
|
|
|
|
Future<void> initializeVideoPlayer() async {
|
|
videoController = VideoPlayerController.network(ApiConsts.marathonBaseUrlServices + marathonDetailModel.sponsors!.first.video!);
|
|
await videoController.initialize();
|
|
await videoController.play();
|
|
await videoController.setVolume(1.0);
|
|
await videoController.setLooping(false);
|
|
totalSponsorVideoSeconds = videoController.value.duration.inSeconds;
|
|
notifyListeners();
|
|
}
|
|
|
|
void disposeVideoPlayer() {
|
|
videoController.dispose();
|
|
notifyListeners();
|
|
}
|
|
|
|
// 9c47d281-c5b5-4b5d-a90a-08dacb8cbdb6
|
|
// MarathonI
|
|
//************************************************ TIMERS **********************************************************
|
|
|
|
int sponsorsSecondsCounter = 0;
|
|
int totalSponsorVideoSeconds = 0;
|
|
Timer timerForSponsorVideo = Timer.periodic(const Duration(seconds: 1), (Timer timer) {});
|
|
|
|
void startTimerForSponsorVideo() {
|
|
const Duration oneSec = Duration(seconds: 1);
|
|
timerForSponsorVideo = Timer.periodic(
|
|
oneSec,
|
|
(Timer timer) async {
|
|
sponsorsSecondsCounter++;
|
|
if (totalSponsorVideoSeconds == 0) {
|
|
timer.cancel();
|
|
notifyListeners();
|
|
return;
|
|
} else {
|
|
totalSponsorVideoSeconds--;
|
|
}
|
|
|
|
notifyListeners();
|
|
},
|
|
);
|
|
}
|
|
|
|
int totalSecondsToWaitForMarathon = 30;
|
|
|
|
set updateTotalSecondsToWaitForMarathon(int value) {
|
|
totalSecondsToWaitForMarathon = value;
|
|
notifyListeners();
|
|
}
|
|
|
|
Timer timerToWaitForMarathon = Timer.periodic(const Duration(seconds: 1), (Timer timer) {});
|
|
|
|
void startTimerToWaitForMarathon() {
|
|
const Duration oneSec = Duration(seconds: 1);
|
|
timerToWaitForMarathon = Timer.periodic(
|
|
oneSec,
|
|
(Timer timer) async {
|
|
if (totalSecondsToWaitForMarathon == 0) {
|
|
timer.cancel();
|
|
if (isUserWaiting) {
|
|
await callNextQuestionApi();
|
|
} else {
|
|
isButtonEnabled = false;
|
|
}
|
|
return;
|
|
} else {
|
|
totalSecondsToWaitForMarathon--;
|
|
}
|
|
notifyListeners();
|
|
},
|
|
);
|
|
}
|
|
|
|
int totalCurrentQuestionTime = 0;
|
|
int currentGapTime = 0;
|
|
Timer timerForQuestion = Timer.periodic(const Duration(seconds: 1), (Timer timer) {});
|
|
int callCountThreshold = 0;
|
|
|
|
void startTimerForQuestion() {
|
|
const Duration oneSec = Duration(seconds: 1);
|
|
timerForQuestion = Timer.periodic(
|
|
oneSec,
|
|
(Timer timer) async {
|
|
// This 1 is just to show the color of answer tile for 1 and then update card status
|
|
if (totalCurrentQuestionTime - currentGapTime == 0) {
|
|
if (callCountThreshold == 0) {
|
|
getCorrectAnswerAndUpdateAnswerColor();
|
|
}
|
|
}
|
|
|
|
if (totalCurrentQuestionTime - currentGapTime == -2) {
|
|
if (callCountThreshold == 0) {
|
|
updateCardStatusToAnswer();
|
|
}
|
|
// scheduleMicrotask(() async {
|
|
// if (AppState().getIsDemoMarathon || isUserOutOfGame) {
|
|
// await callNextQuestionApi();
|
|
// } else {
|
|
// await callSubmitOptionApi().then((bool value) async {
|
|
// updateIsUserOutOfGame = !value;
|
|
// await callNextQuestionApi();
|
|
// });
|
|
// }
|
|
// });
|
|
|
|
if (currentQuestionNumber == (AppState().getIsDemoMarathon ? demoMarathonDetailModel.totalQuestions! : marathonDetailModel.totalQuestions!)) {
|
|
isGettingQualifiers = true;
|
|
updateQuestionCardStatus(QuestionCardStatus.findingWinner);
|
|
timer.cancel();
|
|
cancelTimer();
|
|
notifyListeners();
|
|
}
|
|
totalCurrentQuestionTime--;
|
|
callCountThreshold = 0;
|
|
}
|
|
|
|
if (totalCurrentQuestionTime == 0) {
|
|
gapTimeImage = currentQuestion.gapImage;
|
|
gapTimeText = currentQuestion.gapText;
|
|
gapTimeType = currentQuestion.gapType;
|
|
updateCardData();
|
|
|
|
return;
|
|
} else {
|
|
if (totalCurrentQuestionTime - currentGapTime != -2) {
|
|
totalCurrentQuestionTime--;
|
|
callCountThreshold = 0;
|
|
}
|
|
}
|
|
|
|
notifyListeners();
|
|
},
|
|
);
|
|
}
|
|
|
|
int totalSecondsToWaitForWinner = 30;
|
|
Timer timerForWinnerSelection = Timer.periodic(const Duration(seconds: 1), (Timer timer) {});
|
|
|
|
void startTimerForWinnerSelection() {
|
|
const Duration oneSec = Duration(seconds: 1);
|
|
timerForWinnerSelection = Timer.periodic(
|
|
oneSec,
|
|
(Timer timer) async {
|
|
if (totalSecondsToWaitForWinner == 1) {
|
|
timer.cancel();
|
|
await callGetSelectedWinnersApi().whenComplete(() => updateQuestionCardStatus(QuestionCardStatus.winnerFound));
|
|
return;
|
|
} else if (totalSecondsToWaitForWinner == 15) {
|
|
totalSecondsToWaitForWinner--;
|
|
await callGetQualifiersApi();
|
|
} else {
|
|
totalSecondsToWaitForWinner--;
|
|
}
|
|
|
|
notifyListeners();
|
|
},
|
|
);
|
|
}
|
|
|
|
//************************************************ FUNCTIONS **********************************************************
|
|
|
|
void updateLanguageAsPerMarathon(BuildContext context, MarathonDetailModel detailModel) {
|
|
savedLocale = context.locale;
|
|
if (detailModel.selectedLanguage == 1) {
|
|
context.setLocale(const Locale("en", "US"));
|
|
} else if (detailModel.selectedLanguage == 2) {
|
|
context.setLocale(const Locale("ar", "SA"));
|
|
} else if (detailModel.selectedLanguage == 3) {
|
|
} else {
|
|
context.setLocale(const Locale("en", "US"));
|
|
}
|
|
}
|
|
|
|
Future<bool> callSubmitOptionApi() async {
|
|
return await MarathonApiClient().submitSelectedOption(marathonId: marathonDetailModel.id!, questionId: currentQuestion.id, selectedAnswerId: selectedOptionId);
|
|
}
|
|
|
|
Future<void> callGetQualifiersApi() async {
|
|
if (AppState().getIsDemoMarathon) {
|
|
totalQualifiers = isUserOutOfGame ? 0 : 1;
|
|
} else {
|
|
totalQualifiers = await MarathonApiClient().getQualifiers(marathonId: marathonDetailModel.id!);
|
|
}
|
|
isGettingQualifiers = false;
|
|
notifyListeners();
|
|
}
|
|
|
|
Future<void> callGetSelectedWinnersApi() async {
|
|
if (AppState().getIsDemoMarathon) {
|
|
return;
|
|
}
|
|
selectedWinners = await MarathonApiClient().getSelectedWinner(marathonId: marathonDetailModel.id!);
|
|
if (selectedWinners != null) {
|
|
selectedWinners!.removeWhere((WinnerModel element) {
|
|
if (element.employeeId == AppState().memberInformationList!.eMPLOYEENUMBER) {
|
|
iAmWinner = true;
|
|
return true;
|
|
} else {
|
|
return false;
|
|
}
|
|
});
|
|
}
|
|
|
|
notifyListeners();
|
|
}
|
|
|
|
Future<void> callNextQuestionApi() async {
|
|
if (currentQuestionNumber < (AppState().getIsDemoMarathon ? demoMarathonDetailModel.totalQuestions! : marathonDetailModel.totalQuestions!)) {
|
|
if (currentQuestionNumber == 0) {
|
|
if (!AppState().getIsDemoMarathon) {
|
|
Utils.showLoading(AppRoutes.navigatorKey.currentContext!);
|
|
}
|
|
currentQuestion = AppState().getIsDemoMarathon
|
|
? await DemoMarathonRepo().getDemoNextQuestion(currentQuestionNumber: currentQuestionNumber)
|
|
: (await MarathonApiClient().getNextQuestion(questionId: null, marathonId: marathonDetailModel.id!));
|
|
gapTimeImage = currentQuestion.gapImage;
|
|
gapTimeText = currentQuestion.gapText;
|
|
gapTimeType = currentQuestion.gapType;
|
|
|
|
startTimerForQuestion();
|
|
updateCardData();
|
|
if (Utils.isLoading) {
|
|
Utils.hideLoading(AppRoutes.navigatorKey.currentContext!);
|
|
}
|
|
if (!AppState().getIsDemoMarathon) {
|
|
totalMarathoners = await MarathonApiClient().getMarathonersCount(marathonId: marathonDetailModel.id!);
|
|
}
|
|
Navigator.pushReplacementNamed(AppRoutes.navigatorKey.currentContext!, AppRoutes.marathonScreen);
|
|
} else {
|
|
currentQuestion = AppState().getIsDemoMarathon
|
|
? await DemoMarathonRepo().getDemoNextQuestion(currentQuestionNumber: currentQuestionNumber)
|
|
: (await MarathonApiClient().getNextQuestion(questionId: currentQuestion.id, marathonId: marathonDetailModel.id!));
|
|
}
|
|
notifyListeners();
|
|
}
|
|
}
|
|
|
|
void updateCardData() {
|
|
if (currentQuestionNumber > 0) {
|
|
swiperController.swipeLeft();
|
|
}
|
|
selectedOptionIndex = null;
|
|
currentQuestionNumber++;
|
|
|
|
cardContentList.add(const CardContent());
|
|
totalCurrentQuestionTime = currentQuestion.questionTime! + currentQuestion.nextQuestGap!;
|
|
currentGapTime = currentQuestion.nextQuestGap!;
|
|
totalMarathoners = currentQuestion.remainingParticipantCount!;
|
|
questionCardStatus = QuestionCardStatus.question;
|
|
notifyListeners();
|
|
}
|
|
|
|
void populateQuestionStatusesList() {
|
|
answerStatusesList.clear();
|
|
if (demoMarathonDetailModel.totalQuestions != null) {
|
|
for (int i = 0; i < demoMarathonDetailModel.totalQuestions!; i++) {
|
|
answerStatusesList.add(QuestionCardStatus.question);
|
|
}
|
|
notifyListeners();
|
|
}
|
|
if (isUpComingMarathon) {
|
|
if (marathonDetailModel.totalQuestions != null) {
|
|
for (int i = 0; i < marathonDetailModel.totalQuestions!; i++) {
|
|
answerStatusesList.add(QuestionCardStatus.question);
|
|
}
|
|
notifyListeners();
|
|
}
|
|
}
|
|
}
|
|
|
|
void updateAnswerStatusesList(QuestionCardStatus status) {
|
|
answerStatusesList[currentQuestionNumber - 1] = status;
|
|
notifyListeners();
|
|
}
|
|
|
|
void addItemToList(CardContent value) {
|
|
cardContentList.add(value);
|
|
notifyListeners();
|
|
}
|
|
|
|
void updateCurrentQuestionOptionStatus(QuestionsOptionStatus status, int index) {
|
|
for (int i = 0; i < currentQuestion.questionOptions!.length; i++) {
|
|
currentQuestion.questionOptions![i].optionStatus = QuestionsOptionStatus.unSelected;
|
|
}
|
|
currentQuestion.questionOptions![index].optionStatus = status;
|
|
selectedOptionId = currentQuestion.questionOptions![index].id;
|
|
selectedOptionIndex = index;
|
|
notifyListeners();
|
|
}
|
|
|
|
void updateQuestionCardStatus(QuestionCardStatus status) {
|
|
if (status == QuestionCardStatus.wrongAnswer || status == QuestionCardStatus.skippedAnswer) {
|
|
if (AppState().getIsDemoMarathon) {
|
|
updateIsUserOutOfGame = true;
|
|
}
|
|
}
|
|
questionCardStatus = status;
|
|
notifyListeners();
|
|
}
|
|
|
|
void getCorrectAnswerAndUpdateAnswerColor() {
|
|
callCountThreshold = 1;
|
|
if (selectedOptionIndex != null) {
|
|
scheduleMicrotask(() async {
|
|
if (AppState().getIsDemoMarathon) {
|
|
if (currentQuestion.questionOptions![selectedOptionIndex!].isCorrectOption!) {
|
|
updateCurrentQuestionOptionStatus(QuestionsOptionStatus.correct, selectedOptionIndex!);
|
|
} else {
|
|
updateCurrentQuestionOptionStatus(QuestionsOptionStatus.wrong, selectedOptionIndex!);
|
|
}
|
|
} else {
|
|
await callSubmitOptionApi().then((bool value) async {
|
|
updateIsUserOutOfGame = !value;
|
|
if (value) {
|
|
updateCurrentQuestionOptionStatus(QuestionsOptionStatus.correct, selectedOptionIndex!);
|
|
} else {
|
|
updateCurrentQuestionOptionStatus(QuestionsOptionStatus.wrong, selectedOptionIndex!);
|
|
}
|
|
});
|
|
}
|
|
});
|
|
} else {
|
|
if (!AppState().getIsDemoMarathon) {
|
|
scheduleMicrotask(() async {
|
|
await callSubmitOptionApi().then((bool value) async {
|
|
updateIsUserOutOfGame = !value;
|
|
});
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
void updateCardStatusToAnswer() {
|
|
if (currentQuestionNumber == 0) {
|
|
return;
|
|
}
|
|
callCountThreshold = 1;
|
|
scheduleMicrotask(() async {
|
|
await callNextQuestionApi();
|
|
});
|
|
|
|
if (selectedOptionIndex == null) {
|
|
updateQuestionCardStatus(QuestionCardStatus.skippedAnswer);
|
|
updateAnswerStatusesList(QuestionCardStatus.skippedAnswer);
|
|
return;
|
|
}
|
|
if (AppState().getIsDemoMarathon) {
|
|
if (currentQuestion.questionOptions![selectedOptionIndex!].isCorrectOption!) {
|
|
updateQuestionCardStatus(QuestionCardStatus.correctAnswer);
|
|
updateAnswerStatusesList(QuestionCardStatus.correctAnswer);
|
|
} else {
|
|
updateQuestionCardStatus(QuestionCardStatus.wrongAnswer);
|
|
updateAnswerStatusesList(QuestionCardStatus.wrongAnswer);
|
|
}
|
|
return;
|
|
}
|
|
if (!isUserOutOfGame) {
|
|
updateQuestionCardStatus(QuestionCardStatus.correctAnswer);
|
|
updateAnswerStatusesList(QuestionCardStatus.correctAnswer);
|
|
return;
|
|
}
|
|
updateQuestionCardStatus(QuestionCardStatus.wrongAnswer);
|
|
updateAnswerStatusesList(QuestionCardStatus.wrongAnswer);
|
|
}
|
|
|
|
void resetValues() async {
|
|
_currentQuestionNumber = 0;
|
|
iAmWinner = false;
|
|
cardContentList.clear();
|
|
itsMarathonTime = false;
|
|
timerForWinnerSelection.cancel();
|
|
timerForSponsorVideo.cancel();
|
|
timerToWaitForMarathon.cancel();
|
|
timerForQuestion.cancel();
|
|
_isMarathonCompleted = false;
|
|
isUserOutOfGame = false;
|
|
isButtonEnabled = false;
|
|
isUserWaiting = false;
|
|
canPlayDemo = true;
|
|
totalCurrentQuestionTime = 0;
|
|
sponsorsSecondsCounter = 0;
|
|
totalSponsorVideoSeconds = 0;
|
|
totalSecondsToWaitForWinner = 30;
|
|
totalSecondsToWaitForMarathon = 30;
|
|
AppState().setIsDemoMarathon = false;
|
|
currentGapTime = 0;
|
|
currentQuestion = QuestionModel();
|
|
if (answerStatusesList.isNotEmpty) {
|
|
for (int i = 0; i < answerStatusesList.length; i++) {
|
|
answerStatusesList[i] = QuestionCardStatus.question;
|
|
}
|
|
}
|
|
AppRoutes.navigatorKey.currentContext!.setLocale(savedLocale);
|
|
notifyListeners();
|
|
}
|
|
|
|
void cancelTimer() {
|
|
timerForQuestion.cancel();
|
|
notifyListeners();
|
|
}
|
|
|
|
bool checkIfPrivilegedForMarathon() {
|
|
for (PrivilegeListModel element in AppState().privilegeListModel!) {
|
|
if (element.serviceName == "Marathon") {
|
|
if (element.previlege != null) {
|
|
return element.previlege!;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
Future<void> getMarathonDetailsFromApi() async {
|
|
isLoading = true;
|
|
notifyListeners();
|
|
isPrivilegedWithMarathon = checkIfPrivilegedForMarathon();
|
|
demoMarathonDetailModel = await DemoMarathonRepo().getDemoMarathonDetails();
|
|
|
|
if (isPrivilegedWithMarathon) {
|
|
marathonDetailModel = await MarathonApiClient().getMarathonDetails();
|
|
updateTotalSecondsToWaitForMarathon = marathonDetailModel.marathonBufferTime ?? 30;
|
|
if (marathonDetailModel.id == null) {
|
|
isUpComingMarathon = false;
|
|
isLoading = false;
|
|
populateQuestionStatusesList();
|
|
notifyListeners();
|
|
return;
|
|
}
|
|
isUpComingMarathon = true;
|
|
if (DateTime.parse(marathonDetailModel.startTime!).isAfter(DateTime.now())) {
|
|
itsMarathonTime = false;
|
|
}
|
|
populateQuestionStatusesList();
|
|
}
|
|
isLoading = false;
|
|
notifyListeners();
|
|
}
|
|
|
|
Future<void> onJoinMarathonPressed(BuildContext context) async {
|
|
try {
|
|
Utils.showLoading(AppRoutes.navigatorKey.currentContext!);
|
|
MarathonApiClient().joinMarathonAsParticipant().then((MarathonGenericModel? marathonGenericModel) async {
|
|
Utils.hideLoading(AppRoutes.navigatorKey.currentContext!);
|
|
if (marathonGenericModel != null && marathonGenericModel.data != null) {
|
|
isUserWaiting = true;
|
|
Navigator.pushReplacementNamed(context, AppRoutes.marathonWaitingScreen);
|
|
} else if (marathonGenericModel!.data == null) {
|
|
Utils.showToast(marathonGenericModel.message.toString());
|
|
}
|
|
});
|
|
} catch (e) {
|
|
Utils.hideLoading(AppRoutes.navigatorKey.currentContext!);
|
|
Utils.confirmDialog(context, e.toString());
|
|
}
|
|
}
|
|
|
|
Future<void> onJoinDemoMarathonPressed(BuildContext context) async {
|
|
AppState().setIsDemoMarathon = true;
|
|
await callNextQuestionApi();
|
|
}
|
|
}
|