Compare commits

..

No commits in common. "5cfe6897c6e1e82a418e765cf5374b8d961b2ed0" and "85a09151e34c222ed55635717e96fb61abfc7127" have entirely different histories.

71 changed files with 789 additions and 1073 deletions

View File

@ -25,6 +25,7 @@ import 'package:yimaru_app/services/secure_storage_service.dart';
import 'package:yimaru_app/services/dio_service.dart';
import 'package:yimaru_app/services/status_checker_service.dart';
import 'package:yimaru_app/ui/views/welcome/welcome_view.dart';
import 'package:yimaru_app/ui/views/assessment/assessment_view.dart';
import 'package:yimaru_app/ui/views/learn_lesson/learn_lesson_view.dart';
import 'package:yimaru_app/services/permission_handler_service.dart';
import 'package:yimaru_app/services/image_picker_service.dart';
@ -51,7 +52,6 @@ import 'package:yimaru_app/ui/views/course_practice_question/course_practice_que
import 'package:yimaru_app/services/in_app_update_service.dart';
import 'package:yimaru_app/ui/views/learn_program/learn_program_view.dart';
import 'package:yimaru_app/ui/views/learn_course/learn_course_view.dart';
import 'package:yimaru_app/ui/views/assessment/assessment_view.dart';
// @stacked-import
@StackedApp(
@ -74,6 +74,7 @@ import 'package:yimaru_app/ui/views/assessment/assessment_view.dart';
MaterialRoute(page: LoginView),
MaterialRoute(page: LearnModuleView),
MaterialRoute(page: WelcomeView),
MaterialRoute(page: AssessmentView),
MaterialRoute(page: LearnLessonView),
MaterialRoute(page: ForgetPasswordView),
MaterialRoute(page: LearnLessonDetailView),
@ -90,7 +91,6 @@ import 'package:yimaru_app/ui/views/assessment/assessment_view.dart';
MaterialRoute(page: CoursePracticeQuestionView),
MaterialRoute(page: LearnProgramView),
MaterialRoute(page: LearnCourseView),
MaterialRoute(page: AssessmentView),
// @stacked-route
],
dependencies: [

View File

@ -20,43 +20,43 @@ import 'package:yimaru_app/models/subcategory.dart' as _i45;
import 'package:yimaru_app/ui/common/enmus.dart' as _i41;
import 'package:yimaru_app/ui/views/account_privacy/account_privacy_view.dart'
as _i9;
import 'package:yimaru_app/ui/views/assessment/assessment_view.dart' as _i36;
import 'package:yimaru_app/ui/views/assessment/assessment_view.dart' as _i20;
import 'package:yimaru_app/ui/views/call_support/call_support_view.dart'
as _i12;
import 'package:yimaru_app/ui/views/course/course_view.dart' as _i32;
import 'package:yimaru_app/ui/views/course/course_view.dart' as _i33;
import 'package:yimaru_app/ui/views/course_category/course_category_view.dart'
as _i26;
as _i27;
import 'package:yimaru_app/ui/views/course_lesson/course_lesson_view.dart'
as _i28;
import 'package:yimaru_app/ui/views/course_lesson_detail/course_lesson_detail_view.dart'
as _i29;
import 'package:yimaru_app/ui/views/course_lesson_detail/course_lesson_detail_view.dart'
as _i30;
import 'package:yimaru_app/ui/views/course_payment/course_payment_view.dart'
as _i25;
as _i26;
import 'package:yimaru_app/ui/views/course_practice/course_practice_view.dart'
as _i24;
as _i25;
import 'package:yimaru_app/ui/views/course_practice_question/course_practice_question_view.dart'
as _i33;
as _i34;
import 'package:yimaru_app/ui/views/course_subcategory/course_subcategory_view.dart'
as _i31;
as _i32;
import 'package:yimaru_app/ui/views/downloads/downloads_view.dart' as _i7;
import 'package:yimaru_app/ui/views/duolingo/duolingo_view.dart' as _i30;
import 'package:yimaru_app/ui/views/failure/failure_view.dart' as _i27;
import 'package:yimaru_app/ui/views/duolingo/duolingo_view.dart' as _i31;
import 'package:yimaru_app/ui/views/failure/failure_view.dart' as _i28;
import 'package:yimaru_app/ui/views/forget_password/forget_password_view.dart'
as _i21;
as _i22;
import 'package:yimaru_app/ui/views/home/home_view.dart' as _i2;
import 'package:yimaru_app/ui/views/language/language_view.dart' as _i13;
import 'package:yimaru_app/ui/views/learn_course/learn_course_view.dart'
as _i35;
as _i36;
import 'package:yimaru_app/ui/views/learn_lesson/learn_lesson_view.dart'
as _i20;
as _i21;
import 'package:yimaru_app/ui/views/learn_lesson_detail/learn_lesson_detail_view.dart'
as _i22;
as _i23;
import 'package:yimaru_app/ui/views/learn_module/learn_module_view.dart'
as _i18;
import 'package:yimaru_app/ui/views/learn_practice/learn_practice_view.dart'
as _i23;
as _i24;
import 'package:yimaru_app/ui/views/learn_program/learn_program_view.dart'
as _i34;
as _i35;
import 'package:yimaru_app/ui/views/login/login_view.dart' as _i17;
import 'package:yimaru_app/ui/views/onboarding/onboarding_view.dart' as _i3;
import 'package:yimaru_app/ui/views/privacy_policy/privacy_policy_view.dart'
@ -111,6 +111,8 @@ class Routes {
static const welcomeView = '/welcome-view';
static const assessmentView = '/assessment-view';
static const learnLessonView = '/learn-lesson-view';
static const forgetPasswordView = '/forget-password-view';
@ -143,8 +145,6 @@ class Routes {
static const learnCourseView = '/learn-course-view';
static const assessmentView = '/assessment-view';
static const all = <String>{
homeView,
onboardingView,
@ -164,6 +164,7 @@ class Routes {
loginView,
learnModuleView,
welcomeView,
assessmentView,
learnLessonView,
forgetPasswordView,
learnLessonDetailView,
@ -180,7 +181,6 @@ class Routes {
coursePracticeQuestionView,
learnProgramView,
learnCourseView,
assessmentView,
};
}
@ -258,73 +258,73 @@ class StackedRouter extends _i1.RouterBase {
Routes.welcomeView,
page: _i19.WelcomeView,
),
_i1.RouteDef(
Routes.assessmentView,
page: _i20.AssessmentView,
),
_i1.RouteDef(
Routes.learnLessonView,
page: _i20.LearnLessonView,
page: _i21.LearnLessonView,
),
_i1.RouteDef(
Routes.forgetPasswordView,
page: _i21.ForgetPasswordView,
page: _i22.ForgetPasswordView,
),
_i1.RouteDef(
Routes.learnLessonDetailView,
page: _i22.LearnLessonDetailView,
page: _i23.LearnLessonDetailView,
),
_i1.RouteDef(
Routes.learnPracticeView,
page: _i23.LearnPracticeView,
page: _i24.LearnPracticeView,
),
_i1.RouteDef(
Routes.coursePracticeView,
page: _i24.CoursePracticeView,
page: _i25.CoursePracticeView,
),
_i1.RouteDef(
Routes.coursePaymentView,
page: _i25.CoursePaymentView,
page: _i26.CoursePaymentView,
),
_i1.RouteDef(
Routes.courseCategoryView,
page: _i26.CourseCategoryView,
page: _i27.CourseCategoryView,
),
_i1.RouteDef(
Routes.failureView,
page: _i27.FailureView,
page: _i28.FailureView,
),
_i1.RouteDef(
Routes.courseLessonView,
page: _i28.CourseLessonView,
page: _i29.CourseLessonView,
),
_i1.RouteDef(
Routes.courseLessonDetailView,
page: _i29.CourseLessonDetailView,
page: _i30.CourseLessonDetailView,
),
_i1.RouteDef(
Routes.duolingoView,
page: _i30.DuolingoView,
page: _i31.DuolingoView,
),
_i1.RouteDef(
Routes.courseSubcategoryView,
page: _i31.CourseSubcategoryView,
page: _i32.CourseSubcategoryView,
),
_i1.RouteDef(
Routes.courseView,
page: _i32.CourseView,
page: _i33.CourseView,
),
_i1.RouteDef(
Routes.coursePracticeQuestionView,
page: _i33.CoursePracticeQuestionView,
page: _i34.CoursePracticeQuestionView,
),
_i1.RouteDef(
Routes.learnProgramView,
page: _i34.LearnProgramView,
page: _i35.LearnProgramView,
),
_i1.RouteDef(
Routes.learnCourseView,
page: _i35.LearnCourseView,
),
_i1.RouteDef(
Routes.assessmentView,
page: _i36.AssessmentView,
page: _i36.LearnCourseView,
),
];
@ -490,143 +490,143 @@ class StackedRouter extends _i1.RouterBase {
settings: data,
);
},
_i20.LearnLessonView: (data) {
final args = data.getArgs<LearnLessonViewArguments>(nullOk: false);
_i20.AssessmentView: (data) {
final args = data.getArgs<AssessmentViewArguments>(nullOk: false);
return _i37.MaterialPageRoute<dynamic>(
builder: (context) =>
_i20.LearnLessonView(key: args.key, module: args.module),
_i20.AssessmentView(key: args.key, data: args.data),
settings: data,
);
},
_i21.ForgetPasswordView: (data) {
_i21.LearnLessonView: (data) {
final args = data.getArgs<LearnLessonViewArguments>(nullOk: false);
return _i37.MaterialPageRoute<dynamic>(
builder: (context) =>
_i21.LearnLessonView(key: args.key, module: args.module),
settings: data,
);
},
_i22.ForgetPasswordView: (data) {
final args = data.getArgs<ForgetPasswordViewArguments>(
orElse: () => const ForgetPasswordViewArguments(),
);
return _i37.MaterialPageRoute<dynamic>(
builder: (context) => _i21.ForgetPasswordView(key: args.key),
builder: (context) => _i22.ForgetPasswordView(key: args.key),
settings: data,
);
},
_i22.LearnLessonDetailView: (data) {
_i23.LearnLessonDetailView: (data) {
final args = data.getArgs<LearnLessonDetailViewArguments>(nullOk: false);
return _i37.MaterialPageRoute<dynamic>(
builder: (context) =>
_i22.LearnLessonDetailView(key: args.key, lesson: args.lesson),
_i23.LearnLessonDetailView(key: args.key, lesson: args.lesson),
settings: data,
);
},
_i23.LearnPracticeView: (data) {
_i24.LearnPracticeView: (data) {
final args = data.getArgs<LearnPracticeViewArguments>(nullOk: false);
return _i37.MaterialPageRoute<dynamic>(
builder: (context) => _i23.LearnPracticeView(
builder: (context) => _i24.LearnPracticeView(
key: args.key, id: args.id, practice: args.practice),
settings: data,
);
},
_i24.CoursePracticeView: (data) {
_i25.CoursePracticeView: (data) {
final args = data.getArgs<CoursePracticeViewArguments>(nullOk: false);
return _i37.MaterialPageRoute<dynamic>(
builder: (context) =>
_i24.CoursePracticeView(key: args.key, id: args.id),
_i25.CoursePracticeView(key: args.key, id: args.id),
settings: data,
);
},
_i25.CoursePaymentView: (data) {
_i26.CoursePaymentView: (data) {
final args = data.getArgs<CoursePaymentViewArguments>(nullOk: false);
return _i37.MaterialPageRoute<dynamic>(
builder: (context) =>
_i25.CoursePaymentView(key: args.key, course: args.course),
_i26.CoursePaymentView(key: args.key, course: args.course),
settings: data,
);
},
_i26.CourseCategoryView: (data) {
_i27.CourseCategoryView: (data) {
final args = data.getArgs<CourseCategoryViewArguments>(
orElse: () => const CourseCategoryViewArguments(),
);
return _i37.MaterialPageRoute<dynamic>(
builder: (context) => _i26.CourseCategoryView(key: args.key),
builder: (context) => _i27.CourseCategoryView(key: args.key),
settings: data,
);
},
_i27.FailureView: (data) {
_i28.FailureView: (data) {
final args = data.getArgs<FailureViewArguments>(nullOk: false);
return _i37.MaterialPageRoute<dynamic>(
builder: (context) => _i27.FailureView(
key: args.key, onTap: args.onTap, label: args.label),
builder: (context) =>
_i28.FailureView(key: args.key, label: args.label),
settings: data,
);
},
_i28.CourseLessonView: (data) {
_i29.CourseLessonView: (data) {
final args = data.getArgs<CourseLessonViewArguments>(nullOk: false);
return _i37.MaterialPageRoute<dynamic>(
builder: (context) =>
_i28.CourseLessonView(key: args.key, course: args.course),
_i29.CourseLessonView(key: args.key, course: args.course),
settings: data,
);
},
_i29.CourseLessonDetailView: (data) {
_i30.CourseLessonDetailView: (data) {
final args = data.getArgs<CourseLessonDetailViewArguments>(nullOk: false);
return _i37.MaterialPageRoute<dynamic>(
builder: (context) =>
_i29.CourseLessonDetailView(key: args.key, lesson: args.lesson),
_i30.CourseLessonDetailView(key: args.key, lesson: args.lesson),
settings: data,
);
},
_i30.DuolingoView: (data) {
_i31.DuolingoView: (data) {
final args = data.getArgs<DuolingoViewArguments>(
orElse: () => const DuolingoViewArguments(),
);
return _i37.MaterialPageRoute<dynamic>(
builder: (context) => _i30.DuolingoView(key: args.key),
builder: (context) => _i31.DuolingoView(key: args.key),
settings: data,
);
},
_i31.CourseSubcategoryView: (data) {
_i32.CourseSubcategoryView: (data) {
final args = data.getArgs<CourseSubcategoryViewArguments>(nullOk: false);
return _i37.MaterialPageRoute<dynamic>(
builder: (context) =>
_i31.CourseSubcategoryView(key: args.key, category: args.category),
_i32.CourseSubcategoryView(key: args.key, category: args.category),
settings: data,
);
},
_i32.CourseView: (data) {
_i33.CourseView: (data) {
final args = data.getArgs<CourseViewArguments>(nullOk: false);
return _i37.MaterialPageRoute<dynamic>(
builder: (context) =>
_i32.CourseView(key: args.key, subcategory: args.subcategory),
_i33.CourseView(key: args.key, subcategory: args.subcategory),
settings: data,
);
},
_i33.CoursePracticeQuestionView: (data) {
_i34.CoursePracticeQuestionView: (data) {
final args =
data.getArgs<CoursePracticeQuestionViewArguments>(nullOk: false);
return _i37.MaterialPageRoute<dynamic>(
builder: (context) =>
_i33.CoursePracticeQuestionView(key: args.key, id: args.id),
_i34.CoursePracticeQuestionView(key: args.key, id: args.id),
settings: data,
);
},
_i34.LearnProgramView: (data) {
_i35.LearnProgramView: (data) {
final args = data.getArgs<LearnProgramViewArguments>(
orElse: () => const LearnProgramViewArguments(),
);
return _i37.MaterialPageRoute<dynamic>(
builder: (context) => _i34.LearnProgramView(key: args.key),
builder: (context) => _i35.LearnProgramView(key: args.key),
settings: data,
);
},
_i35.LearnCourseView: (data) {
_i36.LearnCourseView: (data) {
final args = data.getArgs<LearnCourseViewArguments>(nullOk: false);
return _i37.MaterialPageRoute<dynamic>(
builder: (context) => _i35.LearnCourseView(key: args.key, id: args.id),
settings: data,
);
},
_i36.AssessmentView: (data) {
final args = data.getArgs<AssessmentViewArguments>(nullOk: false);
return _i37.MaterialPageRoute<dynamic>(
builder: (context) =>
_i36.AssessmentView(key: args.key, data: args.data),
builder: (context) => _i36.LearnCourseView(key: args.key, id: args.id),
settings: data,
);
},
@ -1045,6 +1045,33 @@ class WelcomeViewArguments {
}
}
class AssessmentViewArguments {
const AssessmentViewArguments({
this.key,
required this.data,
});
final _i37.Key? key;
final Map<String, dynamic> data;
@override
String toString() {
return '{"key": "$key", "data": "$data"}';
}
@override
bool operator ==(covariant AssessmentViewArguments other) {
if (identical(this, other)) return true;
return other.key == key && other.data == data;
}
@override
int get hashCode {
return key.hashCode ^ data.hashCode;
}
}
class LearnLessonViewArguments {
const LearnLessonViewArguments({
this.key,
@ -1230,30 +1257,27 @@ class CourseCategoryViewArguments {
class FailureViewArguments {
const FailureViewArguments({
this.key,
required this.onTap,
required this.label,
});
final _i37.Key? key;
final void Function() onTap;
final String label;
@override
String toString() {
return '{"key": "$key", "onTap": "$onTap", "label": "$label"}';
return '{"key": "$key", "label": "$label"}';
}
@override
bool operator ==(covariant FailureViewArguments other) {
if (identical(this, other)) return true;
return other.key == key && other.onTap == onTap && other.label == label;
return other.key == key && other.label == label;
}
@override
int get hashCode {
return key.hashCode ^ onTap.hashCode ^ label.hashCode;
return key.hashCode ^ label.hashCode;
}
}
@ -1463,33 +1487,6 @@ class LearnCourseViewArguments {
}
}
class AssessmentViewArguments {
const AssessmentViewArguments({
this.key,
required this.data,
});
final _i37.Key? key;
final Map<String, dynamic> data;
@override
String toString() {
return '{"key": "$key", "data": "$data"}';
}
@override
bool operator ==(covariant AssessmentViewArguments other) {
if (identical(this, other)) return true;
return other.key == key && other.data == data;
}
@override
int get hashCode {
return key.hashCode ^ data.hashCode;
}
}
extension NavigatorStateExtension on _i46.NavigationService {
Future<dynamic> navigateToHomeView({
_i37.Key? key,
@ -1781,6 +1778,23 @@ extension NavigatorStateExtension on _i46.NavigationService {
transition: transition);
}
Future<dynamic> navigateToAssessmentView({
_i37.Key? key,
required Map<String, dynamic> data,
int? routerId,
bool preventDuplicates = true,
Map<String, String>? parameters,
Widget Function(BuildContext, Animation<double>, Animation<double>, Widget)?
transition,
}) async {
return navigateTo<dynamic>(Routes.assessmentView,
arguments: AssessmentViewArguments(key: key, data: data),
id: routerId,
preventDuplicates: preventDuplicates,
parameters: parameters,
transition: transition);
}
Future<dynamic> navigateToLearnLessonView({
_i37.Key? key,
required _i39.LearnModule module,
@ -1902,7 +1916,6 @@ extension NavigatorStateExtension on _i46.NavigationService {
Future<dynamic> navigateToFailureView({
_i37.Key? key,
required void Function() onTap,
required String label,
int? routerId,
bool preventDuplicates = true,
@ -1911,7 +1924,7 @@ extension NavigatorStateExtension on _i46.NavigationService {
transition,
}) async {
return navigateTo<dynamic>(Routes.failureView,
arguments: FailureViewArguments(key: key, onTap: onTap, label: label),
arguments: FailureViewArguments(key: key, label: label),
id: routerId,
preventDuplicates: preventDuplicates,
parameters: parameters,
@ -2052,23 +2065,6 @@ extension NavigatorStateExtension on _i46.NavigationService {
transition: transition);
}
Future<dynamic> navigateToAssessmentView({
_i37.Key? key,
required Map<String, dynamic> data,
int? routerId,
bool preventDuplicates = true,
Map<String, String>? parameters,
Widget Function(BuildContext, Animation<double>, Animation<double>, Widget)?
transition,
}) async {
return navigateTo<dynamic>(Routes.assessmentView,
arguments: AssessmentViewArguments(key: key, data: data),
id: routerId,
preventDuplicates: preventDuplicates,
parameters: parameters,
transition: transition);
}
Future<dynamic> replaceWithHomeView({
_i37.Key? key,
int? routerId,
@ -2359,6 +2355,23 @@ extension NavigatorStateExtension on _i46.NavigationService {
transition: transition);
}
Future<dynamic> replaceWithAssessmentView({
_i37.Key? key,
required Map<String, dynamic> data,
int? routerId,
bool preventDuplicates = true,
Map<String, String>? parameters,
Widget Function(BuildContext, Animation<double>, Animation<double>, Widget)?
transition,
}) async {
return replaceWith<dynamic>(Routes.assessmentView,
arguments: AssessmentViewArguments(key: key, data: data),
id: routerId,
preventDuplicates: preventDuplicates,
parameters: parameters,
transition: transition);
}
Future<dynamic> replaceWithLearnLessonView({
_i37.Key? key,
required _i39.LearnModule module,
@ -2480,7 +2493,6 @@ extension NavigatorStateExtension on _i46.NavigationService {
Future<dynamic> replaceWithFailureView({
_i37.Key? key,
required void Function() onTap,
required String label,
int? routerId,
bool preventDuplicates = true,
@ -2489,7 +2501,7 @@ extension NavigatorStateExtension on _i46.NavigationService {
transition,
}) async {
return replaceWith<dynamic>(Routes.failureView,
arguments: FailureViewArguments(key: key, onTap: onTap, label: label),
arguments: FailureViewArguments(key: key, label: label),
id: routerId,
preventDuplicates: preventDuplicates,
parameters: parameters,
@ -2629,21 +2641,4 @@ extension NavigatorStateExtension on _i46.NavigationService {
parameters: parameters,
transition: transition);
}
Future<dynamic> replaceWithAssessmentView({
_i37.Key? key,
required Map<String, dynamic> data,
int? routerId,
bool preventDuplicates = true,
Map<String, String>? parameters,
Widget Function(BuildContext, Animation<double>, Animation<double>, Widget)?
transition,
}) async {
return replaceWith<dynamic>(Routes.assessmentView,
arguments: AssessmentViewArguments(key: key, data: data),
id: routerId,
preventDuplicates: preventDuplicates,
parameters: parameters,
transition: transition);
}
}

View File

@ -1,37 +0,0 @@
import 'package:json_annotation/json_annotation.dart';
part 'assessment.g.dart';
@JsonSerializable()
class Assessment {
final int? id;
final String? title;
final String? status;
final String? description;
@JsonKey(name: 'set_type')
final String? setType;
@JsonKey(name: 'passing_score')
final int? passingScore;
@JsonKey(name: 'shuffle_questions')
final bool? shuffleQuestions;
const Assessment(
{this.id,
this.title,
this.status,
this.setType,
this.description,
this.passingScore,
this.shuffleQuestions});
factory Assessment.fromJson(Map<String, dynamic> json) =>
_$AssessmentFromJson(json);
Map<String, dynamic> toJson() => _$AssessmentToJson(this);
}

View File

@ -1,28 +0,0 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'assessment.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
Assessment _$AssessmentFromJson(Map<String, dynamic> json) => Assessment(
id: (json['id'] as num?)?.toInt(),
title: json['title'] as String?,
status: json['status'] as String?,
setType: json['set_type'] as String?,
description: json['description'] as String?,
passingScore: (json['passing_score'] as num?)?.toInt(),
shuffleQuestions: json['shuffle_questions'] as bool?,
);
Map<String, dynamic> _$AssessmentToJson(Assessment instance) =>
<String, dynamic>{
'id': instance.id,
'title': instance.title,
'status': instance.status,
'description': instance.description,
'set_type': instance.setType,
'passing_score': instance.passingScore,
'shuffle_questions': instance.shuffleQuestions,
};

View File

@ -11,10 +11,7 @@ class Option {
@JsonKey(name: 'option_text')
final String? optionText;
@JsonKey(name: 'option_order')
final int? optionOrder;
const Option({this.id, this.optionText, this.isCorrect, this.optionOrder});
const Option({this.id, this.optionText, this.isCorrect});
factory Option.fromJson(Map<String, dynamic> json) => _$OptionFromJson(json);

View File

@ -10,12 +10,10 @@ Option _$OptionFromJson(Map<String, dynamic> json) => Option(
id: (json['id'] as num?)?.toInt(),
optionText: json['option_text'] as String?,
isCorrect: json['is_correct'] as bool?,
optionOrder: (json['option_order'] as num?)?.toInt(),
);
Map<String, dynamic> _$OptionToJson(Option instance) => <String, dynamic>{
'id': instance.id,
'is_correct': instance.isCorrect,
'option_text': instance.optionText,
'option_order': instance.optionOrder,
};

View File

@ -1,9 +1,9 @@
import 'package:json_annotation/json_annotation.dart';
import 'package:yimaru_app/models/option.dart';
part 'assessment_question.g.dart';
part 'question.g.dart';
@JsonSerializable()
class AssessmentQuestion {
class Question {
final int? id;
final int? points;
@ -18,17 +18,21 @@ class AssessmentQuestion {
@JsonKey(name: 'question_text')
final String? questionText;
const AssessmentQuestion({
@JsonKey(name: 'difficulty_level')
final String? difficultyLevel;
const Question({
this.id,
this.points,
this.status,
this.options,
this.questionText,
this.questionType,
this.difficultyLevel,
});
factory AssessmentQuestion.fromJson(Map<String, dynamic> json) =>
_$AssessmentQuestionFromJson(json);
factory Question.fromJson(Map<String, dynamic> json) =>
_$QuestionFromJson(json);
Map<String, dynamic> toJson() => _$AssessmentQuestionToJson(this);
Map<String, dynamic> toJson() => _$QuestionToJson(this);
}

View File

@ -1,13 +1,12 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'assessment_question.dart';
part of 'question.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
AssessmentQuestion _$AssessmentQuestionFromJson(Map<String, dynamic> json) =>
AssessmentQuestion(
Question _$QuestionFromJson(Map<String, dynamic> json) => Question(
id: (json['id'] as num?)?.toInt(),
points: (json['points'] as num?)?.toInt(),
status: json['status'] as String?,
@ -16,14 +15,15 @@ AssessmentQuestion _$AssessmentQuestionFromJson(Map<String, dynamic> json) =>
.toList(),
questionText: json['question_text'] as String?,
questionType: json['question_type'] as String?,
difficultyLevel: json['difficulty_level'] as String?,
);
Map<String, dynamic> _$AssessmentQuestionToJson(AssessmentQuestion instance) =>
<String, dynamic>{
Map<String, dynamic> _$QuestionToJson(Question instance) => <String, dynamic>{
'id': instance.id,
'points': instance.points,
'status': instance.status,
'options': instance.options,
'question_type': instance.questionType,
'question_text': instance.questionText,
'difficulty_level': instance.difficultyLevel,
};

View File

@ -3,7 +3,7 @@ import 'package:yimaru_app/models/learn_lesson.dart';
import 'package:yimaru_app/models/learn_practice.dart';
import 'package:yimaru_app/models/learn_program.dart';
import 'package:yimaru_app/models/level.dart';
import 'package:yimaru_app/models/assessment_question.dart';
import 'package:yimaru_app/models/question.dart';
import 'package:yimaru_app/models/subcategory.dart';
import 'package:yimaru_app/models/category.dart';
import 'package:yimaru_app/models/course_lesson.dart';
@ -20,7 +20,6 @@ import '../models/learn_module.dart';
import '../models/learn_question.dart';
import '../models/lesson.dart';
import '../models/module.dart';
import '../models/assessment.dart';
import '../models/submodule.dart';
import '../ui/common/enmus.dart';
@ -355,47 +354,23 @@ class ApiService {
}
}
// Get assessment question sets
Future<List<Assessment>> getAssessments() async {
// Get assessments
Future<List<Question>> getAssessments() async {
try {
List<Assessment> assessments = [];
List<Question> assessments = [];
final Response response = await _service.dio.get(
'$kBaseUrl/api/$kApiVersionUrl/$kQuestionSetsUrl?set_type=INITIAL_ASSESSMENT&limit=10&offset=0');
if (response.statusCode == 200) {
var data = response.data;
var decodedData = data['data']['question_sets'] as List;
assessments = decodedData.map(
(e) {
return Assessment.fromJson(e);
},
).toList();
return assessments;
}
return [];
} catch (e) {
return [];
}
}
// Get assessment questions
Future<List<AssessmentQuestion>> getAssessmentQuestions(int id) async {
try {
List<AssessmentQuestion> questions = [];
final Response response = await _service.dio.get(
'$kBaseUrl/api/$kApiVersionUrl/$kQuestionSetsUrl/$id/$kQuestionsUrl');
final Response response =
await _service.dio.get('$kBaseUrl/$kAssessmentsUrl');
if (response.statusCode == 200) {
var data = response.data;
var decodedData = data['data'] as List;
questions = decodedData.map(
assessments = decodedData.map(
(e) {
return AssessmentQuestion.fromJson(e);
return Question.fromJson(e);
},
).toList();
return questions;
return assessments;
}
return [];
} catch (e) {
@ -766,9 +741,9 @@ class ApiService {
}
// Get course practic questions
Future<List<AssessmentQuestion>> getCoursePracticeQuestions(int id) async {
Future<List<Question>> getCoursePracticeQuestions(int id) async {
try {
List<AssessmentQuestion> coursePracticeQuestions = [];
List<Question> coursePracticeQuestions = [];
final Response response = await _service.dio
.get('$kBaseUrl/$kPracticeBaseUrl/$id/$kCoursePracticeQuestions');
@ -778,7 +753,7 @@ class ApiService {
var decodedData = data['data'] as List;
coursePracticeQuestions = decodedData.map(
(e) {
return AssessmentQuestion.fromJson(e);
return Question.fromJson(e);
},
).toList();
return coursePracticeQuestions;
@ -790,14 +765,13 @@ class ApiService {
}
// Get course practice question
Future<AssessmentQuestion?> getCoursePracticeQuestion(int id) async {
Future<Question?> getCoursePracticeQuestion(int id) async {
try {
final Response response =
await _service.dio.get('$kBaseUrl/$kCoursePracticeQuestion/$id');
if (response.statusCode == 200) {
AssessmentQuestion question =
AssessmentQuestion.fromJson(response.data['data']);
Question question = Question.fromJson(response.data['data']);
return question;
}
@ -976,9 +950,9 @@ class ApiService {
}
// Questions
Future<List<AssessmentQuestion>> getQuestions(int id) async {
Future<List<Question>> getQuestions(int id) async {
try {
List<AssessmentQuestion> questions = [];
List<Question> questions = [];
final Response response = await _service.dio.get(
'$kBaseUrl/api/$kApiVersionUrl/$kQuestionSetsUrl/$id/$kQuestionsUrl');
@ -988,7 +962,7 @@ class ApiService {
var decodedData = data['data'] as List;
questions = decodedData.map(
(e) {
return AssessmentQuestion.fromJson(e);
return Question.fromJson(e);
},
).toList();
return questions;

View File

@ -173,6 +173,5 @@ class AuthenticationService with ListenableServiceMixin {
_user = null;
await _secureService.clear();
await setFirstTimeInstall(firstTimeInstall);
notifyListeners();
}
}

View File

@ -27,8 +27,8 @@ class DioService {
DioService() {
_dio.options
..baseUrl = kBaseUrl
..connectTimeout = const Duration(seconds: 5)
..receiveTimeout = const Duration(seconds: 15);
..connectTimeout = const Duration(seconds: 30)
..receiveTimeout = const Duration(seconds: 30);
_dio.interceptors.add(
InterceptorsWrapper(

View File

@ -16,8 +16,8 @@ enum LearnPractices { course, module, lesson }
// Voice recording state
enum VoiceRecordingState { pending, recording }
// // Levels
// enum ProficiencyLevels { a1, a2, b1, b2, none }
// Levels
enum ProficiencyLevels { a1, a2, b1, b2, none }
// Progress status
enum ProgressStatuses { pending, started, completed }
@ -29,11 +29,10 @@ enum DuolingoAssessments { speaking, reading, writing, listening }
enum StateObjects {
none,
courses,
startupView,
register,
verifyOtp,
resendOtp,
assessments,
startupView,
learnLessons,
learnModules,
learnCourses,
@ -57,7 +56,6 @@ enum StateObjects {
learnPracticeSample,
learnPracticeAnswer,
loginWithPhoneNumber,
assessmentQuestions,
learnPracticeQuestion,
coursePracticeQuestion,
coursePracticeQuestions,

View File

@ -312,10 +312,6 @@ TextStyle style14MG400 = const TextStyle(
TextStyle style14DG500 =
const TextStyle(color: kcDarkGrey, fontWeight: FontWeight.w500);
TextStyle style18MG500 =
const TextStyle(fontSize: 18,color: kcMediumGrey, fontWeight: FontWeight.w500);
TextStyle style14DG400 = const TextStyle(
color: kcDarkGrey,
);

View File

@ -56,7 +56,7 @@ class AccountPrivacyView extends StackedView<AccountPrivacyViewModel> {
Widget _buildAppbar(AccountPrivacyViewModel viewModel) => SmallAppBar(
showBackButton: true,
onPop: viewModel.pop,
onTap: viewModel.pop,
title: 'Account Privacy',
);

View File

@ -1,12 +1,10 @@
import 'package:flutter/material.dart';
import 'package:stacked/stacked.dart';
import 'package:yimaru_app/ui/common/enmus.dart';
import 'package:yimaru_app/ui/views/assessment/screens/assessment_questions_screen.dart';
import 'package:yimaru_app/ui/views/assessment/screens/assessment_intro_screen.dart';
import 'package:yimaru_app/ui/views/assessment/screens/assessment_result_screen.dart';
import 'package:yimaru_app/ui/views/assessment/screens/start_lesson_screen.dart';
import '../../widgets/assessment_loading_screen.dart';
import 'assessment_viewmodel.dart';
class AssessmentView extends StackedView<AssessmentViewModel> {
@ -41,29 +39,16 @@ class AssessmentView extends StackedView<AssessmentViewModel> {
Widget _buildAssessmentScreens(AssessmentViewModel viewModel) => IndexedStack(
index: viewModel.currentPage,
children: _buildScreens(viewModel),
children: _buildScreens(),
);
List<Widget> _buildScreens(AssessmentViewModel viewModel) => [
_buildAssessmentIntroWrapper(viewModel),
List<Widget> _buildScreens() => [
_buildAssessmentIntro(),
_buildAssessment(),
_buildAssessmentResult(),
_buildStartLesson(),
];
Widget _buildAssessmentIntroWrapper(AssessmentViewModel viewModel) =>
viewModel.busy(StateObjects.assessments) || viewModel.assessments.isEmpty
? _buildPageLoadingIndicator(viewModel)
: _buildAssessmentIntro();
Widget _buildPageLoadingIndicator(AssessmentViewModel viewModel) =>
AssessmentLoadingScreen(
isEmpty: viewModel.assessments.isEmpty,
onTap: () async => await viewModel.getAssessments(),
isLoading: viewModel.busy(StateObjects.assessments),
onPop: viewModel.assessments.isEmpty ? viewModel.pop : null,
);
Widget _buildAssessmentIntro() => const AssessmentIntroScreen();
Widget _buildAssessment() => const AssessmentQuestionsScreen();

View File

@ -1,14 +1,13 @@
import 'package:flutter/cupertino.dart';
import 'package:stacked/stacked.dart';
import 'package:stacked_services/stacked_services.dart';
import 'package:yimaru_app/models/assessment_question.dart';
import 'package:yimaru_app/models/option.dart';
import 'package:yimaru_app/services/status_checker_service.dart';
import 'package:yimaru_app/ui/common/enmus.dart';
import '../../../app/app.locator.dart';
import '../../../app/app.router.dart';
import '../../../models/assessment.dart';
import '../../../models/question.dart';
import '../../../services/api_service.dart';
import '../../common/app_colors.dart';
import '../../common/ui_helpers.dart';
@ -34,78 +33,82 @@ class AssessmentViewModel extends BaseViewModel {
PageController get pageController => _pageController;
// Assessment
int _currentQuestion = 0;
List<Assessment> _assessments = [];
int get currentQuestion => _currentQuestion;
List<Assessment> get assessments => _assessments;
List<Question> _assessments = [];
Assessment? _currentAssessment;
List<Question> get assessments => _assessments;
Assessment? get currentAssessment => _currentAssessment;
ProficiencyLevels _proficiencyLevel = ProficiencyLevels.none;
int _currentQuestionIndex = 0;
int get currentQuestionIndex => _currentQuestionIndex;
int _currentAssessmentIndex = 0;
int get currentAssessmentIndex => _currentAssessmentIndex;
String? _proficiencyLevel;
String? get proficiencyLevel => _proficiencyLevel;
ProficiencyLevels get proficiencyLevel => _proficiencyLevel;
final Map<String, dynamic> _selectedAnswers = {};
Map<String, dynamic> get selectedAnswers => _selectedAnswers;
List<AssessmentQuestion> _assessmentQuestions = [];
List<AssessmentQuestion> get assessmentQuestions => _assessmentQuestions;
// User data
final Map<String, dynamic> _userData = {};
Map<String, dynamic> get userData => _userData;
// Assessment
Future<void> setFirstAssessment()async{
_proficiencyLevel = null;
_selectedAnswers.clear();
_currentQuestionIndex = 0;
_pageController.jumpToPage(_currentQuestionIndex);
_currentAssessment = assessments[currentAssessmentIndex];
await getAssessmentQuestions(
_currentAssessment?.id ?? 0);
next();
}
Map<String, dynamic> evaluateAssessment() {
bool levelPassed = canPassLevel();
if (levelPassed) {
return {'passed': true, 'level': _currentAssessment?.description};
if (_currentQuestion == 5) {
// A1
final correctCount = countCorrectAnswersUntil(5);
if (correctCount > 3) {
return {'continue': true, 'level': ProficiencyLevels.a1};
} else {
return {'continue': false, 'level': ProficiencyLevels.a1};
}
} else if (_currentQuestion == 10) {
// A2
final correctCount = countCorrectAnswersUntil(10);
if (correctCount > 3) {
return {'continue': true, 'level': ProficiencyLevels.a2};
} else {
return {'continue': false, 'level': ProficiencyLevels.a2};
}
} else if (_currentQuestion == 16) {
// B1
final correctCount = countCorrectAnswersUntil(16);
if (correctCount > 4) {
return {'continue': true, 'level': ProficiencyLevels.b1};
} else {
return {'continue': false, 'level': ProficiencyLevels.b1};
}
} else if (_currentQuestion == 22) {
final correctCount = countCorrectAnswersUntil(16);
if (correctCount > 4) {
return {'continue': false, 'level': ProficiencyLevels.b2};
} else {
return {'continue': false, 'level': ProficiencyLevels.b2};
}
} else {
return {'passed': false, 'level': _currentAssessment?.description};
return {'continue': true, 'level': ProficiencyLevels.none};
}
}
bool canPassLevel() {
int countCorrectAnswersUntil(int untilQuestion) {
int count = 0;
for (int i = 1; i <= _assessmentQuestions.length; i++) {
for (int i = 1; i <= untilQuestion; i++) {
final answer = _selectedAnswers[i.toString()];
if (answer is Map<String, dynamic> && answer['correct'] == true) {
count++;
}
}
print('COUNT: $count');
print('ASSESSMENT: ${_currentAssessment?.passingScore}');
if (count >= (_currentAssessment?.passingScore ?? 0)) {
return true;
}
return false;
return count;
}
bool isSelectedAnswer({required int question, required String answer}) {
@ -122,7 +125,7 @@ class AssessmentViewModel extends BaseViewModel {
question.toString(): {
'correct': correct,
'option': option?.optionText,
'answer': _assessmentQuestions[question - 1]
'answer': _assessments[question - 1]
.options
?.firstWhere((e) => e.isCorrect ?? false)
.optionText
@ -149,41 +152,32 @@ class AssessmentViewModel extends BaseViewModel {
}
// Question navigation
Future<void> nextQuestion() async {
_currentQuestionIndex++;
void nextQuestion() {
_currentQuestion++;
Map<String, dynamic> response = evaluateAssessment();
print('LEVEL: $response');
print('LENGTH: ${_assessmentQuestions.length}');
print('INDEX: $_currentQuestionIndex');
if (_currentQuestionIndex == _assessmentQuestions.length) {
_currentAssessmentIndex = _currentAssessmentIndex + 1;
if (_currentAssessmentIndex == _assessments.length) {
_proficiencyLevel = response['level'];
next();
if (_currentQuestion == _assessments.length) {
_proficiencyLevel = response['level'];
next();
} else {
if (response['level'] == ProficiencyLevels.none) {
_pageController.jumpToPage(_currentQuestion);
} else {
if (response['passed']) {
_selectedAnswers.clear();
_currentQuestionIndex = 0;
_proficiencyLevel = response['level'];
_currentAssessment = assessments[currentAssessmentIndex];
await getAssessmentQuestions(
_currentAssessment?.id ?? 0);
_pageController.jumpToPage(_currentQuestionIndex);
if (response['continue']) {
_pageController.jumpToPage(_currentQuestion);
} else {
_proficiencyLevel = response['level'];
next();
}
}
} else {
_pageController.jumpToPage(_currentQuestionIndex);
}
rebuildUi();
}
void previousQuestion() {
if (_currentQuestionIndex != 0) {
_currentQuestionIndex--;
if (_currentQuestion != 0) {
_currentQuestion--;
_pageController.previousPage(
duration: const Duration(microseconds: 100), curve: Curves.linear);
rebuildUi();
@ -199,7 +193,7 @@ class AssessmentViewModel extends BaseViewModel {
_currentPage = 0;
rebuildUi();
} else if (_currentPage == 3) {
if (_proficiencyLevel != null) {
if (_proficiencyLevel != ProficiencyLevels.none) {
_currentPage--;
} else {
_currentPage = 0;
@ -246,12 +240,12 @@ class AssessmentViewModel extends BaseViewModel {
// Navigation
void pop() => _navigationService.back();
Future<void> replaceWithStartUp() async =>
await _navigationService.clearStackAndShow(Routes.startupView);
Future<void> navigateToLanguage() async =>
await _navigationService.navigateToLanguageView();
Future<void> replaceWittStartUp() async =>
await _navigationService.clearStackAndShow(Routes.startupView);
// Remote api call
// Complete profile
@ -265,7 +259,7 @@ class AssessmentViewModel extends BaseViewModel {
await _apiService.completeProfile(_userData);
if (response['status'] == ResponseStatus.success) {
clearUserData();
await replaceWittStartUp();
await replaceWithStartUp();
showSuccessToast(response['message']);
} else {
showErrorToast(response['message']);
@ -274,23 +268,11 @@ class AssessmentViewModel extends BaseViewModel {
}
// Assessments
Future<void> getAssessments() async =>
await runBusyFuture(_getAssessments(),
busyObject: StateObjects.assessments);
Future<void> _getAssessments() async {
if (await _statusChecker.checkConnection()) {
_assessments = await _apiService.getAssessments();
}
}
Future<void> getAssessmentQuestions(int id) async =>
await runBusyFuture(_getAssessmentQuestions(id),
busyObject: StateObjects.assessmentQuestions);
Future<void> _getAssessmentQuestions(int id) async {
if (await _statusChecker.checkConnection()) {
_assessmentQuestions = await _apiService.getAssessmentQuestions(id);
}
}
Future<void> getAssessments() async => await runBusyFuture(_getAssessments());
}

View File

@ -10,9 +10,6 @@ import '../assessment_viewmodel.dart';
class AssessmentIntroScreen extends ViewModelWidget<AssessmentViewModel> {
const AssessmentIntroScreen({super.key});
Future<void> _next(AssessmentViewModel viewModel) async =>
viewModel.setFirstAssessment();
@override
Widget build(BuildContext context, AssessmentViewModel viewModel) =>
_buildScaffoldWrapper(viewModel);
@ -98,8 +95,8 @@ class AssessmentIntroScreen extends ViewModelWidget<AssessmentViewModel> {
text: 'Continue',
borderRadius: 12,
foregroundColor: kcWhite,
onTap: () => viewModel.next(),
backgroundColor: kcPrimaryColor,
onTap: () async => await _next(viewModel),
);
Widget _buildSkipButtonWrapper(AssessmentViewModel viewModel) => Padding(

View File

@ -1,9 +1,9 @@
import 'package:flutter/material.dart';
import 'package:yimaru_app/ui/widgets/page_loading_indicator.dart';
import 'package:yimaru_app/ui/widgets/refresh_button.dart';
import '../common/app_colors.dart';
import 'large_app_bar.dart';
import '../../../common/app_colors.dart';
import '../../../widgets/large_app_bar.dart';
import '../../../widgets/refresh_button.dart';
class AssessmentLoadingScreen extends StatelessWidget {
final bool isEmpty;

View File

@ -6,15 +6,28 @@ import 'package:yimaru_app/ui/widgets/custom_elevated_button.dart';
import 'package:yimaru_app/ui/widgets/custom_small_radio_button.dart';
import 'package:yimaru_app/ui/widgets/large_app_bar.dart';
import '../../../widgets/assessment_loading_screen.dart';
import '../assessment_viewmodel.dart';
import 'assessment_loading_screen.dart';
class AssessmentQuestionsScreen extends ViewModelWidget<AssessmentViewModel> {
const AssessmentQuestionsScreen({super.key});
@override
Widget build(BuildContext context, AssessmentViewModel viewModel) =>
_buildAssessmentScreensWrapper(viewModel);
_buildAssessmentScreens(viewModel);
Widget _buildAssessmentScreens(AssessmentViewModel viewModel) =>
viewModel.isBusy || viewModel.assessments.isEmpty
? _buildPageLoadingIndicator(viewModel)
: _buildAssessmentScreensWrapper(viewModel);
Widget _buildPageLoadingIndicator(AssessmentViewModel viewModel) =>
AssessmentLoadingScreen(
isLoading: viewModel.isBusy,
isEmpty: viewModel.assessments.isEmpty,
onTap: () async => await viewModel.getAssessments(),
onPop: viewModel.assessments.isEmpty ? viewModel.pop : null,
);
Widget _buildAssessmentScreensWrapper(AssessmentViewModel viewModel) =>
PopScope(
@ -39,7 +52,7 @@ class AssessmentQuestionsScreen extends ViewModelWidget<AssessmentViewModel> {
onClose: viewModel.abort,
showLanguageSelection: false,
onPop: viewModel.previousQuestion,
showBackButton: viewModel.currentQuestionIndex == 0 ? false : true,
showBackButton: viewModel.currentQuestion == 0 ? false : true,
);
Widget _buildExpandedBody(AssessmentViewModel viewModel) =>
@ -52,7 +65,7 @@ class AssessmentQuestionsScreen extends ViewModelWidget<AssessmentViewModel> {
Widget _buildAssessment(AssessmentViewModel viewModel) => PageView.builder(
controller: viewModel.pageController,
itemCount: viewModel.assessmentQuestions.length,
itemCount: viewModel.assessments.length,
physics: const NeverScrollableScrollPhysics(),
itemBuilder: (cotext, index) =>
_buildBodyScroller(index: index, viewModel: viewModel),
@ -85,7 +98,7 @@ class AssessmentQuestionsScreen extends ViewModelWidget<AssessmentViewModel> {
Widget _buildTitle(
{required int index, required AssessmentViewModel viewModel}) =>
Text(
'Q${index + 1}. ${viewModel.assessmentQuestions[index].questionText} ',
'Q${index + 1}. ${viewModel.assessments[index].questionText} ',
style: style16DG600,
);
@ -94,18 +107,15 @@ class AssessmentQuestionsScreen extends ViewModelWidget<AssessmentViewModel> {
ListView.builder(
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
itemCount: viewModel.assessmentQuestions[index].options?.length,
itemCount: viewModel.assessments[index].options?.length,
itemBuilder: (context, inner) => _buildAnswer(
onTap: () => viewModel.setSelectedAnswer(
question: index + 1,
option: viewModel.assessmentQuestions[index].options?[inner]),
title:
viewModel.assessmentQuestions[index].options?[inner].optionText ??
'',
option: viewModel.assessments[index].options?[inner]),
title: viewModel.assessments[index].options?[inner].optionText ?? '',
selected: viewModel.isSelectedAnswer(
question: index + 1,
answer: viewModel
.assessmentQuestions[index].options?[inner].optionText ??
answer: viewModel.assessments[index].options?[inner].optionText ??
''),
),
);
@ -140,8 +150,8 @@ class AssessmentQuestionsScreen extends ViewModelWidget<AssessmentViewModel> {
onTap: viewModel.selectedAnswers.containsKey(question.toString())
? () => viewModel.nextQuestion()
: null,
text: viewModel.currentQuestionIndex == viewModel.assessmentQuestions.length - 1
? 'Finish Level'
text: viewModel.currentQuestion == viewModel.assessments.length - 1
? 'Finish'
: 'Continue',
);
}

View File

@ -75,7 +75,7 @@ class AssessmentResultScreen extends ViewModelWidget<AssessmentViewModel> {
];
Widget _buildTitle(AssessmentViewModel viewModel) => Text(
'Youre likely a ${viewModel.proficiencyLevel?.toUpperCase()} speaker!',
'Youre likely a ${viewModel.proficiencyLevel.name.toUpperCase()} speaker!',
style: style25DG600,
textAlign: TextAlign.center,
);
@ -87,12 +87,12 @@ class AssessmentResultScreen extends ViewModelWidget<AssessmentViewModel> {
);
Widget _buildIconWrapper(AssessmentViewModel viewModel) =>
viewModel.proficiencyLevel != null
viewModel.proficiencyLevel != ProficiencyLevels.none
? _buildIcon(viewModel)
: Container();
Widget _buildIcon(AssessmentViewModel viewModel) => SvgPicture.asset(
'assets/icons/${viewModel.proficiencyLevel?.substring(0, 1).toLowerCase()}_${viewModel.proficiencyLevel?.substring(1).toLowerCase()}.svg');
'assets/icons/${viewModel.proficiencyLevel.name.substring(0, 1)}_${viewModel.proficiencyLevel.name.substring(1)}.svg');
Widget _buildSecondarySubtitle() => Text(
'Let\'s start your practice',

View File

@ -14,9 +14,9 @@ class StartLessonScreen extends ViewModelWidget<AssessmentViewModel> {
const StartLessonScreen({super.key});
Future<void> _start(AssessmentViewModel viewModel) async {
if (viewModel.proficiencyLevel != null) {
if (viewModel.proficiencyLevel != ProficiencyLevels.none) {
Map<String, dynamic> data = {
'knowledge_level': viewModel.proficiencyLevel?.toUpperCase()
'knowledge_level': viewModel.proficiencyLevel.name.toUpperCase()
};
viewModel.addUserData(data);

View File

@ -49,7 +49,7 @@ class CallSupportView extends StackedView<CallSupportViewModel> {
Widget _buildAppbar(CallSupportViewModel viewModel) => SmallAppBar(
showBackButton: true,
onPop: viewModel.pop,
onTap: viewModel.pop,
title: 'Call Support',
);

View File

@ -56,7 +56,7 @@ class CourseView extends StackedView<CourseViewModel> {
);
Widget _buildAppBar(CourseViewModel viewModel) => SmallAppBar(
onPop: viewModel.pop,
onTap: viewModel.pop,
showBackButton: true,
);

View File

@ -57,7 +57,7 @@ class CourseLessonView extends StackedView<CourseLessonViewModel> {
);
Widget _buildAppBar(CourseLessonViewModel viewModel) => SmallAppBar(
onPop: viewModel.pop,
onTap: viewModel.pop,
showBackButton: true,
title: 'Course Detail',
);

View File

@ -57,7 +57,7 @@ class CourseLessonDetailView extends StackedView<CourseLessonDetailViewModel> {
child: _buildAppBar(viewModel));
Widget _buildAppBar(CourseLessonDetailViewModel viewModel) => SmallAppBar(
onPop: viewModel.pop,
onTap: viewModel.pop,
showBackButton: true,
title: lesson.title ?? '',
);

View File

@ -50,7 +50,7 @@ class CoursePaymentView extends StackedView<CoursePaymentViewModel> {
);
Widget _buildAppBar(CoursePaymentViewModel viewModel) => SmallAppBar(
onPop: viewModel.pop,
onTap: viewModel.pop,
showBackButton: true,
);

View File

@ -53,7 +53,7 @@ class CoursePracticeView extends StackedView<CoursePracticeViewModel> {
);
Widget _buildAppBar(CoursePracticeViewModel viewModel) => SmallAppBar(
onPop: viewModel.pop,
onTap: viewModel.pop,
showBackButton: true,
);

View File

@ -4,7 +4,7 @@ import 'package:stacked_services/stacked_services.dart';
import '../../../app/app.locator.dart';
import '../../../models/option.dart';
import '../../../models/assessment_question.dart';
import '../../../models/question.dart';
import '../../../services/api_service.dart';
import '../../../services/status_checker_service.dart';
import '../../common/app_colors.dart';
@ -38,14 +38,13 @@ class CoursePracticeQuestionViewModel extends FormViewModel {
bool get focusAnswer => _focusAnswer;
AssessmentQuestion? _currentQuestion;
Question? _currentQuestion;
AssessmentQuestion? get currentQuestion => _currentQuestion;
Question? get currentQuestion => _currentQuestion;
List<AssessmentQuestion> _coursePracticeQuestions = [];
List<Question> _coursePracticeQuestions = [];
List<AssessmentQuestion> get coursePracticeQuestions =>
_coursePracticeQuestions;
List<Question> get coursePracticeQuestions => _coursePracticeQuestions;
int _currentQuestionIndex = 0;

View File

@ -59,7 +59,7 @@ class CourseSubcategoryView extends StackedView<CourseSubcategoryViewModel> {
);
Widget _buildAppBar(CourseSubcategoryViewModel viewModel) => SmallAppBar(
onPop: viewModel.pop,
onTap: viewModel.pop,
showBackButton: true,
);

View File

@ -53,7 +53,7 @@ class DownloadsView extends StackedView<DownloadsViewModel> {
];
Widget _buildAppbar(DownloadsViewModel viewModel) => SmallAppBar(
onPop: viewModel.pop,
onTap: viewModel.pop,
showBackButton: true,
title: 'Offline Downloads',
);

View File

@ -9,10 +9,8 @@ import 'failure_viewmodel.dart';
class FailureView extends StackedView<FailureViewModel> {
final String label;
final GestureTapCallback onTap;
const FailureView({Key? key, required this.onTap, required this.label})
: super(key: key);
const FailureView({Key? key, required this.label}) : super(key: key);
@override
FailureViewModel viewModelBuilder(BuildContext context) => FailureViewModel();
@ -50,38 +48,19 @@ class FailureView extends StackedView<FailureViewModel> {
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: _buildColumnChildren(),
children: _buildUpperColumnChildren(),
);
List<Widget> _buildColumnChildren() =>
List<Widget> _buildUpperColumnChildren() =>
[_buildIconWrapper(), _buildSafeWrapper()];
Widget _buildIconWrapper() => Padding(
padding: const EdgeInsets.only(top: 100),
child: _buildIcon(),
);
Widget _buildSafeWrapper() => SafeArea(child: _buildLoadingTextContainer());
Widget _buildIcon() => SvgPicture.asset('assets/icons/logo.svg', height: 50);
Widget _buildSafeWrapper() => SafeArea(child: _buildBottomSectionWrapper());
Widget _buildBottomSectionWrapper() => Padding(
Widget _buildLoadingTextContainer() => Padding(
padding: const EdgeInsets.only(bottom: 50),
child: _buildBottomSectionColumn(),
child: _buildLoadingTextWrapper(),
);
Widget _buildBottomSectionColumn() => Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center,
children: _buildBottomSectionChildren(),
);
List<Widget> _buildBottomSectionChildren() => [
_buildLoadingTextWrapper(),
verticalSpaceSmall,
_buildRetryButtonWrapper()
];
Widget _buildLoadingTextWrapper() => Row(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
@ -106,14 +85,10 @@ class FailureView extends StackedView<FailureViewModel> {
Widget _buildIndicator() =>
const CustomCircularProgressIndicator(color: kcWhite);
Widget _buildRetryButtonWrapper() => GestureDetector(
onTap: onTap,
child: _buildRetryButton(),
Widget _buildIconWrapper() => Padding(
padding: const EdgeInsets.only(top: 100),
child: _buildIcon(),
);
Widget _buildRetryButton() => Text(
'Retry',
style: style16W600.copyWith(
fontStyle: FontStyle.italic, decoration: TextDecoration.underline),
);
Widget _buildIcon() => SvgPicture.asset('assets/icons/logo.svg', height: 50);
}

View File

@ -1,21 +1,16 @@
import 'package:flutter/material.dart';
import 'package:stacked/stacked.dart';
import 'package:yimaru_app/ui/common/app_colors.dart';
import 'package:yimaru_app/ui/common/enmus.dart';
import 'package:yimaru_app/ui/views/learn_program/learn_program_view.dart';
import 'package:yimaru_app/ui/views/profile/profile_view.dart';
import 'package:yimaru_app/ui/views/startup/startup_view.dart';
import 'package:yimaru_app/ui/widgets/coming_soon.dart';
import '../../common/enmus.dart';
import '../../widgets/page_loading_indicator.dart';
import 'home_viewmodel.dart';
class HomeView extends StackedView<HomeViewModel> {
const HomeView({Key? key}) : super(key: key);
@override
void onViewModelReady(HomeViewModel viewModel) async {
await viewModel.inAppUpdate();
super.onViewModelReady(viewModel);
}
@override
HomeViewModel viewModelBuilder(BuildContext context) => HomeViewModel();
@ -25,6 +20,8 @@ class HomeView extends StackedView<HomeViewModel> {
BuildContext context, HomeViewModel viewModel, Widget? child) =>
_buildScaffold(viewModel);
Widget _buildScaffold(HomeViewModel viewModel) => Scaffold(
body: getViewForIndex(viewModel.currentPage),
bottomNavigationBar: _buildBottomNav(viewModel),
@ -59,22 +56,22 @@ class HomeView extends StackedView<HomeViewModel> {
label: 'Profile',
icon: _buildProfileIcon(),
);
}
Widget _buildLearnIcon() => const Icon(Icons.school);
Widget _buildLearnIcon() => const Icon(Icons.school);
Widget _buildCourseIcon() => const Icon(Icons.book);
Widget _buildCourseIcon() => const Icon(Icons.book);
Widget _buildProfileIcon() => const Icon(Icons.person);
Widget _buildProfileIcon() => const Icon(Icons.person);
Widget getViewForIndex(int index) {
switch (index) {
case 0:
return const LearnProgramView();
case 1:
return const ComingSoon();
Widget getViewForIndex(int index) {
switch (index) {
case 0:
return const LearnProgramView();
case 1:
return const ComingSoon();
default:
return const ProfileView();
}
default:
return const ProfileView();
}
}

View File

@ -1,19 +1,21 @@
import 'package:yimaru_app/app/app.bottomsheets.dart';
import 'package:yimaru_app/app/app.locator.dart';
import 'package:yimaru_app/app/app.router.dart';
import 'package:yimaru_app/models/user.dart';
import 'package:yimaru_app/services/status_checker_service.dart';
import 'package:yimaru_app/ui/common/app_strings.dart';
import 'package:stacked/stacked.dart';
import 'package:stacked_services/stacked_services.dart';
import '../../../services/api_service.dart';
import '../../../services/authentication_service.dart';
import '../../../services/in_app_update_service.dart';
import '../../../services/image_downloader_service.dart';
import '../../common/enmus.dart';
import '../../common/ui_helpers.dart';
class HomeViewModel extends ReactiveViewModel {
// Dependency injection
final _statusChecker = locator<StatusCheckerService>();
final _bottomSheetService = locator<BottomSheetService>();
final _inAppUpdateService = locator<InAppUpdateService>();
final _authenticationService = locator<AuthenticationService>();
@override
@ -44,12 +46,9 @@ class HomeViewModel extends ReactiveViewModel {
rebuildUi();
}
// Remote api calls
// In-app update
Future<void> inAppUpdate() async {
if (await _statusChecker.checkConnection()) {
await _inAppUpdateService.checkForUpdate();
}
}
}

View File

@ -73,7 +73,7 @@ class LanguageView extends StackedView<LanguageViewModel> {
Widget _buildAppbar(LanguageViewModel viewModel) => SmallAppBar(
showBackButton: true,
onPop: viewModel.pop,
onTap: viewModel.pop,
title: 'Language Preference',
);

View File

@ -55,7 +55,7 @@ class LearnCourseView extends StackedView<LearnCourseViewModel> {
);
Widget _buildAppBar(LearnCourseViewModel viewModel) => SmallAppBar(
onPop: viewModel.pop,
onTap: viewModel.pop,
showBackButton: true,
);

View File

@ -77,7 +77,7 @@ class LearnLessonView extends StackedView<LearnLessonViewModel> {
);
Widget _buildAppBar(LearnLessonViewModel viewModel) => SmallAppBar(
onPop: viewModel.pop,
onTap: viewModel.pop,
showBackButton: true,
);

View File

@ -17,7 +17,7 @@ class LearnLessonDetailView extends StackedView<LearnLessonDetailViewModel> {
Future<void> _navigate(LearnLessonDetailViewModel viewModel) async {
await viewModel.pause();
await viewModel.navigateToLearnPractice(lesson.id ?? 0);
await viewModel.navigateToLearnPractice();
}
@override
@ -60,7 +60,7 @@ class LearnLessonDetailView extends StackedView<LearnLessonDetailViewModel> {
child: _buildAppBar(viewModel));
Widget _buildAppBar(LearnLessonDetailViewModel viewModel) => SmallAppBar(
onPop: viewModel.pop,
onTap: viewModel.pop,
showBackButton: true,
);

View File

@ -4,7 +4,6 @@ import 'package:stacked_services/stacked_services.dart';
import 'package:yimaru_app/ui/common/enmus.dart';
import '../../../app/app.locator.dart';
import '../../../app/app.router.dart';
import '../../../services/status_checker_service.dart';
class LearnLessonDetailViewModel extends BaseViewModel {
@ -45,6 +44,6 @@ class LearnLessonDetailViewModel extends BaseViewModel {
// Navigation
void pop() => _navigationService.back();
Future<void> navigateToLearnPractice(int id) async => await _navigationService
.navigateToLearnPracticeView(id: id, practice: LearnPractices.lesson);
Future<void> navigateToLearnPractice() async {}
// await _navigationService.navigateToLearnPracticeView();
}

View File

@ -19,7 +19,7 @@ class LearnModuleView extends StackedView<LearnModuleViewModel> {
@override
void onViewModelReady(LearnModuleViewModel viewModel) async {
await viewModel.getLearnModules(course.id ?? 0);
await viewModel.getLearnModules(1);
super.onViewModelReady(viewModel);
}
@ -58,7 +58,7 @@ class LearnModuleView extends StackedView<LearnModuleViewModel> {
);
Widget _buildAppBar(LearnModuleViewModel viewModel) => SmallAppBar(
onPop: viewModel.pop,
onTap: viewModel.pop,
showBackButton: true,
);
@ -116,10 +116,10 @@ class LearnModuleView extends StackedView<LearnModuleViewModel> {
physics: const NeverScrollableScrollPhysics(),
itemBuilder: (context, index) => _buildTile(
module: viewModel.modules[index],
onPracticeTap: () async => await viewModel
.navigateToLearnPractice(viewModel.modules[index].id ?? 0),
onModuleTap: () async =>
await viewModel.navigateToLearnLesson(viewModel.modules[index]),
onPracticeTap: () async => await viewModel
.navigateToLearnPractice(viewModel.modules[index].id ?? 0),
),
);

View File

@ -2,7 +2,6 @@ import 'package:flutter/material.dart';
import 'package:stacked/stacked.dart';
import 'package:yimaru_app/ui/common/enmus.dart';
import 'package:yimaru_app/ui/views/learn_practice/screens/finish_learn_practice_screen.dart';
import 'package:yimaru_app/ui/views/learn_practice/screens/learn_loading_screen.dart';
import 'package:yimaru_app/ui/views/learn_practice/screens/learn_practice_completion_screen.dart';
import 'package:yimaru_app/ui/views/learn_practice/screens/learn_practice_result_screen.dart';
import 'package:yimaru_app/ui/views/learn_practice/screens/learn_practice_questions_screen.dart';
@ -79,20 +78,7 @@ class LearnPracticeView extends StackedView<LearnPracticeViewModel> {
Widget _buildBodyState(LearnPracticeViewModel viewModel) =>
viewModel.busy(StateObjects.learnPractices)
? const PageLoadingIndicator()
: viewModel.practices.isEmpty || viewModel.questions.isEmpty
? _buildPageLoadingIndicator(viewModel)
: _buildBody(viewModel);
Widget _buildPageLoadingIndicator(LearnPracticeViewModel viewModel) =>
LearnLoadingScreen(
isLoading: viewModel.busy(StateObjects.learnPractices),
onTap: () async =>
await viewModel.getLearnPractices(id: id, practice: practice),
onPop: viewModel.practices.isEmpty || viewModel.questions.isEmpty
? viewModel.pop
: null,
isEmpty: viewModel.practices.isEmpty || viewModel.questions.isEmpty,
);
: _buildBody(viewModel);
Widget _buildBody(LearnPracticeViewModel viewModel) => IndexedStack(
index: viewModel.currentPage, children: _buildScreens(viewModel));

View File

@ -149,10 +149,6 @@ class LearnPracticeViewModel extends ReactiveViewModel {
await _audioPlayerService.playUrl(question.voicePrompt ?? '');
}
Future<void> replayVoicePrompt(LearnQuestion question) async {
await _audioPlayerService.playUrl(question.voicePrompt ?? '');
}
Future<void> playResult(
{required Map<String, dynamic> answer, required Voice voice}) async {
setBusyObject(playing: voice, object: answer['busy_object']);
@ -226,7 +222,6 @@ class LearnPracticeViewModel extends ReactiveViewModel {
_questionSetController.nextPage(
duration: const Duration(milliseconds: 350),
curve: Curves.easeInOutCubic);
await playVoicePrompt(_questions[index]);
} else {
goTo(3);
}

View File

@ -50,7 +50,7 @@ class FinishLearnPracticeScreen
Widget _buildAppBar(LearnPracticeViewModel viewModel) => SmallAppBar(
showBackButton: true,
onPop: viewModel.goBack,
onTap: viewModel.goBack,
title: 'Practice Speaking',
);

View File

@ -30,8 +30,8 @@ class InteractLearnPracticeScreen
viewModel.stopRecording();
}
void _reply(LearnPracticeViewModel viewModel) =>
viewModel.replayVoicePrompt(question);
void _start(LearnPracticeViewModel viewModel) =>
viewModel.playVoicePrompt(question);
Future<void> _stop(LearnPracticeViewModel viewModel) async =>
await viewModel.nextQuestion(index: index, question: question);
@ -116,7 +116,7 @@ class InteractLearnPracticeScreen
required LearnPracticeViewModel viewModel}) =>
SmallAppBar(
showBackButton: true,
onPop: () async =>
onTap: () async =>
await _showSheet(context: context, viewModel: viewModel),
title: 'Practice Speaking ($index/${viewModel.questions.length})');
@ -263,7 +263,7 @@ class InteractLearnPracticeScreen
: kcLightGrey,
onTap: viewModel.recordingState == VoiceRecordingState.pending &&
viewModel.player.state != PlayerState.playing
? () => _reply(viewModel)
? () => _start(viewModel)
: null,
);
@ -272,15 +272,15 @@ class InteractLearnPracticeScreen
Widget _buildMicButton(LearnPracticeViewModel viewModel) => ElevatedButton(
style: ButtonStyle(
shadowColor: const WidgetStatePropertyAll(kcWhite),
shape: const WidgetStatePropertyAll(CircleBorder()),
padding: const WidgetStatePropertyAll(EdgeInsets.all(15)),
backgroundColor: WidgetStatePropertyAll(
viewModel.player.state == PlayerState.playing ||
viewModel.busy(StateObjects.recordLearnPracticeAnswer)
? kcVeryLightGrey
: kcPrimaryColor,
),
shadowColor: const WidgetStatePropertyAll(kcWhite),
shape: const WidgetStatePropertyAll(CircleBorder()),
padding: const WidgetStatePropertyAll(EdgeInsets.all(15)),
),
onPressed: () async => viewModel.player.state == PlayerState.playing ||
viewModel.busy(StateObjects.recordLearnPracticeAnswer)

View File

@ -1,66 +0,0 @@
import 'package:flutter/material.dart';
import 'package:yimaru_app/ui/widgets/no_data_indicator.dart';
import 'package:yimaru_app/ui/widgets/page_loading_indicator.dart';
import 'package:yimaru_app/ui/widgets/small_app_bar.dart';
import '../../../common/app_colors.dart';
import '../../../common/ui_helpers.dart';
import '../../../widgets/large_app_bar.dart';
import '../../../widgets/refresh_button.dart';
class LearnLoadingScreen extends StatelessWidget {
final bool isEmpty;
final bool isLoading;
final GestureTapCallback? onPop;
final GestureTapCallback? onTap;
const LearnLoadingScreen(
{super.key,
this.onTap,
this.onPop,
required this.isEmpty,
required this.isLoading});
@override
Widget build(BuildContext context) => _buildScaffoldWrapper();
Widget _buildScaffoldWrapper() => Scaffold(
backgroundColor: kcBackgroundColor,
body: _buildScaffold(),
);
Widget _buildScaffold() => SafeArea(child: _buildStack());
Widget _buildStack() => Stack(
children: [
_buildColumn(),
if (isEmpty) _buildRefreshButtonWrapper(),
if (isLoading) _buildPageIndicator()
],
);
Widget _buildColumn() => Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: _buildColumnChildren(),
);
List<Widget> _buildColumnChildren() =>
[verticalSpaceMedium, _buildAppBarWrapper(), _buildBody()];
Widget _buildAppBarWrapper() => Padding(
padding: const EdgeInsets.symmetric(horizontal: 15),
child: _buildAppBar(),
);
Widget _buildAppBar() => SmallAppBar(onPop: onPop, showBackButton: true);
Widget _buildBody() => Expanded(child: Container());
Widget _buildPageIndicator() => const PageLoadingIndicator();
Widget _buildRefreshButtonWrapper() => Align(
alignment: Alignment.center,
child:_buildRefreshButton());
Widget _buildRefreshButton()=> NoDataIndicator(title:'No practice available!' ,onTap: onTap,);
}

View File

@ -72,7 +72,7 @@ class LearnPracticeIntroScreen extends ViewModelWidget<LearnPracticeViewModel> {
SmallAppBar(
showBackButton: true,
title: 'Practice Speaking',
onPop: () async =>
onTap: () async =>
await _showSheet(context: context, viewModel: viewModel),
);

View File

@ -40,7 +40,7 @@ class LearnPracticeQuestionsScreen
required LearnQuestion question,
}) =>
[
if(index ==1) _buildStartLearnPracticeScreen(index: index, question: question),
_buildStartLearnPracticeScreen(index: index, question: question),
_buildInteractLearnPracticeScreen(index: index, question: question)
];

View File

@ -86,7 +86,7 @@ class LearnPracticeResultScreen
SmallAppBar(
title: 'Result',
showBackButton: true,
onPop: () async =>
onTap: () async =>
await _showSheet(context: context, viewModel: viewModel),
);

View File

@ -97,7 +97,7 @@ class StartLearnPracticeScreen extends ViewModelWidget<LearnPracticeViewModel> {
required LearnPracticeViewModel viewModel}) =>
SmallAppBar(
showBackButton: true,
onPop: () async =>
onTap: () async =>
await _showSheet(context: context, viewModel: viewModel),
title: 'Practice Speaking ($index/${viewModel.questions.length})');

View File

@ -155,6 +155,7 @@ class LoginViewModel extends ReactiveViewModel
// Navigation
Future<void> navigateToRegister() async =>
await _navigationService.navigateToRegisterView();
@ -164,6 +165,9 @@ class LoginViewModel extends ReactiveViewModel
Future<void> replaceWithStartUp() async =>
await _navigationService.clearStackAndShow(Routes.startupView);
// Remote api calls
// Login with email

View File

@ -36,7 +36,6 @@ class OnboardingView extends StackedView<OnboardingViewModel>
void _initClearData() {
topicController.clear();
regionController.clear();
fullNameController.clear();
challengeController.clear();
occupationController.clear();

View File

@ -191,7 +191,7 @@ class OnboardingViewModel extends ReactiveViewModel
final List<String> _topics = [
'Food & Cooking',
'Hobbies, Sports, Music',
' Hobbies, Sports, Music',
'Tech, News, Business',
'Travel, Places, Culture',
'Other'
@ -547,7 +547,6 @@ class OnboardingViewModel extends ReactiveViewModel
// Reset country region form screen
void resetCountryRegionFormScreen() {
_focusRegion = false;
_selectedCountry = 'Ethiopia';
rebuildUi();
}
@ -614,4 +613,6 @@ class OnboardingViewModel extends ReactiveViewModel
Future<void> navigateToAssessment() async =>
await _navigationService.navigateToAssessmentView(data: _userData);
}

View File

@ -55,7 +55,7 @@ class PrivacyPolicyView extends StackedView<PrivacyPolicyViewModel> {
Widget _buildAppbar(PrivacyPolicyViewModel viewModel) => SmallAppBar(
showBackButton: true,
onPop: viewModel.pop,
onTap: viewModel.pop,
title: 'Privacy Policy',
);

View File

@ -3,7 +3,6 @@ import 'package:stacked/stacked.dart';
import 'package:yimaru_app/ui/common/app_colors.dart';
import 'package:yimaru_app/ui/common/enmus.dart';
import 'package:yimaru_app/ui/common/ui_helpers.dart';
import 'package:yimaru_app/ui/widgets/page_loading_indicator.dart';
import 'package:yimaru_app/ui/widgets/profile_card.dart';
import 'package:yimaru_app/ui/widgets/profile_image.dart';
import 'package:yimaru_app/ui/widgets/view_profile_button.dart';
@ -156,7 +155,7 @@ class ProfileView extends StackedView<ProfileViewModel> {
children: _buildSettingsChildren(viewModel));
List<Widget> _buildSettingsChildren(ProfileViewModel viewModel) => [
// _buildDownloadsCard(viewModel),
_buildDownloadsCard(viewModel),
_buildProgressCard(viewModel),
_buildAccountCard(viewModel),
_buildSupportCard(viewModel)
@ -192,7 +191,7 @@ class ProfileView extends StackedView<ProfileViewModel> {
Widget _buildLogOutButton(ProfileViewModel viewModel) => CustomElevatedButton(
height: 55,
text: 'Logout',
text: 'Log Out',
borderRadius: 12,
foregroundColor: kcRed,
backgroundColor: kcRed.withOpacity(0.25),

View File

@ -61,6 +61,13 @@ class ProfileViewModel extends ReactiveViewModel {
}
}
// Logout
Future<void> _logout() async {
await _googleAuthService.logout();
await _authenticationService.logout();
await _navigationService.replaceWithLoginView();
}
// Dialog
Future<bool?> showAbortDialog() async {
DialogResponse? response = await _dialogService.showDialog(
@ -75,6 +82,13 @@ class ProfileViewModel extends ReactiveViewModel {
return response?.confirmed;
}
Future<void> logout() async {
bool? response = await showAbortDialog();
if (response != null && response) {
await _logout();
}
}
// Navigation
void pop() => _navigationService.back();
@ -93,9 +107,6 @@ class ProfileViewModel extends ReactiveViewModel {
Future<void> navigateToSupport() async =>
await _navigationService.navigateToSupportView();
Future<void> navigateToLogin() async =>
await _navigationService.clearStackAndShow(Routes.loginView);
// Remote api call
// Update profile
@ -104,21 +115,10 @@ class ProfileViewModel extends ReactiveViewModel {
Future<void> _updateProfilePicture(String image) async {
if (await _statusChecker.checkConnection()) {
Map<String, dynamic> data = {'profile_picture_url': image};
Map<String, dynamic> data = {
'profile_picture_url': image,
};
await _apiService.updateProfileImage(data: data, userId: _user?.userId);
}
}
Future<void> logout() async {
bool? response = await showAbortDialog();
if (response != null && response) {
await _logout();
}
}
Future<void> _logout() async {
await _googleAuthService.logout();
await _authenticationService.logout();
await navigateToLogin();
}
}

View File

@ -34,13 +34,13 @@ class ProfileDetailView extends StackedView<ProfileDetailViewModel>
Future<void> _update(ProfileDetailViewModel viewModel) async {
Map<String, dynamic> data = {
'region': regionController.text,
'region':regionController.text,
'gender': viewModel.selectedGender,
'last_name': lastNameController.text,
'country': viewModel.selectedCountry,
'first_name': firstNameController.text,
'occupation': occupationController.text,
'birth_day': DateFormat('yyyy-MM-dd').format(DateTime.now()),
'birth_day': DateFormat('d MMM, yyyy').format(DateTime.now()),
};
viewModel.addUserData(data);
@ -75,6 +75,7 @@ class ProfileDetailView extends StackedView<ProfileDetailViewModel>
viewModel.clearUserData();
viewModel.setGender(viewModel.user?.gender ?? '');
viewModel.setSelectedCountry(viewModel.user?.country ?? 'Ethiopia');
}
@override
@ -146,7 +147,7 @@ class ProfileDetailView extends StackedView<ProfileDetailViewModel>
];
Widget _buildAppbar(ProfileDetailViewModel viewModel) => SmallAppBar(
onPop: viewModel.pop,
onTap: viewModel.pop,
showBackButton: true,
title: 'Edit Profile',
);
@ -191,8 +192,9 @@ class ProfileDetailView extends StackedView<ProfileDetailViewModel>
verticalSpaceSmall,
_buildCountryDropdown(viewModel),
verticalSpaceMedium,
_buildRegionFormFieldWrapper(viewModel),
_buildRegionFormFieldWrapper(viewModel),
verticalSpaceMedium,
_buildOccupationDropdownWrapper(viewModel),
verticalSpaceLarge,
_buildLowerColumn(viewModel)
@ -531,10 +533,9 @@ class ProfileDetailView extends StackedView<ProfileDetailViewModel>
);
List<Widget> _buildRegionFormFieldChildren(
ProfileDetailViewModel viewModel) =>
ProfileDetailViewModel viewModel) =>
[
_buildRegionFormFieldLabel(),
verticalSpaceSmall,
_buildRegionFormFieldLabel(),verticalSpaceSmall,
_buildRegionFormField(viewModel),
if (viewModel.hasRegionValidationMessage && viewModel.focusRegion)
verticalSpaceTiny,

View File

@ -47,6 +47,7 @@ class ProfileDetailViewModel extends ReactiveViewModel
String? get selectedGender => _selectedGender;
// First name
bool _focusPhoneNumber = false;
@ -62,6 +63,7 @@ class ProfileDetailViewModel extends ReactiveViewModel
String get selectedCountry => _selectedCountry;
// Occupation
bool _focusOccupation = false;
@ -95,6 +97,7 @@ class ProfileDetailViewModel extends ReactiveViewModel
rebuildUi();
}
// Phone number
void setPhoneNumberFocus() {
_focusPhoneNumber = true;
@ -110,165 +113,167 @@ class ProfileDetailViewModel extends ReactiveViewModel
// Country
// Country
List<String> getCountries() => [
"Afghanistan",
"Albania",
"Algeria",
"Andorra",
"Angola",
"Argentina",
"Armenia",
"Australia",
"Austria",
"Azerbaijan",
"Bahrain",
"Bangladesh",
"Belarus",
"Belgium",
"Belize",
"Benin",
"Bhutan",
"Bolivia",
"Bosnia and Herzegovina",
"Botswana",
"Brazil",
"Brunei",
"Bulgaria",
"Burkina Faso",
"Burundi",
"Cambodia",
"Cameroon",
"Canada",
"Chad",
"Chile",
"China",
"Colombia",
"Comoros",
"Congo",
"Costa Rica",
"Croatia",
"Cuba",
"Cyprus",
"Czech Republic",
"Denmark",
"Djibouti",
"Dominican Republic",
"Ecuador",
"Egypt",
"El Salvador",
"Eritrea",
"Estonia",
"Eswatini",
"Ethiopia",
"Finland",
"France",
"Gabon",
"Gambia",
"Georgia",
"Germany",
"Ghana",
"Greece",
"Guatemala",
"Guinea",
"Haiti",
"Honduras",
"Hungary",
"Iceland",
"India",
"Indonesia",
"Iran",
"Iraq",
"Ireland",
"Israel",
"Italy",
"Jamaica",
"Japan",
"Jordan",
"Kazakhstan",
"Kenya",
"Kuwait",
"Kyrgyzstan",
"Laos",
"Latvia",
"Lebanon",
"Liberia",
"Libya",
"Lithuania",
"Luxembourg",
"Madagascar",
"Malawi",
"Malaysia",
"Maldives",
"Mali",
"Malta",
"Mexico",
"Moldova",
"Monaco",
"Mongolia",
"Morocco",
"Mozambique",
"Myanmar",
"Namibia",
"Nepal",
"Netherlands",
"New Zealand",
"Nicaragua",
"Niger",
"Nigeria",
"North Korea",
"Norway",
"Oman",
"Pakistan",
"Panama",
"Paraguay",
"Peru",
"Philippines",
"Poland",
"Portugal",
"Qatar",
"Romania",
"Russia",
"Rwanda",
"Saudi Arabia",
"Senegal",
"Serbia",
"Singapore",
"Slovakia",
"Slovenia",
"Somalia",
"South Africa",
"South Korea",
"Spain",
"Sri Lanka",
"Sudan",
"Sweden",
"Switzerland",
"Syria",
"Taiwan",
"Tajikistan",
"Tanzania",
"Thailand",
"Tunisia",
"Turkey",
"Uganda",
"Ukraine",
"United Arab Emirates",
"United Kingdom",
"United States",
"Uruguay",
"Uzbekistan",
"Venezuela",
"Vietnam",
"Yemen",
"Zambia",
"Zimbabwe"
];
"Afghanistan",
"Albania",
"Algeria",
"Andorra",
"Angola",
"Argentina",
"Armenia",
"Australia",
"Austria",
"Azerbaijan",
"Bahrain",
"Bangladesh",
"Belarus",
"Belgium",
"Belize",
"Benin",
"Bhutan",
"Bolivia",
"Bosnia and Herzegovina",
"Botswana",
"Brazil",
"Brunei",
"Bulgaria",
"Burkina Faso",
"Burundi",
"Cambodia",
"Cameroon",
"Canada",
"Chad",
"Chile",
"China",
"Colombia",
"Comoros",
"Congo",
"Costa Rica",
"Croatia",
"Cuba",
"Cyprus",
"Czech Republic",
"Denmark",
"Djibouti",
"Dominican Republic",
"Ecuador",
"Egypt",
"El Salvador",
"Eritrea",
"Estonia",
"Eswatini",
"Ethiopia",
"Finland",
"France",
"Gabon",
"Gambia",
"Georgia",
"Germany",
"Ghana",
"Greece",
"Guatemala",
"Guinea",
"Haiti",
"Honduras",
"Hungary",
"Iceland",
"India",
"Indonesia",
"Iran",
"Iraq",
"Ireland",
"Israel",
"Italy",
"Jamaica",
"Japan",
"Jordan",
"Kazakhstan",
"Kenya",
"Kuwait",
"Kyrgyzstan",
"Laos",
"Latvia",
"Lebanon",
"Liberia",
"Libya",
"Lithuania",
"Luxembourg",
"Madagascar",
"Malawi",
"Malaysia",
"Maldives",
"Mali",
"Malta",
"Mexico",
"Moldova",
"Monaco",
"Mongolia",
"Morocco",
"Mozambique",
"Myanmar",
"Namibia",
"Nepal",
"Netherlands",
"New Zealand",
"Nicaragua",
"Niger",
"Nigeria",
"North Korea",
"Norway",
"Oman",
"Pakistan",
"Panama",
"Paraguay",
"Peru",
"Philippines",
"Poland",
"Portugal",
"Qatar",
"Romania",
"Russia",
"Rwanda",
"Saudi Arabia",
"Senegal",
"Serbia",
"Singapore",
"Slovakia",
"Slovenia",
"Somalia",
"South Africa",
"South Korea",
"Spain",
"Sri Lanka",
"Sudan",
"Sweden",
"Switzerland",
"Syria",
"Taiwan",
"Tajikistan",
"Tanzania",
"Thailand",
"Tunisia",
"Turkey",
"Uganda",
"Ukraine",
"United Arab Emirates",
"United Kingdom",
"United States",
"Uruguay",
"Uzbekistan",
"Venezuela",
"Vietnam",
"Yemen",
"Zambia",
"Zimbabwe"
];
void setSelectedCountry(String value) {
_selectedCountry = value;
rebuildUi();
}
// Occupation
void setOccupationFocus() {
_focusOccupation = true;

View File

@ -56,7 +56,7 @@ class ProgressView extends StackedView<ProgressViewModel> {
Widget _buildAppbar(ProgressViewModel viewModel) => SmallAppBar(
title: 'My Progress',
showBackButton: true,
onPop: viewModel.pop,
onTap: viewModel.pop,
);
Widget _buildContentScrollViewWrapper(ProgressViewModel viewModel) =>

View File

@ -11,6 +11,7 @@ import 'package:yimaru_app/ui/common/ui_helpers.dart';
import '../../../app/app.locator.dart';
import '../../../models/user.dart';
import '../../../services/google_auth_service.dart';
import '../../../services/smart_auth_service.dart';
import '../../../services/status_checker_service.dart';
class RegisterViewModel extends ReactiveViewModel

View File

@ -51,8 +51,8 @@ class StartupView extends StackedView<StartupViewModel> {
Widget _buildColumn() => Column(
mainAxisSize: MainAxisSize.max,
crossAxisAlignment: CrossAxisAlignment.stretch,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: _buildUpperColumnChildren(),
);

View File

@ -1,6 +1,7 @@
import 'package:stacked/stacked.dart';
import 'package:stacked_services/stacked_services.dart';
import 'package:yimaru_app/services/authentication_service.dart';
import 'package:yimaru_app/services/in_app_update_service.dart';
import '../../../app/app.locator.dart';
import '../../../app/app.router.dart';
@ -9,12 +10,14 @@ import '../../../services/api_service.dart';
import '../../../services/image_downloader_service.dart';
import '../../../services/status_checker_service.dart';
import '../../common/enmus.dart';
import '../../common/ui_helpers.dart';
class StartupViewModel extends ReactiveViewModel {
// Dependency injection
final _apiService = locator<ApiService>();
final _statusChecker = locator<StatusCheckerService>();
final _navigationService = locator<NavigationService>();
final _inAppUpdateService = locator<InAppUpdateService>();
final _authenticationService = locator<AuthenticationService>();
final _imageDownloaderService = locator<ImageDownloaderService>();
@ -27,12 +30,15 @@ class StartupViewModel extends ReactiveViewModel {
User? get user => _user;
// Main startup and navigation logic
// Place anything here that needs to happen before we get into the application
Future runStartupLogic() async {
final loggedIn = await _authenticationService.userLoggedIn();
final firstTimeInstall = await _authenticationService.isFirstTimeInstall();
await _inAppUpdate();
if (firstTimeInstall) {
await _navigationService.replaceWithWelcomeView();
} else {
@ -46,45 +52,63 @@ class StartupViewModel extends ReactiveViewModel {
}
}
// Navigation
Future<void> replaceWithFailure() async => await _navigationService.replaceWithFailureView(
label: 'Check you internet connection',
onTap: () async => await _getProfileStatus());
Future<void> replaceWithFailure() async => await _navigationService
.replaceWithFailureView(label: 'Check you internet connection');
Future<void> replaceWithOnboarding() async =>
await _navigationService.replaceWithOnboardingView();
Future<void> replaceWithHome() async =>
await _navigationService.replaceWithHomeView();
// Remote api calls
// In-app update
Future<void> _inAppUpdate() async {
if (await _statusChecker.checkConnection()) {
await _inAppUpdateService.checkForUpdate();
}
}
// Get profile status
Future<void> _getProfileStatus() async {
final bool? profileCompleted = _user?.profileCompleted;
Map<String, dynamic> response = {};
if (profileCompleted == null) {
if (_user?.profileCompleted == null) {
if (await _statusChecker.checkConnection()) {
print('PATH: 1');
response = await _apiService.getProfileStatus(_user);
} else {
print('PATH: 2');
await Future.delayed(kDuration);
await replaceWithFailure();
}
} else if (!profileCompleted) {
} else if (!(_user?.profileCompleted ?? false)) {
print('PATH: 3');
response = {'data': false, 'status': ResponseStatus.success};
} else {
print('PATH: 4');
response = {'data': true, 'status': ResponseStatus.success};
}
if (response['status'] == ResponseStatus.success && !response['data']) {
print('PATH: 5');
await replaceWithOnboarding();
} else if (response['status'] == ResponseStatus.success &&
response['data']) {
print('PATH: 6');
await saveProfileStatus(response['data']);
await _getProfileData();
await replaceWithHome();
} else {
await replaceWithFailure();
}
}
@ -94,24 +118,26 @@ class StartupViewModel extends ReactiveViewModel {
// Get profile data
Future<void> _getProfileData() async {
bool? infoLoaded = _user?.userInfoLoaded ?? false;
bool? profileCompleted = _user?.profileCompleted ?? false;
if (!infoLoaded) {
if (!(_user?.userInfoLoaded ?? false)) {
Map<String, dynamic> response = {};
if (profileCompleted) {
response = await _apiService.getProfileData(_user?.userId);
if (_user?.profileCompleted != null &&
(_user?.profileCompleted ?? false)) {
if (await _statusChecker.checkConnection()) {
response = await _apiService.getProfileData(_user?.userId);
if (response['status'] == ResponseStatus.success) {
User user = response['data'] as User;
if (response['status'] == ResponseStatus.success) {
User user = response['data'] as User;
await _authenticationService.saveUserData(user);
await _authenticationService.saveUserData(user);
String image =
await _imageDownloaderService.downloader(user.profilePicture);
String image =
await _imageDownloaderService.downloader(user.profilePicture);
await _authenticationService.saveProfilePicture(image);
await _authenticationService.saveProfilePicture(image);
}
} else {
await replaceWithFailure();
}
}
}

View File

@ -53,7 +53,7 @@ class SupportView extends StackedView<SupportViewModel> {
Widget _buildAppbar(SupportViewModel viewModel) => SmallAppBar(
title: 'Need Help?',
showBackButton: true,
onPop: viewModel.pop,
onTap: viewModel.pop,
);
Widget _buildContentWrapper(SupportViewModel viewModel) =>

View File

@ -49,7 +49,7 @@ class TelegramSupportView extends StackedView<TelegramSupportViewModel> {
);
Widget _buildAppbar(TelegramSupportViewModel viewModel) => SmallAppBar(
onPop: viewModel.pop,
onTap: viewModel.pop,
showBackButton: true,
title: 'Telegram Support',
);

View File

@ -57,7 +57,7 @@ class TermsAndConditionsView extends StackedView<TermsAndConditionsViewModel> {
);
Widget _buildAppbar(TermsAndConditionsViewModel viewModel) => SmallAppBar(
onPop: viewModel.pop,
onTap: viewModel.pop,
showBackButton: true,
title: 'Terms and Conditions',
);

View File

@ -55,7 +55,7 @@ class LearnLessonTile extends ViewModelWidget<LearnLessonViewModel> {
expandedCrossAxisAlignment: CrossAxisAlignment.start,
collapsedBackgroundColor: kcPrimaryColor.withOpacity(0.1),
childrenPadding: const EdgeInsets.fromLTRB(15, 0, 15, 15),
// enabled: (lesson.access?.isAccessible ?? false),
// enabled: status != ProgressStatuses.pending,
// backgroundColor: ProgressStatuses.pending == status
// ? kcPrimaryColor.withOpacity(0.1)
// : kcGreen.withOpacity(0.1),

View File

@ -56,7 +56,9 @@ class LearnModuleTile extends ViewModelWidget<LearnModuleViewModel> {
{required BuildContext context,
required LearnModuleViewModel viewModel}) =>
ExpansionTile(
enabled: true,
textColor: kcDarkGrey,
showTrailingIcon: true,
initiallyExpanded: true,
subtitle: _buildContent(),
title: _buildTitleWrapper(),
@ -67,12 +69,13 @@ class LearnModuleTile extends ViewModelWidget<LearnModuleViewModel> {
shape: Border.all(color: kcTransparent),
expandedAlignment: Alignment.centerLeft,
collapsedBackgroundColor: kcBackgroundColor,
enabled: (module.access?.isAccessible ?? false),
controlAffinity: ListTileControlAffinity.trailing,
expandedCrossAxisAlignment: CrossAxisAlignment.start,
tilePadding: const EdgeInsets.symmetric(horizontal: 15),
childrenPadding: const EdgeInsets.fromLTRB(70, 0, 15, 15),
showTrailingIcon: (module.access?.isAccessible ?? false) ? true : false,
// enabled:(module.access?.isAccessible ?? false) ,
// showTrailingIcon: status != ProgressStatuses.pending ? true : false,
//initiallyExpanded: status == ProgressStatuses.started ? true : false,
children:
_buildExpansionTileChildren(context: context, viewModel: viewModel),
);
@ -206,9 +209,9 @@ class LearnModuleTile extends ViewModelWidget<LearnModuleViewModel> {
onTap: viewModel.pop,
);
Widget _buildContainerShaderState() => !(module.access?.isAccessible ?? false)
? _buildContainerShaderWrapper()
: Container();
// Widget _buildContainerShaderState() => status == ProgressStatuses.pending
// ? _buildContainerShaderWrapper()
// : Container();
Widget _buildContainerShaderWrapper() => Positioned.fill(
child: _buildContainerShader(),

View File

@ -4,6 +4,7 @@ import 'package:yimaru_app/ui/common/app_colors.dart';
import 'package:yimaru_app/ui/common/ui_helpers.dart';
import 'package:yimaru_app/ui/views/learn_practice/learn_practice_viewmodel.dart';
class LearnPracticeTipSection extends ViewModelWidget<LearnPracticeViewModel> {
const LearnPracticeTipSection({super.key});

View File

@ -1,45 +0,0 @@
import 'package:flutter/material.dart';
import 'package:yimaru_app/ui/common/app_colors.dart';
import '../common/ui_helpers.dart';
class NoDataIndicator extends StatelessWidget {
final String title;
final GestureTapCallback? onTap;
const NoDataIndicator({super.key, this.onTap, required this.title});
@override
Widget build(BuildContext context) => _buildColumn();
Widget _buildColumn() => Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center,
children: _buildColumnChildren(),
);
List<Widget> _buildColumnChildren() => [
_buildIconWrapper(),
verticalSpaceMedium,
_buildTitle(),
];
Widget _buildTitle() => Text(
title,
style: style16P600,
);
Widget _buildIconWrapper() => GestureDetector(
onTap: onTap,
child: _buildIcon(),
);
Widget _buildIcon() => const Icon(
Icons.replay,
size: 75,
color: kcPrimaryColor,
);
}

View File

@ -5,10 +5,10 @@ import 'package:yimaru_app/ui/widgets/custom_back_button.dart';
class SmallAppBar extends StatelessWidget {
final String? title;
final bool showBackButton;
final GestureTapCallback? onPop;
final GestureTapCallback? onTap;
const SmallAppBar(
{super.key, this.onPop, this.title, required this.showBackButton});
{super.key, this.onTap, this.title, required this.showBackButton});
@override
Widget build(BuildContext context) => _buildAppBar();
@ -28,7 +28,7 @@ class SmallAppBar extends StatelessWidget {
child: _buildBackButton(),
);
Widget _buildBackButton() => CustomBackButton(onTap: onPop);
Widget _buildBackButton() => CustomBackButton(onTap: onTap);
Widget _buildTitleWrapper() => Align(
alignment: Alignment.center,

View File

@ -1,5 +1,5 @@
name: yimaru_app
version: 0.1.9+11
version: 0.1.8+10
publish_to: 'none'
description: A new Flutter project.

View File

@ -8,49 +8,48 @@ import 'dart:ui' as _i10;
import 'package:audioplayers/audioplayers.dart' as _i4;
import 'package:dio/dio.dart' as _i2;
import 'package:firebase_messaging/firebase_messaging.dart' as _i40;
import 'package:firebase_messaging/firebase_messaging.dart' as _i39;
import 'package:flutter/material.dart' as _i8;
import 'package:mockito/mockito.dart' as _i1;
import 'package:mockito/src/dummies.dart' as _i7;
import 'package:permission_handler/permission_handler.dart' as _i35;
import 'package:permission_handler/permission_handler.dart' as _i34;
import 'package:stacked_services/stacked_services.dart' as _i6;
import 'package:waveform_recorder/waveform_recorder.dart' as _i5;
import 'package:yimaru_app/models/assessment.dart' as _i14;
import 'package:yimaru_app/models/assessment_question.dart' as _i15;
import 'package:yimaru_app/models/category.dart' as _i22;
import 'package:yimaru_app/models/course.dart' as _i27;
import 'package:yimaru_app/models/course_detail.dart' as _i43;
import 'package:yimaru_app/models/course_lesson.dart' as _i25;
import 'package:yimaru_app/models/course_progress.dart' as _i24;
import 'package:yimaru_app/models/learn_course.dart' as _i17;
import 'package:yimaru_app/models/learn_lesson.dart' as _i20;
import 'package:yimaru_app/models/learn_module.dart' as _i19;
import 'package:yimaru_app/models/learn_practice.dart' as _i18;
import 'package:yimaru_app/models/learn_program.dart' as _i16;
import 'package:yimaru_app/models/learn_question.dart' as _i21;
import 'package:yimaru_app/models/lesson.dart' as _i31;
import 'package:yimaru_app/models/level.dart' as _i28;
import 'package:yimaru_app/models/module.dart' as _i29;
import 'package:yimaru_app/models/practice.dart' as _i26;
import 'package:yimaru_app/models/subcategory.dart' as _i23;
import 'package:yimaru_app/models/submodule.dart' as _i30;
import 'package:yimaru_app/models/category.dart' as _i21;
import 'package:yimaru_app/models/course.dart' as _i26;
import 'package:yimaru_app/models/course_detail.dart' as _i42;
import 'package:yimaru_app/models/course_lesson.dart' as _i24;
import 'package:yimaru_app/models/course_progress.dart' as _i23;
import 'package:yimaru_app/models/learn_course.dart' as _i16;
import 'package:yimaru_app/models/learn_lesson.dart' as _i19;
import 'package:yimaru_app/models/learn_module.dart' as _i18;
import 'package:yimaru_app/models/learn_practice.dart' as _i17;
import 'package:yimaru_app/models/learn_program.dart' as _i15;
import 'package:yimaru_app/models/learn_question.dart' as _i20;
import 'package:yimaru_app/models/lesson.dart' as _i30;
import 'package:yimaru_app/models/level.dart' as _i27;
import 'package:yimaru_app/models/module.dart' as _i28;
import 'package:yimaru_app/models/practice.dart' as _i25;
import 'package:yimaru_app/models/question.dart' as _i14;
import 'package:yimaru_app/models/subcategory.dart' as _i22;
import 'package:yimaru_app/models/submodule.dart' as _i29;
import 'package:yimaru_app/models/user.dart' as _i12;
import 'package:yimaru_app/services/api_service.dart' as _i13;
import 'package:yimaru_app/services/audio_player_service.dart' as _i44;
import 'package:yimaru_app/services/audio_player_service.dart' as _i43;
import 'package:yimaru_app/services/authentication_service.dart' as _i11;
import 'package:yimaru_app/services/course_service.dart' as _i42;
import 'package:yimaru_app/services/dio_service.dart' as _i32;
import 'package:yimaru_app/services/google_auth_service.dart' as _i37;
import 'package:yimaru_app/services/image_downloader_service.dart' as _i38;
import 'package:yimaru_app/services/image_picker_service.dart' as _i36;
import 'package:yimaru_app/services/in_app_update_service.dart' as _i47;
import 'package:yimaru_app/services/notification_service.dart' as _i39;
import 'package:yimaru_app/services/permission_handler_service.dart' as _i34;
import 'package:yimaru_app/services/course_service.dart' as _i41;
import 'package:yimaru_app/services/dio_service.dart' as _i31;
import 'package:yimaru_app/services/google_auth_service.dart' as _i36;
import 'package:yimaru_app/services/image_downloader_service.dart' as _i37;
import 'package:yimaru_app/services/image_picker_service.dart' as _i35;
import 'package:yimaru_app/services/in_app_update_service.dart' as _i46;
import 'package:yimaru_app/services/notification_service.dart' as _i38;
import 'package:yimaru_app/services/permission_handler_service.dart' as _i33;
import 'package:yimaru_app/services/secure_storage_service.dart' as _i3;
import 'package:yimaru_app/services/smart_auth_service.dart' as _i41;
import 'package:yimaru_app/services/status_checker_service.dart' as _i33;
import 'package:yimaru_app/services/voice_recorder_service.dart' as _i45;
import 'package:yimaru_app/ui/common/enmus.dart' as _i46;
import 'package:yimaru_app/services/smart_auth_service.dart' as _i40;
import 'package:yimaru_app/services/status_checker_service.dart' as _i32;
import 'package:yimaru_app/services/voice_recorder_service.dart' as _i44;
import 'package:yimaru_app/ui/common/enmus.dart' as _i45;
// ignore_for_file: type=lint
// ignore_for_file: avoid_redundant_argument_values
@ -1126,183 +1125,168 @@ class MockApiService extends _i1.Mock implements _i13.ApiService {
) as _i9.Future<Map<String, dynamic>>);
@override
_i9.Future<List<_i14.Assessment>> getAssessments() => (super.noSuchMethod(
_i9.Future<List<_i14.Question>> getAssessments() => (super.noSuchMethod(
Invocation.method(
#getAssessments,
[],
),
returnValue:
_i9.Future<List<_i14.Assessment>>.value(<_i14.Assessment>[]),
returnValue: _i9.Future<List<_i14.Question>>.value(<_i14.Question>[]),
returnValueForMissingStub:
_i9.Future<List<_i14.Assessment>>.value(<_i14.Assessment>[]),
) as _i9.Future<List<_i14.Assessment>>);
_i9.Future<List<_i14.Question>>.value(<_i14.Question>[]),
) as _i9.Future<List<_i14.Question>>);
@override
_i9.Future<List<_i15.AssessmentQuestion>> getAssessmentQuestions(int? id) =>
(super.noSuchMethod(
Invocation.method(
#getAssessmentQuestions,
[id],
),
returnValue: _i9.Future<List<_i15.AssessmentQuestion>>.value(
<_i15.AssessmentQuestion>[]),
returnValueForMissingStub:
_i9.Future<List<_i15.AssessmentQuestion>>.value(
<_i15.AssessmentQuestion>[]),
) as _i9.Future<List<_i15.AssessmentQuestion>>);
@override
_i9.Future<List<_i16.LearnProgram>> getLearnPrograms() => (super.noSuchMethod(
_i9.Future<List<_i15.LearnProgram>> getLearnPrograms() => (super.noSuchMethod(
Invocation.method(
#getLearnPrograms,
[],
),
returnValue:
_i9.Future<List<_i16.LearnProgram>>.value(<_i16.LearnProgram>[]),
_i9.Future<List<_i15.LearnProgram>>.value(<_i15.LearnProgram>[]),
returnValueForMissingStub:
_i9.Future<List<_i16.LearnProgram>>.value(<_i16.LearnProgram>[]),
) as _i9.Future<List<_i16.LearnProgram>>);
_i9.Future<List<_i15.LearnProgram>>.value(<_i15.LearnProgram>[]),
) as _i9.Future<List<_i15.LearnProgram>>);
@override
_i9.Future<List<_i17.LearnCourse>> getLearnCourse(int? id) =>
_i9.Future<List<_i16.LearnCourse>> getLearnCourse(int? id) =>
(super.noSuchMethod(
Invocation.method(
#getLearnCourse,
[id],
),
returnValue:
_i9.Future<List<_i17.LearnCourse>>.value(<_i17.LearnCourse>[]),
_i9.Future<List<_i16.LearnCourse>>.value(<_i16.LearnCourse>[]),
returnValueForMissingStub:
_i9.Future<List<_i17.LearnCourse>>.value(<_i17.LearnCourse>[]),
) as _i9.Future<List<_i17.LearnCourse>>);
_i9.Future<List<_i16.LearnCourse>>.value(<_i16.LearnCourse>[]),
) as _i9.Future<List<_i16.LearnCourse>>);
@override
_i9.Future<List<_i18.LearnPractice>> getLearnCoursePractices(int? id) =>
_i9.Future<List<_i17.LearnPractice>> getLearnCoursePractices(int? id) =>
(super.noSuchMethod(
Invocation.method(
#getLearnCoursePractices,
[id],
),
returnValue:
_i9.Future<List<_i18.LearnPractice>>.value(<_i18.LearnPractice>[]),
_i9.Future<List<_i17.LearnPractice>>.value(<_i17.LearnPractice>[]),
returnValueForMissingStub:
_i9.Future<List<_i18.LearnPractice>>.value(<_i18.LearnPractice>[]),
) as _i9.Future<List<_i18.LearnPractice>>);
_i9.Future<List<_i17.LearnPractice>>.value(<_i17.LearnPractice>[]),
) as _i9.Future<List<_i17.LearnPractice>>);
@override
_i9.Future<List<_i19.LearnModule>> getLearnModules(int? id) =>
_i9.Future<List<_i18.LearnModule>> getLearnModules(int? id) =>
(super.noSuchMethod(
Invocation.method(
#getLearnModules,
[id],
),
returnValue:
_i9.Future<List<_i19.LearnModule>>.value(<_i19.LearnModule>[]),
_i9.Future<List<_i18.LearnModule>>.value(<_i18.LearnModule>[]),
returnValueForMissingStub:
_i9.Future<List<_i19.LearnModule>>.value(<_i19.LearnModule>[]),
) as _i9.Future<List<_i19.LearnModule>>);
_i9.Future<List<_i18.LearnModule>>.value(<_i18.LearnModule>[]),
) as _i9.Future<List<_i18.LearnModule>>);
@override
_i9.Future<List<_i18.LearnPractice>> getLearnModulePractices(int? id) =>
_i9.Future<List<_i17.LearnPractice>> getLearnModulePractices(int? id) =>
(super.noSuchMethod(
Invocation.method(
#getLearnModulePractices,
[id],
),
returnValue:
_i9.Future<List<_i18.LearnPractice>>.value(<_i18.LearnPractice>[]),
_i9.Future<List<_i17.LearnPractice>>.value(<_i17.LearnPractice>[]),
returnValueForMissingStub:
_i9.Future<List<_i18.LearnPractice>>.value(<_i18.LearnPractice>[]),
) as _i9.Future<List<_i18.LearnPractice>>);
_i9.Future<List<_i17.LearnPractice>>.value(<_i17.LearnPractice>[]),
) as _i9.Future<List<_i17.LearnPractice>>);
@override
_i9.Future<List<_i20.LearnLesson>> getLearnLessons(int? id) =>
_i9.Future<List<_i19.LearnLesson>> getLearnLessons(int? id) =>
(super.noSuchMethod(
Invocation.method(
#getLearnLessons,
[id],
),
returnValue:
_i9.Future<List<_i20.LearnLesson>>.value(<_i20.LearnLesson>[]),
_i9.Future<List<_i19.LearnLesson>>.value(<_i19.LearnLesson>[]),
returnValueForMissingStub:
_i9.Future<List<_i20.LearnLesson>>.value(<_i20.LearnLesson>[]),
) as _i9.Future<List<_i20.LearnLesson>>);
_i9.Future<List<_i19.LearnLesson>>.value(<_i19.LearnLesson>[]),
) as _i9.Future<List<_i19.LearnLesson>>);
@override
_i9.Future<List<_i18.LearnPractice>> getLearnLessonPractices(int? id) =>
_i9.Future<List<_i17.LearnPractice>> getLearnLessonPractices(int? id) =>
(super.noSuchMethod(
Invocation.method(
#getLearnLessonPractices,
[id],
),
returnValue:
_i9.Future<List<_i18.LearnPractice>>.value(<_i18.LearnPractice>[]),
_i9.Future<List<_i17.LearnPractice>>.value(<_i17.LearnPractice>[]),
returnValueForMissingStub:
_i9.Future<List<_i18.LearnPractice>>.value(<_i18.LearnPractice>[]),
) as _i9.Future<List<_i18.LearnPractice>>);
_i9.Future<List<_i17.LearnPractice>>.value(<_i17.LearnPractice>[]),
) as _i9.Future<List<_i17.LearnPractice>>);
@override
_i9.Future<List<_i21.LearnQuestion>> getLearnQuestions(int? id) =>
_i9.Future<List<_i20.LearnQuestion>> getLearnQuestions(int? id) =>
(super.noSuchMethod(
Invocation.method(
#getLearnQuestions,
[id],
),
returnValue:
_i9.Future<List<_i21.LearnQuestion>>.value(<_i21.LearnQuestion>[]),
_i9.Future<List<_i20.LearnQuestion>>.value(<_i20.LearnQuestion>[]),
returnValueForMissingStub:
_i9.Future<List<_i21.LearnQuestion>>.value(<_i21.LearnQuestion>[]),
) as _i9.Future<List<_i21.LearnQuestion>>);
_i9.Future<List<_i20.LearnQuestion>>.value(<_i20.LearnQuestion>[]),
) as _i9.Future<List<_i20.LearnQuestion>>);
@override
_i9.Future<List<_i22.Category>> getCategories() => (super.noSuchMethod(
_i9.Future<List<_i21.Category>> getCategories() => (super.noSuchMethod(
Invocation.method(
#getCategories,
[],
),
returnValue: _i9.Future<List<_i22.Category>>.value(<_i22.Category>[]),
returnValue: _i9.Future<List<_i21.Category>>.value(<_i21.Category>[]),
returnValueForMissingStub:
_i9.Future<List<_i22.Category>>.value(<_i22.Category>[]),
) as _i9.Future<List<_i22.Category>>);
_i9.Future<List<_i21.Category>>.value(<_i21.Category>[]),
) as _i9.Future<List<_i21.Category>>);
@override
_i9.Future<List<_i23.Subcategory>> getSubcategories(int? id) =>
_i9.Future<List<_i22.Subcategory>> getSubcategories(int? id) =>
(super.noSuchMethod(
Invocation.method(
#getSubcategories,
[id],
),
returnValue:
_i9.Future<List<_i23.Subcategory>>.value(<_i23.Subcategory>[]),
_i9.Future<List<_i22.Subcategory>>.value(<_i22.Subcategory>[]),
returnValueForMissingStub:
_i9.Future<List<_i23.Subcategory>>.value(<_i23.Subcategory>[]),
) as _i9.Future<List<_i23.Subcategory>>);
_i9.Future<List<_i22.Subcategory>>.value(<_i22.Subcategory>[]),
) as _i9.Future<List<_i22.Subcategory>>);
@override
_i9.Future<List<_i24.CourseProgress>> getCourseProgress(int? id) =>
_i9.Future<List<_i23.CourseProgress>> getCourseProgress(int? id) =>
(super.noSuchMethod(
Invocation.method(
#getCourseProgress,
[id],
),
returnValue: _i9.Future<List<_i24.CourseProgress>>.value(
<_i24.CourseProgress>[]),
returnValueForMissingStub: _i9.Future<List<_i24.CourseProgress>>.value(
<_i24.CourseProgress>[]),
) as _i9.Future<List<_i24.CourseProgress>>);
returnValue: _i9.Future<List<_i23.CourseProgress>>.value(
<_i23.CourseProgress>[]),
returnValueForMissingStub: _i9.Future<List<_i23.CourseProgress>>.value(
<_i23.CourseProgress>[]),
) as _i9.Future<List<_i23.CourseProgress>>);
@override
_i9.Future<List<_i25.CourseLesson>> getCourseLessons(int? id) =>
_i9.Future<List<_i24.CourseLesson>> getCourseLessons(int? id) =>
(super.noSuchMethod(
Invocation.method(
#getCourseLessons,
[id],
),
returnValue:
_i9.Future<List<_i25.CourseLesson>>.value(<_i25.CourseLesson>[]),
_i9.Future<List<_i24.CourseLesson>>.value(<_i24.CourseLesson>[]),
returnValueForMissingStub:
_i9.Future<List<_i25.CourseLesson>>.value(<_i25.CourseLesson>[]),
) as _i9.Future<List<_i25.CourseLesson>>);
_i9.Future<List<_i24.CourseLesson>>.value(<_i24.CourseLesson>[]),
) as _i9.Future<List<_i24.CourseLesson>>);
@override
_i9.Future<Map<String, dynamic>> completeLesson(int? id) =>
@ -1318,136 +1302,130 @@ class MockApiService extends _i1.Mock implements _i13.ApiService {
) as _i9.Future<Map<String, dynamic>>);
@override
_i9.Future<List<_i26.Practice>> getCoursePractices(int? id) =>
_i9.Future<List<_i25.Practice>> getCoursePractices(int? id) =>
(super.noSuchMethod(
Invocation.method(
#getCoursePractices,
[id],
),
returnValue: _i9.Future<List<_i26.Practice>>.value(<_i26.Practice>[]),
returnValue: _i9.Future<List<_i25.Practice>>.value(<_i25.Practice>[]),
returnValueForMissingStub:
_i9.Future<List<_i26.Practice>>.value(<_i26.Practice>[]),
) as _i9.Future<List<_i26.Practice>>);
_i9.Future<List<_i25.Practice>>.value(<_i25.Practice>[]),
) as _i9.Future<List<_i25.Practice>>);
@override
_i9.Future<List<_i15.AssessmentQuestion>> getCoursePracticeQuestions(
int? id) =>
_i9.Future<List<_i14.Question>> getCoursePracticeQuestions(int? id) =>
(super.noSuchMethod(
Invocation.method(
#getCoursePracticeQuestions,
[id],
),
returnValue: _i9.Future<List<_i15.AssessmentQuestion>>.value(
<_i15.AssessmentQuestion>[]),
returnValue: _i9.Future<List<_i14.Question>>.value(<_i14.Question>[]),
returnValueForMissingStub:
_i9.Future<List<_i15.AssessmentQuestion>>.value(
<_i15.AssessmentQuestion>[]),
) as _i9.Future<List<_i15.AssessmentQuestion>>);
_i9.Future<List<_i14.Question>>.value(<_i14.Question>[]),
) as _i9.Future<List<_i14.Question>>);
@override
_i9.Future<_i15.AssessmentQuestion?> getCoursePracticeQuestion(int? id) =>
_i9.Future<_i14.Question?> getCoursePracticeQuestion(int? id) =>
(super.noSuchMethod(
Invocation.method(
#getCoursePracticeQuestion,
[id],
),
returnValue: _i9.Future<_i15.AssessmentQuestion?>.value(),
returnValueForMissingStub: _i9.Future<_i15.AssessmentQuestion?>.value(),
) as _i9.Future<_i15.AssessmentQuestion?>);
returnValue: _i9.Future<_i14.Question?>.value(),
returnValueForMissingStub: _i9.Future<_i14.Question?>.value(),
) as _i9.Future<_i14.Question?>);
@override
_i9.Future<List<_i23.Subcategory>> getLearnSubcategories() =>
_i9.Future<List<_i22.Subcategory>> getLearnSubcategories() =>
(super.noSuchMethod(
Invocation.method(
#getLearnSubcategories,
[],
),
returnValue:
_i9.Future<List<_i23.Subcategory>>.value(<_i23.Subcategory>[]),
_i9.Future<List<_i22.Subcategory>>.value(<_i22.Subcategory>[]),
returnValueForMissingStub:
_i9.Future<List<_i23.Subcategory>>.value(<_i23.Subcategory>[]),
) as _i9.Future<List<_i23.Subcategory>>);
_i9.Future<List<_i22.Subcategory>>.value(<_i22.Subcategory>[]),
) as _i9.Future<List<_i22.Subcategory>>);
@override
_i9.Future<List<_i27.Course>> getCourses(int? id) => (super.noSuchMethod(
_i9.Future<List<_i26.Course>> getCourses(int? id) => (super.noSuchMethod(
Invocation.method(
#getCourses,
[id],
),
returnValue: _i9.Future<List<_i27.Course>>.value(<_i27.Course>[]),
returnValue: _i9.Future<List<_i26.Course>>.value(<_i26.Course>[]),
returnValueForMissingStub:
_i9.Future<List<_i27.Course>>.value(<_i27.Course>[]),
) as _i9.Future<List<_i27.Course>>);
_i9.Future<List<_i26.Course>>.value(<_i26.Course>[]),
) as _i9.Future<List<_i26.Course>>);
@override
_i9.Future<List<_i28.Level>> getLevels(int? id) => (super.noSuchMethod(
_i9.Future<List<_i27.Level>> getLevels(int? id) => (super.noSuchMethod(
Invocation.method(
#getLevels,
[id],
),
returnValue: _i9.Future<List<_i28.Level>>.value(<_i28.Level>[]),
returnValue: _i9.Future<List<_i27.Level>>.value(<_i27.Level>[]),
returnValueForMissingStub:
_i9.Future<List<_i28.Level>>.value(<_i28.Level>[]),
) as _i9.Future<List<_i28.Level>>);
_i9.Future<List<_i27.Level>>.value(<_i27.Level>[]),
) as _i9.Future<List<_i27.Level>>);
@override
_i9.Future<List<_i29.Module>> getModules(int? id) => (super.noSuchMethod(
_i9.Future<List<_i28.Module>> getModules(int? id) => (super.noSuchMethod(
Invocation.method(
#getModules,
[id],
),
returnValue: _i9.Future<List<_i29.Module>>.value(<_i29.Module>[]),
returnValue: _i9.Future<List<_i28.Module>>.value(<_i28.Module>[]),
returnValueForMissingStub:
_i9.Future<List<_i29.Module>>.value(<_i29.Module>[]),
) as _i9.Future<List<_i29.Module>>);
_i9.Future<List<_i28.Module>>.value(<_i28.Module>[]),
) as _i9.Future<List<_i28.Module>>);
@override
_i9.Future<List<_i30.Submodule>> getSubmodules(int? id) =>
_i9.Future<List<_i29.Submodule>> getSubmodules(int? id) =>
(super.noSuchMethod(
Invocation.method(
#getSubmodules,
[id],
),
returnValue: _i9.Future<List<_i30.Submodule>>.value(<_i30.Submodule>[]),
returnValue: _i9.Future<List<_i29.Submodule>>.value(<_i29.Submodule>[]),
returnValueForMissingStub:
_i9.Future<List<_i30.Submodule>>.value(<_i30.Submodule>[]),
) as _i9.Future<List<_i30.Submodule>>);
_i9.Future<List<_i29.Submodule>>.value(<_i29.Submodule>[]),
) as _i9.Future<List<_i29.Submodule>>);
@override
_i9.Future<List<_i31.Lesson>> getLessons(int? id) => (super.noSuchMethod(
_i9.Future<List<_i30.Lesson>> getLessons(int? id) => (super.noSuchMethod(
Invocation.method(
#getLessons,
[id],
),
returnValue: _i9.Future<List<_i31.Lesson>>.value(<_i31.Lesson>[]),
returnValue: _i9.Future<List<_i30.Lesson>>.value(<_i30.Lesson>[]),
returnValueForMissingStub:
_i9.Future<List<_i31.Lesson>>.value(<_i31.Lesson>[]),
) as _i9.Future<List<_i31.Lesson>>);
_i9.Future<List<_i30.Lesson>>.value(<_i30.Lesson>[]),
) as _i9.Future<List<_i30.Lesson>>);
@override
_i9.Future<List<_i26.Practice>> getPractices(int? id) => (super.noSuchMethod(
_i9.Future<List<_i25.Practice>> getPractices(int? id) => (super.noSuchMethod(
Invocation.method(
#getPractices,
[id],
),
returnValue: _i9.Future<List<_i26.Practice>>.value(<_i26.Practice>[]),
returnValue: _i9.Future<List<_i25.Practice>>.value(<_i25.Practice>[]),
returnValueForMissingStub:
_i9.Future<List<_i26.Practice>>.value(<_i26.Practice>[]),
) as _i9.Future<List<_i26.Practice>>);
_i9.Future<List<_i25.Practice>>.value(<_i25.Practice>[]),
) as _i9.Future<List<_i25.Practice>>);
@override
_i9.Future<List<_i15.AssessmentQuestion>> getQuestions(int? id) =>
(super.noSuchMethod(
_i9.Future<List<_i14.Question>> getQuestions(int? id) => (super.noSuchMethod(
Invocation.method(
#getQuestions,
[id],
),
returnValue: _i9.Future<List<_i15.AssessmentQuestion>>.value(
<_i15.AssessmentQuestion>[]),
returnValue: _i9.Future<List<_i14.Question>>.value(<_i14.Question>[]),
returnValueForMissingStub:
_i9.Future<List<_i15.AssessmentQuestion>>.value(
<_i15.AssessmentQuestion>[]),
) as _i9.Future<List<_i15.AssessmentQuestion>>);
_i9.Future<List<_i14.Question>>.value(<_i14.Question>[]),
) as _i9.Future<List<_i14.Question>>);
}
/// A class which mocks [SecureStorageService].
@ -1550,7 +1528,7 @@ class MockSecureStorageService extends _i1.Mock
/// A class which mocks [DioService].
///
/// See the documentation for Mockito's code generation for more information.
class MockDioService extends _i1.Mock implements _i32.DioService {
class MockDioService extends _i1.Mock implements _i31.DioService {
@override
_i2.Dio get dio => (super.noSuchMethod(
Invocation.getter(#dio),
@ -1569,7 +1547,7 @@ class MockDioService extends _i1.Mock implements _i32.DioService {
///
/// See the documentation for Mockito's code generation for more information.
class MockStatusCheckerService extends _i1.Mock
implements _i33.StatusCheckerService {
implements _i32.StatusCheckerService {
@override
_i3.SecureStorageService get storage => (super.noSuchMethod(
Invocation.getter(#storage),
@ -1605,40 +1583,40 @@ class MockStatusCheckerService extends _i1.Mock
///
/// See the documentation for Mockito's code generation for more information.
class MockPermissionHandlerService extends _i1.Mock
implements _i34.PermissionHandlerService {
implements _i33.PermissionHandlerService {
@override
_i9.Future<_i35.PermissionStatus> requestPermission(
_i35.Permission? requestedPermission) =>
_i9.Future<_i34.PermissionStatus> requestPermission(
_i34.Permission? requestedPermission) =>
(super.noSuchMethod(
Invocation.method(
#requestPermission,
[requestedPermission],
),
returnValue: _i9.Future<_i35.PermissionStatus>.value(
_i35.PermissionStatus.denied),
returnValueForMissingStub: _i9.Future<_i35.PermissionStatus>.value(
_i35.PermissionStatus.denied),
) as _i9.Future<_i35.PermissionStatus>);
returnValue: _i9.Future<_i34.PermissionStatus>.value(
_i34.PermissionStatus.denied),
returnValueForMissingStub: _i9.Future<_i34.PermissionStatus>.value(
_i34.PermissionStatus.denied),
) as _i9.Future<_i34.PermissionStatus>);
@override
_i9.Future<_i35.PermissionStatus> request(_i35.Permission? permission) =>
_i9.Future<_i34.PermissionStatus> request(_i34.Permission? permission) =>
(super.noSuchMethod(
Invocation.method(
#request,
[permission],
),
returnValue: _i9.Future<_i35.PermissionStatus>.value(
_i35.PermissionStatus.denied),
returnValueForMissingStub: _i9.Future<_i35.PermissionStatus>.value(
_i35.PermissionStatus.denied),
) as _i9.Future<_i35.PermissionStatus>);
returnValue: _i9.Future<_i34.PermissionStatus>.value(
_i34.PermissionStatus.denied),
returnValueForMissingStub: _i9.Future<_i34.PermissionStatus>.value(
_i34.PermissionStatus.denied),
) as _i9.Future<_i34.PermissionStatus>);
}
/// A class which mocks [ImagePickerService].
///
/// See the documentation for Mockito's code generation for more information.
class MockImagePickerService extends _i1.Mock
implements _i36.ImagePickerService {
implements _i35.ImagePickerService {
@override
_i9.Future<String?> gallery() => (super.noSuchMethod(
Invocation.method(
@ -1663,7 +1641,7 @@ class MockImagePickerService extends _i1.Mock
/// A class which mocks [GoogleAuthService].
///
/// See the documentation for Mockito's code generation for more information.
class MockGoogleAuthService extends _i1.Mock implements _i37.GoogleAuthService {
class MockGoogleAuthService extends _i1.Mock implements _i36.GoogleAuthService {
@override
int get listenersCount => (super.noSuchMethod(
Invocation.getter(#listenersCount),
@ -1733,7 +1711,7 @@ class MockGoogleAuthService extends _i1.Mock implements _i37.GoogleAuthService {
///
/// See the documentation for Mockito's code generation for more information.
class MockImageDownloaderService extends _i1.Mock
implements _i38.ImageDownloaderService {
implements _i37.ImageDownloaderService {
@override
_i9.Future<String> downloader(String? networkImage) => (super.noSuchMethod(
Invocation.method(
@ -1762,7 +1740,7 @@ class MockImageDownloaderService extends _i1.Mock
///
/// See the documentation for Mockito's code generation for more information.
class MockNotificationService extends _i1.Mock
implements _i39.NotificationService {
implements _i38.NotificationService {
@override
_i9.Future<void> initialize() => (super.noSuchMethod(
Invocation.method(
@ -1784,7 +1762,7 @@ class MockNotificationService extends _i1.Mock
) as _i9.Future<void>);
@override
_i9.Future<void> showNotification(_i40.RemoteMessage? message) =>
_i9.Future<void> showNotification(_i39.RemoteMessage? message) =>
(super.noSuchMethod(
Invocation.method(
#showNotification,
@ -1818,7 +1796,7 @@ class MockNotificationService extends _i1.Mock
/// A class which mocks [SmartAuthService].
///
/// See the documentation for Mockito's code generation for more information.
class MockSmartAuthService extends _i1.Mock implements _i41.SmartAuthService {
class MockSmartAuthService extends _i1.Mock implements _i40.SmartAuthService {
@override
bool get listenForMultipleSms => (super.noSuchMethod(
Invocation.getter(#listenForMultipleSms),
@ -1850,26 +1828,26 @@ class MockSmartAuthService extends _i1.Mock implements _i41.SmartAuthService {
/// A class which mocks [CourseService].
///
/// See the documentation for Mockito's code generation for more information.
class MockCourseService extends _i1.Mock implements _i42.CourseService {
class MockCourseService extends _i1.Mock implements _i41.CourseService {
@override
_i9.Future<List<_i43.CourseDetail>> getCoursesDetail(int? id) =>
_i9.Future<List<_i42.CourseDetail>> getCoursesDetail(int? id) =>
(super.noSuchMethod(
Invocation.method(
#getCoursesDetail,
[id],
),
returnValue:
_i9.Future<List<_i43.CourseDetail>>.value(<_i43.CourseDetail>[]),
_i9.Future<List<_i42.CourseDetail>>.value(<_i42.CourseDetail>[]),
returnValueForMissingStub:
_i9.Future<List<_i43.CourseDetail>>.value(<_i43.CourseDetail>[]),
) as _i9.Future<List<_i43.CourseDetail>>);
_i9.Future<List<_i42.CourseDetail>>.value(<_i42.CourseDetail>[]),
) as _i9.Future<List<_i42.CourseDetail>>);
}
/// A class which mocks [AudioPlayerService].
///
/// See the documentation for Mockito's code generation for more information.
class MockAudioPlayerService extends _i1.Mock
implements _i44.AudioPlayerService {
implements _i43.AudioPlayerService {
@override
_i4.AudioPlayer get player => (super.noSuchMethod(
Invocation.getter(#player),
@ -1993,13 +1971,13 @@ class MockAudioPlayerService extends _i1.Mock
///
/// See the documentation for Mockito's code generation for more information.
class MockVoiceRecorderService extends _i1.Mock
implements _i45.VoiceRecorderService {
implements _i44.VoiceRecorderService {
@override
_i46.VoiceRecordingState get recordingState => (super.noSuchMethod(
_i45.VoiceRecordingState get recordingState => (super.noSuchMethod(
Invocation.getter(#recordingState),
returnValue: _i46.VoiceRecordingState.pending,
returnValueForMissingStub: _i46.VoiceRecordingState.pending,
) as _i46.VoiceRecordingState);
returnValue: _i45.VoiceRecordingState.pending,
returnValueForMissingStub: _i45.VoiceRecordingState.pending,
) as _i45.VoiceRecordingState);
@override
_i5.WaveformRecorderController get waveController => (super.noSuchMethod(
@ -2100,7 +2078,7 @@ class MockVoiceRecorderService extends _i1.Mock
///
/// See the documentation for Mockito's code generation for more information.
class MockInAppUpdateService extends _i1.Mock
implements _i47.InAppUpdateService {
implements _i46.InAppUpdateService {
@override
_i9.Future<int> getBatteryLevel() => (super.noSuchMethod(
Invocation.method(

View File

@ -1,11 +0,0 @@
import 'package:flutter_test/flutter_test.dart';
import 'package:yimaru_app/app/app.locator.dart';
import '../helpers/test_helpers.dart';
void main() {
group('AssessmentQuestionViewModel Tests -', () {
setUp(() => registerServices());
tearDown(() => locator.reset());
});
}